ImageMagick API Wrapper - DllCall help Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
RazorHalo
Posts: 45
Joined: 21 Dec 2015, 21:23

ImageMagick API Wrapper - DllCall help

10 May 2022, 01:17

I'm trying to write a wrapper for the ImageMagick C API but have hit a block.

I don't think I'm doing the DllCall correctly for the MagickReadImage method.
https://imagemagick.org/api/magick-image.php#MagickReadImage
it is defined as this in the documentation:
MagickBooleanType MagickReadImage(MagickWand *wand,const char *filename)
and my DllCall looks like this:
DllCall("Core_RL_MagickWand_.dll\MagickReadImage", "Ptr", wand, "char", &filename, "Int")

I should be getting a return value of 1 if the call succeeds, but no matter what I have tried I can only get it to return 0

If anybody could help me understand the correct way to pass the filename, which is I think where I'm going wrong because the exception that it generates is 435 which is an error in reading the file.
https://imagemagick.org/script/exception.php

ImageMagick can be found here https://imagemagick.org/script/download.php#windows

Here is my code so far

Code: Select all

#NoEnv
#SingleInstance Force
SetBatchLines, -1

dir := A_ScriptDir "\"
inFile := "test2b.jpg"

If !(IM := New MagickWandAPI)
   ExitApp

Wand := IM.NewMagickWand()
msgbox % "IsMagickWand: " IM.IsMagickWand(Wand)
msgbox % "IsMagickWandInstantiated: " IM.IsMagickWandInstantiated()
Msgbox % "MagickReadImage: " IM.MagickReadImage(Wand, dir infile)


Msgbox % "MagickGetException: " IM.MagickGetException(Wand, Severity)
 
;Terminate the MagickWand environment.
IM := ""

Return


Class MagickWandAPI {

	; ===================================================================================================================
	; META FUNCTION __New
	; Load and initialize Core_RL_MagickWand_.dll which is supposed to be in the sript's folder.
	; Parameters:    LibPath  - Optional: Absolute path of Core_RL_MagickWand_.dll
	; ===================================================================================================================
	__New(LibPath := "") {
		Static LibMagickWand := A_ScriptDir . "\Core_RL_MagickWand_.dll"
		; Do not instantiate instances!
		If (This.Base.Base.__Class = "MagickWandAPI") {
			MsgBox, 16, MagickWand Error!, You must not instantiate instances of MagickWand!
			Return False
		}
		; Load Core_RL_MagickWand_.dll
		If (LibPath)
			LibMagickWand := LibPath
		If !(MagickWandModule := DllCall("Kernel32.dll\LoadLibrary", "Str", LibMagickWand, "UPtr")) {
			If (A_LastError = 126) ; The specified module could not be found
				MsgBox, 16, MagickWand Error!, Could not find %LibMagickWand%!
			Else {
			ErrCode := A_LastError
				VarSetCapacity(ErrMsg, 131072, 0) ; Unicode
				DllCall("FormatMessage", "UInt", 0x1200, "Ptr", 0, "UInt", ErrCode, "UInt", 0, "Str", ErrMsg, "UInt", 65536, "Ptr", 0)
				MsgBox, 16, MagickWand Error!, % "Could not load " . LibMagickWand . "!`n"
										. "Error code: " . ErrCode . "`n"
										. ErrMsg
			}
			Return False
		}
		This.Module := MagickWandModule
		This.MagickWandGenesis()
	}
	
	; ===================================================================================================================
	; META FUNCTION __Delete
	; Free ressources
	; ===================================================================================================================
	__Delete() {
		This.MagickWandTerminus()
		If (This.Module)
			DllCall("Kernel32.dll\FreeLibrary", "Ptr", This.Module)
	}

	IsMagickWand(wand) {
		; https://imagemagick.org/api/magick-wand.php#IsMagickWand
		; MagickBooleanType IsMagickWand(const MagickWand *wand)
		Return DllCall("Core_RL_MagickWand_.dll\IsMagickWand", "Ptr", Wand, "Int")
	}
	
	IsMagickWandInstantiated() {
		; https://imagemagick.org/api/magick.php#IsMagickWandInstantiated
		; MagickBooleanType IsMagickWandInstantiated(void)
		Return DllCall("Core_RL_MagickWand_.dll\IsMagickWandInstantiated", "Int")
	}

	MagickGetException(Wand, Severity) {
		; https://imagemagick.org/api/magick-wand.php#MagickGetException
		; char *MagickGetException(const MagickWand *wand,ExceptionType *severity)
		DllCall("Core_RL_MagickWand_.dll\MagickGetException", "Ptr", Wand, "Ptr*", Severity)
		Return Severity
	}

	MagickReadImage(wand, filename) {
		; https://imagemagick.org/api/magick-image.php#MagickReadImage
		; MagickBooleanType MagickReadImage(MagickWand *wand,const char *filename)
		OutputDebug, % Filename
		Return DllCall("Core_RL_MagickWand_.dll\MagickReadImage", "Ptr", wand, "char", &filename, "Int")
	}
	
	MagickWandGenesis() {
		; https://imagemagick.org/api/magick-wand.php#MagickWandGenesis
		; MagickWandGenesis() initializes the MagickWand environment.
		; void MagickWandGenesis(void)
		Return DllCall("Core_RL_MagickWand_.dll\MagickWandGenesis", "Int")
	}	
	
	MagickWandTerminus() {
		; https://imagemagick.org/api/magick-wand.php#MagickWandTerminus
		; MagickWandTerminus() terminates the MagickWand environment.
		; void MagickWandTerminus(void)
		Return DllCall("Core_RL_MagickWand_.dll\MagickWandTerminus", "Int")
	}

	NewMagickWand() {
		; https://imagemagick.org/api/magick-wand.php#NewMagickWand
		; NewMagickWand() returns a wand required for all other methods in the API. 
		; A fatal exception is thrown if there is not enough memory to allocate the wand. 
		; Use DestroyMagickWand() to dispose of the wand when it is no longer needed.
		; MagickWand *NewMagickWand(void)
		Return DllCall("Core_RL_MagickWand_.dll\NewMagickWand", "Ptr")
	}
}
Or if someone happens to have a copy of the wrapper already written by Thrawn from this post in the old forum that would also be helpful.
I have spent many hours looking for it in every archive and lost script thread I can find but have had no luck.
https://www.autohotkey.com/board/topic/40797-imagemagick-wrapper-stdlib-r1-2009-05-16/

