Page 1 of 1
Image::resize gives different results on same image
Posted: 2015-10-13T16:07:07-07:00
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?
Re: Image::resize gives different results on same image
Posted: 2015-10-13T16:25:50-07:00
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?
Re: Image::resize gives different results on same image
Posted: 2015-10-13T16:29:28-07:00
by fmw42
IM resize filters use repeatable algorithms. There is nothing random in them.
Re: Image::resize gives different results on same image
Posted: 2015-10-14T10:08:31-07:00
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?
Re: Image::resize gives different results on same image
Posted: 2015-10-14T10:24:56-07:00
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.
Re: Image::resize gives different results on same image
Posted: 2015-10-14T11:05:38-07:00
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".
Re: Image::resize gives different results on same image
Posted: 2015-10-14T12:11:31-07:00
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.