Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > чтение BITMAPFILEHEADER


Автор: _hunter 31.5.2004, 11:41
как его правильно читать?
я делаю так:

BITMAPFILEHEADER FileHeader;
std::ifstream DataFile;
DataFile.open("data.bmp", std::ios::in | std::ios::binary);
DataFile.seekg(0);
DataFile.read((char*)(&Header), sizeof(Header));

и в результате бред получаю sad.gif

Заранее благодарю за ответ.

Автор: AndyY 31.5.2004, 12:36
примерно так и читать.
только ifstream на мой взгляд - наиболее кривой способ.
file mapping куда красивей.

потом нужно не забыть прыгнуть на bfOffBits

Автор: _hunter 31.5.2004, 14:10
примерно так и читаю smile.gif
но как было написанно -- получаю бред: второй Reserved не ноль и размер за два гига sad.gif

P.S.
когда описываю структуру вручную и ставлю выравнивание в байт -- все работает.

P.P.S.
а как из мапа читать?

Автор: AndyY 31.5.2004, 14:43
HANDLE hfile = ::CreateFile( ... )
HANDLE hmap = ::CreateFileMapping( hfile, ... )
void *ptr = ::MapViewOfFile( hmap, ... )

BITMAPFILEHEADER *pbmif = (BITMAPFILEHEADER*)ptr;
дальше работаем как с памятью.

выравнивание не должно сказываться - оно влияет на хвост структуры.
bfType точно BM?

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

Автор: _hunter 31.5.2004, 15:27
буду пробовать через мапы

Type точно BM а потом -- бред: bfSize - 0

Автор: AndyY 31.5.2004, 15:43
только что обратил внимание - у тебя декларирован FileHeader, а читаешь ты Header.
может это и есть бага?

Автор: _hunter 31.5.2004, 15:45
сделал с мапами -- результат аналогичный sad.gif
( причем полностью аналогичный -- значения полей равны что для варианта с ifstream, что для CreateFile / ReadFile, что для CreateFileMapping / MapViewOfFile )
так что собака, похоже, зарыта в другом месте smile.gif
Добавлено @ 15:48
AndyY
это я куски из разных мест вырезал -- ошибся sad.gif
на самом деле читаю FileHeader
( да и такой: BITMAPFILEHEADER *pbmif = (BITMAPFILEHEADER*)ptr; вариант не проходил sad.gif( )

Автор: AndyY 31.5.2004, 15:57
а в файле-то что записано?
там должно быть:
WORD bfType;
это 'BM', 2 байта
DWORD bfSize;
размер, 4 байта
WORD bfReserved1;
WORD bfReserved2;
еще 4 0
DWORD bfOffBits;
и 4 байта - смещение.

посмотри в любом hex редакторе.
может это не битмап?smile.gif. помнится был флейм про то что если bfOffBits > 0x80000000 то переполнение стека в iexplore и можно свой код запустить.

Автор: _hunter 31.5.2004, 16:14
да битмап это, битмап -- сам создал smile.gif
и структура у него -- правильная ( проверял smile.gif )
проблема именно при чтении ( похоже WORD bfType; всю малину портит )

Автор: AndyY 1.6.2004, 10:33
может какая-то проблема с компилятором просто?
или WORD переопределен как DWORD?
используется MSVC?

потому что код очевиден и структура должна размещаться в памяти именно так как описана.

Автор: _hunter 1.6.2004, 16:22
компилятор -- C++ Builder 6

вот кусок из заголовка:
Код
#include <pshpack2.h>
typedef struct tagBITMAPFILEHEADER {
       WORD    bfType;
       DWORD   bfSize;
       WORD    bfReserved1;
       WORD    bfReserved2;
       DWORD   bfOffBits;
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
#include <poppack.h>

Автор: AndyY 1.6.2004, 19:51
тест на вшивость компилятора:

int offset_fize = int(&(BITMAPFILEHEADER*)0)->bfSize);
int offset1 = int(&(BITMAPFILEHEADER*)0)->bfReserved1);
int offset2 = int(&(BITMAPFILEHEADER*)0)->bfReserved2);
int offset_off = int(&(BITMAPFILEHEADER*)0)->bfOffBits);

значения - в студию!

Автор: cardinal 1.6.2004, 20:04
что такое BYTE, BOOL, DWORD и WORD:
Код
typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;

загрузка файла в буфер:
Код

                   BYTE gbuf["размез буфера"];
CFile f;

f.Open("название файла", CFile::modeRead);
f.Read(gbuf, f.GetLength());
f.Close();

структуры BMPFILEHEADER и BMPINFOHEADER:
Код
typedef struct tagBMPFILEHEADER { // bmfh
   WORD    bfType;
   DWORD   bfSize;
   WORD    bfReserved1;
   WORD    bfReserved2;
   DWORD   bfOffBits;
} BMPFILEHEADER;

