• Welcome to Theos PowerBasic Museum 2017.

Using GdipCreateBitmapFromStream with embedded PNG images

Started by Dan Gin zel, March 23, 2013, 09:20:25 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Dan Gin zel

Briefly, I have been trying to figure out how to load a PNG from my embedded resources in hopes of taking advantage of transparency in my images.

I have no issue embedding a BMP in my resources and using GdipCreateBitmapFromStream to load it.

I can load a PNG from a file but I would really rather not have keep a number of PNG files attached to my EXE when embedding with #RESOURCE would be so much cleaner.

Any input that might point me in the right direction would be most appreciated.

Cheers!

Dan

[SIZE="1"]www.thecomputerarchive.com  Preserving the history of companies that advanced the computer revolution[/SIZE]

José Roca


Dan Gin zel

As soon as I saw your response, I realize what I had typed (at 2 AM.)

Yes, I am using GdipCreateBitmapFromResource 

Is there a special way I am supposed to put the PNG file in the resources ? Right now, I'm using

     #RESOURCE BITMAP, 15, "images\options.bmp"
[SIZE="1"]www.thecomputerarchive.com  Preserving the history of companies that advanced the computer revolution[/SIZE]

Patrice Terrier

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

José Roca


Dan Gin zel

I did try that earlier. Just tried it again without success.

     #RESOURCE RCDATA, 15, "images\options2.png"

and

               ResourceName = UCODE$("#15")
               Result = GdipCreateBitmapFromResource(hModule, ResourceName, pGDIPIcon)

The EXE is increasing in size appropriately so I believe the PNG is being included.

I believe my problem is how I am referencing the resource or perhaps there being another step. I have tried using the BMP version as RCDATA and it doesn't work, either.

I shall continue to research...
[SIZE="1"]www.thecomputerarchive.com  Preserving the history of companies that advanced the computer revolution[/SIZE]

Patrice Terrier

It is much more complex than that.

You will have to use GdipCreateBitmapFromStream, at least it is what i am doing in GDImage.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Dan Gin zel

Several things point to using streams but I am not sure I understand what a "stream" is.

Patrice, can you offer a one or two sentence description of what a stream is from your practical experience?

My guess is that it is a collection of data elements combined sequentially.
[SIZE="1"]www.thecomputerarchive.com  Preserving the history of companies that advanced the computer revolution[/SIZE]

Patrice Terrier

#8
The problem is what kind of handle would you retrieve a GDI32 bitmap or a GDIPLUS image?

a stream is a flow of data of any type (audio, image, video, etc.), suitable for internet streaming or resource streaming from a DLL.

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Dan Gin zel

I need to learn about streaming audio. This going me on my to-do list shortly.

I found a function LoadImageFromResource that takes care of everything. (Source: http://www.powerbasic.com/support/pbforums/showthread.php?t=24563)

Thanks for y'alls help. The input helped me get the pieces working together.
[SIZE="1"]www.thecomputerarchive.com  Preserving the history of companies that advanced the computer revolution[/SIZE]

José Roca

This is wrong:

ResourceName = UCODE$("#15")

Give the resource a name in the .rc file, e.g.

PngResource RCDATA "MyImage.png"

and the use

ResourceName = UCODE$("PngResource")

Patrice Terrier

#11
Because i am in a good day  8)

Image handle
FUNCTION ZI_ImageFromResource ALIAS "ZI_ImageFromResource" (BYVAL nInstance AS LONG, zName AS ASCIIZ) EXPORT AS LONG
    LOCAL hResource     AS LONG
    LOCAL imageSize     AS LONG
    LOCAL pResourceData AS DWORD
    LOCAL MemBuffer     AS DWORD
    LOCAL pBuffer       AS DWORD
    LOCAL pStream       AS DWORD PTR
    LOCAL hImage        AS LONG

    hResource = FindResource(nInstance, zName, BYVAL %RT_RCDATA)
    IF hResource THEN
       imageSize = SizeofResource(nInstance, hResource)
       IF imageSize THEN
          pResourceData = LockResource(LoadResource(nInstance, hResource))
          IF pResourceData THEN
             MemBuffer = GlobalAlloc(%GMEM_MOVEABLE OR %GMEM_NODISCARD, imageSize)
             IF MemBuffer THEN
                pBuffer = GlobalLock(MemBuffer)
                IF pBuffer THEN
                   CALL MoveMemory(BYVAL pBuffer, BYVAL pResourceData, imageSize)
                   IF CreateStreamOnHGlobal(MemBuffer, %FALSE, pStream) = 0 THEN
                      IF GdipCreateBitmapFromStream(pStream, hImage) = 0 THEN
                         FUNCTION = hImage
                      END IF
                      CALL IUnknown_Release(pStream)
                   END IF
                END IF
                CALL GlobalUnlock(MemBuffer)
             END IF
             CALL GlobalFree(MemBuffer)
          END IF
       END IF
    END IF
