# How to convert an image to a compressed string representation equivalent to one copied to clipboard by CopyToClipboard[image]?

In my recent question I asked How to embed an image into a string?
The suggested solution was

(* In[1]:= *) image = Import["http://wolfram.com/favicon.ico", "Image"];
(* In[2]:= *) str = ToString[image, StandardForm];


If I execute

(* In[3]:= *) CopyToClipboard[str];


and then paste it into a plain text editor (e.g. notepad on Windows) than I get a very long and verbose string:

\!$$\*GraphicsBox[TagBox[RasterBox[RawArray["Byte", List[List[List[0, 0, 0, 0], (* ... *) List[0, 0, 0, 0]]]], List[List[0, 16], List[16, 0]], List[0, 255], Rule[ColorFunction, RGBColor]], BoxFormImageTag["Byte", Rule[ColorSpace, "RGB"], Rule[Interleaving, True]], Rule[Selectable, False]], Rule[BaseStyle, "ImageGraphics"], Rule[ImageSizeRaw, List[16, 16]], Rule[PlotRange, List[List[0, 16], List[0, 16]]]]$$


But if I copy the image to the clipboard directly

(* In[4]:= *) CopyToClipboard[image];


and then paste it into a plain text editor than I get a compressed representation:

\!$$\* GraphicsBox[ TagBox[RasterBox[CompressedData[" 1:eJyNUgss1HEc/+9CKBIyz928OodzCOdxcU95njh5tIQbpvUgDrFKWtIDPaZk tLTmIiJbWR6pbLVSlNSI0S0j4bS8tiZ9Oi1NFvluv99+n+++n31/3+/nYyxK CIojEQSRrCy/gqLT2ElJ0elCBTngpItjRWvkD43fZz75v3ibne/1+uIF0ipK iVviDPd37ADrBdyRdYz8zZYz9yozS3UhdyckeVPl+csq/+LnpR7hvqG4yUaZ /AP9gf6uMgqtdZwgoY3ilFbtEqJ5gxaa+Zizp7CuVKK03B+K1OwBkgl+MM1m RnjG6GQZo1tJD7V6HGkTwUMfK0Gw0gyZWvSJJ0r2GBP5Y6goBv054ai3scU5 goEhgosB3zjHpZyykL2pD0nMqadkZ9yj2qOSYOKBiRcaOf4oZ3CRqspAsaEH oO8IaNFHe7lBZlLPMKMB7g7qPL+ktEStx0kgnTO1xEBwAHrpbIz7haNdKESN JwtnTeho5nOByG2YJXQBQgdf6VvRHbsv/c+uoyPM4eeK4TA/TIYJgIJTmC6/ irbcFNzmuaEpKhgTp3fik54aBnU2fR7wFdAXz9DnI5S8NzLHc3MqZAejMFlx Ed8bqyAryseL7d6otnBAX7wQI+SNaN3mJVnglSYeXfuAubuhTnGzfEcaqNI3 RWegN3pOijFYdAJIT4DU2Rk3FSwgUWOgS8UK/dpWaDicwZvnF0Ts55+nel/K 0bU9U2VocP1ZgLu8Hw/tgTxI4/0wEcDEoKMDWmy24Jy6BY4Tlrgm16fOjj9V IT4kWqpFl4217EOoJx7RLdCqtwEfPe0AcTDAdsBLbTrynH3Tdhmz1TPN+I7F nCCXv3SMiF9fS1DQTKZBomMwUUNoYZpCwwzVAF8IVYwquqAlu0B5Oe8UBsb4 FPPC48o8vDWvkC1Z9Spus8PrGLjLYf3ya6ey3VhHbnHESv5bHPVOYe0Ngkjf Bdxs6aFy/2Q+bbX8mpScjCpRovZKNT8BKotUng== "], {{0, 16}, {16, 0}}, {0, 255}, ColorFunction->RGBColor], BoxFormImageTag["Byte", ColorSpace -> "RGB", Interleaving -> True], Selectable->False], BaseStyle->"ImageGraphics", ImageSizeRaw->{16, 16}, PlotRange->{{0, 16}, {0, 16}}]$$


Both the long and compressed strings, if being pasted back to a Mathematica notebook, are automatically represented as the original image:

(* In[5]:= *) 

I am interested in

Question 1: How to get the compressed string programmatically, without using the clipboard?

