Search code examples
c#image-processingbackgroundtransparencygdi+

HighQualityBicubic interpolation adds black background during resizing


I'm implementing image scaling function. When I use HighQualityBicubic interpolation mode (which is preferred from quality perspective) I'm getting black background on resized image(only in rectangle of source image. In padding area of destination rectangle it is still transparent). Input image is bmp with transparent background. Output is also bmp 32 bpp. Interesting thing when I change InterpolationMode to NearestNeighbor with some input images background is preserved as transparent after resizing and with another inputs it doesn't help. What I'm doing wrong?

public Bitmap DrawScaledImage(Image img, int width, int height, int scaledWidth, int scaledHeight)
    {
        var resultImg = new Bitmap(width, height, PixelFormat.Format32bppArgb);
        resultImg.SetResolution(img.HorizontalResolution, img.VerticalResolution);
        using (Graphics grPhoto = Graphics.FromImage(resultImg))
        {
            grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;
            grPhoto.DrawImage(img,
                new Rectangle(0, 0, scaledWidth, scaledHeight), //0;0 - image is drawn in left top corner
                new Rectangle(0, 0, img.Width, img.Height),
                GraphicsUnit.Pixel);
        }
        return resultImg;
    }

Input image Output image

Update Found funny thing: I've picked random transparent pixel in source image and took its ARGB in debug: it is ARGB=(255, 0, 0, 0) - pretty clear Then I've picked same pixel which was intended to be transparent in destination image after scaling and it is still ARGB=(255, 0, 0, 0) but in Paint.Net it is displayed as black. Then I've picked another random pixel from destination image that is displayed as transparent in Paint.Net and its ARGB schema is ARGB=(0, 0, 0, 0) - what?

So maybe stupid question - why for 1st pic transparent pixel is [255;0;0;0] but for 2nd [255;0;0;0] means black and transparent is [0;0;0;0]. it looks like something went down-under. and Alfa-channel reversed its meaning from 255- transparent to 255-opaque after scaling. Any ideas? Source pic Destination pic Debug


Solution

  • So I found that reason is some buggy behavior saving file in BMP format after resizing with InterpolationMode = InterpolationMode.HighQualityBicubic. Here are cases for reproduction: 1. If I create brand new image with pixel format PixelFormat.Format32bppArgb make some program manipulations with pixels (e.g. paint some line) and save as bmp - no problem at all, transparency is saved and visible in Paint.Net. 2. If I open existing bmp image already with transparency scale it up/down with Graphics.DrawImage method all seems good in debug. Transparent pixels have Alpha = 0. Then I save that image as bmp. Then Open it again in code like Image.FromFile("resized.bmp") and its pixel format is not same as it was before saving: it is now Format32bppRgb however saved image had Format32bppArgb. On opened image transparent pixels now have Alpha = 255. This is the cause why opening in Paint.Net I see black instead of transparent after resizing.

    I found 2 workarounds to preserve transparency after resizing: 1. Change InterpolationMode from InterpolationMode.HighQualityBicubic to InterpolationMode.NearestNeighbor. This solves transparency issue but not acceptable due to low quality method. 2. Save resized image as .png. This saves correct Alpha values and reopening image preserves it still. So it is my solution to refuse using BMP file format at all.