Announcement

Collapse
No announcement yet.

Win2000, 24-bit DIB section

Collapse
X
 
  • 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.

    Code:
       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, _
                          %LR_CREATEDIBSECTION Or %LR_DEFAULTSIZE Or %LR_LOADFROMFILE)
    
             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
    
          Next
    
          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.

    Code:
    '-----------------------------------------------------------------------------
    ' 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
     
        IF ISFALSE(hbmp) THEN EXIT SUB
     
        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
           LOOP
           y = y + by
        LOOP
        Call DeleteDC( memdc )
    END SUB

    Comment


    • #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.
      Thanx.



      ------------------
      E-MAIL: [email protected]

      Comment


      • #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.

        ------------------

        Comment


        • #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]

          Comment


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

            Code:
            'instead of
            Local bm as BITMAP
            GetObject hMemBmp, SizeOf(bm), bm
            
            'you should
            TYPE DIBSECTION
                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

            regards,

            Torsten

            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).]

            Comment


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

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

              ------------------

              Comment

              Working...
              X