Different output between 6.3.3 Q8 and 6.3.3 Q16

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
rmagick
Posts: 245
Joined: 2006-03-16T17:30:48-07:00
Location: Durham, NC, USA

Different output between 6.3.3 Q8 and 6.3.3 Q16

Post by rmagick »

This may be the expected behavior but I want to confirm it before I respond to the RMagick user who reported it. There is an example C program at the bottom of this post. When built with 6.3.3-1 Q16 it produces this image:
Image

When I build the example program with 6.3.3-1 Q8 it produces this image:
Image

Is this the expected behavior? If so, is there a workaround to get the Q8 version to produce an image closer to the Q16 version of the image?

Here's the input image "bolilla.png" for this test: Image

Code: Select all

/*
gcc `Magick-config --cflags --cppflags` tbe.c `Magick-config --ldflags --libs` -o tbe
*/
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <magick/api.h>


int main(int argc, char **argv)
{
    Image *click_image, *image;
    ImageInfo *image_info;
    ExceptionInfo exception;
    MagickBooleanType okay;
    PixelPacket white;
    unsigned long version;
    char name[50];
    int x;

    InitializeMagick("Test");
    (void) GetMagickVersion(&version);

    GetExceptionInfo(&exception);
    okay = QueryColorDatabase("white", &white, &exception);
    if (!okay)
    {
        MagickFatalError(exception.severity, exception.reason, exception.description);
    }

    image_info=CloneImageInfo((ImageInfo *) NULL);
    strcpy(image_info->filename, "bolilla.png");

    GetExceptionInfo(&exception);

    click_image = ReadImage(image_info, &exception);
    if (exception.severity != UndefinedException)
    {
      MagickFatalError(exception.severity, exception.reason, exception.description);
    }

    image = ColorizeImage(click_image, "97/97/97", white, &exception);
    if (!image)
    {
        MagickFatalError(exception.severity, exception.reason, exception.description);
    }
    DestroyImage(click_image);
    click_image = image;

    DestroyImageInfo(image_info);
    image_info=CloneImageInfo((ImageInfo *) NULL);
    image_info->size = AcquireMemory(sizeof("100x300"));
    strcpy(image_info->size, "100x300");

    okay = QueryColorDatabase("white", &image_info->background_color, &exception);
    if (!okay)
    {
        MagickFatalError(exception.severity, exception.reason, exception.description);
    }

    image_info->background_color = white;

    image = AllocateImage(image_info);
    if (image == (Image *) NULL)
    {
        MagickFatalError(ResourceLimitError, "Unable to allocate image", "Memory allocation failed");
    }

    // (void) SetImageBackgroundColor(image); not available in 6.0.6
    (void) SetImage(image, OpaqueOpacity);

    // Here's the meat
    for (x = 0; x < 50; x++)
    {
        (void) CompositeImage(image, MultiplyCompositeOp, click_image, 20, 30);
        if (exception.severity != UndefinedException)
        {
          MagickFatalError(exception.severity, exception.reason, exception.description);
        }
    }

    NegateImage(image, MagickFalse);

    DestroyImageInfo(image_info);
    image_info = CloneImageInfo((ImageInfo *) NULL);

    sprintf(name, "tbe_output-%3lx.png", version);
    strcpy(image_info->filename, name);
    strcpy(image->filename, image_info->filename);
    WriteImage(image_info, image);

    (void) DestroyExceptionInfo(&exception);
    (void) DestroyImage(image);
    (void) DestroyImage(click_image);
    (void) DestroyImageInfo(image_info);
    (void) DestroyMagick();

    return 0;
}
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Different output between 6.3.3 Q8 and 6.3.3 Q16

Post by magick »

The problem appears to be cumulative round-off error. You can visualize the effect by varying the composite loop from 10 to 50 by 10. Each step introduces additional quantization levels for the Q8 version. We assume the Q32 version of ImageMagick would have a smoother gradient than the Q16 version. The solution may be in an upcoming release where we permit floating point pixels for Q8 and Q16 pixel component depts. This provides for smoother transitions for algorithms such as the one you present here.
tbe

Re: Different output between 6.3.3 Q8 and 6.3.3 Q16

Post by tbe »

magick,

I'm the rmagick user who first reported this problem. When could I expect this new release?
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Different output between 6.3.3 Q8 and 6.3.3 Q16

Post by anthony »

Don't hold your breath.

Cristy is swamped with 'todo' itmes. He also give priority to bugs, rather than new features. SVG gradients and perspective distortions for examples have been waiting to be added for some time.

If other users would like to help, please grab the source and create a patch. If cristy finds your work acceptabe, and you are keen to continue, you can also get direct SVN update access.

I myself have SVN update access, and use it to fix some problems. I also do the occasional update to the command line options description page.

Right now I am looking at the additions needed for GIF animation improvements. Such as...
  • simple transparency optimization,
  • -reverse and -shuffle image sequence ordering,
  • RemoveDups and RemoveZeroDelay -layer frame removal options,
  • and image sequence alpha composition (overlay static source, overlay onto static destination, paired image composition).
All of which I talk about in IM Examples.

Hmmm sorry for the rant, but it was time for an FYI, so you have no illusions about what is happening.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Different output between 6.3.3 Q8 and 6.3.3 Q16

Post by magick »

Floating point support will take some time. We're 95% there but like Anthony mentioned, bug reports and high priority enhancements take priority over new features.
Post Reply