Image::resize gives different results on same image

Magick++ is an object-oriented C++ interface to ImageMagick. Use this forum to discuss, make suggestions about, or report bugs concerning Magick++.
Post Reply
greener
Posts: 3
Joined: 2015-10-13T15:48:14-07:00
Authentication code: 1151

Image::resize gives different results on same image

Post by greener »

When I load an Image from a PNG, and then call:

Code: Select all

image.resize(Geometry(newWidth, newHeight));
(where the new width and height are either about 10% larger or 10% smaller than the original), and then save the resulting image as another PNG, I find that I get slightly different results each time. That's even when I'm starting with the same source image and scaling to the same new size each time. My source images are only black & white & gray, either 8 bpp (grayscale) or 32 bpp (RGB).

The resized images look the same to the naked eye, and if I subtract them from each other, the result looks all black, until I greatly increase the contrast, at which point I can see the differences along borders of the original lighter regions. Also, if I use Image::compare on the resulting images, it returns a normalizedMaxError of about 0.0018 for the 8 bpp images and about 0.288 for the 32 bpp images.

Do the default filters use some random jitter in their sample positions that might account for this?
Is there any way to turn that off, in order to get perfectly repeatable results?
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Image::resize gives different results on same image

Post by snibgo »

I don't think anything in IM should create any jitter. Are you using the same version of IM, on the same computer?

What version of IM, on what platform?
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Image::resize gives different results on same image

Post by fmw42 »

IM resize filters use repeatable algorithms. There is nothing random in them.
greener
Posts: 3
Joined: 2015-10-13T15:48:14-07:00
Authentication code: 1151

Re: Image::resize gives different results on same image

Post by greener »

Thanks for the quick replies! Yes, it's all being done on the same computer, a BeagleBone Black clone running Debian. The Magick++ version is 6.7.7 Q16.

I've now found that these differences are introduced when the image is written out to a file. The following code:

Code: Select all

    const char* original = "test_image.png";
    
    Image image1(original);
    image1.resize(Geometry(1408, 880));
    image1.write("resized_1.png");
    
    Image image2(original);
    image2.resize(Geometry(1408, 880));
    
    int retVal = image2.compare(image1);
    printf("before saving image2, compare returns %d, error = %f\n", 
           retVal, image2.normalizedMaxError());   

    image2.write("resized_2.png");
    
    retVal = image2.compare(image1);
    printf("after saving image2, compare returns %d, error = %f\n", 
           retVal, image2.normalizedMaxError());  
generates this output:
before saving image2, compare returns 0, error = 0.001953
after saving image2, compare returns 1, error = 0.000000

So as long as I do the comparison after writing both images to a file, they are indeed identical.
Is the difference perhaps that the image in memory is quantized when written to a file?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Image::resize gives different results on same image

Post by fmw42 »

Internal calculations are, I believe, double floats, but if using non-hdri IM such as the default Q16, the output images are quantized to integers.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Image::resize gives different results on same image

Post by snibgo »

greener wrote:Is the difference perhaps that the image in memory is quantized when written to a file?
Roughly: yes.

You are using Q16, I assume non-HDRI, so images are stored in memory with 16-bit integers for each channel. If you were writing to a 16-bit PNG, there would be no quantisation. But I suspect you are writing to an 8-bit PNG. (You can check this: what does "identify" say about the file?)

At the command-line interface, we can use "-write" or "+write". "-write" will do any quantisation, write the file, then carry on with that data. By contrast, "+write" will make a copy of the data, quantise and write that then discard it, so it carries on with the original (unquantised) data.

Another option is to use "+depth" which, in this case, would not quantise to 8 bits.

A third option is to ensure the two images undergo the same processing before comparing them.

I don't know the equivalent in other APIs to "+write".
snibgo's IM pages: im.snibgo.com
greener
Posts: 3
Joined: 2015-10-13T15:48:14-07:00
Authentication code: 1151

Re: Image::resize gives different results on same image

Post by greener »

Yes, I'm using PNGs with 8 bits per channel (either 8 bpp grayscale or 32 bpp RGB), so the conversion from 16 bits per channel in memory would account for these differences. The normalized max error of 0.001953 * 255 ~= 0.5 implies the differences are at most a half of one gray level, and it doesn't get any better than that ;-)

Thanks again for your answers.
Post Reply