- start of external Imager API access:
authorTony Cook <tony@develop=help.com>
Tue, 10 Jan 2006 03:09:58 +0000 (03:09 +0000)
committerTony Cook <tony@develop=help.com>
Tue, 10 Jan 2006 03:09:58 +0000 (03:09 +0000)
  - rename headers to avoid conflicts:
    - image.h to imager.h
    - imagei.h to imageri.h
    - datatypes.h to imdatatypes.h
    - config.h to imconfig.h (created by Makefile.PL)
  - moved all public types defined in imager.h to imdatatypes.h
  - supply the PM parameter to WriteMakefile(), to install headers
    under Imager/include, and the Imager typemap in Imager/typemap.
    We scan the MANIFEST for files to add to PM.
  - add "i_" prefix on some functions useful as public at the C level.
  - moved the typedefs that support the typemap from Imager.xs to
    imperl.h
  - set the global callbacks hook in the Imager.xs BOOT section
  - API cleanup:
    - define i_tags_set(), i_tags_setn() - we might not allow multiple
      values for a tag in the future
    - i_copy() now returns a new image instead of doing horrible inplace
      things to an existing image
    - provide actual functions for all of the macros we define in imager.h
      so we can put them in the global callbacks structure
  - define global functions structure (imexttypes.h)
    and initialize it (imext.c)
  - add API include header with macros to setup the define and
    initialize the local callbacks pointer, and macros to call the API
    functions.
  - build Imager::APIRef from C sources, including updating the sources
    to include documentation for each API function.
  - convert dyntest and mandelbrot dynfilts into XS modules (too easy)
  - simple Imager::CountColor example
- support Inline::C :
  - typemap changes to accept Imager or Imager::ImgRaw objects as
    image parameters
  - define Imager output type for trivial cases of returning an i_img as
    a full Imager object
  - Inline WITH hook to filter Imager XS types into types Inline::C can
    accept, supply appropriate headers and initialization.
  - test script t/t82inline.t
- try to use XSLoader instead of DynaLoader (but fallback if necessary)
- paste() can now paste a subset of the source image.
- paste() now has better tests
- paste() should now be faster for larger pastes

83 files changed:
Changes
CountColor/CountColor.pm [new file with mode: 0644]
CountColor/CountColor.xs [new file with mode: 0644]
CountColor/Makefile.PL [new file with mode: 0644]
CountColor/t/t00countcolor.t [new file with mode: 0644]
DynTest/DynTest.pm [new file with mode: 0644]
DynTest/DynTest.xs [new file with mode: 0644]
DynTest/Makefile.PL [new file with mode: 0644]
DynTest/linstretch.c [new file with mode: 0644]
DynTest/t/t00dyntest.t [new file with mode: 0644]
Imager.pm
Imager.xs
MANIFEST
MANIFEST.SKIP [new file with mode: 0644]
Makefile.PL
Mandelbrot/Makefile.PL [new file with mode: 0644]
Mandelbrot/Mandelbrot.pm [new file with mode: 0644]
Mandelbrot/Mandelbrot.xs [new file with mode: 0644]
Mandelbrot/mandel.c [new file with mode: 0644]
Mandelbrot/t/t00mandel.t [new file with mode: 0644]
apidocs.perl [new file with mode: 0644]
bmp.c
color.c
conv.c
convert.c
datatypes.c
datatypes.h [deleted file]
draw.c
draw.h
dynaload.c
error.c
ext.h
feat.h
fills.c
filters.c
font.c
freetyp2.c
gaussian.c
gif.c
hlines.c
image.c
image.h [deleted file]
imagei.h [deleted file]
imager.h [new file with mode: 0644]
imageri.h [new file with mode: 0644]
imdatatypes.h [new file with mode: 0644]
imexif.h
imext.c [new file with mode: 0644]
imext.h [new file with mode: 0644]
imextdef.h [new file with mode: 0644]
imexttypes.h [new file with mode: 0644]
img16.c
imgdouble.c
imperl.h [new file with mode: 0644]
jpeg.c
lib/Imager/API.pm [new file with mode: 0644]
lib/Imager/APIRef.pm [new file with mode: 0644]
lib/Imager/ExtUtils.pm [new file with mode: 0644]
lib/Imager/Inline.pod [new file with mode: 0644]
lib/Imager/Transformations.pod
limits.c
map.c
maskimg.c
metafile.pl [new file with mode: 0644]
palimg.c
plug.h
png.c
pnm.c
polygon.c
quant.c
raw.c
regmach.h
rgb.c
rotate.c
t/t022double.t
t/t66paste.t
t/t82inline.t [new file with mode: 0644]
tags.c
tga.c
tiff.c
trans2.c
typemap
win32.c

diff --git a/Changes b/Changes
index 89d612a..813a5fe 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1248,6 +1248,48 @@ Revision history for Perl extension Imager.
 - extra concept index entries
 - Imager::Draw - align_string()'s valign parameter was invalid in the 
   synopsis
+- start of external Imager API access:
+  - rename headers to avoid conflicts:
+    - image.h to imager.h
+    - imagei.h to imageri.h
+    - datatypes.h to imdatatypes.h
+    - config.h to imconfig.h (created by Makefile.PL)
+  - moved all public types defined in imager.h to imdatatypes.h
+  - supply the PM parameter to WriteMakefile(), to install headers 
+    under Imager/include, and the Imager typemap in Imager/typemap.
+    We scan the MANIFEST for files to add to PM.
+  - add "i_" prefix on some functions useful as public at the C level.
+  - moved the typedefs that support the typemap from Imager.xs to 
+    imperl.h
+  - set the global callbacks hook in the Imager.xs BOOT section
+  - API cleanup:
+    - define i_tags_set(), i_tags_setn() - we might not allow multiple 
+      values for a tag in the future
+    - i_copy() now returns a new image instead of doing horrible inplace
+      things to an existing image
+    - provide actual functions for all of the macros we define in imager.h
+      so we can put them in the global callbacks structure
+  - define global functions structure (imexttypes.h)
+    and initialize it (imext.c)
+  - add API include header with macros to setup the define and
+    initialize the local callbacks pointer, and macros to call the API
+    functions.
+  - build Imager::APIRef from C sources, including updating the sources
+    to include documentation for each API function.
+  - convert dyntest and mandelbrot dynfilts into XS modules (too easy)
+  - simple Imager::CountColor example
+- support Inline::C :
+  - typemap changes to accept Imager or Imager::ImgRaw objects as 
+    image parameters
+  - define Imager output type for trivial cases of returning an i_img as
+    a full Imager object
+  - Inline WITH hook to filter Imager XS types into types Inline::C can
+    accept, supply appropriate headers and initialization.
+  - test script t/t82inline.t
+- try to use XSLoader instead of DynaLoader (but fallback if necessary)
+- paste() can now paste a subset of the source image.
+- paste() now has better tests
+- paste() should now be faster for larger pastes
 
 =================================================================
 
diff --git a/CountColor/CountColor.pm b/CountColor/CountColor.pm
new file mode 100644 (file)
index 0000000..514bc7f
--- /dev/null
@@ -0,0 +1,57 @@
+package Imager::CountColor;
+use strict;
+use Imager;
+use vars qw($VERSION @ISA @EXPORT_OK);
+require Exporter;
+@EXPORT_OK = 'count_color';
+
+BEGIN {
+  $VERSION = "0.01";
+  @ISA = qw(Exporter);
+  
+  eval {
+    require XSLoader;
+    XSLoader::load('Imager::CountColor', $VERSION);
+    1;
+  } or do {
+    require DynaLoader;
+    push @ISA, 'DynaLoader';
+    bootstrap Imager::CountColor $VERSION;
+  };
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Imager::CountColor - demonstrates writing a simple function using Imager.
+
+=head1 SYNOPSIS
+
+  use Imager;
+  use Imager::CountColor;
+  my $im = Imager->new(...); # some Imager image
+  ...; # some sort of manipulation
+  print count_color($im, $color_object);
+
+=head1 DESCRIPTION
+
+This module is a simple demonstration of how to create an XS module
+that works with Imager objects.
+
+You may want to copy the source for this module as a start.
+
+=head1 SEE ALSO
+
+Imager, Imager::Filter::DynTest
+
+=head1 AUTHOR
+
+Tony Cook <tony@imager.perl.org>
+
+=cut
+
+
+  
diff --git a/CountColor/CountColor.xs b/CountColor/CountColor.xs
new file mode 100644 (file)
index 0000000..df4cf1d
--- /dev/null
@@ -0,0 +1,51 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include "ppport.h"
+#ifdef __cplusplus
+}
+#endif
+
+#include "imext.h"
+#include "imperl.h"
+
+DEFINE_IMAGER_CALLBACKS;
+
+int
+count_color(i_img *im, i_color *color) {
+  int x, y, chan;
+  i_color c;
+  int count = 0;
+
+  for (x = 0; x < im->xsize; ++x) {
+    for (y = 0; y < im->ysize; ++y) {
+      i_gpix(im, x, y, &c);
+      int match = 1;
+      for (chan = 0; chan < im->channels; ++chan) {
+        if (c.channel[chan] != color->channel[chan]) {
+          match = 0;
+          break;
+        }
+      }
+      if (match) ++count;
+    }
+  }
+
+  return count;
+}
+
+MODULE = Imager::CountColor   PACKAGE = Imager::CountColor
+
+PROTOTYPES: ENABLE
+
+int
+count_color(im, color)
+        Imager::ImgRaw im
+        Imager::Color color
+
+BOOT:
+        PERL_INITIALIZE_IMAGER_CALLBACKS;
+
diff --git a/CountColor/Makefile.PL b/CountColor/Makefile.PL
new file mode 100644 (file)
index 0000000..908937a
--- /dev/null
@@ -0,0 +1,18 @@
+use ExtUtils::MakeMaker;
+require "../metafile.pl";
+
+my %opts = 
+  (
+   NAME => 'Imager::CountColor',
+   VERSION_FROM => 'CountColor.pm',
+   OBJECT => 'CountColor.o',
+   INC => '-I..',
+  );
+if ($ExtUtils::MakeMaker::VERSION > 6.06) {
+  $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+  $opts{ABSTRACT} = 'Color Count an Imager image';
+}
+
+WriteMakefile(%opts);
+
+
diff --git a/CountColor/t/t00countcolor.t b/CountColor/t/t00countcolor.t
new file mode 100644 (file)
index 0000000..a51e971
--- /dev/null
@@ -0,0 +1,23 @@
+#!perl -w
+use strict;
+use blib;
+use lib '../t';
+use Imager;
+use Test::More tests => 9;
+
+BEGIN { use_ok('Imager::CountColor' => 'count_color') }
+
+my $black = Imager::Color->new(0, 0, 0);
+my $blue = Imager::Color->new(0, 0, 255);
+my $red = Imager::Color->new(255, 0, 0);
+my $im = Imager->new(xsize=>50, ysize=>50);
+is(count_color($im, $black), 2500, "check black vs black image");
+is(count_color($im, $red), 0, "check red vs black image");
+$im->box(filled=>1, color=>$blue, xmin=>25);
+is(count_color($im, $black), 1250, "check black vs black/blue image");
+is(count_color($im, $red), 0, "check red vs black/blue image");
+is(count_color($im, $blue), 1250, "check blue vs black/blue image");
+$im->box(filled=>1, color=>$red, ymin=>25);
+is(count_color($im, $black), 625, "check black vs black/blue/red image");
+is(count_color($im, $blue), 625, "check black vs black/blue/red image");
+is(count_color($im, $red), 1250, "check black vs black/blue/red image");
diff --git a/DynTest/DynTest.pm b/DynTest/DynTest.pm
new file mode 100644 (file)
index 0000000..05f04a1
--- /dev/null
@@ -0,0 +1,32 @@
+package Imager::Filter::DynTest;
+use strict;
+use Imager;
+use vars qw($VERSION @ISA);
+
+BEGIN {
+  $VERSION = "0.01";
+  
+  eval {
+    require XSLoader;
+    XSLoader::load('Imager::Filter::DynTest', $VERSION);
+    1;
+  } or do {
+    require DynaLoader;
+    push @ISA, 'DynaLoader';
+    bootstrap Imager::Filter::DynTest $VERSION;
+  };
+}
+
+
+sub _lin_stretch {
+  my %hsh = @_;
+
+  lin_stretch($hsh{image}, $hsh{a}, $hsh{b});
+}
+
+Imager->register_filter(type=>'lin_stretch',
+                        callsub => \&_lin_stretch,
+                        defaults => { a => 0, b => 255 },
+                        callseq => [ qw/image a b/ ]);
+
+1;
diff --git a/DynTest/DynTest.xs b/DynTest/DynTest.xs
new file mode 100644 (file)
index 0000000..ca8ad27
--- /dev/null
@@ -0,0 +1,29 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include "ppport.h"
+#ifdef __cplusplus
+}
+#endif
+
+#include "imext.h"
+#include "imperl.h"
+
+extern void lin_stretch(i_img *, int, int);
+
+DEFINE_IMAGER_CALLBACKS;
+
+MODULE = Imager::Filter::DynTest   PACKAGE = Imager::Filter::DynTest
+
+void
+lin_stretch(im, a, b)
+        Imager::ImgRaw im
+        int a
+        int b
+
+BOOT:
+        PERL_INITIALIZE_IMAGER_CALLBACKS;
+
diff --git a/DynTest/Makefile.PL b/DynTest/Makefile.PL
new file mode 100644 (file)
index 0000000..1b2ec30
--- /dev/null
@@ -0,0 +1,18 @@
+use ExtUtils::MakeMaker;
+require "../metafile.pl";
+
+my %opts = 
+  (
+   NAME => 'Imager::Filter::DynTest',
+   VERSION_FROM => 'DynTest.pm',
+   OBJECT => 'DynTest.o linstretch.o',
+   INC => '-I..'
+  );
+if ($ExtUtils::MakeMaker::VERSION > 6.06) {
+  $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+  $opts{ABSTRACT} = 'Demo Imager filter extension';
+}
+
+WriteMakefile(%opts);
+
+
diff --git a/DynTest/linstretch.c b/DynTest/linstretch.c
new file mode 100644 (file)
index 0000000..7d2d8fa
--- /dev/null
@@ -0,0 +1,49 @@
+#include "imext.h"
+
+char evalstr[]="Description string of plugin dyntest - kind of like";
+
+void null_plug(void *ptr) { }
+
+/* Example dynamic filter - level stretch (linear) - note it only stretches and doesn't compress */
+
+/* input parameters
+   a: the current black
+   b: the current white
+   
+   0 <= a < b <= 255;
+
+   output pixel value calculated by: o=((i-a)*255)/(b-a);
+
+   note that since we do not have the needed functions to manipulate the data structures *** YET ***
+*/
+
+
+unsigned char
+static
+saturate(int in) {
+  if (in>255) { return 255; }
+  else if (in>0) return in;
+  return 0;
+}
+
+void lin_stretch(i_img *im, int a, int b) {
+
+  i_color rcolor;
+  int i,bytes,x,y;
+  int info[4];
+
+  
+  /*   fprintf(stderr,"parameters: (im 0x%x,a %d,b %d)\n",im,a,b);*/
+  bytes=im->bytes;
+
+  i_img_info(im,info); 
+  for(y=0;y<im->ysize;y++) for(x=0;x<im->xsize;x++) {
+    i_gpix(im,x,y,&rcolor);
+    for(i=0;i<im->channels;i++) rcolor.channel[i]=saturate((255*(rcolor.channel[i]-a))/(b-a));    
+    i_ppix(im,x,y,&rcolor);
+  }
+
+}
+
+
diff --git a/DynTest/t/t00dyntest.t b/DynTest/t/t00dyntest.t
new file mode 100644 (file)
index 0000000..6402eea
--- /dev/null
@@ -0,0 +1,20 @@
+#!perl -w
+use strict;
+use blib;
+use lib '../t';
+use Imager;
+use Test::More tests => 4;
+
+BEGIN { use_ok('Imager::Filter::DynTest') }
+
+my $im = Imager->new;
+SKIP:
+{
+  ok($im->read(file => '../testout/t104.ppm'), "load source image")
+    or skip("couldn't load work image", 2);
+  ok($im->filter(type=>'lin_stretch', a => 50, b => 200),
+     "try filter")
+    or print "# ", $im->errstr, "\n";
+  ok($im->write(file => '../testout/t00dyntest.ppm'),
+     "save result");
+}
index 5027a5e..fe0a874 100644 (file)
--- a/Imager.pm
+++ b/Imager.pm
@@ -145,11 +145,17 @@ use Imager::Font;
 
 BEGIN {
   require Exporter;
-  require DynaLoader;
-
+  @ISA = qw(Exporter);
   $VERSION = '0.47';
-  @ISA = qw(Exporter DynaLoader);
-  bootstrap Imager $VERSION;
+  eval {
+    require XSLoader;
+    XSLoader::load(Imager => $VERSION);
+    1;
+  } or do {
+    require DynaLoader;
+    push @ISA, 'DynaLoader';
+    bootstrap Imager $VERSION;
+  }
 }
 
 BEGIN {
@@ -567,8 +573,7 @@ sub copy {
   }
 
   my $newcopy=Imager->new();
-  $newcopy->{IMG}=i_img_new();
-  i_copy($newcopy->{IMG},$self->{IMG});
+  $newcopy->{IMG} = i_copy($self->{IMG});
   return $newcopy;
 }
 
@@ -576,19 +581,68 @@ sub copy {
 
 sub paste {
   my $self = shift;
-  unless ($self->{IMG}) { $self->{ERRSTR}='empty input image'; return undef; }
-  my %input=(left=>0, top=>0, @_);
-  unless($input{img}) {
-    $self->{ERRSTR}="no source image";
+
+  unless ($self->{IMG}) { 
+    $self->_set_error('empty input image');
+    return;
+  }
+  my %input=(left=>0, top=>0, src_minx => 0, src_miny => 0, @_);
+  my $src = $input{img} || $input{src};
+  unless($src) {
+    $self->_set_error("no source image");
     return;
   }
   $input{left}=0 if $input{left} <= 0;
   $input{top}=0 if $input{top} <= 0;
-  my $src=$input{img};
+
   my($r,$b)=i_img_info($src->{IMG});
+  my ($src_left, $src_top) = @input{qw/src_minx src_miny/};
+  my ($src_right, $src_bottom);
+  if ($input{src_coords}) {
+    ($src_left, $src_top, $src_right, $src_bottom) = @{$input{src_coords}}
+  }
+  else {
+    if (defined $input{src_maxx}) {
+      $src_right = $input{src_maxx};
+    }
+    elsif (defined $input{width}) {
+      if ($input{width} <= 0) {
+        $self->_set_error("paste: width must me positive");
+        return;
+      }
+      $src_right = $src_left + $input{width};
+    }
+    else {
+      $src_right = $r;
+    }
+    if (defined $input{src_maxx}) {
+      $src_bottom = $input{src_maxy};
+    }
+    elsif (defined $input{height}) {
+      if ($input{height} < 0) {
+        $self->_set_error("paste: height must be positive");
+        return;
+      }
+      $src_bottom = $src_top + $input{height};
+    }
+    else {
+      $src_bottom = $b;
+    }
+  }
+
+  $src_right > $r and $src_right = $r;
+  $src_bottom > $r and $src_bottom = $b;
+
+  if ($src_right <= $src_left
+      || $src_bottom < $src_top) {
+    $self->_set_error("nothing to paste");
+    return;
+  }
 
   i_copyto($self->{IMG}, $src->{IMG}, 
-          0,0, $r, $b, $input{left}, $input{top});
+          $src_left, $src_top, $src_right, $src_bottom, 
+           $input{left}, $input{top});
+
   return $self;  # What should go here??
 }
 
@@ -1655,6 +1709,25 @@ sub filter {
   return $self;
 }
 
+sub register_filter {
+  my $class = shift;
+  my %hsh = ( defaults => {}, @_ );
+
+  defined $hsh{type}
+    or die "register_filter() with no type\n";
+  defined $hsh{callsub}
+    or die "register_filter() with no callsub\n";
+  defined $hsh{callseq}
+    or die "register_filter() with no callseq\n";
+
+  exists $filters{$hsh{type}}
+    and return;
+
+  $filters{$hsh{type}} = \%hsh;
+
+  return 1;
+}
+
 # Scale an image to requested size and return the scaled version
 
 sub scale {
@@ -2953,7 +3026,15 @@ sub parseiptc {
   return (caption=>$caption,photogr=>$photogr,headln=>$headln,credit=>$credit);
 }
 
-# Autoload methods go after =cut, and are processed by the autosplit program.
+sub Inline {
+  my ($lang) = @_;
+
+  $lang eq 'C'
+    or die "Only C language supported";
+
+  require Imager::ExtUtils;
+  return Imager::ExtUtils->inline_config;
+}
 
 1;
 __END__
@@ -3086,6 +3167,22 @@ L<Imager::Matrix2d> - Helper class for affine transformations.
 
 L<Imager::Fountain> - Helper for making gradient profiles.
 
+=item *
+
+L<Imager::API> - using Imager's C API
+
+=item *
+
+L<Imager::APIRef> - API function reference
+
+=item *
+
+L<Imager::Inline> - using Imager's C API from Inline::C
+
+=item *
+
+L<Imager::ExtUtils> - tools to get access to Imager's C API.
+
 =back
 
 =head2 Basic Overview
index da982a9..fd09d8c 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -6,33 +6,24 @@ extern "C" {
 #include "XSUB.h"
 #include "ppport.h"
 #ifdef __cplusplus
-
+}
 #endif
 
 #define i_int_hlines_testing() 1
 
-#include "image.h"
+#include "imager.h"
 #include "feat.h"
 #include "dynaload.h"
 #include "regmach.h"
-
-#if i_int_hlines_testing()
-#include "imagei.h"
-#endif
+#include "imextdef.h"
 
 typedef io_glue* Imager__IO;
-typedef i_color* Imager__Color;
-typedef i_fcolor* Imager__Color__Float;
-typedef i_img*   Imager__ImgRaw;
-typedef int undef_neg_int;
 
-#ifdef HAVE_LIBTT
-typedef TT_Fonthandle* Imager__Font__TT;
+#if i_int_hlines_testing()
+#include "imageri.h"
 #endif
 
-#ifdef HAVE_FT2
-typedef FT2_Fonthandle* Imager__Font__FT2;
-#endif
+#include "imperl.h"
 
 /* These functions are all shared - then comes platform dependant code */
 static int getstr(void *hv_t,char *key,char **store) {
@@ -816,12 +807,6 @@ load_fount_segs(AV *asegs, int *count) {
 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
 
-/* for the fill objects
-   Since a fill object may later have dependent images, (or fills!)
-   we need perl wrappers - oh well
-*/
-#define IFILL_DESTROY(fill) i_fill_destroy(fill);
-typedef i_fill_t* Imager__FillHandle;
 
 /* the m_init_log() function was called init_log(), renamed to reduce
     potential naming conflicts */
@@ -1473,9 +1458,8 @@ i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
               int     ty
      Imager::Color     trans
 
-void
-i_copy(im,src)
-    Imager::ImgRaw     im
+Imager::ImgRaw
+i_copy(src)
     Imager::ImgRaw     src
 
 
@@ -4560,3 +4544,6 @@ i_int_hlines_dump(hlines)
        Imager::Internal::Hlines hlines
 
 #endif
+
+BOOT:
+        PERL_SET_GLOBAL_CALLBACKS;
index 0e29eeb..841355f 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,18 +1,33 @@
 Changes
+CountColor/CountColor.pm        sample XS access to API
+CountColor/CountColor.xs
+CountColor/Makefile.PL
+CountColor/t/t00countcolor.t
+DynTest/DynTest.pm      simple conversion of the dyntest sample from dynfilt/
+DynTest/DynTest.xs
+DynTest/Makefile.PL
+DynTest/linstretch.c
+DynTest/t/t00dyntest.t
 Imager.pm
 Imager.xs
 MANIFEST
+MANIFEST.SKIP
 META.yml        Module meta-data
+Mandelbrot/Makefile.PL          more complex filter
+Mandelbrot/Mandelbrot.pm
+Mandelbrot/Mandelbrot.xs
+Mandelbrot/mandel.c
+Mandelbrot/t/t00mandel.t
 Makefile.PL
 README
+apidocs.perl    Build lib/Imager/APIRef.pm
 bigtest.perl   Library selection tester
 bmp.c           Reading and writing Windows BMP files
 color.c         Color translation and handling
 conv.c
 convert.c
-datatypes.c
-datatypes.h
 doco.perl
+datatypes.c
 draw.c
 draw.h
 dynaload.c
@@ -51,23 +66,32 @@ gaussian.c
 gif.c
 hlines.c       Manage sets of horizontal line segments
 image.c
-image.h
-imagei.h
+imager.h
+imageri.h
+imdatatypes.h
+imext.c         Defines the function table
+imext.h         Included by external modules for API access
+imextdef.h
+imexttypes.h    Define API function table type
 imexif.c       Experimental JPEG EXIF decoding
 imexif.h
 img16.c
 imgdouble.c     Implements double/sample images
 imio.h
+imperl.h
 io.c
 iolayer.c
 iolayer.h
 jpeg.c
+lib/Imager/API.pm
+lib/Imager/APIRef.pm    API function reference
 lib/Imager/Color.pm
 lib/Imager/Color/Float.pm
 lib/Imager/Color/Table.pm
 lib/Imager/Cookbook.pod
 lib/Imager/Draw.pod
 lib/Imager/Engines.pod
+lib/Imager/ExtUtils.pm
 lib/Imager/Expr.pm
 lib/Imager/Expr/Assem.pm
 lib/Imager/Files.pod
@@ -83,6 +107,7 @@ lib/Imager/Font/Win32.pm
 lib/Imager/Font/Wrap.pm
 lib/Imager/Fountain.pm
 lib/Imager/ImageTypes.pod
+lib/Imager/Inline.pod           Using Imager with Inline::C
 lib/Imager/Matrix2d.pm
 lib/Imager/Regops.pm
 lib/Imager/Transform.pm
@@ -95,6 +120,7 @@ log.c
 log.h
 map.c
 maskimg.c
+metafile.pl     Common META.yml generation
 palimg.c
 plug.h
 png.c
@@ -168,6 +194,7 @@ t/t70newgif.t
 t/t75polyaa.t
 t/t80texttools.t        Test text wrapping
 t/t81hlines.t          Test hlines.c
+t/t82inline.t           Test Inline::C integration
 t/t90cc.t
 t/t91pod.t             Test POD with Test::Pod
 t/testtools.pl
diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP
new file mode 100644 (file)
index 0000000..f7ed576
--- /dev/null
@@ -0,0 +1,41 @@
+# svn work files'
+^\.svn\b
+/\.svn\b
+
+# editor trash
+~$
+
+# stuff we don't distribute
+^TODO$
+^STATUS$
+^\.cvsignore$
+/\.cvsignore$
+^announce/
+^bench/
+^design/
+^fileformatdocs/
+^extraimages/
+^fontfiles/.*\.sfd$
+
+# might distribute one day
+^tools/imager$
+
+# trash left by Inline::C
+^_Inline/
+
+# build trash
+Makefile$
+Makefile\.old
+\bpm_to_blib$
+\.o$
+^testimg/
+^blib/
+^Imager\.c$
+^Mandelbrot/Mandelbrot\.c$
+^CountColor/CountColor\.c$
+^DynTest/DynTest\.c$
+^dynfilt/.*\.(so|dll)$
+\.bs$
+^meta\.tmp$
+/meta\.tmp$
+^imconfig\.h$
index 028f510..e1334f0 100644 (file)
@@ -4,6 +4,9 @@ use Cwd;
 use Config;
 use File::Spec;
 use Getopt::Long;
+use vars qw(%Recommends);
+require "metafile.pl";
+use ExtUtils::Manifest qw(maniread);
 
 #
 # IM_INCPATH      colon seperated list of paths to extra include paths
@@ -128,7 +131,11 @@ if (defined $Config{'d_dlsymun'}) { $OSDEF  .= ' -DDLSYMUN'; }
           filters.o dynaload.o stackmach.o datatypes.o
           regmach.o trans2.o quant.o error.o convert.o
           map.o tags.o palimg.o maskimg.o img16.o rotate.o
-           bmp.o tga.o rgb.o color.o fills.o imgdouble.o limits.o hlines.o);
+           bmp.o tga.o rgb.o color.o fills.o imgdouble.o limits.o hlines.o
+           imext.o);
+
+$Recommends{Imager} =
+  { 'Parse::RecDescent' => 0 };
 
 %opts=(
        'NAME'         => 'Imager',
@@ -138,6 +145,7 @@ if (defined $Config{'d_dlsymun'}) { $OSDEF  .= ' -DDLSYMUN'; }
        'INC'          => "$lib_cflags $DFLAGS $F_INC",
        'OBJECT'       => join(' ', @objs, $F_OBJECT),
        clean          => { FILES=>'testout meta.tmp' },
+       PM             => gen_PM(),
       );
 
 if ($ExtUtils::MakeMaker::VERSION > 6.06) {
@@ -162,36 +170,16 @@ dyntest.$(MYEXTLIB) : dynfilt/Makefile
 lib/Imager/Regops.pm : regmach.h regops.perl
        $(PERL) regops.perl regmach.h lib/Imager/Regops.pm
 
-imconfig.h: Makefile.PL
+imconfig.h : Makefile.PL
        $(ECHO) "imconfig.h out-of-date with respect to $?"
        $(PERLRUN) Makefile.PL
        $(ECHO) "==> Your Makefile has been rebuilt - re-run your make command <=="
+
+lib/Imager/APIRef.pm : $(C_FILES) apidocs.perl
+       $(PERLRUN) apidocs.perl lib/Imager/APIRef.pm
+
 ';
-}
 
-sub MY::metafile {
-  my ($self) = @_;
-
-  my $meta = <<YAML;
---- #YAML:1.0
-name: Imager
-version: $self->{VERSION}
-version_from: $self->{VERSION_FROM}
-author: $self->{AUTHOR}
-abstract: $self->{ABSTRACT}
-installdirs: $self->{INSTALLDIRS}
-recommends:
-  Parse::RecDescent: 0
-license: perl
-dynamic_config: 1
-distribution_type: module
-generated_by: Imager version $self->{VERSION}
-YAML
-  open META, "> meta.tmp" or die "Cannot create meta.tmp: $!";
-  print META $meta;
-  close META;
-  
-  return sprintf "metafile :\n\t\$(CP) meta.tmp META.yml\n";
 }
 
 # manual configuration of helper libraries
@@ -687,3 +675,38 @@ EOS
   exit 1;
 
 }
+
+# generate the PM MM argument
+# I'd prefer to modify the public version, but there doesn't seem to be 
+# a public API to do that
+sub gen_PM {
+  my %pm;
+  my $instbase = '$(INST_LIBDIR)';
+
+  # first the basics, .pm and .pod files
+  $pm{"Imager.pm"} = "$instbase/Imager.pm";
+
+  my $mani = maniread();
+
+  for my $filename (keys %$mani) {
+    if ($filename =~ m!^lib/! && $filename =~ /\.(pm|pod)$/) {
+      (my $work = $filename) =~ s/^lib//;
+      $pm{$filename} = $instbase . $work;
+    }
+  }
+
+  # need the typemap
+  $pm{typemap} = $instbase . '/Imager/typemap';
+
+  # and the core headers
+  for my $filename (keys %$mani) {
+    if ($filename =~ /^\w+\.h$/) {
+      $pm{$filename} = $instbase . '/Imager/include/' . $filename;
+    }
+  }
+
+  # and the generated header
+  $pm{"imconfig.h"} = $instbase . '/Imager/include/imconfig.h';
+
+  \%pm;
+}
diff --git a/Mandelbrot/Makefile.PL b/Mandelbrot/Makefile.PL
new file mode 100644 (file)
index 0000000..d0a60c4
--- /dev/null
@@ -0,0 +1,18 @@
+use ExtUtils::MakeMaker;
+require "../metafile.pl";
+
+my %opts = 
+  (
+   NAME => 'Imager::Filter::Mandelbrot',
+   VERSION_FROM => 'Mandelbrot.pm',
+   OBJECT => 'Mandelbrot.o mandel.o',
+   INC => '-I..'
+  );
+if ($ExtUtils::MakeMaker::VERSION > 6.06) {
+  $opts{AUTHOR} = 'Tony Cook <tony@imager.perl.org>';
+  $opts{ABSTRACT} = 'Mandelbrot Imager filter extension';
+}
+
+WriteMakefile(%opts);
+
+
diff --git a/Mandelbrot/Mandelbrot.pm b/Mandelbrot/Mandelbrot.pm
new file mode 100644 (file)
index 0000000..1a4c29f
--- /dev/null
@@ -0,0 +1,42 @@
+package Imager::Filter::Mandelbrot;
+use strict;
+use Imager;
+use vars qw($VERSION @ISA);
+
+BEGIN {
+  $VERSION = "0.01";
+  
+  eval {
+    require XSLoader;
+    XSLoader::load('Imager::Filter::Mandelbrot', $VERSION);
+    1;
+  } or do {
+    require DynaLoader;
+    push @ISA, 'DynaLoader';
+    bootstrap Imager::Filter::Mandelbrot $VERSION;
+  };
+}
+
+sub _mandelbrot {
+  my %hsh = @_;
+
+  mandelbrot($hsh{image}, $hsh{minx}, $hsh{miny}, $hsh{maxx}, $hsh{maxy}, $hsh{maxiter});
+}
+
+my %defaults =
+  (
+   minx => -2.5,
+   maxx => 1.5,
+   miny => -1.5,
+   maxy => 1.5,
+   maxiter => 256,
+  );
+
+my @callseq = qw/image minx miny maxx maxy maxiter/;
+
+Imager->register_filter(type=>'mandelbrot',
+                        callsub => \&_mandelbrot,
+                        defaults => \%defaults,
+                        callseq => \@callseq);
+
+1;
diff --git a/Mandelbrot/Mandelbrot.xs b/Mandelbrot/Mandelbrot.xs
new file mode 100644 (file)
index 0000000..a6837ee
--- /dev/null
@@ -0,0 +1,33 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include "ppport.h"
+#ifdef __cplusplus
+}
+#endif
+
+#include "imext.h"
+#include "imperl.h"
+
+void 
+mandelbrot(i_img *im, double minx, double miny, double maxx, double maxy, int max_iter);
+
+DEFINE_IMAGER_CALLBACKS;
+
+MODULE = Imager::Filter::Mandelbrot   PACKAGE = Imager::Filter::Mandelbrot
+
+void
+mandelbrot(im, minx=-2.5, miny=-2.0, maxx=2.5, maxy=-2.0, max_iter=256)
+        Imager::ImgRaw im
+        double minx
+        double miny
+        double maxx
+        double maxy
+        int max_iter
+
+BOOT:
+        PERL_INITIALIZE_IMAGER_CALLBACKS;
+
diff --git a/Mandelbrot/mandel.c b/Mandelbrot/mandel.c
new file mode 100644 (file)
index 0000000..299c084
--- /dev/null
@@ -0,0 +1,72 @@
+#include "imext.h"
+#include <stdlib.h>
+
+char evalstr[]="Mandlebrot renderer";
+
+/* Example Mandlebrot generator */
+
+/* input parameters
+   image is the image object.
+*/
+
+
+static
+int
+mandel(double x, double y, int max_iter) {
+  double xn, yn;
+  double xo, yo;
+  double dist;
+  int iter = 1;
+  /*   Z(n+1) = Z(n) ^2 + c */
+
+  /* printf("(%.2f, %.2f) -> \n", x,y);   */
+
+  xo = x;
+  yo = y;
+
+  while( xo*xo+yo*yo <= 10 && iter < max_iter) {
+    xn = xo*xo-yo*yo + x;
+    yn = 2*xo*yo     + y;
+    xo=xn;
+    yo=yn;
+    iter++;
+  }
+  return (iter == max_iter)?0:iter;
+}
+
+void 
+mandelbrot(i_img *im, double minx, double miny, double maxx, double maxy, int max_iter) {
+
+  i_color vl;
+  int i,bytes,x,y;
+  int idx;
+  double divx, divy;
+
+  i_color icl[256];
+  srand(12235);
+  for(i=1;i<256; i++) {
+    icl[i].rgb.r = 100+(int) (155.0*rand()/(RAND_MAX+1.0));
+    icl[i].rgb.g = 100+(int) (155.0*rand()/(RAND_MAX+1.0));
+    icl[i].rgb.g = 100+(int) (155.0*rand()/(RAND_MAX+1.0));
+  }
+
+  icl[0].rgb.r = 0;
+  icl[0].rgb.g = 0;
+  icl[0].rgb.g = 0;
+    
+  if (maxx <= minx)
+    maxx = minx + 1.0;
+  if (maxy <= miny)
+    maxy = miny + 1.0;
+
+  divx = (maxx - minx) / im->xsize;
+  divy = (maxy - miny) / im->ysize;
+
+  for(y = 0; y < im->ysize; y ++) {
+    for(x = 0; x < im->xsize; x ++ ) {
+      idx = mandel(minx + x*divx , miny + y*divy, max_iter);
+      idx = idx % 256;
+      i_ppix(im,x,y,&icl[idx]); 
+    }
+  }
+}
diff --git a/Mandelbrot/t/t00mandel.t b/Mandelbrot/t/t00mandel.t
new file mode 100644 (file)
index 0000000..c0dc9d3
--- /dev/null
@@ -0,0 +1,18 @@
+#!perl -w
+use strict;
+use blib;
+use lib '../t';
+use Imager;
+use Test::More tests => 3;
+
+BEGIN { use_ok('Imager::Filter::Mandelbrot') }
+
+my $im = Imager->new(xsize=>100, ysize=>100);
+SKIP:
+{
+  ok($im->filter(type=>'mandelbrot'),
+     "try filter")
+    or print "# ", $im->errstr, "\n";
+  ok($im->write(file => '../testout/t00mandel.ppm'),
+     "save result");
+}
diff --git a/apidocs.perl b/apidocs.perl
new file mode 100644 (file)
index 0000000..366c425
--- /dev/null
@@ -0,0 +1,189 @@
+#!perl -w
+use strict;
+
+my $outname = shift || '-';
+
+
+my @funcs = make_func_list();
+my %funcs = map { $_ => 1 } @funcs;
+
+# look for files to parse
+
+my @files = grep $_ ne 'Imager.xs', glob '*.c';
+
+# scan each file for =item <func>\b
+my $func;
+my $start;
+my %alldocs;
+my @funcdocs;
+my %from;
+my $category;
+my %funccats;
+my %cats;
+my $synopsis = '';
+my %funcsyns;
+for my $file (@files) {
+  open SRC, "< $file"
+    or die "Cannot open $file for documentation: $!\n";
+  while (<SRC>) {
+    if (/^=item (\w+)\b/ && $funcs{$1}) {
+      $func = $1;
+      $start = $.;
+      @funcdocs = $_;
+    }
+    elsif ($func && /^=(cut|head)/) {
+      if ($funcs{$func}) { # only save the API functions
+        $alldocs{$func} = [ @funcdocs ];
+        $from{$func} = "Line $start in $file";
+        if ($category) {
+          $funccats{$func} = $category;
+          push @{$cats{$category}}, $func;
+        }
+        if ($synopsis) {
+          $funcsyns{$func} = $synopsis;
+        }
+      }
+      undef $func;
+      undef $category;
+      $synopsis = '';
+    }
+    elsif ($func) {
+      if (/^=category (.*)/) {
+        $category = $1;
+      }
+      elsif (/^=synopsis (.*)/) {
+        $synopsis .= "$1\n";
+      }
+      else {
+        push @funcdocs, $_;
+      }
+    }
+  }
+  $func and
+    die "Documentation for $func not followed by =cut or =head in $file\n";
+  
+  close SRC;
+}
+
+open OUT, "> $outname"
+  or die "Cannot open $outname: $!";
+
+print OUT <<'EOS';
+Do not edit this file, it is generated automatically by apidocs.perl
+from Imager's source files.
+
+Each function description has a comment listing the source file and
+line number where you can find the documentation.
+
+=head1 NAME
+
+Imager::APIRef - Imager's C API.
+
+=head1 SYNOPSIS
+
+  i_color color;
+  color.rgba.red = 255; color.rgba.green = 0; color.rgba.blue = 255;
+  i_fill_t *fill = i_new_fill_...(...);
+
+EOS
+
+for my $cat (sort { lc $a cmp lc $b } keys %cats) {
+  print OUT "\n  # $cat\n";
+  for my $func (grep $funcsyns{$_}, sort @{$cats{$cat}}) {
+    my $syn = $funcsyns{$func};
+    $syn =~ s/^/  /gm;
+    print OUT $syn;
+  }
+}
+
+print OUT <<'EOS';
+
+   i_fill_destroy(fill);
+
+=head1 DESCRIPTION
+
+EOS
+
+my %undoc = %funcs;
+
+for my $cat (sort { lc $a cmp lc $b } keys %cats) {
+  print OUT "=head2 $cat\n\n=over\n\n";
+  for my $func (sort @{$cats{$cat}}) {
+    print OUT @{$alldocs{$func}}, "\n";
+    print OUT "=for comment\nFrom: $from{$func}\n\n";
+    delete $undoc{$func};
+  }
+  print OUT "\n=back\n\n";
+}
+
+# see if we have an uncategorized section
+if (grep $alldocs{$_}, keys %undoc) {
+  print OUT "=head2 Uncategorized functions\n\n=over\n\n";
+  for my $func (sort @funcs) {
+    if ($undoc{$func} && $alldocs{$func}) {
+      print OUT @{$alldocs{$func}}, "\n";
+      print OUT "=for comment\nFrom: $from{$func}\n\n";
+      delete $undoc{$func};
+    }
+  }
+  print OUT "\n\n=back\n\n";
+}
+
+if (keys %undoc) {
+  print OUT <<'EOS';
+
+=head1 UNDOCUMENTED
+
+The following API functions are undocumented so far, hopefully this
+will change:
+
+=over
+
+EOS
+
+  print OUT "=item *\n\nB<$_>\n\n" for sort keys %undoc;
+
+  print OUT "\n\n=back\n\n";
+}
+
+print OUT <<'EOS';
+
+=head1 AUTHOR
+
+Tony Cook <tony@imager.perl.org>
+
+=head1 SEE ALSO
+
+Imager, Imager::ExtUtils, Imager::Inline
+
+=cut
+EOS
+
+close OUT;
+
+
+sub make_func_list {
+  my $funcs;
+  open FUNCS, "< imexttypes.h"
+    or die "Cannot open imexttypes.h: $!\n";
+  my $in_struct;
+  while (<FUNCS>) {
+    /^typedef struct/ && ++$in_struct;
+    if ($in_struct && /\(\*f_(i_\w+)/) {
+      push @funcs, $1;
+    }
+    if (/^\} im_ext_funcs;$/) {
+      $in_struct
+        or die "Found end of functions structure but not the start";
+
+      close FUNCS;
+      return @funcs;
+    }
+  }
+  if ($in_struct) {
+    die "Found start of the functions structure but not the end\n";
+  }
+  else {
+    die "Found neither the start nor end of the functions structure\n";
+  }
+}
diff --git a/bmp.c b/bmp.c
index 8e1e422..f2a15cd 100644 (file)
--- a/bmp.c
+++ b/bmp.c
@@ -1,5 +1,5 @@
 #include <stdarg.h>
