Powerbasic Museum 2020-B

IT-Consultant: Patrice Terrier => GDImage => Topic started by: Patrice Terrier on December 10, 2008, 03:20:51 PM

Title: Post your questions here
Post by: Patrice Terrier on December 10, 2008, 03:20:51 PM
This thread is to post your questions about GDImage ...
Title: Re: Post your questions there
Post by: Donnie Ewald on January 01, 2009, 09:20:05 PM
I've been very pleased with the functionality of GDImage, though I'm having problems with rotating an image that I've loaded from my program's resource file.  Here is the boiled down code that shows where I'm struggling:

#PBFORMS CREATED
'SED_PBWIN
#COMPILE EXE
#DIM ALL

#PBFORMS BEGIN INCLUDES
#RESOURCE "DMV.pbr"
#INCLUDE "DMV.inc"
#PBFORMS END INCLUDES

'--------------------------------------------------------------------------------
'   ** Constants **
'--------------------------------------------------------------------------------
'--------------------------------------------------------------------------------
#PBFORMS BEGIN CONSTANTS
%IDD_DIALOG1      = 101
%IDC_GDimageCTRL1 = 102
%ID_TIMER1        = 103
%ID_BITMAP_ARROW  = 1     ' Bitmap overlay
#PBFORMS END CONSTANTS
'--------------------------------------------------------------------------------

'--------------------------------------------------------------------------------
'   ** Declarations **
'--------------------------------------------------------------------------------
DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
declare sub DisplayArrow(hDlg as long)
#PBFORMS DECLARATIONS
'--------------------------------------------------------------------------------

' Search for "GDImage" in the source code
#INCLUDE "GDImage.inc"   ' GDImage

'$MyImage1 = "level01.jpg" + "<fit>" ' GDImage (edit this using a full path name to image)
$MyImage1 = "" + "<fit>" ' GDImage (edit this using a full path name to image)

global lHor as long, lVer as long, lDep as LONG, lDir as LONG, ghCtrl&

'--------------------------------------------------------------------------------
FUNCTION PBMAIN()
RegisterGDImageClass                ' GDImage
ShowDIALOG1 %HWND_DESKTOP
END FUNCTION 'PBMAIN
'--------------------------------------------------------------------------------

'--------------------------------------------------------------------------------
'   ** CallBacks **
'--------------------------------------------------------------------------------
CALLBACK FUNCTION ShowDIALOG1Proc()
local hBitmapFromResource&

SELECT CASE AS LONG CBMSG
    CASE %WM_INITDIALOG
      STATIC idEvent AS LONG

'Initialization handler
'Load Arrow Bitmap from resource, and create a BITMAP overlay
ghCtrl& = GetDlgItem(cbhndl, %IDC_GDimageCTRL1)
if hBitmapFromResource& = 0 then hBitmapFromResource& = ZI_LoadBitmap("BMP_ARROW") ' Load it ONLY ONCE !
CALL ZD_DrawBitmapToCtrl(ghCtrl&, 174, 0, hBitmapFromResource&, ZD_ColorARGB(255,0), %ID_BITMAP_ARROW, %ZS_VISIBLE)
ZD_SetObjectLocked %ID_BITMAP_ARROW, %TRUE

      'Create WM_TIMER events with the SetTimer API at 500 ms (0.5 s) interval
idEvent = SetTimer(CBHNDL, %ID_TIMER1, 500, BYVAL %NULL)
      DIALOG POST CBHNDL, %WM_TIMER, %ID_TIMER1, 0  ' force an initial %WM_TIMER "event"
CASE %WM_TIMER                                  ' Posted by the created timer
IF CBWPARAM = %ID_TIMER1 THEN               ' Make sure it's corrent timer id
'Do some processing here that's removed
DisplayArrow cbhndl
END IF
    CASE %WM_PALETTECHANGED
      'if in 256 color mode, switching between app's with different palettes
      'can cause weird results. Trapping %WM_PALETTECHANGED and redrawing
      'entire dialog helps some. Maybe not the best solution, but..
      IF CBWPARAM <> CBHNDL THEN
        RedrawWindow CBHNDL, BYVAL 0, BYVAL 0, %RDW_INVALIDATE OR %RDW_UPDATENOW
      END IF
    CASE %WM_DESTROY
    'is sent when program ends - a good place to delete created
    'objects and store settings in file for next run, etc.
    '-------------------------------------------------------------
CASE %WM_NCACTIVATE
STATIC hWndSaveFocus AS DWORD
IF ISFALSE CBWPARAM THEN
' Save control focus
hWndSaveFocus = GetFocus()
ELSEIF hWndSaveFocus THEN
' Restore control focus
SetFocus(hWndSaveFocus)
hWndSaveFocus = 0
END IF
CASE %WM_COMMAND
      ' Process control notifications
      SELECT CASE AS LONG CBCTL
        CASE %IDCANCEL
          IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
DIALOG END CBHNDL, 0
          END IF
      END SELECT
    END SELECT
END FUNCTION 'ShowDIALOG1Proc
'--------------------------------------------------------------------------------

'--------------------------------------------------------------------------------
FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    LOCAL lRslt AS LONG
#PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
LOCAL hDlg  AS DWORD

DIALOG NEW hParent, "Demise Map Viewer", 43, 58, 497, 413, %WS_POPUP OR %WS_BORDER OR _
  %WS_DLGFRAME OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME 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 $GDImageClassName, hDlg, %IDC_GDimageCTRL1, $MyImage1, 7, 5, 423, 390, %WS_CHILD OR _
  %WS_VISIBLE, %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
#PBFORMS END DIALOG

