How to perfectly fit any image on a fixed size picture control

Post your working scripts, libraries and tools
User avatar
SKAN
Posts: 363
Joined: 29 Sep 2013, 16:58

How to perfectly fit any image on a fixed size picture control

20 Jul 2017, 18:39

  • Image
Run the code and drop images ( including icons,DLL, EXE ) on the GUI

Code: Select all

#NoEnv
#SingleInstance, Force

Gui, Margin, 20, 20
OPTIONS := ( SS_BITMAP := 0xE ) | ( SS_CENTERIMAGE := 0x200 )
Gui, Add, Picture, w640 h480 %OPTIONS% Border hwndhwndPic vPicture
Gui, Show,, Image viewer - Just Drag N Drop
Return ;                                                     // End of auto-execute section //

GuiDropFiles:
  File := StrSplit( A_GuiEvent, "`n" ).1
  hBM := LoadPicture( File )
  IfEqual, hBM, 0, Return

  BITMAP := getHBMinfo( hBM )                                ; Extract Width andh height of image 
  New := ScaleRect( BITMAP.Width, BITMAP.Height, 640, 480 )  ; Derive best-fit W x H for source image 

  DllCall( "DeleteObject", "Ptr",hBM )                       ; Delete Image handle ...         
  hBM := LoadPicture( File, "GDI+ w" New.W . " h" . New.H )  ; ..and get a new one with correct W x H

  GuiControl,, Picture,  *w0 *h0 HBITMAP:%hBM% 
Return  

GuiClose:
GuiEscape:
 ExitApp
   
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

getHBMinfo( hBM ) {
Local SzBITMAP := ( A_PtrSize = 8 ? 32 : 24 ),  BITMAP := VarSetCapacity( BITMAP, SzBITMAP )       
  If DllCall( "GetObject", "Ptr",hBM, "Int",SzBITMAP, "Ptr",&BITMAP )
    Return {  Width:      Numget( BITMAP, 4, "UInt"  ),  Height:     Numget( BITMAP, 8, "UInt"  ) 
           ,  WidthBytes: Numget( BITMAP,12, "UInt"  ),  Planes:     Numget( BITMAP,16, "UShort") 
           ,  BitsPixel:  Numget( BITMAP,18, "UShort"),  bmBits:     Numget( BITMAP,20, "UInt"  ) }
}       
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

ScaleRect( SW, SH, TW, TH, Upscale := 0 ) { ; By SKAN | Created: 19-July-2017 | Topic: goo.gl/  

Local  SAF := SW/SH, TAF := TW/TH ; Aspect ratios of Source and Target
  Return  ( !Upscale and SW <= TW and SH <= TH ) ? {W: SW, H: SH}  
      :   ( SAF < TAF ) ? { W: Floor( ( TW / TAF ) * SAF ), H: TH}
      :   ( SAF > TAF ) ? { W: TW, H: Floor( ( TH / SAF ) * TAF )} 
      :   { W: TW, H: TH }
}
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
scriptor2016
Posts: 493
Joined: 21 Dec 2015, 02:34

Re: How to perfectly fit any image on a fixed size picture control

20 Jul 2017, 23:58

Line 12 returns an error:

Call to non existent function.
hBM := LoadPicture( File )

where can we get that function?
User avatar
jeeswg
Posts: 6469
Joined: 19 Dec 2016, 01:58
Location: UK

Re: How to perfectly fit any image on a fixed size picture control

21 Jul 2017, 00:27

homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
carno
Posts: 196
Joined: 20 Jun 2014, 16:48

Re: How to perfectly fit any image on a fixed size picture control

25 Jul 2017, 10:30

Works perfectly!
AutoHotkey : v1.1.24.04 Unicode 32-bit (Installed)
SystemOS : WIN_XP 32-bit Service Pack 2 v5.1.2600 (WIN32_NT)
User avatar
Drugwash
Posts: 687
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania

Re: How to perfectly fit any image on a fixed size picture control

28 Jul 2017, 09:37

AHK is awful at resizing very large images to very small sizes. (example)

