Чтение значений RGB из ppm-файла и сохранение их в 2d-массиве под названием «Image» с использованием struct (динамические массивы c) - PullRequest
1 голос
/ 08 марта 2020

Я пытаюсь прочитать из ppm-файла, извлечь значения RGB и сохранить их в 2d массиве с C ++. Я почти уверен, что решение довольно простое, но для жизни я его не вижу. Все мои попытки дают массу ошибок.

Редактировать: Значения в массиве должны быть в главном порядке столбцов. Очевидно, мне нужно хранить числа в структуре, и эти числа будут храниться в массиве.

Общие сведения:

Первый параметр - это имя файла, который нужно открыть, и читать из. Второй параметр - это двумерный массив пикселей (структур), которые содержат значение цвета. «Ширина» - это ширина массива (то есть количество столбцов), необходимая для «перемещения» по массиву. «Высота» - это высота массива (т. Е. Количество строк), необходимая для «перемещения» по массиву.

Код, который у меня пока есть:

#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;
}

Это заголовок файл, который я включил в заголовочный файл. Пожалуйста, не изменяйте. Мы просто фокусируемся на 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);

Если вам нужна дополнительная информация, пожалуйста, сообщите мне. Спасибо.

1 Ответ

0 голосов
/ 09 марта 2020

Чтение пикселей относительно просто, если вы знаете, как выделить изображение.

Если вы хотите получить доступ к изображению как к двумерному массиву (а разрешение - это параметр), вам нужно выделить массив указателей, которые указывают данные.

Пример:

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

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

См .: Как мне объявить 2d-массив в C ++, используя new?


Я использовал образец изображение из здесь , и добавил еще один столбец.

Входное содержимое файла изображения:

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

L oop, считывающее пиксели:

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
    }
}

Пример всего кода:

#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;
}

Результат (окно просмотра):

-    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
...