No announcement yet.

Win2000, 24-bit DIB section

  • Filter
  • Time
  • Show
Clear All
new posts

  • Win2000, 24-bit DIB section

    Decided to save a memory a little (to use 24 bit DIB section instead of 32 bit) and found something very strange ...

    According MSDN, bm.bmWidthBytes should be divisable 2.
    I create 24-bit DIB section (hMemBmp), retrive bitmap (GetObject hMemBmp, Len(BITMAP), bm) and then work with scan lines directly.

    bm.bmWidth = 31
    bm.bmWidthBytes = 94 (as expected, because 31 * 3 = 93)

    In calculations I accept that distance beetween scan lines is bm.bmWidthBytes.
    All works fine, for example, in 98SE.

    But not under Win2000.
    If to use DWORD alignment (bm.bmWidthBytes = 96), all works fine here too.
    But I see nothing in MSDN about DWORD alignment.
    Like idea, Windows by itself should also use original "bm.bmWidthBytes" (means 94 here).

    Did somebody notice the same ?

    Below is a subroutine, which I debug (analog of FillRect ... CreatePatternBrush, but w/o limit 8*8 pixels).
    Change 32 to 24 and you will see troubles under 2000.

       Global gBackground_BmpFile  As String ' <--- name of background bmp-file
       Global gBackground_hBmp As Long
       Sub MemCopy (ByVal Dest As Dword, ByVal Source As Dword, ByVal ln As Dword)
        ! cld
        ! mov esi, Source
        ! mov edi, Dest
        ! mov ecx, ln
        ! shr ecx, 2
        ! rep movsd
        ! mov ecx, ln
        ! And ecx, 3
        ! rep movsb
       End Sub
       Function DrawBackground(hDC As Long, rc As RECT) As Long
          Static gBackground_BmpFile_Old As String, gBackground_hBmp As Long, bmBkg As BITMAP
          Local bmi As BITMAPINFO, hMemBmp As Long, bm As BITMAP, hMem1DC As Long, hMem2DC As Long, rcMem As RECT
          Local i1 As Long, i2 As Long, j1 As Long, j2 As Long
          Local l1 As Long, l2 As Long, l As Long, p1 As Byte Ptr, p2 As Byte Ptr
          If gBackground_BmpFile_Old <> gBackground_BmpFile Then
             If gBackground_hBmp <> 0 Then DeleteObject gBackground_hBmp: gBackground_hBmp = 0
             gBackground_BmpFile_Old = gBackground_BmpFile
             hMemBmp = LoadImage(ByVal 0, ByVal StrPtr(gBackground_BmpFile), %IMAGE_BITMAP, 0, 0, _
             If hmemBmp Then
                hMem1DC = CreateCompatibleDC(hDC)
                hMem2DC = CreateCompatibleDC(hMem1DC)
                GetObject hMemBmp, SizeOf(bm), bm
                bmi.bmiHeader.biSize = SizeOf(bmi.bmiHeader)
                bmi.bmiHeader.biWidth = bm.bmWidth
                bmi.bmiHeader.biHeight = bm.bmHeight
                bmi.bmiHeader.biPlanes = 1
                bmi.bmiHeader.biBitCount = 32
                bmi.bmiHeader.biCompression = %BI_RGB
                gBackground_hBmp = CreateDIBSection(hMem1DC, bmi, %DIB_RGB_COLORS, 0, 0, 0)
                GlobalLock gBackground_hBmp
                SelectObject hMem1DC, hMemBmp
                SelectObject hMem2DC, gBackground_hBmp
                BitBlt hMem2DC, 0, 0, bm.BmWidth, bm.BmHeight, hMem1Dc, 0, 0, %SRCCOPY
                DeleteDC hMem1DC
                DeleteDC hMem2DC
                DeleteObject hMemBmp
                GetObject gBackground_hBmp, Len(BITMAP), bmBkg
             End If
          End If
          rcMem.nLeft = 0
          rcMem.nTop = 0
          rcMem.nRight = rc.nRight - rc.nLeft
          rcMem.nBottom = rc.nBottom - rc.nTop
          hMem1DC = CreateCompatibleDC(hDC)
          bmi.bmiHeader.biSize = SizeOf(bmi.bmiHeader)
          bmi.bmiHeader.biWidth = rcMem.nRight
          bmi.bmiHeader.biHeight = rcMem.nBottom
          bmi.bmiHeader.biPlanes = 1
          bmi.bmiHeader.biBitCount = 32
          bmi.bmiHeader.biCompression = %BI_RGB
          hMemBmp = CreateDIBSection(hMem1DC, bmi, %DIB_RGB_COLORS, 0, 0, 0)
          GlobalLock hMemBmp
          SelectObject hMem1DC, hMemBmp
          GetObject hMemBmp, Len(BITMAP), bm
          For j1 = bm.bmHeight - 1 To 0 Step -1
             If j2 = 0 Then j2 = bmBkg.bmHeight
             Decr j2
             p1 = bm.bmBits    + bm.bmWidthBytes    * j1
             p2 = bmBkg.bmBits + bmBkg.bmWidthBytes * j2
             l1 = bm.bmWidthBytes
             l2 = bmBkg.bmWidthBytes
             l = l2
             If l > l1 Then l = l1
             If l > 0 Then MemCopy p1, p2, l
             p2 = p1 + l
             l = l1 - l
             If l > 0 Then MemCopy p2, p1, l
          If gPalette Then
             SelectPalette hDC, gPalette, 0
             RealizePalette hDC
          End If
          DrawEdge hMem1DC, rcMem, %EDGE_SUNKEN, %BF_RECT
          BitBlt hDC, rc.nLeft, rc.nTop, rc.nRight - rc.nLeft, rc.nBottom - rc.nTop, hMem1Dc, 0, 0, %SRCCOPY
          DeleteObject hMem1DC
          DeleteObject hMemBmp
       End Function
    E-MAIL: [email protected]

    [This message has been edited by Semen Matusovski (edited October 17, 2001).]

  • #2
    "CreatePatternBrush, but w/o limit 8*8 pixels" I thought only for Win95?

    I know not exactly your needs, but works well with just plain old bitmap.

    ' Tile a bitmap within defined RECT
    SUB FillWithBitmap( ByVal dc AS LONG, ByVal hbmp AS LONG, rc AS RECT )
        LOCAL w     AS LONG, h  AS LONG
        LOCAL x     AS LONG, y  AS LONG, z AS LONG
        LOCAL bx    AS LONG, by AS LONG
        LOCAL memdc AS LONG
        memdc = CreateCompatibleDC( dc )
        Call SelectObject( memdc, hbmp )
        w = rc.nright - rc.nleft
        h = rc.nbottom - rc.ntop
        bx = GetBitmapWidth( hbmp )
        by = GetBitmapHeight( hbmp )
        y = rc.nTop
        DO WHILE y < h
           IF (y+by) > h THEN by = h-y
           z = bx
           x = rc.nLeft
           DO WHILE x < w
              IF  (x+z) > w THEN z = w-x
              Call BitBlt (dc, x, y, z, by, memdc, 0, 0, %SRCCOPY )
              x = x + z
           y = y + by
        Call DeleteDC( memdc )


    • #3
      Jules --
      I was afraid a lot of BitBlt.
      For example, rect size is 1000 * 800, a size of Bmp - 31 * 30.
      About 1000 calls.

      Compared two methods in different resolutions /color depth.
      In some combinations (first of all, 32-bit regime) my method 20-25% faster, but in more typical cases (16/24 bit) - not (because I build big DIB section anyway).

      So, I decided do not investigate bicycle and to use BitBlt.

      E-MAIL: [email protected]


      • #4
        Two quick questions---- Please

        Semen, What were you referancing with "bicycle" ?

        And, I've been using Compatable Bitmaps---- and they have
        been working quite well----What is the advantage of DIB's ?

        Thanks, B.



        • #5
          Brad --
          At the second part of 19th century a lot of guys offered own models of bicycles - three cycles; one big cycle, another small and so on.
          So in Russian language appeared a special termin, which is possible to translate as "to invent a bicycle" and which means to do absurd work, because actually it's impossible to find a bew variant.

          I use DIBs to work with pixels directly (as with array of RGB values).
          For example, you want to change "brightness". To do this you need to multiply RGB of each pixel per coefficient.
          It's possible to do using Get/SetPixel, but these functions are very slowly (imagine a screen of 1024 * 768; 1 mln API calls to get and 1 mln to set).

          E-MAIL: [email protected]


          • #6
            Hi Semen,
            you should try the following.

            'instead of
            Local bm as BITMAP
            GetObject hMemBmp, SizeOf(bm), bm
            'you should
                dsBm                        AS BITMAP
                dsBmih                      AS BITMAPINFOHEADER
                dsBitfields(2)              AS DWORD
                dshSection                  AS DWORD
                dsOffset                    AS DWORD
            END TYPE
            LOCAL bm as DIBSECTION
            GetObject hMemBmp, SizeOf(bm), bm
            'And you should also
            LOCAL bmBitsPtr AS LONG
            gBackground_hBmp = CreateDIBSection(hMem1DC, bmi, %DIB_RGB_COLORS, bmBitsPtr , 0, 0)
            'to get a Pointer to the DIB Bits
            i am very certain, that this will solve
            your problems



            P.S.: Short Comment:
            Because you are obtaining a BITMAP with GetObjct,
            you get a BITMAP wich is DWORD aligned. If you
            obtain a DIBSECTION, you get a DIBSECTION wich is
            WORD aligned.

            [This message has been edited by Torsten Rienow (edited October 18, 2001).]


            • #7
              Interesting,---And Thanks, Semen

              Seems I may have been Bicycling my own version of DIB! B.