Clipboard with transparency



After reading this question I have determined that

Rasterize[Graphics[Circle[]], "Image", Background -> None]

allows you to do Save As on the Image and the keep the transparency. But if you use the the menus Edit->Copy As->Bitmap or Edit->Copy As->Metafile I have noticed that graphics fail to keep their transparency when pasting into other applications.

Now I can Export an image and copy and paste it back into Mathematica(or another application) and everything works just fine, therefore the clipboard can hold references to transparent images.

Doing some further investigation, here is an image of ClipSpy showing how CF_HDROP and FileNameW(FileName doesn't seem to contain the entire piece of text) contain the location of the png file, allowing you to paste it into other applications.

enter image description here

When working with lots of images, exporting every image becomes quite tedious. It seems like their should be some way to automatically have Mathematica export the file and store a reference of it in the clipboard to retain the image transparency.

So how do I patch or extend Mathematica's clipboard functionality to work with transparent images? Possible useful links for myself and others 1 2 3 4

EDIT: It appears a handful of applications like Inkscape and Powerpoint don't allow you to paste with only a CF_DROP reference. Instead it seems to be better to store the actual image as a PNG on the clipboard.


Posted 2013-05-29T20:51:27.993

Reputation: 7 329

What program are you trying to paste into? – 0xFE – 2013-05-30T03:09:46.640

I'm not sure what you are trying to do - if you really have a lot of images, then exporting them as files can be done en masse. It seems to me that dealing with each individual image separately via the clipboard is the definition of tedious. – bill s – 2013-05-30T03:32:15.210



Here is a considerable simplification of Liam's accepted answer. It avoids the need to create and compile a C# program. This is basically just a small modification to Simon Woods' answer, so that it writes directly to the clipboard instead of creating a temporary file on disk. This avoids the need to clean up the file afterward.


WriteToClipboardTransparent[g_] :=
    Module[{png, strm, dataObject},
        png = ExportString[Rasterize[g, "Image", Background->None], "PNG"];
            strm = NETNew["System.IO.MemoryStream", ToCharacterCode[png]];
            dataObject = NETNew["System.Windows.Forms.DataObject"];
            dataObject@SetData["PNG", strm];

The button and menu commands would then simply call WriteToClipboardTransparent[NotebookRead[InputNotebook]].

Todd Gayley

Posted 2013-05-29T20:51:27.993

Reputation: 4 078

@GlenLipka Yes I believe so athlough I'm not entirely sure of the best way to do such. – William – 2014-03-01T20:53:22.757

@ToddGayley, This doesn't work for me since SetData is not recognized. (I'm using Mathematica 11.1 on Ubuntu 17.04) – Miladiouss – 2017-07-27T00:19:44.887

@Miladiouss sadly this is using .NET so it won't work with out such. I doubt you could use mono so Ubuntu probably needs a different solution. – William – 2018-01-30T23:02:02.720


Awesome! How did you get bye without having to use [STAThread]? According to I think you need to run under an a STAThread. I couldn't get the code to run consistently without such an attribute. I mean if it works, it works :)

– William – 2013-07-08T19:12:00.610

4You do need the [STAThread] attribute when writing a standalone program, but the .NET/Link thread that handles calls from Mathematica already has that attribute. If you're curious, you can see this property being set in line 79 of Reader.cs in the .NET/Link source code. – Todd Gayley – 2013-07-08T20:33:52.610

Could this same technique be used to create an .exe file for Snagit? This article has a similar problem, but didn't cover the transparency issue.

– Glen Lipka – 2013-07-15T17:40:08.890


Something like this? It does just what you suggested: export the file and then place a FileDrop reference to it on the clipboard.


exportToClipboard[graphics_] := Module[{dob, file},
  file = FileNameJoin[{$TemporaryDirectory, "mmaClipboard.png"}];
  Export[file, graphics];
   dob = NETNew["System.Windows.Forms.DataObject"];
   dob @ SetData[DataFormats`FileDrop, True, {file}];


image = Rasterize[Graphics[Circle[]], "Image", Background -> None];


Paste into Powerpoint...

enter image description here

Simon Woods

Posted 2013-05-29T20:51:27.993

Reputation: 81 905

Can you use ExportString to avoid dumping to a file? – Ajasja – 2013-05-31T19:12:44.700

2@Ajasja, with this method only the file name goes onto the clipboard, not the contents. It's using the same mechanism as if you "copy" a file on the desktop and paste it into an application, the application just receives the file path and imports the file itself. You can put image data onto the clipboard but it has to be converted to a specific bitmap format. This way is easier! – Simon Woods – 2013-05-31T20:11:24.113

I do love the simpleness of this. I was orignally trying to use C APIs this is better. @Ajasja I have noticed that this solution doesn't work with a select number of apps(Inkscape) while it works great with others like Photoshop. I am looking into copying the image as a PNG to the clipboard. I believe it involves something like MemoryStream ms = new MemoryStream(); bitmap.Save(ms, ImageFormat.Png); IDataObject dataObject = new DataObject(); dataObject.SetData("PNG", false, ms); System.Windows.Forms.Clipboard.Clear(); System.Windows.Forms.Clipboard.SetDataObject(dataObject, false); – William – 2013-05-31T20:18:12.920

@Ajasja It appears dragging and dropping the png file works fine in most any application, while pasting only sometimes works, I am going to try and create a pop up window that opens and stays on top of other windows temporarily while you drag the image into another application. – William – 2013-05-31T20:26:04.290

For anyone using this regularly, I would advise replacing Directory[] with $TemporaryDirectory to avoid putting pictures in random places across your system. My Directory[] location changes depending on the script and what files I might be working on. – William – 2013-06-11T18:43:54.240

@Liam, good idea. – Simon Woods – 2013-06-11T20:40:20.867


The following code copies the actua PNG image to the clipboard with transparency. This varies from the other answer in that it actual stores the entire image instead of a reference to the file. This code will likely work with more applications then the one above. It currently uses the Ctrl+Shift+C to copy with transparency. The code takes a while to run currently because the program gets recompiled and rerun each time you hit the keyboard shortcut. Please suggest any modifications to help make it more portable or faster

To test that it is working run.

   WriteToClipboard["PNG", ExportString[
      , "Image", Background -> None], {"Base64", "PNG"}]]

The following prints a Button that copy the selected Graphic as a PNG, and sets the keyboard shortcut Ctrl + Shift + C.

enter image description here

(* Construct Button *)
Print[Button["Copy Image",
   Head[NotebookRead[EvaluationNotebook[]]] === GraphicsBox,Null,
   MessageDialog["You must select a Graphic."];
       Rasterize[NotebookRead[EvaluationNotebook[]], "Image", 
        Background -> None], {"Base64", "PNG"}]];
(* Set up keyboard shortcut *)
 FrontEnd`AddMenuCommands["ClipboardWithPNG", {
   MenuItem["ClipboardWithPNG", FrontEnd`KernelExecute[Function[

       WriteToClipboard["PNG", ExportString[
          , "Image", Background -> None], {"Base64", "PNG"}]]

     ], MenuKey["c", Modifiers -> {"Control", "Shift"}],
    System`MenuEvaluator -> Automatic]}]]

And the needed code and functions.

Module[{temp, t2, CopyFileOverwrite, csfile, exefile, file, NRun},
 temp  = FileNameJoin[{$TemporaryDirectory, 
 NRun[s_] := (str = OpenWrite[FileNameJoin[{temp, "temp.bat"}]];
   WriteString[str, s];
   Import["!" <> Close[str], "Text"];);

  t2 = Directory[];
  Map[Function[DeleteFile[#]], FileNames[]];
  DeleteDirectory[temp, DeleteContents -> True];
  , Null

  FileNameJoin[{$InstallationDirectory, "SystemFiles", "Links", 
    "NETLink", "Wolfram.NETLink.dll"}],
  FileNameJoin[{temp, "Wolfram.NETLink.dll"}]

 csfile = FileNameJoin[{temp, "File.cs"}];
 exefile = FileNameJoin[{temp, "File.exe"}];
 file = OpenWrite[csfile];
 WriteString[file, "using System;
        using Wolfram.NETLink;
        using System.IO;
        using System.Drawing;
        using System.Windows.Forms;

        public class File{
         public static void Main(String[] args) {
            string input = System.Console.In.ReadToEnd();
            byte[] bytes = Convert.FromBase64String(input); 
            Stream stream = new MemoryStream(bytes);
            IDataObject dataObject = new DataObject();
            dataObject.SetData(args[0], stream);
            Clipboard.SetDataObject(dataObject, true);
 NRun ["cd " <> temp  "
   C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe  \
/reference:Wolfram.NETLink.dll File.cs"];

 WriteToClipboard[type_, data_] := (
   dataloc = FileNameJoin[{temp, "data.txt"}];
   datafile = OpenWrite[dataloc];
   WriteString[datafile, data];
   NRun["type " <> dataloc <> " | " <> exefile <> " " <> type];

To help measure timing I have been using this modified code with this function.

Time[code_] := (
  absolute = AbsoluteTiming[ReleaseHold[code]];
  (* Print[ToString[absolute[[1]]]<>" | "<>ToString[code] ]; *)

Old Code: To help users understand the evolution of the code, here is the old technique. It re compiles the program each time WriteToCliboard is run, therefore it will likely much slower.


Posted 2013-05-29T20:51:27.993

Reputation: 7 329

is there a way to convert it to CF_BITMAP? – Rainb – 2021-02-15T18:37:46.803

@Rainb I'm not sure what the point would be there was already no transparency support – William – 2021-02-15T19:00:38.887

I think CF_DIBV5 has transparency support. – Rainb – 2021-02-15T21:36:09.567