简体   繁体   中英

Reading RGB values from a ppm file & storing them into a 2d array called "Image" using a struct (dynamic arrays)

I am trying to read from a ppm file and extract the RGB values and store them into a 2d array w/ C++. I'm pretty sure the solution is pretty simple but for the life of me, I cannot see it. All of my attempts yield a ton of errors.

Edit: Values in the array must be in column-major order. Apparently I need to store the numbers in a struct and that will store those numbers into the array.

Background knowledge:

The first parameter is the name of the file to open and read from. The second parameter is a 2d array of Pixels (structs) that hold a color value. "Width" is the width of the array (ie the number of columns) needed to 'travel' across the array. "Height" is the height of the array (ie the number of rows) needed to 'travel' across the array

Code I have so so far:

#include "functions.h"
#include <cmath>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

bool imageLoader(string filename, Pixel** image, int width, int height) {
    ifstream fin(filename.c_str());

    if(!fin.is_open()) {
        cout << "Error: failed to open input file - " << filename << endl;
        return false;
    }

    // get type from preamble
    char type[3];
    fin >> type;                                        // should be P3
    if((toupper(type[0]) != 'P') || (type[1] != '3')) { // check that type is correct
        cout << "Error: type is " << type << "instead of P3" << endl;
        return false;
    }

    int w = 0, h = 0;
    fin >> w >> h;
    if(w != width) { // check that width matches what was passed into the function
        cout << "Error: input width (" << width << ")does not match value in file ("
             << w << ")" << endl;
        return false;
    }

    if(h != height) { // check that height matches what was passed into the function
        cout << "Error: input width (" << height
             << ") does not match value in file (" << h << ")" << endl;
        return false;
    }

    // get maximum value from preamble
    int colorMax = 0;
    fin >> colorMax;
    if(colorMax > 255 || colorMax < 0) {
        cout << "Error: invalid color value" << colorMax << endl;
        return false;
    }

    // THIS IS WHAT I NEED HELP WITH
    // I am not sure how this is supposed to work out
    // extract rgb values and place into 2d arr

    /* errors :(
    Pixel colors;
    int colors.r[][] = {0, 0, 0};
    int colors.b[][] = {0, 0, 0};
    int colors.g[][] = {0, 0, 0};
    for (int i = 0; i < height; i++)
    {
    for (int j = 0; j < width; j++) {
        fin >> colors.r >> colors.g >> colors.g;
        cout << colors.r[i][j];

    }
              }
   */

    return true;
}

This is the header file I have included in the header file. Please do not modify. We are just focusing on imageLoader:

#ifndef FUNCTIONS_H
#define FUNCTIONS_H

#include <string>
#include "functions.h"

struct Pixel {
  int r; // red
  int g; // green
  int b; // blue
};


Pixel** createImage(int width, int height);
void deleteImage(Pixel** image, int width);



bool imageLoader(std::string filename, Pixel** image, int width, int height);

If any extra information is needed, please notify me. Thank you.

Reading the pixels is relatively simple, if you know how to allocate the image.

In case you want to access the image as 2D array (and resolution is a parameter), you need to allocate an array of pointers that points the data.

Example:

image -> [col0, col1, col2, ...] 
         (col0, col1, col2 are pointers to columns - applies column major)

col0 -> ####### (points first columns)
col1 -> #######
col2 -> #######

See: How do I declare a 2d array in C++ using new?


I used a sample image from here , and added one more column.

Input image file content:

P3
5 4
255
0  0  0   100 0  0       0  0  0    255   0 255   0  0  255
0  0  0    0 255 175     0  0  0     0    0  0    0  0  255
0  0  0    0  0  0       0 15 175    0    0  0    0  0  255
255 0 255  0  0  0       0  0  0    255  255 255  0  0  255

Loop that reads the pixels:

Pixel colors;

for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; j++) {
        fin >> colors.r >> colors.g >> colors.b;

        //Column major - row index comes first.
        image[j][i] = colors;   //Copy RGB values into image
    }
}

Entire code sample:

#include <string>
#include <cmath>
#include <fstream>
#include <iostream>
#include <sstream>

struct Pixel {
    int r; // red
    int g; // green
    int b; // blue
};


using namespace std;


