Search code examples
c#winformsbitmaprotationimage-rotation

C# merge two rotated bitmaps


I am trying to rotate two bitmaps, then copy the results into a third one.

Bitmap bmp_1 = new Bitmap(Program.Properties.Resources.MyImage); // 100x100 px
Bitmap bmp_2 = new Bitmap(Program.Properties.Resources.MyImage); // 100x100 px
Bitmap bmp_merged = new Bitmap(200, 100, PixelFormat.Format32bppArgb);

float angle, bw2, bh2;

using (Graphics g = Graphics.FromImage(bmp_merged))
{
    using (Graphics graphics = Graphics.FromImage(bmp_1))
    {
        angle = 15;

        bw2 = bmp_1.Width / 2f;
        bh2 = bmp_1.Height / 2f;

        graphics.TranslateTransform(bw2, bh2);
        graphics.RotateTransform(angle);
        graphics.TranslateTransform(-bw2, -bh2);
        graphics.DrawImage(bmp_1, 0, 0);
    }
    using (Graphics graphics = Graphics.FromImage(bmp_2))
    {
        angle = 35;

        bw2 = bmp_2.Width / 2f;
        bh2 = bmp_2.Height / 2f;

        graphics.TranslateTransform(bw2, bh2);
        graphics.RotateTransform(angle);
        graphics.TranslateTransform(-bw2, -bh2);
        graphics.DrawImage(bmp_2, 0, 0);
    }
    g.DrawImage(bmp_1, 0, 0);
    g.DrawImage(bmp_2, 100, 0);
}

Issue:

After using graphics.DrawImage(bmp_1, 0, 0); I expected that bmp_1 will be a rotated image.

But it's actually the original bmp_1 image and its rotated version drawn over it.


Solution

  • Drawing into a Graphics object obtained from a Bitmap instance doesn't clear the Bitmap instance first. It just draws on top of whatever was there.

    Instead of modifying the bitmaps you start with, you should just draw them rotated into the destination. For example, something like this:

    using (Graphics g = Graphics.FromImage(bmp_merged))
    {
        angle = 15;
    
        bw2 = bmp_1.Width / 2f;
        bh2 = bmp_1.Height / 2f;
    
        g.TranslateTransform(bw2, bh2);
        g.RotateTransform(angle);
        g.TranslateTransform(-bw2, -bh2);
        g.DrawImage(bmp_1, 0, 0);
    
        angle = 35;
    
        bw2 = bmp_2.Width / 2f;
        bh2 = bmp_2.Height / 2f;
    
        g.ResetTransform();
        g.TranslateTransform(bw2, bh2);
        g.RotateTransform(angle);
        g.TranslateTransform(-bw2, -bh2);
        g.DrawImage(bmp_2, 0, 0);
    }
    

    Naturally, you should really factor the code for drawing a bitmap rotated at a specific angle out into its own method, so that you don't have two copies of the code. But the above should address your basic problem.