13
$\begingroup$

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[<<5>>]

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?

$\endgroup$
10
  • $\begingroup$ Hi, why your code with In[3]:= in the head of line, not so convenient when copy to notebook to evaluate. $\endgroup$ Commented Jun 17, 2013 at 0:27
  • $\begingroup$ 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]:= *)? $\endgroup$ Commented Jun 17, 2013 at 0:39
  • 1
    $\begingroup$ But 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? $\endgroup$
    – Jens
    Commented Jun 17, 2013 at 6:08
  • 3
    $\begingroup$ 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. $\endgroup$ Commented Jun 17, 2013 at 10:04
  • 2
    $\begingroup$ @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. $\endgroup$
    – Silvia
    Commented Jun 17, 2013 at 10:10

2 Answers 2

11
$\begingroup$

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

$\endgroup$
2
  • $\begingroup$ I think this is quite clearly a malformed box expression, so I'm going to go ahead and tag this question with bugs. $\endgroup$ Commented Jun 19, 2013 at 5:32
  • $\begingroup$ @OleksandrR. I agree. $\endgroup$
    – Silvia
    Commented Jun 19, 2013 at 6:21
0
$\begingroup$

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],
$\endgroup$
2
  • $\begingroup$ 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.) $\endgroup$
    – Silvia
    Commented Jun 19, 2013 at 10:28
  • $\begingroup$ @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. $\endgroup$
    – bill s
    Commented Jun 19, 2013 at 10:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.