Fixes to i_map function and map method. Added a testcase for both.
authorArnar Mar Hrafnkelsson <addi@cpan.org>
Wed, 16 May 2001 18:38:27 +0000 (18:38 +0000)
committerArnar Mar Hrafnkelsson <addi@cpan.org>
Wed, 16 May 2001 18:38:27 +0000 (18:38 +0000)
Imager.pm
Imager.xs
map.c
t/t68map.t [new file with mode: 0644]

index 37eb286..aa10e65 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -58,6 +58,7 @@ use Imager::Font;
                i_conv
                
                i_convert
+               i_map
                
                i_img_diff
 
@@ -1292,6 +1293,54 @@ sub convert {
   }
   return $new;
 }
+
+
+
+
+
+# general function to map an image through lookup tables
+sub map {
+  my ($self, %opts) = @_;
+  my @chlist = qw( r g b a );
+
+  if (!exists($opts{'maps'})) {
+    # make maps from channel maps
+    my $chnum;
+    for $chnum (0..$#chlist) {
+      $opts{'maps'}[$chnum] = $opts{$chlist[$chnum]} if exists $opts{$chlist[$chnum]};
+    }
+  }
+  if ($opts{'maps'} and $self->{IMG}) {
+    i_map($self->{IMG}, $opts{'maps'} );
+  }
+  return $self;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 
 # destructive border - image is shrunk by one pixel all around
index f94e979..181451a 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -826,7 +826,45 @@ i_convert(im, src, coeff)
           myfree(coeff);
        OUTPUT:
          RETVAL
-                 
+
+
+void
+i_map(im, pmaps)
+    Imager::ImgRaw     im
+       PREINIT:
+         unsigned int mask = 0;
+         AV *avmain;
+         AV *avsub;
+          SV **temp;
+         int len;
+         int i, j;
+         unsigned char (*maps)[256];
+        CODE:
+         if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
+           croak("i_map: parameter 2 must be an arrayref\n");
+          avmain = (AV*)SvRV(ST(1));
+         len = av_len(avmain)+1;
+         if (im->channels < len) len = im->channels;
+
+         maps = mymalloc( len * sizeof(unsigned char [256]) );
+
+         for (j=0; j<len ; j++) {
+           temp = av_fetch(avmain, j, 0);
+           if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
+             avsub = (AV*)SvRV(*temp);
+             if(av_len(avsub) != 255) continue;
+             mask |= 1<<j;
+              for (i=0; i<256 ; i++) {
+               temp = av_fetch(avsub, i, 0);
+               maps[j][i] = temp ? SvIV(*temp) : 0;
+             }
+            }
+          }
+          i_map(im, maps, mask);
+         myfree(maps);
+
+
+
 float
 i_img_diff(im1,im2)
     Imager::ImgRaw     im1
diff --git a/map.c b/map.c
index a07066d..7acd64a 100644 (file)
--- a/map.c
+++ b/map.c
@@ -41,7 +41,7 @@ i_map(i_img *im, unsigned char (*maps)[256], unsigned int mask) {
   int mapno, i, ch;
   int minset = -1, maxset;
 
-  mm_log((1,"i_map(im %p, maps %p, chmask %ud)\n", im, maps, mask));
+  mm_log((1,"i_map(im %p, maps %p, chmask %u)\n", im, maps, mask));
 
   if (!mask) return; /* nothing to do here */
 
@@ -50,15 +50,17 @@ i_map(i_img *im, unsigned char (*maps)[256], unsigned int mask) {
       if (minset == -1) minset = i;
       maxset = i;
     }
-  
+
+  mm_log((1, "minset=%d maxset=%d\n", minset, maxset));
+
   vals = mymalloc(sizeof(i_color) * im->xsize);
+
   for (y = 0; y < im->ysize; ++y) {
     i_glin(im, 0, im->xsize, y, vals);
     for (x = 0; x < im->xsize; ++x) {
-      int lidx = x * im->channels;
       for(ch = minset; ch<=maxset; ch++) {
        if (!maps[ch]) continue;
-       vals[lidx].channel[ch] = maps[ch][vals[lidx].channel[ch]];
+       vals[x].channel[ch] = maps[ch][vals[x].channel[ch]];
       }
     }
     i_plin(im, 0, im->xsize, y, vals);
diff --git a/t/t68map.t b/t/t68map.t
new file mode 100644 (file)
index 0000000..4b39a6a
--- /dev/null
@@ -0,0 +1,39 @@
+Imager::init(log=>'testout/t68map.log');
+
+use Imager qw(:all :handy);
+
+print "1..5\n";
+
+my $imbase = Imager::ImgRaw::new(200,300,3);
+
+
+@map1 = map { int($_/2) } 0..255;
+@map2 = map { 255-int($_/2) } 0..255;
+@map3 = 0..255;
+@maps = 0..24;
+@mapl = 0..400;
+
+$tst = 1;
+
+i_map($imbase, [ [],     [],     \@map1 ]);
+print $tst++." ok\n";
+i_map($imbase, [ \@map1, \@map1, \@map1 ]);
+
+print $tst++." ok\n";
+i_map($imbase, [ \@map1, \@map2, \@map3 ]);
+
+print $tst++." ok\n";
+i_map($imbase, [ \@maps, \@mapl, \@map3 ]);
+
+# test the highlevel interface
+# currently this requires visual inspection of the output files
+
+
+my $im = Imager->new;
+if ($im->read(file=>'testimg/scale.ppm')) {
+  print $tst++.( $im->map(r=>\@map1, g=>\@map2, b=>\@map3) ? " ok\n" : " not ok\n");
+  print $tst++.( $im->map(maps=>[\@map1, [], \@map2]) ? " ok\n" : " not ok\n");
+}
+else {
+  die "could not load testout/scale.ppm\n";
+}