switch to using size_t and i_img_dim strictly
authorTony Cook <tony@develop-help.com>
Tue, 14 Jun 2011 13:32:14 +0000 (23:32 +1000)
committerTony Cook <tony@develop-help.com>
Mon, 8 Aug 2011 12:14:13 +0000 (22:14 +1000)
Also, use double instead of float where the value is used in
calculating a co-ordinate, since float may not be able to represent an
image ordinate with sufficient precision

98 files changed:
Changes
CountColor/CountColor.xs
DynTest/linstretch.c
FT2/FT2.xs
FT2/freetyp2.c
FT2/imft2.h
Flines/Flines.xs
GIF/imgif.c
GIF/t/t40limit.t [new file with mode: 0644]
Imager.xs
JPEG/imexif.c
JPEG/imjpeg.c
JPEG/t/t20limit.t [new file with mode: 0644]
MANIFEST
Makefile.PL
Mandelbrot/mandel.c
PNG/impng.c
SGI/imsgi.c
SGI/t/30limit.t [new file with mode: 0644]
T1/T1.xs
T1/imt1.c
T1/imt1.h
TIFF/imtiff.c
W32/W32.pm
W32/W32.xs
W32/imw32.h
W32/win32.c
apidocs.perl
bmp.c
compose.im
conv.im
convert.im
datatypes.c
draw.c
draw.h
dynaload.c
dynfilt/dt2.c
dynfilt/dyntest.c
dynfilt/flines.c
dynfilt/mandelbrot.c
error.c
fileformatdocs/other.txt
fileformatdocs/spec-gif89a.txt [new file with mode: 0644]
fileformatdocs/tga_specs.pdf [new file with mode: 0755]
fileformatdocs/tgaffs.pdf [new file with mode: 0644]
fills.c
filters.im
flip.im
font.c
gaussian.im
hlines.c
image.c
imager.h
imageri.h
imdatatypes.h
imerror.h
imext.c
imext.h
imexttypes.h
img16.c
img8.c
imgdouble.c
io.c
iolayer.c
iolayert.h
lib/Imager/APIRef.pod
lib/Imager/Cookbook.pod
lib/Imager/Files.pod
limits.c
log.c
log.h
map.c
maskimg.c
palimg.c
paste.im
pnm.c
polygon.c
quant.c
raw.c
regmach.c
render.im
rotate.c
rubthru.im
scale.im
t/t01introvert.t
t/t021sixteen.t
t/t022double.t
t/t023palette.t
t/t1000files.t
t/t104ppm.t
t/t107bmp.t
t/t108tga.t
t/t64copyflip.t
testimg/tootall.ppm [new file with mode: 0644]
testimg/toowide.ppm [new file with mode: 0644]
tga.c
trans2.c
typemap

diff --git a/Changes b/Changes
index dcab208..0a2c13e 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,39 @@
 Imager release history.  Older releases can be found in Changes.old
 
+Imager 0.85
+===========
+
+Massive types re-work:
+
+ - the type used internally for pixel co-ordinates and image sizes is
+   now 64-bit on 64-bit platforms (at least sane ones).
+
+ - size_t is now used consistently for memory block sizes.
+
+ - since this changes the binary interface, the Imager API version has
+   been incremented.  Any module that uses the API will need to be
+   rebuilt.  In most cases that will be enough, but calls to any APIs
+   that take a pointer to image sizes may need source changes.
+
+ - you should be able to create very large images on 64-bit systems,
+   if you have enough memory.  Successfully created a 32768 x 49192 x
+   3 channel image, filled with a tiled image and scaled it.  The
+   unscaled image was also successfully saved to a JPEG.
+
+ - check the image size before attempting to write BMP, GIF, JPEG,
+   PNG, SGI, TGA, TIFF images.
+
+ - correctly handle reading TGA images over 32767 pixels wide or tall.
+
+Incidental changes:
+
+ - the gif_left and gif_top tags are now clamped to non-negative
+   values when writing a GIF image.
+
+ - removed dead callback read/write code
+
+The default maximum memory size when reading files is now 1G.
+
 Imager 0.84 - 20 Jun 2011
 ===========
 
index 41a0a55..711b2a8 100644 (file)
@@ -17,7 +17,8 @@ DEFINE_IMAGER_CALLBACKS;
 
 int
 count_color(i_img *im, i_color *color) {
-  int x, y, chan;
+  i_img_dim x, y;
+  int chan;
   i_color c;
   int count = 0;
 
index 7d2d8fa..6579e12 100644 (file)
@@ -29,14 +29,11 @@ saturate(int in) {
 void lin_stretch(i_img *im, int a, int b) {
 
   i_color rcolor;
-  int i,bytes,x,y;
-  int info[4];
+  i_img_dim x,y;
+  int i;
 
   
   /*   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);
index 4bd1801..97c037d 100644 (file)
@@ -22,6 +22,7 @@ FT2_DESTROY(font)
 int
 FT2_CLONE_SKIP(...)
     CODE:
+        (void)items;
         RETVAL = 1;
     OUTPUT:
         RETVAL
@@ -90,7 +91,7 @@ i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
         SV *text_sv
        int utf8
       PREINIT:
-        int bbox[BOUNDING_BOX_COUNT];
+        i_img_dim bbox[BOUNDING_BOX_COUNT];
         int i;
         char *text;
         STRLEN text_len;
@@ -117,7 +118,7 @@ i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
         int vlayout
         int utf8
       PREINIT:
-        int bbox[8];
+        i_img_dim bbox[8];
         int i;
       PPCODE:
 #ifdef SvUTF8
@@ -135,8 +136,8 @@ undef_int
 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
         Imager::Font::FT2x font
         Imager::ImgRaw im
-        int tx
-        int ty
+        i_img_dim tx
+        i_img_dim ty
         Imager::Color cl
         double cheight
         double cwidth
@@ -163,8 +164,8 @@ undef_int
 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
         Imager::Font::FT2x font
         Imager::ImgRaw im
-        int tx
-        int ty
+        i_img_dim tx
+        i_img_dim ty
         int channel
         double cheight
         double cwidth
@@ -190,12 +191,12 @@ i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout
 void
 ft2_transform_box(font, x0, x1, x2, x3)
         Imager::Font::FT2x font
-        int x0
-        int x1
-        int x2
-        int x3
+        i_img_dim x0
+        i_img_dim x1
+        i_img_dim x2
+        i_img_dim x3
       PREINIT:
-        int box[4];
+        i_img_dim box[4];
       PPCODE:
         box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
         ft2_transform_box(font, box);
@@ -214,8 +215,8 @@ i_ft2_has_chars(handle, text_sv, utf8)
         char *text;
         STRLEN len;
         char *work;
-        int count;
-        int i;
+        size_t count;
+        size_t i;
       PPCODE:
 #ifdef SvUTF8
         if (SvUTF8(text_sv))
@@ -241,7 +242,7 @@ i_ft2_face_name(handle)
         Imager::Font::FT2x handle
       PREINIT:
         char name[255];
-        int len;
+        size_t len;
       PPCODE:
         len = i_ft2_face_name(handle, name, sizeof(name));
         if (len) {
index 8d034f9..2249bba 100644 (file)
@@ -12,7 +12,7 @@ freetyp2.c - font support via the FreeType library version 2.
   if (!i_ft2_getdpi(font, &xdpi, &ydpi)) { error }
   double matrix[6];
   if (!i_ft2_settransform(font, matrix)) { error }
-  int bbox[BOUNDING_BOX_COUNT];
+  i_img_dim bbox[BOUNDING_BOX_COUNT];
   if (!i_ft2_bbox(font, cheight, cwidth, text, length, bbox, utf8)) { error }
   i_img *im = ...;
   i_color cl;
@@ -52,8 +52,8 @@ static void ft2_push_message(int code);
 static int ft2_initialized = 0;
 static FT_Library library;
 
-static int i_min(int a, int b);
-static int i_max(int a, int b);
+static i_img_dim i_min(i_img_dim a, i_img_dim b);
+static i_img_dim i_max(i_img_dim a, i_img_dim b);
 
 /*
 =item i_ft2_init(void)
@@ -318,7 +318,7 @@ int i_ft2_sethinting(FT2_Fonthandle *handle, int hinting) {
 }
 
 /*
-=item i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth, char *text, size_t len, int *bbox)
+=item i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth, char *text, size_t len, i_img_dim *bbox)
 
 Retrieves bounding box information for the font at the given 
 character width and height.  This ignores the transformation matrix.
@@ -329,9 +329,9 @@ Returns non-zero on success.
 */
 int
 i_ft2_bbox(FT2_Fonthandle *handle, double cheight, double cwidth, 
-           char const *text, size_t len, int *bbox, int utf8) {
+           char const *text, size_t len, i_img_dim *bbox, int utf8) {
   FT_Error error;
-  int width;
+  i_img_dim width;
   int index;
   int first;
   int ascent = 0, descent = 0;
@@ -439,7 +439,7 @@ too much hard work.
 
 =cut
 */
-void ft2_transform_box(FT2_Fonthandle *handle, int bbox[4]) {
+void ft2_transform_box(FT2_Fonthandle *handle, i_img_dim bbox[4]) {
   double work[8];
   double *matrix = handle->matrix;
   
@@ -466,7 +466,7 @@ bounding box in bbox[] that encloses both.
 
 =cut
 */
-static void expand_bounds(int bbox[4], int bbox2[4]) {
+static void expand_bounds(i_img_dim bbox[4], i_img_dim bbox2[4]) {
   bbox[0] = i_min(bbox[0], bbox2[0]);
   bbox[1] = i_min(bbox[1], bbox2[1]);
   bbox[2] = i_max(bbox[2], bbox2[2]);
@@ -474,7 +474,7 @@ static void expand_bounds(int bbox[4], int bbox2[4]) {
 }
 
 /*
-=item i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth, char *text, size_t len, int vlayout, int utf8, int *bbox)
+=item i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth, char *text, size_t len, int vlayout, int utf8, i_img_dim *bbox)
 
 Retrieves bounding box information for the font at the given 
 character width and height.
@@ -495,16 +495,16 @@ Returns non-zero on success.
 */
 int
 i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth, 
-           char const *text, size_t len, int vlayout, int utf8, int *bbox) {
+           char const *text, size_t len, int vlayout, int utf8, i_img_dim *bbox) {
   FT_Error error;
-  int width;
+  i_img_dim width;
   int index;
   int first;
-  int ascent = 0, descent = 0;
+  i_img_dim ascent = 0, descent = 0;
   int glyph_ascent, glyph_descent;
   FT_Glyph_Metrics *gm;
-  int work[4];
-  int bounds[4];
+  i_img_dim work[4];
+  i_img_dim bounds[4];
   double x = 0, y = 0;
   int i;
   FT_GlyphSlot slot;
@@ -641,13 +641,13 @@ Returns non-zero on success.
 =cut
 */
 int
-i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, const i_color *cl,
+i_ft2_text(FT2_Fonthandle *handle, i_img *im, i_img_dim tx, i_img_dim ty, const i_color *cl,
            double cheight, double cwidth, char const *text, size_t len,
           int align, int aa, int vlayout, int utf8) {
   FT_Error error;
   int index;
   FT_Glyph_Metrics *gm;
-  int bbox[BOUNDING_BOX_COUNT];
+  i_img_dim bbox[BOUNDING_BOX_COUNT];
   FT_GlyphSlot slot;
   int x, y;
   unsigned char *bmp;
@@ -790,10 +790,10 @@ Returns non-zero on success.
 */
 
 int
-i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, int channel,
+i_ft2_cp(FT2_Fonthandle *handle, i_img *im, i_img_dim tx, i_img_dim ty, int channel,
          double cheight, double cwidth, char const *text, size_t len, int align,
          int aa, int vlayout, int utf8) {
-  int bbox[8];
+  i_img_dim bbox[8];
   i_img *work;
   i_color cl, cl2;
   int x, y;
@@ -843,7 +843,8 @@ Returns the number of characters that were checked.
 
 =cut
 */
-int i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, size_t len, 
+size_t
+i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, size_t len, 
                     int utf8, char *out) {
   int count = 0;
   mm_log((1, "i_ft2_has_chars(handle %p, text %p, len %d, utf8 %d)\n", 
@@ -953,10 +954,12 @@ make_bmp_map(FT_Bitmap *bitmap, unsigned char *map) {
 Fills the given buffer with the Postscript Face name of the font,
 if there is one.
 
+Returns the number of bytes copied, including the terminating NUL.
+
 =cut
 */
 
-int
+size_t
 i_ft2_face_name(FT2_Fonthandle *handle, char *name_buf, size_t name_buf_size) {
 #if IM_HAS_FACE_NAME
   char const *name = FT_Get_Postscript_Name(handle->face);
@@ -1134,13 +1137,13 @@ i_ft2_set_mm_coords(FT2_Fonthandle *handle, int coord_count, const long *coords)
 #endif
 }
 
-static int
-i_min(int a, int b) {
+static i_img_dim
+i_min(i_img_dim a, i_img_dim b) {
   return a < b ? a : b;
 }
 
-static int
-i_max(int a, int b) {
+static i_img_dim
+i_max(i_img_dim a, i_img_dim b) {
   return a > b ? a : b;
 }
 
index b283c62..57b7129 100644 (file)
@@ -15,21 +15,23 @@ extern int i_ft2_getdpi(FT2_Fonthandle *handle, int *xdpi, int *ydpi);
 extern int i_ft2_settransform(FT2_Fonthandle *handle, const 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, size_t len, int *bbox, int utf8);
+                      char const *text, size_t len, i_img_dim *bbox, int utf8);
 extern int i_ft2_bbox_r(FT2_Fonthandle *handle, double cheight, double cwidth, 
-                     char const *text, size_t len, int vlayout, int utf8, int *bbox);
-extern int i_ft2_text(FT2_Fonthandle *handle, i_img *im, int tx, int ty, 
+                     char const *text, size_t len, int vlayout, int utf8, i_img_dim *bbox);
+extern int i_ft2_text(FT2_Fonthandle *handle, i_img *im, i_img_dim tx, i_img_dim ty, 
                       const i_color *cl, double cheight, double cwidth, 
                       char const *text, size_t len, int align, int aa, 
                       int vlayout, int utf8);
-extern int i_ft2_cp(FT2_Fonthandle *handle, i_img *im, int tx, int ty, 
+extern int i_ft2_cp(FT2_Fonthandle *handle, i_img *im, i_img_dim tx, i_img_dim ty, 
                     int channel, double cheight, double cwidth, 
                     char const *text, size_t len, int align, int aa, 
                    int vlayout, int utf8);
-extern int i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, size_t len,
+extern size_t
+i_ft2_has_chars(FT2_Fonthandle *handle, char const *text, size_t len,
                            int utf8, char *work);
-extern int i_ft2_face_name(FT2_Fonthandle *handle, char *name_buf, 
-                           size_t name_buf_size);
+extern size_t
+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,
@@ -43,5 +45,8 @@ extern int
 i_ft2_is_multiple_master(FT2_Fonthandle *handle);
 extern int
 i_ft2_set_mm_coords(FT2_Fonthandle *handle, int coord_count, const long *coords);
+
+void ft2_transform_box(FT2_Fonthandle *handle, i_img_dim bbox[4]);
+
 #endif
 
index 4b9164b..282be66 100644 (file)
@@ -26,19 +26,19 @@ saturate(int in) {
 void
 flines(i_img *im) {
   i_color vl;
-  int x,y;
+  i_img_dim x,y;
   
   for(y = 0; y < im->ysize; y ++) {
     for(x = 0; x < im->xsize; x ++ ) {
       i_gpix(im,x,y,&vl); 
                        if (!(y%2)) {
-                               float yf = y/(float)im->ysize;
+                               float yf = y/(double)im->ysize;
                                float mf = 1.2-0.8*yf;
                                vl.rgb.r = saturate(vl.rgb.r*mf);
                                vl.rgb.g = saturate(vl.rgb.g*mf);
                                vl.rgb.b = saturate(vl.rgb.b*mf);
                        } else {
-                               float yf = (im->ysize-y)/(float)im->ysize;
+                               float yf = (im->ysize-y)/(double)im->ysize;
                                float mf = 1.2-0.8*yf;
                                vl.rgb.r = saturate(vl.rgb.r*mf);
                                vl.rgb.g = saturate(vl.rgb.g*mf);
index 623a567..27668ef 100644 (file)
@@ -8,6 +8,7 @@
 #include <errno.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 
 /*
 =head1 NAME
@@ -61,8 +62,6 @@ functionality with giflib3.
 static char const *gif_error_msg(int code);
 static void gif_push_error(void);
 
-static int gif_read_callback(GifFileType *gft, GifByteType *buf, int length);
-
 /* Make some variables global, so we could access them faster: */
 
 static int
@@ -1244,7 +1243,6 @@ quantizing to the caller specified palette.
 
 static int
 has_common_palette(i_img **imgs, int count, i_quantize *quant) {
-  int size = quant->mc_count;
   int i;
   int imgn;
   char used[256];
@@ -1306,7 +1304,7 @@ quant_paletted(i_quantize *quant, i_img *img) {
   i_palidx *p = data;
   i_palidx trans[256];
   int i;
-  int x, y;
+  i_img_dim x, y;
 
   /* build a translation table */
   for (i = 0; i < i_colorcount(img); ++i) {
@@ -1379,7 +1377,7 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
   if (!i_tags_get_int(&imgs[0]->tags, "gif_screen_width", 0, &scrw))
     scrw = 0;
   if (!i_tags_get_int(&imgs[0]->tags, "gif_screen_height", 0, &scrh))
-    scrw = 0;
+    scrh = 0;
 
   anylocal = 0;
   localmaps = mymalloc(sizeof(int) * count);
@@ -1387,26 +1385,39 @@ i_writegif_low(i_quantize *quant, GifFileType *gf, i_img **imgs, int count) {
   glob_img_count = 0;
   glob_want_trans = 0;
   for (imgn = 0; imgn < count; ++imgn) {
+    i_img *im = imgs[imgn];
+    if (im->xsize > 0xFFFF || im->ysize > 0xFFFF) {
+      i_push_error(0, "image too large for GIF");
+      return 0;
+    }
+    
     posx = posy = 0;
-    i_tags_get_int(&imgs[imgn]->tags, "gif_left", 0, &posx);
-    i_tags_get_int(&imgs[imgn]->tags, "gif_top", 0, &posy);
-    if (imgs[imgn]->xsize + posx > scrw)
-      scrw = imgs[imgn]->xsize + posx;
-    if (imgs[imgn]->ysize + posy > scrh)
-      scrh = imgs[imgn]->ysize + posy;
-    if (!i_tags_get_int(&imgs[imgn]->tags, "gif_local_map", 0, localmaps+imgn))
+    i_tags_get_int(&im->tags, "gif_left", 0, &posx);
+    if (posx < 0) posx = 0;
+    i_tags_get_int(&im->tags, "gif_top", 0, &posy);
+    if (posy < 0) posy = 0;
+    if (im->xsize + posx > scrw)
+      scrw = im->xsize + posx;
+    if (im->ysize + posy > scrh)
+      scrh = im->ysize + posy;
+    if (!i_tags_get_int(&im->tags, "gif_local_map", 0, localmaps+imgn))
       localmaps[imgn] = 0;
     if (localmaps[imgn])
       anylocal = 1;
     else {
-      if (imgs[imgn]->channels == 4) {
+      if (im->channels == 4) {
         glob_want_trans = 1;
       }
-      glob_imgs[glob_img_count++] = imgs[imgn];
+      glob_imgs[glob_img_count++] = im;
     }
   }
   glob_want_trans = glob_want_trans && quant->transp != tr_none ;
 
+  if (scrw > 0xFFFF || scrh > 0xFFFF) {
+    i_push_error(0, "screen size too large for GIF");
+    return 0;
+  }
+
   orig_count = quant->mc_count;
   orig_size = quant->mc_size;
 
diff --git a/GIF/t/t40limit.t b/GIF/t/t40limit.t
new file mode 100644 (file)
index 0000000..d08126b
--- /dev/null
@@ -0,0 +1,88 @@
+#!perl -w
+use Imager;
+use Test::More tests => 22;
+use Imager::Test qw(is_image);
+
+{
+  # GIF files are limited to 0xFFFF x 0xFFFF pixels
+  {
+    my $im = Imager->new(xsize => 0x10000, ysize => 1);
+    my $data = '';
+    ok(!$im->write(data => \$data, type => "gif"),
+       "fail to write too wide an image");
+    is($im->errstr, "image too large for GIF",
+       "check error message");
+  }
+ SKIP:
+  {
+    my $im = Imager->new(xsize => 0xFFFF, ysize => 1);
+    $im->box(fill => { hatch => "check4x4" });
+    my $data = '';
+    ok($im->write(data => \$data, type => "gif"),
+       "write image at width limit");
+    my $im2 = Imager->new(data => $data, ftype => "gif");
+    ok($im2, "read it ok")
+      or skip("cannot load the wide image", 1);
+    is_image($im, $im2, "check we read what we wrote");
+    is($im->getwidth, 0xffff, "check width");
+    is($im->getheight, 1, "check height");
+  }
+  {
+    my $im = Imager->new(xsize => 1, ysize => 0x10000);
+    my $data = '';
+    ok(!$im->write(data => \$data, type => "gif"),
+       "fail to write too tall an image");
+    is($im->errstr, "image too large for GIF",
+       "check error message");
+  }
+ SKIP:
+  {
+    my $im = Imager->new(xsize => 1, ysize => 0xFFFF);
+    $im->box(fill => { hatch => "check2x2" });
+    my $data = '';
+    ok($im->write(data => \$data, type => "gif"),
+       "write image at width limit");
+    my $im2 = Imager->new(data => $data, ftype => "gif");
+    ok($im2, "read it ok")
+      or skip("cannot load the wide image", 1);
+    is_image($im, $im2, "check we read what we wrote");
+    is($im->getwidth, 1, "check width");
+    is($im->getheight, 0xffff, "check height");
+  }
+}
+{
+  my $im = Imager->new(xsize => 1, ysize => 1);
+  $im->settag(name => "gif_screen_width", value => 65536);
+  my $data = '';
+  ok(!$im->write(data => \$data, type => "gif"),
+     "save a with a large explicit screen width should fail");
+  is($im->errstr, "screen size too large for GIF",
+     "check error message");
+}
+{
+  my $im = Imager->new(xsize => 0x8000, ysize => 1);
+  $im->settag(name => "gif_left", value => 32768);
+  my $data = '';
+  ok(!$im->write(data => \$data, type => "gif"),
+     "save a with a large implicit screen width should fail");
+  is($im->errstr, "screen size too large for GIF",
+     "check error message");
+}
+{
+  my $im = Imager->new(xsize => 1, ysize => 1);
+  $im->settag(name => "gif_screen_height", value => 65536);
+  my $data = '';
+  ok(!$im->write(data => \$data, type => "gif"),
+     "save a with a large explicit screen height should fail");
+  is($im->errstr, "screen size too large for GIF",
+     "check error message");
+}
+{
+  my $im = Imager->new(xsize => 1, ysize => 0x8000);
+  $im->settag(name => "gif_top", value => 32768);
+  my $data = '';
+  ok(!$im->write(data => \$data, type => "gif"),
+     "save a with a large implicit screen height should fail");
+  is($im->errstr, "screen size too large for GIF",
+     "check error message");
+}
index 434e4e0..5b919d1 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -34,7 +34,7 @@ static int getstr(void *hv_t,char *key,char **store) {
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
-  mm_log((1,"getstr(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
+  mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
@@ -49,7 +49,7 @@ static int getint(void *hv_t,char *key,int *store) {
   SV** svpp;
   HV* hv=(HV*)hv_t;  
 
-  mm_log((1,"getint(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
+  mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
@@ -63,11 +63,11 @@ static int getdouble(void *hv_t,char* key,double *store) {
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
-  mm_log((1,"getdouble(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
+  mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
   svpp=hv_fetch(hv, key, strlen(key), 0);
-  *store=(float)SvNV(*svpp);
+  *store=(double)SvNV(*svpp);
   return 1;
 }
 
@@ -76,7 +76,7 @@ static int getvoid(void *hv_t,char* key,void **store) {
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
-  mm_log((1,"getvoid(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
+  mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
@@ -91,7 +91,7 @@ static int getobj(void *hv_t,char *key,char *type,void **store) {
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
-  mm_log((1,"getobj(hv_t 0x%X, key %s,type %s, store 0x%X)\n",hv_t,key,type,store));
+  mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
@@ -122,98 +122,6 @@ i_log_entry(char *string, int level) {
 }
 
 
-typedef struct i_reader_data_tag
-{
-  /* presumably a CODE ref or name of a sub */
-  SV *sv;
-} i_reader_data;
-
-/* used by functions that want callbacks */
-static int read_callback(char *userdata, char *buffer, int need, int want) {
-  dTHX;
-  i_reader_data *rd = (i_reader_data *)userdata;
-  int count;
-  int result;
-  SV *data;
-  dSP; dTARG = sv_newmortal();
-  /* thanks to Simon Cozens for help with the dTARG above */
-
-  ENTER;
-  SAVETMPS;
-  EXTEND(SP, 2);
-  PUSHMARK(SP);
-  PUSHi(want);
-  PUSHi(need);
-  PUTBACK;
-
-  count = perl_call_sv(rd->sv, G_SCALAR);
-
-  SPAGAIN;
-
-  if (count != 1)
-    croak("Result of perl_call_sv(..., G_SCALAR) != 1");
-
-  data = POPs;
-
-  if (SvOK(data)) {
-    STRLEN len;
-    char *ptr = SvPV(data, len);
-    if (len > want)
-      croak("Too much data returned in reader callback");
-    
-    memcpy(buffer, ptr, len);
-    result = len;
-  }
-  else {
-    result = -1;
-  }
-
-  PUTBACK;
-  FREETMPS;
-  LEAVE;
-
-  return result;
-}
-
-typedef struct
-{
-  SV *sv; /* a coderef or sub name */
-} i_writer_data;
-
-/* used by functions that want callbacks */
-static int write_callback(char *userdata, char const *data, int size) {
-  dTHX;
-  i_writer_data *wd = (i_writer_data *)userdata;
-  int count;
-  int success;
-  SV *sv;
-  dSP; 
-
-  ENTER;
-  SAVETMPS;
-  EXTEND(SP, 1);
-  PUSHMARK(SP);
-  XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
-  PUTBACK;
-
-  count = perl_call_sv(wd->sv, G_SCALAR);
-
-  SPAGAIN;
-
-  if (count != 1)
-    croak("Result of perl_call_sv(..., G_SCALAR) != 1");
-
-  sv = POPs;
-  success = SvTRUE(sv);
-
-
-  PUTBACK;
-  FREETMPS;
-  LEAVE;
-
-  return success;
-}
-
 #define CBDATA_BUFSIZE 8192
 
 struct cbdata {
@@ -873,7 +781,7 @@ validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
 typedef i_int_hlines *Imager__Internal__Hlines;
 
 static i_int_hlines *
-i_int_hlines_new(int start_y, int count_y, int start_x, int count_x) {
+i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
   i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
   i_int_init_hlines(result, start_y, count_y, start_x, count_x);
 
@@ -906,9 +814,9 @@ static int seg_compare(const void *vleft, const void *vright) {
 static SV *
 i_int_hlines_dump(i_int_hlines *hlines) {
   dTHX;
-  SV *dump = newSVpvf("start_y: %d limit_y: %d start_x: %d limit_x: %d\n",
-       hlines->start_y, hlines->limit_y, hlines->start_x, hlines->limit_x);
-  int y;
+  SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
+       i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
+  i_img_dim y;
   
   for (y = hlines->start_y; y < hlines->limit_y; ++y) {
     i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
@@ -918,10 +826,10 @@ i_int_hlines_dump(i_int_hlines *hlines) {
       if (entry->count)
         qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
 
-      sv_catpvf(dump, " %d (%d):", y, entry->count);
+      sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
       for (i = 0; i < entry->count; ++i) {
-        sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx
-                  entry->segs[i].x_limit);
+        sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx)
+                  i_DFc(entry->segs[i].x_limit));
       }
       sv_catpv(dump, "\n");
     }
@@ -932,6 +840,24 @@ i_int_hlines_dump(i_int_hlines *hlines) {
 
 #endif
 
+static off_t
+i_sv_off_t(pTHX_ SV *sv) {
+#if LSEEKSIZE > IVSIZE
+  return (off_t)SvNV(sv);
+#else
+  return (off_t)SvIV(sv);
+#endif
+}
+
+static SV *
+i_new_sv_off_t(pTHX_ off_t off) {
+#if LSEEKSIZE > IVSIZE
+  return newSVnv(off);
+#else
+  return newSViv(off);
+#endif
+}
+
 static im_pl_ext_funcs im_perl_funcs =
 {
   IMAGER_PL_API_VERSION,
@@ -1085,8 +1011,8 @@ MODULE = Imager           PACKAGE = Imager::ImgRaw        PREFIX = IIM_
 
 Imager::ImgRaw
 IIM_new(x,y,ch)
-               int     x
-              int     y
+               i_img_dim     x
+              i_img_dim     y
               int     ch
 
 void
@@ -1164,20 +1090,21 @@ io_slurp(ig)
 
 undef_int
 i_set_image_file_limits(width, height, bytes)
-       int width
-       int height
-       int bytes
+       i_img_dim width
+       i_img_dim height
+       size_t bytes
 
 void
 i_get_image_file_limits()
       PREINIT:
-        int width, height, bytes;
+        i_img_dim width, height;
+       size_t bytes;
       PPCODE:
         if (i_get_image_file_limits(&width, &height, &bytes)) {
          EXTEND(SP, 3);
           PUSHs(sv_2mortal(newSViv(width)));
           PUSHs(sv_2mortal(newSViv(height)));
-          PUSHs(sv_2mortal(newSViv(bytes)));
+          PUSHs(sv_2mortal(newSVuv(bytes)));
         }
 
 MODULE = Imager                PACKAGE = Imager::IO    PREFIX = i_io_
@@ -1206,10 +1133,10 @@ void
 i_io_read(ig, buffer_sv, size)
        Imager::IO ig
        SV *buffer_sv
-       int size
+       IV size
       PREINIT:
         void *buffer;
-       int result;
+       ssize_t result;
       PPCODE:
         if (size <= 0)
          croak("size negative in call to i_io_read()");
@@ -1237,11 +1164,11 @@ i_io_read(ig, buffer_sv, size)
 void
 i_io_read2(ig, size)
        Imager::IO ig
-       int size
+       IV size
       PREINIT:
        SV *buffer_sv;
         void *buffer;
-       int result;
+       ssize_t result;
       PPCODE:
         if (size <= 0)
          croak("size negative in call to i_io_read2()");
@@ -1260,10 +1187,10 @@ i_io_read2(ig, size)
          SvREFCNT_dec(buffer_sv);
         }
 
-int
+off_t
 i_io_seek(ig, position, whence)
        Imager::IO ig
-       long position
+       off_t position
        int whence
 
 int
@@ -1277,6 +1204,7 @@ i_io_DESTROY(ig)
 int
 i_io_CLONE_SKIP(...)
     CODE:
+        (void)items; /* avoid unused warning for XS variable */
        RETVAL = 1;
     OUTPUT:
        RETVAL
@@ -1303,27 +1231,27 @@ i_img_new()
 Imager::ImgRaw
 i_img_empty(im,x,y)
     Imager::ImgRaw     im
-               int     x
-              int     y
+               i_img_dim     x
+              i_img_dim     y
 
 Imager::ImgRaw
 i_img_empty_ch(im,x,y,ch)
     Imager::ImgRaw     im
-               int     x
-              int     y
+               i_img_dim     x
+              i_img_dim     y
               int     ch
 
 Imager::ImgRaw
 i_sametype(im, x, y)
     Imager::ImgRaw im
-               int x
-               int y
+               i_img_dim x
+               i_img_dim y
 
 Imager::ImgRaw
 i_sametype_chans(im, x, y, channels)
     Imager::ImgRaw im
-               int x
-               int y
+               i_img_dim x
+               i_img_dim y
                int channels
 
 int
@@ -1357,7 +1285,7 @@ void
 i_img_info(im)
     Imager::ImgRaw     im
             PREINIT:
-              int     info[4];
+              i_img_dim     info[4];
             PPCODE:
               i_img_info(im,info);
                EXTEND(SP, 4);
@@ -1423,67 +1351,67 @@ i_img_is_monochrome(im)
 void
 i_line(im,x1,y1,x2,y2,val,endp)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
      Imager::Color     val
               int     endp
 
 void
 i_line_aa(im,x1,y1,x2,y2,val,endp)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
      Imager::Color     val
               int     endp
 
 void
 i_box(im,x1,y1,x2,y2,val)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
      Imager::Color     val
 
 void
 i_box_filled(im,x1,y1,x2,y2,val)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
           Imager::Color    val
 
 int
 i_box_filledf(im,x1,y1,x2,y2,val)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
           Imager::Color::Float    val
 
 void
 i_box_cfill(im,x1,y1,x2,y2,fill)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
           Imager::FillHandle    fill
 
 void
 i_arc(im,x,y,rad,d1,d2,val)
     Imager::ImgRaw     im
-              int     x
-              int     y
-             float     rad
-             float     d1
-             float     d2
+              i_img_dim     x
+              i_img_dim     y
+             double     rad
+             double     d1
+             double     d2
           Imager::Color    val
 
 void
@@ -1499,11 +1427,11 @@ i_arc_aa(im,x,y,rad,d1,d2,val)
 void
 i_arc_cfill(im,x,y,rad,d1,d2,fill)
     Imager::ImgRaw     im
-              int     x
-              int     y
-             float     rad
-             float     d1
-             float     d2
+              i_img_dim     x
+              i_img_dim     y
+             double     rad
+             double     d1
+             double     d2
           Imager::FillHandle    fill
 
 void
@@ -1520,9 +1448,9 @@ i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
 void
 i_circle_aa(im,x,y,rad,val)
     Imager::ImgRaw     im
-            float     x
-            float     y
-             float     rad
+            double     x
+            double     y
+             double     rad
           Imager::Color    val
 
 int
@@ -1547,8 +1475,8 @@ i_arc_out(im,x,y,rad,d1,d2,val)
             i_img_dim     x
             i_img_dim     y
              i_img_dim     rad
-            float d1
-            float d2
+            double d1
+            double d2
           Imager::Color    val
 
 int
@@ -1557,8 +1485,8 @@ i_arc_out_aa(im,x,y,rad,d1,d2,val)
             i_img_dim     x
             i_img_dim     y
              i_img_dim     rad
-            float d1
-            float d2
+            double d1
+            double d2
           Imager::Color    val
 
 
@@ -1673,30 +1601,30 @@ i_poly_aa_cfill(im,xc,yc,fill)
 undef_int
 i_flood_fill(im,seedx,seedy,dcol)
     Imager::ImgRaw     im
-              int     seedx
-              int     seedy
+              i_img_dim     seedx
+              i_img_dim     seedy
      Imager::Color     dcol
 
 undef_int
 i_flood_cfill(im,seedx,seedy,fill)
     Imager::ImgRaw     im
-              int     seedx
-              int     seedy
+              i_img_dim     seedx
+              i_img_dim     seedy
      Imager::FillHandle     fill
 
 undef_int
 i_flood_fill_border(im,seedx,seedy,dcol, border)
     Imager::ImgRaw     im
-              int     seedx
-              int     seedy
+              i_img_dim     seedx
+              i_img_dim     seedy
      Imager::Color     dcol
      Imager::Color     border
 
 undef_int
 i_flood_cfill_border(im,seedx,seedy,fill, border)
     Imager::ImgRaw     im
-              int     seedx
-              int     seedy
+              i_img_dim     seedx
+              i_img_dim     seedy
      Imager::FillHandle     fill
      Imager::Color     border
 
@@ -1705,24 +1633,24 @@ void
 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
     Imager::ImgRaw     im
     Imager::ImgRaw     src
-              int     x1
-              int     y1
-              int     x2
-              int     y2
-              int     tx
-              int     ty
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
+              i_img_dim     tx
+              i_img_dim     ty
 
 
 void
 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
     Imager::ImgRaw     im
     Imager::ImgRaw     src
-              int     x1
-              int     y1
-              int     x2
-              int     y2
-              int     tx
-              int     ty
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
+              i_img_dim     tx
+              i_img_dim     ty
      Imager::Color     trans
 
 Imager::ImgRaw
@@ -1734,23 +1662,23 @@ undef_int
 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
     Imager::ImgRaw     im
     Imager::ImgRaw     src
-              int     tx
-              int     ty
-              int     src_minx
-              int     src_miny
-              int     src_maxx
-              int     src_maxy
+              i_img_dim     tx
+              i_img_dim     ty
+              i_img_dim     src_minx
+              i_img_dim     src_miny
+              i_img_dim     src_maxx
+              i_img_dim     src_maxy
 
 undef_int
 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
     Imager::ImgRaw out
     Imager::ImgRaw src
-       int out_left
-       int out_top
-       int src_left
-       int src_top
-       int width
-       int height
+       i_img_dim out_left
+       i_img_dim out_top
+       i_img_dim src_left
+       i_img_dim src_top
+       i_img_dim width
+       i_img_dim height
        int combine
        double opacity
 
@@ -1759,14 +1687,14 @@ i_compose_mask(out, src, mask, out_left, out_top, src_left, src_top, mask_left,
     Imager::ImgRaw out
     Imager::ImgRaw src
     Imager::ImgRaw mask
-       int out_left
-       int out_top
-       int src_left
-       int src_top
-       int mask_left
-       int mask_top
-       int width
-       int height
+       i_img_dim out_left
+       i_img_dim out_top
+       i_img_dim src_left
+       i_img_dim src_top
+       i_img_dim mask_left
+       i_img_dim mask_top
+       i_img_dim width
+       i_img_dim height
        int combine
        double opacity
 
@@ -1851,8 +1779,8 @@ i_rotate_exact(im, amount, ...)
 Imager::ImgRaw
 i_matrix_transform(im, xsize, ysize, matrix, ...)
     Imager::ImgRaw      im
-               int      xsize
-               int      ysize
+               i_img_dim      xsize
+               i_img_dim      ysize
       PREINIT:
         double matrix[9];
         AV *av;
@@ -1899,7 +1827,7 @@ i_gaussian(im,stdev)
 void
 i_unsharp_mask(im,stdev,scale)
     Imager::ImgRaw     im
-            float     stdev
+            double    stdev
              double    scale
 
 int
@@ -2040,9 +1968,6 @@ _is_color_object(sv)
     OUTPUT:
         RETVAL
 
-#ifdef HAVE_LIBT1
-#endif 
-
 #ifdef HAVE_LIBTT
 
 
@@ -2062,6 +1987,7 @@ TT_DESTROY(handle)
 int
 TT_CLONE_SKIP(...)
     CODE:
+        (void)items; /* avoid unused warning */
         RETVAL = 1;
     OUTPUT:
         RETVAL
@@ -2074,10 +2000,10 @@ undef_int
 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
   Imager::Font::TT     handle
     Imager::ImgRaw     im
-              int     xb
-              int     yb
+              i_img_dim     xb
+              i_img_dim     yb
      Imager::Color     cl
-             float     points
+             double     points
              SV *     str_sv
               int     smooth
                int     utf8
@@ -2101,10 +2027,10 @@ undef_int
 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
   Imager::Font::TT     handle
     Imager::ImgRaw     im
-              int     xb
-              int     yb
+              i_img_dim     xb
+              i_img_dim     yb
               int     channel
-             float     points
+             double     points
              SV *     str_sv
               int     smooth
                int     utf8
@@ -2127,11 +2053,12 @@ i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
 void
 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
   Imager::Font::TT     handle
-            float     point
+            double     point
               SV*    str_sv
                int     utf8
             PREINIT:
-              int     cords[BOUNDING_BOX_COUNT],rc;
+              i_img_dim cords[BOUNDING_BOX_COUNT];
+              int rc;
                char *  str;
                STRLEN len;
                int i;
@@ -2157,8 +2084,8 @@ i_tt_has_chars(handle, text_sv, utf8)
         char const *text;
         STRLEN len;
         char *work;
-        int count;
-        int i;
+        size_t count;
+        size_t i;
       PPCODE:
 #ifdef SvUTF8
         if (SvUTF8(text_sv))
@@ -2188,12 +2115,12 @@ i_tt_face_name(handle)
         Imager::Font::TT handle
       PREINIT:
         char name[255];
-        int len;
+        size_t len;
       PPCODE:
         len = i_tt_face_name(handle, name, sizeof(name));
         if (len) {
           EXTEND(SP, 1);
-          PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
+          PUSHs(sv_2mortal(newSVpv(name, len-1)));
         }
 
 void
@@ -2205,7 +2132,7 @@ i_tt_glyph_name(handle, text_sv, utf8 = 0)
         char const *text;
         STRLEN work_len;
         size_t len;
-        int outsize;
+        size_t outsize;
         char name[255];
       PPCODE:
 #ifdef SvUTF8
@@ -2281,8 +2208,8 @@ i_writeppm_wiol(im, ig)
 Imager::ImgRaw
 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
         Imager::IO     ig
-              int     x
-              int     y
+              i_img_dim     x
+              i_img_dim     y
               int     datachannels
               int     storechannels
               int     intrl
@@ -2330,20 +2257,20 @@ i_readtga_wiol(ig, length)
 Imager::ImgRaw
 i_scaleaxis(im,Value,Axis)
     Imager::ImgRaw     im
-             float     Value
+             double     Value
               int     Axis
 
 Imager::ImgRaw
 i_scale_nn(im,scx,scy)
     Imager::ImgRaw     im
-             float     scx
-             float     scy
+             double    scx
+             double    scy
 
 Imager::ImgRaw
 i_scale_mixing(im, width, height)
     Imager::ImgRaw     im
-              int     width
-              int     height
+              i_img_dim     width
+              i_img_dim     height
 
 Imager::ImgRaw
 i_haar(im)
@@ -2377,8 +2304,8 @@ i_transform(im,opx,opy,parm)
     Imager::ImgRaw     im
              PREINIT:
              double* parm;
-             int*    opx;
-             int*    opy;
+             int *opx;
+             int *opy;
              int     opxl;
              int     opyl;
              int     parmlen;
@@ -2431,8 +2358,8 @@ i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
        AV *av_in_imgs
        int channels
             PREINIT:
-             int width;
-             int height;
+             i_img_dim width;
+             i_img_dim height;
             struct rm_op *ops;
             STRLEN ops_len;
             int ops_count;
@@ -2536,9 +2463,9 @@ i_bumpmap(im,bump,channel,light_x,light_y,strength)
     Imager::ImgRaw     im
     Imager::ImgRaw     bump
                int     channel
-               int     light_x
-               int     light_y
-               int     strength
+         i_img_dim     light_x
+         i_img_dim     light_y
+         i_img_dim     strength
 
 
 void
@@ -2546,11 +2473,11 @@ i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
     Imager::ImgRaw     im
     Imager::ImgRaw     bump
                int     channel
-               int     tx
-               int     ty
-             float     Lx
-             float     Ly
-             float     Lz
+               i_img_dim     tx
+               i_img_dim     ty
+             double     Lx
+             double     Ly
+             double     Lz
              float     cd
              float     cs
              float     n
@@ -2568,14 +2495,14 @@ i_postlevels(im,levels)
 void
 i_mosaic(im,size)
     Imager::ImgRaw     im
-               int     size
+         i_img_dim     size
 
 void
 i_watermark(im,wmark,tx,ty,pixdiff)
     Imager::ImgRaw     im
     Imager::ImgRaw     wmark
-               int     tx
-               int     ty
+               i_img_dim     tx
+               i_img_dim     ty
                int     pixdiff
 
 
@@ -2607,8 +2534,8 @@ i_gradgen(im, ...)
     Imager::ImgRaw     im
       PREINIT:
        int num;
-       int *xo;
-       int *yo;
+       i_img_dim *xo;
+       i_img_dim *yo;
         i_color *ival;
        int dmeasure;
        int i;
@@ -2634,12 +2561,12 @@ i_gradgen(im, ...)
        num = num <= av_len(ac) ? num : av_len(ac);
        num++; 
        if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
-       xo = mymalloc( sizeof(int) * num );
-       yo = mymalloc( sizeof(int) * num );
+       xo = mymalloc( sizeof(i_img_dim) * num );
+       yo = mymalloc( sizeof(i_img_dim) * num );
        ival = mymalloc( sizeof(i_color) * num );
        for(i = 0; i<num; i++) {
-         xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
-         yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
+         xo[i]   = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
+         yo[i]   = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
           sv = *av_fetch(ac, i, 0);
          if ( !sv_derived_from(sv, "Imager::Color") ) {
            free(axx); free(ayy); free(ac);
@@ -2755,8 +2682,8 @@ i_nearest_color(im, ...)
     Imager::ImgRaw     im
       PREINIT:
        int num;
-       int *xo;
-       int *yo;
+       i_img_dim *xo;
+       i_img_dim *yo;
         i_color *ival;
        int dmeasure;
        int i;
@@ -2782,12 +2709,12 @@ i_nearest_color(im, ...)
        num = num <= av_len(ac) ? num : av_len(ac);
        num++; 
        if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
-       xo = mymalloc( sizeof(int) * num );
-       yo = mymalloc( sizeof(int) * num );
+       xo = mymalloc( sizeof(i_img_dim) * num );
+       yo = mymalloc( sizeof(i_img_dim) * num );
        ival = mymalloc( sizeof(i_color) * num );
        for(i = 0; i<num; i++) {
-         xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
-         yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
+         xo[i]   = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
+         yo[i]   = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
           sv = *av_fetch(ac, i, 0);
          if ( !sv_derived_from(sv, "Imager::Color") ) {
            free(axx); free(ayy); free(ac);
@@ -2859,8 +2786,8 @@ DSO_call(handle,func_index,hv)
 SV *
 i_get_pixel(im, x, y)
        Imager::ImgRaw im
-       int x
-       int y;
+       i_img_dim x
+       i_img_dim y;
       PREINIT:
         i_color *color;
       CODE:
@@ -2880,14 +2807,14 @@ i_get_pixel(im, x, y)
 int
 i_ppix(im, x, y, cl)
         Imager::ImgRaw im
-        int x
-        int y
+        i_img_dim x
+        i_img_dim y
         Imager::Color cl
 
 Imager::ImgRaw
 i_img_pal_new(x, y, channels, maxpal)
-       int     x
-        int    y
+       i_img_dim x
+        i_img_dim y
         int     channels
        int     maxpal
 
@@ -2920,9 +2847,9 @@ i_img_to_rgb(src)
 void
 i_gpal(im, l, r, y)
         Imager::ImgRaw  im
-        int     l
-        int     r
-        int     y
+        i_img_dim     l
+        i_img_dim     r
+        i_img_dim     y
       PREINIT:
         i_palidx *work;
         int count, i;
@@ -2952,8 +2879,8 @@ i_gpal(im, l, r, y)
 int
 i_ppal(im, l, y, ...)
         Imager::ImgRaw  im
-        int     l
-        int     y
+        i_img_dim     l
+        i_img_dim     y
       PREINIT:
         i_palidx *work;
         int i;
@@ -2976,8 +2903,8 @@ i_ppal(im, l, y, ...)
 int
 i_ppal_p(im, l, y, data)
         Imager::ImgRaw  im
-        int     l
-        int     y
+        i_img_dim     l
+        i_img_dim     y
         SV *data
       PREINIT:
         i_palidx const *work;
@@ -3126,14 +3053,14 @@ i_img_virtual(im)
 void
 i_gsamp(im, l, r, y, ...)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
       PREINIT:
         int *chans;
         int chan_count;
         i_sample_t *data;
-        int count, i;
+        i_img_dim count, i;
       PPCODE:
         if (items < 5)
           croak("No channel numbers supplied to g_samp()");
@@ -3166,17 +3093,17 @@ i_gsamp(im, l, r, y, ...)
 undef_neg_int
 i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
        int bits
        AV *target
-       int offset
+       STRLEN offset
       PREINIT:
         int *chans;
         int chan_count;
         unsigned *data;
-        int count, i;
+        i_img_dim count, i;
       CODE:
        i_clear_error();
         if (items < 8)
@@ -3204,8 +3131,8 @@ i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
 undef_neg_int
 i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
         Imager::ImgRaw im
-        int l
-        int y
+        i_img_dim l
+        i_img_dim y
        int bits
        SV *channels_sv
        AV *data_av
@@ -3214,10 +3141,10 @@ i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count
       PREINIT:
        int chan_count;
        int *channels;
-       int data_count;
-       int data_used;
+       STRLEN data_count;
+       size_t data_used;
        unsigned *data;
-       int i;
+       ptrdiff_t i;
       CODE:
        i_clear_error();
        if (SvOK(channels_sv)) {
@@ -3269,10 +3196,10 @@ i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count
 Imager::ImgRaw
 i_img_masked_new(targ, mask, x, y, w, h)
         Imager::ImgRaw targ
-        int x
-        int y
-        int w
-        int h
+        i_img_dim x
+        i_img_dim y
+        i_img_dim w
+        i_img_dim h
       PREINIT:
         i_img *mask;
       CODE:
@@ -3292,13 +3219,13 @@ i_img_masked_new(targ, mask, x, y, w, h)
 int
 i_plin(im, l, y, ...)
         Imager::ImgRaw  im
-        int     l
-        int     y
+        i_img_dim     l
+        i_img_dim     y
       PREINIT:
         i_color *work;
-        int i;
+        STRLEN i;
         STRLEN len;
-        int count;
+        size_t count;
       CODE:
         if (items > 3) {
           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
@@ -3336,21 +3263,21 @@ i_plin(im, l, y, ...)
 int
 i_ppixf(im, x, y, cl)
         Imager::ImgRaw im
-        int x
-        int y
+        i_img_dim x
+        i_img_dim y
         Imager::Color::Float cl
 
 void
 i_gsampf(im, l, r, y, ...)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
       PREINIT:
         int *chans;
         int chan_count;
         i_fsample_t *data;
-        int count, i;
+        i_img_dim count, i;
       PPCODE:
         if (items < 5)
           croak("No channel numbers supplied to g_sampf()");
@@ -3383,13 +3310,13 @@ i_gsampf(im, l, r, y, ...)
 int
 i_plinf(im, l, y, ...)
         Imager::ImgRaw  im
-        int     l
-        int     y
+        i_img_dim     l
+        i_img_dim     y
       PREINIT:
         i_fcolor *work;
-        int i;
+        i_img_dim i;
         STRLEN len;
-        int count;
+        size_t count;
       CODE:
         if (items > 3) {
           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
@@ -3428,8 +3355,8 @@ i_plinf(im, l, y, ...)
 SV *
 i_gpixf(im, x, y)
        Imager::ImgRaw im
-       int x
-       int y;
+       i_img_dim x
+       i_img_dim y;
       PREINIT:
         i_fcolor *color;
       CODE:
@@ -3448,12 +3375,12 @@ i_gpixf(im, x, y)
 void
 i_glin(im, l, r, y)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
       PREINIT:
         i_color *vals;
-        int count, i;
+        i_img_dim count, i;
       PPCODE:
         if (l < r) {
           vals = mymalloc((r-l) * sizeof(i_color));
@@ -3480,12 +3407,12 @@ i_glin(im, l, r, y)
 void
 i_glinf(im, l, r, y)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
       PREINIT:
         i_fcolor *vals;
-        int count, i;
+        i_img_dim count, i;
         i_fcolor zero;
       PPCODE:
        for (i = 0; i < MAXCHANNELS; ++i)
@@ -3515,8 +3442,8 @@ i_glinf(im, l, r, y)
 
 Imager::ImgRaw
 i_img_16_new(x, y, ch)
-        int x
-        int y
+        i_img_dim x
+        i_img_dim y
         int ch
 
 Imager::ImgRaw
@@ -3525,8 +3452,8 @@ i_img_to_rgb16(im)
 
 Imager::ImgRaw
 i_img_double_new(x, y, ch)
-        int x
-        int y
+        i_img_dim x
+        i_img_dim y
         int ch
 
 Imager::ImgRaw
@@ -3704,6 +3631,7 @@ IFILL_DESTROY(fill)
 int
 IFILL_CLONE_SKIP(...)
     CODE:
+        (void)items; /* avoid unused warning for XS variable */
         RETVAL = 1;
     OUTPUT:
         RETVAL
@@ -3726,8 +3654,8 @@ i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
         Imager::Color bg
         int combine
         int hatch
-        int dx
-        int dy
+        i_img_dim dx
+        i_img_dim dy
       PREINIT:
         unsigned char *cust_hatch;
         STRLEN len;
@@ -3747,8 +3675,8 @@ i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
         Imager::Color::Float bg
         int combine
         int hatch
-        int dx
-        int dy
+        i_img_dim dx
+        i_img_dim dy
       PREINIT:
         unsigned char *cust_hatch;
         STRLEN len;
@@ -3765,8 +3693,8 @@ i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
 Imager::FillHandle
 i_new_fill_image(src, matrix, xoff, yoff, combine)
         Imager::ImgRaw src
-        int xoff
-        int yoff
+        i_img_dim xoff
+        i_img_dim yoff
         int combine
       PREINIT:
         double matrix[9];
@@ -3809,9 +3737,9 @@ i_int_hlines_testing()
 
 Imager::Internal::Hlines
 i_int_hlines_new(start_y, count_y, start_x, count_x)
-       int start_y
+       i_img_dim start_y
        int count_y
-       int start_x
+       i_img_dim start_x
        int count_x
 
 Imager::Internal::Hlines
@@ -3821,9 +3749,9 @@ i_int_hlines_new_img(im)
 void
 i_int_hlines_add(hlines, y, minx, width)
        Imager::Internal::Hlines hlines
-       int y
-       int minx
-       int width
+       i_img_dim y
+       i_img_dim minx
+       i_img_dim width
 
 void
 i_int_hlines_DESTROY(hlines)
@@ -3835,7 +3763,6 @@ i_int_hlines_dump(hlines)
 
 int
 i_int_hlines_CLONE_SKIP(cls)
-       SV *cls
 
 #endif
 
index 9b184a9..07f75b8 100644 (file)
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 #include <float.h>
 #include <string.h>
+#include <stdio.h>
 
 /*
 =head1 NAME
index 6854cb5..eaf9a5d 100644 (file)
@@ -33,11 +33,15 @@ Reads and writes JPEG images
 #include "jerror.h"
 #include <errno.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include "imexif.h"
 
 #define JPEG_APP13       0xED    /* APP13 marker code */
 #define JPEG_APP1 (JPEG_APP0 + 1)
 #define JPGS 16384
 
+#define JPEG_DIM_MAX JPEG_MAX_DIMENSION
+
 static unsigned char fake_eoi[]={(JOCTET) 0xFF,(JOCTET) JPEG_EOI};
 
 /* Bad design right here */
@@ -99,7 +103,7 @@ wiol_fill_input_buffer(j_decompress_ptr cinfo) {
   wiol_src_ptr src = (wiol_src_ptr) cinfo->src;
   ssize_t nbytes; /* We assume that reads are "small" */
   
-  mm_log((1,"wiol_fill_input_buffer(cinfo 0x%p)\n", cinfo));
+  mm_log((1,"wiol_fill_input_buffer(cinfo %p)\n", cinfo));
   
   nbytes = src->data->readcb(src->data, src->buffer, JPGS);
   
@@ -214,7 +218,7 @@ wiol_empty_output_buffer(j_compress_ptr cinfo) {
   ssize_t nbytes     = JPGS - dest->pub.free_in_buffer;
   */
 
-  mm_log((1,"wiol_empty_output_buffer(cinfo 0x%p)\n", cinfo));
+  mm_log((1,"wiol_empty_output_buffer(cinfo %p)\n", cinfo));
   rc = dest->data->writecb(dest->data, dest->buffer, JPGS);
 
   if (rc != JPGS) { /* XXX: Should raise some jpeg error */
@@ -392,7 +396,7 @@ i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
   int channels;
   volatile int src_set = 0;
 
-  mm_log((1,"i_readjpeg_wiol(data 0x%p, length %d,iptc_itext 0x%p)\n", data, length, iptc_itext));
+  mm_log((1,"i_readjpeg_wiol(data %p, length %d,iptc_itext %p)\n", data, length, iptc_itext));
 
   i_clear_error();
 
@@ -589,6 +593,11 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
   
   i_clear_error();
 
+  if (im->xsize > JPEG_DIM_MAX || im->ysize > JPEG_DIM_MAX) {
+    i_push_error(0, "image too large for JPEG");
+    return 0;
+  }
+
   if (!(im->channels==1 || im->channels==3)) { 
     want_channels = im->channels - 1;
   }
diff --git a/JPEG/t/t20limit.t b/JPEG/t/t20limit.t
new file mode 100644 (file)
index 0000000..3a73805
--- /dev/null
@@ -0,0 +1,54 @@
+#!perl -w
+use strict;
+use Imager;
+use Test::More tests => 12;
+
+my $max_dim = 65500;
+
+{
+  # JPEG files are limited to 0xFFFF x 0xFFFF pixels
+  # but libjpeg sets the limit lower to avoid overflows
+  {
+    my $im = Imager->new(xsize => 1+$max_dim, ysize => 1);
+    my $data = '';
+    ok(!$im->write(data => \$data, type => "jpeg"),
+       "fail to write too wide an image");
+    is($im->errstr, "image too large for JPEG",
+       "check error message");
+  }
+ SKIP:
+  {
+    my $im = Imager->new(xsize => $max_dim, ysize => 1);
+    $im->box(fill => { hatch => "check4x4" });
+    my $data = '';
+    ok($im->write(data => \$data, type => "jpeg"),
+       "write image at width limit")
+      or print "# ", $im->errstr, "\n";
+    my $im2 = Imager->new(data => $data, ftype => "jpeg");
+    ok($im2, "read it ok")
+      or skip("cannot load the wide image", 1);
+    is($im->getwidth, $max_dim, "check width");
+    is($im->getheight, 1, "check height");
+  }
+  {
+    my $im = Imager->new(xsize => 1, ysize => 1+$max_dim);
+    my $data = '';
+    ok(!$im->write(data => \$data, type => "jpeg"),
+       "fail to write too tall an image");
+    is($im->errstr, "image too large for JPEG",
+       "check error message");
+  }
+ SKIP:
+  {
+    my $im = Imager->new(xsize => 1, ysize => $max_dim);
+    $im->box(fill => { hatch => "check2x2" });
+    my $data = '';
+    ok($im->write(data => \$data, type => "jpeg"),
+       "write image at width limit");
+    my $im2 = Imager->new(data => $data, ftype => "jpeg");
+    ok($im2, "read it ok")
+      or skip("cannot load the wide image", 1);
+    is($im->getwidth, 1, "check width");
+    is($im->getheight, $max_dim, "check height");
+  }
+}
index 16e6059..58cd63f 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -79,6 +79,7 @@ GIF/README
 GIF/t/t10gif.t
 GIF/t/t20new.t
 GIF/t/t30fixed.t
+GIF/t/t40limit.t
 GIF/testimg/badindex.gif       GIF with a bad color index
 GIF/testimg/bandw.gif
 GIF/testimg/expected.gif
@@ -157,6 +158,7 @@ JPEG/Makefile.PL
 JPEG/README
 JPEG/t/t00load.t
 JPEG/t/t10jpeg.t               Test jpeg support
+JPEG/t/t20limit.t
 JPEG/testimg/209_yonge.jpg     Regression test: #17981
 JPEG/testimg/exiftest.jpg      Test image for EXIF parsing
 JPEG/testimg/scmyk.jpg         Simple CMYK JPEG image
@@ -266,6 +268,7 @@ SGI/SGI.xs
 SGI/t/00load.t
 SGI/t/10read.t
 SGI/t/20write.t
+SGI/t/30limit.t                Test size limit checking
 SGI/testimg/rle.rgb
 SGI/testimg/rle12.rgb
 SGI/testimg/rle16.rgb
@@ -414,6 +417,8 @@ testimg/test.png            Standard test image as PNG
 testimg/test.raw               Standard test image as RAW
 testimg/test.tga               Standard test image as TGA
 testimg/test_gimp_pal          A simple GIMP palette file
+testimg/tootall.ppm
+testimg/toowide.ppm
 testimg/winrgb2.bmp            1-bit bmp base
 testimg/winrgb24.bmp           24-bit bmp base
 testimg/winrgb24off.bmp                24-bit bmp with image data offset from header
index c981e4b..5bdd682 100644 (file)
@@ -734,6 +734,28 @@ EOS
     }
     print CONFIG "#define $define->[0] $define->[1]\n";
   }
+  if ($Config{gccversion} && $Config{gccversion} > 3) {
+    print CONFIG <<EOS;
+/*
+
+Compiler supports the GCC __attribute__((format...)) syntax.
+
+*/
+
+#define IMAGER_FORMAT_ATTR 1
+EOS
+  }
+
+  print CONFIG <<EOS;
+/*
+ Type and format code for formatted output as with printf.
+
+ This is intended for formatting i_img_dim values.
+*/
+typedef $Config{ivtype} i_dim_format_t;
+#define i_DF $Config{ivdformat}
+EOS
+
   print CONFIG "\n#endif\n";
   close CONFIG;
 }
index 09849cd..ee23666 100644 (file)
@@ -36,7 +36,8 @@ mandel(double x, double y, int max_iter) {
 void 
 mandelbrot(i_img *im, double minx, double miny, double maxx, double maxy, int max_iter) {
 
-  int i,x,y;
+  int i;
+  i_img_dim x,y;
   int idx;
   double divx, divy;
 
index 0d41c66..fa3218d 100644 (file)
@@ -73,7 +73,14 @@ i_writepng_wiol(i_img *im, io_glue *ig) {
   int aspect_only, have_res;
 
   mm_log((1,"i_writepng(im %p ,ig %p)\n", im, ig));
-  
+
+  i_clear_error();
+
+  if (im->xsize > PNG_UINT_31_MAX || im->ysize > PNG_UINT_31_MAX) {
+    i_push_error(0, "image too large for PNG");
+    return 0;
+  }
+
   height = im->ysize;
   width  = im->xsize;
 
index 547badc..d8d9be3 100644 (file)
@@ -20,6 +20,9 @@
 /* we add that little bit to avoid rounding issues */
 #define SampleFTo16(num) ((int)((num) * 65535.0 + 0.01))
 
+/* maximum size of an SGI image */
+#define SGI_DIM_LIMIT 0xFFFF
+
 typedef struct {
   unsigned short imagic;
   unsigned char storagetype;
@@ -325,6 +328,11 @@ i_writesgi_wiol(io_glue *ig, i_img *img) {
 
   i_clear_error();
 
+  if (img->xsize > SGI_DIM_LIMIT || img->ysize > SGI_DIM_LIMIT) {
+    i_push_error(0, "image too large for SGI");
+    return 0;
+  }
+
   if (!write_sgi_header(img, ig, &rle, &bpc2))
     return 0;
 
diff --git a/SGI/t/30limit.t b/SGI/t/30limit.t
new file mode 100644 (file)
index 0000000..8e3fd11
--- /dev/null
@@ -0,0 +1,52 @@
+#!perl -w
+use Imager;
+use Test::More tests => 14;
+use Imager::Test qw(is_image);
+
+{
+  # SGI files are limited to 0xFFFF x 0xFFFF pixels
+  {
+    my $im = Imager->new(xsize => 0x10000, ysize => 1);
+    my $data = '';
+    ok(!$im->write(data => \$data, type => "sgi"),
+       "fail to write too wide an image");
+    is($im->errstr, "image too large for SGI",
+       "check error message");
+  }
+ SKIP:
+  {
+    my $im = Imager->new(xsize => 0xFFFF, ysize => 1);
+    $im->box(fill => { hatch => "check4x4" });
+    my $data = '';
+    ok($im->write(data => \$data, type => "sgi"),
+       "write image at width limit");
+    my $im2 = Imager->new(data => $data, ftype => "sgi");
+    ok($im2, "read it ok")
+      or skip("cannot load the wide image", 1);
+    is_image($im, $im2, "check we read what we wrote");
+    is($im->getwidth, 0xffff, "check width");
+    is($im->getheight, 1, "check height");
+  }
+  {
+    my $im = Imager->new(xsize => 1, ysize => 0x10000);
+    my $data = '';
+    ok(!$im->write(data => \$data, type => "sgi"),
+       "fail to write too tall an image");
+    is($im->errstr, "image too large for SGI",
+       "check error message");
+  }
+ SKIP:
+  {
+    my $im = Imager->new(xsize => 1, ysize => 0xFFFF);
+    $im->box(fill => { hatch => "check2x2" });
+    my $data = '';
+    ok($im->write(data => \$data, type => "sgi"),
+       "write image at width limit");
+    my $im2 = Imager->new(data => $data, ftype => "sgi");
+    ok($im2, "read it ok")
+      or skip("cannot load the wide image", 1);
+    is_image($im, $im2, "check we read what we wrote");
+    is($im->getwidth, 1, "check width");
+    is($im->getheight, 0xffff, "check height");
+  }
+}
index 255eec6..659b01d 100644 (file)
--- a/T1/T1.xs
+++ b/T1/T1.xs
@@ -34,11 +34,11 @@ i_t1_destroy(font_id)
 undef_int
 i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
     Imager::ImgRaw     im
-              int     xb
-              int     yb
+        i_img_dim     xb
+        i_img_dim     yb
               int     channel
               int     fontnum
-             float     points
+            double     points
                SV*    str_sv
               int     align
                int     utf8
@@ -61,14 +61,14 @@ i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags=""
 void
 i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
                int     fontnum
-            float     point
+           double     point
                SV*    str_sv
                int     utf8
               char*    flags
             PREINIT:
                char *str;
                STRLEN len;
-              int     cords[BOUNDING_BOX_COUNT];
+              i_img_dim     cords[BOUNDING_BOX_COUNT];
                int i;
                int rc;
             PPCODE:
@@ -89,11 +89,11 @@ i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
 undef_int
 i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
     Imager::ImgRaw     im
-              int     xb
-              int     yb
+        i_img_dim     xb
+        i_img_dim     yb
      Imager::Color    cl
               int     fontnum
-             float     points
+            double     points
                SV*    str_sv
               int     align
                int     utf8
index 1629a14..1c4a1a7 100644 (file)
--- a/T1/imt1.c
+++ b/T1/imt1.c
@@ -181,7 +181,7 @@ Interface to text rendering into a single channel in an image
 */
 
 undef_int
-i_t1_cp(i_img *im,int xb,int yb,int channel,int fontnum,float points,char* str,size_t len,int align, int utf8, char const *flags) {
+i_t1_cp(i_img *im,i_img_dim xb,i_img_dim yb,int channel,int fontnum,double points,char* str,size_t len,int align, int utf8, char const *flags) {
   GLYPH *glyph;
   int xsize,ysize,x,y;
   i_color val;
@@ -255,11 +255,11 @@ function to get a strings bounding box given the font id and sizes
 */
 
 int
-i_t1_bbox(int fontnum,float points,const char *str,size_t len,int cords[6], int utf8,char const *flags) {
+i_t1_bbox(int fontnum, double points,const char *str,size_t len, i_img_dim cords[6], int utf8,char const *flags) {
   BBox bbox;
   BBox gbbox;
   int mod_flags = t1_get_flags(flags);
-  int advance;
+  i_img_dim advance;
   int space_position = T1_GetEncodingIndex(fontnum, "space");
   
   mm_log((1,"i_t1_bbox(fontnum %d,points %.2f,str '%.*s', len %d)\n",fontnum,points,len,str,len));
@@ -297,16 +297,16 @@ i_t1_bbox(int fontnum,float points,const char *str,size_t len,int cords[6], int
          (int)(bbox.ury*points/1000) ));
 
 
-  cords[BBOX_NEG_WIDTH]=((float)bbox.llx*points)/1000;
-  cords[BBOX_POS_WIDTH]=((float)bbox.urx*points)/1000;
+  cords[BBOX_NEG_WIDTH]=((double)bbox.llx*points)/1000;
+  cords[BBOX_POS_WIDTH]=((double)bbox.urx*points)/1000;
 
-  cords[BBOX_GLOBAL_DESCENT]=((float)gbbox.lly*points)/1000;
-  cords[BBOX_GLOBAL_ASCENT]=((float)gbbox.ury*points)/1000;
+  cords[BBOX_GLOBAL_DESCENT]=((double)gbbox.lly*points)/1000;
+  cords[BBOX_GLOBAL_ASCENT]=((double)gbbox.ury*points)/1000;
 
-  cords[BBOX_DESCENT]=((float)bbox.lly*points)/1000;
-  cords[BBOX_ASCENT]=((float)bbox.ury*points)/1000;
+  cords[BBOX_DESCENT]=((double)bbox.lly*points)/1000;
+  cords[BBOX_ASCENT]=((double)bbox.ury*points)/1000;
 
-  cords[BBOX_ADVANCE_WIDTH] = ((float)advance * points)/1000;
+  cords[BBOX_ADVANCE_WIDTH] = ((double)advance * points)/1000;
   cords[BBOX_RIGHT_BEARING] = 
     cords[BBOX_ADVANCE_WIDTH] - cords[BBOX_POS_WIDTH];
 
@@ -333,7 +333,7 @@ Interface to text rendering in a single color onto an image
 */
 
 undef_int
-i_t1_text(i_img *im,int xb,int yb,const i_color *cl,int fontnum,float points,const char* str,size_t len,int align, int utf8, char const *flags) {
+i_t1_text(i_img *im, i_img_dim xb, i_img_dim yb,const i_color *cl,int fontnum, double points,const char* str,size_t len,int align, int utf8, char const *flags) {
   GLYPH *glyph;
   int xsize,ysize,y;
   int mod_flags = t1_get_flags(flags);
@@ -413,8 +413,9 @@ Sets *outlen to the number of bytes used in the output string.
 
 static char *
 t1_from_utf8(char const *in, size_t len, int *outlen) {
-  /* at this point len is from a perl SV, so can't approach MAXINT */
-  char *out = mymalloc(len+1); /* checked 5Nov05 tonyc */
+  /* at this point len is from a STRLEN which should be size_t and can't
+     be too big for mymalloc */
+  char *out = mymalloc(len+1); /* rechecked 29jul11 tonyc */
   char *p = out;
   unsigned long c;
 
index 9b3bbb7..489bcef 100644 (file)
--- a/T1/imt1.h
+++ b/T1/imt1.h
@@ -19,13 +19,13 @@ extern void
 i_t1_set_aa(int st);
 
 extern undef_int
-i_t1_cp(i_img *im,int xb,int yb,int channel,int fontnum,float points,char* str,size_t len,int align, int utf8, char const *flags);
+i_t1_cp(i_img *im,i_img_dim xb,i_img_dim yb,int channel,int fontnum,double points,char* str,size_t len,int align, int utf8, char const *flags);
 
 extern int
-i_t1_bbox(int fontnum,float points,const char *str,size_t len,int cords[6], int utf8,char const *flags);
+i_t1_bbox(int fontnum,double points,const char *str,size_t len,i_img_dim *cords, int utf8,char const *flags);
 
 extern undef_int
-i_t1_text(i_img *im,int xb,int yb,const i_color *cl,int fontnum,float points,const char* str,size_t len,int align, int utf8, char const *flags);
+i_t1_text(i_img *im,i_img_dim xb,i_img_dim yb,const i_color *cl,int fontnum,double points,const char* str,size_t len,int align, int utf8, char const *flags);
 
 extern int
 i_t1_has_chars(int font_num, const char *text, size_t len, int utf8,
index 75d8244..13f8650 100644 (file)
@@ -50,8 +50,8 @@ struct tag_name {
   uint32 tag;
 };
 
-static i_img *read_one_rgb_tiled(TIFF *tif, int width, int height, int allow_incomplete);
-static i_img *read_one_rgb_lines(TIFF *tif, int width, int height, int allow_incomplete);
+static i_img *read_one_rgb_tiled(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete);
+static i_img *read_one_rgb_lines(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete);
 
 static struct tag_name text_tag_names[] =
 {
@@ -100,8 +100,8 @@ typedef int (*read_setup_t)(read_state_t *state);
    the raster buffer, (for tiles against the right side of the
    image) */
 
-typedef int (*read_putter_t)(read_state_t *state, int x, int y, int width, 
-                            int height, int extras);
+typedef int (*read_putter_t)(read_state_t *state, i_img_dim x, i_img_dim y,
+                            i_img_dim width, i_img_dim height, int extras);
 
 /* reads from a tiled or strip image and calls the putter.
    This may need a second type for handling non-contiguous images
@@ -112,7 +112,7 @@ struct read_state_tag {
   TIFF *tif;
   i_img *img;
   void *raster;
-  unsigned long pixels_read;
+  i_img_dim pixels_read;
   int allow_incomplete;
   void *line_buf;
   uint32 width, height;
@@ -136,29 +136,29 @@ static int tile_contig_getter(read_state_t *state, read_putter_t putter);
 static int strip_contig_getter(read_state_t *state, read_putter_t putter);
 
 static int setup_paletted(read_state_t *state);
-static int paletted_putter8(read_state_t *, int, int, int, int, int);
-static int paletted_putter4(read_state_t *, int, int, int, int, int);
+static int paletted_putter8(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
+static int paletted_putter4(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
 
 static int setup_16_rgb(read_state_t *state);
 static int setup_16_grey(read_state_t *state);
-static int putter_16(read_state_t *, int, int, int, int, int);
+static int putter_16(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
 
 static int setup_8_rgb(read_state_t *state);
 static int setup_8_grey(read_state_t *state);
-static int putter_8(read_state_t *, int, int, int, int, int);
+static int putter_8(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
 
 static int setup_32_rgb(read_state_t *state);
 static int setup_32_grey(read_state_t *state);
-static int putter_32(read_state_t *, int, int, int, int, int);
+static int putter_32(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
 
 static int setup_bilevel(read_state_t *state);
-static int putter_bilevel(read_state_t *, int, int, int, int, int);
+static int putter_bilevel(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
 
 static int setup_cmyk8(read_state_t *state);
-static int putter_cmyk8(read_state_t *, int, int, int, int, int);
+static int putter_cmyk8(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
 
 static int setup_cmyk16(read_state_t *state);
-static int putter_cmyk16(read_state_t *, int, int, int, int, int);
+static int putter_cmyk16(read_state_t *, i_img_dim, i_img_dim, i_img_dim, i_img_dim, int);
 
 static const int text_tag_count = 
   sizeof(text_tag_names) / sizeof(*text_tag_names);
@@ -202,7 +202,7 @@ static void warn_handler(char const *module, char const *fmt, va_list ap) {
 static int save_tiff_tags(TIFF *tif, i_img *im);
 
 static void 
-pack_4bit_to(unsigned char *dest, const unsigned char *src, int count);
+pack_4bit_to(unsigned char *dest, const unsigned char *src, i_img_dim count);
 
 
 static toff_t sizeproc(thandle_t x) {
@@ -366,7 +366,7 @@ static i_img *read_one_tiff(TIFF *tif, int allow_incomplete) {
       getterf = strip_contig_getter;
   }
   if (setupf && getterf && putterf) {
-    unsigned long total_pixels = (unsigned long)width * height;
+    i_img_dim total_pixels = width * height;
     memset(&state, 0, sizeof(state));
     state.tif = tif;
     state.allow_incomplete = allow_incomplete;
@@ -629,6 +629,11 @@ i_writetiff_low_faxable(TIFF *tif, i_img *im, int fine) {
   width    = im->xsize;
   height   = im->ysize;
 
+  if (width != im->xsize || height != im->ysize) {
+    i_push_error(0, "image too large for TIFF");
+    return 0;
+  }
+
   switch (im->channels) {
   case 1:
   case 2:
@@ -851,7 +856,7 @@ write_one_bilevel(TIFF *tif, i_img *im, int zero_is_white) {
   unsigned char *in_row;
   unsigned char *out_row;
   unsigned out_size;
-  int x, y;
+  i_img_dim x, y;
   int invert;
 
   mm_log((1, "tiff - write_one_bilevel(tif %p, im %p, zero_is_white %d)\n", 
@@ -956,7 +961,7 @@ write_one_paletted8(TIFF *tif, i_img *im) {
   uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
   unsigned char *out_row;
   unsigned out_size;
-  int y;
+  i_img_dim y;
 
   mm_log((1, "tiff - write_one_paletted8(tif %p, im %p)\n", tif, im));
 
@@ -1000,8 +1005,8 @@ write_one_paletted4(TIFF *tif, i_img *im) {
   uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
   unsigned char *in_row;
   unsigned char *out_row;
-  unsigned out_size;
-  int y;
+  size_t out_size;
+  i_img_dim y;
 
   mm_log((1, "tiff - write_one_paletted4(tif %p, im %p)\n", tif, im));
 
@@ -1084,7 +1089,7 @@ write_one_32(TIFF *tif, i_img *im) {
   unsigned *in_row;
   size_t out_size;
   uint32 *out_row;
-  int y;
+  i_img_dim y;
   size_t sample_count = im->xsize * im->channels;
   size_t sample_index;
     
@@ -1128,7 +1133,7 @@ write_one_16(TIFF *tif, i_img *im) {
   unsigned *in_row;
   size_t out_size;
   uint16 *out_row;
-  int y;
+  i_img_dim y;
   size_t sample_count = im->xsize * im->channels;
   size_t sample_index;
     
@@ -1171,7 +1176,7 @@ write_one_8(TIFF *tif, i_img *im) {
   uint16 compress = get_compression(im, COMPRESSION_PACKBITS);
   size_t out_size;
   unsigned char *out_row;
-  int y;
+  i_img_dim y;
   size_t sample_count = im->xsize * im->channels;
     
   mm_log((1, "tiff - write_one_8(tif %p, im %p)\n", tif, im));
@@ -1210,6 +1215,11 @@ i_writetiff_low(TIFF *tif, i_img *im) {
   height   = im->ysize;
   channels = im->channels;
 
+  if (width != im->xsize || height != im->ysize) {
+    i_push_error(0, "image too large for TIFF");
+    return 0;
+  }
+
   mm_log((1, "i_writetiff_low: width=%d, height=%d, channels=%d, bits=%d\n", width, height, channels, im->bits));
   if (im->type == i_palette_type) {
     mm_log((1, "i_writetiff_low: paletted, colors=%d\n", i_colorcount(im)));
@@ -1268,7 +1278,7 @@ i_writetiff_multi_wiol(io_glue *ig, i_img **imgs, int count) {
   old_handler = TIFFSetErrorHandler(error_handler);
 
   i_clear_error();
-  mm_log((1, "i_writetiff_multi_wiol(ig 0x%p, imgs 0x%p, count %d)\n", 
+  mm_log((1, "i_writetiff_multi_wiol(ig %p, imgs %p, count %d)\n", 
           ig, imgs, count));
 
   /* FIXME: Enable the mmap interface */
@@ -1336,7 +1346,7 @@ i_writetiff_multi_wiol_faxable(io_glue *ig, i_img **imgs, int count, int fine) {
   old_handler = TIFFSetErrorHandler(error_handler);
 
   i_clear_error();
-  mm_log((1, "i_writetiff_multi_wiol(ig 0x%p, imgs 0x%p, count %d)\n", 
+  mm_log((1, "i_writetiff_multi_wiol(ig %p, imgs %p, count %d)\n", 
           ig, imgs, count));
 
   /* FIXME: Enable the mmap interface */
@@ -1400,7 +1410,7 @@ i_writetiff_wiol(i_img *img, io_glue *ig) {
   old_handler = TIFFSetErrorHandler(error_handler);
 
   i_clear_error();
-  mm_log((1, "i_writetiff_wiol(img %p, ig 0x%p)\n", img, ig));
+  mm_log((1, "i_writetiff_wiol(img %p, ig %p)\n", img, ig));
 
   /* FIXME: Enable the mmap interface */
 
@@ -1461,7 +1471,7 @@ i_writetiff_wiol_faxable(i_img *im, io_glue *ig, int fine) {
   old_handler = TIFFSetErrorHandler(error_handler);
 
   i_clear_error();
-  mm_log((1, "i_writetiff_wiol(img %p, ig 0x%p)\n", im, ig));
+  mm_log((1, "i_writetiff_wiol(img %p, ig %p)\n", im, ig));
 
   /* FIXME: Enable the mmap interface */
   
@@ -1517,7 +1527,7 @@ static int save_tiff_tags(TIFF *tif, i_img *im) {
 
 static void
 unpack_4bit_to(unsigned char *dest, const unsigned char *src, 
-              int src_byte_count) {
+              size_t src_byte_count) {
   while (src_byte_count > 0) {
     *dest++ = *src >> 4;
     *dest++ = *src++ & 0xf;
@@ -1526,7 +1536,7 @@ unpack_4bit_to(unsigned char *dest, const unsigned char *src,
 }
 
 static void pack_4bit_to(unsigned char *dest, const unsigned char *src, 
-                        int pixel_count) {
+                        i_img_dim pixel_count) {
   int i = 0;
   while (i < pixel_count) {
     if ((i & 1) == 0) {
@@ -1540,7 +1550,7 @@ static void pack_4bit_to(unsigned char *dest, const unsigned char *src,
 }
 
 static i_img *
-make_rgb(TIFF *tif, int width, int height, int *alpha_chan) {
+make_rgb(TIFF *tif, i_img_dim width, i_img_dim height, int *alpha_chan) {
   uint16 photometric;
   uint16 channels, in_channels;
   uint16 extra_count;
@@ -1579,7 +1589,7 @@ make_rgb(TIFF *tif, int width, int height, int *alpha_chan) {
 }
 
 static i_img *
-read_one_rgb_lines(TIFF *tif, int width, int height, int allow_incomplete) {
+read_one_rgb_lines(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete) {
   i_img *im;
   uint32* raster = NULL;
   uint32 rowsperstrip, row;
@@ -1750,7 +1760,7 @@ myTIFFReadRGBATile(TIFFRGBAImage *img, uint32 col, uint32 row, uint32 * raster)
 }
 
 static i_img *
-read_one_rgb_tiled(TIFF *tif, int width, int height, int allow_incomplete) {
+read_one_rgb_tiled(TIFF *tif, i_img_dim width, i_img_dim height, int allow_incomplete) {
   i_img *im;
   uint32* raster = NULL;
   int ok = 1;
@@ -1968,10 +1978,10 @@ strip_contig_getter(read_state_t *state, read_putter_t putter) {
 }
 
 static int 
-paletted_putter8(read_state_t *state, int x, int y, int width, int height, int extras) {
+paletted_putter8(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, int extras) {
   unsigned char *p = state->raster;
 
-  state->pixels_read += (unsigned long) width * height;
+  state->pixels_read += width * height;
   while (height > 0) {
     i_ppal(state->img, x, x + width, y, p);
     p += width + extras;
@@ -1983,7 +1993,7 @@ paletted_putter8(read_state_t *state, int x, int y, int width, int height, int e
 }
 
 static int 
-paletted_putter4(read_state_t *state, int x, int y, int width, int height, int extras) {
+paletted_putter4(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, int extras) {
   uint32 img_line_size = (width + 1) / 2;
   uint32 skip_line_size = (width + extras + 1) / 2;
   unsigned char *p = state->raster;
@@ -1991,7 +2001,7 @@ paletted_putter4(read_state_t *state, int x, int y, int width, int height, int e
   if (!state->line_buf)
     state->line_buf = mymalloc(state->width);
 
-  state->pixels_read += (unsigned long) width * height;
+  state->pixels_read += width * height;
   while (height > 0) {
     unpack_4bit_to(state->line_buf, p, img_line_size);
     i_ppal(state->img, x, x + width, y, state->line_buf);
@@ -2121,14 +2131,14 @@ setup_16_grey(read_state_t *state) {
 }
 
 static int 
-putter_16(read_state_t *state, int x, int y, int width, int height, 
+putter_16(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, 
          int row_extras) {
   uint16 *p = state->raster;
   int out_chan = state->img->channels;
 
-  state->pixels_read += (unsigned long) width * height;
+  state->pixels_read += width * height;
   while (height > 0) {
-    int i;
+    i_img_dim i;
     int ch;
     unsigned *outp = state->line_buf;
 
@@ -2185,14 +2195,14 @@ setup_8_grey(read_state_t *state) {
 }
 
 static int 
-putter_8(read_state_t *state, int x, int y, int width, int height, 
+putter_8(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, 
          int row_extras) {
   unsigned char *p = state->raster;
   int out_chan = state->img->channels;
 
-  state->pixels_read += (unsigned long) width * height;
+  state->pixels_read += width * height;
   while (height > 0) {
-    int i;
+    i_img_dim i;
     int ch;
     i_color *outp = state->line_buf;
 
@@ -2251,14 +2261,14 @@ setup_32_grey(read_state_t *state) {
 }
 
 static int 
-putter_32(read_state_t *state, int x, int y, int width, int height, 
+putter_32(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, 
          int row_extras) {
   uint32 *p = state->raster;
   int out_chan = state->img->channels;
 
-  state->pixels_read += (unsigned long) width * height;
+  state->pixels_read += width * height;
   while (height > 0) {
-    int i;
+    i_img_dim i;
     int ch;
     i_fcolor *outp = state->line_buf;
 
@@ -2308,16 +2318,16 @@ setup_bilevel(read_state_t *state) {
 }
 
 static int 
-putter_bilevel(read_state_t *state, int x, int y, int width, int height, 
+putter_bilevel(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, 
               int row_extras) {
   unsigned char *line_in = state->raster;
   size_t line_size = (width + row_extras + 7) / 8;
   
   /* tifflib returns the bits in MSB2LSB order even when the file is
      in LSB2MSB, so we only need to handle MSB2LSB */
-  state->pixels_read += (unsigned long) width * height;
+  state->pixels_read += width * height;
   while (height > 0) {
-    int i;
+    i_img_dim i;
     unsigned char *outp = state->line_buf;
     unsigned char *inp = line_in;
     unsigned mask = 0x80;
@@ -2398,13 +2408,13 @@ setup_cmyk8(read_state_t *state) {
 }
 
 static int 
-putter_cmyk8(read_state_t *state, int x, int y, int width, int height, 
+putter_cmyk8(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, 
               int row_extras) {
   unsigned char *p = state->raster;
 
-  state->pixels_read += (unsigned long) width * height;
+  state->pixels_read += width * height;
   while (height > 0) {
-    int i;
+    i_img_dim i;
     int ch;
     i_color *outp = state->line_buf;
 
@@ -2454,16 +2464,16 @@ setup_cmyk16(read_state_t *state) {
 }
 
 static int 
-putter_cmyk16(read_state_t *state, int x, int y, int width, int height, 
+putter_cmyk16(read_state_t *state, i_img_dim x, i_img_dim y, i_img_dim width, i_img_dim height, 
               int row_extras) {
   uint16 *p = state->raster;
   int out_chan = state->img->channels;
 
   mm_log((4, "putter_cmyk16(%p, %d, %d, %d, %d, %d)\n", x, y, width, height, row_extras));
 
-  state->pixels_read += (unsigned long) width * height;
+  state->pixels_read += width * height;
   while (height > 0) {
-    int i;
+    i_img_dim i;
     int ch;
     unsigned *outp = state->line_buf;
 
index bb91fb7..763df5f 100644 (file)
@@ -47,6 +47,8 @@ sub _draw {
              $input{'y'}, $input{color}, $input{size}, 
              $input{string}, $input{align}, $input{aa}, $input{utf8});
   }
+
+  return 1;
 }
 
 
index 9e0020d..e1e977b 100644 (file)
@@ -15,12 +15,12 @@ MODULE = Imager::Font::W32  PACKAGE = Imager::Font::W32
 
 void
 i_wf_bbox(face, size, text_sv, utf8=0)
-       char *face
-       int size
+       const char *face
+       i_img_dim size
        SV *text_sv
        int utf8
       PREINIT:
-       int cords[BOUNDING_BOX_COUNT];
+       i_img_dim cords[BOUNDING_BOX_COUNT];
         int rc, i;
        char const *text;
          STRLEN text_len;
@@ -38,12 +38,12 @@ i_wf_bbox(face, size, text_sv, utf8=0)
 
 undef_int
 i_wf_text(face, im, tx, ty, cl, size, text_sv, align, aa, utf8 = 0)
-       char *face
+       const char *face
        Imager::ImgRaw im
-       int tx
-       int ty
+       i_img_dim tx
+       i_img_dim ty
        Imager::Color cl
-       int size
+       i_img_dim size
        SV *text_sv
        int align
        int aa
@@ -64,12 +64,12 @@ i_wf_text(face, im, tx, ty, cl, size, text_sv, align, aa, utf8 = 0)
 
 undef_int
 i_wf_cp(face, im, tx, ty, channel, size, text_sv, align, aa, utf8 = 0)
-       char *face
+       const char *face
        Imager::ImgRaw im
-       int tx
-       int ty
+       i_img_dim tx
+       i_img_dim ty
        int channel
-       int size
+       i_img_dim size
        SV *text_sv
        int align
        int aa
index 848aa54..a5ea91a 100644 (file)
@@ -3,11 +3,11 @@
 
 #include "imdatatypes.h"
 
-extern int i_wf_bbox(const char *face, int size, const char *text, int length, int *bbox, int utf8);
-extern int i_wf_text(const char *face, i_img *im, int tx, int ty, const i_color *cl, 
-                    int size, const char *text, int len, int align, int aa, int utf8);
-extern int i_wf_cp(const char *face, i_img *im, int tx, int ty, int channel, 
-                  int size, const char *text, int len, int align, int aa, int utf8);
+extern int i_wf_bbox(const char *face, i_img_dim size, const char *text, size_t length, i_img_dim *bbox, int utf8);
+extern int i_wf_text(const char *face, i_img *im, i_img_dim tx, i_img_dim ty, const i_color *cl, 
+                    i_img_dim size, const char *text, size_t len, int align, int aa, int utf8);
+extern int i_wf_cp(const char *face, i_img *im, i_img_dim tx, i_img_dim ty, int channel, 
+                  i_img_dim size, const char *text, size_t len, int align, int aa, int utf8);
 extern int i_wf_addfont(char const *file);
 extern int i_wf_delfont(char const *file);
 
index b466d99..33c8ed1 100644 (file)
@@ -11,7 +11,7 @@ win32.c - implements some win32 specific code, specifically Win32 font support.
 
 =head1 SYNOPSIS
 
-   int bbox[6];
+   i_img_dim bbox[6];
    if (i_wf_bbox(facename, size, text, text_len, bbox)) {
      // we have the bbox
    }
@@ -32,7 +32,7 @@ An Imager interface to font output using the Win32 GDI.
 static void set_logfont(const char *face, int size, LOGFONT *lf);
 
 static LPVOID render_text(const char *face, int size, const char *text, int length, int aa,
-                          HBITMAP *pbm, SIZE *psz, TEXTMETRIC *tm, int *bbox, int utf8);
+                          HBITMAP *pbm, SIZE *psz, TEXTMETRIC *tm, i_img_dim *bbox, int utf8);
 static LPWSTR utf8_to_wide_string(char const *text, int text_len, int *wide_chars);
 
 /*
@@ -43,8 +43,8 @@ Calculate a bounding box for the text.
 =cut
 */
 
-int i_wf_bbox(const char *face, int size, const char *text, int length, int *bbox,
-             int utf8) {
+int i_wf_bbox(const char *face, i_img_dim size, const char *text, size_t length,
+             i_img_dim *bbox, int utf8) {
   LOGFONT lf;
   HFONT font, oldFont;
   HDC dc;
@@ -59,6 +59,8 @@ int i_wf_bbox(const char *face, int size, const char *text, int length, int *bbo
   int got_first_ch = 0;
   unsigned long first_ch, last_ch;
 
+  i_clear_error();
+
   mm_log((1, "i_wf_bbox(face %s, size %d, text %p, length %d, bbox %p, utf8 %d)\n", face, size, text, length, bbox, utf8));
 
   set_logfont(face, size, &lf);
@@ -172,7 +174,11 @@ int i_wf_bbox(const char *face, int size, const char *text, int length, int *bbo
   ReleaseDC(NULL, dc);
   DeleteObject(font);
 
-  mm_log((1, " bbox=> negw=%d glob_desc=%d pos_wid=%d glob_asc=%d desc=%d asc=%d adv_width=%d rightb=%d\n", bbox[0], bbox[1], bbox[2], bbox[3], bbox[4], bbox[5], bbox[6], bbox[7]));
+  mm_log((1, " bbox=> negw=%" i_DF " glob_desc=%" i_DF " pos_wid=%" i_DF
+         " glob_asc=%" i_DF " desc=%" i_DF " asc=%" i_DF " adv_width=%" i_DF 
+         " rightb=%" i_DF "\n", i_DFc(bbox[0]), i_DFc(bbox[1]), i_DFc(bbox[2]),
+         i_DFc(bbox[3]), i_DFc(bbox[4]), i_DFc(bbox[5]), i_DFc(bbox[6]),
+         i_DFc(bbox[7])));
 
   return BBOX_RIGHT_BEARING + 1;
 }
@@ -186,19 +192,21 @@ Draws the text in the given color.
 */
 
 int
-i_wf_text(const char *face, i_img *im, int tx, int ty, const i_color *cl, int size, 
-         const char *text, int len, int align, int aa, int utf8) {
+i_wf_text(const char *face, i_img *im, i_img_dim tx, i_img_dim ty, const i_color *cl, i_img_dim size, 
+         const char *text, size_t len, int align, int aa, int utf8) {
   unsigned char *bits;
   HBITMAP bm;
   SIZE sz;
-  int line_width;
-  int x, y;
+  i_img_dim line_width;
+  i_img_dim x, y;
   int ch;
   TEXTMETRIC tm;
   int top;
-  int bbox[BOUNDING_BOX_COUNT];
+  i_img_dim bbox[BOUNDING_BOX_COUNT];
+
+  i_clear_error();
 
-  mm_log((1, "i_wf_text(face %s, im %p, tx %d, ty %d, cl %p, size %d, text %p, length %d, align %d, aa %d,  utf8 %d)\n", face, im, tx, ty, cl, size, text, len, align, aa, aa, utf8));
+  mm_log((1, "i_wf_text(face %s, im %p, tx %" i_DF ", ty %" i_DF ", cl %p, size %" i_DF ", text %p, length %lu, align %d, aa %d,  utf8 %d)\n", face, im, i_DFcp(tx, ty), cl, i_DFc(size), text, (unsigned long)len, align, aa, aa, utf8));
 
   if (!i_wf_bbox(face, size, text, len, bbox, utf8))
     return 0;
@@ -245,18 +253,20 @@ Draws the text in the given channel.
 */
 
 int
-i_wf_cp(const char *face, i_img *im, int tx, int ty, int channel, int size, 
-         const char *text, int len, int align, int aa, int utf8) {
+i_wf_cp(const char *face, i_img *im, i_img_dim tx, i_img_dim ty, int channel, i_img_dim size, 
+         const char *text, size_t len, int align, int aa, int utf8) {
   unsigned char *bits;
   HBITMAP bm;
   SIZE sz;
   int line_width;
-  int x, y;
+  i_img_dim x, y;
   TEXTMETRIC tm;
-  int top;
-  int bbox[BOUNDING_BOX_COUNT];
+  i_img_dim top;
+  i_img_dim bbox[BOUNDING_BOX_COUNT];
+
+  i_clear_error();
 
-  mm_log((1, "i_wf_cp(face %s, im %p, tx %d, ty %d, channel %d, size %d, text %p, length %d, align %d, aa %d,  utf8 %d)\n", face, im, tx, ty, channel, size, text, len, align, aa, aa, utf8));
+  mm_log((1, "i_wf_cp(face %s, im %p, tx %" i_DF ", ty %" i_DF ", channel %d, size %" i_DF ", text %p, length %lu, align %d, aa %d,  utf8 %d)\n", face, im, i_DFcp(tx, ty), channel, i_DFc(size), text, (unsigned long)len, align, aa, aa, utf8));
 
   if (!i_wf_bbox(face, size, text, len, bbox, utf8))
     return 0;
@@ -394,7 +404,7 @@ native greyscale bitmaps.
 =cut
 */
 static LPVOID render_text(const char *face, int size, const char *text, int length, int aa,
-                  HBITMAP *pbm, SIZE *psz, TEXTMETRIC *tm, int *bbox, int utf8) {
+                  HBITMAP *pbm, SIZE *psz, TEXTMETRIC *tm, i_img_dim *bbox, int utf8) {
   BITMAPINFO bmi;
   BITMAPINFOHEADER *bmih = &bmi.bmiHeader;
   HDC dc, bmpDc;
index 7c5016d..ad5e259 100644 (file)
@@ -58,7 +58,11 @@ for my $file (@files) {
         $category = $1;
       }
       elsif (/^=synopsis (.*)/) {
+       unless (length $synopsis) {
+         push @funcdocs, "\n";
+       }
         $synopsis .= "$1\n";
+       push @funcdocs, "  $1\n";
       }
       elsif (/^=order (.*)$/) {
        $order = $1;
@@ -179,7 +183,7 @@ close OUT;
 
 
 sub make_func_list {
-  my @funcs = qw(i_img i_color i_fcolor i_fill_t mm_log i_img_color_channels i_img_has_alpha i_img_dim);
+  my @funcs = qw(i_img i_color i_fcolor i_fill_t mm_log i_img_color_channels i_img_has_alpha i_img_dim i_DF i_DFc i_DFp i_DFcp);
   open FUNCS, "< imexttypes.h"
     or die "Cannot open imexttypes.h: $!\n";
   my $in_struct;
diff --git a/bmp.c b/bmp.c
index 8f37d32..9cf7615 100644 (file)
--- a/bmp.c
+++ b/bmp.c
@@ -35,6 +35,11 @@ Reads and writes Windows BMP files.
 #define BMPRLE_ENDOFBMP 1
 #define BMPRLE_DELTA 2
 
+#define SIGNBIT32 ((i_upacked_t)1U << 31)
+#define SIGNBIT16 ((i_upacked_t)1U << 15)
+
+#define SIGNMAX32 ((1UL << 31) - 1)
+
 static int read_packed(io_glue *ig, char *format, ...);
 static int write_packed(io_glue *ig, char *format, ...);
 static int write_bmphead(io_glue *ig, i_img *im, int bit_count, 
@@ -54,6 +59,11 @@ static i_img *read_direct_bmp(io_glue *ig, int xsize, int ysize,
                               int bit_count, int clr_used, int compression,
                               long offbits, int allow_incomplete);
 
+/* used for the read_packed() and write_packed() functions, an integer
+ * type */
+typedef long i_packed_t;
+typedef unsigned long i_upacked_t;
+
 /* 
 =item i_writebmp_wiol(im, io_glue)
 
@@ -103,9 +113,9 @@ BI_BITFIELDS images too, but I need a test image.
 
 i_img *
 i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
-  int b_magic, m_magic, filesize, res1, res2, infohead_size;
-  int xsize, ysize, planes, bit_count, compression, size_image, xres, yres;
-  int clr_used, clr_important, offbits;
+  i_packed_t b_magic, m_magic, filesize, res1, res2, infohead_size;
+  i_packed_t xsize, ysize, planes, bit_count, compression, size_image, xres, yres;
+  i_packed_t clr_used, clr_important, offbits;
   i_img *im;
 
   mm_log((1, "i_readbmp_wiol(ig %p)\n", ig));
@@ -113,7 +123,7 @@ i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
   io_glue_commit_types(ig);
   i_clear_error();
 
-  if (!read_packed(ig, "CCVvvVVVVvvVVVVVV", &b_magic, &m_magic, &filesize, 
+  if (!read_packed(ig, "CCVvvVVV!V!vvVVVVVV", &b_magic, &m_magic, &filesize, 
                   &res1, &res2, &offbits, &infohead_size, 
                    &xsize, &ysize, &planes,
                   &bit_count, &compression, &size_image, &xres, &yres, 
@@ -129,9 +139,10 @@ i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
 
   mm_log((1, " bmp header: filesize %d offbits %d xsize %d ysize %d planes %d "
           "bit_count %d compression %d size %d xres %d yres %d clr_used %d "
-          "clr_important %d\n", filesize, offbits, xsize, ysize, planes, 
-          bit_count, compression, size_image, xres, yres, clr_used, 
-          clr_important));
+          "clr_important %d\n", (int)filesize, (int)offbits, (int)xsize,
+         (int)ysize, (int)planes, (int)bit_count, (int)compression, 
+         (int)size_image, (int)xres, (int)yres, (int)clr_used, 
+          (int)clr_important));
 
   if (!i_int_check_image_file_limits(xsize, abs(ysize), 3, sizeof(i_sample_t))) {
     mm_log((1, "i_readbmp_wiol: image size exceeds limits\n"));
@@ -162,7 +173,7 @@ i_readbmp_wiol(io_glue *ig, int allow_incomplete) {
     break;
 
   default:
-    i_push_errorf(0, "unknown bit count for BMP file (%d)", bit_count);
+    i_push_errorf(0, "unknown bit count for BMP file (%d)", (int)bit_count);
     return NULL;
   }
 
@@ -206,28 +217,43 @@ Returns non-zero if all of the arguments were read.
 
 =cut
 */
-static
-int read_packed(io_glue *ig, char *format, ...) {
+static int
+read_packed(io_glue *ig, char *format, ...) {
   unsigned char buf[4];
   va_list ap;
-  int *p;
+  i_packed_t *p;
+  i_packed_t work;
+  int code;
+  int shrieking; /* format code has a ! flag */
 
   va_start(ap, format);
 
   while (*format) {
-    p = va_arg(ap, int *);
+    p = va_arg(ap, i_packed_t *);
 
-    switch (*format) {
+    code = *format++;
+    shrieking = *format == '!';
+    if (shrieking) ++format;
+
+    switch (code) {
     case 'v':
       if (ig->readcb(ig, buf, 2) != 2)
        return 0;
-      *p = buf[0] + (buf[1] << 8);
+      work = buf[0] + ((i_packed_t)buf[1] << 8);
+      if (shrieking)
+       *p = (work ^ SIGNBIT16) - SIGNBIT16;
+      else
+       *p = work;
       break;
 
     case 'V':
       if (ig->readcb(ig, buf, 4) != 4)
        return 0;
-      *p = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24);
+      work = buf[0] + (buf[1] << 8) + ((i_packed_t)buf[2] << 16) + ((i_packed_t)buf[3] << 24);
+      if (shrieking)
+       *p = (work ^ SIGNBIT32) - SIGNBIT32;
+      else
+       *p = work;
       break;
 
     case 'C':
@@ -245,13 +271,12 @@ int read_packed(io_glue *ig, char *format, ...) {
     case '3': /* extension - 24-bit number */
       if (ig->readcb(ig, buf, 3) != 3)
         return 0;
-      *p = buf[0] + (buf[1] << 8) + (buf[2] << 16);
+      *p = buf[0] + (buf[1] << 8) + ((i_packed_t)buf[2] << 16);
       break;
       
     default:
-      i_fatal(1, "Unknown read_packed format code 0x%02x", *format);
+      i_fatal(1, "Unknown read_packed format code 0x%02x", code);
     }
-    ++format;
   }
   return 1;
 }
@@ -275,7 +300,7 @@ write_packed(io_glue *ig, char *format, ...) {
   va_start(ap, format);
 
   while (*format) {
-    i = va_arg(ap, unsigned int);
+    i = va_arg(ap, i_upacked_t);
 
     switch (*format) {
     case 'v':
@@ -328,6 +353,11 @@ int write_bmphead(io_glue *ig, i_img *im, int bit_count, int data_size) {
   int colors_used = 0;
   int offset = FILEHEAD_SIZE + INFOHEAD_SIZE;
 
+  if (im->xsize > SIGNMAX32 || im->ysize > SIGNMAX32) {
+    i_push_error(0, "image too large to write to BMP");
+    return 0;
+  }
+
   got_xres = i_tags_get_float(&im->tags, "i_xres", 0, &xres);
   got_yres = i_tags_get_float(&im->tags, "i_yres", 0, &yres);
   if (!i_tags_get_int(&im->tags, "i_aspect_only", 0,&aspect_only))
@@ -365,10 +395,15 @@ int write_bmphead(io_glue *ig, i_img *im, int bit_count, int data_size) {
     offset += 4 * colors_used;
   }
 
-  if (!write_packed(ig, "CCVvvVVVVvvVVVVVV", 'B', 'M', data_size+offset, 
-                   0, 0, offset, INFOHEAD_SIZE, im->xsize, im->ysize, 1, 
-                   bit_count, BI_RGB, data_size, (int)(xres+0.5), (int)(yres+0.5), 
-                   colors_used, colors_used)){
+  if (!write_packed(ig, "CCVvvVVVVvvVVVVVV", 'B', 'M', 
+                   (i_upacked_t)(data_size+offset), 
+                   (i_upacked_t)0, (i_upacked_t)0, (i_upacked_t)offset,
+                   (i_upacked_t)INFOHEAD_SIZE, (i_upacked_t)im->xsize,
+                   (i_upacked_t)im->ysize, (i_upacked_t)1, 
+                   (i_upacked_t)bit_count, (i_upacked_t)BI_RGB,
+                   (i_upacked_t)data_size, 
+                   (i_upacked_t)(xres+0.5), (i_upacked_t)(yres+0.5), 
+                   (i_upacked_t)colors_used, (i_upacked_t)colors_used)){
     i_push_error(0, "cannot write bmp header");
     return 0;
   }
@@ -379,15 +414,16 @@ int write_bmphead(io_glue *ig, i_img *im, int bit_count, int data_size) {
     for (i = 0; i < colors_used; ++i) {
       i_getcolors(im, i, &c, 1);
       if (im->channels >= 3) {
-       if (!write_packed(ig, "CCCC", c.channel[2], c.channel[1], 
-                         c.channel[0], 0)) {
+       if (!write_packed(ig, "CCCC", (i_upacked_t)(c.channel[2]), 
+                         (i_upacked_t)(c.channel[1]), 
+                         (i_upacked_t)(c.channel[0]), (i_upacked_t)0)) {
          i_push_error(0, "cannot write palette entry");
          return 0;
        }
       }
       else {
-       if (!write_packed(ig, "CCCC", c.channel[0], c.channel[0], 
-                         c.channel[0], 0)) {
+       i_upacked_t v = c.channel[0];
+       if (!write_packed(ig, "CCCC", v, v, v, 0)) {
          i_push_error(0, "cannot write palette entry");
          return 0;
        }
@@ -641,7 +677,7 @@ Returns non-zero on success.
 static int
 read_bmp_pal(io_glue *ig, i_img *im, int count) {
   int i;
-  int r, g, b, x;
+  i_packed_t r, g, b, x;
   i_color c;
   
   for (i = 0; i < count; ++i) {
@@ -1300,10 +1336,12 @@ read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count,
     compression_name = "BI_BITFIELDS";
 
     for (i = 0; i < 3; ++i) {
-      if (!read_packed(ig, "V", masks.masks+i)) {
+      i_packed_t rmask;
+      if (!read_packed(ig, "V", &rmask)) {
         i_push_error(0, "reading pixel masks");
         return 0;
       }
+      masks.masks[i] = rmask;
       /* work out a shift for the mask */
       pos = 0;
       bit = masks.masks[i] & -masks.masks[i];
@@ -1356,7 +1394,7 @@ read_direct_bmp(io_glue *ig, int xsize, int ysize, int bit_count,
   while (y != lasty) {
     p = line;
     for (x = 0; x < xsize; ++x) {
-      unsigned pixel;
+      i_packed_t pixel;
       if (!read_packed(ig, unpack_code, &pixel)) {
         myfree(line);
         if (allow_incomplete) {
index d7e0e81..6d60964 100644 (file)
@@ -4,22 +4,24 @@
 
 int
 i_compose_mask(i_img *out, i_img *src, i_img *mask, 
-              int out_left, int out_top,
-              int src_left, int src_top,
-              int mask_left, int mask_top,
-              int width, int height,
+              i_img_dim out_left, i_img_dim out_top,
+              i_img_dim src_left, i_img_dim src_top,
+              i_img_dim mask_left, i_img_dim mask_top,
+              i_img_dim width, i_img_dim height,
               int combine,
               double opacity) {
   i_render r;
-  int dy;
+  i_img_dim dy;
   i_fill_combine_f combinef_8;
   i_fill_combinef_f combinef_double;
   int channel_zero = 0;
 
-  mm_log((1, "i_compose_mask(out %p, src %p, mask %p, out(%d, %d), src(%d, %d),"
-         " mask(%d,%d), size(%d,%d), combine %d opacity %f\n", out, src, 
-         mask, out_left, out_top, src_left, src_top, mask_left, mask_top, width,
-         height, combine, opacity));
+  mm_log((1, "i_compose_mask(out %p, src %p, mask %p, out(" i_DFp "), "
+         "src(" i_DFp "), mask(" i_DFp "), size(" i_DFp "),"
+         " combine %d opacity %f\n", out, src, 
+         mask, i_DFcp(out_left, out_top), i_DFcp(src_left, src_top),
+         i_DFcp(mask_left, mask_top), i_DFcp(width, height),
+         combine, opacity));
 
   i_clear_error();
   if (out_left >= out->xsize
@@ -99,10 +101,10 @@ i_compose_mask(i_img *out, i_img *src, i_img *mask,
     return 0;
   }
 
-  mm_log((1, "after adjustments: (out(%d, %d), src(%d, %d),"
-         " mask(%d,%d), size(%d,%d)\n", 
-         out_left, out_top, src_left, src_top, mask_left, mask_top, width,
-         height));
+  mm_log((1, "after adjustments: (out(" i_DFp "), src(" i_DFp "),"
+         " mask(" i_DFp "), size(" i_DFp ")\n", 
+         i_DFcp(out_left, out_top), i_DFcp(src_left, src_top),
+         i_DFcp(mask_left, mask_top), i_DFcp(width, height)));
 
   i_get_combine(combine, &combinef_8, &combinef_double);
 
@@ -121,7 +123,7 @@ i_compose_mask(i_img *out, i_img *src, i_img *mask,
     IM_GSAMP(mask, mask_left, mask_left + width, mask_top + dy, 
             mask_line, &channel_zero, 1);
     if (opacity < 1.0) {
-      int i;
+      i_img_dim i;
       IM_SAMPLE_T *maskp = mask_line;
       for (i = 0; i < width; ++i) {
        *maskp = IM_ROUND(*maskp * opacity);
@@ -142,19 +144,20 @@ i_compose_mask(i_img *out, i_img *src, i_img *mask,
 
 int
 i_compose(i_img *out, i_img *src,
-         int out_left, int out_top,
-         int src_left, int src_top,
-         int width, int height,
+         i_img_dim out_left, i_img_dim out_top,
+         i_img_dim src_left, i_img_dim src_top,
+         i_img_dim width, i_img_dim height,
          int combine,
          double opacity) {
   i_render r;
-  int dy;
+  i_img_dim dy;
   i_fill_combine_f combinef_8;
   i_fill_combinef_f combinef_double;
 
-  mm_log((1, "i_compose(out %p, src %p, out(%d, %d), src(%d, %d), size(%d,%d),"
-         " combine %d opacity %f\n", out, src, out_left, out_top,
-         src_left, src_top, width, height, combine, opacity));
+  mm_log((1, "i_compose(out %p, src %p, out(" i_DFp "), src(" i_DFp "), "
+         "size(" i_DFp "), combine %d opacity %f\n", out, src,
+         i_DFcp(out_left, out_top), i_DFcp(src_left, src_top),
+         i_DFcp(width, height), combine, opacity));
 
   i_clear_error();
   if (out_left >= out->xsize
@@ -217,7 +220,7 @@ i_compose(i_img *out, i_img *src,
   int adapt_channels = out->channels;
 
   if (opacity != 1.0) {
-    int i;
+    i_img_dim i;
     IM_SAMPLE_T mask_value = IM_ROUND(opacity * IM_SAMPLE_MAX);
     mask_line = mymalloc(sizeof(IM_SAMPLE_T) * width);
 
diff --git a/conv.im b/conv.im
index b7afa64..b766d7e 100644 (file)
--- a/conv.im
+++ b/conv.im
@@ -6,7 +6,7 @@
   end effects are acounted for by increasing
   scaling the result with the sum of used coefficients
 
-  coeff: (float array) coefficients for filter
+  coeff: (double array) coefficients for filter
     len: length of filter.. number of coefficients
            note that this has to be an odd number
            (since the filter is even);
@@ -14,7 +14,7 @@
 
 int
 i_conv(i_img *im, const double *coeff,int len) {
-  int xo, yo; /* output pixel co-ordinate */
+  i_img_dim xo, yo; /* output pixel co-ordinate */
   int c, ch, center;
   double pc;
   double res[MAXCHANNELS];
@@ -45,7 +45,7 @@ i_conv(i_img *im, const double *coeff,int len) {
       for(ch = 0;ch < im->channels; ch++) 
        res[ch] = 0;
       for(c = 0;c < len; c++) {
-       int xi = xo + c - center;
+       i_img_dim xi = xo + c - center;
        if (xi < 0)
          xi = 0;
        else if (xi >= im->xsize)
@@ -71,7 +71,7 @@ i_conv(i_img *im, const double *coeff,int len) {
       for(ch =  0; ch < im->channels; ch++)
        res[ch] = 0;
       for(c = 0; c < len; c++) {
-       int yi = yo + c - center;
+       i_img_dim yi = yo + c - center;
        if (yi < 0)
          yi = 0;
        else if (yi >= im->ysize)
index b001f4b..9784349 100644 (file)
@@ -65,12 +65,13 @@ Now handles images with more than 8-bits/sample.
 i_img *
 i_convert(i_img *src, const double *coeff, int outchan, int inchan) {
   double work[MAXCHANNELS];
-  int x, y;
+  i_img_dim x, y;
   int i, j;
   int ilimit;
   i_img *im = NULL;
 
-  mm_log((1,"i_convert(src %p, coeff %p,outchan %d, inchan %d)\n",im,src, coeff,outchan, inchan));
+  mm_log((1,"i_convert(im %p, src %p, coeff %p,outchan %d, inchan %d)\n",
+         im, src, coeff, outchan, inchan));
  
   i_clear_error();
 
index a1efb99..c7b37b3 100644 (file)
@@ -8,14 +8,15 @@
 */
 
 struct i_bitmap*
-btm_new(int xsize,int ysize) {
-  int i;
-  int bytes;
+btm_new(i_img_dim xsize,i_img_dim ysize) {
+  i_img_dim i;
+  size_t bytes;
   struct i_bitmap *btm;
   btm=(struct i_bitmap*)mymalloc(sizeof(struct i_bitmap)); /* checked 4jul05 tonyc */
   bytes = (xsize*ysize+8)/8;
   if (bytes * 8 / ysize < xsize-1) { /* this is kind of rough */
-    fprintf(stderr, "Integer overflow allocating bitmap %d x %d", xsize, ysize);
+    fprintf(stderr, "Integer overflow allocating bitmap (" i_DFp ")",
+           i_DFcp(xsize, ysize));
     exit(3);
   }
   btm->data=(char*)mymalloc(bytes); /* checked 4jul05 tonyc */
@@ -34,16 +35,16 @@ btm_destroy(struct i_bitmap *btm) {
 
 
 int
-btm_test(struct i_bitmap *btm,int x,int y) {
-  int btno;
+btm_test(struct i_bitmap *btm,i_img_dim x,i_img_dim y) {
+  i_img_dim btno;
   if (x<0 || x>btm->xsize-1 || y<0 || y>btm->ysize-1) return 0;
   btno=btm->xsize*y+x;
   return (1<<(btno%8))&(btm->data[btno/8]);
 }
 
 void
-btm_set(struct i_bitmap *btm,int x,int y) {
-  int btno;
+btm_set(struct i_bitmap *btm,i_img_dim x,i_img_dim y) {
+  i_img_dim btno;
   if (x<0 || x>btm->xsize-1 || y<0 || y>btm->ysize-1) abort();
   btno=btm->xsize*y+x;
   btm->data[btno/8]|=1<<(btno%8);
@@ -57,49 +58,38 @@ btm_set(struct i_bitmap *btm,int x,int y) {
   Bucketed linked list - stack type 
 */
 
-struct llink *
-llink_new(struct llink* p,int size) {
-  struct llink *l;
-  l       = mymalloc(sizeof(struct llink)); /* checked 4jul05 tonyc */
-  l->n    = NULL;
-  l->p    = p;
-  l->fill = 0;
-  l->data = mymalloc(size); /* checked 4jul05 tonyc - depends on caller to llist_push */
-  return l;
-}
+static struct llink *
+llink_new(struct llink* p,size_t size);
+static int
+llist_llink_push(struct llist *lst, struct llink *lnk,const void *data);
+static void
+llink_destroy(struct llink* l);
 
-/* free's the data pointer, itself, and sets the previous' next pointer to null */
+/*
+=item llist_new()
+=synopsis struct llist *l = llist_new(100, sizeof(foo);
 
-void
-llink_destroy(struct llink* l) {
-  if (l->p != NULL) { l->p->n=NULL; }
-  myfree(l->data);
-  myfree(l);
-}
+Create a new stack structure.  Implemented as a linked list of pools.
 
+Parameters:
 
-/* if it returns true there wasn't room for the
-   item on the link */
+=over
 
-int
-llist_llink_push(struct llist *lst, struct llink *lnk,void *data) {
-  int multip;
-  multip = lst->multip;
+=item *
 
-  /*   fprintf(stderr,"llist_llink_push: data=0x%08X -> 0x%08X\n",data,*(int*)data);
-       fprintf(stderr,"ssize = %d, multip = %d, fill = %d\n",lst->ssize,lst->multip,lnk->fill); */
-  if (lnk->fill == lst->multip) return 1;
-  /*   memcpy((char*)(lnk->data)+lnk->fill*lst->ssize,data,lst->ssize); */
-  memcpy((char*)(lnk->data)+lnk->fill*lst->ssize,data,lst->ssize);
-  
-  /*   printf("data=%X res=%X\n",*(int*)data,*(int*)(lnk->data));*/
-  lnk->fill++;
-  lst->count++;
-  return 0;
-}
+multip - number of entries in each pool
+
+=item *
+
+ssize - size of the objects being pushed/popped
+
+=back
+
+=cut
+*/
 
 struct llist *
-llist_new(int multip, int ssize) {
+llist_new(int multip, size_t ssize) {
   struct llist *l;
   l         = mymalloc(sizeof(struct llist)); /* checked 4jul05 tonyc */
   l->h      = NULL;
@@ -110,9 +100,18 @@ llist_new(int multip, int ssize) {
   return l;
 }
 
+/*
+=item llist_push()
+=synopsis llist_push(l, &foo);
+
+Push an item on the stack.
+
+=cut
+*/
+
 void
-llist_push(struct llist *l,void *data) {
-  int ssize  = l->ssize;
+llist_push(struct llist *l,const void *data) {
+  size_t ssize  = l->ssize;
   int multip = l->multip;
   
   /*  fprintf(stderr,"llist_push: data=0x%08X\n",data);
@@ -136,7 +135,15 @@ llist_push(struct llist *l,void *data) {
   }
 }
 
-/* returns 0 if the list is empty */
+/* 
+=item llist_pop()
+
+Pop an item off the list, storing it at C<data> which must have enough room for an object of the size supplied to llist_new().
+
+returns 0 if the list is empty
+
+=cut
+*/
 
 int
 llist_pop(struct llist *l,void *data) {
@@ -177,6 +184,14 @@ llist_dump(struct llist *l) {
   }
 }
 
+/*
+=item llist_destroy()
+
+Destroy a linked-list based stack.
+
+=cut
+*/
+
 void
 llist_destroy(struct llist *l) {
   struct llink *t,*lnk = l->h;
@@ -188,10 +203,48 @@ llist_destroy(struct llist *l) {
   myfree(l);
 }
 
+/* Links */
+
+static struct llink *
+llink_new(struct llink* p,size_t size) {
+  struct llink *l;
+  l       = mymalloc(sizeof(struct llink)); /* checked 4jul05 tonyc */
+  l->n    = NULL;
+  l->p    = p;
+  l->fill = 0;
+  l->data = mymalloc(size); /* checked 4jul05 tonyc - depends on caller to llist_push */
+  return l;
+}
+
+/* free's the data pointer, itself, and sets the previous' next pointer to null */
+
+static void
+llink_destroy(struct llink* l) {
+  if (l->p != NULL) { l->p->n=NULL; }
+  myfree(l->data);
+  myfree(l);
+}
 
 
+/* if it returns true there wasn't room for the
+   item on the link */
 
+static int
+llist_llink_push(struct llist *lst, struct llink *lnk, const void *data) {
+  int multip;
+  multip = lst->multip;
 
+  /*   fprintf(stderr,"llist_llink_push: data=0x%08X -> 0x%08X\n",data,*(int*)data);
+       fprintf(stderr,"ssize = %d, multip = %d, fill = %d\n",lst->ssize,lst->multip,lnk->fill); */
+  if (lnk->fill == lst->multip) return 1;
+  /*   memcpy((char*)(lnk->data)+lnk->fill*lst->ssize,data,lst->ssize); */
+  memcpy((char*)(lnk->data)+lnk->fill*lst->ssize,data,lst->ssize);
+  
+  /*   printf("data=%X res=%X\n",*(int*)data,*(int*)(lnk->data));*/
+  lnk->fill++;
+  lst->count++;
+  return 0;
+}
 
 /*
   Oct-tree implementation 
@@ -291,3 +344,7 @@ octt_histo(struct octt *ct, unsigned int **col_usage_it_adr) {
 }
 
 
+i_img_dim
+i_abs(i_img_dim x) {
+  return x < 0 ? -x : x;
+}
diff --git a/draw.c b/draw.c
index 58239ed..f36949a 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -29,6 +29,7 @@ i_ppix_norm(i_img *im, i_img_dim x, i_img_dim y, i_color const *col) {
     work = *col;
     i_adapt_colors(2, 4, &work, 1);
     i_gpix(im, x, y, &src);
+    remains = 255 - work.channel[1];
     dest_alpha = work.channel[1] + remains * src.channel[1] / 255;
     if (work.channel[1] == 255) {
       return i_ppix(im, x, y, &work);
@@ -55,6 +56,7 @@ i_ppix_norm(i_img *im, i_img_dim x, i_img_dim y, i_color const *col) {
   case 4:
     work = *col;
     i_gpix(im, x, y, &src);
+    remains = 255 - work.channel[3];
     dest_alpha = work.channel[3] + remains * src.channel[3] / 255;
     if (work.channel[3] == 255) {
       return i_ppix(im, x, y, &work);
@@ -75,12 +77,12 @@ i_ppix_norm(i_img *im, i_img_dim x, i_img_dim y, i_color const *col) {
 
 static void
 cfill_from_btm(i_img *im, i_fill_t *fill, struct i_bitmap *btm, 
-              int bxmin, int bxmax, int bymin, int bymax);
+              i_img_dim bxmin, i_img_dim bxmax, i_img_dim bymin, i_img_dim bymax);
 
 void
-i_mmarray_cr(i_mmarray *ar,int l) {
-  int i;
-  int alloc_size;
+i_mmarray_cr(i_mmarray *ar,i_img_dim l) {
+  i_img_dim i;
+  size_t alloc_size;
 
   ar->lines=l;
   alloc_size = sizeof(minmax) * l;
@@ -100,7 +102,7 @@ i_mmarray_dst(i_mmarray *ar) {
 }
 
 void
-i_mmarray_add(i_mmarray *ar,int x,int y) {
+i_mmarray_add(i_mmarray *ar,i_img_dim x,i_img_dim y) {
   if (y>-1 && y<ar->lines)
     {
       if (x<ar->data[y].min) ar->data[y].min=x;
@@ -109,29 +111,32 @@ i_mmarray_add(i_mmarray *ar,int x,int y) {
 }
 
 int
-i_mmarray_gmin(i_mmarray *ar,int y) {
+i_mmarray_gmin(i_mmarray *ar,i_img_dim y) {
   if (y>-1 && y<ar->lines) return ar->data[y].min;
   else return -1;
 }
 
 int
-i_mmarray_getm(i_mmarray *ar,int y) {
+i_mmarray_getm(i_mmarray *ar,i_img_dim y) {
   if (y>-1 && y<ar->lines) return ar->data[y].max;
   else return MAXINT;
 }
 
+#if 0
+/* unused? */
 void
 i_mmarray_render(i_img *im,i_mmarray *ar,i_color *val) {
-  int i,x;
+  i_img_dim i,x;
   for(i=0;i<ar->lines;i++) if (ar->data[i].max!=-1) for(x=ar->data[i].min;x<ar->data[i].max;x++) i_ppix(im,x,i,val);
 }
+#endif
 
 static
 void
-i_arcdraw(int x1, int y1, int x2, int y2, i_mmarray *ar) {
+i_arcdraw(i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, i_mmarray *ar) {
   double alpha;
   double dsec;
-  int temp;
+  i_img_dim temp;
   alpha=(double)(y2-y1)/(double)(x2-x1);
   if (fabs(alpha) <= 1) 
     {
@@ -139,7 +144,7 @@ i_arcdraw(int x1, int y1, int x2, int y2, i_mmarray *ar) {
       dsec=y1;
       while(x1<=x2)
        {
-         i_mmarray_add(ar,x1,(int)(dsec+0.5));
+         i_mmarray_add(ar,x1,(i_img_dim)(dsec+0.5));
          dsec+=alpha;
          x1++;
        }
@@ -151,7 +156,7 @@ i_arcdraw(int x1, int y1, int x2, int y2, i_mmarray *ar) {
       dsec=x1;
       while(y1<=y2)
        {
-         i_mmarray_add(ar,(int)(dsec+0.5),y1);
+         i_mmarray_add(ar,(i_img_dim)(dsec+0.5),y1);
          dsec+=alpha;
          y1++;
        }
@@ -160,32 +165,33 @@ i_arcdraw(int x1, int y1, int x2, int y2, i_mmarray *ar) {
 
 void
 i_mmarray_info(i_mmarray *ar) {
-  int i;
+  i_img_dim i;
   for(i=0;i<ar->lines;i++)
-  if (ar->data[i].max!=-1) printf("line %d: min=%d, max=%d.\n",i,ar->data[i].min,ar->data[i].max);
+  if (ar->data[i].max!=-1)
+    printf("line %"i_DF ": min=%" i_DF ", max=%" i_DF ".\n",
+          i_DFc(i), i_DFc(ar->data[i].min), i_DFc(ar->data[i].max));
 }
 
 static void
-i_arc_minmax(i_int_hlines *hlines,int x,int y,float rad,float d1,float d2) {
+i_arc_minmax(i_int_hlines *hlines,i_img_dim x,i_img_dim y, double rad,float d1,float d2) {
   i_mmarray dot;
-  float f,fx,fy;
-  int x1,y1;
-
-  /*mm_log((1,"i_arc(im* 0x%x,x %d,y %d,rad %.2f,d1 %.2f,d2 %.2f,val 0x%x)\n",im,x,y,rad,d1,d2,val));*/
+  double f,fx,fy;
+  i_img_dim x1,y1;
 
   i_mmarray_cr(&dot, hlines->limit_y);
 
-  x1=(int)(x+0.5+rad*cos(d1*PI/180.0));
-  y1=(int)(y+0.5+rad*sin(d1*PI/180.0));
+  x1=(i_img_dim)(x+0.5+rad*cos(d1*PI/180.0));
+  y1=(i_img_dim)(y+0.5+rad*sin(d1*PI/180.0));
   fx=(float)x1; fy=(float)y1;
 
   /*  printf("x1: %d.\ny1: %d.\n",x1,y1); */
   i_arcdraw(x, y, x1, y1, &dot);
 
-  x1=(int)(x+0.5+rad*cos(d2*PI/180.0));
-  y1=(int)(y+0.5+rad*sin(d2*PI/180.0));
+  x1=(i_img_dim)(x+0.5+rad*cos(d2*PI/180.0));
+  y1=(i_img_dim)(y+0.5+rad*sin(d2*PI/180.0));
 
-  for(f=d1;f<=d2;f+=0.01) i_mmarray_add(&dot,(int)(x+0.5+rad*cos(f*PI/180.0)),(int)(y+0.5+rad*sin(f*PI/180.0)));
+  for(f=d1;f<=d2;f+=0.01)
+    i_mmarray_add(&dot,(i_img_dim)(x+0.5+rad*cos(f*PI/180.0)),(i_img_dim)(y+0.5+rad*sin(f*PI/180.0)));
   
   /*  printf("x1: %d.\ny1: %d.\n",x1,y1); */
   i_arcdraw(x, y, x1, y1, &dot);
@@ -193,7 +199,7 @@ i_arc_minmax(i_int_hlines *hlines,int x,int y,float rad,float d1,float d2) {
   /* render the minmax values onto the hlines */
   for (y = 0; y < dot.lines; y++) {
     if (dot.data[y].max!=-1) {
-      int minx, width;
+      i_img_dim minx, width;
       minx = dot.data[y].min;
       width = dot.data[y].max - dot.data[y].min + 1;
       i_int_hlines_add(hlines, y, minx, width);
@@ -205,7 +211,7 @@ i_arc_minmax(i_int_hlines *hlines,int x,int y,float rad,float d1,float d2) {
 }
 
 static void
-i_arc_hlines(i_int_hlines *hlines,int x,int y,float rad,float d1,float d2) {
+i_arc_hlines(i_int_hlines *hlines,i_img_dim x,i_img_dim y,double rad,float d1,float d2) {
   if (d1 <= d2) {
     i_arc_minmax(hlines, x, y, rad, d1, d2);
   }
@@ -228,7 +234,7 @@ of angles in degrees from d1 to d2, with the color.
 */
 
 void
-i_arc(i_img *im,int x,int y,float rad,float d1,float d2,const i_color *val) {
+i_arc(i_img *im, i_img_dim x, i_img_dim y,double rad,double d1,double d2,const i_color *val) {
   i_int_hlines hlines;
 
   i_int_init_hlines_img(&hlines, im);
@@ -256,7 +262,7 @@ of angles in degrees from d1 to d2, with the fill object.
 #define MAX_CIRCLE_STEPS 360
 
 void
-i_arc_cfill(i_img *im,int x,int y,float rad,float d1,float d2,i_fill_t *fill) {
+i_arc_cfill(i_img *im, i_img_dim x, i_img_dim y,double rad,double d1,double d2,i_fill_t *fill) {
   i_int_hlines hlines;
 
   i_int_init_hlines_img(&hlines, im);
@@ -273,7 +279,7 @@ arc_poly(int *count, double **xvals, double **yvals,
         double x, double y, double rad, double d1, double d2) {
   double d1_rad, d2_rad;
   double circum;
-  int steps, point_count;
+  i_img_dim steps, point_count;
   double angle_inc;
 
   /* normalize the angles */
@@ -395,19 +401,19 @@ i_arc_aa_cfill(i_img *im, double x, double y, double rad, double d1, double d2,
 /* Temporary AA HACK */
 
 
-typedef int frac;
-static  frac float_to_frac(float x) { return (frac)(0.5+x*16.0); }
+typedef i_img_dim frac;
+static  frac float_to_frac(double x) { return (frac)(0.5+x*16.0); }
 
 static 
 void
-polar_to_plane(float cx, float cy, float angle, float radius, frac *x, frac *y) {
+polar_to_plane(double cx, double cy, float angle, double radius, frac *x, frac *y) {
   *x = float_to_frac(cx+radius*cos(angle));
   *y = float_to_frac(cy+radius*sin(angle));
 }
 
 static
 void
-make_minmax_list(i_mmarray *dot, float x, float y, float radius) {
+make_minmax_list(i_mmarray *dot, double x, double y, double radius) {
   float angle = 0.0;
   float astep = radius>0.1 ? .5/radius : 10;
   frac cx, cy, lx, ly, sx, sy;
@@ -452,7 +458,7 @@ make_minmax_list(i_mmarray *dot, float x, float y, float radius) {
 
 static
 int
-i_pixel_coverage(i_mmarray *dot, int x, int y) {
+i_pixel_coverage(i_mmarray *dot, i_img_dim x, i_img_dim y) {
   frac minx = x*16;
   frac maxx = minx+15;
   frac cy;
@@ -484,12 +490,13 @@ color.
 =cut
 */
 void
-i_circle_aa(i_img *im, float x, float y, float rad, const i_color *val) {
+i_circle_aa(i_img *im, double x, double y, double rad, const i_color *val) {
   i_mmarray dot;
   i_color temp;
-  int ly;
+  i_img_dim ly;
 
-  mm_log((1, "i_circle_aa(im %p, x %d, y %d, rad %.2f, val %p)\n", im, x, y, rad, val));
+  mm_log((1, "i_circle_aa(im %p, centre(" i_DFp "), rad %.2f, val %p)\n",
+         im, i_DFcp(x, y), rad, val));
 
   i_mmarray_cr(&dot,16*im->ysize);
   make_minmax_list(&dot, x, y, rad);
@@ -618,7 +625,6 @@ static i_img_dim
 arc_seg(double angle, int scale) {
   i_img_dim seg = (angle + 45) / 90;
   double remains = angle - seg * 90; /* should be in the range [-45,45] */
-  int sign = remains < 0 ? -1 : remains ? 1 : 0;
 
   while (seg > 4)
     seg -= 4;
@@ -664,7 +670,7 @@ Implementation:
 
 int
 i_arc_out(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r,
-         float d1, float d2, const i_color *col) {
+         double d1, double d2, const i_color *col) {
   i_img_dim x, y;
   i_img_dim dx, dy;
   int error;
@@ -673,7 +679,6 @@ i_arc_out(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r,
   i_img_dim sin_th;
   i_img_dim seg_d1, seg_d2;
   int seg_num;
-  double inv_r;
   i_img_dim scale = r + 1;
   i_img_dim seg1 = scale * 2;
   i_img_dim seg2 = scale * 4;
@@ -766,7 +771,7 @@ i_arc_out(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r,
 
 static double
 cover(i_img_dim r, i_img_dim j) {
-  float rjsqrt = sqrt(r*r - j*j);
+  double rjsqrt = sqrt(r*r - j*j);
 
   return ceil(rjsqrt) - rjsqrt;
 }
@@ -832,8 +837,6 @@ i_circle_out_aa(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, const i_colo
   while (i > j+1) {
     double d;
     int cv, inv_cv;
-    i_color p;
-    int ch;
     j++;
     d = cover(r, j);
     cv = (int)(d * 255 + 0.5);
@@ -912,7 +915,7 @@ Gems.
 */
 
 int
-i_arc_out_aa(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, float d1, float d2, const i_color *col) {
+i_arc_out_aa(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, double d1, double d2, const i_color *col) {
   i_img_dim i, j;
   double t;
   i_color workc = *col;
@@ -977,8 +980,6 @@ i_arc_out_aa(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, float d1, float
     
     while (i > j+1) {
       int cv, inv_cv;
-      i_color p;
-      int ch;
       double d;
       j++;
       d = cover(r, j);
@@ -1050,9 +1051,10 @@ Outlines the box from (x1,y1) to (x2,y2) inclusive with I<color>.
 */
 
 void
-i_box(i_img *im,int x1,int y1,int x2,int y2,const i_color *val) {
-  int x,y;
-  mm_log((1,"i_box(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,val 0x%x)\n",im,x1,y1,x2,y2,val));
+i_box(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val) {
+  i_img_dim x,y;
+  mm_log((1,"i_box(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
+         im, i_DFcp(x1,y1), i_DFcp(x2,y2), val));
   for(x=x1;x<x2+1;x++) {
     i_ppix(im,x,y1,val);
     i_ppix(im,x,y2,val);
@@ -1075,11 +1077,12 @@ Fills the box from (x1,y1) to (x2,y2) inclusive with color.
 */
 
 void
-i_box_filled(i_img *im,int x1,int y1,int x2,int y2, const i_color *val) {
+i_box_filled(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2, const i_color *val) {
   i_img_dim x, y, width;
   i_palidx index;
 
-  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));
+  mm_log((1,"i_box_filled(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
+         im, i_DFcp(x1, y1), i_DFcp(x2,y2) ,val));
 
   if (x1 > x2 || y1 > y2
       || x2 < 0 || y2 < 0
@@ -1135,11 +1138,11 @@ color.
 */
 
 int
-i_box_filledf(i_img *im,int x1,int y1,int x2,int y2, const i_fcolor *val) {
+i_box_filledf(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2, const i_fcolor *val) {
   i_img_dim x, y, width;
-  i_palidx index;
 
-  mm_log((1,"i_box_filledf(im* 0x%x,x1 %d,y1 %d,x2 %d,y2 %d,val 0x%x)\n",im,x1,y1,x2,y2,val));
+  mm_log((1,"i_box_filledf(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
+         im, i_DFcp(x1, y1), i_DFcp(x2, y2), val));
 
   if (x1 > x2 || y1 > y2
       || x2 < 0 || y2 < 0
@@ -1193,9 +1196,11 @@ Fills the box from (x1,y1) to (x2,y2) inclusive with fill.
 */
 
 void
-i_box_cfill(i_img *im,int x1,int y1,int x2,int y2,i_fill_t *fill) {
+i_box_cfill(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_fill_t *fill) {
   i_render r;
-  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));
+
+  mm_log((1,"i_box_cfill(im* %p, p1(" i_DFp "), p2(" i_DFp "), fill %p)\n",
+         im, i_DFcp(x1, y1), i_DFcp(x2,y2), fill));
 
   ++x2;
   if (x1 < 0)
@@ -1238,27 +1243,27 @@ Draw a line to image using Bresenham's line drawing algorithm
 */
 
 void
-i_line(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int endp) {
-  int x, y;
-  int dx, dy;
-  int p;
+i_line(i_img *im, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, const i_color *val, int endp) {
+  i_img_dim x, y;
+  i_img_dim dx, dy;
+  i_img_dim p;
 
   dx = x2 - x1;
   dy = y2 - y1;
 
 
   /* choose variable to iterate on */
-  if (abs(dx)>abs(dy)) {
-    int dx2, dy2, cpy;
+  if (i_abs(dx) > i_abs(dy)) {
+    i_img_dim dx2, dy2, cpy;
 
     /* sort by x */
     if (x1 > x2) {
-      int t;
+      i_img_dim t;
       t = x1; x1 = x2; x2 = t;
       t = y1; y1 = y2; y2 = t;
     }
     
-    dx = abs(dx);
+    dx = i_abs(dx);
     dx2 = dx*2;
     dy = y2 - y1;
 
@@ -1283,16 +1288,16 @@ i_line(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int endp)
       i_ppix(im, x+1, y, val);
     }
   } else {
-    int dy2, dx2, cpx;
+    i_img_dim dy2, dx2, cpx;
 
     /* sort bx y */
     if (y1 > y2) {
-      int t;
+      i_img_dim t;
       t = x1; x1 = x2; x2 = t;
       t = y1; y1 = y2; y2 = t;
     }
     
-    dy = abs(dy);
+    dy = i_abs(dy);
     dx = x2 - x1;
     dy2 = dy*2;
 
@@ -1328,14 +1333,14 @@ i_line(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int endp)
 
 
 void
-i_line_dda(i_img *im, int x1, int y1, int x2, int y2, i_color *val) {
+i_line_dda(i_img *im, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, i_color *val) {
 
-  float dy;
-  int x;
+  double dy;
+  i_img_dim x;
   
   for(x=x1; x<=x2; x++) {
-    dy = y1+ (x-x1)/(float)(x2-x1)*(y2-y1);
-    i_ppix(im, x, (int)(dy+0.5), val);
+    dy = y1+ (x-x1)/(double)(x2-x1)*(y2-y1);
+    i_ppix(im, x, (i_img_dim)(dy+0.5), val);
   }
 }
 
@@ -1352,26 +1357,26 @@ The point (x2, y2) is drawn only if C<endp> is set.
 */
 
 void
-i_line_aa(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int endp) {
-  int x, y;
-  int dx, dy;
-  int p;
+i_line_aa(i_img *im, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, const i_color *val, int endp) {
+  i_img_dim x, y;
+  i_img_dim dx, dy;
+  i_img_dim p;
 
   dx = x2 - x1;
   dy = y2 - y1;
 
   /* choose variable to iterate on */
-  if (abs(dx)>abs(dy)) {
-    int dx2, dy2, cpy;
+  if (i_abs(dx) > i_abs(dy)) {
+    i_img_dim dx2, dy2, cpy;
     
     /* sort by x */
     if (x1 > x2) {
-      int t;
+      i_img_dim t;
       t = x1; x1 = x2; x2 = t;
       t = y1; y1 = y2; y2 = t;
     }
     
-    dx = abs(dx);
+    dx = i_abs(dx);
     dx2 = dx*2;
     dy = y2 - y1;
 
@@ -1389,8 +1394,8 @@ i_line_aa(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int end
     for(x=x1; x<x2-1; x++) {
       int ch;
       i_color tval;
-      float t = (dy) ? -(float)(p)/(float)(dx2) : 1;
-      float t1, t2;
+      double t = (dy) ? -(float)(p)/(float)(dx2) : 1;
+      double t1, t2;
 
       if (t<0) t = 0;
       t1 = 1-t;
@@ -1414,16 +1419,16 @@ i_line_aa(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int end
       }
     }
   } else {
-    int dy2, dx2, cpx;
+    i_img_dim dy2, dx2, cpx;
 
     /* sort bx y */
     if (y1 > y2) {
-      int t;
+      i_img_dim t;
       t = x1; x1 = x2; x2 = t;
       t = y1; y1 = y2; y2 = t;
     }
     
-    dy = abs(dy);
+    dy = i_abs(dy);
     dx = x2 - x1;
     dy2 = dy*2;
 
@@ -1441,8 +1446,8 @@ i_line_aa(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int end
     for(y=y1; y<y2-1; y++) {
       int ch;
       i_color tval;
-      float t = (dx) ? -(float)(p)/(float)(dy2) : 1;
-      float t1, t2;
+      double t = (dx) ? -(double)(p)/(double)(dy2) : 1;
+      double t1, t2;
       
       if (t<0) t = 0;
       t1 = 1-t;
@@ -1450,12 +1455,12 @@ i_line_aa(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int end
 
       i_gpix(im,x,y+1,&tval);
       for(ch=0;ch<im->channels;ch++)
-       tval.channel[ch]=(unsigned char)(t1*(float)tval.channel[ch]+t2*(float)val->channel[ch]);
+       tval.channel[ch]=(unsigned char)(t1*(double)tval.channel[ch]+t2*(double)val->channel[ch]);
       i_ppix(im,x,y+1,&tval);
 
       i_gpix(im,x+cpx,y+1,&tval);
       for(ch=0;ch<im->channels;ch++)
-       tval.channel[ch]=(unsigned char)(t2*(float)tval.channel[ch]+t1*(float)val->channel[ch]);
+       tval.channel[ch]=(unsigned char)(t2*(double)tval.channel[ch]+t1*(double)val->channel[ch]);
       i_ppix(im,x+cpx,y+1,&tval);
 
       if (p<0) {
@@ -1480,9 +1485,9 @@ i_line_aa(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int end
 
 
 static double
-perm(int n,int k) {
+perm(i_img_dim n,i_img_dim k) {
   double r;
-  int i;
+  i_img_dim i;
   r=1;
   for(i=k+1;i<=n;i++) r*=i;
   for(i=1;i<=(n-k);i++) r/=i;
@@ -1500,7 +1505,7 @@ i_bezier_multi(i_img *im,int l,const double *x,const double *y, const i_color *v
   double *bzcoef;
   double t,cx,cy;
   int k,i;
-  int lx = 0,ly = 0;
+  i_img_dim lx = 0,ly = 0;
   int n=l-1;
   double itr,ccoef;
 
@@ -1526,11 +1531,11 @@ i_bezier_multi(i_img *im,int l,const double *x,const double *y, const i_color *v
     }
     /*    printf("%f -> (%d,%d)\n",t,(int)(0.5+cx),(int)(0.5+cy)); */
     if (i++) { 
-      i_line_aa(im,lx,ly,(int)(0.5+cx),(int)(0.5+cy),val, 1);
+      i_line_aa(im,lx,ly,(i_img_dim)(0.5+cx),(i_img_dim)(0.5+cy),val, 1);
     }
-      /*     i_ppix(im,(int)(0.5+cx),(int)(0.5+cy),val); */
-    lx=(int)(0.5+cx);
-    ly=(int)(0.5+cy);
+      /*     i_ppix(im,(i_img_dim)(0.5+cx),(i_img_dim)(0.5+cy),val); */
+    lx=(i_img_dim)(0.5+cx);
+    ly=(i_img_dim)(0.5+cy);
   }
   ICL_info(val);
   myfree(bzcoef);
@@ -1559,9 +1564,9 @@ i_bezier_multi(i_img *im,int l,const double *x,const double *y, const i_color *v
 
 /*
 struct stc {
-  int mylx,myrx; 
-  int dadlx,dadrx;
-  int myy;
+  i_img_dim mylx,myrx; 
+  i_img_dim dadlx,dadrx;
+  i_img_dim myy;
   int mydirection;
 };
 
@@ -1570,9 +1575,9 @@ Not used code???
 
 
 struct stack_element {
-  int myLx,myRx;
-  int dadLx,dadRx;
-  int myY;
+  i_img_dim myLx,myRx;
+  i_img_dim dadLx,dadRx;
+  i_img_dim myY;
   int myDirection;
 };
 
@@ -1581,7 +1586,7 @@ struct stack_element {
 
 static
 struct stack_element*
-crdata(int left,int right,int dadl,int dadr,int y, int dir) {
+crdata(i_img_dim left,i_img_dim right,i_img_dim dadl,i_img_dim dadr,i_img_dim y, int dir) {
   struct stack_element *ste;
   ste              = mymalloc(sizeof(struct stack_element)); /* checked 5jul05 tonyc */
   ste->myLx        = left;
@@ -1616,7 +1621,7 @@ i_ccomp_border(i_color const *val1, i_color const *val2, int ch) {
 }
 
 static int
-i_lspan(i_img *im, int seedx, int seedy, i_color const *val, ff_cmpfunc cmpfunc) {
+i_lspan(i_img *im, i_img_dim seedx, i_img_dim seedy, i_color const *val, ff_cmpfunc cmpfunc) {
   i_color cval;
   while(1) {
     if (seedx-1 < 0) break;
@@ -1629,7 +1634,7 @@ i_lspan(i_img *im, int seedx, int seedy, i_color const *val, ff_cmpfunc cmpfunc)
 }
 
 static int
-i_rspan(i_img *im, int seedx, int seedy, i_color const *val, ff_cmpfunc cmpfunc) {
+i_rspan(i_img *im, i_img_dim seedx, i_img_dim seedy, i_color const *val, ff_cmpfunc cmpfunc) {
   i_color cval;
   while(1) {
     if (seedx+1 > im->xsize-1) break;
@@ -1663,8 +1668,8 @@ i_rspan(i_img *im, int seedx, int seedy, i_color const *val, ff_cmpfunc cmpfunc)
 } while (0)
 
 #define ST_STACK(dir,dadLx,dadRx,lx,rx,y) do {                    \
-  int pushrx = rx+1;                                              \
-  int pushlx = lx-1;                                              \
+  i_img_dim pushrx = rx+1;                                              \
+  i_img_dim pushlx = lx-1;                                              \
   ST_PUSH(lx,rx,pushlx,pushrx,y+dir,dir);                         \
   if (rx > dadRx)                                                 \
     ST_PUSH(dadRx+1,rx,pushlx,pushrx,y-dir,-dir);                 \
@@ -1681,21 +1686,22 @@ i_rspan(i_img *im, int seedx, int seedy, i_color const *val, ff_cmpfunc cmpfunc)
 /* The function that does all the real work */
 
 static struct i_bitmap *
-i_flood_fill_low(i_img *im,int seedx,int seedy,
-                 int *bxminp, int *bxmaxp, int *byminp, int *bymaxp,
+i_flood_fill_low(i_img *im,i_img_dim seedx,i_img_dim seedy,
+                 i_img_dim *bxminp, i_img_dim *bxmaxp, i_img_dim *byminp, i_img_dim *bymaxp,
                 i_color const *seed, ff_cmpfunc cmpfunc) {
-  int ltx, rtx;
-  int tx = 0;
+  i_img_dim ltx, rtx;
+  i_img_dim tx = 0;
 
-  int bxmin = seedx;
-  int bxmax = seedx;
-  int bymin = seedy;
-  int bymax = seedy;
+  i_img_dim bxmin = seedx;
+  i_img_dim bxmax = seedx;
+  i_img_dim bymin = seedy;
+  i_img_dim bymax = seedy;
 
   struct llist *st;
   struct i_bitmap *btm;
 
-  int channels,xsize,ysize;
+  int channels;
+  i_img_dim xsize,ysize;
   i_color cval;
 
   channels = im->channels;
@@ -1717,12 +1723,12 @@ i_flood_fill_low(i_img *im,int seedx,int seedy,
 
   while(st->count) {
     /* Stack variables */
-    int lx,rx;
-    int dadLx,dadRx;
-    int y;
+    i_img_dim lx,rx;
+    i_img_dim dadLx,dadRx;
+    i_img_dim y;
     int direction;
 
-    int x;
+    i_img_dim x;
     int wasIn=0;
 
     ST_POP(); /* sets lx, rx, dadLx, dadRx, y, direction */
@@ -1805,10 +1811,10 @@ Returns false if (C<seedx>, C<seedy>) are outside the image.
 */
 
 undef_int
-i_flood_fill(i_img *im, int seedx, int seedy, const i_color *dcol) {
-  int bxmin, bxmax, bymin, bymax;
+i_flood_fill(i_img *im, i_img_dim seedx, i_img_dim seedy, const i_color *dcol) {
+  i_img_dim bxmin, bxmax, bymin, bymax;
   struct i_bitmap *btm;
-  int x, y;
+  i_img_dim x, y;
   i_color val;
 
   i_clear_error();
@@ -1847,8 +1853,8 @@ Returns false if (C<seedx>, C<seedy>) are outside the image.
 */
 
 undef_int
-i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill) {
-  int bxmin, bxmax, bymin, bymax;
+i_flood_cfill(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill) {
+  i_img_dim bxmin, bxmax, bymin, bymax;
   struct i_bitmap *btm;
   i_color val;
 
@@ -1888,11 +1894,11 @@ Returns false if (C<seedx>, C<seedy>) are outside the image.
 */
 
 undef_int
-i_flood_fill_border(i_img *im, int seedx, int seedy, const i_color *dcol,
+i_flood_fill_border(i_img *im, i_img_dim seedx, i_img_dim seedy, const i_color *dcol,
                    const i_color *border) {
-  int bxmin, bxmax, bymin, bymax;
+  i_img_dim bxmin, bxmax, bymin, bymax;
   struct i_bitmap *btm;
-  int x, y;
+  i_img_dim x, y;
 
   i_clear_error();
   if (seedx < 0 || seedx >= im->xsize ||
@@ -1928,9 +1934,9 @@ Returns false if (C<seedx>, C<seedy>) are outside the image.
 */
 
 undef_int
-i_flood_cfill_border(i_img *im, int seedx, int seedy, i_fill_t *fill,
+i_flood_cfill_border(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill,
                     const i_color *border) {
-  int bxmin, bxmax, bymin, bymax;
+  i_img_dim bxmin, bxmax, bymin, bymax;
   struct i_bitmap *btm;
 
   i_clear_error();
@@ -1953,9 +1959,9 @@ i_flood_cfill_border(i_img *im, int seedx, int seedy, i_fill_t *fill,
 
 static void
 cfill_from_btm(i_img *im, i_fill_t *fill, struct i_bitmap *btm, 
-              int bxmin, int bxmax, int bymin, int bymax) {
-  int x, y;
-  int start;
+              i_img_dim bxmin, i_img_dim bxmax, i_img_dim bymin, i_img_dim bymax) {
+  i_img_dim x, y;
+  i_img_dim start;
 
   i_render r;
 
diff --git a/draw.h b/draw.h
index 3453de3..73d5855 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -1,21 +1,22 @@
 #include "imager.h"
 
 typedef struct {
-  int min,max;
+  i_img_dim min,max;
 }  minmax;
 
 typedef struct {
   minmax *data;
-  int lines;
+  i_img_dim lines;
 } i_mmarray;
 
 /* FIXME: Merge this into datatypes.{c,h} */
 
-void i_mmarray_cr(i_mmarray *ar,int l);
+void i_mmarray_cr(i_mmarray *ar,i_img_dim l);
 void i_mmarray_dst(i_mmarray *ar);
-void i_mmarray_add(i_mmarray *ar,int x,int y);
-int i_mmarray_gmin(i_mmarray *ar,int y);
-int i_mmarray_getm(i_mmarray *ar,int y);
-void i_mmarray_render(i_img *im,i_mmarray *ar,i_color *val);
+void i_mmarray_add(i_mmarray *ar,i_img_dim x,i_img_dim y);
+int i_mmarray_gmin(i_mmarray *ar,i_img_dim y);
+int i_mmarray_getm(i_mmarray *ar,i_img_dim y);
 void i_mmarray_info(i_mmarray *ar);
-
+#if 0
+void i_mmarray_render(i_img *im,i_mmarray *ar,i_color *val);
+#endif
index 75f1b3f..8838038 100644 (file)
@@ -55,7 +55,8 @@ static symbol_table_t symbol_table=
 
 void
 DSO_call(DSO_handle *handle,int func_index,HV* hv) {
-  mm_log((1,"DSO_call(handle 0x%X, func_index %d, hv 0x%X)\n",handle,func_index,hv));
+  mm_log((1,"DSO_call(handle %p, func_index %d, hv %p)\n",
+         handle, func_index, hv));
   (handle->function_list[func_index].iptr)((void*)hv);
 }
 
@@ -129,7 +130,7 @@ DSO_open(char *file, char **evalstring) {
   
   void (*f)(void *s,void *u); /* these will just have to be void for now */
 
-  mm_log( (1,"DSO_open(file '%s' (0x%08X), evalstring 0x%08X)\n",file,file,evalstring) );
+  mm_log( (1,"DSO_open(file '%s' (%p), evalstring %p)\n",file,file,evalstring) );
 
   *evalstring = NULL;
   if ((d_handle = LoadLibrary(file)) == NULL) {
@@ -169,7 +170,7 @@ DSO_open(char *file, char **evalstring) {
   }
   strcpy(dso_handle->filename,file);
 
-  mm_log( (1,"DSO_open <- 0x%X\n",dso_handle) );
+  mm_log( (1,"DSO_open <- %p\n",dso_handle) );
   return (void*)dso_handle;
 
 }
@@ -204,7 +205,8 @@ DSO_open(char* file,char** evalstring) {
   
   *evalstring=NULL;
 
-  mm_log( (1,"DSO_open(file '%s' (0x%08X), evalstring 0x%08X)\n",file,file,evalstring) );
+  mm_log( (1,"DSO_open(file '%s' (%p), evalstring %p)\n",
+          file, file, evalstring) );
 
   if ( (d_handle = dlopen(file, RTLD_LAZY)) == NULL) {
     mm_log( (1,"DSO_open: dlopen failed: %s.\n",dlerror()) );
@@ -265,14 +267,14 @@ DSO_open(char* file,char** evalstring) {
   }
   strcpy(dso_handle->filename,file);
 
-  mm_log( (1,"DSO_open <- 0x%X\n",dso_handle) );
+  mm_log( (1,"DSO_open <- %p\n",dso_handle) );
   return (void*)dso_handle;
 }
 
 undef_int
 DSO_close(void *ptr) {
   DSO_handle *handle;
-  mm_log((1,"DSO_close(ptr 0x%X)\n",ptr));
+  mm_log((1,"DSO_close(ptr %p)\n",ptr));
   handle=(DSO_handle*) ptr;
   return !dlclose(handle->handle);
 }
index 8278d25..664c9ca 100644 (file)
@@ -14,17 +14,17 @@ void
 html_art(void *INP) {
   i_img *im;
   i_color rcolor;
-  int x,y;
+  i_img_dim x,y;
   FILE *fp;
   char *fname;
 
   if ( !getSTR("fname",&fname) ) { fprintf(stderr,"Error: filename is missing\n"); return; } 
   if ( !getOBJ("image","Imager::ImgRaw",&im) ) { fprintf(stderr,"Error: image is missing\n"); return; }
   
-  printf("parameters: (im 0x%p,fname %s)\n",im,fname); 
+  printf("parameters: (im %p,fname %s)\n",im,fname); 
 
-  printf("image info:\n size (%d,%d)\n channels (%d)\n",
-        im->xsize,im->ysize,im->channels); 
+  printf("image info:\n size ("i_DFp ")\n channels (%d)\n",
+        i_DFcp(im->xsize, im->ysize), im->channels); 
 
   fp=fopen(fname,"ab+");
   fprintf(fp,"<TABLE BORDER=\"0\" CELLPADDING=\"0\" CELLSPACING=\"0\">");
index 10e449d..50a9641 100644 (file)
@@ -32,8 +32,10 @@ void lin_stretch(void *INP) {
   int a, b;
   i_img *im;
   i_color rcolor;
-  int i,bytes,x,y;
-  int info[4];
+  int i;
+  i_img_dim x,y;
+  size_t bytes;
+  i_img_dim info[4];
 
   if ( !getOBJ("image","Imager::ImgRaw",&im) ) { fprintf(stderr,"Error: image is missing\n"); }
   if ( !getINT("a",&a) ) { fprintf(stderr,"Error: a is missing\n"); }
@@ -43,9 +45,9 @@ void lin_stretch(void *INP) {
   bytes=im->bytes;
 
   i_img_info(im,info); 
-  for(i=0;i<4;i++) { printf("%d: %d\n",i,info[i]); } 
-  printf("image info:\n size (%d,%d)\n channels (%d)\n",
-        im->xsize, im->ysize, im->channels); 
+  for(i=0;i<4;i++) { printf("%d: %" i_DF "\n", i, i_DFc(info[i])); } 
+  printf("image info:\n size (" i_DFp ")\n channels (%d)\n",
+        i_DFcp(im->xsize, im->ysize), im->channels); 
 
   for(y=0;y<im->ysize;y++) for(x=0;x<im->xsize;x++) {
     i_gpix(im,x,y,&rcolor);
index f018477..0de80e7 100644 (file)
@@ -23,7 +23,7 @@ void
 flines(void *INP) {
   i_img *im;
   i_color vl;
-  int x,y;
+  i_img_dim x,y;
   
   if ( !getOBJ("image","Imager::ImgRaw",&im) ) {
                fprintf(stderr,"Error: image is missing\n"); 
@@ -31,20 +31,20 @@ flines(void *INP) {
        }
   
   fprintf(stderr, "flines: parameters: (im %p)\n",im);
-  fprintf(stderr, "flines: image info:\n size (%d,%d)\n channels (%d)\n",
-         im->xsize,im->ysize,im->channels);
+  fprintf(stderr, "flines: image info:\n size (" i_DFp ")\n channels (%d)\n",
+         i_DFcp(im->xsize,im->ysize), im->channels);
 
   for(y = 0; y < im->ysize; y ++) {
     for(x = 0; x < im->xsize; x ++ ) {
       i_gpix(im,x,y,&vl); 
                        if (!(y%2)) {
-                               float yf = y/(float)im->ysize;
+                               float yf = y/(double)im->ysize;
                                float mf = 1.2-0.8*yf;
                                vl.rgb.r = saturate(vl.rgb.r*mf);
                                vl.rgb.g = saturate(vl.rgb.g*mf);
                                vl.rgb.b = saturate(vl.rgb.b*mf);
                        } else {
-                               float yf = (im->ysize-y)/(float)im->ysize;
+                               float yf = (im->ysize-y)/(double)im->ysize;
                                float mf = 1.2-0.8*yf;
                                vl.rgb.r = saturate(vl.rgb.r*mf);
                                vl.rgb.g = saturate(vl.rgb.g*mf);
index ca3500e..4952ee3 100644 (file)
@@ -14,9 +14,9 @@ char evalstr[]="Mandlebrot renderer";
 
 static
 int
-mandel(float x, float y) {
-  float xn, yn;
-  float xo, yo;
+mandel(double x, double y) {
+  double xn, yn;
+  double xo, yo;
   int iter = 1;
   /*   Z(n+1) = Z(n) ^2 + c */
 
@@ -40,11 +40,12 @@ mandel(float x, float y) {
 void mandlebrot(void *INP) {
 
   i_img *im;
-  int i,bytes,x,y;
+  int i;
+  i_img_dim x,y;
   int idx;
   
-  float xs, ys;
-  float div;
+  double xs, ys;
+  double div;
 
   i_color icl[256];
   srand(12235);
@@ -63,10 +64,9 @@ void mandlebrot(void *INP) {
   if ( !getOBJ("image","Imager::ImgRaw",&im) ) { fprintf(stderr,"Error: image is missing\n"); }
   
   fprintf(stderr,"mandlebrot: parameters: (im %p)\n",im);
-  bytes=im->bytes;
 
-  fprintf(stderr, "mandlebrot: image info:\n size (%d,%d)\n channels (%d)\n",
-         im->xsize,im->ysize,im->channels); 
+  fprintf(stderr, "mandlebrot: image info:\n size (" i_DFp ")\n channels (%d)\n",
+         i_DFcp(im->xsize,im->ysize),im->channels); 
   div = 2.5;
 
   xs = 0.8*div;
diff --git a/error.c b/error.c
index 755f69d..48de989 100644 (file)
--- a/error.c
+++ b/error.c
@@ -222,7 +222,7 @@ error handling is calling function that does.).
 =cut
 */
 void i_push_error(int code, char const *msg) {
-  int size = strlen(msg)+1;
+  size_t size = strlen(msg)+1;
 
   if (error_sp <= 0)
     /* bad, bad programmer */
@@ -315,7 +315,7 @@ int i_failed(int code, char const *msg) {
     failed_cb(error_stack + error_sp);
   if (failures_fatal) {
     int sp;
-    int total; /* total length of error messages */
+    size_t total; /* total length of error messages */
     char *full; /* full message for logging */
     if (argv0)
       fprintf(stderr, "%s: ", argv0);
@@ -329,7 +329,11 @@ int i_failed(int code, char const *msg) {
        i_fatal() */
     total = 1; /* remember the NUL */
     for (sp = error_sp; error_stack[sp].msg; ++sp) {
-      total += strlen(error_stack[sp].msg) + 2;
+      size_t new_total += strlen(error_stack[sp].msg) + 2;
+      if (new_total < total) {
+       /* overflow, somehow */
+       break;
+      }
     }
     full = mymalloc(total);
     if (!full) {
index 764997c..1f19a9a 100644 (file)
@@ -7,3 +7,8 @@ png - http://www.w3.org/TR/PNG/
 gif - zless /usr/share/doc/libungif4g/gif89.txt.gz
 bmp - fileformatdocs/bmp.txt (and MSDN)
 ico - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_icons.asp
+
+TGA
+
+http://paulbourke.net/dataformats/tga/
+
diff --git a/fileformatdocs/spec-gif89a.txt b/fileformatdocs/spec-gif89a.txt
new file mode 100644 (file)
index 0000000..64a0729
--- /dev/null
@@ -0,0 +1,2476 @@
+
+
+
+
+    Cover Sheet for the GIF89a Specification
+
+
+    DEFERRED CLEAR CODE IN LZW COMPRESSION
+
+    There has been confusion about where clear codes can be found in the
+    data stream.  As the specification says, they may appear at anytime.  There
+    is not a requirement to send a clear code when the string table is full.
+
+    It is the encoder's decision as to when the table should be cleared.  When
+    the table is full, the encoder can chose to use the table as is, making no
+    changes to it until the encoder chooses to clear it.  The encoder during
+    this time sends out codes that are of the maximum Code Size.
+
+    As we can see from the above, when the decoder's table is full, it must
+    not change the table until a clear code is received.  The Code Size is that
+    of the maximum Code Size.  Processing other than this is done normally.
+
+    Because of a large base of decoders that do not handle the decompression in
+    this manner, we ask developers of GIF encoding software to NOT implement
+    this feature until at least January 1991 and later if they see that their
+    particular market is not ready for it.  This will give developers of GIF
+    decoding software time to implement this feature and to get it into the
+    hands of their clients before the decoders start "breaking" on the new
+    GIF's.  It is not required that encoders change their software to take
+    advantage of the deferred clear code, but it is for decoders.
+
+    APPLICATION EXTENSION BLOCK - APPLICATION IDENTIFIER
+
+    There will be a Courtesy Directory file located on CompuServe in the PICS
+    forum.  This directory will contain Application Identifiers for Application
+    Extension Blocks that have been used by developers of GIF applications.
+    This file is intended to help keep developers that wish to create
+    Application Extension Blocks from using the same Application Identifiers.
+    This is not an official directory; it is for voluntary participation only
+    and does not guarantee that someone will not use the same identifier.
+
+    E-Mail can be sent to Larry Wood (forum manager of PICS) indicating the
+    request for inclusion in this file with an identifier.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                        GRAPHICS INTERCHANGE FORMAT(sm)
+
+                                  Version 89a
+
+                            (c)1987,1988,1989,1990
+
+                                   Copyright
+                            CompuServe Incorporated
+                                Columbus, Ohio
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+CompuServe Incorporated                           Graphics Interchange Format
+Document Date : 31 July 1990                            Programming Reference
+
+
+
+
+
+
+
+
+
+
+                               Table of Contents
+
+Disclaimer.................................................................  1
+
+Foreword...................................................................  1
+
+Licensing..................................................................  1
+
+About the Document.........................................................  2
+
+General Description........................................................  2
+
+Version Numbers............................................................  2
+
+The Encoder................................................................  3
+
+The Decoder................................................................  3
+
+Compliance.................................................................  3
+
+About Recommendations......................................................  4
+
+About Color Tables.........................................................  4
+
+Blocks, Extensions and Scope...............................................  4
+
+Block Sizes................................................................  5
+
+Using GIF as an embedded protocol..........................................  5
+
+Data Sub-blocks............................................................  5
+
+Block Terminator...........................................................  6
+
+Header.....................................................................  7
+
+Logical Screen Descriptor..................................................  8
+
+Global Color Table......................................................... 10
+
+Image Descriptor........................................................... 11
+
+Local Color Table.......................................................... 13
+
+Table Based Image Data..................................................... 14
+
+Graphic Control Extension.................................................. 15
+
+Comment Extension.......................................................... 17
+
+Plain Text Extension....................................................... 18
+
+Application Extension...................................................... 21
+
+Trailer.................................................................... 23
+
+
+
+
+
+
+
+
+
+
+
+Quick Reference Table...................................................... 24
+
+GIF Grammar................................................................ 25
+
+Glossary................................................................... 27
+
+Conventions................................................................ 28
+
+Interlaced Images.......................................................... 29
+
+Variable-Length-Code LZW Compression....................................... 30
+
+On-line Capabilities Dialogue.............................................. 33
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                         1
+
+
+1. Disclaimer.
+
+The information provided herein is subject to change without notice. In no
+event will CompuServe Incorporated be liable for damages, including any loss of
+revenue, loss of profits or other incidental or consequential damages arising
+out of the use or inability to use the information; CompuServe Incorporated
+makes no claim as to the suitability of the information.
+
+
+2. Foreword.
+
+This document defines the Graphics Interchange Format(sm). The specification
+given here defines version 89a, which is an extension of version 87a.
+
+The Graphics Interchange Format(sm) as specified here should be considered
+complete; any deviation from it should be considered invalid, including but not
+limited to, the use of reserved or undefined fields within control or data
+blocks, the inclusion of extraneous data within or between blocks, the use of
+methods or algorithms not specifically listed as part of the format, etc. In
+general, any and all deviations, extensions or modifications not specified in
+this document should be considered to be in violation of the format and should
+be avoided.
+
+
+3. Licensing.
+
+The Graphics Interchange Format(c) is the copyright property of CompuServe
+Incorporated. Only CompuServe Incorporated is authorized to define, redefine,
+enhance, alter, modify or change in any way the definition of the format.
+
+CompuServe Incorporated hereby grants a limited, non-exclusive, royalty-free
+license for the use of the Graphics Interchange Format(sm) in computer
+software; computer software utilizing GIF(sm) must acknowledge ownership of the
+Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in
+User and Technical Documentation. Computer software utilizing GIF, which is
+distributed or may be distributed without User or Technical Documentation must
+display to the screen or printer a message acknowledging ownership of the
+Graphics Interchange Format and the Service Mark by CompuServe Incorporated; in
+this case, the acknowledgement may be displayed in an opening screen or leading
+banner, or a closing screen or trailing banner. A message such as the following
+may be used:
+
+      "The Graphics Interchange Format(c) is the Copyright property of
+      CompuServe Incorporated. GIF(sm) is a Service Mark property of
+      CompuServe Incorporated."
+
+For further information, please contact :
+
+      CompuServe Incorporated
+      Graphics Technology Department
+      5000 Arlington Center Boulevard
+      Columbus, Ohio  43220
+      U. S. A.
+
+CompuServe Incorporated maintains a mailing list with all those individuals and
+organizations who wish to receive copies of this document when it is corrected
+
+
+
+
+
+
+
+                                                                         2
+
+
+or revised. This service is offered free of charge; please provide us with your
+mailing address.
+
+
+4. About the Document.
+
+This document describes in detail the definition of the Graphics Interchange
+Format.  This document is intended as a programming reference; it is
+recommended that the entire document be read carefully before programming,
+because of the interdependence of the various parts. There is an individual
+section for each of the Format blocks. Within each section, the sub-section
+labeled Required Version refers to the version number that an encoder will have
+to use if the corresponding block is used in the Data Stream. Within each
+section, a diagram describes the individual fields in the block; the diagrams
+are drawn vertically; top bytes in the diagram appear first in the Data Stream.
+Bits within a byte are drawn most significant on the left end.  Multi-byte
+numeric fields are ordered Least Significant Byte first. Numeric constants are
+represented as Hexadecimal numbers, preceded by "0x".  Bit fields within a byte
+are described in order from most significant bits to least significant bits.
+
+
+5. General Description.
+
+The Graphics Interchange Format(sm) defines a protocol intended for the on-line
+transmission and interchange of raster graphic data in a way that is
+independent of the hardware used in their creation or display.
+
+The Graphics Interchange Format is defined in terms of blocks and sub-blocks
+which contain relevant parameters and data used in the reproduction of a
+graphic. A GIF Data Stream is a sequence of protocol blocks and sub-blocks
+representing a collection of graphics. In general, the graphics in a Data
+Stream are assumed to be related to some degree, and to share some control
+information; it is recommended that encoders attempt to group together related
+graphics in order to minimize hardware changes during processing and to
+minimize control information overhead. For the same reason, unrelated graphics
+or graphics which require resetting hardware parameters should be encoded
+separately to the extent possible.
+
+A Data Stream may originate locally, as when read from a file, or it may
+originate remotely, as when transmitted over a data communications line. The
+Format is defined with the assumption that an error-free Transport Level
+Protocol is used for communications; the Format makes no provisions for
+error-detection and error-correction.
+
+The GIF Data Stream must be interpreted in context, that is, the application
+program must rely on information external to the Data Stream to invoke the
+decoder process.
+
+
+6. Version Numbers.
+
+The version number in the Header of a Data Stream is intended to identify the
+minimum set of capabilities required of a decoder in order to fully process the
+Data Stream.  An encoder should use the earliest possible version number that
+includes all the blocks used in the Data Stream. Within each block section in
+this document, there is an entry labeled Required Version which specifies the
+
+
+
+
+
+
+
+                                                                         3
+
+
+earliest version number that includes the corresponding block.  The encoder
+should make every attempt to use the earliest version number covering all the
+blocks in the Data Stream; the unnecessary use of later version numbers will
+hinder processing by some decoders.
+
+
+7. The Encoder.
+
+The Encoder is the program used to create a GIF Data Stream. From raster data
+and other information, the encoder produces the necessary control and data
+blocks needed for reproducing the original graphics.
+
+The encoder has the following primary responsibilities.
+
+            - Include in the Data Stream all the necessary information to
+            reproduce  the graphics.
+
+            - Insure that a Data Stream is labeled with the earliest possible
+            Version Number that will cover the definition of all the blocks in
+            it; this is to ensure that the largest number of decoders can
+            process the Data Stream.
+
+            - Ensure encoding of the graphics in such a way that the decoding
+            process is optimized. Avoid redundant information as much as
+            possible.
+
+            - To the extent possible, avoid grouping graphics which might
+            require resetting hardware parameters during the decoding process.
+
+            - Set to zero (off) each of the bits of each and every field
+            designated as reserved. Note that some fields in the Logical Screen
+            Descriptor and the Image Descriptor were reserved under Version
+            87a, but are used under version 89a.
+
+
+8. The Decoder.
+
+The Decoder is the program used to process a GIF Data Stream. It processes the
+Data Stream sequentially, parsing the various blocks and sub-blocks, using the
+control information to set hardware and process parameters and interpreting the
+data to render the graphics.
+
+The decoder has the following primary responsibilities.
+
+            - Process each graphic in the Data Stream in sequence, without
+            delays other than those specified in the control information.
+
+            - Set its hardware parameters to fit, as closely as possible, the
+            control information contained in the Data Stream.
+
+
+9. Compliance.
+
+An encoder or a decoder is said to comply with a given version of the Graphics
+Interchange Format if and only if it fully conforms with and correctly
+implements the definition of the standard associated with that version.  An
+
+
+
+
+
+
+
+                                                                         4
+
+
+encoder or a decoder may be compliant with a given version number and not
+compliant with some subsequent version.
+
+
+10. About Recommendations.
+
+Each block section in this document contains an entry labeled Recommendation;
+this section lists a set of recommendations intended to guide and organize the
+use of the particular blocks. Such recommendations are geared towards making
+the functions of encoders and decoders more efficient, as well as making
+optimal use of the communications bandwidth.  It is advised that these
+recommendations be followed.
+
+
+11. About Color Tables.
+
+The GIF format utilizes color tables to render raster-based graphics. A color
+table can have one of two different scopes: global or local. A Global Color
+Table is used by all those graphics in the Data Stream which do not have a
+Local Color Table associated with them. The scope of the Global Color Table is
+the entire Data Stream. A Local Color Table is always associated with the
+graphic that immediately follows it; the scope of a Local Color Table is
+limited to that single graphic. A Local Color Table supersedes a Global Color
+Table, that is, if a Data Stream contains a Global Color Table, and an image
+has a Local Color Table associated with it, the decoder must save the Global
+Color Table, use the Local Color Table to render the image, and then restore
+the Global Color Table. Both types of color tables are optional, making it
+possible for a Data Stream to contain numerous graphics without a color table
+at all. For this reason, it is recommended that the decoder save the last
+Global Color Table used until another Global Color Table is encountered. In
+this way, a Data Stream which does not contain either a Global Color Table or
+a Local Color Table may be processed using the last Global Color Table saved.
+If a Global Color Table from a previous Stream is used, that table becomes the
+Global Color Table of the present Stream. This is intended to reduce the
+overhead incurred by color tables. In particular, it is recommended that an
+encoder use only one Global Color Table if all the images in related Data
+Streams can be rendered with the same table.  If no color table is available at
+all, the decoder is free to use a system color table or a table of its own. In
+that case, the decoder may use a color table with as many colors as its
+hardware is able to support; it is recommended that such a table have black and
+white as its first two entries, so that monochrome images can be rendered
+adequately.
+
+The Definition of the GIF Format allows for a Data Stream to contain only the
+Header, the Logical Screen Descriptor, a Global Color Table and the GIF
+Trailer. Such a Data Stream would be used to load a decoder with a Global Color
+Table, in preparation for subsequent Data Streams without a color table at all.
+
+
+12. Blocks, Extensions and Scope.
+
+Blocks can be classified into three groups : Control, Graphic-Rendering and
+Special Purpose.  Control blocks, such as the Header, the Logical Screen
+Descriptor, the Graphic Control Extension and the Trailer, contain information
+used to control the process of the Data Stream or information  used in setting
+hardware parameters.  Graphic-Rendering blocks such as the Image Descriptor and
+
+
+
+
+
+
+
+                                                                         5
+
+
+the Plain Text Extension contain information and data used to render a graphic
+on the display device. Special Purpose blocks such as the Comment Extension and
+the Application Extension are neither used to control the process of the Data
+Stream nor do they contain information or data used to render a graphic on the
+display device. With the exception of the Logical Screen Descriptor and the
+Global Color Table, whose scope is the entire Data Stream, all other Control
+blocks have a limited scope, restricted to the Graphic-Rendering block that
+follows them.  Special Purpose blocks do not delimit the scope of any Control
+blocks; Special Purpose blocks are transparent to the decoding process.
+Graphic-Rendering blocks and extensions are used as scope delimiters for
+Control blocks and extensions. The labels used to identify labeled blocks fall
+into three ranges : 0x00-0x7F (0-127) are the Graphic Rendering blocks,
+excluding the Trailer (0x3B); 0x80-0xF9 (128-249) are the Control blocks;
+0xFA-0xFF (250-255) are the Special Purpose blocks. These ranges are defined so
+that decoders can handle block scope by appropriately identifying block labels,
+even when the block itself cannot be processed.
+
+
+13. Block Sizes.
+
+The Block Size field in a block, counts the number of bytes remaining in the
+block, not counting the Block Size field itself, and not counting the Block
+Terminator, if one is to follow.  Blocks other than Data Blocks are intended to
+be of fixed length; the Block Size field is provided in order to facilitate
+skipping them, not to allow their size to change in the future.  Data blocks
+and sub-blocks are of variable length to accommodate the amount of data.
+
+
+14. Using GIF as an embedded protocol.
+
+As an embedded protocol, GIF may be part of larger application protocols,
+within which GIF is used to render graphics.  In such a case, the application
+protocol could define a block within which the GIF Data Stream would be
+contained. The application program would then invoke a GIF decoder upon
+encountering a block of type GIF.  This approach is recommended in favor of
+using Application Extensions, which become overhead for all other applications
+that do not process them. Because a GIF Data Stream must be processed in
+context, the application must rely on some means of identifying the GIF Data
+Stream outside of the Stream itself.
+
+
+15. Data Sub-blocks.
+
+      a. Description. Data Sub-blocks are units containing data. They do not
+      have a label, these blocks are processed in the context of control
+      blocks, wherever data blocks are specified in the format. The first byte
+      of the Data sub-block indicates the number of data bytes to follow. A
+      data sub-block may contain from 0 to 255 data bytes. The size of the
+      block does not account for the size byte itself, therefore, the empty
+      sub-block is one whose size field contains 0x00.
+
+      b. Required Version.  87a.
+
+
+
+
+
+
+
+
+
+
+
+                                                                         6
+
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+  0  |               |       Block Size                    Byte
+     +---------------+
+  1  |               |
+     +-             -+
+  2  |               |
+     +-             -+
+  3  |               |
+     +-             -+
+     |               |       Data Values                   Byte
+     +-             -+
+ up  |               |
+     +-   . . . .   -+
+ to  |               |
+     +-             -+
+     |               |
+     +-             -+
+255  |               |
+     +---------------+
+
+            i) Block Size - Number of bytes in the Data Sub-block; the size
+            must be within 0 and 255 bytes, inclusive.
+
+            ii) Data Values - Any 8-bit value. There must be exactly as many
+            Data Values as specified by the Block Size field.
+
+      d. Extensions and Scope. This type of block always occurs as part of a
+      larger unit. It does not have a scope of itself.
+
+      e. Recommendation. None.
+
+
+16. Block Terminator.
+
+      a. Description. This zero-length Data Sub-block is used to terminate a
+      sequence of Data Sub-blocks. It contains a single byte in the position of
+      the Block Size field and does not contain data.
+
+      b. Required Version.  87a.
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+  0  |               |       Block Size                    Byte
+     +---------------+
+
+            i) Block Size - Number of bytes in the Data Sub-block; this field
+            contains the fixed value 0x00.
+
+            ii) Data Values - This block does not contain any data.
+
+
+
+
+
+
+
+
+
+                                                                         7
+
+
+      d. Extensions and Scope. This block terminates the immediately preceding
+      sequence of Data Sub-blocks. This block cannot be modified by any
+      extension.
+
+      e. Recommendation. None.
+
+
+17. Header.
+
+      a. Description. The Header identifies the GIF Data Stream in context. The
+      Signature field marks the beginning of the Data Stream, and the Version
+      field identifies the set of capabilities required of a decoder to fully
+      process the Data Stream.  This block is REQUIRED; exactly one Header must
+      be present per Data Stream.
+
+      b. Required Version.  Not applicable. This block is not subject to a
+      version number. This block must appear at the beginning of every Data
+      Stream.
+
+      c. Syntax.
+
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+   0 |               |       Signature                     3 Bytes
+     +-             -+
+   1 |               |
+     +-             -+
+   2 |               |
+     +---------------+
+   3 |               |       Version                       3 Bytes
+     +-             -+
+   4 |               |
+     +-             -+
+   5 |               |
+     +---------------+
+
+            i) Signature - Identifies the GIF Data Stream. This field contains
+            the fixed value 'GIF'.
+
+            ii) Version - Version number used to format the data stream.
+            Identifies the minimum set of capabilities necessary to a decoder
+            to fully process the contents of the Data Stream.
+
+            Version Numbers as of 10 July 1990 :       "87a" - May 1987
+                                                       "89a" - July 1989
+
+            Version numbers are ordered numerically increasing on the first two
+            digits starting with 87 (87,88,...,99,00,...,85,86) and
+            alphabetically increasing on the third character (a,...,z).
+
+            iii) Extensions and Scope. The scope of this block is the entire
+            Data Stream. This block cannot be modified by any extension.
+
+
+
+
+
+
+
+
+
+
+                                                                         8
+
+
+      d. Recommendations.
+
+            i) Signature - This field identifies the beginning of the GIF Data
+            Stream; it is not intended to provide a unique signature for the
+            identification of the data. It is recommended that the GIF Data
+            Stream be identified externally by the application. (Refer to
+            Appendix G for on-line identification of the GIF Data Stream.)
+
+            ii) Version - ENCODER : An encoder should use the earliest possible
+            version number that defines all the blocks used in the Data Stream.
+            When two or more Data Streams are combined, the latest of the
+            individual version numbers should be used for the resulting Data
+            Stream. DECODER : A decoder should attempt to process the data
+            stream to the best of its ability; if it encounters a version
+            number which it is not capable of processing fully, it should
+            nevertheless, attempt to process the data stream to the best of its
+            ability, perhaps after warning the user that the data may be
+            incomplete.
+
+
+18. Logical Screen Descriptor.
+
+      a. Description.  The Logical Screen Descriptor contains the parameters
+      necessary to define the area of the display device within which the
+      images will be rendered.  The coordinates in this block are given with
+      respect to the top-left corner of the virtual screen; they do not
+      necessarily refer to absolute coordinates on the display device.  This
+      implies that they could refer to window coordinates in a window-based
+      environment or printer coordinates when a printer is used.
+
+      This block is REQUIRED; exactly one Logical Screen Descriptor must be
+      present per Data Stream.
+
+      b. Required Version.  Not applicable. This block is not subject to a
+      version number. This block must appear immediately after the Header.
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+  0  |               |       Logical Screen Width          Unsigned
+     +-             -+
+  1  |               |
+     +---------------+
+  2  |               |       Logical Screen Height         Unsigned
+     +-             -+
+  3  |               |
+     +---------------+
+  4  | |     | |     |       <Packed Fields>               See below
+     +---------------+
+  5  |               |       Background Color Index        Byte
+     +---------------+
+  6  |               |       Pixel Aspect Ratio            Byte
+     +---------------+
+
+
+
+
+
+
+
+
+
+                                                                         9
+
+
+     <Packed Fields>  =      Global Color Table Flag       1 Bit
+                             Color Resolution              3 Bits
+                             Sort Flag                     1 Bit
+                             Size of Global Color Table    3 Bits
+
+            i) Logical Screen Width - Width, in pixels, of the Logical Screen
+            where the images will be rendered in the displaying device.
+
+            ii) Logical Screen Height - Height, in pixels, of the Logical
+            Screen where the images will be rendered in the displaying device.
+
+            iii) Global Color Table Flag - Flag indicating the presence of a
+            Global Color Table; if the flag is set, the Global Color Table will
+            immediately follow the Logical Screen Descriptor. This flag also
+            selects the interpretation of the Background Color Index; if the
+            flag is set, the value of the Background Color Index field should
+            be used as the table index of the background color. (This field is
+            the most significant bit of the byte.)
+
+            Values :    0 -   No Global Color Table follows, the Background
+                              Color Index field is meaningless.
+                        1 -   A Global Color Table will immediately follow, the
+                              Background Color Index field is meaningful.
+
+            iv) Color Resolution - Number of bits per primary color available
+            to the original image, minus 1. This value represents the size of
+            the entire palette from which the colors in the graphic were
+            selected, not the number of colors actually used in the graphic.
+            For example, if the value in this field is 3, then the palette of
+            the original image had 4 bits per primary color available to create
+            the image.  This value should be set to indicate the richness of
+            the original palette, even if not every color from the whole
+            palette is available on the source machine.
+
+            v) Sort Flag - Indicates whether the Global Color Table is sorted.
+            If the flag is set, the Global Color Table is sorted, in order of
+            decreasing importance. Typically, the order would be decreasing
+            frequency, with most frequent color first. This assists a decoder,
+            with fewer available colors, in choosing the best subset of colors;
+            the decoder may use an initial segment of the table to render the
+            graphic.
+
+            Values :    0 -   Not ordered.
+                        1 -   Ordered by decreasing importance, most
+                              important color first.
+
+            vi) Size of Global Color Table - If the Global Color Table Flag is
+            set to 1, the value in this field is used to calculate the number
+            of bytes contained in the Global Color Table. To determine that
+            actual size of the color table, raise 2 to [the value of the field
+            + 1].  Even if there is no Global Color Table specified, set this
+            field according to the above formula so that decoders can choose
+            the best graphics mode to display the stream in.  (This field is
+            made up of the 3 least significant bits of the byte.)
+
+            vii) Background Color Index - Index into the Global Color Table for
+
+
+
+
+
+
+
+                                                                        10
+
+
+            the Background Color. The Background Color is the color used for
+            those pixels on the screen that are not covered by an image. If the
+            Global Color Table Flag is set to (zero), this field should be zero
+            and should be ignored.
+
+            viii) Pixel Aspect Ratio - Factor used to compute an approximation
+            of the aspect ratio of the pixel in the original image.  If the
+            value of the field is not 0, this approximation of the aspect ratio
+            is computed based on the formula:
+
+            Aspect Ratio = (Pixel Aspect Ratio + 15) / 64
+
+            The Pixel Aspect Ratio is defined to be the quotient of the pixel's
+            width over its height.  The value range in this field allows
+            specification of the widest pixel of 4:1 to the tallest pixel of
+            1:4 in increments of 1/64th.
+
+            Values :        0 -   No aspect ratio information is given.
+                       1..255 -   Value used in the computation.
+
+      d. Extensions and Scope. The scope of this block is the entire Data
+      Stream. This block cannot be modified by any extension.
+
+      e. Recommendations. None.
+
+
+19. Global Color Table.
+
+      a. Description. This block contains a color table, which is a sequence of
+      bytes representing red-green-blue color triplets. The Global Color Table
+      is used by images without a Local Color Table and by Plain Text
+      Extensions. Its presence is marked by the Global Color Table Flag being
+      set to 1 in the Logical Screen Descriptor; if present, it immediately
+      follows the Logical Screen Descriptor and contains a number of bytes
+      equal to
+                    3 x 2^(Size of Global Color Table+1).
+
+      This block is OPTIONAL; at most one Global Color Table may be present
+      per Data Stream.
+
+      b. Required Version.  87a
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        11
+
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +===============+
+  0  |               |       Red 0                         Byte
+     +-             -+
+  1  |               |       Green 0                       Byte
+     +-             -+
+  2  |               |       Blue 0                        Byte
+     +-             -+
+  3  |               |       Red 1                         Byte
+     +-             -+
+     |               |       Green 1                       Byte
+     +-             -+
+ up  |               |
+     +-   . . . .   -+       ...
+ to  |               |
+     +-             -+
+     |               |       Green 255                     Byte
+     +-             -+
+767  |               |       Blue 255                      Byte
+     +===============+
+
+
+      d. Extensions and Scope. The scope of this block is the entire Data
+      Stream. This block cannot be modified by any extension.
+
+      e. Recommendation. None.
+
+
+20. Image Descriptor.
+
+      a. Description. Each image in the Data Stream is composed of an Image
+      Descriptor, an optional Local Color Table, and the image data.  Each
+      image must fit within the boundaries of the Logical Screen, as defined
+      in the Logical Screen Descriptor.
+
+      The Image Descriptor contains the parameters necessary to process a table
+      based image. The coordinates given in this block refer to coordinates
+      within the Logical Screen, and are given in pixels. This block is a
+      Graphic-Rendering Block, optionally preceded by one or more Control
+      blocks such as the Graphic Control Extension, and may be optionally
+      followed by a Local Color Table; the Image Descriptor is always followed
+      by the image data.
+
+      This block is REQUIRED for an image.  Exactly one Image Descriptor must
+      be present per image in the Data Stream.  An unlimited number of images
+      may be present per Data Stream.
+
+      b. Required Version.  87a.
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        12
+
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+  0  |               |       Image Separator               Byte
+     +---------------+
+  1  |               |       Image Left Position           Unsigned
+     +-             -+
+  2  |               |
+     +---------------+
+  3  |               |       Image Top Position            Unsigned
+     +-             -+
+  4  |               |
+     +---------------+
+  5  |               |       Image Width                   Unsigned
+     +-             -+
+  6  |               |
+     +---------------+
+  7  |               |       Image Height                  Unsigned
+     +-             -+
+  8  |               |
+     +---------------+
+  9  | | | |   |     |       <Packed Fields>               See below
+     +---------------+
+
+     <Packed Fields>  =      Local Color Table Flag        1 Bit
+                             Interlace Flag                1 Bit
+                             Sort Flag                     1 Bit
+                             Reserved                      2 Bits
+                             Size of Local Color Table     3 Bits
+
+           i) Image Separator - Identifies the beginning of an Image
+           Descriptor. This field contains the fixed value 0x2C.
+
+           ii) Image Left Position - Column number, in pixels, of the left edge
+           of the image, with respect to the left edge of the Logical Screen.
+           Leftmost column of the Logical Screen is 0.
+
+           iii) Image Top Position - Row number, in pixels, of the top edge of
+           the image with respect to the top edge of the Logical Screen. Top
+           row of the Logical Screen is 0.
+
+           iv) Image Width - Width of the image in pixels.
+
+           v) Image Height - Height of the image in pixels.
+
+           vi) Local Color Table Flag - Indicates the presence of a Local Color
+           Table immediately following this Image Descriptor. (This field is
+           the most significant bit of the byte.)
+
+
+           Values :    0 -   Local Color Table is not present. Use
+                             Global Color Table if available.
+                       1 -   Local Color Table present, and to follow
+                             immediately after this Image Descriptor.
+
+
+
+
+
+
+
+
+                                                                        13
+
+
+           vii) Interlace Flag - Indicates if the image is interlaced. An image
+           is interlaced in a four-pass interlace pattern; see Appendix E for
+           details.
+
+           Values :    0 - Image is not interlaced.
+                       1 - Image is interlaced.
+
+            viii) Sort Flag - Indicates whether the Local Color Table is
+            sorted.  If the flag is set, the Local Color Table is sorted, in
+            order of decreasing importance. Typically, the order would be
+            decreasing frequency, with most frequent color first. This assists
+            a decoder, with fewer available colors, in choosing the best subset
+            of colors; the decoder may use an initial segment of the table to
+            render the graphic.
+
+            Values :    0 -   Not ordered.
+                        1 -   Ordered by decreasing importance, most
+                              important color first.
+
+            ix) Size of Local Color Table - If the Local Color Table Flag is
+            set to 1, the value in this field is used to calculate the number
+            of bytes contained in the Local Color Table. To determine that
+            actual size of the color table, raise 2 to the value of the field
+            + 1. This value should be 0 if there is no Local Color Table
+            specified. (This field is made up of the 3 least significant bits
+            of the byte.)
+
+     d. Extensions and Scope. The scope of this block is the Table-based Image
+     Data Block that follows it. This block may be modified by the Graphic
+     Control Extension.
+
+     e. Recommendation. None.
+
+
+21. Local Color Table.
+
+     a. Description. This block contains a color table, which is a sequence of
+     bytes representing red-green-blue color triplets. The Local Color Table
+     is used by the image that immediately follows. Its presence is marked by
+     the Local Color Table Flag being set to 1 in the Image Descriptor; if
+     present, the Local Color Table immediately follows the Image Descriptor
+     and contains a number of bytes equal to
+                          3x2^(Size of Local Color Table+1).
+     If present, this color table temporarily becomes the active color table
+     and the following image should be processed using it. This block is
+     OPTIONAL; at most one Local Color Table may be present per Image
+     Descriptor and its scope is the single image associated with the Image
+     Descriptor that precedes it.
+
+     b. Required Version.  87a.
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        14
+
+
+     c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +===============+
+  0  |               |       Red 0                         Byte
+     +-             -+
+  1  |               |       Green 0                       Byte
+     +-             -+
+  2  |               |       Blue 0                        Byte
+     +-             -+
+  3  |               |       Red 1                         Byte
+     +-             -+
+     |               |       Green 1                       Byte
+     +-             -+
+ up  |               |
+     +-   . . . .   -+       ...
+ to  |               |
+     +-             -+
+     |               |       Green 255                     Byte
+     +-             -+
+767  |               |       Blue 255                      Byte
+     +===============+
+
+
+     d. Extensions and Scope. The scope of this block is the Table-based Image
+     Data Block that immediately follows it. This block cannot be modified by
+     any extension.
+
+     e. Recommendations. None.
+
+
+22. Table Based Image Data.
+
+     a. Description. The image data for a table based image consists of a
+     sequence of sub-blocks, of size at most 255 bytes each, containing an
+     index into the active color table, for each pixel in the image.  Pixel
+     indices are in order of left to right and from top to bottom.  Each index
+     must be within the range of the size of the active color table, starting
+     at 0. The sequence of indices is encoded using the LZW Algorithm with
+     variable-length code, as described in Appendix F
+
+     b. Required Version.  87a.
+
+     c. Syntax. The image data format is as follows:
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+     |               |       LZW Minimum Code Size         Byte
+     +---------------+
+
+     +===============+
+     |               |
+     /               /       Image Data                    Data Sub-blocks
+     |               |
+     +===============+
+
+
+
+
+
+
+
+
+                                                                        15
+
+
+            i) LZW Minimum Code Size.  This byte determines the initial number
+            of bits used for LZW codes in the image data, as described in
+            Appendix F.
+
+     d. Extensions and Scope. This block has no scope, it contains raster
+     data. Extensions intended to modify a Table-based image must appear
+     before the corresponding Image Descriptor.
+
+     e. Recommendations. None.
+
+
+23. Graphic Control Extension.
+
+      a. Description. The Graphic Control Extension contains parameters used
+      when processing a graphic rendering block. The scope of this extension is
+      the first graphic rendering block to follow. The extension contains only
+      one data sub-block.
+
+      This block is OPTIONAL; at most one Graphic Control Extension may precede
+      a graphic rendering block. This is the only limit to the number of
+      Graphic Control Extensions that may be contained in a Data Stream.
+
+      b. Required Version.  89a.
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+  0  |               |       Extension Introducer          Byte
+     +---------------+
+  1  |               |       Graphic Control Label         Byte
+     +---------------+
+
+     +---------------+
+  0  |               |       Block Size                    Byte
+     +---------------+
+  1  |     |     | | |       <Packed Fields>               See below
+     +---------------+
+  2  |               |       Delay Time                    Unsigned
+     +-             -+
+  3  |               |
+     +---------------+
+  4  |               |       Transparent Color Index       Byte
+     +---------------+
+
+     +---------------+
+  0  |               |       Block Terminator              Byte
+     +---------------+
+
+
+      <Packed Fields>  =     Reserved                      3 Bits
+                             Disposal Method               3 Bits
+                             User Input Flag               1 Bit
+                             Transparent Color Flag        1 Bit
+
+            i) Extension Introducer - Identifies the beginning of an extension
+
+
+
+
+
+
+
+                                                                        16
+
+
+            block. This field contains the fixed value 0x21.
+
+            ii) Graphic Control Label - Identifies the current block as a
+            Graphic Control Extension. This field contains the fixed value
+            0xF9.
+
+            iii) Block Size - Number of bytes in the block, after the Block
+            Size field and up to but not including the Block Terminator.  This
+            field contains the fixed value 4.
+
+            iv) Disposal Method - Indicates the way in which the graphic is to
+            be treated after being displayed.
+
+            Values :    0 -   No disposal specified. The decoder is
+                              not required to take any action.
+                        1 -   Do not dispose. The graphic is to be left
+                              in place.
+                        2 -   Restore to background color. The area used by the
+                              graphic must be restored to the background color.
+                        3 -   Restore to previous. The decoder is required to
+                              restore the area overwritten by the graphic with
+                              what was there prior to rendering the graphic.
+                     4-7 -    To be defined.
+
+            v) User Input Flag - Indicates whether or not user input is
+            expected before continuing. If the flag is set, processing will
+            continue when user input is entered. The nature of the User input
+            is determined by the application (Carriage Return, Mouse Button
+            Click, etc.).
+
+            Values :    0 -   User input is not expected.
+                        1 -   User input is expected.
+
+            When a Delay Time is used and the User Input Flag is set,
+            processing will continue when user input is received or when the
+            delay time expires, whichever occurs first.
+
+            vi) Transparency Flag - Indicates whether a transparency index is
+            given in the Transparent Index field. (This field is the least
+            significant bit of the byte.)
+
+            Values :    0 -   Transparent Index is not given.
+                        1 -   Transparent Index is given.
+
+            vii) Delay Time - If not 0, this field specifies the number of
+            hundredths (1/100) of a second to wait before continuing with the
+            processing of the Data Stream. The clock starts ticking immediately
+            after the graphic is rendered. This field may be used in
+            conjunction with the User Input Flag field.
+
+            viii) Transparency Index - The Transparency Index is such that when
+            encountered, the corresponding pixel of the display device is not
+            modified and processing goes on to the next pixel. The index is
+            present if and only if the Transparency Flag is set to 1.
+
+            ix) Block Terminator - This zero-length data block marks the end of
+
+
+
+
+
+
+
+                                                                        17
+
+            the Graphic Control Extension.
+
+      d. Extensions and Scope. The scope of this Extension is the graphic
+      rendering block that follows it; it is possible for other extensions to
+      be present between this block and its target. This block can modify the
+      Image Descriptor Block and the Plain Text Extension.
+
+      e. Recommendations.
+
+            i) Disposal Method - The mode Restore To Previous is intended to be
+            used in small sections of the graphic; the use of this mode imposes
+            severe demands on the decoder to store the section of the graphic
+            that needs to be saved. For this reason, this mode should be used
+            sparingly.  This mode is not intended to save an entire graphic or
+            large areas of a graphic; when this is the case, the encoder should
+            make every attempt to make the sections of the graphic to be
+            restored be separate graphics in the data stream. In the case where
+            a decoder is not capable of saving an area of a graphic marked as
+            Restore To Previous, it is recommended that a decoder restore to
+            the background color.
+
+            ii) User Input Flag - When the flag is set, indicating that user
+            input is expected, the decoder may sound the bell (0x07) to alert
+            the user that input is being expected.  In the absence of a
+            specified Delay Time, the decoder should wait for user input
+            indefinitely.  It is recommended that the encoder not set the User
+            Input Flag without a Delay Time specified.
+
+
+24. Comment Extension.
+
+      a. Description. The Comment Extension contains textual information which
+      is not part of the actual graphics in the GIF Data Stream. It is suitable
+      for including comments about the graphics, credits, descriptions or any
+      other type of non-control and non-graphic data.  The Comment Extension
+      may be ignored by the decoder, or it may be saved for later processing;
+      under no circumstances should a Comment Extension disrupt or interfere
+      with the processing of the Data Stream.
+
+      This block is OPTIONAL; any number of them may appear in the Data Stream.
+
+      b. Required Version.  89a.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        18
+
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+  0  |               |       Extension Introducer          Byte
+     +---------------+
+  1  |               |       Comment Label                 Byte
+     +---------------+
+
+     +===============+
+     |               |
+  N  |               |       Comment Data                  Data Sub-blocks
+     |               |
+     +===============+
+
+     +---------------+
+  0  |               |       Block Terminator              Byte
+     +---------------+
+
+            i) Extension Introducer - Identifies the beginning of an extension
+            block. This field contains the fixed value 0x21.
+
+            ii) Comment Label - Identifies the block as a Comment Extension.
+            This field contains the fixed value 0xFE.
+
+            iii) Comment Data - Sequence of sub-blocks, each of size at most
+            255 bytes and at least 1 byte, with the size in a byte preceding
+            the data.  The end of the sequence is marked by the Block
+            Terminator.
+
+            iv) Block Terminator - This zero-length data block marks the end of
+            the Comment Extension.
+
+      d. Extensions and Scope. This block does not have scope. This block
+      cannot be modified by any extension.
+
+      e. Recommendations.
+
+            i) Data - This block is intended for humans.  It should contain
+            text using the 7-bit ASCII character set. This block should
+            not be used to store control information for custom processing.
+
+            ii) Position - This block may appear at any point in the Data
+            Stream at which a block can begin; however, it is recommended that
+            Comment Extensions do not interfere with Control or Data blocks;
+            they should be located at the beginning or at the end of the Data
+            Stream to the extent possible.
+
+
+25. Plain Text Extension.
+
+      a. Description. The Plain Text Extension contains textual data and the
+      parameters necessary to render that data as a graphic, in a simple form.
+      The textual data will be encoded with the 7-bit printable ASCII
+      characters.  Text data are rendered using a grid of character cells
+
+
+
+
+
+
+
+
+                                                                        19
+
+
+      defined by the parameters in the block fields. Each character is rendered
+      in an individual cell. The textual data in this block is to be rendered
+      as mono-spaced characters, one character per cell, with a best fitting
+      font and size. For further information, see the section on
+      Recommendations below. The data characters are taken sequentially from
+      the data portion of the block and rendered within a cell, starting with
+      the upper left cell in the grid and proceeding from left to right and
+      from top to bottom. Text data is rendered until the end of data is
+      reached or the character grid is filled.  The Character Grid contains an
+      integral number of cells; in the case that the cell dimensions do not
+      allow for an integral number, fractional cells must be discarded; an
+      encoder must be careful to specify the grid dimensions accurately so that
+      this does not happen. This block requires a Global Color Table to be
+      available; the colors used by this block reference the Global Color Table
+      in the Stream if there is one, or the Global Color Table from a previous
+      Stream, if one was saved. This block is a graphic rendering block,
+      therefore it may be modified by a Graphic Control Extension.  This block
+      is OPTIONAL; any number of them may appear in the Data Stream.
+
+      b. Required Version.  89a.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        20
+
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+  0  |               |       Extension Introducer          Byte
+     +---------------+
+  1  |               |       Plain Text Label              Byte
+     +---------------+
+
+     +---------------+
+  0  |               |       Block Size                    Byte
+     +---------------+
+  1  |               |       Text Grid Left Position       Unsigned
+     +-             -+
+  2  |               |
+     +---------------+
+  3  |               |       Text Grid Top Position        Unsigned
+     +-             -+
+  4  |               |
+     +---------------+
+  5  |               |       Text Grid Width               Unsigned
+     +-             -+
+  6  |               |
+     +---------------+
+  7  |               |       Text Grid Height              Unsigned
+     +-             -+
+  8  |               |
+     +---------------+
+  9  |               |       Character Cell Width          Byte
+     +---------------+
+ 10  |               |       Character Cell Height         Byte
+     +---------------+
+ 11  |               |       Text Foreground Color Index   Byte
+     +---------------+
+ 12  |               |       Text Background Color Index   Byte
+     +---------------+
+
+     +===============+
+     |               |
+  N  |               |       Plain Text Data               Data Sub-blocks
+     |               |
+     +===============+
+
+     +---------------+
+  0  |               |       Block Terminator              Byte
+     +---------------+
+
+            i) Extension Introducer - Identifies the beginning of an extension
+            block. This field contains the fixed value 0x21.
+
+            ii) Plain Text Label - Identifies the current block as a Plain Text
+            Extension. This field contains the fixed value 0x01.
+
+            iii) Block Size - Number of bytes in the extension, after the Block
+            Size field and up to but not including the beginning of the data
+            portion. This field contains the fixed value 12.
+
+
+
+
+
+
+
+                                                                        21
+
+
+            iv) Text Grid Left Position - Column number, in pixels, of the left
+            edge of the text grid, with respect to the left edge of the Logical
+            Screen.
+
+            v) Text Grid Top Position - Row number, in pixels, of the top edge
+            of the text grid, with respect to the top edge of the Logical
+            Screen.
+
+            vi) Image Grid Width - Width of the text grid in pixels.
+
+            vii) Image Grid Height - Height of the text grid in pixels.
+
+            viii) Character Cell Width - Width, in pixels, of each cell in the
+            grid.
+
+            ix) Character Cell Height - Height, in pixels, of each cell in the
+            grid.
+
+            x) Text Foreground Color Index - Index into the Global Color Table
+            to be used to render the text foreground.
+
+            xi) Text Background Color Index - Index into the Global Color Table
+            to be used to render the text background.
+
+            xii) Plain Text Data - Sequence of sub-blocks, each of size at most
+            255 bytes and at least 1 byte, with the size in a byte preceding
+            the data.  The end of the sequence is marked by the Block
+            Terminator.
+
+            xiii) Block Terminator - This zero-length data block marks the end
+            of the Plain Text Data Blocks.
+
+      d. Extensions and Scope. The scope of this block is the Plain Text Data
+      Block contained in it. This block may be modified by the Graphic Control
+      Extension.
+
+      e. Recommendations. The data in the Plain Text Extension is assumed to be
+      preformatted. The selection of font and size is left to the discretion of
+      the decoder.  If characters less than 0x20 or greater than 0xf7 are
+      encountered, it is recommended that the decoder display a Space character
+      (0x20). The encoder should use grid and cell dimensions such that an
+      integral number of cells fit in the grid both horizontally as well as
+      vertically.  For broadest compatibility, character cell dimensions should
+      be around 8x8 or 8x16 (width x height); consider an image for unusual
+      sized text.
+
+
+26. Application Extension.
+
+      a. Description. The Application Extension contains application-specific
+      information; it conforms with the extension block syntax, as described
+      below, and its block label is 0xFF.
+
+      b. Required Version.  89a.
+
+
+
+
+
+
+
+
+
+                                                                        22
+
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+  0  |               |       Extension Introducer          Byte
+     +---------------+
+  1  |               |       Extension Label               Byte
+     +---------------+
+
+     +---------------+
+  0  |               |       Block Size                    Byte
+     +---------------+
+  1  |               |
+     +-             -+
+  2  |               |
+     +-             -+
+  3  |               |       Application Identifier        8 Bytes
+     +-             -+
+  4  |               |
+     +-             -+
+  5  |               |
+     +-             -+
+  6  |               |
+     +-             -+
+  7  |               |
+     +-             -+
+  8  |               |
+     +---------------+
+  9  |               |
+     +-             -+
+ 10  |               |       Appl. Authentication Code     3 Bytes
+     +-             -+
+ 11  |               |
+     +---------------+
+
+     +===============+
+     |               |
+     |               |       Application Data              Data Sub-blocks
+     |               |
+     |               |
+     +===============+
+
+     +---------------+
+  0  |               |       Block Terminator              Byte
+     +---------------+
+
+            i) Extension Introducer - Defines this block as an extension. This
+            field contains the fixed value 0x21.
+
+            ii) Application Extension Label - Identifies the block as an
+            Application Extension. This field contains the fixed value 0xFF.
+
+            iii) Block Size - Number of bytes in this extension block,
+            following the Block Size field, up to but not including the
+            beginning of the Application Data. This field contains the fixed
+            value 11.
+
+
+
+
+
+
+
+                                                                        23
+
+
+            iv) Application Identifier - Sequence of eight printable ASCII
+            characters used to identify the application owning the Application
+            Extension.
+
+            v) Application Authentication Code - Sequence of three bytes used
+            to authenticate the Application Identifier. An Application program
+            may use an algorithm to compute a binary code that uniquely
+            identifies it as the application owning the Application Extension.
+
+
+      d. Extensions and Scope. This block does not have scope. This block
+      cannot be modified by any extension.
+
+      e. Recommendation. None.
+
+
+27. Trailer.
+
+      a. Description. This block is a single-field block indicating the end of
+      the GIF Data Stream.  It contains the fixed value 0x3B.
+
+      b. Required Version.  87a.
+
+      c. Syntax.
+
+      7 6 5 4 3 2 1 0        Field Name                    Type
+     +---------------+
+  0  |               |       GIF Trailer                   Byte
+     +---------------+
+
+      d. Extensions and Scope. This block does not have scope, it terminates
+      the GIF Data Stream. This block may not be modified by any extension.
+
+      e. Recommendations. None.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        24
+
+
+Appendix
+A. Quick Reference Table.
+
+Block Name                  Required   Label       Ext.   Vers.
+Application Extension       Opt. (*)   0xFF (255)  yes    89a
+Comment Extension           Opt. (*)   0xFE (254)  yes    89a
+Global Color Table          Opt. (1)   none        no     87a
+Graphic Control Extension   Opt. (*)   0xF9 (249)  yes    89a
+Header                      Req. (1)   none        no     N/A
+Image Descriptor            Opt. (*)   0x2C (044)  no     87a (89a)
+Local Color Table           Opt. (*)   none        no     87a
+Logical Screen Descriptor   Req. (1)   none        no     87a (89a)
+Plain Text Extension        Opt. (*)   0x01 (001)  yes    89a
+Trailer                     Req. (1)   0x3B (059)  no     87a
+
+Unlabeled Blocks
+Header                      Req. (1)   none        no     N/A
+Logical Screen Descriptor   Req. (1)   none        no     87a (89a)
+Global Color Table          Opt. (1)   none        no     87a
+Local Color Table           Opt. (*)   none        no     87a
+
+Graphic-Rendering Blocks
+Plain Text Extension        Opt. (*)   0x01 (001)  yes    89a
+Image Descriptor            Opt. (*)   0x2C (044)  no     87a (89a)
+
+Control Blocks
+Graphic Control Extension   Opt. (*)   0xF9 (249)  yes    89a
+
+Special Purpose Blocks
+Trailer                     Req. (1)   0x3B (059)  no     87a
+Comment Extension           Opt. (*)   0xFE (254)  yes    89a
+Application Extension       Opt. (*)   0xFF (255)  yes    89a
+
+legend:           (1)   if present, at most one occurrence
+                  (*)   zero or more occurrences
+                  (+)   one or more occurrences
+
+Notes : The Header is not subject to Version Numbers.
+(89a) The Logical Screen Descriptor and the Image Descriptor retained their
+syntax from version 87a to version 89a, but some fields reserved under version
+87a are used under version 89a.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        25
+
+
+Appendix
+B. GIF Grammar.
+
+A Grammar is a form of notation to represent the sequence in which certain
+objects form larger objects.  A grammar is also used to represent the number of
+objects that can occur at a given position.  The grammar given here represents
+the sequence of blocks that form the GIF Data Stream. A grammar is given by
+listing its rules.  Each rule consists of the left-hand side, followed by some
+form of equals sign, followed by the right-hand side.  In a rule, the
+right-hand side describes how the left-hand side is defined. The right-hand
+side consists of a sequence of entities, with the possible presence of special
+symbols. The following legend defines the symbols used in this grammar for GIF.
+
+Legend:           <>    grammar word
+                  ::=   defines symbol
+                  *     zero or more occurrences
+                  +     one or more occurrences
+                  |     alternate element
+                  []    optional element
+
+Example:
+
+<GIF Data Stream> ::= Header <Logical Screen> <Data>* Trailer
+
+This rule defines the entity <GIF Data Stream> as follows. It must begin with a
+Header. The Header is followed by an entity called Logical Screen, which is
+defined below by another rule. The Logical Screen is followed by the entity
+Data, which is also defined below by another rule. Finally, the entity Data is
+followed by the Trailer.  Since there is no rule defining the Header or the
+Trailer, this means that these blocks are defined in the document.  The entity
+Data has a special symbol (*) following it which means that, at this position,
+the entity Data may be repeated any number of times, including 0 times. For
+further reading on this subject, refer to a standard text on Programming
+Languages.
+
+
+The Grammar.
+
+<GIF Data Stream> ::=     Header <Logical Screen> <Data>* Trailer
+
+<Logical Screen> ::=      Logical Screen Descriptor [Global Color Table]
+
+<Data> ::=                <Graphic Block>  |
+                          <Special-Purpose Block>
+
+<Graphic Block> ::=       [Graphic Control Extension] <Graphic-Rendering Block>
+
+<Graphic-Rendering Block> ::=  <Table-Based Image>  |
+                               Plain Text Extension
+
+<Table-Based Image> ::=   Image Descriptor [Local Color Table] Image Data
+
+<Special-Purpose Block> ::=    Application Extension  |
+                               Comment Extension
+
+
+
+
+
+
+
+
+
+                                                                        26
+
+
+NOTE : The grammar indicates that it is possible for a GIF Data Stream to
+contain the Header, the Logical Screen Descriptor, a Global Color Table and the
+GIF Trailer. This special case is used to load a GIF decoder with a Global
+Color Table, in preparation for subsequent Data Streams without color tables at
+all.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        27
+
+
+Appendix
+C. Glossary.
+
+Active Color Table - Color table used to render the next graphic. If the next
+graphic is an image which has a Local Color Table associated with it, the
+active color table becomes the Local Color Table associated with that image.
+If the next graphic is an image without a Local Color Table, or a Plain Text
+Extension, the active color table is the Global Color Table associated with the
+Data Stream, if there is one; if there is no Global Color Table in the Data
+Stream, the active color table is a color table saved from a previous Data
+Stream, or one supplied by the decoder.
+
+Block - Collection of bytes forming a protocol unit. In general, the term
+includes labeled and unlabeled blocks, as well as Extensions.
+
+Data Stream - The GIF Data Stream is composed of blocks and sub-blocks
+representing images and graphics, together with control information to render
+them on a display device. All control and data blocks in the Data Stream must
+follow the Header and must precede the Trailer.
+
+Decoder - A program capable of processing a GIF Data Stream to render the
+images and graphics contained in it.
+
+Encoder - A program capable of capturing and formatting image and graphic
+raster data, following the definitions of the Graphics Interchange Format.
+
+Extension - A protocol block labeled by the Extension Introducer 0x21.
+
+Extension Introducer - Label (0x21) defining an Extension.
+
+Graphic - Data which can be rendered on the screen by virtue of some algorithm.
+The term graphic is more general than the term image; in addition to images,
+the term graphic also includes data such as text, which is rendered using
+character bit-maps.
+
+Image - Data representing a picture or a drawing; an image is represented by an
+array of pixels called the raster of the image.
+
+Raster - Array of pixel values representing an image.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        28
+
+
+Appendix
+D. Conventions.
+
+Animation - The Graphics Interchange Format is not intended as a platform for
+animation, even though it can be done in a limited way.
+
+Byte Ordering - Unless otherwise stated, multi-byte numeric fields are ordered
+with the Least Significant Byte first.
+
+Color Indices - Color indices always refer to the active color table, either
+the Global Color Table or the Local Color Table.
+
+Color Order - Unless otherwise stated, all triple-component RGB color values
+are specified in Red-Green-Blue order.
+
+Color Tables - Both color tables, the Global and the Local, are optional; if
+present, the Global Color Table is to be used with every image in the Data
+Stream for which a Local Color Table is not given; if present, a Local Color
+Table overrides the Global Color Table.  However, if neither color table is
+present, the application program is free to use an arbitrary color table. If
+the graphics in several Data Streams are related and all use the same color
+table, an encoder could place the color table as the Global Color Table in the
+first Data Stream and leave subsequent Data Streams without a Global Color
+Table or any Local Color Tables; in this way, the overhead for the table is
+eliminated.  It is recommended that the decoder save the previous Global Color
+Table to be used with the Data Stream that follows, in case it does not contain
+either a Global Color Table or any Local Color Tables. In general, this allows
+the application program to use past color tables, significantly reducing
+transmission overhead.
+
+Extension Blocks - Extensions are defined using the Extension Introducer code
+to mark the beginning of the block, followed by a block label, identifying the
+type of extension.  Extension Codes are numbers in the range from 0x00 to 0xFF,
+inclusive. Special purpose extensions are transparent to the decoder and may be
+omitted when transmitting the Data Stream on-line. The GIF capabilities
+dialogue makes the provision for the receiver to request the transmission of
+all blocks; the default state in this regard is no transmission of Special
+purpose blocks.
+
+Reserved Fields - All Reserved Fields are expected to have each bit set to zero
+(off).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        29
+
+
+Appendix
+E. Interlaced Images.
+
+The rows of an Interlaced images are arranged in the following order:
+
+      Group 1 : Every 8th. row, starting with row 0.              (Pass 1)
+      Group 2 : Every 8th. row, starting with row 4.              (Pass 2)
+      Group 3 : Every 4th. row, starting with row 2.              (Pass 3)
+      Group 4 : Every 2nd. row, starting with row 1.              (Pass 4)
+
+The Following example illustrates how the rows of an interlaced image are
+ordered.
+
+      Row Number                                        Interlace Pass
+
+ 0    -----------------------------------------       1
+ 1    -----------------------------------------                         4
+ 2    -----------------------------------------                   3
+ 3    -----------------------------------------                         4
+ 4    -----------------------------------------             2
+ 5    -----------------------------------------                         4
+ 6    -----------------------------------------                   3
+ 7    -----------------------------------------                         4
+ 8    -----------------------------------------       1
+ 9    -----------------------------------------                         4
+ 10   -----------------------------------------                   3
+ 11   -----------------------------------------                         4
+ 12   -----------------------------------------             2
+ 13   -----------------------------------------                         4
+ 14   -----------------------------------------                   3
+ 15   -----------------------------------------                         4
+ 16   -----------------------------------------       1
+ 17   -----------------------------------------                         4
+ 18   -----------------------------------------                   3
+ 19   -----------------------------------------                         4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        30
+
+
+Appendix
+F. Variable-Length-Code LZW Compression.
+
+The Variable-Length-Code LZW Compression is a variation of the Lempel-Ziv
+Compression algorithm in which variable-length codes are used to replace
+patterns detected in the original data. The algorithm uses a code or
+translation table constructed from the patterns encountered in the original
+data; each new pattern is entered into the table and its index is used to
+replace it in the compressed stream.
+
+The compressor takes the data from the input stream and builds a code or
+translation table with the patterns as it encounters them; each new pattern is
+entered into the code table and its index is added to the output stream; when a
+pattern is encountered which had been detected since the last code table
+refresh, its index from the code table is put on the output stream, thus
+achieving the data compression.  The expander takes input from the compressed
+data stream and builds the code or translation table from it; as the compressed
+data stream is processed, codes are used to index into the code table and the
+corresponding data is put on the decompressed output stream, thus achieving
+data decompression.  The details of the algorithm are explained below.  The
+Variable-Length-Code aspect of the algorithm is based on an initial code size
+(LZW-initial code size), which specifies the initial number of bits used for
+the compression codes.  When the number of patterns detected by the compressor
+in the input stream exceeds the number of patterns encodable with the current
+number of bits, the number of bits per LZW code is increased by one.
+
+The Raster Data stream that represents the actual output image can be
+represented as:
+
+         7 6 5 4 3 2 1 0
+        +---------------+
+        | LZW code size |
+        +---------------+
+
+        +---------------+ ----+
+        |  block size   |     |
+        +---------------+     |
+        |               |     +-- Repeated as many
+        |  data bytes   |     |   times as necessary.
+        |               |     |
+        +---------------+ ----+
+
+        . . .       . . . ------- The code that terminates the LZW
+                                  compressed data must appear before
+                                  Block Terminator.
+        +---------------+
+        |0 0 0 0 0 0 0 0|  Block Terminator
+        +---------------+
+
+The conversion of the image from a series of pixel values to a transmitted or
+stored character stream involves several steps. In brief these steps are:
+
+1. Establish the Code Size - Define the number of bits needed to represent the
+actual data.
+
+2. Compress the Data - Compress the series of image pixels to a series of
+
+
+
+
+
+
+
+                                                                        31
+
+
+compression codes.
+
+3. Build a Series of Bytes - Take the set of compression codes and convert to a
+string of 8-bit bytes.
+
+4. Package the Bytes - Package sets of bytes into blocks preceded by character
+counts and output.
+
+ESTABLISH CODE SIZE
+
+The first byte of the Compressed Data stream is a value indicating the minimum
+number of bits required to represent the set of actual pixel values. Normally
+this will be the same as the number of color bits. Because of some algorithmic
+constraints however, black & white images which have one color bit must be
+indicated as having a code size of 2.
+This code size value also implies that the compression codes must start out one
+bit longer.
+
+COMPRESSION
+
+The LZW algorithm converts a series of data values into a series of codes which
+may be raw values or a code designating a series of values. Using text
+characters as an analogy, the output code consists of a character or a code
+representing a string of characters.
+
+The LZW algorithm used in GIF matches algorithmically with the standard LZW
+algorithm with the following differences:
+
+1.  A special Clear code is defined which resets all compression/decompression
+parameters and tables to a start-up state. The value of this code is 2**<code
+size>. For example if the code size indicated was 4 (image was 4 bits/pixel)
+the Clear code value would be 16 (10000 binary). The Clear code can appear at
+any point in the image data stream and therefore requires the LZW algorithm to
+process succeeding codes as if a new data stream was starting. Encoders should
+output a Clear code as the first code of each image data stream.
+
+2. An End of Information code is defined that explicitly indicates the end of
+the image data stream. LZW processing terminates when this code is encountered.
+It must be the last code output by the encoder for an image. The value of this
+code is <Clear code>+1.
+
+3. The first available compression code value is <Clear code>+2.
+
+4. The output codes are of variable length, starting at <code size>+1 bits per
+code, up to 12 bits per code. This defines a maximum code value of 4095
+(0xFFF). Whenever the LZW code value would exceed the current code length, the
+code length is increased by one. The packing/unpacking of these codes must then
+be altered to reflect the new code length.
+
+BUILD 8-BIT BYTES
+
+Because the LZW compression used for GIF creates a series of variable length
+codes, of between 3 and 12 bits each, these codes must be reformed into a
+series of 8-bit bytes that will be the characters actually stored or
+transmitted. This provides additional compression of the image. The codes are
+formed into a stream of bits as if they were packed right to left and then
+
+
+
+
+
+
+
+                                                                        32
+
+
+picked off 8 bits at a time to be output.
+
+Assuming a character array of 8 bits per character and using 5 bit codes to be
+packed, an example layout would be similar to:
+
+
+     +---------------+
+  0  |               |    bbbaaaaa
+     +---------------+
+  1  |               |    dcccccbb
+     +---------------+
+  2  |               |    eeeedddd
+     +---------------+
+  3  |               |    ggfffffe
+     +---------------+
+  4  |               |    hhhhhggg
+     +---------------+
+           . . .
+     +---------------+
+  N  |               |
+     +---------------+
+
+
+Note that the physical packing arrangement will change as the number of bits
+per compression code change but the concept remains the same.
+
+PACKAGE THE BYTES
+
+Once the bytes have been created, they are grouped into blocks for output by
+preceding each block of 0 to 255 bytes with a character count byte. A block
+with a zero byte count terminates the Raster Data stream for a given image.
+These blocks are what are actually output for the GIF image. This block format
+has the side effect of allowing a decoding program the ability to read past the
+actual image data if necessary by reading block counts and then skipping over
+the data.
+
+
+
+FURTHER READING
+
+[1] Ziv, J. and Lempel, A. : "A Universal Algorithm for Sequential Data
+Compression", IEEE Transactions on Information Theory, May 1977.
+[2] Welch, T. : "A Technique for High-Performance Data Compression", Computer,
+June 1984.
+[3] Nelson, M.R. : "LZW Data Compression", Dr. Dobb's Journal, October 1989.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+                                                                        33
+
+
+Appendix
+G. On-line Capabilities Dialogue.
+
+NOTE : This section is currently (10 July 1990) under revision; the information
+provided here should be used as general guidelines. Code written based on this
+information should be designed in a flexible way to accommodate any changes
+resulting from the revisions.
+
+The following sequences are defined for use in mediating control between a GIF
+sender and GIF receiver over an interactive communications line. These
+sequences do not apply to applications that involve downloading of static GIF
+files and are not considered part of a GIF file.
+
+GIF CAPABILITIES ENQUIRY
+
+The GIF Capabilities Enquiry sequence is issued from a host and requests an
+interactive GIF decoder to return a response message that defines the graphics
+parameters for the decoder. This involves returning information about available
+screen sizes, number of bits/color supported and the amount of color detail
+supported. The escape sequence for the GIF Capabilities Enquiry is defined as:
+
+ESC[>0g           0x1B 0x5B 0x3E 0x30 0x67
+
+GIF CAPABILITIES RESPONSE
+
+The GIF Capabilities Response message is returned by an interactive GIF decoder
+and defines the decoder's display capabilities for all graphics modes that are
+supported by the software. Note that this can also include graphics printers as
+well as a monitor screen. The general format of this message is:
+
+#version;protocol{;dev, width, height, color-bits, color-res}...<CR>
+
+
+'#'            GIF Capabilities Response identifier character.
+version        GIF format version number;  initially '87a'.
+protocol='0'   No end-to-end protocol supported by decoder Transfer as direct
+               8-bit data stream.
+protocol='1'   Can use CIS B+ error correction protocol to transfer GIF data
+               interactively from the host directly to the display.
+dev = '0'      Screen parameter set follows.
+dev = '1'      Printer parameter set follows.
+width          Maximum supported display width in pixels.
+height         Maximum supported display height in pixels.
+color-bits     Number of bits per pixel supported. The number of supported
+               colors is therefore 2**color-bits.
+color-res      Number of bits per color component supported in the hardware
+               color palette. If color-res is '0' then no hardware palette
+               table is available.
+
+Note that all values in the GIF Capabilities Response are returned as ASCII
+decimal numbers and the message is terminated by a Carriage Return character.
+
+The following GIF Capabilities Response message describes three standard IBM PC
+Enhanced Graphics Adapter configurations with no printer; the GIF data stream
+
+
+
+
+
+
+
+
+
+                                                                        34
+
+
+can be processed within an error correcting protocol:
+
+#87a;1;0,320,200,4,0;0,640,200,2,2;0,640,350,4,2<CR>
+
+ENTER GIF GRAPHICS MODE
+
+Two sequences are currently defined to invoke an interactive GIF decoder into
+action. The only difference between them is that different output media are
+selected. These sequences are:
+
+ESC[>1g     Display GIF image on screen
+
+                  0x1B 0x5B 0x3E 0x31 0x67
+
+ESC[>2g   Display image directly to an attached graphics printer. The image may
+optionally be displayed on the screen as well.
+
+                  0x1B 0x5B 0x3E 0x32 0x67
+
+Note that the 'g' character terminating each sequence is in lowercase.
+
+INTERACTIVE ENVIRONMENT
+
+The assumed environment for the transmission of GIF image data from an
+interactive application is a full 8-bit data stream from host to micro.  All
+256 character codes must be transferrable. The establishing of an 8-bit data
+path for communications will normally be taken care of by the host application
+programs. It is however up to the receiving communications programs supporting
+GIF to be able to receive and pass on all 256 8-bit codes to the GIF decoder
+software.
+.
diff --git a/fileformatdocs/tga_specs.pdf b/fileformatdocs/tga_specs.pdf
new file mode 100755 (executable)
index 0000000..dab09c6
Binary files /dev/null and b/fileformatdocs/tga_specs.pdf differ
diff --git a/fileformatdocs/tgaffs.pdf b/fileformatdocs/tgaffs.pdf
new file mode 100644 (file)
index 0000000..781a9a0
Binary files /dev/null and b/fileformatdocs/tgaffs.pdf differ
diff --git a/fills.c b/fills.c
index b92eaaf..795f7cd 100644 (file)
--- a/fills.c
+++ b/fills.c
@@ -398,7 +398,7 @@ typedef struct
   i_color fg, bg;
   i_fcolor ffg, fbg;
   unsigned char hatch[8];
-  int dx, dy;
+  i_img_dim dx, dy;
 } i_fill_hatch_t;
 
 static void fill_hatch(i_fill_t *fill, i_img_dim x, i_img_dim y,
@@ -409,7 +409,7 @@ static
 i_fill_t *
 i_new_hatch_low(const i_color *fg, const i_color *bg, const i_fcolor *ffg, const i_fcolor *fbg, 
                 int combine, int hatch, const unsigned char *cust_hatch,
-                int dx, int dy);
+                i_img_dim dx, i_img_dim dy);
 
 /*
 =item i_new_fill_hatch(C<fg>, C<bg>, C<combine>, C<hatch>, C<cust_hatch>, C<dx>, C<dy>)
@@ -434,7 +434,7 @@ with the the side of a filled area.
 */
 i_fill_t *
 i_new_fill_hatch(const i_color *fg, const i_color *bg, int combine, int hatch, 
-            const unsigned char *cust_hatch, int dx, int dy) {
+            const unsigned char *cust_hatch, i_img_dim dx, i_img_dim dy) {
   return i_new_hatch_low(fg, bg, NULL, NULL, combine, hatch, cust_hatch, 
                          dx, dy);
 }
@@ -462,7 +462,7 @@ with the the side of a filled area.
 */
 i_fill_t *
 i_new_fill_hatchf(const i_fcolor *fg, const i_fcolor *bg, int combine, int hatch, 
-                 const unsigned char *cust_hatch, int dx, int dy) {
+                 const unsigned char *cust_hatch, i_img_dim dx, i_img_dim dy) {
   return i_new_hatch_low(NULL, NULL, fg, bg, combine, hatch, cust_hatch, 
                          dx, dy);
 }
@@ -474,7 +474,7 @@ static void fill_imagef(i_fill_t *fill, i_img_dim x, i_img_dim y,
 struct i_fill_image_t {
   i_fill_t base;
   i_img *src;
-  int xoff, yoff;
+  i_img_dim xoff, yoff;
   int has_matrix;
   double matrix[9];
 };
@@ -504,7 +504,7 @@ C<xoff> and C<yoff> are the offset into the image to start filling from.
 =cut
 */
 i_fill_t *
-i_new_fill_image(i_img *im, const double *matrix, int xoff, int yoff, int combine) {
+i_new_fill_image(i_img *im, const double *matrix, i_img_dim xoff, i_img_dim yoff, int combine) {
   struct i_fill_image_t *fill = mymalloc(sizeof(*fill)); /* checked 14jul05 tonyc */
 
   *fill = image_fill_proto;
@@ -547,9 +547,11 @@ struct i_fill_opacity_t {
 static struct i_fill_opacity_t
 opacity_fill_proto =
   {
-    fill_opacity,
-    fill_opacityf,
-    NULL
+    {
+      fill_opacity,
+      fill_opacityf,
+      NULL
+    }
   };
 
 i_fill_t *
@@ -635,7 +637,7 @@ i_fill_t *
 i_new_hatch_low(const i_color *fg, const i_color *bg, 
                const i_fcolor *ffg, const i_fcolor *fbg, 
                 int combine, int hatch, const unsigned char *cust_hatch,
-                int dx, int dy) {
+                i_img_dim dx, i_img_dim dy) {
   i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t)); /* checked 14jul05 tonyc */
 
   *fill = hatch_fill_proto;
@@ -695,7 +697,6 @@ fill_hatch(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
   int mask = 128 >> xpos;
   i_color fg = f->fg;
   i_color bg = f->bg;
-  int want_channels = channels > 2 ? 4 : 2;
 
   if (channels < 3) {
     i_adapt_colors(2, 4, &fg, 1);
@@ -826,12 +827,12 @@ fill_image(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
       ry -= iy * f->src->ysize;
 
       for (dy = 0; dy < 2; ++dy) {
-        if ((int)rx == f->src->xsize-1) {
-          i_gpix(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
-          i_gpix(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
+        if ((i_img_dim)rx == f->src->xsize-1) {
+          i_gpix(f->src, f->src->xsize-1, ((i_img_dim)ry+dy) % f->src->ysize, &c[dy][0]);
+          i_gpix(f->src, 0, ((i_img_dim)ry+dy) % f->src->xsize, &c[dy][1]);
         }
         else {
-          i_glin(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize, 
+          i_glin(f->src, (i_img_dim)rx, (i_img_dim)rx+2, ((i_img_dim)ry+dy) % f->src->ysize, 
                  c[dy]);
         }
         c2[dy] = interp_i_color(c[dy][0], c[dy][1], rx, f->src->channels);
@@ -904,12 +905,12 @@ fill_imagef(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
       ry -= iy * f->src->ysize;
 
       for (dy = 0; dy < 2; ++dy) {
-        if ((int)rx == f->src->xsize-1) {
-          i_gpixf(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
-          i_gpixf(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
+        if ((i_img_dim)rx == f->src->xsize-1) {
+          i_gpixf(f->src, f->src->xsize-1, ((i_img_dim)ry+dy) % f->src->ysize, &c[dy][0]);
+          i_gpixf(f->src, 0, ((i_img_dim)ry+dy) % f->src->xsize, &c[dy][1]);
         }
         else {
-          i_glinf(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize, 
+          i_glinf(f->src, (i_img_dim)rx, (i_img_dim)rx+2, ((i_img_dim)ry+dy) % f->src->ysize, 
                  c[dy]);
         }
         c2[dy] = interp_i_fcolor(c[dy][0], c[dy][1], rx, f->src->channels);
index 9ebb0af..06ac6a1 100644 (file)
@@ -69,7 +69,7 @@ Scales the pixel values by the amount specified.
 
 void
 i_contrast(i_img *im, float intensity) {
-  int x, y;
+  i_img_dim x, y;
   unsigned char ch;
   unsigned int new_color;
   i_color rcolor;
@@ -97,7 +97,7 @@ i_contrast(i_img *im, float intensity) {
 
 static int
 s_hardinvert_low(i_img *im, int all) {
-  int x, y;
+  i_img_dim x, y;
   int ch;
   int invert_channels = all ? im->channels : i_img_color_channels(im);
 
@@ -159,7 +159,10 @@ i_hardinvertall(i_img *im) {
 /*
 =item i_noise(im, amount, type)
 
-Inverts the pixel values by the amount specified.
+Adjusts the sample values randomly by the amount specified.
+
+If type is 0, adjust all channels in a pixel by the same (random)
+amount amount, if non-zero adjust each sample independently.
 
   im     - image object
   amount - deviation in pixel values
@@ -175,7 +178,7 @@ Inverts the pixel values by the amount specified.
 
 void
 i_noise(i_img *im, float amount, unsigned char type) {
-  int x, y;
+  i_img_dim x, y;
   unsigned char ch;
   int new_color;
   float damount = amount * 2;
@@ -216,63 +219,6 @@ i_noise(i_img *im, float amount, unsigned char type) {
   }
 }
 
-
-/* 
-=item i_noise(im, amount, type)
-
-Inverts the pixel values by the amount specified.
-
-  im     - image object
-  amount - deviation in pixel values
-  type   - noise individual for each channel if true
-
-=cut
-*/
-
-
-/*
-=item i_applyimage(im, add_im, mode)
-
-Apply's an image to another image
-
-  im     - target image
-  add_im - image that is applied to target
-  mode   - what method is used in applying:
-
-  0   Normal   
-  1   Multiply
-  2   Screen
-  3   Overlay
-  4   Soft Light
-  5   Hard Light
-  6   Color dodge
-  7   Color Burn
-  8   Darker
-  9   Lighter
-  10  Add
-  11  Subtract
-  12  Difference
-  13  Exclusion
-       
-=cut
-*/
-
-void i_applyimage(i_img *im, i_img *add_im, unsigned char mode) {
-  int x, y;
-  int mx, my;
-
-  mm_log((1, "i_applyimage(im %p, add_im %p, mode %d", im, add_im, mode));
-  
-  mx = (add_im->xsize <= im->xsize) ? add_im->xsize : add_im->xsize;
-  my = (add_im->ysize <= im->ysize) ? add_im->ysize : add_im->ysize;
-  
-  for(x = 0; x < mx; x++) {            
-    for(y = 0; y < my; y++) {
-    }
-  }
-}
-
-
 /* 
 =item i_bumpmap(im, bump, channel, light_x, light_y, st)
 
@@ -289,9 +235,10 @@ Makes a bumpmap on image im using the bump image as the elevation map.
 */
 
 void
-i_bumpmap(i_img *im, i_img *bump, int channel, int light_x, int light_y, int st) {
-  int x, y, ch;
-  int mx, my;
+i_bumpmap(i_img *im, i_img *bump, int channel, i_img_dim light_x, i_img_dim light_y, i_img_dim st) {
+  i_img_dim x, y;
+  int ch;
+  i_img_dim mx, my;
   i_color x1_color, y1_color, x2_color, y2_color, dst_color;
   double nX, nY;
   double tX, tY, tZ;
@@ -301,8 +248,8 @@ i_bumpmap(i_img *im, i_img *bump, int channel, int light_x, int light_y, int st)
   
   i_img new_im;
 
-  mm_log((1, "i_bumpmap(im %p, add_im %p, channel %d, light_x %d, light_y %d, st %d)\n",
-         im, bump, channel, light_x, light_y, st));
+  mm_log((1, "i_bumpmap(im %p, add_im %p, channel %d, light(" i_DFp "), st %" i_DF ")\n",
+         im, bump, channel, i_DFcp(light_x, light_y), i_DFc(st)));
 
 
   if(channel >= bump->channels) {
@@ -342,8 +289,8 @@ i_bumpmap(i_img *im, i_img *bump, int channel, int light_x, int light_y, int st)
 
       fZ = (sqrt((nX * nX) + (nY * nY)) / aL);
  
-      tX = abs(x - light_x) / aL;
-      tY = abs(y - light_y) / aL;
+      tX = i_abs(x - light_x) / aL;
+      tY = i_abs(y - light_y) / aL;
 
       tZ = 1 - (sqrt((tX * tX) + (tY * tY)) * fZ);
       
@@ -357,7 +304,7 @@ i_bumpmap(i_img *im, i_img *bump, int channel, int light_x, int light_y, int st)
     }
   }
 
-  i_copyto(im, &new_im, 0, 0, (int)im->xsize, (int)im->ysize, 0, 0);
+  i_copyto(im, &new_im, 0, 0, im->xsize, im->ysize, 0, 0);
   
   i_img_exorcise(&new_im);
 }
@@ -366,7 +313,7 @@ i_bumpmap(i_img *im, i_img *bump, int channel, int light_x, int light_y, int st)
 
 
 typedef struct {
-  float x,y,z;
+  double x,y,z;
 } fvec;
 
 
@@ -450,11 +397,11 @@ void
 i_bumpmap_complex(i_img *im,
                  i_img *bump,
                  int channel,
-                 int tx,
-                 int ty,
-                 float Lx,
-                 float Ly,
-                 float Lz,
+                 i_img_dim tx,
+                 i_img_dim ty,
+                 double Lx,
+                 double Ly,
+                 double Lz,
                  float cd,
                  float cs,
                  float n,
@@ -464,8 +411,9 @@ i_bumpmap_complex(i_img *im,
   i_img new_im;
   
   int inflight;
-  int x, y, ch;
-  int mx, Mx, my, My;
+  i_img_dim x, y;
+  int ch;
+  i_img_dim mx, Mx, my, My;
   
   float cdc[MAXCHANNELS];
   float csc[MAXCHANNELS];
@@ -479,8 +427,9 @@ i_bumpmap_complex(i_img *im,
   fvec R;         /* Reflection vector    */
   fvec V;         /* Vision vector        */
 
-  mm_log((1, "i_bumpmap_complex(im %p, bump %p, channel %d, tx %d, ty %d, Lx %.2f, Ly %.2f, Lz %.2f, cd %.2f, cs %.2f, n %.2f, Ia %p, Il %p, Is %p)\n",
-         im, bump, channel, tx, ty, Lx, Ly, Lz, cd, cs, n, Ia, Il, Is));
+  mm_log((1, "i_bumpmap_complex(im %p, bump %p, channel %d, t(" i_DFp 
+         "), Lx %.2f, Ly %.2f, Lz %.2f, cd %.2f, cs %.2f, n %.2f, Ia %p, Il %p, Is %p)\n",
+         im, bump, channel, i_DFcp(tx, ty), Lx, Ly, Lz, cd, cs, n, Ia, Il, Is));
   
   if (channel >= bump->channels) {
     mm_log((1, "i_bumpmap_complex: channel = %d while bump image only has %d channels\n", channel, bump->channels));
@@ -566,7 +515,7 @@ i_bumpmap_complex(i_img *im,
     }
   }
   
-  i_copyto(im, &new_im, 0, 0, (int)im->xsize, (int)im->ysize, 0, 0);
+  i_copyto(im, &new_im, 0, 0, im->xsize, im->ysize, 0, 0);
   i_img_exorcise(&new_im);
 }
 
@@ -584,7 +533,8 @@ Quantizes Images to fewer levels.
 
 void
 i_postlevels(i_img *im, int levels) {
-  int x, y, ch;
+  i_img_dim x, y;
+  int ch;
   float pv;
   int rv;
   float av;
@@ -623,9 +573,10 @@ Makes an image looks like a mosaic with tilesize of size
 */
 
 void
-i_mosaic(i_img *im, int size) {
-  int x, y, ch;
-  int lx, ly, z;
+i_mosaic(i_img *im, i_img_dim size) {
+  i_img_dim x, y;
+  int ch, z;
+  i_img_dim lx, ly;
   long sqrsize;
 
   i_color rcolor;
@@ -673,12 +624,13 @@ Applies a watermark to the target image
 */
 
 void
-i_watermark(i_img *im, i_img *wmark, int tx, int ty, int pixdiff) {
-  int vx, vy, ch;
+i_watermark(i_img *im, i_img *wmark, i_img_dim tx, i_img_dim ty, int pixdiff) {
+  i_img_dim vx, vy;
+  int ch;
   i_color val, wval;
 
-       int mx = wmark->xsize;
-       int my = wmark->ysize;
+       i_img_dim mx = wmark->xsize;
+       i_img_dim my = wmark->ysize;
 
   for(vx=0;vx<mx;vx++) for(vy=0;vy<my;vy++) {
     
@@ -711,11 +663,11 @@ occur when changing the contrast.
 void
 i_autolevels(i_img *im, float lsat, float usat, float skew) {
   i_color val;
-  int i, x, y, rhist[256], ghist[256], bhist[256];
-  int rsum, rmin, rmax;
-  int gsum, gmin, gmax;
-  int bsum, bmin, bmax;
-  int rcl, rcu, gcl, gcu, bcl, bcu;
+  i_img_dim i, x, y, rhist[256], ghist[256], bhist[256];
+  i_img_dim rsum, rmin, rmax;
+  i_img_dim gsum, gmin, gmax;
+  i_img_dim bsum, bmin, bmax;
+  i_img_dim rcl, rcu, gcl, gcu, bcl, bcu;
 
   mm_log((1,"i_autolevels(im %p, lsat %f,usat %f,skew %f)\n", im, lsat,usat,skew));
 
@@ -772,9 +724,9 @@ Pseudo noise utility function used to generate perlin noise. (internal)
 */
 
 static
-float
-Noise(int x, int y) {
-  int n = x + y * 57; 
+double
+Noise(i_img_dim x, i_img_dim y) {
+  i_img_dim n = x + y * 57; 
   n = (n<<13) ^ n;
   return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
 }
@@ -791,11 +743,11 @@ Pseudo noise utility function used to generate perlin noise. (internal)
 */
 
 static
-float
-SmoothedNoise1(float x, float y) {
-  float corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16;
-  float sides   = ( Noise(x-1, y)  +Noise(x+1, y)  +Noise(x, y-1)  +Noise(x, y+1) ) /  8;
-  float center  =  Noise(x, y) / 4;
+double
+SmoothedNoise1(double x, double y) {
+  double corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16;
+  double sides   = ( Noise(x-1, y)  +Noise(x+1, y)  +Noise(x, y-1)  +Noise(x, y+1) ) /  8;
+  double center  =  Noise(x, y) / 4;
   return corners + sides + center;
 }
 
@@ -809,10 +761,11 @@ Utility function used to generate perlin noise. (internal)
 */
 
 static
-float C_Interpolate(float a, float b, float x) {
+double
+C_Interpolate(double a, double b, double x) {
   /*  float ft = x * 3.1415927; */
-  float ft = x * PI;
-  float f = (1 - cos(ft)) * .5;
+  double ft = x * PI;
+  double f = (1 - cos(ft)) * .5;
   return  a*(1-f) + b*f;
 }
 
@@ -826,21 +779,21 @@ Utility function used to generate perlin noise. (internal)
 */
 
 static
-float
-InterpolatedNoise(float x, float y) {
+double
+InterpolatedNoise(double x, double y) {
 
-  int integer_X = x;
-  float fractional_X = x - integer_X;
-  int integer_Y = y;
-  float fractional_Y = y - integer_Y;
+  i_img_dim integer_X = x;
+  double fractional_X = x - integer_X;
+  i_img_dim integer_Y = y;
+  double fractional_Y = y - integer_Y;
 
-  float v1 = SmoothedNoise1(integer_X,     integer_Y);
-  float v2 = SmoothedNoise1(integer_X + 1, integer_Y);
-  float v3 = SmoothedNoise1(integer_X,     integer_Y + 1);
-  float v4 = SmoothedNoise1(integer_X + 1, integer_Y + 1);
+  double v1 = SmoothedNoise1(integer_X,     integer_Y);
+  double v2 = SmoothedNoise1(integer_X + 1, integer_Y);
+  double v3 = SmoothedNoise1(integer_X,     integer_Y + 1);
+  double v4 = SmoothedNoise1(integer_X + 1, integer_Y + 1);
 
-  float i1 = C_Interpolate(v1 , v2 , fractional_X);
-  float i2 = C_Interpolate(v3 , v4 , fractional_X);
+  double i1 = C_Interpolate(v1 , v2 , fractional_X);
+  double i2 = C_Interpolate(v3 , v4 , fractional_X);
 
   return C_Interpolate(i1 , i2 , fractional_Y);
 }
@@ -859,8 +812,8 @@ static
 float
 PerlinNoise_2D(float x, float y) {
   int i,frequency;
-  float amplitude;
-  float total = 0;
+  double amplitude;
+  double total = 0;
   int Number_Of_Octaves=6;
   int n = Number_Of_Octaves - 1;
 
@@ -889,16 +842,17 @@ Perlin-like radial noise.
 */
 
 void
-i_radnoise(i_img *im, int xo, int yo, float rscale, float ascale) {
-  int x, y, ch;
+i_radnoise(i_img *im, i_img_dim xo, i_img_dim yo, double rscale, double ascale) {
+  i_img_dim x, y;
+  int ch;
   i_color val;
   unsigned char v;
-  float xc, yc, r;
+  double xc, yc, r;
   double a;
   
   for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
-    xc = (float)x-xo+0.5;
-    yc = (float)y-yo+0.5;
+    xc = (double)x-xo+0.5;
+    yc = (double)y-yo+0.5;
     r = rscale*sqrt(xc*xc+yc*yc)+1.2;
     a = (PI+atan2(yc,xc))*ascale;
     v = saturate(128+100*(PerlinNoise_2D(a,r)));
@@ -923,14 +877,15 @@ Perlin-like 2d noise noise.
 */
 
 void
-i_turbnoise(i_img *im, float xo, float yo, float scale) {
-  int x,y,ch;
+i_turbnoise(i_img *im, double xo, double yo, double scale) {
+  i_img_dim x,y;
+  int ch;
   unsigned char v;
   i_color val;
 
   for(y = 0; y < im->ysize; y++) for(x = 0; x < im->xsize; x++) {
     /*    v=saturate(125*(1.0+PerlinNoise_2D(xo+(float)x/scale,yo+(float)y/scale))); */
-    v = saturate(120*(1.0+sin(xo+(float)x/scale+PerlinNoise_2D(xo+(float)x/scale,yo+(float)y/scale))));
+    v = saturate(120*(1.0+sin(xo+(double)x/scale+PerlinNoise_2D(xo+(double)x/scale,yo+(float)y/scale))));
     for(ch=0; ch<im->channels; ch++) val.channel[ch] = v;
     i_ppix(im, x, y, &val);
   }
@@ -958,21 +913,22 @@ Gradient generating function.
 
 
 void
-i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
+i_gradgen(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *ival, int dmeasure) {
   
   i_color val;
-  int p, x, y, ch;
+  int p, ch;
+  i_img_dim x, y;
   int channels = im->channels;
-  int xsize    = im->xsize;
-  int ysize    = im->ysize;
-  int bytes;
+  i_img_dim xsize    = im->xsize;
+  i_img_dim ysize    = im->ysize;
+  size_t bytes;
 
-  float *fdist;
+  double *fdist;
 
   mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
   
   for(p = 0; p<num; p++) {
-    mm_log((1,"i_gradgen: (%d, %d)\n", xo[p], yo[p]));
+    mm_log((1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
     ICL_info(&ival[p]);
   }
 
@@ -984,19 +940,19 @@ i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
      overflow is a programming error rather than an end-user error, so
      calling exit() is justified.
   */
-  bytes = sizeof(float) * num;
-  if (bytes / num != sizeof(float)) {
+  bytes = sizeof(double) * num;
+  if (bytes / num != sizeof(double)) {
     fprintf(stderr, "integer overflow calculating memory allocation");
     exit(1);
   }
   fdist = mymalloc( bytes ); /* checked 14jul05 tonyc */
   
   for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
-    float cs = 0;
-    float csd = 0;
+    double cs = 0;
+    double csd = 0;
     for(p = 0; p<num; p++) {
-      int xd    = x-xo[p];
-      int yd    = y-yo[p];
+      i_img_dim xd    = x-xo[p];
+      i_img_dim yd    = y-yo[p];
       switch (dmeasure) {
       case 0: /* euclidean */
        fdist[p]  = sqrt(xd*xd + yd*yd); /* euclidean distance */
@@ -1029,26 +985,27 @@ i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
 }
 
 void
-i_nearest_color_foo(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure) {
+i_nearest_color_foo(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *ival, int dmeasure) {
 
-  int p, x, y;
-  int xsize    = im->xsize;
-  int ysize    = im->ysize;
+  int p;
+  i_img_dim x, y;
+  i_img_dim xsize    = im->xsize;
+  i_img_dim ysize    = im->ysize;
 
   mm_log((1,"i_gradgen(im %p, num %d, xo %p, yo %p, ival %p, dmeasure %d)\n", im, num, xo, yo, ival, dmeasure));
   
   for(p = 0; p<num; p++) {
-    mm_log((1,"i_gradgen: (%d, %d)\n", xo[p], yo[p]));
+    mm_log((1,"i_gradgen: p%d(" i_DFp ")\n", p, i_DFcp(xo[p], yo[p])));
     ICL_info(&ival[p]);
   }
 
   for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
-    int   midx    = 0;
-    float mindist = 0;
-    float curdist = 0;
+    int    midx    = 0;
+    double mindist = 0;
+    double curdist = 0;
 
-    int xd        = x-xo[0];
-    int yd        = y-yo[0];
+    i_img_dim xd        = x-xo[0];
+    i_img_dim yd        = y-yo[0];
 
     switch (dmeasure) {
     case 0: /* euclidean */
@@ -1112,11 +1069,11 @@ int num - number of points/colors in xo, yo, oval
 
 =item *
 
-int *xo - array of I<num> x positions
+i_img_dim *xo - array of I<num> x positions
 
 =item *
 
-int *yo - array of I<num> y positions
+i_img_dim *yo - array of I<num> y positions
 
 =item *
 
@@ -1157,16 +1114,17 @@ An invalid value causes an error exit (the program is aborted).
  */
 
 int
-i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *oval, int dmeasure) {
+i_nearest_color(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *oval, int dmeasure) {
   i_color *ival;
   float *tval;
-  float c1, c2;
+  double c1, c2;
   i_color val;
-  int p, x, y, ch;
-  int xsize    = im->xsize;
-  int ysize    = im->ysize;
+  int p, ch;
+  i_img_dim x, y;
+  i_img_dim xsize    = im->xsize;
+  i_img_dim ysize    = im->ysize;
   int *cmatch;
-  int ival_bytes, tval_bytes;
+  size_t ival_bytes, tval_bytes;
 
   mm_log((1,"i_nearest_color(im %p, num %d, xo %p, yo %p, oval %p, dmeasure %d)\n", im, num, xo, yo, oval, dmeasure));
 
@@ -1204,11 +1162,11 @@ i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *oval, int dmeasur
   
   for(y = 0; y<ysize; y++) for(x = 0; x<xsize; x++) {
     int   midx    = 0;
-    float mindist = 0;
-    float curdist = 0;
+    double mindist = 0;
+    double curdist = 0;
     
-    int xd        = x-xo[0];
-    int yd        = y-yo[0];
+    i_img_dim xd        = x-xo[0];
+    i_img_dim yd        = y-yo[0];
 
     switch (dmeasure) {
     case 0: /* euclidean */
@@ -1257,8 +1215,14 @@ i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *oval, int dmeasur
   
   }
 
-  for(p = 0; p<num; p++) for(ch = 0; ch<im->channels; ch++)
-    ival[p].channel[ch] = tval[p*im->channels + ch];
+  for(p = 0; p<num; p++) {
+    for(ch = 0; ch<im->channels; ch++)
+      ival[p].channel[ch] = tval[p*im->channels + ch];
+
+    /* avoid uninitialized value messages from valgrind */
+    while (ch < MAXCHANNELS)
+      ival[p].channel[ch++] = 0;
+  }
 
   i_nearest_color_foo(im, num, xo, yo, ival, dmeasure);
 
@@ -1277,7 +1241,8 @@ image from double the original.
 void
 i_unsharp_mask(i_img *im, double stddev, double scale) {
   i_img *copy;
-  int x, y, ch;
+  i_img_dim x, y;
+  int ch;
 
   if (scale < 0)
     return;
@@ -1354,7 +1319,7 @@ i_img *
 i_diff_image(i_img *im1, i_img *im2, double mindist) {
   i_img *out;
   int outchans, diffchans;
-  int xsize, ysize;
+  i_img_dim xsize, ysize;
 
   i_clear_error();
   if (im1->channels != im2->channels) {
@@ -1375,7 +1340,8 @@ i_diff_image(i_img *im1, i_img *im2, double mindist) {
     i_color *line1 = mymalloc(xsize * sizeof(*line1)); /* checked 17feb2005 tonyc */
     i_color *line2 = mymalloc(xsize * sizeof(*line1)); /* checked 17feb2005 tonyc */
     i_color empty;
-    int x, y, ch;
+    i_img_dim x, y;
+    int ch;
     int imindist = (int)mindist;
 
     for (ch = 0; ch < MAXCHANNELS; ++ch)
@@ -1410,7 +1376,8 @@ i_diff_image(i_img *im1, i_img *im2, double mindist) {
     i_fcolor *line1 = mymalloc(xsize * sizeof(*line1)); /* checked 17feb2005 tonyc */
     i_fcolor *line2 = mymalloc(xsize * sizeof(*line2)); /* checked 17feb2005 tonyc */
     i_fcolor empty;
-    int x, y, ch;
+    i_img_dim x, y;
+    int ch;
     double dist = mindist / 255.0;
 
     for (ch = 0; ch < MAXCHANNELS; ++ch)
@@ -1536,7 +1503,7 @@ struct fount_state {
   double cos;
   double sin;
   double theta;
-  int xa, ya;
+  i_img_dim xa, ya;
   void *ssample_data;
   fount_func ffunc;
   fount_repeat rpfunc;
@@ -1668,10 +1635,10 @@ i_fountain(i_img *im, double xa, double ya, double xb, double yb,
            int combine, int super_sample, double ssample_param, 
            int count, i_fountain_seg *segs) {
   struct fount_state state;
-  int x, y;
+  i_img_dim x, y;
   i_fcolor *line = NULL;
   i_fcolor *work = NULL;
-  int line_bytes;
+  size_t line_bytes;
   i_fountain_seg *my_segs;
   i_fill_combine_f combine_func = NULL;
   i_fill_combinef_f combinef_func = NULL;
@@ -1798,7 +1765,7 @@ fount_init_state(struct fount_state *state, double xa, double ya,
                  i_fountain_repeat repeat, int combine, int super_sample, 
                  double ssample_param, int count, i_fountain_seg *segs) {
   int i, j;
-  int bytes;
+  size_t bytes;
   i_fountain_seg *my_segs = mymalloc(sizeof(i_fountain_seg) * count); /* checked 2jul06 - duplicating original */
   /*int have_alpha = im->channels == 2 || im->channels == 4;*/
   
@@ -2005,7 +1972,7 @@ square.
 */
 static double
 square_fount_f(double x, double y, struct fount_state *state) {
-  int xc, yc; /* centred on A */
+  i_img_dim xc, yc; /* centred on A */
   double xt, yt; /* rotated by theta */
   xc = x - state->xa;
   yc = y - state->ya;
@@ -2187,7 +2154,7 @@ Simple grid-based super-sampling.
 static int
 simple_ssample(i_fcolor *out, double x, double y, struct fount_state *state) {
   i_fcolor *work = state->ssample_data;
-  int dx, dy;
+  i_img_dim dx, dy;
   int grid = state->parm;
   double base = -0.5 + 0.5 / grid;
   double step = 1.0 / grid;
diff --git a/flip.im b/flip.im
index c3df8f7..5bb1c74 100644 (file)
--- a/flip.im
+++ b/flip.im
@@ -87,7 +87,7 @@ IM_SUFFIX(flip_row)(IM_COLOR *row, i_img_dim width) {
 
 static void
 flip_h(i_img *im) {
-  int y;
+  i_img_dim y;
   if (im->type == i_palette_type) {
     i_palidx *line = mymalloc(im->xsize * sizeof(i_palidx));
     for (y = 0; y < im->ysize; ++y) {
@@ -112,8 +112,8 @@ flip_h(i_img *im) {
 
 static void
 flip_v(i_img *im) {
-  int topy = 0;
-  int boty = im->ysize - 1;
+  i_img_dim topy = 0;
+  i_img_dim boty = im->ysize - 1;
   if (im->type == i_palette_type) {
     i_palidx *top_line = mymalloc(im->xsize * sizeof(i_palidx));
     i_palidx *bot_line = mymalloc(im->xsize * sizeof(i_palidx));
@@ -148,8 +148,8 @@ flip_v(i_img *im) {
 
 static void
 flip_hv(i_img *im) {
-  int topy = 0;
-  int boty = im->ysize - 1;
+  i_img_dim topy = 0;
+  i_img_dim boty = im->ysize - 1;
   if (im->type == i_palette_type) {
     i_palidx *top_line = mymalloc(im->xsize * sizeof(i_palidx));
     i_palidx *bot_line = mymalloc(im->xsize * sizeof(i_palidx));
diff --git a/font.c b/font.c
index efb8355..f6f69a8 100644 (file)
--- a/font.c
+++ b/font.c
@@ -23,7 +23,7 @@ font.c - implements font handling functions for t1 and truetype fonts
 
   #ifdef HAVE_LIBT1
   fontnum = i_t1_new(path_to_pfb, path_to_afm);
-  i_t1_bbox(fontnum, points, "foo", 3, int cords[6]);
+  i_t1_bbox(fontnum, points, "foo", 3, i_img_dim cords[BOUNDING_BOX_COUNT]);
   rc = i_t1_destroy(fontnum);
   #endif
 
@@ -94,8 +94,8 @@ struct TT_Instancehandle_ {
   TT_Glyph_Metrics gmetrics[256];
   i_tt_glyph_entry glyphs[256];
   int smooth;
-  int ptsize;
   int order;
+  i_img_dim ptsize;
 };
 
 typedef struct TT_Instancehandle_ TT_Instancehandle;
@@ -120,26 +120,26 @@ static void i_tt_push_error(TT_Error rc);
 
 /* Prototypes */
 
-static  int i_tt_get_instance( TT_Fonthandle *handle, int points, int smooth );
-static void i_tt_init_raster_map( TT_Raster_Map* bit, int width, int height, int smooth );
+static  int i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth );
+static void i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth );
 static void i_tt_done_raster_map( TT_Raster_Map *bit );
 static void i_tt_clear_raster_map( TT_Raster_Map* bit );
-static void i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,int x_off, int y_off );
+static void i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off );
 static  int i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j );
 static void 
 i_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics, 
                    TT_Raster_Map *bit, TT_Raster_Map *small_bit, 
-                   int x_off, int y_off, int smooth );
+                   i_img_dim x_off, i_img_dim y_off, int smooth );
 static int
 i_tt_render_all_glyphs( TT_Fonthandle *handle, int inst, TT_Raster_Map *bit, 
-                        TT_Raster_Map *small_bit, int cords[6], 
+                        TT_Raster_Map *small_bit, i_img_dim cords[6], 
                         char const* txt, size_t len, int smooth, int utf8 );
-static void i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, int xb, int yb, const i_color *cl, int smooth );
-static void i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, int xb, int yb, int channel, int smooth );
+static void i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, const i_color *cl, int smooth );
+static void i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, i_img_dim xb, i_img_dim yb, int channel, int smooth );
 static  int
-i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, int cords[6], 
-                float points, char const* txt, size_t len, int smooth, int utf8 );
-static undef_int i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, int cords[6], int utf8 );
+i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, i_img_dim cords[6], 
+                double points, char const* txt, size_t len, int smooth, int utf8 );
+static undef_int i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim cords[6], int utf8 );
 
 
 /* static globals needed */
@@ -173,7 +173,8 @@ i_init_tt(void) {
   mm_log((1,"init_tt()\n"));
   error = TT_Init_FreeType( &engine );
   if ( error ){
-    mm_log((1,"Initialization of freetype failed, code = 0x%x\n",error));
+    mm_log((1,"Initialization of freetype failed, code = 0x%x\n",
+           (unsigned)error));
     i_tt_push_error(error);
     i_push_error(0, "Could not initialize freetype 1.x");
     return(1);
@@ -182,7 +183,8 @@ i_init_tt(void) {
 #ifdef FTXPOST
   error = TT_Init_Post_Extension( engine );
   if (error) {
-    mm_log((1, "Initialization of Post extension failed = 0x%x\n", error));
+    mm_log((1, "Initialization of Post extension failed = 0x%x\n",
+           (unsigned)error));
     
     i_tt_push_error(error);
     i_push_error(0, "Could not initialize FT 1.x POST extension");
@@ -192,7 +194,8 @@ i_init_tt(void) {
 
   error = TT_Set_Raster_Gray_Palette(engine, palette);
   if (error) {
-    mm_log((1, "Initialization of gray levels failed = 0x%x\n", error));
+    mm_log((1, "Initialization of gray levels failed = 0x%x\n",
+           (unsigned)error));
     i_tt_push_error(error);
     i_push_error(0, "Could not initialize FT 1.x POST extension");
     return 1;
@@ -220,12 +223,12 @@ allocates room and returns its cache entry
 
 static
 int
-i_tt_get_instance( TT_Fonthandle *handle, int points, int smooth ) {
+i_tt_get_instance( TT_Fonthandle *handle, i_img_dim points, int smooth ) {
   int i,idx;
   TT_Error error;
   
-  mm_log((1,"i_tt_get_instance(handle 0x%X, points %d, smooth %d)\n",
-          handle,points,smooth));
+  mm_log((1,"i_tt_get_instance(handle %p, points %" i_DF ", smooth %d)\n",
+          handle, i_DFc(points), smooth));
   
   if (smooth == -1) { /* Smooth doesn't matter for this search */
     for(i=0;i<TT_CHC;i++) {
@@ -252,7 +255,7 @@ i_tt_get_instance( TT_Fonthandle *handle, int points, int smooth ) {
   }
 
   mm_log((1,"i_tt_get_instance: lru item is %d\n",idx));
-  mm_log((1,"i_tt_get_instance: lru pointer 0x%X\n",
+  mm_log((1,"i_tt_get_instance: lru pointer %p\n",
           USTRCT(handle->instanceh[idx].instance) ));
   
   if ( USTRCT(handle->instanceh[idx].instance) ) {
@@ -280,7 +283,8 @@ i_tt_get_instance( TT_Fonthandle *handle, int points, int smooth ) {
          ( error = TT_Set_Instance_CharSize( handle->instanceh[idx].instance, points*64 ) ) );
   
   if ( error ) {
-    mm_log((1, "Could not create and initialize instance: error 0x%x.\n",error ));
+    mm_log((1, "Could not create and initialize instance: error %x.\n",
+           (unsigned)error ));
     return -1;
   }
   
@@ -345,7 +349,7 @@ i_tt_new(const char *fontname) {
     }
     else {
       mm_log((1, "Error while opening %s, error code = 0x%x.\n",fontname, 
-              error )); 
+              (unsigned)error )); 
     }
     i_tt_push_error(error);
     return NULL;
@@ -385,7 +389,7 @@ i_tt_new(const char *fontname) {
   handle->loaded_names = 0;
 #endif
 
-  mm_log((1,"i_tt_new <- 0x%X\n",handle));
+  mm_log((1,"i_tt_new <- %p\n",handle));
   return handle;
 }
 
@@ -410,9 +414,10 @@ Allocates internal memory for the bitmap as needed by the parameters (internal)
 
 static
 void
-i_tt_init_raster_map( TT_Raster_Map* bit, int width, int height, int smooth ) {
+i_tt_init_raster_map( TT_Raster_Map* bit, i_img_dim width, i_img_dim height, int smooth ) {
 
-  mm_log((1,"i_tt_init_raster_map( bit 08x%08X, width %d, height %d, smooth %d)\n", bit, width, height, smooth));
+  mm_log((1,"i_tt_init_raster_map( bit %p, width %" i_DF ", height %" i_DF
+         ", smooth %d)\n", bit, i_DFc(width), i_DFc(height), smooth));
   
   bit->rows  = height;
   bit->width = ( width + 3 ) & -4;
@@ -432,7 +437,7 @@ i_tt_init_raster_map( TT_Raster_Map* bit, int width, int height, int smooth ) {
             bit->width, bit->rows);
   }
   
-  mm_log((1,"i_tt_init_raster_map: bit->width %d, bit->cols %d, bit->rows %d, bit->size %d)\n", bit->width, bit->cols, bit->rows, bit->size ));
+  mm_log((1,"i_tt_init_raster_map: bit->width %d, bit->cols %d, bit->rows %d, bit->size %ld)\n", bit->width, bit->cols, bit->rows, bit->size ));
 
   bit->bitmap = (void *) mymalloc( bit->size ); /* checked 6Nov05 tonyc */
   if ( !bit->bitmap ) i_fatal(0,"Not enough memory to allocate bitmap (%d)!\n",bit->size );
@@ -490,9 +495,9 @@ function that blits one raster map into another (internal)
 
 static
 void
-i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,int x_off, int y_off ) {
-  int  x,  y;
-  int  x1, x2, y1, y2;
+i_tt_blit_or( TT_Raster_Map *dst, TT_Raster_Map *src,i_img_dim x_off, i_img_dim y_off ) {
+  i_img_dim  x,  y;
+  i_img_dim  x1, x2, y1, y2;
   unsigned char *s, *d;
   
   x1 = x_off < 0 ? -x_off : 0;
@@ -557,14 +562,14 @@ i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j) {
   unsigned short load_flags, code;
   TT_Error error;
 
-  mm_log((1, "i_tt_get_glyph(handle 0x%X, inst %d, j %d (%c))\n",
-          handle,inst,j, ((j >= ' ' && j <= '~') ? j : '.')));
+  mm_log((1, "i_tt_get_glyph(handle %p, inst %d, j %lu (%c))\n",
+          handle,inst,j, (int)((j >= ' ' && j <= '~') ? j : '.')));
   
   /*mm_log((1, "handle->instanceh[inst].glyphs[j]=0x%08X\n",handle->instanceh[inst].glyphs[j] ));*/
 
   if ( TT_VALID(handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)
        && handle->instanceh[inst].glyphs[TT_HASH(j)].ch == j) {
-    mm_log((1,"i_tt_get_glyph: %d in cache\n",j));
+    mm_log((1,"i_tt_get_glyph: %lu in cache\n",j));
     return 1;
   }
 
@@ -585,12 +590,12 @@ i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j) {
   } else code = TT_Char_Index( handle->char_map, j );
   
   if ( (error = TT_New_Glyph( handle->face, &handle->instanceh[inst].glyphs[TT_HASH(j)].glyph)) ) {
-    mm_log((1, "Cannot allocate and load glyph: error 0x%x.\n", error ));
+    mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
     i_push_error(error, "TT_New_Glyph()");
     return 0;
   }
   if ( (error = TT_Load_Glyph( handle->instanceh[inst].instance, handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, code, load_flags)) ) {
-    mm_log((1, "Cannot allocate and load glyph: error 0x%x.\n", error ));
+    mm_log((1, "Cannot allocate and load glyph: error %#x.\n", (unsigned)error ));
     /* Don't leak */
     TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
     USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
@@ -605,7 +610,7 @@ i_tt_get_glyph( TT_Fonthandle *handle, int inst, unsigned long j) {
   error = TT_Get_Glyph_Metrics( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph, 
                                 &handle->instanceh[inst].gmetrics[TT_HASH(j)] );
   if (error) {
-    mm_log((1, "TT_Get_Glyph_Metrics: error 0x%x.\n", error ));
+    mm_log((1, "TT_Get_Glyph_Metrics: error %#x.\n", (unsigned)error ));
     TT_Done_Glyph( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph );
     USTRCT( handle->instanceh[inst].glyphs[TT_HASH(j)].glyph ) = NULL;
     handle->instanceh[inst].glyphs[TT_HASH(j)].ch = TT_NOCHAR;
@@ -628,12 +633,12 @@ Returns the number of characters that were checked.
 =cut
 */
 
-int
+size_t
 i_tt_has_chars(TT_Fonthandle *handle, char const *text, size_t len, int utf8,
                char *out) {
-  int count = 0;
-  mm_log((1, "i_tt_has_chars(handle %p, text %p, len %d, utf8 %d)\n", 
-          handle, text, len, utf8));
+  size_t count = 0;
+  mm_log((1, "i_tt_has_chars(handle %p, text %p, len %ld, utf8 %d)\n", 
+          handle, text, (long)len, utf8));
 
   while (len) {
 &