Announcement

Collapse
No announcement yet.

GDI+ ... how to load a non-BMP image ie PNG/JPG and convert it to a BMP?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • GDI+ ... how to load a non-BMP image ie PNG/JPG and convert it to a BMP?

    Hey guys,
    I have a GDI+ related problem thats been doing my head in all day and despite going through various GDI+ samples from our beloved Poffs I'm still none the wiser as to how to go about this as i have very little experience with GDI+. (I think Patrice could probably do this in his sleep)

    Basically, I have a PNG file, and I need to convert that to a BITMAP, and do this all in memory - I have no need to display the image, as all I want to do is analyse the image contents - basically I just want to look at the pixels in memory.

    Is GDI+ the right way to go about this, and if so does anybody know how on earth to do it !?

    Thanks
    -

  • #2
    FreeImage

    I use FreeImage.DLL (Free Image Reader Library) to do all of my graphics conversions. It works really great, and did I mention... Its free!!

    http://freeimage.sourceforge.net/

    Here is the routine I used to load images from FreeImage and convert to Windows bitmaps. (This routines does a bit more but you can probably strip out what you need from it. Basically the last 12- 15 lines are your critical functions.)

    Code:
    FUNCTION PBSetBitmapBits(BYVAL PBBits AS INTEGER, BYVAL hBitmap AS LONG, BYVAL Src AS DWORD) AS LONG
        LOCAL ok AS LONG, success AS LONG
        LOCAL hdcBMP AS LONG
        LOCAL oldHnd AS LONG, bufSize AS LONG
        LOCAL SrcBuffer AS DWORD
    
        ON ERROR RESUME NEXT                       
    
        hdcBMP = GETDC(hBitmap)
        IF hdcBMP = %NULL THEN
        	hdcBMP = CREATEDC("DISPLAY", "", "", BYVAL 0&)
        END IF                                           
        ok = GetObject (hBitmap, LEN(CurrentBMP), CurrentBMP)
    
        oldHnd = SelectObject(hdcBMP, hBitmap)
        Set_DIBTileHeader PBBits, ABS(CurrentBMP.bmWidth), ABS(CurrentBMP.bmHeight)
    
        IF Src = %NULL THEN
            bufSize = ABS(CurrentBMP.bmHeight * CurrentBMP.bmWidth * INT(PBBits/8)) - LEN(CurrentBMPBits)
            IF bufSize > 0 THEN
                CurrentBMPBits = CurrentBMPBits + SPACE$(bufSize)
            END IF
            SrcBuffer = STRPTR(CurrentBMPBits)
        ELSE
            SrcBuffer = Src
        END IF
    
        success = SETDIBITS(BYVAL hdcBMP, BYVAL hBitmap, BYVAL 0, BYVAL ABS(CurrentBMP.bmHeight), BYVAL SrcBuffer, CurrentBMI, BYVAL %DIB_RGB_COLORS)  
        ok = SELECTOBJECT(hdcBMP, oldHnd) : ok = DELETEDC(hdcBMP)
    
        FUNCTION = success
    END FUNCTION
    
    FUNCTION GetBMPResource (BYVAL hBitmap AS LONG, BYVAL bmType%, BYVAL bmpWidth AS LONG , BYVAL bmpHeight AS LONG) EXPORT AS LONG
        LOCAL hBMP AS LONG
        LOCAL ok AS LONG, Create%
        LOCAL ScreenDC AS LONG
        LOCAL retVal AS LONG
    
        Create% = %True
        IF hBitmap <> %NULL THEN
            ok = GetObject (hBitmap, LEN(CurrentBMP), CurrentBMP)
            IF bmpWidth <> CurrentBMP.bmWidth OR bmpHeight <> CurrentBMP.bmHeight THEN
                Create% = %True
            ELSE
                retVal = hBitmap
                Create% = %False
            END IF
            IF (bmType% = 1 AND CurrentBMP.bmBitsPixel <> 1) OR (bmType% <> 1 AND CurrentBMP.bmBitsPixel = 1) THEN
                Create% = %True
            END IF
        END IF
    
        IF Create% = %True THEN
            IF hBitmap <> %NULL THEN ok = DeleteObject (hBitmap)
    
            SELECT CASE bmType%
                CASE 1
                    hBMP = CreateBitmap(bmpWidth, bmpHeight, 1, 1, BYVAL %NULL)
    
                CASE %NULL
                    ScreenDC = CreateDC("DISPLAY", "", "", BYVAL 0&)
                    hBMP = CreateCompatibleBitmap(ScreenDC, bmpWidth, bmpHeight)
                    ok = DeleteDC (ScreenDC)
    
                CASE ELSE
                    hBMP = CreateBitmap(bmpWidth, bmpHeight, 1, bmType%, BYVAL %NULL)
            END SELECT
            retVal = hBMP
        END IF
        FUNCTION = retVal
    END FUNCTION
    
    
    FUNCTION LoadGraphic(gfxFile$, BYVAL frmt AS INTEGER, BYVAL sFrame AS INTEGER, BYVAL eFrame AS INTEGER) AS LONG
        LOCAL retVal AS LONG, resFile$, OK AS LONG
        LOCAL Pic AS BitmapInfoType
        LOCAL bmpX AS LONG, bmpY AS LONG
        LOCAL fiBMP AS LONG, fiBMP24 AS LONG
        LOCAL fiWidth AS LONG, fiHeight AS LONG
        LOCAL bmpFile$, bmpExt$, bmpDel AS INTEGER
    
        ON ERROR RESUME NEXT
        bmpFile$ = gfxFile$   
        IF DOSFileExists(bmpFile) = %False THEN
    	    IF DumpResource(GetFileFromPath$(bmpFile$)) = %True THEN
    	        bmpDel = %True
    	        bmpFile$ = Program_Path$ + "TEMP\" + GetFileFromPath$(gfxFile$)
    	    END IF
    	END IF
    	
        bmpExt$ = UCASE$(FileExtension$(bmpFile$))
        SELECT CASE bmpExt$
            CASE "GFX"
                vbGetGFXInfo bmpFile$, Pic
                retVal = GetBMPResource(retVal, frmt, Pic.pWidth, Pic.pHeight)
                PBLoadGFXImage bmpFile$, retVal
    
            CASE "CLP"
                vbGetCLPInfo bmpFile$, Pic
                retVal = GetBMPResource(retVal, frmt, Pic.pWidth, Pic.pHeight)
                IF sFrame <= 0 AND eFrame <= 0 THEN
                    eFrame = INT(Pic.pWidth / Pic.FrameWidth) * INT(Pic.pHeight / Pic.FrameHeight)
                    retVal = PBLoadAnimClip(bmpFile$, retVal, 0, eFrame - 1, 1)
                ELSE
                    retVal = PBLoadAnimClip(bmpFile$, retVal, sFrame, eFrame, 1)
                END IF
    
            CASE "HDR"
                fiBMP = FreeImage_Load(%FIF_HDR, BYCOPY bmpFile$, %HDR_DEFAULT)
            CASE "GIF"
                fiBMP = FreeImage_Load(%FIF_GIF, BYCOPY bmpFile$, %GIF_DEFAULT)
            CASE "ICO"
                fiBMP = FreeImage_Load(%FIF_ICO, BYCOPY bmpFile$, %ICO_DEFAULT)
            CASE "BMP"
                fiBMP = FreeImage_Load(%FIF_BMP, BYCOPY bmpFile$, %BMP_DEFAULT)
            CASE "WBMP"
                fiBMP = FreeImage_Load(%FIF_WBMP, BYCOPY bmpFile$, %WBMP_DEFAULT)
            CASE "JPG", "JIF"
                fiBMP = FreeImage_Load(%FIF_JPEG, BYCOPY bmpFile$, %JPEG_ACCURATE)
     [B]       CASE "PNG"
                fiBMP = FreeImage_Load(%FIF_PNG, BYCOPY bmpFile$, %PNG_DEFAULT)[/B]
            CASE "JNG"
                fiBMP = FreeImage_Load(%FIF_JNG, BYCOPY bmpFile$, %JPEG_DEFAULT)
            CASE "PCX"
                fiBMP = FreeImage_Load(%FIF_PCX, BYCOPY bmpFile$, %PCX_DEFAULT)
            CASE "TIFF"
                fiBMP = FreeImage_Load(%FIF_TIFF, BYCOPY bmpFile$, %TIFF_DEFAULT)
            CASE "TARGA"
                fiBMP = FreeImage_Load(%FIF_TARGA, BYCOPY bmpFile$, %TARGA_DEFAULT)
            CASE "XPM"
                fiBMP = FreeImage_Load(%FIF_XPM, BYCOPY bmpFile$, %XPM_DEFAULT)
    
            CASE "RES"
                retVal = LoadBitmap(GetModuleHandle(""), BYCOPY GetFileFromPath$(bmpFile$))
        END SELECT
    
        IF bmpDel = %True THEN KILL bmpFile$
    
       [B] SELECT CASE bmpExt$
            CASE "BMP", "JPG", "JIF", "PNG", "HDR", "ICO", "WBMP", "JNG", "PCX", "TIFF", "TARGA", "XPM"'
                FreeImage_FlipVertical fiBMP
                fiBMP24 = FreeImage_ConvertTo24Bits(fiBMP) : FreeImage_Unload fiBMP
    
                fiWidth = FreeImage_GetWidth(fiBMP24)
                fiHeight = FreeImage_GetHeight(fiBMP24)
    
                retVal = GetBMPResource(retVal, %NULL, fiWidth, fiHeight)
                ok = PBSetBitmapBits(24, retVal, BYVAL FreeImage_GetBits(fiBMP24))
                FreeImage_Unload fiBMP24
        END SELECT[/B]
    
        FUNCTION = retVal
    END FUNCTION

    The GetBMPResource will create a bitmap when needed. It will resize bitmap space and make sure everything is "cleaned up" without memory leaks. It can create color or monochrome bitmaps.

    The PBSetbitmap Bits is the "re-creation" of the Windows SetbitmapBits using the SetDIBits() function. Microsoft deprecated the SetBitmapBits command, which was very easy & straight-forward. SetDIBits() is a little more difficult to use so I made this function to keep my brain from cramping.

    NOTE: Ignore any CLIP/GFX file functions. These are for my game engine's proprietary graphics formats.

    Good luck! And fee free to check me out!

    http://www.explore-rpg.com/cgi-bin/f...1206582666/8#8
    Last edited by Tyrone W. Lee; 2 May 2008, 06:28 AM.
    Explorations v9.10 RPG Development System
    http://www.explore-rpg.com

    Comment


    • #3
      See: http://www.powerbasic.com/support/pb...ad.php?t=23625

      Use the function ConvertImgToBmp.
      Forum: http://www.jose.it-berater.org/smfforum/index.php

      Comment


      • #4
        Originally posted by José Roca View Post
        See: http://www.powerbasic.com/support/pb...ad.php?t=23625

        Use the function ConvertImgToBmp.
        José,
        It appears this just converts file to file. I believe he wants the bmp in memory?

        James

        Comment


        • #5
          Then he can try the following functions:

          Code:
          DECLARE FUNCTION GdipCreateBitmapFromFile LIB "GDIPLUS.DLL" ALIAS "GdipCreateBitmapFromFile" ( _
             BYVAL STRING _                           ' GDIPCONST WCHAR *filename
           , BYREF DWORD _                            ' GpBitmap **bitmap
           ) AS LONG                                  ' GpStatus
          
          DECLARE FUNCTION GdipCreateHBITMAPFromBitmap LIB "GDIPLUS.DLL" ALIAS "GdipCreateHBITMAPFromBitmap" ( _
             BYVAL DWORD _                            ' GpBitmap *bitmap
           , BYREF DWORD _                            ' HBITMAP *hbmReturn
           , BYVAL DWORD _                            ' ARGB background
           ) AS LONG                                  ' GpStatus
          Code:
          DIM hr AS LONG
          DIM strFileName AS STRING
          DIM pBitmap AS DWORD
          DIM hBitmap AS DWORD
          
          strFilename = UCODE$(<file name>)
          hr = GdipCreateBitmapFromFile (strFileName, pBitmap)
          hr = GdipCreateHBITMAPFromBitmap (pBitmap, hBitmap, 0)
          Forum: http://www.jose.it-berater.org/smfforum/index.php

          Comment


          • #6
            Jose it is very late in the night here so I can't try that out now but I will try out your code tomorrow. Like Patrice's work your work has also stood out to me over the years And I thank you for coming to my aid here!!! Graphics really isn't something I've ever spent much time on so it is awesome to be able to get assistance from coders like yourself who've masterminded these fields, and I take my hat off to people like you and Patrice for their contributions in this field (your name regularly pops up on POFFS)
            -

            Comment


            • #7
              When you find the time, take a tour in my forum: http://www.jose.it-berater.org/smfforum/index.php

              There is a board devoted to graphics programming, with tons of examples, and Patrice has his own board.
              Last edited by José Roca; 2 May 2008, 09:04 AM.
              Forum: http://www.jose.it-berater.org/smfforum/index.php

              Comment


              • #8
                Very cool! I will have a thorough look through it tomorrow
                No surprise to see that Patrice has his own board for graphics lol
                -

                Comment


                • #9
                  Too easy! I had a feeling that there might be such an elegantly simple solution in GDI+ but this is the first time I've got my feet wet with it, and as it exports so many APIs I didn't know where to start. I searched through all the GDI+ samples I could find but couldn't really find one that just did this.

                  btw I thought there was some problem with your code at first because I was getting 0 for hBitmap and pBitmap ...... half an hour later I realised none of it will work unless I call GdiplusStartup first ... this fixed the problem

                  Thankyou very much Jose, I can begin tackling the real problem now - the in-memory image analysis itself. This should be fun!

                  Thanks also Tyrone for pointing me towards that free image library, it looks pretty interesting so I'll have to check it out

                  Thanks again and have a great weekend!
                  -

                  Comment


                  • #10
                    Bugger! It seems that's only half the job done ... the data at pBitmap isn't actually the pixel data. There's an address there, but if I go to that there's more data, but again not the pixel data in bitmap form.

                    But I think I'm only 1 more GDI+ API away from the pixel data...

                    From a bit more reading it seems I may need to call GdipBitmapLockBits, but according to POFFS nobody has ever used it before! Apparently that API is supposed to give you access to this structure:
                    TYPE BitmapData
                    nWIDTH AS LONG
                    nHeight AS LONG
                    stride AS LONG
                    PixelFormat AS LONG
                    scan0 AS LONG '<--- PTR to the actual pixel data I'm after!
                    Reserved AS LONG
                    END TYPE

                    But I'm not getting very far with it and its starting to do my head in!
                    Here's what I've come up with so far, any ideas???

                    Code:
                    #COMPILE EXE
                    #DIM ALL
                    #INCLUDE "win32api.inc"
                    
                    %SHIFT_LEFT_8_8  = 2048
                    %SHIFT_LEFT_32_8 = 8192
                    %PixelFormatIndexed     = &h00010000 ' Indexes into a palette
                    %PixelFormatGDI         = &h00020000 ' Is a GDI-supported format
                    %PixelFormatAlpha       = &h00040000 ' Has an alpha component
                    %PixelFormatPAlpha      = &h00080000 ' Pre-multiplied alpha
                    %PixelFormatExtended    = &h00100000 ' Extended color 16 bits/channel
                    %PixelFormatCanonical   = &h00200000
                    %PixelFormatUndefined   = 0
                    %PixelFormatDontCare    = 0
                    %PixelFormat8bppIndexed     =  3 OR %SHIFT_LEFT_8_8  OR %PixelFormatIndexed OR %PixelFormatGDI
                    %PixelFormat32bppRGB        =  9 OR %SHIFT_LEFT_32_8 OR %PixelFormatGDI
                    %PixelFormat32bppARGB       = 10 OR %SHIFT_LEFT_32_8 OR %PixelFormatAlpha OR %PixelFormatGDI OR %PixelFormatCanonical
                    %PixelFormat32bppPARGB      = 11 OR %SHIFT_LEFT_32_8 OR %PixelFormatAlpha OR %PixelFormatPAlpha OR %PixelFormatGDI
                    
                    TYPE GdiplusStartupInput
                       GdiplusVersion AS DWORD             '// Must be 1
                       DebugEventCallback AS DWORD         '// Ignored on free builds
                       SuppressBackgroundThread AS LONG    '// FALSE unless you're prepared to call the hook/unhook functions properly
                       SuppressExternalCodecs AS LONG      '// FALSE unless you want GDI+ only to use its internal image codecs.
                    END TYPE
                    
                    TYPE GdiplusStartupOutput
                       NotificationHook AS DWORD
                       NotificationUnhook AS DWORD
                    END TYPE
                    
                    DECLARE FUNCTION GdipCreateBitmapFromFile LIB "GDIPLUS.DLL" ALIAS "GdipCreateBitmapFromFile" ( _
                       BYVAL STRING _                           ' GDIPCONST WCHAR *filename
                     , BYREF DWORD _                            ' GpBitmap **bitmap
                     ) AS LONG                                  ' GpStatus
                    
                    DECLARE FUNCTION GdipCreateHBITMAPFromBitmap LIB "GDIPLUS.DLL" ALIAS "GdipCreateHBITMAPFromBitmap" ( _
                       BYVAL DWORD _                            ' GpBitmap *bitmap
                     , BYREF DWORD _                            ' HBITMAP *hbmReturn
                     , BYVAL DWORD _                            ' ARGB background
                     ) AS LONG                                  ' GpStatus
                    
                    DECLARE FUNCTION GdiplusStartup LIB "GDIPLUS.DLL" ALIAS "GdiplusStartup" _
                                (token AS DWORD, inputbuf AS GdiplusStartupInput, outputbuf AS GdiplusStartupOutput) AS LONG
                    DECLARE SUB GdiplusShutdown LIB "GDIPLUS.DLL" ALIAS "GdiplusShutdown" (BYVAL token AS DWORD)
                    
                    TYPE BitmapData
                       nWIDTH AS LONG
                       nHeight AS LONG
                       stride AS LONG
                       PixelFormat AS LONG
                       scan0 AS LONG
                       Reserved AS LONG
                    END TYPE
                    
                    DECLARE FUNCTION GdipBitmapLockBits LIB "gdiplus.dll" ALIAS "GdipBitmapLockBits" (BYVAL nBitmap AS LONG, nRect AS RECTL, BYVAL flags AS LONG, BYVAL PixelFormat AS LONG, lockedBitmapData AS BitmapData) AS LONG
                    
                    FUNCTION PBMAIN () AS LONG
                    LOCAL hr AS LONG, strFileName AS STRING, pBitmap AS DWORD, hBitmap AS DWORD, token AS DWORD, nStatus AS LONG
                    LOCAL StartupInput AS GdiplusStartupInput, nRect AS RECTL, bmpData AS BitmapData
                    
                    StartupInput.GdiplusVersion = 1
                    nStatus = GdiplusStartup(token, StartupInput, BYVAL %NULL)
                    IF nStatus THEN
                       MSGBOX "Error initializing GDI+": EXIT FUNCTION
                    END IF
                    
                    strFilename = UCODE$("E:\temp\test.png")
                    hr = GdipCreateBitmapFromFile (strFileName, pBitmap)
                    'hr = GdipCreateHBITMAPFromBitmap (pBitmap, hBitmap, 0)   '// Probably not required?
                    
                    MSGBOX "Lock=" & STR$(GdipBitmapLockBits (BYVAL dwPtr, nRect, BYVAL 1, BYVAL 0, bmpData))
                    MSGBOX "Width=" & STR$(bmpData.nWIDTH) & ", Height=" & STR$(bmpData.nHeight)
                    
                    GdiplusShutdown token
                    END FUNCTION
                    -

                    Comment


                    • #11
                      There are some 150 GDI+ examples in my forum. This one shows how to lock pixels for reading and access the Scan0 member:
                      http://www.jose.it-berater.org/smffo...picseen#msg421

                      Each example has an attachment (only visible and downloadable if you are a registered user) containing a full, compilable example.

                      Also, don't forget to release the bitmap using GdipDisposeImage pBitmap when done.

                      Complete headers for GDI+ can be downloaded here: http://www.jose.it-berater.org/smffo...php?topic=88.0

                      BTW there are also headers for FreeImage: http://www.jose.it-berater.org/smffo...p?topic=1488.0
                      and many other graphic libraries. Even wrapper functions and examples for DirectX9.
                      Forum: http://www.jose.it-berater.org/smfforum/index.php

                      Comment


                      • #12
                        Originally posted by José Roca View Post
                        This one shows how to lock pixels for reading and access the Scan0 member:
                        http://www.jose.it-berater.org/smffo...picseen#msg421
                        One word - WOOOHOOO!!! (or is that 2?)
                        That example looks like exactly the thing I was after, awesome

                        Scan0 here I come
                        -

                        Comment


                        • #13
                          Wayne,

                          If it is for your private use then you could use the GDImage trial version, it has built-in function to retrieve the pixels form any image under the form of an array.

                          Low level procedure to retrieve a device-independent bitmap.

                          FUNCTION zGetDIBits ( _
                          BYVAL hBitmap AS LONG, _ ' A valid bitmap handle.
                          PixelArray() AS LONG _ ' Array using 2 dimensions (Y,Y) matching the pixel coordinates.
                          ) AS LONG


                          Return:
                          If the function succeeds, the return value is the number of scan lines copied.
                          If the function fails, the return value is zero.

                          Low level procedure to replace a copy of a bitmap that was retrieved as a device-independent bitmap.

                          FUNCTION zSetDIBits ( _
                          BYVAL hBitmap AS LONG, _ ' A valid bitmap handle.
                          PixelArray() AS LONG _ ' Array using 2 dimensions (Y,Y) matching the pixel coordinates.
                          ) AS LONG


                          Return:
                          If the function succeeds, the return value is the number of scan lines copied from the bitmap.

                          ...
                          Patrice Terrier
                          www.zapsolution.com
                          www.objreader.com
                          Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

                          Comment


                          • #14
                            Originally posted by Patrice Terrier View Post
                            Wayne,
                            If the function succeeds, the return value is the number of scan lines copied.
                            Yep that sounds exactly like the same sort of thing I'm trying to do here, very cool!
                            I'll try to accomplish this with raw GDI+ first but if I get nowhere with that then I'll definately give GDImage a burl

                            ps. can I just say it's bloody awesome what yourself and Jose have managed to do in regards to making GDI+ available to PB programmers. (I mean now we can use PNG/GIF/TIFF/JPG which we couldnt before!)
                            I mean if Poffs stats are anything to go by then not too many people have done too much work in GDI+, but you two have contributed a hell of a lot and I've no doubt that a LOT of PB programmers would've benefited greatly from your contributions.
                            I think a lot of people here including myself owe you both a round of drinks lol
                            Awesome work guys, absolutely awesome. I hereby declare Patrice and Jose GDI+ Jedis !
                            -

                            Comment


                            • #15
                              Wayne

                              GDImage is the only graphic package that would work with VISTA in DWM composited mode.

                              If you have at least VISTA Premium try this:
                              The GDImage Crystal demo on José Roca's forum

                              ...
                              Patrice Terrier
                              www.zapsolution.com
                              www.objreader.com
                              Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

                              Comment


                              • #16
                                Originally posted by José Roca View Post
                                There are some 150 GDI+ examples in my forum. This one shows how to lock pixels for reading and access the Scan0 member:
                                http://www.jose.it-berater.org/smffo...picseen#msg421
                                Hmmm even that one is failing on GdipBitmapLockBits with an error code of 2, just like my one is. I tried it with a BMP file instead of a PNG but still the same fail, any ideas? Apparently error #2 = Invalid Parameter. A google for GdipBitmapLockBits shows that it seems to be a common problem

                                One guy said "i found data type BitmapData has multiple defines, one in bitmap-private.h and another in GdiPlusFlat.h, this cause the error", but he didn't have a fix for it

                                So maybe my defines are wrong ... I couldn't find TB_GDIPLUS.INC so I had to use my own definitions, could you hit me with a link to that include file please? I used the Search function at your forum but it didnt find any matches. Hopefully that'll fix the problem!

                                Many thanks again
                                -

                                Comment


                                • #17
                                  I have already posted the link for TB_GDIPLUS.INC
                                  http://www.jose.it-berater.org/smffo...php?topic=88.0

                                  It is included included in the file TB_GDIPLUS.ZIP, posted as an attachment, but you won't see it nor download it unless you register first as a member of the forum.

                                  Code:
                                  TYPE BitmapData
                                     nWidth AS DWORD
                                     nHeight AS DWORD
                                     Stride AS LONG
                                     PixelFormat AS DWORD
                                     Scan0 AS DWORD
                                     Reserved AS DWORD
                                  END TYPE
                                  Code:
                                  DECLARE FUNCTION GdipBitmapLockBits LIB "GDIPLUS.DLL" ALIAS "GdipBitmapLockBits" ( _
                                      BYVAL pbitmap AS DWORD _                            ' *GpBitmap
                                    , BYREF prect AS RECTL _                              ' *GDIPCONST GpRect <record>
                                    , BYVAL flags AS DWORD _                              ' UINT
                                    , BYVAL PixelFormat AS LONG _                         ' PixelFormat
                                    , BYREF lockedBitmapData AS BitmapData _              ' *BitmapData <record>
                                      ) AS LONG                                           ' GpStatus <enum>
                                  I have run the example and works fine with the bitmap file included in the attachment.
                                  Forum: http://www.jose.it-berater.org/smfforum/index.php

                                  Comment


                                  • #18
                                    Ok, for those wanting to take it the hard way ( easy way is GDImage )

                                    One important thing you must be aware: GDIPLUS graphics are full 32-bit and the alpha channel must be preserved if you want to work with graphic formats using it, like PNG files for example.

                                    Code:
                                    ' Information about image pixel data
                                    TYPE BitmapData
                                       nWIDTH AS LONG
                                       nHeight AS LONG
                                       stride AS LONG
                                       PixelFormat AS LONG
                                       scan0 AS LONG
                                       Reserved AS LONG
                                    END TYPE
                                    
                                    %ImageLockModeRead = &H1
                                    %ImageLockModeWrite = &H2
                                    %ImageLockModeUserInputBuf = &H4
                                    
                                    DECLARE FUNCTION GdipBitmapLockBits LIB "gdiplus.dll" ALIAS "GdipBitmapLockBits" (BYVAL nBitmap AS LONG, nRect AS RECTL, BYVAL ImageLockMode AS LONG, BYVAL PixelFormat AS LONG, lockedBitmapData AS BitmapData) AS LONG
                                    DECLARE FUNCTION GdipBitmapUnlockBits LIB "gdiplus.dll" ALIAS "GdipBitmapUnlockBits" (BYVAL nBitmap AS LONG, lockedBitmapData AS BitmapData) AS LONG
                                    Code:
                                    TYPE MYBITMAPINFO
                                        bmiHeader AS BITMAPINFOHEADER
                                        bmiColors(256) AS RGBQUAD ' Patrice
                                    END TYPE
                                    
                                    FUNCTION zGetDIBits ALIAS "zGetDIBits" (BYVAL hBitmap AS LONG, PixelArray() AS LONG) EXPORT AS LONG
                                        LOCAL bi AS MYBITMAPINFO
                                        LOCAL bm AS BITMAP
                                        LOCAL dwp AS DWORD PTR
                                        LOCAL hIC AS LONG, hDC AS LONG
                                        IF hBitmap THEN
                                           hIC = zDisplayDC()
                                           hDC = CreateCompatibleDC(hIC)
                                           CALL SelectObject(hDC, hBitmap)
                                    
                                           CALL GetObject(hBitmap, SIZEOF(bm), bm)
                                           bi.bmiHeader.biSize        = SIZEOF(bi.bmiHeader)
                                           bi.bmiHeader.biWidth       = bm.bmWidth
                                           bi.bmiHeader.biHeight      = -bm.bmHeight ' Put top in TOP instead on bottom!
                                           bi.bmiHeader.biPlanes      = 1
                                           bi.bmiHeader.biBitCount    = 32
                                           bi.bmiHeader.biCompression = %BI_RGB
                                           REDIM PixelArray(bm.bmWidth - 1, bm.bmHeight - 1) AS LONG
                                           dwp = VARPTR(PixelArray(0,0))
                                           FUNCTION = GetDIBits(hDC, hBitmap, 0, bm.bmHeight, BYVAL dwp, bi, %DIB_RGB_COLORS)
                                    
                                           CALL DeleteDC(hIC)
                                           CALL DeleteDC(hDC)
                                    
                                        END IF
                                    END FUNCTION
                                    '
                                    FUNCTION zSetDIBits ALIAS "zSetDIBits" (BYVAL hBitmap AS LONG, PixelArray() AS LONG) EXPORT AS LONG
                                        LOCAL bi AS MYBITMAPINFO
                                        LOCAL bm AS BITMAP
                                        LOCAL dwp AS DWORD PTR
                                        LOCAL hIC AS LONG, hDC AS LONG
                                        IF hBitmap THEN
                                           hIC = zDisplayDC()
                                           hDC = CreateCompatibleDC(hIC)
                                           CALL SelectObject(hDC, hBitmap)
                                    
                                           CALL GetObject(hBitmap, SIZEOF(bm), bm)
                                           bi.bmiHeader.biSize        = SIZEOF(bi.bmiHeader)
                                           bi.bmiHeader.biWidth       = bm.bmWidth
                                           bi.bmiHeader.biHeight      = -bm.bmHeight ' Put top in TOP instead on bottom!
                                           bi.bmiHeader.biPlanes      = 1
                                           bi.bmiHeader.biBitCount    = 32
                                           bi.bmiHeader.biCompression = %BI_RGB
                                           dwp = VARPTR(PixelArray(0,0))
                                           FUNCTION = SetDIBits(hDC, hBitmap, 0, bm.bmHeight, BYVAL dwp, bi, %DIB_RGB_COLORS)
                                    
                                           CALL DeleteDC(hIC)
                                           CALL DeleteDC(hDC)
                                    
                                        END IF
                                    END FUNCTION
                                    In the GDImage trial version, look at the source code of resource.bas and search for ZD_GetBitmapObjectBits and ZD_SetBitmapObjectBits they are the helper functions to manipulate a pixel array.

                                    ...
                                    Last edited by Patrice Terrier; 4 May 2008, 05:36 AM.
                                    Patrice Terrier
                                    www.zapsolution.com
                                    www.objreader.com
                                    Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

                                    Comment


                                    • #19
                                      Cool, Jose I downloaded that demo of yours and the BMP was read successfully (was a big relief to call that API successfully after so many failed attempts!), then I changed it over to a PNG but it failed with error 2 again. But changing the pixel format to %PixelFormat24bppRGB fixed that (which works for both 8 and 24bit PNGs - strangely %PixelFormat8bppIndexed didnt work for the 8bit one). %PixelFormat24bppRGB seems to be the only one that works for PNG

                                      Ok so now that ive finally got access to this damned bitmap data I can start the real work

                                      Many cheers again Jose and Patrice

                                      ps. awesome GDI header file Jose, looks very complete
                                      -

                                      Comment

                                      Working...
                                      X