Its a very useful function.
Secondly, the function works great but theres a problem with it, the transparency from a png image becomes white. It supposed to just cut off edges or make it round if a solid image is being rendered or if the image is too large.
Is there a way around this or am i doing something wrong?
Heres an example:
Code: Select all
#NoEnv
;#Warn
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance, Force
#Persistent
SetBatchLines, -1
; Comment out if in your standard lib.
#Include, %A_ScriptDir%\Gdip_All.ahk
If !pToken := Gdip_Startup() {
MsgBox, 48, Winamp Widget: gdiplus error!, Gdiplus failed to start. Please ensure you have the proper gdiplus on your system.`n`nWinamp Widget will now exit.
exitapp
}
OnExit, Exit
ImageW := 100 ; End image width. Here you specify how large the image is going to be displayed (Gui width essentially).
ImageH := 100 ; End image height. Here you specify how large the image is going to be displayed (Gui width essentially).
Padding := 50 ; In percent! Padding 0 - 100, 0 = cubic, 100 = round (is making cubes rounder called padding?)
AspectRatioType := 2 ; 0 = Resize freely, 1 = by largest dimension between width and height, 2 = by smallest dimension between width and height.
hbm := CreateDIBSection(ImageW, ImageH)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetSmoothingMode(G, 4)
Gui, Base: -Caption +E0x80000 +OwnDialogs ;+Owner
Gui, Base: +LastFound +AlwaysOnTop
LastParentHwnd := hwndBase := WinExist()
Gui, Base: Show, NA
pBrush := Gdip_BrushCreateSolid(0x0100ff00)
Gdip_FillRectangle(G, pBrush, 0, 0, ImageW, ImageH)
Gdip_DeleteBrush(pBrush)
UpdateLayeredWindow(hwndBase, hdc, A_ScreenWidth-ImageW-200, 200, ImageW, ImageH)
Gdip_GraphicsClear(G)
Gui, 1: -Caption +E0x80000 +OwnDialogs ;+Owner
Gui, 1: +LastFound +AlwaysOnTop
Gui, 1: +E0x10
Gui, 1: +Parent%LastParentHwnd%
hwnd1 := WinExist()
Gui, 1: Show, NA
pBrush := Gdip_BrushCreateSolid(0xff00ff00)
Gdip_FillRectangle(G, pBrush, 0, 0, ImageW, ImageH)
Gdip_DeleteBrush(pBrush)
UpdateLayeredWindow(hwnd1, hdc, 0, 0, ImageW, ImageH)
Gdip_GraphicsClear(G)
OnMessage(0x201, "WM_LBUTTONDOWN")
return
GuiDropFiles:
Image := A_GuiEvent
pBitmap := Gdip_CreateBitmapFromFile(Image), Gdip_GetDimensions(pBitmap, W, H)
ImgW := ImageW
ImgH := ImageH
Resize(ImgW, ImgH, W, H, AspectRatioType)
pBitmapMask := Gdip_CreateBitmap(W, H), G2 := Gdip_GraphicsFromImage(pBitmapMask), Gdip_SetSmoothingMode(G2, 4),Gdip_SetInterpolationMode(G2, 7)
pBrush := Gdip_BrushCreateSolid(0xff00ff00)
CanvasW := W
CanvasH := H
CanvasOffsetX := 0
CanvasOffsetY := 0
if (CanvasW > CanvasH) {
CanvasW := CanvasH
CanvasOffsetX := (W/2)-(H/2)
NewPadding := ((CanvasW/2)/100) * Clamp(Padding,0,100)
} else {
CanvasH := CanvasW
CanvasOffsetY := (W/2)-(H/2)
NewPadding := ((CanvasH/2)/100) * Clamp(Padding,0,100)
}
Gdip_FillRoundedRectangle(G2, pBrush, CanvasOffsetX, CanvasOffsetY, CanvasW, CanvasH, NewPadding)
Gdip_DeleteBrush(pBrush), Gdip_DeleteGraphics(G2)
pBitmapNew := Gdip_AlphaMask(pBitmap, pBitmapMask, 0, 0, 0)
DrawW := (ImageW/2)-ImgW/2
DrawH := (ImageH/2)-ImgH/2
Gdip_DrawImage(G, pBitmapNew, DrawW, DrawH, ImgW, ImgH, 0, 0, W, H)
UpdateLayeredWindow(hwnd1, hdc, 0, 0, ImageW, ImageH)
Gdip_GraphicsClear(G)
Gdip_DisposeImage(pBitmapNew), Gdip_DisposeImage(pBitmap), Gdip_DisposeImage(pBitmapMask)
return
F1::reload
^Esc::exitapp
Exit:
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Gdip_DeleteGraphics(G2)
Gdip_Shutdown(pToken)
exitapp
return
WM_LBUTTONDOWN() {
PostMessage, 0xA1, 2
}
; Resize by theimmersion
Resize(byref NewW, byref NewH, OrigW, OrigH, aspectRatio=0) {
if (aspectRatio = 1 or aspectRatio = 2) {
if NewW and NewH {
if aspectRatio = 1
(OrigW-NewW) > (OrigH-NewH) ? NewH := round(OrigH/OrigW*NewW) : NewW := round(OrigW/OrigH*NewH)
else if aspectRatio = 2
(OrigW-NewW) < (OrigH-NewH) ? NewH := round(OrigH/OrigW*NewW) : NewW := round(OrigW/OrigH*NewH)
}
}
NewW := NewW = "" ? round(OrigW/OrigH*NewH) : NewW
NewH := NewH = "" ? round(OrigH/OrigW*NewW) : NewH
}
; Clamp by theimmersion
Clamp(ByRef Val, Min, Max) {
If (Val < Min)
Val := Min
If (Val > Max)
Val := Max
return Val
}
; by Tic. http://www.autohotkey.com/board/topic/103475-gdi-cutting-anti-aliasing/#entry638772
MCode(mcode)
{
static e := {1:4, 2:1}, c := (A_PtrSize=8) ? "x64" : "x86"
if (!regexmatch(mcode, "^([0-9]+),(" c ":|.*?," c ":)([^,]+)", m))
return
if (!DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", 0, "uint*", s, "ptr", 0, "ptr", 0))
return
p := DllCall("GlobalAlloc", "uint", 0, "ptr", s, "ptr")
if (c="x64")
DllCall("VirtualProtect", "ptr", p, "ptr", s, "uint", 0x40, "uint*", op)
if (DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", p, "uint*", s, "ptr", 0, "ptr", 0))
return p
DllCall("GlobalFree", "ptr", p)
}
Gdip_AlphaMask(pBitmap, pBitmapMask, x, y, invert=0) {
static _AlphaMask := MCode("
(LTrim Join
1,x86:518b4424249983e2035355568d0c028b4424349983e203c1f902578d3402c1fe02837c2444000f85980000008b4424
308944243885c00f8e340100008d1c8d000000000faf4c24408d14b500000000895c24348b7424208b5c241c89542444034c
243c8d2c8e8b4c242c8b742434669085c97e3b8b7c24188bd52b7c24208bc38bf18b0c178d40043348fc8d520481e1ffffff
003348fc894afc83ee0175e38b4424388b4c242c8b5424448b74243403ee03da83e8018944243875b45f5e5d33c05b59c38b
5424308954241085d20f8e9c0000008b7c24208d04b5000000008b6c241c894424348d048d000000000faf4c24408b5c2434
894424388bf0034c243c8d048f8b4c242c894424440f1f400085c97e4b8b5c24188bd02bdf8bf58bf98b068d760425000000
ff8d5204b9000000ff2bc88b441afc25ffffff000bc8894afc83ef0175d98b4424448b5424108b4c242c8b5c24348b742438
8b7c242003c603eb83ea01894424448954241075a05f5e5d33c05b59c3,x64:48895c24084c8944241848895424105556574
1544155415641574883ec108b8424900000004c8bc248637424789983e2034c8be903c2c1f8024c63d08b842488000000998
3e20303c2c1f80283bc24a8000000004863c848890c240f85a60000008b8c248000000085c90f8e3a0100004c63bc24a0000
0004e8d3495000000004c63a424980000004533c9458bd9498bea498bd88bf94885f67e584c8b5424604b8d1439480faf142
4488bc3492bd34903d448c1e202492bd04c03d24e8d042a488bd60f1f4000660f1f840000000000418b0c003308488d40048
1e1ffffff003348fc41894c02fc4883ea0175e24c8b4424584c03dd4903de49ffc14883ef017594e9a30000008b842480000
00085c00f8e940000004c63b424a00000004533c94c63bc2498000000418bd94c8b642458498bea8bf84885f67e634c8b542
4604b8d1431480fafd14c8bdb4c2bda4d2bdf49c1e3024a8d043a4d2bdd4c8d0485000000004d03dc4d03c5488bd64d2bd54
38b04184d8d400425000000ffb9000000ff2bc8418b40fc25ffffff000bc843894c02fc4883ea0175d6488b0c244803dd49f
fc14883ef01758c33c0488b5c24504883c410415f415e415d415c5f5e5dc3
)")
Gdip_GetDimensions(pBitmap, w1, h1), Gdip_GetDimensions(pBitmapMask, w2, h2)
pBitmapNew := Gdip_CreateBitmap(w1, h1)
if !pBitmapNew
return -1
E1 := Gdip_LockBits(pBitmap, 0, 0, w1, h1, Stride1, Scan01, BitmapData1)
E2 := Gdip_LockBits(pBitmapMask, 0, 0, w2, h2, Stride2, Scan02, BitmapData2)
E3 := Gdip_LockBits(pBitmapNew, 0, 0, w1, h1, Stride3, Scan03, BitmapData3)
if (E1 || E2 || E3)
return -2
E := DllCall(_AlphaMask, "ptr", Scan01, "ptr", Scan02, "ptr", Scan03, "int", w1, "int", h1, "int", w2, "int", h2, "int", Stride1, "int", Stride2, "int", x, "int", y, "int", invert, "cdecl int")
Gdip_UnlockBits(pBitmap, BitmapData1), Gdip_UnlockBits(pBitmapMask, BitmapData2), Gdip_UnlockBits(pBitmapNew, BitmapData3)
return (E = "") ? -3 : pBitmapNew
}
The rendering and everything else relevant to Gdip_AlphaMask() function is in GuiDropFiles: subroutine and the function itself of course.
EDIT
Setting x and/or y (i assume offsets) in Gdip_AlphaMask() to anything other than 0 crashes AHK v1.1.