Push damages IM object in PerlMagick?
Posted: 2013-12-13T10:51:02-07:00
Hi,
I have a program with 3 IM objects:
A) one to read single files
B) one to accumulate files read by A
c) one to take the take the appended -> stack object B and print it.
This may not be the most optimal design, but it should work.
I have an option to stack N copies of the same object in a loop. It only works if I destroy A and re-read it before pushing it onto B each time.
I have a trivial test program which:
1) clears A, B and C,
2) reads a file into A
3) pushes A onto B N times in a loop
4) appends B, stack=>'true' and places the resulting IM object in C
5) writes C to disk.
C should contain N copies of the picture. It only contains one.
The fix is to expand step 3):
push A onto B
destroy A
Reread A
repeat N times
I know that this simple operation can be done on the command line. I have many stacks, rotations, resizes, etc so need a real programming language, not just shell commands. The object is to solve the mystery of why the IM arrays appear to be misbehaving or why I am abusing them (much more likely).
Here is the log from the misbehaving run:
M:\print\2013.1210>bb.pl 3
Running C:\bin\bb.pl 3 Fri Dec 13 11:06:16 2013
IM sig = "ImageMagick 6.8.7-9 Q16 x64 2013-11-28 http://www.imagemagick.org".
Count = 3, ImageA size = 3600 x 900.
0) Stacking image to @$imageB [1], @$imageA [1].
1) Stacking image to @$imageB [2], @$imageA [1].
2) Stacking image to @$imageB [3], @$imageA [1].
Scalar @{$imageB} = 3.
ImageB[0] size = 3600 x 900.
ImageB[1] size = 3600 x 900.
ImageB[2] size = 3600 x 900.
Append stack -> TRUE. scalar @imageC = 1.
Scalar @{$imageA} = 1.
Scalar @{$imageB} = 3.
Scalar @{$imageC} = 1.
Final image stack.3.jpg X 3600, Y 900. << NOTE: Final image resolution is the same as the original. Only 1 copy. IM B array has 3.
===========================================
here is the correct behavior truncating the A object and rereading the file every time through the loop:
M:\print\2013.1210>bb.pl 3 DESTROY_AND_REREAD
Running C:\bin\bb.pl 3, DESTROY_AND_REREAD Fri Dec 13 11:13:53 2013
IM sig = "ImageMagick 6.8.7-9 Q16 x64 2013-11-28 http://www.imagemagick.org".
Count = 3, ImageA size = 3600 x 900.
0) Stacking image to @$imageB [1], @$imageA [1].
Truncating IA and re-reading.
1) Stacking image to @$imageB [2], @$imageA [1].
Truncating IA and re-reading.
2) Stacking image to @$imageB [3], @$imageA [1].
Truncating IA and re-reading.
Scalar @{$imageB} = 3.
ImageB[0] size = 3600 x 900.
ImageB[1] size = 3600 x 900.
ImageB[2] size = 3600 x 900.
Append stack -> TRUE. scalar @imageC = 1.
Scalar @{$imageA} = 1.
Scalar @{$imageB} = 3.
Scalar @{$imageC} = 1.
Final image stack.3.jpg X 3600, Y 2700. << NOTE: Y dimension is N times the original, 3 copies, not one.
The only difference in the code path is:
Activestate Perl, latest, IM latest:
>perl -v
This is perl 5, version 16, subversion 3 (v5.16.3) built for MSWin32-x64-multi-t...
Here is the full program:
I have a program with 3 IM objects:
A) one to read single files
B) one to accumulate files read by A
c) one to take the take the appended -> stack object B and print it.
This may not be the most optimal design, but it should work.
I have an option to stack N copies of the same object in a loop. It only works if I destroy A and re-read it before pushing it onto B each time.
I have a trivial test program which:
1) clears A, B and C,
2) reads a file into A
3) pushes A onto B N times in a loop
4) appends B, stack=>'true' and places the resulting IM object in C
5) writes C to disk.
C should contain N copies of the picture. It only contains one.
The fix is to expand step 3):
push A onto B
destroy A
Reread A
repeat N times
I know that this simple operation can be done on the command line. I have many stacks, rotations, resizes, etc so need a real programming language, not just shell commands. The object is to solve the mystery of why the IM arrays appear to be misbehaving or why I am abusing them (much more likely).
Here is the log from the misbehaving run:
M:\print\2013.1210>bb.pl 3
Running C:\bin\bb.pl 3 Fri Dec 13 11:06:16 2013
IM sig = "ImageMagick 6.8.7-9 Q16 x64 2013-11-28 http://www.imagemagick.org".
Count = 3, ImageA size = 3600 x 900.
0) Stacking image to @$imageB [1], @$imageA [1].
1) Stacking image to @$imageB [2], @$imageA [1].
2) Stacking image to @$imageB [3], @$imageA [1].
Scalar @{$imageB} = 3.
ImageB[0] size = 3600 x 900.
ImageB[1] size = 3600 x 900.
ImageB[2] size = 3600 x 900.
Append stack -> TRUE. scalar @imageC = 1.
Scalar @{$imageA} = 1.
Scalar @{$imageB} = 3.
Scalar @{$imageC} = 1.
Final image stack.3.jpg X 3600, Y 900. << NOTE: Final image resolution is the same as the original. Only 1 copy. IM B array has 3.
===========================================
here is the correct behavior truncating the A object and rereading the file every time through the loop:
M:\print\2013.1210>bb.pl 3 DESTROY_AND_REREAD
Running C:\bin\bb.pl 3, DESTROY_AND_REREAD Fri Dec 13 11:13:53 2013
IM sig = "ImageMagick 6.8.7-9 Q16 x64 2013-11-28 http://www.imagemagick.org".
Count = 3, ImageA size = 3600 x 900.
0) Stacking image to @$imageB [1], @$imageA [1].
Truncating IA and re-reading.
1) Stacking image to @$imageB [2], @$imageA [1].
Truncating IA and re-reading.
2) Stacking image to @$imageB [3], @$imageA [1].
Truncating IA and re-reading.
Scalar @{$imageB} = 3.
ImageB[0] size = 3600 x 900.
ImageB[1] size = 3600 x 900.
ImageB[2] size = 3600 x 900.
Append stack -> TRUE. scalar @imageC = 1.
Scalar @{$imageA} = 1.
Scalar @{$imageB} = 3.
Scalar @{$imageC} = 1.
Final image stack.3.jpg X 3600, Y 2700. << NOTE: Y dimension is N times the original, 3 copies, not one.
The only difference in the code path is:
- print("Truncating IA and re-reading.\n");
@$imagea = ();
$err = $imagea->Read("$file"); # Read the Fully Qualified Path.
warn $err if $err;
Activestate Perl, latest, IM latest:
>perl -v
This is perl 5, version 16, subversion 3 (v5.16.3) built for MSWin32-x64-multi-t...
Here is the full program:
Code: Select all
#!/usr/local/bin/perl -w
use Image::Magick;
use Time::HiRes qw(gettimeofday tv_interval );
$stime = [gettimeofday]; # Current start time to microseconds.
printf("Running $0 %s %s\n", join(", ", @ARGV), scalar localtime());
$| = 1;
&im_array(); # ImageManick array append problem!
printf("Elapsed time = %4.3f seconds.\n", tv_interval($stime, [gettimeofday]));
sub im_array() {
my $imagea = Image::Magick->new;
my $imageb = Image::Magick->new;
my $imagec = Image::Magick->new;
$sig = $imagea->Get('version');
print("IM sig = \"$sig\".\n");
@$imagea = @$imageb = @$imagec = (); # Truncate image arrays.
my $file = "4/bs-2012.0824-p2c.3x12.jpg";
my $count = 2;
$reread = 0;
my $ii = 0;
$count = $ARGV[0] if $ARGV[0];
$reread = $ARGV[1] if $ARGV[1];
my $ofn = "stack.$count.jpg";
$err = $imagea->Read("$file"); # Read the Fully Qualified Path.
warn $err if $err;
($xres, $yres) = $imagea->Get('columns', 'Rows');
print("Count = $count, ImageA size = $xres x $yres.\n");
for($ii = 0; $ii < $count; $ii++) {
push(@$imageb, @$imagea); # Push current image onto image array.
printf("$ii) Stacking image to \@\$imageB [%d], \@\$imageA [%d].\n",
scalar @$imageb, scalar @$imagea);
next unless $reread;
print("Truncating IA and re-reading.\n");
@$imagea = ();
$err = $imagea->Read("$file"); # Read the Fully Qualified Path.
warn $err if $err;
}
printf("Scalar \@{\$imageB} = %d.\n", scalar @$imageb);
for($ii = 0; $ii < $count; $ii++) {
($xres, $yres) = $imageb->[$ii]->Get('columns', 'Rows');
print("ImageB[$ii] size = $xres x $yres.\n");
}
$imagec = $imageb->Append(stack=>'true'); # Stack TOP to BOTtom.
printf("Append stack -> TRUE. scalar \@imageC = %d.\n", scalar @$imagec);
printf("Scalar \@{\$imageA} = %d.\n", scalar @$imagea);
printf("Scalar \@{\$imageB} = %d.\n", scalar @$imageb);
printf("Scalar \@{\$imageC} = %d.\n", scalar @$imagec);
($xres, $yres) = $imagec->Get('columns', 'Rows');
$err = $imagec->Write("$ofn");
printf("Final image $ofn X $xres, Y $yres.\n");
}