 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
skrommel
Joined: 30 Jul 2004 Posts: 181
|
Posted: Tue Sep 02, 2008 11:11 pm Post subject: |
|
|
Thanks, tic!
I've tried similar code, and if UpdateLayeredWindow could be made to only update the area around the last stroke, it would be much faster. I couldn't make it work, however.
Skrommel _________________ www.1HourSoftware.com |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1375
|
Posted: Wed Sep 03, 2008 12:06 am Post subject: |
|
|
Come on little guy have a little ingenuity
Here's a simple idea to have it run perfectly fast (for ahk) without having to rewrite the code:
| Code: | #SingleInstance, Force
DetectHiddenWindows, On
#NoEnv
SetBatchLines, -1
Coordmode, Pixel, Screen
Coordmode, Mouse, Screen
AppName = Desktop.Painter
VersionNum = 1.02
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)
hbmDraw := CreateDIBSection(WAWidth, WAHeight), hdcDraw := CreateCompatibleDC(), obmDraw := SelectObject(hdcDraw, hbmDraw), GDraw := Gdip_GraphicsFromHDC(hdcDraw)
Gdip_SetSmoothingMode(GDraw, 4)
pBrush := Gdip_BrushCreateSolid(0x01ffffff)
Gdip_FillRectangle(GDrawplus, pBrush, 0, 0, WAWidth, WAHeight), Gdip_FillRectangle(GDraw, pBrush, 0, 0, WAWidth, WAHeight)
Gdip_DeleteBrush(pBrush)
UpdateLayeredWindow(hwnd1, hdcDraw, WALeft, WATop, WAWidth, WAHeight)
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" : 40) ;%
Return
;####################################################################################
CheckPos:
Critical
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
}
SetTimer, DelayedSave, Off
Gdip_FillEllipse(GDraw, pBrushDraw, x-(PenWidth//2), y-(PenWidth//2), PenWidth, PenWidth)
Gdip_DrawLine(GDraw, pPenDraw, Ox ? Ox : x, Oy ? Oy : y, x, y)
UpdateLayeredWindow(hwnd1, hdcDraw, WALeft, WATop, WAWidth, WAHeight)
Array .= x "," y "," Ox "," Oy "|"
SetTimer, DelayedSave, -300
Ox := x, Oy := y
Return
;####################################################################################
DelayedSave:
Critical
Loop, Parse, Array, |
{
StringSplit, c, A_LoopField, `,
Gdip_FillEllipse(GDrawplus, pBrushDraw, c1-(PenWidth//2), c2-(PenWidth//2), PenWidth, PenWidth)
Gdip_DrawLine(GDrawplus, pPenDraw, c3 ? c3 : c1, c4 ? c4 : c2, c1, c2)
}
Array := ""
Return
;####################################################################################
IsWindowVisible(hwnd)
{
Return, DllCall("IsWindowVisible", "UInt", hwnd)
}
;####################################################################################
Exit:
Gdip_DeleteBrush(pBrushDraw), Gdip_DeletePen(pPenDraw)
Gdip_DeleteGraphics(GDrawplus), Gdip_DisposeImage(pBitmapDraw)
Gdip_DeleteGraphics(GDraw), SelectObject(hdcDraw, obmDraw), DeleteObject(hbmDraw), DeleteDC(hdcDraw)
Gdip_Shutdown(pToken)
ExitApp
Return |
I slowed the timer to save some cpu
It would also be nice to use GetSaveFileName rather than that button, but that isnt within the scope of me just mucking around  |
|
| Back to top |
|
 |
rani
Joined: 18 Mar 2008 Posts: 95
|
Posted: Wed Sep 03, 2008 3:43 pm Post subject: getpixel |
|
|
Hi tic,
1.
I tried again the getpixel (GDIP) on strong server,
and the results where not good also.
2. if I compile ahk it will be faster ?
it is an .exe like any other ?
3.I think the problem is not ahk, .
the getpixel is slow.
any help will be apprecieated |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1375
|
Posted: Thu Sep 04, 2008 12:02 am Post subject: |
|
|
I hope this test will prove I am right:
| Code: | SetBatchLines, -1
#Include, Gdip.ahk
pToken := Gdip_Startup()
pBitmap := Gdip_CreateBitmap(400, 400)
Time1 := A_TickCount
Loop, 100000
Gdip_GetPixel(pBitmap, 1, 1)
Time2 := A_TickCount
Loop, 100000
test += Add(A_Index, A_Index)
MsgBox, % "Time to get pixels: " Time2-Time1 "`nTime to add a bunch of numbers: " A_TickCount-Time2 ;%
Gdip_DisposeImage(pBitmap), Gdip_Shutdown(pToken)
ExitApp
Return
Add(x, y)
{
add := x+y ; 2 lines for function to make it a fair comparison with Gdip_GetPixel
Return, add
} |
Now you can see on my computer it takes 800 ms to get the colour of 100,000 pixels, which id say is pretty fast, compare that to the most basic function imaginable, which just adds 2 numbers together, it is only 2.5 times slower than it!
| Quote: | 2. if I compile ahk it will be faster ?
it is an .exe like any other ? |
It will be the same speed as if the ahk was not compiled |
|
| Back to top |
|
 |
rani
Joined: 18 Mar 2008 Posts: 95
|
Posted: Fri Sep 05, 2008 7:56 am Post subject: pixelget speed |
|
|
hi tic,
I made some minor changes to your code-time-test
for actual (width,hight) image I try to run.
and the time I get is much much slower.
| Code: |
SetBatchLines, -1
#Include, Gdip.ahk
pToken := Gdip_Startup()
w :=1800,h:=770
pBitmap := Gdip_CreateBitmap(w, h)
Time1 := A_TickCount
ix=0,iy=0
Loop, %h%
{
iy +=1
ix :=0
LOOP,%w%
{
ix +=1
; pixel :=getPixel(ix,iy)
pixel :=Gdip_GetPixel(pBitmap, ix,iy)
}
}
Time2 := A_TickCount
i := w*h
Loop, %i%
{
test += Add(A_Index, A_Index)
}
MsgBox, % "Time to get pixels: " Time2-Time1 "`nTime to add a bunch of numbers: " A_TickCount-Time2 ;%
Gdip_DisposeImage(pBitmap)
Gdip_Shutdown(pToken)
ExitApp
Return
Add(x, y)
{
add := x+y ; 2 lines for function to make it a fair comparison with Gdip_GetPixel
Return, add
}
getPixel(ix,iy)
{
pixel :=Gdip_GetPixel(pBitmap, ix,iy)
return,pixel
}
|
the time I get:
calculate a number : 6625
getpixel : 24979
if I run the function getPixel, instead pixel := ... it's also more slower..
or the loops are not buid ok ?
I tried same (more or less) loops on strong server
and got same results
pls note that I still didn't use the setPixel....
lockbits
how I set back to pBitmap the array I get from lockbits ?
can you add these functions to your GDIP library ?
means:
by lockbits -> ahk array
make some correction on array (colors)
and then ahk array -> pBitmap
and save to file
or you can send some code sample or link how to do it.
actually I didn't see how I set array to pBitmap |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1375
|
Posted: Fri Sep 05, 2008 8:47 am Post subject: |
|
|
There is not a faster way to do this in ahk! You've even further proven my point with your code sample......
You have attempted to do ~1.4 million loops, thus it takes longer. The code I sent is much quicker, with you only adding lines with simple setting of variables and addition, proving that these commands are actually making it much slower, this showing that the GetPixel function is not actually what is slowing it down
ahk is not meant to do 1.4 million loops in succession in any kind of timely manner. Even if you came up with another solution, you would still need to perform the loops as ahk is not a compiled language and so arrays are not properly handled as an array should be, but are just references to places in memory, so you would still have to perform that many numgets, so still have to perform the loops which is what is slowing it down!
If you want to perform 1.4 million iterations of getting a pixels colour in a timely manner, then I suggest you look at a compiled language such as C#, although for me it is perfectly fine. In the test I show how long the actual function takes...on my comp it is 800ms for 100,000 loops, so I think it's a bit much complaining at the speed of a funtion in ahk that takes 8 nanoseconds! Even in your test with your added lines, each loop only takes 19 nanoseconds! |
|
| Back to top |
|
 |
BoBo² Guest
|
Posted: Sun Sep 07, 2008 10:36 am Post subject: |
|
|
[cross reference]
tic kindly solved [here] one of my requests regarding ~ "how to create a screenshoot of the active window, and rescale it to get a thumbnail image".
Keywords: thumbnail - gdi - gdiplus - screen - screenshoot - image - active window - fullscreen - rescale
[/cross reference] |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1375
|
Posted: Sun Sep 07, 2008 11:46 am Post subject: |
|
|
Sorry Bobo I should have also mentioned...It will be better if you change the default interpolation mode:
| Code: | #SingleInstance, Force
SetBatchLines, -1
#Include, Gdip.ahk
Size := 0.8
FileType = png
Font = Arial
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
OnExit, Exit
Hotkey, ^PrintScreen, SaveScreen, On
Return
;####################################################################################
SaveScreen:
pBitmap := Gdip_BitmapFromScreen()
Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap)
PBitmapResized := Gdip_CreateBitmap(Round(Width*Size), Round(Height*Size)), G := Gdip_GraphicsFromImage(pBitmapResized), Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, Round(Width*Size), Round(Height*Size), 0, 0, Width, Height)
Gdip_TextToGraphics(G, A_Hour ":" A_Min ":" A_Sec " " A_DD "/" A_MM "/" A_YYYY, "x0 y0 r4 cff000000 s5p", Font, Round(Width*Size), Round(Height*Size))
Gdip_SaveBitmapToFile(PBitmapResized, A_Now "." FileType)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmapResized)
Gdip_DisposeImage(pBitmap)
Return
;####################################################################################
Exit:
Gdip_Shutdown(pToken)
ExitApp
Return |
So I have used:
| Code: | | Gdip_SetInterpolationMode(G, 7) |
as I do several times in the examples. This will mean that it uses HighQualityBicubic when resizing the image rather than default |
|
| Back to top |
|
 |
