3

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();
 }
BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
BPS
  • 607
  • 8
  • 29
  • And problem is? You don't want white background? – Adriano Repetti Dec 15 '14 at 20:05
  • Yes - like I mentioned above, it must be transparent. As you probably know, pasting a "transparent" bitmap to a rich text field yields a grey background. – BPS Dec 15 '14 at 20:07
  • `g.Clear(System.Drawing.Color.White);` why are you doing this then? – Blorgbeard Dec 15 '14 at 20:08
  • Blorgbeard: "My current solution first renders a white background." – BPS Dec 15 '14 at 20:09
  • I still don't understand why you're doing that if your question is how **not** to have a white background.. – Blorgbeard Dec 15 '14 at 20:10
  • @Blorgbeard: That is my current solution, which is OK for most applications. What if the application has a textured background or a background that is not white? I need to be able to support those scenarios, too. – BPS Dec 15 '14 at 20:14
  • The better solution is to put it on the clipboard as PNG stream. Most modern apps do it that way nowadays. – Nyerguds Sep 26 '17 at 11:59

2 Answers2

3

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.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • Thanks for the code snippet, but I'm back to the grey background (testing by pasting in Wordpad) – BPS Dec 15 '14 at 20:16
  • Wordpad, it's how _old_ RTF control handles transparency. Newer versions (just tested on Win 8.1) properly handle that (no gray background). If you do not know target control (then you can't read its background color) you may use FromArgb(254, 255, 255, 255). White if not supported, transparent where it's handled. – Adriano Repetti Dec 15 '14 at 20:20
  • Adriano Repetti Thanks for that bit of information. I did not know there was an older/newer way of handling. I may just have to put code in to handle those cases. – BPS Dec 15 '14 at 20:23
  • @BPS unfortunately you there is little you can do and it's hard to _detect_ if target control will handle it well or not, that's why a dirty workaround... – Adriano Repetti Dec 15 '14 at 20:25
  • So, just to be clear - This code: g.Clear(System.Drawing.Color.FromArgb(254, 255, 255, 255)); will render the bitmap white to handle the cases where transparent appears as grey, and this code: tempImage.MakeTransparent(); will actually render the bitmap transparent where Windows supports it? – BPS Dec 15 '14 at 20:34
  • yes but unless you use Color.Transparent then you have to specify same color for MakeTransparent too. Then g.Clear(System.Drawing.Color.FromArgb(254, 255, 255, 255)); and tempImage.MakeTransparent(System.Drawing.Color.FromArgb(254, 255, 255, 255)); – Adriano Repetti Dec 15 '14 at 20:52
  • It still isn't completely transparent. Very close, but I can still see the background. Any other suggestions to make it 100% transparent? – BPS Dec 16 '14 at 20:05
  • @BPS if you see it's not _completely_ transparent then...it's supporting transparency but it picks wrong background color. Well nothing (AFAIK) you can do about that because you can't know to which control it'll be pasted and, for RTF, it also may have a colored background. I'd say it's not your problem if target control is buggy. You may also try to go through a metafile which embeds bitmap: http://tech.pro/tutorial/899/wpf-tutorial-getting-from-wpf-to-a-metafile-and-onto-the-clipboard (in case something is different with that). In that case I'd use transparency Color.FromArgb(0, Color.White) – Adriano Repetti Dec 17 '14 at 08:58
  • Most applications nowadays accept the clipboard format "PNG", with as data object a `MemoryStream` containing the actual PNG image bytes. – Nyerguds Sep 26 '17 at 12:32
1

The Windows clipboard, by default, does not support transparency, but you can put content on the clipboard in many types together to make sure most applications find some type in it that they can use. Generally, if, in addition to the normal nontransparent clipboard Bitmap format, you put the image on the clipboard in both PNG and DIB formats, most applications will be able to use at least one of them to get the image in a format they support as being transparent.

These formats are put on the clipboard in a specific way, though. They need to have their data (for png, that's not the loaded image object but the actual png file's bytes) put in a MemoryStream that is then put on the clipboard.

PNG put on the clipboard like that will be accepted by a multitude of applications, including Gimp and the newer MS Office. And of course, if you implement reading for it too, you can use it in your own application. The (rather dirty) DIB format should take care of most other applications, if they indeed support transparent image pasting at all.

I detailed how to do both the copying and the retrieving in this answer:

https://stackoverflow.com/a/46424800/395685

Nyerguds
  • 5,360
  • 1
  • 31
  • 63