Thanks!!
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: ImageMagick API Wrapper - DllCall help  Topic is solved

10 May 2022, 02:50

Code: Select all

Return DllCall("Core_RL_MagickWand_.dll\MagickReadImage", "Ptr", wand, "char", &filename, "Int")
should be

Code: Select all

Return DllCall("Core_RL_MagickWand_.dll\MagickReadImage", "Ptr", wand, "AStr", filename, "Int")
User avatar
RazorHalo
Posts: 45
Joined: 21 Dec 2015, 21:23

Re: ImageMagick API Wrapper - DllCall help

10 May 2022, 14:38

Thanks Swagfag! That is what I needed.

How would I tell that the data type for the DllCall should have been Astr?
The documentation for ImageMagick listed that parameter as char and using this utility by jNizM viewtopic.php?t=7342
I would have thought that the data type in AHK would have also been char.
Char data type.jpg
Char data type.jpg (40.98 KiB) Viewed 657 times
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: ImageMagick API Wrapper - DllCall help

11 May 2022, 18:50

actually u could have used "char", &filename as well, but that would have only worked if u ran the script with the ahkANSI32.exe

why would u know u had to use AStr? because by convention if the type is a char* (because thats what it is according to Imagemagics docs - a pointer to char; not simply char - ie a single char passed by value, as u seem to think it is), and u arent passing a string length or a byte count or a char count to the function (which u arent, since it isnt defined that way), it is understood that the function expects a null-terminated ANSI C string. in other words, an array of char with a nullbyte at the end of it. this means, if u incorrectly pass a UNICODE string instead, since the characters ure likely to find contained in a file path (ie the ones from the Basic Latin and the Latin-1 Supplement set) are 2 byte sequences in the range 0x0000:0x00FF (ie each character's second byte is a nullbyte), the function would only ever attempt to read the first character of the string and then stop (because it encountered a nullbyte). hence, the function interprets this as an invalid filepath. hence, the function returns a failure code
User avatar
RazorHalo
Posts: 45
Joined: 21 Dec 2015, 21:23

Re: ImageMagick API Wrapper - DllCall help

11 May 2022, 23:12

Excellent information! I see now why it would be that way. again, much appreciated. Thank you for the detail.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot] and 122 guests