Hi Bob,
I noticed GraphicsMagick version 1.3.22 introduced a couple of bugs in the ScaleImage() function in resize.c.
The first issue involves scaling an image by 100%. The returned scaled image does not contain any image data and will result in a No IDATs error when trying to perform further image operations or attempting to save the scaled image. The issue can be tested with the attached test program (scale_image). Note that the issue isn't triggered with gm convert using -scale 100% as ScaleImage() is not called.
e.g.
gm convert logo: logo.png
./scale_image logo.png
Input image size: 654 x 418
Scaled image size: 654 x 418
Start: 1446194868.214077
Magick: No IDATs written into file (scaled.png).
Previously calling ScaleImage() with columns and rows set to the same as the input image would result in the function simply peforming the complete scaling operation and returning the scaled image. In v1.3.22, ScaleImage() returns early after calling CloneImage() if the scaled columns and rows equals the input image's columns and rows. However, the CloneImage() function does not duplicate the image data unless the columns and rows parameters are set to 0. The solution is to simply to test whether the scaled image columns and rows match the input image's and if so, call CloneImage with the columns and rows set to zero. See attached patch GraphicsMagick-1.3.22-scale-image-exact-fix.patch.
The second issue in ScaleImage() is a double free() memory issue when the scaled height matches the input image height but the width differs. This issue can be replicated with gm convert.
e.g.
gm convert logo: -scale 120%x100% logo2.png
*** Error in `gm': double free or corruption (!prev): 0x000000000261bb10 ***
gm convert: abort due to signal 6 (SIGABRT) "Abort"...
Aborted
or with the attached test program:
gm convert logo: logo.png
./scale_image logo.png 660 418
Input image size: 654 x 418
Scaled image size: 660 x 418
Start: 1446195124.276007
*** Error in `./scale_image': double free or corruption (!prev): 0x0000000000e63250 ***
Magick: abort due to signal 6 (SIGABRT) "Abort"...
Aborted
This issue occurs because the variable scanline re-uses the x_vector buffer if the number of scaled rows equals the number of input image rows but is always being freed. The solution is to simply check whether scanline differs from x_vector before freeing. See attached patch GraphicsMagick-1.3.22-scale-image-exact-height-fix.patch (applied after the first).
It might be worth adding test cases for both issues.
Troy Patteson
The Magick++ 'zoom' demo provides access to testing the 'scale' algorithm (illustrating problems):
These were both regressions added in 1.3.22. Scale issues are fixed now. Test cases have been added to assure that such issues are caught in the future.