Reputation: 1
this is my first Post as I came along with using the search function so far. But now I wasted a whole day on the following issue:
I recorded a 12bit (written as 16bit) grayscale video and wrote it directly into a binary stream-file (no headers or such).
Now the task is to read the file and output every frame as a 16bit pgm.
The following snipped illustrates what i tried. The output is a valid pgm, but whith "white noise on it".
...
imageBufferShort = new short[imageWidth*imageHeight* sizeof(short)];
...
streamFileHandle.read(reinterpret_cast<char*>(imageBufferShort),2*imageWidth*imageHeight); //double amount because 8bit chars!
// As .read only takes chars, I thought, that I just read the double amount of char-bytes and when it is interpreted as short (=16bit) everything is ok?!?
...now the pgm output:
std::ofstream f_hnd(fileName,std::ios_base::out |std::ios_base::binary |std::ios_base::trunc);
// write simple header
f_hnd.write("P5\n",3);
f_hnd << imageWidth << " " << imageHeight << "\n4095\n"; //4095 should tell the pgm to use 2 bytes for each pixel
f_hnd.write(reinterpret_cast<char*>(imageBufferShort),2*imageWidth*imageHeight);
f_hnd.close();
Again, the file is produced and viewable but contains rubbish. Is the initial guess ok? read 2 "chars" and handle them as one "short"? I also trieb a whitespace after every line but this changes nothing, so I decided to post this shorter code.
Thanks for any help!
Upvotes: 0
Views: 1445
Reputation: 1
Problem Solved. Thank you all very much. The Endianess was indeed the Problem. The solution is given below:
f_hnd << "P5" << " " << imDimensions.GetWidth() << " " << imDimensions.GetHeight() << " " << "4095\n";
// convert imageBufferShort to Big-Endian format
unsigned short imageBufferShortBigEndian[imDimensions.GetWidth()*imDimensions.GetHeight()];
for (int k=0 ; k<imDimensions.GetWidth()*imDimensions.GetHeight() ; k++)
{
imageBufferShortBigEndian[k] = ( (imageBufferShort[k] << 8) | (imageBufferShort[k] >> 8) );
}
f_hnd.write(reinterpret_cast<char*>(imageBufferShortBigEndian),2*imDimensions.GetWidth()*imDimensions.GetHeight());
f_hnd.close();
imageBufferShort has also to an unsigned short-array. If signed types are used, the bitshift-conversion gets slightly more difficult.
Thanks again!
Upvotes: 0
Reputation: 24528
As @Domi and @JoeZ pointed out: Your endianness is probably screwed up. Meaning, the order of your bytes is wrong.
To fix your problem, you will have to iterate over every pixel and swap it's bytes before writing it back to file.
Upvotes: 1