1 package FS::Misc::eps2png;
3 #based on eps2png by Johan Vromans
4 #Copyright 1994,2008 by Johan Vromans.
5 #This program is free software; you can redistribute it and/or
6 #modify it under the terms of the Perl Artistic License or the
7 #GNU General Public License as published by the Free Software
8 #Foundation; either version 2 of the License, or (at your option) any
12 use vars qw( @ISA @EXPORT_OK );
15 use File::Slurp qw( slurp );
18 @ISA = qw( Exporter );
19 @EXPORT_OK = qw( eps2png );
21 ################ Program parameters ################
23 # Some GhostScript programs can produce GIF directly.
24 # If not, we need the PBM package for the conversion.
25 # NOTE: This will be changed upon install.
28 my $res = 82; # default resolution
29 my $scale = 1; # default scaling
30 my $mono = 0; # produce BW images if non-zero
31 my $format; # output format
32 my $gs_format; # GS output type
33 my $output; # output, defaults to STDOUT
34 my $antialias = 4; # antialiasing
35 my $DEF_width; # desired widht
36 my $DEF_height; # desired height
37 #my $DEF_width = 90; # desired widht
38 #my $DEF_height = 36; # desired height
40 my ($verbose,$trace,$test,$debug) = (0,0,0,0);
42 set_out_type ('png'); # unless defined $format;
43 warn "Producing $format ($gs_format) image.\n" if $verbose;
45 $trace |= $test | $debug;
48 ################ Presets ################
50 ################ The Process ################
55 my( $eps, %options ) = @_; #well, no options yet
57 my $dir = $FS::UID::conf_dir. "/cache.". $FS::UID::datasrc;
58 my $eps_file = new File::Temp( TEMPLATE => 'image.XXXXXXXX',
62 ) or die "can't open temp file: $!\n";
66 my @eps = split(/\r?\n/, $eps);
68 warn "converting eps (". length($eps). " bytes, ". scalar(@eps). " lines)\n"
71 my $line = shift @eps; #<EPS>;
72 unless ( $eps =~ /^%!PS-Adobe.*EPSF-/ ) {
73 warn "not EPS file (no %!PS-Adobe header)\n";
74 return; #empty png file?
77 my $ps = ""; # PostScript input data
82 # Prevent derived values from propagating.
83 my $width = $DEF_width;
84 my $height = $DEF_height;
88 $line = shift(@eps)."\n";
90 # Search for BoundingBox.
91 if ( $line =~ /^%%BoundingBox:\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/i ) {
93 warn "$eps_file: x0=$1, y0=$2, w=", $3-$1, ", h=", $4-$2
96 if ( defined $width ) {
98 $xscale = $width / ($3 - $1);
99 if ( defined $height ) {
100 $yscale = $height / ($4 - $2);
104 $height = ($4 - $2) * $yscale;
107 elsif ( defined $height ) {
109 $yscale = $height / ($4 - $2);
110 if ( defined $width ) {
111 $xscale = $width / ($3 - $1);
115 $width = ($3 - $1) * $xscale;
118 unless ( defined $xscale ) {
119 $xscale = $yscale = $scale;
120 # Calculate actual width.
123 # Normal PostScript resolution is 72.
124 $width *= $res/72 * $xscale;
125 $height *= $res/72 * $yscale;
127 $width = int ($width + 0.5) + 1;
128 $height = int ($height + 0.5) + 1;
130 warn ", width=$width, height=$height\n" if $verbose;
133 $ps .= "$xscale $yscale scale\n"
134 if $xscale != 1 || $yscale != 1;
136 # Create PostScript code to translate coordinates.
137 $ps .= (0-$1) . " " . (0-$2) . " translate\n"
138 unless $1 == 0 && $2 == 0;
140 # Include the image, show and quit.
141 $ps .= "($eps_file) run\n".
147 elsif ( $line =~ /^%%EndComments/i ) {
153 warn "No bounding box in $eps_file\n";
157 #it would be better to ask gs to spit out files on stdout, but c'est la vie
159 #my $out_file; # output file
160 #my $pbm_file; # temporary file for PBM conversion
162 my $out_file = new File::Temp( TEMPLATE => 'image.XXXXXXXX',
166 ) or die "can't open temp file: $!\n";
168 my $pbm_file = new File::Temp( TEMPLATE => 'image.XXXXXXXX',
172 ) or die "can't open temp file: $!\n";
174 # Note the temporary PBM file is created where the output file is
175 # located, since that will guarantee accessibility (and a valid
177 warn "Creating $out_file\n" if $verbose;
179 my $gs0 = "gs -q -dNOPAUSE -r$res -g${width}x$height";
181 $gs0 .= " -dTextAlphaBits=$antialias -dGraphicsAlphaBits=$antialias"
183 if ( $format eq 'png' ) {
184 mysystem ("$gs0 -sDEVICE=". ($mono ? "pngmono" : $gs_format).
185 " -sOutputFile=$out_file $gs1", $ps);
187 elsif ( $format eq 'jpg' ) {
188 mysystem ("$gs0 -sDEVICE=". ($mono ? "jpeggray" : $gs_format).
189 " -sOutputFile=$out_file $gs1", $ps);
191 elsif ( $format eq 'gif' ) {
193 # Convert to PPM and use some of the PBM converters.
194 mysystem ("$gs0 -sDEVICE=". ($mono ? "pbm" : "ppm").
195 " -sOutputFile=$pbm_file $gs1", $ps);
196 # mysystem ("pnmcrop $pbm_file | ppmtogif > $out_file");
197 mysystem ("ppmtogif $pbm_file > $out_file");
201 # GhostScript has GIF drivers built-in.
202 mysystem ("$gs0 -sDEVICE=". ($mono ? "gifmono" : "gif8").
203 " -sOutputFile=$out_file $gs1", $ps);
207 warn "ASSERT ERROR: Unhandled output type: $format\n";
211 # unless ( -s $out_file ) {
212 # warn "Problem creating $out_file for $eps_file\n";
222 ################ Subroutines ################
225 my ($cmd, $data) = @_;
226 warn "+ $cmd\n" if $trace;
229 my $dp = ">> " . $data;
230 $dp =~ s/\n(.)/\n>> $1/g;
233 open (CMD, "|$cmd") or die ("$cmd: $!\n");
235 close CMD or die ("$cmd close: $!\n");
243 my ($opt) = lc (shift (@_));
244 if ( $opt =~ /^png(mono|gray|16|256|16m|alpha)?$/ ) {
246 $gs_format = $format.(defined $1 ? $1 : '16m');
248 elsif ( $opt =~ /^gif(mono)?$/ ) {
250 $gs_format = $format.(defined $1 ? $1 : '');
252 elsif ( $opt =~ /^(jpg|jpeg)(gray)?$/ ) {
254 $gs_format = 'jpeg'.(defined $2 ? $2 : '');
257 warn "ASSERT ERROR: Invalid value to set_out_type: $opt\n";
262 # 'antialias|aa=i' => \$antialias,
263 # 'noantialias|noaa' => sub { $antialias = 0 },
264 # 'scale=f' => \$scale,
265 # 'width=i' => \$width,
266 # 'height=i' => \$height,
267 # 'resolution=i' => \$res,
269 # die ("Antialias value must be 0, 1, 2, 4, or 8\n")
271 # -width XXX desired with
272 # -height XXX desired height
273 # -resolution XXX resolution (default = $res)
274 # -scale XXX scaling factor
275 # -antialias XX antialias factor (must be 0, 1, 2, 4 or 8; default: 4)
276 # -noantialias no antialiasing (same as -antialias 0)