Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

merge in tiff re-work branch

  • Loading branch information...
commit bd8052a6c49bf23a2fb5965c59f18192b26bb8b4 1 parent 5c96c6b
authored

Showing 49 changed files with 3,564 additions and 686 deletions. Show diff stats Hide diff stats

  1. 18  Changes
  2. 140  Imager.pm
  3. 135  Imager.xs
  4. 15  MANIFEST
  5. 9  README
  6. 2  TODO
  7. 4  apidocs.perl
  8. 62  conv.c → conv.im
  9. 4  gaussian.im
  10. 166  image.c
  11. 12  imager.h
  12. 4  imageri.h
  13. 108  imdatatypes.h
  14. 6  imext.c
  15. 3  imext.h
  16. 6  imexttypes.h
  17. 194  img16.c
  18. 41  imgdouble.c
  19. 209  lib/Imager/APIRef.pod
  20. 67  lib/Imager/Draw.pod
  21. 70  lib/Imager/Files.pod
  22. 7  lib/Imager/Handy.pod
  23. 36  lib/Imager/ImageTypes.pod
  24. 203  lib/Imager/Test.pm
  25. 8  log.c
  26. 12  log.h
  27. 48  palimg.c
  28. 11  t/t01introvert.t
  29. 80  t/t021sixteen.t
  30. 3  t/t022double.t
  31. 35  t/t023palette.t
  32. 314  t/t106tiff.t
  33. 2  t/t61filters.t
  34. 3  t/testtools.pl
  35. BIN  testimg/alpha.tif
  36. BIN  testimg/comp4t.tif
  37. BIN  testimg/gralpha.tif
  38. BIN  testimg/grey16.tif
  39. BIN  testimg/grey32.tif
  40. BIN  testimg/imager.pbm
  41. BIN  testimg/imager.tif
  42. BIN  testimg/pengtile.tif
  43. BIN  testimg/rgb16.tif
  44. BIN  testimg/rgb16t.tif
  45. BIN  testimg/scmyka16.tif
  46. BIN  testimg/srgba16.tif
  47. BIN  testimg/srgba32.tif
  48. BIN  testimg/srgbaa.tif
  49. 2,213  tiff.c
18  Changes
@@ -3,6 +3,24 @@ Imager release history.  Older releases can be found in Changes.old
3 3
 Imager 0.62 - not yet released
4 4
 ===========
5 5
 
  6
+ - major TIFF support re-work
  7
+   http://rt.cpan.org/Ticket/Display.html?id=20329
  8
+
  9
+ - added a C level image interface for accessing samples from 1-32
  10
+   bits, exposed this at the perl level in getsamples()
  11
+
  12
+ - the conv filter now works at floating point precision for high bit
  13
+   images
  14
+
  15
+ - added is_bilevel method to test whether an image should be written as
  16
+   a bilevel image if the image format supports it.
  17
+
  18
+ - added -log-stderr as an Imager import list option
  19
+
  20
+ - added some important types to Imager::APIRef
  21
+
  22
+ - added test_image_double() to Imager::Test
  23
+
6 24
 Bug fixes:
7 25
 
8 26
  - Imager::Fountain couldn't read GIMP gradient files with 10 or more
140  Imager.pm
@@ -117,6 +117,7 @@ use Imager::Font;
117 117
 		newcolour
118 118
 		NC
119 119
 		NF
  120
+                NCF
120 121
 );
121 122
 
122 123
 @EXPORT=qw(
@@ -136,6 +137,7 @@ use Imager::Font;
136 137
 		newcolor
137 138
 		NF
138 139
 		NC
  140
+                NCF
139 141
 	       )],
140 142
    all => [@EXPORT_OK],
