Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Graphics.DrawImage cropping part of my image?

If you consider the following image, it's a fairly basic icon, sized at 32x32. Around the icon is a transparent rectangle, although I filled in the four corners with a solid colour while testing.

Source Image

Now consider this code, which simply draws the image, but at a larger scale:

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

Note that I'm drawing the full image and I'm not attempting to crop it in any way, just enlarge it.

Finally, this is the output the test gives me:

Painted example

Notice the problem? Half of the pixels in the top row and left column have vanished. If I then try and overlay a grid on top of this, it looks pretty awful as the grid is correctly aligned, but the image is not. Even just doubling the size to 64, 64 introduces this first row/column crop.

Note, I also tried offset the destination rectangle just in case it was drawing before 0,0, but this was not the case.

I also tried using different interpolation modes, but as far as I could tell through the headache inducing blur, the pixels were still cropped, so I don't believe it's due to the interpolation mode.

I also attempted using different graphics modes, but aside from the fact that it didn't seem to help, I need to stick with pixels anyway.

I tried again with a new copy of the image at 96dpi out of curiosity and got the same effect so I don't think it's the resolution of the source images.

Clutching at straws and using Rectangle instead of RectangleF also had no effect.

Can anyone offer any clues as to why this apparent crop is occurring?

Thanks;

like image 446
Richard Moss Avatar asked Dec 28 '12 13:12

Richard Moss


2 Answers

The PixelOffsetMode is set by default to PixelOffsetMode.Half:

Specifies that pixels are offset by -.5 units, both horizontally and vertically, for high speed antialiasing.

In your case half a pixel in the original image is 8 pixels in the resulting image, which is exactly what you are missing.

Try setting it to PixelOffsetMode.None PixelOffsetMode.HighQuality:

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

     e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
     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);
}
like image 99
Rotem Avatar answered Oct 07 '22 19:10

Rotem


Just covering reply comfirmed by users, I tried it myself and the problem was solved with PixelOffsetMode.HighQuality instead none.

c#

e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;

my case c++ managed:

e->graphics->PixelOffsetMode = System::Drawing::Drawing2D::PixelOffsetMode::HighQuality;
like image 21
Andrei Ortolan Avatar answered Oct 07 '22 17:10

Andrei Ortolan