News: Check out our online Video Tutorials ! http://www.youtube.com/user/ComputerWorkshopSoft
TO REGISTER on Forum, contact tech support: http://cwsof.com/support.html
 
Pages: [1]   Go Down
  Print  
Author Topic: Image loading using GDIplus (JPeg,GIF,PNG)  (Read 2745 times)
Chris Boss
Administrator
Hero Member
*****
Posts: 1800


View Profile
« on: May 11, 2011, 11:08:08 PM »

Here is an include file which has a routine which allows you to load JPeg,GIF and PNG images using GDIplus.
The beauty of this routine is that you don't need any GDI+ API include files to use it. It is a self contained include file of its own.

The routine can load images for either DDT or SDK coding.

I finally got it working for DDT, but there is still one small problem with it. There is a white line at the top of the image and I have no idea why.

I don't know what DDT does with its own Bitmaps, but I had to go through loops to convert the image to a DDT Bitmap. I had to load the image as a DIB and using pointers run the image through a conversion routine before BitBlt'ing it to a DDt Bitmap.

If anyone can figure out what the problem is (the white line) please email me or post the solution so I can fix the problem.

Here are the routines in the include file

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 written by Dan Ginzel.
His code can be found here:   http://chrisboss.hypermart.net/ubb/Forum36/HTML/000002.html

Here is the actual code in the EZ include file:

Code:
' Public domain
' conversion of code originally by Dan Ginzel
' see: http://chrisboss.hypermart.net/ubb/Forum36/HTML/000002.html
' requires no include files for GDIplus
DECLARE FUNCTION GdiplusStartupX LIB "GDIPLUS.DLL" ALIAS "GdiplusStartup" (BYREF token AS DWORD, BYVAL lpGDI_I AS DWORD, BYVAL lpGDI_O AS DWORD) AS LONG
DECLARE FUNCTION GdipLoadImageFromFileX LIB "GDIPLUS.DLL" ALIAS "GdipLoadImageFromFile" (BYVAL pFilename AS STRING, BYREF pImage AS DWORD) AS LONG
DECLARE FUNCTION GdipGetImageDimensionX LIB "GDIPLUS.DLL" ALIAS "GdipGetImageDimension" (BYVAL pImage AS DWORD, BYREF nWidth AS SINGLE, BYREF nHeight AS SINGLE) AS LONG
DECLARE FUNCTION GdipCreateFromHDCX LIB "GDIPLUS.DLL" ALIAS "GdipCreateFromHDC" ( BYVAL hDC AS LONG, BYREF graphics AS DWORD) AS LONG
DECLARE FUNCTION GdipSetInterpolationModeX LIB "GDIPLUS.DLL" ALIAS "GdipSetInterpolationMode" (BYVAL graphics AS DWORD, BYVAL interpolationMode AS LONG) AS LONG
DECLARE FUNCTION GdipDrawImageRectIX LIB "GDIPLUS.DLL" ALIAS "GdipDrawImageRectI" (BYVAL graphics AS DWORD, BYVAL pImage AS DWORD, BYVAL x AS LONG, BYVAL y AS LONG, BYVAL nWidth AS LONG, BYVAL nHeight AS LONG) AS LONG
DECLARE FUNCTION GdipDisposeImageX LIB "GDIPLUS.DLL" ALIAS "GdipDisposeImage" ( BYVAL pImage AS DWORD) AS LONG
DECLARE SUB GdiplusShutdownX LIB "GDIPLUS.DLL" ALIAS "GdiplusShutdown" ( BYVAL token AS DWORD)

SUB GDIP_GetImageSize(BYVAL F$, W&,H&)
     LOCAL GDIToken AS LONG, Picture AS STRING, Result AS LONG, pImage AS DWORD
     LOCAL hDC AS LONG, pGraphics AS LONG, QMode AS LONG, RV$, PWidth AS SINGLE, PHeight AS SINGLE
     LOCAL GDI_S() AS DWORD
     RV$=""
     DIM GDI_S(1 TO 4)   ' use instead of GdiplusStartupInput structure
     GDI_S(1)=1          ' version
     F$=UCODE$(TRIM$(F$))
     W&=0
     H&=0
     IF GDIplusStartupX(GDItoken, BYVAL VARPTR(GDI_S(1)), BYVAL 0)=0 THEN
          Result = GDIPLoadImageFromFileX(F$, pImage)
          GDIPGetImageDimensionX pImage, PWidth, PHeight
          W&=PWidth
          H&=PHeight
          IF pImage<>0 THEN GDIPDisposeImageX(pImage)
          GDIplusShutdownX GDItoken
     END IF