141 143
    default => [qw(
@@ -426,13 +428,19 @@ BEGIN {
426 428
 # initlize Imager
427 429
 # NOTE: this might be moved to an import override later on
428 430
 
429  
-#sub import {
430  
-#  my $pack = shift;
431  
-#  (look through @_ for special tags, process, and remove them);   
432  
-#  use Data::Dumper;
433  
-#  print Dumper($pack);
434  
-#  print Dumper(@_);
435  
-#}
  431
+sub import {
  432
+  my $i = 1;
  433
+  while ($i < @_) {
  434
+    if ($_[$i] eq '-log-stderr') {
  435
+      init_log(undef, 4);
  436
+      splice(@_, $i, 1);
  437
+    }
  438
+    else {
  439
+      ++$i;
  440
+    }
  441
+  }
  442
+  goto &Exporter::import;
  443
+}
436 444
 
437 445
 sub init_log {
438 446
   i_init_log($_[0],$_[1]);
@@ -1025,6 +1033,14 @@ sub virtual {
1025 1033
   $self->{IMG} and i_img_virtual($self->{IMG});
1026 1034
 }
1027 1035
 
  1036
+sub is_bilevel {
  1037
+  my ($self) = @_;
  1038
+
  1039
+  $self->{IMG} or return;
  1040
+
  1041
+  return i_img_is_monochrome($self->{IMG});
  1042
+}
  1043
+
1028 1044
 sub tags {
1029 1045
   my ($self, %opts) = @_;
1030 1046
 
@@ -3041,7 +3057,7 @@ sub setscanline {
3041 3057
 
3042 3058
 sub getsamples {
3043 3059
   my $self = shift;
3044  
-  my %opts = ( type => '8bit', x=>0, @_);
  3060
+  my %opts = ( type => '8bit', x=>0, offset => 0, @_);
3045 3061
 
3046 3062
   defined $opts{width} or $opts{width} = $self->getwidth - $opts{x};
3047 3063
 
@@ -3054,18 +3070,103 @@ sub getsamples {
3054 3070
     $opts{channels} = [ 0 .. $self->getchannels()-1 ];
3055 3071
   }
3056 3072
 
3057  
-  if ($opts{type} eq '8bit') {
3058  
-    return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3059  
-		   $opts{y}, @{$opts{channels}});
3060  
-  }
3061  
-  elsif ($opts{type} eq 'float') {
3062  
-    return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
3063  
-		    $opts{y}, @{$opts{channels}});
  3073
+  if ($opts{target}) {
  3074
+    my $target = $opts{target};
  3075
+    my $offset = $opts{offset};
  3076
+    if ($opts{type} eq '8bit') {
  3077
+      my @samples = i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
  3078
+			    $opts{y}, @{$opts{channels}})
  3079
+	or return;
  3080
+      @{$target}{$offset .. $offset + @samples - 1} = @samples;
  3081
+      return scalar(@samples);
  3082
+    }
  3083
+    elsif ($opts{type} eq 'float') {
  3084
+      my @samples = i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
  3085
+			     $opts{y}, @{$opts{channels}});
  3086
+      @{$target}{$offset .. $offset + @samples - 1} = @samples;
  3087
+      return scalar(@samples);
  3088
+    }
  3089
+    elsif ($opts{type} =~ /^(\d+)bit$/) {
  3090
+      my $bits = $1;
  3091
+
  3092
+      my @data;
  3093
+      my $count = i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width}, 
  3094
+			       $opts{y}, $bits, $target, 
  3095
+			       $offset, @{$opts{channels}});
  3096
+      unless (defined $count) {
  3097
+	$self->_set_error(Imager->_error_as_msg);
  3098
+	return;
  3099
+      }
  3100
+
  3101
+      return $count;
  3102
+    }
  3103
+    else {
  3104
+      $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
  3105
+      return;
  3106
+    }
3064 3107
   }
3065 3108
   else {
3066  
-    $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
  3109
+    if ($opts{type} eq '8bit') {
  3110
+      return i_gsamp($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
  3111
+		     $opts{y}, @{$opts{channels}});
  3112
+    }
  3113
+    elsif ($opts{type} eq 'float') {
  3114
+      return i_gsampf($self->{IMG}, $opts{x}, $opts{x}+$opts{width},
  3115
+		      $opts{y}, @{$opts{channels}});
  3116
+    }
  3117
+    elsif ($opts{type} =~ /^(\d+)bit$/) {
  3118
+      my $bits = $1;
  3119
+
  3120
+      my @data;
  3121
+      i_gsamp_bits($self->{IMG}, $opts{x}, $opts{x}+$opts{width}, 
  3122
+		   $opts{y}, $bits, \@data, 0, @{$opts{channels}})
  3123
+	or return;
  3124
+      return @data;
  3125
+    }
  3126
+    else {
  3127
+      $self->_set_error("invalid type parameter - must be '8bit' or 'float'");
  3128
+      return;
  3129
+    }
  3130
+  }
  3131
+}
  3132
+
  3133
+sub setsamples {
  3134
+  my $self = shift;
  3135
+  my %opts = ( x => 0, offset => 0, @_ );
  3136
+
  3137
+  unless ($self->{IMG}) {
  3138
+    $self->_set_error('setsamples: empty input image');
  3139
+    return;
  3140
+  }
  3141
+
  3142
+  unless(defined $opts{data} && ref $opts{data}) {
  3143
+    $self->_set_error('setsamples: data parameter missing or invalid');
3067 3144
     return;
3068 3145
   }
  3146
+
  3147
+  unless ($opts{channels}) {
  3148
+    $opts{channels} = [ 0 .. $self->getchannels()-1 ];
  3149
+  }
  3150
+
  3151
+  unless ($opts{type} && $opts{type} =~ /^(\d+)bit$/) {
  3152
+    $self->_set_error('setsamples: type parameter missing or invalid');
  3153
+    return;
  3154
+  }
  3155
+  my $bits = $1;
  3156
+
  3157
+  unless (defined $opts{width}) {
  3158
+    $opts{width} = $self->getwidth() - $opts{x};
  3159
+  }
  3160
+
  3161
+  my $count = i_psamp_bits($self->{IMG}, $opts{x}, $opts{y}, $bits,
  3162
+			   $opts{channels}, $opts{data}, $opts{offset}, 
  3163
+			   $opts{width});
  3164
+  unless (defined $count) {
  3165
+    $self->_set_error(Imager->_error_as_msg);
  3166
+    return;
  3167
+  }
  3168
+
  3169
+  return $count;
3069 3170
 }
3070 3171
 
3071 3172
 # make an identity matrix of the given size
@@ -3446,6 +3547,7 @@ sub get_file_limits {
3446 3547
 
3447 3548
 sub newcolor { Imager::Color->new(@_); }
3448 3549
 sub newfont  { Imager::Font->new(@_); }
  3550
+sub NCF { Imager::Color::Float->new(@_) }
3449 3551
 
3450 3552
 *NC=*newcolour=*newcolor;
3451 3553
 *NF=*newfont;
@@ -3840,6 +3942,8 @@ img_set() - L<Imager::ImageTypes/img_set>
3840 3942
 
3841 3943
 init() - L<Imager::ImageTypes/init>
3842 3944
 
  3945
+is_bilevel - L<Imager::ImageTypes/is_bilevel>
  3946
+
3843 3947
 line() - L<Imager::Draw/line>
3844 3948
 
3845 3949
 load_plugin() - L<Imager::Filters/load_plugin>
@@ -3855,6 +3959,8 @@ maxcolors() - L<Imager::ImageTypes/maxcolors>
3855 3959
 
3856 3960
 NC() - L<Imager::Handy/NC>
3857 3961
 
  3962
+NCF() - L<Imager::Handy/NCF>
  3963
+
3858 3964
 new() - L<Imager::ImageTypes/new>
3859 3965
 
3860 3966
 newcolor() - L<Imager::Handy/newcolor>
@@ -3910,6 +4016,8 @@ setmask() - L<Imager::ImageTypes/setmask>
3910 4016
 
3911 4017
 setpixel() - L<Imager::Draw/setpixel>
3912 4018
 
  4019
+setsamples() - L<Imager::Draw/setsamples>
  4020
+
3913 4021
 setscanline() - L<Imager::Draw/setscanline>
3914 4022
 
3915 4023
 settag() - L<Imager::ImageTypes/settag>
135  Imager.xs
@@ -1287,9 +1287,13 @@ i_sametype_chans(im, x, y, channels)
1287 1287
                int channels
1288 1288
 
1289 1289
 void
1290  
-i_init_log(name,level)
1291  
-	      char*    name
  1290
+i_init_log(name_sv,level)
  1291
+	      SV*    name_sv
1292 1292
 	       int     level
  1293
+	PREINIT:
  1294
+	  const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
  1295
+	CODE:
  1296
+	  i_init_log(name, level);
1293 1297
 
1294 1298
 void
1295 1299
 i_log_entry(string,level)
@@ -1343,6 +1347,25 @@ i_img_getdata(im)
1343 1347
 	             sv_2mortal(newSVpv((char *)im->idata, im->bytes)) 
1344 1348
 		     : &PL_sv_undef);
1345 1349
 
  1350
+void
  1351
+i_img_is_monochrome(im)
  1352
+	Imager::ImgRaw im
  1353
+      PREINIT:
  1354
+	int zero_is_white;
  1355
+	int result;
  1356
+      PPCODE:
  1357
+	result = i_img_is_monochrome(im, &zero_is_white);
  1358
+	if (result) {
  1359
+	  if (GIMME_V == G_ARRAY) {
  1360
+	    EXTEND(SP, 2);
  1361
+	    PUSHs(&PL_sv_yes);
  1362
+	    PUSHs(sv_2mortal(newSViv(zero_is_white)));
  1363
+ 	  }
  1364
+	  else {
  1365
+	    EXTEND(SP, 1);
  1366
+	    PUSHs(&PL_sv_yes);
  1367
+	  }
  1368
+	}
1346 1369
 
1347 1370
 void
1348 1371
 i_line(im,x1,y1,x2,y2,val,endp)
@@ -2368,6 +2391,12 @@ i_writetiff_multi_wiol_faxable(ig, fine, ...)
2368 2391
       OUTPUT:
2369 2392
         RETVAL
2370 2393
 
  2394
+const char *
  2395
+i_tiff_libversion()
  2396
+
  2397
+bool
  2398
+i_tiff_has_compression(name)
  2399
+	const char *name
2371 2400
 
2372 2401
 #endif /* HAVE_LIBTIFF */
2373 2402
 
@@ -3772,6 +3801,108 @@ i_gsamp(im, l, r, y, ...)
3772 3801
           }
