Matt Wilko
Matt Wilko

Reputation: 27342

When overlaying two identically-sized images, one is offset

I am attempting to create an image by overlaying one on top of another. The code works, but the image I am overlaying seems to be slightly stretched and I can't work out why.

So the code just creates a blank red 24x24 rectangle, then I overlay a 24x24 png file which looks like this:

enter image description here

What I am expecting is this:

enter image description here

But I actually get this:

enter image description here

Using backGround As New Bitmap(24, 24, Imaging.PixelFormat.Format32bppArgb)
        Using g = Graphics.FromImage(backGround)
            Using brush1 As New SolidBrush(Color.Red)
                g.FillRectangle(brush1, 0, 0, 24, 24)
                Using topimage = Image.FromFile("C:\Scratch\ManNoRecords24.png")
                    g.DrawImage(topimage, New Point(0, 0))
                End Using
            End Using
        End Using
        backGround.Save("C:\Scratch\Emp.png", Imaging.ImageFormat.Png)
    End Using

Debugger showing the properties of the topImage:

enter image description here

Upvotes: 2

Views: 234

Answers (1)

Jens
Jens

Reputation: 6375

You can use

g.DrawImageUnscaledAndClipped(topimage, New Rectangle(0, 0, 24, 24))

instead, to avoid any scaling of the source image while drawing it. This works but I am actually not quite sure what is wrong with your solution.

From the Reference Source, DrawImageUnscaledAndClipped seems to use Pixel as the default unit for the image size and hence ignores the DPI setting of the source image:

/// <include file='doc\Graphics.uex' path='docs/doc[@for="Graphics.DrawImageUnscaledAndClipped"]/*' />
/// <devdoc>
/// </devdoc>
public void DrawImageUnscaledAndClipped(Image image, Rectangle rect) {
    if(image == null) {
        throw new ArgumentNullException("image");
    }

    int width = Math.Min(rect.Width, image.Width);
    int height = Math.Min(rect.Height, image.Height);

    //We could put centering logic here too for the case when the image is smaller than the rect
    DrawImage(image, rect, 0, 0, width, height, GraphicsUnit.Pixel);
}

DrawImage and DrawImageUnscaled do not and then probably rescale the image based on its internal DPI setting, which Matt found out to be less than the default 96, which leads to stretching of the image:

/// <include file='doc\Graphics.uex' path='docs/doc[@for="Graphics.DrawImageUnscaled"]/*' />
/// <devdoc>
/// </devdoc>
public void DrawImageUnscaled(Image image, Point point) {
    DrawImage(image, point.X, point.Y);
}

Upvotes: 4

Related Questions