-#include "imagei.h"
+#include "imageri.h"
 
 /*
 =head1 NAME
diff --git a/color.c b/color.c
index d83d866..10376a3 100644 (file)
--- a/color.c
+++ b/color.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 #include <math.h>
 
 /*
diff --git a/conv.c b/conv.c
index 7e8513d..3e560d3 100644 (file)
--- a/conv.c
+++ b/conv.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 
 /*
   General convolution for 2d decoupled filters
index 6d92fbb..eb411e9 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -17,7 +17,7 @@ converting from RGBA to greyscale and back.
 =cut
 */
 
-#include "image.h"
+#include "imager.h"
 
 
 /*
index cc93044..5a623ab 100644 (file)
@@ -1,5 +1,5 @@
 #include "imio.h"
-#include "datatypes.h"
+#include "imdatatypes.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
diff --git a/datatypes.h b/datatypes.h
deleted file mode 100644 (file)
index f492565..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-#ifndef _DATATYPES_H_
-#define _DATATYPES_H_
-
-#include "imio.h"
-
-#define MAXCHANNELS 4
-
-/* used for palette indices in some internal code (which might be 
-   exposed at some point
-*/
-typedef unsigned char i_palidx;
-
-/* We handle 2 types of sample, this is hopefully the most common, and the
-   smaller of the ones we support */
-typedef unsigned char i_sample_t;
-
-typedef struct { i_sample_t gray_color; } gray_color;
-typedef struct { i_sample_t r,g,b; } rgb_color;
-typedef struct { i_sample_t r,g,b,a; } rgba_color;
-typedef struct { i_sample_t c,m,y,k; } cmyk_color;
-
-typedef int undef_int; /* special value to put in typemaps to retun undef on 0 and 1 on 1 */
-
-typedef union {
-  gray_color gray;
-  rgb_color rgb;
-  rgba_color rgba;
-  cmyk_color cmyk;
-  i_sample_t channel[MAXCHANNELS];
-  unsigned int ui;
-} i_color;
-
-/* this is the larger sample type, it should be able to accurately represent
-   any sample size we use */
-typedef double i_fsample_t;
-
-typedef struct { i_fsample_t gray_color; } i_fgray_color_t;
-typedef struct { i_fsample_t r, g, b; } i_frgb_color_t;
-typedef struct { i_fsample_t r, g, b, a; } i_frgba_color_t;
-typedef struct { i_fsample_t c, m, y, k; } i_fcmyk_color_t;
-
-typedef union {
-  i_fgray_color_t gray;
-  i_frgb_color_t rgb;
-  i_frgba_color_t rgba;
-  i_fcmyk_color_t cmyk;
-  i_fsample_t channel[MAXCHANNELS];
-} i_fcolor;
-
-typedef enum {
-  i_direct_type, /* direct colour, keeps RGB values per pixel */
-  i_palette_type /* keeps a palette index per pixel */
-} i_img_type_t;
-
-typedef enum { 
-  /* bits per sample, not per pixel */
-  /* a paletted image might have one bit per sample */
-  i_8_bits = 8,
-  i_16_bits = 16,
-  i_double_bits = sizeof(double) * 8
-} i_img_bits_t;
-
-typedef struct {
-  char *name; /* name of a given tag, might be NULL */
-  int code; /* number of a given tag, -1 if it has no meaning */
-  char *data; /* value of a given tag if it's not an int, may be NULL */
-  int size; /* size of the data */
-  int idata; /* value of a given tag if data is NULL */
-} i_img_tag;
-
-typedef struct {
-  int count; /* how many tags have been set */
-  int alloc; /* how many tags have been allocated for */
-  i_img_tag *tags;
-} i_img_tags;
-
-typedef struct i_img_ i_img;
-typedef int (*i_f_ppix_t)(i_img *im, int x, int y, i_color *pix);
-typedef int (*i_f_ppixf_t)(i_img *im, int x, int y, i_fcolor *pix);
-typedef int (*i_f_plin_t)(i_img *im, int x, int r, int y, i_color *vals);
-typedef int (*i_f_plinf_t)(i_img *im, int x, int r, int y, i_fcolor *vals);
-typedef int (*i_f_gpix_t)(i_img *im, int x, int y, i_color *pix);
-typedef int (*i_f_gpixf_t)(i_img *im, int x, int y, i_fcolor *pix);
-typedef int (*i_f_glin_t)(i_img *im, int x, int r, int y, i_color *vals);
-typedef int (*i_f_glinf_t)(i_img *im, int x, int r, int y, i_fcolor *vals);
-
-typedef int (*i_f_gsamp_t)(i_img *im, int x, int r, int y, i_sample_t *samp,
-                           const int *chans, int chan_count);
-typedef int (*i_f_gsampf_t)(i_img *im, int x, int r, int y, i_fsample_t *samp,
-                            const int *chan, int chan_count);
-
-typedef int (*i_f_gpal_t)(i_img *im, int x, int r, int y, i_palidx *vals);
-typedef int (*i_f_ppal_t)(i_img *im, int x, int r, int y, i_palidx *vals);
-typedef int (*i_f_addcolors_t)(i_img *im, i_color *colors, int count);
-typedef int (*i_f_getcolors_t)(i_img *im, int i, i_color *, int count);
-typedef int (*i_f_colorcount_t)(i_img *im);
-typedef int (*i_f_maxcolors_t)(i_img *im);
-typedef int (*i_f_findcolor_t)(i_img *im, i_color *color, i_palidx *entry);
-typedef int (*i_f_setcolors_t)(i_img *im, int index, i_color *colors, 
-                              int count);
-
-typedef void (*i_f_destroy_t)(i_img *im);
-
-struct i_img_ {
-  int channels;
-  int xsize,ysize,bytes;
-  unsigned int ch_mask;
-  i_img_bits_t bits;
-  i_img_type_t type;
-  int virtual; /* image might not keep any data, must use functions */
-  unsigned char *idata; /* renamed to force inspection of existing code */
-                        /* can be NULL if virtual is non-zero */
-  i_img_tags tags;
-
-  void *ext_data;
-
-  /* interface functions */
-  i_f_ppix_t i_f_ppix;
-  i_f_ppixf_t i_f_ppixf;
-  i_f_plin_t i_f_plin;
-  i_f_plinf_t i_f_plinf;
-  i_f_gpix_t i_f_gpix;
-  i_f_gpixf_t i_f_gpixf;
-  i_f_glin_t i_f_glin;
-  i_f_glinf_t i_f_glinf;
-  i_f_gsamp_t i_f_gsamp;
-  i_f_gsampf_t i_f_gsampf;
-  
-  /* only valid for type == i_palette_type */
-  i_f_gpal_t i_f_gpal;
-  i_f_ppal_t i_f_ppal;
-  i_f_addcolors_t i_f_addcolors;
-  i_f_getcolors_t i_f_getcolors;
-  i_f_colorcount_t i_f_colorcount;
-  i_f_maxcolors_t i_f_maxcolors;
-  i_f_findcolor_t i_f_findcolor;
-  i_f_setcolors_t i_f_setcolors;
-
-  i_f_destroy_t i_f_destroy;
-};
-
-/* ext_data for paletted images
- */
-typedef struct {
-  int count; /* amount of space used in palette (in entries) */
-  int alloc; /* amount of space allocated for palette (in entries) */
-  i_color *pal;
-  int last_found;
-} i_img_pal_ext;
-
-/* Helper datatypes
-  The types in here so far are:
-
-  doubly linked bucket list - pretty efficient
-  octtree - no idea about goodness
-  
-  needed: hashes.
-
-*/
-
-
-
-
-
-/* bitmap mask */
-
-struct i_bitmap {
-  int xsize,ysize;
-  char *data;
-};
-
-struct i_bitmap* btm_new(int xsize,int ysize);
-void btm_destroy(struct i_bitmap *btm);
-int btm_test(struct i_bitmap *btm,int x,int y);
-void btm_set(struct i_bitmap *btm,int x,int y);
-
-
-
-
-
-
-
-
-/* Stack/Linked list */
-
-struct llink {
-  struct llink *p,*n;
-  void *data;
-  int fill;            /* Number used in this link */
-};
-
-struct llist {
-  struct llink *h,*t;
-  int multip;          /* # of copies in a single chain  */
-  int ssize;           /* size of each small element     */
-  int count;           /* number of elements on the list */
-};
-
-
-/* Links */
-
-struct llink *llink_new( struct llink* p,int size );
-int  llist_llink_push( struct llist *lst, struct llink *lnk, void *data );
-
-/* Lists */
-
-struct llist *llist_new( int multip, int ssize );
-void llist_destroy( struct llist *l );
-void llist_push( struct llist *l, void *data );
-void llist_dump( struct llist *l );
-int llist_pop( struct llist *l,void *data );
-
-
-
-
-/* Octtree */
-
-struct octt {
-  struct octt *t[8]; 
-  int cnt;
-};
-
-struct octt *octt_new(void);
-int octt_add(struct octt *ct,unsigned char r,unsigned char g,unsigned char b);
-void octt_dump(struct octt *ct);
-void octt_count(struct octt *ct,int *tot,int max,int *overflow);
-void octt_delete(struct octt *ct);
-
-/* font bounding box results */
-enum bounding_box_index_t {
-  BBOX_NEG_WIDTH,
-  BBOX_GLOBAL_DESCENT,
-  BBOX_POS_WIDTH,
-  BBOX_GLOBAL_ASCENT,
-  BBOX_DESCENT,
-  BBOX_ASCENT,
-  BBOX_ADVANCE_WIDTH,
-  BBOX_RIGHT_BEARING,
-  BOUNDING_BOX_COUNT
-};
-
-#endif
-
diff --git a/draw.c b/draw.c
index 6cca0a0..ec719f6 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -1,7 +1,7 @@
-#include "image.h"
+#include "imager.h"
 #include "draw.h"
 #include "log.h"
-#include "imagei.h"
+#include "imageri.h"
 
 #include <limits.h>
 
@@ -201,6 +201,18 @@ i_arc_hlines(i_int_hlines *hlines,int x,int y,float rad,float d1,float d2) {
   }
 }
 
