MagickWand IMv6 testing....

The MagickWand interface is a new high-level C API interface to ImageMagick core methods. We discourage the use of the core methods and encourage the use of this API instead. Post MagickWand questions, bug reports, and suggestions to this forum.
Post Reply
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

MagickWand IMv6 testing....

Post 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.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: MagickWand IMv6 testing....

Post 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.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: MagickWand IMv6 testing....

Post by el_supremo »

Anthony, the URL for your test programs is a dead link.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: MagickWand IMv6 testing....

Post 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!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: MagickWand IMv6 testing....

Post by el_supremo »

Yup, got it now.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: MagickWand IMv6 testing....

Post 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();
}
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply