e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
bae6381999-04-15Per Hedbor #include "global.h"
d9db231999-05-30Mirar (Pontus Hagland) #include "image_machine.h"
bae6381999-04-15Per Hedbor  #include "pike_macros.h" #include "object.h" #include "module_support.h" #include "interpret.h" #include "svalue.h" #include "threads.h" #include "mapping.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
bae6381999-04-15Per Hedbor #include "stralloc.h" #include "builtin_functions.h" #include "image.h" #include "colortable.h"
c026b22001-03-18Henrik Grubbström (Grubba) #include "bignum.h"
63888b1999-05-07Fredrik Hübinette (Hubbe) 
1784aa1999-05-06David Hedbor #ifdef HAVE_NETINET_IN_H
bae6381999-04-15Per Hedbor #include <netinet/in.h>
1784aa1999-05-06David Hedbor #endif
bae6381999-04-15Per Hedbor 
920aff2000-07-07Henrik Grubbström (Grubba) 
afcf402002-05-11Martin Nilsson #define sp Pike_sp
920aff2000-07-07Henrik Grubbström (Grubba) 
bae6381999-04-15Per Hedbor extern struct program *image_colortable_program; extern struct program *image_program;
01a9572000-02-03Henrik Grubbström (Grubba) #define STRING(X) static struct pike_string *PIKE_CONCAT(s_, X)
bae6381999-04-15Per Hedbor #include "psd_constant_strings.h" #undef STRING struct buffer {
3bd87a2000-08-03Henrik Grubbström (Grubba)  size_t len;
bae6381999-04-15Per Hedbor  unsigned char *str; };
2db2b62000-11-21Per Hedbor static unsigned int psd_read_uint( struct buffer *from )
bae6381999-04-15Per Hedbor { unsigned int res; if(from->len < 4)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Not enough space for 4 bytes (uint32)\n");
bae6381999-04-15Per Hedbor  res = from->str[0]<<24|from->str[1]<<16|from->str[2]<<8|from->str[3]; from->str += 4; from->len -= 4; return res; }
6dc2772000-07-28Fredrik Hübinette (Hubbe) static int psd_read_int( struct buffer *from )
bae6381999-04-15Per Hedbor {
2db2b62000-11-21Per Hedbor  return (int)psd_read_uint( from );
bae6381999-04-15Per Hedbor }
2db2b62000-11-21Per Hedbor static unsigned short psd_read_ushort( struct buffer *from )
bae6381999-04-15Per Hedbor { unsigned short res; if(from->len < 2)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Not enough space for 2 bytes (uint16)\n");
bae6381999-04-15Per Hedbor  res = from->str[0]<<8 | from->str[1]; from->str += 2; from->len -= 2; return res; }
2db2b62000-11-21Per Hedbor static int psd_read_short( struct buffer *from )
bae6381999-04-15Per Hedbor {
2db2b62000-11-21Per Hedbor  return (short)psd_read_ushort( from );
bae6381999-04-15Per Hedbor }
2db2b62000-11-21Per Hedbor static unsigned char psd_read_uchar( struct buffer *from )
bae6381999-04-15Per Hedbor { unsigned char res = 0; if(from->len) { res = from->str[0]; from->str++; from->len--; } return res; }
19035c2014-08-14Henrik Grubbström (Grubba) static int psd_read_schar(struct buffer *from) { return (signed char)psd_read_uchar(from); }
2db2b62000-11-21Per Hedbor static char *psd_read_data( struct buffer * from, size_t len )
bae6381999-04-15Per Hedbor { char *res; if( from->len < len )
cc7cf42015-10-14Martin Nilsson  Pike_error("Not enough space for %lu bytes\n", (unsigned long)len);
01a9572000-02-03Henrik Grubbström (Grubba)  res = (char *)from->str;
bae6381999-04-15Per Hedbor  from->str += len; from->len -= len; return res; }
2db2b62000-11-21Per Hedbor static struct buffer psd_read_string( struct buffer *data )
bae6381999-04-15Per Hedbor { struct buffer res;
6dc2772000-07-28Fredrik Hübinette (Hubbe)  res.len = psd_read_int( data );
2db2b62000-11-21Per Hedbor  res.str = (unsigned char *)psd_read_data( data, res.len );
bae6381999-04-15Per Hedbor  if(res.len > 0) res.len--; /* len includes ending \0 */ if(!res.str)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("String read failed\n");
bae6381999-04-15Per Hedbor  return res; }
2db2b62000-11-21Per Hedbor static struct buffer psd_read_pstring( struct buffer *data )
a8f8652000-11-16Per Hedbor { struct buffer res;
2db2b62000-11-21Per Hedbor  res.len = psd_read_uchar( data ); res.str = (unsigned char *)psd_read_data( data, res.len );
a8f8652000-11-16Per Hedbor  if(!res.str)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("PString read failed\n");
a8f8652000-11-16Per Hedbor  return res; }
bae6381999-04-15Per Hedbor enum image_mode { Bitmap = 0, Greyscale = 1, Indexed = 2, RGB = 3, CMYK = 4, Multichannel = 7, Duotone = 8, Lab = 9, }; struct psd_image { unsigned short num_channels; unsigned int rows; unsigned int columns; unsigned int compression; unsigned short depth; enum image_mode mode; struct buffer color_data; struct buffer resource_data; struct buffer layer_data; struct buffer image_data; struct layer *first_layer; }; struct channel_info { short id; struct buffer data; }; struct layer { struct layer *next; struct layer *prev;
12dc192005-10-13Anders Johansson  int top; int left; int right; int bottom; int mask_top; int mask_left; int mask_right; int mask_bottom;
2767d51999-04-17Per Hedbor  unsigned int mask_default_color; unsigned int mask_flags;
bae6381999-04-15Per Hedbor  unsigned int opacity; unsigned int num_channels; unsigned int clipping; unsigned int flags; struct channel_info channel_info[24]; struct buffer mode; struct buffer extra_data;
a8f8652000-11-16Per Hedbor  struct buffer name;
bae6381999-04-15Per Hedbor };
13670c2015-05-25Martin Nilsson static void decode_layers_and_masks( struct psd_image *dst,
bae6381999-04-15Per Hedbor  struct buffer *src ) { short count, first_alpha_is_magic; struct layer *layer = NULL;
0dd2d42000-08-08Henrik Grubbström (Grubba)  ptrdiff_t exp_offset;
13670c2015-05-25Martin Nilsson  if(!src->len)
bae6381999-04-15Per Hedbor  return;
6dc2772000-07-28Fredrik Hübinette (Hubbe)  exp_offset = src->len-psd_read_int( src ); /* size of layer region */
2db2b62000-11-21Per Hedbor  count = psd_read_short( src );
13670c2015-05-25Martin Nilsson 
bae6381999-04-15Per Hedbor  if( count < 0 ) {
3f74fa2014-05-06Arne Goedeke  if (DO_INT16_NEG_OVERFLOW(count, &count)) Pike_error("overflow\n");
bae6381999-04-15Per Hedbor  first_alpha_is_magic = 1; } else if(count == 0) return; while( count-- ) { unsigned int cnt;
dc8d022014-04-27Martin Nilsson  struct layer *l = layer = xcalloc( sizeof( struct layer ), 1);
bae6381999-04-15Per Hedbor  layer->next = dst->first_layer; if(dst->first_layer) dst->first_layer->prev = layer; dst->first_layer = layer;
6dc2772000-07-28Fredrik Hübinette (Hubbe)  layer->top = psd_read_int( src ); layer->left = psd_read_int( src ); layer->bottom = psd_read_int( src ); layer->right = psd_read_int( src );
161c032015-04-20Henrik Grubbström (Grubba)  layer->num_channels = psd_read_ushort( src ); if (layer->num_channels * 6 > src->len) Pike_error("Too many channels.\n");
bae6381999-04-15Per Hedbor  for(cnt=0; cnt<layer->num_channels; cnt++) {
2db2b62000-11-21Per Hedbor  layer->channel_info[cnt].id = psd_read_ushort(src); layer->channel_info[cnt].data.len = psd_read_uint(src);
bae6381999-04-15Per Hedbor  }
2db2b62000-11-21Per Hedbor  psd_read_uint( src ); /* '8BIM' */
bae6381999-04-15Per Hedbor  layer->mode.len = 4;
2db2b62000-11-21Per Hedbor  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 );
7abdbe2003-07-23Martin Nilsson  psd_read_uchar( src ); /* filler byte */
2db2b62000-11-21Per Hedbor  layer->extra_data = psd_read_string( src );
a8f8652000-11-16Per Hedbor  layer->extra_data.len++;
2767d51999-04-17Per Hedbor  if(layer->extra_data.len) { struct buffer tmp = layer->extra_data; struct buffer tmp2;
2db2b62000-11-21Per Hedbor  tmp2 = psd_read_string( &tmp );
2767d51999-04-17Per Hedbor  if( tmp2.len ) {
6dc2772000-07-28Fredrik Hübinette (Hubbe)  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 );
2db2b62000-11-21Per Hedbor  layer->mask_default_color = psd_read_uchar( &tmp2 );
3caccc2003-09-24Jonas Wallden  layer->mask_flags = psd_read_uchar( &tmp2 );
a8f8652000-11-16Per Hedbor  }
2db2b62000-11-21Per Hedbor  tmp2 = psd_read_string( &tmp );
a8f8652000-11-16Per Hedbor  if( tmp2.len ) {
7abdbe2003-07-23Martin Nilsson  /* Layer blending ranges data */
2767d51999-04-17Per Hedbor  }
2db2b62000-11-21Per Hedbor  layer->name = psd_read_pstring( &tmp );
2767d51999-04-17Per Hedbor  }
bae6381999-04-15Per Hedbor  } while(layer->next) layer = layer->next; /* Now process the layer channel data.. */ while(layer) { unsigned int i; for(i=0; i<layer->num_channels; i++) { layer->channel_info[i].data.str=
2db2b62000-11-21Per Hedbor  (unsigned char *)psd_read_data(src,layer->channel_info[i].data.len);
bae6381999-04-15Per Hedbor  } layer = layer->prev; } } static struct buffer
13670c2015-05-25Martin Nilsson packbitsdecode(struct buffer src, struct buffer dst,
3f74fa2014-05-06Arne Goedeke  size_t nbytes)
bae6381999-04-15Per Hedbor {
340c562001-06-13Henrik Grubbström (Grubba)  int n;
bae6381999-04-15Per Hedbor 
f558f61999-07-16Per Hedbor  while( nbytes-- )
bae6381999-04-15Per Hedbor  {
19035c2014-08-14Henrik Grubbström (Grubba)  n = psd_read_schar( &src );
bae6381999-04-15Per Hedbor  if (n > 0) { ++n; while(n--) { if(dst.len) {
2db2b62000-11-21Per Hedbor  *(dst.str++) = psd_read_uchar( &src );
bae6381999-04-15Per Hedbor  dst.len--; } else return src; } } else if( n == -128 ){ /* noop */ } else { unsigned char val; n = -n+1;
2db2b62000-11-21Per Hedbor  val = psd_read_uchar( &src );
bae6381999-04-15Per Hedbor  while(n--) { if(dst.len) { *(dst.str++) = val; dst.len--; } else return src; } } } if(dst.len)
0af1852000-08-11Henrik Grubbström (Grubba)  fprintf(stderr, "%ld bytes left to write! (should be 0)\n",
cc7cf42015-10-14Martin Nilsson  (long)dst.len);
bae6381999-04-15Per Hedbor  return src; } static void f_decode_packbits_encoded(INT32 args) {
d67e0d2008-01-19Henrik Grubbström (Grubba)  struct pike_string *src = NULL; int nelems = 0; int width = 0; int multiplier = 1;
bae6381999-04-15Per Hedbor  struct pike_string *dest;
d67e0d2008-01-19Henrik Grubbström (Grubba)  int compression = -1;
bae6381999-04-15Per Hedbor  struct buffer b, ob, d;
017b572011-10-28Henrik Grubbström (Grubba)  if(TYPEOF(sp[-args]) != T_STRING)
6de0852004-01-23Martin Nilsson  Pike_error("Internal argument error.\n");
bae6381999-04-15Per Hedbor 
391ac52018-08-05Martin Nilsson  get_all_args(NULL, args,
d67e0d2008-01-19Henrik Grubbström (Grubba)  "%T%d%d.%d%d", &src, &nelems, &width, &multiplier, &compression); nelems *= multiplier; b.str = (unsigned char *)src->str; b.len = src->len; if (compression < 0) {
3f74fa2014-05-06Arne Goedeke  compression = psd_read_ushort(&b);
2767d51999-04-17Per Hedbor  }
d67e0d2008-01-19Henrik Grubbström (Grubba)  pop_n_elems(args-1);
3f74fa2014-05-06Arne Goedeke  if (nelems < 0 || b.len < (size_t)nelems*2) Pike_error("Not enough space for %d short integers.\n", nelems);
bae6381999-04-15Per Hedbor  ob = b; ob.str += nelems*2; ob.len -= nelems*2;
2767d51999-04-17Per Hedbor  switch(compression)
bae6381999-04-15Per Hedbor  { case 1:
3f74fa2014-05-06Arne Goedeke  d.len = width * nelems; dest = begin_shared_string( d.len ); d.str = (unsigned char *)dest->str; packbitsdecode( ob, d, d.len );
f558f61999-07-16Per Hedbor  push_string( end_shared_string( dest ) );
bae6381999-04-15Per Hedbor  break; case 0:
01a9572000-02-03Henrik Grubbström (Grubba)  push_string( make_shared_binary_string((char *)b.str,b.len));
bae6381999-04-15Per Hedbor  break; default:
d67e0d2008-01-19Henrik Grubbström (Grubba)  Pike_error("Unsupported compression (%d)!\n", compression);
bae6381999-04-15Per Hedbor  } stack_swap(); pop_stack(); return; } static void f_decode_image_channel( INT32 args ) {
340c562001-06-13Henrik Grubbström (Grubba)  INT_TYPE w, h;
bae6381999-04-15Per Hedbor  int y; struct pike_string *s; struct object *io; unsigned char *source; rgb_group *dst;
391ac52018-08-05Martin Nilsson  get_all_args( NULL, args, "%i%i%S", &w,&h,&s);
bae6381999-04-15Per Hedbor  ref_push_string( s ); push_int( h ); push_int( w ); f_decode_packbits_encoded( 3 ); s = sp[-1].u.string; stack_swap(); pop_stack(); if(s->len < w*h)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Not enough data in string for this channel\n");
01a9572000-02-03Henrik Grubbström (Grubba)  source = (unsigned char *)s->str;
bae6381999-04-15Per Hedbor  push_int( w ); push_int( h ); io = clone_object( image_program, 2 );
13b5ed2014-05-26Per Hedbor  dst = ((struct image*)get_storage(io,image_program))->img;
bae6381999-04-15Per Hedbor  for(y=0; y<w*h; y++)
09b5b42000-03-26Fredrik Hübinette (Hubbe)  { dst->r = dst->g = dst->b = *(source++); dst++; }
bae6381999-04-15Per Hedbor  pop_n_elems(args); push_object( io ); }
2767d51999-04-17Per Hedbor static void f_decode_image_data( INT32 args ) {
65a5492000-08-10Per Hedbor  INT_TYPE w, h, c, d, m;
2767d51999-04-17Per Hedbor  int y; struct pike_string *s, *ct; struct object *io; unsigned char *source, *source2, *source3, *source4; rgb_group *dst;
391ac52018-08-05Martin Nilsson  get_all_args( NULL, args, "%i%i%i%i%i%S%S",
2767d51999-04-17Per Hedbor  &w,&h,&d,&m,&c,&s,&ct);
bae6381999-04-15Per Hedbor 
2767d51999-04-17Per Hedbor  if(!ct->len) ct = NULL; ref_push_string( s ); push_int( h ); push_int( w ); push_int( d ); push_int( c ); f_decode_packbits_encoded( 5 ); s = sp[-1].u.string; stack_swap(); pop_stack(); if(s->len < w*h*d)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Not enough data in string for this channel\n");
01a9572000-02-03Henrik Grubbström (Grubba)  source = (unsigned char *)s->str; source2 = source+w*h; source3 = source+w*h*2; source4 = source+w*h*3;
2767d51999-04-17Per Hedbor  push_int( w ); push_int( h ); io = clone_object( image_program, 2 );
13b5ed2014-05-26Per Hedbor  dst = ((struct image*)get_storage(io,image_program))->img;
2767d51999-04-17Per Hedbor  for(y=0; y<w*h; y++) { switch( d ) { case 4: /* cmyk.. */
ab86181999-05-02Fredrik Hübinette (Hubbe)  dst->r = MAXIMUM(255-(*(source++) + *source4), 0); dst->g = MAXIMUM(255-(*(source2++) + *source4), 0); dst->b = MAXIMUM(255-(*(source3++) + *source4), 0);
c11b971999-04-22Per Hedbor  dst++; source4++;
2767d51999-04-17Per Hedbor  break; case 3:
c11b971999-04-22Per Hedbor  if( m != CMYK ) { dst->r = *(source++); dst->g = *(source2++); (dst++)->b = *(source3++); } else { dst->r = 255-*(source++); dst->g = 255-*(source2++); dst->b = 255-*(source3++); }
2767d51999-04-17Per Hedbor  break; case 2: case 1: if(ct) { dst->r = ct->str[*source]; dst->g = ct->str[*source+256]; dst->b = ct->str[*source+256*2];
6857c72008-01-15Henrik Grubbström (Grubba)  source++; dst++;
2767d51999-04-17Per Hedbor  } else
09b5b42000-03-26Fredrik Hübinette (Hubbe)  { dst->r = dst->g = dst->b = *(source++); dst++; }
2767d51999-04-17Per Hedbor  break; } } pop_n_elems(args); push_object( io ); }
bae6381999-04-15Per Hedbor  static void free_image( struct psd_image *i ) { while(i->first_layer) { struct layer *t = i->first_layer; i->first_layer = t->next; free(t); } } static struct psd_image low_psd_decode( struct buffer *b ) { int *s = (int *)b->str; struct psd_image i; ONERROR err;
21b12a2014-09-03Martin Nilsson  memset(&i, 0, sizeof(i));
bae6381999-04-15Per Hedbor  SET_ONERROR( err, free_image, &i );
2db2b62000-11-21Per Hedbor  i.num_channels = psd_read_ushort( b ); i.rows = psd_read_uint( b );
13670c2015-05-25Martin Nilsson  i.columns = psd_read_uint( b );
2db2b62000-11-21Per Hedbor  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 );
bae6381999-04-15Per Hedbor  i.image_data = *b; decode_layers_and_masks( &i, &i.layer_data ); UNSET_ONERROR( err ); return i; } void push_buffer( struct buffer *b ) {
01a9572000-02-03Henrik Grubbström (Grubba)  push_string( make_shared_binary_string( (char *)b->str, b->len ) );
bae6381999-04-15Per Hedbor } void push_layer( struct layer *l) { unsigned int i; struct svalue *osp = sp; ref_push_string( s_top ); push_int( l->top ); ref_push_string( s_left ); push_int( l->left ); ref_push_string( s_right ); push_int( l->right ); ref_push_string( s_bottom ); push_int( l->bottom );
2767d51999-04-17Per Hedbor  ref_push_string( s_mask_top ); push_int( l->mask_top ); ref_push_string( s_mask_left ); push_int( l->mask_left ); ref_push_string( s_mask_right ); push_int( l->mask_right ); ref_push_string( s_mask_bottom ); push_int( l->mask_bottom ); ref_push_string( s_mask_flags ); push_int( l->mask_flags );
3caccc2003-09-24Jonas Wallden  ref_push_string( s_mask_default_color ); push_int( l->mask_default_color );
bae6381999-04-15Per Hedbor  ref_push_string( s_opacity ); push_int( l->opacity ); ref_push_string( s_clipping ); push_int( l->clipping ); ref_push_string( s_flags ); push_int( l->flags ); ref_push_string( s_mode ); push_buffer( &l->mode ); ref_push_string( s_extra_data ); push_buffer( &l->extra_data );
a8f8652000-11-16Per Hedbor  ref_push_string( s_name ); push_buffer( &l->name );
bae6381999-04-15Per Hedbor  ref_push_string( s_channels ); for( i = 0; i<l->num_channels; i++ ) { ref_push_string( s_id ); push_int( l->channel_info[i].id ); ref_push_string( s_data ); push_buffer( &l->channel_info[i].data ); f_aggregate_mapping( 4 ); } f_aggregate( l->num_channels );
cc7cf42015-10-14Martin Nilsson  f_aggregate_mapping((INT32)(sp - osp));
bae6381999-04-15Per Hedbor }
2db2b62000-11-21Per Hedbor static void decode_resources( struct buffer *b );
bae6381999-04-15Per Hedbor void push_psd_image( struct psd_image *i ) { struct svalue *osp = sp, *tsp; struct layer *l; ref_push_string( s_channels ); push_int( i->num_channels ); ref_push_string( s_height ); push_int( i->rows ); ref_push_string( s_width ); push_int( i->columns ); ref_push_string( s_compression ); push_int( i->compression );
7abdbe2003-07-23Martin Nilsson  ref_push_string( s_depth ); push_int( i->depth );
bae6381999-04-15Per Hedbor  ref_push_string( s_mode ); push_int( i->mode ); ref_push_string( s_color_data ); push_buffer( &i->color_data );
2db2b62000-11-21Per Hedbor  ref_push_string( s_resources ); decode_resources( &i->resource_data );
bae6381999-04-15Per Hedbor  ref_push_string( s_image_data ); push_buffer( &i->image_data ); ref_push_string( s_layers ); l = i->first_layer; tsp = sp; while( l ) { push_layer( l ); l = l->next; }
cc7cf42015-10-14Martin Nilsson  f_aggregate((INT32)(sp - tsp)); f_aggregate_mapping((INT32)(sp - osp));
bae6381999-04-15Per Hedbor }
2db2b62000-11-21Per Hedbor 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;
7abdbe2003-07-23Martin Nilsson  /* Non-photoshop software may use another identifier and still be compatible with the Adobe PSD file format specification. FIXME? */
2db2b62000-11-21Per Hedbor  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++; if( data.len & 1 ) psd_read_uchar( b ); switch( id ) { case 0x03f0: /* caption */ { struct buffer b = psd_read_pstring( &data );
5e9fc02015-08-18Per Hedbor  push_static_text( "caption" );
2db2b62000-11-21Per Hedbor  push_buffer( &b ); } break; case 0x0400: /* layer state info */
5e9fc02015-08-18Per Hedbor  push_static_text( "active_layer" );
2db2b62000-11-21Per Hedbor  push_int( psd_read_short( &data ) ); break; case 0x0408: /* guides */
5e9fc02015-08-18Per Hedbor  push_static_text( "guides" );
2db2b62000-11-21Per Hedbor  { int i,num_guides;
759fe62000-11-23Per Hedbor  short magic1, magic2, magic3, magic4, magic5, magic6; /*from gimp.*/
2db2b62000-11-21Per Hedbor  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++) {
986b522001-03-17Henrik Grubbström (Grubba)  ptrdiff_t p = psd_read_int( &data );
2db2b62000-11-21Per Hedbor  int h = psd_read_uchar( &data ); if( h )
986b522001-03-17Henrik Grubbström (Grubba)  p = (ptrdiff_t)((((double)p) * (magic4>>8)) / ((double)(magic4&255)));
2db2b62000-11-21Per Hedbor  else
986b522001-03-17Henrik Grubbström (Grubba)  p = (ptrdiff_t)((((double)p) * (magic6>>8)) / ((double)(magic6&255)));
5e9fc02015-08-18Per Hedbor  push_static_text( "pos" ); push_int64( p ); push_static_text( "vertical" ); push_int( !h );
2db2b62000-11-21Per Hedbor  f_aggregate_mapping( 4 ); } f_aggregate( num_guides ); } break;
7abdbe2003-07-23Martin Nilsson  case 0x040b: /* URL */ { struct buffer b = psd_read_pstring( &data );
5e9fc02015-08-18Per Hedbor  push_static_text( "url" );
7abdbe2003-07-23Martin Nilsson  push_buffer( &b ); } break;
2db2b62000-11-21Per Hedbor  case 0x03ed: /* res. info. */
5e9fc02015-08-18Per Hedbor  push_static_text( "resinfo" );
2db2b62000-11-21Per Hedbor 
5e9fc02015-08-18Per Hedbor  push_static_text( "hres" ); push_int(psd_read_int( &data ) ); push_static_text( "hres_unit" ); push_int(psd_read_short( &data ) ); push_static_text( "width_unit" ); push_int(psd_read_short( &data ) );
2db2b62000-11-21Per Hedbor 
5e9fc02015-08-18Per Hedbor  push_static_text( "vres" ); push_int(psd_read_int( &data ) ); push_static_text( "vres_unit" ); push_int(psd_read_short( &data ) ); push_static_text( "height_unit" );push_int(psd_read_short( &data ) );
2db2b62000-11-21Per Hedbor  f_aggregate_mapping( 12 ); break;
7abdbe2003-07-23Martin Nilsson  case 0x03fc: /* Declared completely obsolete by Adobe */ case 0x03ff: case 0x0403: break; case 0x03e8: /* Photoshop 2.0. Obsolete! */ /* 5*int16 channels, rows, columns, depth, mode */ case 0x03e9: /* Machintosh print manager print info record. */ case 0x03eb: /* Photoshop 2.0. Obsolete! Indexed color table */ case 0x03ee: /* Names of alpha channels as a series of pascal strings */ case 0x03ef: /* DisplayInfo structure */ case 0x03f1: /* Border information */ /* Contains a fixed-number for the border width and an int16 for the border units (1=inches, 2=cm, 3=points, 4=picas, 5=columns) */ case 0x03f2: /* Background color. */ case 0x03f3: /* Print flags */ /* A series of one byte boolean values for labels, crop marks, color bars, registration marks, negative, flip interpolate and caption */ case 0x03f4: /* Grayscale and multichannel halftoning information. */ case 0x03f5: /* Color halftoning information. */ case 0x03f6: /* Duotone halftoning information. */ case 0x03f7: /* Grayscale and multichannel transfer functions. */ case 0x03f8: /* Color transfer functions. */ case 0x03f9: /* Duotone transfer functions. */ case 0x03fa: /* Duotone image information. */ case 0x03fb: /* Two bytes for the effective black and white values for the dot range. */ case 0x03fd: /* EPS options */ case 0x03fe: /* Quick Mask information. 2 bytes containing Quick Mask channel ID. One byte boolean indicating whether the mask was initially empty. */ case 0x0401: /* Working path */ case 0x0402: /* Layers group information. 2 bytes per layer containing a group ID for the dragging groups. */ case 0x0404: /* IPTC-NAA record */ case 0x0405: /* Image mode for raw format files. */ case 0x0406: /* JPEG quality */ case 0x040A: /* Copyright flag */ case 0x0bb7: /* Name of clipping path */ case 0x2710: /* Print flags information . 2 bytes version (=1), 1 byte center crop marks, 1 zeroed byte, 4 bytes bleed width value, 2 bytes bleed width scale. */
2db2b62000-11-21Per Hedbor  default:
93b9462003-07-24Henrik Grubbström (Grubba)  if ((id >= 0x07d0) && (id <= 0x0bb6)) { /* Path information */ }
2db2b62000-11-21Per Hedbor  push_int( id ); push_buffer( &data ); break; } }
cc7cf42015-10-14Martin Nilsson  f_aggregate_mapping( (int)(sp-osp) );
2db2b62000-11-21Per Hedbor }
bae6381999-04-15Per Hedbor static void image_f_psd___decode( INT32 args ) { struct pike_string *s; struct buffer b;
391ac52018-08-05Martin Nilsson  get_all_args( NULL, args, "%S", &s );
bae6381999-04-15Per Hedbor  if(args > 1) pop_n_elems( args-1 );
7abdbe2003-07-23Martin Nilsson  if(s->len < 26+4+4+4 ) /* header+color mode+image res+layers */ Pike_error("This is not a Photoshop PSD file (too short)\n");
13670c2015-05-25Martin Nilsson  if(s->str[0] != '8' || s->str[1] != 'B'
bae6381999-04-15Per Hedbor  || s->str[2] != 'P' || s->str[3] != 'S' )
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("This is not a Photoshop PSD file (invalid signature)\n");
bae6381999-04-15Per Hedbor  if(s->str[4] || s->str[5] != 1)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("This is not a Photoshop PSD file (invalid version)\n");
13670c2015-05-25Martin Nilsson 
bae6381999-04-15Per Hedbor  b.len = s->len-12;
01a9572000-02-03Henrik Grubbström (Grubba)  b.str = (unsigned char *)s->str+12;
bae6381999-04-15Per Hedbor  { ONERROR onerr; struct psd_image i = low_psd_decode( &b ); SET_ONERROR( onerr, free_image, &i ); push_psd_image( &i ); UNSET_ONERROR( onerr ); free_image( &i ); stack_swap(); pop_stack(); } }
2767d51999-04-17Per Hedbor static void f_apply_cmap( INT32 args ) { struct object *io; struct image *i; rgb_group *d; struct pike_string *cmap; int n;
391ac52018-08-05Martin Nilsson  get_all_args( NULL, args, "%o%S", &io, &cmap );
2767d51999-04-17Per Hedbor  if(cmap->len < 256*3)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid colormap resource\n");
13b5ed2014-05-26Per Hedbor  if(!(i = get_storage( io, image_program )))
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Invalid image object\n");
2767d51999-04-17Per Hedbor  n = i->xsize * i->ysize; d = i->img; THREADS_ALLOW(); while(n--) { int i = d->g; d->r = cmap->str[i]; d->g = cmap->str[i+256]; d->b = cmap->str[i+512]; } THREADS_DISALLOW(); }
bae6381999-04-15Per Hedbor static struct program *image_encoding_psd_program=NULL;
c9eefb2014-08-21Martin Nilsson void init_image_psd(void)
bae6381999-04-15Per Hedbor {
226ec82005-01-23Martin Nilsson  ADD_FUNCTION( "___decode", image_f_psd___decode, tFunc(tStr,tMapping), 0); ADD_FUNCTION( "___decode_image_channel", f_decode_image_channel,tFunction,0); ADD_FUNCTION( "___decode_image_data", f_decode_image_data,tFunction,0); ADD_FUNCTION( "__apply_cmap", f_apply_cmap, tFunc(tObj tStr,tVoid), 0);
bae6381999-04-15Per Hedbor  add_integer_constant("Bitmap" , Bitmap, 0 ); add_integer_constant("Greyscale" , Greyscale, 0 ); add_integer_constant("Indexed" , Indexed, 0 ); add_integer_constant("RGB" , RGB, 0 ); add_integer_constant("CMYK" , CMYK, 0 ); add_integer_constant("Multichannel" , Multichannel, 0 ); add_integer_constant("Duotone" , Duotone, 0 ); add_integer_constant("Lab" , Lab, 0 );
a8f8652000-11-16Per Hedbor  add_integer_constant("LAYER_FLAG_PRESERVE_TRANSPARENCY", 0x01, 0 ); add_integer_constant("LAYER_FLAG_INVISIBLE", 0x02, 0 );
bae6381999-04-15Per Hedbor  add_integer_constant("LAYER_FLAG_BIT4", 0x04, 0 ); add_integer_constant("LAYER_FLAG_NOPIX", 0x08, 0 );
5aa7661999-09-06Henrik Grubbström (Grubba) #define STRING(X) PIKE_CONCAT(s_, X) = \ make_shared_binary_string(#X,sizeof( #X )-sizeof(""))
bae6381999-04-15Per Hedbor #include "psd_constant_strings.h" #undef STRING }
c9eefb2014-08-21Martin Nilsson void exit_image_psd(void)
bae6381999-04-15Per Hedbor {
5aa7661999-09-06Henrik Grubbström (Grubba) #define STRING(X) free_string(PIKE_CONCAT(s_, X))
bae6381999-04-15Per Hedbor #include "psd_constant_strings.h" #undef STRING }