Search code examples
c#pngtransparencyclipboard

C# Win8: copy .PNG to the Windows clipboard; paste with transparency preserved


I have been tasked with capturing an image, copy it to the clipboard, and paste it to the application below. I must be able to support pretty much any rich text field, and it must preserve transparency. My current solution first renders a white background. Here is my code:

The RenderTargetBitmap contains the image that I wish to copy as a .PNG

public static void CopyImageToClipboard(RenderTargetBitmap b)
{

    MemoryStream stream = new MemoryStream();
    PngBitmapEncoder encoder = new PngBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(b));
    encoder.Save(stream);

    Bitmap bmp = new Bitmap(stream);
    Bitmap blank = new Bitmap(Convert.ToInt32(b.Width), Convert.ToInt32(b.Height));
    Graphics g = Graphics.FromImage(blank);
    g.Clear(System.Drawing.Color.White);
    System.Drawing.Image img = System.Drawing.Image.FromStream(stream);
    g.DrawImage(img, 0, 0, Convert.ToInt32(b.Width), Convert.ToInt32(b.Height));

    Bitmap tempImage = new Bitmap(blank);
    blank.Dispose();
    img.Dispose();

    bmp = new Bitmap(tempImage);
    tempImage.Dispose();

    System.Windows.Forms.Clipboard.SetImage(bmp);
    stream.Dispose();
 }

Solution

  • Just pick a random color to use it as background, let's say

    var background = Color.FromArgb(1, 255, 1, 255);
    

    Erase background to it:

    g.Clear(background); // instead of System.Drawing.Color.White
    

    Then make that color transparent:

    Bitmap tempImage = new Bitmap(blank);
    tempImage.MakeTransparent(background);
    

    Note that also default transparent color works pretty well, no need to pick a magic color (check if you need to Clear() background, it may be - I didn't check - default bitmap background):

    g.Clear(Color.Transparent);
    // ...
    tempImage.MakeTransparent();
    

    EDIT Some older RTF control versions won't handle transparency and there is nothing (AFAIK) you can do for it. A half decent workaround (if you can't detect control class of paste target and read its background color) is to use Color.FromArgb(254, 255, 255, 255). White where transparency isn't supported and...completely transparent (because of MakeTransparent()) where it is.