BoBo² Guest
|
Posted: Sun Sep 07, 2008 5:17 pm Post subject: |
|
|
| Quote: | | This will mean that it uses HighQualityBicubic when resizing the image rather than default | Worked perfect. Thanks for that extra!  |
|
| Back to top |
|
 |
BoBo² Guest
|
Posted: Mon Sep 08, 2008 10:31 pm Post subject: |
|
|
I've embedded the script to work as a function: | Code: | !PrintScreen::
SaveScreen(1,"png","Window")
Sleep, 750
SaveScreen(0.33,"png","Window")
Return
SaveScreen(Size,FileType,ToShot) {
.
.
.
Return
} | Interestingly I've to add a >=750 ms sleep between bot shots/function calls. Otherwise I'll get only the result of the first call. Are there any memory usage specifics I've to care for? |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1375
|
Posted: Mon Sep 08, 2008 10:39 pm Post subject: |
|
|
| BoBo² wrote: | I've embedded the script to work as a function: | Code: | !PrintScreen::
SaveScreen(1,"png","Window")
Sleep, 750
SaveScreen(0.33,"png","Window")
Return
SaveScreen(Size,FileType,ToShot) {
.
.
.
Return
} | Interestingly I've to add a >=750 ms sleep between bot shots/function calls. Otherwise I'll get only the result of the first call. Are there any memory usage specifics I've to care for? |
Heh well you need to show me exactly what your function is before I can answer that. You always must ensure you dispose of everything you create at some point. I doubt theres any reason youd need a sleep |
|
| Back to top |
|
 |
