Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert a base64 image?

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?

like image 939
skiphoppy Avatar asked Sep 21 '15 14:09

skiphoppy


2 Answers

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.

like image 141
Mark Setchell Avatar answered Sep 21 '22 13:09

Mark Setchell


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
like image 42
emcconville Avatar answered Sep 22 '22 13:09

emcconville