+/*
+=item i_arc(im, x, y, rad, d1, d2, color)
+
+=category Drawing
+=synopsis i_arc(im, 50, 50, 20, 45, 135, &color);
+
+Fills an arc centered at (x,y) with radius I<rad> covering the range
+of angles in degrees from d1 to d2, with the color.
+
+=cut
+*/
+
 void
 i_arc(i_img *im,int x,int y,float rad,float d1,float d2,i_color *val) {
   i_int_hlines hlines;
@@ -214,6 +226,18 @@ i_arc(i_img *im,int x,int y,float rad,float d1,float d2,i_color *val) {
   i_int_hlines_destroy(&hlines);
 }
 
+/*
+=item i_arc_cfill(im, x, y, rad, d1, d2, fill)
+
+=category Drawing
+=synopsis i_arc_cfill(im, 50, 50, 35, 90, 135, fill);
+
+Fills an arc centered at (x,y) with radius I<rad> covering the range
+of angles in degrees from d1 to d2, with the fill object.
+
+=cut
+*/
+
 #define MIN_CIRCLE_STEPS 8
 #define MAX_CIRCLE_STEPS 360
 
@@ -301,6 +325,18 @@ arc_poly(int *count, double **xvals, double **yvals,
   ++*count;
 }
 
+/*
+=item i_arc_aa(im, x, y, rad, d1, d2, color)
+
+=category Drawing
+=synopsis i_arc_aa(im, 50, 50, 35, 90, 135, &color);
+
+Antialias fills an arc centered at (x,y) with radius I<rad> covering
+the range of angles in degrees from d1 to d2, with the color.
+
+=cut
+*/
+
 void
 i_arc_aa(i_img *im, double x, double y, double rad, double d1, double d2,
         i_color *val) {
@@ -315,6 +351,18 @@ i_arc_aa(i_img *im, double x, double y, double rad, double d1, double d2,
   myfree(yvals);
 }
 
+/*
+=item i_arc_aa_cfill(im, x, y, rad, d1, d2, fill)
+
+=category Drawing
+=synopsis i_arc_aa_cfill(im, 50, 50, 35, 90, 135, fill);
+
+Antialias fills an arc centered at (x,y) with radius I<rad> covering
+the range of angles in degrees from d1 to d2, with the fill object.
+
+=cut
+*/
+
 void
 i_arc_aa_cfill(i_img *im, double x, double y, double rad, double d1, double d2,
               i_fill_t *fill) {
@@ -425,6 +473,17 @@ i_pixel_coverage(i_mmarray *dot, int x, int y) {
   return cnt;
 }
 
+/*
+=item i_circle_aa(im, x, y, rad, color)
+
+=category Drawing
+=synopsis i_circle_aa(im, 50, 50, 45, &color);
+
+Antialias fills a circle centered at (x,y) for radius I<rad> with
+color.
+
+=cut
+*/
 void
 i_circle_aa(i_img *im, float x, float y, float rad, i_color *val) {
   i_mmarray dot;
@@ -468,10 +527,16 @@ i_circle_aa(i_img *im, float x, float y, float rad, i_color *val) {
   i_mmarray_dst(&dot);
 }
 
+/*
+=item i_box(im, x1, y1, x2, y2, color)
 
+=category Drawing
+=synopsis i_box(im, 0, 0, im->xsize-1, im->ysize-1, &color).
 
+Outlines the box from (x1,y1) to (x2,y2) inclusive with I<color>.
 
-
+=cut
+*/
 
 void
 i_box(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
@@ -487,6 +552,17 @@ i_box(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
   }
 }
 
+/*
+=item i_box_filled(im, x1, y1, x2, y2, color)
+
+=category Drawing
+=synopsis i_box_filled(im, 0, 0, im->xsize-1, im->ysize-1, &color);
+
+Fills the box from (x1,y1) to (x2,y2) inclusive with color.
+
+=cut
+*/
+
 void
 i_box_filled(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
   int x,y;
@@ -494,6 +570,17 @@ i_box_filled(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
   for(x=x1;x<x2+1;x++) for (y=y1;y<y2+1;y++) i_ppix(im,x,y,val);
 }
 
+/*
+=item i_box_cfill(im, x1, y1, x2, y2, fill)
+
+=category Drawing
+=synopsis i_box_cfill(im, 0, 0, im->xsize-1, im->ysize-1, fill);
+
+Fills the box from (x1,y1) to (x2,y2) inclusive with fill.
+
+=cut
+*/
+
 void
 i_box_cfill(i_img *im,int x1,int y1,int x2,int y2,i_fill_t *fill) {
   mm_log((1,"i_box_cfill(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,fill 0x%x)\n",im,x1,y1,x2,y2,fill));
@@ -557,6 +644,8 @@ i_box_cfill(i_img *im,int x1,int y1,int x2,int y2,i_fill_t *fill) {
 /* 
 =item i_line(im, x1, y1, x2, y2, val, endp)
 
+=category Drawing
+
 Draw a line to image using bresenhams linedrawing algorithm
 
    im   - image to draw to
@@ -756,7 +845,17 @@ i_line_aa3(i_img *im,int x1,int y1,int x2,int y2,i_color *val) {
 }
 
 
+/*
+=item i_line_aa(im, x1, x2, y1, y2, color, endp)
+
+=category Drawing
+
+Antialias draws a line from (x1,y1) to (x2, y2) in color.
 
+The point (x2, y2) is drawn only if endp is set.
+
+=cut
+*/
 
 void
 i_line_aa(i_img *im, int x1, int y1, int x2, int y2, i_color *val, int endp) {
@@ -1192,8 +1291,19 @@ i_flood_fill_low(i_img *im,int seedx,int seedy,
   return btm;
 }
 
+/*
+=item i_flood_fill(im, seedx, seedy, color)
+
+=category Drawing
+=synopsis i_flood_fill(im, 50, 50, &color);
 
+Flood fills the 4-connected region starting from the point (seedx,
+seedy) with I<color>.
 
+Returns false if (seedx, seedy) are outside the image.
+
+=cut
+*/
 
 undef_int
 i_flood_fill(i_img *im, int seedx, int seedy, i_color *dcol) {
@@ -1218,7 +1328,19 @@ i_flood_fill(i_img *im, int seedx, int seedy, i_color *dcol) {
   return 1;
 }
 
+/*
+=item i_flood_cfill(im, seedx, seedy, fill)
+
+=category Drawing
+=synopsis i_flood_cfill(im, 50, 50, fill);
 
+Flood fills the 4-connected region starting from the point (seedx,
+seedy) with I<fill>.
+
+Returns false if (seedx, seedy) are outside the image.
+
+=cut
+*/
 
 undef_int
 i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
diff --git a/draw.h b/draw.h
index 2fb33a9..c9dfdbc 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 
 typedef struct {
   int min,max;
index 1d308fd..b36df8a 100644 (file)
@@ -1,7 +1,7 @@
-#include "image.h"
+#include "imager.h"
 #include "dynaload.h"
 /* #include "XSUB.h"  so we can compile on threaded perls */
-#include "imagei.h"
+#include "imageri.h"
 
 static symbol_table_t symbol_table={i_has_format,ICL_set_internal,ICL_info,
                             i_img_new,i_img_empty,i_img_empty_ch,i_img_exorcise,
diff --git a/error.c b/error.c
index 9876ac6..3dcab3c 100644 (file)
--- a/error.c
+++ b/error.c
@@ -61,7 +61,7 @@ C).  The Perl level won't use all of this.
 =cut
 */
 
-#include "image.h"
+#include "imager.h"
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -184,9 +184,14 @@ the mark.
 
 =item i_clear_error()
 
+=category Error handling
+
+Clears the error stack.
+
 Called by any imager function before doing any other processing.
 
-=cut */
+=cut
+*/
 void i_clear_error() {
 #ifdef IMAGER_DEBUG_MALLOC
   int i;
@@ -205,6 +210,8 @@ void i_clear_error() {
 /*
 =item i_push_error(int code, char const *msg)
 
+=category Error handling
+
 Called by an imager function to push an error message onto the stack.
 
 No message is pushed if the stack is full (since this means someone
@@ -241,6 +248,8 @@ void i_push_error(int code, char const *msg) {
 /*
 =item i_push_errorvf(int code, char const *fmt, va_list ap)
 
+=category Error handling
+
 Intended for use by higher level functions, takes a varargs pointer
 and a format to produce the finally pushed error message.
 
@@ -263,6 +272,8 @@ void i_push_errorvf(int code, char const *fmt, va_list ap) {
 /*
 =item i_push_errorf(int code, char const *fmt, ...)
 
+=category Error handling
+
 A version of i_push_error() that does printf() like formating.
 
 =cut
diff --git a/ext.h b/ext.h
index 15cb3ff..dd1cfbd 100644 (file)
--- a/ext.h
+++ b/ext.h
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 
 #ifndef IMAGER_EXT_H
 #define IMAGER_EXT_H
diff --git a/feat.h b/feat.h
index bfcb4c0..1a7289d 100644 (file)
--- a/feat.h
+++ b/feat.h
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 
 static char *i_format_list[]={
 #ifdef HAVE_LIBJPEG
diff --git a/fills.c b/fills.c
index e075c53..3bccde5 100644 (file)
--- a/fills.c
+++ b/fills.c
@@ -1,5 +1,5 @@
-#include "image.h"
-#include "imagei.h"
+#include "imager.h"
+#include "imageri.h"
 
 /*
 =head1 NAME
@@ -195,6 +195,8 @@ static i_fill_solid_t base_solid_fill_comb =
 /*
 =item i_fill_destroy(fill)
 
+=category Fills
+
 Call to destroy any fill object.
 
 =cut
@@ -210,6 +212,8 @@ i_fill_destroy(i_fill_t *fill) {
 /*
 =item i_new_fill_solidf(color, combine)
 
+=category Fills
+
 Create a solid fill based on a float color.
 
 If combine is non-zero then alpha values will be combined.
@@ -239,7 +243,9 @@ i_new_fill_solidf(i_fcolor *c, int combine) {
 /*
 =item i_new_fill_solid(color, combine)
 
-Create a solid fill based.
+=category Fills
+
+Create a solid fill based on an 8-bit color.
 
 If combine is non-zero then alpha values will be combined.
 
@@ -420,6 +426,8 @@ i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
 /*
 =item i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
 
+=category Fills
+
 Creates a new hatched fill with the fg color used for the 1 bits in
 the hatch and bg for the 0 bits.  If combine is non-zero alpha values
 will be combined.
@@ -443,6 +451,8 @@ i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch,
 /*
 =item i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
 
+=category Fills
+
 Creates a new hatched fill with the fg color used for the 1 bits in
 the hatch and bg for the 0 bits.  If combine is non-zero alpha values
 will be combined.
@@ -478,8 +488,14 @@ struct i_fill_image_t {
 /*
 =item i_new_fill_image(im, matrix, xoff, yoff, combine)
 
+=category Fills
+
 Create an image based fill.
 
+matrix is an array of 9 doubles representing a transformation matrix.
+
+xoff and yoff are the offset into the image to start filling from.
+
 =cut
 */
 i_fill_t *
index dfd12ca..0efa89a 100644 (file)
--- a/filters.c
+++ b/filters.c
@@ -1,5 +1,5 @@
-#include "image.h"
-#include "imagei.h"
+#include "imager.h"
+#include "imageri.h"
 #include <stdlib.h>
 #include <math.h>
 
@@ -109,21 +109,24 @@ i_hardinvert(i_img *im) {
   int x, y;
   unsigned char ch;
   
-  i_color rcolor;
+  i_color *row, *entry;
   
-    mm_log((1,"i_hardinvert(im %p)\n", im));
+  mm_log((1,"i_hardinvert(im %p)\n", im));
+
+  row = mymalloc(sizeof(i_color) * im->xsize);
 
   for(y = 0; y < im->ysize; y++) {
+    i_glin(im, 0, im->xsize, y, row);
+    entry = row;
     for(x = 0; x < im->xsize; x++) {
-      i_gpix(im, x, y, &rcolor);
-      
       for(ch = 0; ch < im->channels; ch++) {
-       rcolor.channel[ch] = 255 - rcolor.channel[ch];
+       entry->channel[ch] = 255 - entry->channel[ch];
       }
-      
-      i_ppix(im, x, y, &rcolor);
+      ++entry;
     }
+    i_plin(im, 0, im->xsize, y, row);
   }  
+  myfree(row);
 }
 
 
@@ -1220,7 +1223,7 @@ image from double the original.
 =cut
 */
 void i_unsharp_mask(i_img *im, double stddev, double scale) {
-  i_img copy;
+  i_img *copy;
   int x, y, ch;
 
   if (scale < 0)
@@ -1229,14 +1232,14 @@ void i_unsharp_mask(i_img *im, double stddev, double scale) {
   if (scale > 100)
     scale = 100;
 
-  i_copy(&copy, im);
-  i_gaussian(&copy, stddev);
+  copy = i_copy(im);
+  i_gaussian(copy, stddev);
   if (im->bits == i_8_bits) {
     i_color *blur = mymalloc(im->xsize * sizeof(i_color) * 2);
     i_color *out = blur + im->xsize;
 
     for (y = 0; y < im->ysize; ++y) {
-      i_glin(&copy, 0, copy.xsize, y, blur);
+      i_glin(copy, 0, copy->xsize, y, blur);
       i_glin(im, 0, im->xsize, y, out);
       for (x = 0; x < im->xsize; ++x) {
         for (ch = 0; ch < im->channels; ++ch) {
@@ -1260,7 +1263,7 @@ void i_unsharp_mask(i_img *im, double stddev, double scale) {
     i_fcolor *out = blur + im->xsize;
 
     for (y = 0; y < im->ysize; ++y) {
-      i_glinf(&copy, 0, copy.xsize, y, blur);
+      i_glinf(copy, 0, copy->xsize, y, blur);
       i_glinf(im, 0, im->xsize, y, out);
       for (x = 0; x < im->xsize; ++x) {
         for (ch = 0; ch < im->channels; ++ch) {
@@ -1278,7 +1281,7 @@ void i_unsharp_mask(i_img *im, double stddev, double scale) {
 
     myfree(blur);
   }
-  i_img_exorcise(&copy);
+  i_img_destroy(copy);
 }
 
 /*
@@ -1660,7 +1663,12 @@ static void
 fount_fill_destroy(i_fill_t *fill);
 
 /*
-=item i_new_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs)
+=item i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs)
+
+=category Fills
+=synopsis fill = i_new_fill_fount(0, 0, 100, 100, i_ft_linear, i_ft_linear, 
+=synopsis                         i_fr_triangle, 0, i_fts_grid, 9, 1, segs);
+
 
 Creates a new general fill which fills with a fountain fill.
 
diff --git a/font.c b/font.c
index 4dc1349..d1fadf0 100644 (file)
--- a/font.c
+++ b/font.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -1084,6 +1084,7 @@ i_tt_init_raster_map( TT_Raster_Map* bit, int width, int height, int smooth ) {
     bit->size  = bit->rows * bit->cols;     /* number of bytes in buffer */
   }
 
+  /* rows can be 0 for some glyphs, for example ' ' */
   if (bit->rows && bit->size / bit->rows != bit->cols) {
     m_fatal(0, "Integer overflow calculating bitmap size (%d, %d)\n",
             bit->width, bit->rows);
index 687e268..fed4411 100644 (file)
@@ -34,7 +34,7 @@ Truetype, Type1 and Windows FNT.
 =cut
 */
 
-#include "image.h"
+#include "imager.h"
 #include <stdio.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
index dee1f57..ce0c295 100644 (file)
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 
 static float
 gauss(int x,float std) {
diff --git a/gif.c b/gif.c
index 8a538c4..e300831 100644 (file)
--- a/gif.c
+++ b/gif.c
@@ -1,4 +1,4 @@
-#include "imagei.h"
+#include "imageri.h"
 #include <gif_lib.h>
 #ifdef _MSCVER
 #include <io.h>
@@ -1721,7 +1721,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
     }
     else {
       glob_paletted = 0;
-      quant_makemap(quant, glob_imgs, glob_img_count);
+      i_quant_makemap(quant, glob_imgs, glob_img_count);
     }
     glob_color_count = quant->mc_count;
     quant->mc_colors = orig_colors;
@@ -1748,7 +1748,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
     }
     else {
       colors_paletted = 0;
-      quant_makemap(quant, imgs, 1);
+      i_quant_makemap(quant, imgs, 1);
     }
   }
   if ((map = make_gif_map(quant, imgs[0], want_trans)) == NULL) {
@@ -1818,7 +1818,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
       }
       else {
         colors_paletted = 0;
-        quant_makemap(quant, imgs, 1);
+        i_quant_makemap(quant, imgs, 1);
       }
       if ((map = make_gif_map(quant, imgs[0], want_trans)) == NULL) {
         i_mempool_destroy(&mp);
@@ -1838,7 +1838,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
   if (colors_paletted)
     result = quant_paletted(quant, imgs[0]);
   else
-    result = quant_translate(quant, imgs[0]);
+    result = i_quant_translate(quant, imgs[0]);
   if (!result) {
     i_mempool_destroy(&mp);
     quant->mc_colors = orig_colors;
@@ -1846,7 +1846,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
     return 0;
   }
   if (want_trans) {
-    quant_transparent(quant, result, imgs[0], quant->mc_count);
+    i_quant_transparent(quant, result, imgs[0], quant->mc_count);
     trans_index = quant->mc_count;
   }
 
@@ -1917,18 +1917,18 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
         result = quant_paletted(quant, imgs[imgn]);
       }
       else {
-        quant_makemap(quant, imgs+imgn, 1);
-        result = quant_translate(quant, imgs[imgn]);
+        i_quant_makemap(quant, imgs+imgn, 1);
+        result = i_quant_translate(quant, imgs[imgn]);
       }
       if (!result) {
         i_mempool_destroy(&mp);
         quant->mc_colors = orig_colors;
         EGifCloseFile(gf);
-        mm_log((1, "error in quant_translate()"));
+        mm_log((1, "error in i_quant_translate()"));
         return 0;
       }
       if (want_trans) {
-        quant_transparent(quant, result, imgs[imgn], quant->mc_count);
+        i_quant_transparent(quant, result, imgs[imgn], quant->mc_count);
         trans_index = quant->mc_count;
       }
 
@@ -1947,10 +1947,10 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
       if (glob_paletted)
         result = quant_paletted(quant, imgs[imgn]);
       else
-        result = quant_translate(quant, imgs[imgn]);
+        result = i_quant_translate(quant, imgs[imgn]);
       want_trans = glob_want_trans && imgs[imgn]->channels == 4;
       if (want_trans) {
-        quant_transparent(quant, result, imgs[imgn], quant->mc_count);
+        i_quant_transparent(quant, result, imgs[imgn], quant->mc_count);
         trans_index = quant->mc_count;
       }
       map = NULL;
index aa5c15b..e44c4e6 100644 (file)
--- a/hlines.c
+++ b/hlines.c
@@ -1,4 +1,4 @@
-#include "imagei.h"
+#include "imageri.h"
 #include <stdlib.h>
 
 #define OVERLAPPED(start1, end1, start2, end2) \
diff --git a/image.c b/image.c
index eba037c..19c9823 100644 (file)
--- a/image.c
+++ b/image.c
@@ -1,5 +1,5 @@
-#include "image.h"
-#include "imagei.h"
+#include "imager.h"
+#include "imageri.h"
 
 /*
 =head1 NAME
@@ -254,7 +254,12 @@ static i_img IIM_base_8bit_direct =
 /*
 =item IIM_new(x, y, ch)
 
-Creates a new image object I<x> pixels wide, and I<y> pixels high with I<ch> channels.
+=item i_img_8_new(x, y, ch)
+
+=category Image creation
+
+Creates a new image object I<x> pixels wide, and I<y> pixels high with
+I<ch> channels.
 
 =cut
 */
@@ -279,8 +284,6 @@ IIM_DESTROY(i_img *im) {
   /*   myfree(cl); */
 }
 
-
-
 /* 
 =item i_img_new()
 
@@ -420,6 +423,8 @@ i_img_exorcise(i_img *im) {
 /* 
 =item i_img_destroy(im)
 
+=category Image
+
 Destroy image and free data via exorcise.
 
    im - Image pointer
@@ -437,6 +442,8 @@ i_img_destroy(i_img *im) {
 /* 
 =item i_img_info(im, info)
 
+=category Image
+
 Return image information
 
    im - Image pointer
@@ -507,6 +514,8 @@ i_img_getchannels(i_img *im) { return im->channels; }
 /*
 =item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
 
+=category Image
+
 (x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
 (tx,ty) specifies the upper left corner for the target image.
 pass NULL in trans for non transparent i_colors.
@@ -547,6 +556,8 @@ i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_
 /*
 =item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
 
+=category Image
+
 Copies image data from the area (x1,y1)-[x2,y2] in the source image to
 a rectangle the same size with it's top-left corner at (tx,ty) in the
 destination image.
@@ -562,22 +573,39 @@ i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty)
   
   if (x2<x1) { t=x1; x1=x2; x2=t; }
   if (y2<y1) { t=y1; y1=y2; y2=t; }
-  
+  if (tx < 0) {
+    /* adjust everything equally */
+    x1 += -tx;
+    x2 += -tx;
+    tx = 0;
+  }
+  if (ty < 0) {
+    y1 += -ty;
+    y2 += -ty;
+    ty = 0;
+  }
+  if (x1 >= src->xsize || y1 >= src->ysize)
+    return; /* nothing to do */
+  if (x2 > src->xsize)
+    x2 = src->xsize;
+  if (y2 > src->ysize)
+    y2 = src->ysize;
+  if (x1 == x2 || y1 == y2)
+    return; /* nothing to do */
+
   mm_log((1,"i_copyto(im* %p, src %p, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d)\n",
          im, src, x1, y1, x2, y2, tx, ty));
   
   if (im->bits == i_8_bits) {
-    i_color pv;
+    i_color *row = mymalloc(sizeof(i_color) * (x2-x1));
     tty = ty;
     for(y=y1; y<y2; y++) {
       ttx = tx;
-      for(x=x1; x<x2; x++) {
-        i_gpix(src, x,   y,   &pv);
-        i_ppix(im,  ttx, tty, &pv);
-        ttx++;
-      }
+      i_glin(src, x1, x2, y, row);
+      i_plin(im, tx, tx+x2-x1, tty, row);
       tty++;
     }
+    myfree(row);
   }
   else {
     i_fcolor pv;
@@ -595,25 +623,34 @@ i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty)
 }
 
 /*
-=item i_copy(im, src)
+=item i_copy(src)
+
+=category Image
+
+Creates a new image that is a copy of src.
+
+Tags are not copied, only the image data.
 
-Copies the contents of the image I<src> over the image I<im>.
+Returns: i_img *
 
 =cut
 */
 
-void
-i_copy(i_img *im, i_img *src) {
+i_img *
+i_copy(i_img *src) {
   int y, y1, x1;
+  i_img *im = i_sametype(src, src->xsize, src->ysize);
+
+  mm_log((1,"i_copy(src %p)\n", src));
 
-  mm_log((1,"i_copy(im* %p,src %p)\n", im, src));
+  if (!im)
+    return NULL;
 
   x1 = src->xsize;
   y1 = src->ysize;
   if (src->type == i_direct_type) {
     if (src->bits == i_8_bits) {
       i_color *pv;
-      i_img_empty_ch(im, x1, y1, src->channels);
       pv = mymalloc(sizeof(i_color) * x1);
       
       for (y = 0; y < y1; ++y) {
@@ -624,14 +661,6 @@ i_copy(i_img *im, i_img *src) {
     }
     else {
       i_fcolor *pv;
-      if (src->bits == i_16_bits)
-       i_img_16_new_low(im, x1, y1, src->channels);
-      else if (src->bits == i_double_bits)
-       i_img_double_new_low(im, x1, y1, src->channels);
-      else {
-       fprintf(stderr, "i_copy(): Unknown image bit size %d\n", src->bits);
-       return; /* I dunno */
-      }
 
       pv = mymalloc(sizeof(i_fcolor) * x1);
       for (y = 0; y < y1; ++y) {
@@ -663,12 +692,16 @@ i_copy(i_img *im, i_img *src) {
     }
     myfree(vals);
   }
+
+  return im;
 }
 
 
 /*
 =item i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy )
 
+=category Image
+
 Takes the sub image I<src[src_minx, src_maxx)[src_miny, src_maxy)> and
 overlays it at (I<tx>,I<ty>) on the image object.
 
@@ -1073,6 +1106,8 @@ i_scale_nn(i_img *im, float scx, float scy) {
 /*
 =item i_sametype(i_img *im, int xsize, int ysize)
 
+=category Image creation
+
 Returns an image of the same type (sample size, channels, paletted/direct).
 
 For paletted images the palette is copied from the source.
@@ -1113,6 +1148,8 @@ i_img *i_sametype(i_img *src, int xsize, int ysize) {
 /*
 =item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
 
+=category Image creation
+
 Returns an image of the same type (sample size).
 
 For paletted images the equivalent direct type is returned.
diff --git a/image.h b/image.h
deleted file mode 100644 (file)
index 20bfabf..0000000
--- a/image.h
+++ /dev/null
@@ -1,804 +0,0 @@
-#ifndef _IMAGE_H_
-#define _IMAGE_H_
-
-#include "imconfig.h"
-#include "imio.h"
-#include "iolayer.h"
-#include "log.h"
-#include "stackmach.h"
-
-
-#ifndef _MSC_VER
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-#include <stdlib.h>
-
-#ifdef SUNOS
-#include <strings.h>
-#endif
-
-#ifndef PI
-#define PI 3.14159265358979323846
-#endif
-
-#ifndef MAXINT
-#define MAXINT 2147483647
-#endif
-
-#include "datatypes.h"
-
-undef_int i_has_format(char *frmt);
-
-/* constructors and destructors */
-
-i_color *ICL_new_internal(            unsigned char r,unsigned char g,unsigned char b,unsigned char a);
-i_color *ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a);
-void     ICL_info        (i_color *cl);
-void     ICL_DESTROY     (i_color *cl);
-void     ICL_add         (i_color *dst, i_color *src, int ch);
-
-extern i_fcolor *i_fcolor_new(double r, double g, double b, double a);
-extern void i_fcolor_destroy(i_fcolor *cl);
-
-extern void i_rgb_to_hsvf(i_fcolor *color);
-extern void i_hsv_to_rgbf(i_fcolor *color);
-extern void i_rgb_to_hsv(i_color *color);
-extern void i_hsv_to_rgb(i_color *color);
-
-i_img *IIM_new(int x,int y,int ch);
-void   IIM_DESTROY(i_img *im);
-i_img *i_img_new( void );
-i_img *i_img_empty(i_img *im,int x,int y);
-i_img *i_img_empty_ch(i_img *im,int x,int y,int ch);
-void   i_img_exorcise(i_img *im);
-void   i_img_destroy(i_img *im);
-
-void   i_img_info(i_img *im,int *info);
-
-extern i_img *i_sametype(i_img *im, int xsize, int ysize);
-extern i_img *i_sametype_chans(i_img *im, int xsize, int ysize, int channels);
-
-i_img *i_img_pal_new(int x, int y, int ch, int maxpal);
-
-/* Image feature settings */
-
-void   i_img_setmask    (i_img *im,int ch_mask);
-int    i_img_getmask    (i_img *im);
-int    i_img_getchannels(i_img *im);
-
-/* Base functions */
-
-#if 0
-int i_ppix(i_img *im,int x,int y,i_color *val);
-int i_gpix(i_img *im,int x,int y,i_color *val);
-int i_ppixf(i_img *im,int x,int y,i_color *val);
-int i_gpixf(i_img *im,int x,int y,i_color *val);
-#endif
-
-#define i_ppix(im, x, y, val) (((im)->i_f_ppix)((im), (x), (y), (val)))
-#define i_gpix(im, x, y, val) (((im)->i_f_gpix)((im), (x), (y), (val)))
-#define i_ppixf(im, x, y, val) (((im)->i_f_ppixf)((im), (x), (y), (val)))
-#define i_gpixf(im, x, y, val) (((im)->i_f_gpixf)((im), (x), (y), (val)))
-
-#if 0
-int i_ppix_d(i_img *im,int x,int y,i_color *val);
-int i_gpix_d(i_img *im,int x,int y,i_color *val);
-int i_plin_d(i_img *im,int l, int r, int y, i_color *val);
-int i_glin_d(i_img *im,int l, int r, int y, i_color *val);
-#endif
-
-#define i_plin(im, l, r, y, val) (((im)->i_f_plin)(im, l, r, y, val))
-#define i_glin(im, l, r, y, val) (((im)->i_f_glin)(im, l, r, y, val))
-#define i_plinf(im, l, r, y, val) (((im)->i_f_plinf)(im, l, r, y, val))
-#define i_glinf(im, l, r, y, val) (((im)->i_f_glinf)(im, l, r, y, val))
-
-#define i_gsamp(im, l, r, y, samps, chans, count) \
-  (((im)->i_f_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
-#define i_gsampf(im, l, r, y, samps, chans, count) \
-  (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
-
-#define i_psamp(im, l, r, y, samps, chans, count) \
-  (((im)->i_f_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
-#define i_psampf(im, l, r, y, samps, chans, count) \
-  (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
-
-
-
-
-#define i_findcolor(im, color, entry) \
-  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
-
-#define i_gpal(im, l, r, y, vals) \
-  (((im)->i_f_gpal) ? ((im)->i_f_gpal)((im), (l), (r), (y), (vals)) : 0)
-#define i_ppal(im, l, r, y, vals) \
-  (((im)->i_f_ppal) ? ((im)->i_f_ppal)((im), (l), (r), (y), (vals)) : 0)
-#define i_addcolors(im, colors, count) \
-  (((im)->i_f_addcolors) ? ((im)->i_f_addcolors)((im), (colors), (count)) : -1)
-#define i_getcolors(im, index, color, count) \
-  (((im)->i_f_getcolors) ? \
-   ((im)->i_f_getcolors)((im), (index), (color), (count)) : 0)
-#define i_setcolors(im, index, color, count) \
-  (((im)->i_f_setcolors) ? \
-   ((im)->i_f_setcolors)((im), (index), (color), (count)) : 0)
-#define i_colorcount(im) \
-  (((im)->i_f_colorcount) ? ((im)->i_f_colorcount)(im) : -1)
-#define i_maxcolors(im) \
-  (((im)->i_f_maxcolors) ? ((im)->i_f_maxcolors)(im) : -1)
-#define i_findcolor(im, color, entry) \
-  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
-
-#define i_img_virtual(im) ((im)->virtual)
-#define i_img_type(im) ((im)->type)
-#define i_img_bits(im) ((im)->bits)
-
-/* Generic fills */
-struct i_fill_tag;
-
-typedef void (*i_fill_with_color_f)
-     (struct i_fill_tag *fill, int x, int y, int width, int channels, 
-      i_color *data);
-typedef void (*i_fill_with_fcolor_f)
-     (struct i_fill_tag *fill, int x, int y, int width, int channels,
-      i_fcolor *data);
-typedef void (*i_fill_destroy_f)(struct i_fill_tag *fill);
-typedef void (*i_fill_combine_f)(i_color *out, i_color *in, int channels, 
-                                 int count);
-typedef void (*i_fill_combinef_f)(i_fcolor *out, i_fcolor *in, int channels,
-                                  int count);
-
-
-typedef struct i_fill_tag
-{
-  /* called for 8-bit/sample image (and maybe lower) */
-  /* this may be NULL, if so call fill_with_fcolor */
-  i_fill_with_color_f fill_with_color;
-
-  /* called for other sample sizes */
-  /* this must be non-NULL */
-  i_fill_with_fcolor_f fill_with_fcolor;
-
-  /* called if non-NULL to release any extra resources */
-  i_fill_destroy_f destroy;
-
-  /* if non-zero the caller will fill data with the original data
-     from the image */
-  i_fill_combine_f combine;
-  i_fill_combinef_f combinef;
-} i_fill_t;
-
-typedef enum {
-  ic_none,
-  ic_normal,
-  ic_multiply,
-  ic_dissolve,
-  ic_add,
-  ic_subtract,
-  ic_diff,
-  ic_lighten,
-  ic_darken,
-  ic_hue,
-  ic_sat,
-  ic_value,
-  ic_color
-} i_combine_t;
-
-extern i_fill_t *i_new_fill_solidf(i_fcolor *c, int combine);
-extern i_fill_t *i_new_fill_solid(i_color *c, int combine);
-extern i_fill_t *
-i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch, 
-                 unsigned char *cust_hatch, int dx, int dy);
-extern i_fill_t *
-i_new_fill_hatchf(i_fcolor *fg, i_fcolor *bg, int combine, int hatch, 
-                  unsigned char *cust_hatch, int dx, int dy);
-extern i_fill_t *
-i_new_fill_image(i_img *im, double *matrix, int xoff, int yoff, int combine);
-extern void i_fill_destroy(i_fill_t *fill);
-
-float i_gpix_pch(i_img *im,int x,int y,int ch);
-
-/* functions for drawing primitives */
-
-void i_box         (i_img *im,int x1,int y1,int x2,int y2,i_color *val);
-void i_box_filled  (i_img *im,int x1,int y1,int x2,int y2,i_color *val);
-void i_box_cfill(i_img *im, int x1, int y1, int x2, int y2, i_fill_t *fill);
-void i_line        (i_img *im,int x1,int y1,int x2,int y2,i_color *val, int endp);
-void i_line_aa     (i_img *im,int x1,int y1,int x2,int y2,i_color *val, int endp);
-void i_arc         (i_img *im,int x,int y,float rad,float d1,float d2,i_color *val);
-void i_arc_aa         (i_img *im, double x, double y, double rad, double d1, double d2,i_color *val);
-void i_arc_cfill(i_img *im,int x,int y,float rad,float d1,float d2,i_fill_t *fill);
-void i_arc_aa_cfill(i_img *im,double x,double y,double rad,double d1,double d2,i_fill_t *fill);
-void i_circle_aa   (i_img *im,float x, float y,float rad,i_color *val);
-void i_copyto      (i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty);
-void i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans);
-void i_copy        (i_img *im,i_img *src);
-int  i_rubthru     (i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny, int src_maxx, int src_maxy);
-
-
-undef_int i_flipxy (i_img *im, int direction);
-extern i_img *i_rotate90(i_img *im, int degrees);
-extern i_img *i_rotate_exact(i_img *im, double amount);
-extern i_img *i_rotate_exact_bg(i_img *im, double amount, i_color *backp, i_fcolor *fbackp);
-extern i_img *i_matrix_transform(i_img *im, int xsize, int ysize, double *matrix);
-extern i_img *i_matrix_transform_bg(i_img *im, int xsize, int ysize, double *matrix,  i_color *backp, i_fcolor *fbackp);
-
-void i_bezier_multi(i_img *im,int l,double *x,double *y,i_color *val);
-void i_poly_aa     (i_img *im,int l,double *x,double *y,i_color *val);
-void i_poly_aa_cfill(i_img *im,int l,double *x,double *y,i_fill_t *fill);
-
-undef_int i_flood_fill  (i_img *im,int seedx,int seedy,i_color *dcol);
-undef_int i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill);
-
-
-/* image processing functions */
-
-void i_gaussian    (i_img *im,float stdev);
-void i_conv        (i_img *im,float *coeff,int len);
-void i_unsharp_mask(i_img *im, double stddev, double scale);
-
-/* colour manipulation */
-extern int i_convert(i_img *im, i_img *src, float *coeff, int outchan, int inchan);
-extern void i_map(i_img *im, unsigned char (*maps)[256], unsigned int mask);
-
-float i_img_diff   (i_img *im1,i_img *im2);
-
-/* font routines */
-
-undef_int i_init_fonts( int t1log );
-
-/*
-   describes an axis of a MM font.
-   Modelled on FT2's FT_MM_Axis.
-   It would be nice to have a default entry too, but FT2 
-   doesn't support it.
-*/
-typedef struct i_font_mm_axis_tag {
-  char const *name;
-  int minimum;
-  int maximum;
-} i_font_mm_axis;
-
-#define IM_FONT_MM_MAX_AXES 4
-
-/* 
-   multiple master information for a font, if any 
-   modelled on FT2's FT_Multi_Master.
-*/
-typedef struct i_font_mm_tag {
-  int num_axis;
-  int num_designs; /* provided but not necessarily useful */
-  i_font_mm_axis axis[IM_FONT_MM_MAX_AXES];
-} i_font_mm;
-
-#ifdef HAVE_LIBT1
-
-undef_int i_init_t1( int t1log );
-int       i_t1_new( char *pfb, char *afm );
-int       i_t1_destroy( int font_id );
-undef_int i_t1_cp( i_img *im, int xb, int yb, int channel, int fontnum, float points, char* str, int len, int align, int utf8, char const *flags );
-undef_int i_t1_text( i_img *im, int xb, int yb, i_color *cl, int fontnum, float points, char* str, int len, int align, int utf8, char const *flags );
-int      i_t1_bbox( int fontnum, float point, char *str, int len, int cords[6], int utf8, char const *flags );
-void      i_t1_set_aa( int st );
-void      close_t1( void );
-int       i_t1_has_chars(int font_num, char const *text, int len, int utf8, char *out);
-extern int i_t1_face_name(int font_num, char *name_buf, size_t name_buf_size);
-extern int i_t1_glyph_name(int font_num, unsigned long ch, char *name_buf, 
-                           size_t name_buf_size);
-#endif
-
-#ifdef HAVE_LIBTT
-
-struct TT_Fonthandle_;
-
-typedef struct TT_Fonthandle_ TT_Fonthandle;
-
-undef_int i_init_tt( void );
-TT_Fonthandle* i_tt_new(char *fontname);
-void i_tt_destroy( TT_Fonthandle *handle );
-undef_int i_tt_cp( TT_Fonthandle *handle,i_img *im,int xb,int yb,int channel,float points,char const* txt,int len,int smooth, int utf8, int align);
-undef_int i_tt_text( TT_Fonthandle *handle, i_img *im, int xb, int yb, i_color *cl, float points, char const* txt, int len, int smooth, int utf8, int align);
-undef_int i_tt_bbox( TT_Fonthandle *handle, float points,char *txt,int len,int cords[6], int utf8);
-int i_tt_has_chars(TT_Fonthandle *handle, char const *text, int len, int utf8, char *out);
-void i_tt_dump_names(TT_Fonthandle *handle);
-int i_tt_face_name(TT_Fonthandle *handle, char *name_buf, 
-                   size_t name_buf_size);
-int i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf,
-                    size_t name_buf_size);
-
-#endif  /* End of freetype headers */
-
-#ifdef HAVE_FT2
-
-typedef struct FT2_Fonthandle FT2_Fonthandle;
-extern int i_ft2_init(void);
-extern FT2_Fonthandle * i_ft2_new(char *name, int index);
-extern void i_ft2_destroy(FT2_Fonthandle *handle);
-extern int i_ft2_setdpi(FT2_Fonthandle *handle, int xdpi, int ydpi);
-extern int i_ft2_getdpi(FT2_Fonthandle *handle, int *xdpi, int *ydpi);
-extern int i_ft2_settransform(FT2_Fonthandle *handle, double *matrix);
-extern int i_ft2_sethinting(FT2_Fonthandle *handle, int hinting);
-extern int i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth, 
-                      char const *text, int len, int *bbox, int utf8);
-extern int i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth, 
-                     char const *text, int len, int vlayout, int utf8, int *bbox);
-extern int i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, 
-                      i_color *cl, double cheight, double cwidth, 
-                      char const *text, int len, int align, int aa, 
-                      int vlayout, int utf8);
-extern int i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, 
-                    int channel, double cheight, double cwidth, 
-                    char const *text, int len, int align, int aa, int vlayout, 
-                    int utf8);
-extern int i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, int len,
-                           int utf8, char *work);
-extern int i_ft2_face_name(FT2_Fonthandle *handle, char *name_buf, 
-                           size_t name_buf_size);
-extern int i_ft2_can_face_name(void);
-extern int i_ft2_glyph_name(FT2_Fonthandle *handle, unsigned long ch, 
-                            char *name_buf, size_t name_buf_size,
-                            int reliable_only);
-extern int i_ft2_can_do_glyph_names(void);
-extern int i_ft2_face_has_glyph_names(FT2_Fonthandle *handle);
-
-extern int i_ft2_get_multiple_masters(FT2_Fonthandle *handle,
-                                      i_font_mm *mm);
-extern int
-i_ft2_is_multiple_master(FT2_Fonthandle *handle);
-extern int
-i_ft2_set_mm_coords(FT2_Fonthandle *handle, int coord_count, long *coords);
-#endif
-
-#ifdef WIN32
-
-extern int i_wf_bbox(char *face, int size, char *text, int length, int *bbox);
-extern int i_wf_text(char *face, i_img *im, int tx, int ty, i_color *cl, 
-                    int size, char *text, int len, int align, int aa);
-extern int i_wf_cp(char *face, i_img *im, int tx, int ty, int channel, 
-                  int size, char *text, int len, int align, int aa);
-extern int i_wf_addfont(char const *file);
-
-#endif
-
-/* functions for reading and writing formats */
-
-/* general reader callback 
- userdata - data the user passed into the reader
- buffer - the buffer to fill with data
- need - the amount of data needed
- want - the amount of space we have to store data
- fill buffer and return the number of bytes read, 0 for eof, -1 for error
-*/
-
-typedef int (*i_read_callback_t)(char *userdata, char *buffer, int need, 
-                                int want);
-
-/* i_gen_reader() translates the low-level requests from whatever library
-   into buffered requests.
-   but the called function can always bypass buffering by only ever 
-   reading I<need> bytes.
-*/
-#define CBBUFSIZ 4096
-
-typedef struct {
-  i_read_callback_t cb;
-  char *userdata;
-  char buffer[CBBUFSIZ];
-  int length;
-  int cpos;
-} i_gen_read_data;
-
-extern int  i_gen_reader(i_gen_read_data *info, char *buffer, int need);
-extern      i_gen_read_data *i_gen_read_data_new(i_read_callback_t cb, char *userdata);
-extern void i_free_gen_read_data(i_gen_read_data *);
-
-/* general writer callback
-   userdata - the data the user passed into the writer
-   data - the data to write
-   data_size - the number of bytes to write
-   write the data, return non-zero on success, zero on failure.
-*/
-typedef int (*i_write_callback_t)(char *userdata, char const *data, int size);
-
-typedef struct {
-  i_write_callback_t cb;
-  char *userdata;
-  char buffer[CBBUFSIZ];
-  int maxlength;
-  int filledto;
-} i_gen_write_data;
-
-extern int i_gen_writer(i_gen_write_data *info, char const *data, int size);
-extern i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb, char *userdata, int maxlength);
-extern int i_free_gen_write_data(i_gen_write_data *, int flush);
-
-/* transparency handling for quantized output */
-typedef enum i_transp_tag {
-  tr_none, /* ignore any alpha channel */
-  tr_threshold, /* threshold the transparency - uses tr_threshold */
-  tr_errdiff, /* error diffusion */
-  tr_ordered /* an ordered dither */
-} i_transp;
-
-/* controls how we build the colour map */
-typedef enum i_make_colors_tag {
-  mc_none, /* user supplied colour map only */
-  mc_web_map, /* Use the 216 colour web colour map */
-  mc_addi, /* Addi's algorithm */
-  mc_median_cut, /* median cut - similar to giflib, hopefully */
-  mc_mask = 0xFF /* (mask for generator) */
-} i_make_colors;
-
-/* controls how we translate the colours */
-typedef enum i_translate_tag {
-  pt_giflib, /* get gif lib to do it (ignores make_colours) */
-  pt_closest, /* just use the closest match within the hashbox */
-  pt_perturb, /* randomly perturb the data - uses perturb_size*/
-  pt_errdiff /* error diffusion dither - uses errdiff */
-} i_translate;
-
-/* Which error diffusion map to use */
-typedef enum i_errdiff_tag {
-  ed_floyd, /* floyd-steinberg */
-  ed_jarvis, /* Jarvis, Judice and Ninke */
-  ed_stucki, /* Stucki */
-  ed_custom, /* the map found in ed_map|width|height|orig */
-  ed_mask = 0xFF, /* mask to get the map */
-  ed_bidir = 0x100 /* change direction for each row */
-} i_errdiff;
-
-/* which ordered dither map to use
-   currently only available for transparency
-   I don't know of a way to do ordered dither of an image against some 
-   general palette
- */
-typedef enum i_ord_dith_tag
-{
-  od_random, /* sort of random */
-  od_dot8, /* large dot */
-  od_dot4,
-  od_hline,
-  od_vline,
-  od_slashline, /* / line dither */
-  od_backline, /* \ line dither */
-  od_tiny, /* small checkerbox */
-  od_custom /* custom 8x8 map */
-} i_ord_dith;
-
-typedef struct i_gif_pos_tag {
-  int x, y;
-} i_gif_pos;
-
-/* passed into i_writegif_gen() to control quantization */
-typedef struct i_quantize_tag {
-  /* how to handle transparency */
-  i_transp transp;
-  /* the threshold at which to make pixels opaque */
-  int tr_threshold;
-  i_errdiff tr_errdiff;
-  i_ord_dith tr_orddith;
-  unsigned char tr_custom[64];
-  
-  /* how to make the colour map */
-  i_make_colors make_colors;
-
-  /* any existing colours 
-     mc_existing is an existing colour table
-     mc_count is the number of existing colours
-     mc_size is the total size of the array that mc_existing points
-     at - this must be at least 256
-  */
-  i_color *mc_colors;
-  int mc_size;
-  int mc_count;
-
-  /* how we translate the colours */
-  i_translate translate;
-
-  /* the error diffusion map to use if translate is mc_errdiff */
-  i_errdiff errdiff;
-  /* the following define the error diffusion values to use if 
-     errdiff is ed_custom.  ed_orig is the column on the top row that
-     represents the current 
-  */
-  int *ed_map;
-  int ed_width, ed_height, ed_orig;
-
-  /* the amount of perturbation to use for translate is mc_perturb */
-  int perturb;
-} i_quantize;
-
-typedef struct i_gif_opts {
-  /* each image has a local color map */
-  int each_palette;
-
-  /* images are interlaced */
-  int interlace;
-
-  /* time for which image is displayed 
-   (in 1/100 seconds)
-   default: 0
-  */
-  int delay_count;
-  int *delays;
-
-  /* user input flags 
-     default: 0
-   */
-  int user_input_count;
-  char *user_input_flags;
-
-  /* disposal
-     default: 0 */
-  int disposal_count;
-  char *disposal;
-
-  /* this is added to the color table when we make an image transparent */
-  i_color tran_color;
-
-  /* image positions */
-  int position_count;
-  i_gif_pos *positions;
-
-  /* Netscape loop extension - number of loops */
-  int loop_count;
-
-  /* should be eliminate unused colors? */
-  int eliminate_unused;
-} i_gif_opts;
-
-extern void quant_makemap(i_quantize *quant, i_img **imgs, int count);
-extern i_palidx *quant_translate(i_quantize *quant, i_img *img);
-extern void quant_transparent(i_quantize *quant, i_palidx *indices, i_img *img, i_palidx trans_index);
-
-extern i_img *i_img_pal_new(int x, int y, int channels, int maxpal);
-extern i_img *i_img_pal_new_low(i_img *im, int x, int y, int channels, int maxpal);
-extern i_img *i_img_to_pal(i_img *src, i_quantize *quant);
-extern i_img *i_img_to_rgb(i_img *src);
-extern i_img *i_img_masked_new(i_img *targ, i_img *mask, int x, int y, 
-                               int w, int h);
-extern i_img *i_img_16_new(int x, int y, int ch);
-extern i_img *i_img_16_new_low(i_img *im, int x, int y, int ch);
-extern i_img *i_img_double_new(int x, int y, int ch);
-extern i_img *i_img_double_new_low(i_img *im, int x, int y, int ch);
-
-
-char * i_test_format_probe(io_glue *data, int length);
-
-
-#ifdef HAVE_LIBJPEG
-i_img *   
-i_readjpeg_wiol(io_glue *ig, int length, char** iptc_itext, int *itlength);
-undef_int i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor);
-#endif /* HAVE_LIBJPEG */
-
-#ifdef HAVE_LIBTIFF
-i_img   * i_readtiff_wiol(io_glue *ig, int length, int page);
-i_img  ** i_readtiff_multi_wiol(io_glue *ig, int length, int *count);
-undef_int i_writetiff_wiol(i_img *im, io_glue *ig);
-undef_int i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count);
-undef_int i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine);
-undef_int i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine);
-
-#endif /* HAVE_LIBTIFF */
-
-#ifdef HAVE_LIBPNG
-i_img    *i_readpng_wiol(io_glue *ig, int length);
-undef_int i_writepng_wiol(i_img *im, io_glue *ig);
-#endif /* HAVE_LIBPNG */
-
-#ifdef HAVE_LIBGIF
-i_img *i_readgif(int fd, int **colour_table, int *colours);
-i_img *i_readgif_wiol(io_glue *ig, int **colour_table, int *colours);
-i_img *i_readgif_scalar(char *data, int length, int **colour_table, int *colours);
-i_img *i_readgif_callback(i_read_callback_t callback, char *userdata, int **colour_table, int *colours);
-i_img *i_readgif_single_wiol(io_glue *ig, int page);
-extern i_img **i_readgif_multi(int fd, int *count);
-extern i_img **i_readgif_multi_scalar(char *data, int length, int *count);
-extern i_img **i_readgif_multi_callback(i_read_callback_t callback, char *userdata, int *count);
-extern i_img **i_readgif_multi_wiol(io_glue *ig, int *count);
-undef_int i_writegif(i_img *im,int fd,int colors,int pixdev,int fixedlen,i_color fixed[]);
-undef_int i_writegifmc(i_img *im,int fd,int colors);
-undef_int i_writegifex(i_img *im,int fd);
-undef_int i_writegif_gen(i_quantize *quant, int fd, i_img **imgs, int count);
-undef_int i_writegif_callback(i_quantize *quant, i_write_callback_t cb, char *userdata, int maxbuffer, i_img **imgs, int count);
-undef_int i_writegif_wiol(io_glue *ig, i_quantize *quant, 
-                          i_img **imgs, int count);
-void i_qdist(i_img *im);
-
-#endif /* HAVE_LIBGIF */
-
-i_img   * i_readraw_wiol(io_glue *ig, int x, int y, int datachannels, int storechannels, int intrl);
-undef_int i_writeraw_wiol(i_img* im, io_glue *ig);
-
-i_img   * i_readpnm_wiol(io_glue *ig, int length);
-undef_int i_writeppm_wiol(i_img *im, io_glue *ig);
-
-extern int    i_writebmp_wiol(i_img *im, io_glue *ig);
-extern i_img *i_readbmp_wiol(io_glue *ig);
-
-int tga_header_verify(unsigned char headbuf[18]);
-
-i_img   * i_readtga_wiol(io_glue *ig, int length);
-undef_int i_writetga_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen);
-
-i_img   * i_readrgb_wiol(io_glue *ig, int length);
-undef_int i_writergb_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen);
-
-i_img * i_scaleaxis(i_img *im, float Value, int Axis);
-i_img * i_scale_nn(i_img *im, float scx, float scy);
-i_img * i_haar(i_img *im);
-int     i_count_colors(i_img *im,int maxc);
-
-i_img * i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen);
-
-struct rm_op;
-i_img * i_transform2(int width, int height, int channels,
-                    struct rm_op *ops, int ops_count, 
-                    double *n_regs, int n_regs_count, 
-                    i_color *c_regs, int c_regs_count, 
-                    i_img **in_imgs, int in_imgs_count);
-
-/* filters */
-
-void i_contrast(i_img *im, float intensity);
-void i_hardinvert(i_img *im);
-void i_noise(i_img *im, float amount, unsigned char type);
-void i_bumpmap(i_img *im,i_img *bump,int channel,int light_x,int light_y,int strength);
-void i_bumpmap_complex(i_img *im, i_img *bump, int channel, int tx, int ty, float Lx, float Ly, 
-                      float Lz, float cd, float cs, float n, i_color *Ia, i_color *Il, i_color *Is);
-void i_postlevels(i_img *im,int levels);
-void i_mosaic(i_img *im,int size);
-void i_watermark(i_img *im,i_img *wmark,int tx,int ty,int pixdiff);
-void i_autolevels(i_img *im,float lsat,float usat,float skew);
-void i_radnoise(i_img *im,int xo,int yo,float rscale,float ascale);
-void i_turbnoise(i_img *im,float xo,float yo,float scale);
-void i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure);
-void i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure);
-i_img *i_diff_image(i_img *im, i_img *im2, int mindist);
-typedef enum {
-  i_fst_linear,
-  i_fst_curved,
-  i_fst_sine,
-  i_fst_sphere_up,
-  i_fst_sphere_down,
-  i_fst_end
-} i_fountain_seg_type;
-typedef enum {
-  i_fc_direct,
-  i_fc_hue_up,
-  i_fc_hue_down,
-  i_fc_end
-} i_fountain_color;
-typedef struct {
-  double start, middle, end;
-  i_fcolor c[2];
-  i_fountain_seg_type type;
-  i_fountain_color color;
-} i_fountain_seg;
-typedef enum {
-  i_fr_none,
-  i_fr_sawtooth,
-  i_fr_triangle,
-  i_fr_saw_both,
-  i_fr_tri_both
-} i_fountain_repeat;
-typedef enum {
-  i_ft_linear,
-  i_ft_bilinear,
-  i_ft_radial,
-  i_ft_radial_square,
-  i_ft_revolution,
-  i_ft_conical,
-  i_ft_end
-} i_fountain_type;
-typedef enum {
-  i_fts_none,
-  i_fts_grid,
-  i_fts_random,
-  i_fts_circle
-} i_ft_supersample;
-void i_fountain(i_img *im, double xa, double ya, double xb, double yb, 
-                i_fountain_type type, i_fountain_repeat repeat, 
-                int combine, int super_sample, double ssample_param,
-                int count, i_fountain_seg *segs);
-extern i_fill_t *
-i_new_fill_fount(double xa, double ya, double xb, double yb, 
-                 i_fountain_type type, i_fountain_repeat repeat, 
-                 int combine, int super_sample, double ssample_param, 
-                 int count, i_fountain_seg *segs);
-
-/* Debug only functions */
-
-void malloc_state( void );
-
-/* this is sort of obsolete now */
-
-typedef struct {
-  undef_int (*i_has_format)(char *frmt);
-  i_color*(*ICL_set)(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a);
-  void (*ICL_info)(i_color *cl);
-
-  i_img*(*i_img_new)( void );
-  i_img*(*i_img_empty)(i_img *im,int x,int y);
-  i_img*(*i_img_empty_ch)(i_img *im,int x,int y,int ch);
-  void(*i_img_exorcise)(i_img *im);
-
-  void(*i_img_info)(i_img *im,int *info);
-  
-  void(*i_img_setmask)(i_img *im,int ch_mask);
-  int (*i_img_getmask)(i_img *im);
-  
-  /*
-  int (*i_ppix)(i_img *im,int x,int y,i_color *val);
-  int (*i_gpix)(i_img *im,int x,int y,i_color *val);
-  */
-  void(*i_box)(i_img *im,int x1,int y1,int x2,int y2,i_color *val);
-  void(*i_line)(i_img *im,int x1,int y1,int x2,int y2,i_color *val,int endp);
-  void(*i_arc)(i_img *im,int x,int y,float rad,float d1,float d2,i_color *val);
-  void(*i_copyto)(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty);
-  void(*i_copyto_trans)(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans);
-  int(*i_rubthru)(i_img *im,i_img *src,int tx,int ty);
-
-} symbol_table_t;
-
-/* error handling 
-   see error.c for documentation
-   the error information is currently global
-*/
-typedef struct {
-  char *msg;
-  int code;
-} i_errmsg;
-
-typedef void (*i_error_cb)(int code, char const *msg);
-typedef void (*i_failed_cb)(i_errmsg *msgs);
-extern i_error_cb i_set_error_cb(i_error_cb);
-extern i_failed_cb i_set_failed_cb(i_failed_cb);
-extern void i_set_argv0(char const *);
-extern int i_set_errors_fatal(int new_fatal);
-extern i_errmsg *i_errors(void);
-
-extern void i_push_error(int code, char const *msg);
-extern void i_push_errorf(int code, char const *fmt, ...);
-extern void i_push_errorvf(int code, char const *fmt, va_list);
-extern void i_clear_error(void);
-extern int i_failed(int code, char const *msg);
-
-/* image tag processing */
-extern void i_tags_new(i_img_tags *tags);
-extern int i_tags_addn(i_img_tags *tags, char const *name, int code, 
-                       int idata);
-extern int i_tags_add(i_img_tags *tags, char const *name, int code, 
-                      char const *data, int size, int idata);
-extern void i_tags_destroy(i_img_tags *tags);
-extern int i_tags_find(i_img_tags *tags, char const *name, int start, 
-                       int *entry);
-extern int i_tags_findn(i_img_tags *tags, int code, int start, int *entry);
-extern int i_tags_delete(i_img_tags *tags, int entry);
-extern int i_tags_delbyname(i_img_tags *tags, char const *name);
-extern int i_tags_delbycode(i_img_tags *tags, int code);
-extern int i_tags_get_float(i_img_tags *tags, char const *name, int code, 
-                           double *value);
-extern int i_tags_set_float(i_img_tags *tags, char const *name, int code, 
-                           double value);
-extern int i_tags_set_float2(i_img_tags *tags, char const *name, int code, 
-                           double value, int places);
-extern int i_tags_get_int(i_img_tags *tags, char const *name, int code, 
-                          int *value);
-extern int i_tags_get_string(i_img_tags *tags, char const *name, int code, 
-                            char *value, size_t value_size);
-extern int i_tags_get_color(i_img_tags *tags, char const *name, int code, 
-                            i_color *value);
-extern int i_tags_set_color(i_img_tags *tags, char const *name, int code, 
-                            i_color const *value);
-extern void i_tags_print(i_img_tags *tags);
-
-/* image file limits */
-extern int
-i_set_image_file_limits(int width, int height, int bytes);
-extern int
-i_get_image_file_limits(int *width, int *height, int *bytes);
-
-#endif
diff --git a/imagei.h b/imagei.h
deleted file mode 100644 (file)
index ce58e50..0000000
--- a/imagei.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* Declares utility functions useful across various files which
-   aren't meant to be available externally
-*/
-
-#ifndef IMAGEI_H_
-#define IMAGEI_H_
-
-#include "image.h"
-
-/* wrapper functions that implement the floating point sample version of a 
-   function in terms of the 8-bit sample version
-*/
-extern int i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix);
-extern int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix);
-extern int i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix);
-extern int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix);
-extern int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp,
-                       int const *chans, int chan_count);
-
-/* wrapper functions that forward palette calls to the underlying image,
-   assuming the underlying image is the first pointer in whatever
-   ext_data points at
-*/
-extern int i_addcolors_forward(i_img *im, i_color *, int count);
-extern int i_getcolors_forward(i_img *im, int i, i_color *, int count);
-extern int i_colorcount_forward(i_img *im);
-extern int i_maxcolors_forward(i_img *im);
-extern int i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry);
-extern int i_setcolors_forward(i_img *im, int index, i_color *colors, 
-                               int count);
-
-#define SampleFTo16(num) ((int)((num) * 65535.0 + 0.01))
-/* we add that little bit to avoid rounding issues */
-#define Sample16ToF(num) ((num) / 65535.0)
-
-#define SampleFTo8(num) ((int)((num) * 255.0 + 0.01))
-#define Sample8ToF(num) ((num) / 255.0)
-
-#define Sample16To8(num) ((num) / 257)
-#define Sample8To16(num) ((num) * 257)
-
-extern void i_get_combine(int combine, i_fill_combine_f *, i_fill_combinef_f *);
-
-extern int
-i_int_check_image_file_limits(int width, int height, int channels, int sample_size);
-
-#define im_min(a, b) ((a) < (b) ? (a) : (b))
-#define im_max(a, b) ((a) > (b) ? (a) : (b))
-
-#include "ext.h"
-
-extern UTIL_table_t i_UTIL_table;
-
-/* Ideally this will move into imconfig.h if we ever probe */
-#if defined(_GNU_SOURCE) || __STDC_VERSION__ >= 199901L
-/* snprintf() is part of C99 and provided by Glibc */
-#define HAVE_SNPRINTF
-#endif
-
-/* test if all channels are writable */
-#define I_ALL_CHANNELS_WRITABLE(im) (((im)->ch_mask & 0xF) == 0xf)
-
-typedef struct i_int_hline_seg_tag {
-  int minx, x_limit;
-} i_int_hline_seg;
-
-typedef struct i_int_hline_entry_tag {
-  int count;
-  int alloc;
-  i_int_hline_seg segs[1];
-} i_int_hline_entry;
-
-/* represents a set of horizontal line segments to be filled in later */
-typedef struct i_int_hlines_tag {
-  int start_y, limit_y;
-  int start_x, limit_x;
-  i_int_hline_entry **entries;
-} i_int_hlines;
-
-extern void 
-i_int_init_hlines(
-                 i_int_hlines *hlines, 
-                 int start_y,
-                 int count_y, 
-                 int start_x, 
-                 int width_x
-                 );
-extern void i_int_init_hlines_img(i_int_hlines *hlines, i_img *img);
-extern void i_int_hlines_add(i_int_hlines *hlines, int y, int minx, int width);
-extern void i_int_hlines_destroy(i_int_hlines *hlines);
-
-extern void i_int_hlines_fill_color(i_img *im, i_int_hlines *hlines, i_color *val);
-extern void i_int_hlines_fill_fill(i_img *im, i_int_hlines *hlines, i_fill_t *fill);
-
-#endif
diff --git a/imager.h b/imager.h
new file mode 100644 (file)
index 0000000..2fd775c
--- /dev/null
+++ b/imager.h
@@ -0,0 +1,553 @@
+#ifndef _IMAGE_H_
+#define _IMAGE_H_
+
+#include "imconfig.h"
+#include "imio.h"
+#include "iolayer.h"
+#include "log.h"
+#include "stackmach.h"
+
+
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+#ifdef SUNOS
+#include <strings.h>
+#endif
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+#ifndef MAXINT
+#define MAXINT 2147483647
+#endif
+
+#include "imdatatypes.h"
+
+undef_int i_has_format(char *frmt);
+
+/* constructors and destructors */
+
+i_color *ICL_new_internal(            unsigned char r,unsigned char g,unsigned char b,unsigned char a);
+i_color *ICL_set_internal(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a);
+void     ICL_info        (i_color *cl);
+void     ICL_DESTROY     (i_color *cl);
+void     ICL_add         (i_color *dst, i_color *src, int ch);
+
+extern i_fcolor *i_fcolor_new(double r, double g, double b, double a);
+extern void i_fcolor_destroy(i_fcolor *cl);
+
+extern void i_rgb_to_hsvf(i_fcolor *color);
+extern void i_hsv_to_rgbf(i_fcolor *color);
+extern void i_rgb_to_hsv(i_color *color);
+extern void i_hsv_to_rgb(i_color *color);
+
+i_img *IIM_new(int x,int y,int ch);
+#define i_img_8_new IIM_new
+void   IIM_DESTROY(i_img *im);
+i_img *i_img_new( void );
+i_img *i_img_empty(i_img *im,int x,int y);
+i_img *i_img_empty_ch(i_img *im,int x,int y,int ch);
+void   i_img_exorcise(i_img *im);
+void   i_img_destroy(i_img *im);
+
+void   i_img_info(i_img *im,int *info);
+
+extern i_img *i_sametype(i_img *im, int xsize, int ysize);
+extern i_img *i_sametype_chans(i_img *im, int xsize, int ysize, int channels);
+
+i_img *i_img_pal_new(int x, int y, int ch, int maxpal);
+
+/* Image feature settings */
+
+void   i_img_setmask    (i_img *im,int ch_mask);
+int    i_img_getmask    (i_img *im);
+int    i_img_getchannels(i_img *im);
+
+/* Base functions */
+
+extern int i_ppix(i_img *im,int x,int y,i_color *val);
+extern int i_gpix(i_img *im,int x,int y,i_color *val);
+extern int i_ppixf(i_img *im,int x,int y,i_fcolor *val);
+extern int i_gpixf(i_img *im,int x,int y,i_fcolor *val);
+
+#define i_ppix(im, x, y, val) (((im)->i_f_ppix)((im), (x), (y), (val)))
+#define i_gpix(im, x, y, val) (((im)->i_f_gpix)((im), (x), (y), (val)))
+#define i_ppixf(im, x, y, val) (((im)->i_f_ppixf)((im), (x), (y), (val)))
+#define i_gpixf(im, x, y, val) (((im)->i_f_gpixf)((im), (x), (y), (val)))
+
+extern int i_plin(i_img *im, int l, int r, int y, i_color *vals);
+extern int i_glin(i_img *im, int l, int r, int y, i_color *vals);
+extern int i_plinf(i_img *im, int l, int r, int y, i_fcolor *vals);
+extern int i_glinf(i_img *im, int l, int r, int y, i_fcolor *vals);
+extern int i_gsamp(i_img *im, int l, int r, int y, i_sample_t *samp, 
+                   const int *chans, int chan_count);
+extern int i_gsampf(i_img *im, int l, int r, int y, i_fsample_t *samp, 
+                   const int *chans, int chan_count);
+extern int i_gpal(i_img *im, int x, int r, int y, i_palidx *vals);
+extern int i_ppal(i_img *im, int x, int r, int y, i_palidx *vals);
+extern int i_addcolors(i_img *im, i_color *colors, int count);
+extern int i_getcolors(i_img *im, int i, i_color *, int count);
+extern int i_colorcount(i_img *im);
+extern int i_maxcolors(i_img *im);
+extern int i_findcolor(i_img *im, i_color *color, i_palidx *entry);
+extern int i_setcolors(i_img *im, int index, i_color *colors, 
+                       int count);
+
+#define i_plin(im, l, r, y, val) (((im)->i_f_plin)(im, l, r, y, val))
+#define i_glin(im, l, r, y, val) (((im)->i_f_glin)(im, l, r, y, val))
+#define i_plinf(im, l, r, y, val) (((im)->i_f_plinf)(im, l, r, y, val))
+#define i_glinf(im, l, r, y, val) (((im)->i_f_glinf)(im, l, r, y, val))
+
+#define i_gsamp(im, l, r, y, samps, chans, count) \
+  (((im)->i_f_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
+#define i_gsampf(im, l, r, y, samps, chans, count) \
+  (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
+
+#define i_findcolor(im, color, entry) \
+  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
+
+#define i_gpal(im, l, r, y, vals) \
+  (((im)->i_f_gpal) ? ((im)->i_f_gpal)((im), (l), (r), (y), (vals)) : 0)
+#define i_ppal(im, l, r, y, vals) \
+  (((im)->i_f_ppal) ? ((im)->i_f_ppal)((im), (l), (r), (y), (vals)) : 0)
+#define i_addcolors(im, colors, count) \
+  (((im)->i_f_addcolors) ? ((im)->i_f_addcolors)((im), (colors), (count)) : -1)
+#define i_getcolors(im, index, color, count) \
+  (((im)->i_f_getcolors) ? \
+   ((im)->i_f_getcolors)((im), (index), (color), (count)) : 0)
+#define i_setcolors(im, index, color, count) \
+  (((im)->i_f_setcolors) ? \
+   ((im)->i_f_setcolors)((im), (index), (color), (count)) : 0)
+#define i_colorcount(im) \
+  (((im)->i_f_colorcount) ? ((im)->i_f_colorcount)(im) : -1)
+#define i_maxcolors(im) \
+  (((im)->i_f_maxcolors) ? ((im)->i_f_maxcolors)(im) : -1)
+#define i_findcolor(im, color, entry) \
+  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
+
+#define i_img_virtual(im) ((im)->virtual)
+#define i_img_type(im) ((im)->type)
+#define i_img_bits(im) ((im)->bits)
+
+extern i_fill_t *i_new_fill_solidf(i_fcolor *c, int combine);
+extern i_fill_t *i_new_fill_solid(i_color *c, int combine);
+extern i_fill_t *
+i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch, 
+                 unsigned char *cust_hatch, int dx, int dy);
+extern i_fill_t *
+i_new_fill_hatchf(i_fcolor *fg, i_fcolor *bg, int combine, int hatch, 
+                  unsigned char *cust_hatch, int dx, int dy);
+extern i_fill_t *
+i_new_fill_image(i_img *im, double *matrix, int xoff, int yoff, int combine);
+extern void i_fill_destroy(i_fill_t *fill);
+
+float i_gpix_pch(i_img *im,int x,int y,int ch);
+
+/* functions for drawing primitives */
+
+void i_box         (i_img *im,int x1,int y1,int x2,int y2,i_color *val);
+void i_box_filled  (i_img *im,int x1,int y1,int x2,int y2,i_color *val);
+void i_box_cfill(i_img *im, int x1, int y1, int x2, int y2, i_fill_t *fill);
+void i_line        (i_img *im,int x1,int y1,int x2,int y2,i_color *val, int endp);
+void i_line_aa     (i_img *im,int x1,int y1,int x2,int y2,i_color *val, int endp);
+void i_arc         (i_img *im,int x,int y,float rad,float d1,float d2,i_color *val);
+void i_arc_aa         (i_img *im, double x, double y, double rad, double d1, double d2,i_color *val);
+void i_arc_cfill(i_img *im,int x,int y,float rad,float d1,float d2,i_fill_t *fill);
+void i_arc_aa_cfill(i_img *im,double x,double y,double rad,double d1,double d2,i_fill_t *fill);
+void i_circle_aa   (i_img *im,float x, float y,float rad,i_color *val);
+void i_copyto      (i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty);
+void i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans);
+i_img* i_copy        (i_img *src);
+int  i_rubthru     (i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny, int src_maxx, int src_maxy);
+
+
+undef_int i_flipxy (i_img *im, int direction);
+extern i_img *i_rotate90(i_img *im, int degrees);
+extern i_img *i_rotate_exact(i_img *im, double amount);
+extern i_img *i_rotate_exact_bg(i_img *im, double amount, i_color *backp, i_fcolor *fbackp);
+extern i_img *i_matrix_transform(i_img *im, int xsize, int ysize, double *matrix);
+extern i_img *i_matrix_transform_bg(i_img *im, int xsize, int ysize, double *matrix,  i_color *backp, i_fcolor *fbackp);
+
+void i_bezier_multi(i_img *im,int l,double *x,double *y,i_color *val);
+void i_poly_aa     (i_img *im,int l,double *x,double *y,i_color *val);
+void i_poly_aa_cfill(i_img *im,int l,double *x,double *y,i_fill_t *fill);
+
+undef_int i_flood_fill  (i_img *im,int seedx,int seedy,i_color *dcol);
+undef_int i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill);
+
+
+/* image processing functions */
+
+void i_gaussian    (i_img *im,float stdev);
+void i_conv        (i_img *im,float *coeff,int len);
+void i_unsharp_mask(i_img *im, double stddev, double scale);
+
+/* colour manipulation */
+extern int i_convert(i_img *im, i_img *src, float *coeff, int outchan, int inchan);
+extern void i_map(i_img *im, unsigned char (*maps)[256], unsigned int mask);
+
+float i_img_diff   (i_img *im1,i_img *im2);
+
+/* font routines */
+
+undef_int i_init_fonts( int t1log );
+
+#ifdef HAVE_LIBT1
+
+undef_int i_init_t1( int t1log );
+int       i_t1_new( char *pfb, char *afm );
+int       i_t1_destroy( int font_id );
+undef_int i_t1_cp( i_img *im, int xb, int yb, int channel, int fontnum, float points, char* str, int len, int align, int utf8, char const *flags );
+undef_int i_t1_text( i_img *im, int xb, int yb, i_color *cl, int fontnum, float points, char* str, int len, int align, int utf8, char const *flags );
+int      i_t1_bbox( int fontnum, float point, char *str, int len, int cords[6], int utf8, char const *flags );
+void      i_t1_set_aa( int st );
+void      close_t1( void );
+int       i_t1_has_chars(int font_num, char const *text, int len, int utf8, char *out);
+extern int i_t1_face_name(int font_num, char *name_buf, size_t name_buf_size);
+extern int i_t1_glyph_name(int font_num, unsigned long ch, char *name_buf, 
+                           size_t name_buf_size);
+#endif
+
+#ifdef HAVE_LIBTT
+
+undef_int i_init_tt( void );
+TT_Fonthandle* i_tt_new(char *fontname);
+void i_tt_destroy( TT_Fonthandle *handle );
+undef_int i_tt_cp( TT_Fonthandle *handle,i_img *im,int xb,int yb,int channel,float points,char const* txt,int len,int smooth, int utf8, int align);
+undef_int i_tt_text( TT_Fonthandle *handle, i_img *im, int xb, int yb, i_color *cl, float points, char const* txt, int len, int smooth, int utf8, int align);
+undef_int i_tt_bbox( TT_Fonthandle *handle, float points,char *txt,int len,int cords[6], int utf8);
+int i_tt_has_chars(TT_Fonthandle *handle, char const *text, int len, int utf8, char *out);
+void i_tt_dump_names(TT_Fonthandle *handle);
+int i_tt_face_name(TT_Fonthandle *handle, char *name_buf, 
+                   size_t name_buf_size);
+int i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf,
+                    size_t name_buf_size);
+
+#endif  /* End of freetype headers */
+
+#ifdef HAVE_FT2
+
+extern int i_ft2_init(void);
+extern FT2_Fonthandle * i_ft2_new(char *name, int index);
+extern void i_ft2_destroy(FT2_Fonthandle *handle);
+extern int i_ft2_setdpi(FT2_Fonthandle *handle, int xdpi, int ydpi);
+extern int i_ft2_getdpi(FT2_Fonthandle *handle, int *xdpi, int *ydpi);
+extern int i_ft2_settransform(FT2_Fonthandle *handle, double *matrix);
+extern int i_ft2_sethinting(FT2_Fonthandle *handle, int hinting);
+extern int i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth, 
+                      char const *text, int len, int *bbox, int utf8);
+extern int i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth, 
+                     char const *text, int len, int vlayout, int utf8, int *bbox);
+extern int i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, 
+                      i_color *cl, double cheight, double cwidth, 
+                      char const *text, int len, int align, int aa, 
+                      int vlayout, int utf8);
+extern int i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, 
+                    int channel, double cheight, double cwidth, 
+                    char const *text, int len, int align, int aa, int vlayout, 
+                    int utf8);
+extern int i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, int len,
+                           int utf8, char *work);
+extern int i_ft2_face_name(FT2_Fonthandle *handle, char *name_buf, 
+                           size_t name_buf_size);
+extern int i_ft2_can_face_name(void);
+extern int i_ft2_glyph_name(FT2_Fonthandle *handle, unsigned long ch, 
+                            char *name_buf, size_t name_buf_size,
+                            int reliable_only);
+extern int i_ft2_can_do_glyph_names(void);
+extern int i_ft2_face_has_glyph_names(FT2_Fonthandle *handle);
+
+extern int i_ft2_get_multiple_masters(FT2_Fonthandle *handle,
+                                      i_font_mm *mm);
+extern int
+i_ft2_is_multiple_master(FT2_Fonthandle *handle);
+extern int
+i_ft2_set_mm_coords(FT2_Fonthandle *handle, int coord_count, long *coords);
+#endif
+
+#ifdef WIN32
+
+extern int i_wf_bbox(char *face, int size, char *text, int length, int *bbox);
+extern int i_wf_text(char *face, i_img *im, int tx, int ty, i_color *cl, 
+                    int size, char *text, int len, int align, int aa);
+extern int i_wf_cp(char *face, i_img *im, int tx, int ty, int channel, 
+                  int size, char *text, int len, int align, int aa);
+extern int i_wf_addfont(char const *file);
+
+#endif
+
+/* functions for reading and writing formats */
+
+/* general reader callback 
+ userdata - data the user passed into the reader
+ buffer - the buffer to fill with data
+ need - the amount of data needed
+ want - the amount of space we have to store data
+ fill buffer and return the number of bytes read, 0 for eof, -1 for error
+*/
+
+typedef int (*i_read_callback_t)(char *userdata, char *buffer, int need, 
+                                int want);
+
+/* i_gen_reader() translates the low-level requests from whatever library
+   into buffered requests.
+   but the called function can always bypass buffering by only ever 
+   reading I<need> bytes.
+*/
+#define CBBUFSIZ 4096
+
+typedef struct {
+  i_read_callback_t cb;
+  char *userdata;
+  char buffer[CBBUFSIZ];
+  int length;
+  int cpos;
+} i_gen_read_data;
+
+extern int  i_gen_reader(i_gen_read_data *info, char *buffer, int need);
+extern      i_gen_read_data *i_gen_read_data_new(i_read_callback_t cb, char *userdata);
+extern void i_free_gen_read_data(i_gen_read_data *);
+
+/* general writer callback
+   userdata - the data the user passed into the writer
+   data - the data to write
+   data_size - the number of bytes to write
+   write the data, return non-zero on success, zero on failure.
+*/
+typedef int (*i_write_callback_t)(char *userdata, char const *data, int size);
+
+typedef struct {
+  i_write_callback_t cb;
+  char *userdata;
+  char buffer[CBBUFSIZ];
+  int maxlength;
+  int filledto;
+} i_gen_write_data;
+
+extern int i_gen_writer(i_gen_write_data *info, char const *data, int size);
+extern i_gen_write_data *i_gen_write_data_new(i_write_callback_t cb, char *userdata, int maxlength);
+extern int i_free_gen_write_data(i_gen_write_data *, int flush);
+
+extern void i_quant_makemap(i_quantize *quant, i_img **imgs, int count);
+extern i_palidx *i_quant_translate(i_quantize *quant, i_img *img);
+extern void i_quant_transparent(i_quantize *quant, i_palidx *indices, i_img *img, i_palidx trans_index);
+
+extern i_img *i_img_pal_new(int x, int y, int channels, int maxpal);
+extern i_img *i_img_pal_new_low(i_img *im, int x, int y, int channels, int maxpal);
+extern i_img *i_img_to_pal(i_img *src, i_quantize *quant);
+extern i_img *i_img_to_rgb(i_img *src);
+extern i_img *i_img_masked_new(i_img *targ, i_img *mask, int x, int y, 
+                               int w, int h);
+extern i_img *i_img_16_new(int x, int y, int ch);
+extern i_img *i_img_16_new_low(i_img *im, int x, int y, int ch);
+extern i_img *i_img_double_new(int x, int y, int ch);
+extern i_img *i_img_double_new_low(i_img *im, int x, int y, int ch);
+
+
+char * i_test_format_probe(io_glue *data, int length);
+
+
+#ifdef HAVE_LIBJPEG
+i_img *   
+i_readjpeg_wiol(io_glue *ig, int length, char** iptc_itext, int *itlength);
+undef_int i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor);
+#endif /* HAVE_LIBJPEG */
+
+#ifdef HAVE_LIBTIFF
+i_img   * i_readtiff_wiol(io_glue *ig, int length, int page);
+i_img  ** i_readtiff_multi_wiol(io_glue *ig, int length, int *count);
+undef_int i_writetiff_wiol(i_img *im, io_glue *ig);
+undef_int i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count);
+undef_int i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine);
+undef_int i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine);
+
+#endif /* HAVE_LIBTIFF */
+
+#ifdef HAVE_LIBPNG
+i_img    *i_readpng_wiol(io_glue *ig, int length);
+undef_int i_writepng_wiol(i_img *im, io_glue *ig);
+#endif /* HAVE_LIBPNG */
+
+#ifdef HAVE_LIBGIF
+i_img *i_readgif(int fd, int **colour_table, int *colours);
+i_img *i_readgif_wiol(io_glue *ig, int **colour_table, int *colours);
+i_img *i_readgif_scalar(char *data, int length, int **colour_table, int *colours);
+i_img *i_readgif_callback(i_read_callback_t callback, char *userdata, int **colour_table, int *colours);
+i_img *i_readgif_single_wiol(io_glue *ig, int page);
+extern i_img **i_readgif_multi(int fd, int *count);
+extern i_img **i_readgif_multi_scalar(char *data, int length, int *count);
+extern i_img **i_readgif_multi_callback(i_read_callback_t callback, char *userdata, int *count);
+extern i_img **i_readgif_multi_wiol(io_glue *ig, int *count);
+undef_int i_writegif(i_img *im,int fd,int colors,int pixdev,int fixedlen,i_color fixed[]);
+undef_int i_writegifmc(i_img *im,int fd,int colors);
+undef_int i_writegifex(i_img *im,int fd);
+undef_int i_writegif_gen(i_quantize *quant, int fd, i_img **imgs, int count);
+undef_int i_writegif_callback(i_quantize *quant, i_write_callback_t cb, char *userdata, int maxbuffer, i_img **imgs, int count);
+undef_int i_writegif_wiol(io_glue *ig, i_quantize *quant, 
+                          i_img **imgs, int count);
+void i_qdist(i_img *im);
+
+#endif /* HAVE_LIBGIF */
+
+i_img   * i_readraw_wiol(io_glue *ig, int x, int y, int datachannels, int storechannels, int intrl);
+undef_int i_writeraw_wiol(i_img* im, io_glue *ig);
+
+i_img   * i_readpnm_wiol(io_glue *ig, int length);
+undef_int i_writeppm_wiol(i_img *im, io_glue *ig);
+
+extern int    i_writebmp_wiol(i_img *im, io_glue *ig);
+extern i_img *i_readbmp_wiol(io_glue *ig);
+
+int tga_header_verify(unsigned char headbuf[18]);
+
+i_img   * i_readtga_wiol(io_glue *ig, int length);
+undef_int i_writetga_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen);
+
+i_img   * i_readrgb_wiol(io_glue *ig, int length);
+undef_int i_writergb_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen);
+
+i_img * i_scaleaxis(i_img *im, float Value, int Axis);
+i_img * i_scale_nn(i_img *im, float scx, float scy);
+i_img * i_haar(i_img *im);
+int     i_count_colors(i_img *im,int maxc);
+
+i_img * i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen);
+
+struct rm_op;
+i_img * i_transform2(int width, int height, int channels,
+                    struct rm_op *ops, int ops_count, 
+                    double *n_regs, int n_regs_count, 
+                    i_color *c_regs, int c_regs_count, 
+                    i_img **in_imgs, int in_imgs_count);
+
+/* filters */
+
+void i_contrast(i_img *im, float intensity);
+void i_hardinvert(i_img *im);
+void i_noise(i_img *im, float amount, unsigned char type);
+void i_bumpmap(i_img *im,i_img *bump,int channel,int light_x,int light_y,int strength);
+void i_bumpmap_complex(i_img *im, i_img *bump, int channel, int tx, int ty, float Lx, float Ly, 
+                      float Lz, float cd, float cs, float n, i_color *Ia, i_color *Il, i_color *Is);
+void i_postlevels(i_img *im,int levels);
+void i_mosaic(i_img *im,int size);
+void i_watermark(i_img *im,i_img *wmark,int tx,int ty,int pixdiff);
+void i_autolevels(i_img *im,float lsat,float usat,float skew);
+void i_radnoise(i_img *im,int xo,int yo,float rscale,float ascale);
+void i_turbnoise(i_img *im,float xo,float yo,float scale);
+void i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure);
+void i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure);
+i_img *i_diff_image(i_img *im, i_img *im2, int mindist);
+void i_fountain(i_img *im, double xa, double ya, double xb, double yb, 
+                i_fountain_type type, i_fountain_repeat repeat, 
+                int combine, int super_sample, double ssample_param,
+                int count, i_fountain_seg *segs);
+extern i_fill_t *
+i_new_fill_fount(double xa, double ya, double xb, double yb, 
+                 i_fountain_type type, i_fountain_repeat repeat, 
+                 int combine, int super_sample, double ssample_param, 
+                 int count, i_fountain_seg *segs);
+
+/* Debug only functions */
+
+void malloc_state( void );
+
+/* this is sort of obsolete now */
+
+typedef struct {
+  undef_int (*i_has_format)(char *frmt);
+  i_color*(*ICL_set)(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char a);
+  void (*ICL_info)(i_color *cl);
+
+  i_img*(*i_img_new)( void );
+  i_img*(*i_img_empty)(i_img *im,int x,int y);
+  i_img*(*i_img_empty_ch)(i_img *im,int x,int y,int ch);
+  void(*i_img_exorcise)(i_img *im);
+
+  void(*i_img_info)(i_img *im,int *info);
+  
+  void(*i_img_setmask)(i_img *im,int ch_mask);
+  int (*i_img_getmask)(i_img *im);
+  
+  /*
+  int (*i_ppix)(i_img *im,int x,int y,i_color *val);
+  int (*i_gpix)(i_img *im,int x,int y,i_color *val);
+  */
+  void(*i_box)(i_img *im,int x1,int y1,int x2,int y2,i_color *val);
+  void(*i_line)(i_img *im,int x1,int y1,int x2,int y2,i_color *val,int endp);
+  void(*i_arc)(i_img *im,int x,int y,float rad,float d1,float d2,i_color *val);
+  void(*i_copyto)(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty);
+  void(*i_copyto_trans)(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,i_color *trans);
+  int(*i_rubthru)(i_img *im,i_img *src,int tx,int ty);
+
+} symbol_table_t;
+
+/* error handling 
+   see error.c for documentation
+   the error information is currently global
+*/
+typedef struct {
+  char *msg;
+  int code;
+} i_errmsg;
+
+typedef void (*i_error_cb)(int code, char const *msg);
+typedef void (*i_failed_cb)(i_errmsg *msgs);
+extern i_error_cb i_set_error_cb(i_error_cb);
+extern i_failed_cb i_set_failed_cb(i_failed_cb);
+extern void i_set_argv0(char const *);
+extern int i_set_errors_fatal(int new_fatal);
+extern i_errmsg *i_errors(void);
+
+extern void i_push_error(int code, char const *msg);
+extern void i_push_errorf(int code, char const *fmt, ...);
+extern void i_push_errorvf(int code, char const *fmt, va_list);
+extern void i_clear_error(void);
+extern int i_failed(int code, char const *msg);
+
+/* image tag processing */
+extern void i_tags_new(i_img_tags *tags);
+extern int i_tags_addn(i_img_tags *tags, char const *name, int code, 
+                       int idata);
+extern int i_tags_add(i_img_tags *tags, char const *name, int code, 
+                      char const *data, int size, int idata);
+extern int i_tags_set(i_img_tags *tags, char const *name,
+                      char const *data, int size);
+extern int i_tags_setn(i_img_tags *tags, char const *name, int idata);
+                       
+extern void i_tags_destroy(i_img_tags *tags);
+extern int i_tags_find(i_img_tags *tags, char const *name, int start, 
+                       int *entry);
+extern int i_tags_findn(i_img_tags *tags, int code, int start, int *entry);
+extern int i_tags_delete(i_img_tags *tags, int entry);
+extern int i_tags_delbyname(i_img_tags *tags, char const *name);
+extern int i_tags_delbycode(i_img_tags *tags, int code);
+extern int i_tags_get_float(i_img_tags *tags, char const *name, int code, 
+                           double *value);
+extern int i_tags_set_float(i_img_tags *tags, char const *name, int code, 
+                           double value);
+extern int i_tags_set_float2(i_img_tags *tags, char const *name, int code, 
+                           double value, int places);
+extern int i_tags_get_int(i_img_tags *tags, char const *name, int code, 
+                          int *value);
+extern int i_tags_get_string(i_img_tags *tags, char const *name, int code, 
+                            char *value, size_t value_size);
+extern int i_tags_get_color(i_img_tags *tags, char const *name, int code, 
+                            i_color *value);
+extern int i_tags_set_color(i_img_tags *tags, char const *name, int code, 
+                            i_color const *value);
+extern void i_tags_print(i_img_tags *tags);
+
+/* image file limits */
+extern int
+i_set_image_file_limits(int width, int height, int bytes);
+extern int
+i_get_image_file_limits(int *width, int *height, int *bytes);
+
+#endif
diff --git a/imageri.h b/imageri.h
new file mode 100644 (file)
index 0000000..99d6211
--- /dev/null
+++ b/imageri.h
@@ -0,0 +1,95 @@
+/* Declares utility functions useful across various files which
+   aren't meant to be available externally
+*/
+
+#ifndef IMAGEI_H_
+#define IMAGEI_H_
+
+#include "imager.h"
+
+/* wrapper functions that implement the floating point sample version of a 
+   function in terms of the 8-bit sample version
+*/
+extern int i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix);
+extern int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix);
+extern int i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix);
+extern int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix);
+extern int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp,
+                       int const *chans, int chan_count);
+
+/* wrapper functions that forward palette calls to the underlying image,
+   assuming the underlying image is the first pointer in whatever
+   ext_data points at
+*/
+extern int i_addcolors_forward(i_img *im, i_color *, int count);
+extern int i_getcolors_forward(i_img *im, int i, i_color *, int count);
+extern int i_colorcount_forward(i_img *im);
+extern int i_maxcolors_forward(i_img *im);
+extern int i_findcolor_forward(i_img *im, i_color *color, i_palidx *entry);
+extern int i_setcolors_forward(i_img *im, int index, i_color *colors, 
+                               int count);
+
+#define SampleFTo16(num) ((int)((num) * 65535.0 + 0.01))
+/* we add that little bit to avoid rounding issues */
+#define Sample16ToF(num) ((num) / 65535.0)
+
+#define SampleFTo8(num) ((int)((num) * 255.0 + 0.01))
+#define Sample8ToF(num) ((num) / 255.0)
+
+#define Sample16To8(num) ((num) / 257)
+#define Sample8To16(num) ((num) * 257)
+
+extern void i_get_combine(int combine, i_fill_combine_f *, i_fill_combinef_f *);
+
+extern int
+i_int_check_image_file_limits(int width, int height, int channels, int sample_size);
+
+#define im_min(a, b) ((a) < (b) ? (a) : (b))
+#define im_max(a, b) ((a) > (b) ? (a) : (b))
+
+#include "ext.h"
+
+extern UTIL_table_t i_UTIL_table;
+
+/* Ideally this will move into imconfig.h if we ever probe */
+#if defined(_GNU_SOURCE) || __STDC_VERSION__ >= 199901L
+/* snprintf() is part of C99 and provided by Glibc */
+#define HAVE_SNPRINTF
+#endif
+
+/* test if all channels are writable */
+#define I_ALL_CHANNELS_WRITABLE(im) (((im)->ch_mask & 0xF) == 0xf)
+
+typedef struct i_int_hline_seg_tag {
+  int minx, x_limit;
+} i_int_hline_seg;
+
+typedef struct i_int_hline_entry_tag {
+  int count;
+  int alloc;
+  i_int_hline_seg segs[1];
+} i_int_hline_entry;
+
+/* represents a set of horizontal line segments to be filled in later */
+typedef struct i_int_hlines_tag {
+  int start_y, limit_y;
+  int start_x, limit_x;
+  i_int_hline_entry **entries;
+} i_int_hlines;
+
+extern void 
+i_int_init_hlines(
+                 i_int_hlines *hlines, 
+                 int start_y,
+                 int count_y, 
+                 int start_x, 
+                 int width_x
+                 );
+extern void i_int_init_hlines_img(i_int_hlines *hlines, i_img *img);
+extern void i_int_hlines_add(i_int_hlines *hlines, int y, int minx, int width);
+extern void i_int_hlines_destroy(i_int_hlines *hlines);
+
+extern void i_int_hlines_fill_color(i_img *im, i_int_hlines *hlines, i_color *val);
+extern void i_int_hlines_fill_fill(i_img *im, i_int_hlines *hlines, i_fill_t *fill);
+
+#endif
diff --git a/imdatatypes.h b/imdatatypes.h
new file mode 100644 (file)
index 0000000..774e9d9
--- /dev/null
@@ -0,0 +1,514 @@
+#ifndef _DATATYPES_H_
+#define _DATATYPES_H_
+
+#include "imio.h"
+#include "imconfig.h"
+
+#define MAXCHANNELS 4
+
+/* used for palette indices in some internal code (which might be 
+   exposed at some point
+*/
+typedef unsigned char i_palidx;
+
+/* We handle 2 types of sample, this is hopefully the most common, and the
+   smaller of the ones we support */
+typedef unsigned char i_sample_t;
+
+typedef struct { i_sample_t gray_color; } gray_color;
+typedef struct { i_sample_t r,g,b; } rgb_color;
+typedef struct { i_sample_t r,g,b,a; } rgba_color;
+typedef struct { i_sample_t c,m,y,k; } cmyk_color;
+
+typedef int undef_int; /* special value to put in typemaps to retun undef on 0 and 1 on 1 */
+
+typedef union {
+  gray_color gray;
+  rgb_color rgb;
+  rgba_color rgba;
+  cmyk_color cmyk;
+  i_sample_t channel[MAXCHANNELS];
+  unsigned int ui;
+} i_color;
+
+/* this is the larger sample type, it should be able to accurately represent
+   any sample size we use */
+typedef double i_fsample_t;
+
+typedef struct { i_fsample_t gray_color; } i_fgray_color_t;
+typedef struct { i_fsample_t r, g, b; } i_frgb_color_t;
+typedef struct { i_fsample_t r, g, b, a; } i_frgba_color_t;
+typedef struct { i_fsample_t c, m, y, k; } i_fcmyk_color_t;
+
+typedef union {
+  i_fgray_color_t gray;
+  i_frgb_color_t rgb;
+  i_frgba_color_t rgba;
+  i_fcmyk_color_t cmyk;
+  i_fsample_t channel[MAXCHANNELS];
+} i_fcolor;
+
+typedef enum {
+  i_direct_type, /* direct colour, keeps RGB values per pixel */
+  i_palette_type /* keeps a palette index per pixel */
+} i_img_type_t;
+
+typedef enum { 
+  /* bits per sample, not per pixel */
+  /* a paletted image might have one bit per sample */
+  i_8_bits = 8,
+  i_16_bits = 16,
+  i_double_bits = sizeof(double) * 8
+} i_img_bits_t;
+
+typedef struct {
+  char *name; /* name of a given tag, might be NULL */
+  int code; /* number of a given tag, -1 if it has no meaning */
+  char *data; /* value of a given tag if it's not an int, may be NULL */
+  int size; /* size of the data */
+  int idata; /* value of a given tag if data is NULL */
+} i_img_tag;
+
+typedef struct {
+  int count; /* how many tags have been set */
+  int alloc; /* how many tags have been allocated for */
+  i_img_tag *tags;
+} i_img_tags;
+
+typedef struct i_img_ i_img;
+typedef int (*i_f_ppix_t)(i_img *im, int x, int y, i_color *pix);
+typedef int (*i_f_ppixf_t)(i_img *im, int x, int y, i_fcolor *pix);
+typedef int (*i_f_plin_t)(i_img *im, int x, int r, int y, i_color *vals);
+typedef int (*i_f_plinf_t)(i_img *im, int x, int r, int y, i_fcolor *vals);
+typedef int (*i_f_gpix_t)(i_img *im, int x, int y, i_color *pix);
+typedef int (*i_f_gpixf_t)(i_img *im, int x, int y, i_fcolor *pix);
+typedef int (*i_f_glin_t)(i_img *im, int x, int r, int y, i_color *vals);
+typedef int (*i_f_glinf_t)(i_img *im, int x, int r, int y, i_fcolor *vals);
+
+typedef int (*i_f_gsamp_t)(i_img *im, int x, int r, int y, i_sample_t *samp,
+                           const int *chans, int chan_count);
+typedef int (*i_f_gsampf_t)(i_img *im, int x, int r, int y, i_fsample_t *samp,
+                            const int *chan, int chan_count);
+
+typedef int (*i_f_gpal_t)(i_img *im, int x, int r, int y, i_palidx *vals);
+typedef int (*i_f_ppal_t)(i_img *im, int x, int r, int y, i_palidx *vals);
+typedef int (*i_f_addcolors_t)(i_img *im, i_color *colors, int count);
+typedef int (*i_f_getcolors_t)(i_img *im, int i, i_color *, int count);
+typedef int (*i_f_colorcount_t)(i_img *im);
+typedef int (*i_f_maxcolors_t)(i_img *im);
+typedef int (*i_f_findcolor_t)(i_img *im, i_color *color, i_palidx *entry);
+typedef int (*i_f_setcolors_t)(i_img *im, int index, i_color *colors, 
+                              int count);
+
+typedef void (*i_f_destroy_t)(i_img *im);
+
+struct i_img_ {
+  int channels;
+  int xsize,ysize,bytes;
+  unsigned int ch_mask;
+  i_img_bits_t bits;
+  i_img_type_t type;
+  int virtual; /* image might not keep any data, must use functions */
+  unsigned char *idata; /* renamed to force inspection of existing code */
+                        /* can be NULL if virtual is non-zero */
+  i_img_tags tags;
+
+  void *ext_data;
+
+  /* interface functions */
+  i_f_ppix_t i_f_ppix;
+  i_f_ppixf_t i_f_ppixf;
+  i_f_plin_t i_f_plin;
+  i_f_plinf_t i_f_plinf;
+  i_f_gpix_t i_f_gpix;
+  i_f_gpixf_t i_f_gpixf;
+  i_f_glin_t i_f_glin;
+  i_f_glinf_t i_f_glinf;
+  i_f_gsamp_t i_f_gsamp;
+  i_f_gsampf_t i_f_gsampf;
+  
+  /* only valid for type == i_palette_type */
+  i_f_gpal_t i_f_gpal;
+  i_f_ppal_t i_f_ppal;
+  i_f_addcolors_t i_f_addcolors;
+  i_f_getcolors_t i_f_getcolors;
+  i_f_colorcount_t i_f_colorcount;
+  i_f_maxcolors_t i_f_maxcolors;
+  i_f_findcolor_t i_f_findcolor;
+  i_f_setcolors_t i_f_setcolors;
+
+  i_f_destroy_t i_f_destroy;
+};
+
+/* ext_data for paletted images
+ */
+typedef struct {
+  int count; /* amount of space used in palette (in entries) */
+  int alloc; /* amount of space allocated for palette (in entries) */
+  i_color *pal;
+  int last_found;
+} i_img_pal_ext;
+
+/* Helper datatypes
+  The types in here so far are:
+
+  doubly linked bucket list - pretty efficient
+  octtree - no idea about goodness
+  
+  needed: hashes.
+
+*/
+
+
+
+
+
+/* bitmap mask */
+
+struct i_bitmap {
+  int xsize,ysize;
+  char *data;
+};
+
+struct i_bitmap* btm_new(int xsize,int ysize);
+void btm_destroy(struct i_bitmap *btm);
+int btm_test(struct i_bitmap *btm,int x,int y);
+void btm_set(struct i_bitmap *btm,int x,int y);
+
+
+
+
+
+
+
+
+/* Stack/Linked list */
+
+struct llink {
+  struct llink *p,*n;
+  void *data;
+  int fill;            /* Number used in this link */
+};
+
+struct llist {
+  struct llink *h,*t;
+  int multip;          /* # of copies in a single chain  */
+  int ssize;           /* size of each small element     */
+  int count;           /* number of elements on the list */
+};
+
+
+/* Links */
+
+struct llink *llink_new( struct llink* p,int size );
+int  llist_llink_push( struct llist *lst, struct llink *lnk, void *data );
+
+/* Lists */
+
+struct llist *llist_new( int multip, int ssize );
+void llist_destroy( struct llist *l );
+void llist_push( struct llist *l, void *data );
+void llist_dump( struct llist *l );
+int llist_pop( struct llist *l,void *data );
+
+
+
+
+/* Octtree */
+
+struct octt {
+  struct octt *t[8]; 
+  int cnt;
+};
+
+struct octt *octt_new(void);
+int octt_add(struct octt *ct,unsigned char r,unsigned char g,unsigned char b);
+void octt_dump(struct octt *ct);
+void octt_count(struct octt *ct,int *tot,int max,int *overflow);
+void octt_delete(struct octt *ct);
+
+/* font bounding box results */
+enum bounding_box_index_t {
+  BBOX_NEG_WIDTH,
+  BBOX_GLOBAL_DESCENT,
+  BBOX_POS_WIDTH,
+  BBOX_GLOBAL_ASCENT,
+  BBOX_DESCENT,
+  BBOX_ASCENT,
+  BBOX_ADVANCE_WIDTH,
+  BBOX_RIGHT_BEARING,
+  BOUNDING_BOX_COUNT
+};
+
+/* Generic fills */
+struct i_fill_tag;
+
+typedef void (*i_fill_with_color_f)
+     (struct i_fill_tag *fill, int x, int y, int width, int channels, 
+      i_color *data);
+typedef void (*i_fill_with_fcolor_f)
+     (struct i_fill_tag *fill, int x, int y, int width, int channels,
+      i_fcolor *data);
+typedef void (*i_fill_destroy_f)(struct i_fill_tag *fill);
+typedef void (*i_fill_combine_f)(i_color *out, i_color *in, int channels, 
+                                 int count);
+typedef void (*i_fill_combinef_f)(i_fcolor *out, i_fcolor *in, int channels,
+                                  int count);
+
+/* fountain fill types */
+typedef enum {
+  i_fst_linear,
+  i_fst_curved,
+  i_fst_sine,
+  i_fst_sphere_up,
+  i_fst_sphere_down,
+  i_fst_end
+} i_fountain_seg_type;
+typedef enum {
+  i_fc_direct,
+  i_fc_hue_up,
+  i_fc_hue_down,
+  i_fc_end
+} i_fountain_color;
+typedef struct {
+  double start, middle, end;
+  i_fcolor c[2];
+  i_fountain_seg_type type;
+  i_fountain_color color;
+} i_fountain_seg;
+typedef enum {
+  i_fr_none,
+  i_fr_sawtooth,
+  i_fr_triangle,
+  i_fr_saw_both,
+  i_fr_tri_both
+} i_fountain_repeat;
+typedef enum {
+  i_ft_linear,
+  i_ft_bilinear,
+  i_ft_radial,
+  i_ft_radial_square,
+  i_ft_revolution,
+  i_ft_conical,
+  i_ft_end
+} i_fountain_type;
+typedef enum {
+  i_fts_none,
+  i_fts_grid,
+  i_fts_random,
+  i_fts_circle
+} i_ft_supersample;
+
+
+typedef struct i_fill_tag
+{
+  /* called for 8-bit/sample image (and maybe lower) */
+  /* this may be NULL, if so call fill_with_fcolor */
+  i_fill_with_color_f fill_with_color;
+
+  /* called for other sample sizes */
+  /* this must be non-NULL */
+  i_fill_with_fcolor_f fill_with_fcolor;
+
+  /* called if non-NULL to release any extra resources */
+  i_fill_destroy_f destroy;
+
+  /* if non-zero the caller will fill data with the original data
+     from the image */
+  i_fill_combine_f combine;
+  i_fill_combinef_f combinef;
+} i_fill_t;
+
+typedef enum {
+  ic_none,
+  ic_normal,
+  ic_multiply,
+  ic_dissolve,
+  ic_add,
+  ic_subtract,
+  ic_diff,
+  ic_lighten,
+  ic_darken,
+  ic_hue,
+  ic_sat,
+  ic_value,
+  ic_color
+} i_combine_t;
+
+/*
+   describes an axis of a MM font.
+   Modelled on FT2's FT_MM_Axis.
+   It would be nice to have a default entry too, but FT2 
+   doesn't support it.
+*/
+typedef struct i_font_mm_axis_tag {
+  char const *name;
+  int minimum;
+  int maximum;
+} i_font_mm_axis;
+
+#define IM_FONT_MM_MAX_AXES 4
+
+/* 
+   multiple master information for a font, if any 
+   modelled on FT2's FT_Multi_Master.
+*/
+typedef struct i_font_mm_tag {
+  int num_axis;
+  int num_designs; /* provided but not necessarily useful */
+  i_font_mm_axis axis[IM_FONT_MM_MAX_AXES];
+} i_font_mm;
+
+#ifdef HAVE_LIBTT
+
+struct TT_Fonthandle_;
+
+typedef struct TT_Fonthandle_ TT_Fonthandle;
+
+#endif
+
+#ifdef HAVE_FT2
+
+typedef struct FT2_Fonthandle FT2_Fonthandle;
+
+#endif
+
+/* transparency handling for quantized output */
+typedef enum i_transp_tag {
+  tr_none, /* ignore any alpha channel */
+  tr_threshold, /* threshold the transparency - uses tr_threshold */
+  tr_errdiff, /* error diffusion */
+  tr_ordered /* an ordered dither */
+} i_transp;
+
+/* controls how we build the colour map */
+typedef enum i_make_colors_tag {
+  mc_none, /* user supplied colour map only */
+  mc_web_map, /* Use the 216 colour web colour map */
+  mc_addi, /* Addi's algorithm */
+  mc_median_cut, /* median cut - similar to giflib, hopefully */
+  mc_mask = 0xFF /* (mask for generator) */
+} i_make_colors;
+
+/* controls how we translate the colours */
+typedef enum i_translate_tag {
+  pt_giflib, /* get gif lib to do it (ignores make_colours) */
+  pt_closest, /* just use the closest match within the hashbox */
+  pt_perturb, /* randomly perturb the data - uses perturb_size*/
+  pt_errdiff /* error diffusion dither - uses errdiff */
+} i_translate;
+
+/* Which error diffusion map to use */
+typedef enum i_errdiff_tag {
+  ed_floyd, /* floyd-steinberg */
+  ed_jarvis, /* Jarvis, Judice and Ninke */
+  ed_stucki, /* Stucki */
+  ed_custom, /* the map found in ed_map|width|height|orig */
+  ed_mask = 0xFF, /* mask to get the map */
+  ed_bidir = 0x100 /* change direction for each row */
+} i_errdiff;
+
+/* which ordered dither map to use
+   currently only available for transparency
+   I don't know of a way to do ordered dither of an image against some 
+   general palette
+ */
+typedef enum i_ord_dith_tag
+{
+  od_random, /* sort of random */
+  od_dot8, /* large dot */
+  od_dot4,
+  od_hline,
+  od_vline,
+  od_slashline, /* / line dither */
+  od_backline, /* \ line dither */
+  od_tiny, /* small checkerbox */
+  od_custom /* custom 8x8 map */
+} i_ord_dith;
+
+typedef struct i_gif_pos_tag {
+  int x, y;
+} i_gif_pos;
+
+/* passed into i_writegif_gen() to control quantization */
+typedef struct i_quantize_tag {
+  /* how to handle transparency */
+  i_transp transp;
+  /* the threshold at which to make pixels opaque */
+  int tr_threshold;
+  i_errdiff tr_errdiff;
+  i_ord_dith tr_orddith;
+  unsigned char tr_custom[64];
+  
+  /* how to make the colour map */
+  i_make_colors make_colors;
+
+  /* any existing colours 
+     mc_existing is an existing colour table
+     mc_count is the number of existing colours
+     mc_size is the total size of the array that mc_existing points
+     at - this must be at least 256
+  */
+  i_color *mc_colors;
+  int mc_size;
+  int mc_count;
+
+  /* how we translate the colours */
+  i_translate translate;
+
+  /* the error diffusion map to use if translate is mc_errdiff */
+  i_errdiff errdiff;
+  /* the following define the error diffusion values to use if 
+     errdiff is ed_custom.  ed_orig is the column on the top row that
+     represents the current 
+  */
+  int *ed_map;
+  int ed_width, ed_height, ed_orig;
+
+  /* the amount of perturbation to use for translate is mc_perturb */
+  int perturb;
+} i_quantize;
+
+typedef struct i_gif_opts {
+  /* each image has a local color map */
+  int each_palette;
+
+  /* images are interlaced */
+  int interlace;
+
+  /* time for which image is displayed 
+   (in 1/100 seconds)
+   default: 0
+  */
+  int delay_count;
+  int *delays;
+
+  /* user input flags 
+     default: 0
+   */
+  int user_input_count;
+  char *user_input_flags;
+
+  /* disposal
+     default: 0 */
+  int disposal_count;
+  char *disposal;
+
+  /* this is added to the color table when we make an image transparent */
+  i_color tran_color;
+
+  /* image positions */
+  int position_count;
+  i_gif_pos *positions;
+
+  /* Netscape loop extension - number of loops */
+  int loop_count;
+
+  /* should be eliminate unused colors? */
+  int eliminate_unused;
+} i_gif_opts;
+
+
+
+#endif
+
index 6221ab3..70a2b16 100644 (file)
--- a/imexif.h
+++ b/imexif.h
@@ -1,9 +1,9 @@
 /* imexif.h - interface to Exif handling */
 #ifndef IMAGER_IMEXIF_H
