Skip to content
Browse files

- 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
  • Loading branch information...
1 parent cad360a commit 92bda6321b472bb18726d950da8833b950abf4ee Tony Cook committed Jan 10, 2006
Showing with 4,492 additions and 484 deletions.
  1. +42 −0 Changes
  2. +57 −0 CountColor/CountColor.pm
  3. +51 −0 CountColor/CountColor.xs
  4. +18 −0 CountColor/Makefile.PL
  5. +23 −0 CountColor/t/t00countcolor.t
  6. +32 −0 DynTest/DynTest.pm
  7. +29 −0 DynTest/DynTest.xs
  8. +18 −0 DynTest/Makefile.PL
  9. +49 −0 DynTest/linstretch.c
  10. +20 −0 DynTest/t/t00dyntest.t
  11. +110 −13 Imager.pm
  12. +11 −24 Imager.xs
  13. +31 −4 MANIFEST
  14. +41 −0 MANIFEST.SKIP
  15. +49 −26 Makefile.PL
  16. +18 −0 Mandelbrot/Makefile.PL
  17. +42 −0 Mandelbrot/Mandelbrot.pm
  18. +33 −0 Mandelbrot/Mandelbrot.xs
  19. +72 −0 Mandelbrot/mandel.c
  20. +18 −0 Mandelbrot/t/t00mandel.t
  21. +189 −0 apidocs.perl
  22. +1 −1 bmp.c
  23. +1 −1 color.c
  24. +1 −1 conv.c
  25. +1 −1 convert.c
  26. +1 −1 datatypes.c
  27. +125 −3 draw.c
  28. +1 −1 draw.h
  29. +2 −2 dynaload.c
  30. +13 −2 error.c
  31. +1 −1 ext.h
  32. +1 −1 feat.h
  33. +19 −3 fills.c
  34. +24 −16 filters.c
  35. +2 −1 font.c
  36. +1 −1 freetyp2.c
  37. +1 −1 gaussian.c
  38. +12 −12 gif.c
  39. +1 −1 hlines.c
  40. +63 −26 image.c
  41. +31 −282 image.h → imager.h
  42. +1 −1 imagei.h → imageri.h
  43. +271 −0 datatypes.h → imdatatypes.h
  44. +2 −2 imexif.h
  45. +454 −0 imext.c
  46. +163 −0 imext.h
  47. +11 −0 imextdef.h
  48. +119 −0 imexttypes.h
  49. +15 −3 img16.c
  50. +4 −2 imgdouble.c
  51. +33 −0 imperl.h
  52. +1 −1 jpeg.c
  53. +211 −0 lib/Imager/API.pm
  54. +1,007 −0 lib/Imager/APIRef.pm
  55. +125 −0 lib/Imager/ExtUtils.pm
  56. +73 −0 lib/Imager/Inline.pod
  57. +41 −3 lib/Imager/Transformations.pod
  58. +1 −1 limits.c
  59. +1 −1 map.c
  60. +2 −2 maskimg.c
  61. +36 −0 metafile.pl
  62. +18 −6 palimg.c
  63. +1 −1 plug.h
  64. +1 −1 png.c
  65. +2 −2 pnm.c
  66. +1 −1 polygon.c
  67. +48 −6 quant.c
  68. +1 −1 raw.c
  69. +1 −1 regmach.h
  70. +1 −1 rgb.c
  71. +1 −1 rotate.c
  72. +1 −1 t/t022double.t
  73. +72 −14 t/t66paste.t
  74. +231 −0 t/t82inline.t
  75. +200 −1 tags.c
  76. +1 −1 tga.c
  77. +2 −2 tiff.c
  78. +1 −1 trans2.c
  79. +82 −1 typemap
  80. +1 −1 win32.c
View
42 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
=================================================================
View
57 CountColor/CountColor.pm
@@ -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
+
+
+
View
51 CountColor/CountColor.xs
@@ -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;
+
View
18 CountColor/Makefile.PL
@@ -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);
+
+
View
23 CountColor/t/t00countcolor.t
@@ -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");
View
32 DynTest/DynTest.pm
@@ -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;
View
29 DynTest/DynTest.xs
@@ -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;
+
View
18 DynTest/Makefile.PL
@@ -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);
+
+
View
49 DynTest/linstretch.c
@@ -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);
+ }
+
+}
+
+
View
20 DynTest/t/t00dyntest.t
@@ -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");
+}
View
123 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,28 +573,76 @@ 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;
}
# Paste a region
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
View
35 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;
View
35 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
View
41 MANIFEST.SKIP
@@ -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$
View
75 Makefile.PL
@@ -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;
+}
View
18 Mandelbrot/Makefile.PL
@@ -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);
+
+
View
42 Mandelbrot/Mandelbrot.pm
@@ -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;
View
33 Mandelbrot/Mandelbrot.xs
@@ -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;
+
View
72 Mandelbrot/mandel.c
@@ -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]);
+ }
+ }
+}
View
18 Mandelbrot/t/t00mandel.t
@@ -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");
+}
View
189 apidocs.perl
@@ -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";
+ }
+}
View
2 bmp.c
@@ -1,5 +1,5 @@
#include <stdarg.h>
-#include "imagei.h"
+#include "imageri.h"
/*
=head1 NAME
View
2 color.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
#include <math.h>
/*
View
2 conv.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
/*
General convolution for 2d decoupled filters
View
2 convert.c
@@ -17,7 +17,7 @@ converting from RGBA to greyscale and back.
=cut
*/
-#include "image.h"
+#include "imager.h"
/*
View
2 datatypes.c
@@ -1,5 +1,5 @@
#include "imio.h"
-#include "datatypes.h"
+#include "imdatatypes.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
View
128 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,13 +552,35 @@ 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;
mm_log((1,"i_box_filled(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,val 0x%x)\n",im,x1,y1,x2,y2,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) {
View
2 draw.h
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
typedef struct {
int min,max;
View
4 dynaload.c
@@ -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,
View
15 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
View
2 ext.h
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
#ifndef IMAGER_EXT_H
#define IMAGER_EXT_H
View
2 feat.h
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
static char *i_format_list[]={
#ifdef HAVE_LIBJPEG
View
22 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 *
View
40 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.
View
3 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);
View
2 freetyp2.c
@@ -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
View
2 gaussian.c
@@ -1,4 +1,4 @@
-#include "image.h"
+#include "imager.h"
static float
gauss(int x,float std) {
View
24 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,15 +1838,15 @@ 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;
EGifCloseFile(gf);
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;
View
2 hlines.c
@@ -1,4 +1,4 @@
-#include "imagei.h"
+#include "imageri.h"
#include <stdlib.h>
#define OVERLAPPED(start1, end1, start2, end2) \
View
89 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;