From 541e1a319698050d349a96b1748e560a6cb7ea1e Mon Sep 17 00:00:00 2001 From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org> Date: Mon, 6 Apr 1998 04:37:00 +0200 Subject: [PATCH] encoding works (just RGB and RGBA, but that'll do for now) + bugfix Rev: src/modules/Image/encodings/png.c:1.9 --- src/modules/Image/encodings/png.c | 155 +++++++++++++++++++++++------- 1 file changed, 119 insertions(+), 36 deletions(-) diff --git a/src/modules/Image/encodings/png.c b/src/modules/Image/encodings/png.c index fe2eee9238..9935872a94 100644 --- a/src/modules/Image/encodings/png.c +++ b/src/modules/Image/encodings/png.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: png.c,v 1.8 1998/04/06 00:51:24 mirar Exp $"); +RCSID("$Id: png.c,v 1.9 1998/04/06 02:37:00 mirar Exp $"); #include "config.h" @@ -36,6 +36,8 @@ static struct pike_string *param_background; void f_add(INT32 args); void f_aggregate(INT32 args); +void f_index(INT32 args); + /* **! module Image @@ -1031,14 +1033,12 @@ static void image_png__decode(INT32 args) { ct=(struct neo_colortable*) get_storage(sp[-1].u.object,image_colortable_program); - push_string(param_palette); - param_palette->refs++; + push_string(param_palette); param_palette->refs++; mapping_insert(m,sp-1,sp-2); } else { - push_string(param_spalette); - param_spalette->refs++; + push_string(param_spalette); param_spalette->refs++; mapping_insert(m,sp-1,sp-2); } pop_n_elems(2); @@ -1112,8 +1112,7 @@ static void image_png__decode(INT32 args) break; } f_aggregate(3); - push_string(param_background); - param_background->refs++; + push_string(param_background); param_background->refs++; mapping_insert(m,sp-1,sp-2); pop_n_elems(2); break; @@ -1282,8 +1281,7 @@ static void image_png__decode(INT32 args) /* --- done, store in mapping --- */ - push_string(param_image); - param_image->refs++; + push_string(param_image); param_image->refs++; push_object(clone_object(image_program,0)); img=(struct image*)get_storage(sp[-1].u.object,image_program); if (img->img) free(img->img); /* protect from memleak */ @@ -1295,8 +1293,7 @@ static void image_png__decode(INT32 args) if (wa1) { - push_string(param_alpha); - param_image->refs++; + push_string(param_alpha); param_alpha->refs++; push_object(clone_object(image_program,0)); img=(struct image*)get_storage(sp[-1].u.object,image_program); if (img->img) free(img->img); /* protect from memleak */ @@ -1344,35 +1341,123 @@ static void image_png__decode(INT32 args) **! **! <pre> **! normal options: -**! "quality":0..100 -**! Set quality of result. Default is 75. -**! "optimize":0|1 -**! Optimize Huffman table. Default is on (1) for -**! images smaller than 50kpixels. -**! "progressive":0|1 -**! Make a progressive JPEG. Default is off. +**! "alpha":image object +**! Use this image as alpha channel +**! (Note that PNG alpha channel is grey. +**! The values are calculated by (r+2g+b)/3.) **! -**! advanced options: -**! "smooth":1..100 -**! Smooth input. Value is strength. -**! "method":JPEG.IFAST|JPEG.ISLOW|JPEG.FLOAT|JPEG.DEFAULT|JPEG.FASTEST -**! DCT method to use. -**! DEFAULT and FASTEST is from the jpeg library, -**! probably ISLOW and IFAST respective. -**! -**! wizard options: -**! "baseline":0|1 -**! Force baseline output. Useful for quality<20. **! </pre> **! **! note -**! Please read some about JPEG files. A quality -**! setting of 100 does not mean the result is -**! lossless. +**! Please read some about PNG files. */ static void image_png_encode(INT32 args) { + struct image *img,*alpha=NULL; + rgb_group *s,*sa; + + int n=0,y,x; + char buf[20]; + + if (!args) + error("Image.PNG.encode: too few arguments\n"); + + if (sp[-args].type!=T_OBJECT || + !(img=(struct image*) + get_storage(sp[-args].u.object,image_program))) + error("Image.PNG.encode: illegal argument 1\n"); + + if (!img->img) + error("Image.PNG.encode: no image\n"); + + if (args>1) + { + if (sp[1-args].type!=T_MAPPING) + error("Image.PNG.encode: illegal argument 2\n"); + + push_svalue(sp+1-args); + push_string(param_alpha); param_alpha->refs++; + f_index(2); + if (!(sp[-1].type==T_INT + && sp[-1].subtype==NUMBER_UNDEFINED)) + if (sp[-1].type!=T_OBJECT || + !(alpha=(struct image*) + get_storage(sp[-1].u.object,image_program))) + error("Image.PNG.encode: option (arg 2) \"alpha\" has illegal type\n"); + if (alpha && + (alpha->xsize!=img->xsize || + alpha->ysize!=img->ysize)) + error("Image.PNG.encode option (arg 2) \"alpha\"; images differ in size\n"); + if (alpha && !alpha->img) + error("Image.PNG.encode option (arg 2) \"alpha\"; no image\n"); + } + + sprintf(buf,"%c%c%c%c%c%c%c%c", + 137,'P','N','G',13,10,26,10); + push_string(make_shared_binary_string(buf,8)); + n++; + + sprintf(buf,"%c%c%c%c%c%c%c%c%c%c%c%c%c", + (img->xsize>>24)&255,(img->xsize>>16)&255, + (img->xsize>>8)&255,(img->xsize)&255, + (img->ysize>>24)&255,(img->ysize>>16)&255, + (img->ysize>>8)&255,(img->ysize)&255, + 8 /* bpp */, + alpha?6:2 /* type (RGBA/RGB) */, + 0 /* compression */, + 0 /* filter */, + 0 /* interlace */); + push_string(make_shared_binary_string(buf,13)); + + push_png_chunk("IHDR",NULL); + n++; + + y=img->ysize; + s=img->img; + if (alpha) sa=alpha->img; + while (y--) + { + struct pike_string *ps; + unsigned char *d; + ps=begin_shared_string(img->xsize*(3+!!alpha)+1); + d=(unsigned char*)ps->str; + x=img->xsize; + *(d++)=0; /* filter */ + if (alpha) + while (x--) + { + *(d++)=s->r; + *(d++)=s->g; + *(d++)=s->b; + *(d++)=(sa->r+sa->g*2+sa->b)>>2; + s++; + sa++; + } + else + while (x--) + { + *(d++)=s->r; + *(d++)=s->g; + *(d++)=s->b; + s++; + } + push_string(end_shared_string(ps)); + } + f_add(img->ysize); + png_compress(0); + push_png_chunk("IDAT",NULL); + n++; + + push_string(make_shared_binary_string("",0)); + push_png_chunk("IEND",NULL); + n++; + + f_add(n); + sp--; + pop_n_elems(args); + *sp=sp[args]; + sp++; } /* @@ -1390,8 +1475,6 @@ static void image_png_encode(INT32 args) **! Throws upon error in data. */ -void f_index(INT32 args); - static void image_png_decode(INT32 args) { if (!args) @@ -1424,7 +1507,7 @@ static void image_png_decode_alpha(INT32 args) push_int(255); push_int(255); push_int(255); - push_object(clone_object(image_program,3)); + push_object(clone_object(image_program,5)); } free_svalue(&s); } @@ -1501,7 +1584,7 @@ struct object *init_image_png(void) "function(string,void|mapping(string:int):object)",0); } add_function("encode",image_png_encode, - "function(object,void|mapping(string:int):string)", + "function(object,void|mapping(string:mixed):string)", OPT_TRY_OPTIMIZE); } -- GitLab