possible bug -extent IM 6.9.0.0 Mac Snow Leopard
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
possible bug -extent IM 6.9.0.0 Mac Snow Leopard
I have found some times when -extent loses or disables the alpha channel and I do not understand why.
Consider the following examples where the first and third stay transparent but the second and third become black or red. The first 3 turn the alpha off before the extent and back on afterwards. The fourth leaves the alpha channel on the whole time but uses rgba rather than rgb for the extent color
This works as expected:
convert -size 100x100 xc:none -gravity center \
-alpha off -background "rgb(255,0,0)" -extent 150x150 -alpha on tmp1.png
This turns the transparent center black (note the extent is 150x150)
convert -size 100x100 xc:white -bordercolor "gray(50)" -border 25 \
-fuzz 10% -transparent white \
-fill "rgba(255,0,0,1)" +opaque none \
-gravity center -bordercolor none -border 10x10 \
-fuzz 0 -trim +repage \
-alpha off -background "rgb(255,0,0)" -extent 150x150 -alpha on tmp2.png
This is the same as above, only the extent size is 151x151:
convert -size 100x100 xc:white -bordercolor "gray(50)" -border 25 \
-fuzz 10% -transparent white \
-fill "rgba(255,0,0,1)" +opaque none \
-gravity center -bordercolor none -border 10x10 \
-fuzz 0 -trim +repage \
-alpha off -background "rgb(255,0,0)" -extent 151x151 -alpha on tmp3.png
This turns the transparent area red (even using extent size 151x151 as above):
convert -size 100x100 xc:white -bordercolor "gray(50)" -border 25 \
-fuzz 10% -transparent white \
-fill "rgba(255,0,0,1)" +opaque none \
-gravity center -bordercolor none -border 10x10 \
-fuzz 0 -trim +repage \
-background "rgba(255,0,0,1)" -extent 151x151 tmp4.png
Seems like at least two bugs, one using -alpha off/-alpha on and the other when not turning alpha off and on.
Consider the following examples where the first and third stay transparent but the second and third become black or red. The first 3 turn the alpha off before the extent and back on afterwards. The fourth leaves the alpha channel on the whole time but uses rgba rather than rgb for the extent color
This works as expected:
convert -size 100x100 xc:none -gravity center \
-alpha off -background "rgb(255,0,0)" -extent 150x150 -alpha on tmp1.png
This turns the transparent center black (note the extent is 150x150)
convert -size 100x100 xc:white -bordercolor "gray(50)" -border 25 \
-fuzz 10% -transparent white \
-fill "rgba(255,0,0,1)" +opaque none \
-gravity center -bordercolor none -border 10x10 \
-fuzz 0 -trim +repage \
-alpha off -background "rgb(255,0,0)" -extent 150x150 -alpha on tmp2.png
This is the same as above, only the extent size is 151x151:
convert -size 100x100 xc:white -bordercolor "gray(50)" -border 25 \
-fuzz 10% -transparent white \
-fill "rgba(255,0,0,1)" +opaque none \
-gravity center -bordercolor none -border 10x10 \
-fuzz 0 -trim +repage \
-alpha off -background "rgb(255,0,0)" -extent 151x151 -alpha on tmp3.png
This turns the transparent area red (even using extent size 151x151 as above):
convert -size 100x100 xc:white -bordercolor "gray(50)" -border 25 \
-fuzz 10% -transparent white \
-fill "rgba(255,0,0,1)" +opaque none \
-gravity center -bordercolor none -border 10x10 \
-fuzz 0 -trim +repage \
-background "rgba(255,0,0,1)" -extent 151x151 tmp4.png
Seems like at least two bugs, one using -alpha off/-alpha on and the other when not turning alpha off and on.
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: possible bug -extent IM 6.9.0.0 Mac Snow Leopart
Your examples seem over-complicated. You add a border then trim it away. Does this make any difference?
If an image is 150x150, and we "-extent 150x150", we might expect a no-op. But that is not the case.
Internally, in transform.c ExtentImage(), IM creates a new image then composes the input image over that new image. Hence the size of the result is the size given in "-extent". Hence also, if the entent colour is opaque and is at least as large as the input, the output will be opaque.
Does that answer the question?
If an image is 150x150, and we "-extent 150x150", we might expect a no-op. But that is not the case.
Internally, in transform.c ExtentImage(), IM creates a new image then composes the input image over that new image. Hence the size of the result is the size given in "-extent". Hence also, if the entent colour is opaque and is at least as large as the input, the output will be opaque.
Does that answer the question?
snibgo's IM pages: im.snibgo.com
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: possible bug -extent IM 6.9.0.0 Mac Snow Leopart
It was a simplified (generic) example from some processing I was trying to do (from another post viewtopic.php?f=1&t=26584) with an image that had an opaque border around a central transparent image and outside of that was a some more transparency on that I wanted to trim away.snibgo wrote:Your examples seem over-complicated. You add a border then trim it away. Does this make any difference?
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: possible bug -extent IM 6.9.0.0 Mac Snow Leopart
Ah, those bricks in the wall.
For tmp4.png, inserting "-compose Copy" before the final "-extent" will retain the transparency. This is often a better setting for both "-extent" and "-border".
It doesn't help for tmp2.png, as the "-alpha off" means that alpha channel is ignored in the composite.
For tmp4.png, inserting "-compose Copy" before the final "-extent" will retain the transparency. This is often a better setting for both "-extent" and "-border".
It doesn't help for tmp2.png, as the "-alpha off" means that alpha channel is ignored in the composite.
snibgo's IM pages: im.snibgo.com
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: possible bug -extent IM 6.9.0.0 Mac Snow Leopart
Thanks snibgo.
This does indeed retain the transparent center
convert -size 100x100 xc:white -bordercolor "gray(50)" -border 25 \
-fuzz 10% -transparent white \
-fill "rgba(255,0,0,1)" +opaque none \
-gravity center -bordercolor none -border 10x10 \
-fuzz 0 -trim +repage \
-background "rgba(255,0,0,1)" -compose copy -extent 151x151 show:
I have known that one needs to reset -compose over before doing -flatten if one has used other non-mathematical compose settings prior in the command line. I did not know about this issue with -extent. Can you explain why -compose copy?
I have read http://www.imagemagick.org/Usage/compose/#copy, but I do not understand how that relates to -extent.
This does indeed retain the transparent center
convert -size 100x100 xc:white -bordercolor "gray(50)" -border 25 \
-fuzz 10% -transparent white \
-fill "rgba(255,0,0,1)" +opaque none \
-gravity center -bordercolor none -border 10x10 \
-fuzz 0 -trim +repage \
-background "rgba(255,0,0,1)" -compose copy -extent 151x151 show:
I have known that one needs to reset -compose over before doing -flatten if one has used other non-mathematical compose settings prior in the command line. I did not know about this issue with -extent. Can you explain why -compose copy?
I have read http://www.imagemagick.org/Usage/compose/#copy, but I do not understand how that relates to -extent.
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: possible bug -extent IM 6.9.0.0 Mac Snow Leopard
It does not answer why 1 more pixel makes a difference between tmp2 and tmp3.snibgo wrote:Does that answer the question?
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: possible bug -extent IM 6.9.0.0 Mac Snow Leopard
Hmm.
The behaviour of composing a source transparent-black (or opaque-black) "over" a destination red rectangle of the same or larger size, with or without bracketing the composite between alpha off/on (so there are 2x2x2=8 tested cases), seems to be:
1. The RGB channels are correct. We get red in pixels corresponding to outside the source, and either black or red inside the source according to whether or not alpha worked its way to the composite.
2. Pixels corresponding to outside the source are always opaque, as expected.
3. In most cases, pixels corresponding to inside the source are opaque. This is because the destination image is opaque, and for "over", each resulting alpha is taken from the destination, whether the pixel is inside or outside the source. More formally: result.a = 1 - ((1 - dest.a) * (1 - src.a)), and dest.a = 1, so result.a = 1.
3a. The sole exception to rule 3 is:
This is transparent where the pixels came from the source.
The intermediate result from "+write alphaover_c2aw.png" is opaque, as expected. But the result alphaover_c2a.png is transparent for the "inside" pixels. So the result from composite must have transparent black pixels, but they seem opaque because alpha is (at that point) off.
I think the (3a) result shouldn't have transparent pixels, because dest.a = 1 for all pixels. Clearly, "-alpha off" followed by "-alpha on" is causing the problem. Perhaps having alpha off causes the code that would calculate alpha correctly to be bypassed.
------
Later at night, looking at the code:
composite-private.h, function MagickPixelCompositeOver(), I see all calculations are skipped if source.opacity == OpaqueOpacity, so the result is set to the source.
In composite.c, we have:
(I think composite_image->matte comes from the "-alpha" setting.)
Otherwise, source.opacity is left at the default from GetMagickPixelPacket(), which sets it to OpaqueOpacity. Ha!
So, I think (tentatively) that the problem is that because "-alpha off", the four RGBA channels are copied from source pixel, as it is in the cache. This would be fine, except that source.opacity is incorrect. It hasn't been picked up from the pixel cache. So the alpha parameter to MagickPixelCompositeOver() is wrong, and we shouldn't skip the calculation. If we did the calculation, we would get the correct result of composite->opacity=OpaqueOpacity.
------
Those are my current thoughts. They may be wrong.
The behaviour of composing a source transparent-black (or opaque-black) "over" a destination red rectangle of the same or larger size, with or without bracketing the composite between alpha off/on (so there are 2x2x2=8 tested cases), seems to be:
1. The RGB channels are correct. We get red in pixels corresponding to outside the source, and either black or red inside the source according to whether or not alpha worked its way to the composite.
2. Pixels corresponding to outside the source are always opaque, as expected.
3. In most cases, pixels corresponding to inside the source are opaque. This is because the destination image is opaque, and for "over", each resulting alpha is taken from the destination, whether the pixel is inside or outside the source. More formally: result.a = 1 - ((1 - dest.a) * (1 - src.a)), and dest.a = 1, so result.a = 1.
3a. The sole exception to rule 3 is:
Code: Select all
convert -size 300x300 xc:Red -size 150x150 xc:None -alpha off -composite +write alphaover_c2aw.png -alpha on alphaover_c2a.png
The intermediate result from "+write alphaover_c2aw.png" is opaque, as expected. But the result alphaover_c2a.png is transparent for the "inside" pixels. So the result from composite must have transparent black pixels, but they seem opaque because alpha is (at that point) off.
I think the (3a) result shouldn't have transparent pixels, because dest.a = 1 for all pixels. Clearly, "-alpha off" followed by "-alpha on" is causing the problem. Perhaps having alpha off causes the code that would calculate alpha correctly to be bypassed.
------
Later at night, looking at the code:
composite-private.h, function MagickPixelCompositeOver(), I see all calculations are skipped if source.opacity == OpaqueOpacity, so the result is set to the source.
In composite.c, we have:
Code: Select all
if (composite_image->matte != MagickFalse)
source.opacity=(MagickRealType) GetPixelOpacity(p);
Otherwise, source.opacity is left at the default from GetMagickPixelPacket(), which sets it to OpaqueOpacity. Ha!
So, I think (tentatively) that the problem is that because "-alpha off", the four RGBA channels are copied from source pixel, as it is in the cache. This would be fine, except that source.opacity is incorrect. It hasn't been picked up from the pixel cache. So the alpha parameter to MagickPixelCompositeOver() is wrong, and we shouldn't skip the calculation. If we did the calculation, we would get the correct result of composite->opacity=OpaqueOpacity.
------
Those are my current thoughts. They may be wrong.
snibgo's IM pages: im.snibgo.com
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: possible bug -extent IM 6.9.0.0 Mac Snow Leopard
I should add: I think your OP has inverted conclusions. Because you have an implied "-compose over", I think all the results should be entirely opaque.
snibgo's IM pages: im.snibgo.com
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: possible bug -extent IM 6.9.0.0 Mac Snow Leopard
It could be argued that changing the behaviour of such a fundamental building block is unwise. Perhaps the documentation http://www.imagemagick.org/script/comma ... .php#alpha should be changed, so "alpha off" reads:
"Disables the image's transparency channel. Does not delete or change the existing data, just turns off the use (and possibly calculation) of that data."
"Disables the image's transparency channel. Does not delete or change the existing data, just turns off the use (and possibly calculation) of that data."
snibgo's IM pages: im.snibgo.com
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: possible bug -extent IM 6.9.0.0 Mac Snow Leopard
The more I think about this, the more I am inclined to leave code unchanged. For example:
In this simple example, multiplying by 2 within "-alpha off" doesn't multiply alpha by 2, or leave it unchanged, but zeros it.
I suspect that fixing all places where alpha isn't correctly calculated when it is "off" would be a major problem.
Code: Select all
f:\web\im>%IM%convert xc:rgba(10%,20%,30%,0.4) -channel RGBA -evaluate multiply 2 txt:
# ImageMagick pixel enumeration: 1,1,65535,srgba
0,0: (20.0015%,40%,60.0015%,0.8) #33346666999ACCCC srgba(20.0015%,40%,60.0015%,0.8)
f:\web\im>%IM%convert xc:rgba(10%,20%,30%,0.4) -channel RGBA -alpha off -evaluate multiply 2 -alpha on txt:
# ImageMagick pixel enumeration: 1,1,65535,srgba
0,0: (20.0015%,40%,60.0015%,0) #33346666999A0000 srgba(20.0015%,40%,60.0015%,0)
I suspect that fixing all places where alpha isn't correctly calculated when it is "off" would be a major problem.
snibgo's IM pages: im.snibgo.com