Конференция "WinAPI" » Как загрузить BMP в массив? [D7, WinXP]
 
  • kalexi (11.09.08 14:37) [0]
    Нужно загрузить bmp файл и перевести его в массив типа
    array [0..width*height*3] of byte;

    . Как это реализовать без сторонних библиотек (только на Windows.pas)?
  • Renegat © (11.09.08 14:43) [1]
    GetDIBits/CreateDIBSection + F1.
    Пример, к сожалению, есть только под asm.
  • MBo © (11.09.08 14:46) [2]
    >Нужно загрузить bmp файл и перевести его в массив
    Для чего?
    ScanLine, например, позволяет работать напрямую с цветовыми данными
  • Vlad Oshin © (11.09.08 17:13) [3]
    for h := 0 to Bitmap.Height-1 do
     begin
       for w := 0 to Bitmap.Width-1 do
       begin
         Color := ColorToRGB(Bitmap.Canvas.Pixels[w,h]);
         r := GetRValue(Color);
         g := GetGValue(Color);
         b := GetBValue(Color);
         array[]ofbyte := r,g,b
       end;
     end;

    медленно, и
    вообще, см

    >  [2]
  • kalexi (11.09.08 18:03) [4]
    2 Renegat
    Рассеяно, но попытаюсь поискать. Дай асм исходники плз.

    2 MBo, Vlad Oshin
    Блин, да что же такое... Неужели нельзя полностью посмотреть вопрос? А? И в ветке WinApi положено же! Мне не нужны ExtCtrls, Graphics и другие библиотеки, надо сделать это средствами винды. С VCL любой дурак сделает...
  • Sapersky (11.09.08 19:07) [5]
    LoadImage + GetDIBits или непосредственная загрузка в массив, благо формат простой, заголовок [+ палитра] + данные.

    А откуда, кстати, такая ненависть к библиотекам?
    Если из-за размера exe - так есть FastLIB, KOL.TBitmap, SpriteUtils, которые дают весьма компактный размер. Даже если хочешь писать свою, полезно для начала посмотреть как сделано у других.
  • Renegat © (11.09.08 21:08) [6]
     LoadGIFJPGMem proc G: DWORD, Sz: DWORD, BD: DWORD, Sk: DWORD;
       IPicture STRUCT;
         QueryInterface DWORD ?;
         AddRef         DWORD ?;
         Release        DWORD ?;
         get_Handle     DWORD ?;
       IPicture ENDS;
       IStream STRUCT;
         QueryInterface DWORD ?;
         AddRef         DWORD ?;
         Release        DWORD ?;
         Read           DWORD ?;
         Write          DWORD ?;
         Seek           DWORD ?;
         SetSize        DWORD ?;
       IStream ENDS;
     .data
       sGUID_JPG TEXTEQU <{07BF80980h, 0BF32h, 0101Ah, {08Bh, 0BBh, 000h, 0AAh, 000h, 030h, 00Ch, 0ABh}}>;
       GUID_JPG GUID sGUID_JPG;
     .data?
       s DWORD ?;
       p DWORD ?;
       bi BITMAPINFO <>;
     .code
       PUSH EBX;
       invoke CreateStreamOnHGlobal, G, TRUE, ADDR s;

       MOV EAX, s;
       MOV EBX, DWORD PTR [EAX];

       CMP Sk, 0;
       JE @seek;
         PUSH 0;
         PUSH 0;
         PUSH 0;
         PUSH Sk;
         PUSH EAX;

         CALL [EBX].IStream.Seek;
       @seek:

       invoke OleLoadPicture, s, Sz, TRUE, ADDR GUID_JPG, ADDR p;

       MOV EAX, p;
       MOV EBX, DWORD PTR [EAX];
       PUSH OFFSET s;
       PUSH EAX;
       CALL [EBX].IPicture.get_Handle;

       PUSH p;
       CALL [EBX].IPicture.AddRef;      

       invoke CreateCompatibleDC, 0;
       PUSH EAX;

       PUSH SRCCOPY;
       PUSH 0;
       PUSH 0;
       PUSH EAX;

       PUSH s;
       PUSH s;
       PUSH EAX;
       MOV s, EAX;

       CALL SelectObject;
       CALL GetBitmapSize;
       MOVZX EDX, AX;
       SHR EAX, 16;
       PUSH EAX;
       PUSH EDX;
       PUSH 0;
       PUSH 0;

       CMP BD, 0;
       JNE @mdib;
         invoke CreateCompatibleBitmap, s, EDX, EAX;
         MOV Sz, EAX;
         PUSH EAX;

         invoke CreateCompatibleDC, 0;
         MOV s, EAX;
         PUSH EAX;
         CALL SelectObject;
         PUSH s;
         CALL BitBlt;
         invoke DeleteDC, s;
       JMP @mddb;
       @mdib:
         PUSH EAX;
         PUSH EDX;
         MOV bi.bmiHeader.biSize, SIZEOF BITMAPINFOHEADER;
         POP bi.bmiHeader.biWidth;
         POP bi.bmiHeader.biHeight;
         MOV bi.bmiHeader.biPlanes, 1;
         MOV bi.bmiHeader.biBitCount, 32;
         MOV bi.bmiHeader.biCompression, BI_RGB;

         invoke CreateCompatibleDC, 0;
         MOV EDX, BD;
         MOV DWORD PTR [EDX], EAX;
         PUSH EAX;
         PUSH EAX;
         PUSH EAX;

         LEA EDX, [EBP+8]; <---- Offset for "G" parameter
         invoke CreateDIBSection, s, ADDR bi, DIB_RGB_COLORS, EDX, 0, 0;
         MOV Sz, EAX;

         MOV DWORD PTR [ESP+4], EAX;
         CALL SelectObject;

         CALL BitBlt;
       @mddb:
       CALL DeleteDC;

       PUSH p;
       CALL [EBX].IPicture.Release;

       MOV EAX, Sz;
       POP EBX;
       RET;
     LoadGIFJPGMem endp;



    Да простят меня модеры за выкладывание такой здоровенной портянки прямо на форум =)
    То что вам, kalexi, нужно, расположено между метками @mdib и @mddb.
    Если разберётесь - ваше счастье ;)
  • Renegat © (11.09.08 21:16) [7]
    Впрочем, я зря это выкладывал. Если делфяной TBitmap изначально является DIB-ом (я хз, так ли это - пусть ответят Мастера), то его не нужно пересоздавать как DIB и копировать массив пикселей в него. Можно воспользоваться вот этим:

     DIBgetRGBarr proc BTFS: HBITMAP;
     .data?
       dgr BITMAP <>;
     .code
       invoke GetObject, BTFS, SIZEOF BITMAP, ADDR dgr;
       MOV EAX, dgr.bmBits;
       RET;
     DIBgetRGBarr endp;



    Выдаёт ссылку (делфийский Pointer) на массив пикселей DIB-а. Структура каждого из элементов такова: три нижних байта - это цвет, верхний - зарезервирован. Обычно там хранят альфа-компонент.

    Впрочем, даже если исходный битмап - не DIB, его легко можно сконвертить в таковой с помощью лёгкой обработки напильником кода из [6].
  • kalexi (11.09.08 21:42) [8]
    2 Sapersky
    Спасибо, на счет библиотек - посмотрю.

    2 Renegat
    Спс, буду изучать ))
  • Renegat © (11.09.08 21:44) [9]
    Ах да. Описание входных парамов для функции LoadGIFJPGMem:

    G  - блок памяти с картинкой внутре (указатель, разумеется, а не сам блок).
    Sz - ^^^ его размер
    BD - если равен 0, картинка загружается в DDB, иначе - в DIB, и по адресу, который здесь передан, пишется DC созданного битмапа.
    Sk - смещение относительно первого байта в блоке RAM содержащем картинку.
  • kalexi (11.09.08 21:57) [10]
    Все! Решил! Формат действительно очень простой, поэтому не стану морочить голову и сделаю без WinApi
  • Renegat © (11.09.08 21:59) [11]
    ...а если битмап попадётся не 32-битный, а скажем 2-цветный?
  • MBo © (12.09.08 05:09) [12]
    >Если делфяной TBitmap изначально является DIB-ом
    Загружаемый из файла - да, является DIB-ом.
    При создании TBitmap.Create  -  DDB, но если затем задать PixelFormat или HandleType - то DIB
  • GrayFace © (13.09.08 21:38) [13]
    в WinAPI:
    GetBitmapBits() и SetBitmapBits()
  • Renegat © (13.09.08 21:50) [14]
    > [13] GrayFace ©   (13.09.08 21:38)

    К сожалению, это не совсем так.

    > The GetBitmapBits function is not implemented in the Win32 API.
  • GrayFace © (14.09.08 01:40) [15]
    В Висте? На ХР отлично работает.
  • Григорьев Антон © (15.09.08 12:14) [16]

    > Renegat ©   (13.09.08 21:50) [14]
    > К сожалению, это не совсем так.
    > > The GetBitmapBits function is not implemented in the Win32
    > API.

    У меня про GetBitmapBits другое написано:

    > This function is provided only for compatibility with 16-
    > bit versions of Windows. Applications should use the GetDIBits
    > function.
  • brother © (15.09.08 12:14) [17]
    > У меня про GetBitmapBits другое написано:

    где?
  • Григорьев Антон © (15.09.08 12:31) [18]

    > brother ©   (15.09.08 12:14) [17]
    > где?

    В той версии MSDN, которая у меня установлена. Да и вот здесь то же самое: http://msdn.microsoft.com/en-us/library/ms532332(VS.85).aspx
  • brother © (15.09.08 12:56) [19]
    > [18] Григорьев Антон ©   (15.09.08 12:31)


    > is not implemented in the Win32


    > only for compatibility with 16-

    ;)
  • имя (19.11.08 00:41) [20]
    Удалено модератором
  • han_malign © (19.11.08 10:04) [21]

    > но если затем задать PixelFormat или HandleType - то DIB

    - или Dormant :)

    > Загружаемый из файла - да, является DIB-ом.

    - почти - если его целиком загрузить образ файла в память, получив таким образом "packed bitmap"(MSDN: Windows GDI - BITMAPINFO - remarks) - и скормить его StretchDIBits то для 8,16 - бит - прокатывает, а для 32 - нет(есть подозрение, что нужно выравнивание на страницу памяти - не проверял)
  • имя (02.04.09 09:14) [22]
    Удалено модератором
 
Конференция "WinAPI" » Как загрузить BMP в массив? [D7, WinXP]
Есть новые Нет новых   [134435   +34][b:0][p:0.003]