3773 3802
         }
3774 3803
 
  3804
+undef_neg_int
  3805
+i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
  3806
+        Imager::ImgRaw im
  3807
+        int l
  3808
+        int r
  3809
+        int y
  3810
+	int bits
  3811
+	AV *target
  3812
+	int offset
  3813
+      PREINIT:
  3814
+        int *chans;
  3815
+        int chan_count;
  3816
+        unsigned *data;
  3817
+        int count, i;
  3818
+      CODE:
  3819
+	i_clear_error();
  3820
+        if (items < 8)
  3821
+          croak("No channel numbers supplied to g_samp()");
  3822
+        if (l < r) {
  3823
+          chan_count = items - 7;
  3824
+          chans = mymalloc(sizeof(int) * chan_count);
  3825
+          for (i = 0; i < chan_count; ++i)
  3826
+            chans[i] = SvIV(ST(i+7));
  3827
+          data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
  3828
+          count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
  3829
+	  myfree(chans);
  3830
+	  for (i = 0; i < count; ++i) {
  3831
+	    av_store(target, i+offset, newSVuv(data[i]));
  3832
+	  }
  3833
+	  myfree(data);
  3834
+	  RETVAL = count;
  3835
+        }
  3836
+        else {
  3837
+	  RETVAL = 0;
  3838
+        }
  3839
+      OUTPUT:
  3840
+	RETVAL
  3841
+
  3842
+undef_neg_int
  3843
+i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
  3844
+        Imager::ImgRaw im
  3845
+        int l
  3846
+        int y
  3847
+	int bits
  3848
+	SV *channels_sv
  3849
+	AV *data_av
  3850
+        int data_offset
  3851
+        int pixel_count
  3852
+      PREINIT:
  3853
+	int chan_count;
  3854
+	int *channels;
  3855
+	int data_count;
  3856
+	int data_used;
  3857
+	unsigned *data;
  3858
+	int i;
  3859
+      CODE:
  3860
+	i_clear_error();
  3861
+	if (SvOK(channels_sv)) {
  3862
+	  AV *channels_av;
  3863
+	  if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
  3864
+	    croak("channels is not an array ref");
  3865
+	  }
  3866
+	  channels_av = (AV *)SvRV(channels_sv);
  3867
+ 	  chan_count = av_len(channels_av) + 1;
  3868
+	  if (chan_count < 1) {
  3869
+	    croak("i_psamp_bits: no channels provided");
  3870
+	  }
  3871
+	  channels = mymalloc(sizeof(int) * chan_count);
  3872
+ 	  for (i = 0; i < chan_count; ++i)
  3873
+	    channels[i] = SvIV(*av_fetch(channels_av, i, 0));
  3874
+        }
  3875
+	else {
  3876
+	  chan_count = im->channels;
  3877
+	  channels = NULL;
  3878
+	}
  3879
+
  3880
+	data_count = av_len(data_av) + 1;
  3881
+	if (data_offset < 0) {
  3882
+	  croak("data_offset must by non-negative");
  3883
+	}
  3884
+	if (data_offset > data_count) {
  3885
+	  croak("data_offset greater than number of samples supplied");
  3886
+        }
  3887
+	if (pixel_count == -1 || 
  3888
+	    data_offset + pixel_count * chan_count > data_count) {
  3889
+	  pixel_count = (data_count - data_offset) / chan_count;
  3890
+	}
  3891
+
  3892
+	data_used = pixel_count * chan_count;
  3893
+	data = mymalloc(sizeof(unsigned) * data_count);
  3894
+	for (i = 0; i < data_used; ++i)
  3895
+	  data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
  3896
+
  3897
+	RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels, 
  3898
+	                      chan_count, bits);
  3899
+
  3900
+	if (data)
  3901
+	  myfree(data);
  3902
+	if (channels)
  3903
+	  myfree(channels);
  3904
+      OUTPUT:
  3905
+	RETVAL
3775 3906
 
3776 3907
 Imager::ImgRaw
3777 3908
 i_img_masked_new(targ, mask, x, y, w, h)
15  MANIFEST
@@ -75,7 +75,7 @@ apidocs.perl    Build lib/Imager/APIRef.pm
75 75
 bigtest.perl	Library selection tester
76 76
 bmp.c           Reading and writing Windows BMP files
77 77
 color.c         Color translation and handling
78  
-conv.c
  78
+conv.im
79 79
 convert.c
80 80
 doco.perl
81 81
 datatypes.c
@@ -274,6 +274,7 @@ t/tr18561.t		Regression tests
274 274
 t/tr18561b.t
275 275
 tags.c
276 276
 testimg/209_yonge.jpg	Regression test: #17981
  277
+testimg/alpha.tif	Alpha scaling test image
277 278
 testimg/bad1oflow.bmp   1-bit/pixel, overflow integer on 32-bit machines
278 279
 testimg/bad1wid0.bmp    1-bit/pixel, zero width
279 280
 testimg/bad24comp.bmp   24-bit/pixel, bad compression
@@ -302,11 +303,17 @@ testimg/base.jpg	Base JPEG test image
302 303
 testimg/comp4.bmp       Compressed 4-bit/pixel BMP
303 304
 testimg/comp4.tif       4-bit/pixel paletted TIFF
304 305
 testimg/comp4bad.tif    corrupted 4-bit/pixel paletted TIFF
  306
+testimg/comp4t.tif      4-bit/pixel paletted TIFF (tiled)
305 307
 testimg/comp8.bmp       Compressed 8-bit/pixel BMP
306 308
 testimg/comp8.tif       8-bit/pixel paletted TIFF
307 309
 testimg/exiftest.jpg	Test image for EXIF parsing
308 310
 testimg/expected.gif
309 311
 testimg/gimpgrad        A GIMP gradient file
  312
