From 8d14daabc32a4346d5c20dbe864acc65ca66315b Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Tue, 14 Jun 2011 23:32:14 +1000 Subject: [PATCH] switch to using size_t and i_img_dim strictly 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 --- Changes | 34 + CountColor/CountColor.xs | 3 +- DynTest/linstretch.c | 7 +- FT2/FT2.xs | 29 +- FT2/freetyp2.c | 51 +- FT2/imft2.h | 19 +- Flines/Flines.xs | 6 +- GIF/imgif.c | 39 +- GIF/t/t40limit.t | 88 ++ Imager.xs | 591 ++++---- JPEG/imexif.c | 1 + JPEG/imjpeg.c | 15 +- JPEG/t/t20limit.t | 54 + MANIFEST | 5 + Makefile.PL | 22 + Mandelbrot/mandel.c | 3 +- PNG/impng.c | 9 +- SGI/imsgi.c | 8 + SGI/t/30limit.t | 52 + T1/T1.xs | 16 +- T1/imt1.c | 27 +- T1/imt1.h | 6 +- TIFF/imtiff.c | 116 +- W32/W32.pm | 2 + W32/W32.xs | 22 +- W32/imw32.h | 10 +- W32/win32.c | 46 +- apidocs.perl | 6 +- bmp.c | 98 +- compose.im | 47 +- conv.im | 8 +- convert.im | 5 +- datatypes.c | 149 +- draw.c | 272 ++-- draw.h | 17 +- dynaload.c | 14 +- dynfilt/dt2.c | 8 +- dynfilt/dyntest.c | 12 +- dynfilt/flines.c | 10 +- dynfilt/mandelbrot.c | 18 +- error.c | 10 +- fileformatdocs/other.txt | 5 + fileformatdocs/spec-gif89a.txt | 2476 ++++++++++++++++++++++++++++++++ fileformatdocs/tga_specs.pdf | Bin 0 -> 63496 bytes fileformatdocs/tgaffs.pdf | Bin 0 -> 181468 bytes fills.c | 39 +- filters.im | 313 ++-- flip.im | 10 +- font.c | 160 ++- gaussian.im | 21 +- hlines.c | 32 +- image.c | 182 +-- imager.h | 206 ++- imageri.h | 33 +- imdatatypes.h | 132 +- imerror.h | 2 +- imext.c | 40 +- imext.h | 7 + imexttypes.h | 97 +- img16.c | 115 +- img8.c | 92 +- imgdouble.c | 95 +- io.c | 50 +- iolayer.c | 26 +- iolayert.h | 1 + lib/Imager/APIRef.pod | 170 ++- lib/Imager/Cookbook.pod | 2 +- lib/Imager/Files.pod | 10 +- limits.c | 63 +- log.c | 1 + log.h | 3 +- map.c | 2 +- maskimg.c | 92 +- palimg.c | 60 +- paste.im | 25 +- pnm.c | 39 +- polygon.c | 29 +- quant.c | 35 +- raw.c | 34 +- regmach.c | 12 +- render.im | 8 +- rotate.c | 42 +- rubthru.im | 30 +- scale.im | 50 +- t/t01introvert.t | 2 +- t/t021sixteen.t | 4 +- t/t022double.t | 2 +- t/t023palette.t | 4 +- t/t1000files.t | 4 +- t/t104ppm.t | 17 +- t/t107bmp.t | 5 +- t/t108tga.t | 79 +- t/t64copyflip.t | 5 +- testimg/tootall.ppm | 5 + testimg/toowide.ppm | 5 + tga.c | 29 +- trans2.c | 4 +- typemap | 6 + 98 files changed, 5108 insertions(+), 1859 deletions(-) create mode 100644 GIF/t/t40limit.t create mode 100644 JPEG/t/t20limit.t create mode 100644 SGI/t/30limit.t create mode 100644 fileformatdocs/spec-gif89a.txt create mode 100755 fileformatdocs/tga_specs.pdf create mode 100644 fileformatdocs/tgaffs.pdf create mode 100644 testimg/tootall.ppm create mode 100644 testimg/toowide.ppm diff --git a/Changes b/Changes index dcab208e..0a2c13e7 100644 --- 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 =========== diff --git a/CountColor/CountColor.xs b/CountColor/CountColor.xs index 41a0a558..711b2a88 100644 --- a/CountColor/CountColor.xs +++ b/CountColor/CountColor.xs @@ -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; diff --git a/DynTest/linstretch.c b/DynTest/linstretch.c index 7d2d8faa..6579e121 100644 --- a/DynTest/linstretch.c +++ b/DynTest/linstretch.c @@ -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;yysize;y++) for(x=0;xxsize;x++) { i_gpix(im,x,y,&rcolor); diff --git a/FT2/FT2.xs b/FT2/FT2.xs index 4bd18013..97c037da 100644 --- a/FT2/FT2.xs +++ b/FT2/FT2.xs @@ -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) { diff --git a/FT2/freetyp2.c b/FT2/freetyp2.c index 8d034f9d..2249bbac 100644 --- a/FT2/freetyp2.c +++ b/FT2/freetyp2.c @@ -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; } diff --git a/FT2/imft2.h b/FT2/imft2.h index b283c628..57b71293 100644 --- a/FT2/imft2.h +++ b/FT2/imft2.h @@ -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 diff --git a/Flines/Flines.xs b/Flines/Flines.xs index 4b9164be..282be666 100644 --- a/Flines/Flines.xs +++ b/Flines/Flines.xs @@ -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); diff --git a/GIF/imgif.c b/GIF/imgif.c index 623a5671..27668ef9 100644 --- a/GIF/imgif.c +++ b/GIF/imgif.c @@ -8,6 +8,7 @@ #include #include #include +#include /* =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 index 00000000..d08126b3 --- /dev/null +++ b/GIF/t/t40limit.t @@ -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"); +} diff --git a/Imager.xs b/Imager.xs index 434e4e00..5b919d1c 100644 --- 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 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 diff --git a/JPEG/imexif.c b/JPEG/imexif.c index 9b184a9b..07f75b87 100644 --- a/JPEG/imexif.c +++ b/JPEG/imexif.c @@ -3,6 +3,7 @@ #include #include #include +#include /* =head1 NAME diff --git a/JPEG/imjpeg.c b/JPEG/imjpeg.c index 6854cb58..eaf9a5d7 100644 --- a/JPEG/imjpeg.c +++ b/JPEG/imjpeg.c @@ -33,11 +33,15 @@ Reads and writes JPEG images #include "jerror.h" #include #include +#include +#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 index 00000000..3a738053 --- /dev/null +++ b/JPEG/t/t20limit.t @@ -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"); + } +} diff --git a/MANIFEST b/MANIFEST index 16e60597..58cd63fe 100644 --- 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 diff --git a/Makefile.PL b/Makefile.PL index c981e4b0..5bdd6824 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -734,6 +734,28 @@ EOS } print CONFIG "#define $define->[0] $define->[1]\n"; } + if ($Config{gccversion} && $Config{gccversion} > 3) { + print CONFIG <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; diff --git a/SGI/imsgi.c b/SGI/imsgi.c index 547badcf..d8d9be3d 100644 --- a/SGI/imsgi.c +++ b/SGI/imsgi.c @@ -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 index 00000000..8e3fd11a --- /dev/null +++ b/SGI/t/30limit.t @@ -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"); + } +} diff --git a/T1/T1.xs b/T1/T1.xs index 255eec64..659b01dc 100644 --- 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 diff --git a/T1/imt1.c b/T1/imt1.c index 1629a147..1c4a1a7b 100644 --- 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; diff --git a/T1/imt1.h b/T1/imt1.h index 9b3bbb75..489bcef7 100644 --- 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, diff --git a/TIFF/imtiff.c b/TIFF/imtiff.c index 75d82440..13f86505 100644 --- a/TIFF/imtiff.c +++ b/TIFF/imtiff.c @@ -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; diff --git a/W32/W32.pm b/W32/W32.pm index bb91fb7f..763df5fe 100644 --- a/W32/W32.pm +++ b/W32/W32.pm @@ -47,6 +47,8 @@ sub _draw { $input{'y'}, $input{color}, $input{size}, $input{string}, $input{align}, $input{aa}, $input{utf8}); } + + return 1; } diff --git a/W32/W32.xs b/W32/W32.xs index 9e0020d3..e1e977be 100644 --- a/W32/W32.xs +++ b/W32/W32.xs @@ -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 diff --git a/W32/imw32.h b/W32/imw32.h index 848aa542..a5ea91ac 100644 --- a/W32/imw32.h +++ b/W32/imw32.h @@ -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); diff --git a/W32/win32.c b/W32/win32.c index b466d991..33c8ed14 100644 --- a/W32/win32.c +++ b/W32/win32.c @@ -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; diff --git a/apidocs.perl b/apidocs.perl index 7c5016de..ad5e259f 100644 --- a/apidocs.perl +++ b/apidocs.perl @@ -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 8f37d32a..9cf76157 100644 --- 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) { diff --git a/compose.im b/compose.im index d7e0e81e..6d609648 100644 --- a/compose.im +++ b/compose.im @@ -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 b7afa647..b766d7eb 100644 --- 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) diff --git a/convert.im b/convert.im index b001f4bd..9784349a 100644 --- a/convert.im +++ b/convert.im @@ -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(); diff --git a/datatypes.c b/datatypes.c index a1efb995..c7b37b3d 100644 --- a/datatypes.c +++ b/datatypes.c @@ -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 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 58239edc..f36949aa 100644 --- 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 && ylines) { if (xdata[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 && ylines) 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 && ylines) 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;ilines;i++) if (ar->data[i].max!=-1) for(x=ar->data[i].min;xdata[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;ilines;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. */ 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 || 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 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 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; ychannels;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;chchannels;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, C) 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, C) 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, C) 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, C) 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 3453de30..73d58555 100644 --- 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 diff --git a/dynaload.c b/dynaload.c index 75f1b3f5..8838038a 100644 --- a/dynaload.c +++ b/dynaload.c @@ -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); } diff --git a/dynfilt/dt2.c b/dynfilt/dt2.c index 8278d25b..664c9ca3 100644 --- a/dynfilt/dt2.c +++ b/dynfilt/dt2.c @@ -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,""); diff --git a/dynfilt/dyntest.c b/dynfilt/dyntest.c index 10e449d4..50a9641c 100644 --- a/dynfilt/dyntest.c +++ b/dynfilt/dyntest.c @@ -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;yysize;y++) for(x=0;xxsize;x++) { i_gpix(im,x,y,&rcolor); diff --git a/dynfilt/flines.c b/dynfilt/flines.c index f018477c..0de80e7a 100644 --- a/dynfilt/flines.c +++ b/dynfilt/flines.c @@ -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); diff --git a/dynfilt/mandelbrot.c b/dynfilt/mandelbrot.c index ca3500e8..4952ee36 100644 --- a/dynfilt/mandelbrot.c +++ b/dynfilt/mandelbrot.c @@ -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 755f69d1..48de989a 100644 --- 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) { diff --git a/fileformatdocs/other.txt b/fileformatdocs/other.txt index 764997c1..1f19a9a8 100644 --- a/fileformatdocs/other.txt +++ b/fileformatdocs/other.txt @@ -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 index 00000000..64a07299 --- /dev/null +++ b/fileformatdocs/spec-gif89a.txt @@ -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 | | | | | See below + +---------------+ + 5 | | Background Color Index Byte + +---------------+ + 6 | | Pixel Aspect Ratio Byte + +---------------+ + + + + + + + + + + 9 + + + = 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 | | | | | | See below + +---------------+ + + = 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 | | | | | See below + +---------------+ + 2 | | Delay Time Unsigned + +- -+ + 3 | | + +---------------+ + 4 | | Transparent Color Index Byte + +---------------+ + + +---------------+ + 0 | | Block Terminator Byte + +---------------+ + + + = 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: + + ::= Header * Trailer + +This rule defines the entity 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. + + ::= Header * Trailer + + ::= Logical Screen Descriptor [Global Color Table] + + ::= | + + + ::= [Graphic Control Extension] + + ::= | + Plain Text Extension + + ::= Image Descriptor [Local Color Table] Image Data + + ::= 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**. 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 +1. + +3. The first available compression code value is +2. + +4. The output codes are of variable length, starting at +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}... + + +'#' 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 + +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 index 0000000000000000000000000000000000000000..dab09c6bbba1c0a04c87a86076bd3f89d4b473ca GIT binary patch literal 63496 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 literal 0 HcmV?d00001 diff --git a/fileformatdocs/tgaffs.pdf b/fileformatdocs/tgaffs.pdf new file mode 100644 index 0000000000000000000000000000000000000000..781a9a08aeb12da1d6ef95ee53e899ccb57865a3 GIT binary patch literal 181468 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 z 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 literal 0 HcmV?d00001 diff --git a/fills.c b/fills.c index b92eaaf3..795f7cd8 100644 --- 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, C, C, C, C, C, C) @@ -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 and C 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); diff --git a/filters.im b/filters.im index 9ebb0af7..06ac6a1f 100644 --- a/filters.im +++ b/filters.im @@ -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;vxysize; 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; chchannels; 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; pxsize; - 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 x positions +i_img_dim *xo - array of I x positions =item * -int *yo - array of I y positions +i_img_dim *yo - array of I 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; ychannels; ch++) - ival[p].channel[ch] = tval[p*im->channels + ch]; + for(p = 0; pchannels; 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 c3df8f7f..5bb1c74f 100644 --- 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 efb83550..f6f69a87 100644 --- 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;iinstanceh[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) { unsigned long c; @@ -722,10 +727,11 @@ Renders a single glyph into the bit rastermap (internal) 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_tt_render_glyph( TT_Glyph glyph, TT_Glyph_Metrics* gmetrics, TT_Raster_Map *bit, TT_Raster_Map *small_bit, i_img_dim x_off, i_img_dim y_off, int smooth ) { - mm_log((1,"i_tt_render_glyph(glyph 0x0%X, gmetrics 0x0%X, bit 0x%X, small_bit 0x%X, x_off %d, y_off %d, smooth %d)\n", - USTRCT(glyph), gmetrics, bit, small_bit, x_off,y_off,smooth)); + mm_log((1,"i_tt_render_glyph(glyph %p, gmetrics %p, bit %p, small_bit %p, x_off %" i_DF ", y_off %" i_DF ", smooth %d)\n", + USTRCT(glyph), gmetrics, bit, small_bit, i_DFc(x_off), + i_DFc(y_off), smooth)); if ( !smooth ) TT_Get_Glyph_Bitmap( glyph, bit, x_off * 64, y_off * 64); else { @@ -762,13 +768,13 @@ calls i_tt_render_glyph to render each glyph into the bit rastermap (internal) 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 ) { unsigned long j; TT_F26Dot6 x,y; - mm_log((1,"i_tt_render_all_glyphs( handle 0x%X, inst %d, bit 0x%X, small_bit 0x%X, txt '%.*s', len %d, smooth %d, utf8 %d)\n", - handle, inst, bit, small_bit, len, txt, len, smooth, utf8)); + mm_log((1,"i_tt_render_all_glyphs( handle %p, inst %d, bit %p, small_bit %p, txt '%.*s', len %ld, smooth %d, utf8 %d)\n", + handle, inst, bit, small_bit, (int)len, txt, (long)len, smooth, utf8)); /* y=-( handle->properties.horizontal->Descender * handle->instanceh[inst].imetrics.y_ppem )/(handle->properties.header->Units_Per_EM); @@ -821,10 +827,11 @@ Function to dump a raster onto an image in color used by i_tt_text() (internal). static void -i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, int xb, int yb, const i_color *cl, int smooth ) { +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 ) { unsigned char *bmap; - int x, y; - mm_log((1,"i_tt_dump_raster_map2(im 0x%x, bit 0x%X, xb %d, yb %d, cl 0x%X)\n",im,bit,xb,yb,cl)); + i_img_dim x, y; + mm_log((1,"i_tt_dump_raster_map2(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", cl %p)\n", + im, bit, i_DFc(xb), i_DFc(yb), cl)); bmap = bit->bitmap; @@ -833,18 +840,7 @@ i_tt_dump_raster_map2( i_img* im, TT_Raster_Map* bit, int xb, int yb, const i_co i_render r; i_render_init(&r, im, bit->cols); for(y=0;yrows;y++) { -#if 0 - for(x=0;xwidth;x++) { - c = (unsigned char)bmap[y*(bit->cols)+x]; - i=255-c; - i_gpix(im,x+xb,y+yb,&val); - for(ch=0;chchannels;ch++) - val.channel[ch] = (c*cl->channel[ch]+i*val.channel[ch])/255; - i_ppix(im,x+xb,y+yb,&val); - } -#else i_render_color(&r, xb, yb+y, bit->cols, bmap + y*bit->cols, cl); -#endif } i_render_done(&r); } else { @@ -884,14 +880,16 @@ Function to dump a raster onto a single channel image in color (internal) static void -i_tt_dump_raster_map_channel( i_img* im, TT_Raster_Map* bit, int xb, int yb, int channel, int smooth ) { +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 ) { unsigned char *bmap; i_color val; - int c,x,y; + int c; + i_img_dim x,y; int old_mask = im->ch_mask; im->ch_mask = 1 << channel; - mm_log((1,"i_tt_dump_raster_channel(im 0x%x, bit 0x%X, xb %d, yb %d, channel %d)\n",im,bit,xb,yb,channel)); + mm_log((1,"i_tt_dump_raster_channel(im %p, bit %p, xb %" i_DF ", yb %" i_DF ", channel %d)\n", + im, bit, i_DFc(xb), i_DFc(yb), channel)); bmap = bit->bitmap; @@ -940,9 +938,9 @@ interface for generating single channel raster of text (internal) 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 ) { +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 ) { int inst; - int width, height; + i_img_dim width, height; TT_Raster_Map small_bit; /* find or install an instance */ @@ -959,7 +957,8 @@ i_tt_rasterize( TT_Fonthandle *handle, TT_Raster_Map *bit, int cords[6], float p width = cords[2]-cords[0]; height = cords[5]-cords[4]; - mm_log((1,"i_tt_rasterize: width=%d, height=%d\n",width, height )); + mm_log((1,"i_tt_rasterize: width=%" i_DF ", height=%" i_DF "\n", + i_DFc(width), i_DFc(height) )); i_tt_init_raster_map ( bit, width, height, smooth ); i_tt_clear_raster_map( bit ); @@ -1001,10 +1000,10 @@ Interface to text rendering into a single channel in an image */ undef_int -i_tt_cp( TT_Fonthandle *handle, i_img *im, int xb, int yb, int channel, float points, char const* txt, size_t len, int smooth, int utf8, int align ) { +i_tt_cp( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, int channel, double points, char const* txt, size_t len, int smooth, int utf8, int align ) { - int cords[BOUNDING_BOX_COUNT]; - int ascent, st_offset, y; + i_img_dim cords[BOUNDING_BOX_COUNT]; + i_img_dim ascent, st_offset, y; TT_Raster_Map bit; i_clear_error(); @@ -1039,9 +1038,9 @@ Interface to text rendering in a single color onto an image */ undef_int -i_tt_text( TT_Fonthandle *handle, i_img *im, int xb, int yb, const i_color *cl, float points, char const* txt, size_t len, int smooth, int utf8, int align) { - int cords[BOUNDING_BOX_COUNT]; - int ascent, st_offset, y; +i_tt_text( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, const i_color *cl, double points, char const* txt, size_t len, int smooth, int utf8, int align) { + i_img_dim cords[BOUNDING_BOX_COUNT]; + i_img_dim ascent, st_offset, y; TT_Raster_Map bit; i_clear_error(); @@ -1075,11 +1074,11 @@ Function to get texts bounding boxes given the instance of the font (internal) static undef_int -i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, int cords[BOUNDING_BOX_COUNT], int utf8 ) { +i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, i_img_dim cords[BOUNDING_BOX_COUNT], int utf8 ) { int upm, casc, cdesc, first; int start = 0; - int width = 0; + i_img_dim width = 0; int gdescent = 0; int gascent = 0; int descent = 0; @@ -1090,7 +1089,8 @@ i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, in unsigned char *ustr; ustr=(unsigned char*)txt; - mm_log((1,"i_tt_box_inst(handle 0x%X,inst %d,txt '%.*s', len %d, utf8 %d)\n",handle,inst,len,txt,len, utf8)); + mm_log((1,"i_tt_box_inst(handle %p,inst %d,txt '%.*s', len %ld, utf8 %d)\n", + handle, inst, (int)len, txt, (long)len, utf8)); upm = handle->properties.header->Units_Per_EM; gascent = ( handle->properties.horizontal->Ascender * handle->instanceh[inst].imetrics.y_ppem + upm - 1) / upm; @@ -1121,7 +1121,7 @@ i_tt_bbox_inst( TT_Fonthandle *handle, int inst ,const char *txt, size_t len, in cdesc = (gm->bbox.yMin-63) / 64; mm_log((1, "i_tt_box_inst: glyph='%c' casc=%d cdesc=%d\n", - ((j >= ' ' && j <= '~') ? j : '.'), casc, cdesc)); + (int)((j >= ' ' && j <= '~') ? j : '.'), casc, cdesc)); if (first) { start = gm->bbox.xMin / 64; @@ -1175,11 +1175,12 @@ Interface to get a strings bounding box */ undef_int -i_tt_bbox( TT_Fonthandle *handle, float points,const char *txt,size_t len,int cords[6], int utf8) { +i_tt_bbox( TT_Fonthandle *handle, double points,const char *txt,size_t len,i_img_dim cords[6], int utf8) { int inst; i_clear_error(); - mm_log((1,"i_tt_box(handle 0x%X,points %f,txt '%.*s', len %d, utf8 %d)\n",handle,points,len,txt,len, utf8)); + mm_log((1,"i_tt_box(handle %p,points %f,txt '%.*s', len %ld, utf8 %d)\n", + handle, points, (int)len, txt, (long)len, utf8)); if ( (inst=i_tt_get_instance(handle,points,-1)) < 0) { i_push_errorf(0, "i_tt_get_instance(%g)", points); @@ -1199,7 +1200,7 @@ This is complicated by the need to handle encodings and so on. =cut */ -int +size_t i_tt_face_name(TT_Fonthandle *handle, char *name_buf, size_t name_buf_size) { TT_Face_Properties props; int name_count; @@ -1292,7 +1293,7 @@ void i_tt_dump_names(TT_Fonthandle *handle) { fflush(stdout); } -int +size_t i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf, size_t name_buf_size) { #ifdef FTXPOST @@ -1310,7 +1311,8 @@ i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf, } if (handle->load_cond) { - i_push_errorf(handle->load_cond, "error loading names (%d)", handle->load_cond); + i_push_errorf(handle->load_cond, "error loading names (%#x)", + (unsigned)handle->load_cond); return 0; } diff --git a/gaussian.im b/gaussian.im index 8489273a..45fc02d9 100644 --- a/gaussian.im +++ b/gaussian.im @@ -3,7 +3,7 @@ static double gauss(int x, double std) { - return 1.0/(sqrt(2.0*PI)*std)*exp(-(double)(x)*(float)(x)/(2*std*std)); + return 1.0/(sqrt(2.0*PI)*std)*exp(-(double)(x)*(double)(x)/(2*std*std)); } /* Counters are as follows @@ -18,7 +18,8 @@ gauss(int x, double std) { int i_gaussian(i_img *im, double stddev) { - int i,l,c,ch; + int i, c, ch; + i_img_dim x, y; double pc; double *coeff; double res[MAXCHANNELS]; @@ -59,13 +60,13 @@ i_gaussian(i_img *im, double stddev) { #code im->bits <= 8 IM_COLOR rcolor; - for(l=0;lysize;l++) { - for(i=0;ixsize;i++) { + for(y = 0; y < im->ysize; y++) { + for(x = 0; x < im->xsize; x++) { pc=0.0; for(ch=0;chchannels;ch++) res[ch]=0; for(c = 0;c < diameter; c++) - if (IM_GPIX(im,i+c-radius,l,&rcolor)!=-1) { + if (IM_GPIX(im,x+c-radius,y,&rcolor)!=-1) { for(ch=0;chchannels;ch++) res[ch]+= rcolor.channel[ch] * coeff[c]; pc+=coeff[c]; @@ -74,17 +75,17 @@ i_gaussian(i_img *im, double stddev) { double value = res[ch] / pc; rcolor.channel[ch] = value > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : IM_ROUND(value); } - IM_PPIX(timg,i,l,&rcolor); + IM_PPIX(timg, x, y, &rcolor); } } - for(l=0;lxsize;l++) { - for(i=0;iysize;i++) { + for(x = 0;x < im->xsize; x++) { + for(y = 0; y < im->ysize; y++) { pc=0.0; for(ch=0; chchannels; ch++) res[ch]=0; for(c=0; c < diameter; c++) - if (IM_GPIX(timg,l,i+c-radius,&rcolor)!=-1) { + if (IM_GPIX(timg, x, y+c-radius, &rcolor)!=-1) { for(ch=0;chchannels;ch++) res[ch]+= rcolor.channel[ch] * coeff[c]; pc+=coeff[c]; @@ -93,7 +94,7 @@ i_gaussian(i_img *im, double stddev) { double value = res[ch]/pc; rcolor.channel[ch] = value > IM_SAMPLE_MAX ? IM_SAMPLE_MAX : IM_ROUND(value); } - IM_PPIX(im,l,i,&rcolor); + IM_PPIX(im, x, y, &rcolor); } } #/code diff --git a/hlines.c b/hlines.c index 68b81131..c4b04cc1 100644 --- a/hlines.c +++ b/hlines.c @@ -59,13 +59,13 @@ range. Any x or y values outside the given ranges will be ignored. void i_int_init_hlines( i_int_hlines *hlines, - int start_y, - int count_y, - int start_x, - int width_x + i_img_dim start_y, + i_img_dim count_y, + i_img_dim start_x, + i_img_dim width_x ) { - int bytes = count_y * sizeof(i_int_hline_entry *); + size_t bytes = count_y * sizeof(i_int_hline_entry *); if (bytes / count_y != sizeof(i_int_hline_entry *)) { i_fatal(3, "integer overflow calculating memory allocation\n"); @@ -107,8 +107,8 @@ Add to the list, merging with existing entries. */ void -i_int_hlines_add(i_int_hlines *hlines, int y, int x, int width) { - int x_limit = x + width; +i_int_hlines_add(i_int_hlines *hlines, i_img_dim y, i_img_dim x, i_img_dim width) { + i_img_dim x_limit = x + width; if (width < 0) { i_fatal(3, "negative width %d passed to i_int_hlines_add\n", width); @@ -132,7 +132,7 @@ i_int_hlines_add(i_int_hlines *hlines, int y, int x, int width) { if (hlines->entries[y - hlines->start_y]) { i_int_hline_entry *entry = hlines->entries[y - hlines->start_y]; - int i, found = -1; + i_img_dim i, found = -1; for (i = 0; i < entry->count; ++i) { i_int_hline_seg *seg = entry->segs + i; @@ -183,7 +183,7 @@ i_int_hlines_add(i_int_hlines *hlines, int y, int x, int width) { /* add a new segment */ if (entry->count == entry->alloc) { /* expand it */ - int alloc = entry->alloc * 3 / 2; + size_t alloc = entry->alloc * 3 / 2; entry = myrealloc(entry, sizeof(i_int_hline_entry) + sizeof(i_int_hline_seg) * (alloc - 1)); entry->alloc = alloc; @@ -218,8 +218,8 @@ Releases all memory associated with the structure. void i_int_hlines_destroy(i_int_hlines *hlines) { - int entry_count = hlines->limit_y - hlines->start_y; - int i; + size_t entry_count = hlines->limit_y - hlines->start_y; + size_t i; for (i = 0; i < entry_count; ++i) { if (hlines->entries[i]) @@ -240,7 +240,7 @@ Fill the areas given by hlines with color. void i_int_hlines_fill_color(i_img *im, i_int_hlines *hlines, const i_color *col) { - int y, i, x; + i_img_dim y, i, x; for (y = hlines->start_y; y < hlines->limit_y; ++y) { i_int_hline_entry *entry = hlines->entries[y - hlines->start_y]; @@ -264,7 +264,7 @@ i_int_hlines_fill_fill(im, hlines, fill) void i_int_hlines_fill_fill(i_img *im, i_int_hlines *hlines, i_fill_t *fill) { i_render r; - int y, i; + i_img_dim y, i; i_render_init(&r, im, im->xsize); @@ -273,7 +273,7 @@ i_int_hlines_fill_fill(i_img *im, i_int_hlines *hlines, i_fill_t *fill) { if (entry) { for (i = 0; i < entry->count; ++i) { i_int_hline_seg *seg = entry->segs + i; - int width = seg->x_limit-seg->minx; + i_img_dim width = seg->x_limit-seg->minx; i_render_fill(&r, seg->minx, y, width, NULL, fill); } @@ -293,7 +293,7 @@ i_int_hlines_fill_fill(i_img *im, i_int_hlines *hlines, i_fill_t *fill) { if (entry) { for (i = 0; i < entry->count; ++i) { i_int_hline_seg *seg = entry->segs + i; - int width = seg->x_limit-seg->minx; + i_img_dim width = seg->x_limit-seg->minx; if (fill->combine) { i_glin(im, seg->minx, seg->x_limit, y, line); @@ -324,7 +324,7 @@ i_int_hlines_fill_fill(i_img *im, i_int_hlines *hlines, i_fill_t *fill) { if (entry) { for (i = 0; i < entry->count; ++i) { i_int_hline_seg *seg = entry->segs + i; - int width = seg->x_limit-seg->minx; + i_img_dim width = seg->x_limit-seg->minx; if (fill->combinef) { i_glinf(im, seg->minx, seg->x_limit, y, line); diff --git a/image.c b/image.c index 3510bd64..abf86768 100644 --- a/image.c +++ b/image.c @@ -37,7 +37,7 @@ Some of these functions are internal. #define minmax(a,b,i) ( ((a>=i)?a: ( (b<=i)?b:i )) ) /* Hack around an obscure linker bug on solaris - probably due to builtin gcc thingies */ -static void fake(void) { ceil(1); } +void i_linker_bug_fake(void) { ceil(1); } /* =item i_img_alloc() @@ -243,7 +243,7 @@ Free image data. void i_img_exorcise(i_img *im) { - mm_log((1,"i_img_exorcise(im* 0x%x)\n",im)); + mm_log((1,"i_img_exorcise(im* %p)\n",im)); i_tags_destroy(&im->tags); if (im->i_f_destroy) (im->i_f_destroy)(im); @@ -296,11 +296,13 @@ info is an array of 4 integers with the following values: void -i_img_info(i_img *im,int *info) { - mm_log((1,"i_img_info(im 0x%x)\n",im)); +i_img_info(i_img *im, i_img_dim *info) { + mm_log((1,"i_img_info(im %p)\n",im)); if (im != NULL) { - mm_log((1,"i_img_info: xsize=%d ysize=%d channels=%d mask=%ud\n",im->xsize,im->ysize,im->channels,im->ch_mask)); - mm_log((1,"i_img_info: idata=0x%d\n",im->idata)); + mm_log((1,"i_img_info: xsize=%" i_DF " ysize=%" i_DF " channels=%d " + "mask=%ud\n", + i_DFc(im->xsize), i_DFc(im->ysize), im->channels,im->ch_mask)); + mm_log((1,"i_img_info: idata=%p\n",im->idata)); info[0] = im->xsize; info[1] = im->ysize; info[2] = im->channels; @@ -395,12 +397,14 @@ the target image. pass NULL in C for non transparent i_colors. */ void -i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,const i_color *trans) { +i_copyto_trans(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans) { i_color pv; - int x,y,t,ttx,tty,tt,ch; + i_img_dim x,y,t,ttx,tty,tt; + int ch; - mm_log((1,"i_copyto_trans(im* %p,src 0x%x, x1 %d, y1 %d, x2 %d, y2 %d, tx %d, ty %d, trans* 0x%x)\n", - im, src, x1, y1, x2, y2, tx, ty, trans)); + mm_log((1,"i_copyto_trans(im* %p,src %p, p1(" i_DFp "), p2(" i_DFp "), " + "to(" i_DFp "), trans* %p)\n", + im, src, i_DFcp(x1, y1), i_DFcp(x2, y2), i_DFcp(tx, ty), trans)); if (x2xsize, src->ysize); mm_log((1,"i_copy(src %p)\n", src)); @@ -486,10 +490,11 @@ i_copy(i_img *src) { return im; } +/* +http://en.wikipedia.org/wiki/Lanczos_resampling - - +*/ static float @@ -515,12 +520,13 @@ wither the x-axis (I == 0) or the y-axis (I == 1). */ i_img* -i_scaleaxis(i_img *im, float Value, int Axis) { - int hsize, vsize, i, j, k, l, lMax, iEnd, jEnd; - int LanczosWidthFactor; - float *l0, *l1, OldLocation; - int T; - float t; +i_scaleaxis(i_img *im, double Value, int Axis) { + i_img_dim hsize, vsize, i, j, k, l, lMax, iEnd, jEnd; + i_img_dim LanczosWidthFactor; + float *l0, *l1; + double OldLocation; + i_img_dim T; + double t; float F, PictureValue[MAXCHANNELS]; short psave; i_color val,val1,val2; @@ -532,7 +538,7 @@ i_scaleaxis(i_img *im, float Value, int Axis) { mm_log((1,"i_scaleaxis(im %p,Value %.2f,Axis %d)\n",im,Value,Axis)); if (Axis == XAXIS) { - hsize = (int)(0.5 + im->xsize * Value); + hsize = (i_img_dim)(0.5 + im->xsize * Value); if (hsize < 1) { hsize = 1; Value = 1.0 / im->xsize; @@ -543,7 +549,7 @@ i_scaleaxis(i_img *im, float Value, int Axis) { iEnd = vsize; } else { hsize = im->xsize; - vsize = (int)(0.5 + im->ysize * Value); + vsize = (i_img_dim)(0.5 + im->ysize * Value); if (vsize < 1) { vsize = 1; @@ -561,16 +567,16 @@ i_scaleaxis(i_img *im, float Value, int Axis) { } /* 1.4 is a magic number, setting it to 2 will cause rather blurred images */ - LanczosWidthFactor = (Value >= 1) ? 1 : (int) (1.4/Value); + LanczosWidthFactor = (Value >= 1) ? 1 : (i_img_dim) (1.4/Value); lMax = LanczosWidthFactor << 1; l0 = mymalloc(lMax * sizeof(float)); l1 = mymalloc(lMax * sizeof(float)); for (j=0; jchannels; k++) PictureValue[k] = 0.0; for (l=0; l= im->xsize) ? im->xsize-1 : Mx; @@ -651,8 +657,8 @@ i_scaleaxis(i_img *im, float Value, int Axis) { for (i=0; ichannels; k++) PictureValue[k] = 0.0; for (l=0; l < lMax; l++) { - int mx = T-lMax+l+1; - int Mx = T+l+1; + i_img_dim mx = T-lMax+l+1; + i_img_dim Mx = T+l+1; mx = (mx < 0) ? 0 : mx; Mx = (Mx >= im->ysize) ? im->ysize-1 : Mx; @@ -722,20 +728,20 @@ nothing is gained by doing it in two steps i_img* -i_scale_nn(i_img *im, float scx, float scy) { +i_scale_nn(i_img *im, double scx, double scy) { - int nxsize,nysize,nx,ny; + i_img_dim nxsize,nysize,nx,ny; i_img *new_img; i_color val; - mm_log((1,"i_scale_nn(im 0x%x,scx %.2f,scy %.2f)\n",im,scx,scy)); + mm_log((1,"i_scale_nn(im %p,scx %.2f,scy %.2f)\n",im,scx,scy)); - nxsize = (int) ((float) im->xsize * scx); + nxsize = (i_img_dim) ((double) im->xsize * scx); if (nxsize < 1) { nxsize = 1; scx = 1.0 / im->xsize; } - nysize = (int) ((float) im->ysize * scy); + nysize = (i_img_dim) ((double) im->ysize * scy); if (nysize < 1) { nysize = 1; scy = 1.0 / im->ysize; @@ -745,11 +751,11 @@ i_scale_nn(i_img *im, float scx, float scy) { new_img=i_img_empty_ch(NULL,nxsize,nysize,im->channels); for(ny=0;nytype == i_direct_type) { if (src->bits == 8) { return i_img_empty_ch(NULL, xsize, ysize, src->channels); @@ -810,7 +816,7 @@ For paletted images the equivalent direct type is returned. =cut */ -i_img *i_sametype_chans(i_img *src, int xsize, int ysize, int channels) { +i_img *i_sametype_chans(i_img *src, i_img_dim xsize, i_img_dim ysize, int channels) { if (src->bits == 8) { return i_img_empty_ch(NULL, xsize, ysize, channels); } @@ -848,11 +854,11 @@ The operators for this function are defined in L. i_img* i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen) { double rx,ry; - int nxsize,nysize,nx,ny; + i_img_dim nxsize,nysize,nx,ny; i_img *new_img; i_color val; - mm_log((1,"i_transform(im 0x%x, opx 0x%x, opxl %d, opy 0x%x, opyl %d, parm 0x%x, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen)); + mm_log((1,"i_transform(im %p, opx %p, opxl %d, opy %p, opyl %d, parm %p, parmlen %d)\n",im,opx,opxl,opy,opyl,parm,parmlen)); nxsize = im->xsize; nysize = im->ysize ; @@ -874,7 +880,7 @@ i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int par i_ppix(new_img,nx,ny,&val); } - mm_log((1,"(0x%x) <- i_transform\n",new_img)); + mm_log((1,"(%p) <- i_transform\n",new_img)); return new_img; } @@ -893,17 +899,19 @@ can return zero. float i_img_diff(i_img *im1,i_img *im2) { - int x,y,ch,xb,yb,chb; + i_img_dim x, y, xb, yb; + int ch, chb; float tdiff; i_color val1,val2; - mm_log((1,"i_img_diff(im1 0x%x,im2 0x%x)\n",im1,im2)); + mm_log((1,"i_img_diff(im1 %p,im2 %p)\n",im1,im2)); xb=(im1->xsizexsize)?im1->xsize:im2->xsize; yb=(im1->ysizeysize)?im1->ysize:im2->ysize; chb=(im1->channelschannels)?im1->channels:im2->channels; - mm_log((1,"i_img_diff: xb=%d xy=%d chb=%d\n",xb,yb,chb)); + mm_log((1,"i_img_diff: b=(" i_DFp ") chb=%d\n", + i_DFcp(xb,yb), chb)); tdiff=0; for(y=0;yxsizexsize)?im1->xsize:im2->xsize; yb=(im1->ysizeysize)?im1->ysize:im2->ysize; chb=(im1->channelschannels)?im1->channels:im2->channels; - mm_log((1,"i_img_diffd: xb=%d xy=%d chb=%d\n",xb,yb,chb)); + mm_log((1,"i_img_diffd: b(" i_DFp ") chb=%d\n", + i_DFcp(xb, yb), chb)); tdiff=0; for(y=0;yxsizexsize)?im1->xsize:im2->xsize; yb=(im1->ysizeysize)?im1->ysize:im2->ysize; chb=(im1->channelschannels)?im1->channels:im2->channels; - mm_log((1,"i_img_samef: xb=%d xy=%d chb=%d\n",xb,yb,chb)); + mm_log((1,"i_img_samef: b(" i_DFp ") chb=%d\n", + i_DFcp(xb, yb), chb)); for(y = 0; y < yb; y++) { for(x = 0; x < xb; x++) { @@ -984,7 +996,8 @@ i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) { for(ch = 0; ch < chb; ch++) { double sdiff = val1.channel[ch] - val2.channel[ch]; if (fabs(sdiff) > epsilon) { - mm_log((1,"i_img_samef <- different %g @(%d,%d)\n", sdiff, x, y)); + mm_log((1,"i_img_samef <- different %g @(" i_DFp ")\n", + sdiff, i_DFcp(x, y))); return 0; } } @@ -999,9 +1012,9 @@ i_img_samef(i_img *im1,i_img *im2, double epsilon, char const *what) { i_img* i_haar(i_img *im) { - int mx,my; - int fx,fy; - int x,y; + i_img_dim mx,my; + i_img_dim fx,fy; + i_img_dim x,y; int ch,c; i_img *new_img,*new_img2; i_color val1,val2,dval1,dval2; @@ -1057,13 +1070,13 @@ to indicate that it was more than max colors int i_count_colors(i_img *im,int maxc) { struct octt *ct; - int x,y; + i_img_dim x,y; int colorcnt; int channels[3]; int *samp_chans; i_sample_t * samp; - int xsize = im->xsize; - int ysize = im->ysize; + i_img_dim xsize = im->xsize; + i_img_dim ysize = im->ysize; int samp_cnt = 3 * xsize; if (im->channels >= 3) { @@ -1146,15 +1159,15 @@ hpsort(unsigned int n, unsigned *ra) { int i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc) { struct octt *ct; - int x,y; + i_img_dim x,y; int colorcnt; unsigned int *col_usage_it; i_sample_t * samp; int channels[3]; int *samp_chans; - int xsize = im->xsize; - int ysize = im->ysize; + i_img_dim xsize = im->xsize; + i_img_dim ysize = im->ysize; int samp_cnt = 3 * xsize; ct = octt_new(); @@ -1199,12 +1212,12 @@ i_sample_t versions. =over -=item i_ppixf_fp(i_img *im, int x, int y, i_fcolor *pix) +=item i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) =cut */ -int i_ppixf_fp(i_img *im, int x, int y, const i_fcolor *pix) { +int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) { i_color temp; int ch; @@ -1215,11 +1228,11 @@ int i_ppixf_fp(i_img *im, int x, int y, const i_fcolor *pix) { } /* -=item i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) +=item i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) =cut */ -int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) { +int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) { i_color temp; int ch; @@ -1233,19 +1246,21 @@ int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix) { } /* -=item i_plinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) +=item i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) =cut */ -int i_plinf_fp(i_img *im, int l, int r, int y, const i_fcolor *pix) { +i_img_dim +i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix) { i_color *work; if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; if (r > l) { - int ret; - int i, ch; + i_img_dim ret; + i_img_dim i; + int ch; work = mymalloc(sizeof(i_color) * (r-l)); for (i = 0; i < r-l; ++i) { for (ch = 0; ch < im->channels; ++ch) @@ -1266,19 +1281,21 @@ int i_plinf_fp(i_img *im, int l, int r, int y, const i_fcolor *pix) { } /* -=item i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) +=item i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) =cut */ -int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) { +i_img_dim +i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix) { i_color *work; if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; if (r > l) { - int ret; - int i, ch; + i_img_dim ret; + i_img_dim i; + int ch; work = mymalloc(sizeof(i_color) * (r-l)); ret = i_plin(im, l, r, y, work); for (i = 0; i < r-l; ++i) { @@ -1299,11 +1316,13 @@ int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix) { } /* -=item i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, int *chans, int chan_count) +=item i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int *chans, int chan_count) =cut */ -int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, + +i_img_dim +i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int const *chans, int chan_count) { i_sample_t *work; @@ -1311,8 +1330,8 @@ int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, if (r > im->xsize) r = im->xsize; if (r > l) { - int ret; - int i; + i_img_dim ret; + i_img_dim i; work = mymalloc(sizeof(i_sample_t) * (r-l)); ret = i_gsamp(im, l, r, y, work, chans, chan_count); for (i = 0; i < ret; ++i) { @@ -1407,8 +1426,8 @@ int i_findcolor_forward(i_img *im, const i_color *color, i_palidx *entry) { =cut */ -int -i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps, +i_img_dim +i_gsamp_bits_fb(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps, const int *chans, int chan_count, int bits) { if (bits < 1 || bits > 32) { i_push_error(0, "Invalid bits, must be 1..32"); @@ -1417,7 +1436,8 @@ i_gsamp_bits_fb(i_img *im, int l, int r, int y, unsigned *samps, if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { double scale; - int ch, count, i, w; + int ch; + i_img_dim count, i, w; if (bits == 32) scale = 4294967295.0; @@ -1937,7 +1957,7 @@ i_get_file_backgroundf(i_img *im, i_fcolor *fbg) { Arnar M. Hrafnkelsson -Tony Cook +Tony Cook =head1 SEE ALSO diff --git a/imager.h b/imager.h index 1c25aa46..62451c78 100644 --- a/imager.h +++ b/imager.h @@ -48,23 +48,23 @@ extern void i_hsv_to_rgbf(i_fcolor *color); extern void i_rgb_to_hsv(i_color *color); extern void i_hsv_to_rgb(i_color *color); -i_img *IIM_new(int x,int y,int ch); +i_img *IIM_new(i_img_dim x,i_img_dim y,int ch); #define i_img_8_new IIM_new void IIM_DESTROY(i_img *im); i_img *i_img_new( void ); -i_img *i_img_empty(i_img *im,int x,int y); -i_img *i_img_empty_ch(i_img *im,int x,int y,int ch); +i_img *i_img_empty(i_img *im,i_img_dim x,i_img_dim y); +i_img *i_img_empty_ch(i_img *im,i_img_dim x,i_img_dim y,int ch); void i_img_exorcise(i_img *im); void i_img_destroy(i_img *im); i_img *i_img_alloc(void); void i_img_init(i_img *im); -void i_img_info(i_img *im,int *info); +void i_img_info(i_img *im,i_img_dim *info); -extern i_img *i_sametype(i_img *im, int xsize, int ysize); -extern i_img *i_sametype_chans(i_img *im, int xsize, int ysize, int channels); +extern i_img *i_sametype(i_img *im, i_img_dim xsize, i_img_dim ysize); +extern i_img *i_sametype_chans(i_img *im, i_img_dim xsize, i_img_dim ysize, int channels); -i_img *i_img_pal_new(int x, int y, int ch, int maxpal); +i_img *i_img_pal_new(i_img_dim x, i_img_dim y, int ch, int maxpal); /* Image feature settings */ @@ -76,26 +76,26 @@ i_img_dim i_img_get_height(i_img *im); /* Base functions */ -extern int i_ppix(i_img *im,int x,int y, const i_color *val); -extern int i_gpix(i_img *im,int x,int y,i_color *val); -extern int i_ppixf(i_img *im,int x,int y, const i_fcolor *val); -extern int i_gpixf(i_img *im,int x,int y,i_fcolor *val); +extern int i_ppix(i_img *im,i_img_dim x,i_img_dim y, const i_color *val); +extern int i_gpix(i_img *im,i_img_dim x,i_img_dim y,i_color *val); +extern int i_ppixf(i_img *im,i_img_dim x,i_img_dim y, const i_fcolor *val); +extern int i_gpixf(i_img *im,i_img_dim x,i_img_dim y,i_fcolor *val); #define i_ppix(im, x, y, val) (((im)->i_f_ppix)((im), (x), (y), (val))) #define i_gpix(im, x, y, val) (((im)->i_f_gpix)((im), (x), (y), (val))) #define i_ppixf(im, x, y, val) (((im)->i_f_ppixf)((im), (x), (y), (val))) #define i_gpixf(im, x, y, val) (((im)->i_f_gpixf)((im), (x), (y), (val))) -extern int i_plin(i_img *im, int l, int r, int y, const i_color *vals); -extern int i_glin(i_img *im, int l, int r, int y, i_color *vals); -extern int i_plinf(i_img *im, int l, int r, int y, const i_fcolor *vals); -extern int i_glinf(i_img *im, int l, int r, int y, i_fcolor *vals); -extern int i_gsamp(i_img *im, int l, int r, int y, i_sample_t *samp, +extern i_img_dim i_plin(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals); +extern i_img_dim i_glin(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals); +extern i_img_dim i_plinf(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals); +extern i_img_dim i_glinf(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals); +extern i_img_dim i_gsamp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samp, const int *chans, int chan_count); -extern int i_gsampf(i_img *im, int l, int r, int y, i_fsample_t *samp, +extern i_img_dim i_gsampf(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, const int *chans, int chan_count); -extern int i_gpal(i_img *im, int x, int r, int y, i_palidx *vals); -extern int i_ppal(i_img *im, int x, int r, int y, const i_palidx *vals); +extern i_img_dim i_gpal(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_palidx *vals); +extern i_img_dim i_ppal(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_palidx *vals); extern int i_addcolors(i_img *im, const i_color *colors, int count); extern int i_getcolors(i_img *im, int i, i_color *, int count); extern int i_colorcount(i_img *im); @@ -149,47 +149,47 @@ extern i_fill_t *i_new_fill_solidf(const i_fcolor *c, int combine); extern i_fill_t *i_new_fill_solid(const i_color *c, int combine); extern 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); extern 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); extern 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); extern i_fill_t *i_new_fill_opacity(i_fill_t *, double alpha_mult); extern void i_fill_destroy(i_fill_t *fill); -float i_gpix_pch(i_img *im,int x,int y,int ch); +float i_gpix_pch(i_img *im,i_img_dim x,i_img_dim y,int ch); /* functions for drawing primitives */ -void i_box (i_img *im,int x1,int y1,int x2,int y2,const i_color *val); -void i_box_filled (i_img *im,int x1,int y1,int x2,int y2,const i_color *val); -int i_box_filledf (i_img *im,int x1,int y1,int x2,int y2,const i_fcolor *val); -void i_box_cfill(i_img *im, int x1, int y1, int x2, int y2, i_fill_t *fill); -void i_line (i_img *im,int x1,int y1,int x2,int y2,const i_color *val, int endp); -void i_line_aa (i_img *im,int x1,int y1,int x2,int y2,const i_color *val, int endp); -void i_arc (i_img *im,int x,int y,float rad,float d1,float d2,const i_color *val); -int i_arc_out(i_img *im,i_img_dim x,i_img_dim y,i_img_dim rad,float d1,float d2,const i_color *val); -int i_arc_out_aa(i_img *im,i_img_dim x,i_img_dim y,i_img_dim rad,float d1,float d2,const i_color *val); +void 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); +void 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); +int 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); +void 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); +void 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); +void 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); +void i_arc (i_img *im,i_img_dim x,i_img_dim y,double rad,double d1,double d2,const i_color *val); +int i_arc_out(i_img *im,i_img_dim x,i_img_dim y,i_img_dim rad,double d1,double d2,const i_color *val); +int i_arc_out_aa(i_img *im,i_img_dim x,i_img_dim y,i_img_dim rad,double d1,double d2,const i_color *val); void i_arc_aa (i_img *im, double x, double y, double rad, double d1, double d2, const i_color *val); -void i_arc_cfill(i_img *im,int x,int y,float rad,float d1,float d2,i_fill_t *fill); +void i_arc_cfill(i_img *im,i_img_dim x,i_img_dim y,double rad,double d1,double d2,i_fill_t *fill); void i_arc_aa_cfill(i_img *im,double x,double y,double rad,double d1,double d2,i_fill_t *fill); -void i_circle_aa (i_img *im,float x, float y,float rad,const i_color *val); +void i_circle_aa (i_img *im,double x, double y,double rad,const i_color *val); int i_circle_out (i_img *im,i_img_dim x, i_img_dim y, i_img_dim rad,const i_color *val); int i_circle_out_aa (i_img *im,i_img_dim x, i_img_dim y, i_img_dim rad,const i_color *val); -void i_copyto (i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty); -void i_copyto_trans(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,const i_color *trans); +void i_copyto (i_img *im,i_img *src,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(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans); i_img* i_copy (i_img *src); -int i_rubthru (i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny, int src_maxx, int src_maxy); +int i_rubthru (i_img *im, i_img *src, 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); extern 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); extern 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, int combine, double opacity); + 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); extern i_img * i_combine(i_img **src, const int *channels, int in_count); @@ -198,17 +198,17 @@ undef_int i_flipxy (i_img *im, int direction); extern i_img *i_rotate90(i_img *im, int degrees); extern i_img *i_rotate_exact(i_img *im, double amount); extern i_img *i_rotate_exact_bg(i_img *im, double amount, const i_color *backp, const i_fcolor *fbackp); -extern i_img *i_matrix_transform(i_img *im, int xsize, int ysize, const double *matrix); -extern i_img *i_matrix_transform_bg(i_img *im, int xsize, int ysize, const double *matrix, const i_color *backp, const i_fcolor *fbackp); +extern i_img *i_matrix_transform(i_img *im, i_img_dim xsize, i_img_dim ysize, const double *matrix); +extern i_img *i_matrix_transform_bg(i_img *im, i_img_dim xsize, i_img_dim ysize, const double *matrix, const i_color *backp, const i_fcolor *fbackp); void i_bezier_multi(i_img *im,int l,const double *x,const double *y,const i_color *val); int i_poly_aa (i_img *im,int l,const double *x,const double *y,const i_color *val); int i_poly_aa_cfill(i_img *im,int l,const double *x,const double *y,i_fill_t *fill); -undef_int i_flood_fill (i_img *im,int seedx,int seedy, const i_color *dcol); -undef_int i_flood_cfill(i_img *im, int seedx, int seedy, i_fill_t *fill); -undef_int i_flood_fill_border (i_img *im,int seedx,int seedy, const i_color *dcol, const i_color *border); -undef_int i_flood_cfill_border(i_img *im, int seedx, int seedy, i_fill_t *fill, const i_color *border); +undef_int i_flood_fill (i_img *im,i_img_dim seedx,i_img_dim seedy, const i_color *dcol); +undef_int i_flood_cfill(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill); +undef_int i_flood_fill_border (i_img *im,i_img_dim seedx,i_img_dim seedy, const i_color *dcol, const i_color *border); +undef_int i_flood_cfill_border(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill, const i_color *border); /* image processing functions */ @@ -229,35 +229,19 @@ int i_img_samef(i_img *im1,i_img *im2, double epsilon, const char *what); undef_int i_init_fonts( int t1log ); -#ifdef HAVE_LIBT1 - -undef_int i_init_t1( int t1log ); -int i_t1_new( char *pfb, char *afm ); -int i_t1_destroy( int font_id ); -undef_int i_t1_cp( i_img *im, int xb, int yb, int channel, int fontnum, float points, char* str, size_t len, int align, int utf8, char const *flags ); -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 ); -int i_t1_bbox( int fontnum, float point, const char *str, size_t len, int cords[6], int utf8, char const *flags ); -void i_t1_set_aa( int st ); -void close_t1( void ); -int i_t1_has_chars(int font_num, char const *text, size_t len, int utf8, char *out); -extern int i_t1_face_name(int font_num, char *name_buf, size_t name_buf_size); -extern int i_t1_glyph_name(int font_num, unsigned long ch, char *name_buf, - size_t name_buf_size); -#endif - #ifdef HAVE_LIBTT undef_int i_init_tt( void ); TT_Fonthandle* i_tt_new(const char *fontname); void i_tt_destroy( TT_Fonthandle *handle ); -undef_int i_tt_cp( TT_Fonthandle *handle,i_img *im,int xb,int yb,int channel,float points,char const* txt,size_t len,int smooth, int utf8, int align); -undef_int i_tt_text( TT_Fonthandle *handle, i_img *im, int xb, int yb, const i_color *cl, float points, char const* txt, size_t len, int smooth, int utf8, int align); -undef_int i_tt_bbox( TT_Fonthandle *handle, float points,const char *txt,size_t len,int cords[6], int utf8); -int i_tt_has_chars(TT_Fonthandle *handle, char const *text, size_t len, int utf8, char *out); +undef_int i_tt_cp( TT_Fonthandle *handle,i_img *im,i_img_dim xb,i_img_dim yb,int channel,double points,char const* txt,size_t len,int smooth, int utf8, int align); +undef_int i_tt_text( TT_Fonthandle *handle, i_img *im, i_img_dim xb, i_img_dim yb, const i_color *cl, double points, char const* txt, size_t len, int smooth, int utf8, int align); +undef_int i_tt_bbox( TT_Fonthandle *handle, double points,const char *txt,size_t len,i_img_dim cords[6], int utf8); +size_t i_tt_has_chars(TT_Fonthandle *handle, char const *text, size_t len, int utf8, char *out); void i_tt_dump_names(TT_Fonthandle *handle); -int i_tt_face_name(TT_Fonthandle *handle, char *name_buf, +size_t i_tt_face_name(TT_Fonthandle *handle, char *name_buf, size_t name_buf_size); -int i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf, +size_t i_tt_glyph_name(TT_Fonthandle *handle, unsigned long ch, char *name_buf, size_t name_buf_size); #endif /* End of freetype headers */ @@ -318,14 +302,14 @@ extern void i_quant_makemap(i_quantize *quant, i_img **imgs, int count); extern i_palidx *i_quant_translate(i_quantize *quant, i_img *img); extern void i_quant_transparent(i_quantize *quant, i_palidx *indices, i_img *img, i_palidx trans_index); -extern i_img *i_img_pal_new(int x, int y, int channels, int maxpal); +extern i_img *i_img_pal_new(i_img_dim x, i_img_dim y, int channels, int maxpal); extern i_img *i_img_to_pal(i_img *src, i_quantize *quant); extern i_img *i_img_to_rgb(i_img *src); -extern i_img *i_img_masked_new(i_img *targ, i_img *mask, int x, int y, - int w, int h); -extern i_img *i_img_16_new(int x, int y, int ch); +extern i_img *i_img_masked_new(i_img *targ, i_img *mask, i_img_dim x, i_img_dim y, + i_img_dim w, i_img_dim h); +extern i_img *i_img_16_new(i_img_dim x, i_img_dim y, int ch); extern i_img *i_img_to_rgb16(i_img *im); -extern i_img *i_img_double_new(int x, int y, int ch); +extern i_img *i_img_double_new(i_img_dim x, i_img_dim y, int ch); extern i_img *i_img_to_drgb(i_img *im); extern int i_img_is_monochrome(i_img *im, int *zero_is_white); @@ -335,13 +319,7 @@ extern void i_get_file_backgroundf(i_img *im, i_fcolor *bg); const char * i_test_format_probe(io_glue *data, int length); -#ifdef HAVE_LIBJPEG -i_img * -i_readjpeg_wiol(io_glue *ig, int length, char** iptc_itext, int *itlength); -undef_int i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor); -#endif /* HAVE_LIBJPEG */ - -i_img * i_readraw_wiol(io_glue *ig, int x, int y, int datachannels, int storechannels, int intrl); +i_img * i_readraw_wiol(io_glue *ig, i_img_dim x, i_img_dim y, int datachannels, int storechannels, int intrl); undef_int i_writeraw_wiol(i_img* im, io_glue *ig); i_img * i_readpnm_wiol(io_glue *ig, int allow_incomplete); @@ -359,17 +337,17 @@ undef_int i_writetga_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, i_img * i_readrgb_wiol(io_glue *ig, int length); undef_int i_writergb_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen); -i_img * i_scaleaxis(i_img *im, float Value, int Axis); -i_img * i_scale_nn(i_img *im, float scx, float scy); -i_img * i_scale_mixing(i_img *src, int width, int height); +i_img * i_scaleaxis(i_img *im, double Value, int Axis); +i_img * i_scale_nn(i_img *im, double scx, double scy); +i_img * i_scale_mixing(i_img *src, i_img_dim width, i_img_dim height); i_img * i_haar(i_img *im); int i_count_colors(i_img *im,int maxc); int i_get_anonymous_color_histo(i_img *im, unsigned int **col_usage, int maxc); -i_img * i_transform(i_img *im, int *opx,int opxl,int *opy,int opyl,double parm[],int parmlen); +i_img * i_transform(i_img *im, int *opx, int opxl, int *opy,int opyl,double parm[],int parmlen); struct rm_op; -i_img * i_transform2(int width, int height, int channels, +i_img * i_transform2(i_img_dim width, i_img_dim height, int channels, struct rm_op *ops, int ops_count, double *n_regs, int n_regs_count, i_color *c_regs, int c_regs_count, @@ -381,17 +359,17 @@ void i_contrast(i_img *im, float intensity); void i_hardinvert(i_img *im); void i_hardinvertall(i_img *im); void i_noise(i_img *im, float amount, unsigned char type); -void i_bumpmap(i_img *im,i_img *bump,int channel,int light_x,int light_y,int strength); -void i_bumpmap_complex(i_img *im, i_img *bump, int channel, int tx, int ty, float Lx, float Ly, - float Lz, float cd, float cs, float n, i_color *Ia, i_color *Il, i_color *Is); +void i_bumpmap(i_img *im,i_img *bump,int channel,i_img_dim light_x,i_img_dim light_y,i_img_dim strength); +void i_bumpmap_complex(i_img *im, i_img *bump, int channel, i_img_dim tx, i_img_dim ty, double Lx, double Ly, + double Lz, float cd, float cs, float n, i_color *Ia, i_color *Il, i_color *Is); void i_postlevels(i_img *im,int levels); -void i_mosaic(i_img *im,int size); -void i_watermark(i_img *im,i_img *wmark,int tx,int ty,int pixdiff); +void i_mosaic(i_img *im,i_img_dim size); +void i_watermark(i_img *im,i_img *wmark,i_img_dim tx,i_img_dim ty,int pixdiff); void i_autolevels(i_img *im,float lsat,float usat,float skew); -void i_radnoise(i_img *im,int xo,int yo,float rscale,float ascale); -void i_turbnoise(i_img *im,float xo,float yo,float scale); -void i_gradgen(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure); -int i_nearest_color(i_img *im, int num, int *xo, int *yo, i_color *ival, int dmeasure); +void i_radnoise(i_img *im,i_img_dim xo,i_img_dim yo,double rscale,double ascale); +void i_turbnoise(i_img *im,double xo,double yo,double scale); +void i_gradgen(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *ival, int dmeasure); +int i_nearest_color(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *ival, int dmeasure); i_img *i_diff_image(i_img *im, i_img *im2, double mindist); int i_fountain(i_img *im, double xa, double ya, double xb, double yb, @@ -416,25 +394,25 @@ typedef struct { void (*ICL_info)(const i_color *cl); i_img*(*i_img_new)( void ); - i_img*(*i_img_empty)(i_img *im,int x,int y); - i_img*(*i_img_empty_ch)(i_img *im,int x,int y,int ch); + i_img*(*i_img_empty)(i_img *im,i_img_dim x,i_img_dim y); + i_img*(*i_img_empty_ch)(i_img *im,i_img_dim x,i_img_dim y,int ch); void(*i_img_exorcise)(i_img *im); - void(*i_img_info)(i_img *im,int *info); + void(*i_img_info)(i_img *im,i_img_dim *info); void(*i_img_setmask)(i_img *im,int ch_mask); int (*i_img_getmask)(i_img *im); /* - int (*i_ppix)(i_img *im,int x,int y,i_color *val); - int (*i_gpix)(i_img *im,int x,int y,i_color *val); + int (*i_ppix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val); + int (*i_gpix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val); */ - void(*i_box)(i_img *im,int x1,int y1,int x2,int y2,const i_color *val); - void(*i_line)(i_img *im,int x1,int y1,int x2,int y2,const i_color *val,int endp); - void(*i_arc)(i_img *im,int x,int y,float rad,float d1,float d2,const i_color *val); - void(*i_copyto)(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty); - void(*i_copyto_trans)(i_img *im,i_img *src,int x1,int y1,int x2,int y2,int tx,int ty,const i_color *trans); - int(*i_rubthru)(i_img *im,i_img *src,int tx,int ty, int src_minx, int src_miny, int src_maxx, int src_maxy); + void(*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); + void(*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); + void(*i_arc)(i_img *im,i_img_dim x,i_img_dim y,double rad,double d1,double d2,const i_color *val); + void(*i_copyto)(i_img *im,i_img *src,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)(i_img *im,i_img *src,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,i_img_dim tx,i_img_dim ty,const i_color *trans); + int(*i_rubthru)(i_img *im,i_img *src,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); } symbol_table_t; @@ -475,14 +453,14 @@ extern void i_tags_print(i_img_tags *tags); /* image file limits */ extern int -i_set_image_file_limits(int width, int height, int bytes); +i_set_image_file_limits(i_img_dim width, i_img_dim height, size_t bytes); extern int -i_get_image_file_limits(int *width, int *height, int *bytes); +i_get_image_file_limits(i_img_dim *width, i_img_dim *height, size_t *bytes); extern int -i_int_check_image_file_limits(int width, int height, int channels, int sample_size); +i_int_check_image_file_limits(i_img_dim width, i_img_dim height, int channels, size_t sample_size); /* memory allocation */ -void* mymalloc(int size); +void* mymalloc(size_t size); void myfree(void *p); void* myrealloc(void *p, size_t newsize); void* mymalloc_file_line (size_t size, char* file, int line); @@ -496,12 +474,10 @@ void* myrealloc_file_line(void *p, size_t newsize, char* file,int line); #define myfree(x) (myfree_file_line((x), __FILE__, __LINE__)) void malloc_state (void); -void* mymalloc_comm (int size, char *comm); void bndcheck_all (void); #else -#define malloc_comm(a,b) (mymalloc(a)) void malloc_state(void); #endif /* IMAGER_MALLOC_DEBUG */ @@ -524,11 +500,13 @@ i_adapt_fcolors_bg(int dest_channels, int src_channels, i_fcolor *colors, size_t count, i_fcolor const *bg); extern int -i_gsamp_bg(i_img *im, int l, int r, int y, i_sample_t *samples, +i_gsamp_bg(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samples, int out_channels, i_color const *bg); extern int -i_gsampf_bg(i_img *im, int l, int r, int y, i_fsample_t *samples, +i_gsampf_bg(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samples, int out_channels, i_fcolor const *bg); +#include "imio.h" + #endif diff --git a/imageri.h b/imageri.h index 9037ff5b..08fdd195 100644 --- a/imageri.h +++ b/imageri.h @@ -10,11 +10,11 @@ /* wrapper functions that implement the floating point sample version of a function in terms of the 8-bit sample version */ -extern int i_ppixf_fp(i_img *im, int x, int y, const i_fcolor *pix); -extern int i_gpixf_fp(i_img *im, int x, int y, i_fcolor *pix); -extern int i_plinf_fp(i_img *im, int l, int r, int y, const i_fcolor *pix); -extern int i_glinf_fp(i_img *im, int l, int r, int y, i_fcolor *pix); -extern int i_gsampf_fp(i_img *im, int l, int r, int y, i_fsample_t *samp, +extern int i_ppixf_fp(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix); +extern int i_gpixf_fp(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix); +extern i_img_dim i_plinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *pix); +extern i_img_dim i_glinf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *pix); +extern i_img_dim i_gsampf_fp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int const *chans, int chan_count); /* wrapper functions that forward palette calls to the underlying image, @@ -31,7 +31,7 @@ extern int i_setcolors_forward(i_img *im, int index, const i_color *colors, int count); /* fallback handler for gsamp_bits */ -extern int i_gsamp_bits_fb(i_img *im, int x, int r, int y, unsigned *samp, +extern i_img_dim i_gsamp_bits_fb(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, unsigned *samp, const int *chans, int chan_count, int bits); #define SampleFTo16(num) ((int)((num) * 65535.0 + 0.01)) @@ -63,32 +63,32 @@ extern UTIL_table_t i_UTIL_table; #define I_ALL_CHANNELS_WRITABLE(im) (((im)->ch_mask & 0xF) == 0xf) typedef struct i_int_hline_seg_tag { - int minx, x_limit; + i_img_dim minx, x_limit; } i_int_hline_seg; typedef struct i_int_hline_entry_tag { - int count; - int alloc; + i_img_dim count; + size_t alloc; i_int_hline_seg segs[1]; } i_int_hline_entry; /* represents a set of horizontal line segments to be filled in later */ typedef struct i_int_hlines_tag { - int start_y, limit_y; - int start_x, limit_x; + i_img_dim start_y, limit_y; + i_img_dim start_x, limit_x; i_int_hline_entry **entries; } i_int_hlines; extern void i_int_init_hlines( i_int_hlines *hlines, - int start_y, - int count_y, - int start_x, - int width_x + i_img_dim start_y, + i_img_dim count_y, + i_img_dim start_x, + i_img_dim width_x ); extern void i_int_init_hlines_img(i_int_hlines *hlines, i_img *img); -extern void i_int_hlines_add(i_int_hlines *hlines, int y, int minx, int width); +extern void i_int_hlines_add(i_int_hlines *hlines, i_img_dim y, i_img_dim minx, i_img_dim width); extern void i_int_hlines_destroy(i_int_hlines *hlines); extern void i_int_hlines_fill_color(i_img *im, i_int_hlines *hlines, const i_color *val); @@ -110,6 +110,7 @@ extern void im_assert_fail(char const *, int, char const *); i_img_dim i_minx(i_img_dim a, i_img_dim b); i_img_dim i_maxx(i_img_dim x, i_img_dim y); +i_img_dim i_abs(i_img_dim x); #define i_min(a, b) i_minx((a), (b)) #define i_max(a, b) i_maxx((a), (b)) diff --git a/imdatatypes.h b/imdatatypes.h index 7866d7b2..d760d4ba 100644 --- a/imdatatypes.h +++ b/imdatatypes.h @@ -3,7 +3,6 @@ #include #include "imconfig.h" -#include "imio.h" #define MAXCHANNELS 4 @@ -23,6 +22,21 @@ typedef struct { i_sample_t c,m,y,k; } cmyk_color; typedef int undef_int; /* special value to put in typemaps to retun undef on 0 and 1 on 1 */ +/* +=item i_img_dim +=category Data Types +=synopsis i_img_dim x, y; +=order 90 + +A signed integer type that represents an image dimension or ordinate. + +May be larger than int on some platforms. + +=cut +*/ + +typedef ptrdiff_t i_img_dim; + /* =item i_color =category Data Types @@ -131,22 +145,22 @@ typedef struct { } i_img_tags; typedef struct i_img_ i_img; -typedef int (*i_f_ppix_t)(i_img *im, int x, int y, const i_color *pix); -typedef int (*i_f_ppixf_t)(i_img *im, int x, int y, const i_fcolor *pix); -typedef int (*i_f_plin_t)(i_img *im, int x, int r, int y, const i_color *vals); -typedef int (*i_f_plinf_t)(i_img *im, int x, int r, int y, const i_fcolor *vals); -typedef int (*i_f_gpix_t)(i_img *im, int x, int y, i_color *pix); -typedef int (*i_f_gpixf_t)(i_img *im, int x, int y, i_fcolor *pix); -typedef int (*i_f_glin_t)(i_img *im, int x, int r, int y, i_color *vals); -typedef int (*i_f_glinf_t)(i_img *im, int x, int r, int y, i_fcolor *vals); - -typedef int (*i_f_gsamp_t)(i_img *im, int x, int r, int y, i_sample_t *samp, +typedef int (*i_f_ppix_t)(i_img *im, i_img_dim x, i_img_dim y, const i_color *pix); +typedef int (*i_f_ppixf_t)(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix); +typedef i_img_dim (*i_f_plin_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_color *vals); +typedef i_img_dim (*i_f_plinf_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_fcolor *vals); +typedef int (*i_f_gpix_t)(i_img *im, i_img_dim x, i_img_dim y, i_color *pix); +typedef int (*i_f_gpixf_t)(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix); +typedef i_img_dim (*i_f_glin_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_color *vals); +typedef i_img_dim (*i_f_glinf_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_fcolor *vals); + +typedef i_img_dim (*i_f_gsamp_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_sample_t *samp, const int *chans, int chan_count); -typedef int (*i_f_gsampf_t)(i_img *im, int x, int r, int y, i_fsample_t *samp, +typedef i_img_dim (*i_f_gsampf_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_fsample_t *samp, const int *chan, int chan_count); -typedef int (*i_f_gpal_t)(i_img *im, int x, int r, int y, i_palidx *vals); -typedef int (*i_f_ppal_t)(i_img *im, int x, int r, int y, const i_palidx *vals); +typedef i_img_dim (*i_f_gpal_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_palidx *vals); +typedef i_img_dim (*i_f_ppal_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_palidx *vals); typedef int (*i_f_addcolors_t)(i_img *im, const i_color *colors, int count); typedef int (*i_f_getcolors_t)(i_img *im, int i, i_color *, int count); typedef int (*i_f_colorcount_t)(i_img *im); @@ -157,26 +171,11 @@ typedef int (*i_f_setcolors_t)(i_img *im, int index, const i_color *colors, typedef void (*i_f_destroy_t)(i_img *im); -typedef int (*i_f_gsamp_bits_t)(i_img *im, int x, int r, int y, unsigned *samp, +typedef i_img_dim (*i_f_gsamp_bits_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, unsigned *samp, const int *chans, int chan_count, int bits); -typedef int (*i_f_psamp_bits_t)(i_img *im, int x, int r, int y, unsigned const *samp, +typedef i_img_dim (*i_f_psamp_bits_t)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, unsigned const *samp, const int *chans, int chan_count, int bits); -/* -=item i_img_dim -=category Data Types -=synopsis i_img_dim x; -=order 90 - -A signed integer type that represents an image dimension or ordinate. - -May be larger than int on some platforms. - -=cut -*/ - -typedef int i_img_dim; - /* =item i_img =category Data Types @@ -342,14 +341,14 @@ typedef struct { /* bitmap mask */ struct i_bitmap { - int xsize,ysize; + i_img_dim xsize,ysize; char *data; }; -struct i_bitmap* btm_new(int xsize,int ysize); +struct i_bitmap* btm_new(i_img_dim xsize,i_img_dim ysize); void btm_destroy(struct i_bitmap *btm); -int btm_test(struct i_bitmap *btm,int x,int y); -void btm_set(struct i_bitmap *btm,int x,int y); +int btm_test(struct i_bitmap *btm,i_img_dim x,i_img_dim y); +void btm_set(struct i_bitmap *btm,i_img_dim x,i_img_dim y); /* Stack/Linked list */ @@ -363,21 +362,16 @@ struct llink { struct llist { struct llink *h,*t; int multip; /* # of copies in a single chain */ - int ssize; /* size of each small element */ + size_t ssize; /* size of each small element */ int count; /* number of elements on the list */ }; -/* Links */ - -struct llink *llink_new( struct llink* p,int size ); -int llist_llink_push( struct llist *lst, struct llink *lnk, void *data ); - /* Lists */ -struct llist *llist_new( int multip, int ssize ); +struct llist *llist_new( int multip, size_t ssize ); void llist_destroy( struct llist *l ); -void llist_push( struct llist *l, void *data ); +void llist_push( struct llist *l, const void *data ); void llist_dump( struct llist *l ); int llist_pop( struct llist *l,void *data ); @@ -711,5 +705,57 @@ enum { typedef struct i_render_tag i_render; +#ifdef IMAGER_FORMAT_ATTR +#define I_FORMAT_ATTR(format_index, va_index) \ + __attribute ((format (printf, format_index, va_index))) +#else +#define I_FORMAT_ATTR(format_index, va_index) +#endif + +/* +=item i_DF +=category Data Types +=synopsis printf("left %" i_DF "\n", i_DFc(x)); +=order 95 + +This is a constant string that can be used with functions like +printf() to format i_img_dim values after they're been cast with i_DFc(). + +Does not include the leading C<%>. + +=cut + +=item i_DFc +=category Data Types +=order 95 + +Cast an C value to a type for use with the i_DF format +string. + +=cut + +=item i_DFp +=category Data Types +=synopsis printf("point (" i_DFp ")\n", i_DFcp(x, y)); +=order 95 + +Format a pair of C values. This format string I +include the leading C<%>. + +=cut + +=item i_DFcp +=category Data Types +=order 95 + +Casts two C values for use with the i_DF (or i_DFp) format. + +=cut + */ + +#define i_DFc(x) ((i_dim_format_t)(x)) +#define i_DFcp(x, y) i_DFc(x), i_DFc(y) +#define i_DFp "%" i_DF ", %" i_DF + #endif diff --git a/imerror.h b/imerror.h index 313834f4..da56df1f 100644 --- a/imerror.h +++ b/imerror.h @@ -19,7 +19,7 @@ extern int i_set_errors_fatal(int new_fatal); extern i_errmsg *i_errors(void); extern void i_push_error(int code, char const *msg); -extern void i_push_errorf(int code, char const *fmt, ...); +extern void i_push_errorf(int code, char const *fmt, ...) I_FORMAT_ATTR(2, 3); extern void i_push_errorvf(int code, char const *fmt, va_list); extern void i_clear_error(void); extern int i_failed(int code, char const *msg); diff --git a/imext.c b/imext.c index ed5c4169..d0544e6e 100644 --- a/imext.c +++ b/imext.c @@ -158,7 +158,7 @@ color to the image. */ int -(i_ppix)(i_img *im, int x, int y, const i_color *val) { +(i_ppix)(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) { return i_ppix(im, x, y, val); } @@ -175,7 +175,7 @@ Returns 0 if the pixel was retrieved, or -1 if not. */ int -(i_gpix)(i_img *im,int x,int y,i_color *val) { +(i_gpix)(i_img *im,i_img_dim x,i_img_dim y,i_color *val) { return i_gpix(im, x, y, val); } @@ -194,7 +194,7 @@ color to the image. =cut */ int -(i_ppixf)(i_img *im, int x, int y, const i_fcolor *val) { +(i_ppixf)(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) { return i_ppixf(im, x, y, val); } @@ -212,7 +212,7 @@ Returns 0 if the pixel was retrieved, or -1 if not. */ int -(i_gpixf)(i_img *im,int x,int y,i_fcolor *val) { +(i_gpixf)(i_img *im,i_img_dim x,i_img_dim y,i_fcolor *val) { return i_gpixf(im, x, y, val); } @@ -229,8 +229,8 @@ Returns the number of pixels set. =cut */ -int -(i_plin)(i_img *im, int l, int r, int y, const i_color *vals) { +i_img_dim +(i_plin)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) { return i_plin(im, l, r, y, vals); } @@ -246,8 +246,8 @@ Returns the number of pixels retrieved. =cut */ -int -(i_glin)(i_img *im, int l, int r, int y, i_color *vals) { +i_img_dim +(i_glin)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) { return i_glin(im, l, r, y, vals); } @@ -264,8 +264,8 @@ Returns the number of pixels set. =cut */ -int -(i_plinf)(i_img *im, int l, int r, int y, const i_fcolor *vals) { +i_img_dim +(i_plinf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) { return i_plinf(im, l, r, y, vals); } @@ -282,8 +282,8 @@ Returns the number of pixels retrieved. =cut */ -int -(i_glinf)(i_img *im, int l, int r, int y, i_fcolor *vals) { +i_img_dim +(i_glinf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) { return i_glinf(im, l, r, y, vals); } @@ -304,8 +304,8 @@ channel_count) =cut */ -int -(i_gsamp)(i_img *im, int l, int r, int y, i_sample_t *samp, +i_img_dim +(i_gsamp)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samp, const int *chans, int chan_count) { return i_gsamp(im, l, r, y, samp, chans, chan_count); } @@ -327,8 +327,8 @@ Returns the number of samples read (which should be (C-C) =cut */ -int -(i_gsampf)(i_img *im, int l, int r, int y, i_fsample_t *samp, +i_img_dim +(i_gsampf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, const int *chans, int chan_count) { return i_gsampf(im, l, r, y, samp, chans, chan_count); } @@ -347,8 +347,8 @@ Always returns 0 for direct color images. =cut */ -int -(i_gpal)(i_img *im, int x, int r, int y, i_palidx *vals) { +i_img_dim +(i_gpal)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_palidx *vals) { return i_gpal(im, x, r, y, vals); } @@ -366,8 +366,8 @@ Always returns 0 for direct color images. =cut */ -int -(i_ppal)(i_img *im, int x, int r, int y, const i_palidx *vals) { +i_img_dim +(i_ppal)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_palidx *vals) { return i_ppal(im, x, r, y, vals); } diff --git a/imext.h b/imext.h index 73af77a9..08d6a0ca 100644 --- a/imext.h +++ b/imext.h @@ -234,4 +234,11 @@ extern im_ext_funcs *imager_function_ext_table; #define i_render_linef(r, x, y, width, src, line, combine) \ ((im_extt->f_i_render_linef)((r), (x), (y), (width), (src), (line), (combine))) +#ifdef IMAGER_LOG +#define mm_log(x) { i_lhead(__FILE__,__LINE__); i_loog x; } +#else +#define mm_log(x) +#endif + + #endif diff --git a/imexttypes.h b/imexttypes.h index f1561d42..573cdc72 100644 --- a/imexttypes.h +++ b/imexttypes.h @@ -4,13 +4,18 @@ /* keep this file simple - apidocs.perl parses it. */ #include "imdatatypes.h" +#include /* IMAGER_API_VERSION is similar to the version number in the third and fourth bytes of TIFF files - if it ever changes then the API has changed too much for any application to remain compatible. + + Version 2 changed the types of some parameters and pointers. A + simple recompile should be enough in most cases. + */ -#define IMAGER_API_VERSION 1 +#define IMAGER_API_VERSION 2 /* IMAGER_API_LEVEL is the level of the structure. New function pointers @@ -25,36 +30,36 @@ typedef struct { int level; /* IMAGER_API_LEVEL 1 functions */ - void * (*f_mymalloc)(int size); + void * (*f_mymalloc)(size_t size); void (*f_myfree)(void *block); void * (*f_myrealloc)(void *block, size_t newsize); void* (*f_mymalloc_file_line)(size_t size, char* file, int line); void (*f_myfree_file_line)(void *p, char*file, int line); void* (*f_myrealloc_file_line)(void *p, size_t newsize, char* file,int line); - i_img *(*f_i_img_8_new)(int xsize, int ysize, int channels); - i_img *(*f_i_img_16_new)(int xsize, int ysize, int channels); - i_img *(*f_i_img_double_new)(int xsize, int ysize, int channels); - i_img *(*f_i_img_pal_new)(int xsize, int ysize, int channels, int maxpal); + i_img *(*f_i_img_8_new)(i_img_dim xsize, i_img_dim ysize, int channels); + i_img *(*f_i_img_16_new)(i_img_dim xsize, i_img_dim ysize, int channels); + i_img *(*f_i_img_double_new)(i_img_dim xsize, i_img_dim ysize, int channels); + i_img *(*f_i_img_pal_new)(i_img_dim xsize, i_img_dim ysize, int channels, int maxpal); void (*f_i_img_destroy)(i_img *im); - i_img *(*f_i_sametype)(i_img *im, int xsize, int ysize); - i_img *(*f_i_sametype_chans)(i_img *im, int xsize, int ysize, int channels); - void (*f_i_img_info)(i_img *im, int *info); - - int (*f_i_ppix)(i_img *im, int x, int y, const i_color *val); - int (*f_i_gpix)(i_img *im, int x, int y, i_color *val); - int (*f_i_ppixf)(i_img *im, int x, int y, const i_fcolor *val); - int (*f_i_gpixf)(i_img *im, int x, int y, i_fcolor *val); - int (*f_i_plin)(i_img *im, int l, int r, int y, const i_color *vals); - int (*f_i_glin)(i_img *im, int l, int r, int y, i_color *vals); - int (*f_i_plinf)(i_img *im, int l, int r, int y, const i_fcolor *vals); - int (*f_i_glinf)(i_img *im, int l, int r, int y, i_fcolor *vals); - int (*f_i_gsamp)(i_img *im, int l, int r, int y, i_sample_t *samp, + i_img *(*f_i_sametype)(i_img *im, i_img_dim xsize, i_img_dim ysize); + i_img *(*f_i_sametype_chans)(i_img *im, i_img_dim xsize, i_img_dim ysize, int channels); + void (*f_i_img_info)(i_img *im, i_img_dim *info); + + int (*f_i_ppix)(i_img *im, i_img_dim x, i_img_dim y, const i_color *val); + int (*f_i_gpix)(i_img *im, i_img_dim x, i_img_dim y, i_color *val); + int (*f_i_ppixf)(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val); + int (*f_i_gpixf)(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val); + i_img_dim (*f_i_plin)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals); + i_img_dim (*f_i_glin)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals); + i_img_dim (*f_i_plinf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals); + i_img_dim (*f_i_glinf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals); + i_img_dim (*f_i_gsamp)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samp, const int *chans, int chan_count); - int (*f_i_gsampf)(i_img *im, int l, int r, int y, i_fsample_t *samp, + i_img_dim (*f_i_gsampf)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, const int *chans, int chan_count); - int (*f_i_gpal)(i_img *im, int x, int r, int y, i_palidx *vals); - int (*f_i_ppal)(i_img *im, int x, int r, int y, const i_palidx *vals); + i_img_dim (*f_i_gpal)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, i_palidx *vals); + i_img_dim (*f_i_ppal)(i_img *im, i_img_dim x, i_img_dim r, i_img_dim y, const i_palidx *vals); int (*f_i_addcolors)(i_img *im, const i_color *colors, int count); int (*f_i_getcolors)(i_img *im, int i, i_color *, int count); int (*f_i_colorcount)(i_img *im); @@ -68,12 +73,12 @@ typedef struct { i_fill_t *(*f_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); + i_img_dim dx, i_img_dim dy); i_fill_t *(*f_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); - i_fill_t *(*f_i_new_fill_image)(i_img *im, const double *matrix, int xoff, - int yoff, int combine); + i_img_dim dx, i_img_dim dy); + i_fill_t *(*f_i_new_fill_image)(i_img *im, const double *matrix, i_img_dim xoff, + i_img_dim yoff, int combine); i_fill_t *(*f_i_new_fill_fount)(double xa, double ya, double xb, double yb, i_fountain_type type, i_fountain_repeat repeat, int combine, int super_sample, double ssample_param, @@ -117,30 +122,30 @@ typedef struct { int (*f_i_tags_set_color)(i_img_tags *tags, char const *name, int code, i_color const *value); - void (*f_i_box)(i_img *im, int x1, int y1, int x2, int y2, const i_color *val); - void (*f_i_box_filled)(i_img *im, int x1, int y1, int x2, int y2, const i_color *val); - void (*f_i_box_cfill)(i_img *im, int x1, int y1, int x2, int y2, i_fill_t *fill); - void (*f_i_line)(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int endp); - void (*f_i_line_aa)(i_img *im, int x1, int y1, int x2, int y2, const i_color *val, int endp); - void (*f_i_arc)(i_img *im, int x, int y, float rad, float d1, float d2, const i_color *val); + void (*f_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); + void (*f_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); + void (*f_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); + void (*f_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); + void (*f_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); + void (*f_i_arc)(i_img *im, i_img_dim x, i_img_dim y, double rad, double d1, double d2, const i_color *val); void (*f_i_arc_aa)(i_img *im, double x, double y, double rad, double d1, double d2, const i_color *val); - void (*f_i_arc_cfill)(i_img *im, int x, int y, float rad, float d1, float d2, i_fill_t *val); + void (*f_i_arc_cfill)(i_img *im, i_img_dim x, i_img_dim y, double rad, double d1, double d2, i_fill_t *val); void (*f_i_arc_aa_cfill)(i_img *im, double x, double y, double rad, double d1, double d2, i_fill_t *fill); - void (*f_i_circle_aa)(i_img *im, float x, float y, float rad, const i_color *val); - int (*f_i_flood_fill)(i_img *im, int seedx, int seedy, const i_color *dcol); - int (*f_i_flood_cfill)(i_img *im, int seedx, int seedy, i_fill_t *fill); + void (*f_i_circle_aa)(i_img *im, double x, double y, double rad, const i_color *val); + int (*f_i_flood_fill)(i_img *im, i_img_dim seedx, i_img_dim seedy, const i_color *dcol); + int (*f_i_flood_cfill)(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill); - void (*f_i_copyto)(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty); - void (*f_i_copyto_trans)(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty, const i_color *trans); + void (*f_i_copyto)(i_img *im, i_img *src, 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 (*f_i_copyto_trans)(i_img *im, i_img *src, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, i_img_dim tx, i_img_dim ty, const i_color *trans); i_img *(*f_i_copy)(i_img *im); - int (*f_i_rubthru)(i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny, int src_maxx, int src_maxy); + int (*f_i_rubthru)(i_img *im, i_img *src, 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); /* IMAGER_API_LEVEL 2 functions */ - int (*f_i_set_image_file_limits)(int width, int height, int bytes); - int (*f_i_get_image_file_limits)(int *width, int *height, int *bytes); - int (*f_i_int_check_image_file_limits)(int width, int height, int channels, int sample_size); - int (*f_i_flood_fill_border)(i_img *im, int seedx, int seedy, const i_color *dcol, const i_color *border); - int (*f_i_flood_cfill_border)(i_img *im, int seedx, int seedy, i_fill_t *fill, const i_color *border); + int (*f_i_set_image_file_limits)(i_img_dim width, i_img_dim height, size_t bytes); + int (*f_i_get_image_file_limits)(i_img_dim *width, i_img_dim *height, size_t *bytes); + int (*f_i_int_check_image_file_limits)(i_img_dim width, i_img_dim height, int channels, size_t sample_size); + int (*f_i_flood_fill_border)(i_img *im, i_img_dim seedx, i_img_dim seedy, const i_color *dcol, const i_color *border); + int (*f_i_flood_cfill_border)(i_img *im, i_img_dim seedx, i_img_dim seedy, i_fill_t *fill, const i_color *border); /* IMAGER_API_LEVEL 3 functions */ void (*f_i_img_setmask)(i_img *im, int ch_mask); @@ -158,9 +163,9 @@ typedef struct { /* IMAGER_API_LEVEL 5 functions will be added here */ /* added i_psampf?_bits macros */ int (*f_i_img_is_monochrome)(i_img *, int *zero_is_white); - int (*f_i_gsamp_bg)(i_img *im, int l, int r, int y, i_sample_t *samples, + int (*f_i_gsamp_bg)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samples, int out_channels, i_color const * bg); - int (*f_i_gsampf_bg)(i_img *im, int l, int r, int y, i_fsample_t *samples, + int (*f_i_gsampf_bg)(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samples, int out_channels, i_fcolor const * bg); void (*f_i_get_file_background)(i_img *im, i_color *bg); void (*f_i_get_file_backgroundf)(i_img *im, i_fcolor *bg); diff --git a/img16.c b/img16.c index 321821e0..267c1d6b 100644 --- a/img16.c +++ b/img16.c @@ -5,7 +5,7 @@ img16.c - implements 16-bit images =head1 SYNOPSIS - i_img *im = i_img_16_new(int x, int y, int channels); + i_img *im = i_img_16_new(i_img_dim x, i_img_dim y, int channels); # use like a normal image =head1 DESCRIPTION @@ -23,21 +23,21 @@ sample image type to work with. #include "imager.h" #include "imageri.h" -static int i_ppix_d16(i_img *im, int x, int y, const i_color *val); -static int i_gpix_d16(i_img *im, int x, int y, i_color *val); -static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals); -static int i_plin_d16(i_img *im, int l, int r, int y, const i_color *vals); -static int i_ppixf_d16(i_img *im, int x, int y, const i_fcolor *val); -static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val); -static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals); -static int i_plinf_d16(i_img *im, int l, int r, int y, const i_fcolor *vals); -static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps, +static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val); +static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val); +static i_img_dim i_glin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals); +static i_img_dim i_plin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals); +static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val); +static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val); +static i_img_dim i_glinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals); +static i_img_dim i_plinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals); +static i_img_dim i_gsamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int const *chans, int chan_count); -static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps, +static i_img_dim i_gsampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps, int const *chans, int chan_count); -static int i_gsamp_bits_d16(i_img *im, int l, int r, int y, unsigned *samps, +static i_img_dim i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps, int const *chans, int chan_count, int bits); -static int i_psamp_bits_d16(i_img *im, int l, int r, int y, unsigned const *samps, +static i_img_dim i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned const *samps, int const *chans, int chan_count, int bits); /* @@ -155,11 +155,12 @@ Returns the image on success, or NULL on failure. =cut */ -i_img *i_img_16_new(int x, int y, int ch) { +i_img *i_img_16_new(i_img_dim x, i_img_dim y, int ch) { i_img *im; - int bytes, line_bytes; + size_t bytes, line_bytes; - mm_log((1,"i_img_16_new(x %d, y %d, ch %d)\n", x, y, ch)); + mm_log((1,"i_img_16_new(x %" i_DF ", y %" i_DF ", ch %d)\n", + i_DFc(x), i_DFc(y), ch)); if (x < 1 || y < 1) { i_push_error(0, "Image sizes must be positive"); @@ -216,7 +217,7 @@ i_img * i_img_to_rgb16(i_img *im) { i_img *targ; i_fcolor *line; - int y; + i_img_dim y; targ = i_img_16_new(im->xsize, im->ysize, im->channels); if (!targ) @@ -232,8 +233,9 @@ i_img_to_rgb16(i_img *im) { return targ; } -static int i_ppix_d16(i_img *im, int x, int y, const i_color *val) { - int off, ch; +static int i_ppix_d16(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) { + i_img_dim off; + int ch; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) return -1; @@ -252,8 +254,9 @@ static int i_ppix_d16(i_img *im, int x, int y, const i_color *val) { return 0; } -static int i_gpix_d16(i_img *im, int x, int y, i_color *val) { - int off, ch; +static int i_gpix_d16(i_img *im, i_img_dim x, i_img_dim y, i_color *val) { + i_img_dim off; + int ch; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) return -1; @@ -265,8 +268,9 @@ static int i_gpix_d16(i_img *im, int x, int y, i_color *val) { return 0; } -static int i_ppixf_d16(i_img *im, int x, int y, const i_fcolor *val) { - int off, ch; +static int i_ppixf_d16(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) { + i_img_dim off; + int ch; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) return -1; @@ -285,8 +289,9 @@ static int i_ppixf_d16(i_img *im, int x, int y, const i_fcolor *val) { return 0; } -static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val) { - int off, ch; +static int i_gpixf_d16(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) { + i_img_dim off; + int ch; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) return -1; @@ -298,9 +303,10 @@ static int i_gpixf_d16(i_img *im, int x, int y, i_fcolor *val) { return 0; } -static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals) { - int ch, count, i; - int off; +static i_img_dim i_glin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) { + int ch; + i_img_dim count, i; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; @@ -319,9 +325,10 @@ static int i_glin_d16(i_img *im, int l, int r, int y, i_color *vals) { } } -static int i_plin_d16(i_img *im, int l, int r, int y, const i_color *vals) { - int ch, count, i; - int off; +static i_img_dim i_plin_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) { + int ch; + i_img_dim count, i; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; @@ -351,9 +358,10 @@ static int i_plin_d16(i_img *im, int l, int r, int y, const i_color *vals) { } } -static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) { - int ch, count, i; - int off; +static i_img_dim i_glinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) { + int ch; + i_img_dim count, i; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; @@ -372,9 +380,10 @@ static int i_glinf_d16(i_img *im, int l, int r, int y, i_fcolor *vals) { } } -static int i_plinf_d16(i_img *im, int l, int r, int y, const i_fcolor *vals) { - int ch, count, i; - int off; +static i_img_dim i_plinf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) { + int ch; + i_img_dim count, i; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; @@ -404,10 +413,11 @@ static int i_plinf_d16(i_img *im, int l, int r, int y, const i_fcolor *vals) { } } -static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps, +static i_img_dim i_gsamp_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int const *chans, int chan_count) { - int ch, count, i, w; - int off; + int ch; + i_img_dim count, i, w; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -454,10 +464,11 @@ static int i_gsamp_d16(i_img *im, int l, int r, int y, i_sample_t *samps, } } -static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps, +static i_img_dim i_gsampf_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps, int const *chans, int chan_count) { - int ch, count, i, w; - int off; + int ch; + i_img_dim count, i, w; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -504,11 +515,12 @@ static int i_gsampf_d16(i_img *im, int l, int r, int y, i_fsample_t *samps, } } -static int -i_gsamp_bits_d16(i_img *im, int l, int r, int y, unsigned *samps, +static i_img_dim +i_gsamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned *samps, int const *chans, int chan_count, int bits) { - int ch, count, i, w; - int off; + int ch; + i_img_dim count, i, w; + i_img_dim off; if (bits != 16) { return i_gsamp_bits_fb(im, l, r, y, samps, chans, chan_count, bits); @@ -559,11 +571,12 @@ i_gsamp_bits_d16(i_img *im, int l, int r, int y, unsigned *samps, } } -static int -i_psamp_bits_d16(i_img *im, int l, int r, int y, unsigned const *samps, +static i_img_dim +i_psamp_bits_d16(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, unsigned const *samps, int const *chans, int chan_count, int bits) { - int ch, count, i, w; - int off; + int ch; + i_img_dim count, i, w; + i_img_dim off; if (bits != 16) { i_push_error(0, "Invalid bits for 16-bit image"); diff --git a/img8.c b/img8.c index bd5a0194..ea23d281 100644 --- a/img8.c +++ b/img8.c @@ -1,16 +1,16 @@ #include "imager.h" #include "imageri.h" -static int i_ppix_d(i_img *im, int x, int y, const i_color *val); -static int i_gpix_d(i_img *im, int x, int y, i_color *val); -static int i_glin_d(i_img *im, int l, int r, int y, i_color *vals); -static int i_plin_d(i_img *im, int l, int r, int y, const i_color *vals); -static int i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val); -static int i_gpixf_d(i_img *im, int x, int y, i_fcolor *val); -static int i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals); -static int i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals); -static int i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, const int *chans, int chan_count); -static int i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, const int *chans, int chan_count); +static int i_ppix_d(i_img *im, i_img_dim x, i_img_dim y, const i_color *val); +static int i_gpix_d(i_img *im, i_img_dim x, i_img_dim y, i_color *val); +static i_img_dim i_glin_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals); +static i_img_dim i_plin_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals); +static int i_ppixf_d(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val); +static int i_gpixf_d(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val); +static i_img_dim i_glinf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals); +static i_img_dim i_plinf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals); +static i_img_dim i_gsamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, const int *chans, int chan_count); +static i_img_dim i_gsampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps, const int *chans, int chan_count); /* =item IIM_base_8bit_direct (static) @@ -91,9 +91,11 @@ I channels. i_img * -IIM_new(int x,int y,int ch) { +IIM_new(i_img_dim x,i_img_dim y,int ch) { i_img *im; - mm_log((1,"IIM_new(x %d,y %d,ch %d)\n",x,y,ch)); + + mm_log((1,"IIM_new(x %" i_DF ", y %" i_DF ", ch %d)\n", + i_DFc(x), i_DFc(y), ch)); im=i_img_empty_ch(NULL,x,y,ch); @@ -158,8 +160,9 @@ Should this just call i_img_empty_ch()? */ i_img * -i_img_empty(i_img *im,int x,int y) { - mm_log((1,"i_img_empty(*im %p, x %d, y %d)\n",im, x, y)); +i_img_empty(i_img *im,i_img_dim x,i_img_dim y) { + mm_log((1,"i_img_empty(*im %p, x %" i_DF ", y %" i_DF ")\n", + im, i_DFc(x), i_DFc(y))); return i_img_empty_ch(im, x, y, 3); } @@ -177,10 +180,11 @@ Re-new image reference */ i_img * -i_img_empty_ch(i_img *im,int x,int y,int ch) { - int bytes; +i_img_empty_ch(i_img *im,i_img_dim x,i_img_dim y,int ch) { + size_t bytes; - mm_log((1,"i_img_empty_ch(*im %p, x %d, y %d, ch %d)\n", im, x, y, ch)); + mm_log((1,"i_img_empty_ch(*im %p, x %" i_DF ", y %" i_DF ", ch %d)\n", + im, i_DFc(x), i_DFc(y), ch)); if (x < 1 || y < 1) { i_push_error(0, "Image sizes must be positive"); @@ -239,7 +243,7 @@ Returns 0 if the pixel could be set, -1 otherwise. */ static int -i_ppix_d(i_img *im, int x, int y, const i_color *val) { +i_ppix_d(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) { int ch; if ( x>-1 && xxsize && y>-1 && yysize ) { @@ -265,7 +269,7 @@ Returns 0 if the pixel could be set, -1 otherwise. */ static int -i_gpix_d(i_img *im, int x, int y, i_color *val) { +i_gpix_d(i_img *im, i_img_dim x, i_img_dim y, i_color *val) { int ch; if (x>-1 && xxsize && y>-1 && yysize) { for(ch=0;chchannels;ch++) @@ -293,9 +297,10 @@ Returns the number of pixels copied (eg. if r, l or y is out of range) =cut */ static -int -i_glin_d(i_img *im, int l, int r, int y, i_color *vals) { - int ch, count, i; +i_img_dim +i_glin_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) { + int ch; + i_img_dim count, i; unsigned char *data; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -330,9 +335,10 @@ Returns the number of pixels copied (eg. if r, l or y is out of range) =cut */ static -int -i_plin_d(i_img *im, int l, int r, int y, const i_color *vals) { - int ch, count, i; +i_img_dim +i_plin_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) { + int ch; + i_img_dim count, i; unsigned char *data; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -360,7 +366,7 @@ i_plin_d(i_img *im, int l, int r, int y, const i_color *vals) { */ static int -i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val) { +i_ppixf_d(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) { int ch; if ( x>-1 && xxsize && y>-1 && yysize ) { @@ -381,7 +387,7 @@ i_ppixf_d(i_img *im, int x, int y, const i_fcolor *val) { */ static int -i_gpixf_d(i_img *im, int x, int y, i_fcolor *val) { +i_gpixf_d(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) { int ch; if (x>-1 && xxsize && y>-1 && yysize) { for(ch=0;chchannels;ch++) { @@ -410,9 +416,10 @@ Returns the number of pixels copied (eg. if r, l or y is out of range) =cut */ static -int -i_glinf_d(i_img *im, int l, int r, int y, i_fcolor *vals) { - int ch, count, i; +i_img_dim +i_glinf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) { + int ch; + i_img_dim count, i; unsigned char *data; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -447,9 +454,10 @@ Returns the number of pixels copied (eg. if r, l or y is out of range) =cut */ static -int -i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals) { - int ch, count, i; +i_img_dim +i_plinf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) { + int ch; + i_img_dim count, i; unsigned char *data; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -471,7 +479,7 @@ i_plinf_d(i_img *im, int l, int r, int y, const i_fcolor *vals) { } /* -=item i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, int *chans, int chan_count) +=item i_gsamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int *chans, int chan_count) Reads sample values from im for the horizontal line (l, y) to (r-1,y) for the channels specified by chans, an array of int with chan_count @@ -482,10 +490,11 @@ Returns the number of samples read (which should be (r-l) * bits_set(chan_mask) =cut */ static -int -i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, +i_img_dim +i_gsamp_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, const int *chans, int chan_count) { - int ch, count, i, w; + int ch; + i_img_dim count, i, w; unsigned char *data; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { @@ -534,7 +543,7 @@ i_gsamp_d(i_img *im, int l, int r, int y, i_sample_t *samps, } /* -=item i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, int *chans, int chan_count) +=item i_gsampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps, int *chans, int chan_count) Reads sample values from im for the horizontal line (l, y) to (r-1,y) for the channels specified by chan_mask, where bit 0 is the first @@ -545,10 +554,11 @@ Returns the number of samples read (which should be (r-l) * bits_set(chan_mask) =cut */ static -int -i_gsampf_d(i_img *im, int l, int r, int y, i_fsample_t *samps, +i_img_dim +i_gsampf_d(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps, const int *chans, int chan_count) { - int ch, count, i, w; + int ch; + i_img_dim count, i, w; unsigned char *data; for (ch = 0; ch < chan_count; ++ch) { if (chans[ch] < 0 || chans[ch] >= im->channels) { diff --git a/imgdouble.c b/imgdouble.c index c2fb7e5f..c6b2a5bb 100644 --- a/imgdouble.c +++ b/imgdouble.c @@ -5,7 +5,7 @@ imgdouble.c - implements double per sample images =head1 SYNOPSIS - i_img *im = i_img_double_new(int x, int y, int channels); + i_img *im = i_img_double_new(width, height, channels); # use like a normal image =head1 DESCRIPTION @@ -23,17 +23,17 @@ sample image type to work with. #include "imager.h" #include "imageri.h" -static int i_ppix_ddoub(i_img *im, int x, int y, const i_color *val); -static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val); -static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals); -static int i_plin_ddoub(i_img *im, int l, int r, int y, const i_color *vals); -static int i_ppixf_ddoub(i_img *im, int x, int y, const i_fcolor *val); -static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val); -static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals); -static int i_plinf_ddoub(i_img *im, int l, int r, int y, const i_fcolor *vals); -static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps, +static int i_ppix_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_color *val); +static int i_gpix_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_color *val); +static i_img_dim i_glin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals); +static i_img_dim i_plin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals); +static int i_ppixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val); +static int i_gpixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val); +static i_img_dim i_glinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals); +static i_img_dim i_plinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals); +static i_img_dim i_gsamp_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int const *chans, int chan_count); -static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps, +static i_img_dim i_gsampf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps, int const *chans, int chan_count); /* @@ -84,7 +84,7 @@ static i_img IIM_base_double_direct = }; /* -=item i_img_double_new(int x, int y, int ch) +=item i_img_double_new(i_img_dim x, i_img_dim y, int ch) =category Image creation/destruction =synopsis i_img *img = i_img_double_new(width, height, channels); @@ -92,11 +92,12 @@ Creates a new double per sample image. =cut */ -i_img *i_img_double_new(int x, int y, int ch) { - int bytes; +i_img *i_img_double_new(i_img_dim x, i_img_dim y, int ch) { + size_t bytes; i_img *im; - mm_log((1,"i_img_double_new(x %d, y %d, ch %d)\n", x, y, ch)); + mm_log((1,"i_img_double_new(x %" i_DF ", y %" i_DF ", ch %d)\n", + i_DFc(x), i_DFc(y), ch)); if (x < 1 || y < 1) { i_push_error(0, "Image sizes must be positive"); @@ -127,8 +128,9 @@ i_img *i_img_double_new(int x, int y, int ch) { return im; } -static int i_ppix_ddoub(i_img *im, int x, int y, const i_color *val) { - int off, ch; +static int i_ppix_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) { + i_img_dim off; + int ch; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) return -1; @@ -147,8 +149,9 @@ static int i_ppix_ddoub(i_img *im, int x, int y, const i_color *val) { return 0; } -static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val) { - int off, ch; +static int i_gpix_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_color *val) { + i_img_dim off; + int ch; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) return -1; @@ -160,8 +163,9 @@ static int i_gpix_ddoub(i_img *im, int x, int y, i_color *val) { return 0; } -static int i_ppixf_ddoub(i_img *im, int x, int y, const i_fcolor *val) { - int off, ch; +static int i_ppixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *val) { + i_img_dim off; + int ch; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) return -1; @@ -180,8 +184,9 @@ static int i_ppixf_ddoub(i_img *im, int x, int y, const i_fcolor *val) { return 0; } -static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val) { - int off, ch; +static int i_gpixf_ddoub(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *val) { + i_img_dim off; + int ch; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) return -1; @@ -193,9 +198,10 @@ static int i_gpixf_ddoub(i_img *im, int x, int y, i_fcolor *val) { return 0; } -static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals) { - int ch, count, i; - int off; +static i_img_dim i_glin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) { + int ch; + i_img_dim count, i; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; @@ -214,9 +220,10 @@ static int i_glin_ddoub(i_img *im, int l, int r, int y, i_color *vals) { } } -static int i_plin_ddoub(i_img *im, int l, int r, int y, const i_color *vals) { - int ch, count, i; - int off; +static i_img_dim i_plin_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) { + int ch; + i_img_dim count, i; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; @@ -246,9 +253,10 @@ static int i_plin_ddoub(i_img *im, int l, int r, int y, const i_color *vals) { } } -static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals) { - int ch, count, i; - int off; +static i_img_dim i_glinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) { + int ch; + i_img_dim count, i; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; @@ -267,9 +275,10 @@ static int i_glinf_ddoub(i_img *im, int l, int r, int y, i_fcolor *vals) { } } -static int i_plinf_ddoub(i_img *im, int l, int r, int y, const i_fcolor *vals) { - int ch, count, i; - int off; +static i_img_dim i_plinf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) { + int ch; + i_img_dim count, i; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; @@ -299,10 +308,11 @@ static int i_plinf_ddoub(i_img *im, int l, int r, int y, const i_fcolor *vals) { } } -static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps, +static i_img_dim i_gsamp_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int const *chans, int chan_count) { - int ch, count, i, w; - int off; + int ch; + i_img_dim count, i, w; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -349,10 +359,11 @@ static int i_gsamp_ddoub(i_img *im, int l, int r, int y, i_sample_t *samps, } } -static int i_gsampf_ddoub(i_img *im, int l, int r, int y, i_fsample_t *samps, +static i_img_dim i_gsampf_ddoub(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samps, int const *chans, int chan_count) { - int ch, count, i, w; - int off; + int ch; + i_img_dim count, i, w; + i_img_dim off; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -415,7 +426,7 @@ i_img * i_img_to_drgb(i_img *im) { i_img *targ; i_fcolor *line; - int y; + i_img_dim y; targ = i_img_double_new(im->xsize, im->ysize, im->channels); if (!targ) diff --git a/io.c b/io.c index df00421c..82efec96 100644 --- a/io.c +++ b/io.c @@ -75,17 +75,18 @@ set_entry(int i, char *buf, size_t size, char *file, int line) { void malloc_state(void) { - int i, total = 0; + int i; + size_t total = 0; i_clear_error(); mm_log((0,"malloc_state()\n")); bndcheck_all(); for(i=0; i %d bytes allocated at %p for %s (%d)\n", i, size, buf, file, line)); + mm_log((1,"mymalloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)size, buf, file, line)); return buf; } void * -(mymalloc)(int size) { +(mymalloc)(size_t size) { return mymalloc_file_line(size, "unknown", 0); } @@ -143,12 +144,13 @@ myrealloc_file_line(void *ptr, size_t newsize, char* file, int line) { } if ( (buf = realloc(((char *)ptr)-UNDRRNVAL, UNDRRNVAL+OVERRNVAL+newsize)) == NULL ) { - mm_log((1,"Unable to reallocate %i bytes at %p for %s (%i)\n", newsize, ptr, file, line)); + mm_log((1,"Unable to reallocate %ld bytes at %p for %s (%i)\n", (long) + newsize, ptr, file, line)); exit(3); } buf = set_entry(i, buf, newsize, file, line); - mm_log((1,"realloc_file_line: slot <%d> %d bytes allocated at %p for %s (%d)\n", i, newsize, buf, file, line)); + mm_log((1,"realloc_file_line: slot <%d> %ld bytes allocated at %p for %s (%d)\n", i, (long)newsize, buf, file, line)); return buf; } @@ -168,13 +170,15 @@ bndcheck(int idx) { return; } - for(i=0;i %p\n", size, buf)); + mm_log((1, "mymalloc(size %ld) -> %p\n", (long)size, buf)); return buf; } @@ -264,7 +266,7 @@ void * myrealloc(void *block, size_t size) { void *result; - mm_log((1, "myrealloc(block %p, size %u)\n", block, size)); + mm_log((1, "myrealloc(block %p, size %ld)\n", block, (long)size)); if ((result = realloc(block, size)) == NULL) { mm_log((1, "myrealloc: out of memory\n")); fprintf(stderr, "Out of memory.\n"); @@ -353,11 +355,15 @@ Retrieve a C character from the stream. Modifies *p and *len to indicate the consumed characters. This doesn't support the extended C encoding used by later -versions of Perl. +versions of Perl. Since this is typically used to implement text +output by font drivers, the strings supplied shouldn't have such out +of range characters. This doesn't check that the C character is using the shortest possible representation. +Returns ~0UL on failure. + =cut */ diff --git a/iolayer.c b/iolayer.c index 5f499762..5cb8753b 100644 --- a/iolayer.c +++ b/iolayer.c @@ -246,7 +246,7 @@ off_t realseek_seek(io_glue *ig, off_t offset, int whence) { /* io_ex_rseek *ier = ig->exdata; Needed later */ void *p = ig->source.cb.p; - int rc; + off_t rc; IOL_DEB( printf("realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) ); rc = ig->source.cb.seekcb(p, offset, whence); @@ -290,13 +290,13 @@ buffer_read(io_glue *ig, void *buf, size_t count) { IOL_DEB( printf("buffer_read: ieb->cpos = %ld, buf = %p, count = %d\n", (long) ieb->cpos, buf, count) ); if ( ieb->cpos+count > ig->source.buffer.len ) { - mm_log((1,"buffer_read: short read: cpos=%d, len=%d, count=%d\n", ieb->cpos, ig->source.buffer.len)); + mm_log((1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ieb->cpos, (long)ig->source.buffer.len, (long)count)); count = ig->source.buffer.len - ieb->cpos; } memcpy(buf, ig->source.buffer.data+ieb->cpos, count); ieb->cpos += count; - IOL_DEB( printf("buffer_read: count = %d\n", count) ); + IOL_DEB( printf("buffer_read: count = %ld\n", (long)count) ); return count; } @@ -597,7 +597,7 @@ bufchain_read(io_glue *ig, void *buf, size_t count) { char *cbuf = buf; size_t sk; - mm_log((1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, count)); + mm_log((1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count)); while( scount ) { int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len; @@ -617,7 +617,7 @@ bufchain_read(io_glue *ig, void *buf, size_t count) { ieb->gpos += sk; } - mm_log((1, "bufchain_read: returning %d\n", count-scount)); + mm_log((1, "bufchain_read: returning %ld\n", (long)(count-scount))); return count-scount; } @@ -645,14 +645,14 @@ bufchain_write(io_glue *ig, const void *buf, size_t count) { size_t ocount = count; size_t sk; - mm_log((1, "bufchain_write: ig = %p, buf = %p, count = %d\n", ig, buf, count)); + mm_log((1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count)); - IOL_DEB( printf("bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %d\n", ig, (long) ieb->cpos, buf, count) ); + IOL_DEB( printf("bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) ); while(count) { - mm_log((2, "bufchain_write: - looping - count = %d\n", count)); + mm_log((2, "bufchain_write: - looping - count = %ld\n", (long)count)); if (ieb->cp->len == ieb->cpos) { - mm_log((1, "bufchain_write: cp->len == ieb->cpos = %d - advancing chain\n", (long) ieb->cpos)); + mm_log((1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos)); io_bchain_advance(ieb); } @@ -718,7 +718,7 @@ bufchain_seek(io_glue *ig, off_t offset, int whence) { off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence); off_t sk; - mm_log((1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, offset, whence)); + mm_log((1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence)); if (scount < 0) { i_push_error(0, "invalid whence supplied or seek before start of file"); @@ -760,14 +760,14 @@ bufchain_seek(io_glue *ig, off_t offset, int whence) { while(wrlen > 0) { ssize_t rc, wl = i_min(wrlen, BBSIZ); - mm_log((1, "bufchain_seek: wrlen = %d, wl = %d\n", wrlen, wl)); + mm_log((1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl)); rc = bufchain_write( ig, TB, wl ); if (rc != wl) i_fatal(0, "bufchain_seek: Unable to extend file\n"); wrlen -= rc; } } - mm_log((2, "bufchain_seek: returning ieb->gpos = %d\n", ieb->gpos)); + mm_log((2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos)); return ieb->gpos; } @@ -944,7 +944,7 @@ io_new_buffer(char *data, size_t len, i_io_closebufp_t closecb, void *closedata) io_glue *ig; io_ex_buffer *ieb = mymalloc(sizeof(io_ex_buffer)); - mm_log((1, "io_new_buffer(data %p, len %d, closecb %p, closedata %p)\n", data, len, closecb, closedata)); + mm_log((1, "io_new_buffer(data %p, len %ld, closecb %p, closedata %p)\n", data, (long)len, closecb, closedata)); ig = mymalloc(sizeof(io_glue)); memset(ig, 0, sizeof(*ig)); diff --git a/iolayert.h b/iolayert.h index 9857d67b..f7fdac9b 100644 --- a/iolayert.h +++ b/iolayert.h @@ -6,6 +6,7 @@ #endif #include #include +#include typedef enum { FDSEEK, FDNOSEEK, BUFFER, CBSEEK, CBNOSEEK, BUFCHAIN } io_type; diff --git a/lib/Imager/APIRef.pod b/lib/Imager/APIRef.pod index 0efe76fc..4e7c6ce3 100644 --- a/lib/Imager/APIRef.pod +++ b/lib/Imager/APIRef.pod @@ -21,7 +21,9 @@ Imager::APIRef - Imager's C API - reference. i_color black; black.rgba.r = black.rgba.g = black.rgba.b = black.rgba.a = 0; i_fill_t *fill; - i_img_dim x; + i_img_dim x, y; + printf("left %" i_DF "\n", i_DFc(x)); + printf("point (" i_DFp ")\n", i_DFcp(x, y)); # Drawing i_arc(im, 50, 50, 20, 45, 135, &color); @@ -159,6 +161,8 @@ From: File render.im =item i_img + i_img *img; + This is Imager's image type. It contains the following members: @@ -254,6 +258,9 @@ From: File imdatatypes.h =item i_color + i_color black; + black.rgba.r = black.rgba.g = black.rgba.b = black.rgba.a = 0; + Type for 8-bit/sample color. Samples as per; @@ -304,6 +311,8 @@ From: File imdatatypes.h =item i_fill_t + i_fill_t *fill; + This is the "abstract" base type for Imager's fill types. Unless you're implementing a new fill type you'll typically treat this @@ -315,11 +324,54 @@ From: File imdatatypes.h =item i_img_dim + i_img_dim x, y; + A signed integer type that represents an image dimension or ordinate. May be larger than int on some platforms. +=for comment +From: File imdatatypes.h + +=item i_DF + + printf("left %" i_DF "\n", i_DFc(x)); + +This is a constant string that can be used with functions like +printf() to format i_img_dim values after they're been cast with i_DFc(). + +Does not include the leading C<%>. + + +=for comment +From: File imdatatypes.h + +=item i_DFc + +Cast an C value to a type for use with the i_DF format +string. + + +=for comment +From: File imdatatypes.h + +=item i_DFcp + +Casts two C values for use with the i_DF (or i_DFp) format. + + +=for comment +From: File imdatatypes.h + +=item i_DFp + + printf("point (" i_DFp ")\n", i_DFcp(x, y)); + +Format a pair of C values. This format string I +include the leading C<%>. + + =for comment From: File imdatatypes.h @@ -333,6 +385,8 @@ From: File imdatatypes.h =item i_arc(im, x, y, rad, d1, d2, color) + i_arc(im, 50, 50, 20, 45, 135, &color); + Fills an arc centered at (x,y) with radius I covering the range of angles in degrees from d1 to d2, with the color. @@ -343,6 +397,8 @@ From: File draw.c =item i_arc_aa(im, x, y, rad, d1, d2, color) + i_arc_aa(im, 50, 50, 35, 90, 135, &color); + Anti-alias fills an arc centered at (x,y) with radius I covering the range of angles in degrees from d1 to d2, with the color. @@ -353,6 +409,8 @@ From: File draw.c =item i_arc_aa_cfill(im, x, y, rad, d1, d2, fill) + i_arc_aa_cfill(im, 50, 50, 35, 90, 135, fill); + Anti-alias fills an arc centered at (x,y) with radius I covering the range of angles in degrees from d1 to d2, with the fill object. @@ -363,6 +421,8 @@ From: File draw.c =item i_arc_cfill(im, x, y, rad, d1, d2, fill) + i_arc_cfill(im, 50, 50, 35, 90, 135, fill); + Fills an arc centered at (x,y) with radius I covering the range of angles in degrees from d1 to d2, with the fill object. @@ -373,6 +433,8 @@ From: File draw.c =item i_box(im, x1, y1, x2, y2, color) + i_box(im, 0, 0, im->xsize-1, im->ysize-1, &color). + Outlines the box from (x1,y1) to (x2,y2) inclusive with I. @@ -382,6 +444,8 @@ From: File draw.c =item i_box_cfill(im, x1, y1, x2, y2, fill) + i_box_cfill(im, 0, 0, im->xsize-1, im->ysize-1, fill); + Fills the box from (x1,y1) to (x2,y2) inclusive with fill. @@ -391,6 +455,8 @@ From: File draw.c =item i_box_filled(im, x1, y1, x2, y2, color) + i_box_filled(im, 0, 0, im->xsize-1, im->ysize-1, &color); + Fills the box from (x1,y1) to (x2,y2) inclusive with color. @@ -400,6 +466,8 @@ From: File draw.c =item i_circle_aa(im, x, y, rad, color) + i_circle_aa(im, 50, 50, 45, &color); + Anti-alias fills a circle centered at (x,y) for radius I with color. @@ -410,6 +478,8 @@ From: File draw.c =item i_flood_cfill(C, C, C, C) + i_flood_cfill(im, 50, 50, fill); + Flood fills the 4-connected region starting from the point (C, C) with C. @@ -422,6 +492,8 @@ From: File draw.c =item i_flood_cfill_border(C, C, C, C, C) + i_flood_cfill_border(im, 50, 50, fill, border); + Flood fills the 4-connected region starting from the point (C, C) with C, the fill stops when it reaches pixels of color C. @@ -435,6 +507,8 @@ From: File draw.c =item i_flood_fill(C, C, C, C) + i_flood_fill(im, 50, 50, &color); + Flood fills the 4-connected region starting from the point (C, C) with I. @@ -447,6 +521,8 @@ From: File draw.c =item i_flood_fill_border(C, C, C, C, C) + i_flood_fill_border(im, 50, 50, &color, &border); + Flood fills the 4-connected region starting from the point (C, C) with C, fill stops when the fill reaches a pixels with color C. @@ -682,6 +758,8 @@ From: File imext.c =item i_clear_error() + i_clear_error(); + Clears the error stack. Called by any Imager function before doing any other processing. @@ -692,6 +770,9 @@ From: File error.c =item i_push_error(int code, char const *msg) + i_push_error(0, "Yep, it's broken"); + i_push_error(errno, "Error writing"); + Called by an Imager function to push an error message onto the stack. No message is pushed if the stack is full (since this means someone @@ -704,6 +785,8 @@ From: File error.c =item i_push_errorf(int code, char const *fmt, ...) + i_push_errorf(errno, "Cannot open file %s: %d", filename, errno); + A version of i_push_error() that does printf() like formatting. Does not support perl specific format codes. @@ -759,8 +842,22 @@ From: File image.c =item i_get_image_file_limits(&width, &height, &bytes) + i_get_image_file_limits(&width, &height, &bytes) + Retrieves the file limits set by i_set_image_file_limits(). +=over + +=item * + +i_img_dim *width, *height - the maximum width and height of the image. + +=item * + +size_t *bytes - size in memory of the image in bytes. + +=back + =for comment From: File limits.c @@ -768,6 +865,8 @@ From: File limits.c =item i_int_check_image_file_limits(width, height, channels, sample_size) + i_i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t)) + Checks the size of a file in memory against the configured image file limits. @@ -785,12 +884,28 @@ From: File limits.c =item i_set_image_file_limits(width, height, bytes) + i_set_image_file_limits(500, 500, 1000000); + Set limits on the sizes of images read by Imager. Setting a limit to 0 means that limit is ignored. Negative limits result in failure. +Parameters: + +=over + +=item * + +i_img_dim width, height - maximum width and height. + +=item * + +size_t bytes - maximum size in memory in bytes + +=back + Returns non-zero on success. @@ -807,6 +922,9 @@ From: File limits.c =item i_new_fill_fount(C, C, C, C, C, C, C, C, C, C, C) + fill = i_new_fill_fount(0, 0, 100, 100, i_ft_linear, i_ft_linear, + i_fr_triangle, 0, i_fts_grid, 9, 1, segs); + Creates a new general fill which fills with a fountain fill. @@ -817,6 +935,8 @@ From: File filters.im =item i_new_fill_hatch(C, C, C, C, C, C, C) + i_fill_t *fill = i_new_fill_hatch(&fg_color, &bg_color, combine, hatch, custom_hatch, dx, dy); + Creates a new hatched fill with the C color used for the 1 bits in the hatch and C for the 0 bits. If C is non-zero alpha values will be combined. @@ -837,6 +957,8 @@ From: File fills.c =item i_new_fill_hatchf(C, C, C, C, C, C, C) + i_fill_t *fill = i_new_fill_hatchf(&fg_fcolor, &bg_fcolor, combine, hatch, custom_hatch, dx, dy); + Creates a new hatched fill with the C color used for the 1 bits in the hatch and C for the 0 bits. If C is non-zero alpha values will be combined. @@ -857,6 +979,8 @@ From: File fills.c =item i_new_fill_image(C, C, C, C, C) + i_fill_t *fill = i_new_fill_image(src_img, matrix, x_offset, y_offset, combine); + Create an image based fill. matrix is an array of 9 doubles representing a transformation matrix. @@ -870,6 +994,8 @@ From: File fills.c =item i_new_fill_solid(color, combine) + i_fill_t *fill = i_new_fill_solid(&color, combine); + Create a solid fill based on an 8-bit color. If combine is non-zero then alpha values will be combined. @@ -881,6 +1007,8 @@ From: File fills.c =item i_new_fill_solidf(color, combine) + i_fill_t *fill = i_new_fill_solidf(&fcolor, combine); + Create a solid fill based on a float color. If combine is non-zero then alpha values will be combined. @@ -891,6 +1019,8 @@ From: File fills.c =item i_fill_destroy(fill) + i_fill_destroy(fill); + Call to destroy any fill object. @@ -986,6 +1116,8 @@ From: File rubthru.im =item i_img_16_new(x, y, ch) + i_img *img = i_img_16_new(width, height, channels); + Create a new 16-bit/sample image. Returns the image on success, or NULL on failure. @@ -998,6 +1130,8 @@ From: File img16.c + i_img *img = i_img_8_new(width, height, channels); + Creates a new image object I pixels wide, and I pixels high with I channels. @@ -1005,7 +1139,9 @@ I channels. =for comment From: File img8.c -=item i_img_double_new(int x, int y, int ch) +=item i_img_double_new(i_img_dim x, i_img_dim y, int ch) + + i_img *img = i_img_double_new(width, height, channels); Creates a new double per sample image. @@ -1016,6 +1152,8 @@ From: File imgdouble.c =item i_img_pal_new(C, C, C, C) + i_img *img = i_img_pal_new(width, height, channels, max_palette_size) + Creates a new paletted image of the supplied dimensions. C is the maximum palette size and should normally be 256. @@ -1029,6 +1167,8 @@ From: File palimg.c =item i_sametype(C, C, C) + i_img *img = i_sametype(src, width, height); + Returns an image of the same type (sample size, channels, paletted/direct). For paletted images the palette is copied from the source. @@ -1040,6 +1180,8 @@ From: File image.c =item i_sametype_chans(C, C, C, C) + i_img *img = i_sametype_chans(src, width, height, channels); + Returns an image of the same type (sample size). For paletted images the equivalent direct type is returned. @@ -1050,6 +1192,8 @@ From: File image.c =item i_img_destroy(C) + i_img_destroy(img) + Destroy an image object @@ -1121,6 +1265,8 @@ From: File immacros.h =item i_img_get_height(C) + i_img_dim height = i_img_get_height(im); + Returns the height in pixels of the image. @@ -1129,6 +1275,8 @@ From: File image.c =item i_img_get_width(C) + i_img_dim width = i_img_get_width(im); + Returns the width in pixels of the image. @@ -1137,6 +1285,8 @@ From: File image.c =item i_img_getchannels(C) + int channels = i_img_getchannels(img); + Get the number of channels in C. @@ -1145,6 +1295,8 @@ From: File image.c =item i_img_getmask(C) + int mask = i_img_getmask(img); + Get the image channel mask for C. @@ -1192,6 +1344,9 @@ From: File image.c =item i_img_setmask(C, C) + // only channel 0 writeable + i_img_setmask(img, 0x01); + Set the image channel mask for C to C. The image channel mask gives some control over which channels can be @@ -1535,6 +1690,8 @@ From: File tags.c =item i_tags_set(tags, name, data, size) + i_tags_set(&img->tags, "i_comment", -1); + Sets the given tag to the string I If size is -1 then the strlen(I) bytes are stored. @@ -1579,6 +1736,9 @@ From: File tags.c =item i_tags_setn(C, C, C) + i_tags_setn(&img->tags, "i_xres", 204); + i_tags_setn(&img->tags, "i_yres", 196); + Sets the given tag to the integer C Even on failure, if an existing tag C exists, it will be @@ -1602,11 +1762,15 @@ Retrieve a C character from the stream. Modifies *p and *len to indicate the consumed characters. This doesn't support the extended C encoding used by later -versions of Perl. +versions of Perl. Since this is typically used to implement text +output by font drivers, the strings supplied shouldn't have such out +of range characters. This doesn't check that the C character is using the shortest possible representation. +Returns ~0UL on failure. + =for comment From: File io.c diff --git a/lib/Imager/Cookbook.pod b/lib/Imager/Cookbook.pod index 0724ec02..21bc3d52 100644 --- a/lib/Imager/Cookbook.pod +++ b/lib/Imager/Cookbook.pod @@ -292,7 +292,7 @@ Imager distribution for example code. You may also want to set limits on the size of the image read, using Imager's C method, documented in -L. For example: +L. For example: # limit to 10 million bytes of memory usage Imager->set_file_limits(bytes => 10_000_000); diff --git a/lib/Imager/Files.pod b/lib/Imager/Files.pod index 45faceb9..6c162571 100644 --- a/lib/Imager/Files.pod +++ b/lib/Imager/Files.pod @@ -341,7 +341,7 @@ C. =over -=item set_file_limits +=item set_file_limits() In some cases you will be receiving images from an untested source, such as submissions via CGI. To prevent such images from consuming @@ -376,10 +376,10 @@ pass are left as they were. Any limit of zero is treated as unlimited. -By default, all of the limits are zero, or unlimited. +By default, the width and height limits are zero, or unlimited. The +default memory size limit is one gigabyte. -You can reset all of the limited to their defaults by passing in the -reset parameter as a true value: +You can reset all limits to unlimited with the reset parameter: # no limits Imager->set_file_limits(reset=>1); @@ -393,7 +393,7 @@ pass: # only bytes is limited Imager->set_file_limits(reset=>1, bytes=>10_000_000); -=item get_file_limits +=item get_file_limits() You can get the current limits with the get_file_limits() method: diff --git a/limits.c b/limits.c index 6a524740..bd13917a 100644 --- a/limits.c +++ b/limits.c @@ -26,8 +26,8 @@ Setting a value of zero means that limit will be ignored. #include "imageri.h" -static int max_width, max_height; -static int max_bytes; +static i_img_dim max_width, max_height; +static size_t max_bytes = 0x40000000; /* =item i_set_image_file_limits(width, height, bytes) @@ -41,13 +41,27 @@ Setting a limit to 0 means that limit is ignored. Negative limits result in failure. +Parameters: + +=over + +=item * + +i_img_dim width, height - maximum width and height. + +=item * + +size_t bytes - maximum size in memory in bytes + +=back + Returns non-zero on success. =cut */ int -i_set_image_file_limits(int width, int height, int bytes) { +i_set_image_file_limits(i_img_dim width, i_img_dim height, size_t bytes) { i_clear_error(); if (width < 0) { @@ -78,11 +92,23 @@ i_set_image_file_limits(int width, int height, int bytes) { Retrieves the file limits set by i_set_image_file_limits(). +=over + +=item * + +i_img_dim *width, *height - the maximum width and height of the image. + +=item * + +size_t *bytes - size in memory of the image in bytes. + +=back + =cut */ int -i_get_image_file_limits(int *width, int *height, int *bytes) { +i_get_image_file_limits(i_img_dim *width, i_img_dim *height, size_t *bytes) { i_clear_error(); *width = max_width; @@ -112,30 +138,30 @@ This function is intended to be called by image file read functions. */ int -i_int_check_image_file_limits(int width, int height, int channels, int sample_size) { - int bytes; +i_int_check_image_file_limits(i_img_dim width, i_img_dim height, int channels, size_t sample_size) { + size_t bytes; i_clear_error(); if (width <= 0) { - i_push_errorf(0, "file size limit - image width of %d is not positive", - width); + i_push_errorf(0, "file size limit - image width of %" i_DF " is not positive", + i_DFc(width)); return 0; } if (max_width && width > max_width) { - i_push_errorf(0, "file size limit - image width of %d exceeds limit of %d", - width, max_width); + i_push_errorf(0, "file size limit - image width of %" i_DF " exceeds limit of %" i_DF, + i_DFc(width), i_DFc(max_width)); return 0; } if (height <= 0) { - i_push_errorf(0, "file size limit - image height %d is not positive", - height); + i_push_errorf(0, "file size limit - image height %" i_DF " is not positive", + i_DFc(height)); return 0; } if (max_height && height > max_height) { - i_push_errorf(0, "file size limit - image height of %d " - "exceeds limit of %d", height, max_height); + i_push_errorf(0, "file size limit - image height of %" i_DF + " exceeds limit of %" i_DF, i_DFc(height), i_DFc(max_height)); return 0; } @@ -146,8 +172,8 @@ i_int_check_image_file_limits(int width, int height, int channels, int sample_si } if (sample_size < 1 || sample_size > sizeof(long double)) { - i_push_errorf(0, "file size limit - sample_size %d out of range", - sample_size); + i_push_errorf(0, "file size limit - sample_size %ld out of range", + (long)sample_size); return 0; } @@ -163,8 +189,9 @@ i_int_check_image_file_limits(int width, int height, int channels, int sample_si } if (max_bytes) { if (bytes > max_bytes) { - i_push_errorf(0, "file size limit - storage size of %d " - "exceeds limit of %d", bytes, max_bytes); + i_push_errorf(0, "file size limit - storage size of %lu " + "exceeds limit of %lu", (unsigned long)bytes, + (unsigned long)max_bytes); return 0; } } diff --git a/log.c b/log.c index 05197707..0a807e70 100644 --- a/log.c +++ b/log.c @@ -2,6 +2,7 @@ #include "log.h" #include #include +#include "imerror.h" #ifdef IMAGER_LOG diff --git a/log.h b/log.h index 6cec6eb3..16b58310 100644 --- a/log.h +++ b/log.h @@ -4,6 +4,7 @@ #include #include #include +#include "imdatatypes.h" /* input: name of file to log too input: onoff, 0 means no logging @@ -13,7 +14,7 @@ int i_init_log( const char *name, int onoff ); void i_fatal ( int exitcode,const char *fmt, ... ); void i_lhead ( const char *file, int line ); -void i_loog(int level,const char *msg, ... ); +void i_loog(int level,const char *msg, ... ) I_FORMAT_ATTR(2,3); /* =item mm_log((level, format, ...)) diff --git a/map.c b/map.c index f1a6db5b..0431367f 100644 --- a/map.c +++ b/map.c @@ -37,7 +37,7 @@ maps im inplace into another image. void i_map(i_img *im, unsigned char (*maps)[256], unsigned int mask) { i_color *vals; - int x, y; + i_img_dim x, y; int i, ch; int minset = -1, maxset = 0; diff --git a/maskimg.c b/maskimg.c index a0b90477..828c3917 100644 --- a/maskimg.c +++ b/maskimg.c @@ -27,27 +27,27 @@ image. typedef struct { i_img *targ; i_img *mask; - int xbase, ybase; + i_img_dim xbase, ybase; i_sample_t *samps; /* temp space */ } i_img_mask_ext; #define MASKEXT(im) ((i_img_mask_ext *)((im)->ext_data)) static void i_destroy_masked(i_img *im); -static int i_ppix_masked(i_img *im, int x, int y, const i_color *pix); -static int i_ppixf_masked(i_img *im, int x, int y, const i_fcolor *pix); -static int i_plin_masked(i_img *im, int l, int r, int y, const i_color *vals); -static int i_plinf_masked(i_img *im, int l, int r, int y, const i_fcolor *vals); -static int i_gpix_masked(i_img *im, int x, int y, i_color *pix); -static int i_gpixf_masked(i_img *im, int x, int y, i_fcolor *pix); -static int i_glin_masked(i_img *im, int l, int r, int y, i_color *vals); -static int i_glinf_masked(i_img *im, int l, int r, int y, i_fcolor *vals); -static int i_gsamp_masked(i_img *im, int l, int r, int y, i_sample_t *samp, +static int i_ppix_masked(i_img *im, i_img_dim x, i_img_dim y, const i_color *pix); +static int i_ppixf_masked(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix); +static i_img_dim i_plin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals); +static i_img_dim i_plinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals); +static int i_gpix_masked(i_img *im, i_img_dim x, i_img_dim y, i_color *pix); +static int i_gpixf_masked(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix); +static i_img_dim i_glin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals); +static i_img_dim i_glinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals); +static i_img_dim i_gsamp_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samp, int const *chans, int chan_count); -static int i_gsampf_masked(i_img *im, int l, int r, int y, i_fsample_t *samp, +static i_img_dim i_gsampf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int const *chans, int chan_count); -static int i_gpal_masked(i_img *im, int l, int r, int y, i_palidx *vals); -static int i_ppal_masked(i_img *im, int l, int r, int y, const i_palidx *vals); +static i_img_dim i_gpal_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_palidx *vals); +static i_img_dim i_ppal_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_palidx *vals); /* =item IIM_base_masked @@ -92,7 +92,7 @@ static i_img IIM_base_masked = }; /* -=item i_img_masked_new(i_img *targ, i_img *mask, int xbase, int ybase, int w, int h) +=item i_img_masked_new(i_img *targ, i_img *mask, i_img_dim xbase, i_img_dim ybase, i_img_dim w, i_img_dim h) Create a new masked image. @@ -112,7 +112,7 @@ sample is treated as boolean. =cut */ -i_img *i_img_masked_new(i_img *targ, i_img *mask, int x, int y, int w, int h) { +i_img *i_img_masked_new(i_img *targ, i_img *mask, i_img_dim x, i_img_dim y, i_img_dim w, i_img_dim h) { i_img *im; i_img_mask_ext *ext; @@ -168,7 +168,7 @@ static void i_destroy_masked(i_img *im) { } /* -=item i_ppix_masked(i_img *im, int x, int y, const i_color *pix) +=item i_ppix_masked(i_img *im, i_img_dim x, i_img_dim y, const i_color *pix) Write a pixel to a masked image. @@ -176,7 +176,7 @@ Internal function. =cut */ -static int i_ppix_masked(i_img *im, int x, int y, const i_color *pix) { +static int i_ppix_masked(i_img *im, i_img_dim x, i_img_dim y, const i_color *pix) { i_img_mask_ext *ext = MASKEXT(im); int result; @@ -194,7 +194,7 @@ static int i_ppix_masked(i_img *im, int x, int y, const i_color *pix) { } /* -=item i_ppixf_masked(i_img *im, int x, int y, const i_fcolor *pix) +=item i_ppixf_masked(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) Write a pixel to a masked image. @@ -202,7 +202,7 @@ Internal function. =cut */ -static int i_ppixf_masked(i_img *im, int x, int y, const i_fcolor *pix) { +static int i_ppixf_masked(i_img *im, i_img_dim x, i_img_dim y, const i_fcolor *pix) { i_img_mask_ext *ext = MASKEXT(im); int result; @@ -220,7 +220,7 @@ static int i_ppixf_masked(i_img *im, int x, int y, const i_fcolor *pix) { } /* -=item i_plin_masked(i_img *im, int l, int r, int y, const i_color *vals) +=item i_plin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) Write a row of data to a masked image. @@ -228,17 +228,17 @@ Internal function. =cut */ -static int i_plin_masked(i_img *im, int l, int r, int y, const i_color *vals) { +static i_img_dim i_plin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) { i_img_mask_ext *ext = MASKEXT(im); if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; if (ext->mask) { - int i; + i_img_dim i; int simple = 0; i_sample_t *samps = ext->samps; - int w = r - l; + i_img_dim w = r - l; i_gsamp(ext->mask, l, r, y, samps, NULL, 1); if (w < 10) @@ -246,7 +246,7 @@ static int i_plin_masked(i_img *im, int l, int r, int y, const i_color *vals) { else { /* the idea is to make a fast scan to see how often the state changes */ - int changes = 0; + i_img_dim changes = 0; for (i = 0; i < w-1; ++i) if (!samps[i] != !samps[i+1]) ++changes; @@ -269,7 +269,7 @@ static int i_plin_masked(i_img *im, int l, int r, int y, const i_color *vals) { /* the scan above indicates there should be some contiguous regions, look for them and render */ - int start; + i_img_dim start; i = 0; while (i < w) { while (i < w && !samps[i]) @@ -286,7 +286,7 @@ static int i_plin_masked(i_img *im, int l, int r, int y, const i_color *vals) { } } else { - int result = i_plin(ext->targ, l + ext->xbase, r + ext->xbase, + i_img_dim result = i_plin(ext->targ, l + ext->xbase, r + ext->xbase, y + ext->ybase, vals); im->type = ext->targ->type; return result; @@ -298,7 +298,7 @@ static int i_plin_masked(i_img *im, int l, int r, int y, const i_color *vals) { } /* -=item i_plinf_masked(i_img *im, int l, int r, int y, const i_fcolor *vals) +=item i_plinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) Write a row of data to a masked image. @@ -306,16 +306,16 @@ Internal function. =cut */ -static int i_plinf_masked(i_img *im, int l, int r, int y, const i_fcolor *vals) { +static i_img_dim i_plinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_fcolor *vals) { i_img_mask_ext *ext = MASKEXT(im); if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; if (ext->mask) { - int i; + i_img_dim i; int simple = 0; i_sample_t *samps = ext->samps; - int w = r - l; + i_img_dim w = r - l; i_gsamp(ext->mask, l, r, y, samps, NULL, 1); if (w < 10) @@ -323,7 +323,7 @@ static int i_plinf_masked(i_img *im, int l, int r, int y, const i_fcolor *vals) else { /* the idea is to make a fast scan to see how often the state changes */ - int changes = 0; + i_img_dim changes = 0; for (i = 0; i < w-1; ++i) if (!samps[i] != !samps[i+1]) ++changes; @@ -346,7 +346,7 @@ static int i_plinf_masked(i_img *im, int l, int r, int y, const i_fcolor *vals) /* the scan above indicates there should be some contiguous regions, look for them and render */ - int start; + i_img_dim start; i = 0; while (i < w) { while (i < w && !samps[i]) @@ -363,7 +363,7 @@ static int i_plinf_masked(i_img *im, int l, int r, int y, const i_fcolor *vals) } } else { - int result = i_plinf(ext->targ, l + ext->xbase, r + ext->xbase, + i_img_dim result = i_plinf(ext->targ, l + ext->xbase, r + ext->xbase, y + ext->ybase, vals); im->type = ext->targ->type; return result; @@ -375,7 +375,7 @@ static int i_plinf_masked(i_img *im, int l, int r, int y, const i_fcolor *vals) } /* -=item i_gpix_masked(i_img *im, int x, int y, i_color *pix) +=item i_gpix_masked(i_img *im, i_img_dim x, i_img_dim y, i_color *pix) Read a pixel from a masked image. @@ -383,7 +383,7 @@ Internal. =cut */ -static int i_gpix_masked(i_img *im, int x, int y, i_color *pix) { +static int i_gpix_masked(i_img *im, i_img_dim x, i_img_dim y, i_color *pix) { i_img_mask_ext *ext = MASKEXT(im); if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) @@ -393,7 +393,7 @@ static int i_gpix_masked(i_img *im, int x, int y, i_color *pix) { } /* -=item i_gpixf_masked(i_img *im, int x, int y, i_fcolor *pix) +=item i_gpixf_masked(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) Read a pixel from a masked image. @@ -401,7 +401,7 @@ Internal. =cut */ -static int i_gpixf_masked(i_img *im, int x, int y, i_fcolor *pix) { +static int i_gpixf_masked(i_img *im, i_img_dim x, i_img_dim y, i_fcolor *pix) { i_img_mask_ext *ext = MASKEXT(im); if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) @@ -410,7 +410,7 @@ static int i_gpixf_masked(i_img *im, int x, int y, i_fcolor *pix) { return i_gpixf(ext->targ, x + ext->xbase, y + ext->ybase, pix); } -static int i_glin_masked(i_img *im, int l, int r, int y, i_color *vals) { +static i_img_dim i_glin_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) { i_img_mask_ext *ext = MASKEXT(im); if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -423,7 +423,7 @@ static int i_glin_masked(i_img *im, int l, int r, int y, i_color *vals) { } } -static int i_glinf_masked(i_img *im, int l, int r, int y, i_fcolor *vals) { +static i_img_dim i_glinf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fcolor *vals) { i_img_mask_ext *ext = MASKEXT(im); if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -436,7 +436,7 @@ static int i_glinf_masked(i_img *im, int l, int r, int y, i_fcolor *vals) { } } -static int i_gsamp_masked(i_img *im, int l, int r, int y, i_sample_t *samp, +static i_img_dim i_gsamp_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samp, int const *chans, int chan_count) { i_img_mask_ext *ext = MASKEXT(im); if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { @@ -450,7 +450,7 @@ static int i_gsamp_masked(i_img *im, int l, int r, int y, i_sample_t *samp, } } -static int i_gsampf_masked(i_img *im, int l, int r, int y, i_fsample_t *samp, +static i_img_dim i_gsampf_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_fsample_t *samp, int const *chans, int chan_count) { i_img_mask_ext *ext = MASKEXT(im); if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { @@ -464,7 +464,7 @@ static int i_gsampf_masked(i_img *im, int l, int r, int y, i_fsample_t *samp, } } -static int i_gpal_masked(i_img *im, int l, int r, int y, i_palidx *vals) { +static i_img_dim i_gpal_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_palidx *vals) { i_img_mask_ext *ext = MASKEXT(im); if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) @@ -477,16 +477,16 @@ static int i_gpal_masked(i_img *im, int l, int r, int y, i_palidx *vals) { } } -static int i_ppal_masked(i_img *im, int l, int r, int y, const i_palidx *vals) { +static i_img_dim i_ppal_masked(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_palidx *vals) { i_img_mask_ext *ext = MASKEXT(im); if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { if (r > im->xsize) r = im->xsize; if (ext->mask) { - int i; + i_img_dim i; i_sample_t *samps = ext->samps; - int w = r - l; - int start; + i_img_dim w = r - l; + i_img_dim start; i_gsamp(ext->mask, l, r, y, samps, NULL, 1); i = 0; diff --git a/palimg.c b/palimg.c index e151cd37..07720d9e 100644 --- a/palimg.c +++ b/palimg.c @@ -22,13 +22,13 @@ Basic 8-bit/sample paletted image #include "imageri.h" #define PALEXT(im) ((i_img_pal_ext*)((im)->ext_data)) -static int i_ppix_p(i_img *im, int x, int y, const i_color *val); -static int i_gpix_p(i_img *im, int x, int y, i_color *val); -static int i_glin_p(i_img *im, int l, int r, int y, i_color *vals); -static int i_plin_p(i_img *im, int l, int r, int y, const i_color *vals); -static int i_gsamp_p(i_img *im, int l, int r, int y, i_sample_t *samps, int const *chans, int chan_count); -static int i_gpal_p(i_img *pm, int l, int r, int y, i_palidx *vals); -static int i_ppal_p(i_img *pm, int l, int r, int y, const i_palidx *vals); +static int i_ppix_p(i_img *im, i_img_dim x, i_img_dim y, const i_color *val); +static int i_gpix_p(i_img *im, i_img_dim x, i_img_dim y, i_color *val); +static i_img_dim i_glin_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals); +static i_img_dim i_plin_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals); +static i_img_dim i_gsamp_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int const *chans, int chan_count); +static i_img_dim i_gpal_p(i_img *pm, i_img_dim l, i_img_dim r, i_img_dim y, i_palidx *vals); +static i_img_dim i_ppal_p(i_img *pm, i_img_dim l, i_img_dim r, i_img_dim y, const i_palidx *vals); static int i_addcolors_p(i_img *im, const i_color *color, int count); static int i_getcolors_p(i_img *im, int i, i_color *color, int count); static int i_colorcount_p(i_img *im); @@ -91,10 +91,10 @@ Returns a new image or NULL on failure. =cut */ i_img * -i_img_pal_new(int x, int y, int channels, int maxpal) { +i_img_pal_new(i_img_dim x, i_img_dim y, int channels, int maxpal) { i_img *im; i_img_pal_ext *palext; - int bytes, line_bytes; + size_t bytes, line_bytes; i_clear_error(); if (maxpal < 1 || maxpal > 256) { @@ -159,7 +159,7 @@ same width, height and channels. */ static void i_img_rgb_convert(i_img *targ, i_img *src) { i_color *row = mymalloc(sizeof(i_color) * targ->xsize); - int y; + i_img_dim y; for (y = 0; y < targ->ysize; ++y) { i_glin(src, 0, src->xsize, y, row); i_plin(targ, 0, src->xsize, y, row); @@ -263,7 +263,7 @@ static void i_destroy_p(i_img *im) { } /* -=item i_ppix_p(i_img *im, int x, int y, const i_color *val) +=item i_ppix_p(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) Write to a pixel in the image. @@ -273,7 +273,7 @@ present in the image. =cut */ static int -i_ppix_p(i_img *im, int x, int y, const i_color *val) { +i_ppix_p(i_img *im, i_img_dim x, i_img_dim y, const i_color *val) { i_palidx which; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) return -1; @@ -291,13 +291,13 @@ i_ppix_p(i_img *im, int x, int y, const i_color *val) { } /* -=item i_gpix_p(i_img *im, int x, int y, i_color *val) +=item i_gpix_p(i_img *im, i_img_dim x, i_img_dim y, i_color *val) Retrieve a pixel, converting from a palette index to a color. =cut */ -static int i_gpix_p(i_img *im, int x, int y, i_color *val) { +static int i_gpix_p(i_img *im, i_img_dim x, i_img_dim y, i_color *val) { i_palidx which; if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) { return -1; @@ -311,18 +311,18 @@ static int i_gpix_p(i_img *im, int x, int y, i_color *val) { } /* -=item i_glinp(i_img *im, int l, int r, int y, i_color *vals) +=item i_glinp(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) Retrieve a row of pixels. =cut */ -static int i_glin_p(i_img *im, int l, int r, int y, i_color *vals) { +static i_img_dim i_glin_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_color *vals) { if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { int palsize = PALEXT(im)->count; i_color *pal = PALEXT(im)->pal; i_palidx *data; - int count, i; + i_img_dim count, i; if (r > im->xsize) r = im->xsize; data = ((i_palidx *)im->idata) + l + y * im->xsize; @@ -340,7 +340,7 @@ static int i_glin_p(i_img *im, int l, int r, int y, i_color *vals) { } /* -=item i_plin_p(i_img *im, int l, int r, int y, const i_color *vals) +=item i_plin_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) Write a line of color data to the image. @@ -349,9 +349,9 @@ RGB. =cut */ -static int -i_plin_p(i_img *im, int l, int r, int y, const i_color *vals) { - int count, i; +static i_img_dim +i_plin_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_color *vals) { + i_img_dim count, i; i_palidx *data; i_palidx which; if (y >=0 && y < im->ysize && l < im->xsize && l >= 0) { @@ -377,18 +377,18 @@ i_plin_p(i_img *im, int l, int r, int y, const i_color *vals) { } /* -=item i_gsamp_p(i_img *im, int l, int r, int y, i_sample_t *samps, int chans, int chan_count) +=item i_gsamp_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int chans, int chan_count) =cut */ -static int i_gsamp_p(i_img *im, int l, int r, int y, i_sample_t *samps, +static i_img_dim i_gsamp_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_sample_t *samps, int const *chans, int chan_count) { int ch; if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { int palsize = PALEXT(im)->count; i_color *pal = PALEXT(im)->pal; i_palidx *data; - int count, i, w; + i_img_dim count, i, w; if (r > im->xsize) r = im->xsize; data = ((i_palidx *)im->idata) + l + y * im->xsize; @@ -435,15 +435,15 @@ static int i_gsamp_p(i_img *im, int l, int r, int y, i_sample_t *samps, } /* -=item i_gpal_p(i_img *im, int l, int r, int y, i_palidx *vals) +=item i_gpal_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_palidx *vals) =cut */ -static int i_gpal_p(i_img *im, int l, int r, int y, i_palidx *vals) { +static i_img_dim i_gpal_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, i_palidx *vals) { if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { i_palidx *data; - int i, w; + i_img_dim i, w; if (r > im->xsize) r = im->xsize; data = ((i_palidx *)im->idata) + l + y * im->xsize; @@ -459,15 +459,15 @@ static int i_gpal_p(i_img *im, int l, int r, int y, i_palidx *vals) { } /* -=item i_ppal_p(i_img *im, int l, int r, int y, const i_palidx *vals) +=item i_ppal_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_palidx *vals) =cut */ -static int i_ppal_p(i_img *im, int l, int r, int y, const i_palidx *vals) { +static i_img_dim i_ppal_p(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, const i_palidx *vals) { if (y >= 0 && y < im->ysize && l < im->xsize && l >= 0) { i_palidx *data; - int i, w; + i_img_dim i, w; if (r > im->xsize) r = im->xsize; data = ((i_palidx *)im->idata) + l + y * im->xsize; diff --git a/paste.im b/paste.im index 220e0177..8cd2b710 100644 --- a/paste.im +++ b/paste.im @@ -17,8 +17,8 @@ are swapped. */ void -i_copyto(i_img *im, i_img *src, int x1, int y1, int x2, int y2, int tx, int ty) { - int y, t, ttx, tty; +i_copyto(i_img *im, i_img *src, i_img_dim x1, i_img_dim y1, i_img_dim x2, i_img_dim y2, i_img_dim tx, i_img_dim ty) { + i_img_dim y, t, ttx, tty; if (x2bits == i_8_bits IM_COLOR *row = mymalloc(sizeof(IM_COLOR) * (x2-x1)); @@ -358,7 +359,7 @@ i_gsamp_bg #else i_gsampf_bg #endif -(i_img *im, int l, int r, int y, IM_SAMPLE_T *samples, +(i_img *im, i_img_dim l, i_img_dim r, i_img_dim y, IM_SAMPLE_T *samples, int out_channels, IM_COLOR const *bg) { if (out_channels == im->channels) return IM_GSAMP(im, l, r, y, samples, NULL, im->channels); @@ -368,10 +369,10 @@ i_gsampf_bg switch (im->channels) { case 2: { - int x; + i_img_dim x; IM_SAMPLE_T *inp = samples, *outp = samples; IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg)); - int count; + i_img_dim count; count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels); if (!count) @@ -401,9 +402,10 @@ i_gsampf_bg } case 2: { - int x, ch; + i_img_dim x; + int ch; IM_SAMPLE_T *inp = samples, *outp = samples; - int count; + i_img_dim count; int channels[4] = { 0, 0, 0, 1 }; count = IM_GSAMP(im, l, r, y, samples, channels, im->channels); @@ -424,9 +426,10 @@ i_gsampf_bg case 4: { - int x, ch; + i_img_dim x; + int ch; IM_SAMPLE_T *inp = samples, *outp = samples; - int count; + i_img_dim count; count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels); if (!count) diff --git a/pnm.c b/pnm.c index 906ab5e2..31afbd50 100644 --- a/pnm.c +++ b/pnm.c @@ -229,7 +229,13 @@ gnum(mbuf *mb, int *i) { if (!misnumber(*cp)) return 0; while( (cp = gpeek(mb)) && misnumber(*cp) ) { - *i = *i*10+(*cp-'0'); + int work = *i*10+(*cp-'0'); + if (work < *i) { + /* overflow */ + i_push_error(0, "integer overflow"); + return 0; + } + *i = work; cp = gnext(mb); } return 1; @@ -541,7 +547,7 @@ static i_img * i_readpnm_wiol_low( mbuf *buf, int allow_incomplete) { i_img* im; int type; - int width, height, maxval, channels, pcount; + int width, height, maxval, channels; int rounder; char *cp; @@ -630,7 +636,7 @@ i_readpnm_wiol_low( mbuf *buf, int allow_incomplete) { else if (maxval > 65535) { i_push_errorf(0, "maxval of %d is over 65535 - invalid pnm file", maxval); - mm_log((1, "i_readpnm: maxval of %d is over 65535 - invalid pnm file\n")); + mm_log((1, "i_readpnm: maxval of %d is over 65535 - invalid pnm file\n", maxval)); return NULL; } } else maxval=1; @@ -643,7 +649,6 @@ i_readpnm_wiol_low( mbuf *buf, int allow_incomplete) { } channels = (type == 3 || type == 6) ? 3:1; - pcount = width*height*channels; if (!i_int_check_image_file_limits(width, height, channels, sizeof(i_sample_t))) { mm_log((1, "i_readpnm: image size exceeds limits\n")); @@ -770,14 +775,14 @@ int write_pbm(i_img *im, io_glue *ig, int zero_is_white) { int x, y; i_palidx *line; - int write_size; + i_img_dim write_size; unsigned char *write_buf; unsigned char *writep; char header[255]; unsigned mask; - sprintf(header, "P4\012# CREATOR: Imager\012%d %d\012", - im->xsize, im->ysize); + sprintf(header, "P4\012# CREATOR: Imager\012%" i_DF " %" i_DF "\012", + i_DFc(im->xsize), i_DFc(im->ysize)); if (i_io_write(ig, header, strlen(header)) < 0) { i_push_error(0, "could not write pbm header"); return 0; @@ -815,10 +820,10 @@ write_pbm(i_img *im, io_glue *ig, int zero_is_white) { static int write_ppm_data_8(i_img *im, io_glue *ig, int want_channels) { - int write_size = im->xsize * want_channels; - int buf_size = im->xsize * im->channels; + size_t write_size = im->xsize * want_channels; + size_t buf_size = im->xsize * im->channels; unsigned char *data = mymalloc(buf_size); - int y = 0; + i_img_dim y = 0; int rc = 1; i_color bg; @@ -840,15 +845,15 @@ write_ppm_data_8(i_img *im, io_glue *ig, int want_channels) { static int write_ppm_data_16(i_img *im, io_glue *ig, int want_channels) { - int line_size = im->channels * im->xsize * sizeof(i_fsample_t); - int sample_count = want_channels * im->xsize; - int write_size = sample_count * 2; + size_t line_size = im->channels * im->xsize * sizeof(i_fsample_t); + size_t sample_count = want_channels * im->xsize; + size_t write_size = sample_count * 2; i_fsample_t *line_buf = mymalloc(line_size); i_fsample_t *samplep; unsigned char *write_buf = mymalloc(write_size); unsigned char *writep; - int sample_num; - int y = 0; + size_t sample_num; + i_img_dim y = 0; int rc = 1; i_fcolor bg; @@ -920,8 +925,8 @@ i_writeppm_wiol(i_img *im, io_glue *ig) { else maxval = 65535; - sprintf(header,"P%d\n#CREATOR: Imager\n%d %d\n%d\n", - type, im->xsize, im->ysize, maxval); + sprintf(header,"P%d\n#CREATOR: Imager\n%" i_DF " %" i_DF"\n%d\n", + type, i_DFc(im->xsize), i_DFc(im->ysize), maxval); if (ig->writecb(ig,header,strlen(header)) != strlen(header)) { i_push_error(errno, "could not write ppm header"); diff --git a/polygon.c b/polygon.c index a426b583..3ea18d7a 100644 --- a/polygon.c +++ b/polygon.c @@ -17,7 +17,7 @@ #endif -typedef int pcord; +typedef i_img_dim pcord; typedef struct { int n; @@ -38,14 +38,9 @@ typedef struct { double x; } p_slice; -typedef struct { - int start; - int stop; -} ss_pair; - typedef struct { int *line; /* temporary buffer for scanline */ - int linelen; /* length of scanline */ + i_img_dim linelen; /* length of scanline */ } ss_scanline; static @@ -126,7 +121,7 @@ ss_scanline_reset(ss_scanline *ss) { static void -ss_scanline_init(ss_scanline *ss, int linelen, int linepairs) { +ss_scanline_init(ss_scanline *ss, i_img_dim linelen, int linepairs) { ss->line = mymalloc( sizeof(int) * linelen ); ss->linelen = linelen; ss_scanline_reset(ss); @@ -329,10 +324,10 @@ render_slice_scanline(ss_scanline *ss, int y, p_line *l, p_line *r, pcord miny, pcord lminx, lmaxx; /* left line min/max within y bounds in fine coords */ pcord rminx, rmaxx; /* right line min/max within y bounds in fine coords */ - int cpix; /* x-coordinate of current pixel */ + i_img_dim cpix; /* x-coordinate of current pixel */ int thin; /* boolean for thin/thick segment */ - int startpix; /* temporary variable for "start of this interval" */ - int stoppix; /* temporary variable for "end of this interval" */ + i_img_dim startpix; /* temporary variable for "start of this interval" */ + i_img_dim stoppix; /* temporary variable for "end of this interval" */ /* Find the y bounds of scanline_slice */ @@ -415,10 +410,10 @@ render_slice_scanline(ss_scanline *ss, int y, p_line *l, p_line *r, pcord miny, static void i_poly_aa_low(i_img *im, int l, const double *x, const double *y, void *ctx, scanline_flusher flusher) { int i ,k; /* Index variables */ - int clc; /* Lines inside current interval */ + i_img_dim clc; /* Lines inside current interval */ /* initialize to avoid compiler warnings */ pcord tempy = 0; - int cscl = 0; /* Current scanline */ + i_img_dim cscl = 0; /* Current scanline */ ss_scanline templine; /* scanline accumulator */ p_point *pset; /* List of points in polygon */ @@ -458,8 +453,8 @@ i_poly_aa_low(i_img *im, int l, const double *x, const double *y, void *ctx, sca /* loop on intervals */ for(i=0; iysize); + i_img_dim startscan = i_max( coarse(pset[i].y), 0); + i_img_dim stopscan = i_min( coarse(pset[i+1].y+15), im->ysize); pcord miny, maxy; /* y bounds in fine coordinates */ POLY_DEB( pcord cc = (pset[i].y + pset[i+1].y)/2 ); @@ -556,8 +551,8 @@ struct poly_render_state { static void scanline_flush_render(i_img *im, ss_scanline *ss, int y, void *ctx) { - int x; - int left, right; + i_img_dim x; + i_img_dim left, right; struct poly_render_state *state = (struct poly_render_state *)ctx; left = 0; diff --git a/quant.c b/quant.c index 32938ac0..a37a1236 100644 --- a/quant.c +++ b/quant.c @@ -105,7 +105,7 @@ This function will fail if the supplied palette contains no colors. i_palidx * i_quant_translate(i_quantize *quant, i_img *img) { i_palidx *result; - int bytes; + size_t bytes; mm_log((1, "quant_translate(quant %p, img %p)\n", quant, img)); @@ -283,12 +283,13 @@ for each side of the cube, but this will require even more memory. static void makemap_addi(i_quantize *quant, i_img **imgs, int count) { cvec *clr; - int cnum, i, x, y, bst_idx=0, ld, cd, iter, currhb, img_num; + int cnum, i, bst_idx=0, ld, cd, iter, currhb, img_num; + i_img_dim x, y; i_sample_t *val; float dlt, accerr; hashbox *hb; i_mempool mp; - int maxwidth = 0; + i_img_dim maxwidth = 0; i_sample_t *line; const int *sample_indices; @@ -471,7 +472,7 @@ typedef struct { i_sample_t max[3]; /* maximum for each channel */ i_sample_t width[3]; /* width for each channel */ int start, size; /* beginning and size of the partition */ - int pixels; /* number of pixels represented by this partition */ + i_img_dim pixels; /* number of pixels represented by this partition */ } medcut_partition; /* @@ -537,11 +538,11 @@ static void makemap_mediancut(i_quantize *quant, i_img **imgs, int count) { quant_color_entry *colors; i_mempool mp; - int imgn, x, y, i, ch; - int max_width; + int imgn, i, ch; + i_img_dim x, y, max_width; i_color *line; int color_count; - int total_pixels; + i_img_dim total_pixels; medcut_partition *parts; int part_num; int in, out; @@ -790,7 +791,7 @@ makemap_palette(i_quantize *quant, i_img **imgs, int count) { if (eliminate_unused) { i_palidx *line = mymalloc(sizeof(i_palidx) * imgs[imgn]->xsize); - int x, y; + i_img_dim x, y; memset(used, 0, sizeof(used)); for (y = 0; y < imgs[imgn]->ysize; ++y) { @@ -1239,7 +1240,8 @@ static int rand2dist_find(i_color val, i_quantize *quant, i_dists *dists, int in #endif static void translate_addi(i_quantize *quant, i_img *img, i_palidx *out) { - int x, y, i, k, bst_idx = 0; + i_img_dim x, y, k; + int i, bst_idx = 0; i_color val; int pixdev = quant->perturb; CF_VARS; @@ -1333,9 +1335,9 @@ translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) { int mapw, maph, mapo; int i; errdiff_t *err; - int errw; + i_img_dim errw; int difftotal; - int x, y, dx, dy; + i_img_dim x, y, dx, dy; int bst_idx = 0; int is_gray = is_gray_map(quant); CF_VARS; @@ -1376,7 +1378,6 @@ translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) { for (y = 0; y < img->ysize; ++y) { for (x = 0; x < img->xsize; ++x) { i_color val; - long ld, cd; errdiff_t perr; i_gpix(img, x, y, &val); if (img->channels < 3) { @@ -1423,7 +1424,8 @@ translate_errdiff(i_quantize *quant, i_img *img, i_palidx *out) { static void prescan(i_img **imgs,int count, int cnum, cvec *clr, i_sample_t *line) { - int i,k,j,x,y; + int i,k,j; + i_img_dim x,y; i_sample_t *val; const int *chans; @@ -1665,7 +1667,7 @@ static void transparent_threshold(i_quantize *quant, i_palidx *data, i_img *img, i_palidx trans_index) { - int x, y; + i_img_dim x, y; i_sample_t *line = mymalloc(img->xsize * sizeof(i_sample_t)); int trans_chan = img->channels > 2 ? 3 : 1; @@ -1688,7 +1690,8 @@ transparent_errdiff(i_quantize *quant, i_palidx *data, i_img *img, int mapw, maph, mapo; int errw, *err, *errp; int difftotal, out, error; - int x, y, dx, dy, i; + i_img_dim x, y, dx, dy; + int i; i_sample_t *line; int trans_chan = img->channels > 2 ? 3 : 1; @@ -1847,7 +1850,7 @@ transparent_ordered(i_quantize *quant, i_palidx *data, i_img *img, i_palidx trans_index) { unsigned char *spot; - int x, y; + i_img_dim x, y; i_sample_t *line; int trans_chan = img->channels > 2 ? 3 : 1; if (quant->tr_orddith == od_custom) diff --git a/raw.c b/raw.c index 912aaf90..9159e5a6 100644 --- a/raw.c +++ b/raw.c @@ -29,8 +29,9 @@ static void -interleave(unsigned char *inbuffer,unsigned char *outbuffer,int rowsize,int channels) { - int ch,ind,i; +interleave(unsigned char *inbuffer,unsigned char *outbuffer,i_img_dim rowsize,int channels) { + i_img_dim ind,i; + int ch; i=0; if (inbuffer == outbuffer) return; /* Check if data is already in interleaved format */ for (ind=0; ind datachannels ? datachannels : storechannels; if (inbuffer == outbuffer) return; /* Check if data is already in expanded format */ @@ -55,21 +57,22 @@ expandchannels(unsigned char *inbuffer, unsigned char *outbuffer, } i_img * -i_readraw_wiol(io_glue *ig, int x, int y, int datachannels, int storechannels, int intrl) { +i_readraw_wiol(io_glue *ig, i_img_dim x, i_img_dim y, int datachannels, int storechannels, int intrl) { i_img* im; - int rc,k; + ssize_t rc; + i_img_dim k; unsigned char *inbuffer; unsigned char *ilbuffer; unsigned char *exbuffer; - int inbuflen,ilbuflen,exbuflen; + size_t inbuflen,ilbuflen,exbuflen; i_clear_error(); io_glue_commit_types(ig); - mm_log((1, "i_readraw(ig %p,x %d,y %d,datachannels %d,storechannels %d,intrl %d)\n", - ig, x, y, datachannels, storechannels, intrl)); + mm_log((1, "i_readraw(ig %p,x %" i_DF ",y %" i_DF ",datachannels %d,storechannels %d,intrl %d)\n", + ig, i_DFc(x), i_DFc(y), datachannels, storechannels, intrl)); if (intrl != 0 && intrl != 1) { i_push_error(0, "raw_interleave must be 0 or 1"); @@ -88,7 +91,8 @@ i_readraw_wiol(io_glue *ig, int x, int y, int datachannels, int storechannels, i ilbuflen = inbuflen; exbuflen = im->xsize*storechannels; inbuffer = (unsigned char*)mymalloc(inbuflen); - mm_log((1,"inbuflen: %d, ilbuflen: %d, exbuflen: %d.\n",inbuflen,ilbuflen,exbuflen)); + mm_log((1,"inbuflen: %ld, ilbuflen: %ld, exbuflen: %ld.\n", + (long)inbuflen, (long)ilbuflen, (long)exbuflen)); if (intrl==0) ilbuffer = inbuffer; else ilbuffer=mymalloc(inbuflen); @@ -130,7 +134,7 @@ i_readraw_wiol(io_glue *ig, int x, int y, int datachannels, int storechannels, i undef_int i_writeraw_wiol(i_img* im, io_glue *ig) { - int rc; + ssize_t rc; io_glue_commit_types(ig); i_clear_error(); @@ -148,10 +152,10 @@ i_writeraw_wiol(i_img* im, io_glue *ig) { if (im->type == i_direct_type) { /* just save it as 8-bits, maybe support saving higher bit count raw images later */ - int line_size = im->xsize * im->channels; + size_t line_size = im->xsize * im->channels; unsigned char *data = mymalloc(line_size); - int y = 0; + i_img_dim y = 0; rc = line_size; while (rc == line_size && y < im->ysize) { i_gsamp(im, 0, im->xsize, y, data, NULL, im->channels); @@ -167,10 +171,10 @@ i_writeraw_wiol(i_img* im, io_glue *ig) { /* paletted image - assumes the caller puts the palette somewhere else */ - int line_size = sizeof(i_palidx) * im->xsize; + size_t line_size = sizeof(i_palidx) * im->xsize; i_palidx *data = mymalloc(sizeof(i_palidx) * im->xsize); - int y = 0; + i_img_dim y = 0; rc = line_size; while (rc == line_size && y < im->ysize) { i_gpal(im, 0, im->xsize, y, data); diff --git a/regmach.c b/regmach.c index c3d629cf..64783432 100644 --- a/regmach.c +++ b/regmach.c @@ -168,7 +168,7 @@ static i_color make_rgb(int r, int g, int b, int a) { It isn't currently used for inequalities */ -#define n_epsilon(x, y) (abs(x)+abs(y))*0.001 +#define n_epsilon(x, y) (fabs(x)+fabs(y))*0.001 static i_color bcol = {{ 0 }}; i_color i_rm_run(struct rm_op codes[], size_t code_count, @@ -196,14 +196,14 @@ i_color i_rm_run(struct rm_op codes[], size_t code_count, break; case rbc_div: - if (abs(nb) < 1e-10) + if (fabs(nb) < 1e-10) nout = 1e10; else nout = na / nb; break; case rbc_mod: - if (abs(nb) > 1e-10) { + if (fabs(nb) > 1e-10) { nout = fmod(na, nb); } else { @@ -343,11 +343,11 @@ i_color i_rm_run(struct rm_op codes[], size_t code_count, break; case rbc_eq: - nout = abs(na-nb) <= n_epsilon(na,nb); + nout = fabs(na-nb) <= n_epsilon(na,nb); break; case rbc_ne: - nout = abs(na-nb) > n_epsilon(na,nb); + nout = fabs(na-nb) > n_epsilon(na,nb); break; case rbc_and: @@ -363,7 +363,7 @@ i_color i_rm_run(struct rm_op codes[], size_t code_count, break; case rbc_abs: - nout = abs(na); + nout = fabs(na); break; case rbc_ret: diff --git a/render.im b/render.im index 08129142..e17da1cf 100644 --- a/render.im +++ b/render.im @@ -353,16 +353,22 @@ i_render_fill(i_render *r, i_img_dim x, i_img_dim y, i_img_dim width, #/code } +#if 0 + +/* for debuggin */ + static void dump_src(const char *note, unsigned char const *src, i_img_dim width) { i_img_dim i; - printf("%s - %p/%d\n", note, src, width); + printf("%s - %p/%" i_DF "\n", note, src, i_DFc(width)); for (i = 0; i < width; ++i) { printf("%02x ", src[i]); } putchar('\n'); } +#endif + #code /* diff --git a/rotate.c b/rotate.c index bec2b8a6..90cf5912 100644 --- a/rotate.c +++ b/rotate.c @@ -22,7 +22,7 @@ Other rotations will be added as tuits become available. i_img *i_rotate90(i_img *src, int degrees) { i_img *targ; - int x, y; + i_img_dim x, y; i_clear_error(); @@ -80,8 +80,8 @@ i_img *i_rotate90(i_img *src, int degrees) { return targ; } else if (degrees == 270 || degrees == 90) { - int tx, txstart, txinc; - int ty, tystart, tyinc; + i_img_dim tx, txstart, txinc; + i_img_dim ty, tystart, tyinc; if (degrees == 270) { txstart = 0; @@ -222,12 +222,12 @@ static i_fcolor interp_i_fcolor(i_fcolor before, i_fcolor after, double pos, return out; } -i_img *i_matrix_transform_bg(i_img *src, int xsize, int ysize, const double *matrix, +i_img *i_matrix_transform_bg(i_img *src, i_img_dim xsize, i_img_dim ysize, const double *matrix, const i_color *backp, const i_fcolor *fbackp) { i_img *result = i_sametype(src, xsize, ysize); - int x, y; + i_img_dim x, y; int ch; - int i, j; + i_img_dim i, j; double sx, sy, sz; if (src->type == i_direct_type) { @@ -269,8 +269,8 @@ i_img *i_matrix_transform_bg(i_img *src, int xsize, int ysize, const double *mat && sx >= -1 && sx < src->xsize && sy >= -1 && sy < src->ysize) { - if (sx != (int)sx) { - if (sy != (int)sy) { + if (sx != (i_img_dim)sx) { + if (sy != (i_img_dim)sy) { i_color c[2][2]; i_color ci2[2]; for (i = 0; i < 2; ++i) @@ -290,7 +290,7 @@ i_img *i_matrix_transform_bg(i_img *src, int xsize, int ysize, const double *mat } } else { - if (sy != (int)sy) { + if (sy != (i_img_dim)sy) { i_color ci2[2]; for (i = 0; i < 2; ++i) if (i_gpix(src, sx, floor(sy)+i, ci2+i)) @@ -347,8 +347,8 @@ i_img *i_matrix_transform_bg(i_img *src, int xsize, int ysize, const double *mat && sx >= -1 && sx < src->xsize && sy >= -1 && sy < src->ysize) { - if (sx != (int)sx) { - if (sy != (int)sy) { + if (sx != (i_img_dim)sx) { + if (sy != (i_img_dim)sy) { i_fcolor c[2][2]; i_fcolor ci2[2]; for (i = 0; i < 2; ++i) @@ -368,7 +368,7 @@ i_img *i_matrix_transform_bg(i_img *src, int xsize, int ysize, const double *mat } } else { - if (sy != (int)sy) { + if (sy != (i_img_dim)sy) { i_fcolor ci2[2]; for (i = 0; i < 2; ++i) if (i_gpixf(src, sx, floor(sy)+i, ci2+i)) @@ -397,7 +397,7 @@ i_img *i_matrix_transform_bg(i_img *src, int xsize, int ysize, const double *mat i_palidx back = 0; i_color min; int minval = 256 * 4; - int ix, iy; + i_img_dim ix, iy; i_color want_back; i_fsample_t fsamp; @@ -451,8 +451,8 @@ i_img *i_matrix_transform_bg(i_img *src, int xsize, int ysize, const double *mat && sy >= -0.5 && sy < src->ysize-0.5) { /* all the world's an integer */ - ix = (int)(sx+0.5); - iy = (int)(sy+0.5); + ix = (i_img_dim)(sx+0.5); + iy = (i_img_dim)(sy+0.5); if (!i_gpal(src, ix, ix+1, iy, vals+x)) vals[i] = back; } @@ -468,7 +468,7 @@ i_img *i_matrix_transform_bg(i_img *src, int xsize, int ysize, const double *mat return result; } -i_img *i_matrix_transform(i_img *src, int xsize, int ysize, const double *matrix) { +i_img *i_matrix_transform(i_img *src, i_img_dim xsize, i_img_dim ysize, const double *matrix) { return i_matrix_transform_bg(src, xsize, ysize, matrix, NULL, NULL); } @@ -494,7 +494,7 @@ i_img *i_rotate_exact_bg(i_img *src, double amount, double rotate[9]; double xlate2[9] = { 0 }; double temp[9], matrix[9]; - int x1, x2, y1, y2, newxsize, newysize; + i_img_dim x1, x2, y1, y2, newxsize, newysize; /* first translate the centre of the image to (0,0) */ xlate1[0] = 1; @@ -514,10 +514,10 @@ i_img *i_rotate_exact_bg(i_img *src, double amount, rotate[7] = 0; rotate[8] = 1; - x1 = ceil(abs(src->xsize * rotate[0] + src->ysize * rotate[1])); - x2 = ceil(abs(src->xsize * rotate[0] - src->ysize * rotate[1])); - y1 = ceil(abs(src->xsize * rotate[3] + src->ysize * rotate[4])); - y2 = ceil(abs(src->xsize * rotate[3] - src->ysize * rotate[4])); + x1 = ceil(i_abs(src->xsize * rotate[0] + src->ysize * rotate[1])); + x2 = ceil(i_abs(src->xsize * rotate[0] - src->ysize * rotate[1])); + y1 = ceil(i_abs(src->xsize * rotate[3] + src->ysize * rotate[4])); + y2 = ceil(i_abs(src->xsize * rotate[3] - src->ysize * rotate[4])); newxsize = x1 > x2 ? x1 : x2; newysize = y1 > y2 ? y1 : y2; /* translate the centre back to the center of the image */ diff --git a/rubthru.im b/rubthru.im index a9577f92..796a9e8b 100644 --- a/rubthru.im +++ b/rubthru.im @@ -2,13 +2,13 @@ static int rubthru_targ_noalpha(i_img *im, i_img *src, - int tx, int ty, - int src_minx, int src_miny, - int src_maxx, int src_maxy) { - int x, y, ttx, tty; + 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) { + i_img_dim x, y, ttx, tty; int alphachan; int ch; - int width = src_maxx - src_minx; + i_img_dim width = src_maxx - src_minx; int want_channels; i_clear_error(); @@ -64,15 +64,15 @@ rubthru_targ_noalpha(i_img *im, i_img *src, } static int -rubthru_targ_alpha(i_img *im, i_img *src, int tx, int ty, - int src_minx, int src_miny, - int src_maxx, int src_maxy) { - int x, y, ttx, tty; +rubthru_targ_alpha(i_img *im, i_img *src, 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) { + i_img_dim x, y, ttx, tty; int want_channels; int alphachan; int ch; int targ_alpha_chan; - int width = src_maxx - src_minx; + i_img_dim width = src_maxx - src_minx; if (im->channels == 4 && (src->channels == 4 || src->channels == 2)) { alphachan = 3; @@ -98,7 +98,7 @@ rubthru_targ_alpha(i_img *im, i_img *src, int tx, int ty, tty = ty; for(y = src_miny; y < src_maxy; y++) { - int min_x, max_x; + i_img_dim min_x, max_x; IM_COLOR *srcp = src_line; IM_COLOR *destp = dest_line; IM_GLIN(src, src_minx, src_maxx, y, src_line); @@ -116,8 +116,8 @@ rubthru_targ_alpha(i_img *im, i_img *src, int tx, int ty, } if (max_x > min_x) { - int work_left = tx + min_x - src_minx; - int work_width = max_x - min_x; + i_img_dim work_left = tx + min_x - src_minx; + i_img_dim work_width = max_x - min_x; ttx = work_left; IM_GLIN(im, work_left, work_left + work_width, tty, dest_line); @@ -169,8 +169,8 @@ unmodified. */ int -i_rubthru(i_img *im, i_img *src, int tx, int ty, int src_minx, int src_miny, - int src_maxx, int src_maxy) { +i_rubthru(i_img *im, i_img *src, 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) { if (src_minx < 0) { tx -= src_minx; src_minx = 0; diff --git a/scale.im b/scale.im index 36ed2a56..4e45a300 100644 --- a/scale.im +++ b/scale.im @@ -24,15 +24,15 @@ static void -zero_row(i_fcolor *row, int width, int channels); +zero_row(i_fcolor *row, i_img_dim width, int channels); #code static void IM_SUFFIX(accum_output_row)(i_fcolor *accum, double fraction, IM_COLOR const *in, - int width, int channels); + i_img_dim width, int channels); static void -IM_SUFFIX(horizontal_scale)(IM_COLOR *out, int out_width, - i_fcolor const *in, int in_width, +IM_SUFFIX(horizontal_scale)(IM_COLOR *out, i_img_dim out_width, + i_fcolor const *in, i_img_dim in_width, int channels); #/code @@ -49,26 +49,27 @@ Adapted from pnmscale. =cut */ i_img * -i_scale_mixing(i_img *src, int x_out, int y_out) { +i_scale_mixing(i_img *src, i_img_dim x_out, i_img_dim y_out) { i_img *result; i_fcolor *accum_row = NULL; - int x, y, ch; - int accum_row_bytes; + i_img_dim x, y; + int ch; + size_t accum_row_bytes; double rowsleft, fracrowtofill; - int rowsread; + i_img_dim rowsread; double y_scale; - mm_log((1, "i_scale_mixing(src %p, x_out %d, y_out %d)\n", - src, x_out, y_out)); + mm_log((1, "i_scale_mixing(src %p, out(" i_DFp "))\n", + src, i_DFcp(x_out, y_out))); i_clear_error(); if (x_out <= 0) { - i_push_errorf(0, "output width %d invalid", x_out); + i_push_errorf(0, "output width %" i_DF " invalid", i_DFc(x_out)); return NULL; } if (y_out <= 0) { - i_push_errorf(0, "output height %d invalid", y_out); + i_push_errorf(0, "output height %" i_DF " invalid", i_DFc(y_out)); return NULL; } @@ -93,7 +94,7 @@ i_scale_mixing(i_img *src, int x_out, int y_out) { #code src->bits <= 8 IM_COLOR *in_row = NULL; IM_COLOR *xscale_row = NULL; - int in_row_bytes, out_row_bytes; + size_t in_row_bytes, out_row_bytes; in_row_bytes = sizeof(IM_COLOR) * src->xsize; if (in_row_bytes / sizeof(IM_COLOR) != src->xsize) { @@ -115,7 +116,8 @@ i_scale_mixing(i_img *src, int x_out, int y_out) { if (y_out == src->ysize) { /* no vertical scaling, just load it */ #ifdef IM_EIGHT_BIT - int x, ch; + i_img_dim x; + int ch; /* load and convert to doubles */ IM_GLIN(src, 0, src->xsize, y, in_row); for (x = 0; x < src->xsize; ++x) { @@ -166,7 +168,8 @@ i_scale_mixing(i_img *src, int x_out, int y_out) { /* we've accumulated a vertically scaled row */ if (x_out == src->xsize) { #if IM_EIGHT_BIT - int x, ch; + i_img_dim x; + int ch; /* no need to scale, but we need to convert it */ if (result->channels == 2 || result->channels == 4) { int alpha_chan = result->channels - 1; @@ -218,8 +221,8 @@ i_scale_mixing(i_img *src, int x_out, int y_out) { } static void -zero_row(i_fcolor *row, int width, int channels) { - int x; +zero_row(i_fcolor *row, i_img_dim width, int channels) { + i_img_dim x; int ch; /* with IEEE floats we could just use memset() but that's not @@ -236,8 +239,9 @@ zero_row(i_fcolor *row, int width, int channels) { static void IM_SUFFIX(accum_output_row)(i_fcolor *accum, double fraction, IM_COLOR const *in, - int width, int channels) { - int x, ch; + i_img_dim width, int channels) { + i_img_dim x; + int ch; /* it's tempting to change this into a pointer iteration loop but modern CPUs do the indexing as part of the instruction */ @@ -259,12 +263,12 @@ IM_SUFFIX(accum_output_row)(i_fcolor *accum, double fraction, IM_COLOR const *in } static void -IM_SUFFIX(horizontal_scale)(IM_COLOR *out, int out_width, - i_fcolor const *in, int in_width, +IM_SUFFIX(horizontal_scale)(IM_COLOR *out, i_img_dim out_width, + i_fcolor const *in, i_img_dim in_width, int channels) { double frac_col_to_fill, frac_col_left; - int in_x; - int out_x; + i_img_dim in_x; + i_img_dim out_x; double x_scale = (double)out_width / in_width; int ch; double accum[MAXCHANNELS] = { 0 }; diff --git a/t/t01introvert.t b/t/t01introvert.t index 5b3e5975..296d2304 100644 --- a/t/t01introvert.t +++ b/t/t01introvert.t @@ -236,7 +236,7 @@ cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/, SKIP: { use Config; - skip("don't want to allocate 4Gb", 8) unless $Config{intsize} == 4; + skip("don't want to allocate 4Gb", 8) unless $Config{ptrsize} == 4; my $uint_range = 256 ** $Config{intsize}; print "# range $uint_range\n"; diff --git a/t/t021sixteen.t b/t/t021sixteen.t index a49e53fc..5315bc88 100644 --- a/t/t021sixteen.t +++ b/t/t021sixteen.t @@ -147,8 +147,8 @@ cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/, # type of exit SKIP: { use Config; - $Config{intsize} == 4 - or skip("don't want to allocate 4Gb", 8); + $Config{ptrsize} == 4 + or skip("don't want to allocate 4Gb", 10); my $uint_range = 256 ** $Config{intsize}; print "# range $uint_range\n"; my $dim1 = int(sqrt($uint_range/2))+1; diff --git a/t/t022double.t b/t/t022double.t index 79aee302..22d97afa 100644 --- a/t/t022double.t +++ b/t/t022double.t @@ -108,7 +108,7 @@ cmp_ok(Imager->errstr, '=~', qr/channels must be between 1 and 4/, use Config; SKIP: { - $Config{intsize} == 4 + $Config{ptrsize} == 4 or skip "don't want to allocate 4Gb", 8; my $uint_range = 256 ** $Config{intsize}; my $dbl_size = $Config{doublesize} || 8; diff --git a/t/t023palette.t b/t/t023palette.t index a7ed1b0c..c0ec8cac 100644 --- a/t/t023palette.t +++ b/t/t023palette.t @@ -145,7 +145,7 @@ cmp_ok(Imager->errstr, '=~', qr/Channels must be positive and <= 4/, SKIP: { skip("don't want to allocate 4Gb", 10) - unless $Config{intsize} == 4; + unless $Config{ptrsize} == 4; my $uint_range = 256 ** $Config{intsize}; my $dim1 = int(sqrt($uint_range))+1; @@ -180,7 +180,7 @@ cmp_ok(Imager->errstr, '=~', qr/Channels must be positive and <= 4/, # test the scanline allocation check # divide by 2 to get int range, by 3 so that the image (one byte/pixel) # doesn't integer overflow, but the scanline of i_color (4/pixel) does - my $dim4 = $uint_range / 2 / 3; + my $dim4 = $uint_range / 3; my $im_o = Imager->new(xsize=>$dim4, ysize=>1, channels=>3, type=>'paletted'); is($im_o, undef, "integer overflow check - scanline size"); cmp_ok(Imager->errstr, '=~', diff --git a/t/t1000files.t b/t/t1000files.t index f28c6229..b0baac61 100644 --- a/t/t1000files.t +++ b/t/t1000files.t @@ -49,10 +49,10 @@ PERL # test the file limit functions # by default the limits are zero (unlimited) print "# image file limits\n"; -is_deeply([ Imager->get_file_limits() ], [0, 0, 0], +is_deeply([ Imager->get_file_limits() ], [0, 0, 0x40000000 ], "check defaults"); ok(Imager->set_file_limits(width=>100), "set only width"); -is_deeply([ Imager->get_file_limits() ], [100, 0, 0 ], +is_deeply([ Imager->get_file_limits() ], [100, 0, 0x40000000 ], "check width set"); ok(Imager->set_file_limits(height=>150, bytes=>10000), "set height and bytes"); diff --git a/t/t104ppm.t b/t/t104ppm.t index 2cb3ac9f..b6f95268 100644 --- a/t/t104ppm.t +++ b/t/t104ppm.t @@ -1,6 +1,6 @@ #!perl -w use Imager ':all'; -use Test::More tests => 191; +use Test::More tests => 195; use strict; use Imager::Test qw(test_image_raw test_image_16 is_color3 is_color1 is_image); @@ -596,6 +596,21 @@ print "# check error handling\n"; Imager->close_log; +{ # image too large handling + { + ok(!Imager->new(file => "testimg/toowide.ppm", filetype => "pnm"), + "fail to read a too wide image"); + is(Imager->errstr, "unable to read pnm image: could not read image width: integer overflow", + "check error message"); + } + { + ok(!Imager->new(file => "testimg/tootall.ppm", filetype => "pnm"), + "fail to read a too wide image"); + is(Imager->errstr, "unable to read pnm image: could not read image height: integer overflow", + "check error message"); + } +} + unless ($ENV{IMAGER_KEEP_FILES}) { unlink "testout/t104ppm.log"; unlink map "testout/$_", @files; diff --git a/t/t107bmp.t b/t/t107bmp.t index 85e3f9ba..0129ea83 100644 --- a/t/t107bmp.t +++ b/t/t107bmp.t @@ -140,14 +140,15 @@ my @tests = 'bad compression (24-bit)' ], ); use Config; -my $intsize = $Config{intsize}; +my $ptrsize = $Config{ptrsize}; for my $test (@tests) { my ($file, $error, $comment, $bit32only) = @$test; SKIP: { skip("only tested on 32-bit machines", 2) - if $bit32only && $intsize != 4; + if $bit32only && $ptrsize != 4; ok(!$imoo->read(file=>"testimg/$file"), $comment); + print "# ", $imoo->errstr, "\n"; is($imoo->errstr, $error, "check error message"); } } diff --git a/t/t108tga.t b/t/t108tga.t index fd502c00..11be19ec 100644 --- a/t/t108tga.t +++ b/t/t108tga.t @@ -1,7 +1,7 @@ #!perl -w use Imager qw(:all); use strict; -use Test::More tests=>46; +use Test::More tests=>66; use Imager::Test qw(is_color4 is_image); -d "testout" or mkdir "testout"; @@ -155,6 +155,83 @@ is($compressed, 1, "check compressed tag"); is_image($im, $im2, "check they match"); } +{ # prior to the types re-work we treated the tga xsize/ysize as + # signed short, which is wrong + SKIP: + { + my $im = Imager->new(xsize => 40960, ysize => 1); + my $data; + ok($im->write(data => \$data, type => "tga"), + "write a wide (but not too wide) image out"); + my $im2 = Imager->new(data => $data); + ok($im2, "read it back in") + or skip("Couldn't read the wide image", 2); + is($im2->getwidth, 40960, "make sure the width survived the trip"); + is($im2->getheight, 1, "make sure the height survived the trip"); + } + + SKIP: + { + my $im = Imager->new(xsize => 1, ysize => 40960); + my $data; + ok($im->write(data => \$data, type => "tga"), + "write a tall (but not too tall) image out"); + my $im2 = Imager->new(data => $data); + ok($im2, "read it back in") + or skip("Couldn't read the tall image", 2); + is($im2->getwidth, 1, "make sure the width survived the trip"); + is($im2->getheight, 40960, "make sure the height survived the trip"); + } +} + +{ + # TGA files are limited to 0xFFFF x 0xFFFF pixels + my $max_dim = 0xFFFF; + { + my $im = Imager->new(xsize => 1+$max_dim, ysize => 1); + my $data = ''; + ok(!$im->write(data => \$data, type => "tga"), + "fail to write too wide an image"); + is($im->errstr, "image too large for TGA", + "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 => "tga"), + "write image at width limit") + or print "# ", $im->errstr, "\n"; + my $im2 = Imager->new(data => $data, ftype => "tga"); + 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 => "tga"), + "fail to write too tall an image"); + is($im->errstr, "image too large for TGA", + "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 => "tga"), + "write image at width limit"); + my $im2 = Imager->new(data => $data, ftype => "tga"); + 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"); + } +} + sub write_test { my ($im, $filename, $wierdpack, $compress, $idstring) = @_; local *FH; diff --git a/t/t64copyflip.t b/t/t64copyflip.t index 58a6ff94..15526e3b 100644 --- a/t/t64copyflip.t +++ b/t/t64copyflip.t @@ -201,7 +201,10 @@ sub rot_test { my $work = $rot->convert(preset => 'noalpha'); my $im_pal = $work->to_paletted(make_colors => 'mediancut'); my @colors = $im_pal->getcolors; - is(@colors, 2, "should be only 2 colors"); + is(@colors, 2, "should be only 2 colors") + or do { + print "# ", join(",", $_->rgba), "\n" for @colors; + }; @colors = sort { ($a->rgba)[0] <=> ($b->rgba)[0] } @colors; is_color3($colors[0], 0, 0, 0, "check we got black"); is_color3($colors[1], 255, 0, 0, "and red"); diff --git a/testimg/tootall.ppm b/testimg/tootall.ppm new file mode 100644 index 00000000..3af85ee2 --- /dev/null +++ b/testimg/tootall.ppm @@ -0,0 +1,5 @@ +P6 +1 +999999999999999999999999999999999999999999999999999999999999999999999999999999 +65535 +# we don't get this far \ No newline at end of file diff --git a/testimg/toowide.ppm b/testimg/toowide.ppm new file mode 100644 index 00000000..6f9f8609 --- /dev/null +++ b/testimg/toowide.ppm @@ -0,0 +1,5 @@ +P6 +999999999999999999999999999999999999999999999999999999999999999999999999999999 +1 +65535 +# we don't get this far \ No newline at end of file diff --git a/tga.c b/tga.c index 96e1f944..ac02f503 100644 --- a/tga.c +++ b/tga.c @@ -46,8 +46,8 @@ typedef struct { char colourmapdepth; short int x_origin; short int y_origin; - short width; - short height; + int width; + int height; char bitsperpixel; char imagedescriptor; } tga_header; @@ -57,7 +57,7 @@ typedef enum { NoInit, Raw, Rle } rle_state; typedef struct { int compressed; - int bytepp; + size_t bytepp; rle_state state; unsigned char cval[4]; int len; @@ -72,7 +72,7 @@ typedef struct { io_glue *ig; } tga_dest; - +#define TGA_MAX_DIM 0xFFFF /* =item bpp_to_bytes(bpp) @@ -86,7 +86,7 @@ Convert bits per pixel into bytes per pixel static -int +size_t bpp_to_bytes(unsigned int bpp) { switch (bpp) { case 8: @@ -590,7 +590,7 @@ static int tga_palette_write(io_glue *ig, i_img *img, int bitspp, int colourmaplength) { int i; - int bytepp = bpp_to_bytes(bitspp); + size_t bytepp = bpp_to_bytes(bitspp); size_t palbsize = i_colorcount(img)*bytepp; unsigned char *palbuf = mymalloc(palbsize); @@ -664,6 +664,7 @@ i_readtga_wiol(io_glue *ig, int length) { mm_log((1,"Descriptor: %d\n",header.imagedescriptor)); if (header.idlength) { + /* max of 256, so this is safe */ idstring = mymalloc(header.idlength+1); if (ig->readcb(ig, idstring, header.idlength) != header.idlength) { i_push_error(errno, "short read on targa idstring"); @@ -781,7 +782,9 @@ i_readtga_wiol(io_glue *ig, int length) { } /* Allocate buffers */ + /* width is max 0xffff, src.bytepp is max 4, so this is safe */ databuf = mymalloc(width*src.bytepp); + /* similarly here */ if (!mapped) linebuf = mymalloc(width*sizeof(i_color)); for(y=0; ytype == i_palette_type; - mm_log((1,"i_writetga_wiol(img %p, ig %p, idstring %p, idlen %d, wierdpack %d, compress %d)\n", - img, ig, idstring, idlen, wierdpack, compress)); + mm_log((1,"i_writetga_wiol(img %p, ig %p, idstring %p, idlen %ld, wierdpack %d, compress %d)\n", + img, ig, idstring, (long)idlen, wierdpack, compress)); mm_log((1, "virtual %d, paletted %d\n", img->virtual, mapped)); mm_log((1, "channels %d\n", img->channels)); i_clear_error(); - io_glue_commit_types(ig); + + if (img->xsize > TGA_MAX_DIM || img->ysize > TGA_MAX_DIM) { + i_push_error(0, "image too large for TGA"); + return 0; + } switch (img->channels) { case 1: @@ -930,8 +937,8 @@ i_writetga_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idst } } else { /* direct type */ int x, y; - int bytepp = wierdpack ? 2 : bpp_to_bytes(bitspp); - int lsize = bytepp * img->xsize; + size_t bytepp = wierdpack ? 2 : bpp_to_bytes(bitspp); + size_t lsize = bytepp * img->xsize; i_color *vals = mymalloc(img->xsize*sizeof(i_color)); unsigned char *buf = mymalloc(lsize); diff --git a/trans2.c b/trans2.c index 37198930..b1656f94 100644 --- a/trans2.c +++ b/trans2.c @@ -29,14 +29,14 @@ over the image - most of the work is done in L =cut */ -i_img* i_transform2(int width, int height, int channels, +i_img* i_transform2(i_img_dim width, i_img_dim height, int channels, struct rm_op *ops, int ops_count, double *n_regs, int n_regs_count, i_color *c_regs, int c_regs_count, i_img **in_imgs, int in_imgs_count) { i_img *new_img; - int x, y; + i_img_dim x, y; i_color val; int i; int need_images; diff --git a/typemap b/typemap index 74d5ae71..12b37be5 100644 --- a/typemap +++ b/typemap @@ -25,6 +25,8 @@ Imager__IO T_PTROBJ_INV # mostly intended for non-Imager-core use Imager T_IMAGER_FULL_IMAGE +off_t T_OFF_T + ############################################################################# INPUT T_PTR_NULL @@ -84,6 +86,8 @@ T_PTROBJ_INV else croak(\"$var is not of type ${(my $ntt=$ntype)=~s/__/::/g;\$ntt}\"); +T_OFF_T + $var = i_sv_off_t(aTHX_ $arg); ############################################################################# OUTPUT @@ -116,3 +120,5 @@ T_IMAGER_FULL_IMAGE else { $arg = &PL_sv_undef; } +T_OFF_T + $arg = i_new_sv_off_t(aTHX_ $var); -- 2.39.5