Get the height / width of an image - to an array (object) Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Albireo
Posts: 1776
Joined: 16 Oct 2013, 13:53

Get the height / width of an image - to an array (object)

01 Oct 2020, 14:12

Intending to display an image with a AHK-GUI
Since I do not know how to scale an image with AHK GUI (I think it's impossible), I need to know the width and height of the image to be displayed to get structure on the entire GUI.

One way to get the size is to use IrfanView - Command line
Another way is to use gdip_all
Maybe there are better ways to do this on?

My wish is to create an object (selLogo) that contains information about the image. (eg. selLogo.name, selLogo.width, selLogo.height ...)
Tried to write a program below, but failed (in a way)
(selLogo is changed after the function call getImageSize(selLogo.name) and the selLogo.name is gone!)

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force

#include gdip_all.ahk  ;  If it is not in your lib http://www.autohotkey.com/forum/topic32238.html

selLogo := []

FileSelectFile Logo, 3, C:\Users...\images, Select a imagefile, Images (*.jpg)
selLogo.name := Logo

selLogo := getImageSize(selLogo.name)
MsgBox ,, %A_ScriptName% - Row %A_LineNumber%, % "- " selLogo.Count() "`n- " selLogo.name "`n`nheight .: " selLogo.height "`nwidth .: " selLogo.width

ExitApp

getImageSize(imageFile)
{	; https://autohotkey.com/board/topic/61076-get-image-height-property-from-file-property-details/
	; lib .: gdip_all.ahk
	aImage := []
	
	If !pToken := Gdip_Startup()
	{	MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
		ExitApp
	}
	
	pBitmap := Gdip_CreateBitmapFromFile(imageFile)
	Gdip_GetDimensions(pBitmap, width, height)
	Gdip_DisposeImage(pBitmap)
	Gdip_Shutdown(pToken)
	
	aImage.width := width
	aImage.height := height

	Return % aImage
}
User avatar
mikeyww
Posts: 27198
Joined: 09 Sep 2014, 18:38

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 14:29

GUI does scale. You can specify one dimension, and it will adjust the other.
To shrink or enlarge the image while preserving its aspect ratio, specify -1 for one of the dimensions and a positive number for the other. For example, specifying w200 h-1 would make the image 200 pixels wide and cause its height to be set automatically.
A little trick to find an image's size is below.

Code: Select all

imgWidth(img, ByRef height) { ; Get image's dimensions
 If FileExist(img) {
  GUI, Add, Picture, hwndpic, %img%
  ControlGetPos,,, width, height,, ahk_id %pic%
  Gui, Destroy
 } Else height := width := 0
 Return width
}
teadrinker
Posts: 4370
Joined: 29 Mar 2015, 09:41
Contact:

Re: Get the height / width of an image - to an array (object)  Topic is solved

01 Oct 2020, 15:29

Code: Select all

filePath := "D:\MyImage.jpg"
size := GetImageSize(filePath)
MsgBox, % size.W . "`n" size.H

GetImageSize(imageFilePath) {
   if !hBitmap := LoadPicture(imageFilePath, "GDI+")
      throw "Failed to load the image"
   VarSetCapacity(BITMAP, size := 4*4 + A_PtrSize*2, 0)
   DllCall("GetObject", "Ptr", hBitmap, "Int", size, "Ptr", &BITMAP)
   DllCall("DeleteObject", "Ptr", hBitmap)
   Return { W: NumGet(BITMAP, 4, "UInt"), H: NumGet(BITMAP, 8, "UInt") }
}
User avatar
mikeyww
Posts: 27198
Joined: 09 Sep 2014, 18:38

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 15:35

Very nice as well! It's handy to have the dimensions in an array.
Albireo
Posts: 1776
Joined: 16 Oct 2013, 13:53

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 15:55

Thank you! (Nice solution)

My result

Code: Select all

#NoEnv  		; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input 			; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  	; Ensures a consistent starting directory.
#SingleInstance force

Logo := []

FileSelectFile LogoName, 3, C:\Users\...\images, Select a PDF-file, Images (*.jpg)
Logo.name := LogoName

Logo.width := imgWidth(Logo.name, height)
Logo.height := height

MsgBox ,, %A_ScriptName% - Row %A_LineNumber%, % "Logo.name .: " Logo.name "`nLogo.height .: " Logo.height "`nLogo.width .: " Logo.width
ExitApp

imgWidth(img, ByRef height) { ; Get image's dimensions
 If FileExist(img) {
  GUI, Add, Picture, hwndpic, %img%
  ControlGetPos,,, width, height,, ahk_id %pic%
  Gui, Destroy
 } Else height := width := 0
 Return width
}
About scale GUI (thank you! - again!)
a scale test of an image
User avatar
mikeyww
Posts: 27198
Joined: 09 Sep 2014, 18:38

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 16:04

Good! Here's the array version in case you like that.

Code: Select all

FileSelectFile LogoName, 3, C:\Users\...\images, Select an image file, Images (*.jpg; *.tif; *.bmp; *.jpeg; *.png; *.gif; *.tiff)
If FileExist(LogoName)
 MsgBox, 64, %A_ScriptName% - Row %A_LineNumber%
  , % Format("Name:  {}`nSize:    {} x {}", LogoName, (logo := imgSize(LogoName)).w, logo.h)
ExitApp

imgSize(img) { ; Get image's dimensions
 If FileExist(img) {
  GUI, Add, Picture, hwndpic, %img%
  ControlGetPos,,, width, height,, ahk_id %pic%
  Gui, Destroy
 }
 Return {w: width, h: height}
}
Last edited by mikeyww on 01 Oct 2020, 16:12, edited 1 time in total.
Albireo
Posts: 1776
Joined: 16 Oct 2013, 13:53

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 16:05

the solution from @teadrinker
(easy to handle with an array)

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force

Logo := []

FileSelectFile filePath, 3, A_ScripDir "\..", Select a PDF-file, Images (*.jpg)

size := GetImageSize(filePath)
MsgBox, % size.W . "`n" size.H

GetImageSize(imageFilePath) {
   if !hBitmap := LoadPicture(imageFilePath, "GDI+")
      throw "Failed to load the image"
   VarSetCapacity(BITMAP, size := 4*4 + A_PtrSize*2, 0)
   DllCall("GetObject", "Ptr", hBitmap, "Int", size, "Ptr", &BITMAP)
   DllCall("DeleteObject", "Ptr", hBitmap)
   Return { W: NumGet(BITMAP, 4, "UInt"), H: NumGet(BITMAP, 8, "UInt") }
}
Albireo
Posts: 1776
Joined: 16 Oct 2013, 13:53

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 16:09

mikeyww wrote:
01 Oct 2020, 16:04
Good! Here's the array version in case you like that.
...
Also works well (you are good at handling Format())
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 16:14

Stolen from here: http://autohotkey.com/board/topic/56987-com-object-reference-autohotkey-v11/?p=387238 (by sbc/@sbcglobal?)

Code: Select all

SplitPath,% USERPROFILE "\Pictures\DunningKruger.jpg", FileName, DirPath,

objShell		:= ComObjCreate("Shell.Application")
objFolder		:= objShell.NameSpace(DirPath)								; set the directry path
objFolderItem	:= objFolder.ParseName(FileName)							; set the file name
MsgBox % objFolder.GetDetailsOf(objFolderItem, 31)							; 31	= 'width x height'
MsgBox % StrSplit(objFolder.GetDetailsOf(objFolderItem, 176), A_Space).1	; 176	= '<width> Pixel'
MsgBox % StrSplit(objFolder.GetDetailsOf(objFolderItem, 178), A_Space).1	; 178	= '<height> Pixel'
Here limited to width & height. BTW, the original script delivers 29 image properties (and its descriptions) for my image :)
User avatar
mikeyww
Posts: 27198
Joined: 09 Sep 2014, 18:38

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 16:19