+testimg/gralpha.tif	Grey alpha test image
  313
+testimg/grey16.tif	16-bit/sample greyscale TIFF
  314
+testimg/grey32.tif	32-bit/sample greyscale+alpha TIFF
  315
+testimg/imager.pbm	Test bi-level
  316
+testimg/imager.tif	Test bi-level
310 317
 testimg/junk.ppm
311 318
 testimg/loccmap.gif
312 319
 testimg/longid.tga      Test TGA with a long id string
@@ -321,13 +328,17 @@ testimg/nocmap.gif
321 328
 testimg/palette.png
322 329
 testimg/palette_out.png
323 330
 testimg/penguin-base.ppm
  331
+testimg/pengtile.tif	Tiled tiff image, same as penguin-base.ppm
324 332
 testimg/pgm.pgm		Simple pgm for testing the right sample is in the right place
  333
+testimg/rgb16.tif	16-bit/sample RGB image - strips
  334
+testimg/rgb16t.tif	16-bit/sample RGB image - tiled
325 335
 testimg/scale.gif
326 336
 testimg/scale.ppm
327 337
 testimg/scalei.gif
328 338
 testimg/scmyk.tif	Simple CMYK TIFF image
329 339
 testimg/scmyk.jpg	Simple CMYK JPEG image
330 340
 testimg/scmyka.tif	CMYK with one alpha channel
  341
+testimg/scmyka16.tif	CMYK with one alpha channel (16-bit)
331 342
 testimg/scmykaa.tif	CMYK with 2 alpha channels
332 343
 testimg/screen2.gif
333 344
 testimg/screen3.gif
@@ -349,6 +360,8 @@ testimg/simple.pbm
349 360
 testimg/slab.tif	Lab color image
350 361
 testimg/srgb.tif	Simple RGB image
351 362
 testimg/srgba.tif	RGB with one alpha
  363
+testimg/srgba16.tif
  364
+testimg/srgba32.tif
352 365
 testimg/srgbaa.tif	RGB with 2 alpha
353 366
 testimg/test_gimp_pal   A simple GIMP palette file
354 367
 testimg/tiffwarn.tif	Generates a warning while being read
9  README
@@ -110,10 +110,11 @@ Stock libungif 4.1.4 or later seems to fix all of the bugs, if you
110 110
 have a problem that version of linungif (or later), let us know and
111 111
 we'll look into it.
112 112
 
