Image conversions and capturing with GDI+
I immediately thought: "Why use a third party DLL that has to be installed, when Windows now provide such facility with GDI+?".
GDI+ (gdiplus.dll) is provided by default in the latest versions of Windows, and can be installed freely on older versions.
So I started to look at the GDI+ API.
Ow! It wasn't so simple at all!
First problem: GDI+ is (AFAIK) really a bunch of pure C functions, and Microsoft created a C++ wrapper around them, to offer an object-oriented interface. It is nice if you use C++, some .NET language or other OO languages, but it is unusable in AutoHotkey, of course.
MS provides a "flat API", ie. access to the pure C functions, but under-document them to discourage its use...
Fortunately, Visual Basic (and PowerBASIC) users has the same problem, solved it, and provided some samples of flat API use.
Here comes the second problem: this interface might be flexible, but it is awful to use!
You have to convert, for some obscure reason, good Mime types like image/jpeg, to arcane GUIDs like {1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}, it abuses of pointers to pointers, opaque structures, and so on.
I had hard time converting the examples and even harder making them work!
Well, finally, I successed (otherwise I would be in the Ask for Help section...).
So, here is a simple script, converting a file of whatever read format supported by GDI+ (BMP, JPeg, Gif, PNG, Tiff, WMF, EMF, icon) to whatever write format it supports (BMP, JPG, GIF, PNG, TIF).
It uses the GDIplusWrapper.ahk file (wrapper around some GDI+ functions) which depends on the DllCallStruct.ahk library, which itself depends on BinaryEncodingDecoding.ahk...
[EDIT] Note: holomind already used this library to take screenshots. Great! For compactness, he gathered all necessary functions in one file.
I summarize here the functions to copy from DllCallStruct (BinaryEncodingDecoding is actually not used, here only because of generic inclusion of files in generic library files): GetUnicodeString, GetAnsiStringFromUnicodePointer (all strings in GDI+ are encoded in Unicode) and GetInteger/SetInteger. Just copy these functions in your copy of GDIplusWrapper and you have a nice, compact library. :-)
The test code was short, I used to just give it here, but it gets longer, so just download it:
TestGDIplus.ahk
I don't plan to extend much this library right now, but I am open to suggestions. I think it opens a whole world of image creation/alteration...
[EDIT 4] 1.04.000 -- 2006/10/02 (PL) -- Added GDIplus_FreeImage.
[EDIT 3] 1.03.000 -- 2006/09/15 (PL) -- Added GDIplus_CaptureScreenRectangle.
[EDIT 2] 1.02.000 -- 2006/08/22 (PL) -- Added GDIplus_LoadBitmapFromClipboard.
[EDIT 1] 1.01.000 -- 2006/08/21 (PL) -- Some fixes, support of more parameters.
The interface for parameters is changed.
I didn't found https://ahknet.autoh...plusWrapper.ahk
Dear PhiLho,
Are you not in town? The link is still not working! ...
Eagerly waiting.
Regards,
@Titan: If you're reading this .., Please let us know if there is a typo in the URL.
Sorry for the inconvenience, and tell me what you think of my little library.
Thanks you for bringing this up, I should have tested my links.
I tried it in Windows 2000 SP4. The script hinted me to put GDIPlus.dll in the Path.
Since I have WIN XP installed, I borrowed a copy of GDIPlus.dll and dropped it into the Scripts folder...
I tested with a BMP snapshot of my desktop 1024x768 file size: 2305 KB.
Oh my! Terrific speed ... I did not expect it to be fast! :shock:
I have to spend time with your code to understand the internals! How does this work fast?
Thanks for putting such a great effort .. and for sharing the wonderful code with us.
I don't plan to extend much this library right now, but I am open to suggestions. I think it opens a whole world of image creation/alteration...
What would I ask? or What should I request?
One thing is missing in this forum for a long time...
Saving Clipboard Bitmap data to a file..
Maybe, this is too much to ask .. but it will definitely supplement.
Please consider ..
Regards,
Easy: I let Windows (ie. the GDI+ DLL) to all the hard work! So it is as fast as a C program can be...I have to spend time with your code to understand the internals! How does this work fast?
Perhaps something like this Unicode Logo Generator... Yes, that's the kind of things that you can do with GDI+! And what I won't do, at least not soon...What would I ask? or What should I request?
Excellent idea, I will consider it.One thing is missing in this forum for a long time...
Saving Clipboard Bitmap data to a file..
By the way, I think someone above mentioned something about needing the DLL on XP. However, any system running XP or later shouldn't need a GDIplus DLL because the system already has one.
I think someone above mentioned something about needing the DLL on XP. However, any system running XP or later shouldn't need a GDIplus DLL because the system already has one.
I was that someone above!
I tested in Window 2000 - SP4 & so had to borrow GDIplus.dll from Windows XP (which is also installed in my computer.)
I mentioned it to alert Windows 2000 users.
Regards,
You read too fast ;-) It was on Win2k.I think someone above mentioned something about needing the DLL on XP.
I rewrite part of the code to add flexibility to define the encoding parameters. But it is a nightmare, because MS doesn't clearly define what parameters each encoder accepts (it just shows how to query these parameters from the encoders, and give some examples).
It can also be used to get some stats on images, like dimensions or content of EXIF fields, but it doesn't seems straightforward either.
It can also be used to get some stats on images, like dimensions or content of EXIF fields, but it doesn't seems straightforward either.
:shock: EXIF! Oooh! Sounds pretty interesting .. Regards,
Perhaps I should simplify a bit the interface. The GDIplus_GetEncoderCLSID function could be avoided by just providing the Mime type of the format to the functions. They would have to call internally the function to get the encoder CLSID each time, but I suppose it wouldn't be noticeable on a modern computer.
Likewise, calling GDIplus_InitEncoderParameters isn't very nice, but currently needed to allocate the right size of memory.
support to images on clipboard. File is updated, I give a small example.
Thanks for including support for Clipboard image data.
I downloaded the three .ahk's afresh as well as the example code.
Then took a snapshot of Destktop ( {PrintScreen} ) and tried the example - but I get an error
However, I am able to paste the image in any Image editor!
Please look into this.
Regards,
Edit: The first example also does not work for me. I get the following error:
Error in GdipCreateBitmapFromFile (2: InvalidParameter) 0
For some mysterious reason, the parameter to the GetClipboardData call went back to 8 (CF_DIB) instead of 2 (CF_BITMAP).I downloaded the three .ahk's afresh as well as the example code.
Then took a snapshot of Destktop ( {PrintScreen} ) and tried the example - but I get an error
Well, I corrected this, it should work now, thanks for reporting.
Well, it still works for me...The first example also does not work for me. I get the following error:
Error in GdipCreateBitmapFromFile (2: InvalidParameter) 0
You should try and change the tiffColorDepth value (if the problem comes from here, I haven't added an error locator... but I had similar problems here), maybe it depends on the image you chose to test.
Thanks for the fast response.
Things are perfect now.
However, Jpeg Image Quality is not satisfactory!
jpegQuality = 3
What will be the range for above variable?
I tried 10 .. I think the compression is heavy with too much of artifacts. :roll:
What am I missing?
Regards,
Edit: Oops sorry! I found that the range is 1-100
I suggest this: It will be better you change the value to 80 in you example.