13

I am trying to use the "convert" command-line tool from ImageMagick. I have a base64 encoded png file and I need to convert it to another format. I am looking at documentation and a forum discussion which suggests that I should be able to use this syntax:

convert inline:file.txt file.jpg

But when I do this, I get this error message:

convert: corrupt image `file.txt' @ error/constitute.c/ReadInlineImage/910.

What am I doing wrong? How do I get convert to read a base64 image file?

skiphoppy
  • 97,646
  • 72
  • 174
  • 218

2 Answers2

17

Updated Answer - now that I understand it better myself :-)

Basically, you can base64 encode an image using openssl like this:

openssl enc -base64 -in image.png > image.b64

However, if you want ImageMagick to be able to read it, you need a small header at the start, to tell ImageMagick what follows. The header must contain:

data:image/png;base64,

followed by your base64 encoded data generated using the openssl command above. So, depending on what features your shell has, you could do it like this with a compound statement in bash:

{ echo "data:image/png;base64,"; openssl enc -base64 -in input.png; } > image.b64

or like this in Windows:

echo data:image/png;base64,         > image.b64
openssl enc -base64 -in image.png  >> image.b64

Once you have the image in that format, you can then proceed to process it with ImageMagick like this:

convert inline:image.b64 result.png

For those who use this in css, add -A flag to output in one line

openssl enc -base64 -A -in image.png > image.b64

Original Answer

After MUCH experimenting, I can do it!!! :-)

Start with Eric's (@emcconville) setup:

# For example
convert rose: rose.png
# Create base64 file
openssl enc -base64 -in rose.png -out rose.txt

and now add this mess as the last line:

{ echo "data:image/png;base64,"; cat rose.txt; } | convert inline:- out.jpg

I guess the data:image/png;base64, is not present in the base64 file created by openssl so I create a compound statement that sends that plus the file to stdin of ImageMagick.

mehany
  • 3,747
  • 2
  • 17
  • 28
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
3

Updated answer

From ImageMagick format docs...

The inline image look similar to inline:data:;base64,/9j/4AAQSk...knrn//2Q==. If the inline image exceeds 5000 characters, reference it from a file (e.g. inline:inline.txt).

This hints at two "gotcha" when using the inline format. First any standard base64 whitespace (unix line break) should be removed such that all information would be on one line. And second, that any data above 5000 characters should be read from a file buffer.

# Copy data to new file, striping line-breaks & adding INLINE header. (Please advise better sed/awk.)
cat file.txt | tr -d "\r\n" | awk '{print "data:image/png;base64,"$1}' > file.inline
# Read file as expected
convert inline:file.inline file.jpg

Original (not really correct) answer

The "corrupt image" message tells me that there may be whitespace in the base64 file. If so, the utility would work.

# For example
convert rose: rose.png
# Create base64 file
openssl enc -base64 -in rose.png -out rose.txt
# Read inline & data from stdin -- after stripping whitespace
cat rose.txt | tr -d "\r\n" | convert inline:data:- out.jpg
emcconville
  • 23,800
  • 4
  • 50
  • 66
  • I'm afraid that gave me basically the same error: "convert: corrupt image `data:-' @ error/constitute.c/ReadInlineImage/910." I don't see any whitespace in the original file other than the line ending (unix). – skiphoppy Sep 21 '15 at 16:37
  • Can you recreate the same message from a new image? – emcconville Sep 21 '15 at 16:40
  • Yes, I get it with any base64 image I use. – skiphoppy Sep 21 '15 at 17:09
  • I can't understand how that syntax is supposed to be used, or else it simply doesn't work. Can't find any explicit examples online of how to read a base64 image file with convert. – skiphoppy Sep 21 '15 at 18:26
  • Okay, updated answer. @MarkSetchell Please feel free to simplify as needed. – emcconville Sep 21 '15 at 18:35
  • I think we have pretty much both come to the same thing at the same time! You modify the file and rewrite it with the header in, and I create a compound statement that dynamically adds it into the stream that IM sees. It's horses for courses! I think the linebreaks are a red herring actually - I don't strip them. – Mark Setchell Sep 21 '15 at 18:39
  • Awesome, you got it! I agree with Mark, I didn't need to strip the linebreaks. Thank you guys for figuring this out when the provided documentation was inadequate. – skiphoppy Sep 22 '15 at 18:26
  • Very hard to decide whether to credit emcconville or @Mark Setchell with the answer. I finally gave it to Mark because of the straightforward comment "if you want ImageMagick to be able to read it, you need a small header at the start." If only ImageMagick themselves had seen fit to include that piece of the explanation in the first place. – skiphoppy Sep 22 '15 at 18:35