-#define IMAGER_IMEXIT_H
+#define IMAGER_IMEXIF_H
 
 #include <stddef.h>
-#include "imagei.h"
+#include "imageri.h"
 
 extern int i_int_decode_exif(i_img *im, unsigned char *data, size_t length);
 
diff --git a/imext.c b/imext.c
new file mode 100644 (file)
index 0000000..fc7fce4
--- /dev/null
+++ b/imext.c
@@ -0,0 +1,454 @@
+#include "imexttypes.h"
+#include "imager.h"
+
+/*
+ DON'T ADD CASTS TO THESE
+*/
+im_ext_funcs imager_function_table =
+  {
+    mymalloc,
+    myfree,
+    myrealloc,
+
+    i_img_8_new,
+    i_img_16_new,
+    i_img_double_new,
+    i_img_pal_new,
+    i_img_destroy,
+    i_sametype,
+    i_sametype_chans,
+    i_img_info,
+
+    i_ppix,
+    i_gpix,
+    i_ppixf,
+    i_gpixf,
+    i_plin,
+    i_glin,
+    i_plinf,
+    i_glinf,
+    i_gsamp,
+    i_gsampf,
+    i_gpal,
+    i_ppal,
+    i_addcolors,
+    i_getcolors,
+    i_colorcount,
+    i_maxcolors,
+    i_findcolor,
+    i_setcolors,
+
+    i_new_fill_solid,
+    i_new_fill_solidf,
+    i_new_fill_hatch,
+    i_new_fill_hatchf,
+    i_new_fill_image,
+    i_new_fill_fount,
+    i_fill_destroy,
+
+    i_quant_makemap,
+    i_quant_translate,
+    i_quant_transparent,
+
+    i_clear_error,
+    i_push_error,
+    i_push_errorf,
+    i_push_errorvf,
+
+    i_tags_new,
+    i_tags_set,
+    i_tags_setn,
+    i_tags_destroy,
+    i_tags_find,
+    i_tags_findn,
+    i_tags_delete,
+    i_tags_delbyname,
+    i_tags_delbycode,
+    i_tags_get_float,
+    i_tags_set_float,
+    i_tags_set_float2,
+    i_tags_get_int,
+    i_tags_get_string,
+    i_tags_get_color,
+    i_tags_set_color,
+
+    i_box,
+    i_box_filled,
+    i_box_cfill,
+    i_line,
+    i_line_aa,
+    i_arc,
+    i_arc_aa,
+    i_arc_cfill,
+    i_arc_aa_cfill,
+    i_circle_aa,
+    i_flood_fill,
+    i_flood_cfill,
+
+    i_copyto,
+    i_copyto_trans,
+    i_copy,
+    i_rubthru,
+  };
+
+/* in general these functions aren't called by Imager internally, but
+   only via the pointers above, since faster macros that call the
+   image vtable pointers are used.
+
+   () are used around the function names to prevent macro replacement
+   on the function names.
+*/
+
+/*
+=item i_ppix(im, x, y, color)
+
+=category Drawing
+
+Sets the pixel at (x,y) to I<color>.
+
+Returns 0 if the pixel was drawn, or -1 if not.
+
+Does no alpha blending, just copies the channels from the supplied
+color to the image.
+
+=cut
+*/
+
+int 
+(i_ppix)(i_img *im,int x,int y,i_color *val) {
+  return i_ppix(im, x, y, val);
+}
+
+/*
+=item i_gpix(im, x, y, color)
+
+=category Drawing
+
+Retrieves the I<color> of the pixel (x,y).
+
+Returns 0 if the pixel was retrieved, or -1 if not.
+
+=cut
+*/
+
+int
+(i_gpix)(i_img *im,int x,int y,i_color *val) {
+  return i_gpix(im, x, y, val);
+}
+
+/*
+=item i_ppixf(im, x, y, fcolor)
+
+=category Drawing
+
+Sets the pixel at (x,y) to the floating point color I<fcolor>.
+
+Returns 0 if the pixel was drawn, or -1 if not.
+
+Does no alpha blending, just copies the channels from the supplied
+color to the image.
+
+=cut
+*/
+int
+(i_ppixf)(i_img *im,int x,int y,i_fcolor *val) {
+  return i_ppixf(im, x, y, val);
+}
+
+/*
+=item i_gpixf(im, x, y, fcolor)
+
+=category Drawing
+
+Retrieves the color of the pixel (x,y) as a floating point color into
+I<fcolor>.
+
+Returns 0 if the pixel was retrieved, or -1 if not.
+
+=cut
+*/
+
+int
+(i_gpixf)(i_img *im,int x,int y,i_fcolor *val) {
+  return i_gpixf(im, x, y, val);
+}
+
+/*
+=item i_plin(im, l, r, y, colors)
+
+=category Drawing
+
+Sets (r-l) pixels starting from (l,y) using (r-l) values from
+I<colors>.
+
+Returns the number of pixels set.
+
+=cut
+*/
+
+int
+(i_plin)(i_img *im, int l, int r, int y, i_color *vals) {
+  return i_plin(im, l, r, y, vals);
+}
+
+/*
+=item i_glin(im, l, r, y, colors)
+
+=category Drawing
+
+Retrieves (r-l) pixels starting from (l,y) into I<colors>.
+
+Returns the number of pixels retrieved.
+
+=cut
+*/
+
+int
+(i_glin)(i_img *im, int l, int r, int y, i_color *vals) {
+  return i_glin(im, l, r, y, vals);
+}
+
+/*
+=item i_plinf(im, l, r, fcolors)
+
+=category Drawing
+
+Sets (r-l) pixels starting from (l,y) using (r-l) floating point
+colors from I<colors>.
+
+Returns the number of pixels set.
+
+=cut
+*/
+
+int
+(i_plinf)(i_img *im, int l, int r, int y, i_fcolor *vals) {
+  return i_plinf(im, l, r, y, vals);
+}
+
+/*
+=item i_glinf(im, l, r, y, colors)
+
+=category Drawing
+
+Retrieves (r-l) pixels starting from (l,y) into I<colors> as floating
+point colors.
+
+Returns the number of pixels retrieved.
+
+=cut
+*/
+
+int
+(i_glinf)(i_img *im, int l, int r, int y, i_fcolor *vals) {
+  return i_glinf(im, l, r, y, vals);
+}
+
+/*
+=item i_gsamp(im, l, r, y, samp, chans, chan_count)
+
+=category Drawing
+
+Reads sample values from im for the horizontal line (l, y) to (r-1,y)
+for the channels specified by chans, an array of int with chan_count
+elements.
+
+If chans is NULL then the first chan_count channels are retrieved for
+each pixel.
+
+Returns the number of samples read (which should be (r-l) *
+chan_count)
+
+=cut
+*/
+int
+(i_gsamp)(i_img *im, int l, int r, int y, i_sample_t *samp, 
+                   const int *chans, int chan_count) {
+  return i_gsamp(im, l, r, y, samp, chans, chan_count);
+}
+
+/*
+=item i_gsampf(im, l, r, y, samp, chans, chan_count)
+
+=category Drawing
+
+Reads floating point sample values from im for the horizontal line (l,
+y) to (r-1,y) for the channels specified by chans, an array of int
+with chan_count elements.
+
+If chans is NULL then the first chan_count channels are retrieved for
+each pixel.
+
+Returns the number of samples read (which should be (r-l) *
+chan_count)
+
+=cut
+*/
+int
+(i_gsampf)(i_img *im, int l, int r, int y, i_fsample_t *samp, 
+           const int *chans, int chan_count) {
+  return i_gsampf(im, l, r, y, samp, chans, chan_count);
+}
+
+/*
+=item i_gpal(im, x, r, y, indexes)
+
+=category Drawing
+
+Reads palette indexes for the horizontal line (x, y) to (r-1, y) into
+indexes.
+
+Returns the number of indexes read.
+
+Always returns 0 for direct color images.
+
+=cut
+*/
+int
+(i_gpal)(i_img *im, int x, int r, int y, i_palidx *vals) {
+  return i_gpal(im, x, r, y, vals);
+}
+
+/*
+=item i_ppal(im, x, r, y, indexes)
+
+=category Drawing
+
+Writes palette indexes for the horizontal line (x, y) to (r-1, y) from
+indexes.
+
+Returns the number of indexes written.
+
+Always returns 0 for direct color images.
+
+=cut
+*/
+int
+(i_ppal)(i_img *im, int x, int r, int y, i_palidx *vals) {
+  return i_ppal(im, x, r, y, vals);
+}
+
+/*
+=item i_addcolors(im, colors, count)
+
+=category Paletted images
+
+Adds colors to the image's palette.
+
+On success returns the index of the lowest color added.
+
+On failure returns -1.
+
+Always fails for direct color images.
+
+=cut
+*/
+
+int
+(i_addcolors)(i_img *im, i_color *colors, int count) {
+  return i_addcolors(im, colors, count);
+}
+
+/*
+=item i_getcolors(im, index, colors, count)
+
+=category Paletted images
+
+Retrieves I<count> colors starting from I<index> in the image's
+palette.
+
+On success stores the colors into I<colors> and returns true.
+
+On failure returns false.
+
+Always fails for direct color images.
+
+Fails if there are less than I<index>+I<count> colors in the image's
+palette.
+
+=cut
+*/
+
+int
+(i_getcolors)(i_img *im, int i, i_color *colors, int count) {
+  return i_getcolors(im, i, colors, count);
+}
+
+/*
+=item i_colorcount(im)
+
+=category Paletted images
+
+Returns the number of colors in the image's palette.
+
+Returns -1 for direct images.
+
+=cut
+*/
+
+int
+(i_colorcount)(i_img *im) {
+  return i_colorcount(im);
+}
+
+/*
+=item i_maxcolors(im)
+
+=category Paletted images
+
+Returns the maximum number of colors the palette can hold for the
+image.
+
+Returns -1 for direct color images.
+
+=cut
+*/
+
+int
+(i_maxcolors)(i_img *im) {
+  return i_maxcolors(im);
+}
+
+/*
+=item i_findcolor(im, color, &entry)
+
+=category Paletted images
+
+Searches the images palette for the given color.
+
+On success sets *I<entry> to the index of the color, and returns true.
+
+On failure returns false.
+
+Always fails on direct color images.
+
+=cut
+*/
+int
+(i_findcolor)(i_img *im, i_color *color, i_palidx *entry) {
+  return i_findcolor(im, color, entry);
+}
+
+/*
+=item i_setcolors(im, index, colors, count)
+
+=category Paletted images
+
+Sets I<count> colors starting from I<index> in the image's palette.
+
+On sucess returns true.
+
+On failure returns false.
+
+The image must have at least I<index>+I<count> colors in it's palette
+for this to succeed.
+
+Always fails on direct color images.
+
+=cut
+*/
+int
+(i_setcolors)(i_img *im, int index, i_color *colors, int count) {
+  return i_setcolors(im, index, colors, count);
+}
+
diff --git a/imext.h b/imext.h
new file mode 100644 (file)
index 0000000..e5b7d98
--- /dev/null
+++ b/imext.h
@@ -0,0 +1,163 @@
+#ifndef IMAGER_IMEXT_H_
+#define IMAGER_IMEXT_H_
+
+#include "imexttypes.h"
+
+extern im_ext_funcs *imager_function_ext_table;
+
+#define DEFINE_IMAGER_CALLBACKS im_ext_funcs *imager_function_ext_table
+
+#define PERL_INITIALIZE_IMAGER_CALLBACKS \
+  imager_function_ext_table = INT2PTR(im_ext_funcs *, SvIV(get_sv(PERL_FUNCTION_TABLE_NAME, 1)))
+
+/* just for use here */
+#define im_extt imager_function_ext_table
+
+#define mymalloc(size) ((im_extt->f_mymalloc)(size))
+#define myfree(size) ((im_extt->f_myfree)(size))
+#define myrealloc(block, newsize) ((im_extt->f_myrealloc)((block), (newsize)))
+
+#define i_img_8_new(xsize, ysize, channels) ((im_extt->f_i_img_8_new)((xsize), (ysize), (channels)))
+#define i_img_16_new(xsize, ysize, channels) ((im_extt->f_i_img_16_new)((xsize), (ysize), (channels)))
+#define i_img_double_new(xsize, ysize, channels) ((im_extt->f_i_img_double_new)((xsize), (ysize), (channels)))
+#define i_img_pal_new(xsize, ysize, channels, maxpal) ((im_extt->f_i_img_pal_new)((xsize), (ysize), (channels), (maxpal)))
+
+#define i_img_destroy(im) ((im_extt->f_i_img_destroy)(im))
+#define i_sametype(im, xsize, ysize) ((im_extt->f_i_sametype)((im), (xsize), (ysize)))
+#define i_sametype_chans(im, xsize, ysize, channels) ((im_extt->f_i_sametype_chans)((im), (xsize), (ysize), (channels)))
+#define i_img_info(im, info) ((im_extt->f_i_img_info)((im), (info)))
+
+#ifndef IMAGER_DIRECT_IMAGE_CALLS
+#define IMAGER_DIRECT_IMAGE_CALLS 1
+#endif
+
+#if IMAGER_DIRECT_IMAGE_CALLS
+#define i_ppix(im, x, y, val) (((im)->i_f_ppix)((im), (x), (y), (val)))
+#define i_gpix(im, x, y, val) (((im)->i_f_gpix)((im), (x), (y), (val)))
+#define i_ppixf(im, x, y, val) (((im)->i_f_ppixf)((im), (x), (y), (val)))
+#define i_gpixf(im, x, y, val) (((im)->i_f_gpixf)((im), (x), (y), (val)))
+#define i_plin(im, l, r, y, val) (((im)->i_f_plin)(im, l, r, y, val))
+#define i_glin(im, l, r, y, val) (((im)->i_f_glin)(im, l, r, y, val))
+#define i_plinf(im, l, r, y, val) (((im)->i_f_plinf)(im, l, r, y, val))
+#define i_glinf(im, l, r, y, val) (((im)->i_f_glinf)(im, l, r, y, val))
+
+#define i_gsamp(im, l, r, y, samps, chans, count) \
+  (((im)->i_f_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
+#define i_gsampf(im, l, r, y, samps, chans, count) \
+  (((im)->i_f_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
+
+#define i_findcolor(im, color, entry) \
+  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
+
+#define i_gpal(im, l, r, y, vals) \
+  (((im)->i_f_gpal) ? ((im)->i_f_gpal)((im), (l), (r), (y), (vals)) : 0)
+#define i_ppal(im, l, r, y, vals) \
+  (((im)->i_f_ppal) ? ((im)->i_f_ppal)((im), (l), (r), (y), (vals)) : 0)
+#define i_addcolors(im, colors, count) \
+  (((im)->i_f_addcolors) ? ((im)->i_f_addcolors)((im), (colors), (count)) : -1)
+#define i_getcolors(im, index, color, count) \
+  (((im)->i_f_getcolors) ? \
+   ((im)->i_f_getcolors)((im), (index), (color), (count)) : 0)
+#define i_setcolors(im, index, color, count) \
+  (((im)->i_f_setcolors) ? \
+   ((im)->i_f_setcolors)((im), (index), (color), (count)) : 0)
+#define i_colorcount(im) \
+  (((im)->i_f_colorcount) ? ((im)->i_f_colorcount)(im) : -1)
+#define i_maxcolors(im) \
+  (((im)->i_f_maxcolors) ? ((im)->i_f_maxcolors)(im) : -1)
+#define i_findcolor(im, color, entry) \
+  (((im)->i_f_findcolor) ? ((im)->i_f_findcolor)((im), (color), (entry)) : 0)
+#else
+#define i_ppix(im, x, y, val) ((im_extt->f_i_ppix)((im), (x), (y), (val)))
+#define i_gpix(im, x, y, val) ((im_extt->f_i_gpix)((im), (x), (y), (val)))
+#define i_ppixf(im, x, y, val) ((im_extt->f_i_ppixf)((im), (x), (y), (val)))
+#define i_gpixf(im, x, y, val) ((im_extt->f_i_gpixf)((im), (x), (y), (val)))
+#define i_plin(im, l, r, y, val) ((im_extt->f_i_plin)((im), (l), (r), (y), (val)))
+#define i_glin(im, l, r, y, val) ((im_extt->f_i_glin)((im), (l), (r), (y), (val)))
+#define i_plinf(im, l, r, y, val) ((im_extt->f_i_plinf)((im), (l), (r), (y), (val)))
+#define i_glinf(im, l, r, y, val) ((im_extt->f_i_glinf)((im), (l), (r), (y), (val)))
+#define i_gsamp(im, l, r, y, samps, chans, count) \
+  ((im_extt->f_i_gsamp)((im), (l), (r), (y), (samps), (chans), (count)))
+#define i_gsampf(im, l, r, y, samps, chans, count) \
+  ((im_extt->f_i_gsampf)((im), (l), (r), (y), (samps), (chans), (count)))
+
+#endif
+
+#define i_new_fill_solid(c, combine) ((im_extt->f_i_new_fill_solid)((c), (combine)))
+#define i_new_fill_solidf(c, combine) ((im_extt->f_i_new_fill_solidf)((c), (combine)))
+#define i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy) \
+  ((im_extt->f_i_new_fill_hatch)((fg), (bg), (combine), (hatch), (cust_hatch), (dx), (dy)))
+#define i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy) \
+  ((im_extt->f_i_new_fill_hatchf)((fg), (bg), (combine), (hatch), (cust_hatch), (dx), (dy)))
+#define i_new_fill_image(im, matrix, xoff, yoff, combine) \
+  ((im_extt->f_i_new_fill_image)((im), (matrix), (xoff), (yoff), (combine)))
+#define i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs) \
+  ((im_extt->f_i_new_fill_fount)((xa), (ya), (xb), (yb), (type), (repeat), (combine), (super_sample), (ssample_param), (count), (segs)))
+#define i_fill_destroy(fill) ((im_extt->f_i_fill_destroy)(fill))
+
+#define i_quant_makemap(quant, imgs, count) \
+  ((im_extt->f_i_quant_makemap)((quant), (imgs), (count)))
+#define i_quant_translate(quant, img) \
+  ((im_extt->f_i_quant_translate)((quant), (img)))
+#define i_quant_transparent(quant, indices, img, trans_index) \
+  ((im_extt->f_i_quant_transparent)((quant), (indices), (img), (trans_index)))
+
+#define i_clear_error() ((im_extt->f_i_clear_error)())
+#define i_push_error(code, msg) ((im_extt->f_i_push_error)((code), (msg)))
+#define i_push_errorf (im_extt->f_i_push_errorf)
+#define i_push_errorvf(code, fmt, list) \
+  ((im_extt->f_i_push_errorvf)((code), (fmt), (list)))
+
+#define i_tags_new(tags) ((im_extt->f_i_tags_new)(tags))
+#define i_tags_set(tags, name, data, size) \
+  ((im_extt->f_i_tags_set)((tags), (name), (data), (size)))
+#define i_tags_setn(tags, name, idata) \
+  ((im_extt->f_i_tags_setn)((tags), (name), (idata)))
+#define i_tags_destroy(tags) ((im_extt->f_i_tags_destroy)(tags))
+#define i_tags_find(tags, name, start, entry) \
+  ((im_extt->f_i_tags_find)((tags), (name), (start), (entry)))
+#define i_tags_findn(tags, code, start, entry) \
+  ((im_extt->f_i_tags_findn)((tags), (code), (start), (entry)))
+#define i_tags_delete(tags, entry) \
+  ((im_extt->f_i_tags_delete)((tags), (entry)))
+#define i_tags_delbyname(tags, name) \
+  ((im_extt->f_i_tags_delbyname)((tags), (name)))
+#define i_tags_delbycode(tags, code) \
+  ((im_extt->f_i_tags_delbycode)((tags), (code)))
+#define i_tags_get_float(tags, name, code, value) \
+  ((im_extt->f_i_tags_get_float)((tags), (name), (code), (value)))
+#define i_tags_set_float(tags, name, code, value) \
+  ((im_extt->f_i_tags_set_float)((tags), (name), (code), (value)))
+#define i_tags_set_float2(tags, name, code, value, places) \
+  ((im_extt->f_i_tags_set_float2)((tags), (name), (code), (value), (places)))
+#define i_tags_get_int(tags, name, code, value) \
+  ((im_extt->f_i_tags_get_int)((tags), (name), (code), (value)))
+#define i_tags_get_string(tags, name, code, value, value_size) \
+  ((im_extt->f_i_tags_get_string)((tags), (name), (code), (value), (value_size)))
+#define i_tags_get_color(tags, name, code, value) \
+  ((im_extt->f_i_tags_get_color)((tags), (name), (code), (value)))
+#define i_tags_set_color(tags, name, code, value) \
+  ((im_extt->f_i_tags_set_color)((tags), (name), (code), (value)))
+
+#define i_box(im, x1, y1, x2, y2, val) ((im_extt->f_i_box)((im), (x1), (y1), (x2), (y2), (val)))
+#define i_box_filled(im, x1, y1, x2, y2, val) ((im_extt->f_i_box_filled)((im), (x1), (y1), (x2), (y2), (val)))
+#define i_box_cfill(im, x1, y1, x2, y2, fill) ((im_extt->f_i_box_cfill)((im), (x1), (y1), (x2), (y2), (fill)))
+#define i_line(im, x1, y1, x2, y2, val, endp) ((im_extt->f_i_line)((im), (x1), (y1), (x2), (y2), (val), (endp)))
+#define i_line_aa(im, x1, y1, x2, y2, val, endp) ((im_extt->f_i_line_aa)((im), (x1), (y1), (x2), (y2), (val), (endp)))
+#define i_arc(im, x, y, rad, d1, d2, val) ((im_extt->f_i_arc)((im), (x), (y), (rad), (d1), (d2), (val)))
+#define i_arc_aa(im, x, y, rad, d1, d2, val) ((im_extt->f_i_arc_aa)((im), (x), (y), (rad), (d1), (d2), (val)))
+#define i_arc_cfill(im, x, y, rad, d1, d2, fill) ((im_extt->f_i_arc_cfill)((im), (x), (y), (rad), (d1), (d2), (fill)))
+#define i_arc_aa_cfill(im, x, y, rad, d1, d2, fill) ((im_extt->f_i_arc_aa_cfill)((im), (x), (y), (rad), (d1), (d2), (fill)))
+#define i_circle_aa(im, x, y, rad, val) ((im_extt->f_i_circle_aa)((im), (x), (y), (rad), (val)))
+#define i_flood_fill(im, seedx, seedy, dcol) ((im_extt->f_i_flood_fill)((im), (seedx), (seedy), (dcol)))
+#define i_flood_cfill(im, seedx, seedy, fill) ((im_extt->f_i_flood_cfill)((im), (seedx), (seedy), (fill)))
+
+#define i_copyto(im, src, x1, y1, x2, y2, tx, ty) \
+  ((im_extt->f_i_copyto)((im), (src), (x1), (y1), (x2), (y2), (tx), (ty)))
+#define i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans) \
+  ((im_extt->f_i_copyto_trans)((im), (src), (x1), (y1), (x2), (y2), (tx), (ty), (trans)))
+#define i_copy(im) ((im_extt->f_i_copy)(im))
+#define i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy) \
+  ((im_extt->f_i_rubthru)((im), (src), (tx), (ty), (src_minx), (src_miny), (src_maxx), (src_maxy)))
+
+#endif
diff --git a/imextdef.h b/imextdef.h
new file mode 100644 (file)
index 0000000..d1c5f50
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef IMAGER_IMEXTDEF_H
+#define IMAGER_IMEXTDEF_H
+
+#include "imexttypes.h"
+
+extern im_ext_funcs imager_function_table;
+
+#define PERL_SET_GLOBAL_CALLBACKS \
+  sv_setiv(get_sv(PERL_FUNCTION_TABLE_NAME, 1), PTR2IV(&imager_function_table));
+
+#endif
diff --git a/imexttypes.h b/imexttypes.h
new file mode 100644 (file)
index 0000000..4c4c559
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef IMAGER_IMEXTTYPES_H_
+#define IMAGER_IMEXTTYPES_H_
+
+/* keep this file simple - apidocs.perl parses it. */
+
+#include "imdatatypes.h"
+
+typedef struct {
+  void * (*f_mymalloc)(int size);
+  void (*f_myfree)(void *block);
+  void * (*f_myrealloc)(void *block, size_t newsize);
+
+  i_img *(*f_i_img_8_new)(int xsize, int ysize, int channels);
+  i_img *(*f_i_img_16_new)(int xsize, int ysize, int channels);
+  i_img *(*f_i_img_double_new)(int xsize, int ysize, int channels);
+  i_img *(*f_i_img_pal_new)(int xsize, int ysize, int channels, int maxpal);
+  void (*f_i_img_destroy)(i_img *im);
+  i_img *(*f_i_sametype)(i_img *im, int xsize, int ysize);
+  i_img *(*f_i_sametype_chans)(i_img *im, int xsize, int ysize, int channels);
+  void (*f_i_img_info)(i_img *im, int *info);
+
+  int (*f_i_ppix)(i_img *im, int x, int y, i_color *val);
+  int (*f_i_gpix)(i_img *im, int x, int y, i_color *val);
+  int (*f_i_ppixf)(i_img *im, int x, int y, i_fcolor *val);
+  int (*f_i_gpixf)(i_img *im, int x, int y, i_fcolor *val);
+  int (*f_i_plin)(i_img *im, int l, int r, int y, i_color *vals);
+  int (*f_i_glin)(i_img *im, int l, int r, int y, i_color *vals);
+  int (*f_i_plinf)(i_img *im, int l, int r, int y, i_fcolor *vals);
+  int (*f_i_glinf)(i_img *im, int l, int r, int y, i_fcolor *vals);
+  int (*f_i_gsamp)(i_img *im, int l, int r, int y, i_sample_t *samp, 
+                   const int *chans, int chan_count);
+  int (*f_i_gsampf)(i_img *im, int l, int r, int y, i_fsample_t *samp, 
+                   const int *chans, int chan_count);
+  int (*f_i_gpal)(i_img *im, int x, int r, int y, i_palidx *vals);
+  int (*f_i_ppal)(i_img *im, int x, int r, int y, i_palidx *vals);
+  int (*f_i_addcolors)(i_img *im, i_color *colors, int count);
+  int (*f_i_getcolors)(i_img *im, int i, i_color *, int count);
+  int (*f_i_colorcount)(i_img *im);
+  int (*f_i_maxcolors)(i_img *im);
+  int (*f_i_findcolor)(i_img *im, i_color *color, i_palidx *entry);
+  int (*f_i_setcolors)(i_img *im, int index, i_color *colors, 
+                       int count);
+
+  i_fill_t *(*f_i_new_fill_solid)(i_color *c, int combine);
+  i_fill_t *(*f_i_new_fill_solidf)(i_fcolor *c, int combine);
+
+  i_fill_t *(*f_i_new_fill_hatch)(i_color *fg, i_color *bg, int combine, 
+                                  int hatch, unsigned char *cust_hatch, 
+                                  int dx, int dy);
+  i_fill_t *(*f_i_new_fill_hatchf)(i_fcolor *fg, i_fcolor *bg, int combine, 
+                                  int hatch, unsigned char *cust_hatch, 
+                                  int dx, int dy);
+  i_fill_t *(*f_i_new_fill_image)(i_img *im, double *matrix, int xoff, 
+                                int yoff, int combine);
+  i_fill_t *(*f_i_new_fill_fount)(double xa, double ya, double xb, double yb, 
+                 i_fountain_type type, i_fountain_repeat repeat, 
+                 int combine, int super_sample, double ssample_param, 
+                 int count, i_fountain_seg *segs);  
+
+  void (*f_i_fill_destroy)(i_fill_t *fill);
+
+  void (*f_i_quant_makemap)(i_quantize *quant, i_img **imgs, int count);
+  i_palidx * (*f_i_quant_translate)(i_quantize *quant, i_img *img);
+  void (*f_i_quant_transparent)(i_quantize *quant, i_palidx *indices, 
+                                i_img *img, i_palidx trans_index);
+
+  void (*f_i_clear_error)(void);
+  void (*f_i_push_error)(int code, char const *msg);
+  void (*f_i_push_errorf)(int code, char const *fmt, ...);
+  void (*f_i_push_errorvf)(int code, char const *fmt, va_list);
+  
+  void (*f_i_tags_new)(i_img_tags *tags);
+  int (*f_i_tags_set)(i_img_tags *tags, char const *name, char const *data, 
+                      int size);
+  int (*f_i_tags_setn)(i_img_tags *tags, char const *name, int idata);
+  void (*f_i_tags_destroy)(i_img_tags *tags);
+  int (*f_i_tags_find)(i_img_tags *tags, char const *name, int start, 
+                       int *entry);
+  int (*f_i_tags_findn)(i_img_tags *tags, int code, int start, int *entry);
+  int (*f_i_tags_delete)(i_img_tags *tags, int entry);
+  int (*f_i_tags_delbyname)(i_img_tags *tags, char const *name);
+  int (*f_i_tags_delbycode)(i_img_tags *tags, int code);
+  int (*f_i_tags_get_float)(i_img_tags *tags, char const *name, int code, 
+                            double *value);
+  int (*f_i_tags_set_float)(i_img_tags *tags, char const *name, int code, 
+                            double value);
+  int (*f_i_tags_set_float2)(i_img_tags *tags, char const *name, int code,
+                             double value, int places);
+  int (*f_i_tags_get_int)(i_img_tags *tags, char const *name, int code, 
+                          int *value);
+  int (*f_i_tags_get_string)(i_img_tags *tags, char const *name, int code,
+                             char *value, size_t value_size);
+  int (*f_i_tags_get_color)(i_img_tags *tags, char const *name, int code,
+                            i_color *value);
+  int (*f_i_tags_set_color)(i_img_tags *tags, char const *name, int code,
+                            i_color const *value);
+
+  void (*f_i_box)(i_img *im, int x1, int y1, int x2, int y2, i_color *val);
+  void (*f_i_box_filled)(i_img *im, int x1, int y1, int x2, int y2, i_color *val);
+  void (*f_i_box_cfill)(i_img *im, int x1, int y1, int x2, int y2, i_fill_t *fill);
+  void (*f_i_line)(i_img *im, int x1, int y1, int x2, int y2, i_color *val, int endp);
+  void (*f_i_line_aa)(i_img *im, int x1, int y1, int x2, int y2, i_color *val, int endp);
+  void (*f_i_arc)(i_img *im, int x, int y, float rad, float d1, float d2, i_color *val);
+  void (*f_i_arc_aa)(i_img *im, double x, double y, double rad, double d1, double d2, i_color *val);
+  void (*f_i_arc_cfill)(i_img *im, int x, int y, float rad, float d1, float d2, i_fill_t *val);
+  void (*f_i_arc_aa_cfill)(i_img *im, double x, double y, double rad, double d1, double d2, i_fill_t *fill);
+  void (*f_i_circle_aa)(i_img *im, float x, float y, float rad, i_color *val);
+  int (*f_i_flood_fill)(i_img *im, int seedx, int seedy, i_color *dcol);
+  int (*f_i_flood_cfill)(i_img *im, int seedx, int seedy, i_fill_t *fill);
+
+  void (*f_i_copyto)(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty);
+  void (*f_i_copyto_trans)(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty, i_color *trans);
+  i_img *(*f_i_copy)(i_img *im);
+  int (*f_i_rubthru)(i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny, int src_maxx, int src_maxy);
+} im_ext_funcs;
+
+#define PERL_FUNCTION_TABLE_NAME "Imager::__ext_func_table"
+
+#endif
diff --git a/img16.c b/img16.c
index 5db8172..af477ce 100644 (file)
--- a/img16.c
+++ b/img16.c
@@ -20,8 +20,8 @@ sample image type to work with.
 =cut
 */
 
-#include "image.h"
-#include "imagei.h"
+#include "imager.h"
+#include "imageri.h"
 
 static int i_ppix_d16(i_img *im, int x, int y, i_color *val);
 static int i_gpix_d16(i_img *im, int x, int y, i_color *val);
@@ -136,7 +136,7 @@ typedef unsigned short i_sample16_t;
 #endif
 
 /*
-=item i_img_16_new(int x, int y, int ch)
+=item i_img_16_new_low(int x, int y, int ch)
 
 Creates a new 16-bit per sample image.
 
@@ -188,6 +188,18 @@ i_img *i_img_16_new_low(i_img *im, int x, int y, int ch) {
   return im;
 }
 
+/*
+=item i_img_16_new(x, y, ch)
+
+=category Image creation
+
+Create a new 16-bit/sample image.
+
+Returns the image on success, or NULL on failure.
+
+=cut
+*/
+
 i_img *i_img_16_new(int x, int y, int ch) {
   i_img *im;
   
index 5f063a6..21d0b4c 100644 (file)
@@ -20,8 +20,8 @@ sample image type to work with.
 =cut
 */
 
-#include "image.h"
-#include "imagei.h"
+#include "imager.h"
+#include "imageri.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);
@@ -81,6 +81,8 @@ static i_img IIM_base_double_direct =
 /*
 =item i_img_double_new(int x, int y, int ch)
 
+=category Image creation
+
 Creates a new double per sample image.
 
 =cut
diff --git a/imperl.h b/imperl.h
new file mode 100644 (file)
index 0000000..93db837
--- /dev/null
+++ b/imperl.h
@@ -0,0 +1,33 @@
+/*
+  This header file defines types that Imager's typemap uses to convert to
+  perl types.
+
+  This is meant for use in XS code, not in normal C source.
+ */
+#ifndef IMAGER_IMPERL_H
+#define IMAGER_IMPERL_H
+
+#include "imdatatypes.h"
+
+typedef i_color* Imager__Color;
+typedef i_fcolor* Imager__Color__Float;
+typedef i_img*   Imager__ImgRaw;
+typedef int undef_neg_int;
+typedef i_img * Imager;
+
+#ifdef HAVE_LIBTT
+typedef TT_Fonthandle* Imager__Font__TT;
+#endif
+
+#ifdef HAVE_FT2
+typedef FT2_Fonthandle* Imager__Font__FT2;
+#endif
+
+/* for the fill objects
+   Since a fill object may later have dependent images, (or fills!)
+   we need perl wrappers - oh well
+*/
+#define IFILL_DESTROY(fill) i_fill_destroy(fill);
+typedef i_fill_t* Imager__FillHandle;
+
+#endif
diff --git a/jpeg.c b/jpeg.c
index 1ba75ac..42535d5 100644 (file)
--- a/jpeg.c
+++ b/jpeg.c
@@ -28,7 +28,7 @@ Reads and writes JPEG images
 #include <setjmp.h>
 
 #include "iolayer.h"
-#include "imagei.h"
+#include "imageri.h"
 #include "jpeglib.h"
 #include "jerror.h"
 #include <errno.h>
diff --git a/lib/Imager/API.pm b/lib/Imager/API.pm
new file mode 100644 (file)
index 0000000..acb6397
--- /dev/null
@@ -0,0 +1,211 @@
+=head1 NAME
+
+Imager::API - Imager's C API - introduction.
+
+=head1 SYNOPSIS
+
+  #include "imext.h"
+  #include "imperl.h"
+
+  DEFINE_IMAGER_CALLBACKS;
+
+  MODULE = Your::Module  PACKAGE = Your::Module
+
+  ...
+
+  BOOT:
+    PERL_INITIALIZE_IMAGER_CALLBACKS;
+  
+
+=head1 DESCRIPTION
+
+The API allows you to access Imager functions at the C level from XS
+and from Inline::C.
+
+The intent is to allow users to:
+
+=over
+
+=item *
+
+write C code that does Imager operations the user might do from Perl,
+but faster, for example, the Imager::CountColor example.
+
+=item *
+
+write C code that implements an application specific version of some
+core Imager object, for example, Imager::SDL.
+
+=item *
+
+write C code that hooks into Imagers existing methods, such as filter
+or file format handlers.
+
+=back
+
+See L<Imager::Inline> for information on using Imager's Inline::C
+support.
+
+=head1 Types
+
+The API makes the following types visible:
+
+=over
+
+=item *
+
+i_img - used to represent an image
+
+=item *
+
+i_color - used to represent a color with up to 8 bits per sample.
+
+=item *
+
+i_fcolor - used to represent a color with a double per sample.
+
+=item *
+
+i_fill_t - an abstract fill
+
+=back
+
+At this point there is no consolidated font object type, and hence the
+font functions are not visible through Imager's API.
+
+=head2 i_img - images
+
+This contains the dimensions of the image (xsize, ysize, channels),
+image metadata (ch_mask, bits, type, virtual), potentially image data
+(idata) and the a function table, with pointers to functions to
+perform various low level image operations.
+
+The only time you should directly write to any value in this type is
+if you're implementing your own image type.
+
+=head2 i_color - 8-bit color
+
+Represents an 8-bit per sample color.  This is a union containing
+several different structs for access to components of a color:
+
+=over
+
+=item *
+
+gray - single member gray_color.
+
+=item *
+
+rgb - r, g, b members.
+
+=item *
+
+rgba - r, g, b, a members.
+
+=item *
+
+channels - array of channels.
+
+=back
+
+=head2 i_fcolor - floating point color
+
+Similar to i_fcolor except that each component is a double instead of
+an unsigned char.
+
+=head2 i_fill_t - fill objects
+
+Abstract type containing pointers called to perform low level fill
+operations.
+
+Unless you're defining your own fill objects you should treat this as
+an opaque type.
+
+=head1 Create an XS module using the Imager API
+
+=head2 Foo.xs
+
+You'll need the following in your XS source:
+
+=over
+
+=item *
+
+include the Imager external API header, and the perl interface header:
+
+  #include "imext.h"
+  #include "imperl.h"
+
+=item *
+
+create the variables used to hold the callback table:
+
+  DEFINE_IMAGER_CALLBACKS;
+
+=item *
+
+initialize the callback table in your BOOT code:
+
+  BOOT:
+    PERL_INITIALIZE_IMAGER_CALLBACKS;
+
+=back
+
+=head2 foo.c
+
+In any other source files where you want to access the Imager API,
+you'll need to:
+
+=over
+
+=item *
+
+include the Imager external API header:
+
+  #include "imext.h"
+
+=back
+
+=head2 Makefile.PL
+
+If you're creating an XS module that depends on Imager's API your
+Makefile.PL will need to do the following:
+
+=over
+
+=item *
+
+C<use Imager::ExtUtils;>
+
+=item *
+
+include Imager's include directory in INC:
+
+  INC => Imager::ExtUtils->includes
+
+=item *
+
+use Imager's typemap:
+
+  TYPEMAPS => [ Imager::ExtUtils->typemap ]
+
+=item *
+
+include Imager 0.48 as a PREREQ_PM:
+
+   PREREQ_PM =>
+   {
+    Imager => 0.48,
+   },
+
+=back
+
+=head1 AUTHOR
+
+Tony Cook <tony@imager.perl.org>
+
+=head1 SEE ALSO
+
+Imager, Imager::ExtUtils, Imager::APIRef, Imager::Inline
+
+=cut
diff --git a/lib/Imager/APIRef.pm b/lib/Imager/APIRef.pm
new file mode 100644 (file)
index 0000000..1abc984
--- /dev/null
@@ -0,0 +1,1007 @@
+Do not edit this file, it is generated automatically by apidocs.perl
+from Imager's source files.
+
+Each function description has a comment listing the source file and
+line number where you can find the documentation.
+
+=head1 NAME
+
+Imager::APIRef - Imager's C API.
+
+=head1 SYNOPSIS
+
+  i_color color;
+  color.rgba.red = 255; color.rgba.green = 0; color.rgba.blue = 255;
+  i_fill_t *fill = i_new_fill_...(...);
+
+
+  # Drawing
+  i_arc(im, 50, 50, 20, 45, 135, &color);
+  i_arc_aa(im, 50, 50, 35, 90, 135, &color);
+  i_arc_aa_cfill(im, 50, 50, 35, 90, 135, fill);
+  i_arc_cfill(im, 50, 50, 35, 90, 135, fill);
+  i_box(im, 0, 0, im->xsize-1, im->ysize-1, &color).
+  i_box_cfill(im, 0, 0, im->xsize-1, im->ysize-1, fill);
+  i_box_filled(im, 0, 0, im->xsize-1, im->ysize-1, &color);
+  i_circle_aa(im, 50, 50, 45, &color);
+  i_flood_cfill(im, 50, 50, fill);
+  i_flood_fill(im, 50, 50, &color);
+
+  # Error handling
+
+  # Fills
+  fill = i_new_fill_fount(0, 0, 100, 100, i_ft_linear, i_ft_linear, 
+                          i_fr_triangle, 0, i_fts_grid, 9, 1, segs);
+
+  # Image
+
+  # Image creation
+
+  # Image quantization
+
+  # Paletted images
+
+  # Tags
+
+   i_fill_destroy(fill);
+
+=head1 DESCRIPTION
+
+=head2 Drawing
+
+=over
+
+=item i_arc(im, x, y, rad, d1, d2, color)
+
+
+Fills an arc centered at (x,y) with radius I<rad> covering the range
+of angles in degrees from d1 to d2, with the color.
+
+
+=for comment
+From: Line 205 in draw.c
+
+=item i_arc_aa(im, x, y, rad, d1, d2, color)
+
+
+Antialias fills an arc centered at (x,y) with radius I<rad> covering
+the range of angles in degrees from d1 to d2, with the color.
+
+
+=for comment
+From: Line 329 in draw.c
+
+=item i_arc_aa_cfill(im, x, y, rad, d1, d2, fill)
+
+
+Antialias fills an arc centered at (x,y) with radius I<rad> covering
+the range of angles in degrees from d1 to d2, with the fill object.
+
+
+=for comment
+From: Line 355 in draw.c
+
+=item i_arc_cfill(im, x, y, rad, d1, d2, fill)
+
+
+Fills an arc centered at (x,y) with radius I<rad> covering the range
+of angles in degrees from d1 to d2, with the fill object.
+
+
+=for comment
+From: Line 230 in draw.c
+
+=item i_box(im, x1, y1, x2, y2, color)
+
+
+Outlines the box from (x1,y1) to (x2,y2) inclusive with I<color>.
+
+
+=for comment
+From: Line 531 in draw.c
+
+=item i_box_cfill(im, x1, y1, x2, y2, fill)
+
+
+Fills the box from (x1,y1) to (x2,y2) inclusive with fill.
+
+
+=for comment
+From: Line 574 in draw.c
+
+=item i_box_filled(im, x1, y1, x2, y2, color)
+
+
+Fills the box from (x1,y1) to (x2,y2) inclusive with color.
+
+
+=for comment
+From: Line 556 in draw.c
+
+=item i_circle_aa(im, x, y, rad, color)
+
+
+Antialias fills a circle centered at (x,y) for radius I<rad> with
+color.
+
+
+=for comment
+From: Line 477 in draw.c
+
+=item i_flood_cfill(im, seedx, seedy, fill)
+
+
+Flood fills the 4-connected region starting from the point (seedx,
+seedy) with I<fill>.
+
+Returns false if (seedx, seedy) are outside the image.
+
+
+=for comment
+From: Line 1332 in draw.c
+
+=item i_flood_fill(im, seedx, seedy, color)
+
+
+Flood fills the 4-connected region starting from the point (seedx,
+seedy) with I<color>.
+
+Returns false if (seedx, seedy) are outside the image.
+
+
+=for comment
+From: Line 1295 in draw.c
+
+=item i_glin(im, l, r, y, colors)
+
+
+Retrieves (r-l) pixels starting from (l,y) into I<colors>.
+
+Returns the number of pixels retrieved.
+
+
+=for comment
+From: Line 195 in imext.c
+
+=item i_glinf(im, l, r, y, colors)
+
+
+Retrieves (r-l) pixels starting from (l,y) into I<colors> as floating
+point colors.
+
+Returns the number of pixels retrieved.
+
+
+=for comment
+From: Line 230 in imext.c
+
+=item i_gpal(im, x, r, y, indexes)
+
+
+Reads palette indexes for the horizontal line (x, y) to (r-1, y) into
+indexes.
+
+Returns the number of indexes read.
+
+Always returns 0 for direct color images.
+
+
+=for comment
+From: Line 294 in imext.c
+
+=item i_gpix(im, x, y, color)
+
+
+Retrieves the I<color> of the pixel (x,y).
+
+Returns 0 if the pixel was retrieved, or -1 if not.
+
+
+=for comment
+From: Line 123 in imext.c
+
+=item i_gpixf(im, x, y, fcolor)
+
+
+Retrieves the color of the pixel (x,y) as a floating point color into
+I<fcolor>.
+
+Returns 0 if the pixel was retrieved, or -1 if not.
+
+
+=for comment
+From: Line 159 in imext.c
+
+=item i_gsamp(im, l, r, y, samp, chans, chan_count)
+
+
+Reads sample values from im for the horizontal line (l, y) to (r-1,y)
+for the channels specified by chans, an array of int with chan_count
+elements.
+
+If chans is NULL then the first chan_count channels are retrieved for
+each pixel.
+
+Returns the number of samples read (which should be (r-l) *
+chan_count)
+
+
+=for comment
+From: Line 248 in imext.c
+
+=item i_gsampf(im, l, r, y, samp, chans, chan_count)
+
+
+Reads floating point sample values from im for the horizontal line (l,
+y) to (r-1,y) for the channels specified by chans, an array of int
+with chan_count elements.
+
+If chans is NULL then the first chan_count channels are retrieved for
+each pixel.
+
+Returns the number of samples read (which should be (r-l) *
+chan_count)
+
+
+=for comment
+From: Line 271 in imext.c
+
+=item i_line(im, x1, y1, x2, y2, val, endp)
+
+
+Draw a line to image using bresenhams linedrawing algorithm
+
+   im   - image to draw to
+   x1   - starting x coordinate
+   y1   - starting x coordinate
+   x2   - starting x coordinate
+   y2   - starting x coordinate
+   val  - color to write to image
+   endp - endpoint flag (boolean)
+
+
+=for comment
+From: Line 645 in draw.c
+
+=item i_line_aa(im, x1, x2, y1, y2, color, endp)
+
+
+Antialias draws a line from (x1,y1) to (x2, y2) in color.
+
+The point (x2, y2) is drawn only if endp is set.
+
+
+=for comment
+From: Line 849 in draw.c
+
+=item i_plin(im, l, r, y, colors)
+
+
+Sets (r-l) pixels starting from (l,y) using (r-l) values from
+I<colors>.
+
+Returns the number of pixels set.
+
+
+=for comment
+From: Line 177 in imext.c
+
+=item i_plinf(im, l, r, fcolors)
+
+
+Sets (r-l) pixels starting from (l,y) using (r-l) floating point
+colors from I<colors>.
+
+Returns the number of pixels set.
+
+
+=for comment
+From: Line 212 in imext.c
+
+=item i_ppal(im, x, r, y, indexes)
+
+
+Writes palette indexes for the horizontal line (x, y) to (r-1, y) from
+indexes.
+
+Returns the number of indexes written.
+
+Always returns 0 for direct color images.
+
+
+=for comment
+From: Line 313 in imext.c
+
+=item i_ppix(im, x, y, color)
+
+
+Sets the pixel at (x,y) to I<color>.
+
+Returns 0 if the pixel was drawn, or -1 if not.
+
+Does no alpha blending, just copies the channels from the supplied
+color to the image.
+
+
+=for comment
+From: Line 103 in imext.c
+
+=item i_ppixf(im, x, y, fcolor)
+
+
+Sets the pixel at (x,y) to the floating point color I<fcolor>.
+
+Returns 0 if the pixel was drawn, or -1 if not.
+
+Does no alpha blending, just copies the channels from the supplied
+color to the image.
+
+
+=for comment
+From: Line 140 in imext.c
+
+
+=back
+
+=head2 Error handling
+
+=over
+
+=item i_clear_error()
+
+
+Clears the error stack.
+
+Called by any imager function before doing any other processing.
+
+
+=for comment
+From: Line 185 in error.c
+
+=item i_push_error(int code, char const *msg)
+
+
+Called by an imager function to push an error message onto the stack.
+
+No message is pushed if the stack is full (since this means someone
+forgot to call i_clear_error(), or that a function that doesn't do
+error handling is calling function that does.).
+
+
+=for comment
+From: Line 211 in error.c
+
+=item i_push_errorf(int code, char const *fmt, ...)
+
+
+A version of i_push_error() that does printf() like formating.
+
+
+=for comment
+From: Line 273 in error.c
+
+=item i_push_errorvf(int code, char const *fmt, va_list ap)
+
+
+Intended for use by higher level functions, takes a varargs pointer
+and a format to produce the finally pushed error message.
+
+
+=for comment
+From: Line 249 in error.c
+
+
+=back
+
+=head2 Fills
+
+=over
+
+=item i_fill_destroy(fill)
+
+
+Call to destroy any fill object.
+
+
+=for comment
+From: Line 196 in fills.c
+
+=item i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs)
+
+
+
+Creates a new general fill which fills with a fountain fill.
+
+
+=for comment
+From: Line 1666 in filters.c
+
+=item i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
+
+
+Creates a new hatched fill with the fg color used for the 1 bits in
+the hatch and bg for the 0 bits.  If combine is non-zero alpha values
+will be combined.
+
+If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
+hash definition, with the high-bits to the left.
+
+If cust_hatch is NULL then one of the standard hatches is used.
+
+(dx, dy) are an offset into the hatch which can be used to unalign adjoining areas, or to align the origin of a hatch with the the side of a filled area.
+
+
+=for comment
+From: Line 427 in fills.c
+
+=item i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
+
+
+Creates a new hatched fill with the fg color used for the 1 bits in
+the hatch and bg for the 0 bits.  If combine is non-zero alpha values
+will be combined.
+
+If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
+hash definition, with the high-bits to the left.
+
+If cust_hatch is NULL then one of the standard hatches is used.
+
+(dx, dy) are an offset into the hatch which can be used to unalign adjoining areas, or to align the origin of a hatch with the the side of a filled area.
+
+
+=for comment
+From: Line 452 in fills.c
+
+=item i_new_fill_image(im, matrix, xoff, yoff, combine)
+
+
+Create an image based fill.
+
+matrix is an array of 9 doubles representing a transformation matrix.
+
+xoff and yoff are the offset into the image to start filling from.
+
+
+=for comment
+From: Line 489 in fills.c
+
+=item i_new_fill_solid(color, combine)
+
+
+Create a solid fill based on an 8-bit color.
+
+If combine is non-zero then alpha values will be combined.
+
+
+=for comment
+From: Line 244 in fills.c
+
+=item i_new_fill_solidf(color, combine)
+
+
+Create a solid fill based on a float color.
+
+If combine is non-zero then alpha values will be combined.
+
+
+=for comment
+From: Line 213 in fills.c
+
+
+=back
+
+=head2 Image
+
+=over
+
+=item i_copy(src)
+
+
+Creates a new image that is a copy of src.
+
+Tags are not copied, only the image data.
+
+Returns: i_img *
+
+
+=for comment
+From: Line 626 in image.c
+
+=item i_copyto(dest, src, x1, y1, x2, y2, tx, ty)
+
+
+Copies image data from the area (x1,y1)-[x2,y2] in the source image to
+a rectangle the same size with it's top-left corner at (tx,ty) in the
+destination image.
+
+If x1 > x2 or y1 > y2 then the corresponding co-ordinates are swapped.
+
+
+=for comment
+From: Line 557 in image.c
+
+=item i_copyto_trans(im, src, x1, y1, x2, y2, tx, ty, trans)
+
+
+(x1,y1) (x2,y2) specifies the region to copy (in the source coordinates)
+(tx,ty) specifies the upper left corner for the target image.
+pass NULL in trans for non transparent i_colors.
+
+
+=for comment
+From: Line 515 in image.c
+
+=item i_img_destroy(im)
+
+
+Destroy image and free data via exorcise.
+
+   im - Image pointer
+
+
+=for comment
+From: Line 424 in image.c
+
+=item i_img_info(im, info)
+
+
+Return image information
+
+   im - Image pointer
+   info - pointer to array to return data
+
+info is an array of 4 integers with the following values:
+
+ info[0] - width
+ info[1] - height
+ info[2] - channels
+ info[3] - channel mask
+
+
+=for comment
+From: Line 443 in image.c
+
+=item i_rubthru(im, src, tx, ty, src_minx, src_miny, src_maxx, src_maxy )
+
+
+Takes the sub image I<src[src_minx, src_maxx)[src_miny, src_maxy)> and
+overlays it at (I<tx>,I<ty>) on the image object.
+
+The alpha channel of each pixel in I<src> is used to control how much
+the existing colour in I<im> is replaced, if it is 255 then the colour
+is completely replaced, if it is 0 then the original colour is left 
+unmodified.
+
+
+=for comment
+From: Line 701 in image.c
+
+
+=back
+
+=head2 Image creation
+
+=over
+
+=item i_img_16_new(x, y, ch)
+
+
+Create a new 16-bit/sample image.
+
+Returns the image on success, or NULL on failure.
+
+
+=for comment
+From: Line 192 in img16.c
+
+=item i_img_8_new(x, y, ch)
+
+
+Creates a new image object I<x> pixels wide, and I<y> pixels high with
+I<ch> channels.
+
+
+=for comment
+From: Line 257 in image.c
+
+=item i_img_double_new(int x, int y, int ch)
+
+
+Creates a new double per sample image.
+
+
+=for comment
+From: Line 82 in imgdouble.c
+
+=item i_img_pal_new(x, y, channels, maxpal)
+
+
+Creates a new paletted image of the supplied dimensions.
+
+Returns a new image or NULL on failure.
+
+
+=for comment
+From: Line 136 in palimg.c
+
+=item i_sametype(i_img *im, int xsize, int ysize)
+
+
+Returns an image of the same type (sample size, channels, paletted/direct).
+
+For paletted images the palette is copied from the source.
+
+
+=for comment
+From: Line 1107 in image.c
+
+=item i_sametype_chans(i_img *im, int xsize, int ysize, int channels)
+
+
+Returns an image of the same type (sample size).
+
+For paletted images the equivalent direct type is returned.
+
+
+=for comment
+From: Line 1149 in image.c
+
+
+=back
+
+=head2 Image quantization
+
+=over
+
+=item i_quant_makemap(quant, imgs, count)
+
+
+Analyzes the I<count> images in I<imgs> according to the rules in
+I<quant> to build a color map (optimal or not depending on
+quant->make_colors).
+
+
+=for comment
+From: Line 30 in quant.c
+
+=item i_quant_translate(quant, img)
+
+
+Quantize the image given the palette in quant.
+
+On success returns a pointer to a memory block of img->xsize *
+img->ysize i_palidx entries.
+
+On failure returns NULL.
+
+You should call myfree() on the returned block when you're done with
+it.
+
+This function will fail if the supplied palette contains no colors.
+
+
+=for comment
+From: Line 86 in quant.c
+
+=item i_quant_transparent(quant, data, img, trans_index)
+
+
+Dither the alpha channel on I<img> into the palette indexes in
+I<data>.  Pixels to be transparent are replaced with I<trans_pixel>.
+
+The method used depends on the tr_* members of quant.
+
+
+=for comment
+From: Line 1470 in quant.c
+
+
+=back
+
+=head2 Paletted images
+
+=over
+
+=item i_addcolors(im, colors, count)
+
+
+Adds colors to the image's palette.
+
+On success returns the index of the lowest color added.
+
+On failure returns -1.
+
+Always fails for direct color images.
+
+
+=for comment
+From: Line 332 in imext.c
+
+=item i_colorcount(im)
+
+
+Returns the number of colors in the image's palette.
+
+Returns -1 for direct images.
+
+
+=for comment
+From: Line 378 in imext.c
+
+=item i_findcolor(im, color, &entry)
+
+
+Searches the images palette for the given color.
+
+On success sets *I<entry> to the index of the color, and returns true.
+
+On failure returns false.
+
+Always fails on direct color images.
+
+
+=for comment
+From: Line 413 in imext.c
+
+=item i_getcolors(im, index, colors, count)
+
+
+Retrieves I<count> colors starting from I<index> in the image's
+palette.
+
+On success stores the colors into I<colors> and returns true.
+
+On failure returns false.
+
+Always fails for direct color images.
+
+Fails if there are less than I<index>+I<count> colors in the image's
+palette.
+
+
+=for comment
+From: Line 353 in imext.c
+
+=item i_maxcolors(im)
+
+
+Returns the maximum number of colors the palette can hold for the
+image.
+
+Returns -1 for direct color images.
+
+
+=for comment
+From: Line 395 in imext.c
+
+=item i_setcolors(im, index, colors, count)
+
+
+Sets I<count> colors starting from I<index> in the image's palette.
+
+On sucess returns true.
+
+On failure returns false.
+
+The image must have at least I<index>+I<count> colors in it's palette
+for this to succeed.
+
+Always fails on direct color images.
+
+
+=for comment
+From: Line 433 in imext.c
+
+
+=back
+
+=head2 Tags
+
+=over
+
+=item i_tags_delbycode(tags, code)
+
+
+Delete any tags with the given code.
+
+Returns the number of tags deleted.
+
+
+=for comment
+From: Line 294 in tags.c
+
+=item i_tags_delbyname(tags, name)
+
+
+Delete any tags with the given name.
+
+Returns the number of tags deleted.
+
+
+=for comment
+From: Line 264 in tags.c
+
+=item i_tags_delete(tags, index)
+
+
+Delete a tag by index.
+
+Returns true on success.
+
+
+=for comment
+From: Line 235 in tags.c
+
+=item i_tags_destroy(tags)
+
+
+Destroys the given tags structure.  Called by i_img_destroy().
+
+
+=for comment
+From: Line 158 in tags.c
+
+=item i_tags_find(tags, name, start, &entry)
+
+
+Searchs for a tag of the given I<name> starting from index I<start>.
+
+On success returns true and sets *I<entry>.
+
+On failure returns false.
+
+
+=for comment
+From: Line 181 in tags.c
+
+=item i_tags_findn(tags, code, start, &entry)
+
+
+Searchs for a tag of the given I<code> starting from index I<start>.
+
+On success returns true and sets *I<entry>.
+
+On failure returns false.
+
+
+=for comment
+From: Line 208 in tags.c
+
+=item i_tags_get_color(tags, name, code, &value)
+
+
+Retrieve a tag specified by name or code as color.
+
+On success sets the i_color *I<value> to the color and returns true.
+
+On failure returns false.
+
+
+=for comment
+From: Line 505 in tags.c
+
+=item i_tags_get_float(tags, name, code, value)
+
+
+Retrieves a tag as a floating point value.  
+
+If the tag has a string value then that is parsed as a floating point
+number, otherwise the integer value of the tag is used.
+
+On success sets *I<value> and returns true.
+
+On failure returns false.
+
+
+=for comment
+From: Line 320 in tags.c
+
+=item i_tags_get_int(tags, name, code, &value)
+
+
+Retrieve a tag specified by name or code as an integer.
+
+On success sets the i_color *I<value> to the color and returns true.
+
+On failure returns false.
+
+
+=for comment
+From: Line 406 in tags.c
+
+=item i_tags_get_string(tags, name, code, value, value_size)
+
+
+Retrieves a tag by name or code as a string.
+
+On success copies the string to value for a max of value_size and
+returns true.
+
+On failure returns false.
+
+value_size must be at least large enough for a string representation
+of an integer.
+
+The copied value is always NUL terminated.
+
+
+=for comment
+From: Line 569 in tags.c
+
+=item i_tags_new(i_img_tags *tags)
+
+
+Initialize a tags structure.  Should not be used if the tags structure
+has been previously used.
+
+This should be called tags member of an i_img object on creation (in
+i_img_*_new() functions).
+
+To destroy the contents use i_tags_destroy()
+
+
+=for comment
+From: Line 61 in tags.c
+
+=item i_tags_set(tags, name, data, size)
+
+
+Sets the given tag to the string I<data>
+
+
+=for comment
+From: Line 617 in tags.c
+
+=item i_tags_set_color(tags, name, code, &value)
+
+
+Stores the given color as a tag with the given name and code.
+
+
+=for comment
+From: Line 545 in tags.c
+
+=item i_tags_set_float(tags, name, code, value)
+
+
+Equivalent to i_tags_set_float2(tags, name, code, value, 30).
+
+
+=for comment
+From: Line 359 in tags.c
+
+=item i_tags_set_float2(tags, name, code, value, places)
+
+
+Sets the tag with the given name and code to the given floating point
+value.
+
+Since tags are strings or ints, we convert the value to a string before
+storage at the precision specified by C<places>.
+
+
+=for comment
+From: Line 374 in tags.c
+
+=item i_tags_setn(tags, name, idata)
+
+
+Sets the given tag to the integer I<idata>
+
+
+=for comment
+From: Line 634 in tags.c
+
+
+=back
+
+
+=head1 AUTHOR
+
+Tony Cook <tony@imager.perl.org>
+
+=head1 SEE ALSO
+
+Imager, Imager::ExtUtils, Imager::Inline
+
+=cut
diff --git a/lib/Imager/ExtUtils.pm b/lib/Imager/ExtUtils.pm
new file mode 100644 (file)
index 0000000..069dc9f
--- /dev/null
@@ -0,0 +1,125 @@
+package Imager::ExtUtils;
+use strict;
+
+=head1 NAME
+
+Imager::ExtUtils - functions handy in writing Imager extensions
+
+=head1 SYNOPSIS
+
+  # make Imager easier to use with Inline
+  # perldoc Imager::Inline
+  use Inline with => 'Imager';
+
+=head1 DESCRIPTION
+
+=over
+
+=item base_dir
+
+Returns the base directory where Imager is installed.
+
+=cut
+
+# figure out where Imager is installed
+sub base_dir {
+  for my $dir (@INC) {
+    if (-e "$dir/Imager.pm") {
+      return $dir;
+    }
+  }
+
+  die "Cannot locate an installed Imager!";
+}
+
+=item inline_config
+
+Implements Imager's Inline::C C<with> hook.
+
+=cut
+
+sub inline_config {
+  my ($class) = @_;
+  my $base = base_dir();
+
+  return
+    {
+     INC => $class->includes,
+     TYPEMAPS => $class->typemap,
+     AUTO_INCLUDE => <<'CODE',
+#include "imext.h"
+#include "imperl.h"
+DEFINE_IMAGER_CALLBACKS;
+CODE
+     BOOT => 'PERL_INITIALIZE_IMAGER_CALLBACKS;',
+     FILTERS => \&_inline_filter,
+    };
+}
+
+my @inline_replace =
+  qw(
+   Imager::ImgRaw
+   Imager::Color::Float
+   Imager::Color
+   Imager::IO
+  );
+
+my %inline_replace =
+  map { (my $tmp = $_) =~ s/::/__/g; $_ => $tmp } @inline_replace;
+
+my $inline_replace_re = "\\b(" . join('|', @inline_replace) . ")\\b";
+
+sub _inline_filter {
+  my $code = shift;
+
+  $code =~ s/$inline_replace_re/$inline_replace{$1}/g;
+
+  $code;
+}
+
+=item includes
+
+Returns -I options suitable for use with ExtUtils::MakeMaker's INC
+option.
+
+=cut
+
+sub includes {
+  my $class = shift;
+  my $base = $class->base_dir();
+
+  "-I" . $base . '/Imager/include',
+}
+
+=item typemap
+
+Returns the full path to Imager's installed typemap.
+
+=cut
+
+sub typemap {
+  my $class = shift;
+  my $base = $class->base_dir();
+
+  $base . '/Imager/typemap';
+}
+
+1;
+
+__END__
+
+=back
+
+=head1 AUTHOR
+
+Tony Cook <tony@imager.perl.org>
+
+=head1 REVISION
+
+$Revision$
+
+=head1 SEE ALSO
+
+Imager, Imager::API, Imager::Inline, Imager::APIRef.
+
+=cut
diff --git a/lib/Imager/Inline.pod b/lib/Imager/Inline.pod
new file mode 100644 (file)
index 0000000..a4d329a
--- /dev/null
@@ -0,0 +1,73 @@
+=head1 NAME
+
+Imager::Inline - using Imager with Inline::C.
+
+=head1 SYNOPSIS
+
+  use Inline with => 'Imager';
+  use Inline C => <<'EOS';
+  Imager some_func(Imager::Color c, Imager::Fill f) {
+    Imager img = i_img_8_new(200, 200, 3);
+    /* fill with color */
+    i_box_filled(img, 0, 0, 199, 199, c);
+    /* inner area with fill */
+    i_box_cfill(img, 50, 50, 149, 149, f);
+
+    return img;
+  }
+  EOS
+
+=head1 DESCRIPTION
+
+Imager hooks into Inline's C<with> syntax to make it easier to write
+Inline::C code that works with Imager, you can call Imager functions
+without having to include headers or perform initialization.
+
+Imager's inline C<with> support does the following:
+
+=over
+
+=item *
+
+add the installed Imager include directory to INC
+
+=item *
+
+add the Imager typemap to TYPEMAPS
+
+=item *
+
+include the headers needed by Imager C extension modules.
+
+=item *
+
+declare and initialize the Imager API function table pointer
+
+=item *
+
+filter the supplied code to replace Imager's class names with those
+that Inline::C can handle.
+
+=back
+
+=head1 LIMITATIONS
+
+The filtering mechanism is global, it will replace the class names
+even inside string constants.  If you need a string matching the name
+of one of Imager's classes, like C<"Imager::Color"> you will need to
+split it into 2 to use C's string pasting mechanism, for example:
+C<"Imager:" ":Color">.
+
+=head1 AUTHOR
+
+Tony Cook <tony@imager.perl.org>
+
+=head1 REVISION
+
+$Revision$
+
+=head1 SEE ALSO
+
+Imager, Imager::ExtUtils, Imager::API, Imager::APIRef
+
+=cut
index 10c112a..7892257 100644 (file)
@@ -301,15 +301,53 @@ A list of the transformations that alter the source image follows:
 
 =item paste
 
+X<paste>To copy an image to onto another image use the C<paste()>
+method.
 
-To copy an image to onto another image use the C<paste()> method.
-
-  $dest->paste(left=>40,top=>20,img=>$logo);
+  $dest->paste(left=>40, top=>20, src=>$logo);
 
 That copies the entire C<$logo> image onto the C<$dest> image so that the
 upper left corner of the C<$logo> image is at (40,20).
 
+Parameters:
+
+=over
+
+=item *
+
+src, img - the source image.  I<src> added for compatibility with
+rubthrough().
+
+=item *
+
+left, top - position in output of the top left of the pasted image.
+Default: (0,0)
+
+=item *
+
+src_minx, src_miny - the top left corner in the source image to start
+the paste from.  Default: (0, 0)
+
+=item *
+
+src_maxx, src_maxy - the bottom right in the source image of the sub
+image to paste.  This position is B<non> inclusive.  Default: bottom
+right corner of the source image.
+
+=item *
+
+width, height - if the corresponding src_maxx or src_maxy is not
+defined then width or height is used for the width or height of the
+sub image to be pasted.
+
+=back
 
+  # copy the 20x20 pixel image from (20,20) in $src_image to (10,10) in $img
+  $img->paste(src=>$src_image,
+              left => 10, top => 10,
+              src_minx => 20, src_miny => 20,
+              src_maxx => 40, src_maxx => 40);
+              
 =item rubthrough
 
 A more complicated way of blending images is where one image is
index cc2b119..de02ddd 100644 (file)
--- a/limits.c
+++ b/limits.c
@@ -24,7 +24,7 @@ Setting a value of zero means that limit will be ignored.
   
  */
 
-#include "imagei.h"
+#include "imageri.h"
 
 static int max_width, max_height;
 static int max_bytes;
diff --git a/map.c b/map.c
index 0e9c47d..e88dfcc 100644 (file)
--- a/map.c
+++ b/map.c
@@ -17,7 +17,7 @@ converting from RGBA to greyscale and back.
 =cut
 */
 
-#include "image.h"
+#include "imager.h"
 
 
 /*
index aa8f5ef..6786850 100644 (file)
--- a/maskimg.c
+++ b/maskimg.c
@@ -11,8 +11,8 @@ maskimg.c - implements masked images/image subsets
 =cut
 */
 
-#include "image.h"
-#include "imagei.h"
+#include "imager.h"
+#include "imageri.h"
 
 #include <stdio.h>
 /*
diff --git a/metafile.pl b/metafile.pl
new file mode 100644 (file)
index 0000000..ef24bdc
--- /dev/null
@@ -0,0 +1,36 @@
+# some versions of EU::MM have problems with recursive Makefile.PLs with
+# this method defined.
+undef &MY::metafile;
+
+sub MY::metafile {
+  my ($self) = @_;
+
+  my $meta = <<YAML;
+--- #YAML:1.0
+name: $self->{NAME}
+version: $self->{VERSION}
+version_from: $self->{VERSION_FROM}
+author: $self->{AUTHOR}
+abstract: $self->{ABSTRACT}
+installdirs: $self->{INSTALLDIRS}
+YAML
+  if (keys %{$Recommends{$self->{NAME}}}) {
+    $meta .= "recommends:\n";
+    while (my ($module, $version) = each %{$Recommends{$self->{NAME}}}) {
+      $meta .= "$module: $version\n";
+    }
+  }
+  $meta .= <<YAML;
+license: perl
+dynamic_config: 1
+distribution_type: module
+generated_by: $self->{NAME} version $self->{VERSION}
+YAML
+  open META, "> meta.tmp" or die "Cannot create meta.tmp: $!";
+  print META $meta;
+  close META;
+  
+  return sprintf "metafile :\n\t\$(CP) meta.tmp META.yml\n";
+}
+
+1;
index f586f4e..90ec29e 100644 (file)
--- a/palimg.c
+++ b/palimg.c
@@ -18,8 +18,8 @@ Basic 8-bit/sample paletted image
 =cut
 */
 
-#include "image.h"
-#include "imagei.h"
+#include "imager.h"
+#include "imageri.h"
 
 #define PALEXT(im) ((i_img_pal_ext*)((im)->ext_data))
 static int i_ppix_p(i_img *im, int x, int y, i_color *val);
@@ -74,7 +74,7 @@ static i_img IIM_base_8bit_pal =
 };
 
 /*
-=item i_img_pal_new_low(i_img *im, int x, int y, int channels, int maxpal)
+=item i_img_pal_new_low(im, x, y, channels, maxpal)
 
 Creates a new paletted image.
 
@@ -132,6 +132,18 @@ i_img *i_img_pal_new_low(i_img *im, int x, int y, int channels, int maxpal) {
   return im;
 }
 
+/*
+=item i_img_pal_new(x, y, channels, maxpal)
+
+=category Image creation
+
+Creates a new paletted image of the supplied dimensions.
+
+Returns a new image or NULL on failure.
+
+=cut
+*/
+
 i_img *i_img_pal_new(int x, int y, int channels, int maxpal) {
   i_img *im;
   mm_log((1, "i_img_pal_new(x %d, y %d, channels %d, maxpal %d)\n", x, y, channels, maxpal));
@@ -210,8 +222,8 @@ i_img *i_img_to_pal(i_img *src, i_quantize *quant) {
 
   i_clear_error();
   
-  quant_makemap(quant, &src, 1);
-  result = quant_translate(quant, src);
+  i_quant_makemap(quant, &src, 1);
+  result = i_quant_translate(quant, src);
 
   if (result) {
 
@@ -289,7 +301,7 @@ static int i_ppix_p(i_img *im, int x, int y, i_color *val) {
 }
 
 /*
-=item i_gpix(i_img *im, int x, int y, i_color *val)
+=item i_gpix_p(i_img *im, int x, int y, i_color *val)
 
 Retrieve a pixel, converting from a palette index to a color.
 
diff --git a/plug.h b/plug.h
index 3e23b83..e3583fc 100644 (file)
--- a/plug.h
+++ b/plug.h
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 
 /* structures for passing data between Imager-plugin and the Imager-module */
 
diff --git a/png.c b/png.c
index 684d53f..19af7e5 100644 (file)
--- a/png.c
+++ b/png.c
@@ -1,5 +1,5 @@
 #include "iolayer.h"
-#include "imagei.h"
+#include "imageri.h"
 #include "png.h"
 
 /* Check to see if a file is a PNG file using png_sig_cmp().  png_sig_cmp()
diff --git a/pnm.c b/pnm.c
index eef1799..e5d3050 100644 (file)
--- a/pnm.c
+++ b/pnm.c
@@ -1,7 +1,7 @@
-#include "image.h"
+#include "imager.h"
 #include "log.h"
 #include "iolayer.h"
-#include "imagei.h"
+#include "imageri.h"
 
 #include <stdlib.h>
 #include <errno.h>
index 257713c..d480254 100644 (file)
--- a/polygon.c
+++ b/polygon.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 #include "draw.h"
 #include "log.h"
 
diff --git a/quant.c b/quant.c
index 51524cd..dc74beb 100644 (file)
--- a/quant.c
+++ b/quant.c
@@ -2,7 +2,7 @@
    currently only used by gif.c, but maybe we'll support producing 
    8-bit (or bigger indexed) png files at some point
 */
-#include "image.h"
+#include "imager.h"
 
 static void makemap_addi(i_quantize *, i_img **imgs, int count);
 static void makemap_mediancut(i_quantize *, i_img **imgs, int count);
@@ -26,8 +26,20 @@ setcol(i_color *cl,unsigned char r,unsigned char g,unsigned char b,unsigned char
    handle multiple colour maps.
 */
 
+/*
+=item i_quant_makemap(quant, imgs, count)
+
+=category Image quantization
+
+Analyzes the I<count> images in I<imgs> according to the rules in
+I<quant> to build a color map (optimal or not depending on
+quant->make_colors).
+
+=cut
+*/
+
 void
-quant_makemap(i_quantize *quant, i_img **imgs, int count) {
+i_quant_makemap(i_quantize *quant, i_img **imgs, int count) {
 
   if (quant->translate == pt_giflib) {
     /* giflib does it's own color table generation */
@@ -70,11 +82,27 @@ static void translate_closest(i_quantize *, i_img *, i_palidx *);
 static void translate_errdiff(i_quantize *, i_img *, i_palidx *);
 static void translate_addi(i_quantize *, i_img *, i_palidx *);
 
-/* Quantize the image given the palette in quant.
+/*
+=item i_quant_translate(quant, img)
+
+=category Image quantization
+
+Quantize the image given the palette in quant.
+
+On success returns a pointer to a memory block of img->xsize *
+img->ysize i_palidx entries.
+
+On failure returns NULL.
 
-   The giflib quantizer ignores the palette.
+You should call myfree() on the returned block when you're done with
+it.
+
+This function will fail if the supplied palette contains no colors.
+
+=cut
 */
-i_palidx *quant_translate(i_quantize *quant, i_img *img) {
+i_palidx *
+i_quant_translate(i_quantize *quant, i_img *img) {
   i_palidx *result;
   int bytes;
 
@@ -1438,7 +1466,21 @@ static void transparent_threshold(i_quantize *, i_palidx *, i_img *, i_palidx);
 static void transparent_errdiff(i_quantize *, i_palidx *, i_img *, i_palidx);
 static void transparent_ordered(i_quantize *, i_palidx *, i_img *, i_palidx);
 
-void quant_transparent(i_quantize *quant, i_palidx *data, i_img *img,
+/*
+=item i_quant_transparent(quant, data, img, trans_index)
+
+=category Image quantization
+
+Dither the alpha channel on I<img> into the palette indexes in
+I<data>.  Pixels to be transparent are replaced with I<trans_pixel>.
+
+The method used depends on the tr_* members of quant.
+
+=cut
+*/
+
+void 
+i_quant_transparent(i_quantize *quant, i_palidx *data, i_img *img,
                       i_palidx trans_index)
 {
   switch (quant->transp) {
diff --git a/raw.c b/raw.c
index 214bc21..8b363d5 100644 (file)
--- a/raw.c
+++ b/raw.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 #include <stdio.h>
 #include "iolayer.h"
 #ifndef _MSC_VER
index 448ef7a..e8df6ea 100644 (file)
--- a/regmach.h
+++ b/regmach.h
@@ -3,7 +3,7 @@
 
 #include <stdio.h>
 #include <math.h>
-#include "image.h"
+#include "imager.h"
 
 enum rm_byte_codes {
   rbc_add, /* ra + rb -> r*/
diff --git a/rgb.c b/rgb.c
index 7559a06..cb47a8c 100644 (file)
--- a/rgb.c
+++ b/rgb.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 #include "log.h"
 #include "iolayer.h"
 
index cb2e3e5..457fea0 100644 (file)
--- a/rotate.c
+++ b/rotate.c
@@ -16,7 +16,7 @@ Other rotations will be added as tuits become available.
 =cut
 */
 
-#include "image.h"
+#include "imager.h"
 #include <math.h> /* for floor() */
 
 i_img *i_rotate90(i_img *src, int degrees) {
index e809c86..80d7823 100644 (file)
@@ -66,7 +66,7 @@ ok($ooimg->bits eq 'double', "oo didn't give double image");
 
 # check that the image is copied correctly
 my $oocopy = $ooimg->copy;
-ok($oocopy->bits eq 'double', "oo copy didn't give double image");
+is($oocopy->bits, 'double', "oo copy didn't give double image");
 
 ok(!Imager->new(xsize=>0, ysize=>1, bits=>'double'),
     "fail making 0 width image");
index 5a6ef2e..b55692f 100644 (file)
@@ -1,28 +1,86 @@
-BEGIN { $| = 1; print "1..4\n"; }
-END {print "not ok 1\n" unless $loaded;}
-use Imager;
+#!perl -w
+use strict;
+use Test::More tests => 15;
 
-$loaded = 1;
+BEGIN { use_ok("Imager") }
 
 #$Imager::DEBUG=1;
 
 Imager::init('log'=>'testout/t66paste.log');
 
-$img=Imager->new() || die "unable to create image object\n";
+# the original smoke tests
+my $img=Imager->new() || die "unable to create image object\n";
 
-print "ok 1\n";
+ok($img->open(file=>'testimg/scale.ppm',type=>'pnm'), "load test img");
 
-$img->open(file=>'testimg/scale.ppm',type=>'pnm');
+my $nimg=Imager->new() or die "Unable to create image object\n";
+ok($nimg->open(file=>'testimg/scale.ppm',type=>'pnm'), "load test img again");
 
-$nimg=Imager->new() or die "Unable to create image object\n";
-$nimg->open(file=>'testimg/scale.ppm',type=>'pnm');
-print "ok 2\n";
+ok($img->paste(img=>$nimg, top=>30, left=>30), "paste it")
+  or print "# ", $img->errstr, "\n";;
 
-$img->paste(img=>$nimg, top=>30, left=>30) or die $img->{ERRSTR};
-print "ok 3\n";
+ok($img->write(type=>'pnm',file=>'testout/t66.ppm'), "save it")
+  or print "# ", $img->errstr, "\n";
 
+# more stringent tests
+{
+  my $src = Imager->new(xsize => 100, ysize => 100);
+  $src->box(filled=>1, color=>'FF0000');
 
-$img->write(type=>'pnm',file=>'testout/t66.ppm') || die "error in write()\n";
-print "ok 4\n";
+  $src->box(filled=>1, color=>'0000FF', xmin => 20, ymin=>20,
+            xmax=>79, ymax=>79);
 
+  my $targ = Imager->new(xsize => 100, ysize => 100);
+  $targ->box(filled=>1, color=>'00FF00', xmin=>20, ymin=>20, xmax=>79,
+             ymax=>79);
 
+  my $work = $targ->copy;
+  ok($work->paste(src=>$src, left => 15, top => 10), "paste whole image");
+  # build comparison image
+  my $cmp = $targ->copy;
+  $cmp->box(filled=>1, xmin=>15, ymin => 10, color=>'FF0000');
+  $cmp->box(filled=>1, xmin=>35, ymin => 30, xmax=>94, ymax=>89, 
+            color=>'0000FF');
+
+  is(Imager::i_img_diff($work->{IMG}, $cmp->{IMG}), 0,
+     "compare pasted and expected");
+
+  $work = $targ->copy;
+  ok($work->paste(src=>$src, left=>2, top=>7, src_minx => 10, src_miny => 15),
+     "paste from inside src");
+  $cmp = $targ->copy;
+  $cmp->box(filled=>1, xmin=>2, ymin=>7, xmax=>91, ymax=>91, color=>'FF0000');
+  $cmp->box(filled=>1, xmin=>12, ymin=>12, xmax=>71, ymax=>71, 
+            color=>'0000FF');
+  is(Imager::i_img_diff($work->{IMG}, $cmp->{IMG}), 0,
+     "compare pasted and expected");
+
+  # paste part source
+  $work = $targ->copy;
+  ok($work->paste(src=>$src, left=>15, top=>20, 
+                  src_minx=>10, src_miny=>15, src_maxx=>80, src_maxy =>70),
+     "paste src cropped all sides");
+  $cmp = $targ->copy;
+  $cmp->box(filled=>1, xmin=>15, ymin=>20, xmax=>84, ymax=>74, 
+            color=>'FF0000');
+  $cmp->box(filled=>1, xmin=>25, ymin=>25, xmax=>84, ymax=>74,
+            color=>'0000FF');
+  is(Imager::i_img_diff($work->{IMG}, $cmp->{IMG}), 0,
+     "compare pasted and expected");
+
+  # go by width instead
+  $work = $targ->copy;
+  ok($work->paste(src=>$src, left=>15, top=>20,
+                  src_minx=>10, src_miny => 15, width => 70, height => 55),
+     "same but specify width/height instead");
+  is(Imager::i_img_diff($work->{IMG}, $cmp->{IMG}), 0,
+     "compare pasted and expected");
+
+  # use src_coords
+  $work = $targ->copy;
+  ok($work->paste(src=>$src, left => 15, top => 20,
+                  src_coords => [ 10, 15, 80, 70 ]),
+     "using src_coords");
+  is(Imager::i_img_diff($work->{IMG}, $cmp->{IMG}), 0,
+     "compare pasted and expected");
+}
diff --git a/t/t82inline.t b/t/t82inline.t
new file mode 100644 (file)
index 0000000..177dc9c
--- /dev/null
@@ -0,0 +1,231 @@
+#!perl -w
+#
+# this tests both the Inline interface and the API
+use strict;
+use lib 't';
+use Test::More;
+eval "require Inline::C;";
+plan skip_all => "Inline required for testing API - $@" if $@;
+
+plan tests => 8;
+require Inline;
+Inline->import(with => 'Imager');
+
+Inline->bind(C => <<'EOS');
+#include <math.h>
+
+int pixel_count(Imager::ImgRaw im) {
+  return im->xsize * im->ysize;
+}
+
+int count_color(Imager::ImgRaw im, Imager::Color c) {
+  int count = 0, x, y, chan;
+  i_color read_c;
+
+  for (x = 0; x < im->xsize; ++x) {
+    for (y = 0; y < im->ysize; ++y) {
+      int match = 1;
+      i_gpix(im, x, y, &read_c);
+      for (chan = 0; chan < im->channels; ++chan) {
+        if (read_c.channel[chan] != c->channel[chan]) {
+          match = 0;
+          break;
+        }
+      }
+      if (match)
+        ++count;
+    }
+  }
+
+  return count;
+}
+
+Imager make_10x10() {
+  i_img *im = i_img_8_new(10, 10, 3);
+  i_color c;
+  c.channel[0] = c.channel[1] = c.channel[2] = 255;
+  i_box_filled(im, 0, 0, im->xsize-1, im->ysize-1, &c);
+
+  return im;
+}
+
+/* tests that all of the APIs are visible - most of them anyway */
+Imager do_lots(Imager src) {
+  i_img *im = i_img_8_new(100, 100, 3);
+  i_img *fill_im = i_img_8_new(5, 5, 3);
+  i_img *testim;
+  i_color red, blue, temp_color;
+  i_fcolor redf, bluef;
+  i_fill_t *hatch, *fhatch_fill;
+  i_fill_t *im_fill;
+  i_fill_t *solid_fill, *fsolid_fill;
+  i_fill_t *fount_fill;
+  void *block;
+  double matrix[9] = /* 30 degree rotation */
+    {
+      0.866025,  -0.5,      0, 
+      0.5,       0.866025,  0, 
+      0,         0,         1,      
+    };
+  i_fountain_seg fseg;
+  i_img_tags tags;
+  int entry;
+  double temp_double;
+
+  red.channel[0] = 255; red.channel[1] = 0; red.channel[2] = 0;
+  red.channel[3] = 255;
+  blue.channel[0] = 0; blue.channel[1] = 0; blue.channel[2] = 255;
+  blue.channel[3] = 255;
+  hatch = i_new_fill_hatch(&red, &blue, 0, 1, NULL, 0, 0);
+
+  i_box(im, 0, 0, 9, 9, &red);
+  i_box_filled(im, 10, 0, 19, 9, &blue);
+  i_box_cfill(im, 20, 0, 29, 9, hatch);
+
+  /* make an image fill, and try it */
+  i_box_cfill(fill_im, 0, 0, 4, 4, hatch);
+  im_fill = i_new_fill_image(fill_im, matrix, 2, 2, 0);
+
+  i_box_cfill(im, 30, 0, 39, 9, im_fill);
+
+  /* make a solid fill and try it */
+  solid_fill = i_new_fill_solid(&red, 0);
+  i_box_cfill(im, 40, 0, 49, 9, solid_fill);
+
+  /* floating fills */
+  redf.channel[0] = 1.0; redf.channel[1] = 0; redf.channel[2] = 0;
+  redf.channel[3] = 1.0;
+  bluef.channel[0] = 0; bluef.channel[1] = 0; bluef.channel[2] = 1.0;
+  bluef.channel[3] = 1.0;
+
+  fsolid_fill = i_new_fill_solidf(&redf, 0);
+  i_box_cfill(im, 50, 0, 59, 9, fsolid_fill);
+  fhatch_fill = i_new_fill_hatchf(&redf, &bluef, 0, 2, NULL, 0, 0);
+  i_box_cfill(im, 60, 0, 69, 9, fhatch_fill);
+
+  /* fountain fill */
+  fseg.start = 0;
+  fseg.middle = 0.5;
+  fseg.end = 1.0;
+  fseg.c[0] = redf;
+  fseg.c[1] = bluef;
+  fseg.type = i_fst_linear;
+  fseg.color = i_fc_hue_down;
+  fount_fill = i_new_fill_fount(70, 0, 80, 0, i_ft_linear, i_fr_triangle, 0, i_fts_none, 1, 1, &fseg);
+
+  i_box_cfill(im, 70, 0, 79, 9, fount_fill);
+
+  i_line(im, 0, 10, 10, 15, &blue, 1);
+  i_line_aa(im, 0, 19, 10, 15, &red, 1);
+  
+  i_arc(im, 15, 15, 4, 45, 160, &blue);
+  i_arc_aa(im, 25, 15, 4, 75, 280, &red);
+  i_arc_cfill(im, 35, 15, 4, 0, 215, hatch);
+  i_arc_aa_cfill(im, 45, 15, 4, 30, 210, hatch);
+  i_circle_aa(im, 55, 15, 4, &red);
+  
+  i_box(im, 61, 11, 68, 18, &red);
+  i_flood_fill(im, 65, 15, &blue);
+  i_box(im, 71, 11, 78, 18, &red);
+  i_flood_cfill(im, 75, 15, hatch);
+
+  i_fill_destroy(fount_fill);
+  i_fill_destroy(fhatch_fill);
+  i_fill_destroy(solid_fill);
+  i_fill_destroy(fsolid_fill);
+  i_fill_destroy(hatch);
+  i_fill_destroy(im_fill);
+  i_img_destroy(fill_im);
+
+  /* make sure we can make each image type */
+  testim = i_img_16_new(100, 100, 3);
+  i_img_destroy(testim);
+  testim = i_img_double_new(100, 100, 3);
+  i_img_destroy(testim);
+  testim = i_img_pal_new(100, 100, 3, 256);
+  i_img_destroy(testim);
+  testim = i_sametype(im, 50, 50);
+  i_img_destroy(testim);
+  testim = i_sametype_chans(im, 50, 50, 4);
+  i_img_destroy(testim);
+
+  i_clear_error();
+  i_push_error(0, "Hello");
+  i_push_errorf(0, "%s", "World");
+
+  /* make sure tags create/destroy work */
+  i_tags_new(&tags);
+  i_tags_destroy(&tags);  
+
+  block = mymalloc(20);
+  block = myrealloc(block, 50);
+  myfree(block);
+
+  i_tags_set(&im->tags, "lots_string", "foo", -1);
+  i_tags_setn(&im->tags, "lots_number", 101);
+
+  if (!i_tags_find(&im->tags, "lots_number", 0, &entry)) {
+    i_push_error(0, "lots_number tag not found");
+    i_img_destroy(im);
+    return NULL;
+  }
+  i_tags_delete(&im->tags, entry);
+
+  /* these won't delete anything, but it makes sure the macros and function
+     pointers are correct */
+  i_tags_delbyname(&im->tags, "unknown");
+  i_tags_delbycode(&im->tags, 501);
+  i_tags_set_float(&im->tags, "lots_float", 0, 3.14);
+  if (!i_tags_get_float(&im->tags, "lots_float", 0, &temp_double)) {
+    i_push_error(0, "lots_float not found");
+    i_img_destroy(im);
+    return NULL;
+  }
+  if (fabs(temp_double - 3.14) > 0.001) {
+    i_push_errorf(0, "lots_float incorrect %g", temp_double);
+    i_img_destroy(im);
+    return NULL;
+  }
+  i_tags_set_float2(&im->tags, "lots_float2", 0, 100 * sqrt(2.0), 5);
+  if (!i_tags_get_int(&im->tags, "lots_float2", 0, &entry)) {
+    i_push_error(0, "lots_float2 not found as int");
+    i_img_destroy(im);
+    return NULL;
+  }
+  if (entry != 141) { 
+    i_push_errorf(0, "lots_float2 unexpected value %d", entry);
+    i_img_destroy(im);
+    return NULL;
+  }
+
+  i_tags_set_color(&im->tags, "lots_color", 0, &red);
+  if (!i_tags_get_color(&im->tags, "lots_color", 0, &temp_color)) {
+    i_push_error(0, "lots_color not found as color");
+    i_img_destroy(im);
+    return NULL;
+  }
+    
+  return im;
+}
+
+EOS
+
+my $im = Imager->new(xsize=>50, ysize=>50);
+is(pixel_count($im), 2500, "pixel_count");
+
+my $black = Imager::Color->new(0,0,0);
+is(count_color($im, $black), 2500, "count_color black on black image");
+
+my $im2 = make_10x10();
+my $white = Imager::Color->new(255, 255, 255);
+is(count_color($im2, $white), 100, "check new image white count");
+ok($im2->box(filled=>1, xmin=>1, ymin=>1, xmax => 8, ymax=>8, color=>$black),
+   "try new image");
+is(count_color($im2, $black), 64, "check modified black count");
+is(count_color($im2, $white), 36, "check modified white count");
+
+my $im3 = do_lots($im2);
+ok($im3, "do_lots()")
+  or print "# ", Imager->_error_as_msg, "\n";
+ok($im3->write(file=>'testout/t82lots.ppm'), "write t82lots.ppm");
diff --git a/tags.c b/tags.c
index bf8d3a5..951d1fe 100644 (file)
--- a/tags.c
+++ b/tags.c
@@ -48,7 +48,7 @@ A tag is represented by an i_img_tag structure:
 =cut
 */
 
-#include "image.h"
+#include "imager.h"
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
@@ -60,9 +60,14 @@ void i_tags_print(i_img_tags *tags);
 /*
 =item i_tags_new(i_img_tags *tags)
 
+=category Tags
+
 Initialize a tags structure.  Should not be used if the tags structure
 has been previously used.
 
+This should be called tags member of an i_img object on creation (in
+i_img_*_new() functions).
+
 To destroy the contents use i_tags_destroy()
 
 =cut
@@ -149,6 +154,16 @@ int i_tags_add(i_img_tags *tags, char const *name, int code, char const *data,
   return 1;
 }
 
+/*
+=item i_tags_destroy(tags)
+
+=category Tags
+
+Destroys the given tags structure.  Called by i_img_destroy().
+
+=cut
+*/
+
 void i_tags_destroy(i_img_tags *tags) {
   if (tags->tags) {
     int i;
@@ -162,6 +177,20 @@ void i_tags_destroy(i_img_tags *tags) {
   }
 }
 
+/*
+=item i_tags_find(tags, name, start, &entry)
+
+=category Tags
+
+Searchs for a tag of the given I<name> starting from index I<start>.
+
+On success returns true and sets *I<entry>.
+
+On failure returns false.
+
+=cut
+*/
+
 int i_tags_find(i_img_tags *tags, char const *name, int start, int *entry) {
   if (tags->tags) {
     while (start < tags->count) {
@@ -175,6 +204,20 @@ int i_tags_find(i_img_tags *tags, char const *name, int start, int *entry) {
   return 0;
 }
 
+/*
+=item i_tags_findn(tags, code, start, &entry)
+
+=category Tags
+
+Searchs for a tag of the given I<code> starting from index I<start>.
+
+On success returns true and sets *I<entry>.
+
+On failure returns false.
+
+=cut
+*/
+
 int i_tags_findn(i_img_tags *tags, int code, int start, int *entry) {
   if (tags->tags) {
     while (start < tags->count) {
@@ -188,6 +231,17 @@ int i_tags_findn(i_img_tags *tags, int code, int start, int *entry) {
   return 0;
 }
 
+/*
+=item i_tags_delete(tags, index)
+
+=category Tags
+
+Delete a tag by index.
+
+Returns true on success.
+
+=cut
+*/
 int i_tags_delete(i_img_tags *tags, int entry) {
   /*printf("i_tags_delete(tags %p [count %d], entry %d)\n",
     tags, tags->count, entry);*/
@@ -206,6 +260,18 @@ int i_tags_delete(i_img_tags *tags, int entry) {
   return 0;
 }
 
+/*
+=item i_tags_delbyname(tags, name)
+
+=category Tags
+
+Delete any tags with the given name.
+
+Returns the number of tags deleted.
+
+=cut
+*/
+
 int i_tags_delbyname(i_img_tags *tags, char const *name) {
   int count = 0;
   int i;
@@ -224,6 +290,18 @@ int i_tags_delbyname(i_img_tags *tags, char const *name) {
   return count;
 }
 
+/*
+=item i_tags_delbycode(tags, code)
+
+=category Tags
+
+Delete any tags with the given code.
+
+Returns the number of tags deleted.
+
+=cut
+*/
+
 int i_tags_delbycode(i_img_tags *tags, int code) {
   int count = 0;
   int i;
@@ -238,6 +316,23 @@ int i_tags_delbycode(i_img_tags *tags, int code) {
   return count;
 }
 
+/*
+=item i_tags_get_float(tags, name, code, value)
+
+=category Tags
+
+Retrieves a tag as a floating point value.  
+
+If the tag has a string value then that is parsed as a floating point
+number, otherwise the integer value of the tag is used.
+
+On success sets *I<value> and returns true.
+
+On failure returns false.
+
+=cut
+*/
+
 int i_tags_get_float(i_img_tags *tags, char const *name, int code, 
                      double *value) {
   int index;
@@ -260,6 +355,16 @@ int i_tags_get_float(i_img_tags *tags, char const *name, int code,
   return 1;
 }
 
+/*
+=item i_tags_set_float(tags, name, code, value)
+
+=category Tags
+
+Equivalent to i_tags_set_float2(tags, name, code, value, 30).
+
+=cut
+*/
+
 int i_tags_set_float(i_img_tags *tags, char const *name, int code, 
                      double value) {
   return i_tags_set_float2(tags, name, code, value, 30);
@@ -268,6 +373,8 @@ int i_tags_set_float(i_img_tags *tags, char const *name, int code,
 /*
 =item i_tags_set_float2(tags, name, code, value, places)
 
+=category Tags
+
 Sets the tag with the given name and code to the given floating point
 value.
 
@@ -295,6 +402,20 @@ int i_tags_set_float2(i_img_tags *tags, char const *name, int code,
   return i_tags_add(tags, name, code, temp, strlen(temp), 0);
 }
 
+/*
+=item i_tags_get_int(tags, name, code, &value)
+
+=category Tags
+
+Retrieve a tag specified by name or code as an integer.
+
+On success sets the i_color *I<value> to the color and returns true.
+
+On failure returns false.
+
+=cut
+*/
+
 int i_tags_get_int(i_img_tags *tags, char const *name, int code, int *value) {
   int index;
   i_img_tag *entry;
@@ -380,6 +501,20 @@ static int parse_color(char *data, char **end, i_color *value) {
   return 1;
 }
 
+/*
+=item i_tags_get_color(tags, name, code, &value)
+
+=category Tags
+
+Retrieve a tag specified by name or code as color.
+
+On success sets the i_color *I<value> to the color and returns true.
+
+On failure returns false.
+
+=cut
+*/
+
 int i_tags_get_color(i_img_tags *tags, char const *name, int code, 
                      i_color *value) {
   int index;
@@ -406,6 +541,16 @@ int i_tags_get_color(i_img_tags *tags, char const *name, int code,
   return 1;
 }
 
+/*
+=item i_tags_set_color(tags, name, code, &value)
+
+=category Tags
+
+Stores the given color as a tag with the given name and code.
+
+=cut
+*/
+
 int i_tags_set_color(i_img_tags *tags, char const *name, int code, 
                      i_color const *value) {
   char temp[80];
@@ -420,6 +565,26 @@ int i_tags_set_color(i_img_tags *tags, char const *name, int code,
   return i_tags_add(tags, name, code, temp, strlen(temp), 0);
 }
 
+/*
+=item i_tags_get_string(tags, name, code, value, value_size)
+
+=category Tags
+
+Retrieves a tag by name or code as a string.
+
+On success copies the string to value for a max of value_size and
+returns true.
+
+On failure returns false.
+
+value_size must be at least large enough for a string representation
+of an integer.
+
+The copied value is always NUL terminated.
+
+=cut
+*/
+
 int i_tags_get_string(i_img_tags *tags, char const *name, int code, 
                       char *value, size_t value_size) {
   int index;
@@ -448,6 +613,40 @@ int i_tags_get_string(i_img_tags *tags, char const *name, int code,
   return 1;
 }
 
+/*
+=item i_tags_set(tags, name, data, size)
+
+=category Tags
+
+Sets the given tag to the string I<data>
+
+=cut
+*/
+
+int
+i_tags_set(i_img_tags *tags, char const *name, char const *data, int size) {
+  i_tags_delbyname(tags, name);
+
+  return i_tags_add(tags, name, 0, data, size, 0);
+}
+
+/*
+=item i_tags_setn(tags, name, idata)
+
+=category Tags
+
+Sets the given tag to the integer I<idata>
+
+=cut
+*/
+
+int
+i_tags_setn(i_img_tags *tags, char const *name, int idata) {
+  i_tags_delbyname(tags, name);
+
+  return i_tags_addn(tags, name, 0, idata);
+}
+
 void i_tags_print(i_img_tags *tags) {
   int i;
   printf("Alloc %d\n", tags->alloc);
diff --git a/tga.c b/tga.c
index 2e37353..230be5b 100644 (file)
--- a/tga.c
+++ b/tga.c
@@ -1,4 +1,4 @@
-#include "imagei.h"
+#include "imageri.h"
 #include "log.h"
 #include "iolayer.h"
 
diff --git a/tiff.c b/tiff.c
index 9833cbc..4f2b0e6 100644 (file)
--- a/tiff.c
+++ b/tiff.c
@@ -1,7 +1,7 @@
-#include "image.h"
+#include "imager.h"
 #include "tiffio.h"
 #include "iolayer.h"
-#include "imagei.h"
+#include "imageri.h"
 
 /*
 =head1 NAME
index daf74b0..3719893 100644 (file)
--- a/trans2.c
+++ b/trans2.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
 #include "regmach.h"
 
 /*
diff --git a/typemap b/typemap
index 82d8a4a..f3d1738 100644 (file)
--- a/typemap
+++ b/typemap
@@ -1,7 +1,7 @@
 #i_img *                       T_PTR_NULL
 Imager::Color           T_PTROBJ
 Imager::Color::Float    T_PTROBJ
-Imager::ImgRaw          T_PTROBJ
+Imager::ImgRaw          T_IMAGER_IMAGE
 Imager::Font::TT       T_PTROBJ
 Imager::IO              T_PTROBJ
 Imager::Font::FT2       T_PTROBJ
@@ -14,6 +14,17 @@ undef_int            T_IV_U
 undef_neg_int           T_IV_NEGU
 HASH                   T_HVREF
 utf8_str               T_UTF8_STR
+
+# these types are for use by Inline, which can't handle types containing ::
+Imager__Color           T_PTROBJ_INV
+Imager__Color__Float    T_PTROBJ_INV
+Imager__ImgRaw          T_IMAGER_IMAGE
+Imager__FillHandle      T_PTROBJ_INV
+Imager__IO              T_PTROBJ_INV
+
+# mostly intended for non-Imager-core use
+Imager                  T_IMAGER_FULL_IMAGE
+
 #############################################################################
 INPUT
 T_PTR_NULL
@@ -27,6 +38,53 @@ T_AVREF
         else
             Perl_croak(aTHX_ \"$var is not an array reference\")
 
+# handles Imager objects rather than just raw objects
+T_IMAGER_IMAGE
+        if (sv_derived_from($arg, \"Imager::ImgRaw\")) {
+            IV tmp = SvIV((SV*)SvRV($arg));
+            $var = INT2PTR($type,tmp);
+        }
+        else if (sv_derived_from($arg, \"Imager\") && 
+                 SvTYPE(SvRV($arg)) == SVt_PVHV) {
+            HV *hv = (HV *)SvRV($arg);
+            SV **sv = hv_fetch(hv, \"IMG\", 3, 0);
+            if (sv && *sv && sv_derived_from(*sv, \"Imager::ImgRaw\")) {
+                IV tmp = SvIV((SV*)SvRV(*sv));
+                $var = INT2PTR($type,tmp);
+            }
+            else
+                Perl_croak(aTHX_ \"$var is not of type Imager::ImgRaw\");
+        }
+        else
+            Perl_croak(aTHX_ \"$var is not of type Imager::ImgRaw\");
+
+T_IMAGER_FULL_IMAGE
+        if (sv_derived_from($arg, \"Imager\") && 
+                 SvTYPE(SvRV($arg)) == SVt_PVHV) {
+            HV *hv = (HV *)SvRV($arg);
+            SV **sv = hv_fetch(hv, \"IMG\", 3, 0);
+            if (sv && *sv && sv_derived_from(*sv, \"Imager::ImgRaw\")) {
+                IV tmp = SvIV((SV*)SvRV(*sv));
+                $var = INT2PTR($type,tmp);
+            }
+            else
+                Perl_croak(aTHX_ \"$var is not of type Imager::ImgRaw\");
+        }
+        else
+            Perl_croak(aTHX_ \"$var is not of type Imager\");
+
+# same as T_PTROBJ, but replace __ with ::, the opposite of the way
+# xsubpp's processing works
+# this is to compensate for Inline's problem with type names containing ::
+T_PTROBJ_INV
+        if (sv_derived_from($arg, \"${(my $ntt=$ntype)=~s/__/::/g;\$ntt}\")) {
+            IV tmp = SvIV((SV*)SvRV($arg));
+            $var = INT2PTR($type,tmp);
+        }
+        else
+            croak(\"$var is not of type ${(my $ntt=$ntype)=~s/__/::/g;\$ntt}\");
+
+
 #############################################################################
 OUTPUT
 T_IV_U
@@ -37,3 +95,26 @@ T_IV_NEGU
        else sv_setiv($arg, (IV)$var);
 T_PTR_NULL
        sv_setiv($arg, (IV)$var);
+
+# same as T_PTROBJ
+T_IMAGER_IMAGE
+        sv_setref_pv($arg, \"Imager::ImgRaw\", (void*)$var);
+
+T_PTROBJ_INV
+        sv_setref_pv($arg, \"${(my $ntt=$ntype)=~s/__/::/g;\$ntt}\", (void*)$var);
+
+# ugh, the things we do for ease of use
+# this isn't suitable in some cases
+T_IMAGER_FULL_IMAGE
+        if ($var) {
+          SV *imobj = NEWSV(0, 0);
+          HV *hv = newHV();
+          SV *hvref;
+          SV *imgref;
+          sv_setref_pv(imobj, \"Imager::ImgRaw\", $var);
+          hv_store(hv, "IMG", 3, imobj, 0);
+          $arg = sv_2mortal(sv_bless(newRV((SV*)hv), gv_stashpv("Imager", 1)));
+        }
+        else {
+          $arg = &PL_sv_undef;
+        }
diff --git a/win32.c b/win32.c
index 1a3ed5c..ab9b8b0 100644 (file)
--- a/win32.c
+++ b/win32.c
@@ -1,5 +1,5 @@
 #define _WIN32_WINNT 0x500
-#include "image.h"
+#include "imager.h"
 #define STRICT
 #include <windows.h>