END SUB

FUNCTION GDIP_LoadImage(BYVAL DMode&, BYVAL F$, BYVAL W&, BYVAL H&, BYVAL QFlag&) AS DWORD
     LOCAL GDIToken AS LONG, Picture AS DWORD, Result AS LONG, pImage AS DWORD
     LOCAL hDC AS DWORD, pGraphics AS LONG, QMode AS LONG, RV AS DWORD, PWidth AS SINGLE, PHeight AS SINGLE, hOldBmp AS DWORD
     LOCAL GDI_S() AS DWORD, hDCD AS DWORD
     LOCAL BM AS BITMAPINFO, PA AS DWORD, BP AS BYTE PTR, LX&,LY&, Pad&, BRow&
     REGISTER BX&, BY&
     RV=0
     DIM GDI_S(1 TO 4)   ' use instead of GdiplusStartupInput structure
     GDI_S(1)=1          ' version
     F$=UCODE$(TRIM$(F$))
     Picture=0
     IF GDIplusStartupX(GDItoken, BYVAL VARPTR(GDI_S(1)), BYVAL 0)=0 THEN
          Result = GDIPLoadImageFromFileX(F$, pImage)
          GDIPGetImageDimensionX pImage, PWidth, PHeight
          IF W&>0 THEN PWidth=W&
          IF H&>0 THEN PHeight=H&
          hDCD = GetDC(%HWND_DESKTOP)
          hDC=CreateCompatibleDC(hDCD)
          GOSUB MakeDIB
          ReleaseDC %HWND_DESKTOP, hDCD
          IF hDC<>0 THEN
               hOldBmp=SelectObject(hDC,Picture)
               IF QFlag& THEN
                    QMode=2
               ELSE
                    QMode=1
               END IF
               Result = GDIPCreateFromHDCX(hDC, pGraphics)
               Result = GDIPSetInterpolationModeX(pGraphics, QMode)
               Result = GDIPDrawImageRectIX(pGraphics, pImage, 0, 0, PWidth, PHeight)
          END IF
          IF pImage<>0 THEN GDIPDisposeImageX(pImage)
          GDIplusShutdownX GDItoken
          IF hDC<>0 THEN
               IF DMode&<>0 THEN
                    GOSUB SwapRedBlue
                    GOSUB ConvertToDDTGraphic
                    DeleteDC hDC
               ELSE
                    SelectObject hDC, hOldBmp
                    DeleteDC hDC
               END IF
          END IF
          RV=Picture

     END IF
     FUNCTION=RV
     EXIT FUNCTION

MakeDDB:
     Picture=CreateCompatibleBitmap(hDCD,INT(PWidth),INT(PHeight))
RETURN

MakeDIB:
     BM.bmiHeader.biSize=SIZEOF(BM.bmiHeader)
     BM.bmiHeader.biWidth=INT(PWidth)
     BM.bmiHeader.biHeight=-INT(PHeight)    ' pass a negative value for a topdown Bitmap
     BM.bmiHeader.biPlanes=1
     BM.bmiHeader.biBitCount=24
     BM.bmiHeader.biCompression=%BI_RGB
     Picture=CreateDIBSection (hDCD, BM, %DIB_RGB_COLORS, VARPTR(PA), %NULL, %NULL)
RETURN

SwapRedBlue:
     GDIFlush
     LX&=INT(PWidth)
     BRow&=LX&*3
     Pad&=BRow& MOD 4
     IF Pad&<>0 THEN Pad&=4-Pad&
     LX&=LX&-1
     LY&=INT(PHeight)-1
     BP=PA
     FOR BY&=0 TO LY&
          FOR BX&=0 TO LX&
               @BP[0]=255-@BP[0]
               @BP[1]=255-@BP[1]
               @BP[2]=255-@BP[2]
               SWAP @BP[0],@BP[2]
               BP=BP+3
          NEXT BX&
          BP=BP+Pad&
     NEXT BY&
RETURN

ConvertToDDTGraphic:
     LOCAL hBmp AS DWORD, hGDC AS DWORD, MapMode&
     GRAPHIC BITMAP NEW INT(PWidth),INT(PHeight) TO hBmp
     GRAPHIC ATTACH hBmp,0
     GRAPHIC SET OVERLAP 1
     GRAPHIC SCALE PIXELS
     GRAPHIC GET DC TO hGDC
     bitBlt hGDC,0,0,INT(PWidth),INT(PHeight), hDC, 0,0,%SRCCOPY
     GRAPHIC DETACH
     SelectObject hDC, hOldBmp
     DeleteObject Picture
     Picture=hBmp
