C ++: записать ошибку формата изображения BMP в WINDOWS

У меня самая странная проблема здесь … Я использую тот же код (копировать-вставить) из Linux в Windows, чтобы ЧИТАТЬ а также ЗАПИСЫВАТЬ а также BMP образ. И по какой-то причине в Linux все работает прекрасно, но когда я прихожу к Windows 10 из некоторых я не могу открыть эти изображения, и я получаю сообщение об ошибке, как сказал что-то вроде этого:

«Похоже, мы не поддерживаем этот формат файла».

Ты хоть представляешь, что мне делать? Я поставлю код ниже.

РЕДАКТИРОВАТЬ:

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

struct BMP {
int width;
int height;
unsigned char header[54];
unsigned char *pixels;
int size;
int row_padded;
};

void writeBMP(string filename, BMP image) {
string fileName = "Output Files\\" + filename;
FILE *out = fopen(fileName.c_str(), "wb");
fwrite(image.header, sizeof(unsigned char), 54, out);

unsigned char tmp;
for (int i = 0; i < image.height; i++) {
for (int j = 0; j < image.width * 3; j += 3) {
// Convert (B, G, R) to (R, G, B)
tmp = image.pixels[j];
image.pixels[j] = image.pixels[j + 2];
image.pixels[j + 2] = tmp;
}
fwrite(image.pixels, sizeof(unsigned char), image.row_padded, out);
}
fclose(out);
}

BMP readBMP(string filename) {
BMP image;
string fileName = "Input Files\\" + filename;
FILE *f = fopen(fileName.c_str(), "rb");

if (f == NULL)
throw "Argument Exception";

fread(image.header, sizeof(unsigned char), 54, f); // read the 54-byte header

// extract image height and width from header
image.width = *(int *) &image.header[18];
image.height = *(int *) &image.header[22];

image.row_padded = (image.width * 3 + 3) & (~3);
image.pixels = new unsigned char[image.row_padded];
unsigned char tmp;

for (int i = 0; i < image.height; i++) {
fread(image.pixels, sizeof(unsigned char), image.row_padded, f);
for (int j = 0; j < image.width * 3; j += 3) {
// Convert (B, G, R) to (R, G, B)
tmp = image.pixels[j];
image.pixels[j] = image.pixels[j + 2];
image.pixels[j + 2] = tmp;
}
}
fclose(f);
return image;

}

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

Спасибо за помощь

0

Решение

Проверьте заголовок

заголовок должен начинаться со следующих двух подпись байт: 0x42 0x4D, Если это что-то другое, стороннее приложение подумает, что этот файл не содержит изображения bmp, несмотря на расширение файла .bmp.

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

Кроме того, размер заголовка зависит также от Версия BMP вы используете, который вы можете обнаружить с помощью 4-байтовое целое число со смещением 14.

Улучши свой код

При загрузке файла проверьте подпись, версию bmp, количество бит на пиксель и степень сжатия. В целях отладки рассмотрите дамп заголовка, чтобы проверить его вручную:

for (int i=0; i<54; i++)
cout << hex << image.header[i] << " ";`
cout <<endl;

Кроме того, когда вы fread() убедитесь, что количество прочитанных байтов соответствует размеру, который вы хотите прочитать, поэтому убедитесь, что вы не работаете с данными неинициализированного буфера.

Редактировать:

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

image.row_padded = (image.width * 3 + 3) & (~3);     // ok size of a single row rounded up to multiple of 4
image.pixels = new unsigned char[image.row_padded];  // oops !  A little short ?

На самом деле вы читаете построчно, но в памяти остается только последний! Это отличается от вашей первой версии, где вы прочитали все пиксели картинки.

Точно так же вы записываете в последнем ряду повторенное время высот

Пересмотрите свой отступ, работая с общим размером дополнения.

image.row_padded = (image.width * 3 + 3) & (~3);     // ok size of a single row rounded up to multiple of 4
image.size_padded = image.row_padded * image.height;  // padded full size
image.pixels = new unsigned char[image.size_padded];  // yeah !
if (fread(image.pixels, sizeof(unsigned char), image.size_padded, f) !=  image.size_padded) {
cout << "Error: all bytes couldn't be read"<<endl;
}
else {
... // process the pixels as expected
}
...
1

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

Других решений пока нет …