0

I have 8 bit raw data representing a grayscale image (int value 0-255) in a file looking like this:

0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 001c 354d 6576 8797
9fa4 a7a4 864b 252e 5973 7673 7b86 7e6d
6164 6c7a 8b98 a2ac b8bd ae96 857f 6d40
1d14 160b 0000 0000 0000 0000 0000 0000

and i need to read them and print their int value (0-255). I try this, but all result looks like this: 0020 0a00 2000 2000 2000 2000 2000 2000 I dont know what is wrong, fopen as binary file is OK?

FILE * pFile;
pFile = fopen(inFileName.c_str(), "rb");
if (pFile==NULL){
    cerr << "erro" << endl;
}

uint8_t bufferImmagine[height*width];
fread(bufferImmagine,1,height*width,pFile);

fclose (pFile);
for (int i = 0; i < height*width; ++i)
{
   cout << bufferImmagine[i] << " ";
}
adamc9988
  • 1
  • 2
  • 3
    `uint8_t bufferImmagine[height*width];` isn't valid standard c++ code. – πάντα ῥεῖ Apr 19 '19 at 18:45
  • 1
    This is a strange mix of C++ (`cout`) and C (`fread`). Consider using more [idiomatic C++](https://stackoverflow.com/questions/15138785/how-to-read-a-file-into-vector-in-c) and C++ Standard Library containers like `std::vector` or `std::array`. – tadman Apr 19 '19 at 18:52
  • How many pixels wide and how many pixels tall is your image? And what is the size of the file in bytes? – Mark Setchell Apr 19 '19 at 19:17
  • it is variable but for example width = height = 412 px – adamc9988 Apr 20 '19 at 04:53
  • Would you be able to answer the other part of my question too please? And please make sure you tell me the filesize corresponding to the pixel dimensions you gave. Thank you. – Mark Setchell Apr 21 '19 at 18:22
  • Can you share an actual file please rather than an imitation version? With pixel dimensions. – Mark Setchell Apr 21 '19 at 18:25

2 Answers2

0

So bufferImmagine is an array of type uint8_t, and on many platforms uint8_t is an alias for unsigned char. When you stream unsigned char into std::cout, the stream treats it like a character, rather than a number.

If you want to print out each byte as a number 0-255, convert each byte to a wider integral type, like unsigned:

std::cout << static_cast<unsigned int>(bufferImmagine[i]) << " ";
Jack C.
  • 744
  • 3
  • 7
  • it looks like it works, but only at the end of the file. The first 400 lines are all zeros and that's wrong. I dont know why. Looks like a buffer or fread problem – adamc9988 Apr 20 '19 at 04:57
  • I can't see anything in the code that is posted that would cause a misread at the beginning of the file specifically. Some things I would look at debugging this: (1) Does the input file really not have 400 lines of zeros at the front? (2) Does height*width equal the size of the file? (3) As others point out, does the return value of fread indicate all bytes are read? – Jack C. Apr 23 '19 at 01:25
0

I see a few potential problems with the code:

1) As mentioned in the comments, uint8_t bufferImmagine[height*width]; is problematic, in that C++ doesn't support variable-length arrays, so unless height and width can be made into compile-time constants, it would be better to use a std::vector instead (or if you are allergic to data structures you could allocate an array with the new operator, but then you risk leaking memory if you aren't very careful).

2) Depending on the values of width and height, the size of bufferImmagine could be quite large; possibly larger than the amount of stack space available. Another reason to use std::vector or allocate on the heap, instead.

3) You never check the return value of the fread() call to see if it read all of the data, or not. It might be reading fewer bytes than you asked it to read (most likely because the file you're reading isn't long enough), but without checking the value you won't know anything has gone wrong, so you'll be very confused if/when an error occurs.

4) As Jack C. mentioned in his answer, cout may print out uint8_t's as ASCII characters rather than integers, which isn't what you want here.

5) Not really a problem, but if you'd like the rows of your output to correspond to the rows-of-pixels in your file, then you'll want to apply carriage returns at the end of each 'row'. E.g.:

int i = 0;
for (int y = 0; y < height; y++)
{
   for (int x = 0; x < width; x++)
   {
      const unsigned int iVal = bufferImmagine[i];
      cout << iVal << " ";
      i++;
   }  
   cout << endl;
}  
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234