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
tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
thirtydot with many thanks to Philho and one of his old posts I found the 2 functions necessary to modify the encoder parameters when saving a file. for jpgs you can now specify quality 1-100 and I even wrote a header to that function! :p

Edit:

I'm sure I'm still thankful to Philho somehow :p but it should be a big thank you to Sean:

<!-- m -->http://www.autohotke... ... =30#108561<!-- m -->

thirtydot
  • Members
  • 3 posts
  • Last active: Sep 01 2008 12:25 PM
  • Joined: 24 Jul 2008
Wow, you did that much sooner than I expected. It works perfectly, thanks!

skrommel
  • Members
  • 193 posts
  • Last active: Jun 07 2010 08:30 AM
  • Joined: 30 Jul 2004
:) Thanks tic and Lexikos!

I'll write a quick app to show how I think it should be done



What I need is a way to combine Example 4 and 5.

Skrommel

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Sorry Skrommel, I've been really busy, but I promise I'll write a very good example very soon. I already started, but I realise it will take a couple more hours to complete and i start a new job tomorrow!

Thrawn
  • Members
  • 30 posts
  • Last active: Apr 05 2011 06:07 PM
  • Joined: 12 May 2008
tic,
i love you.
very good work!

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

tic,
i love you.
very good work!


Thanks very much Thrawn. I am glad to see people liking this library. I would like to create more tutorials at some point when I can find the time (and also write that example for skrommel - sorry :oops: )

Thrawn
  • Members
  • 30 posts
  • Last active: Apr 05 2011 06:07 PM
  • Joined: 12 May 2008
Is it possible to erase an area previously drawn on?
Example: Drawing a fullscreen black gui, then "cutting" out a rectangle (ellipse? even text?) somewhere on it, so the underlying windows / wallpaper become visible again.
Thanks

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
I have added 2 more examples which I hope everyone will find useful

Thrawn, what you want to do is use the function:

Gdip_SetCompositingMode(pGraphics, CompositingMode=0)

You will need to set compositing mode to 1 for your graphics (this makes it so that any drawing operations, instead of blending with what already exists, will actually draw over anything (so a transparent bruh could be used to erase an area - but it would need to be set back to 0 afterwards to carry on drawing normally)

You would need to mix this with the funtion:

Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0)

This function limits the area that is drawn onto. You can specify a rectangle and then only that will be drawn to (or only that area will not be drawn to depending on the CombineMode)

All this may sound a bit much Thrawn and I will work up to examples of this in the tutorials, but dont want to go too fast too soon

skrommel
  • Members
  • 193 posts
  • Last active: Jun 07 2010 08:30 AM
  • Joined: 30 Jul 2004
:) Great additions, tic!

However, just to nag, example 6 still doesn't save a transparent PNG, at least not on my computer. Is is supposed to? The source code says

Bear in mind transparencies may be lost with some image formats and will appear black

Mine turns light green.

Skrommel

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

:) Great additions, tic!

However, just to nag, example 6 still doesn't save a transparent PNG, at least not on my computer. Is is supposed to? The source code says

Bear in mind transparencies may be lost with some image formats and will appear black

Mine turns light green.

Skrommel


Glad you liked them Skrommel. Maybe I wasn't very clear on that example:

; Create a green brush (this will be used to fill the background with green). The brush is fully opaque (ARGB)
pBrush := Gdip_BrushCreateSolid(0xff00ff00)

makes a green background :wink: If you want a transparent background then just leave out the fill rectangle part

skrommel
  • Members
  • 193 posts
  • Last active: Jun 07 2010 08:30 AM
  • Joined: 30 Jul 2004
:oops: Sorry, tic, I didn't read the source code, and I forgot what my original problem was... :) Is there anywhere I can research saving a HDC as a transparent PNG so you don't have to

write that example for skrommel

?

Skrommel

rani
  • Members
  • 217 posts
  • Last active: Jul 21 2016 12:53 PM
  • Joined: 18 Mar 2008
hi tic,
Create a gui from an existing image on disk

I tried your code demo on image gui,
I got the image on whole screen,
anc could not escape from the image...

how I can control this viewer under Gui Window, and some gui Control
with scrolls and zooms/rotate ... ?

rani
  • Members
  • 217 posts
  • Last active: Jul 21 2016 12:53 PM
  • Joined: 18 Mar 2008
Hi tic

are you still support the GDIP thread ?

I tried to run on an Image (w2400,h3600)
with getpixel and it was really slow, can't make a batch run on many images from it.

