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?
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
.
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 tr 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