db9f1c1999-04-15Per Hedbor inherit Image._PSD; class Layer { string mode; int opacity; object image; object alpha; int flags; int xoffset, yoffset; int width, height;
2767d51999-04-17Per Hedbor  int mask_flags; int mask_xoffset, mask_yoffset; int mask_width, mask_height;
db9f1c1999-04-15Per Hedbor  Layer copy() { Layer l = Layer(); l->mode = mode; l->opacity = opacity; l->image = image; l->alpha = alpha; l->flags = flags; l->xoffset = xoffset; l->yoffset = yoffset; l->width = width; l->height = height; return l; } Layer get_opaqued( int opaque_value ) { Layer res = copy(); if(opaque_value != 255) { if(res->alpha) res->alpha *= opaque_value/255.0; else res->alpha = Image.image(width,height, opaque_value,opaque_value,opaque_value); } return res; } }
9b68cc1999-07-16Per Hedbor int foo;
db9f1c1999-04-15Per Hedbor Layer decode_layer(mapping layer, mapping i) {
92464e1999-11-02Per Hedbor // int stt = gethrtime();
db9f1c1999-04-15Per Hedbor  Layer l = Layer(); int use_cmap; l->opacity = layer->opacity; l->width = layer->right-layer->left; l->height = layer->bottom-layer->top; l->xoffset = layer->left; l->yoffset = layer->top; l->image = Image.image( l->width, l->height ); l->mode = layer->mode; l->flags = layer->flags;
2767d51999-04-17Per Hedbor  l->mask_width = layer->mask_right-layer->mask_left; l->mask_height = layer->mask_bottom-layer->mask_top; l->mask_xoffset = layer->mask_left; l->mask_yoffset = layer->mask_top; if( !(l->mask_flags & 1 ) ) // pos relative to layer { l->mask_xoffset -= l->xoffset; l->mask_yoffset -= l->yoffset; }
db9f1c1999-04-15Per Hedbor  array colors;
2767d51999-04-17Per Hedbor  int inverted;
9b68cc1999-07-16Per Hedbor 
db9f1c1999-04-15Per Hedbor  switch(i->mode) { case RGB:
9b68cc1999-07-16Per Hedbor  array lays = ({}); foreach( layer->channels, mapping c ) { string mode; switch( (int)c->id ) { case 0: mode = "red"; break; case 1: mode = "green"; break; case 2: mode = "blue"; break; } if( mode ) {
92464e1999-11-02Per Hedbor // int st = gethrtime();
9b68cc1999-07-16Per Hedbor  if( !sizeof(lays) ) lays += ({ Image.Layer(___decode_image_channel(l->width, l->height, c->data)) }); else lays += (({ Image.Layer( ([ "image":___decode_image_channel(l->width, l->height, c->data), "alpha_value":1.0, "mode":mode, ]) ) }));
92464e1999-11-02Per Hedbor // werror(mode+" took %4.5f seconds\n", (gethrtime()-st)/1000000.0 );
9b68cc1999-07-16Per Hedbor  c->data = 0; } }
92464e1999-11-02Per Hedbor // int st = gethrtime();
9b68cc1999-07-16Per Hedbor  l->image = Image.lay( lays )->image();
92464e1999-11-02Per Hedbor // werror("combine took %4.5f seconds\n", (gethrtime()-st)/1000000.0 );
db9f1c1999-04-15Per Hedbor  break;
9b68cc1999-07-16Per Hedbor 
2767d51999-04-17Per Hedbor  case CMYK: inverted = 1; colors = ({ ({255,0,0,}), ({0,255,0,}), ({0,0,255,}), }) + ({ 255,255,255 }) * 24;
c11b971999-04-22Per Hedbor  l->image = Image.image( l->width, l->height, 255, 255, 255);
2767d51999-04-17Per Hedbor  break;
9b68cc1999-07-16Per Hedbor 
db9f1c1999-04-15Per Hedbor  case Indexed: use_cmap = 1; break; default:
9b68cc1999-07-16Per Hedbor  werror("Unsupported layer format mode (for now), using greyscale\n"); case Greyscale: colors = ({ 255,255,255 })*24;
db9f1c1999-04-15Per Hedbor  break; }
92464e1999-11-02Per Hedbor // int st = gethrtime();
db9f1c1999-04-15Per Hedbor  foreach(layer->channels, mapping c) {
2767d51999-04-17Per Hedbor  object tmp;
9b68cc1999-07-16Per Hedbor  if( !colors && (c->id >= 0 )) continue;
2767d51999-04-17Per Hedbor  if( c->id != -2) tmp = ___decode_image_channel(l->width, l->height, c->data); else tmp = ___decode_image_channel(l->mask_width,l->mask_height,c->data);
9b68cc1999-07-16Per Hedbor  switch( c->id )
db9f1c1999-04-15Per Hedbor  { default:
2767d51999-04-17Per Hedbor  if(!use_cmap) { if(inverted) l->image -= tmp*colors[c->id%sizeof(colors)]; else l->image += tmp*colors[c->id%sizeof(colors)]; } else { __apply_cmap( tmp, i->color_data ); l->image = tmp; }
db9f1c1999-04-15Per Hedbor  break; case -1: /* alpha */ if(!l->alpha) l->alpha = tmp; else l->alpha *= tmp; break;
2767d51999-04-17Per Hedbor  case -2: /* user mask */ if(!(l->mask_flags & 2 )) /* layer mask disabled */ { array pad_color = ({255,255,255}); if( (l->mask_flags & 4 ) ) /* invert mask */ tmp = tmp->invert(); tmp = tmp->copy( -l->mask_xoffset, -l->mask_yoffset, l->image->xsize()-1, l->image->ysize()-1, @pad_color ) ->copy(0,0,l->image->xsize()-1,l->image->ysize()-1, @pad_color); if(!l->alpha) l->alpha = tmp; else l->alpha *= tmp; break; }
db9f1c1999-04-15Per Hedbor  }
9b68cc1999-07-16Per Hedbor  c->data = 0;
db9f1c1999-04-15Per Hedbor  }
92464e1999-11-02Per Hedbor // werror("alpha/mask took %4.5f seconds\n", (gethrtime()-st)/1000000.0 ); // werror("TOTAL took %4.5f seconds\n\n", (gethrtime()-stt)/1000000.0 );
db9f1c1999-04-15Per Hedbor  return l; } mapping __decode( mapping|string what, mapping|void options ) { mapping data; if(mappingp(what)) data = what; else data = ___decode( what ); what=0; array rl = ({}); foreach( data->layers, mapping l )
9b68cc1999-07-16Per Hedbor  rl += ({ decode_layer( l, data ) });
db9f1c1999-04-15Per Hedbor  data->layers = rl; return data; }
92464e1999-11-02Per Hedbor array(object) decode_background( mapping data )
db9f1c1999-04-15Per Hedbor {
9b68cc1999-07-16Per Hedbor  object img;
92464e1999-11-02Per Hedbor 
2767d51999-04-17Per Hedbor  if( data->image_data ) img = ___decode_image_data(data->width, data->height, data->channels, data->mode, data->compression, data->image_data,
92464e1999-11-02Per Hedbor 
2767d51999-04-17Per Hedbor  data->color_data);
9b68cc1999-07-16Per Hedbor  return ({ img, 0 }); } string translate_mode( string mode ) { switch( mode ) { case "norm": return "normal"; case "mul ": return "multiply"; case "add ": return "add"; case "diff": return "difference"; case "sub ": return "subtract"; case "diss": return "dissolve"; case "scrn": return "screen"; case "over": return "overlay"; case "div ": return "divide"; //? case "idiv": return "divide"; //? case "dark": return "min"; case "lite": return "max"; case "hue ": return "hue"; case "sat ": return "saturation"; case "colr": return "color"; case "lum ": return "value"; case "smud": werror("WARNING: Unsupported mode (smudge). Skipping layer\n"); return 0; // WARNING: PSD: Unsupported mode: sLit // WARNING: PSD: Unsupported mode: hLit default: werror("WARNING: PSD: Unsupported mode: "+mode+"\n"); werror("Skipping layer\n"); return 0; } } array decode_layers( string|mapping what, mapping|void opts ) { if(!opts) opts = ([]); if(!mappingp( what ) ) what = __decode( what ); mapping lopts = ([ "tiled":1, ]);
c776f31999-11-02Per Hedbor  if( opts->background )
9b68cc1999-07-16Per Hedbor  {
c776f31999-11-02Per Hedbor  lopts->image = Image.Image( 32, 32, opts->background ); lopts->alpha = Image.Image( 32, 32, Image.Color.white );
9b68cc1999-07-16Per Hedbor  lopts->alpha_value = 1.0; }
c776f31999-11-02Per Hedbor  object img, alpha; if( !what->layers || !sizeof(what->layers)) { [ img, alpha ] = decode_background( what ); if( img ) { lopts->image = img; if( alpha ) lopts->alpha = alpha; else lopts->alpha = 0; lopts->alpha_value = 1.0; } }
92464e1999-11-02Per Hedbor  array layers; if( lopts->image ) layers = ({ Image.Layer( lopts ) }); else layers = ({});
9b68cc1999-07-16Per Hedbor  foreach(reverse(what->layers), object l) { if( string m = translate_mode( l->mode ) ) {
92464e1999-11-02Per Hedbor  Image.Layer lay = Image.Layer( l->image, l->alpha, m );
9b68cc1999-07-16Per Hedbor  l->image = 0; l->alpha = 0; lay->set_alpha_value( l->opacity / 255.0 ); lay->set_offset( l->xoffset, l->yoffset ); layers += ({ lay }); } } return layers;
db9f1c1999-04-15Per Hedbor } mapping _decode( string|mapping what, mapping|void opts ) {
9b68cc1999-07-16Per Hedbor // mixed e = catch{
db9f1c1999-04-15Per Hedbor  mapping data; if(!opts) opts = ([]); if(mappingp(what)) data = what; else data = __decode( what ); what=0;
9b68cc1999-07-16Per Hedbor  Image.Layer res = Image.lay(decode_layers( data, opts ), 0,0,data->width,data->height ); Image.Image img = res->image(); Image.Image alpha = res->alpha();
db9f1c1999-04-15Per Hedbor  return ([ "image":img, "alpha":alpha, ]);
c11b971999-04-22Per Hedbor // }; // werror(describe_backtrace(e));
db9f1c1999-04-15Per Hedbor }