typedef struct tagBMPINFOHEADER{ // bmih
   DWORD  biSize;
   int    biWidth;
   int    biHeight;
   WORD   biPlanes;
   WORD   biBitCount;
   DWORD  biCompression;
   DWORD  biSizeImage;
   int    biXPelsPerMeter;
   int    biYPelsPerMeter;
   DWORD  biClrUsed;
   DWORD  biClrImportant;
} BMPINFOHEADER;

читаешь из gbuf в структуры:
Код
BMPFILEHEADER psf;
BMPINFOHEADER psi;

psf = *((BMPFILEHEADER*)gbuf);
psi = *((BMPINFOHEADER*)(gbuf+sizeof(psf)));

Автор: AndyY 1.6.2004, 20:48
cardinal
если бы все было так просто... я подозреваю глюк компилера.

si = *((BMPINFOHEADER*)(gbuf+sizeof(psf)));
это - неверно, нужно учитывать bfOffBits;

Автор: cardinal 1.6.2004, 22:20
Цитата
si = *((BMPINFOHEADER*)(gbuf+sizeof(psf)));
это - неверно, нужно учитывать bfOffBits;

Ты мой вариант попробовал или просто так сказал, что неверно. Я тебе дал кусок работающей проги. Я компилировал в Microsoft Visual C++ 6.0.
Цитата
если бы все было так просто...

Все на самом деле именно так просто и есть.

Сделай простой проектик и вставь туда то, что я тебе дал. Должно работать!

Автор: AndyY 2.6.2004, 00:10
cardinal
пробовал конечно. работает, но не всегдаsmile.gif - некоторые проги пишут левую инфу перед непосредственно дибом. фиксиsmile.gif

у меня в vc все работает. у человека глючит builder при врубленном выравнивании структур - вот и копаем, глюк кода или компилера. почитай внимательно тред.

Автор: cardinal 2.6.2004, 13:38
Цитата
некоторые проги пишут левую инфу перед непосредственно дибом.

А что именно?
Цитата
выравнивании структур

А это что? Просвети плиз.

Автор: AndyY 2.6.2004, 14:57
cardinal
вспомнил. bitmapinfoheader лежит за bitmafileheader - это правда.
неправда то, что за bitmapinfoheader сразу лежит диб даже при отсутствии паллитры.
впрочем, hunter видно и сам разобрался с проблемой, а мне вопрос чтения дибов неинтересен - будет надо - вопросов не возникнет.

Автор: cardinal 2.6.2004, 15:22
Цитата
неправда то, что за bitmapinfoheader сразу лежит диб даже при отсутствии паллитры.

Я такого не говорил.

Вот структура bmp:
http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html

Автор: Sined 3.6.2004, 12:57
Ya,Ya глюк кмопилера меняй старший-младший байт(в каждом считанном слове) местами. Если самзаголовок делал под MSVC, то такое наверняка поможет.

Автор: _hunter 3.6.2004, 16:02
код еще не пробывал ( приду домой -- проверю ) но сразу вопрос:
bfType -- WORD, из за выравнивания он приводится к DWORD соответсвенно все следующие за ним значения плывут.
даже при таком присвоении: psf = *((BMPFILEHEADER*)gbuf);
два байта уйдут не по адресу sad.gif

я прав?

Автор: cardinal 3.6.2004, 16:43
Цитата
из за выравнивания он приводится к DWORD

я выше уже спрашивал, что такое выравнивание, но никто нчиего не объяснил bored.gif.

А вообще что это такое
Цитата
bfType -- WORD, из за выравнивания он приводится к DWORD соответсвенно все следующие за ним значения плывут.

программируешь ты или твой компилятор? Конечно след. значения плывут если ты меняшь структуру struct. Я в шоке smile.gif

Автор: _hunter 3.6.2004, 16:58
программирую то я smile.gif, но MS в .h прописали -- выравнивание по DWORD' y -- и единственный путь -- править wingdi.h -- что не есть првильно

выравнивание -- дополнение нулями полей стрктур до определенного размера -- 1, 2, 4, 8 байт
т.е. структура {char a, WORD b} в памяти выглядит так( с выравниванием по 1):
a - один байт b - два байта идут последовательно
а с выравниванием 2:
a - два байта b - два байта

как смог -- так объяснил smile.gif

Автор: cardinal 3.6.2004, 19:10
Аааа, вспомнил smile.gif. Есть такая параша как pragma. Напиши так, как в примере ниже и будет все выравниваться по 1.
Код
#pragma pack (push)
#pragma pack (1)

typedef struct tagPALETTE { // rgbq
   BYTE    rgbBlue;
   BYTE    rgbGreen;
   BYTE    rgbRed;
   BYTE    rgbReserved;
} PALETTE;
 
typedef struct tagBMPFILEHEADER { // bmfh
   WORD    bfType;
   DWORD   bfSize;
   WORD    bfReserved1;
   WORD    bfReserved2;
   DWORD   bfOffBits;
} BMPFILEHEADER;

