From 1c59c7619cae6df803f962cb542ac335c899c27c Mon Sep 17 00:00:00 2001 From: Per Hedbor <ph@opera.com> Date: Sat, 10 Apr 1999 01:19:00 +0200 Subject: [PATCH] Added palette based encoding Rev: src/modules/Image/encodings/pcx.c:1.3 --- src/modules/Image/encodings/pcx.c | 284 +++++++++++++++++++++++++++--- 1 file changed, 262 insertions(+), 22 deletions(-) diff --git a/src/modules/Image/encodings/pcx.c b/src/modules/Image/encodings/pcx.c index e21a31137b..b7c6f1eba1 100644 --- a/src/modules/Image/encodings/pcx.c +++ b/src/modules/Image/encodings/pcx.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: pcx.c,v 1.2 1999/04/09 04:50:43 hubbe Exp $"); +RCSID("$Id: pcx.c,v 1.3 1999/04/09 23:19:00 per Exp $"); #include "config.h" @@ -17,6 +17,8 @@ RCSID("$Id: pcx.c,v 1.2 1999/04/09 04:50:43 hubbe Exp $"); #include "mapping.h" #include "error.h" #include "stralloc.h" +#include "builtin_functions.h" +#include "operators.h" #include "dynamic_buffer.h" #include "image.h" @@ -95,7 +97,7 @@ void get_rle_decoded_from_data( unsigned char *dest, struct buffer * source, { unsigned char *c = get_chunk( source, nelems ); if(c) - MEMCPY( dest, source, nelems ); + MEMCPY( dest, c, nelems ); else MEMSET( dest, 0, nelems ); return; @@ -135,7 +137,7 @@ static void load_rgb_pcx( struct pcx_header *hdr, struct buffer *b, for(y=0; y<height; y++) { - get_rle_decoded_from_data( line, b,hdr->bytesperline*hdr->planes, hdr, &state ); + get_rle_decoded_from_data(line, b,hdr->bytesperline*hdr->planes, hdr, &state); /* rrrr... ggg... bbb.. */ for(x=0; x<width; x++) { @@ -335,24 +337,248 @@ void image_pcx__decode( INT32 args ) -static struct pike_string *param_raw; - -/* TODO: */ +static struct pike_string *opt_raw, *opt_dpy, *opt_xdpy, *opt_colortable, + *opt_ydpy, *opt_xoffset, *opt_yoffset; /* -** method string encode(object image) -** method string encode(object image, mapping options) -** Encodes a Targa image. -** -** The <tt>options</tt> argument may be a mapping -** containing zero or more encoding options: -** -** <pre> -** normal options: -** "raw":1 -** Do not RLE encode the image -** </pre> +**! method string encode(object image) +**! method string encode(object image, mapping options) +**! method string _encode(object image) +**! method string _encode(object image, mapping options) +**! Encodes a PCX image. The _encode and the encode functions are identical +**! +**! The <tt>options</tt> argument may be a mapping +**! containing zero or more encoding options: +**! +**! <pre> +**! normal options: +**! "raw":1 +**! Do not RLE encode the image +**! "dpy":int +**! "xdpy":int +**! "ydpy":int +**! Image resolution (in pixels/inch, integer numbers) +**! "xoffset":int +**! "yoffset":int +**! Image offset (not used by most programs, but gimp uses it) +**! </pre> */ +struct options +{ + int raw; + int offset_x, offset_y; + int hdpi, vdpi; + struct neo_colortable *colortable; +}; + + +static void f_rle_encode( INT32 args ) +{ + struct pike_string *data; + struct string_builder result; + unsigned char value, *source; + unsigned char nelems; + int i; + get_all_args( "rle_encode", args, "%S", &data ); + init_string_builder( &result, 0 ); + + source = (unsigned char *)data->str; + for(i=0; i<data->len;) + { + value = *(source++); + nelems = 1; + i++; + while( i<data->len && nelems<63 && *source == value) + { + nelems++; + source++; + i++; + } + if(nelems == 1 && value < 0xC0 ) + string_builder_putchar( &result, value ); + else + { + string_builder_putchar( &result, 0xC0 + nelems ); + string_builder_putchar( &result, value ); + } + } +/* fprintf(stderr, "RLE encode source len = %d; dest len = %d\n", */ +/* sp[-1].u.string->len, result.s->len ); */ + pop_n_elems( args ); + push_string( finish_string_builder( &result )); +} + +static struct pike_string *encode_pcx_24( struct pcx_header *pcx_header, + struct image *data, + struct options *opts ) +{ + struct pike_string *b; + int x, y; + char *buffer; + rgb_group *s; + + pcx_header->planes = 3; + + push_string( make_shared_binary_string( (char *)pcx_header, + sizeof(struct pcx_header) ) ); + + buffer = malloc(data->xsize*data->ysize*3); + s = data->img; + for(y=0; y<data->ysize; y++) + { + unsigned char *line = buffer+y*data->xsize*3; + for(x=0; x<data->xsize; x++) + { + line[x] = s->r; + line[x+data->xsize] = s->g; + line[x+data->xsize*2] = s->b; + s++; + } + } + push_string(make_shared_binary_string(buffer,data->xsize*data->ysize*3)); + free(buffer); + + if(pcx_header->rle_encoded) + f_rle_encode( 1 ); + + f_add( 2 ); + b = sp[-1].u.string; + sp--; + return b; +} + + +static struct pike_string *encode_pcx_8( struct pcx_header *pcx_header, + struct image *data, + struct options *opts ) +{ + struct pike_string *b; + int x, y; + char *buffer; + + pcx_header->planes = 1; + push_string( make_shared_binary_string( (char *)pcx_header, + sizeof(struct pcx_header) ) ); + + + buffer = malloc(data->xsize*data->ysize); + image_colortable_index_8bit_image( opts->colortable, + data->img, buffer, data->xsize*data->ysize, + data->xsize ); + push_string(make_shared_binary_string(buffer,data->xsize*data->ysize)); + free(buffer); + + if(pcx_header->rle_encoded) + f_rle_encode( 1 ); + + { + char data[256*3+1]; + MEMSET(data, 0x0c, 256*3+1); + image_colortable_write_rgb(opts->colortable, data+1); + push_string(make_shared_binary_string(data,256*3+1)); + } + + f_add( 3 ); + b = sp[-1].u.string; + sp--; + return b; +} + +static struct pike_string *low_pcx_encode(struct image *data,struct options *opts) +{ + struct pcx_header pcx_header; + pcx_header.x1 = opts->offset_x; + pcx_header.x2 = opts->offset_x+data->xsize-1; + pcx_header.y1 = opts->offset_y; + pcx_header.y2 = opts->offset_y+data->ysize-1; + pcx_header.hdpi = opts->hdpi; + pcx_header.vdpi = opts->vdpi; + pcx_header.bytesperline = data->xsize; + pcx_header.rle_encoded = opts->raw?0:1; + pcx_header.manufacturer = 10; + pcx_header.version = 5; + pcx_header.reserved = 0; + pcx_header.bpp = 8; + MEMSET(pcx_header.palette, 0, 48); + MEMSET(pcx_header.filler, 0, 58); + pcx_header.color = 1; +#if BYTEORDER == 1234 + SWAP_S(pcx_header.hdpi); + SWAP_S(pcx_header.vdpi); + SWAP_S(pcx_header.x1); + SWAP_S(pcx_header.y1); + SWAP_S(pcx_header.x2); + SWAP_S(pcx_header.y2); + SWAP_S(pcx_header.bytesperline); + SWAP_S(pcx_header.color); +#endif + if(!opts->colortable) + return encode_pcx_24( &pcx_header, data, opts ); + return encode_pcx_8( &pcx_header, data, opts ); +} + +static int parameter_int(struct svalue *map,struct pike_string *what, + INT32 *p) +{ + struct svalue *v; + v=low_mapping_string_lookup(map->u.mapping,what); + if (!v || v->type!=T_INT) + return 0; + *p=v->u.integer; + return 1; +} + +static int parameter_colortable(struct svalue *map,struct pike_string *what, + struct neo_colortable **p) +{ + struct svalue *v; + v=low_mapping_string_lookup(map->u.mapping,what); + if (!v || v->type!=T_OBJECT) return 0; + if( !(*p = (struct neo_colortable *)get_storage( v->u.object, image_colortable_program ))) + return 0; + return 1; +} + +void image_pcx_encode( INT32 args ) +{ + struct options c; + struct pike_string *res; + struct object *i; + struct image *img; + ONERROR onerr; + + get_all_args( "Image.PCX.encode", args, "%o", &i ); + + if(!get_storage( i, image_program )) + error("Invalid object argument to Image.PCX.encode\n"); + + img = ((struct image *)get_storage( i, image_program )); + + MEMSET(&c, sizeof(c), 0); + c.hdpi = 150; + c.vdpi = 150; + c.raw = 0; + c.offset_x = c.offset_y = 0; + c.colortable = 0; + if(args > 1) + { + int dpy; + if(sp[-args+1].type != T_MAPPING) + error("Invalid argument 2 to Image.PCX.encode. Expected mapping.\n"); + parameter_int( sp-args+1, opt_raw, &c.raw ); + if(parameter_int( sp-args+1, opt_dpy, &dpy )) + c.hdpi = c.vdpi = dpy; + parameter_int( sp-args+1, opt_xdpy, &c.hdpi ); + parameter_int( sp-args+1, opt_ydpy, &c.vdpi ); + parameter_int( sp-args+1, opt_xoffset, &c.offset_x ); + parameter_int( sp-args+1, opt_yoffset, &c.offset_y ); + parameter_colortable( sp-args+1, opt_colortable, &c.colortable ); + } + res = low_pcx_encode( img, &c ); + pop_n_elems( args ); + push_string( res ); +} + static struct program *image_encoding_pcx_program=NULL; void init_image_pcx( ) { @@ -361,8 +587,10 @@ void init_image_pcx( ) "function(string:mapping(string:object))", 0); add_function( "decode", image_pcx_decode, "function(string:object)", 0); -/* add_function( "encode", image_pcx_encode, */ -/* "function(object,mapping|void:string)", 0); */ + add_function( "encode", image_pcx_encode, + "function(object,mapping|void:string)", 0); + add_function( "_encode", image_pcx_encode, + "function(object,mapping|void:string)", 0); image_encoding_pcx_program=end_program(); push_object(clone_object(image_encoding_pcx_program,0)); @@ -371,7 +599,13 @@ void init_image_pcx( ) add_constant(s,sp-1,0); free_string(s); } - param_raw=make_shared_string("raw"); + opt_raw=make_shared_string("raw"); + opt_dpy=make_shared_string("dpy"); + opt_xdpy=make_shared_string("xdpy"); + opt_ydpy=make_shared_string("ydpy"); + opt_xoffset=make_shared_string("xoffset"); + opt_colortable=make_shared_string("colortable"); + opt_yoffset=make_shared_string("yoffset"); } void exit_image_pcx(void) @@ -380,6 +614,12 @@ void exit_image_pcx(void) { free_program(image_encoding_pcx_program); image_encoding_pcx_program=0; - free_string(param_raw); + free_string(opt_raw); + free_string(opt_dpy); + free_string(opt_xdpy); + free_string(opt_ydpy); + free_string(opt_xoffset); + free_string(opt_colortable); + free_string(opt_yoffset); } } -- GitLab