bool imageLoader(string filename, Pixel** image, int width, int height) {
    ifstream fin(filename.c_str());

    if(!fin.is_open()) {
        cout << "Error: failed to open input file - " << filename << endl;
        return false;
    }

    // get type from preamble
    char type[3];
    fin >> type;                                        // should be P3
    if((toupper(type[0]) != 'P') || (type[1] != '3')) { // check that type is correct
        cout << "Error: type is " << type << "instead of P3" << endl;
        return false;
    }

    int w = 0, h = 0;
    fin >> w >> h;
    if(w != width) { // check that width matches what was passed into the function
        cout << "Error: input width (" << width << ")does not match value in file ("
             << w << ")" << endl;
        return false;
    }

    if(h != height) { // check that height matches what was passed into the function
        cout << "Error: input width (" << height
             << ") does not match value in file (" << h << ")" << endl;
        return false;
    }

    // get maximum value from preamble
    int colorMax = 0;
    fin >> colorMax;
    if(colorMax > 255 || colorMax < 0) {
        cout << "Error: invalid color value" << colorMax << endl;
        return false;
    }

    // THIS IS WHAT I NEED HELP WITH
    // I am not sure how this is supposed to work out
    // extract rgb values and place into 2d arr

    /* errors :(    
    int colors.r[][] = {0, 0, 0};
    int colors.b[][] = {0, 0, 0};
    int colors.g[][] = {0, 0, 0};
    */
    Pixel colors;

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++) {
            fin >> colors.r >> colors.g >> colors.b;
            //cout << "(" << i << ", " << j << "): " << colors.r << " " << colors.g << " " << colors.b << endl;

            //Column major - row index comes first.
            image[j][i] = colors;   //Copy RGB values into image
        }
    }

    return true;
}



int main()
{
    //img.ppm
    //https://www.cs.swarthmore.edu/~soni/cs35/f12/Labs/extras/01/ppm_info.html

    //P3
    //5 4
    //255
    //0  0  0   100 0  0       0  0  0    255   0 255   0  0  255
    //0  0  0    0 255 175     0  0  0     0    0  0    0  0  255
    //0  0  0    0  0  0       0 15 175    0    0  0    0  0  255
    //255 0 255  0  0  0       0  0  0    255  255 255  0  0  255

    int width = 5;    //Number of columns
    int height = 4;   //Number of rows

    //Allocate memory
    //////////////////////////////////////////////////////////////////////////
    //Allocate array of 128 pointers (pointer to columns - since column major is required)
    Pixel** image = new Pixel* [width];

    //Allocate columns (each column is 96 pixels).
    for (int j = 0; j < width; j++) {
        image[j] = new Pixel[height];
    }
    //////////////////////////////////////////////////////////////////////////

    bool res = imageLoader("img.ppm", image, width, height);

    if (!res) {
        cout << "res = " << res << endl;
    }

    //Free memory
    //////////////////////////////////////////////////////////////////////////
    //Delete columns.
    for (int j = 0; j < width; j++) {
        delete [] image[j];
    }

    //Delete image.
    delete [] image;
    //////////////////////////////////////////////////////////////////////////

    return 0;
}

Result (Watch window):

-    image[0],4    0x0000000000ba2f20 {r=0 g=0 b=0 }    Pixel *
+    [0]    {r=0 g=0 b=0 }    Pixel
+    [1]    {r=0 g=0 b=0 }    Pixel
+    [2]    {r=0 g=0 b=0 }    Pixel
+    [3]    {r=255 g=0 b=255 }    Pixel
-    image[1],4    0x0000000000ba2fc0 {r=100 g=0 b=0 }    Pixel *
+    [0]    {r=100 g=0 b=0 }    Pixel
+    [1]    {r=0 g=255 b=175 }    Pixel
+    [2]    {r=0 g=0 b=0 }    Pixel
+    [3]    {r=0 g=0 b=0 }    Pixel
-    image[2],4    0x0000000000ba7470 {r=0 g=0 b=0 }    Pixel *
+    [0]    {r=0 g=0 b=0 }    Pixel
+    [1]    {r=0 g=0 b=0 }    Pixel
+    [2]    {r=0 g=15 b=175 }    Pixel
+    [3]    {r=0 g=0 b=0 }    Pixel
-    image[3],4    0x0000000000ba7510 {r=255 g=0 b=255 }    Pixel *
+    [0]    {r=255 g=0 b=255 }    Pixel
+    [1]    {r=0 g=0 b=0 }    Pixel
+    [2]    {r=0 g=0 b=0 }    Pixel
+    [3]    {r=255 g=255 b=255 }    Pixel
-    image[4],4    0x0000000000ba75b0 {r=0 g=0 b=255 }    Pixel *
+    [0]    {r=0 g=0 b=255 }    Pixel
+    [1]    {r=0 g=0 b=255 }    Pixel
+    [2]    {r=0 g=0 b=255 }    Pixel
+    [3]    {r=0 g=0 b=255 }    Pixel

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM