title: GDI+ Compose bitmap with transparency
body: <p>I'd like to rewrite this method by using <code>Graphics.DrawImage()</code>. No matter the <code>PixelFormat</code> of <code>bitmapToDrawOn</code> and <code>bitmapDrawn</code> values (I tried all combinations) which should be typically <code>PixelFormat.Format32bppRgb</code> and <code>PixelFormat.Format32bppArgb</code> (or <code>PixelFormat.Format32bppPArgb</code>), I cannot obtain this result.</p>
  
  <p>This compose operation seems pretty obvious to me, so it looks like I am missing something.</p>
  
  <pre><code>private static void ComposeBitmapWithTransparency(Bitmap bitmapToDrawOn, Bitmap bitmapDrawn) {
     Debug.Assert(bitmapToDrawOn != null);
     Debug.Assert(bitmapToDrawOn.PixelFormat == PixelFormat.Format32bppRgb);
  
     Debug.Assert(bitmapDrawn != null);
     Debug.Assert(bitmapDrawn.PixelFormat == PixelFormat.Format32bppArgb);
  
     var width = bitmapToDrawOn.Width;
     Debug.Assert(bitmapDrawn.Width == width);
  
     var height = bitmapToDrawOn.Height;
     Debug.Assert(bitmapDrawn.Height == height);
  
     var rect = new Rectangle(0, 0, width, height);
     var bitmapToDrawOnData = bitmapToDrawOn.LockBits(
           rect,
           ImageLockMode.ReadWrite,
           bitmapToDrawOn.PixelFormat);
     var bitmapDrawnData = bitmapDrawn.LockBits(
           rect,
           ImageLockMode.ReadOnly,
           bitmapDrawn.PixelFormat);
  
     unsafe {
        var pBitmapToDrawOn = (StructPixel*)bitmapToDrawOnData.Scan0;
        var pBitmapDrawn = (StructPixel*)bitmapDrawnData.Scan0;
  
        for (int y = 0; y &lt; height; y++) {
           for (int x = 0; x &lt; width; x++) {
              byte r = pBitmapToDrawOn-&gt;R;
              byte g = pBitmapToDrawOn-&gt;G;
              byte b = pBitmapToDrawOn-&gt;B;
  
              byte rX = pBitmapDrawn-&gt;R;
              byte gX = pBitmapDrawn-&gt;G;
              byte bX = pBitmapDrawn-&gt;B;
  
              // Only the transparency of bitmapDrawn is taken account.
              byte alphaX = pBitmapDrawn-&gt;Alpha;
              byte alphaXComplement = (byte)(255 - alphaX);
  
              pBitmapToDrawOn-&gt;R = (byte)((r * alphaXComplement + rX * alphaX) &gt;&gt; 8);
              pBitmapToDrawOn-&gt;G = (byte)((g * alphaXComplement + gX * alphaX) &gt;&gt; 8);
              pBitmapToDrawOn-&gt;B = (byte)((b * alphaXComplement + bX * alphaX) &gt;&gt; 8);
  
              pBitmapToDrawOn++;
              pBitmapDrawn++;
           }
        }
     }
  
     bitmapDrawn.UnlockBits(bitmapDrawnData);
     bitmapToDrawOn.UnlockBits(bitmapToDrawOnData);
  }
  </code></pre>
  
  <p>The code for <code>StructPixel</code>:</p>
  
  <pre><code>   [StructLayout(LayoutKind.Explicit)]
     public struct StructPixel {
        [FieldOffset(0)]
        public byte B;
        [FieldOffset(1)]
        public byte G;
        [FieldOffset(2)]
        public byte R;
        [FieldOffset(3)]
        public byte Alpha;
     }
  </code></pre>