I saw in the forum some examples with lockbits method to internal AHK array
can you write some code sample how I use the lockbits to array
make some corrections on pixel elements (color change)
and save the array back to external file

tic
  • Members
  • 1934 posts
  • Last active: May 30 2018 08:13 PM
  • Joined: 22 Apr 2007
Hi skrommel. I keep meaning to optimize this code so that it runs faster, but just havent found the time. I figured I'd post it anyway so that you can at least see I didnt ignore you :wink:

#SingleInstance, Force
DetectHiddenWindows, On
#NoEnv
SetBatchLines, -1
Coordmode, Pixel, Screen
Coordmode, Mouse, Screen

AppName = Desktop.Painter
VersionNum = 1.01

ColourN = Red|Green|Blue
ColourH = ffff0000|ff00ff00|ff0000ff
StringSplit, ColourN, ColourN, |
StringSplit, ColourH, ColourH, |

SW := 50
BackColour := 0xff475155

#Include, Gdip.ahk

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

Menu, Tray, NoStandard
Menu, Tray, DeleteAll
Menu, Tray, Add, Toggle Notes, ToggleNotes
Menu, Tray, Add, Exit, Exit
Menu, Tray, Default, Toggle Notes

SysGet, MonitorPrimary, MonitorPrimary
SysGet, WA, MonitorWorkArea, %MonitorPrimary%
WAWidth := WARight-WALeft, WAHeight := WABottom-WATop

Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Show, NA Hide
hwnd1 := WinExist()

Gui, 2: -Caption +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs +Owner1
hwnd2 := WinExist()
Gui, 2: Color, 475155

Gui, 2: Add, Button, x135 y10 w50 gSave Default, &Save...
Loop, %ColourN0%
{
	Gui, 2: Add, Picture, % ((A_Index = 1) ? "x15 y+10" : "x+10 yp+0") " w" SW " h" SW " gChangeColour 0xE v" ColourH%A_Index% " hwnd" ColourN%A_Index%
	
	pBrush := Gdip_BrushCreateSolid("0x" ColourH%A_Index%)
	pBitmap := Gdip_CreateBitmap(SW, SW), G := Gdip_GraphicsFromImage(pBitmap)
	Gdip_FillRectangle(G, pBrush, 0, 0, SW, SW)
	hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
	hwnd := ColourN%A_Index%, SetImage(%hwnd%, hBitmap)
	
	Gdip_DeleteBrush(pBrush), Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
}
Gui, 2: Add, Picture, % "x75 y+30 w" SW " h" SW " 0xE hwndPreview"		;%
Gui, 2: Add, Slider, x10 y+40 w180 vPenWidth Tooltip Range1-30 gUpdatePreview, 12
ChosenColour := 0xffff0000
GoSub, UpdatePreview

Gui, 2: Show, w200 h250 x20 y20 NA Hide

pBitmapDraw := Gdip_CreateBitmap(WAWidth, WAHeight), GDrawplus := Gdip_GraphicsFromImage(pBitmapDraw)
Gdip_SetSmoothingMode(GDrawplus, 4)
pBrush := Gdip_BrushCreateSolid(0x01ffffff)
Gdip_FillRectangle(GDrawplus, pBrush, 0, 0, WAWidth, WAHeight)
Gdip_DeleteBrush(pBrush)

hbmDraw := CreateDIBSection(WAWidth, WAHeight), hdcDraw := CreateCompatibleDC(), obmDraw := SelectObject(hdcDraw, hbmDraw), GDraw := Gdip_GraphicsFromHDC(hdcDraw)
Gdip_DrawImage(GDraw, pBitmapDraw, 0, 0, WAWidth, WAHeight)

UpdateLayeredWindow(hwnd1, hdcDraw, WALeft, WATop, WAWidth, WAHeight)

Gdip_DeleteGraphics(GDraw), SelectObject(hdcDraw, obmDraw), DeleteObject(hbmDraw), DeleteDC(hdcDraw)
Return

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

