Announcement

Collapse
No announcement yet.

Using GDIP to place image on GRAPHIC WINDOW

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

  • Using GDIP to place image on GRAPHIC WINDOW

    The GDI Plus library has some very clever stuff in it - which is enough to scare most people off. Only the brave and talented have mastered it - the rest of us just creep around the edges. Fortunately, only a few API calls are needed to load and display many image formats, and the results are - at least for those of us who are dealing with photographic images - very acceptable, and superior for this purpose to the "builtin" functions like GRAPHIC STRETCH.

    I started with Patrice Terrier's include file and whittled it doen to a bare minimum to load and resize an image. The include file is below, with a little demonstration program. You will need an image file called test.jpg in the same directory as the application. Or you can change the code, of course. I suggest that you use a photographic image.

    *** Added *** also, note that the aspect ratio is preserved. (This is not a GDIP exclusive!)



    include file picogdip.inc:
    Code:
    '--------------------------------------------------------------------------------
    ' picoGDIP.inc  placed in public domain by Chris Holbrook May 2008
    '
    ' based on code by Messrs Terrier, Schullian, Walker & others, thanks to Simon Morgan for debugging.
    ' modified Jan 2008: globals no longer used
    '          Dec 2008: some redundant code removed
    '--------------------------------------------------------------------------------
    'GDIP CONSTANTS
    %QualityModeHigh = 2       ' Best rendering quality
    %UnitPixel       = 2 ' Each unit is one device pixel.
    '--------------------------------------------------------------------------------
    ' pico-GDIP.inc
    '
    '-----------------------------------------------------------------------------------------------------------------------
    '
    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
    '  // The following 2 fields are NULL if SuppressBackgroundThread is FALSE.
    '  // Otherwise, they are functions which must be called appropriately to
    '  // replace the background thread.
    '  //
    '  // These should be called on the application's main message loop - i.e.
    '  // a message loop which is active for the lifetime of GDI+.
    '  // "NotificationHook" should be called before starting the loop,
    '  // and "NotificationUnhook" should be called after the loop ends.
       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 GdipSetInterpolationMode lib "gdiplus.dll" alias "GdipSetInterpolationMode" (byval graphics as long, byval interpolation as long) as long
    declare function GdipDrawImageRectI lib "gdiplus.dll" alias "GdipDrawImageRectI" (byval graphics as long, byval nImage as long, byval x as long, byval y as long, byval nWidth as long, byval Height as long) as long
    
    declare function GdipGetImageWidth lib "gdiplus.dll" alias "GdipGetImageWidth" (byval nImage as long, nWidth as long) as long
    declare function GdipGetImageHeight lib "gdiplus.dll" alias "GdipGetImageHeight" (byval nImage as long, Height as long) as long
    
    declare function GdipDeleteGraphics lib "gdiplus.dll" alias "GdipDeleteGraphics" (byval graphics as long) as long
    
    declare function GdipGraphicsClear lib "gdiplus.dll" alias "GdipGraphicsClear" (byval graphics as long, byval lColor as long) as long
    declare function GdipCreateFromHWND lib "gdiplus.dll" alias "GdipCreateFromHWND" (byval hwnd as long, graphics as long) as long
    declare function GdipCreateFromHDC lib "gdiplus.dll" alias "GdipCreateFromHDC" (byval hdc as long, graphics as long) as long
    
    declare function GdipGetImagePixelFormat lib "gdiplus.dll" alias "GdipGetImagePixelFormat" _
                (byval nImage as long, PixelFormat as long) as long
    declare function GdipGetImageDimension lib "gdiplus.dll" alias "GdipGetImageDimension" _
                (byval nImage as long, nWidth as single, Height as single) as long
    declare function GdipGetImageGraphicsContext lib "gdiplus.dll" alias "GdipGetImageGraphicsContext" _
                (byval nImage as long, graphics as long) as long
    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 GdipLoadImageFromFile lib "GDIPLUS.DLL" alias "GdipLoadImageFromFile" _
                (byval flname as string, lpImage as dword) as long
    declare function GdipDisposeImage lib "GDIPLUS.DLL" alias "GdipDisposeImage" _
                (byval lpImage as dword) as long
    declare function GdipCreateBitmapFromScan0 lib "gdiplus.dll" alias "GdipCreateBitmapFromScan0" _
                (byval nWidth as long, byval Height as long, byval stride as long, byval PixelFormat as long, _
                 scan0 as any, nBitmap as long) as long
    declare function GdipGetInterpolationMode lib "gdiplus.dll" alias "GdipGetInterpolationMode" _
                (byval graphics as long, interpolation as long) as long
    declare function GdipDrawImageRectRectI lib "gdiplus.dll" alias "GdipDrawImageRectRectI" _
                (byval graphics as long, byval nImage as long, byval dstx as long, byval dsty as long, _
                 byval dstwidth as long,  byval dstheight as long, byval srcx as long, byval srcy as long, _
                 byval srcwidth as long, byval srcheight as long, byval srcUnit as long, _
                 optional byval imageAttributes as long, optional byval pCALLBACK as long, _
                 optional byval callbackData as long) as long
    declare sub skIconise (byval xPic as long, byval yPic as long,            _ picture dimensions
                   byval xCell as long, byval yCell as long,          _ FRAME dimensions
                   byref xOfs as long, byref yOfs as long,            _ calc'd offset in frame
                   byref xSize as long, byref ySize as long)   ' thumbnail dimensions
    '
    
    '-----------------------------------------------------------------------------------------------------------------------
    ' write resized image to file and/or window.
    function ResizeImage (picpath as string, hW as dword, maxwidth as dword, maxheight as dword) as long
        local origwidth as single
        local origheight as single
        local lPixelFormat as long
        local s as string
        local extn as string
        local imagestyle as string
        local lresult, OfsX, OfsY, Tx, Ty as long
        local hbitmap, himage, graphics as dword
        local encoderCLSID as GUIDAPI
    
        GDIPLoadImageFromFile ucode$(picPath), hImage
        '
        if hImage = 0 then
            ' return image handle value of zero to indicate failure
            exit function
        end if
        '
        GdipGetImageDimension hImage, origwidth, origheight
        '
        skIconise ( origwidth, origheight, maxwidth, maxheight, ofsX, ofsY, tX, tY)
        '
        GdipGetImagePixelFormat hImage, lPixelFormat
    
        ' create right-size bitmap
        GdipCreateBitmapFromScan0 tX, tY, 0, lPixelFormat, byval 0&, hBitmap
        ' get graphics handle to bitmap
        GdipGetImageGraphicsContext hBitmap, graphics
        GdipSetInterpolationMode graphics, %QualityModeHigh
        ' drop image into graphics object
        GdipDrawImageRectRectI graphics, hImage, 0, 0, tX, tY, 0, 0, origwidth, origheight, %UnitPixel
        ' get rid of GDI objects
        call GdipDeleteGraphics(graphics)
        deleteobject hbitmap
        function = himage
    end function
    '
    '-------------------------------------------------------------------------------------------------------
    ' Computes location and size to stretch a bitmap preserving its aspect.
    '
    sub skIconise (byval xPic as long, byval yPic as long,            _ picture dimensions
                   byval xCell as long, byval yCell as long,          _ FRAME dimensions
                   byref xOfs as long, byref yOfs as long,            _ calc'd offset in frame
                   byref xSize as long, byref ySize as long) export   ' thumbnail dimensions
      local scale as single
    
        if xPIC& then scale! = xCell& / xPic&
        if scale! > 1 then scale! = 1
        xSize& = xPic& * scale!: ySize& = yPic& * scale!
      ' In case Height > 150 compute new scale factor
        if ySize& > yCell& then
           if yPic& then scale! = yCell& / yPic&
           xSize& = xPic& * scale!: ySize& = yPic& * scale!
        end if
        xOfs& = (xCell& - xSize&) \ 2
        yOfs& = (yCell& - ySize&) \ 2
    end sub
    demo program:
    Code:
    ' to show GDIPlus resizing an image in a GRAPHIC WINDOW
    ' Chris Holbrook 7 Dec 2008
    
    #compile exe
    #dim all
    #include once "win32api.inc"
    #include once "picogdip.inc"
    
    %pic_margin = 3
        '----------------------------------------------------------------------
    sub ShowImage ( hwin as dword, currentrect as rect, gdip_image as dword)
        local hdc, hG as dword
        local tx, ty, framex, framey, ofsx, ofsy as long
        local wide, high as single
    
        graphic get dc to hDC
        frameX = currentrect.nRight - currentrect.nLeft
        frameY = currentrect.nBottom - currentrect.nTop
        GdipGetImageDimension gdip_Image, wide, high
        ' calc coordinates to centre image in frame, retaining original proportion
        skIconise ( wide, high, frameX, frameY, ofsX, ofsY, tX, tY)
        if GdipCreatefromHDC ( hDC, hG) =  0 then
            if hG <> 0 then
               ' can also set smoothing mode, etc here
               GdipSetInterpolationMode(hG, %QualityModeHigh)
               GdipDrawImageRectI(hG, gdip_image, currentrect.nleft + %pic_margin, _
                                                  currentrect.ntop + %pic_margin, _
                                                  tX - 2*%pic_margin, tY - 2 * %pic_margin )
               if hG <> 0 then gdipdeletegraphics hG
            end if
        end if
        graphic redraw
    end sub
    
    function pbmain () as long
        static nstatus as long
        static token as dword
        static StartupInput as GdiplusStartupInput
        local skey as string
        local currentrect as rect
        local gdip_image as dword
        local clicked, X, Y as long
        local pt as point
        
        StartupInput.GdiplusVersion = 1
        nStatus = GdiplusStartup(token, StartupInput, byval %NULL)
        if nStatus then
            ?  "Error initializing GDI+", %mb_applmodal, "Warning"
            exit function
        end if
    
        ' Create and show a Graphic window on screen
    
        local hWin as dword
    
        graphic window "", 130, 130, 500, 500 to hWin
    
        graphic attach hWin, 0, redraw
        graphic set pos (0,0)
        
        setrect currentrect, 0, 30, 250, 250
        gdip_image = resizeimage ( "test.jpg", hwin, _
                               currentrect.nright - currentrect.nleft, _
                               currentrect.nbottom - currentrect.ntop )
        do
            graphic clear -1, 0
            graphic print "GDIP is being used to resize the image on a GRAPHIC WINDOW"
            graphic print "Use the mouse to size the image. Press esc to exit"
            showimage ( hWin, currentrect , gdip_image)
            sleep 2
            getcursorpos pt  ' a crude way of tracking the mouse!
            
            if (currentrect.nright <> pt.X ) or (currentrect.nbottom <> pt.Y ) then
                currentrect.nright = pt.X
                currentrect.nbottom = pt.Y
            else
                skey = ""
                graphic inkey$ to skey
                if skey = $esc then exit loop
            end if
        loop
                                                              
        GdiplusShutdown token
        graphic window end
    
    end function
    Last edited by Chris Holbrook; 7 Dec 2008, 06:53 PM. Reason: short attention - er...
Working...
X