MagickWand portability

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
Post Reply
*void

MagickWand portability

Post by *void »

The core API, in earlier incarnations, was said to be "C source compatible", and not designed to be portable to other languages. I assume this still to be true. No problem.

The MagickWand API, however, is (mostly) extremely portable at the compiled level. It seems to be architected with that specific intent. Yet, there seem to be a handful of (basically unnecessary) oddities that diminish its portability.

Cases in point:
1) MagickPingImageBlob, MagickGetImageBlob, MagickReadImageBlob, MagickGetImageProfile, MagickSetImageProfile, MagickRemoveImageProfile, MagickProfileImage methods all define arguments of type size_t. I find it strange that this, fundamentally C, environment-dependent, type appears in an API presumably designed specifically for execution time portability. I would expect MagickWand API argument types to all be declared in the distributed MagickWand headers, in an easily portable form.

I am guessing size_t is actually unsigned long in the distributed Windows binary (Q8 specifically), since in the MagickPingImageBlob method call it has to be passed by value on the stack in a 32-bit architecture. I have used MagickGetImageBlob successfully, passing an unsigned long, but I am not totally certain this is not going to bite me somewhere along the way. I would appreciate knowing what the actual size is in the Windows DLLs.

2) MagickSizeType appears only two places in the MagickWand API. One of these is as an argument of the MagickSetImageProgressMonitor method. Progress monitors would appear to require at least some C language bridging in any event, and I don't plan to use that facility, so this usage is a minor blip on my radar screen.

However, the MagickGetImageSize method returns this type as a function. This is the only API appearance other than the one cited above. According to a response to a query by me in December, "MagickSizeType is 64 bits in most cases". It wasn't clear from this response what size it is in the distributed Windows DLLs. But, it appears it likely is 64 bits in those DLLs. This makes perfectly good sense to me, as image files larger than 4GB are certainly possible on average systems given the size of common hard drives. So, being able to at least detect that size is arguably necessary, regardless of processor architecture.

My non-C compiler does not have a 64-bit type. If I prototype the return value of this method as unsigned long, I get the least significant 32 bits, and no compile or runtime errors. The method is portable to at least that extent. Used with MagickPingImage, this gives my program the ability to correctly determine the size of an image smaller than 4GB. But what if the image is larger than 4GB? I presume my program will crash attempting to load a larger image than it can handle. A situation I didn't find desirable. I found the response less than helpful that I should create a C function to act as glue to make the function usable in my chosen language. (Seriously, I should buy an entire C development system so as to be able to create one tiny procedure in order to work around a trivially fixable problem in the C source?) It makes me question the seriousness of the architecture of the API. Be that as it may, it would seem to me to be highly desirable to design the calling sequence for this hugely important method so as to make it universally portable without resorting to the steps I have taken (described below). This could easily be accomplished by prototying the method as:
(void) MagickGetImageSize(MagickWand *wand,MagickSizeType *size)
(The ability to declare variables of 8 byte size is assumed to be universal, but the ability to receive 64 bit integer return values from functions is certainly not)

Using a debugger, it appears that in the distributed Q8 Windows DLL, MagickGetImageSize returns a 64 bit integer in EDX:EAX. (This appears to be a standard way to return 64 bit values on 32 bit architecture with at least some C compilers, so I feel fairly certain that is accurate) Typing the return value as long results in my non-C compiler storing EAX and ignoring EDX. Based on the assumed knowledge that EDX holds the most significant 32 bits of the return value, I created a tiny assembler language glue function that calls the method and captures the contents of both 32 bit registers in an 8 byte field (two longs) on return. I have probably worked around the issue, but lack an image of sufficient size to test it.

I hope these tiny criticisms of an otherwise fantastically portable API may inspire the development team to expend the effort to make it even more portable.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Post by magick »

Once a method is released, its signature cannot change. We certainly could introduce a new method though. Given that what are your recommendations for change? We assume you would like
  • MagickGetImageLength(MagickWand *wand,MagickSizeType *size)
What else?
*void

Post by *void »

Sorry about the delay responding. I was called away suddenly for several days and have not kept up with this forum.
magick wrote: Once a method is released, its signature cannot change. We certainly could introduce a new method though. Given that what are your recommendations for change? We assume you would like
  • MagickGetImageLength(MagickWand *wand,MagickSizeType *size)
What else?


That would be a great help!
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Post by magick »

ImageMagick 6.3.2-1, the current release, has the MagickGetImageLength() method as you suggested.
*void

Post by *void »

Works great for me.

I even tested (inadvertently) an error case. On a MagickGetImageLength following a MagickPingImage, it got error 470, "Wand contains no image". (I had forgotten to put the test image in the correct folder) :)

Which leads me to observe that MagickGetImageLengh is also cleaner from the perspective of error handling than MagickGetImageSize. I assume the latter returns size 0 on error, which is slightly ambiguous.

Thanks again.
Post Reply