How to embed an image into a string?

13

1

Note: The bug described in the post is in Mathematica 9, and has been fixed in 10.0.

The documentation for String contains the following statements:

Strings can contain any sequence of ordinary and special characters:

Strings preserve internal formatting:

Strings can have any expression embedded:

"ab \[Integral]\!\(\*FractionBox[\(1\), \(x\)]\)\[DifferentialD]x cd"

Strings can contain graphics:

"ab \!\(\*\nGraphicsBox[DiskBox[{0, 0}],\nImageSize->{34., Automatic}]\) cd"

So I assumed that an image could be inserted anywhere in the string. I tried to copy images in different ways:

  • from other Mathematica notebook cells, explicitly Imported before
  • from web pages opened in a browser
  • from image editors e.g. Paint
  • taking screenshots

and paste them into expressions (as list elements, function arguments etc) and it all worked perfectly well. But when I try to paste images into string literals, then the string looks good (with the image embedded) in the input cell, but the expression gets corrupted when evaluated -- it is not even a String anymore:

(* In[1]:= *) logo = Import["https://wolfram.com/favicon.ico", "Image"]
(* Out[1]= *) 

(* In[2]:= *) Shallow["Mathematica ", 1] (* The image was copy-pasted from the previous cell *)
(* Out[2]//Shallow= *) Times[<&lt5>>]

Question 1: Is it a bug?

It is interesting that inserting plots into string literals works well.

I need a solution to insert images into strings programmatically. It could also serve as a workaround for this bug. I was not able to find a built-in function that does exactly this, so I tried to use "\!\(\*…\)" markup mentioned in the documentation for String. I was not able to find a documentation for this markup, so I started experimenting.

Question 2: Is there a complete documentation for this markup?

After several attempts, I ended up with the following function:

(* In[3]:= *) imageToString[image_Image] := 
    "\!\(\*" <> ToString[ToBoxes[image], InputForm] <> "\)";

(* In[4]:= *) "Mathematica " <> imageToString[logo]
(* Out[4]= *) Mathematica 

It seems to do what I need.

Question 3: Are there any shortcomings in my implementation? Is there a more simple/standard way to do this?

Vladimir Reshetnikov

Posted 2013-06-17T00:06:39.297

Reputation: 6 772

Hi, why your code with In[3]:= in the head of line, not so convenient when copy to notebook to evaluate. – HyperGroups – 2013-06-17T00:27:35.380

I tried to make it look as close as possible to what I see on the screen. I did not think about copying from the question, sorry for that. What is the preferred way to format Mathematica input/output? Would it help if I used comments (* In[1]:= *)? – Vladimir Reshetnikov – 2013-06-17T00:39:43.880

What kind of string of image do you want? This is also one string. "Mathematica "<>ToString[logo,InputForm]? And in CellExpression, it uses Graphics Compressed data string.

I'm a newbie in formatting too, I think add an comment is one good way, I use my DIY In/Out tags such like (*input 1*) and tried that in my incomplete answer of your previous compound operator's question. – HyperGroups – 2013-06-17T00:45:22.123

@HyperGroups The command "Mathematica "<>ToString[logo,InputForm] produces a long output Mathematica Image[RawArray["Byte", {{{0, 0, 0, 0}, …, {0, 0, 0, 0}}}], "Byte", ColorSpace -> "RGB", Interleaving -> True that does not contain a visual representation of the image. – Vladimir Reshetnikov – 2013-06-17T01:02:27.553

I'm curious what exactly are you going to do with these strings... – Jens – 2013-06-17T03:47:04.087

@Jens For the most part the same that I do with other strings ;) But I could, for example, insert custom glyphs that do not appear in existing fonts. – Vladimir Reshetnikov – 2013-06-17T05:04:49.780

1But you realize that these aren't really custom glyphs, in the sense that they won't be displayed by external applications when you copy or export them, right? So if you're confined to Mathematica anyway, why are you forced to store the information as String type in the first place? – Jens – 2013-06-17T06:08:23.927

@Jens I understand your reasoning. I don't have any immediate real use for this feature yet. I used to work as an ERP/CRM software developer, but then moved to the area of design and implementation of programming languages and IDE. I have an interest in any language feature or design decision just for general educational (or even aesthetic) purposes, even if I don't yet have any practical applications for it (that's perhaps the main reason why I moved). For me every language has its own beauty that I admire and learn from.

– Vladimir Reshetnikov – 2013-06-17T07:45:20.763

3

It looks like a bug to me, since pasting directly into a string literal works for Graphics but not for Image. The tutorial String Representation of Boxes is probably the best documentation for the markup.

– Simon Woods – 2013-06-17T10:04:49.250

2@Jens I sometimes convert things to String to get a more strict Hold attribute than HoldComplete. It usually acts as an atom object and prevents any affection from outside for good and ever. – Silvia – 2013-06-17T10:10:35.823

Answers

11

You can convert any expression to string by using ToString. If you want to preserve the visual representation, you should use ToString[(*your expression*), StandardForm].

logo = Import["http://wolfram.com/favicon.ico", "Image"]
logostr = ToString[logo, StandardForm]
StringJoin["Mathematica", logostr]
% // StringQ

string with image

Edit:

By checking the cell expression of the paste-into cell, I think I'd like to agree with Simon's comment that it looks like a bug:

error parsed cell expression

Silvia

Posted 2013-06-17T00:06:39.297

Reputation: 25 336

I think this is quite clearly a malformed box expression, so I'm going to go ahead and tag this question with [tag:bugs]. – Oleksandr R. – 2013-06-19T05:32:52.767

@OleksandrR. I agree. – Silvia – 2013-06-19T06:21:43.990

0

It's not clear when it is desirable to save an image inside a string. A similar outcome can be achieved by keeping everything (any possible format image, graphics, text, equation) in a list, and then just choosing the method of display. For example:

logo = Import["http://wolfram.com/favicon.ico", "Image"];
list = {"a string, an image ", logo, " and another image ", logo};

Of course this is not naturally formatted well for presentation, but this can be easily achieved by

Row[list]

enter image description here

If you look at the FullForm of this, it is perfectly well formed -- it is a long expression starting with

Row[List["a string, an image ", <<1>>, <<21>>, 
   Image[RawArray["Byte", List[List[List[0, 0, 0, 0],

bill s

Posted 2013-06-17T00:06:39.297

Reputation: 62 963

IMO, sometimes Row (or any non-atom expression) could be too fragile in certain contexts. In that case, keeping things in String could serve as a more complete "HoldForm" wrapper than other structures. (But not always. e.g. String cannot prevent Dynamic in it.) – Silvia – 2013-06-19T10:28:07.610

@Silvia -- I guess I wasn't imagining that the Row was used for anything other than display; it's the List that forms the backbone and contains the objects. – bill s – 2013-06-19T10:57:37.597