#!/usr/bin/perl BEGIN { die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'}; unshift (@INC, "$ENV{'GSDLHOME'}/perllib"); } use Image::Magick; use parsargv; sub main { # Parse command line arguments if (!parsargv::parse(\@ARGV, 'background_image/.*/xc:white', \$background_image, 'image_width/^\d+$/', \$image_width, 'image_height/^\d+$/', \$image_height, 'stretchable_width', \$stretchable_width, 'stretchable_height', \$stretchable_height, 'note_if_stretched', \$note_if_stretched, 'no_text_height_warnings', \$no_text_height_warnings, 'h_align/.*/center', \$h_align, 'v_align/.*/bottom', \$v_align, 'padding_left/^\d+$/1', \$padding_left, 'padding_right/^\d+$/1', \$padding_right, 'padding_top/^(\\\-)?\d+$/0', \$padding_top, 'padding_bottom/^(\\\-)?\d+$/0', \$padding_bottom, 'baseline_offset/^(\\\-)?\d+$/0', \$baseline_offset, 'font/.*/', \$font, 'font_size/^\d+$/10', \$font_size, 'text/.*/', \$text, 'text_colour/.*/black', \$text_colour, 'output_file/.*/', \$output_file, 'verbose', \$verbose)) { print STDERR "Error: Bad command line arguments...\n"; die "\n"; } # Create a new image, basing it on the background image my $image = Image::Magick->new(font => $font, pointsize => $font_size); $res = $image->Read($background_image); die "$res" if $res; # Check required parameter values are set if (!$image_width) { $image_width = $image->Get('width'); } if (!$image_height) { $image_height = $image->Get('height'); } if ($h_align ne "left" && $h_align ne "center" && $h_align ne "right") { die "Error: Bad h_align $h_align...\n"; } if ($v_align ne "top" && $v_align ne "center" && $v_align ne "bottom") { die "Error: Bad v_align $v_align...\n"; } # Negative padding values (only top and bottom make sense) must be parsed specially if ($padding_top =~ /^\\\-(\d+)$/) { $padding_top = -$1; } if ($padding_bottom =~ /^\\\-(\d+)$/) { $padding_bottom = -$1; } # The baseline offset may be negative also... if ($baseline_offset =~ /^\\\-(\d+)$/) { $baseline_offset = -$1; } if (!$font) { die "Error: Font not specified...\n"; } if (!$text) { die "Error: Text not specified...\n"; } if (!$output_file) { die "Error: Output file not specified...\n"; } $output_file =~ /\/([^\/]+)$/; my $output_file_name = $1; # Calculate the usable image area my $usable_image_width = $image_width - $padding_left - $padding_right; my $usable_image_height = $image_height - $padding_top - $padding_bottom; if ($verbose) { print STDERR "\nGenerating: $output_file\n"; print STDERR "Pasting \"$text\" ($text_colour) in font $font ($font_size pt) onto $background_image\n"; 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"; } # Resize the image to the desired size (it may be increased later) $res = $image->Resize(width => $image_width, height => $image_height); die "$res" if $res; # Convert the (escaped) text string into a Unicode string my $text_unicode = $text; $text_unicode =~ s/\\(0x([0-9A-F]){4})/chr(oct($1))/ieg; # Determine the space required to display the text my $text_width = 0; my $text_height = 0; foreach $line (split(/\\n/, $text_unicode)) { ($x_ppem, $y_ppem, $ascender, $descender, $line_width, $line_height, $max_advance) = $image->QueryFontMetrics(text => $line); $line_height = $line_height - $baseline_offset; # Use the longest line as the text width if ($line_width > $text_width) { $text_width = $line_width; } $text_height += $line_height; } print STDERR "Text size is $text_width x $text_height\n" if $verbose; # If necessary, expand the image horizontally to fit the text... if ($text_width > $usable_image_width) { # ...provided that 'stretchable_width' has been specified if ($stretchable_width) { $usable_image_width = $text_width; $image_width = $usable_image_width + $padding_left + $padding_right; $res = $image->Resize(width => $image_width); die "$res" if $res; if ($note_if_stretched) { print STDERR "NOTE: Image width of $output_file_name was stretched to $image_width...\n"; } } else { print STDERR "WARNING: Text width ($text_width) is greater than usable image width ($usable_image_width) for $output_file_name...\n"; } } # If necessary, expand the image vertically to fit the text... if ($text_height > $usable_image_height) { # ...provided that 'stretchable_height' has been specified if ($stretchable_height) { $usable_image_height = $text_height; $image_height = $usable_image_height + $padding_top + $padding_bottom; $res = $image->Resize(height => $image_height); die "$res" if $res; if ($note_if_stretched) { print STDERR "NOTE: Image height of $output_file_name was stretched to $image_height...\n"; } } else { 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; } } # Determine where the text should be placed in the y dimension, based on v_align if ($v_align eq "top") { $ypos = $font_size - 1; } elsif ($v_align eq "center") { $ypos = (($usable_image_height - $text_height) / 2) + $font_size - 1; } elsif ($v_align eq "bottom") { $ypos = $usable_image_height - $text_height + $font_size - 1; } $ypos = $ypos + $padding_top; # Draw each line of the text onto the image foreach $line (split(/\\n/, $text_unicode)) { ($x_ppem, $y_ppem, $ascender, $descender, $line_width, $line_height, $max_advance) = $image->QueryFontMetrics(text => $line); $line_height = $line_height - $baseline_offset; # Determine where the text should be placed in the x dimension, based on h_align if ($h_align eq "left") { $xpos = 0; } elsif ($h_align eq "center") { $xpos = ($usable_image_width - $line_width) / 2; } elsif ($h_align eq "right") { $xpos = $usable_image_width - $line_width; } $xpos = $xpos + $padding_left; if ($xpos < 0) { $xpos = 0; } # print STDERR "Line coordinates: ($xpos, $ypos)\n"; # Why, why, oh why it is necessary to do this under Windows? # if ($ENV{'GSDLOS'} =~ /windows/i) { # $res = $image->Annotate(text => $line, encoding => 'UTF-8', fill => $text_colour, # x => -$xpos, y => -$ypos, undercolor => 'white'); # die "$res" if $res; # } # Draw the line text onto the image $res = $image->Annotate(text => $line, encoding => 'UTF-8', fill => $text_colour, x => $xpos, y => $ypos); die "$res" if $res; $ypos = $ypos + $line_height; } # Save the image to file $res = $image->Write($output_file); die "$res" if $res; } &main();