Does anybody know of a fast and efficient resizing algorithm usable with AHK that produces results similar to the right picture in the example? (resized with FastStone Image Viewer, using default Lanczos algorithm - most notable difference is the title in white)
I've deleted my CloudMe account because of GDPR - the now legal base for privacy invasion and data theft.
gwarble
Posts: 334
Joined: 30 Sep 2013, 15:01

Re: How to perfectly fit any image on a fixed size picture control

28 Jul 2017, 11:16

its a limitation of GDI/GDI+ from what I understand, you have to roll your own
https://www.codeproject.com/Articles/11 ... erform-GDI
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
User avatar
SKAN
Posts: 363
Joined: 29 Sep 2013, 16:58

Re: How to perfectly fit any image on a fixed size picture control

29 Jul 2017, 17:33

gwarble wrote:its a limitation of GDI/GDI+ from what I understand, you have to roll your own
https://www.codeproject.com/Articles/11 ... erform-GDI
Thanks for the link.
There is a 32bit DLL based on that code
Plain C Resampling DLL : https://www.codeproject.com/Articles/22 ... mpling-DLL

Wish AHK have this incorporated.. Not sure if CPOL License is compatible with GPL v2

:)
User avatar
SKAN
Posts: 363
Joined: 29 Sep 2013, 16:58

Re: How to perfectly fit any image on a fixed size picture control

29 Jul 2017, 17:37

Drugwash wrote:Does anybody know of a fast and efficient resizing algorithm usable with AHK that produces results similar to the right picture in the example? (resized with FastStone Image Viewer, using default Lanczos algorithm - most notable difference is the title in white)
Here we go:
  • Image

Code: Select all

#NoEnv
#Warn
#SingleInstance, Force
SetWorkingDir %A_ScriptDir% 

If ! FileExist( "logo.png" )
URLDownloadToFile, https://autohotkey.com/boards/styles/simplicity/theme/images/logo.png, logo.png
 
DllCall( "LoadLibrary", "Str", "Resample.dll" )

BELL              := 0x00000000
BOX               := 0x00000001
CATMULLROM        := 0x00000002
COSINE            := 0x00000003
CUBICCONVOLUTION  := 0x00000004
CUBICSPLINE       := 0x00000005
HERMITE           := 0x00000006					
LANCZOS3          := 0x00000007
LANCZOS8          := 0x00000008
MITCHELL          := 0x00000009
QUADRATIC         := 0x0000000A
QUADRATICBSPLINE  := 0x0000000B
TRIANGLE          := 0x0000000C


hBM1 := LoadPicture( "Logo.png", "GDI+")
hBM2 := DllCall( "Resample\CreateResampledBitmap", "UInt",DllCall( "GetDC", "UInt", 0 )
                , "UInt",hBM1, "UInt",300, "UInt",45, "UInt",LANCZOS3 )


Gui, Font, S10, Calibri
Gui, Add, Text,    xm  ym,             Resampled by AHK
Gui, Add, Picture, xm  y+5   w300 h45, Logo.png           ; AHK will use GDI+ for PNG

Gui, Add, Text,    xm  Y+10          , Resampled by DLL
Gui, Add, Picture, xm  y+5   w300 h45, HBITMAP:%hBM2%

Gui, Show,, Resampling
Attachments
ResampleDLL.zip
(53.8 KiB) Downloaded 75 times
User avatar
Drugwash
Posts: 687
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania

Re: How to perfectly fit any image on a fixed size picture control

29 Jul 2017, 19:15

Thank you both. Few years ago I actually read that article but the code was (and still is) unusable for me with AHK Basic.
I'll test the Resample library soon; now it's 3AM and gotta go to sleep.
However until now I fought with gdiplus and found out it can produce higher quality output when appropriate settings are made.
Also certain versions of gdiplus (currently I have 11 versions for testing) may produce different results with the same settings.
Contrary to opinions found on the web, gdiplus v6.0 does work in Win9x and effects are applied correctly (at least on my system). Just tested blur minutes ago.
I'll be back with details and screenshots.
I've deleted my CloudMe account because of GDPR - the now legal base for privacy invasion and data theft.
arcticir
Posts: 565
Joined: 17 Nov 2013, 11:32

Re: How to perfectly fit any image on a fixed size picture control

