Code

Prune initial timer work.
[inkscape.git] / share / extensions / embed_raster_in_svg.pl
1 #!/usr/bin/perl
3 #----------------------------------------------------------------------------------------------
4 # embed_raster_in_svg
5 # B. Crowell, crowellXX at lightandmatter.com (replace XX with last two digits of current year)
6 # (c) 2004 B. Crowell
7 # This program is available under version 2 of the GPL License, http://www.gnu.org/copyleft/gpl.html,
8 # or, at your option, under the same license as Perl.
9 # For information about this program, scroll down in the source code, or invoke the program
10 # without any command-line arguments.
11 #----------------------------------------------------------------------------------------------
13 use strict;
15 use MIME::Base64;
16 use Cwd;
17 use File::Basename;
19 my $info = <<'INFO';
20  usage:
21     embed_raster_in_svg foo.svg
22  Looks through the svg file for raster images that are given as links, rather than
23  being embedded, and embeds them in the file. The links must be local URIs, and if
24  they're relative, they must be relative to the directory where the svg file is located.
25  Starting with Inkscape 0.41, Inkscape can
26  handle embedded raster images as well as ones that are linked to (?).
27  Typical input looks like this:
28   <image
29      xlink:href="beer.jpg"
30      sodipodi:absref="/home/bcrowell/Documents/programming/embed_raster_in_svg/tests/beer.jpg"
31      width="202.50000"
32      height="537.00000"
33      id="image1084"
34      x="281.67480"
35      y="242.58502" />
36   The output should look like this:
37    <image
38      width="202.50000"
39      height="537.00000"
40      id="image1084"
41      x="281.67480"
42      y="242.58502"
43      xlink:href="data:;base64,...
44   The SVG standard only allows the <image> tag to refer to data of type png, jpg, or svg,
45   and this script only handles png or jpg.
46 INFO
48 undef $/; # slurp whole file
50 my $svg = $ARGV[0];
52 if (!$svg) {
53   print $info;
54   exit;
55 }
57 die "input file $svg not found" if ! -e $svg;
58 die "input file $svg not readable" if ! -r $svg;
60 open(FILE,"<$svg") or die "error opening file $svg for input, $!";
61 my $data = <FILE>;
62 close FILE;
64 chdir dirname(Cwd::realpath($svg)); # so from now on, we can open raster files if they're relative to this directory
67 # The file is now in memory.
68 # First we go once through it and (1) find out if there are indeed any links to raster images,
69 # (2) rearrange things a little so that the (lengthy) base64 data will be the last attribute of the
70 # image tag.
72 my $n = 0;
73 my @raster_files = ();
74 $data =~
75   s@\<image\s+((?:(?:\w|\:)+\=\"[^"]*\"\s*)*)xlink\:href=\"([^"]+)\"\s*((?:(?:\w|:)+\=\"[^"]*\"\s*)*)\/>@<imageHOBBITSES $1 $3 ITHURTSUS\"$2\"MYPRECIOUSS />@g;
76 while ($data=~m@<imageHOBBITSES\s*(?:(?:(?:\w|\:)+\=\"[^"]*\"\s*)*)ITHURTSUS\"([^"]+)\"MYPRECIOUSS />@g) {
77   my $raster = $1;
78   die "error, raster filename $raster contains a double quote" if $raster=~m/\"/;
79   if (!($raster=~m/data\:\;/)) {
80     ++$n;
81     push @raster_files,$raster;
82   }
83 }
85 if ($n==0) {
86   print "no embedded jpgs found in file $svg\n";
87   exit;
88 }
91 # Eliminate sodipodi:absref attributes. If these are present, Inkscape looks for the linked
92 # file, and ignores the embedded data. Also, get rid of those nasty hobbitses.
93 $data=~s@(<image)HOBBITSES\s*((?:(?:\w|\:)+\=\"[^"]*\"\s*)*)sodipodi\:absref\=\"[^"]+\"\s*((:?(?:\w|\:)+\=\"[^"]*\"\s*)*ITHURTSUS)@$1 $2 $3@g;
94 $data=~s@(<image)HOBBITSES@$1@g;
97 # Now embed the data:
99 foreach my $raster(@raster_files) {
100   die "file $raster not found relative to directory ".getcwd() if ! -e $raster;
101   die "file $raster is nor readable" if ! -r $raster;
102   open(RASTER,"<$raster") or die "error opening file $raster for input, $!";
103   my $raster_data = <RASTER>;
104   close RASTER;
105   my $type = '';
106   $type='image/png' if $raster_data=~m/^\x{89}PNG/;
107   $type='image/jpg' if $raster_data=~m/^\x{ff}\x{d8}/;
108   die "file $raster does not appear to be of type PNG or JPG" unless $type;
109   my $raster_data_base64 = encode_base64($raster_data);
110   ($data =~ s@ITHURTSUS\"$raster\"MYPRECIOUSS@\n     xlink:href=\"data\:$type\;base64,$raster_data_base64\"@) or die "error embedding data for $raster";
111   print "embedded raster file $raster, $type\n";
113 my $bak = "$svg.bak";
114 rename $svg,$bak or die "error renaming file $svg to $bak, $!";
115 open(FILE,">$svg") or die "error creating new version of file $svg for output, $!";
116 print FILE $data;
117 close FILE;