diff --git a/src/modules/Image/encodings/gif.c b/src/modules/Image/encodings/gif.c index c3acaa8a16de066d4e3efa2c92e2930f88191174..2dffe68ab30ae845e3ec8e1a96bea8f8bf8e7c79 100644 --- a/src/modules/Image/encodings/gif.c +++ b/src/modules/Image/encodings/gif.c @@ -1,9 +1,9 @@ -/* $Id: gif.c,v 1.48 1999/05/23 17:46:52 mirar Exp $ */ +/* $Id: gif.c,v 1.49 1999/05/28 13:33:25 mirar Exp $ */ /* **! module Image **! note -**! $Id: gif.c,v 1.48 1999/05/23 17:46:52 mirar Exp $ +**! $Id: gif.c,v 1.49 1999/05/28 13:33:25 mirar Exp $ **! submodule GIF **! **! This submodule keep the GIF encode/decode capabilities @@ -31,7 +31,7 @@ #include <ctype.h> #include "stralloc.h" -RCSID("$Id: gif.c,v 1.48 1999/05/23 17:46:52 mirar Exp $"); +RCSID("$Id: gif.c,v 1.49 1999/05/28 13:33:25 mirar Exp $"); #include "pike_macros.h" #include "object.h" #include "constants.h" @@ -45,11 +45,13 @@ RCSID("$Id: gif.c,v 1.48 1999/05/23 17:46:52 mirar Exp $"); #include "image.h" #include "colortable.h" #include "builtin_functions.h" +#include "mapping.h" #include "gif_lzw.h" extern struct program *image_colortable_program; extern struct program *image_program; +extern struct program *image_layer_program; extern void f_add(INT32 args); @@ -2061,6 +2063,153 @@ void image_gif_decode(INT32 args) pop_stack(); } +/* +**! method object decode_layers(string data) +**! method object decode_layers(array _decoded) +**! method object decode_layer(string data) +**! method object decode_layer(array _decoded) +**! Decodes GIF data and creates an array of layers +**! or the resulting layer. +**! +**! see also: encode, decode_map +**! +**! note +**! The resulting layer may not have the same size +**! as the gif image, but the resulting bounding box +**! of all render chunks in the gif file. +**! The offset should be correct, though. +**! +*/ + +void image_gif_decode_layers(INT32 args) +{ + struct array *a,*b; + struct image *img,*src,*alpha; + struct object *o; + int n; + int numlayers=0; + + if (!args) + error("Image.GIF.decode_layers: too few argument\n"); + + if (sp[-args].type==T_ARRAY) + { + pop_n_elems(args-1); + if (sp[-args].u.array->size<4) + error("Image.GIF.decode: illegal argument\n"); + if (sp[-args].u.array->item[3].type!=T_ARRAY) + image_gif__decode(1); + } + else + image_gif__decode(args); + + if (sp[-1].type!=T_ARRAY) + error("Image.GIF.decode: internal error: " + "illegal result from _decode\n"); + + a=sp[-1].u.array; + if (a->size<4) + error("Image.GIF.decode: given (_decode'd) array " + "is too small\n"); + + for (n=4; n<a->size; n++) + if (a->item[n].type==T_ARRAY + && (b=a->item[n].u.array)->size==11 + && b->item[0].type==T_INT + && b->item[0].u.integer==GIF_RENDER + && b->item[3].type==T_OBJECT + && (src=(struct image*)get_storage(b->item[3].u.object, + image_program)) ) + { + if (b->item[4].type==T_OBJECT) + alpha=(struct image*)get_storage(b->item[4].u.object, + image_program); + else + alpha=NULL; + + if (alpha) + { + push_constant_text("image"); + push_svalue(b->item+3); + push_constant_text("alpha"); + push_svalue(b->item+4); + push_constant_text("xoffset"); + push_svalue(b->item+1); + push_constant_text("yoffset"); + push_svalue(b->item+2); + f_aggregate_mapping(8); + push_object(clone_object(image_layer_program,1)); + numlayers++; + } + else + { + push_constant_text("image"); + push_svalue(b->item+3); + push_constant_text("xoffset"); + push_svalue(b->item+1); + push_constant_text("yoffset"); + push_svalue(b->item+2); + f_aggregate_mapping(6); + push_object(clone_object(image_layer_program,1)); + numlayers++; + } + } + + f_aggregate(numlayers); + stack_swap(); + pop_stack(); +} + +void image_gif_decode_layer(INT32 args) +{ + image_gif_decode_layers(args); + image_lay(1); +} + +/* +**! method mapping decode_map(INT32 args) +**! Returns a mapping similar to other decoders +**! <tt>_decode</tt> function. +**! +**! <pre> +**! "image":the image +**! "alpha":the alpha channel +**! +**! "xsize":int +**! "ysize":int +**! size of image +**! "type":"image/gif" +**! file type information as MIME type +**! </pre> +**! +**! note: +**! The wierd name of this function (not <tt>_decode</tt> +**! as the other decoders) is because gif was the first +**! decoder and was written before the API was finally +**! defined. Sorry about that. /Mirar +*/ + +void image_gif_decode_map(INT32 args) +{ + image_gif_decode_layer(args); + + push_constant_text("image"); + push_constant_text("alpha"); + push_constant_text("xsize"); + push_constant_text("ysize"); + f_aggregate(4); +#define stack_swap_behind() do { struct svalue _=sp[-2]; sp[-2]=sp[-3]; sp[-3]=_; } while(0) + stack_dup(); + stack_swap_behind(); + f_rows(2); + f_call_function(1); + f_mkmapping(2); + push_constant_text("type"); + push_constant_text("image/gif"); + f_aggregate_mapping(2); + f_add(2); +} + /* **! method string _encode(array data) **! Encodes GIF data; reverses _decode. @@ -2557,6 +2706,12 @@ void init_image_gif(void) "function(string|array:array)",0); add_function("decode",image_gif_decode, "function(string|array:object)",0); + add_function("decode_layers",image_gif_decode_layers, + "function(string|array:array(object))",0); + add_function("decode_layer",image_gif_decode_layer, + "function(string|array:object)",0); + add_function("decode_map",image_gif_decode_map, + "function(string|array:mapping)",0); add_function("_encode",image_gif__encode, "function(array:string)",0);