Very impressive!

I compared times of GUI vs. ComObj. Perhaps as expected, larger images favored ComObj, whereas smaller images favored GUI. On some runs, the GUI time measured was zero!

38 x 42 image: 78 ms for ComObj, 31 ms for GUI

676 x 1200 image: 78 ms for ComObj, 125 ms for GUI
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 17:09

I've edited the code to skip the loop that would check for 283 optional properties/items and directly access the items that are of interest instead: width&height/width/height
That way ComObj is acting instantaneously (at least for me, myself and I).
For testing, I used/downloaded this photo: https://upload.wikimedia.org/wikipedia/commons/4/41/Sunflower_from_Silesia2.jpg (2434x1697) = 31/32ms and if using SetBatchLines, -1 = 15/16ms.
teadrinker
Posts: 4370
Joined: 29 Mar 2015, 09:41
Contact:

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 17:23

The last code doesn't actually get the picture size, it just reads metadata and shows what is wriiten there.
User avatar
mikeyww
Posts: 27198
Joined: 09 Sep 2014, 18:38

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 17:31

Sunflower with default SetBatchLines:

ComObj: 78 ms; wins again!

GUI: 530 ms
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 17:36

@teadrinker Valid point. I've edited/shrank the test image. The script returned the new measurements correctly. So ...? :think:
teadrinker
Posts: 4370
Joined: 29 Mar 2015, 09:41
Contact:

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 18:18

