Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

GDI+ standard library 1.45 by tic


  • Please log in to reply
1385 replies to this topic
LuceGold2
  • Guests
  • Last active:
  • Joined: --
Tic, thank you incredibly for the reference to this post.

Please see what I have here and hopefully you can guide me further:

Below is basically what I am using, which works, to generate a image file from a PSTREAM


; GENERATE GDI+ BITMAP FROM A PSTREAM

DllCall( "LoadLibrary", Str,"gdiplus" )
VarSetCapacity(si, 16, 0), si := Chr(1)
DllCall( "gdiplus\GdiplusStartup", UIntP,pToken, UInt,&si, UInt,0 )
DllCall( "gdiplus\GdipCreateBitmapFromStream", UInt,pStream, UIntP,bitmap )

; SAVE THIS BITMAP TO A FILE

GDIplus_GetEncoderCLSID(pngEncoder, "image/png")
GDIplus_SaveImage(bitmap, "C:\image.png", pngEncoder, encoderParams)


... but what I really want to do, is load up more than one pStream into the Bitmap before it is saved. Where I am slightly confused is this


Gdip_DrawImage(G, pBitmap, dx, dy, dw, dh, sx, sy, sw, sh, 0.5)


I don't really understand how this line works... but where I am very confused is the transparency part. I really don't want one image less 'transparent' than the other... They are both assumed to be semi-transparent PNG's, and I want to Composite them over each other.

Basically, what would be so awesome is if I can see a working model, where a 500x500 flat red or green background is generated,.... and 2 images of 100x100 are placed over this background. The images should be semi-transparent (i.e. some PNG image that would have transparent parts blended over this color backdrop ---) :)

I hope this makes sense. I am really greatful for your assistance.

:D

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Do you want this to be saved to disk or displayed as a gui? Also is there any reason you keep mentioning using streams? Is this what you are asking:


Create a 500x500 green background
Take a png from disk and draw it over the green background
Save the result to disk as another png

LuceGold2
  • Guests
  • Last active:
  • Joined: --
Hiyas!

1) Create a 500x500 green background
2) Take a png from disk and draw it over the green background at x25 y25
3) Take another png from disk and draw it over the green background x100 y100
4) Save the result to disk as another png

Correct :), this would be the desired flow I would be seeking to get a feel for how this all works.

Sorry for my mixed terminology on 'pstreams'. Basically what I mean is to load the image from a file into a stream... but maybe I should be using a different term there. Sorry for any mixup :)

The main thing I am looking for is the general ability to lay these images over in a blended fashion, so if the PNG has transparent properties, it looks proper over the layout :D

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Try example 6 on the 1st post. I recommend you try all the other 5 examples also however as it will give you a better understanding of how it all works.

Note for everyone: Always ensure you have the latest Gdip.ahk!

Hope this helps :)

LuceGold2
  • Guests
  • Last active:
  • Joined: --
Thank you Tic for this pro documentation and learning examples, it has been very helpful in my knowledge learning of this. Have a very good weekend!

Cheers!, Steven

PixelVision
  • Members
  • 4 posts
  • Last active: Jul 20 2008 07:51 AM
  • Joined: 28 Jun 2008
Hi Tic! I have been working with your tutorials, and think this is best thing since sliced bread & you make it easy to follow.

May I pose one question? I am not so clear on all syntaxs. Basically, I want to take a 500x500 image, ... a green block will do.... and write a Blue border around it with a 2 pixel border thickness @ 50% transparency :)

How can this be done efficiently? :) Have a great day!

PixelVision

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007

Hi Tic! I have been working with your tutorials, and think this is best thing since sliced bread & you make it easy to follow.

May I pose one question? I am not so clear on all syntaxs. Basically, I want to take a 500x500 image, ... a green block will do.... and write a Blue border around it with a 2 pixel border thickness @ 50% transparency :)

How can this be done efficiently? :) Have a great day!

PixelVision


:D It makes me very happy that you have been able to follow the tutorials and will release a few more in time, but don't want to make them too hard too early

I need to be clear about some things....Is this the order of events you are wanting:

Take an exisiting image on disk
Draw a blue border with 50% opacity round it
Save that back to disk (overwrite/new file?)

I ask this because I am unsure when people ask questions whether they want to turn their idea into a file on disk, or show it in a gui

tic

PixelVision
  • Members
  • 4 posts
  • Last active: Jul 20 2008 07:51 AM
  • Joined: 28 Jun 2008

:D It makes me very happy that you have been able to follow the tutorials and will release a few more in time, but don't want to make them too hard too early

I need to be clear about some things....Is this the order of events you are wanting:

Take an exisiting image on disk
Draw a blue border with 50% opacity round it
Save that back to disk (overwrite/new file?)

I ask this because I am unsure when people ask questions whether they want to turn their idea into a file on disk, or show it in a gui

tic




*Take an exisiting image on disk
*Draw a blue border with 50% opacity round it
*Save that back to disk (overwrite/new file?)


Very cool! :) That is basically what I would be hoping for (+ also to adjust the variable thickness of the border) :)... as far as what to do with the bitmap, either way would work for demo purposes. I've figured out how to display or save bitmap data, following your standards,... so no worries :D

trik
  • Members
  • 1317 posts
  • Last active: Jun 11 2010 11:48 PM
  • Joined: 15 Jul 2007
PixelVision, at least put some effort forth.

pToken       := Gdip_Startup() ; Startup Gdip

sOutput      := "MyBitmap.png" ; File to save bitmap to.

pBitmap      := Gdip_CreateBitmap(500, 500) ; Make a new bitmap, 500x500 pixels
pGraphics    := Gdip_GraphicsFromImage(pBitmap) ; Get graphics from pBitmap

hBrush       := Gdip_BrushCreateSolid(0x7F0000FF) ; Create a blue brush with 50% opacity
Gdip_FillRectangle(pGraphics, hBrush, 0, 0, 500, 500) ; Draw a rectangle in the bitmap, 500x500 pixels, of hBrush
Gdip_DeleteBrush(hBrush) ; Delete hBrush

hBrush       := Gdip_BrushCreateSolid(0xFF00FF00) ; Create a green brush with 100% opacity
Gdip_FillRectangle(pGraphics, hBrush, 2, 2, 496, 496) ; Draw a rectangle in the bitmap, 496x496 pixels, of hBrush
Gdip_DeleteBrush(hBrush) ; Delete hBrush

Gdip_SaveBitmapToFile(pBitmap, sOutput) ; Save pBitmap to sOutput

Gdip_Shutdown(pToken) ; Shutdown Gdip

This would have not been made had it not been for tic teaching me bin2hex conversion.
Religion is false. >_>

arunsonnet
  • Members
  • 2 posts
  • Last active: Nov 18 2008 02:46 PM
  • Joined: 16 Feb 2008
I'm getting this error message whenever i tried to use Gdip. I've tried only the examples given by tic.

Error at line 193 in #include file "F:\ahk\Gdip.ahk".


Line Text: ppvBits
Error: Default value not allowed with ByRef.


The program will exit.


tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007

I'm getting this error message whenever i tried to use Gdip. I've tried only the examples given by tic.

Error at line 193 in #include file "F:\ahk\Gdip.ahk".


Line Text: ppvBits
Error: Default value not allowed with ByRef.


The program will exit.


I think you need to get the latest version of ahk

This would have not been made had it not been for tic teaching me bin2hex conversion.


Heh...I think you mean dec2hex though :p
You need to remember to dispose of everything you create though, like pBitmap, pGraphics and the 1st hBrush....also I think he wants to take an existing image from disk (like a photo or whatever):

#SingleInstance, Force
#NoEnv
SetBatchLines, -1
SetWorkingDir %A_ScriptDir%

; Uncomment if Gdip is not in your standard library directory
;#Include, Gdip.ahk

If !pToken := Gdip_Startup()
{
	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
	ExitApp
}

InFile := "InImage.png", OutFile := "OutImage.png"
BorderWidth := 3

pBitmap := Gdip_CreateBitmapFromFile(InFile), G := Gdip_GraphicsFromImage(pBitmap)
Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap)

hPen := Gdip_CreatePen(0x7f0000ff, BorderWidth)
Gdip_DrawRectangle(G, hPen, BorderWidth//2, BorderWidth//2, Width-BorderWidth, Height-BorderWidth)
Gdip_DeletePen(hPen)

Gdip_SaveBitmapToFile(pBitmap, OutFile)

Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
ExitApp
Return

...Although you are correct that all the information in the code above can be found in the examples :) happy scripting...

arunsonnet
  • Members
  • 2 posts
  • Last active: Nov 18 2008 02:46 PM
  • Joined: 16 Feb 2008

I think you need to get the latest version of ahk


ya.. that worked . Thanks a lot.

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
I have updated the library again with some new functions, most notably:

Gdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r)
Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)

I will give examples how to use these soon (r is the radius of the rounded corner)

Also I have made a tiny mistake :oops: The variable names hBrush and hPen should actually be pBrush and pPen respectively, as for example pBrush is actually a pointer to a brush object in memory and is not a handle. It's a very small mistake, but has just been changed in all files on the 1st post for correctness.

  • Guests
  • Last active:
  • Joined: --
Tic! Hi, can you help me with a save issue?

... from reading your tutorials, I understand if I do something like


pBitmap := Gdip_CreateBitmap(100,100)
[color=green]G := Gdip_GraphicsFromIMage(pBitmap)[/color]


.... I can do stuff with it, and later run this


GdipSaveBitmapToFile(pBitmap, "savedimage.png")


ok, so I clear on this. but what if I working with a display image in a gui


Gui, 1: -Caption +E0x80000 +ToolWindow 
Gui, 1: Show, GRAPHIC

hwnd1 := WinExist()

hbm := CreateDIBSection(100,100)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)

[color=green]G := Gdip_GraphicsFromHDC(hdc)[/color]

...
..

UpdateLayeredWindow(hwnd1, hdc, 0, 0, 100, 100)


I am confused, ... I get the stuff to display in GUI fine... but I want to modify above block of code, to let me save to PNG? I started writing this, and never really understood what I needed to do for me to write the pBitmap to a file. Sorry I am new, but can you see what I am missing concept wise? :)

Great tutorials, & thank you for your time tic!!

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Sure.....when working with guis then you will need a hBitmap (hbm), this is a gdi bitmap, and not a gdi+ bitmap (pBitmap), as a gdi bitmap is required to update a gui. In order to save the gdi bitmap the same way we save the gdi+ bitmap, one simple method would be to get pBitmap from hbm.....so here is the 1st example from the front page, but with 3 extra lines (one of them used to dispose of the pBitmap created), allowing us to save a gdi bitmap to disk:

; gdi+ ahk tutorial 1 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Tutorial to draw a single ellipse and rectangle to the screen

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip.ahk

; Start gdi+
If !pToken := Gdip_Startup()
{
	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
	ExitApp
}
OnExit, Exit

; Set the width and height we want as our drawing area, to draw everything in. This will be the dimensions of our bitmap
Width := 600, Height := 400

; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs

; Show the window
Gui, 1: Show, NA

; Get a handle to this window we have created in order to update it later
hwnd1 := WinExist()

; Create a gdi bitmap with width and height of what we are going to draw into it. This is the entire drawing area for everything
hbm := CreateDIBSection(Width, Height)

; Get a device context compatible with the screen
hdc := CreateCompatibleDC()

; Select the bitmap into the device context
obm := SelectObject(hdc, hbm)

; Get a pointer to the graphics of the bitmap, for use with drawing functions
G := Gdip_GraphicsFromHDC(hdc)

; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling)
Gdip_SetSmoothingMode(G, 4)

; Create a fully opaque red brush (ARGB = Transparency, red, green, blue) to draw a circle
pBrush := Gdip_BrushCreateSolid(0xffff0000)

; Fill the graphics of the bitmap with an ellipse using the brush created
; Filling from coordinates (100,50) an ellipse of 200x300
Gdip_FillEllipse(G, pBrush, 100, 50, 200, 300)

; Delete the brush as it is no longer needed and wastes memory
Gdip_DeleteBrush(pBrush)

; Create a slightly transparent (66) blue brush (ARGB = Transparency, red, green, blue) to draw a rectangle
pBrush := Gdip_BrushCreateSolid(0x660000ff)

; Fill the graphics of the bitmap with a rectangle using the brush created
; Filling from coordinates (250,80) a rectangle of 300x200
Gdip_FillRectangle(G, pBrush, 250, 80, 300, 200)

; Delete the brush as it is no longer needed and wastes memory
Gdip_DeleteBrush(pBrush)


; Update the specified window we have created (hwnd1) with a handle to our bitmap (hdc), specifying the x,y,w,h we want it positioned on our screen
; So this will position our gui at (0,0) with the Width and Height specified earlier
UpdateLayeredWindow(hwnd1, hdc, 0, 0, Width, Height)

pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
Gdip_SaveBitmapToFile(pBitmap, "file.bmp")
Gdip_DisposeImage(pBitmap)

; Select the object back into the hdc
SelectObject(hdc, obm)

; Now the bitmap may be deleted
DeleteObject(hbm)

; Also the device context related to the bitmap may be deleted
DeleteDC(hdc)

; The graphics may now be deleted
Gdip_DeleteGraphics(G)
Return

;#######################################################################

Exit:
; gdi+ may now be shutdown on exiting the program
Gdip_Shutdown(pToken)
ExitApp
Return