'Example for above as PBForms always jacks it up.
'CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL1, $MyImage1, 7, 5, 420, 190

DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt

#PBFORMS BEGIN CLEANUP %IDD_DIALOG1
#PBFORMS END CLEANUP

    FUNCTION = lRslt
END FUNCTION 'ShowDIALOG1
'--------------------------------------------------------------------------------

sub DisplayArrow(hDlg as long)
local lHorP as LONG, lVerP as long

'Layout looks like this:
'1,45   45,45
'1, 1   45, 1

lHor = 24 'Horizontal coordinate
lVer = 3  'Vertical coordinate
lDep = 1  'Which map we're on
lDir = 2  'Direction facing

lHorP = (lHor * 14) - 12
lVerP = ((45 - lVer) * 14) + 2

select CASE lDir
case 1 'North
ZD_SetObjectRotation %ID_BITMAP_ARROW, 0
case 2 'East
CALL ZD_SetObjectAngle(%ID_BITMAP_ARROW, 90, %TRUE)
'ZD_SetObjectRotation %ID_BITMAP_ARROW, 90
'ZD_RotateObjectClockWise90 (%ID_BITMAP_ARROW)
case 3 'South
ZD_SetObjectRotation %ID_BITMAP_ARROW, 180
'ZD_FlipObjectY %ID_BITMAP_ARROW
case 4 'West
'ZD_SetObjectRotation (%ID_BITMAP_ARROW, 270)
END SELECT

ZD_SetObjectXY %ID_BITMAP_ARROW, lHorP, lVerP, 1
CALL ZI_UpdateWindow(ghCtrl&, %TRUE)
END SUB


Here's a zip archive that is compilable but does not include the GDImage.dll file or the includes.  I'm using the demo version available from the ZAP site that is version 4.06 (according to the header file).

<I've pulled the link as it's been replaced>

...in the SUB DisplayArrow I update the placement of an arrow against a map background based on a timer.  When my program is ran, the arrow moves along just fine using the SUB as it is; but, it doesn't face the way that I would like.  I'd like to have it point east when traveling east and so on.  The placement is pulled from a game. In the above SUB I've given sample coordinates to showcase the basics.  I've tried a few things that you can see in the SELECT CASE to no avail.  Any ideas or am I horribly butchering something?
Title: Re: Post your questions there
Post by: Patrice Terrier on January 01, 2009, 11:54:36 PM
Donnie,

I am not comfortable with the DDT proprietary syntax, however the first thing that comes to my mind is that your arrow PNG file uses an original angle rotation of 90° instead of 0°, and that could explain the problem you have to perform the correct rotation of your arrow.

If you are looking at a clock, then three = 0°, while twelve = 90°, nine = 180°, six = 270°.

Also with PNG file you must always use
CALL ZD_UsePngOpacity(%ID_BITMAP_ARROW, %TRUE)
in order to use alpha channel and zooming capabilities


'Initialization handler
'Load Arrow Bitmap from resource, and create a BITMAP overlay
ghCtrl& = GetDlgItem(cbhndl, %IDC_GDimageCTRL1)
if hBitmapFromResource& = 0 then hBitmapFromResource& = ZI_LoadBitmap("BMP_ARROW") ' Load it ONLY ONCE !
CALL ZD_DrawBitmapToCtrl(ghCtrl&, 174, 0, hBitmapFromResource&, ZD_ColorARGB(255,0), %ID_BITMAP_ARROW, %ZS_VISIBLE)

CALL ZD_UsePngOpacity(%ID_BITMAP_ARROW, %TRUE)
CALL ZD_SetObjectAngle(%ID_BITMAP_ARROW, 180, %TRUE)
Title: Re: Post your questions there
Post by: Donnie Ewald on January 02, 2009, 12:27:43 AM
This is perfect.  I was able to incorporate what you showed me and placed it in my code.  It very neatly works now.
Title: Re: Post your questions there
Post by: Robert Sarrazin on January 02, 2009, 06:36:57 AM
Hi. I try to use the:
I call:
---------------------------
MsgBox "Past #1 "
    Call  ZI_GetImageSizeFromFile ("c:\aFireFly\GDImage\image.jpg", 0, 0 )
    MsgBox "Result #2 = " + Str$(imgWidth)
    Call test()
    ..............

SUB ZI_GetImageSizeFromFile ( _
      zFullPathName As Asciiz, _      ' The name  graphic file size.
      imgWidth As Long, _             ' Width of the picture.
      imgHeight As Long _             ' Height of the picture.
      )
      MsgBox "Past #3 here "
End Sub

'------------------------------
Sub test()
      MsgBox "Past #4 testsub ok "
End Sub
-------------------------------
Result
display Past #1
display Result #2 = 0
display Past #4 testsub ok
-------------------------------
It seem it never go to sub ZI_GetImageSizeFromFile
I never see Past #3 here
I use your trail version
I download today not sure about the way I code.
but my kind of trace help me to figure out I have a problem.
I try to use Firefly 2.91
Thanks.
Title: Re: Post your questions there
Post by: Patrice Terrier on January 02, 2009, 09:43:05 AM
Robert,

ZI_GetImageSizeFromFile is a GDImage API, thus you are not allowed to duplicate the name of this API in your own code, that is a NoNo.

Also to get the width and height values, you must first declare in your code two numeric parameters like this:
LOCAL imgWidth, imgHeight AS LONG

Then use the API this way:

CALL ZI_GetImageSizeFromFile("c:\aFireFly\GDImage\image.jpg", imgWidth, imgHeight)
MsgBox STR$(imgWidth) + STR$(imgHeight)

