Menu

#381 Artifacts when scaling a PNG with semi-transparent pixels

v1.0_(example)
closed-fixed
None
5
2018-12-19
2016-04-08
No

In the simplest case, if you have a circle with antialiasing on a transparent background and scale it down with GraphicsMagick, a darker border will appear.

$ gm convert -size 90x90 xc:none -fill "#D3DEE6" -stroke none -draw "circle 45,45 45,0" +antialias circle.png
$ gm convert -scale 24 circle.png circle-24.png 

circle.png:
circle

circle-24.png
circle-24

2 Attachments

Discussion

  • Glenn Randers-Pehrson

    Try "-resize" instead of "-scale". BTW "+antialias" means do not use antialiasing.

     
  • Jorge Bernal

    Jorge Bernal - 2016-04-08

    That seems to work, thanks :)

     

    Last edit: Jorge Bernal 2016-04-08
  • Troy Patteson

    Troy Patteson - 2018-12-18

    ScaleImage() suffers from two problems related to the blending of fully transparent pixels with non-fully transparent pixels during the scaling operation.

    The first is that the colour values for fully transparent pixels are contributing to the colour values of the blended pixels when they should not.

    The second is that the colour values of pixels blended with fully and non-fully transparent pixels are scaled as though the fully transparent pixels contribute to the blended pixels' colour values when they should not. For example, if blending 10% of a fully opaque white pixel with 90% of a fully transparent black pixel one would expect the blended pixel RGBA values to be 255,255,255,25.5 assuming 8 bit colour but they are in fact 25.5,25.5,25.5,25.5.

    The provided patch solves the first issue by treating the colour values of fully transparent pixels as zero and the second issue by recording the volume of each blended pixel made up of pxiels that are not fully transparent (0.1 in the above example) and then scaling the blended pixel RGB values by dividing by that amount. In the above example, 25.5/0.1 = 255.

    I find it easy to test this by scaling a white ellipse with transparent background and then compositing that onto a white background image:

    COLOUR=white
    
    gm convert -size 1200x1200 xc:transparent -fill ${COLOUR} -stroke ${COLOUR} -draw "ellipse 600,600 580,350 0,360" ellipse.png
    gm convert -size 600x600 xc:white background.png
    gm convert ellipse.png -scale 580x580 scaled.png
    gm composite scaled.png -geometry +10+10 background.png output.png
    

    It is worth patching ScaleImage() as it is considerably faster than ResizeImage() and also because we should always fix bugs ;-)

    Troy Patteson

     

    Last edit: Troy Patteson 2018-12-18
  • Bob Friesenhahn

    Bob Friesenhahn - 2018-12-19
    • status: open --> closed-fixed
    • assigned_to: Bob Friesenhahn
     
  • Bob Friesenhahn

    Bob Friesenhahn - 2018-12-19

    Thanks to Troy, this problem is finally solved. See Mercurial changesets 15870:113103cc7272 and 15871:e82340b7c814.

     

Log in to post a comment.