I come here with a well known procedure to create a region based on a bitmap with a colour treated as transparent colour. I some threads I heard about the technique I used to write this code but couldn't find the source, so I decided to post it for discussion to see if it can be improved.

Here the code

Bmp2Rgn proc uses ebx edi esi hBmp:Handle, dTransparentColor:dword
    local Bmp:BITMAP, BmpInfoHdr:BITMAPINFOHEADER, hDC:Handle
    local pBuffer:Pointer, pRectBuffer:Pointer, dRectCount:dword
    local dCurrScanLine:dword, sdIncrement:sdword

    invoke GetObject, hBmp, sizeof Bmp, addr Bmp
    .if eax != 0
      mov ecx, dTransparentColor            ;Transform the RGB to a BGR color as it is found in mem.
      rol ecx, 8                            ;  RR GG BB AA
      ror cx, 8                            ;  RR GG AA BB
      rol ecx, 16                          ;  AA BB RR GG
      ror cx, 8                            ;  AA BB GG RR
      mov dTransparentColor, ecx

      mov eax, Bmp.bmWidth
      shl eax, 2
      mov BmpInfoHdr.biSizeImage, eax
      mov BmpInfoHdr.biSize, sizeof BmpInfoHdr
      mov eax, Bmp.bmWidth
      mov BmpInfoHdr.biWidth, eax

      mov ecx, Bmp.bmHeight
      mov BmpInfoHdr.biHeight, ecx

      .if sdword ptr (ecx) > 0              ;Detect top-down or bottom-up bitmaps
        mov sdIncrement, -1                ;Bottom-up bitmap
        mov dCurrScanLine, ecx
        mov sdIncrement, 1                  ;Top-down bitmap
        mov dCurrScanLine, -1

      mov BmpInfoHdr.biPlanes, 1
      mov BmpInfoHdr.biBitCount, 32
      mov BmpInfoHdr.biCompression, BI_RGB

      shl eax, 2                            ;Scanline buffer = Bmp.bmWidth * 4
      push eax
      mul ecx                              ;Max possible number of rects = width x height / 2
      shl eax, 1
      add eax,
      add eax, sizeof RGNDATAHEADER
      invoke VirtualAlloc, NULL, eax, MEM_COMMIT, PAGE_READWRITE
      pop ecx
      .if eax != NULL
        mov pBuffer, eax
        add eax, ecx
        mov pRectBuffer, eax
        mov .RGNDATAHEADER.dwSize, sizeof RGNDATAHEADER
        mov .RGNDATAHEADER.nRgnSize, 0
        add eax, sizeof RGNDATAHEADER - sizeof RECT
        mov edi, eax
        mov hDC, $invoke(GetDC, 0)
        xor ebx, ebx
        mov dRectCount, ebx

        .while ebx < Bmp.bmHeight
          mov ecx, sdIncrement
          add dCurrScanLine, ecx
          invoke GetDIBits, hDC, hBmp, dCurrScanLine, 1, pBuffer, addr BmpInfoHdr, DIB_RGB_COLORS

          mov esi, pBuffer
          xor ecx, ecx                      ;ecx = 0 => not in region flag
          xor edx, edx                      ;Reset Scanline pixel counter
          .while edx < Bmp.bmWidth
            mov eax,
            and eax, 00FFFFFFh              ;Ignore alpha value
            .if eax == dTransparentColor
              .if ecx != 0                  ;Terminate the current Rect
                mov .RECT.right, edx
                xor ecx, ecx                ;Reset flag
            .elseif ecx == 0                ;Start a new Rect
              inc dRectCount
              add edi, sizeof RECT          ;Point to next Rect
              mov eax, ebx
              mov .RECT.left, edx
              inc eax
              mov .RECT.top, ebx
              mov .RECT.bottom, eax
              inc ecx                      ;Set flag
            inc edx
            add esi, 4

          .if ecx != 0                      ;Close last Rect
            mov .RECT.right, edx

          inc ebx

        mov eax, pRectBuffer
        mov ecx, dRectCount
        mov .RGNDATAHEADER.nCount, ecx
        shl ecx, 4
        add ecx, sizeof RGNDATAHEADER
        invoke ExtCreateRegion, NULL, ecx, pRectBuffer
        push eax
        invoke ReleaseDC, 0, hDC
        invoke VirtualFree, pBuffer, 0, MEM_RELEASE
        pop eax
Bmp2Rgn endp


Posted on 2006-04-30 15:41:11 by Biterider
There's a thread called "my new getpixel, 20x faster" or something similar - there's some source there. The board search engine doesn't work right now, but the files can be downloaded from http://flork.dk/junk/customshape_20040319.rar . It's C++ source though, but LEAN_AND_MEAN, and there's assembly dump of it.

I guess we have sortof the same way of doing things, at least I also use ExtCreateRegion... I allocate memory as needed though, instead of one big chunk. As for the rest of the algorithm, I'm too tired to study yours right now :)
Posted on 2006-05-01 06:39:59 by f0dder
there is an issue with the RGB/BGR memory representation of the transparent color. I corrected it and out it in the first post.

Posted on 2006-05-01 12:27:19 by Biterider