Проблемы с записью BMP файла
От: wbear  
Дата: 06.09.22 09:52
Оценка:
Добрый день.
Помогите разобраться в вопросе определения длины файла BMP.

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

Одной из команд сервера является передача растрового файла в формате BMP. И вот возникла проблема с сохранением данных в файл формата BMP.

Приведу пример первых 54 байт получаемых данных из потока:
0x4D42 ; bfType
0x0000518E ; bfSize
0x00000000 ; bfReserved
0x00000436 ; bfOffBits
0x00000028 ; biSize
0x0000018A ; biWidth
0x00000032 ; biHeght
0x0001 ; biPlanes
0x0008 ; biBitCount
0x00000000 ; biCompression
0x00004D58 ; biSizeImage
0x00000EC4 ; biXPilsPerMeter
0x00000EC4 ; biYPilsPerMeter
0x00000000 ; biClrUsed
0x00000000 ; biClrImportant

Алгоритм такой, анализируем первые 54 байта. В поле bfSize указывается весь размер данных(размер файла BMP). На основании этого числа за вычетом (54) считываем из потока нужное количество байт. Записываем заголовок + считанные данные в файл и должен получиться графический файл в формате BMP.

Но что-то не так получается. Просмотреть файл в графическом вьювере не получается, пишет ошибка.

Предполагаю, что неправильно определяю длину данных.

На основании данных из заголовка пытаюсь альтернативным способом определить длину данных и результат вычисления не совпадает с bfSize.
bfSize = biSizeImage + 54

Как правильно определить длину.

К серверу доступа нет. Посмотреть файл BMP до передачи по сети тоже нет возможности.
Re: Проблемы с записью BMP файла
От: DiPaolo Россия  
Дата: 06.09.22 10:11
Оценка:
W>Приведу пример первых 54 байт получаемых данных из потока:
W>0x4D42 ; bfType
W>0x0000518E ; bfSize
W>0x00000000 ; bfReserved
W>0x00000436 ; bfOffBits
W>0x00000028 ; biSize
W>0x0000018A ; biWidth
W>0x00000032 ; biHeght
W>0x0001 ; biPlanes
W>0x0008 ; biBitCount
W>0x00000000 ; biCompression
W>0x00004D58 ; biSizeImage
W>0x00000EC4 ; biXPilsPerMeter
W>0x00000EC4 ; biYPilsPerMeter
W>0x00000000 ; biClrUsed
W>0x00000000 ; biClrImportant

Первое, что бросается в глаза: неверный порядок байт. В оригинале должен быть 0x42 0x4D. Может не переводите (или наоборот, переводите) из/в сетевого порядка в обычный?
Патриот здравого смысла
Re: Проблемы с записью BMP файла
От: kov_serg Россия  
Дата: 06.09.22 12:01
Оценка:
Здравствуйте, wbear, Вы писали:

W>Суть вот в чем, по каналу связи принимается байтовый поток(данные) от сервера. Данные представляют собой команды и последовательность данных. Приняв порцию данных, определяем тип команды. В зависимости от типа команды сохраняем полученные данные в файл.


W>Одной из команд сервера является передача растрового файла в формате BMP. И вот возникла проблема с сохранением данных в файл формата BMP.



W>Алгоритм такой, анализируем первые 54 байта. В поле bfSize указывается ...

А нафига козе баян? Если вы принимаете поток данных от сервера там и должна быть длинна. Зачем вы анализируете принятые данные? Это же совсем другой уровень.

W>Как правильно определить длину.

Она должна приходить от сервера, и не зависить от того bmp это или webp или какой еще тип данных.

W>К серверу доступа нет. Посмотреть файл BMP до передачи по сети тоже нет возможности.

Могу предположить что вы записываете данные в файл не так как они пришли. В C++ для этого есть множество возможностей
Re[2]: Проблемы с записью BMP файла
От: denis.st Россия  
Дата: 06.09.22 12:38
Оценка:
W>>0x4D42 ; bfType
DP>Первое, что бросается в глаза: неверный порядок байт. В оригинале должен быть 0x42 0x4D. Может не переводите (или наоборот, переводите) из/в сетевого порядка в обычный?
это же обычный uint16 считанный как LE
Re: Проблемы с записью BMP файла
От: denis.st Россия  
Дата: 06.09.22 13:38
Оценка:
W>Алгоритм такой, анализируем первые 54 байта. В поле bfSize указывается весь размер данных(размер файла BMP). На основании этого числа за вычетом (54) считываем из потока нужное количество байт. Записываем заголовок + считанные данные в файл и должен получиться графический файл в формате BMP.
Зачем 54 байта? Проверить первые два байта подходящие 0x42 и 0x4D, затем взять следующие 4 байта длины, и сохранить указанное количество включая эти первые 6 байт. Типа такого:

1. копим буфер пока не наберётся как минимум 6 байт, допустим считалось len
2. проверяем 0x4D42 == (uint16_t&)buf[0]
3. получаем total = (uint32_t&)buf[2]
4. записываем в файл содержимое буфера длиной min(total, len)
5. копируем из потока в файл ещё total — min(total, len) байт

W>На основании данных из заголовка пытаюсь альтернативным способом определить длину данных и результат вычисления не совпадает с bfSize.

