Replacing all images in a CSS file with base64 encoded strings from the command line

Basically, I am trying to write a smart single command line that outputs base64 encoded strings instead of where the image path used to be. So:

background-image: url(path/to/my/image.png); 

... will turn into:

 background-image: url(data:image/png;base64,ABvR0…+tC==); 

Usually I turn an image into its base64 encoded string via:

 openssl enc -base64 -in path/to/my/image.png 

Which displays base64 ... but with new lines in it. This is fixed by laying it through tr as follows:

 openssl enc -base64 -in path/to/my/image.png | tr -d '\n' 

which just prints a long base64 encoded string. Using pbcopy (on Mac OS), which is sent to the clipboard, for example:

 openssl enc -base64 -in path/to/my/image.png | tr -d '\n' | pbcopy 

It's nice that ad hoc replaces the random image with its base64 representation, but what I would like to do is automate the replacement of all url(path/to/whatever.ext) occurrences url(path/to/whatever.ext) in the file according to their corresponding base64 lines. Making sure that there are only actual paths and no uris data in this place outside the scope :)

I'm trying to replace sed stuff, but I'm stuck in its terrible documentation. It is not so difficult to find the occurrences in the url(…) pattern in the css file, but the bit between the brackets needs to be replaced by the output of this command, and I do not know if this is possible. So, here it is, help, or some pointers (do I also need to look into awk?). "You cannot do this without a proper script," of course also :)

+7
source share
4 answers

Using openssl tool

 #!/bin/bash awk -F'[()]' -vq="'" ' /background-image: url(.*)/ { cmd=sprintf("openssl enc -base64 -in %s | tr -d %c\\n%c",$2,q,q) cmd | getline b64 close(cmd) $0=$1 "(data:image/png;base64," b64 ");" }1' /path/to/css/file 

Proof of concept

See HERE for a working example.


With base64 tool

 #!/bin/bash awk -F'[()]' ' /background-image: url(.*)/ { cmd=sprintf("base64 -w0 %s",$2) cmd | getline b64 close(cmd) $0=$1 "(data:image/png;base64," b64 ");" }1' /path/to/css/file 

Proof of concept

See HERE for a working example.

+8
source

Consider using Perl rather than sed. Skipping awk in general is inconvenient :-). (Actually, it was one of the first programming languages ​​that I learned, but Perl is much better).

Better yet, do not do this at all, as it will not work in 50% of user's browsers. In any case, be very, very sure that you do not care about these users before telling them about it this way.

0
source

I don’t have much experience with ccs and png files, but considering your very useful , I have this line, I need line descriptions. Here is the first draft

 #! /bin/ksh # -vx (bash should work too) usageMsg="pngReplacer pngFile ccsFile" case $# in [!2] ) print "usage: ${usageMsg}" ; exit 1 esac set -- ${@} # I'm surprised that we need this line base64Str=$(openssl enc -base64 -in "$1" 2>/dev/null | tr -d '\n') { if ${testMode:-false} ; then print -- " background-image: url(path/to/my/image.png);" else cat "$2" fi } | sed ' s@url (.*)@url(data:image/png;base64,'"$base64Str"')@g' 

There is a lot of fragility

  • I have this right, png file and css file, right?
  • you know about the arguments ksh / bash $ 1 $ 2 etc, right?
  • the test for the count argument is ok but
  • you probably really want to confirm that $ 1 and $ 2 really exist
  • Unable to specify output file, run it as

PNGReplacer pngFile ccsFile> newCcsFile

  • If the stuff in {} gives you gaby bending, you can cut everything right on '|' char immediately before sed and put $ 2 at the end of the sed command.
  • I would be surprised if AIX sed handles the 280 char replacement expression, but I no longer need to test it. In general, seeds are fragile in such things.
  • the biggest fragility of all, @ reg-exp @ replace-exp @delimiter (@). If you end with the @ sign in base64Str, you will need to find a char that is not used in the new base64Str.

Hope this helps.

0
source

This command line that I wrote encodes all the images contained in the HTML file, instead.

It can be easily adapted to encode all images in a CSS file (by editing the base64images function).

It just requires a PHP command line interpreter.

 #!/usr/bin/php <?php /** * This command line tool encodes all images contained in the specified HTML file. * The encoded contents will be returned on standard output. * Use redirection to store it into a file. * @author Massimiliano Alessandri < m.alessandri@spaziocolore.it > */ /** * Converts a "src" property embedding the referenced image. * This way, the recipient won't have to click on "display images" to view the images. * @param array $matches the array sent by the preg_replace_callback function * @return string the encoded "src" property */ function base64images($matches) { return 'src="data:'.mime_content_type($matches[1]).';base64,'.base64_encode(file_get_contents($matches[1])).'"'; } if($argc < 2) { echo 'Usage: '.$argv[0].' [file to be encoded]'; echo 'The encoded file will be returned to standard output.'; exit; } $filename = $argv[1]; if(file_exists($filename)) echo preg_replace_callback('/src="([^"]+)"/', 'base64images', file_get_contents($filename)); else echo 'File not found: '.$filename."\n"; 
0
source

All Articles