typedef struct tagBMPINFOHEADER{ // bmih
   DWORD  biSize;
   int    biWidth;
   int    biHeight;
   WORD   biPlanes;
   WORD   biBitCount;
   DWORD  biCompression;
   DWORD  biSizeImage;
   int    biXPelsPerMeter;
   int    biYPelsPerMeter;
   DWORD  biClrUsed;
   DWORD  biClrImportant;
} BMPINFOHEADER;

#pragma pack (pop)

Автор: _hunter 4.6.2004, 17:30
дык это не есть правильное решение т.к. нужно править или заголовок от MS или писать свой

Автор: cardinal 4.6.2004, 17:41
Цитата
нужно править или заголовок от MS или писать свой

И это будет правильней?

Хотелось бы что-нибудь от других услышать по этому поводу, а вообще мне кажется что ты _hunter из мухи слона делаешь. Правильное или неправильное решение - работает ведь, что еще надо?

Автор: AndyY 4.6.2004, 19:44
к слову о выравнивании. вот что пишет ms:

Цитата

When you use #pragma pack(n), where n is 1, 2, 4, 8, or 16, each structure member after the first is stored on the smaller member type or n-byte boundaries.


то есть pragma pack(4) влияет только на поля структуры более 4 байт.
соответственно, все должно собираться и с заголовком от ms

Автор: _hunter 4.6.2004, 19:55
кто ж спорит smile.gif
только такой код:
Код
#include <pshpack2.h>
typedef struct tagBITMAPFILEHEADER {
       WORD    bfType;
       DWORD   bfSize;
       WORD    bfReserved1;
       WORD    bfReserved2;
       DWORD   bfOffBits;
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
#include <poppack.h>

ровняется по DWORD' y sad.gif
( почем -- не знаю )

Автор: cardinal 5.6.2004, 02:04
Еще раз даю тебе кусок работающей проги.
Код
#pragma pack (push)
#pragma pack (1)

typedef struct tagPALETTE { // rgbq
  BYTE    rgbBlue;
  BYTE    rgbGreen;
  BYTE    rgbRed;
  BYTE    rgbReserved;
} PALETTE;

typedef struct tagBMPFILEHEADER { // bmfh
  WORD    bfType;
  DWORD   bfSize;
  WORD    bfReserved1;
  WORD    bfReserved2;
  DWORD   bfOffBits;
} BMPFILEHEADER;

typedef struct tagBMPINFOHEADER{ // bmih
  DWORD  biSize;
  int    biWidth;
  int    biHeight;
  WORD   biPlanes;
  WORD   biBitCount;
  DWORD  biCompression;
  DWORD  biSizeImage;
  int    biXPelsPerMeter;
  int    biYPelsPerMeter;
  DWORD  biClrUsed;
  DWORD  biClrImportant;
} BMPINFOHEADER;

#pragma pack (pop)

У тебя это не работает или ты такой вариант не хочешь потому, что он "неправильный"? Если "неправильный" то объясни почему.

Автор: _hunter 5.6.2004, 14:05
да я так и делаю ( просто других путей пока не вижу ), но считаю его неправильным ( скорее некрасивым smile.gif ).
Почему? Т.к. нужно писать свои структуры вместо существующих ( Не плодите сущностей сверх
меры ). Это что-то типа INT да BOOL получается smile.gif

Автор: cardinal 5.6.2004, 17:19
Цитата
Т.к. нужно писать свои структуры вместо существующих

Вот этого я не понял... bored.gif

Автор: _hunter 5.6.2004, 17:27
тот код, что ты предлагаеш нужно записать куда-то ( в файл желательно smile.gif ) -- это будет своя структура. вместо существующей -- уже есть аналогичная
так примерно smile.gif

Автор: cardinal 5.6.2004, 17:33
а где она есть?

Автор: _hunter 5.6.2004, 17:48
приплыли smile.gif
wingdi.h
typedef struct tagBITMAPFILEHEADER {

Автор: cardinal 5.6.2004, 18:42
Цитата
приплыли smile.gif

Ну я просто спросил потому, что лень искать было smile.gif
Вообще я взял структуру bmp или из MSDN или из инета.

Когда я делал процедуру для одной встроенной системы в принтере, то никаким wingdi.h не пользовался потому, что моя процедура вообще не в windows выполнялась, а прямо в принтере. Зачем мне wingdi.h?

Тебе что-то надо еще в wingdi.h кроме структуры BITMAPFILEHEADER? Если нет, то зачем она вообще нужна, тем более что с ней возникают сплошные проблемы.

Я сделал просто файл bmpstruct.h и включаю его в те проекты, в которых работаю с bmp файлами.

Помоему мы дошли до того, что просто надо найти ответ на вопрос "Что лучше и правильней - использовать wingdi.h или свой собственный header файл, в котором ничего ненужного нет?" smile.gif Может отдельный топик сделать?

Автор: _hunter 5.6.2004, 22:36
"приплыли" -- это к тому, что выше я уже приводил и эту структуру и то, что она стандартная smile.gif

свой собственный header файл -- как я уже писал "не плодите сущностей без меры" smile.gif но в принципе можно и к такому вопросу свести smile.gif


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)