a580e12000-09-27Fredrik Hübinette (Hubbe) #pike __REAL_VERSION__
a20af62000-09-26Fredrik Hübinette (Hubbe) 
d1f3142013-07-08Henrik Grubbström (Grubba) //! eXperimental Computing Facility (aka GIMP native) format. //! @appears Image.XCF
bc73c61999-04-11Per Hedbor inherit Image._XCF;
fb14c42000-09-06Per Hedbor #define SIGNED(X) if(X>=(1<<31)) X=-((1<<32)-X)
bc73c61999-04-11Per Hedbor class PathPoint { int type; float x; float y; } class Path { string name; int ptype; int tattoo; int closed; int state; int locked; array (PathPoint) points = ({}); } class Guide { int pos; int vertical; void create(string data) {
79757c1999-04-12Per Hedbor  sscanf(data, "%4c%c", pos,vertical);vertical--;
fb14c42000-09-06Per Hedbor  SIGNED(pos);
bc73c61999-04-11Per Hedbor  } }
c9804a2000-10-08Per Hedbor class Parasite( string name, int flags, string data ) { }
bc73c61999-04-11Per Hedbor 
c9804a2000-10-08Per Hedbor array(Parasite) decode_parasites( mixed data )
bc73c61999-04-11Per Hedbor { array res = ({});
c9804a2000-10-08Per Hedbor  data = (string)data;
ead9722003-01-20Martin Nilsson  while(sizeof(data))
bc73c61999-04-11Per Hedbor  { int slen, flags; sscanf(data, "%4c", slen);
4c9e4b2008-01-13Martin Nilsson  string name = data[..slen-2];
bc73c61999-04-11Per Hedbor  data = data[slen..]; sscanf(data, "%4c%4c", flags, slen);
e6c0c42000-02-08Per Hedbor  res += ({ Parasite( name,flags,data[8..slen+8-1] ) });
bc73c61999-04-11Per Hedbor  data = data[slen+8..]; } return res; }
c9804a2000-10-08Per Hedbor #define FLAG(X,Y) case PROP_##X: flags->Y=p->data->get_int(0); break; #define INT(X,Y) case PROP_##X: Y = p->data->get_uint( 0 ); break; #define SINT(X,Y) case PROP_##X: Y = p->data->get_int( 0 ); break;
0e02e91999-04-11Per Hedbor 
c9804a2000-10-08Per Hedbor int id;
0e02e91999-04-11Per Hedbor 
c9804a2000-10-08Per Hedbor class Hierarchy( int width, int height, int bpp, array tiles, int compression, Image.Colortable ct ) { Image.Layer get_layer( int|void shrink )
0e02e91999-04-11Per Hedbor  {
c9804a2000-10-08Per Hedbor  Image.Image img, alpha; if(!shrink) shrink = 1; img = Image.Image( width/shrink, height/shrink ); if( !(bpp & 1 ) ) alpha = Image.Image( width/shrink, height/shrink ); _decode_tiles( img,alpha,tiles,compression,bpp,ct, shrink,width,height ); return Image.Layer( img, alpha );
0e02e91999-04-11Per Hedbor  }
bc73c61999-04-11Per Hedbor } int iid; Hierarchy decode_image_data( mapping what, object i ) {
e6c0c42000-02-08Per Hedbor  Hierarchy h =
c9804a2000-10-08Per Hedbor  Hierarchy( what->width, what->height, what->bpp, what->tiles, i->compression, i->colormap );
bc73c61999-04-11Per Hedbor  return h; } class Channel { string name; int width; int height; int opacity; int r, g, b; int tattoo; Hierarchy image_data; object parent; mapping flags = ([]); array (Parasite) parasites; void decode_properties( array properties ) { foreach(properties, mapping p) { switch(p->type) { case PROP_ACTIVE_CHANNEL:
563bd72004-01-11Martin Nilsson  parent->active_channel = this;
bc73c61999-04-11Per Hedbor  break; case PROP_SELECTION:
563bd72004-01-11Martin Nilsson  parent->selection = this;
bc73c61999-04-11Per Hedbor  break; INT(OPACITY,opacity); FLAG(VISIBLE,visible); FLAG(LINKED,linked); FLAG(PRESERVE_TRANSPARENCY,preserve_transparency); FLAG(EDIT_MASK,edit_mask); FLAG(SHOW_MASKED,show_masked); INT(TATTOO,tattoo); case PROP_COLOR:
c9804a2000-10-08Per Hedbor  sscanf( (string)p->data, "%c%c%c", r, g, b);
bc73c61999-04-11Per Hedbor  break;
e6c0c42000-02-08Per Hedbor 
bc73c61999-04-11Per Hedbor  case PROP_PARASITES:
c9804a2000-10-08Per Hedbor  parasites = decode_parasites( (string)p->data );
bc73c61999-04-11Per Hedbor  break; } } } void create( mapping d, object p ) { parent = p;
c9804a2000-10-08Per Hedbor  name = (string)d->name;
bc73c61999-04-11Per Hedbor  width = d->width; height = d->height; image_data = decode_image_data( d->image_data, parent ); if(d->properties) decode_properties( d->properties ); } } class LayerMask { inherit Channel; }
d1f3142013-07-08Henrik Grubbström (Grubba) //!
bc73c61999-04-11Per Hedbor class Layer { string name; int opacity; int type; int mode; int tattoo; mapping flags = ([]); int width, height; int xoffset, yoffset; array (Parasite) parasites; LayerMask mask; Hierarchy image; object parent; void decode_properties( array properties ) { foreach( properties, mapping p) { switch(p->type) { case PROP_ACTIVE_LAYER:
563bd72004-01-11Martin Nilsson  parent->active_layer = this;
bc73c61999-04-11Per Hedbor  break; case PROP_SELECTION:
563bd72004-01-11Martin Nilsson  parent->selection = this;
bc73c61999-04-11Per Hedbor  break;
0e02e91999-04-11Per Hedbor  case PROP_OFFSETS:
c9804a2000-10-08Per Hedbor  xoffset = p->data->get_int( 0 ); yoffset = p->data->get_int( 1 );
0e02e91999-04-11Per Hedbor  break;
bc73c61999-04-11Per Hedbor  INT(OPACITY,opacity); FLAG(VISIBLE,visible);
0e02e91999-04-11Per Hedbor  FLAG(LINKED,linked); FLAG(PRESERVE_TRANSPARENCY,preserve_transparency); FLAG(APPLY_MASK,apply_mask); FLAG(EDIT_MASK,edit_mask); FLAG(SHOW_MASK,show_mask); INT(MODE,mode);
bc73c61999-04-11Per Hedbor  INT(TATTOO,tattoo); case PROP_PARASITES:
c9804a2000-10-08Per Hedbor  parasites = decode_parasites( (string)p->data );
bc73c61999-04-11Per Hedbor  break; } } } void create( mapping data, object pa ) { parent = pa;
c9804a2000-10-08Per Hedbor  name = (string)data->name;
bc73c61999-04-11Per Hedbor  type = data->type; width = data->width; height = data->height; decode_properties( data->properties ); image = decode_image_data( data->image_data, pa ); if(data->mask) mask = LayerMask( data->mask, pa ); } }
d1f3142013-07-08Henrik Grubbström (Grubba) //!
bc73c61999-04-11Per Hedbor class GimpImage { int width; int height; int compression; int type; int tattoo_state; float xres = 72.0; float yres = 72.0; int res_unit;
c9804a2000-10-08Per Hedbor  Image.Colortable colormap; Image.Colortable meta_colormap;
79757c1999-04-12Per Hedbor  array(Layer) layers = ({}); // bottom-to-top array(Channel) channels = ({}); // unspecified order, really
bc73c61999-04-11Per Hedbor  array(Guide) guides = ({}); array(Parasite) parasites = ({}); array(Path) paths = ({}); Layer active_layer; Channel active_channel; Channel selection;
9eaf1d2008-06-28Martin Nilsson  protected string read_point_bz1( string data, Path path )
bc73c61999-04-11Per Hedbor  { object p = PathPoint( ); int x, y;
d2a7272008-05-18Henrik Grubbström (Grubba)  sscanf(data, "%4c%4c%4c%s", p->type, x, y, data);
fb14c42000-09-06Per Hedbor  SIGNED(x); SIGNED(y);
bc73c61999-04-11Per Hedbor  p->x = (float)x; p->y = (float)y; return data; }
9eaf1d2008-06-28Martin Nilsson  protected string read_point_bz2( string data, Path path )
bc73c61999-04-11Per Hedbor  { object p = PathPoint( );
d2a7272008-05-18Henrik Grubbström (Grubba)  sscanf(data, "%4c%4F%4F%s", p->type, p->x, p->y, data);
bc73c61999-04-11Per Hedbor  return data; }
9eaf1d2008-06-28Martin Nilsson  protected string decode_one_path( string data, Path path )
bc73c61999-04-11Per Hedbor  { int nlen, version, num_points; sscanf(data, "%4c", nlen ); path->name = data[..nlen-2]; data = data[nlen..]; sscanf(data, "%4c%4c%4c%4c%4c", path->locked, path->state, path->closed, num_points, version); switch(version) { case 1: while(num_points--) data = read_point_bz1( data, path ); break; case 2: sscanf(data, "%4c%s", path->ptype, data ); while(num_points--) data = read_point_bz2( data, path ); break; case 3:
d2a7272008-05-18Henrik Grubbström (Grubba)  sscanf(data, "%4c%4c%s", path->ptype, path->tattoo, data );
bc73c61999-04-11Per Hedbor  while(num_points--) data = read_point_bz2( data, path ); break; default: data =""; } return data; } array(Path) decode_paths( string data ) { int last_selected_row; int num_paths; array res = ({});
517db32000-10-08Per Hedbor  if( stringp( data ) )
bc73c61999-04-11Per Hedbor  {
517db32000-10-08Per Hedbor  sscanf( data, "%4c%4c%s", last_selected_row, num_paths, data ); while(num_paths--) { Path path = Path(); data = decode_one_path( data, path ); res += ({ path }); }
bc73c61999-04-11Per Hedbor  } return res; } void decode_properties(array props) { foreach( props, mapping p) { switch(p->type) { case PROP_COLORMAP: if(type == INDEXED)
c9804a2000-10-08Per Hedbor  meta_colormap = colormap = Image.Colortable( (string)p->data );
bc73c61999-04-11Per Hedbor  else
c9804a2000-10-08Per Hedbor  meta_colormap = Image.Colortable( (string)p->data );
bc73c61999-04-11Per Hedbor  break;
79757c1999-04-12Per Hedbor  case PROP_COMPRESSION:
c9804a2000-10-08Per Hedbor  compression = ((string)p->data)[0];
79757c1999-04-12Per Hedbor  break;
bc73c61999-04-11Per Hedbor  case PROP_GUIDES:
c9804a2000-10-08Per Hedbor  guides = Array.map(((string)p->data)/5,Guide);
bc73c61999-04-11Per Hedbor  break; case PROP_RESOLUTION:
c9804a2000-10-08Per Hedbor  sscanf( (string)p->data, "%4F%4F", xres,yres);
bc73c61999-04-11Per Hedbor  if (xres < 1e-5 || xres> 1e+5 || yres<1e-5 || yres>1e+5) xres = yres = 72.0; break;
e6c0c42000-02-08Per Hedbor  case PROP_TATTOO:
c9804a2000-10-08Per Hedbor  tattoo_state = p->data->get_int( 0 );
bc73c61999-04-11Per Hedbor  break; case PROP_PARASITES:
c9804a2000-10-08Per Hedbor  parasites = decode_parasites( (string)p->data );
bc73c61999-04-11Per Hedbor  break; case PROP_UNIT:
c9804a2000-10-08Per Hedbor  res_unit = p->data->get_int( 0 );
bc73c61999-04-11Per Hedbor  break; case PROP_PATHS:
517db32000-10-08Per Hedbor  paths = decode_paths( (string)p->data );
bc73c61999-04-11Per Hedbor  break; case PROP_USER_UNIT: /* NYI */ break; } } } void create( mapping data ) { type = data->type; decode_properties( data->properties ); width = data->width; height = data->height; foreach(data->layers, mapping l )
563bd72004-01-11Martin Nilsson  layers += ({ Layer( l, this ) });
bc73c61999-04-11Per Hedbor  foreach(data->channels, mapping c )
563bd72004-01-11Martin Nilsson  channels += ({ Channel( c, this ) });
bc73c61999-04-11Per Hedbor  } }
d1f3142013-07-08Henrik Grubbström (Grubba) //!
bc73c61999-04-11Per Hedbor GimpImage __decode( string|mapping what ) {
79757c1999-04-12Per Hedbor  if(stringp(what)) what = ___decode( what );
bc73c61999-04-11Per Hedbor  return GimpImage(what); }
d1f3142013-07-08Henrik Grubbström (Grubba) //!
c9804a2000-10-08Per Hedbor mapping decode_header( string|mapping|object(GimpImage) data ) { if( !objectp(data) ) { if( stringp( data ) ) data = ___decode( data ); data = GimpImage( data ); } return ([ "type":"image/x-gimp-image", "xsize":data->width, "ysize":data->height, ]); }
bc73c61999-04-11Per Hedbor 
c1be651999-07-01Per Hedbor string translate_mode( int mode ) { switch( mode ) { case NORMAL_MODE: return "normal"; case MULTIPLY_MODE: return "multiply"; case ADDITION_MODE: return "add"; case DIFFERENCE_MODE: return "difference"; case SUBTRACT_MODE: return "subtract"; case DIVIDE_MODE: return "divide"; case DISSOLVE_MODE: return "dissolve"; case DARKEN_ONLY_MODE: return "min"; case LIGHTEN_ONLY_MODE:return "max"; case HUE_MODE: return "hue"; case SATURATION_MODE: return "saturation"; case COLOR_MODE: return "color"; case VALUE_MODE: return "value"; case SCREEN_MODE: return "screen"; case OVERLAY_MODE: return "overlay"; default: werror("WARNING: XCF: Unsupported mode: "+mode+"\n"); return "normal"; } }
79757c1999-04-12Per Hedbor 
d1f3142013-07-08Henrik Grubbström (Grubba) //!
c9804a2000-10-08Per Hedbor array decode_layers( string|object|mapping what, mapping|void opts, int|void concat )
bc73c61999-04-11Per Hedbor {
0e02e91999-04-11Per Hedbor  if(!opts) opts = ([]);
1a617b2000-10-17Per Hedbor  int shrink = (opts->shrink_fact||1);
79757c1999-04-12Per Hedbor 
9b68cc1999-07-16Per Hedbor  if(!objectp( what ) ) what = __decode( what );
e6c0c42000-02-08Per Hedbor  array layers = ({});
c1be651999-07-01Per Hedbor  if( opts->background ) {
c9804a2000-10-08Per Hedbor  mapping lopts = ([ "tiled":1, ]);
c1be651999-07-01Per Hedbor  lopts->image = Image.Image( 32, 32, opts->background );
9b68cc1999-07-16Per Hedbor  lopts->alpha = Image.Image( 32, 32, Image.Color.white );
c1be651999-07-01Per Hedbor  lopts->alpha_value = 1.0;
e6c0c42000-02-08Per Hedbor  layers = ({ Image.Layer( lopts ) });
c1be651999-07-01Per Hedbor  }
0e02e91999-04-11Per Hedbor 
9b68cc1999-07-16Per Hedbor  foreach(what->layers, object l)
a8f8652000-11-16Per Hedbor  if((l->flags->visible && l->opacity > 0) || opts->draw_all_layers)
0e02e91999-04-11Per Hedbor  {
c9804a2000-10-08Per Hedbor  Image.Layer lay = l->image->get_layer( shrink ); lay->set_mode( translate_mode( l->mode ) ); if( l->opacity != 255 )
33364f2000-12-16Per Hedbor  { if( lay->alpha() ) lay->set_image( lay->image(), lay->alpha()*(l->opacity/255.0) ); else lay->set_image( lay->image(), Image.Image( lay->xsize(), lay->yszize(), l->opacity, l->opacity, l->opacity)); }
c9804a2000-10-08Per Hedbor  lay->set_offset( l->xoffset/shrink, l->yoffset/shrink );
79757c1999-04-12Per Hedbor 
c1be651999-07-01Per Hedbor  if(l->mask && l->flags->apply_mask)
0e02e91999-04-11Per Hedbor  {
c9804a2000-10-08Per Hedbor  object a = lay->alpha(); object a2 =l->mask->image_data->get_layer(shrink)->image(); int x = lay->image()->xsize( ); int y = lay->image()->ysize( ); if( a2->xsize() != x || a2->ysize() != y ) a2 = a2->copy( 0,0, x, y, 255,255,255 );
c1be651999-07-01Per Hedbor  if(a)
c9804a2000-10-08Per Hedbor  a *= l->mask->image_data->get_layer(shrink)->image();
c1be651999-07-01Per Hedbor  else
c9804a2000-10-08Per Hedbor  a = a2;
f369fc2000-12-19Per Hedbor  lay->set_image( lay->image(), a );
0e02e91999-04-11Per Hedbor  }
c1be651999-07-01Per Hedbor  layers += ({ lay });
c9804a2000-10-08Per Hedbor  if(!concat) /* No reason to set these flags if they are just going to be ignored. */ { /* Not really layer related */ lay->set_misc_value( "image_xres", l->parent->xres/shrink ); lay->set_misc_value( "image_yres", l->parent->yres/shrink ); lay->set_misc_value( "image_colormap", l->parent->colormap ); lay->set_misc_value( "image_guides", l->parent->guides ); lay->set_misc_value( "image_parasites", l->parent->parasites ); /* But these are. :) */ lay->set_misc_value( "name", l->name ); lay->set_misc_value( "tattoo", l->tattoo ); lay->set_misc_value( "parasites", l->parasites ); lay->set_misc_value( "visible", l->flags->visible ); if( l == l->parent->active_layer ) lay->set_misc_value( "active", 1 ); }
0e02e91999-04-11Per Hedbor  }
c9804a2000-10-08Per Hedbor 
9b68cc1999-07-16Per Hedbor  return layers; }
0e02e91999-04-11Per Hedbor 
d1f3142013-07-08Henrik Grubbström (Grubba) //!
c9804a2000-10-08Per Hedbor mapping _decode( string|mapping|object(GimpImage) what, mapping|void opts )
9b68cc1999-07-16Per Hedbor { if(!opts) opts = ([]);
c9804a2000-10-08Per Hedbor  GimpImage data; if( objectp( what ) ) data = what; else data = __decode( what );
9b68cc1999-07-16Per Hedbor  what = 0;
e6c0c42000-02-08Per Hedbor 
c9804a2000-10-08Per Hedbor  int shrink = (opts->shrink_fact||1); Image.Layer res = Image.lay(decode_layers( data, opts, 1 ), 0,0,data->width/shrink,data->height/shrink );
c1be651999-07-01Per Hedbor  Image.Image img = res->image(); Image.Image alpha = res->alpha(); res = 0;
79757c1999-04-12Per Hedbor  if(opts->draw_guides) foreach( data->guides, Guide g ) if(g->vertical)
c1be651999-07-01Per Hedbor  {
c9804a2000-10-08Per Hedbor  img->line( g->pos/shrink, 0, g->pos/shrink, img->ysize(), 0,155,0 );
c1be651999-07-01Per Hedbor  if( alpha )
c9804a2000-10-08Per Hedbor  alpha->line( g->pos/shrink,0,g->pos/shrink,img->ysize(), 255,255,255 );
c1be651999-07-01Per Hedbor  }
79757c1999-04-12Per Hedbor  else
c1be651999-07-01Per Hedbor  {
c9804a2000-10-08Per Hedbor  img->line( 0,g->pos/shrink, img->xsize(), g->pos/shrink, 0,155,0 );
c1be651999-07-01Per Hedbor  if( alpha )
c9804a2000-10-08Per Hedbor  alpha->line( 0,g->pos/shrink, img->xsize(),g->pos/shrink, 255,255,255 );
c1be651999-07-01Per Hedbor  }
79757c1999-04-12Per Hedbor 
c9804a2000-10-08Per Hedbor // if(opts->draw_selection) // if(data->selection) // img->paste_alpha_color( data->selection->image_data->img*0.25, // data->selection->r, data->selection->g, // data->selection->b );
79757c1999-04-12Per Hedbor  if(opts->mark_layers) { foreach(data->layers, Layer l) { if(l->flags->visible || opts->draw_all_layers) {
c9804a2000-10-08Per Hedbor  int x1 = l->xoffset/shrink; int x2 = (l->xoffset+l->width)/shrink; int y1 = (l->yoffset)/shrink; int y2 = (l->yoffset+l->height)/shrink;
9642201999-11-24Per Hedbor  img->setcolor(0,0,255);
79757c1999-04-12Per Hedbor  img->line( x1,y1,x2,y1 ); img->line( x2,y1,x2,y2 ); img->line( x2,y2,x1,y2 ); img->line( x1,y2,x1,y1 );
e6c0c42000-02-08Per Hedbor  if(alpha)
c1be651999-07-01Per Hedbor  {
9642201999-11-24Per Hedbor  alpha->setcolor(0,0,255);
c1be651999-07-01Per Hedbor  alpha->line( x1,y1,x2,y1 ); alpha->line( x2,y1,x2,y2 ); alpha->line( x2,y2,x1,y2 ); alpha->line( x1,y2,x1,y1 ); }
79757c1999-04-12Per Hedbor  } } }
e6c0c42000-02-08Per Hedbor 
79757c1999-04-12Per Hedbor  if(opts->mark_layer_names) { foreach(data->layers, Layer l) { if(l->flags->visible || opts->draw_all_layers) {
c1be651999-07-01Per Hedbor  int x, y;
c9804a2000-10-08Per Hedbor  int x1 = l->xoffset/shrink; int y1 = (l->yoffset+3)/shrink;
c1be651999-07-01Per Hedbor  object a = opts->mark_layer_names->write( l->name ); for( x=-1; x<2; x++ ) for( y=-1; y<2; y++ ) { img->paste_alpha_color( a, 0,0,0, x1+x, y1+y ); if(alpha) alpha->paste_alpha_color(a,255,255,255, x1+x,y1+y ); } img->paste_alpha_color( a, 255,255,255, x1, y1 );
79757c1999-04-12Per Hedbor  } } } if(opts->mark_active_layer) { if(data->active_layer) {
c9804a2000-10-08Per Hedbor  int x1 = data->active_layer->xoffset/shrink; int x2 = (data->active_layer->xoffset+data->active_layer->width)/shrink; int y1 = data->active_layer->yoffset/shrink; int y2 = (data->active_layer->yoffset+data->active_layer->height)/shrink;
79757c1999-04-12Per Hedbor  img->setcolor(255,0,0); img->line( x1,y1,x2,y1 ); img->line( x2,y1,x2,y2 ); img->line( x2,y2,x1,y2 ); img->line( x1,y2,x1,y1 );
e6c0c42000-02-08Per Hedbor  if(alpha)
c1be651999-07-01Per Hedbor  {
9642201999-11-24Per Hedbor  alpha->setcolor(0,0,255);
c1be651999-07-01Per Hedbor  alpha->line( x1,y1,x2,y1 ); alpha->line( x2,y1,x2,y2 ); alpha->line( x2,y2,x1,y2 ); alpha->line( x1,y2,x1,y1 ); }
79757c1999-04-12Per Hedbor  } }
c9804a2000-10-08Per Hedbor // Array.map( data->layers, lambda(object o) { destruct(o); } ); // destruct( data );
e6c0c42000-02-08Per Hedbor  return
c1be651999-07-01Per Hedbor  ([
1365a92002-05-08Marcus Comstedt  "type":"image/x-gimp-image",
0e02e91999-04-11Per Hedbor  "image":img, "alpha":alpha, ]);
bc73c61999-04-11Per Hedbor }
d1f3142013-07-08Henrik Grubbström (Grubba) //! @decl Image.Image decode(string bytes, mapping|void options)
0e02e91999-04-11Per Hedbor object decode( string what,mapping|void opts )
bc73c61999-04-11Per Hedbor {
0e02e91999-04-11Per Hedbor  return _decode( what,opts )->image;
bc73c61999-04-11Per Hedbor }
33da032003-12-31Martin Nilsson  // --- Encoding #if 0 #define PROP(X,Y) sprintf("%4c%4c%s", PROP_##X, sizeof(Y), (Y)) #define UINT(X) sprintf("%4c", (X)) #define STRING(X) sprintf("%4c%s\0", sizeof(X)+1, (X))
9eaf1d2008-06-28Martin Nilsson protected string make_hiearchy(Image.Image img) {
33da032003-12-31Martin Nilsson  string data = ""; data += UINT(img->xsize()); data += UINT(img->ysize()); data += UINT(3); // rgb // Make just one tile string i = (string)img; string tile = ""; tile += UINT(img->xsize()); tile += UINT(img->ysize()); tile += UINT(sizeof(i)); tile += i; data += UINT(sizeof(tile)); data += tile; return data; }
9eaf1d2008-06-28Martin Nilsson protected int make_mode(string mode) {
33da032003-12-31Martin Nilsson  switch(mode) { case "normal": return NORMAL_MODE; } werror("Mode %O not supported in XCF.\n", mode); return NORMAL_MODE; }
9eaf1d2008-06-28Martin Nilsson protected string make_layer(Image.Image|Image.Layer img) {
33da032003-12-31Martin Nilsson  string data = ""; data += UINT(img->xsize()); data += UINT(img->ysize()); data += UINT(1); // FIXME: layer type if(img->get_misc_value) data += STRING(img->get_misc_value("name")); else data += STRING(" "); // Layer properties { // ACTIVE_LAYER // SELECTION if(img->xoffset && img->yoffset) data += PROP(OFFSETS, UINT(img->xoffset()) + UINT(img->yoffset())); if(img->alpha_value) data += PROP(OPACITY, UINT(255*img->alpha_value())); else data += PROP(OPACITY, UINT(255)); data += PROP(VISIBLE, UINT(1)); // LINKED // PRESERVE_TRANSPARENCY // APPLY_MASK // EDIT_MASK // SHOW_MASK if(img->mode) data += PROP(MODE, UINT(make_mode(img->mode))); else data += PROP(MODE, UINT(NORMAL_MODE)); // TATTOO // PARASITES data += PROP(END, ""); } string h; if(img->image) h = make_hiearchy(img->image()); else h = make_hiearchy(img); string lm = ""; // make_layer_mask data += UINT(sizeof(h)); // hiearchy size data += UINT(sizeof(lm)); // layer mask size data += lm; data += h; return data; } string encode(Image.Image img) { String.Buffer buf = String.Buffer(); buf->add("gimp xcf file\0"); // width, height, type buf->add( sprintf("%4c%4c%4c", img->xsize(), img->ysize(), 0) ); // Properties // PROP_COLORMAP // PROP_GUIDES // PROP_RESOLUTION // PROP_TATTOO // PROP_PARASITES // PROP_UNIT // PROP_PATHS // PROP_USER_UNIT buf->add( PROP(COMPRESSION, UINT(0)) ); buf->add( PROP(END,"") ); // Layers if(objectp(img)) { string lay = make_layer(img); buf->add( UINT(sizeof(lay)) ); buf->add(lay); } // foreach(indices(layers), Image.Layer layer) { // } buf->add( UINT(0) ); // Channels buf->add( UINT(0) ); return (string)buf; } #endif