The content of CompressedData["..."] looks like a result of the Compress function, and indeed it could be checked that

(* In[6]:= *) ToBoxes[image][[1, 1, 1]] ===
Uncompress["
1:eJyNUgss1HEc/+9CKBIyz928OodzCOdxcU95njh5tIQbpvUgDrFKWtIDPaZk
tLTmIiJbWR6pbLVSlNSI0S0j4bS8tiZ9Oi1NFvluv99+n+++n31/3+/nYyxK
CIojEQSRrCy/gqLT2ElJ0elCBTngpItjRWvkD43fZz75v3ibne/1+uIF0ipK
/AP9gf6uMgqtdZwgoY3ilFbtEqJ5gxaa+Zizp7CuVKK03B+K1OwBkgl+MM1m
RnjG6GQZo1tJD7V6HGkTwUMfK0Gw0gyZWvSJJ0r2GBP5Y6goBv054ai3scU5
oO8IaNFHe7lBZlLPMKMB7g7qPL+ktEStx0kgnTO1xEBwAHrpbIz7haNdKESN
JwtnTeho5nOByG2YJXQBQgdf6VvRHbsv/c+uoyPM4eeK4TA/TIYJgIJTmC6/
irbcFNzmuaEpKhgTp3fik54aBnU2fR7wFdAXz9DnI5S8NzLHc3MqZAejMFlx
Ed8bqyAryseL7d6otnBAX7wQI+SNaN3mJVnglSYeXfuAubuhTnGzfEcaqNI3
0bU9U2VocP1ZgLu8Hw/tgTxI4/0wEcDEoKMDWmy24Jy6BY4Tlrgm16fOjj9V
nCCXv3SMiF9fS1DQTKZBomMwUUNoYZpCwwzVAF8IVYwquqAlu0B5Oe8UBsb4
FPPC48o8vDWvkC1Z9Spus8PrGLjLYf3ya6ey3VhHbnHESv5bHPVOYe0Ngkjf
Bdxs6aFy/2Q+bbX8mpScjCpRovZKNT8BKotUng==
"]
(* Out[6]= True *)


Unfortunately, RawArray, CompressedData and BoxFormImageTag are all undocumented. It looks like RawArray represents (probably, optimized) internal representation of a multi-dimensional array, and CompressedData is equivalent to Uncompress (e.g. unless being held, it automatically evaluates to the object represented by the compressed string) except that CompressedData can be successfully interpreted as part of an input of the form \!$$\* ...$$.

Question 2: Did I get their meaning right? Can they be useful in any other context?

Assuming I did it right, the closest result I was able to obtain to what I need is given by

(* In[7]:= *) toCompressedString[image_Image] :=
"\!$$\*" <> ToString[ ToBoxes[image] /. array_RawArray :> With[{compressed = Compress[array]}, CompressedData[compressed] /; True], InputForm] <> "$$";


(/; True is the Trott-Strzebonski trick that I learned trying to write this code).

Is there a more strightforward way to get this string?

-

If you look at the internal expression of the cell containing the image, you'll find that it also uses the compressed form. However, the usual trick of Cell@BoxData@ToBoxes... doesn't seem to work here, as that only gives us the RawArray representation. This gives us a hint at a possible way of retrieving the compressed representation without having to build it up ourselves.

In the following implementation, we create a new document with the image, flip the cell to show its expression (as if you had chosen Cell > Show Expression from the menu bar), copy its contents and then discard the notebook.

ClearAll@getCompressedString
getCompressedString[img_] := Module[{nb = CreateDocument[img, Visible -> False], str},
SelectionMove[nb, Next, Cell];
FrontEndTokenExecute[nb, "ToggleShowExpression"];
str = First[FrontEndExecute[FrontEndExportPacket[NotebookSelection[nb], "InputText"]]];
NotebookClose@nb;
First@StringCases[str, x : ("GraphicsBox" ~~ __) :> StringDrop[x, -2]]
]


If you now call getCompressedString on your image, you should get the string you want, which you can then pad with "\!\(\*" and "/)" to get back the image.

-
It's an interesting approach, I voted it up. But I would not call it a "more straightforward" than the one given in the question. Probably, it has a much more significant overhead. And it fails with FrontEndObject::notavail: A front end is not available; certain operations require a front end. message when there is no GUI Front End running (e.g. when executed from a console). –  TauMu Jun 20 '13 at 8:46