views:

163

answers:

2

Hi,

I'm trying to scale down a Bitmap using GDI+ by doing the following:

Bitmap newImage = new Bitmap(NewWidth, NewHeight, Im.PixelFormat);           
Graphics g = Graphics.FromImage(newImage);

g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

g.ScaleTransform(0.1, 0.1); // 10%
g.DrawImage(Im, 0, 0, Im.Width, Im.Height);

Im is the original image, NewWidth and NewHeight are 10% or the original image. I've tested this on a 1000x1000 image (shrinking it down to 100x100)

The scaling is done correctly with high quality as promised but for some reason there is a gray border on the left, right and top borders (none on the bottom).

I assume this is due to the fact the all the image borders are white and the color "outside" of the bitmap is by default black so some of the default black get mixed into the scaling interpolation.

I looked for a way to set the default background color to white (white will do just fine) but couldn't find it anywhere..

My alternative is to pad the border with a white frame, scale the image down and the crop it but I was wondering if there is a simpler and less CPU consuming way?

Any ideas?

+1  A: 

Well. After some more digging I found it..

System.Drawing.Imaging.ImageAttributes Att = new System.Drawing.Imaging.ImageAttributes();
Att.SetWrapMode(System.Drawing.Drawing2D.WrapMode.Clamp, System.Drawing.Color.White); 
g.DrawImage(Im, new Rectangle(0,0,Im.Width,Im.Height), 0, 0, Im.Width, Im.Height, GraphicsUnit.Pixel, Att);
Gilad
A: 

Try adding an alpha overlay with an extra transparent pixel or two on all sides. This should get a better result than using either an explicit or implied solid color frame. Though converting to RGBA and adding the frame has a higher execution cost, if you are really interested in high quality and don't want to switch graphics libraries it may be the way to go.

martinr
The number of extra pixels you need in the frame will depend on scaling factors and the graphics library itself ("one or two" might not cut it).
martinr
Can you recommend a different graphic library? I only needs basic image operations (scale, rotate, translate..) but the quality should be, at least, as good as GDI+ best quality.
Gilad
Perhaps GDI (as opposed to GDI+) or DirectX. If most of your images are very very very small (eg <16 pixels/side) it may be faster to scale them with a software library such as AntiGrain (though this is GPL and C++). Test with graphics card hardware acceleration turned off to see if the base result with unaccelerated GDI is what you want then turn it back on again and compare with acceleration turned on.
martinr
(Probably a lot smaller than 16 pixels aside, in both source and destination actually, and AntiGrain still of course likely slower than DirectX.) If it was me I'd probably start using GDI.
martinr