]> git.imager.perl.org - imager.git/commitdiff
oops
authorTony Cook <tony@develop=help.com>
Sun, 7 Oct 2001 23:23:04 +0000 (23:23 +0000)
committerTony Cook <tony@develop=help.com>
Sun, 7 Oct 2001 23:23:04 +0000 (23:23 +0000)
imgdouble.c [new file with mode: 0644]
t/t022double.t [new file with mode: 0644]

diff --git a/imgdouble.c b/imgdouble.c
new file mode 100644 (file)
index 0000000..df5df96
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+=head1 NAME
+
+imgdouble.c - implements double per sample images
+
+=head1 SYNOPSIS
+
+  i_img *im = i_img_double_new(int x, int y, int channels);
+  # use like a normal image
+
+=head1 DESCRIPTION
+
+Implements double/sample images.
+
+This basic implementation is required so that we have some larger 
+sample image type to work with.
+
+=over
+
+=cut
+*/
+
+#include "image.h"
+#include "imagei.h"
+
+static int i_ppix_ddoub(i_img *im, int x, int y, i_color *val);
+static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val);
+static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals);
+static int i_plin_ddoub(i_img *im, int l, int r, int y, i_color *vals);
+static int i_ppixf_ddoub(i_img *im, int x, int y, i_fcolor *val);
+static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val);
+static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals);
+static int i_plinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals);
+static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps, 
+                       int *chans, int chan_count);
+static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps, 
+                        int *chans, int chan_count);
+
+/*
+=item IIM_base_16bit_direct
+
+Base structure used to initialize a 16-bit/sample image.
+
+Internal.
+
+=cut
+*/
+static i_img IIM_base_double_direct =
+{
+  0, /* channels set */
+  0, 0, 0, /* xsize, ysize, bytes */
+  ~0, /* ch_mask */
+  i_double_bits, /* bits */
+  i_direct_type, /* type */
+  0, /* virtual */
+  NULL, /* idata */
+  { 0, 0, NULL }, /* tags */
+  NULL, /* ext_data */
+
+  i_ppix_ddoub, /* i_f_ppix */
+  i_ppixf_ddoub, /* i_f_ppixf */
+  i_plin_ddoub, /* i_f_plin */
+  i_plinf_ddoub, /* i_f_plinf */
+  i_gpix_ddoub, /* i_f_gpix */
+  i_gpixf_ddoub, /* i_f_gpixf */
+  i_glin_ddoub, /* i_f_glin */
+  i_glinf_ddoub, /* i_f_glinf */
+  i_gsamp_ddoub, /* i_f_gsamp */
+  i_gsampf_ddoub, /* i_f_gsampf */
+
+  NULL, /* i_f_gpal */
+  NULL, /* i_f_ppal */
+  NULL, /* i_f_addcolor */
+  NULL, /* i_f_getcolor */
+  NULL, /* i_f_colorcount */
+  NULL, /* i_f_findcolor */
+
+  NULL, /* i_f_destroy */
+};
+
+/*
+=item i_img_double_new(int x, int y, int ch)
+
+Creates a new double per sample image.
+
+=cut
+*/
+i_img *i_img_double_new_low(i_img *im, int x, int y, int ch) {
+  mm_log((1,"i_img_double_new(x %d, y %d, ch %d)\n", x, y, ch));
+  
+  *im = IIM_base_double_direct;
+  i_tags_new(&im->tags);
+  im->xsize = x;
+  im->ysize = y;
+  im->channels = ch;
+  im->bytes = x * y * ch * sizeof(double);
+  im->ext_data = NULL;
+  im->idata = mymalloc(im->bytes);
+  if (im->idata) {
+    memset(im->idata, 0, im->bytes);
+  }
+  else {
+    i_tags_destroy(&im->tags);
+    im = NULL;
+  }
+  
+  return im;
+}
+
+i_img *i_img_double_new(int x, int y, int ch) {
+  i_img *im;
+
+  im = mymalloc(sizeof(i_img));
+  if (im) {
+    if (!i_img_double_new_low(im, x, y, ch)) {
+      myfree(im);
+      im = NULL;
+    }
+  }
+  
+  mm_log((1, "(%p) <- i_img_double_new\n", im));
+  
+  return im;
+}
+
+static int i_ppix_ddoub(i_img *im, int x, int y, i_color *val) {
+  int off, ch;
+
+  if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize) 
+    return -1;
+
+  off = (x + y * im->xsize) * im->channels;
+  for (ch = 0; ch < im->channels; ++ch)
+    ((double*)im->idata)[off+ch] = Sample8ToF(val->channel[ch]);
+
+  return 0;
+}
+
+static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val) {
+  int off, ch;
+
+  if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize) 
+    return -1;
+
+  off = (x + y * im->xsize) * im->channels;
+  for (ch = 0; ch < im->channels; ++ch)
+    val->channel[ch] = SampleFTo8(((double *)im->idata)[off+ch]);
+
+  return 0;
+}
+
+static int i_ppixf_ddoub(i_img *im, int x, int y, i_fcolor *val) {
+  int off, ch;
+
+  if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize) 
+    return -1;
+
+  off = (x + y * im->xsize) * im->channels;
+  for (ch = 0; ch < im->channels; ++ch)
+    ((double *)im->idata)[off+ch] = val->channel[ch];;
+
+  return 0;
+}
+
+static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val) {
+  int off, ch;
+
+  if (x < 0 || x >= im->xsize || y < 0 || y > im->ysize) 
+    return -1;
+
+  off = (x + y * im->xsize) * im->channels;
+  for (ch = 0; ch < im->channels; ++ch)
+    val->channel[ch] = ((double *)im->idata)[off+ch];
+
+  return 0;
+}
+
+static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals) {
+  int ch, count, i;
+  int off;
+  if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+    if (r > im->xsize)
+      r = im->xsize;
+    off = (l+y*im->xsize) * im->channels;
+    count = r - l;
+    for (i = 0; i < count; ++i) {
+      for (ch = 0; ch < im->channels; ++ch) {
+       vals[i].channel[ch] = SampleFTo8(((double *)im->idata)[off]);
+        ++off;
+      }
+    }
+    return count;
+  }
+  else {
+    return 0;
+  }
+}
+
+static int i_plin_ddoub(i_img *im, int l, int r, int y, i_color *vals) {
+  int ch, count, i;
+  int off;
+  if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+    if (r > im->xsize)
+      r = im->xsize;
+    off = (l+y*im->xsize) * im->channels;
+    count = r - l;
+    for (i = 0; i < count; ++i) {
+      for (ch = 0; ch < im->channels; ++ch) {
+        ((double *)im->idata)[off] = Sample8ToF(vals[i].channel[ch]);
+        ++off;
+      }
+    }
+    return count;
+  }
+  else {
+    return 0;
+  }
+}
+
+static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals) {
+  int ch, count, i;
+  int off;
+  if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+    if (r > im->xsize)
+      r = im->xsize;
+    off = (l+y*im->xsize) * im->channels;
+    count = r - l;
+    for (i = 0; i < count; ++i) {
+      for (ch = 0; ch < im->channels; ++ch) {
+       vals[i].channel[ch] = ((double *)im->idata)[off];
+        ++off;
+      }
+    }
+    return count;
+  }
+  else {
+    return 0;
+  }
+}
+
+static int i_plinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals) {
+  int ch, count, i;
+  int off;
+  if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+    if (r > im->xsize)
+      r = im->xsize;
+    off = (l+y*im->xsize) * im->channels;
+    count = r - l;
+    for (i = 0; i < count; ++i) {
+      for (ch = 0; ch < im->channels; ++ch) {
+        ((double *)im->idata)[off] = vals[i].channel[ch];
+        ++off;
+      }
+    }
+    return count;
+  }
+  else {
+    return 0;
+  }
+}
+
+static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps, 
+                       int *chans, int chan_count) {
+  int ch, count, i, w;
+  int off;
+
+  if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+    if (r > im->xsize)
+      r = im->xsize;
+    off = (l+y*im->xsize) * im->channels;
+    w = r - l;
+    count = 0;
+
+    if (chans) {
+      /* make sure we have good channel numbers */
+      for (ch = 0; ch < chan_count; ++ch) {
+        if (chans[ch] < 0 || chans[ch] >= im->channels) {
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
+          return 0;
+        }
+      }
+      for (i = 0; i < w; ++i) {
+        for (ch = 0; ch < chan_count; ++ch) {
+          *samps++ = SampleFTo8(((double *)im->idata)[off+chans[ch]]);
+          ++count;
+        }
+        off += im->channels;
+      }
+    }
+    else {
+      for (i = 0; i < w; ++i) {
+        for (ch = 0; ch < chan_count; ++ch) {
+          *samps++ = SampleFTo8(((double *)im->idata)[off+ch]);
+          ++count;
+        }
+        off += im->channels;
+      }
+    }
+
+    return count;
+  }
+  else {
+    return 0;
+  }
+}
+
+static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps, 
+                        int *chans, int chan_count) {
+  int ch, count, i, w;
+  int off;
+
+  if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
+    if (r > im->xsize)
+      r = im->xsize;
+    off = (l+y*im->xsize) * im->channels;
+    w = r - l;
+    count = 0;
+
+    if (chans) {
+      /* make sure we have good channel numbers */
+      for (ch = 0; ch < chan_count; ++ch) {
+        if (chans[ch] < 0 || chans[ch] >= im->channels) {
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
+          return 0;
+        }
+      }
+      for (i = 0; i < w; ++i) {
+        for (ch = 0; ch < chan_count; ++ch) {
+          *samps++ = ((double *)im->idata)[off+chans[ch]];
+          ++count;
+        }
+        off += im->channels;
+      }
+    }
+    else {
+      for (i = 0; i < w; ++i) {
+        for (ch = 0; ch < chan_count; ++ch) {
+          *samps++ = ((double *)im->idata)[off+ch];
+          ++count;
+        }
+        off += im->channels;
+      }
+    }
+
+    return count;
+  }
+  else {
+    return 0;
+  }
+}
+
diff --git a/t/t022double.t b/t/t022double.t
new file mode 100644 (file)
index 0000000..64f9b1f
--- /dev/null
@@ -0,0 +1,113 @@
+#!perl -w
+use strict;
+BEGIN { $| = 1; print "1..29\n"; }
+my $loaded;
+END {print "not ok 1\n" unless $loaded;}
+use Imager qw(:all :handy);
+#use Data::Dumper;
+$loaded = 1;
+print "ok 1\n";
+init_log("testout/t022double.log", 1);
+
+use Imager::Color::Float;
+
+my $im_g = Imager::i_img_double_new(100, 101, 1);
+
+ok(2, Imager::i_img_getchannels($im_g) == 1, 
+   "1 channel image channel count mismatch");
+ok(3, Imager::i_img_getmask($im_g) & 1, "1 channel image bad mask");
+ok(4, Imager::i_img_virtual($im_g) == 0, 
+  "1 channel image thinks it is virtual");
+my $double_bits = length(pack("d", 1)) * 8;
+ok(5, Imager::i_img_bits($im_g) == $double_bits, 
+   "1 channel image has bits != $double_bits");
+ok(6, Imager::i_img_type($im_g) == 0, "1 channel image isn't direct");
+
+my @ginfo = i_img_info($im_g);
+ok(7, $ginfo[0] == 100, "1 channel image width incorrect");
+ok(8, $ginfo[1] == 101, "1 channel image height incorrect");
+
+undef $im_g;
+
+my $im_rgb = Imager::i_img_double_new(100, 101, 3);
+
+ok(9, Imager::i_img_getchannels($im_rgb) == 3,
+   "3 channel image channel count mismatch");
+ok(10, (Imager::i_img_getmask($im_rgb) & 7) == 7, "3 channel image bad mask");
+ok(11, Imager::i_img_bits($im_rgb) == $double_bits,
+  "3 channel image has bits != $double_bits");
+ok(12, Imager::i_img_type($im_rgb) == 0, "3 channel image isn't direct");
+
+my $redf = NCF(1, 0, 0);
+my $greenf = NCF(0, 1, 0);
+my $bluef = NCF(0, 0, 1);
+
+# fill with red
+for my $y (0..101) {
+  Imager::i_plinf($im_rgb, 0, $y, ($redf) x 100);
+}
+print "ok 13\n";
+# basic sanity
+test_colorf_gpix(14, $im_rgb, 0,  0,   $redf);
+test_colorf_gpix(16, $im_rgb, 99, 0,   $redf);
+test_colorf_gpix(18, $im_rgb, 0,  100, $redf);
+test_colorf_gpix(20, $im_rgb, 99, 100, $redf);
+test_colorf_glin(22, $im_rgb, 0,  0,   ($redf) x 100);
+test_colorf_glin(24, $im_rgb, 0,  100, ($redf) x 100);
+
+Imager::i_plinf($im_rgb, 20, 1, ($greenf) x 60);
+test_colorf_glin(26, $im_rgb, 0, 1, 
+                 ($redf) x 20, ($greenf) x 60, ($redf) x 20);
+
+# basic OO tests
+my $oo16img = Imager->new(xsize=>200, ysize=>201, bits=>16)
+  or print "not ";
+print "ok 28\n";
+$oo16img->bits == 16 or print "not ";
+print "ok 29\n";
+
+
+sub NCF {
+  return Imager::Color::Float->new(@_);
+}
+
+sub test_colorf_gpix {
+  my ($test_base, $im, $x, $y, $expected) = @_;
+  my $c = Imager::i_gpixf($im, $x, $y);
+  $c or print "not ";
+  print "ok ",$test_base++,"\n";
+  colorf_cmp($c, $expected) == 0 or print "not ";
+  print "ok ",$test_base++,"\n";
+}
+
+sub test_colorf_glin {
+  my ($test_base, $im, $x, $y, @pels) = @_;
+
+  my @got = Imager::i_glinf($im, $x, $x+@pels, $y);
+  @got == @pels or print "not ";
+  print "ok ",$test_base++,"\n";
+  grep(colorf_cmp($pels[$_], $got[$_]), 0..$#got) and print "not ";
+  print "ok ",$test_base++,"\n";
+}
+
+sub colorf_cmp {
+  my ($c1, $c2) = @_;
+  my @s1 = map { int($_*65535.99) } $c1->rgba;
+  my @s2 = map { int($_*65535.99) } $c2->rgba;
+
+  # print "# (",join(",", @s1[0..2]),") <=> (",join(",", @s2[0..2]),")\n";
+  return $s1[0] <=> $s2[0] 
+    || $s1[1] <=> $s2[1]
+      || $s1[2] <=> $s2[2];
+}
+
+sub ok {
+  my ($test_num, $ok, $comment) = @_;
+
+  if ($ok) {
+    print "ok $test_num\n";
+  }
+  else {
+    print "not ok $test_num # $comment\n";
+  }
+}