mcoblentz has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

I continually have trouble with the invocation of API's and the incorporation of variables into that invocation. For example, this

$image->Draw( fill=>'rgba(100,0,0,0.55)', primitive=>'rectangle', points=>'1460,1060 2060,1180');

works just fine. When I start substituting in variables, like this:

$image->Draw( fill=>'rgba(100,0,0,0.55)', primitive=>'rectangle', points=>'$box_left_x,$box_left_y $box_x,$box_y' );

I am apparently screwing it up. What is the syntax supposed to be? I have tried single quotes, no quotes, double quotes, etc. I'm sure that it's possible but somehow it feels like the simple things have just eluded me.

And I checked that the variables all have the right value, so that's not it.

The script, in it's entirety...

#!/opt/local/bin/perl use strict; use warnings; use Image::magick; my $image; $image = Image::Magick->new; open( IMAGE, '/Users/coblem/testing/rectangular.jpg' ); $image->Read( file=>\*IMAGE ); # initialize my $i; my $fh; my $mtime; my $color; my $filename; my $fontsize = "18"; my $directory = "/Users/coblem/xplanet/"; my $outfile = "markers/updatelabel"; my @labelpos = (+500, -500); # for each component, we obtain: # - the marker file location and last modified time # - the warning threshold for that component # - the alarm threshold for that component my @config_data = ( ["Quake ", "markers/quake", "3600", "21600", ], ["NORAD ", "satellites/NORAD.tle", "86400", "259200", ], ["Cloud ", "image_files/clouds_4096.jpg", "21600", "86400", ], ["Volcano", "markers/volcano", "86400", "604800", ], ["Fires ", "markers/fires", "86400", "259200", ], ["Storm ", "markers/storm", "21600", "192800", ], ); # processing # draw the semi-transparent box for the label data. This box is locat +ed at a # fixed position on the graphic image. The height of the box is depen +dent on the # number of items to be listed, which the count of items in the config +_data # array. # Then multiply the number of lines by the fontsize (which needs some +padding) my $box_height = ($#config_data + 1) * ($fontsize + 2); my $box_width = 600; my $box_x = 2060; my $box_y = 1180; my $box_left_x = $box_x - $box_width; my $box_left_y = $box_y - $box_height; print "box ", $box_left_x, ",", $box_left_y, " ", $box_x, ",", $box_y, + "\n"; # draw the box and fill it with semi-transparent color (the 'a' part o +f the # rgba value. $image->Draw( fill=>'rgba(100,0,0,0.55)', primitive=>'rectangle', poin +ts=>'$box_left_x,$box_left_y $box_x,$box_y' ); # loop through configuration data items and obtain: # full path to marker file, if it exists. If file does not exist, ret +urn error! # time difference, in days, since script started and last modifed time + (-M[FILENAME]) # use the 3rd and 4th columns as warning and alarm thresholds. If the + time # difference is over the threshold, color code appropriately. open $fh, ">", ($directory . $outfile); my $y = 100; foreach $i ( 0 .. $#config_data ) { $filename = $directory . $config_data[$i][1]; if ( -e $filename) { # test if file exists $mtime = -M $filename; # use -M operator to get +time difference if ( ($mtime * 86400) > $config_data[$i][3]) { # if over +alarm value, -->red $color = 'red'; } elsif ( ($mtime * 86400) > $config_data[$i][2]) { # if ov +er alarm value, -->yellow $color = 'yellow'; } else { $color = 'green'; } # print the label information # at some point, may have to have a routine to calculate the label pos +itions. # right now, it starts in the upper right corner at -35,-1; and drops +10 pixels # for every new line. print $fh ( ($labelpos[0] - ($i*10) ), " ", $labelpos[1], +" ", $config_data[$i][0], " Information Last Updated at: ", scalar lo +caltime((stat($filename))[9]), " color=$color image=none position=pix +el\n"); $image->Annotate( gravity=>'southeast', font=>'Arial', poi +ntsize=>$fontsize, fill=>$color, x=>500, y=>$y, text=>($labelpos[0] - + ($i*10) ), " ", $labelpos[1], " ", $config_data[$i][0], " Informatio +n Last Updated at: ", scalar localtime((stat($filename))[9]) ); $y = $y + $fontsize + 2; } else { print $fh ( ($labelpos[0] - ($i*10) ), " ", $labelpos[1], +" ", "Error! Component \"", $config_data[$i][0], "\" does not exist!! +! color=red image=none position=pixel\n"); $y = $y + $fontsize + 2; } } close $fh; open( IMAGE, ">/Users/coblemtesting/rectangle.jpg" ); $image->write( file=>\*IMAGE, filename=>'/Users/coblem/testing/rectang +le.jpg' ); close (IMAGE);

Replies are listed 'Best First'.
Re: Invoking API
by tobyink (Canon) on Jul 04, 2013 at 23:44 UTC

    Double quotes interpolate; single quotes do not.

    sub say { print @_, "\n" }; my $foo = "Hello"; say "$foo World"; say '$foo World';
    package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
      Ah, thank you! I was putting double quotes around every variable, and not just the set.

      So for this line,

      $image->Annotate( gravity =>'southeast', font =>'Arial', pointsize =>$fontsize, fill =>$color, x =>500, y =>$y, text =>$config_data[$i][0], " Information Last + Updated at: ", scalar localtime((stat($filename))[9]))";

      It's the text section that's driving me crazy. Normally the text is supplied with single quotes, which as you've explained is not interpolated. But having the line like this isn't working either:

      ... text =>"$config_data[$i][0] Information Last U +pdated at: scalar localtime((stat($filename))[9]))";

      Nor is any combination of double quotes, no quotes, or comma-separated values I can think of. I keep getting syntax errors. I'm sure this is simple but I just don't see it.

        scalar localtime((stat($filename))[9]) is not a variable (although its result varies, of course), so I guess variable interpolation doesn't help here.

        Here, I'd use the string concatenation operator, like this:

        text =>$config_data[$i][0] . " Information Last Updated at: " . lo +caltime((stat($filename))[9]) );

        My perl is a bit rusty (peak use was at the turn of the century), but AFAIR the scalar can be omitted here

Re: Invoking API
by choroba (Cardinal) on Jul 04, 2013 at 23:46 UTC
    Single quotes do not interpolate variables. Double quotes should work. See Quote Like Operators.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Invoking API
by rpnoble419 (Pilgrim) on Jul 05, 2013 at 02:13 UTC
    as it looks like you are populating a hash, this should work

    your code

    $image->Draw( fill=>'rgba(100,0,0,0.55)', primitive=>'rectangle', points=>'$box_left_x,$box_left_y $box_x,$box_y' );

    New code

    $image->Draw( fill =>'rgba(100,0,0,0.55)', primitive=>'rectangle', points =>$box_left_x,$box_left_y, $box_x,$box_y );