RETURN
END FUNCTION
Logged
Brice Manuel
Newbie
*
Posts: 31


View Profile
« Reply #1 on: May 11, 2011, 11:37:48 PM »

Thank you for your hard work on this.  As a DDT user, this could be very helpful.  I appreciate you utilizing a direct link to here for those of us who are banned from downloading attachments on the official forums.

The white line is a perplexing issue.
Logged
Chris Boss
Administrator
Hero Member
*****
Posts: 1800


View Profile
« Reply #2 on: May 12, 2011, 08:44:19 AM »

I want to maintain the quality of this code, but still update and improve it, so any who have suggestions of how to improve it, please post your comments here and I will rework the code myself and repost it.

This is one feature often requested by Powerbasic users, so the post is "sticky noted" to the top of this forum.

Logged
Peter Jinks
PreRelease 4.5
Newbie
*
Posts: 33


View Profile
« Reply #3 on: May 12, 2011, 04:17:47 PM »

Hi Chris,

I may be missing something, but when I try the sample program and then paste the result into a paint program, I get a bad image - like a negative photograph. However, if I remove the call to "SwapRedBlue" from the include file, it all appears normal. See attached image.

I also don't seem to be seeing the single white line you and Brice mention.

Regards,

Pete.
Logged
Chris Boss
Administrator
Hero Member
*****
Posts: 1800


View Profile
« Reply #4 on: May 12, 2011, 05:05:00 PM »

Do not use the DDT/SDK version of the image load code with EZGUI !

Use the version specific to EZGUI. EZGUI does not need the conversion code I use in the DDT version.

This version in this forum is for DDT/SDK.

The version for EZGUI is found here:  http://cwsof.com/forums/index.php?topic=485.0

« Last Edit: May 12, 2011, 05:06:51 PM by Chris Boss » Logged
Peter Jinks
PreRelease 4.5
Newbie
*
Posts: 33


View Profile
« Reply #5 on: May 12, 2011, 08:07:12 PM »

Hi Chris,

Quote
Do not use the DDT/SDK version of the image load code with EZGUI !

Umm - I didn't use EZGUI.  Embarrassed The original EXE included in the ddtimg.zip file is what I ran to get the "original code" image. The second image was obtained by recompiling the showimg.bas file as provided, but with the call to "SwapRedBlue" commented out, with a fresh install of PB/Win10. Nothing else.

Huh

It might also be worth mentioning that when it is recompiled the window that appears has no caption bar or border at all - which I seem to remember seeing a post about in the PowerBASIC forums, so I'll go and check there too. Maybe there's something gone awry with my PB/Win10 installation.

[Added] Small update on the window appearance - changing:
Code:
LOCAL Style&, ExStyle&

in the declarations in ShowDialog_Form1 to
Code:
LOCAL dwStyle, dwExStyle AS DWORD

(and altering references to them as necessary) makes the form display correctly. (Jose Roca suggests this "fix" in the thread on the PB Forums).

Regards,

Pete.
« Last Edit: May 12, 2011, 08:30:52 PM by Peter Jinks » Logged
Chris Boss
Administrator
Hero Member
*****
Posts: 1800


View Profile
« Reply #6 on: May 12, 2011, 09:07:31 PM »

Maybe there is something about my PC (Windows XP) which causes a problem.

If I don't use the invert code, I get an inverted image.

Logged
Peter Jinks
PreRelease 4.5
Newbie
*
Posts: 33


View Profile
« Reply #7 on: May 12, 2011, 10:18:06 PM »

Hi Chris,

I'm also using Windows XP (Pro, SP3), so it doesn't look like the difference is in the OS. My desktop is set to 1280x1024, 32bit on an nVidia GeForce Go 6600 using ForceWare 71.13, if that helps at all.

Just as a test, I've also run the two versions of the program on a Windows 7 Ultimate 64-bit system, same resolution and colour depth, on an nVidia Quadro FX 880M, and the result is the same.

Not too sure where that gets us until anyone else chimes in, but hopefully it will help in some way.

In any event, the code is still useful to me and I'm grateful for the work you have put in to getting it working as a "drop-in", and your generosity in posting it (and of course to Dan Gin zel for his work too).

Must go to bed now!

Regards,

Pete.
Logged
Russ Srole
Newbie
*
Posts: 22


View Profile
« Reply #8 on: November 19, 2011, 11:41:23 PM »

BTW, the code Chris posted will also work with tif files.  Good job
Logged
Pages: [1]   Go Up
  Print  
 
Jump to: