InterpolationMode HighQualityBicubic представляет артефакты на краю измененных изображений

Использование некоторого довольно стандартного С# кода для изменения размера изображения и размещения его на цветном фоне

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");

Результат имеет забавный артефакт в 0-м и 1-м столбцах пикселей. 0-я колонка, кажется, смешана с цветом фона, и 1-й столбец стал легче.

См. верхний левый угол, увеличенный для бикубического и бикубического качества.

HighQualityBicubic

Bicubic

.. и HighQualityBilinear

HighQualityBilinear

Это сообщение на форуме похоже на кого-то с той же проблемой: DrawImage с острыми краями

Звучит как ошибка для меня? Я могу понять, почему цвета будут смешиваться в верхней части измененного изображения. Но смешивание цветов на левом/правом краях не имеет смысла. Кто-нибудь знает об исправлении для предотвращения этих артефактов?

Обновление: очень похожий разговор происходит в комментариях здесь: GDI + InterpolationMode

Ответ 1

Бесстыдно поднимая ответ из этого вопроса, я нашел, что это исправляет его:

using (ImageAttributes wrapMode = new ImageAttributes())
{
    wrapMode.SetWrapMode(WrapMode.TileFlipXY);
    g.DrawImage(input, rect, 0, 0, input.Width, input.Height, GraphicsUnit.Pixel, wrapMode);
}

Ответ 2

Ниже приведено изображение типичного изменения размера HighQualityBicubic (нарисовано на белом фоне).

Вы можете видеть полупрозрачные пиксели по краям. Вы можете назвать это ошибкой. Я думаю, что это просто техническая деталь GDI+. И это просто, чтобы обойти этот артефакт.

1) Предотвращение сглаживания.

...
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// add below line
g.CompositingMode = CompositingMode.SourceCopy;
...

С CompositingMode.SourceCopy результат будет показывать видимый контур, но не сглаживаться с фоновыми пикселями.

2) Обрезать полупрозрачную область

Вы можете полностью игнорировать эти полупрозрачные пиксели.

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");

Ответ 3

Задайте свойство PixelOffsetMode для HighQuality, чтобы получить лучшую смесь с фоном по краям.