113  
-Imager needs to have a libtiff version of at least 3.5.5.  In the
114  
-future we might consider supporting older libtiff versions.  For
115  
-now you can either configure Imager manually (by
116  
-setting the IM_MANUAL environment variable to 1, in sh:
  113
+Imager needs to have a libtiff version of at least 3.5.5, but you
  114
+should use a later version since some noticable bugs have been fixed.
  115
+
  116
+For now you can either configure Imager manually (by setting the
  117
+IM_MANUAL environment variable to 1, in sh:
117 118
 
118 119
 $ IM_MANUAL=1 perl Makefile.PL
119 120
 
2  TODO
@@ -28,7 +28,7 @@ general alpha channel fixes (#29879, etc)
28 28
 
29 29
 For 0.62:
30 30
 
31  
-TIFF improvements (to be detailed) (#20329)
  31
+TIFF improvements (to be detailed) (#20329) (done)
32 32
  - read/write 16-bit RGB w/ and w/o alpha
33 33
  - read 16-bit CMYK w/ and w/o alpha
34 34
  - read/write 32-bit RGB w/ and w/o alpha
4  apidocs.perl
@@ -11,7 +11,7 @@
11 11
 # look for files to parse
12 12
 
13 13
 my $mani = maniread;
14  
-my @files = grep /\.(c|im)$/, keys %$mani;
  14
+my @files = grep /\.(c|im|h)$/, keys %$mani;
15 15
 
16 16
 # scan each file for =item <func>\b
17 17
 my $func;
@@ -162,7 +162,7 @@ =head1 SEE ALSO
162 162
 
163 163
 
164 164
 sub make_func_list {
165  
-  my $funcs;
  165
+  my @funcs = qw(i_img i_color i_fcolor i_fill_t mm_log);
166 166
   open FUNCS, "< imexttypes.h"
167 167
     or die "Cannot open imexttypes.h: $!\n";
168 168
   my $in_struct;
62  conv.c → conv.im
@@ -14,60 +14,62 @@
14 14
 void
15 15
 i_conv(i_img *im,const float *coeff,int len) {
16 16
   int i,l,c,ch,center;
17  
-  float pc;
18  
-  i_color rcolor;
19  
-  float res[11];
20  
-  i_img timg;
  17
+  double pc;
  18
+  double res[11];
  19
+  i_img *timg;
21 20
 
22 21
   mm_log((1,"i_conv(im %p, coeff %p, len %d)\n",im,coeff,len));
23 22
  
24  
-  i_img_empty_ch(&timg,im->xsize,im->ysize,im->channels);
  23
+  timg = i_sametype(im, im->xsize, im->ysize);
25 24
 
26 25
   center=(len-1)/2;
27 26
 
  27
+#code im->bits <= 8
  28
+  IM_COLOR rcolor;
28 29
   /* don't move the calculation of pc up here, it depends on which pixels
29 30
      are readable */
30 31
   for(l=0;l<im->ysize;l++) {
31 32
     for(i=0;i<im->xsize;i++) {
32 33
       pc=0.0;
33  
-      for(ch=0;ch<im->channels;ch++) res[ch]=0;
  34
+      for(ch=0;ch<im->channels;ch++) 
  35
+	res[ch]=0;
34 36
       for(c=0;c<len;c++)
35  
-	if (i_gpix(im,i+c-center,l,&rcolor)!=-1) {
  37
+	if (IM_GPIX(im,i+c-center,l,&rcolor)!=-1) {
36 38
 	  for(ch=0;ch<im->channels;ch++) 
37  
-            res[ch]+=(float)(rcolor.channel[ch])*coeff[c];
  39
+            res[ch] += (rcolor.channel[ch])*coeff[c];
38 40
 	  pc+=coeff[c];
39 41
 	}
40 42
       for(ch=0;ch<im->channels;ch++) {
41 43
         double temp = res[ch]/pc;
42 44
         rcolor.channel[ch] = 
43  
-          temp < 0 ? 0 : temp > 255 ? 255 : (unsigned char)temp;
  45
+          temp < 0 ? 0 : temp > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : (IM_SAMPLE_T)temp;
44 46
       }
45  
-      i_ppix(&timg,i,l,&rcolor);
  47
+      IM_PPIX(timg,i,l,&rcolor);
46 48
     }
47 49
   }
48 50
 
49  
-  for(l=0;l<im->xsize;l++)
50  
-    {
51  
-      for(i=0;i<im->ysize;i++)
52  
-	{
53  
-	  pc=0.0;
54  
-	  for(ch=0;ch<im->channels;ch++) res[ch]=0;
55  
-	  for(c=0;c<len;c++)
56  
-	    if (i_gpix(&timg,l,i+c-center,&rcolor)!=-1)
57  
-	      {
58  
-		for(ch=0;ch<im->channels;ch++) 
59  
-                  res[ch]+=(float)(rcolor.channel[ch])*coeff[c];
60  
-		pc+=coeff[c];
61  
-	      }
62  
-	  for(ch=0;ch<im->channels;ch++) {
63  
-            double temp = res[ch]/pc;
64  
-            rcolor.channel[ch]= 
65  
-              temp < 0 ? 0 : temp > 255 ? 255 : (unsigned char)temp;
66  
-          }
67  
-	  i_ppix(im,l,i,&rcolor);
  51
+  for(l=0;l<im->xsize;l++) {
  52
+    for(i=0;i<im->ysize;i++) {
  53
+      pc=0.0;	
  54
+      for(ch=0;ch<im->channels;ch++) res[ch]=0;
  55
+      for(c=0;c<len;c++) {
  56
+	if (IM_GPIX(timg,l,i+c-center,&rcolor)!=-1) {
  57
+	  for(ch=0;ch<im->channels;ch++) 
  58
+	    res[ch] += (rcolor.channel[ch])*coeff[c];
  59
+	  pc+=coeff[c];
68 60
 	}
  61
+      }
  62
+      for(ch=0;ch<im->channels;ch++) {
  63
+	double temp = res[ch]/pc;
  64
+	rcolor.channel[ch]= 
  65
+	  temp < 0 ? 0 : temp > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : (IM_SAMPLE_T)temp;
  66
+      }
  67
+      IM_PPIX(im,l,i,&rcolor);
69 68
     }
70  
-  i_img_exorcise(&timg);
  69
+  }
  70
+#/code
  71
+
  72
+  i_img_destroy(timg);
71 73
 }
72 74
 
73 75
 
4  gaussian.im
@@ -72,7 +72,7 @@ i_gaussian(i_img *im, double stddev) {
72 72
 	}
73 73
       for(ch=0;ch<im->channels;ch++) {
74 74
 	double value = res[ch] / pc;
75  
-	rcolor.channel[ch] = value > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : value;
  75
+	rcolor.channel[ch] = value > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : IM_ROUND(value);
76 76
       }
77 77
       IM_PPIX(timg,i,l,&rcolor);
78 78
     }
@@ -91,7 +91,7 @@ i_gaussian(i_img *im, double stddev) {
91 91
 	}
92 92
       for(ch=0;ch<im->channels;ch++) {
93 93
 	double value = res[ch]/pc;
94  
-	rcolor.channel[ch] = value > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : value;
  94
+	rcolor.channel[ch] = value > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : IM_ROUND(value);
95 95
       }
96 96
       IM_PPIX(im,l,i,&rcolor);
97 97
     }
166  image.c
@@ -49,8 +49,58 @@ static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals);
49 49
 static int i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals);
50 50
 static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count);
51 51
 static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count);
52  
-/*static int i_psamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count);
53  
-  static int i_psampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count);*/
  52
+
  53
+/*
  54
+=item i_img_alloc()
  55
+=category Image Implementation
  56
+
  57
+Allocates a new i_img structure.
  58
+
  59
+When implementing a new image type perform the following steps in your
  60
+image object creation function:
  61
+
  62
+=over
  63
+
  64
+=item 1.
  65
+
  66
+allocate the image with i_img_alloc().
  67
+
  68
+=item 2.
  69
+
  70
+initialize any function pointers or other data as needed, you can
  71
+overwrite the whole block if you need to.
  72
+
  73
+=item 3.
  74
+
  75
+initialize Imager's internal data by calling i_img_init() on the image
  76
+object.
  77
+
  78
+=back
  79
+
  80
+=cut
  81
+*/
  82
+
  83
+i_img *
  84
+i_img_alloc(void) {
  85
+  return mymalloc(sizeof(i_img));
  86
+}
  87
+
  88
+/*
  89
+=item i_img_init(img)
  90
+=category Image Implementation
  91
+
  92
+Imager interal initialization of images.
  93
+
  94
+Currently this does very little, in the future it may be used to
  95
+support threads, or color profiles.
  96
+
  97
+=cut
  98
+*/
  99
+
  100
+void
  101
+i_img_init(i_img *img) {
  102
+  img->im_data = NULL;
  103
+}
54 104
 
55 105
 /* 
56 106
 =item ICL_new_internal(r, g, b, a)
@@ -232,6 +282,9 @@ static i_img IIM_base_8bit_direct =
232 282
   NULL, /* i_f_setcolors */
233 283
 
234 284
   NULL, /* i_f_destroy */
  285
+
  286
+  i_gsamp_bits_fb,
  287
+  NULL, /* i_f_psamp_bits */
235 288
 };
236 289
 
237 290
 /*static void set_8bit_direct(i_img *im) {
@@ -301,8 +354,8 @@ i_img_new() {
301 354
   i_img *im;
302 355
   
303 356
   mm_log((1,"i_img_struct()\n"));
304  
-  if ( (im=mymalloc(sizeof(i_img))) == NULL)
305  
-    i_fatal(2,"malloc() error\n");
  357
+
  358
+  im = i_img_alloc();
306 359
   
307 360
   *im = IIM_base_8bit_direct;
308 361
   im->xsize=0;
@@ -311,6 +364,8 @@ i_img_new() {
311 364
   im->ch_mask=MAXINT;
312 365
   im->bytes=0;
313 366
   im->idata=NULL;
  367
+
  368
+  i_img_init(im);
314 369
   
315 370
   mm_log((1,"(%p) <- i_img_struct\n",im));
316 371
   return im;
@@ -373,8 +428,7 @@ i_img_empty_ch(i_img *im,int x,int y,int ch) {
373 428
   }
374 429
 
375 430
   if (im == NULL)
376  
-    if ( (im=mymalloc(sizeof(i_img))) == NULL)
377  
-      i_fatal(2,"malloc() error\n");
  431
+    im = i_img_alloc();
378 432
 
379 433
   memcpy(im, &IIM_base_8bit_direct, sizeof(i_img));
380 434
   i_tags_new(&im->tags);
@@ -388,6 +442,8 @@ i_img_empty_ch(i_img *im,int x,int y,int ch) {
388 442
   memset(im->idata,0,(size_t)im->bytes);
389 443
   
390 444
   im->ext_data = NULL;
  445
+
  446
+  i_img_init(im);
391 447
   
392 448
   mm_log((1,"(%p) <- i_img_empty_ch\n",im));
393 449
   return im;
@@ -705,20 +761,8 @@ i_copy(i_img *src) {
705 761
     }
706 762
   }
707 763
   else {
708  
-    i_color temp;
709  
-    int index;
710  
-    int count;
711 764
     i_palidx *vals;
712 765
 
713  
-    /* paletted image */
714  
-    i_img_pal_new_low(im, x1, y1, src->channels, i_maxcolors(src));
715  
-    /* copy across the palette */
716  
-    count = i_colorcount(src);
717  
-    for (index = 0; index < count; ++index) {
718  
-      i_getcolors(src, index, &temp, 1);
719  
-      i_addcolors(im, &temp, 1);
720  
-    }
721  
-
722 766
     vals = mymalloc(sizeof(i_palidx) * x1);
723 767
     for (y = 0; y < y1; ++y) {
724 768
       i_gpal(src, 0, x1, y, vals);
@@ -1985,6 +2029,80 @@ int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) {
1985 2029
 /*
1986 2030
 =back
1987 2031
 
  2032
+=head2 Fallback handler
  2033
+
  2034
+=over
  2035
+
  2036
+=item i_gsamp_bits_fb
  2037
+
  2038
+=cut
  2039
+*/
  2040
+
  2041
+int 
  2042
+i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps, 
  2043
+		const int *chans, int chan_count, int bits) {
  2044
+  if (bits < 1 || bits > 32) {
  2045
+    i_push_error(0, "Invalid bits, must be 1..32");
  2046
+    return -1;
  2047
+  }
  2048
+
  2049
+  if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) {
  2050
+    double scale;
  2051
+    int ch, count, i, w;
  2052
+    
  2053
+    if (bits == 32)
  2054
+      scale = 4294967295.0;
  2055
+    else
  2056
+      scale = (double)(1 << bits) - 1;
  2057
+
  2058
+    if (r > im->xsize)
  2059
+      r = im->xsize;
  2060
+    w = r - l;
  2061
+    count = 0;
  2062
+
  2063
+    if (chans) {
  2064
+      /* make sure we have good channel numbers */
  2065
+      for (ch = 0; ch < chan_count; ++ch) {
  2066
+        if (chans[ch] < 0 || chans[ch] >= im->channels) {
  2067
+          i_push_errorf(0, "No channel %d in this image", chans[ch]);
  2068
+          return -1;
  2069
+        }
  2070
+      }
  2071
+      for (i = 0; i < w; ++i) {
  2072
+	i_fcolor c;
  2073
+	i_gpixf(im, l+i, y, &c);
  2074
+        for (ch = 0; ch < chan_count; ++ch) {
  2075
+          *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
  2076
+          ++count;
  2077
+        }
  2078
+      }
  2079
+    }
  2080
+    else {
  2081
+      if (chan_count <= 0 || chan_count > im->channels) {
  2082
+	i_push_error(0, "Invalid channel count");
  2083
+	return -1;
  2084
+      }
  2085
+      for (i = 0; i < w; ++i) {
  2086
+	i_fcolor c;
  2087
+	i_gpixf(im, l+i, y, &c);
  2088
+        for (ch = 0; ch < chan_count; ++ch) {
  2089
+          *samps++ = (unsigned)(c.channel[ch] * scale + 0.5);
  2090
+          ++count;
  2091
+        }
  2092
+      }
  2093
+    }
  2094
+
  2095
+    return count;
  2096
+  }
  2097
+  else {
  2098
+    i_push_error(0, "Image position outside of image");
  2099
+    return -1;
  2100
+  }
  2101
+}
  2102
+
  2103
+/*
  2104
+=back
  2105
+
1988 2106
 =head2 Stream reading and writing wrapper functions
1989 2107
 
1990 2108
 =over
@@ -2353,7 +2471,7 @@ i_img_is_monochrome(i_img *im, int *zero_is_white) {
2353 2471
           colors[1].rgb.r == 0 &&
2354 2472
           colors[1].rgb.g == 0 &&
2355 2473
           colors[1].rgb.b == 0) {
2356  
-        *zero_is_white = 0;
  2474
+        *zero_is_white = 1;
2357 2475
         return 1;
2358 2476
       }
2359 2477
       else if (colors[0].rgb.r == 0 && 
@@ -2362,19 +2480,19 @@ i_img_is_monochrome(i_img *im, int *zero_is_white) {
2362 2480
                colors[1].rgb.r == 255 &&
2363 2481
                colors[1].rgb.g == 255 &&
2364 2482
                colors[1].rgb.b == 255) {
2365  
-        *zero_is_white = 1;
  2483
+        *zero_is_white = 0;
2366 2484
         return 1;
2367 2485
       }
2368 2486
     }
2369 2487
     else if (im->channels == 1) {
2370 2488
       if (colors[0].channel[0] == 255 &&
2371  
-          colors[1].channel[1] == 0) {
2372  
-        *zero_is_white = 0;
  2489
+          colors[1].channel[0] == 0) {
  2490
+        *zero_is_white = 1;
2373 2491
         return 1;
2374 2492
       }
2375 2493
       else if (colors[0].channel[0] == 0 &&
2376  
-               colors[0].channel[0] == 255) {
2377  
-        *zero_is_white = 1;
  2494
+               colors[1].channel[0] == 255) {
  2495
+        *zero_is_white = 0;
2378 2496
         return 1;         
2379 2497
       }
2380 2498
     }
12  imager.h
@@ -56,6 +56,8 @@ i_img *i_img_empty(i_img *im,int x,int y);
56 56
 i_img *i_img_empty_ch(i_img *im,int x,int y,int ch);
57 57
 void   i_img_exorcise(i_img *im);
58 58
 void   i_img_destroy(i_img *im);
  59
+i_img *i_img_alloc(void);
  60
+void i_img_init(i_img *im);
59 61
 
60 62
 void   i_img_info(i_img *im,int *info);
61 63
 
@@ -112,6 +114,11 @@ extern int i_setcolors(i_img *im, int index, const i_color *colors,
112 114
 #define i_gsampf(im, l, r, y, samps, chans, count) \
113 115
   (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
114 116
 
  117
+#define i_gsamp_bits(im, l, r, y, samps, chans, count, bits) \
  118
+  (((im)->i_f_gsamp_bits) ? ((im)->i_f_gsamp_bits)((im), (l), (r), (y), (samps), (chans), (count), (bits)) : -1)
  119
+#define i_psamp_bits(im, l, r, y, samps, chans, count, bits) \
  120
+  (((im)->i_f_psamp_bits) ? ((im)->i_f_psamp_bits)((im), (l), (r), (y), (samps), (chans), (count), (bits)) : -1)
  121
+
115 122
 #define i_findcolor(im, color, entry) \
116 123
   (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
117 124
 
@@ -345,16 +352,13 @@ extern i_palidx *i_quant_translate(i_quantize *quant, i_img *img);
345 352
 extern void i_quant_transparent(i_quantize *quant, i_palidx *indices, i_img *img, i_palidx trans_index);
346 353
 
347 354
 extern i_img *i_img_pal_new(int x, int y, int channels, int maxpal);
348  
-extern i_img *i_img_pal_new_low(i_img *im, int x, int y, int channels, int maxpal);
349 355
 extern i_img *i_img_to_pal(i_img *src, i_quantize *quant);
350 356
 extern i_img *i_img_to_rgb(i_img *src);
351 357
 extern i_img *i_img_masked_new(i_img *targ, i_img *mask, int x, int y, 
352 358
                                int w, int h);
353 359
 extern i_img *i_img_16_new(int x, int y, int ch);
354  
-extern i_img *i_img_16_new_low(i_img *im, int x, int y, int ch);
355 360
 extern i_img *i_img_to_rgb16(i_img *im);
356 361
 extern i_img *i_img_double_new(int x, int y, int ch);
357  
-extern i_img *i_img_double_new_low(i_img *im, int x, int y, int ch);
358 362
 
359 363
 extern int i_img_is_monochrome(i_img *im, int *zero_is_white);
360 364
 
@@ -374,6 +378,8 @@ undef_int i_writetiff_wiol(i_img *im, io_glue *ig);
374 378
 undef_int i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count);
375 379
 undef_int i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine);
376 380
 undef_int i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine);
  381
+char const * i_tiff_libversion(void);
  382
+int i_tiff_has_compression(char const *name);
377 383
 
378 384
 #endif /* HAVE_LIBTIFF */
379 385
 
4  imageri.h
@@ -30,6 +30,10 @@ extern int i_findcolor_forward(i_img *im, const i_color *color,
30 30
 extern int i_setcolors_forward(i_img *im, int index, const i_color *colors, 
31 31
                                int count);
32 32
 
  33
+/* fallback handler for gsamp_bits */
  34
+extern int i_gsamp_bits_fb(i_img *im, int x, int r, int y, unsigned *samp, 
  35
+			   const int *chans, int chan_count, int bits);
  36
+
33 37
 #define SampleFTo16(num) ((int)((num) * 65535.0 + 0.01))
34 38
 /* we add that little bit to avoid rounding issues */
35 39
 #define Sample16ToF(num) ((num) / 65535.0)
108  imdatatypes.h
@@ -102,8 +102,110 @@ typedef int (*i_f_setcolors_t)(i_img *im, int index, const i_color *colors,
102 102
 
103 103
 typedef void (*i_f_destroy_t)(i_img *im);
104 104
 
  105
+typedef int (*i_f_gsamp_bits_t)(i_img *im, int x, int r, int y, unsigned *samp,
  106
+                           const int *chans, int chan_count, int bits);
  107
+typedef int (*i_f_psamp_bits_t)(i_img *im, int x, int r, int y, unsigned const *samp,
  108
+				 const int *chans, int chan_count, int bits);
  109
+
105 110
 typedef int i_img_dim;
106 111
 
  112
+/*
  113
+=item i_img
  114
+=category Data Types
  115
+=synopsis i_img *img;
  116
+
  117
+This is Imager's image type.
  118
+
  119
+It contains the following members:
  120
+
  121
+=over
  122
+
  123
+=item *
  124
+
  125
+channels - the number of channels in the image
  126
+
  127
+=item *
  128
+
  129
+xsize, ysize - the width and height of the image in pixels
  130
+
  131
+=item *
  132
+
  133
+bytes - the number of bytes used to store the image data.  Undefined
  134
+where virtual is non-zero.
  135
+
  136
+=item *
  137
+
  138
+ch_mask - a mask of writable channels.  eg. if this is 6 then only
  139
+channels 1 and 2 are writable.  There may be bits set for which there
  140
+are no channels in the image.
  141
+
  142
+=item *
  143
+
  144
+bits - the number of bits stored per sample.  Should be one of
  145
+i_8_bits, i_16_bits, i_double_bits.
  146
+
  147
+=item *
  148
+
  149
+type - either i_direct_type for direct color images, or i_palette_type
  150
+for paletted images.
  151
+
  152
+=item *
  153
+
  154
+virtual - if zero then this image is-self contained.  If non-zero then
  155
+this image could be an interface to some other implementation.
  156
+
  157
+=item *
  158
+
  159
+idata - the image data.  This should not be directly accessed.  A new
  160
+image implementation can use this to store its image data.
  161
+i_img_destroy() will myfree() this pointer if it's non-null.
  162
+
  163
+=item *
  164
+
  165
+tags - a structure storing the image's tags.  This should only be
  166
+accessed via the i_tags_*() functions.
  167
+
  168
+=item *
  169
+
  170
+ext_data - a pointer for use internal to an image implementation.
  171
+This should be freed by the image's destroy handler.
  172
+
  173
+=item *
  174
+
  175
+im_data - data internal to Imager.  This is initialized by
  176
+i_img_init().
  177
+
  178
+=item *
  179
+
  180
+i_f_ppix, i_f_ppixf, i_f_plin, i_f_plinf, i_f_gpix, i_f_gpixf,
  181
+i_f_glin, i_f_glinf, i_f_gsamp, i_f_gampf - implementations for each
  182
+of the required image functions.  An image implementation should
  183
+initialize these between calling i_img_alloc() and i_img_init().
  184
+
  185
+=item *
  186
+
  187
+i_f_gpal, i_f_ppal, i_f_addcolors, i_f_getcolors, i_f_colorcount,
  188
+i_f_maxcolors, i_f_findcolor, i_f_setcolors - implementations for each
  189
+paletted image function.
  190
+
  191
+=item *
  192
+
  193
+i_f_destroy - custom image destruction function.  This should be used
  194
+to release memory if necessary.
  195
+
  196
+=item *
  197
+
  198
+i_f_gsamp_bits - implements i_gsamp_bits() for this image.
  199
+
  200
+=item *
  201
+
  202
+i_f_psamp_bits - implements i_psamp_bits() for this image.
  203
+
  204
+=back
  205
+
  206
+=cut
  207
+*/
  208
+
107 209
 struct i_img_ {
108 210
   int channels;
109 211
   i_img_dim xsize,ysize;
@@ -141,6 +243,12 @@ struct i_img_ {
141 243
   i_f_setcolors_t i_f_setcolors;
142 244
 
143 245
   i_f_destroy_t i_f_destroy;
  246
+
  247
+  /* as of 0.61 */
  248
+  i_f_gsamp_bits_t i_f_gsamp_bits;
  249
+  i_f_psamp_bits_t i_f_psamp_bits;
  250
+
  251
+  void *im_data;
144 252
 };
145 253
 
146 254
 /* ext_data for paletted images
6  imext.c
@@ -112,7 +112,11 @@ im_ext_funcs imager_function_table =
112 112
     i_img_get_width,
113 113
     i_img_get_height,
114 114
     i_lhead,
115  
-    i_loog
  115
+    i_loog,
  116
+
  117
+    /* IMAGER_API_LEVEL 4 functions */
  118
+    i_img_alloc,
  119
+    i_img_init,
116 120
   };
117 121
 
118 122
 /* in general these functions aren't called by Imager internally, but
3  imext.h
@@ -199,4 +199,7 @@ extern im_ext_funcs *imager_function_ext_table;
199 199
 #define i_lhead(file, line) ((im_extt->f_i_lhead)((file), (line)))
200 200
 #define i_loog (im_extt->f_i_loog)
201 201
 
  202
+#define i_img_alloc() ((im_extt->f_i_img_alloc)())
  203
+#define i_img_init(img) ((im_extt->f_i_img_init)(img))
  204
+
202 205
 #endif
6  imexttypes.h
@@ -18,7 +18,7 @@
18 18
  will result in an increment of IMAGER_API_LEVEL.
19 19
 */
20 20
 
21  
-#define IMAGER_API_LEVEL 3
  21
+#define IMAGER_API_LEVEL 4
22 22
 
23 23
 typedef struct {
24 24
   int version;
@@ -152,6 +152,10 @@ typedef struct {
152 152
   void (*f_i_loog)(int level, const char *msg, ...);
153 153
 
154 154
   /* IMAGER_API_LEVEL 4 functions will be added here */
  155
+  i_img *(*f_i_img_alloc)(void);
  156
+  void (*f_i_img_init)(i_img *);
  157
+
  158
+  /* IMAGER_API_LEVEL 5 functions will be added here */
155 159
 } im_ext_funcs;
156 160
 
157 161
 #define PERL_FUNCTION_TABLE_NAME "Imager::__ext_func_table"
194  img16.c
@@ -35,6 +35,10 @@ static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps,
35 35
                        int const *chans, int chan_count);
36 36
 static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps, 
37 37
                         int const *chans, int chan_count);
  38
+static int i_gsamp_bits_d16(i_img *im, int l, int r, int y, unsigned *samps, 
  39
+			    int const *chans, int chan_count, int bits);
  40
+static int i_psamp_bits_d16(i_img *im, int l, int r, int y, unsigned const *samps, 
  41
+			    int const *chans, int chan_count, int bits);
38 42
 
39 43
 /*
40 44
 =item IIM_base_16bit_direct
@@ -70,12 +74,17 @@ static i_img IIM_base_16bit_direct =
70 74
 
71 75
   NULL, /* i_f_gpal */
72 76
   NULL, /* i_f_ppal */
73  
-  NULL, /* i_f_addcolor */
74  
-  NULL, /* i_f_getcolor */
  77
+  NULL, /* i_f_addcolors */
  78
+  NULL, /* i_f_getcolors */
75 79
   NULL, /* i_f_colorcount */
  80
+  NULL, /* i_f_maxcolors */
76 81
   NULL, /* i_f_findcolor */
  82
+  NULL, /* i_f_setcolors */
77 83
 
78 84
   NULL, /* i_f_destroy */
  85
+
  86
+  i_gsamp_bits_d16,
  87
+  i_psamp_bits_d16,
79 88
 };
80 89
 
81 90
 /* it's possible some platforms won't have a 16-bit integer type,
@@ -111,12 +120,9 @@ typedef unsigned short i_sample16_t;
111 120
 #define STORE16(bytes, offset, word) \
112 121
    (((i_sample16_t *)(bytes))[offset] = (word))
113 122
 #define STORE8as16(bytes, offset, byte) \
114  
-   (((i_sample16_t *)(bytes))[offset] = (byte) * 256)
  123
+   (((i_sample16_t *)(bytes))[offset] = (byte) * 256 + (byte))
115 124
 #define GET16(bytes, offset) \
116 125
      (((i_sample16_t *)(bytes))[offset])
117  
-#define GET16as8(bytes, offset) \
118  
-     (((i_sample16_t *)(bytes))[offset] / 256)
119  
-
120 126
 #else
121 127
 
122 128
 /* we have to do this the hard way */
@@ -125,25 +131,34 @@ typedef unsigned short i_sample16_t;
125 131
     (((unsigned char *)(bytes))[(offset)*2+1] = (word) & 0xFF))
