2016-06-06 3 views
0

Я пытаюсь получить количество бит на пиксель в BMP-файле. Согласно Википедии, он должен быть на 28-м байте. Таким образом, после чтения файла:C++ - Чтение количества бит на пиксель из файла BMP

// Przejscie do bajtu pod ktorym zapisana jest liczba bitow na pixel 
     plik.seekg(28, ios::beg); 

     // Read number of bytes used per pixel 
     int liczbaBitow; 
     plik.read((char*)&liczbaBitow, 2); 

     cout << "liczba bitow " << liczbaBitow << endl; 

Но liczbaBitow (переменная, которая должна удерживать количество бит на значение пикселя) является -859045864. Я не знаю, откуда это происходит ... Я довольно потерян.

Любые идеи?

+0

Необходимо показать, как файл был открыт.Был ли он открыт с использованием флага 'ios :: binary'? – PaulMcKenzie

+0

Вы помещаете два байта в единичное (возможно, 4 байта) целое число. Попробуйте инициализировать 'liczbaBitow' до нуля в качестве первого шага. – Machtl

+0

Формат [формат растрового файла] (https://msdn.microsoft.com/en-us/library/dd183391.aspx) ** слишком сложный **, чтобы написать собственный синтаксический анализатор. Используйте библиотеку, встроенную в вашу платформу, или стороннюю библиотеку. – IInspectable

ответ

2

-859045864 можно представить в шестнадцатеричном виде как 0xCCCC0018.

Чтение второго байта дает нам 0x0018 = 24bpp.

Что, скорее всего, происходит здесь, это то, что liczbaBitow инициализируется 0xCCCCCCCC; в то время как ваш plik.read записывает только младшие 16 бит и не меняет верхние 16 бит. Изменение этой линии должно решить эту проблему:

int liczbaBitow = 0;

Хотя, особенно с чем-то вроде этого, то лучше использовать тип данных, который точно соответствует вашим данным:

int16_t liczbaBitow = 0;

Это может быть найдено в <cstdint>.

+1

Вы можете добавить, что компилятор msvc в режиме отладки инициализирует интегральные типы с помощью '0xCCCCCCCC' или более, в зависимости от типа. – Machtl

+1

@Machtl Спасибо, я добавил больше подробностей, объясняющих ответ. – Thebluefish

+0

Спасибо большое, ребята! Действительно ценю это. – MindRoller

3

Для уточнения @ ответ TheBluefish, этот код имеет ошибку

// Read number of bytes used per pixel 
int liczbaBitow; 
plik.read((char*)&liczbaBitow, 2); 

При использовании (char*)&libczbaBitow, вы принимаете адрес 4 байта целое, и, говоря код поставить 2 байта там.

Остальные два байта этого целого числа являются неуказанными и неинициализированными. В этом случае они равны 0xCC, потому что это значение инициализации стека, используемое системой.

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

Если вы инициализируете переменную, вы получите ожидаемое значение.

Но есть еще одна ошибка. Здесь также есть порядок байтов. Этот код предполагает, что собственный байтовый порядок машины точно соответствует порядку байтов из спецификации файла. Есть целый ряд различных растровых форматов, но с вашей ссылки, в статье Википедии говорит:

Все целых значений сохраняются в маленьком формате обратного порядка байт (то есть наименее значащий байт первый).

Это то же самое, что и у вас, что, очевидно, тоже x86 малое. Другие поля не определены как маленькие, так как вы приступаете к декодированию изображения, вам придется следить за ним.

В идеале вы читали в байтовый массив и помещали байты, в которых они принадлежат. См. Convert Little Endian to Big Endian

int libczbaBitow; 
unsigned char bpp[2]; 
plik.read(bpp, 2); 
libczbaBitow = bpp[0] | (bpp[1]<<8); 
Смежные вопросы