W>bfSize = biSizeImage + 54
Конечно не совпадает, ибо bfSize = bfOffBits + biSizeImage. Там после заголовка ещё палитра может быть и какой-то ещё хлам.
Re: Проблемы с записью BMP файла
От: alexander_r  
Дата: 06.09.22 13:54
Оценка:
Здравствуйте, wbear, Вы писали:

W>Добрый день.

W>Помогите разобраться в вопросе определения длины файла BMP.

W>Суть вот в чем, по каналу связи принимается байтовый поток(данные) от сервера. Данные представляют собой команды и последовательность данных. Приняв порцию данных, определяем тип команды. В зависимости от типа команды сохраняем полученные данные в файл.


W>Одной из команд сервера является передача растрового файла в формате BMP. И вот возникла проблема с сохранением данных в файл формата BMP.


W>Приведу пример первых 54 байт получаемых данных из потока:

W>0x4D42 ; bfType
W>0x0000518E ; bfSize
W>0x00000000 ; bfReserved
W>0x00000436 ; bfOffBits
W>0x00000028 ; biSize
W>0x0000018A ; biWidth
W>0x00000032 ; biHeght
W>0x0001 ; biPlanes
W>0x0008 ; biBitCount
W>0x00000000 ; biCompression
W>0x00004D58 ; biSizeImage
W>0x00000EC4 ; biXPilsPerMeter
W>0x00000EC4 ; biYPilsPerMeter
W>0x00000000 ; biClrUsed
W>0x00000000 ; biClrImportant

W>Алгоритм такой, анализируем первые 54 байта. В поле bfSize указывается весь размер данных(размер файла BMP). На основании этого числа за вычетом (54) считываем из потока нужное количество байт. Записываем заголовок + считанные данные в файл и должен получиться графический файл в формате BMP.


W>Но что-то не так получается. Просмотреть файл в графическом вьювере не получается, пишет ошибка.


W>Предполагаю, что неправильно определяю длину данных.


W>На основании данных из заголовка пытаюсь альтернативным способом определить длину данных и результат вычисления не совпадает с bfSize.

W>bfSize = biSizeImage + 54

W>Как правильно определить длину.


W>К серверу доступа нет. Посмотреть файл BMP до передачи по сети тоже нет возможности.


https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapfileheader

bfSize
The size, in bytes, of the bitmap file.

bfOffBits
The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.


bfSize = bfOffBits + biSizeImage

20878 = 1078 + 19800 те. весь файл 20878, заголовок 1078, rgb 19800, все вроде бы сходится
можно попробовать сохранить данные без заголовка и потом посмотреть их каким нибудь редактором в сыром виде
Re[2]: Проблемы с записью BMP файла
От: wbear  
Дата: 15.09.22 13:46
Оценка:
Здравствуйте, kov_serg, Вы писали:


W>>Алгоритм такой, анализируем первые 54 байта. В поле bfSize указывается ...

_>А нафига козе баян? Если вы принимаете поток данных от сервера там и должна быть длинна. Зачем вы анализируете принятые данные? Это же совсем другой уровень.
Сервер просто отправляет в сеть информацию. Разработчика создали вот такой протокол со своей спецификой передаваемых данных. Задача стоит в том чтобы разобраться с передаваемыми данными.



W>>Как правильно определить длину.

_>Она должна приходить от сервера, и не зависить от того bmp это или webp или какой еще тип данных.
Общий пакет содержит и длину данных и CRC для проверки целостности данных. Там все впорядке.

W>>К серверу доступа нет. Посмотреть файл BMP до передачи по сети тоже нет возможности.

_>Могу предположить что вы записываете данные в файл не так как они пришли. В C++ для этого есть множество возможностей
Как оказалось делаю все правильно. Просто разработчики системы определили что файл BMP является контейнером для хранения структурированных данных. О чем на момент написания первичного поста я не знал. И предолагал что должен после записи данных в файл увидеть что то "внятное". Оказалось что это не так
Re[2]: Проблемы с записью BMP файла
От: wbear  
Дата: 15.09.22 13:49
Оценка:
Здравствуйте, denis.st, Вы писали:


DS>Зачем 54 байта? Проверить первые два байта подходящие 0x42 и 0x4D, затем взять следующие 4 байта длины, и сохранить указанное количество включая эти первые 6 байт. Типа такого:

Анализ первых 54 байт делается в отладочных целях. Просто можно сразуже на глаз определить что считанные данные являются заголовком BMP файла или же это является мусором.
Re[2]: Проблемы с записью BMP файла
От: wbear  
Дата: 15.09.22 13:53
Оценка:
Здравствуйте, alexander_r, Вы писали:

_>bfSize = bfOffBits + biSizeImage


_>20878 = 1078 + 19800 те. весь файл 20878, заголовок 1078, rgb 19800, все вроде бы сходится


Спасибо. Просто за несколько дней глаз замылился на данных и коде.
Хороший сон и кружка горячего шоколада позволили оценить свою бестолковость.

_>можно попробовать сохранить данные без заголовка и потом посмотреть их каким нибудь редактором в сыром виде


Разработчики системы определили что файл BMP является контейнером для хранения структурированных данных. О чем на момент написания первичного поста я не знал. И предолагал что должен после записи данных в файл увидеть что то "внятное". Оказалось что это не так.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.