Save:
Gui, 2: +OwnDialogs
FileSelectFolder, OutFolder,,, Select where you would like to save the image
If !OutFolder
Return
Gdip_SaveBitmapToFile(pBitmapDraw, OutFolder "\" A_Now ".png")
Return

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

UpdatePreview:
Gui, 2: Submit, NoHide

pBrush := Gdip_BrushCreateSolid(ChosenColour)
pBrushBack := Gdip_BrushCreateSolid(BackColour)
pBitmap := Gdip_CreateBitmap(SW, SW), G := Gdip_GraphicsFromImage(pBitmap), Gdip_SetSmoothingMode(G, 4)
Gdip_FillRectangle(G, pBrushBack, -2, -2, SW+4, SW+4)
Gdip_FillEllipse(G, pBrush, (SW-PenWidth)//2, (SW-PenWidth)//2, PenWidth, PenWidth)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
SetImage(Preview, hBitmap)

Gdip_DeleteBrush(pBrushDraw), Gdip_DeletePen(pPenDraw)
pBrushDraw := Gdip_BrushCreateSolid(ChosenColour), pPenDraw := Gdip_CreatePen(ChosenColour, PenWidth)

Gdip_DeleteBrush(pBrush), Gdip_DeleteBrush(pBrushBack), Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmap), DeleteObject(hBitmap)
Return

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

ChangeColour:
ChosenColour := "0x" A_GuiControl
GoSub, UpdatePreview
Return

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

WM_LBUTTONDOWN()
{
	Global

	If (A_Gui != 2)
	Return, -1	
	PostMessage, 0xA1, 2
	Drag := 1
}

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

ToggleNotes:
v := IsWindowVisible(hwnd1) || IsWindowVisible(hwnd2)
Gui, % "2: " (v ? "Hide" : "Show")			;%
Gui, % "1: " (v ? "Hide" : "Show")			;%
SetTimer, CheckPos, % (v ? "Off" : 20)		;%
Return

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

CheckPos:
MouseGetPos, x, y, Win
OnMessage(0x201, (Win = hwnd2) ? "WM_LBUTTONDOWN" : "")
If !GetKeyState("LButton", "P")
Drag := 0
If (Win != hwnd1) || !GetKeyState("LButton", "P") || Drag
{
	Ox := Oy := ""
	Return
}

hbmDraw := CreateDIBSection(WAWidth, WAHeight), hdcDraw := CreateCompatibleDC(), obmDraw := SelectObject(hdcDraw, hbmDraw), GDraw := Gdip_GraphicsFromHDC(hdcDraw)
Gdip_FillEllipse(GDrawplus, pBrushDraw, x-(PenWidth//2), y-(PenWidth//2), PenWidth, PenWidth)
Gdip_DrawLine(GDrawplus, pPenDraw, Ox ? Ox : x, Oy ? Oy : y, x, y)

Gdip_DrawImage(GDraw, pBitmapDraw, 0, 0, WAWidth, WAHeight)
UpdateLayeredWindow(hwnd1, hdcDraw, WALeft, WATop, WAWidth, WAHeight)

Gdip_DeleteGraphics(GDraw), SelectObject(hdcDraw, obmDraw), DeleteObject(hbmDraw), DeleteDC(hdcDraw)
Ox := x, Oy := y
Return

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

IsWindowVisible(hwnd)
{
	Return, DllCall("IsWindowVisible", "UInt", hwnd)
}

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

Exit:
Gdip_DeleteBrush(pBrushDraw), Gdip_DeletePen(pPenDraw)
Gdip_DeleteGraphics(GDrawplus), Gdip_DisposeImage(pBitmapDraw)
Gdip_Shutdown(pToken)
ExitApp
Return

Run it, and then double click the tray icon to show/hide drawing. you just draw onto the desktop and then save. it is especially slow as it updates the entire window every time. ideally I should be using clipping regions, but I havent got onto that in the tutorials yet. I can optimize it another time if you wish. Obviously I could make it a lot better than this, but just thought I should post something...

Hi rani....yes I am still supporting this thread :) but do not find time every day to answer, but will always help when I get time! I have already showed in the examples how to "zoom" this is done with Gdip_DrawImage and specifying the new width/height. I have not yet shown how to rotate, but I promise I will write an example for that also. Its a bit complex, but requires Gdip_ResetWorldTransform and the functions around it to help. The getpixel is actually surprisingly fast when i test it, so i dont know what specs you are testing on. obviously it is not meant to scan a whole image pixel by pixel, but this is not a limitation of the library, this is a limitation of ahk (and other scripting languages) as it is slow anyway to perform many loops

Edit for skrommel:

This probably isnt much help, but I realise I can make it muuuch faster. It will use the same method though, so the above is still all valid :O

rani
  • Members
  • 217 posts
  • Last active: Jul 21 2016 12:53 PM
  • Joined: 18 Mar 2008
Hi Tic
GdipBitmaplockBits

can you write a little code sample how to get/set pixels
by lockbits ?
means to put the bits to array.
I saw saw some samples in this forum, but they are too complicated for me

also how you save the array back to file disk.