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. */
4211a81998-03-23Mirar (Pontus Hagland)  /* **! module Image **! submodule XWD **!
13670c2015-05-25Martin Nilsson **! This submodule keeps the XWD (X Windows Dump)
4211a81998-03-23Mirar (Pontus Hagland) **! decode capabilities of the <ref>Image</ref> module. **! **! XWD is the output format for the xwd program. **! **! Simple decoding:<br> **! <ref>decode</ref> **! **! Advanced decoding:<br> **! <ref>_decode</ref> **!
448c201999-04-13Mirar (Pontus Hagland) **! see also: Image, Image.Image, Image.PNM, Image.X
4211a81998-03-23Mirar (Pontus Hagland) */
fec6251998-03-25Fredrik Hübinette (Hubbe) #include "global.h"
4211a81998-03-23Mirar (Pontus Hagland)  #include <math.h> #include <ctype.h> #include "stralloc.h" #include "object.h" #include "interpret.h" #include "svalue.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
132f0d2000-08-13Henrik Grubbström (Grubba) #include "mapping.h"
4211a81998-03-23Mirar (Pontus Hagland)  #include "image.h" #include "builtin_functions.h"
6dc2772000-07-28Fredrik Hübinette (Hubbe) #include "operators.h"
82ff642000-07-03Henrik Grubbström (Grubba) #include "encodings.h"
6a932b2014-08-18Martin Nilsson #include "pike_types.h"
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
6ad2372002-05-11Martin Nilsson #define sp Pike_sp
6dc2772000-07-28Fredrik Hübinette (Hubbe) 
4211a81998-03-23Mirar (Pontus Hagland) extern struct program *image_colortable_program; extern struct program *image_program; void image_x_decode_truecolor_masks(INT32 args);
6ec0681998-03-25Mirar (Pontus Hagland) void image_x_decode_pseudocolor(INT32 args);
4211a81998-03-23Mirar (Pontus Hagland)  /* **! method mapping _decode(string data)
3ca1361999-05-20Mirar (Pontus Hagland) **! method mapping decode_header(string data)
4211a81998-03-23Mirar (Pontus Hagland) **! Decodes XWD data and returns the result.
82a1ab1998-05-09Mirar (Pontus Hagland) **! **! Supported XWD visual classes and encoding formats are **! TrueColor / ZPixmap
3ca1361999-05-20Mirar (Pontus Hagland) **! DirectColor / ZPixmap
82a1ab1998-05-09Mirar (Pontus Hagland) **! PseudoColor / ZPixmap **! **! If someone sends me files of other formats, these formats
115ea02003-09-26Mirar (Pontus Hagland) **! may be implemented. <tt>:)</tt> /<tt>mirar+pike@mirar.org</tt>
82a1ab1998-05-09Mirar (Pontus Hagland) **! **! see also: decode
4211a81998-03-23Mirar (Pontus Hagland) **! **! note **! This function may throw errors upon illegal or unknown XWD data. **! **! returns the decoded image as an image object */
01b9212016-01-12Per Hedbor static inline unsigned long int_from_32bit(unsigned char *data)
4211a81998-03-23Mirar (Pontus Hagland) {
0c5a2b2012-12-07Arne Goedeke  return ((unsigned long)data[0]<<24)|(data[1]<<16)|(data[2]<<8)|(data[3]);
4211a81998-03-23Mirar (Pontus Hagland) }
01b9212016-01-12Per Hedbor static inline unsigned long int_from_16bit(unsigned char *data)
4211a81998-03-23Mirar (Pontus Hagland) { return (data[0]<<8)|(data[1]); } #define CARD32n(S,N) int_from_32bit((unsigned char*)(S)->str+(N)*4)
3ca1361999-05-20Mirar (Pontus Hagland) void img_xwd__decode(INT32 args,int header_only,int skipcmap)
4211a81998-03-23Mirar (Pontus Hagland) { struct object *co=NULL; struct pike_string *s;
13670c2015-05-25Martin Nilsson  struct
4211a81998-03-23Mirar (Pontus Hagland)  {
13670c2015-05-25Martin Nilsson  unsigned long header_size;
4211a81998-03-23Mirar (Pontus Hagland)  unsigned long file_version; /* = XWD_FILE_VERSION above */ unsigned long pixmap_format; /* ZPixmap or XYPixmap */ unsigned long pixmap_depth; /* Pixmap depth */ unsigned long pixmap_width; /* Pixmap width */ unsigned long pixmap_height; /* Pixmap height */ unsigned long xoffset; /* Bitmap x offset, normally 0 */ unsigned long byte_order; /* of image data: MSBFirst, LSBFirst */
13670c2015-05-25Martin Nilsson 
4211a81998-03-23Mirar (Pontus Hagland)  unsigned long bitmap_unit; /* scanline padding for bitmaps */
13670c2015-05-25Martin Nilsson 
4211a81998-03-23Mirar (Pontus Hagland)  unsigned long bitmap_bit_order; /* bitmaps only: MSBFirst, LSBFirst */
13670c2015-05-25Martin Nilsson 
4211a81998-03-23Mirar (Pontus Hagland)  unsigned long bitmap_pad; /* scanline padding for pixmaps */
13670c2015-05-25Martin Nilsson 
4211a81998-03-23Mirar (Pontus Hagland)  unsigned long bits_per_pixel; /* Bits per pixel */ /* bytes_per_line is pixmap_width padded to bitmap_unit (bitmaps) * or bitmap_pad (pixmaps). It is the delta (in bytes) to get * to the same x position on an adjacent row. */ unsigned long bytes_per_line; unsigned long visual_class; /* Class of colormap */ unsigned long red_mask; /* Z red mask */ unsigned long green_mask; /* Z green mask */ unsigned long blue_mask; /* Z blue mask */ unsigned long bits_per_rgb; /* Log2 of distinct color values */ unsigned long colormap_entries; /* Number of entries in colmap unused?*/ unsigned long ncolors; /* Number of XWDColor structures */ unsigned long window_width; /* Window width */ unsigned long window_height; /* Window height */ unsigned long window_x; /* Window upper left X coordinate */ unsigned long window_y; /* Window upper left Y coordinate */ unsigned long window_bdrwidth; /* Window border width */ } header;
3ca1361999-05-20Mirar (Pontus Hagland)  int n=0;
4211a81998-03-23Mirar (Pontus Hagland) 
dcc2432000-01-11Martin Stjernholm  ONERROR uwp;
017b572011-10-28Henrik Grubbström (Grubba)  if (args<1 || TYPEOF(sp[-args]) != T_STRING)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.XWD._decode(): Illegal arguments\n");
13670c2015-05-25Martin Nilsson 
dcc2432000-01-11Martin Stjernholm  s=sp[-args].u.string;
4211a81998-03-23Mirar (Pontus Hagland)  /* header_size = SIZEOF(XWDheader) + length of null-terminated * window name. */
13670c2015-05-25Martin Nilsson  if (s->len<4)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.XWD._decode: header to small\n");
4211a81998-03-23Mirar (Pontus Hagland)  header.header_size=CARD32n(s,0);
bfccef2000-08-04Henrik Grubbström (Grubba)  if ((size_t)s->len < header.header_size || s->len<100)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.XWD._decode: header to small\n");
4211a81998-03-23Mirar (Pontus Hagland) 
13670c2015-05-25Martin Nilsson  header.file_version=CARD32n(s,1);
4211a81998-03-23Mirar (Pontus Hagland)  if (header.file_version!=7)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.XWD._decode: don't understand any other file format then 7\n");
dcc2432000-01-11Martin Stjernholm  add_ref(s); pop_n_elems(args); SET_ONERROR(uwp,do_free_string,s); header.pixmap_format=CARD32n(s,2);
13670c2015-05-25Martin Nilsson  header.pixmap_depth=CARD32n(s,3); header.pixmap_width=CARD32n(s,4); header.pixmap_height=CARD32n(s,5); header.xoffset=CARD32n(s,6); header.byte_order=CARD32n(s,7); header.bitmap_unit=CARD32n(s,8); header.bitmap_bit_order=CARD32n(s,9); header.bitmap_pad=CARD32n(s,10); header.bits_per_pixel=CARD32n(s,11); header.bytes_per_line=CARD32n(s,12); header.visual_class=CARD32n(s,13); header.red_mask=CARD32n(s,14); header.green_mask=CARD32n(s,15); header.blue_mask=CARD32n(s,16); header.bits_per_rgb=CARD32n(s,17); header.colormap_entries=CARD32n(s,18); header.ncolors=CARD32n(s,19); header.window_width=CARD32n(s,20); header.window_height=CARD32n(s,21); header.window_x=CARD32n(s,22); header.window_y=CARD32n(s,23); header.window_bdrwidth=CARD32n(s,24);
5e9fc02015-08-18Per Hedbor  push_static_text("header_size");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.header_size);
5e9fc02015-08-18Per Hedbor  push_static_text("file_version");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.file_version);
5e9fc02015-08-18Per Hedbor  push_static_text("pixmap_format");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.pixmap_format);
5e9fc02015-08-18Per Hedbor  push_static_text("pixmap_depth");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.pixmap_depth);
5e9fc02015-08-18Per Hedbor  push_static_text("pixmap_width");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.pixmap_width);
5e9fc02015-08-18Per Hedbor  push_static_text("pixmap_height");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.pixmap_height);
5e9fc02015-08-18Per Hedbor  push_static_text("xoffset");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.xoffset);
5e9fc02015-08-18Per Hedbor  push_static_text("byte_order");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.byte_order);
5e9fc02015-08-18Per Hedbor  push_static_text("bitmap_unit");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.bitmap_unit);
5e9fc02015-08-18Per Hedbor  push_static_text("bitmap_bit_order");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.bitmap_bit_order);
5e9fc02015-08-18Per Hedbor  push_static_text("bitmap_pad");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.bitmap_pad);
5e9fc02015-08-18Per Hedbor  push_static_text("bits_per_pixel");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.bits_per_pixel);
5e9fc02015-08-18Per Hedbor  push_static_text("bytes_per_line");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.bytes_per_line);
5e9fc02015-08-18Per Hedbor  push_static_text("visual_class");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.visual_class);
5e9fc02015-08-18Per Hedbor  push_static_text("red_mask");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.red_mask);
5e9fc02015-08-18Per Hedbor  push_static_text("green_mask");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.green_mask);
5e9fc02015-08-18Per Hedbor  push_static_text("blue_mask");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.blue_mask);
5e9fc02015-08-18Per Hedbor  push_static_text("bits_per_rgb");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.bits_per_rgb);
5e9fc02015-08-18Per Hedbor  push_static_text("colormap_entries");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.colormap_entries);
5e9fc02015-08-18Per Hedbor  push_static_text("ncolors");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.ncolors);
5e9fc02015-08-18Per Hedbor  push_static_text("window_width");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.window_width);
5e9fc02015-08-18Per Hedbor  push_static_text("window_height");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.window_height);
5e9fc02015-08-18Per Hedbor  push_static_text("window_x");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.window_x);
5e9fc02015-08-18Per Hedbor  push_static_text("window_y");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.window_y);
5e9fc02015-08-18Per Hedbor  push_static_text("window_bdrwidth");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(header.window_bdrwidth);
3ca1361999-05-20Mirar (Pontus Hagland)  n+=25;
6a932b2014-08-18Martin Nilsson  ref_push_string(literal_type_string);
5e9fc02015-08-18Per Hedbor  push_static_text("image/x-xwd");
3ca1361999-05-20Mirar (Pontus Hagland)  n++;
4211a81998-03-23Mirar (Pontus Hagland)  /* the size of the header is 100 bytes, name is null-terminated */
5e9fc02015-08-18Per Hedbor  push_static_text("windowname");
82a1ab1998-05-09Mirar (Pontus Hagland)  if (header.header_size>100) push_string(make_shared_binary_string(s->str+100,header.header_size-100-1));
13670c2015-05-25Martin Nilsson  else
82a1ab1998-05-09Mirar (Pontus Hagland)  push_int(0);
3ca1361999-05-20Mirar (Pontus Hagland)  n++;
4211a81998-03-23Mirar (Pontus Hagland)  /* header.ncolors XWDColor structs */
05bc722009-08-06Henrik Grubbström (Grubba)  /* NB: The cmap needs to be decoded if the image is to be decoded. */ if (!skipcmap || !header_only ||
13670c2015-05-25Martin Nilsson  header.visual_class==3 ||
3ca1361999-05-20Mirar (Pontus Hagland)  header.visual_class==5)
4211a81998-03-23Mirar (Pontus Hagland)  {
5e9fc02015-08-18Per Hedbor  push_static_text("colors");
4211a81998-03-23Mirar (Pontus Hagland)  if (s->len-header.header_size>=12*header.ncolors) { unsigned long i; if (skipcmap) push_int(0); else { for (i=0; i<header.ncolors; i++) { push_int(int_from_32bit((unsigned char*)s->str+header.header_size+i*12 +0)); push_int(int_from_16bit((unsigned char*)s->str+header.header_size+i*12 +4)); push_int(int_from_16bit((unsigned char*)s->str+header.header_size+i*12 +6)); push_int(int_from_16bit((unsigned char*)s->str+header.header_size+i*12 +8)); push_int(*(unsigned char*)(s->str+header.header_size+i*12 +10)); push_int(*(unsigned char*)(s->str+header.header_size+i*12 +11)); f_aggregate(6); } f_aggregate(header.ncolors); }
5e9fc02015-08-18Per Hedbor  push_static_text("colortable");
4211a81998-03-23Mirar (Pontus Hagland)  for (i=0; i<header.ncolors; i++) { push_int(int_from_16bit((unsigned char*)s->str+header.header_size+i*12 +4)>>8); push_int(int_from_16bit((unsigned char*)s->str+header.header_size+i*12 +6)>>8); push_int(int_from_16bit((unsigned char*)s->str+header.header_size+i*12 +8)>>8); f_aggregate(3); }
13670c2015-05-25Martin Nilsson 
4211a81998-03-23Mirar (Pontus Hagland)  f_aggregate(header.ncolors); push_object(co=clone_object(image_colortable_program,1)); } else { f_aggregate(0); /* no room for colors */
5e9fc02015-08-18Per Hedbor  push_static_text("colortable");
4211a81998-03-23Mirar (Pontus Hagland)  push_int(0); }
3ca1361999-05-20Mirar (Pontus Hagland)  n+=2;
4211a81998-03-23Mirar (Pontus Hagland)  skipcmap=0; }
3ca1361999-05-20Mirar (Pontus Hagland)  if (!header_only) { n++;
5e9fc02015-08-18Per Hedbor  push_static_text("image");
4211a81998-03-23Mirar (Pontus Hagland) 
3ca1361999-05-20Mirar (Pontus Hagland)  if (s->len-(int)(header.header_size+header.ncolors*12)<0)
7863d62005-05-06Martin Nilsson  push_empty_string();
3ca1361999-05-20Mirar (Pontus Hagland)  else push_string(make_shared_binary_string( s->str+(header.header_size+header.ncolors*12), s->len-(header.header_size+header.ncolors*12)));
4211a81998-03-23Mirar (Pontus Hagland) 
3ca1361999-05-20Mirar (Pontus Hagland)  switch (header.visual_class*100+header.pixmap_format) { /* #define StaticGray 0 #define GrayScale 1 #define StaticColor 2 #define PseudoColor 3 #define TrueColor 4 #define DirectColor 5 */ case 402: /* TrueColor / ZPixmap */ push_int(header.pixmap_width); push_int(header.pixmap_height); push_int(header.bits_per_pixel); push_int(header.bitmap_pad); push_int(header.byte_order==1); push_int(header.red_mask); push_int(header.green_mask); push_int(header.blue_mask); image_x_decode_truecolor_masks(9); break; case 502: /* DirectColor / ZPixmap */ push_int(header.pixmap_width); push_int(header.pixmap_height); push_int(header.bits_per_pixel); push_int(header.bitmap_pad); push_int(header.byte_order==1); push_int(header.red_mask); push_int(header.green_mask); push_int(header.blue_mask); if (!co) image_x_decode_truecolor_masks(9); else { ref_push_object(co); image_x_decode_truecolor_masks(10); } break; case 302: /* PseudoColor / ZPixmap */ push_int(header.pixmap_width); push_int(header.pixmap_height); push_int(header.bits_per_pixel); push_int(header.bitmap_pad); push_int(header.byte_order==1);
05bc722009-08-06Henrik Grubbström (Grubba)  if (!co) image_x_decode_pseudocolor(6); else { ref_push_object(co); image_x_decode_pseudocolor(7); }
3ca1361999-05-20Mirar (Pontus Hagland)  break; default: pop_stack(); push_int(0); }
4211a81998-03-23Mirar (Pontus Hagland)  }
dcc2432000-01-11Martin Stjernholm  free_string(s);
cc7cf42015-10-14Martin Nilsson  f_aggregate_mapping(n*2);
4211a81998-03-23Mirar (Pontus Hagland) 
dcc2432000-01-11Martin Stjernholm  UNSET_ONERROR(uwp);
4211a81998-03-23Mirar (Pontus Hagland) }
3ca1361999-05-20Mirar (Pontus Hagland) void image_xwd__decode(INT32 args) { img_xwd__decode(args,0,0); } void image_xwd_decode_header(INT32 args) { img_xwd__decode(args,1,0); }
65352b1999-04-12Mirar (Pontus Hagland) /* **! method object decode(string data) **! Simple decodes a XWD image file. */
4211a81998-03-23Mirar (Pontus Hagland) static void image_xwd_decode(INT32 args) { if (!args)
b2d3e42000-12-01Fredrik Hübinette (Hubbe)  Pike_error("Image.XWD.decode: missing argument\n");
4211a81998-03-23Mirar (Pontus Hagland)  pop_n_elems(args-1); push_int(1);
3ca1361999-05-20Mirar (Pontus Hagland)  img_xwd__decode(2,0,1);
13670c2015-05-25Martin Nilsson 
5e9fc02015-08-18Per Hedbor  push_static_text("image");
4211a81998-03-23Mirar (Pontus Hagland)  f_index(2); } struct program *image_xwd_module_program=NULL; void init_image_xwd(void) {
226ec82005-01-23Martin Nilsson  ADD_FUNCTION("_decode",image_xwd__decode, tFunc(tStr tOr(tInt,tVoid), tMap(tStr,tOr3(tInt,tArray,tObj))),0);
4211a81998-03-23Mirar (Pontus Hagland) 
226ec82005-01-23Martin Nilsson  ADD_FUNCTION("decode",image_xwd_decode,tFunc(tStr,tObj),0);
3ca1361999-05-20Mirar (Pontus Hagland) 
226ec82005-01-23Martin Nilsson  ADD_FUNCTION("decode_header",image_xwd_decode_header,tFunc(tStr,tObj),0);
4211a81998-03-23Mirar (Pontus Hagland) } void exit_image_xwd(void) { }