• Welcome to Theos PowerBasic Museum 2017.

News:

Attachments are only available to registered users.
Please register using your full, real name.

Main Menu

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.

Patrice Terrier

#15
Yes for GDI+

bitmap = gdiplus image
while
HBITMAP = GDI32 bitmap

The case makes all the difference! (remember GDIPLUS is written in plain C that is a very case sensitive language).

This is why i am using the word image in my code for GDIPLUS handle, and bitmap for GDI32 handle, then i can quickly determine which one i am refering to, when reading back the source code.

I had also to write my own low level API in GDImage to convert from image to bitmap, and from bitmap to image.
Because GdipCreateHBITMAPFromBitmap and GdipCreateBitmapFromHBITMAP won't work with PNG using transparency nor with DWM.

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

José Roca

I have an small problem with that. I wrote some routines to make icons from .png files (see one of them below) to allow to use .png icons in toolbars. Works fine excepting that the grayed ones, made using a light gray tone, are rendered darker than they should.


' ========================================================================================
' Loads an image from a resource using GDI+, converts it to an icon and returns the icon handle.
' Parameter:
' - hInstance  = [in] Handle to the instance that contains the resource.
' - bstrImage  = [in] Name of the image in the resource file (.RES). If the image resource uses
'                an integral identifier, bstrImage should begin with a number symbol (#)
'                followed by the identifier in an ASCII format, e.g., "#998". Otherwise,
'                use the text identifier name for the image. Only images embedded as raw data
'                (type RCDATA) are valid. These must be icons in format .png, .jpg, .gif, .tiff.
' Return Value:
'   If the function succeeds, the return value is the handle of the created icon.
'   If the function fails, the return value is NULL.
'   Call GetLasrError to retrieve the error code.
' ========================================================================================
FUNCTION GdiPlusCreateHICONFromResource (BYVAL hInstance AS DWORD, BYVAL bstrImage AS WSTRING) AS DWORD

   LOCAL hStatus AS LONG                        ' // Status
   LOCAL token AS DWORD                         ' // Token to shutdown GDI+
   LOCAL StartupInput AS GdiplusStartupInput    ' // Structure to initialize GDI+
   LOCAL pImage AS DWORD                        ' // Image handle
   LOCAL hIcon AS DWORD                         ' // Icon handle
   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 imageSize     AS DWORD                 ' // Image size
   LOCAL wID AS WORD
   LOCAL dwID AS DWORD

   IF hInstance = 0 THEN EXIT FUNCTION

   StartupInput.GdiplusVersion = 1
   hStatus = GdiplusStartup(token, StartupInput, BYVAL %NULL)
   IF hStatus <> %S_OK THEN EXIT FUNCTION

   ' // Find the resource and lock it
   IF LEFT$(bstrImage, 1) = "#" THEN
      wID = VAL(MID$(bstrImage, 2))
      dwID = MAK(DWORD, wID, 0)
      hResource = FindResourceW(hInstance, BYVAL dwID, BYVAL %RT_RCDATA)
   ELSE
      hResource = FindResourceW(hInstance, BYCOPY bstrImage, BYVAL %RT_RCDATA)
   END IF
   IF hResource = %NULL THEN SetLastError(%E_INVALIDARG) : GOTO LExit
   imageSize = SizeofResource(hInstance, hResource)
   IF imageSize = 0 THEN SetLastError(%E_INVALIDARG) : GOTO LExit
   pResourceData = LockResource(LoadResource(hInstance, hResource))
   IF pResourceData = %NULL THEN SetLastError(%E_INVALIDARG) : GOTO LExit
   ' // 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, pImage)
            IF hStatus = %StatusOk THEN
               IF pImage THEN
                  hStatus = GdipCreateHICONFromBitmap(pImage, hIcon)
                  GdipDisposeImage pImage
               END IF
            END IF
            pImageStream = NOTHING
         END IF
         ' // Unlock the memory
         GlobalUnlock pGlobalBuffer
      END IF
      ' // Free the memory
      GlobalFree hGlobal
   END IF

LExit:

   GdiplusShutdown token

   FUNCTION = hIcon

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


Patrice Terrier

#17
Yes that's just the visible part of the problem, and one of the reason why i had to write my own API to keep the same aspect than within the original, the problem becomes even worse when you want to render on a DirectDraw surface (DWM) while preserving the progressive transparency.

This problem doesn't exist with D2D, because of the native use of the DirectDraw surface.

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

José Roca

Maybe I should try the Windows Imaging Component. I used GDI+ for compatibility reasons with the damned XP.

Patrice Terrier

José--

Try with this

//GDImage 3.55 setup alpha channel for PNG image
rAlphaCoef = (@pBits[3] / 255)
@pBits[2] = @pBits[2] / rAlphaCoef
@pBits[1] = @pBits[1] / rAlphaCoef
@pBits[0] = @pBits[0] / rAlphaCoef
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

José Roca

#20
Quote from: John Spikowski on March 24, 2013, 04:06:04 PM
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.

Inactive in programming. I have many other things to do.

Maybe you should look at the source code of the PHP language. It is written in C, that Charles understands quite well. I don't use COM automation and scripting languages.

John Spikowski

Have you looked at the PHP or Python API interfaces for these scripting languages?   :o

Thanks, but I'm going to take a more direct approach with the functionality DLLC offers with dynamic scripting of APIs at runtime.


Charles Pegge

Am I right in thinking all the good stuffs has Iunknown interfaces?. Hooking up SB to Iunknow is pretty simple, so I wonder whether we need to go down the automation route. I think you mentioned Crystal Reports, John.

Charles

José Roca

Currently, Automation is only needed to automate Office and little more (some ActiveX controls written for VB). Since I don't use Office, I don't need Automation, that I dislike, at all. Microsoft has implemented all his new stuff as low-level interfaces. Even the Windows Ribbon was implemented as a low-level component that, contrarily to ActiveX controls, doesn't require the use of an OLE container. Low-level COM is faster and use the same conventions for parameter passing that standard functions. No problem to pass arrays or UDTs, no need for the use of Variants, no need for type libraries, no need to register the components to use them, etc.


John Spikowski

Quotethink you mentioned Crystal Reports, John.

Memories of the past it seems. A faded dream when Offices integration was a requirement by your customers. Please strike the automation inquiry as it's not within the scope of the project. (FFI++)

QuoteLow-level COM is faster and use the same conventions for parameter passing that standard functions. No problem to pass arrays or UDTs, no need for the use of Variants, no need for type libraries, no need to register the components to use them, etc.

Music to my ears!!!