29 Jul 2017, 23:00

Using GDI to draw controls has a nice effect.

Image
User avatar
SKAN
Posts: 363
Joined: 29 Sep 2013, 16:58

Re: How to perfectly fit any image on a fixed size picture control

30 Jul 2017, 01:53

arcticir wrote:Using GDI to draw controls has a nice effect.
Looks nice... Post some code, please!.
arcticir
Posts: 565
Joined: 17 Nov 2013, 11:32

Re: How to perfectly fit any image on a fixed size picture control

30 Jul 2017, 02:21

I did not save the test code, so I rewrote one. It needed H2.

Code: Select all

gui:=GuiCreate()
k:=GuiCreate("+E0x80000 0x10000000 +Parent" gui.hwnd)
pic:="Z:\logo.png"
GdipCreateBitmapFromFile(&PIC,getvar(pBitmap:=0))
GdipGetImageDimension(pBitmap,__w:=getvar(width:=0), __h:=getvar(height:=0))
width:=width:=NumGet(__w,"Float")
height:=height:=NumGet(__h,"Float")
VarSetCapacity(bi, 40, 0),NumPut(300,bi,4),NumPut(45,bi,8),NumPut(40, bi, 0),NumPut(1,bi,12,"ushort"),NumPut(0, bi, 16),NumPut(32, bi, 14, "ushort")
hbm:=hbm := CreateDIBSection( hdc:=GetDC(), &bi),ReleaseDC(0,hdc)
hdc := CreateCompatibleDC(),obm := SelectObject(hdc, hbm)
GdipCreateFromHDC(hdc,getvar(G:=0)),GdipSetInterpolationMode(G, 7)
GdipDrawImageRectRectI(G,pBitmap,0,0,300,45,0,0,width,height,2)
pt:=Struct("x,y")
pt.x:=10,pt.y:=0
UpdateLayeredWindow(k.hwnd,0,pt[],getvar(temp1:=300|45<<32),hdc, getvar(temp2:=0),0,getvar(temp3:=255<<16|1<<24),2)
gui.show("w400 h120")
Return
HotKeyIt
Posts: 1850
Joined: 29 Sep 2013, 18:35
Contact:

Re: How to perfectly fit any image on a fixed size picture control

30 Jul 2017, 03:51

I have optimized the code above for AHK_H v2 a little bit ;)

Code: Select all

(gui:=GuiCreate()).OnEvent("Close","ExitApp")
k:=GuiCreate("+E0x80000 0x10000000 +Parent" gui.hwnd)
GdiplusStartup(getvar(pToken:=0),(si:=Struct("UINT GdiplusVersion;PTR DebugEventCallback;BOOL SuppressBackgroundThread;BOOL SuppressExternalCodecs",{GdiplusVersion:1}))[])
GdipCreateBitmapFromFile(&"G:\logo.png",getvar(pBitmap:=0))
GdipGetImageDimension(pBitmap, getvar(width:=0), getvar(height:=0))
BITMAPINFOHEADER:="DWORD biSize;LONG biWidth;LONG biHeight;WORD biPlanes;WORD biBitCount;DWORD biCompression;DWORD biSizeImage;LONG biXPelsPerMeter;LONG biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;"
bi:=Struct(BITMAPINFOHEADER,{biSize:sizeof(BITMAPINFOHEADER),biWidth:300,biHeight:45,biPlanes:1,biBitCount:32})
hbm := CreateDIBSection( hdc:=GetDC(), bi[]),ReleaseDC(0,hdc)
hdc := CreateCompatibleDC(),obm := SelectObject(hdc, hbm)
GdipCreateFromHDC(hdc,getvar(G:=0)),GdipSetInterpolationMode(G, 7)
GdipDrawImageRectRectI(G,pBitmap,0,0,300,45,0,0,Cast("UInt",width,"Float"),Cast("Uint",height,"Float"),2)
UpdateLayeredWindow(k.hwnd,0,(pt:=Struct("x,y",{x:10}))[],getvar(temp1:=300|45<<32),hdc, getvar(temp2:=0),0,getvar(temp3:=255<<16|1<<24),2)
gui.show("w320 h50")
Return
User avatar
Drugwash
Posts: 687
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania

Re: How to perfectly fit any image on a fixed size picture control

30 Jul 2017, 14:37

What language is that above…? I can't read it.
Honestly, that's not the AHK I once knew. But forget that.

The only way I could get XP to actually use the specific version of gdiplus I wanted was to modify the AHK exe manifest. 98SE has no shame in loading and using whatever library I feed it. Unfortunately 98 has a problem in manipulating and displaying the alpha channel. Not that it matters for any of you.

The highest "official" version of gdiplus on my XP is 5.2.6002.23846 and although it's branded "vistasp2" it does not have the effects-related API. Those come only with v6.0+ (or as some call it v1.1). Such version can be found in Power Point Viewer, for one or in some newer version of MS Office (Office 13 might have a newer gdiplus 6 that PPViewer).

Enough talking, here's the old-fashioned code; if you get a crash or last image isn't blurred then you need to coerce your AHK into using a specific gdiplus:
code+screenshots (~2.8MB)

Screenshots are in the package because the board resizes images and destroys their quality. Both screenshots were captured in 98SE, the one using gdiplus 5.2 can't create blur on last image but image quality for InterpolationMode 5 is visibly better than with v6 (compare the white text).
I've deleted my CloudMe account because of GDPR - the now legal base for privacy invasion and data theft.
User avatar
SKAN
Posts: 363
Joined: 29 Sep 2013, 16:58

Re: How to perfectly fit any image on a fixed size picture control

31 Jul 2017, 17:00

Thanks arcticir and HotKeyIt. :)

@HotKeyIt

Doesn't AHK use GDI+ Smoothing / Interpolation settings?!
Or does it use GDI+ only to open the image and then use CopyImage() to resize?
Please confirm.
User avatar
SKAN
Posts: 363
Joined: 29 Sep 2013, 16:58

Re: How to perfectly fit any image on a fixed size picture control

31 Jul 2017, 17:59

HotKeyIt wrote:As far as I can see it uses CopyImage to resize
Ah.. I see.. Disappointing . :(
Thanks for the confirmation.
User avatar
SKAN
Posts: 363
Joined: 29 Sep 2013, 16:58

Re: How to perfectly fit any image on a fixed size picture control

01 Aug 2017, 02:11

Drugwash wrote:here's the old-fashioned code; if you get a crash or last image isn't blurred then you need to coerce your AHK into using a specific gdiplus:
code+screenshots (~2.8MB)
Excellent! Thanks for sharing Drugwash. :)
Can you explain what the last parameter does?. Won't 0xFFFFFFFF mess up a PNG with semitransparent pixels?

Code: Select all

		DllCall("gdiplus\GdipCreateHBITMAPFromBitmap"
			, Ptr, pB
			, PtrP, hBmp%A_Index%
			, "Int", 0xFFFFFFFF)
User avatar
jNizM
Posts: 2422
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: How to perfectly fit any image on a fixed size picture control

01 Aug 2017, 03:11

Code: Select all

GdipCreateHBITMAPFromBitmap(GpBitmap* bitmap, HBITMAP* hbmReturn, ARGB background)

bitmap      -> [in]  Pointer to the Bitmap object.
hbmReturn   -> [out] Pointer to an HBITMAP that receives a handle to the GDI bitmap.
background  -> [in]  ARGB color that specifies the background color. This parameter is ignored if the bitmap is totally opaque.
[AHK] 1.1.30.03 x64 Unicode | [WIN] 10 Pro (Version 1903) x64 | [GitHub] Profile
Donations are appreciated if I could help you
User avatar
Drugwash
Posts: 687
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania

Re: How to perfectly fit any image on a fixed size picture control

01 Aug 2017, 03:18

@ SKAN: You're welcome. :)

Honestly, part of the code I found here and there on the web, didn't get documented much about all API.
In regard to the one you mentioned I don't think it breaks anything, i tried the same script with logo.png (same AHK logo used in yours and arcticir's examples) and it displayed it properly in XP (apart from bad aspect ratio); only 98 has problems (transparent background was displayed blue instead).
I've deleted my CloudMe account because of GDPR - the now legal base for privacy invasion and data theft.

Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 39 guests