InterpolationMode HighQualityBicubic introducing artefacts on edge of resized images
Using some pretty stock standard C# code to resize an image, and place it on a coloured background
Image imgToResize = Image.FromFile(@"Dejeuner.jpg");
Size size = new Size(768, 1024);
Bitmap b = new Bitmap(size.Width, size.Height);
Graphics g = Graphics.FromImage((Image)b);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.FillRectangle(Brushes.Green, 0, 0, size.Width, size.Height);
g.DrawImage(imgToResize, new Rectangle(0,150,768, 570));
b.Save("sized_HighQualityBicubic.jpg");
The result has a funny artefact in the 0th and 1st columns of pixels. The 0th column appears to be mixed with the background colour, and the 1st column has been made lighter.
See the top left corner zoomed for high quality bicubic and bicubic.
..and HighQualityBilinear
This forum post appears to be someone with the same problem: DrawImage with sharp edges
The sounds like a bug to me? I can understand why the colours wou开发者_开发问答ld mix at the top of the resized image. But mixing the colours on the left / right edges doesn't make sense. Does anyone know of a fix to prevent these artefacts?
Update: very similar conversation going on in the comments here: GDI+ InterpolationMode
Shamelessly lifting the answer from this question, I found this fixes it:
using (ImageAttributes wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
g.DrawImage(input, rect, 0, 0, input.Width, input.Height, GraphicsUnit.Pixel, wrapMode);
}
Below is the resulting image of typical HighQualityBicubic
resizing (drawn over white background).
You can see semi-transparent pixels at edge lines. You can call it a bug. I think it is just a technical detail of the GDI+. And it is simple to workaround this artifact.
1) Prevent anti-aliasing.
...
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// add below line
g.CompositingMode = CompositingMode.SourceCopy;
...
With CompositingMode.SourceCopy
result image will show visible outline but not anti-aliased with background pixels.
2) Crop semi-transparent area
You can ignore those semi-transparent pixels altogether.
Image imgToResize = Image.FromFile(@"Dejeuner.jpg");
Size size = new Size(768, 1024);
Bitmap b = new Bitmap(size.Width, size.Height);
Graphics g = Graphics.FromImage((Image)b);
g.FillRectangle(Brushes.Green, 0, 0, size.Width, size.Height);
Bitmap b2 = new Bitmap(768 + 8, 570 + 8);
{
Graphics g2 = Graphics.FromImage((Image)b2);
g2.Clear(Color.White);
g2.InterpolationMode = InterpolationMode.HighQualityBicubic;
g2.DrawImage(imgToResize, new Rectangle(2, 2, 768 + 4, 570 + 4));
}
g.CompositingMode = CompositingMode.SourceCopy;
g.DrawImage(b2, 0, 150, new Rectangle(4, 4, 768, 570), GraphicsUnit.Pixel);
b.Save("sized_HighQualityBicubic.jpg");
Set the PixelOffsetMode property to HighQuality to get a better blend with the background at the edges.
精彩评论