Струткутра BMP файла

Как отобразить BMP картинку на эльфе. Руководство от cbn версия 0.1
http://cbn.narod.ru/AboutBMP.txt



1. ОПИСАНИЕ ФОРМАТА BMP
BMP файл начинается с заголовка (см. приложение 1).

Из заголовка вам понадобятся:
int по смещению 18 - ширина изображения, 22 - высота,
10 - начало изображения(от начала файла), 50 - число "важных" цветов палитры, 
short на 28 - бит на пиксел.

После заголовка по смещению 54 начинается палитра цветов (есть только для 8 битных изобр.)
В палитре каждый цвет задается 4 байтами 0RGB. Далее каждое значение цвета представляет 
собой индекс в этой палитре. Сколько всего в палитре цветов задано в int заголовка по смещ. 50

За ней по смещению, заданному в поле 10, расположено само изображение.
Число байт на пиксел считается как число бит/8. Если 1, то это индекс в палитре.
Изображение расположено по строкам, выравненным на границу 4, т.е.
если ширина изобр. некратна 4, то к каждой строке добавл. нули,
например ширина = 13 и режим 8 бит на пиксел - строка занимает 13 байт
- расширяется до 16 байт.
Строки располагаются в обратном порядке, т.е. снизу вверх.


2. ВЫВОД BMP НА ЭКРАН
//В примере TED от Rst7 есть функция вывода имиджа на экран:

void DrwImg(IMGHDR *img, int x, int y, int *pen, int *brush)
{
  RECT rc;
  DRWOBJ drwobj;
  StoreXYWHtoRECT(&rc,x,y,img->w,img->h);
  SetPropTo_Obj5(&drwobj,&rc,0,img);
  SetColor(&drwobj,pen,brush);
  DrawObject(&drwobj);
}

//Вызывается так:
DrwImg((IMGHDR *)&img,2,3,GetPaletteAdrByColorIndex(0),GetPaletteAdrByColorIndex(1));
//где 2,3 координаты на экране x и y.

//имидж описан как:
const IMGHDR img={132,176,5,0,(char *)bmp};
//8 бит изобр.132х176, bmp содержит данные цветов размером 132x176 байт.

//в swilib.h структура IMGHDR задана как:
typedef struct
{
  char w;
  char h;
  char bpnum; //For BW=1, 8bit=5, 16bit=8, 0x80 - packed
  char zero;
  char *bitmap;
}IMGHDR;
//где w,h ширина и высота изображения, bpnum наш режим:
//5 = 8bit(RGB332), 8 = 16bit(RGB565), bitmap - сами данные пикселов.

//макросы преобраз-я цветов:
#define RGB8(R,G,B) (B+(G<<2)+(R<<5))
#define RGB16(R,G,B) ((B>31?31:B)+((G>63?63:G)<<5)+((R>31?31:R)<<11))

Дописать преобр.пикселов оставляю вам самим :)


ПРИЛОЖЕНИЕ 1. Заголовок графического формата BMP
------------------
смещ. размер имя
00 2 'BM'
02 4 Размер файла в байтах;
06 2 0
08 2 0
10 4 Смещение начала изображения в файле;
14 4 Размер этого заголовка, 40;
18 4 Ширина изображения в пикселях;
22 4 Высота изображения в пикселях;
26 2 Число плоскостей изображения, 1;
28 2 Бит на пиксел: 1,4,8,16,24,32;
30 4 Тип сжатия;
34 4 Размер сжатого изображения в байтах или 0;
38 4 Горизонтальное разрешение, в пикселях / на метр;
42 4 Вертикальное разрешение, в пикселях / на метр;
46 4 Количество используемых цветов;
50 4 Число "важных" цветов;
54 4*N Карты цветов BGRР;

BMP заголовок 54 б + палитра 4*256(вместо 256 число "важных" цветов);
 строки повернуты, выравнены на границу кратную 4
----------

ПРИЛОЖЕНИЕ 2. Структуры заголовка BMP
--------------------------------------
//ЧИТАЕМ примечание в конце!!!
#pragma pack(1)
struct BMP_header {
unsigned short BMP_id ; // 'B''M'
unsigned long size, // size in bytes of the BMP file
      zero_res, // 0
      offbits,  // 54
      biSize,   // 0x28
      Width,    // X
      Height;   // Y
unsigned short biPlanes, // 1
      biBitCount ; // 24
unsigned long biCompression, // 0 = BI_RGB
      biSizeImage, // 0
      biXPelsPerMeter, // 0xB40
      biYPelsPerMeter, // 0xB40
      biClrUsed, file://0
      biClrImportant; file://0
};

struct BMPst{
unsigned short bfType;
unsigned long bfSize;
unsigned short bfReserved1,
  bfReserved2;
unsigned long bfOffBits,
    biSize,
    biWidth,
    biHeight;
unsigned short biPlanes,
    biBitCount;
unsigned long biCompression,
    biSizeImage,
    biXPelsPerMeter,
    biYPelsPerMeter,
    biClrUsed,
    biClrImportant;
};
#pragma pack()
---------------------

ПРИЛОЖЕНИЕ 3. Функции перекодировки цветов
Чтобы Вам было легче работать и не мучиться
с переводом цветов разных битностей выложил ф-ции.
Если заканч. на ...tobyte переводим в 8 бит, ...toshort в 16

inline unsigned char rgb888tobyte(int color){
  return ((color>>6)&3)|((color>>11)&0x1C)|((color>>16)&0xE0); }

inline short rgb888toshort(int color){
  return ((color>>3)&0x1f)|((color>>5)&0x7e0)|((color>>8)&0xf800); }

inline unsigned char rgb565tobyte(short color){
  return ((color>>3)&3)|((color>>6)&0x1C)|((color>>8)&0xE0); }

inline short rgb565toshort(short color){
  return color; }

------------------
ПРИМЕЧАНИЕ:
ВАЖНО!!!
НЕ забываем про выравнивание на АРМ, т.е. *(int*)(bmp+10) = pickoff (граница некратна 4м!)
Нужно собирать по байтам: bmp[10]+(bmp[11]<<8)+(bmp[12]<<16)+(bmp[13]<<24);
Поэтому вышеуказанные структуры bmp вам не пригодятся :(