Чтение двоичного 16-битного потокового файла и запись в 16-битный PGM (C ++)

это мой первый пост, поскольку я до сих пор пользовался функцией поиска. Но теперь я потратил целый день на следующую проблему:

Я записал 12-битное (записанное как 16-битное) видео в градациях серого и записал его непосредственно в двоичный потоковый файл (без заголовков или тому подобное).

Теперь задача — прочитать файл и вывести каждый кадр в виде 16-битного pgm.

Следующий отрывок иллюстрирует то, что я пробовал. Вывод является действительным pgm, но с «белым шумом на нем».

    ...
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();

Опять же, файл создается и просматривается, но содержит мусор. Начальная догадка в порядке? читать 2 «символа» и обрабатывать их как один «короткий»? Я также убираю пробел после каждой строки, но это ничего не меняет, поэтому я решил опубликовать этот более короткий код.

Спасибо за любую помощь!

0

Решение

Как указали @Domi и @JoeZ: Ваша последовательность может быть испорчена. Это означает, что порядок ваших байтов неправильный.

Чтобы решить вашу проблему, вам придется перебирать каждый пиксель и менять его байты, прежде чем записать его обратно в файл.

1

Другие решения

Задача решена. Спасибо всем большое. Endianess был действительно проблемой. Решение приведено ниже:

    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 также имеет неподписанный короткий массив. Если используются подписанные типы, преобразование битового сдвига становится немного сложнее.

Еще раз спасибо!

0

По вопросам рекламы [email protected]