1 | #!/usr/bin/perl
|
---|
2 |
|
---|
3 |
|
---|
4 | BEGIN {
|
---|
5 | die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
|
---|
6 | unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
|
---|
7 | }
|
---|
8 |
|
---|
9 |
|
---|
10 | use Image::Magick;
|
---|
11 | use parsargv;
|
---|
12 |
|
---|
13 |
|
---|
14 | sub main
|
---|
15 | {
|
---|
16 | # Parse command line arguments
|
---|
17 | if (!parsargv::parse(\@ARGV,
|
---|
18 | 'background_image/.*/xc:white', \$background_image,
|
---|
19 | 'image_width/^\d+$/', \$image_width,
|
---|
20 | 'image_height/^\d+$/', \$image_height,
|
---|
21 | 'stretchable_width', \$stretchable_width,
|
---|
22 | 'stretchable_height', \$stretchable_height,
|
---|
23 | 'note_if_stretched', \$note_if_stretched,
|
---|
24 | 'no_text_height_warnings', \$no_text_height_warnings,
|
---|
25 | 'h_align/.*/center', \$h_align,
|
---|
26 | 'v_align/.*/bottom', \$v_align,
|
---|
27 | 'padding_left/^\d+$/1', \$padding_left,
|
---|
28 | 'padding_right/^\d+$/1', \$padding_right,
|
---|
29 | 'padding_top/^(\\\-)?\d+$/0', \$padding_top,
|
---|
30 | 'padding_bottom/^(\\\-)?\d+$/0', \$padding_bottom,
|
---|
31 | 'baseline_offset/^(\\\-)?\d+$/0', \$baseline_offset,
|
---|
32 | 'font/.*/', \$font,
|
---|
33 | 'font_size/^\d+$/10', \$font_size,
|
---|
34 | 'text/.*/', \$text,
|
---|
35 | 'text_colour/.*/black', \$text_colour,
|
---|
36 | 'output_file/.*/', \$output_file,
|
---|
37 | 'verbose', \$verbose)) {
|
---|
38 | print STDERR "Error: Bad command line arguments...\n";
|
---|
39 | die "\n";
|
---|
40 | }
|
---|
41 |
|
---|
42 |
|
---|
43 | # Create a new image, basing it on the background image
|
---|
44 | my $image = Image::Magick->new(font => $font, pointsize => $font_size);
|
---|
45 | $res = $image->Read($background_image);
|
---|
46 | die "$res" if $res;
|
---|
47 |
|
---|
48 | # Check required parameter values are set
|
---|
49 | if (!$image_width) {
|
---|
50 | $image_width = $image->Get('width');
|
---|
51 | }
|
---|
52 | if (!$image_height) {
|
---|
53 | $image_height = $image->Get('height');
|
---|
54 | }
|
---|
55 | if ($h_align ne "left" && $h_align ne "center" && $h_align ne "right") {
|
---|
56 | die "Error: Bad h_align $h_align...\n";
|
---|
57 | }
|
---|
58 | if ($v_align ne "top" && $v_align ne "center" && $v_align ne "bottom") {
|
---|
59 | die "Error: Bad v_align $v_align...\n";
|
---|
60 | }
|
---|
61 |
|
---|
62 | # Negative padding values (only top and bottom make sense) must be parsed specially
|
---|
63 | if ($padding_top =~ /^\\\-(\d+)$/) {
|
---|
64 | $padding_top = -$1;
|
---|
65 | }
|
---|
66 | if ($padding_bottom =~ /^\\\-(\d+)$/) {
|
---|
67 | $padding_bottom = -$1;
|
---|
68 | }
|
---|
69 |
|
---|
70 | # The baseline offset may be negative also...
|
---|
71 | if ($baseline_offset =~ /^\\\-(\d+)$/) {
|
---|
72 | $baseline_offset = -$1;
|
---|
73 | }
|
---|
74 |
|
---|
75 | if (!$font) {
|
---|
76 | die "Error: Font not specified...\n";
|
---|
77 | }
|
---|
78 | if (!$text) {
|
---|
79 | die "Error: Text not specified...\n";
|
---|
80 | }
|
---|
81 | if (!$output_file) {
|
---|
82 | die "Error: Output file not specified...\n";
|
---|
83 | }
|
---|
84 |
|
---|
85 | $output_file =~ /\/([^\/]+)$/;
|
---|
86 | my $output_file_name = $1;
|
---|
87 |
|
---|
88 | # Calculate the usable image area
|
---|
89 | my $usable_image_width = $image_width - $padding_left - $padding_right;
|
---|
90 | my $usable_image_height = $image_height - $padding_top - $padding_bottom;
|
---|
91 |
|
---|
92 | if ($verbose) {
|
---|
93 | print STDERR "\nGenerating: $output_file\n";
|
---|
94 | print STDERR "Pasting \"$text\" ($text_colour) in font $font ($font_size pt) onto $background_image\n";
|
---|
95 | print STDERR "Basic size of $image_width x $image_height minus padding (LRTB: $padding_left $padding_right $padding_top $padding_bottom) gives usable area $usable_image_width x $usable_image_height\n";
|
---|
96 | }
|
---|
97 |
|
---|
98 | # Resize the image to the desired size (it may be increased later)
|
---|
99 | $res = $image->Resize(width => $image_width, height => $image_height);
|
---|
100 | die "$res" if $res;
|
---|
101 |
|
---|
102 | # Convert the (escaped) text string into a Unicode string
|
---|
103 | my $text_unicode = $text;
|
---|
104 | $text_unicode =~ s/\\(0x([0-9A-F]){4})/chr(oct($1))/ieg;
|
---|
105 |
|
---|
106 | # Determine the space required to display the text
|
---|
107 | my $text_width = 0;
|
---|
108 | my $text_height = 0;
|
---|
109 | foreach $line (split(/\\n/, $text_unicode)) {
|
---|
110 | ($x_ppem, $y_ppem, $ascender, $descender, $line_width, $line_height, $max_advance) =
|
---|
111 | $image->QueryFontMetrics(text => $line);
|
---|
112 | $line_height = $line_height - $baseline_offset;
|
---|
113 |
|
---|
114 | # Use the longest line as the text width
|
---|
115 | if ($line_width > $text_width) {
|
---|
116 | $text_width = $line_width;
|
---|
117 | }
|
---|
118 | $text_height += $line_height;
|
---|
119 | }
|
---|
120 | print STDERR "Text size is $text_width x $text_height\n" if $verbose;
|
---|
121 |
|
---|
122 | # If necessary, expand the image horizontally to fit the text...
|
---|
123 | if ($text_width > $usable_image_width) {
|
---|
124 | # ...provided that 'stretchable_width' has been specified
|
---|
125 | if ($stretchable_width) {
|
---|
126 | $usable_image_width = $text_width;
|
---|
127 | $image_width = $usable_image_width + $padding_left + $padding_right;
|
---|
128 | $res = $image->Resize(width => $image_width);
|
---|
129 | die "$res" if $res;
|
---|
130 |
|
---|
131 | if ($note_if_stretched) {
|
---|
132 | print STDERR "NOTE: Image width of $output_file_name was stretched to $image_width...\n";
|
---|
133 | }
|
---|
134 | }
|
---|
135 | else {
|
---|
136 | print STDERR "WARNING: Text width ($text_width) is greater than usable image width ($usable_image_width) for $output_file_name...\n";
|
---|
137 | }
|
---|
138 | }
|
---|
139 |
|
---|
140 | # If necessary, expand the image vertically to fit the text...
|
---|
141 | if ($text_height > $usable_image_height) {
|
---|
142 | # ...provided that 'stretchable_height' has been specified
|
---|
143 | if ($stretchable_height) {
|
---|
144 | $usable_image_height = $text_height;
|
---|
145 | $image_height = $usable_image_height + $padding_top + $padding_bottom;
|
---|
146 | $res = $image->Resize(height => $image_height);
|
---|
147 | die "$res" if $res;
|
---|
148 |
|
---|
149 | if ($note_if_stretched) {
|
---|
150 | print STDERR "NOTE: Image height of $output_file_name was stretched to $image_height...\n";
|
---|
151 | }
|
---|
152 | }
|
---|
153 | else {
|
---|
154 | print STDERR "WARNING: Text height ($text_height) is greater than usable image height ($usable_image_height) for $output_file_name...\n" unless $no_text_height_warnings;
|
---|
155 | }
|
---|
156 | }
|
---|
157 |
|
---|
158 | # Determine where the text should be placed in the y dimension, based on v_align
|
---|
159 | if ($v_align eq "top") {
|
---|
160 | $ypos = $font_size - 1;
|
---|
161 | }
|
---|
162 | elsif ($v_align eq "center") {
|
---|
163 | $ypos = (($usable_image_height - $text_height) / 2) + $font_size - 1;
|
---|
164 | }
|
---|
165 | elsif ($v_align eq "bottom") {
|
---|
166 | $ypos = $usable_image_height - $text_height + $font_size - 1;
|
---|
167 | }
|
---|
168 | $ypos = $ypos + $padding_top;
|
---|
169 |
|
---|
170 | # Draw each line of the text onto the image
|
---|
171 | foreach $line (split(/\\n/, $text_unicode)) {
|
---|
172 | ($x_ppem, $y_ppem, $ascender, $descender, $line_width, $line_height, $max_advance) =
|
---|
173 | $image->QueryFontMetrics(text => $line);
|
---|
174 | $line_height = $line_height - $baseline_offset;
|
---|
175 |
|
---|
176 | # Determine where the text should be placed in the x dimension, based on h_align
|
---|
177 | if ($h_align eq "left") {
|
---|
178 | $xpos = 0;
|
---|
179 | }
|
---|
180 | elsif ($h_align eq "center") {
|
---|
181 | $xpos = ($usable_image_width - $line_width) / 2;
|
---|
182 | }
|
---|
183 | elsif ($h_align eq "right") {
|
---|
184 | $xpos = $usable_image_width - $line_width;
|
---|
185 | }
|
---|
186 | $xpos = $xpos + $padding_left;
|
---|
187 |
|
---|
188 | if ($xpos < 0) {
|
---|
189 | $xpos = 0;
|
---|
190 | }
|
---|
191 |
|
---|
192 | # print STDERR "Line coordinates: ($xpos, $ypos)\n";
|
---|
193 |
|
---|
194 | # Why, why, oh why it is necessary to do this under Windows?
|
---|
195 | # if ($ENV{'GSDLOS'} =~ /windows/i) {
|
---|
196 | # $res = $image->Annotate(text => $line, encoding => 'UTF-8', fill => $text_colour,
|
---|
197 | # x => -$xpos, y => -$ypos, undercolor => 'white');
|
---|
198 | # die "$res" if $res;
|
---|
199 | # }
|
---|
200 |
|
---|
201 | # Draw the line text onto the image
|
---|
202 | $res = $image->Annotate(text => $line, encoding => 'UTF-8', fill => $text_colour,
|
---|
203 | x => $xpos, y => $ypos);
|
---|
204 | die "$res" if $res;
|
---|
205 |
|
---|
206 | $ypos = $ypos + $line_height;
|
---|
207 | }
|
---|
208 |
|
---|
209 | # Save the image to file
|
---|
210 | $res = $image->Write($output_file);
|
---|
211 | die "$res" if $res;
|
---|
212 | }
|
---|
213 |
|
---|
214 |
|
---|
215 | &main();
|
---|