a580e12000-09-27Fredrik Hübinette (Hubbe) #pike __REAL_VERSION__
a20af62000-09-26Fredrik Hübinette (Hubbe) 
db9f1c1999-04-15Per Hedbor inherit Image._PSD; class Layer {
a8f8652000-11-16Per Hedbor  string mode, name;
db9f1c1999-04-15Per Hedbor  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 }
9b68cc1999-07-16Per Hedbor int foo;
db9f1c1999-04-15Per Hedbor Layer decode_layer(mapping layer, mapping i) {
2db2b62000-11-21Per 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;
a8f8652000-11-16Per Hedbor  l->name = layer->name;
2db2b62000-11-21Per Hedbor 
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 ) {
2db2b62000-11-21Per Hedbor // int st = gethrtime();
9b68cc1999-07-16Per Hedbor  if( !sizeof(lays) ) lays += ({
a8f8652000-11-16Per Hedbor  Image.Layer(___decode_image_channel(l->width, l->height,
9b68cc1999-07-16Per Hedbor  c->data)) }); else lays += (({ Image.Layer( ([ "image":___decode_image_channel(l->width, l->height, c->data),
b9e5cc2000-10-21Per Hedbor // "alpha_value":1.0,
9b68cc1999-07-16Per Hedbor  "mode":mode,
b9e5cc2000-10-21Per Hedbor  ]) )
9b68cc1999-07-16Per Hedbor  }));
2db2b62000-11-21Per Hedbor // werror(mode+" took %4.5f seconds\n", (gethrtime()-st)/1000000.0 );
9b68cc1999-07-16Per Hedbor  c->data = 0; } }
2db2b62000-11-21Per Hedbor // int st = gethrtime();
9b68cc1999-07-16Per Hedbor  l->image = Image.lay( lays )->image();
2db2b62000-11-21Per Hedbor // werror("combine took %4.5f seconds\n", (gethrtime()-st)/1000000.0 );
db9f1c1999-04-15Per Hedbor  break;
a8f8652000-11-16Per Hedbor  case CMYK:
2767d51999-04-17Per Hedbor  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:
2db2b62000-11-21Per Hedbor  werror("Unsupported layer format mode ("+i->mode+"), using greyscale\n");
9b68cc1999-07-16Per Hedbor  case Greyscale: colors = ({ 255,255,255 })*24;
db9f1c1999-04-15Per Hedbor  break; }
2db2b62000-11-21Per 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  }
2db2b62000-11-21Per 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:
2db2b62000-11-21Per Hedbor  werror("WARNING: PSD: Unsupported mode: "+mode+". Skipping layer\n"); // werror("Skipping layer\n");
9b68cc1999-07-16Per Hedbor  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;
2db2b62000-11-21Per Hedbor  Image.Layer lay;
92464e1999-11-02Per Hedbor  if( lopts->image )
2db2b62000-11-21Per Hedbor  { 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 ); }
92464e1999-11-02Per Hedbor  else layers = ({});
9b68cc1999-07-16Per Hedbor  foreach(reverse(what->layers), object l) {
a8f8652000-11-16Per Hedbor  if( !(l->flags & LAYER_FLAG_INVISIBLE) || opts->draw_all_layers )
9b68cc1999-07-16Per Hedbor  {
a8f8652000-11-16Per Hedbor  if( string m = translate_mode( l->mode ) ) {
2db2b62000-11-21Per Hedbor  lay = Image.Layer( l->image, l->alpha, m );
a8f8652000-11-16Per Hedbor  lay->set_misc_value( "visible", !(l->flags & LAYER_FLAG_INVISIBLE) ); lay->set_misc_value( "name", l->name );
2db2b62000-11-21Per Hedbor  lay->set_misc_value( "image_guides", what->resources->guides );
a8f8652000-11-16Per Hedbor  l->image = 0; l->alpha = 0;
33364f2000-12-16Per Hedbor 
a8f8652000-11-16Per Hedbor  if( l->opacity != 255 )
33364f2000-12-16Per Hedbor  { float lo = 1.0 - l->opacity / 255.0; if( lay->alpha() ) lay->set_image( lay->image(), lay->alpha()*lo ); else lay->set_image( lay->image(), Image.Image( lay->xsize(), lay->yszize(), (int)(255*lo), (int)(255*lo), (int)(255*lo))); }
a8f8652000-11-16Per Hedbor  lay->set_offset( l->xoffset, l->yoffset ); layers += ({ lay }); }
9b68cc1999-07-16Per Hedbor  } } return layers;
db9f1c1999-04-15Per Hedbor } mapping _decode( string|mapping what, mapping|void opts ) { 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, ]);
2db2b62000-11-21Per Hedbor } 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();
db9f1c1999-04-15Per Hedbor }