126 132
 #define STORE8as16(bytes, offset, byte) \
127 133
    ((((unsigned char *)(bytes))[(offset)*2] = (byte)), \
128  
-    (((unsigned char *)(bytes))[(offset)*2+1] = 0))
  134
+    (((unsigned char *)(bytes))[(offset)*2+1] = (byte)))
129 135
    
130 136
 #define GET16(bytes, offset) \
131 137
    (((unsigned char *)(bytes))[(offset)*2] * 256 \
132 138
     + ((unsigned char *)(bytes))[(offset)*2+1])
133  
-#define GET16as8(bytes, offset) \
134  
-   (((unsigned char *)(bytes))[(offset)*2] << 8)
135 139
 
136 140
 #endif
137 141
 
  142
+#define GET16as8(bytes, offset) \
  143
+     ((((i_sample16_t *)(bytes))[offset]+127) / 257)
  144
+
138 145
 /*
139  
-=item i_img_16_new_low(int x, int y, int ch)
  146
+=item i_img_16_new(x, y, ch)
140 147
 
141  
-Creates a new 16-bit per sample image.
  148
+=category Image creation
  149
+=synopsis i_img *img = i_img_16_new(width, height, channels);
  150
+
  151
+Create a new 16-bit/sample image.
  152
+
  153
+Returns the image on success, or NULL on failure.
142 154
 
143 155
 =cut
144 156
 */
145  
-i_img *i_img_16_new_low(i_img *im, int x, int y, int ch) {
  157
+
  158
+i_img *i_img_16_new(int x, int y, int ch) {
  159
+  i_img *im;
146 160
   int bytes, line_bytes;
  161
+
147 162
   mm_log((1,"i_img_16_new(x %d, y %d, ch %d)\n", x, y, ch));
148 163
 
149 164
   if (x < 1 || y < 1) {
@@ -169,6 +184,7 @@ i_img *i_img_16_new_low(i_img *im, int x, int y, int ch) {
169 184
     return NULL;
170 185
   }
171 186
 
  187
+  im = i_img_alloc();
172 188
   *im = IIM_base_16bit_direct;
173 189
   i_tags_new(&im->tags);
174