diff --git a/lib/modules/_Image_PSD.pmod b/lib/modules/_Image_PSD.pmod index 5851238059919ca4a2a35c5d787d55e6becc013e..7cf74a1022ca811fc23c695472ef713eebe58cad 100644 --- a/lib/modules/_Image_PSD.pmod +++ b/lib/modules/_Image_PSD.pmod @@ -21,7 +21,7 @@ class Layer int foo; Layer decode_layer(mapping layer, mapping i) { - int stt = gethrtime(); +// int stt = gethrtime(); Layer l = Layer(); int use_cmap; l->opacity = layer->opacity; @@ -33,7 +33,7 @@ Layer decode_layer(mapping layer, mapping i) l->mode = layer->mode; l->flags = layer->flags; l->name = layer->name; - + l->mask_width = layer->mask_right-layer->mask_left; l->mask_height = layer->mask_bottom-layer->mask_top; l->mask_xoffset = layer->mask_left; @@ -68,7 +68,7 @@ Layer decode_layer(mapping layer, mapping i) } if( mode ) { - int st = gethrtime(); +// int st = gethrtime(); if( !sizeof(lays) ) lays += ({ Image.Layer(___decode_image_channel(l->width, @@ -82,13 +82,13 @@ Layer decode_layer(mapping layer, mapping i) "mode":mode, ]) ) })); - werror(mode+" took %4.5f seconds\n", (gethrtime()-st)/1000000.0 ); +// werror(mode+" took %4.5f seconds\n", (gethrtime()-st)/1000000.0 ); c->data = 0; } } - int st = gethrtime(); +// int st = gethrtime(); l->image = Image.lay( lays )->image(); - werror("combine took %4.5f seconds\n", (gethrtime()-st)/1000000.0 ); +// werror("combine took %4.5f seconds\n", (gethrtime()-st)/1000000.0 ); break; case CMYK: inverted = 1; @@ -103,14 +103,14 @@ Layer decode_layer(mapping layer, mapping i) use_cmap = 1; break; default: - werror("Unsupported layer format mode (for now), using greyscale\n"); + werror("Unsupported layer format mode ("+i->mode+"), using greyscale\n"); case Greyscale: colors = ({ 255,255,255 })*24; break; } - int st = gethrtime(); +// int st = gethrtime(); foreach(layer->channels, mapping c) { object tmp; @@ -163,8 +163,8 @@ Layer decode_layer(mapping layer, mapping i) } c->data = 0; } - werror("alpha/mask took %4.5f seconds\n", (gethrtime()-st)/1000000.0 ); - werror("TOTAL took %4.5f seconds\n\n", (gethrtime()-stt)/1000000.0 ); +// werror("alpha/mask took %4.5f seconds\n", (gethrtime()-st)/1000000.0 ); +// werror("TOTAL took %4.5f seconds\n\n", (gethrtime()-stt)/1000000.0 ); return l; } @@ -231,15 +231,14 @@ string translate_mode( string mode ) default: - werror("WARNING: PSD: Unsupported mode: "+mode+"\n"); - werror("Skipping layer\n"); + werror("WARNING: PSD: Unsupported mode: "+mode+". Skipping layer\n"); +// werror("Skipping layer\n"); return 0; } } array decode_layers( string|mapping what, mapping|void opts ) { - if(!opts) opts = ([]); if(!mappingp( what ) ) @@ -269,8 +268,14 @@ array decode_layers( string|mapping what, mapping|void opts ) } } array layers; + Image.Layer lay; if( lopts->image ) - layers = ({ Image.Layer( lopts ) }); + { + layers = ({ (lay=Image.Layer( lopts )) }); + lay->set_misc_value( "visible", 1 ); + lay->set_misc_value( "name", "Background" ); + lay->set_misc_value( "image_guides", what->resources->guides ); + } else layers = ({}); @@ -280,10 +285,11 @@ array decode_layers( string|mapping what, mapping|void opts ) { if( string m = translate_mode( l->mode ) ) { - Image.Layer lay = Image.Layer( l->image, l->alpha, m ); + lay = Image.Layer( l->image, l->alpha, m ); lay->set_misc_value( "visible", !(l->flags & LAYER_FLAG_INVISIBLE) ); lay->set_misc_value( "name", l->name ); + lay->set_misc_value( "image_guides", what->resources->guides ); l->image = 0; l->alpha = 0; if( l->opacity != 255 ) @@ -298,7 +304,6 @@ array decode_layers( string|mapping what, mapping|void opts ) mapping _decode( string|mapping what, mapping|void opts ) { -// mixed e = catch{ mapping data; if(!opts) opts = ([]); if(mappingp(what)) @@ -317,6 +322,19 @@ mapping _decode( string|mapping what, mapping|void opts ) "image":img, "alpha":alpha, ]); -// }; -// werror(describe_backtrace(e)); +} + +Image.Image decode( string|mapping what, mapping|void opts ) +{ + mapping data; + if(!opts) opts = ([]); + if(mappingp(what)) + data = what; + else + data = __decode( what ); + what=0; + + Image.Layer res = Image.lay(decode_layers( data, opts ), + 0,0,data->width,data->height ); + return res->image(); } diff --git a/src/modules/Image/encodings/psd.c b/src/modules/Image/encodings/psd.c index a21ee5a6563479754581f69d24398e6e57bc4d5e..06be473ad84504a98ad6e9087606cae843cfab7f 100644 --- a/src/modules/Image/encodings/psd.c +++ b/src/modules/Image/encodings/psd.c @@ -1,5 +1,5 @@ #include "global.h" -RCSID("$Id: psd.c,v 1.23 2000/11/16 18:26:20 per Exp $"); +RCSID("$Id: psd.c,v 1.24 2000/11/21 10:38:11 per Exp $"); #include "image_machine.h" @@ -66,7 +66,7 @@ struct buffer unsigned char *str; }; -static unsigned int read_uint( struct buffer *from ) +static unsigned int psd_read_uint( struct buffer *from ) { unsigned int res; if(from->len < 4) @@ -79,10 +79,10 @@ static unsigned int read_uint( struct buffer *from ) static int psd_read_int( struct buffer *from ) { - return (int)read_uint( from ); + return (int)psd_read_uint( from ); } -static unsigned short read_ushort( struct buffer *from ) +static unsigned short psd_read_ushort( struct buffer *from ) { unsigned short res; if(from->len < 2) @@ -93,12 +93,12 @@ static unsigned short read_ushort( struct buffer *from ) return res; } -static int read_short( struct buffer *from ) +static int psd_read_short( struct buffer *from ) { - return (short)read_ushort( from ); + return (short)psd_read_ushort( from ); } -static unsigned char read_uchar( struct buffer *from ) +static unsigned char psd_read_uchar( struct buffer *from ) { unsigned char res = 0; if(from->len) @@ -110,13 +110,13 @@ static unsigned char read_uchar( struct buffer *from ) return res; } -static int read_char( struct buffer *from ) +static int psd_read_char( struct buffer *from ) { - return (char)read_uchar( from ); + return (char)psd_read_uchar( from ); } -static char *read_data( struct buffer * from, size_t len ) +static char *psd_read_data( struct buffer * from, size_t len ) { char *res; if( from->len < len ) @@ -128,24 +128,24 @@ static char *read_data( struct buffer * from, size_t len ) return res; } -static struct buffer read_string( struct buffer *data ) +static struct buffer psd_read_string( struct buffer *data ) { struct buffer res; res.len = psd_read_int( data ); - res.str = (unsigned char *)read_data( data, res.len ); + res.str = (unsigned char *)psd_read_data( data, res.len ); if(res.len > 0) res.len--; /* len includes ending \0 */ if(!res.str) error("String read failed\n"); return res; } -static struct buffer read_pstring( struct buffer *data ) +static struct buffer psd_read_pstring( struct buffer *data ) { struct buffer res; - res.len = read_uchar( data ); - res.str = (unsigned char *)read_data( data, res.len ); + res.len = psd_read_uchar( data ); + res.str = (unsigned char *)psd_read_data( data, res.len ); if(!res.str) - error("String read failed\n"); + error("PString read failed\n"); return res; } @@ -225,7 +225,7 @@ static void decode_layers_and_masks( struct psd_image *dst, return; exp_offset = src->len-psd_read_int( src ); /* size of layer region */ - count = read_short( src ); + count = psd_read_short( src ); if( count < 0 ) { @@ -246,41 +246,41 @@ static void decode_layers_and_masks( struct psd_image *dst, layer->left = psd_read_int( src ); layer->bottom = psd_read_int( src ); layer->right = psd_read_int( src ); - layer->num_channels = read_short( src ); + layer->num_channels = psd_read_short( src ); for(cnt=0; cnt<layer->num_channels; cnt++) { - layer->channel_info[cnt].id = read_ushort(src); - layer->channel_info[cnt].data.len = read_uint(src); + layer->channel_info[cnt].id = psd_read_ushort(src); + layer->channel_info[cnt].data.len = psd_read_uint(src); } - read_uint( src ); /* '8BIM' */ + psd_read_uint( src ); /* '8BIM' */ layer->mode.len = 4; - layer->mode.str = (unsigned char *)read_data( src, 4 ); - layer->opacity = read_uchar( src ); - layer->clipping = read_uchar( src ); - layer->flags = read_uchar( src ); - read_uchar( src ); - layer->extra_data = read_string( src ); + layer->mode.str = (unsigned char *)psd_read_data( src, 4 ); + layer->opacity = psd_read_uchar( src ); + layer->clipping = psd_read_uchar( src ); + layer->flags = psd_read_uchar( src ); + psd_read_uchar( src ); + layer->extra_data = psd_read_string( src ); layer->extra_data.len++; if(layer->extra_data.len) { struct buffer tmp = layer->extra_data; struct buffer tmp2; - tmp2 = read_string( &tmp ); + tmp2 = psd_read_string( &tmp ); if( tmp2.len ) { layer->mask_top = psd_read_int( &tmp2 ); layer->mask_left = psd_read_int( &tmp2 ); layer->mask_bottom = psd_read_int( &tmp2 ); layer->mask_right = psd_read_int( &tmp2 ); - layer->mask_default_color = read_uchar( &tmp2 ); -/* layer->mask_flags = read_uchar( &tmp2 ); */ + layer->mask_default_color = psd_read_uchar( &tmp2 ); +/* layer->mask_flags = psd_read_uchar( &tmp2 ); */ } - tmp2 = read_string( &tmp ); + tmp2 = psd_read_string( &tmp ); if( tmp2.len ) { /* ranges (?) */ } - layer->name = read_pstring( &tmp ); + layer->name = psd_read_pstring( &tmp ); } } while(layer->next) @@ -292,7 +292,7 @@ static void decode_layers_and_masks( struct psd_image *dst, for(i=0; i<layer->num_channels; i++) { layer->channel_info[i].data.str= - (unsigned char *)read_data(src,layer->channel_info[i].data.len); + (unsigned char *)psd_read_data(src,layer->channel_info[i].data.len); } layer = layer->prev; } @@ -308,7 +308,7 @@ packbitsdecode(struct buffer src, while( nbytes-- ) { - n = read_uchar( &src ); + n = psd_read_uchar( &src ); if(n >= 128) n -= 256; if (n > 0) @@ -318,7 +318,7 @@ packbitsdecode(struct buffer src, { if(dst.len) { - *(dst.str++) = read_uchar( &src ); + *(dst.str++) = psd_read_uchar( &src ); dst.len--; } else return src; @@ -328,7 +328,7 @@ packbitsdecode(struct buffer src, } else { unsigned char val; n = -n+1; - val = read_uchar( &src ); + val = psd_read_uchar( &src ); while(n--) { if(dst.len) @@ -529,15 +529,15 @@ static struct psd_image low_psd_decode( struct buffer *b ) ONERROR err; MEMSET(&i, 0, sizeof(i)); SET_ONERROR( err, free_image, &i ); - i.num_channels = read_ushort( b ); - i.rows = read_uint( b ); - i.columns = read_uint( b ); - i.depth = read_ushort( b ); - i.mode = read_ushort( b ); - i.color_data = read_string( b ); - i.resource_data = read_string( b ); - i.layer_data = read_string( b ); - i.compression = read_short( b ); + i.num_channels = psd_read_ushort( b ); + i.rows = psd_read_uint( b ); + i.columns = psd_read_uint( b ); + i.depth = psd_read_ushort( b ); + i.mode = psd_read_ushort( b ); + i.color_data = psd_read_string( b ); + i.resource_data = psd_read_string( b ); i.resource_data.len++; + i.layer_data = psd_read_string( b ); /*i.layer_data.len++;*/ + i.compression = psd_read_short( b ); i.image_data = *b; decode_layers_and_masks( &i, &i.layer_data ); UNSET_ONERROR( err ); @@ -584,6 +584,7 @@ void push_layer( struct layer *l) } +static void decode_resources( struct buffer *b ); void push_psd_image( struct psd_image *i ) { struct svalue *osp = sp, *tsp; @@ -595,7 +596,8 @@ void push_psd_image( struct psd_image *i ) ref_push_string( s_depth ); push_int( i->compression ); ref_push_string( s_mode ); push_int( i->mode ); ref_push_string( s_color_data ); push_buffer( &i->color_data ); - ref_push_string( s_resource_data ); push_buffer( &i->resource_data ); +/* ref_push_string( s_resource_data ); push_buffer( &i->resource_data ); */ + ref_push_string( s_resources ); decode_resources( &i->resource_data ); ref_push_string( s_image_data ); push_buffer( &i->image_data ); ref_push_string( s_layers ); l = i->first_layer; @@ -609,6 +611,97 @@ void push_psd_image( struct psd_image *i ) f_aggregate_mapping(DO_NOT_WARN(sp - osp)); } +static void decode_resources( struct buffer *b ) +{ + struct svalue *osp = Pike_sp; + + while( b->len > 11 ) + { + char *signature = psd_read_data( b, 4 ); + + int id; + struct buffer data; + struct buffer name; + if( signature[0] != '8' || signature[1] != 'B' || + signature[2] != 'I' || signature[3] != 'M' ) + break; + + id = psd_read_short( b ); + name = psd_read_pstring( b ); + if( !(name.len & 1) ) psd_read_uchar( b ); + data = psd_read_string( b ); + data.len++; +/* fprintf( stderr, "id: %d; namelen=%d; size=%d\n", */ +/* id, name.len, data.len ); */ + + if( data.len & 1 ) psd_read_uchar( b ); + + switch( id ) + { + case 0x03f0: /* caption */ + { + struct buffer b = psd_read_pstring( &data ); + push_constant_text( "caption" ); + push_buffer( &b ); + } + break; + + case 0x0400: /* layer state info */ + push_constant_text( "active_layer" ); + push_int( psd_read_short( &data ) ); + break; + case 0x0408: /* guides */ + push_constant_text( "guides" ); + { + int i,num_guides; + short magic1, magic2, magic3, magic4, magic5, magic6; // from gimp. + magic1 = psd_read_short( &data ); magic2 = psd_read_short( &data ); + magic3 = psd_read_short( &data ); magic4 = psd_read_short( &data ); + magic5 = psd_read_short( &data ); magic6 = psd_read_short( &data ); + num_guides = psd_read_int( &data ); + + if( data.len != (unsigned)(num_guides * 5) ) + { + f_aggregate( 0 ); + break; + } + for (i=0; i<num_guides; i++) + { + int p = psd_read_int( &data ); + int h = psd_read_uchar( &data ); + if( h ) + p = (int)((((double)p) * (magic4>>8)) / ((double)(magic4&255))); + else + p = (int)((((double)p) * (magic6>>8)) / ((double)(magic6&255))); + push_constant_text( "pos" ); push_int( p ); + push_constant_text( "vertical" ); push_int( !h ); + f_aggregate_mapping( 4 ); + } + f_aggregate( num_guides ); + } + break; + case 0x03ed: /* res. info. */ + push_constant_text( "resinfo" ); + + push_constant_text( "hres" ); push_int(psd_read_int( &data ) ); + push_constant_text( "hres_unit" ); push_int(psd_read_short( &data ) ); + push_constant_text( "width_unit" ); push_int(psd_read_short( &data ) ); + + push_constant_text( "vres" ); push_int(psd_read_int( &data ) ); + push_constant_text( "vres_unit" ); push_int(psd_read_short( &data ) ); + push_constant_text( "height_unit" );push_int(psd_read_short( &data ) ); + + f_aggregate_mapping( 12 ); + break; + default: + push_int( id ); + push_buffer( &data ); + break; + } + } + f_aggregate_mapping( sp-osp ); +} + static void image_f_psd___decode( INT32 args ) { struct pike_string *s; diff --git a/src/modules/Image/encodings/psd_constant_strings.h b/src/modules/Image/encodings/psd_constant_strings.h index 1338159edf4ee4be75b4983fc94fd366209b20a8..046f6d69fe54c0dd0f9dcd47b5f847e4c2bca71f 100644 --- a/src/modules/Image/encodings/psd_constant_strings.h +++ b/src/modules/Image/encodings/psd_constant_strings.h @@ -19,7 +19,6 @@ STRING(mode); STRING(extra_data); STRING(id); STRING(color_data); -STRING(resource_data); STRING(channels); STRING(name); STRING(data); @@ -30,3 +29,4 @@ STRING(name); STRING(properties); STRING(tiles); STRING(type); +STRING(resources);