BoBo² Guest
|
Posted: Mon Sep 08, 2008 11:11 pm Post subject: |
|
|
That's pretty much the same code you provided ... | Code: | #SingleInstance, Force
#Include, Gdip.ahk
SetBatchLines, -1
If !pToken := Gdip_Startup()
{
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
ExitApp
}
OnExit, Exit
!y::
SaveScreen(1.00,"png","Window")
Sleep, 650
SaveScreen(0.33,"png","Window")
Return
SaveScreen(Size,FileType,Type)
{
WinGetPos, X, Y, W, H, A
If (Type = "Window")
pBitmap := Gdip_BitmapFromScreen(X "|" Y "|" W "|" H)
Else
pBitmap := Gdip_BitmapFromScreen()
Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap)
PBitmapResized := Gdip_CreateBitmap(Round(Width*Size), Round(Height*Size)), G := Gdip_GraphicsFromImage(pBitmapResized)
Gdip_SetInterpolationMode(G, 7)
Gdip_DrawImage(G, pBitmap, 0, 0, Round(Width*Size), Round(Height*Size), 0, 0, Width, Height)
Gdip_SaveBitmapToFile(PBitmapResized, A_ScriptDir "\" A_Now "." FileType)
Gdip_DeleteGraphics(G), Gdip_DisposeImage(pBitmapResized)
Gdip_DisposeImage(pBitmap)
Return
}
Exit:
Gdip_Shutdown(pToken)
ExitApp
Return |
|
|
| Back to top |
|
 |
