Page 1 of 1
MagickWand IMv6 testing....
Posted: 2012-03-15T05:14:05-07:00
by anthony
I am at this time fixing ImageMagick's MagickAddImage() function, which is also used by MagickReadImage().
I must say the default behaviour of this core function is stupid.
Adding one image at a time works fine, each image being appended one image at a time.
adding multiple groups of images does not append them.
For example
read 3 images (0,1,2) and them as a group to an empty wand - no problem.
Resent = 0,1,2
But then if I then try to add a second group of images (3,4,5)
They get added after the first image in the list.
That is the images in the wand become 0,3,4,5,1,2
This was without a call to MagickSetLastImage() before the Add image.
In other word before Adding or Reading in new images into a existing wand it is a good idea
to always call MagickSetLastImage() before adding images.
However in IMv7 I have already fixed this so that regardless of if images are added individually, or in groups (animations), if the wand has not been otherwise processed or the 'current image' set, then images will be added to the end of the wand.
This will be backported into IMv6 as soon as I can, along with additional function documentation.
Additional... It seems that 'prepending' images (calling MagickSetFirstIterator() before MagickAddImages() ) Also adds them AFTER the first (zeroth) image, and not before that image. This will also be fixed ASAP.
Re: MagickWand IMv6 testing....
Posted: 2012-03-15T06:39:10-07:00
by anthony
The changes to add/read image insertion into wand has now been fixed.
By default (up until a wand is processed in some way) images and image lists will be appened to the wand's image list when
MagickAddImage or
MagickReadImage is called.
Using
MagickSetLastIterator will ensure later images or image lists will be appened,
while using
MagickSetFirstIterator will make added image prepend to the wand. the order of image list being prepended will not change.
After using
MagickSetIteratorIndex or during a Image iteration loop, images added or read into the wand will be added after the current image. The exception to this is if you used
MagickPreviousImage until you have no more 'previous' images, in which case the images will again be prepended to start (as the iteration point is then in front of the first image).
If you like to play or check out that these rules are being obeyed (at least after next IM version release 6.7.5-10) you can download my test programs from
http://www.ict.griffith.edu.au/anthony/ ... sts.tar.gz
Tomorrow I will be doing some testing of the four different ways you can iterate over images in a wand, and ensuring they are working as expected, though I do not fore-see any errors in this aspect.
Re: MagickWand IMv6 testing....
Posted: 2012-03-15T07:53:21-07:00
by el_supremo
Anthony, the URL for your test programs is a dead link.
Pete
Re: MagickWand IMv6 testing....
Posted: 2012-03-15T19:56:35-07:00
by anthony
It downloads fine for me, though perhaps my system automatically fixed it up this morning (australian time).
Hold I'll check from a external (american) site...
Yeap it is working fine! Downloads a gzipped tar file!
Re: MagickWand IMv6 testing....
Posted: 2012-03-15T19:58:42-07:00
by el_supremo
Yup, got it now.
Pete
Re: MagickWand IMv6 testing....
Posted: 2012-03-15T21:19:09-07:00
by anthony
the above example_tests archive now contains another program "loop_over_lists.c"
This demonstarts and tests about 4 different ways of looping over the images in a wand.
It does not output or display the images, only lists the images indexes and filenames as it 'loops' though them.
Code: Select all
#include <stdio.h>
#include <wand/MagickWand.h>
/* set this to true to test loops methods with a empty wand */
#define TEST_EMPTY_WAND 0
/* Simplify the exception handling
* technically we should abort the program if
* severity >= ErrorException
*/
void ThrowWandException(MagickWand *wand)
{ char
*description;
ExceptionType
severity;
description=MagickGetException(wand,&severity);
(void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description);
description=(char *) MagickRelinquishMemory(description);
}
/* useful function especially after appending two wands together */
#define SwapWands(a,b) { MagickWand *tmp=a; a=b; b=tmp; }
int main(int argc, char *argv[])
{
MagickWand
*wand,
*output;
MagickBooleanType
status;
MagickWandGenesis();
printf("Read in a list of 6 images...\n");
wand = NewMagickWand();
#if !TEST_EMPTY_WAND
status = MagickReadImage(wand, "font_0.gif" )
&& MagickReadImage(wand, "font_1.gif" )
&& MagickReadImage(wand, "font_2.gif" )
&& MagickReadImage(wand, "font_3.gif" )
&& MagickReadImage(wand, "font_4.gif" )
&& MagickReadImage(wand, "font_5.gif" );
if (status == MagickFalse)
ThrowWandException(wand);
#endif
printf("I actually read in %u images\n",
(unsigned) MagickGetNumberImages(wand) );
printf("\n");
printf("After reading current image is #%d \"%s\"\n",
(unsigned) MagickGetIteratorIndex(wand),
MagickGetImageFilename(wand) );
printf("\n");
// Note that using MagickGetIteratorIndex() is slower than just
// keeping track of the current image index yourself! But not a great cost.
printf("Standard 'Reset while Next' loop through images\n");
// keeping track of it to start with!
MagickResetIterator(wand);
while (MagickNextImage(wand) != MagickFalse)
printf("image #%u \"%s\"\n",
(unsigned) MagickGetIteratorIndex(wand),
MagickGetImageFilename(wand) );
printf("\n");
printf("At this point, any image 'added' to wand will be appended!\n");
printf("This special condition can be set by using either\n");
printf("just MagickSetLastIterator(w)\n");
printf("or MagickSetIteratorIndex(-1)\n");
printf("Now that we are at the end, lets loop backward using 'Previous'\n");
while (MagickPreviousImage(wand) != MagickFalse)
printf("image #%u \"%s\"\n",
(unsigned) MagickGetIteratorIndex(wand),
MagickGetImageFilename(wand) );
printf("\n");
printf("Note at this point, any image 'added' to wand will be prepended!\n");
printf("This special condition can be set by using either\n");
printf("just MagickSetFirstIterator(w)\n");
printf("Or MagickResetIterator(w); MagickPreviousImage(w);\n");
printf("The latter method being the cause of the current condition\n");
printf("\n");
printf("Directly loop though images backward using 'Last, while Previous'\n");
MagickSetLastIterator(wand);
while ( MagickPreviousImage(wand) != MagickFalse )
printf("image #%u \"%s\"\n",
(unsigned) MagickGetIteratorIndex(wand),
MagickGetImageFilename(wand) );
printf("\n");
printf("Loop through images using Indexes, in a weird flip-flop way!\n");
printf("Note that indexing using a negative number, indexes from end.\n");
{ ssize_t i;
ssize_t n = (ssize_t) MagickGetNumberImages(wand);
for ( i=0; i!=n; i= (i>=0) ? -(i+1):-i ) {
(void) MagickSetIteratorIndex(wand,i);
/* Note that a return of MagickFalse by the above is not actually an
* error (no exception will be generated). It just means that the
* index value used (positive or negative) is too large for the
* size of the current image list (EG: range error: -n <= i < n )
* When it does happen, no change is made to the current image
*/
printf("index %2d -> #%u \"%s\"\n", (int) i,
(unsigned) MagickGetIteratorIndex(wand),
MagickGetImageFilename(wand) );
}
}
printf("\n");
wand=DestroyMagickWand(wand);
MagickWandTerminus();
}