...
Title: Re: Post your questions there
Post by: Robert Sarrazin on January 02, 2009, 10:47:47 PM
Thanks more clear, now it work well but to came back to
my goal to resize image I find 1 command to seize image.

    Call  ZI_GetImageSizeFromFile ("c:\aFireFly\GDImage\10.jpg", imgWidth, imgHeight )
    imgWidth=imgWidth / 10
    imgHeight=imgHeight / 10
    ZI_FitImageFromFile("c:\aFireFly\GDImage\10.jpg",imgWidth,imgHeight)

But I don't know where the fitImage go in memory? or where?
How to sent this image to hWndForm, I never sent this image to hWndForm.
Now if I want to use the only one else commande to save:

    ZI_SaveBitmapToFile("c:\aFireFly\GDImage\10n.jpg",hWndForm,80)

Easy to see is not working the hWndForm have no instruction.

I read all the function 1 by 1 to find how to resize image that only 2
function I find. Again few for zomming a lot of get but not to many
for set image.

I am right?, It look you convert all image (Jpg, Tif, gif, etc.) to bitmap,
at that point you modify you play with the way you want, and if we
want to save the result; you convert again to save in any format.

1 more question: when I use:
      gnCtrl = CreateWindowEx(ExStyles, _   ' 0
                              ClassName, _  ' "ZIMAGECTRL"
                              Caption, _    ' Full path to default image ""
                              Styles, _     ' %WS_CHILD Or %WS_VISIBLE
                              nLeft, nTop, nWidth, nHeight, _
                              hWndParent, IDC_FORM1_GDIMAGECONTROL, _
                              GetModuleHandle(ByVal %Null), _
                              ByVal %Null)

If I got no picture It came with, BLACK windows, can we change that color
by white or any or transparency.
The color is just the look but the way to use resize or save is all the program.
Thanks again.


Title: Re: Post your questions there
Post by: Patrice Terrier on January 02, 2009, 11:29:08 PM
Robert,

Please studdy the examples provided with the trial version, then start modifying one of them to achieve your goal.

Usualy the ZI_FitimageFromFile returns a resized bitmap handle that must be assigned to a GDImage graphic control.

But if you want you can save the newly created bitmap directly to disk, using ZI_SaveBitmap.

GDImage is able to handle either GDI bitmap or GDIPLUS bitmap (image).

There is also a low level GDImage API to convert from Bitmap to Image (GDIPLUS), its name is zBitmapToImage.

See the convert.bas example, i think it could help you, and it can't be simpler than that:


#COMPILE EXE "convert.exe"
%WINAPI                                         = 1
%WM_USER                                        = &H400
TYPE POINTS
  x AS INTEGER
  y AS INTEGER
END TYPE

#INCLUDE "gdimage.inc"

FUNCTION PBMAIN
    LOCAL hBitmap AS LONG, ErrorCode AS LONG

    hBitmap = ZI_FitImageFromFile("C:\multimedia\pictures\skins\wallpapers\cogs2.jpg", 48, 48)
    ErrorCode = ZI_SaveBitmapToFile("c:\travail\gdimage\icon.jpg", hBitmap, 0)
    CALL DeleteObject(hBitmap)

END FUNCTION

Title: Re: Post your questions there
Post by: Robert Sarrazin on January 04, 2009, 09:37:22 PM
Thanks Patrice
I post the result:
http://www.jose.it-berater.org/smfforum/index.php?topic=2966.msg9040#msg9040

With the help for drag and drop from: Paul Squires
and the project is done. Voila!  8)
I got the drop and drag.
The resize all image and .ext
The preview image for the result.
The detection for not graphics file.
The performance.

Thanks to answer:  "all my questions".
Robert.
Title: Re: Post your questions there
Post by: Patrice Terrier on January 04, 2009, 10:04:12 PM
Robert,

When saving to JPEG you can select the Quality (using the last parameter of ZI_SaveBitmapToFile).

GDImage's default for JPEG is always the highest quality if you don't specify a value (see the CHM help file).

...
Title: Re: Post your questions there
Post by: Patrice Terrier on January 05, 2009, 01:22:38 AM
Robert,

I forget to say that you must delete the bitmap object when you are done, using:
CALL DeleteObject(hBitmap)
Title: Re: Post your questions there
Post by: Donnie Ewald on January 05, 2009, 03:47:37 AM
The example code has been a great boon to me in having some fun with graphics..  I didn't realize that I would have to do so much math though.  I've edited the zoomplus.bas file a bit to show my question.  If you right-click on the black square of Monaco you'll get the coordinates around 301, 209.  If you zoom all the way in, recenter Monaco and click the black square, you'll get 211, 192.  If you maximize the dialog, recenter Monaco I got 543, 476 with my settings.  I understand that I'm getting different coordinates because of the size of the image and the zoom factor; but, is it possible to mathematically get them all to match?  What would I need to do to accomplish that?

Title: Re: Post your questions there
Post by: Donnie Ewald on January 05, 2009, 05:43:37 PM
Feel free to look at the attachment; but, I think I'm getting closer to solving this.  I'll post a changed attachment if I do.  I will be out of town for a few days so it might be a bit.
Title: Re: Post your questions there
Post by: Patrice Terrier on January 05, 2009, 06:13:50 PM
Donnie,

