0

I've been trying to read a greyscale image file(pgm) and store the pixel values in an array. .pgm files have first three lines containing infos on the type(binary or ASCII) the size(64 by 64 for this image), and maximum pixel value(255). And from the fourth line, the data(pixel values in binary) begins. So I am trying to read from the fourth line.

However, when I run the code, what I get is just some unreadable broken text. The image file I am trying to open is about 5kb and can be downloaded at https://drive.google.com/file/d/1DoaaU9tPc_kO9Uu3TKjBmxTQVP3b-SO8/view?usp=sharing

Any help/suggestions would be appreciated. Thank you very much!

#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

int main()
{
    ifstream::pos_type _Start, _End, _Size, _Size2;
    ifstream::off_type _newStart;
    char * memblock;
    std::ifstream inf;
    inf.open("Aaron_Eckhart_0001.pgm", ios_base::in | ios_base::binary);
    if (inf) {
        std::string line;

        for (int i = 0; i<3; i++)//skip the first 3 lines that contain the info
        {
            std::getline(inf, line);
        }

        _Start = inf.tellg();//starting point just after those 3 lines
        inf.seekg(0, ios::end);
        _End = inf.tellg();
        _Size = (_End - _Start);


        cout << _Size << endl;
        memblock = new char[_Size];
        _newStart = (ifstream::off_type) _Start;//casting _Start to off_type to be passes as offset, to start reading the file after the first three lines, idon't know if that idea is right or not
        cout << _newStart << endl;
        inf.seekg(_newStart, ios::beg);
        inf.read(memblock, _Size); 
        cout << memblock << endl; 

    }

    system("pause");

    inf.close();
}

I want to store the pixel values in an array so that I can make some changes and manipulate them.

Jaewon Lee
  • 33
  • 4
  • To begin with, if you have a binary file you can't treat its contents like text. – Some programmer dude Jul 29 '19 at 17:31
  • On an unrelated note, all symbols beginning with an underscore and followed by an upper-case letter (like e.g. `_Size`) is *reserved* in all scopes. See [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) for details. – Some programmer dude Jul 29 '19 at 17:32
  • 3
    `unreadable broken text` is pretty much what I would expect a binary image file to contain. – 500 - Internal Server Error Jul 29 '19 at 17:34
  • @500 - Internal Server Error then is there a way to read the binary pixel values as float and manipulate them? – Jaewon Lee Jul 29 '19 at 17:41
  • Sure. Well, not floats, probably, but more like sets of integers (RGB) or integer grat scale levels. You need to look for a file format specification for PGM files (whatever that is). – 500 - Internal Server Error Jul 29 '19 at 17:46
  • When first two symbols of PGM file are P2 then you can read the gray scale values as text, when P5 then you should read these as binary bytes. Your code posted ignores all the important part in start of file. – Öö Tiib Jul 29 '19 at 18:05
  • Would you give me a suggestion as to how to read it as binary byte and convert it into integer value? – Jaewon Lee Jul 29 '19 at 18:07
  • you can read it like inf.read(&unsigned_char_variable, 1); c++ will convert it implicitly to int when you need int like int_variable = unsigned_char_variable; – Öö Tiib Jul 29 '19 at 18:10
  • @ÖöTiib Awesome, it works! well sort of.. When I tried your suggestion, I got an error msg saying I cannot use identifier unsigned char as an parameter for read function. So I tried it with char * with size of 1, and changed it to integer variable and finally for the first time got an integer value. Although, it is signed so i'll have to manually add 128 to get all positive pixel values. I can use for loop to read all 64*64 integers and add 128 to each of them, now, but I am wondering if there wou;d be a more elegant solution to this. Sorry to bother you but do you have any other suggestion? – Jaewon Lee Jul 29 '19 at 18:46
  • uhh, you need first to declare it like all variables for example as `unsigned char unsigned_char_variable;` Find yourself some good textbook about C++, it is too complex to learn by trial and error. – Öö Tiib Jul 29 '19 at 19:07
  • @ÖöTiib I did declare first, but the read member function won’t take unsigned char type variable as the first parameter... – Jaewon Lee Jul 29 '19 at 19:14
  • Did you omit the character & in `inf.read(&unsigned_char_variable, 1);` that I suggested? – Öö Tiib Jul 29 '19 at 19:17
  • @ÖöTiib I didn’t. I put & as well, and still not working! – Jaewon Lee Jul 29 '19 at 19:20
  • Hmm then it should be `inf.read((char*)&unsigned_char_variable, 1);` – Öö Tiib Jul 29 '19 at 19:23
  • Works like a charm. I appreciate man hope you have a great day! – Jaewon Lee Jul 29 '19 at 19:24

0 Answers0