Why can't Bilinear/Bicubic resize transparent images properly?

Started by
8 comments, last by Helicobster 11 years, 6 months ago
I've noticed that Bilinear/Bicubic resize filters refuse to blend transparent images. No matter what graphics program you're using. Photoshop, Gimp, Paint Shop Pro. The same thing. They fill the transparent pixels up with random grey shades and blend all of the edge pixels in the image with the grayscale noise, which is profoundly stupid as far as I can see. I understand they're made to average pixels by taking input from surrounding pixels. But clearly it can't require eight neighbor pixels to each one - because rectangular images *still* have edges. And the edges do not end up averaged with random grayscale noise.

So could someone explain to me exactly why Bilinear/Bicubic don't treat transparent pixels the exact same way they treat the edge of a rectangular image?

Attached examples of what I'm talking about(may need to zoom in to see all the grayscale artifacts). First image is transparent, second is the full sized image with a background, third is resized image with background(I resized it without a background and added it afterwards).

Felt like this topic belongs slightly more here than the creative graphics section, and I figure someone here is more likely to know why this is handled the way it is.

"You can't say no to waffles" - Toxic Hippo

Advertisement
I have not been able to reproduce the problem with the steps you've provided with GIMP. I have taken the first image, resized it to 50%, and added a magenta background layer, then collapsed the image onto the background, and the image has no artifacts. However, I noticed that I was able to reproduce your problem if I were to remove the alpha channel from the image then do a magenta flood-fill on the background.

Perhaps somewhere along the way the alpha channel is being lost somewhere along the way, perhaps being merged with a white background...
Resizing by halves will always reduce any problem. Try something like %65 or %85. If you still don't see if, please do save it as a png and attach it. I would be interested in seeing it. I was reading about this problem and someone from Adobe's development team indicated this is just a fact of life. If it can be gotten around with raster images - awesome wink.png

Then it's just a matter of figuring out how. I've been aware of this problem for over ten years. I just never asked or looked into it before. If I *really* needed transparency, I would just use nearest neighbor/pixel resize, which has no averaging and thus doesn't cause this. But old bilinear and bicubic do. Or always have that I've seen.

"You can't say no to waffles" - Toxic Hippo

Your source image is the problem. There're similiar problems with alpha blending of transparent textures and a solution is pre-multiplied alpha channel.

Back to your problem, go into gimp, add the alpha layer from the image , and press either ctrl+mouse or alt+mouse on the alpha layer. The alpha layer now have a red border and the alpha channel is disabled, displaying only the RGB channels. Your image will most likely have a white background where the image is transparent. Fill this background to black (=edge color of your drawing), enable the alpha channel again (ctrl+mouse/alt+mouse) , apply the alpha channel and do your resizing again.

When resizing to a smaller resolution, your border got blended with neighbor pixels, which are white and not black, therefore the grey artifacts.
Works just fine when I resize in paint.net (scaled 84% and 56%). Are you sure you didn't flood fill with magenta instead of placing a magenta layer behind your image? (if i flood fill the result instead of adding a background layer it looks pretty much exactly like your example)
I like computer graphics and digital image processing, and therefore made a painting program in my spare time. This program works on RGBA by default for almost every filter. So possibly it will rescale correctly for you. Does it do what you want? http://sourceforge.n...ects/lodepaint/

If it doesn't work, then pick foreground color R=0, B=0, G=0, A=0 (so black and fully transparent, where black is the same color as the outlines of the image), and floodfill that on the transparent areas. Then try the resizing again.
When resizing to a smaller resolution, your border got blended with neighbor pixels, which are white and not black, therefore the grey artifacts.
Yes, I'm aware that I could change the alpha channel to black and get a black rather than grey ring around the image. I'm just curious why it's merging with the alpha channel. It does not do this on the outermost pixels. So it can average without eight neighbor pixels. There is nothing to the left of or above pixel 0,0 but you don't see 0,0 ending up whiter. Why does it fill in transparency with the alpha channel color instead of treating it like the border of a rectangle? I don't see why it blends with the alpha channel. That makes no sense to me at all.

To clear up, this isn't a "help me resize my image" thread. And as far as I can see no one here is talking about resizing a fully transparent image with either the bilinear or bicubic filters... This isn't a problem when interpolation isn't applied.

I know there are tricks to overcome this issue, I've been relying on them for a decade. Mostly, magic wand+add border of 2 pixels, resize with a totally different color and use magic want+delete to clean(and take care of the rest by hand).
I was just curious why it treats border pixels on an uneven surface differently that the outermost pixels of a rectangle.


Works just fine when I resize in paint.net (scaled 84% and 56%). Are you sure you didn't flood fill with magenta instead of placing a magenta layer behind your image? (if i flood fill the result instead of adding a background layer it looks pretty much exactly like your example)
What resizing method are you using? Nearest neighbor won't. It happens on bilinear/bicubic.

I like computer graphics and digital image processing, and therefore made a painting program in my spare time. This program works on RGBA by default for almost every filter. So possibly it will rescale correctly for you. Does it do what you want?
Hi, Lode smile.png I remember you helped me something before. I like the program quite a lot and it may just compete with my old copy of PSP7 for stripped down editor. Thanks for sharing. After using it a little more I'll try to remember to give some feedback. I do like it's design. A lot of features, but without all the clutter of Photoshop.
Kind of reminds me of Pixia but with better priorities.

It does however, use the same bilinear/bicubic resize functions as everyone else, so same problem wink.png

"You can't say no to waffles" - Toxic Hippo

There's no reason that this shouldn't work in theory. If you've got a reproducible case that does something obviously wrong, send a bug report to the authors of your art tool.

In Photoshop, there's generally two ways of working with transparency.
The first, is to have a layer where you actually delete some pixels, so you have "transparent" pixels on that layer -- I've found that this mode can behave in some pretty weird ways in certain situations.
The second is to actually ensure that all pixels have colour, and represent transparency via another channel (either the alpha channel, or a mask channel) -- I've found this mode to be much better behaved.

E.g. if I've got a cut-out sprite on a black background, with a transparency mask layer, and resize it, then it does what it supposed to do. The black/white transparency layer develops a grey gradient, and the colour layer develops a fade-to-black edge. When I then render the image in-game with pre-multiplied alpha (src=one, dst=1-srcAlpha) then it appears as intended.


N.B. if you're expecting the resulting image to still have a hard on/off transparency mask, then that is a problem. Bicubic/bilinear filters should produce a fractional alpha result.

What resizing method are you using? Nearest neighbor won't. It happens on bilinear/bicubic.


"Best Quality" which in this case means supersampling. Works fine with bilinear and bicubic as well though. As I said, the effect you are getting only happens if i flood fill the transparent areas with magenta instead of placing a magenta layer behind the (resized) image.
The problem is that the transparent pixels bordering the opaque pixels are still light grey in their RGB values, even when they have zero alpha.

So when you take anything other than a nearest-neighbour sample of those borders, you get a blend of each pixel and its neighbours. So you're getting a blend of alpha values and a blend of RGB values.

So say you get a 50-50 blend of opaque warrior and transparent background. That's a 50-50 blend of alphas (in this case: 50%) and a 50-50 blend of RGB values, in this case a shade of grey that's between the background colour and the warrior's colour. The result you're getting is in fact completely correct - it's your source material that's gone wrong.

The solution is to always, always save your sprite art with a black background, even where it's completely transparent. Some programs will solve the problem for you automatically, but most will not. Don't expect a game engine or realtime graphics API to get it right, because alpha blending always expects the foreground layer's transparent areas to fade to black.

This topic is closed to new replies.

Advertisement