简体   繁体   English

从 ppm 文件中读取 RGB 值并使用结构(动态数组)将它们存储到名为“Image”的二维数组中

[英]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++.我正在尝试从 ppm 文件中读取并提取 RGB 值并将它们存储到带有 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:我们只关注 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.如果您想将图像作为 2D 数组访问(并且分辨率是一个参数),您需要分配一个指向数据的指针数组。

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?请参阅: 如何使用 new 在 C++ 中声明二维数组?


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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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