AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

GDI+ standard library 1.25 by tic
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
skrommel



Joined: 30 Jul 2004
Posts: 181

PostPosted: Tue Sep 02, 2008 11:11 pm    Post subject: Reply with quote

Smile 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
View user's profile Send private message Visit poster's website
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Wed Sep 03, 2008 12:06 am    Post subject: Reply with quote

Come on little guy Wink 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 Smile
Back to top
View user's profile Send private message
rani



Joined: 18 Mar 2008
Posts: 95

PostPosted: Wed Sep 03, 2008 3:43 pm    Post subject: getpixel Reply with quote

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
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Thu Sep 04, 2008 12:02 am    Post subject: Reply with quote

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
View user's profile Send private message
rani



Joined: 18 Mar 2008
Posts: 95

PostPosted: Fri Sep 05, 2008 7:56 am    Post subject: pixelget speed Reply with quote

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
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Fri Sep 05, 2008 8:47 am    Post subject: Reply with quote

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
View user's profile Send private message
BoBo²
Guest





PostPosted: Sun Sep 07, 2008 10:36 am    Post subject: Reply with quote

[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". Very Happy

Keywords: thumbnail - gdi - gdiplus - screen - screenshoot - image - active window - fullscreen - rescale
[/cross reference]
Back to top
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Sun Sep 07, 2008 11:46 am    Post subject: Reply with quote

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
View user's profile Send private message
BoBo²
Guest





PostPosted: Sun Sep 07, 2008 5:17 pm    Post subject: Reply with quote

Quote:
This will mean that it uses HighQualityBicubic when resizing the image rather than default
Worked perfect. Thanks for that extra! Very Happy
Back to top
BoBo²
Guest





PostPosted: Mon Sep 08, 2008 10:31 pm    Post subject: Reply with quote

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

PostPosted: Mon Sep 08, 2008 10:39 pm    Post subject: Reply with quote

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
View user's profile Send private message
BoBo²
Guest





PostPosted: Mon Sep 08, 2008 11:11 pm    Post subject: Reply with quote

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

PostPosted: Tue Sep 09, 2008 7:37 am    Post subject: Gdip merge images Reply with quote

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
View user's profile Send private message
tic



Joined: 22 Apr 2007
Posts: 1375

PostPosted: Tue Sep 09, 2008 3:25 pm    Post subject: Reply with quote

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 Sad

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
View user's profile Send private message
BoBo²
Guest





PostPosted: Tue Sep 09, 2008 3:45 pm    Post subject: Reply with quote

@ tic
Wanna get blamed? Check [this] out! Wink Cool - and yes, thanks again for your effort. Very Happy
Back to top
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3, 4, 5, 6, 7, 8  Next
Page 5 of 8

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group