Why not? It shows what you can see in file properties. 176 and 178 doesn't show width and hight for me, they show Folder Name and Location.
User avatar
mikeyww
Posts: 27198
Joined: 09 Sep 2014, 18:38

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 19:52

A puzzle.

Code: Select all

img = [pathToImage]
size := imgSize(img)
x := 10
n := size.w
sum := x + n
MsgBox, x='%x%' n='%n%' sum='%sum%'
ExitApp

imgSize(img) {
 SplitPath, img, fn, dir
 objShell := ComObjCreate("Shell.Application")
 objFolder := objShell.NameSpace(dir)
 objFolderItem := objFolder.ParseName(fn)
 scale := StrSplit(objFolder.GetDetailsOf(objFolderItem, 31), " x ")
 Return {w: scale.1, h: scale.2}
}
Yields:

x='10' n='‪58' sum=''

The GUI version does not have this issue. If I hard code the GetDetailsOf with something like "58 x 9", it works. It's especially bizarre because both x and n are correct. Further: Round(n) is 0. It's like it's showing "58", but it's not really 58; it's a different character set.

What is happening with the blank sum?
User avatar
mikeyww
Posts: 27198
Joined: 09 Sep 2014, 18:38

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 20:44

Fixed.

Code: Select all

imgSize(img) {
 SplitPath, img, fn, dir
 objShell := ComObjCreate("Shell.Application")
 objFolder := objShell.NameSpace(dir)
 objFolderItem := objFolder.ParseName(fn)
 scale := StrSplit(RegExReplace(objFolder.GetDetailsOf(objFolderItem, 31), ".(.+).", "$1"), " x ")
 Return {w: scale.1, h: scale.2}
}
Interesting to see the size flanked by control codes: ASCII 8234 and 8236.
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: Get the height / width of an image - to an array (object)

01 Oct 2020, 23:58

mikeyww wrote:
01 Oct 2020, 16:19
I compared times of GUI vs. ComObj. Perhaps as expected, larger images favored ComObj, whereas smaller images favored GUI. On some runs, the GUI time measured was zero!

38 x 42 image: 78 ms for ComObj, 31 ms for GUI

676 x 1200 image: 78 ms for ComObj, 125 ms for GUI
 
Fastest: IsPicture()
BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Get the height / width of an image - to an array (object)

02 Oct 2020, 03:40

@teadrinker
176 and 178 doesn't show width and hight for me, they show Folder Name and Location.
My output:
... what sbc's script is doing.
... after removing the condition. So in both cases it'll return 'Breite'/'width' at 176 and 'Höhe'/'height' at 178
That's WIS + WIG . :shifty:

@mikeyww - Confirmed that this sporadically has returned '0' for the same image + the output (if copied to clipboard, see my spoilered examples above) is showing/contains those characters, interestingly only for a few of its properties?!
User avatar
mikeyww
Posts: 27198
Joined: 09 Sep 2014, 18:38

Re: Get the height / width of an image - to an array (object)

02 Oct 2020, 06:44

Thanks for those test results and output!

I tested IsPicture(). It was initially impressive with a run time of zero ms. On further testing, it retrieved the wrong dimensions for one of my JPG files, so I'm not able to use it.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: CodeKiller and 202 guests