rani
Joined: 18 Mar 2008 Posts: 95
|
Posted: Tue Sep 09, 2008 7:37 am Post subject: Gdip merge images |
|
|
Hi tic
Gdip functions
with what functions I can paste (merge) one image bitmap
to some other image bitmap
means:
I want to cut some rectangle of image one (x,y,w,h)
and paste it to other image(bitmap) on specific (x2,y2) location on image two
and save image two to file
can you point on some code sample or link ? |
|
| Back to top |
|
 |
tic
Joined: 22 Apr 2007 Posts: 1375
|
Posted: Tue Sep 09, 2008 3:25 pm Post subject: |
|
|
BoBo²:
I have made a couple of alterations to the library. See whether it is any better now. I specifically changed the raster operation code involved with the bitblt when copying the dc of the screen. Nothing to do with this also, I also added functions to get the dpi of an image
rani:
I had hoped I had explained this well enough in the examples
If you wish to copy an image (or part of an image onto another) you would need to get the graphics from the bitmap you want as your background (so behind the other):
| Code: | pBitmapBackground := Gdip_CreateBitmapFromFile(sFileBackground)
G := Gdip_GraphicsFromImage(pBitmapBackground) |
You will then need a bitmap of the file you wish to put over it:
| Code: | | pBitmapForeground := Gdip_CreateBitmapFromFile(sFileForeground) |
You will need to know the dimensions of the file you are using as your top file:
| Code: | | Width := Gdip_GetImageWidth(pBitmap), Height := Gdip_GetImageHeight(pBitmap) |
You can then draw onto the Graphics of the first bitmap with the bitmap of the 2nd:
| Code: |
Gdip_DrawImage(GBackground, pBitmapForeground, DestinationxPos, DestinationyPos, DestinationWidth, DestinationHeight, SourcexPos, SourceyPos, SourceWidth, SourceHeight) |
So you can see that you can select a rectangle from the top image and draw it at a chosen width and height on the background image wherever you want. You can see this being done in Bobo's code above
I strongly advise you try the examples as they are a good way to get to see how a few things can be done. I will add to them in time... |
|
| Back to top |
|
 |
BoBo² Guest
|
Posted: Tue Sep 09, 2008 3:45 pm Post subject: |
|
|
@ tic
Wanna get blamed? Check [this] out! - and yes, thanks again for your effort.  |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|