GDImage does already the hard work for you.
ZI_GetCropCoordinates API returns real coordinates as if you were viewing without zoom factor (1/1)
Title: Re: Post your questions there
Post by: Donnie Ewald on January 05, 2009, 07:17:59 PM
I noticed that; but, I'd prefer a mouse-click instead of creating a crop rectangle.  I don't see any other way to use that SUB.  I've got it figured out when the user resizes the dialog or maximizes; but, no luck yet on zooming.  Hopefully I'll get a chance to tackle it when I'm back.
Title: Re: Post your questions there
Post by: Donnie Ewald on January 10, 2009, 12:37:33 AM
Well, I'm going to keep working on it; but, I've not figured it out yet.  I'm sure that the ZI_GetZoomValue is part of the equation; but, I'm stumped.  Patrice, do you mind sharing how the ZI_GetCropCoordinates API gains it's information? I feel like I should be getting this; but, I'm not.

On another note (and still using the zoomplus.bas example), if I added a sprite above Monaco, would it be possible that once zoomed in we could automatically center the sprite and the background image would still scroll with it using ZD_SetObjectScroll?  Any similar examples or should I start tinkering?
Title: Re: Post your questions there
Post by: Patrice Terrier on January 10, 2009, 12:33:39 PM
Donnie,

Here are some insights to help you:

Note: X1, Y1 are the mouse coordinates and hWnd is the handle of the GDImage control.


                    LOCAL lpr AS RECT, ZoomValue AS SINGLE, nW, nH, ZoomWidth, ZoomHeight, xOffset, yOffset, imgWidth, imgHeight AS LONG
                    ' Get current Zoom value
                    ZoomValue! = ZI_GetZoomValue(hWnd)
                    ' Retrieve the size of the memory bitmap
                    CALL ZI_GetImageSizeFromControl(hWnd, nW&, nH&)
                    ' Get the client size of the control
                    CALL GetClientRect(hWnd, lpr)
                    ' Compute x,y offset
                    ZoomWidth& = nW& * ZoomValue!
                    ZoomHeight& = nH& * ZoomValue!
                    xOffset& = 0: yOffset& = 0
                    IF ZoomWidth& < lpr.nRight OR ZoomHeight& < lpr.nBottom THEN
                      IF ZoomWidth& < lpr.nRight THEN xOffset& = (lpr.nRight - ZoomWidth&) \ 2
                      IF ZoomHeight& < lpr.nBottom THEN yOffset& = (lpr.nBottom - ZoomHeight&) \ 2
                    END IF
                    ' Compute real coordinates
                    IF ZoomValue! > 0 THEN
                       x1& = (x1& - xOffset&) / ZoomValue!
                       y1& = (y1& - yOffset&) / ZoomValue!
                       imgWidth& = imgWidth& / ZoomValue!
                       imgHeight& = imgHeight& / ZoomValue!
                    END IF


For your other question you can always change the location of a sprite at any time.
The ZI_GetXscroll and ZI_GetYscroll API give you the horizontal and vertical scroll range for a specific GDImage control.

Title: Re: Post your questions there
Post by: Patrice Terrier on January 10, 2009, 02:52:14 PM
Donnie

Here is a WinDev procedure that is being used to display the mouse coordinates in a GDImage ZOOM control.
It can be easily translated to PowerBASIC


PROCEDURE GDImageDisplayMouseXY(hWnd is int, x is int, y is int)
lpr is RECT
// Get current Zoom value
ZoomValue is 4-byte real = ZI_GetZoomValue(hWnd)
// Retrieve the size of the memory bitmap
nW, nH are int; ZI_GetImageSizeFromControl(hWnd, nW, nH)
// Get the client size of the control
GetClientRect(hWnd, lpr)
// Compute x,y offset
ZoomWidth is int = nW * ZoomValue
ZoomHeight is int = nH * ZoomValue
xOffset is int = 0; yOffset is int = 0
IF ZoomWidth < lpr:nRight OR ZoomHeight < lpr:nBottom THEN
IF ZoomWidth < lpr:nRight THEN xOffset = Round((lpr:nRight - ZoomWidth) / 2)
IF ZoomHeight < lpr:nBottom THEN yOffset = Round((lpr:nBottom - ZoomHeight)/ 2)
END
// Retrieve scroll values
xCurrentScroll is int = ZI_GetXscroll(hWnd)
yCurrentScroll is int = ZI_GetYscroll(hWnd)
// Show mouse coordinates
SC_Coord.X = NumToString(Round((x + xCurrentScroll - xOffset) / ZoomValue, 0))
SC_Coord.Y = NumToString(Round((y + yCurrentScroll - yOffset) / ZoomValue, 0))
Title: Re: Post your questions there
Post by: Patrice Terrier on January 10, 2009, 03:57:30 PM
Donnie,

I have posted a WinDev project named GeneScene there:
http://www.zapsolution.com/demo/GeneScene.zip (http://www.zapsolution.com/demo/GeneScene.zip)

It displays a map(s) with pushpin sprites spread on it.
Each pushpin is a hot spot that does match a specific tunnel (Try with the one named "l'Arme" located above Monaco).

