PSD to PNG alpha white border

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
noon

PSD to PNG alpha white border

Post by noon »

Hello,

I'm trying to convert PSD files to PNG using ImageMagick, and I get a white border where the alpha is less than 255.
Here is an image that shows the difference. For you to notice, I put a black background after converting it to PNG.
Image

I tried using the -background parameter like so :
-background none
-background black
-background rgba(0, 0, 0, 0)

But it doesn't change anything.

The original PSD file :
http://rapidshare.com/files/417478899/Border.psd

Any idea ?

Thanks
Last edited by noon on 2010-09-06T12:37:56-07:00, edited 1 time in total.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: PSD to PNG alpha white border

Post by fmw42 »

Best to post a link to your original PSD file for others to test and examine
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: PSD to PNG alpha white border

Post by fmw42 »

The problem is that either the PSD file has near white below the (fully and partially) transparent areas (or IM reads it that way)


convert Border.psd -format %c histogram:info:
...
517: (250,250,250, 5) #FAFAFA05 rgba(250,250,250,0.0196078)
9: (251,250,250, 6) #FBFAFA06 rgba(251,250,250,0.0235294)
1: (251,251,250, 5) #FBFBFA05 rgba(251,251,250,0.0196078)
60: (251,251,251, 4) #FBFBFB04 rgba(251,251,251,0.0156863)
2: (252,252,251, 4) #FCFCFB04 rgba(252,252,251,0.0156863)
248: (252,252,252, 3) #FCFCFC03 rgba(252,252,252,0.0117647)
6: (253,253,252, 3) #FDFDFC03 rgba(253,253,252,0.0117647)
476: (253,253,253, 2) #FDFDFD02 rgba(253,253,253,0.00784314)
738: (254,254,254, 1) #FEFEFE01 rgba(254,254,254,0.00392157)
17487: (255,255,255, 0) #FFFFFF00 rgba(255,255,255,0)


Thus where the image is partially transparent the near white is coming through as a halo.

You can try recreating your input file with black under the transparent.

I have tried to change white to black in IM, but as the white is not consistent, I need a very large fuzz factor which then destroys part of the image as well.

The only thing that I can do is reduce the extent of the transparency area so that it does not cover where the image is kind of white.

Try

convert Border.psd \
\( -clone 0 -alpha extract -level 50x100% \) \
\( -clone 0 -alpha off \) \
-delete 0 +swap -compose copy_opacity -composite Border6.png
noon

Re: PSD to PNG alpha white border

Post by noon »

Thanks fmw42.

I wonder why IM reads white values. Seems to me the colors are linearly interpolated from their actual RBG values to a White according their Alpha values.
Something like :

dst.A = src.A
dst.R = Lerp(255, src.R, src.A / 255.0)
dst.G = Lerp(255, src.G, src.A / 255.0)
dst.B = Lerp(255, src.B, src.A / 255.0)

with Lerp(a, b, f) = a + f(b-a)

That would explain the values you outputted.
- When the alpha is 255 we get the normal source color
- When the alpha gets a little below 255 we get something whiter.
- When the alpha is amost 0 we get something almost white : 517: (250,250,250, 5)
- When the alpha is 0 we get a perfect white : 17487 : (255,255,255, 0)

I did the test with another image. Here is the source PSD file : http://rapidshare.com/files/417511737/ColorTest.psd
It's 4 circles Balck; Red Green, Blue, with 52% opacity.

Here is the PNG file saved from the PSD by Photoshop
Image

Here is the PNG file converted from the PSD by IM
Image

Here is a comparison of the result with a black background :
Image

I wonder if this is a IM bug, or if it's Photoshop who's giving those weird values.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: PSD to PNG alpha white border

Post by fmw42 »

No, basically you cannot have a transparency without an underlying color. When IM creates pure transparent pixels it has a black color underneath R=0,B=0,G=0,A=0. But in your image, the underlying color is white or near white, R=255,G=255,B=255,A=0. When you have partial transparency, then IM will take some fraction of the underlying color and show that according to the amount of transparency. In this case, you see partial white, which creates a halo effect.

So I think your problem is in your PSD file. But I could be wrong.

What it appears to me is that PS is treating the background as black, but in exporting it or when IM imports it, it somehow gets white rather than black.

But someone with more expertise than I regarding PSD files needs to look at it.

Your ColorTest.psd file has both background transparency and an alpha transparency (in your colors layer). Perhaps, IM cannot handle this properly as it can only deal with one kind of transparency at a time. (Both files also appear to contain one vertical cyan line that does not show up in IM).

I think Magick may have to look at these files.
Last edited by fmw42 on 2010-09-06T16:40:52-07:00, edited 1 time in total.
noon

Re: PSD to PNG alpha white border

Post by noon »

fmw42 wrote:basically you cannot have a transparency without an underlying color.


There is no reason to choose the white color as the underlying color. Why not use the RBG color of the pixel instead.
fmw42 wrote:What it appears to me is that PS is treating the background as black, but in exporting it or when IM imports it, it somehow gets white rather than black.


I don't think PS treat the background as black. Otherwise the colors in the circle test should have appeared draker when saved to PNG.

Let's take an example of a red pixel inside a photoshop layer : (255, 0, 0, 255)
Now I change the opacity of the layer to 50. We get: (255, 0, 0, 128)
When we save to PNG inside photoshop we get : (255, 0, 0, 128)
When we convert to PNG with IM we get : (255, 128, 128, 128)

