Почему это графика.DrawImage обрезка часть моего изображения?

Если вы считаете следующее изображение, это довольно простой значок, размером 32x32. Вокруг значка прозрачный прямоугольник, хотя я заполнил четыре угла сплошным цветом во время тестирования.

Source Image

Теперь рассмотрим этот код, который просто рисует изображение, но в большем масштабе:

protected override void OnPaint(PaintEventArgs e)
{
  base.OnPaint(e);

  e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
  e.Graphics.DrawImage(Properties.Resources.icon_32a, new RectangleF(0, 0, 512, 512), new RectangleF(0, 0, 32, 32), GraphicsUnit.Pixel);
}

обратите внимание, что я рисую полное изображение, и я не пытаюсь обрезать его каким-либо образом, просто увеличьте его.

наконец, это вывод теста дает мне:

Painted example

замечать проблемы? Половина пикселей в верхнем ряду и левом столбце исчезли. Если я затем попытаюсь наложить сетку поверх этого, это выглядит довольно ужасно, поскольку сетка правильно выровнена, но изображение нет. Даже просто удвоив размер до 64, 64 вводит этот первый кадр строки/столбца.

Примечание, я также попытался смещать прямоугольник назначения на случай, если он рисовал до 0,0, но это не было случай.

Я также пытался использовать различные режимы интерполяции, но, насколько я мог судить через головную боль, вызывающую размытие, пиксели все еще были обрезаны, поэтому я не считаю, что это связано с режимом интерполяции.

Я также попытался использовать различные графические режимы, но помимо того, что это не помогло, мне все равно нужно придерживаться пикселей.

я попробовал снова с новой копией изображения на 96dpi из любопытства и получил тот же эффект, поэтому я не думаю, это разрешение исходных изображений.

хватаясь за соломинки и используя Rectangle вместо RectangleF также не имел никакого эффекта.

может ли кто-нибудь предложить какие-либо подсказки о том, почему этот очевидный урожай происходит?

спасибо;

2 ответов


на PixelOffsetMode по умолчанию PixelOffsetMode.Half:

указывает, что пиксели смещены на -.5 единиц по горизонтали и вертикально, для высокоскоростной сглаживания.

в вашем случае половина пикселя в исходном изображении составляет 8 пикселей в результирующем изображении, что именно то, что вам не хватает.

попробуйте установить его в PixelOffsetMode.None:

protected override void OnPaint(PaintEventArgs e)
{
     base.OnPaint(e);

     e.Graphics.PixelOffsetMode = PixelOffsetMode.None;
     e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
     e.Graphics.DrawImage(Properties.Resources.icon_32a, new RectangleF(0, 0, 512, 512), new RectangleF(0, 0, 32, 32), GraphicsUnit.Pixel);
}

просто охватывая ответ, подтвержденный пользователями, я попробовал его сам, и проблема была решена с PixelOffsetMode.HighQuality вместо none.

в C#

e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

мой случай c++ управляемый:

e->graphics->PixelOffsetMode = System::Drawing::Drawing2D::PixelOffsetMode::HighQuality;