(http://www.zapsolution.com/pictures/GeneScene.jpg)

You will see also on this example that the mouse X,Y location is shown below the map while you are moving the mouse, and it display the correct location whatever the zoom being used.

Perhaps it is something like that you want to achieve?

Title: Re: Post your questions there
Post by: Donnie Ewald on January 10, 2009, 04:09:34 PM
This is perfect!  For whatever reason, I'm not able to replicate that functionality when I'm zoomed in.  I must be letting something slide somewhere.
Title: Re: Post your questions there
Post by: Patrice Terrier on January 10, 2009, 04:18:17 PM
GDImage allows you to process/monitor all the messages of its graphic controls via a callback procedure.

Note: in the GeneScene project all the pushpins (except one) are clone objects, this is a very unique GDImage feature.


Title: Re: Post your questions there
Post by: Donnie Ewald on January 10, 2009, 06:06:54 PM
I was handling the current scroll in the wrong spot.  The WinDev post though nearly the same as the PB showed me where I was screwing up.  I was so sure that some of my own code was accurate I was blinded to the truth.  I've attached the zoomplus sample with my changes in case anyone else is interested.  The output information is sent as a debug string.  I capture those with DebugView.
Title: Re: Post your questions there
Post by: Donnie Ewald on January 10, 2009, 11:26:09 PM
A few more questions.  I have a bit of code:

'Find current zoom and scoll values
hCtrl& = GetDlgItem(cbhndl, %IDC_GDimageCTRL1)
ZoomValue! = ZI_GetZoomValue(hCtrl&)
xCurrentScroll = ZI_GetXscroll(hCtrl&)
yCurrentScroll = ZI_GetYscroll(hCtrl&)

'Load the new image
call GDImageLoadFile(cbhndl, FilName$)

'Reassign zoom and scroll values after loading file
CALL ZI_SetZoomValue(hCtrl&, ZoomValue!)
CALL ZI_SetZoomScrollInfo(hCtrl&, ZoomValue!, ZoomValue!)
call ZI_SetProperty(hCtrl&, %ZI_Horizontal, xCurrentScroll)
call ZI_SetProperty(hCtrl&, %ZI_Vertical, yCurrentScroll)


...that while checking each of the values they seem to be fine.  Unfortunately, the image control doesn't show the changed %ZI_Horizontal and %ZI_Vertical settings, instead they show the default zero.  I tossed in a redraw for fun and still don't see anything.  Anything I might be overlooking?

Also, I can see from ZD_GetObjectQuality that you can change the rendering quality.  Is it possible to have no adjustment at all when zooming and such?  I'd like to see pixels and all without any interpolation.
Title: Re: Post your questions there
Post by: Patrice Terrier on January 11, 2009, 12:29:27 AM
Donnie,

A GDImage ZOOM control always use HALFTONE interpolation, because the zoom can be smaller than the 1/1 pixel ratio (for example 0.33)

If you want to have full control on your image, then use it as a sprite object (a layer floating above the background, like in PhotoShop). See on this forum the PhotoSetup demo project.

Then you have a bunch of properties you can apply to your sprite, see all the API prefixed with ZD_SetOblect... and ZD_GetObject... in the GDImage.inc file (the include file is more accurate than the CHM help file).

To facilitate the manipulation of GDImage's sprite object use a Sprite type like this one


TYPE SpriteStruct
     ID              is int                         '// The unique sprite object IDentifier
     objtype         is int                         '// The object type     
     filename        is string ASCIIZ on MAX_PATH   '// File of the sprite bitmap
     label           is string ASCIIZ on 64         '// Friendly name
     xPos            is int                         '// X location
     yPos            is int                         '// Y location
     xWidth          is int                         '// Width of the sprite object
     yHeight         is int                         '// Height of the sprite object
     ARGB            is int                         '// ARGB color
     visibility      is int                         '// ZS_HIDDEN or ZS_VISIBLE state
     scrollmode      is int                         '// True/False scrolling mode
     opacity         is int                         '// True/False PNG opacity
     userotate       is int                         '// Rotate90FlipNone or Rotate270FlipNone
     flipmode        is int                         '// ZD_Reverse (FlipX) or ZD_Flip (FlipY) constant       
     angle           is int                         '// Rotation angle 0-360
     locked          is int                         '// True/False condition
     zorder          is int                         '// The z-order value
     scale           is 4-byte real                 '// The scale value
     style           is int                         '// The object style
     quality         is int                         '// The object quality
     clone           is int                         '// The unique ID of the cloned object
                                                    '//
     resizeW         is int                         '// Resize width to use
     resizeH         is int                         '// Resize height to use
     trueW           is int                         '// True width of the native bitmap
     trueH           is int                         '// True height of the native bitmap
     selected    is 1-byte unsigned int             '// Selected status
     reserved    is string ASCIIZ on 111            '// For future extension
END TYPE


I can't remember exactly what you want to achieve, because i lost a part of my latest e-mails during the blown up of my notebook, that occured 9 days ago.
Title: Assigning a GDImage Sprite array
Post by: Patrice Terrier on January 11, 2009, 11:04:19 AM
Here is a WinDev example showing how to assign a GDImage sprite array.

This one can be very easily translated to PowerBASIC
WD []: is PB ().
WD : is PB .
WD zItem is ZOBJECT is PB DIM zItem AS ZOBJECT

the ZD_GetObjectProperties API allows you to retrieve all the properties of a sprite object in one single call.


'// Assign the ZOBJECT structure/type parameters to the Sprite array
PROCEDURE SpriteArrayGet(ID is int)
x, y, xW, yH are int
'//ZD_GetObjectXY(ID, x, y)
'//ZD_GetObjectBound(ID, xW, yH)
'//gSprite[ID]:ID = ID                                  '// The unique sprite object IDentifier
'//gSprite[ID]:objtype = ZD_GetObjectType(ID)           '// The object type (bitmap, text, arrow, curve, rectangle, ellipse, polypolyline)
'//gSprite[ID]:label = ZD_GetObjectImageLabel(ID)       '// Friendly name
'//gSprite[ID]:xPos = x                                 '// X location
'//gSprite[ID]:yPos = y                                 '// Y location
'//gSprite[ID]:xWidth = xW                              '// Width of the sprite object
'//gSprite[ID]:yHeight = yH                             '// Height of the sprite object
'//gSprite[ID]:ARGB = ZD_GetObjectARGBcolor(ID)         '// ARGB color
'//gSprite[ID]:visibility = ZD_IsObjectVisible(ID)      '// ZS_HIDDEN or ZS_VISIBLE state
'//gSprite[ID]:scrollmode = ZD_GetObjectScroll(ID)      '// Scrolling mode
'//gSprite[ID]:opacity = ZD_GetObjectOpacity(ID)                '// True/False PNG opacity
'//gSprite[ID]:userotate = ZD_GetObjectRotation(ID)     '// Rotate90FlipNone or Rotate270FlipNone
'//gSprite[ID]:flipmode = ZD_GetObjectFlipMode(ID)      '// True/False condition         
'//gSprite[ID]:angle = ZD_GetObjectAngle(ID)            '// Rotation angle 0-360
'//gSprite[ID]:locked = ZD_GetObjectLocked(ID)          '// True/False condition
'//gSprite[ID]:zorder = ZD_GetObjectZorder(ID)          '// The z-order value
'//gSprite[ID]:scale = ZD_GetObjectScale(ID)            '// The scale value
'//gSprite[ID]:style = ZD_GetObjectStyle(ID)            '// The object style
'//gSprite[ID]:quality = ZD_GetObjectQuality(ID)                '// The object quality
'//gSprite[ID]:clone = ZD_GetObjectClone(ID)            '// The unique ID of the cloned object
'//gSprite[ID]:selected = 0                             '// Set selected status to Off

zItem is ZOBJECT
ZD_GetObjectProperties(ID, zItem)                       '// Retrieves all the details about a GDImage sprite object in one single step.
gSprite[ID]:ID = ID                                     '// The unique sprite object IDentifier
gSprite[ID]:objtype = zItem:objType                     '// The object type (bitmap, text, arrow, curve, rectangle, ellipse, polypolyline)
gSprite[ID]:label = zItem:objLabel                      '// Friendly name
gSprite[ID]:xPos = zItem:x1                             '// X location
gSprite[ID]:yPos = zItem:y1                             '// Y location
gSprite[ID]:xWidth = zItem:x2                           '// Width of the sprite object
gSprite[ID]:yHeight = zItem:y2                          '// Height of the sprite object
gSprite[ID]:ARGB = zItem:useARGB                        '// ARGB color
gSprite[ID]:visibility = zItem:visibility               '// ZS_HIDDEN or ZS_VISIBLE state
IF BinaryAND(zItem:Style, ZS_SCROLL) = ZS_SCROLL THEN   '// Scrolling mode
        gSprite[ID]:scrollmode = -1                                     
ELSE
        gSprite[ID]:scrollmode = 0
END
gSprite[ID]:opacity = zItem:opacity                     '// True/False PNG opacity
gSprite[ID]:userotate = zItem:userotate                 '// Rotate90FlipNone or Rotate270FlipNone
gSprite[ID]:flipmode = zItem:flipmode                   '// True/False condition         
gSprite[ID]:angle = zItem:angle                         '// Rotation angle 0-360
gSprite[ID]:locked = zItem:locked                       '// True/False condition
gSprite[ID]:zorder = zItem:order                        '// The z-order value
gSprite[ID]:scale = zItem:scale                         '// The scale value
gSprite[ID]:style = zItem:Style                         '// The object style
gSprite[ID]:quality = zItem:quality                     '// The object quality
gSprite[ID]:clone = zItem:clone                         '// The unique ID of the cloned object
gSprite[ID]:selected = 0                                '// Set selected status to Off

Title: Using GDImage with PowrBasic DDT Controls
Post by: Pete Malcom on June 21, 2012, 11:52:02 AM
I can only find one example of using GDImage with PowerBasic DDT Controls – the GDWDDT example.   This is clear, but what I can't see is how to do more than create the control (and give it an initial image):

    CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL1, _
        $MyImage1, 7, 5, 420, 190, %WS_CHILD OR %WS_VISIBLE _
        OR %WS_HSCROLL OR %WS_VSCROLL, %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
        %WS_EX_RIGHTSCROLLBAR

Works fine, but how do I then get a handle to do other tasks on the control?  Eg:

ZD_FillRect (handle, 0, 0, 200, 200, color)

I tried ZI_GetDC and CONTROL HANDLE, but neither worked ...

Perhaps there is a more comprehensive example of using DDT?   I can't easily use direct Windows SDK as I am adding graphics to an existing program ...
Title: Re: Post your questions here
Post by: Patrice Terrier on June 21, 2012, 02:56:14 PM
Pete,

See the code below in red.

Quote
FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    LOCAL lRslt AS LONG

    LOCAL hDlg  AS DWORD

    DIALOG NEW hParent, "DDT + GDImage image control ", 108, 135, 434, 337, %WS_POPUP OR _
        %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR _
        %WS_VISIBLE OR %DS_MODALFRAME 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

  ' GDImage
    CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL1, _
        $MyImage1, 7, 5, 420, 190, %WS_CHILD OR %WS_VISIBLE _
        OR %WS_HSCROLL OR %WS_VSCROLL, %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
        %WS_EX_RIGHTSCROLLBAR

LOCAL hCtl AS LONG
CONTROL HANDLE hDlg, %IDC_GDimageCTRL1 TO hCtl
ZD_FillRect(ZI_GetDC(hCtl), 10,10, 50,50, RGB(255,0,0))
       
  ' GDImage
    CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL2, _
        $MyImage2, 152, 210, 130, 110, %WS_CHILD OR _
        %WS_VISIBLE, %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
        %WS_EX_RIGHTSCROLLBAR

    DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt

    FUNCTION = lRslt
END FUNCTION

Note: ZD_FillRect draw a rectangle onto the provided DC using a 24-bit RGB color.
If you want to draw a rectangle with an ARGB color (alpha channel), then use ZD_DrawRectangleToCtrl.

I would rather manipulate GDImage sprite objects (multiple layers) than drawing using a DC.
Drawing using a DC = static image, GDImage sprite objects = dynamic image (you can change the location, z-order, and all parameters of each object).

...
Title: Re: Post your questions here
Post by: Pete Malcom on June 26, 2012, 10:44:01 AM
Perfect, thanks Patrice.
Title: Re: Post your questions here
Post by: Pete Malcom on June 27, 2012, 07:23:21 PM
The ZD_FillRect example above will only draw over the background image.   If there is no background image loaded (ie the CONTROL ADD specified "" as the image name) or the image is smaller than the control, ZD_FillRect only draws over the image, or not at all (if there is no image).

I know I can create a sprite overlay, but all I want is to set a background colour for the image area before I load the background bitmap (has to happen later).   

Also tried ZI_PaintBrushBitmap, but it has been deprecated (help file needs updating).

Thanks

Pete


Title: Re: Post your questions here
Post by: Patrice Terrier on June 27, 2012, 08:12:23 PM
Pete

There are several ways to tell GDImage how to paint a specific control background:

Using a gradient color
          CALL ZI_SetProperty(GetDlgItem(hMain, %ID_CTRL), %ZI_GradientTop, RGB(93,3,28))
          CALL ZI_SetProperty(GetDlgItem(hMain, %ID_CTRL), %ZI_GradientBottom, RGB(146,3,40))

Using a flat color with same color for Top and Bottom
          CALL ZI_SetProperty(GetDlgItem(hMain, %ID_CTRL), %ZI_GradientTop, RGB(255,0,0))
          CALL ZI_SetProperty(GetDlgItem(hMain, %ID_CTRL), %ZI_GradientBottom, RGB(255,0,0))

Using a tiled background
          hTiledBitmap& = ZI_CreateBitmapFromFile("038.jpg", 0,0)
          CALL ZI_SetTiledBackground(hCtrl&, hTiledBitmap&)

And of course using an image for background (that could be resized on the fly to match the control size).

See all details in the Resource.bas example.

...
Title: Re: Post your questions here
Post by: Pete Malcom on July 03, 2012, 04:52:52 PM
And the next ...

Taking the GDWDDT example again, if we add a sprite to the GDImage Control:

CONTROL ADD $GDImageClassName, hDlg, %IDC_GDimageCTRL1, _
    $MyImage1, 7, 5, 420, 190, %WS_CHILD OR %WS_VISIBLE _
    OR %WS_HSCROLL OR %WS_VSCROLL, %WS_EX_LEFT OR %WS_EX_LTRREADING OR _
    %WS_EX_RIGHTSCROLLBAR

LOCAL hCtl AS LONG
CONTROL HANDLE hDlg, %IDC_GDimageCTRL1 TO hCtl
ZD_FillRect(ZI_GetDC(hCtl), 10,10, 50,50, RGB(255,0,0))

ZD_DrawRectangleToCtrl(hCtl, 10,10,100,100, &HFFFFFFFF, 0, %IDC_Sprite, %ZS_VISIBLE, %ZD_DRAW_FILLED)

We get a nice independant sprite rectangle overlaid, which we can move, manipulate (and remove) without affecting the underlying image.   This is really cool.

Two questions:

1.   Without adding any code to GDWDDT, hovering over the sprite changes the mouse cursor, and you can drag the sprite anywhere you want in the GDImage control.   Again, very cool, EXCEPT if you don't want the user to be able to do this ....   How do we prevent the mouse hover and the drag?

2.    With a standard PowerBasic Image control, adding the %SS_NOTIFY attribute causes the callback to fire if the user clicks anywhere on the control.   But the same does not happen with the custom control.    How do we get mouseclicks on the GDImage control, and how do we get them one of the sprites?

Thanks!
Title: Re: Post your questions here
Post by: Patrice Terrier on July 03, 2012, 05:20:22 PM
Quote1.  Without adding any code to GDWDDT, hovering over the sprite changes the mouse cursor, and you can drag the sprite anywhere you want in the GDImage control.   Again, very cool, EXCEPT if you don't want the user to be able to do this ....   How do we prevent the mouse hover and the drag?

Easy, just lock and disable the sprite image, using:
ZD_SetObjectLocked(nSpriteID, %TRUE)

Quote2.  How do we get mouseclicks on the GDImage control, and how do we get them one of the sprites?

Use a GDImage callback, in correlation with the ZI_EventMessage you want to monitor.
Search in the AEROGLASS demo project for:
CALL ZI_EventMessage(CODEPTR(MyCallBack), %WM_LBUTTONDOWN, %TRUE)

and look inside
FUNCTION MyCallBack(BYVAL hWnd AS LONG, BYVAL Msg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG
    LOCAL sMessage AS STRING, ObjectID AS LONG, rc AS RECT, nRet AS LONG
    LOCAL x AS LONG, y AS LONG

    nRet = %FALSE ' Do not stop the event processing in GDImage
   
    IF hWnd = GetDlgItem(hMain, %ID_CTRL) THEN ' In case we use the same callback for several GDImage control
                                               ' make sure that we handle the good one.
       SELECT CASE LONG Msg                 

       CASE %WM_LBUTTONDOWN
            ObjectID = ZI_MouseOverObjectID()
            IF ObjectID = GetDlgCtrlID(hWnd) THEN LabelIs$ = $Background ELSE LabelIs$ = ZD_GetObjectImageLabel(ObjectID)
'nID& = ZD_GetItemObjectAndColorAtXY(hWnd, LO(INTEGER, lParam), HI(INTEGER, lParam), ColorRGB&)
            sMessage = "WM_LBUTTONDOWN on object" + str$(ObjectID) + " >" + LabelIs$ + "<" '+ str$(nID&)+" &H"+HEX$(ColorRGB&)
            CALL SetWindowText(GetDlgItem(hMain, %ID_STATUSBAR), (sMessage))

       CASE %WM_RBUTTONDOWN
            ObjectID = ZI_MouseOverObjectID()
            IF ObjectID = GetDlgCtrlID(hWnd) THEN LabelIs$ = $Background ELSE LabelIs$ = ZD_GetObjectImageLabel(ObjectID)
            sMessage = "WM_RBUTTONDOWN on object" + str$(ObjectID) + " >" + LabelIs$ + "< at location" + str$(LOWRD(lParam))+","+str$(HIWRD(lParam))
            CALL SetWindowText(GetDlgItem(hMain, %ID_STATUSBAR), (sMessage))

       CASE %WM_MOUSEMOVE
            ObjectID = ZI_GetMovingSpriteID()
            IF ObjectID THEN
             ' Does %ID_BTN_CHECK is checked ?
               IF SendMessage(GetDlgItem(GetParent(hWnd), %ID_BTN_CHECK), %BM_GETCHECK, 0, 0) THEN
                  x = LOWRD(lParam): y = HIWRD(lParam)
                  xCurrentScroll& = ZI_GetProperty(hWnd, %ZI_Horizontal)
                  yCurrentScroll& = ZI_GetProperty(hWnd, %ZI_Vertical)
                  ZD_GetObjectXY(ObjectID, x1&, y1&)
                  ZD_GetObjectXYcapture(ObjectID, xCapture&, yCapture&)
                  DX& = (x - xCapture& +  xCurrentScroll&) - x1&
                  DY& = (y - yCapture& +  yCurrentScroll&) - y1&
                  FOR ID& = %ID_FIRST TO %ID_LAST
                      IF ID& <> ObjectID THEN
                         CALL ZD_GetObjectXY(ID&, x, y)
                       ' Add the DX,DY offset
                         CALL ZD_SetObjectXY(ID&, x + DX&, y + DY&, %ZD_DRAW_DEFERRED) ' Move, without immediate redraw
                      END IF
                  NEXT
                ' Note: The display's refresh is yeld by the default GDImage WM_MOUSE event
               END IF
            END IF

       CASE %WM_KEYDOWN
            ObjectID = ZI_GetObjectFocusID()
            IF ObjectID THEN
               CALL ZD_GetObjectXY(ObjectID, x, y)
               x1& = x ' Make a copy to keep the orignal x location unchanged
               y1& = y ' Make a copy to keep the orignal y location unchanged

             ' Check accelerator keys to compute the step range
               IF ZI_IsCtrlKeyPressed THEN
                  UseStep& = 4
                  IF ZI_IsShiftKeyPressed THEN UseStep& = 16
               ELSEIF ZI_IsShiftKeyPressed THEN
                  UseStep& = 2
               ELSE
                  UseStep& = 1
               END IF
               
               IF ZD_GetObjectScroll(ObjectID) THEN ' If object scroll with the bitmap background
                ' Get the size of the bitmap background
                  CALL ZI_GetBitmapSize(ZI_GetBMP(GetDlgItem(hMain, %ID_CTRL)), useWidth&, useHeight&)
               ELSE
                ' Get the control client size 
                  CALL GetClientRect(GetDlgItem(hMain, %ID_CTRL), rc)
                  useWidth& = rc.nRight: useHeight& = rc.nBottom
               END IF
             ' Get the sprite object size
               CALL ZD_GetObjectBound(ObjectID, BoundWidth&, BoundHeight&)

               x2Div2& = (BoundWidth& \ 2): y2Div2& = BoundHeight& \ 2
               SELECT CASE wParam
               CASE %VK_HOME
                    x1& = 0
               CASE %VK_END
                    x1& = MAX&(useWidth& - BoundWidth&, 0)
               CASE %VK_PRIOR
                    y1& = 0
               CASE %VK_NEXT
                    y1& = MAX&(useHeight& - BoundHeight&, 0)
               CASE %VK_LEFT, %VK_NUMPAD4
                    IF x1& > -x2Div2& THEN x1& = MAX&(x1& - UseStep&, -x2Div2&)
               CASE %VK_UP, %VK_NUMPAD8
                    IF y1& > -y2Div2& THEN y1& = MAX&(y1& - UseStep&, -y2Div2&)
               CASE %VK_RIGHT, %VK_NUMPAD6
                    IF x1& < useWidth& - x2Div2& THEN
                       x1& = MIN&(x1& + UseStep&, useWidth& - x2Div2&)
                    END IF
               CASE %VK_DOWN, %VK_NUMPAD2
                    IF y1& < useHeight& - y2Div2& THEN
                    y1& = MIN&(y1& + UseStep&, useHeight& - y2Div2&)
                    END IF
               END SELECT
               
               IF x <> x1& OR y <> y1& THEN
                  x = x1&: y = y1&         
                  CALL ZD_SetObjectXY(ObjectID, x1&, y1&, %TRUE)
               END IF
               sMessage = "Object" + str$(ObjectID) + " coordinates" + str$(x&)+","+str$(y&)
               CALL SetWindowText(GetDlgItem(hMain, %ID_STATUSBAR), (sMessage))
               
            END IF
       END SELECT
    END IF

    FUNCTION = nRet
END FUNCTION