Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Graphics.DrawImage() clips image when using RotateTransform()

I have following code to draw my border2.bmp in 4 direction

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Bitmap border = new Bitmap("border2.bmp");
    int borderThick = border.Height;

    Graphics g = e.Graphics;
    Size region = g.VisibleClipBounds.Size.ToSize();

    Rectangle desRectW = new Rectangle(0, 0, region.Width - borderThick, borderThick);

    // 1. LEFT - RIGHT border
    g.TranslateTransform(30, 30);
    g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel);

    // 2. UP - BUTTOM border
    g.ResetTransform();
    g.TranslateTransform(50, 50);
    g.RotateTransform(90);
    g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel);

    // 3. RIGHT-LEFT border
    g.ResetTransform();
    g.TranslateTransform(100, 100);
    g.RotateTransform(180);
    g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel);

    // 4. BOTTOM - UP border
    g.ResetTransform();
    g.TranslateTransform(150, 150);
    g.RotateTransform(270);
    g.DrawImage(border, desRectW, desRectW, GraphicsUnit.Pixel);
}

My original image is:

enter image description here

But the result of rotations are not exactly as I expected. 90 degrees is missing the first red line, 270 degrees is missing first black column, and 180 degrees is missing both.

Like image I attached:

enter image description here

PS: you can get border2.bmp at: https://i.sstatic.net/GtgGA.png

Edit: I tried g.PixelOffsetMode = PixelOffsetMode.HighQuality; as @Peter Duniho comment, but I found it also does't draw correctly. Example: 4 line is not starting at same position as we expect.

g.TranslateTransform(50, 50);

// LEFT - RIGHT border
g.DrawLine(Pens.Red, 0, 0, 100, 0);

// UP - BOTTOM border
g.RotateTransform(90);
g.DrawLine(new Pen(Color.FromArgb(128, Color.Blue)), 0, 0, 100, 0);

// RIGHT-LEFT border
g.RotateTransform(90);
g.DrawLine(new Pen(Color.FromArgb(128, Color.Green)), 0, 0, 100, 0);

// BOTTOM - UP border
g.RotateTransform(90);
g.DrawLine(new Pen(Color.FromArgb(128, Color.Gray)), 0, 0, 100, 0);
like image 319
KevinBui Avatar asked Feb 23 '26 09:02

KevinBui


1 Answers

I can't really explain why this happens, except that any graphics API is necessarily going to include optimizations which may lead to imprecise behaviors at times and it seems that you are running into such a situation here.

In your particular example, the problem can be corrected by adding the following statement to the code, before you draw the images:

g.PixelOffsetMode = PixelOffsetMode.HighQuality;

Setting it to Half will also work. It is equivalent to HighQuality (or technically, HighQuality is equivalent to it…but I find HighQuality more descriptive in the code :) ).

This will slow the rendering of the bitmap down somewhat, but probably not in a way that is perceptible to your users.

While the .NET documentation isn't very helpful in terms of describing this setting, the native Win32 docs for the same feature has slightly more detail: PixelOffsetMode enumeration. From the description, one can infer that with the logical center of the pixel at (0,0), it's possible to lose a pixel on one edge when rotating (and/or gain a pixel on another edge). Switching to Half fixes this.

like image 118
Peter Duniho Avatar answered Feb 24 '26 23:02

Peter Duniho