if IM needs to use an underlying color, it would make more sense to use the original RBG (255, 0, 0).
But I don't really see why IM should have to use an underlying color.
Last edited by noon on 2010-09-06T23:16:33-07:00, edited 1 time in total.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: PSD to PNG alpha white border

Post by fmw42 »

Take a look a the histogram I made first. Look at the last line which is pure transparency. It has white underneath it. Pure transparency has to have some underlying color defined for it or colors from the image. In your first image at least, the underlying color is white when you turn the alpha channel off in IM. I don't know where the white is coming from.

But every one of my display tools on the Mac displays your image differently. Some are lighter and some are darker. PSD files are Photoshop and can have proprietary fields that only they know how to interpret.

I just don't know what is going on and it will take some expert to resolve this.
noon

Re: PSD to PNG alpha white border

Post by noon »

I agree when the pixel is pure transparency, the RBG value has to be chosen. The White color is a good pick for this case.
It does not matter a lot since pure transparent pixel are not visible. It would matter when trying to interpolate with neighboors pixels, for a bilinear interpolation for example, but that's another subject.

But when the pixel is not fully transparent, I can't think of any good reason to use an underlying color. The RBG color should be used.

Thanks for your help !
noon

Re: PSD to PNG alpha white border

Post by noon »

I used the libpsd (http://sourceforge.net/projects/lib/) and did a simple application to test if it was Photoshop or ImageMagick who was messing with the color values.
As ImageMagick, libpsd can read the merged image and every layer.

I created a layer in photoshop and painted it in red with 50% opacity brush.
The layer itslef has 100% opacity, but all his pixels are supposed to be (255, 0, 0, 128).

What I should read: (255, 0, 0, 128)
What I get when reading the merged image: (255, 127, 127, 255)
What I get when reading the first layer: (255, 0, 0, 128)

Now, I don't understand why the alpha is wrong when reading the merged image (255 instead of 128), but you can notice the RBG values move to white.
On the othe hand reading the first layer gives the right values!

To confirm this test I tried using ImageMagick to convert the PSD to PNG, but instead of using the merged image (layer 0), I convert the layer 1 :
convert ColorTest.psd[1] ColorTest.png

This does give the same result as saving the PNG directly from photoshop!
So it seems Photoshop is to blame. More precisly the merged image of Photoshop is to blame.
It kinda sucks, because to get the right color values, all the layers need to be merged into one inside photoshop to convert only the layer 1...
noon

Re: PSD to PNG alpha white border

Post by noon »

I understood why the alpha value was 255 when reading in the merged image.
It seems the alpha values of the merged image need to be read in a separated alpha channel.
When reading this channel instead, I get the right alpha value (128).

This mean there is maybe a way to get the original colors from the RGB and the Alpha channel.
I'm looking for it and I'll post if I find out.
noon

Re: PSD to PNG alpha white border

Post by noon »

I'm not sure but here is a formula I think would work to get the real pixels colors from the merged image in the PSD file :

x = (x - (255 - A)) * (255 / A)

Where A is the alpha channel and x is the R, G, or B component of the pixel.
I came up with this after exporting a red image with 50% opacity and a red image with 25% opacity.

50% opacity:
Expected (255, 0, 0, 128)
Result (255, 127, 127, 128)

25% opacity:
Expected (255, 0, 0, 64)
Result (255, 191, 191, 64)

You may have noticed the G and B values grow according alpha like so : 255 - A.
So we can retract it from G :
G = G - (255 - A).
G = 191 - (255 - 64)
G = 191 - 191
G = 0

But it wouldn't work for R :
R = R - (255 - A)
R = 255 - (255 - 64)
R = 255 - 191
R = 64

Now we would get RBG = (64, 0, 0)
To get back on our feet we just need to multiply the R, G and B by (255 / A)

And we get (255, 0, 0, 64)
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: PSD to PNG alpha white border

Post by fmw42 »

noon wrote:I agree when the pixel is pure transparency, the RBG value has to be chosen. The White color is a good pick for this case.
It does not matter a lot since pure transparent pixel are not visible. It would matter when trying to interpolate with neighboors pixels, for a bilinear interpolation for example, but that's another subject.

But when the pixel is not fully transparent, I can't think of any good reason to use an underlying color. The RBG color should be used.

Thanks for your help !

The problem is that the colors under the partially transparent pixels are near white, so you get a halo.
noon

Re: PSD to PNG alpha white border

Post by noon »

Yes, I knew the color under the partially transparent pixels were white, and caused the white border.
That's why in my first post I said I tried using the -background parameter with "black" or "rgba(0, 0, 0, 0)".

My question was :
- Why a white background color was used when there is no need to (for non full transparent pixels)
- Was it because of the data contained in the PSD file or because of the way ImageMagick reads the PSD file.

After my tests, seems to me ImageMagick could do a better job during the PSD to PNG conversion, or at least provide an optional parameter to manage the alpha as Photoshop does.

Thanks
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: PSD to PNG alpha white border

Post by fmw42 »

My question was :
- Why a white background color was used when there is no need to (for non full transparent pixels)
- Was it because of the data contained in the PSD file or because of the way ImageMagick reads the PSD file.


In both cases it seems to be in the image or the way the image is interpreted by IM. I don't know. One of the IM experts will need to look into this.

How did you create this images? What were the steps? Is there some control in PS that says what the background will be under transparency? How did you add the transparency?

Too many unknowns for me to be able to give you an answer. Other than PSD files are very hard to translate if you are not photoshop.
Post Reply