Announcement

Collapse
No announcement yet.

Source code for Loading JPEg,GIF,PNG using GDIplus (for DDT and SDK)

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

  • Source code for Loading JPEg,GIF,PNG using GDIplus (for DDT and SDK)

    I spent hours working on this code, but I finally have it working somewhat (DDT version).

    The code works perfectly for loading JPeg,GIF and PNG images and returning an API Bitmap handle. SDK'ers get perfect working code.

    I finally got it working where it can return a DDT Bitmap handle (not the same an API bitmap), but the routine has go through hoops to do it. The image has to be loaded into a 24 bit DIB and then run through the image using pointers inverting all the pixel bytes and then swapping the red and blue pixels. I am not sure, but I think DDT stores images in CMYK format rather than RGB.

    The code works, but for some unknown reason when I BitBlt the image to a DDT bitmap, there is a white line at the top.

    Maybe someone can figure it out, so even the DDT version works perfectly. But I did the hard stuff.

    You can see the code and download it here:
    http://cwsof.com/forums/index.php?topic=488.0

    The beauty of this include file is that it does not require any GDI+ API includes to use it. All the GDI+ declarations necessary are in it.

    At least for SDK coders you can now load JPeg,GIF and PNG effortlessly. Just add the include to your app and then a simple call loads the image, like this:

    ie.

    hBmp = GDIP_LoadImage(0, F$, -1,-1,1)

    Loads image and returns an API Bitmap.

    There are two functions in the include, which are:

    GDIP_GetImageSize F$, W&, H&

    Reads an image file and returns the size (width and height) in pixels, without loading.

    F$ is the filename (full path) of any Image file windows supports (ie. JPeg, PNG, GIF)
    W& is a long variable to return the width in pixels
    H& is a long variable to return the height in pixels

    hBmp& = GDIP_LoadImage(DMode&, F$, W&, H&, QFlag&)

    Loads an image file (JPeg,GIF or PNG)

    DMode& if non-zero (1) makes function return a DDT Bitmap, rather than an API Bitmap
    F$ is the filename (full path) of any Image file windows supports (ie. JPeg, PNG, GIF)
    W& is the requested width of the image (in pixels)
    H& is the requested height of the image (in pixels)
    QFlag& if set to non-zero (1) requests best quality possible image

    If W& and H& are set to -1 (or even zero) then the routine will use the actual size of the image on file.

    The return value is a Bitmap handle.
    If DMode& is non-zero (1) then the handle is a DDT Bitmap handle which can only be used with DDT Graphic commands.
    If DMode& is zero, then the handle is an API Bitmap handle, which can only be used with the API and not DDT Graphic commands.

    The code is based on code by Dan Ginzel, but totally reworked to make it simple and easy to use.

    Enjoy!
    Chris Boss
    Computer Workshop
    Developer of "EZGUI"
    http://cwsof.com
    http://twitter.com/EZGUIProGuy

  • #2
    As a DDT user, thank you for your hard work on this, Chris!

    Comment


    • #3
      Forgive my ignorance about bitmaps.
      The code compiles ok.
      But how can I use the handle hBmp to display the image in a DDT window?
      /Fim W.
      Fim Wästberg

      Comment


      • #4
        Don't know about Chris' code, but here's a demo of gettiing an image file and displaying it in DDT.

        It uses a cut down GDI+ include file

        Application:
        Code:
        #COMPILE EXE
        #DIM ALL
        %UNICODE = 1
        #INCLUDE "Win32API.inc"
        #INCLUDE ONCE "Gdicut.inc"
        
        ENUM Controls SINGULAR
         IDC_btnGetImage = 1001
         IDC_btnClose
         IDC_txtPhotoname
         IDC_Graphic
        END ENUM
        
        FUNCTION PBMAIN() AS LONG
            LOCAL GdipToken, hDlg AS DWORD
            LOCAL lResult AS LONG
            LOCAL StartupInput AS GdiplusStartupInput
            StartupInput.GdiplusVersion = 1
            IF GdiplusStartup(GdipToken,StartupInput, BYVAL %NULL) THEN
                MSGBOX "Error initialising GDI+ ... (Also, program needs XP or later)"
                EXIT FUNCTION
            END IF
        
            DIALOG NEW 0, "Image Demo", 203, 90, 368, 217, %WS_OVERLAPPED OR _
                %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _
                %WS_MAXIMIZEBOX OR %WS_VISIBLE OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
                %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
            CONTROL ADD GRAPHIC, hDlg, %IDC_Graphic, "", 35, 15, 180, 140, %SS_SUNKEN _
                OR %WS_CHILD OR %WS_VISIBLE
            CONTROL ADD TEXTBOX, hDlg, %IDC_txtPhotoName, "", 40, 160, 300, 10
            CONTROL ADD BUTTON,  hDlg, %IDC_btnGetImage, "Get Image", 260, 125, 70, _
                25
            CONTROL ADD BUTTON,  hDlg, %IDC_btnClose, "Close", 260, 175, 70, 25
            DIALOG SHOW MODAL hDlg, CALL DlgProc TO lResult
         GdiplusShutdown GdipToken       'Shutdown GDI plus
        
        END FUNCTION
        
        CALLBACK FUNCTION DlgProc() AS LONG
        LOCAL lResult AS LONG
        LOCAL wstrImg AS WSTRING
            SELECT CASE AS LONG CB.MSG
                CASE %WM_COMMAND
                    SELECT CASE AS LONG CB.CTL
                        CASE %IDC_txtPhotoName
        
                        CASE %IDC_btnGetImage
                            IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                               lResult =  BrowseForImage(CB.HNDL,wstrImg )
                               lResult = ShowImage( CB.HNDL,wstrImg)
                            END IF
        
                        CASE %IDC_btnClose
                            IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                DIALOG END CB.HNDL
                            END IF
        
                    END SELECT
            END SELECT
        END FUNCTION
        
        '------------------------------------------------------------------------------
        '   ** Image  Functions**
        '------------------------------------------------------------------------------
        FUNCTION BrowseForImage(hDlg AS DWORD, _            'hDlg is handle of Parent
                    BYREF InputImage AS WSTRING) AS LONG     'Browse for file InputImage
            DISPLAY OPENFILE hDlg, , , _                    'Browse to file
                "Browse for Main photo / image", _
                PATHNAME$(PATH,  InputImage ), _
                CHR$("Images",0,"*.jpg;*.png;*.gif;*.bmp",0, "All Files", 0, "*.*"), _
                PATHNAME$(NAMEX, InputImage ), "jpg", _
                %OFN_FILEMUSTEXIST OR %OFN_ENABLESIZING TO InputImage
        END FUNCTION
        
        FUNCTION ShowImage(hDlg AS DWORD,Photo AS WSTRING) AS LONG
           LOCAL hGraphic AS DWORD
           LOCAL wsTemp AS STRING
           LOCAL x,y AS LONG
           DIALOG UNITS hDlg, 180, 140 TO PIXELS y,x  'PB 10.04 reversed! 10.03  use x,y
           wsTemp = Photo
           IF DIR$(wsTemp) = "" THEN
               MSGBOX  wsTemp & " not found!"
               EXIT FUNCTION
           END IF
             hGraphic = GraphicLoadImageFileToBitmap(wsTemp,x,y,0)
             GRAPHIC ATTACH hGraphic,0
             GRAPHIC GET CANVAS TO X,Y
             GRAPHIC ATTACH hDlg,  %IDC_Graphic
        
             GRAPHIC CLEAR
             GRAPHIC COPY hGraphic,%IDC_Graphic
             GRAPHIC ATTACH hGraphic,0
             GRAPHIC BITMAP END
             CONTROL SET TEXT hdlg,%IDC_txtPhotoName, Photo
        END FUNCTION
        Include File: GDICut.inc

        Code:
        '==================================================================================================
        ' GDI Plus includes for Loading images from file (eg .jpg) to/from PB Bitmaps
        '==================================================================================================
        ' Code below based on "" by Chris Holbrook PB Forums 3 Jan 2010, based on Jose Roca's work
        '
        ' When dealing with API's such as GDI plus the proper course of action is to grab the type library
        ' from Jose Roca's site (or others...) as an include, and all the functions will be available.
        ' The downside is that your compile time may well go through the roof, and you have no chance of
        ' browsing or understanding just HOW MUCH of that library is being used. And because it basically
        ' supersedes the powerbasic libraries, things may get complicated when you upgrade. Following the
        ' approach used by Chris Holbrook (and others...) a second method is to include this file, with
        ' just the stripped down declarations necessary to get the job done - about 2% of the original.
        '
        ' You need need to be able to find out about GDI plus, reference Jose Rocas site (link @ 2/2/2010)
        ' http://www.jose.it-berater.org/gdiplus/iframe/index.htm
        ' You also should have on hand a link to full type library from Jose Roca (link valid @ 2/2/2010)
        ' http://www.jose.it-berater.org/smfforum/index.php?board=344.0
        '
        '--------------------------------------------------------------------------------------------------
        %UnitPixel = 2 ' Sets each unit to be one device pixel
        '--------------------------------------------------------------------------------------------------
        '
        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
        '--------------------------------------------------------------------------------------------------
        '
        TYPE ImageCodecInfo
        ClassID AS GUID ' CLSID. Codec identifier
        FormatID AS GUID ' GUID. File format identifier
        CodecName AS DWORD ' WCHAR*. Pointer to a null-terminated string
        ' that contains the codec name
        DllName AS DWORD ' WCHAR*. Pointer to a null-terminated string
        ' that contains the path name of the DLL in
        ' which the codec resides. If the codec is not
        ' a DLL, this pointer is NULL
        FormatDescription AS DWORD ' WCHAR*. Pointer to a null-terminated string
        ' that contains the name of the format used by the codec
        FilenameExtension AS DWORD ' WCHAR*. Pointer to a null-terminated string
        ' that contains all file-name extensions associated
        ' with the codec. The extensions are separated with semicolons.
        MimeType AS DWORD ' WCHAR*. Pointer to a null-terminated string
        ' that contains the mime type of the codec
        Flags AS DWORD ' Combination of flags from the ImageCodecFlags enumeration
        Version AS DWORD ' Integer that indicates the version of the codec
        SigCount AS DWORD ' Integer that indicates the number of signatures
        ' used by the file format associated with the codec
        SigSize AS DWORD ' Integer that indicates the number of bytes of each signature
        SigPattern AS DWORD ' BYTE*. Pointer to an array of bytes that contains
        ' the pattern for each signature
        SigMask AS DWORD ' BYTE*. Pointer to an array of bytes that contains
        ' the mask for each signature
        END TYPE
        '--------------------------------------------------------------------------------------------------
        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)
        DECLARE FUNCTION GdipGetImageEncodersSize LIB "GDIPLUS.DLL" ALIAS "GdipGetImageEncodersSize" _
        (numEncoders AS DWORD, nSize AS DWORD) AS LONG
        DECLARE FUNCTION GdipGetImageEncoders LIB "GDIPLUS.DLL" ALIAS "GdipGetImageEncoders" _
        (BYVAL numEncoders AS DWORD, BYVAL nSize AS DWORD, BYVAL lpEncoders AS DWORD) AS LONG
        DECLARE FUNCTION GdipSaveImageToFile LIB "GDIPLUS.DLL" ALIAS "GdipSaveImageToFile" _
        (BYVAL lpImage AS DWORD, BYVAL flname AS DWORD, BYREF clsidEncoder AS GUID, _
        BYREF EncoderParams AS DWORD) AS LONG
        DECLARE FUNCTION GdipLoadImageFromFile LIB "GDIPLUS.DLL" ALIAS "GdipLoadImageFromFile" _
        (BYVAL flnameptr AS DWORD, lpImage AS DWORD) AS LONG
        '1st parm of GdipLoadImageFromFile is byval string in Patrice's translation and byval dword in
        ' Jose Roca's translation "for consistency with 1000s of functions..." per PBforums 19/11/09
        DECLARE FUNCTION GdipGetImageDimension LIB "GDIPLUS.DLL" ALIAS "GdipGetImageDimension" _
        (BYVAL nImage AS LONG, nWidth AS SINGLE, Height AS SINGLE) AS LONG
        DECLARE FUNCTION GdipCreateFromHDC LIB "GDIPLUS.DLL" ALIAS "GdipCreateFromHDC" _
        (BYVAL hdc AS LONG, graphics AS LONG) AS LONG
        DECLARE FUNCTION GdipDrawImageRectRect LIB "GDIPLUS.DLL" ALIAS "GdipDrawImageRectRect" _
        (BYVAL graphics AS DWORD, BYVAL pImage AS DWORD, _
        BYVAL dstx AS SINGLE, BYVAL dsty AS SINGLE, BYVAL dstwidth AS SINGLE, BYVAL dstheight AS SINGLE, _
        BYVAL srcx AS SINGLE, BYVAL srcy AS SINGLE, BYVAL srcwidth AS SINGLE, BYVAL srcheight AS SINGLE, _
        BYVAL srcUnit AS LONG, BYVAL imageAttributes AS DWORD, _
        BYVAL pcallback AS DWORD, BYVAL callbackData AS DWORD) AS LONG
        DECLARE FUNCTION GdipCreateBitmapFromGdiDib LIB "GDIPLUS.DLL" ALIAS "GdipCreateBitmapFromGdiDib" _
        (BYREF BitMapInfo, BYVAL DWORD, BYREF DWORD) AS LONG
        DECLARE FUNCTION GdipDisposeImage LIB "GDIPLUS.DLL" ALIAS "GdipDisposeImage" _
        (BYVAL lpImage AS DWORD) AS LONG
        DECLARE FUNCTION GdipDeleteGraphics LIB "GDIPLUS.DLL" ALIAS "GdipDeleteGraphics" _
        (BYVAL Graphics AS LONG) AS LONG
        ' I need to leave 3 more (unused) definitions here for compatibility with another module I use:
        'declare function GdipGetImagePixelFormat lib "GDIPLUS.DLL" alias "GdipGetImagePixelFormat" _
        ' (byval nImage as long, PixelFormat as long) as long
        'declare function GdipCreateBitmapFromScan0 lib "GDIPLUS.DLL" alias "GdipCreateBitmapFromScan0" _
        ' (byval long, byval long, byval long, byval long, byref any, byref dword) as long
        'declare function GdipGetImageGraphicsContext lib "GDIPLUS.DLL" alias "GdipGetImageGraphicsContext" _
        ' (byval nImage as long, graphics as long) as long
        '--------------------------------------------------------------------------------------------------
        
        ' ==========================================================================
        ' GetEncoderClsid
        ' The function GetEncoderClsid in the following example receives the MIME
        ' type of an encoder and returns the class identifier (CLSID) of that encoder.
        ' The MIME types of the encoders built into GDI+ are as follows:
        ' image/bmp image/jpeg image/gif image/tiff image/png
        ' ==========================================================================
        FUNCTION GdiPlusGetEncoderClsid (BYVAL strMimeType AS STRING) AS STRING
        'Retrieve encoder's clsid, where strMimeType is ansi string e.g. "image/jpeg"
        'Routine courtesy Jose Roca GdipUtils.inc, freeware, posted PB Forums 23/12/09
        
        LOCAL hr AS LONG
        LOCAL pImageCodecInfo AS ImageCodecInfo PTR
        LOCAL numEncoders AS DWORD
        LOCAL nSize AS DWORD
        LOCAL i AS LONG
        LOCAL wstrlen AS LONG
        LOCAL sMimeType AS STRING
        
        hr = GdipGetImageEncodersSize(numEncoders, nSize)
        REDIM buffer(nSize - 1) AS BYTE
        pImageCodecInfo = VARPTR(buffer(0))
        hr = GdipGetImageEncoders(numEncoders, nSize, BYVAL pImageCodecInfo)
        IF hr = 0 THEN
        FOR i = 1 TO numEncoders
        wstrlen = lstrlenW(BYVAL @pImageCodecInfo.MimeType)
        IF wstrlen THEN sMimeType = ACODE$(PEEK$(@pImageCodecInfo.MimeType, wstrlen * 2))
        IF INSTR(UCASE$(sMimeType), UCASE$(strMimeType) ) THEN
        FUNCTION = GUIDTXT$(@pImageCodecInfo.ClassID)
        EXIT FOR
        END IF
        INCR pImageCodecInfo '// Increments pointer
        NEXT
        END IF
        
        END FUNCTION
        
        '===============================================================================
        ' Loading images from file .png .jpg .gif .tif ( and .bmp) to/from PB Bitmaps
        '===============================================================================
        
        FUNCTION GraphicLoadImageFileToBitmap( _
        BYREF sImageFileName AS STRING, _ 'Image to load, extension = type
        OPTIONAL BYVAL MaxWidth AS DWORD, _ 'Constrain Width to value, 0 = None
        OPTIONAL BYVAL MaxHeight AS DWORD, _ 'Constrain Height value, 0 = None
        OPTIONAL BYVAL StretchImg AS DWORD _ '0 = normal, 1 = Stretch image to xy
        ) AS DWORD 'Returns PB bitmap handle of image
        '-------------------------------------------------------------------------------
        'Supply the function with an ImageFileName - for instance photo.jpg - and it
        ' will attempt to make a new PB Graphic memory bitmap containing the image.
        'You can optionally specify a maximum width and/or height for the image, and
        ' have the routine scale it as it is read in. While rarely needed, you can
        ' also optionally stretch the image, in which case the image will be made to
        ' equal MaxWidth and MaxHeight even though that may stretch or squash it.
        'sImageFileName can be name or path+name, extn determines file type, eg jpg, png
        'The function needs GDIPlus - so your program needs XP or better, basically.
        'You need to call GdiplusStartup and GdiplusShutdown in your apps init/close
        ' If you do not Gdiplus calls will access memory they are not allowed - a GPF
        'When you are finished using the PB memory bitmap, you must delete it with
        ' GRAPHIC BITMAP END. (Steven Murray 3 February 2010 airborn.com.au)
        '-------------------------------------------------------------------------------
        LOCAL ucImageFileName AS WSTRING 'sImageFileName converted to unicode
        LOCAL pImage AS DWORD 'GDI+ image pointer, after reading in
        LOCAL ImgWidth AS SINGLE 'Image width, pixels
        LOCAL ImgHeight AS SINGLE 'Image height, pixels
        LOCAL hBmp AS DWORD 'PB Graphic bitmap handle for image
        LOCAL hDC AS DWORD 'Device context for PB Graphic bitmap
        LOCAL pGraphics AS DWORD 'GDI+ Graphics object used to draw image
        LOCAL hStatus AS LONG 'Status return value
        
        IF StretchImg<>0 AND (MaxWidth=0 OR MaxHeight=0) THEN EXIT FUNCTION 'If bogus xy
        IF ISFALSE ISFILE(sImageFileName) THEN
        MSGBOX "[GraphicLoadImageFileToBitmap] called on <" & sImageFileName & _
        "> Missing file"
        EXIT FUNCTION 'Exit if image not available
        END IF
        ucImageFileName = sImageFileName 'Gdip wants filename as unicode
        'Next ask GDI+ to read in the picture (ucImageFileName) to GDI+ image (pImage)
        hStatus = GdipLoadImagefromFile(STRPTR(ucImageFileName),pImage)
        IF hStatus THEN
        MSGBOX "[GraphicLoadImageFileToBitmap] [GdipLoadImagefromFile] read error on <" & _
        sImageFileName & ">"
        EXIT FUNCTION 'Exit if GDI plus error on read
        END IF
        
        GdipGetImageDimension(pImage, ImgWidth, ImgHeight) 'Quiz GDI to get image size
        IF ImgWidth = 0 OR ImgHeight = 0 THEN EXIT FUNCTION 'Exit if bogus image size
        
        IF MaxWidth = 0 THEN MaxWidth = ImgWidth 'If not specified, width = actual
        IF MaxHeight = 0 THEN MaxHeight = ImgHeight 'If not specified, height = actual
        IF StretchImg= 0 THEN 'Only find maximums if no stretch
        IF (ImgWidth / MaxWidth) > (ImgHeight / MaxHeight) THEN 'If width constrained
        IF ImgWidth > MaxWidth THEN 'If a shrink is needed
        MaxHeight = ImgHeight / (ImgWidth / MaxWidth) 'MaxHeight is now new y
        END IF
        ELSE
        IF ImgHeight > MaxHeight THEN 'If a shrink is needed
        MaxWidth = ImgWidth / (ImgHeight / MaxHeight) 'MaxWidth is now new x
        END IF
        END IF
        END IF
        
        GRAPHIC BITMAP NEW MaxWidth, MaxHeight TO hBmp 'Make a correctly sized PB Bitmap
        IF hBmp = 0 THEN 'Test if PB could make the Bitmap
        IF pImage THEN GdipDisposeImage(pImage) 'Cleanup
        EXIT FUNCTION 'Exit if PB could not make Bitmap
        END IF
        'Else, we have proper sized Bitmap
        GRAPHIC ATTACH hBmp, 0 'Select Bitmap as graphic target
        GRAPHIC GET DC TO hDC 'Get a device context for Bitmap
        
        hStatus = GdipCreateFromHDC(hDC, pGraphics) 'Create Graphic object
        hStatus = GdipDrawImageRectRect(pGraphics, pImage, 0, 0, MaxWidth, MaxHeight, _
        0, 0, ImgWidth, ImgHeight, %UnitPixel, %NULL, %NULL, %NULL)
        
        IF pImage THEN GdipDisposeImage(pImage) 'Cleanup
        IF pGraphics THEN GdipDeleteGraphics(pGraphics) ' more Cleanup
        
        IF hStatus = 0 THEN
        FUNCTION = hBmp 'If draw worked, return Bitmap
        ELSE
        GRAPHIC BITMAP END 'If draw failed, release Bitmap
        END IF
        
        GRAPHIC DETACH 'Finished with Bitmap, detach
        END FUNCTION
        
        '===============================================================================
        FUNCTION GraphicSaveBitmapToImageFile(BYVAL hBmp AS DWORD, _
        sImageFileName AS STRING) AS LONG
        '-------------------------------------------------------------------------------
        'Supply the function with a PB Graphic memory bitmap containing an image,
        ' while specifying an ImageFileName - For instance photo.jpg - to write
        'The extension of the filename selects image type: .png/.jpg/.gif/.bmp/.tif
        'This function is intended as the complement of GraphicLoadImageFileToBitmap
        'The function needs GDIPlus - so your program needs XP or better, basically.
        'When you are finished using the PB memory bitmap, you must delete it with
        ' GRAPHIC BITMAP END. (Steven Murray 3 February 2010 airborn.com.au)
        '-------------------------------------------------------------------------------
        ' hBmp PB bitmap handle of image to be saved
        ' sImageFileName Name image to be saved as, extn = type
        LOCAL ucImageFileName AS STRING 'sImageFileName converted to unicode
        LOCAL Exten AS STRING 'sImageFileName extension eg ".jpg"
        LOCAL FType AS STRING 'sImageFileName mime-type eg "image-jpeg"
        LOCAL EncoderClsid AS GUID '16 byte GUID string of image encoder
        
        LOCAL bmpDat AS STRING 'PB graphic bitmap saved to this string
        LOCAL ImgWidth AS LONG 'Width of the bitmap in pixels
        LOCAL ImgHeight AS LONG 'Height of the bitmap in pixels
        LOCAL PixelPtr AS DWORD 'Pointer the start of the pixel data
        
        LOCAL sbmi AS Bitmapinfo 'Bitmapinfo Structure - dib header
        LOCAL pImage AS DWORD 'GDI+ image pointer, after conversion
        LOCAL hStatus AS LONG 'Status return value
        
        FUNCTION = %TRUE '
        GRAPHIC ATTACH hBmp, 0 'Select Bitmap as "graphic target" to read out of
        GRAPHIC GET BITS TO bmpDat 'And get the image data into the string bmpDat
        
        ImgWidth = CVL(bmpDat,1) : ImgHeight = CVL(bmpDat,5) 'Get PB bitmap dimensions
        PixelPtr = STRPTR(bmpDat) + 8 'First 8 bytes are width/height, then pixels
        
        sbmi.bmiHeader.biSize = SIZEOF(sbmi.bmiHeader) 'Length of the structure
        sbmi.bmiHeader.biWidth = ImgWidth 'Width of the bitmap
        sbmi.bmiHeader.biHeight = 0-ImgHeight 'Height + sign is drawing direction
        sbmi.bmiHeader.biPlanes = 1
        sbmi.bmiHeader.biBitCount = 32 'Each pixel in bitmap is 32 bits
        sbmi.bmiHeader.biCompression = %BI_RGB 'Actually, PB says it is BGR, but this works
        
        'Next create a GDI+ bitmap (called pImage) from the bmi header we just made
        ' and the Pixel data supplied by "Graphic Get Bits" from the original bitmap
        hStatus = GdipCreateBitmapFromGdiDib(BYREF sbmi, BYVAL PixelPtr, pImage)
        IF hStatus THEN FUNCTION = %FALSE : EXIT FUNCTION 'Indicate failure and exit
        
        Exten = LCASE$(PATHNAME$(EXTN,sImageFileName)) : FType = "" 'Get extension
        'Now translate the file extension (eg ".png") to mimetype (eg "image/png")
        FType = SWITCH$(Exten=".png", "image/png", Exten=".jpg", "image/jpeg", _
        Exten=".gif", "image/gif", Exten=".tif", "image/tiff", _
        Exten=".bmp", "image/bmp") 'Default seems to be bmp
        EncoderClsid = GUID$(GdiPlusGetEncoderClsid(FType)) 'Get the CLSID of selected encoder
        ucImageFileName = UCODE$(sImageFileName & $NUL) 'Translate the filename to unicode
        
        'Next save the GDI+ bitmap (pImage) as an image of type specified by EncoderClsid
        'to the filename specified when this function was called with no Encoder parameters
        hStatus = GdipSaveImageToFile(pImage, STRPTR(ucImageFileName), EncoderClsid, BYVAL %Null)
        IF hStatus THEN FUNCTION = %FALSE
        
        IF pImage THEN GdipDisposeImage(pImage) 'Cleanup
        END FUNCTION
        '-----------------------------------------------------------------------------

        Comment


        • #5
          Stuart,
          Works as I intended, but it will probably take a while before I understand what I am doing.
          Fim Wästberg

          Comment

          Working...
          X