END FUNCTION


bitmap handle
FUNCTION ZI_LoadFromResource ALIAS "ZI_LoadFromResource" (BYVAL hWnd AS LONG, zName AS ASCIIZ) EXPORT AS LONG
    LOCAL hResource     AS LONG
    LOCAL imageSize     AS LONG
    LOCAL pResourceData AS DWORD
    LOCAL MemBuffer     AS DWORD
    LOCAL pBuffer       AS DWORD
    LOCAL pStream       AS DWORD PTR
    LOCAL hImage        AS LONG
    LOCAL hbmReturn     AS LONG

    hResource = FindResource(zInstance, zName, BYVAL %RT_RCDATA)
    IF hResource THEN
       imageSize = SizeofResource(zInstance, hResource)
       IF imageSize THEN
          pResourceData = LockResource(LoadResource(zInstance, hResource))
          IF pResourceData THEN
             MemBuffer = GlobalAlloc(%GMEM_MOVEABLE OR %GMEM_NODISCARD, imageSize)
             IF MemBuffer THEN
                pBuffer = GlobalLock(MemBuffer)
                IF pBuffer THEN
                   CALL MoveMemory(BYVAL pBuffer, BYVAL pResourceData, imageSize)
                   IF CreateStreamOnHGlobal(MemBuffer, %FALSE, pStream) = 0 THEN
                      IF GdipCreateBitmapFromStream(pStream, hImage) = 0 THEN
                         IF hWnd THEN
                            IF zSetGdipImageHandle(hWnd, hImage) THEN CALL ZI_UpdateWindow(hWnd, %TRUE)
                         ELSE ' Return a standard bitmap
                            CALL GdipCreateHBITMAPFromBitmap(hImage, hbmReturn, background&)
                            CALL GdipDisposeImage(hImage) ' Delete image
                            FUNCTION = hbmReturn
                         END IF
                      END IF
                      CALL IUnknown_Release(pStream)
                   END IF
                END IF
                CALL GlobalUnlock(MemBuffer)
             END IF
             CALL GlobalFree(MemBuffer)
          END IF
       END IF
    END IF
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

José Roca

Ah, yes. I had forgot that GdipCreateBitmapFromResource only works with bitmaps. Looks like after some months of inactivity I'm beginning to forget programming.

In my graphic control I'm using:


' ========================================================================================
' Loads an image from a resource file using GDI+
' Parameters:
' * hwnd = Control's window handle
' * hInstance = Instance handle
' * wszResourceName = Name of the resource image.
' Return value:
' * %StatusOk or an error code.
' ========================================================================================
FUNCTION GdipImageCtx_LoadImageFromResource (BYVAL hwnd AS DWORD, BYVAL hInstance AS DWORD, BYREF wszResourceName AS WSTRINGZ) AS LONG

   LOCAL hStatus AS LONG                   ' // Result code
   LOCAL hDc AS DWORD                      ' // Device context handle
   LOCAL pGraphics AS DWORD                ' // Graphocs object pointer
   LOCAL hResource AS DWORD                ' // Resource handle
   LOCAL pResourceData AS DWORD            ' // Pointer to the resoruce data
   LOCAL hGlobal AS DWORD                  ' // Global memory handle
   LOCAL pGlobalBuffer AS DWORD            ' // Pointer to global memory buffer
   LOCAL pImageStream AS IStream           ' // IStream interface pointer
   LOCAL hBgBrush AS DWORD                 ' // Background brush
   LOCAL imageSize AS DWORD                ' // Image size
   LOCAL rc AS RECT                        ' // Image bounds
   LOCAL rcFill AS RECT                    ' // Fill area
   LOCAL pData AS GDIP_IMAGECTXDATA PTR    ' // Pointer to the control data

   ' // Checks the validity of the parameters
   IF hwnd = %NULL THEN FUNCTION = %E_POINTER : EXIT FUNCTION
   IF LEN(wszResourceName) = 0 THEN FUNCTION = %E_INVALIDARG : EXIT FUNCTION

   ' // Gets a Pointer to the control data
   pData = GetWindowLong(hwnd, 0)
   IF pData = %NULL THEN FUNCTION = %E_POINTER : EXIT FUNCTION

   ' // Dispose a previous instance of the Image object, if any
   IF @pData.m_pImage THEN
      GdipDisposeImage(@pData.m_pImage)
      @pData.m_pImage = 0
   END IF

   ' // Find the resource and lock it
   hResource = FindResourceW(hInstance, wszResourceName, BYVAL %RT_RCDATA)
   IF hResource = %NULL THEN FUNCTION = %E_INVALIDARG : EXIT FUNCTION
   imageSize = SizeofResource(hInstance, hResource)
   IF imageSize = 0 THEN FUNCTION = %E_INVALIDARG : EXIT FUNCTION
   pResourceData = LockResource(LoadResource(hInstance, hResource))
   IF pResourceData = %NULL THEN FUNCTION = %E_INVALIDARG : EXIT FUNCTION
   ' // Allocate memory to hold the image
   hGlobal = GlobalAlloc(%GMEM_MOVEABLE, imageSize)
   IF hGlobal THEN
      ' // Lock the memory
      pGlobalBuffer = GlobalLock(hGlobal)
      IF pGlobalBuffer THEN
         ' // Copy the image from the resource file to global memory
         CopyMemory pGlobalBuffer, pResourceData, imageSize
         ' // Create an stream in global memory
         IF CreateStreamOnHGlobal(hGlobal, %FALSE, pImageStream) = %S_OK THEN
            ' // Create a bitmap from the data contained in the stream
            hStatus = GdipCreateBitmapFromStream(pImageStream, @pData.m_pImage)
            IF hStatus = %StatusOk THEN
               ' // Gets the device context handle
               hDc = GetDc(hwnd)
               ' // Creates a graphics object from it
               IF hDc THEN hStatus = GdipCreateFromHDC(hDc, pGraphics)
               ' // Draws the image (required to keep it in memory, since we are
               ' // going to unlock and free the resource)
               IF pGraphics THEN hStatus = GdipDrawImageI(pGraphics, @pData.m_pImage, 0, 0)
               ' // Deletes the graphics object
               IF pGraphics THEN GdipDeleteGraphics(pGraphics)
               ' // Releases the device context handle
               IF hDc THEN DeleteDc hDc
            END IF
            pImageStream = NOTHING
         END IF
         ' // Unlock the memory
         GlobalUnlock pGlobalBuffer
      END IF
      ' // Free the memory
      GlobalFree hGlobal
   END IF

   ' // Erases the window's client area
   hBgBrush = CreateSolidBrush(@pData.m_BkColor)
   IF hBgBrush THEN
      hDc = GetDc(hwnd)
      IF hDc THEN
         GetClientRect hwnd, rcFill
         FillRect hDc, rcFill, hBgBrush
         DeleteDc hDc
      END IF
      DeleteObject hBgBrush
   END IF

   ' // Redraws the control
   InvalidateRect hwnd, BYVAL %NULL, 0
   UpdateWindow hwnd

   FUNCTION = hStatus

END FUNCTION
' ========================================================================================


John Spikowski

QuoteLooks like after some months of inactivity I'm beginning to forget programming.

I have the cure!

We could sure use your help with COM integration with the Windows version of ScriptBasic. Charles has done an incredible job with DLLC (FFI extension module) to access APIs / COM dynamically at runtime. If you would consider being our mentor and keep us from straying off the path, it would be much appreciated.

All your work is priceless no matter what direction PB ends up going in.


Dan Gin zel

I will review these routines in detail shortly.

As usual, my deepest appreciation!

Dan
[SIZE="1"]www.thecomputerarchive.com  Preserving the history of companies that advanced the computer revolution[/SIZE]