Coin Logo Coin3D is Free Software,
published under the BSD 3-clause license.
https://coin3d.github.io
https://www.kongsberg.com/en/kogt/
simage_xwd.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) Kongsberg Oil & Gas Technologies
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /* *************************************************************************
18  * simage_xwd.c -- xwd support without Xlib.
19  * Written by Lars J. Aas <larsa@sim.no>
20  * See include/X11/XWDFile.h for format information.
21  * This implementation is far from complete and kind of "ad hoc".
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif /* HAVE_CONFIG_H */
27 
28 #ifdef SIMAGE_XWD_SUPPORT
29 
30 #include <simage_xwd.h>
31 
32 #include <sys/stat.h>
33 #if HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif /* HAVE_UNISTD_H */
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 /* #include <errno.h> */
41 
42 /* ********************************************************************** */
43 
44 #define XWD_HEADER_SIZE 100
45 #define XWD_COLOR_SIZE 12
46 
47 /* header offsets - all 32 bit */
48 #define XWD_HOFF_HEADER_SIZE 0
49 #define XWD_HOFF_FILE_VERSION 4 /* current was 7 */
50 #define XWD_HOFF_FORMAT 8
51 #define XWD_HOFF_DEPTH 12
52 #define XWD_HOFF_WIDTH 16
53 #define XWD_HOFF_HEIGHT 20
54 #define XWD_HOFF_XOFFSET 24
55 #define XWD_HOFF_BYTEORDER 28
56 #define XWD_HOFF_BITMAP_UNIT 32
57 #define XWD_HOFF_BITMAP_BITORDER 36
58 #define XWD_HOFF_BITMAP_PAD 40
59 #define XWD_HOFF_BITS_PER_PIXEL 44
60 #define XWD_HOFF_BYTES_PER_LINE 48
61 #define XWD_HOFF_VISUAL_CLASS 52
62 #define XWD_HOFF_RED_MASK 56
63 #define XWD_HOFF_GREEN_MASK 60
64 #define XWD_HOFF_BLUE_MASK 64
65 #define XWD_HOFF_BITS_PER_RGB 68
66 #define XWD_HOFF_COLORMAP_ENTRIES 72
67 #define XWD_HOFF_NUM_COLORS 76
68 #define XWD_HOFF_WINDOW_WIDTH 80
69 #define XWD_HOFF_WINDOW_HEIGHT 84
70 #define XWD_HOFF_WINDOW_X 88
71 #define XWD_HOFF_WINDOW_Y 92
72 #define XWD_HOFF_WINDOW_BORDERWIDTH 96
73 
74 /* color offsets */
75 #define XWD_COFF_PIXEL 0
76 #define XWD_COFF_RED 4
77 #define XWD_COFF_GREEN 6
78 #define XWD_COFF_BLUE 8
79 #define XWD_COFF_FLAGS 10 /* 8 bit */
80 
81 /* ********************************************************************** */
82 
83 /* internal error codes */
84 #define XWD_NO_ERROR 0
85 #define XWD_FILE_STAT_ERROR 1
86 #define XWD_FILE_OPEN_ERROR 2
87 #define XWD_FILE_READ_ERROR 3
88 #define XWD_MALLOC_ERROR 4
89 #define XWD_NO_SUPPORT_ERROR 5
90 
91 static int xwderror = XWD_NO_ERROR;
92 /* static int xwderrno = 0; */
93 
94 /* ********************************************************************** */
95 
96 #define StaticGray 0
97 #define GrayScale 1
98 #define StaticColor 2
99 #define PseudoColor 3
100 #define TrueColor 4
101 #define DirectColor 5
102 
103 #define LSBFirst 0 /* little-endian */
104 #define MSBFirst 1 /* big-endian */
105 
106 #define XYBitmap 0 /* depth 1, XYFormat */
107 #define XYPixmap 1 /* depth == drawable depth */
108 #define ZPixmap 2 /* depth == drawable depth */
109 
110 /* ********************************************************************** */
111 
112 #define INT32BE(ptr) ((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3])
113 #define INT16BE(ptr) ((ptr[0] << 8) | ptr[1])
114 
115 unsigned long getuint32be( const unsigned char * data ) { return INT32BE(data); }
116 unsigned long getuint16be( const unsigned char * data ) { return INT16BE(data); }
117 
118 unsigned long swap32( unsigned long value ) {
119  value = ((value & 0xff00ff00) >> 8) | ((value & 0x00ff00ff) << 8);
120  return ((value & 0xffff0000) >> 16) | ((value & 0x0000ffff) << 16);
121 } /* swap32() */
122 
123 /* ********************************************************************** */
124 
125 int
127  char * buffer,
128  int bufferlen )
129 {
130  switch ( xwderror ) {
131  case XWD_FILE_STAT_ERROR:
132  strncpy( buffer, "XWD loader: file stat error", bufferlen );
133  break;
134  case XWD_FILE_OPEN_ERROR:
135  strncpy( buffer, "XWD loader: file open error", bufferlen );
136  break;
137  case XWD_FILE_READ_ERROR:
138  strncpy( buffer, "XWD loader: file read error", bufferlen );
139  break;
140  case XWD_MALLOC_ERROR:
141  strncpy( buffer, "XWD loader: malloc error", bufferlen );
142  break;
143  case XWD_NO_SUPPORT_ERROR:
144  strncpy( buffer, "XWD loader: unsupported operation", bufferlen );
145  break;
146  }
147  return xwderror;
148 } /* simage_xwd_error() */
149 
150 /* ********************************************************************** */
151 
152 int
154  const char * filename,
155  const unsigned char * header,
156  int headerlen )
157 {
158  /* this test could certainly be improved */
159 
160  if ( headerlen < 12 ) return 0;
161  if ( getuint32be( header + XWD_HOFF_HEADER_SIZE ) < XWD_HEADER_SIZE ) {
162  /* FIXME: should store error message somewhere for the client app
163  to read. Should anyway *not* print to stdout/stderr, as that
164  can cause a crash when simage is built as a DLL under
165  MSWin. 20020820 mortene. */
166  /* fprintf( stdout, "headersize failure\n" ); */
167  return 0;
168  }
169  if ( getuint32be( header + XWD_HOFF_FILE_VERSION ) != 7 ) {
170  /* FIXME: should store error message somewhere for the client app
171  to read. Should anyway *not* print to stdout/stderr, as that
172  can cause a crash when simage is built as a DLL under
173  MSWin. 20020820 mortene. */
174  /* fprintf( stdout, "version failure\n" ); */
175  return 0;
176  }
177  if ( getuint32be( header + XWD_HOFF_FORMAT ) != ZPixmap ) {
178  /* FIXME: should store error message somewhere for the client app
179  to read. Should anyway *not* print to stdout/stderr, as that
180  can cause a crash when simage is built as a DLL under
181  MSWin. 20020820 mortene. */
182  /* fprintf( stdout, "format failure\n" ); */
183  return 0;
184  }
185  return 1;
186 } /* simage_xwd_identify() */
187 
188 /* ********************************************************************** */
189 
190 unsigned char *
192  const char * filename,
193  int * width,
194  int * height,
195  int * components )
196 {
197  unsigned char * buf, * image, * ptr, * line, * imageptr;
198  unsigned long * palette;
199  unsigned int w, h, c, /* i, */ x, y, num_colors; /* , colormap_entries; */
200  unsigned int /* bits_per_rgb, */ bits_per_pixel, bytes_per_line;
201  unsigned int pixel, /* red, green, blue, */ bits, got_bits, value;
202  unsigned int swap;
203  FILE * xwdfile;
204  struct stat statdata;
205 
206  if ( stat( filename, &statdata ) == -1 ) {
207  xwderror = XWD_FILE_STAT_ERROR;
208  /* xwderrno = errno; */
209  return NULL;
210  }
211  if ( (buf = (unsigned char *) malloc( statdata.st_size )) == NULL ) {
212  xwderror = XWD_MALLOC_ERROR;
213  /* xwderrno = errno; */
214  return NULL;
215  }
216  xwdfile = fopen( filename, "rb" );
217  if ( (xwdfile = fopen( filename, "rb" )) == NULL ) {
218  free( buf );
219  xwderror = XWD_FILE_OPEN_ERROR;
220  /* xwderrno = errno; */
221  return NULL;
222  }
223  if ( fread( buf, 1, statdata.st_size, xwdfile ) != statdata.st_size ) {
224  free( buf );
225  fclose( xwdfile );
226  xwderror = XWD_FILE_READ_ERROR;
227  /* xwderrno = errno; */
228  return NULL;
229  }
230  fclose( xwdfile );
231 
232  w = getuint32be( buf + XWD_HOFF_WIDTH );
233  h = getuint32be( buf + XWD_HOFF_HEIGHT );
234  c = 3;
235  if ( (image = (unsigned char *) malloc( w * h * c )) == NULL ) {
236  free( buf );
237  xwderror = XWD_MALLOC_ERROR;
238  /* xwderrno = errno; */
239  return NULL;
240  }
241  /* bits_per_rgb = getuint32be( buf + XWD_HOFF_BITS_PER_RGB ); */
242  bytes_per_line = getuint32be( buf + XWD_HOFF_BYTES_PER_LINE );
243  bits_per_pixel = getuint32be( buf + XWD_HOFF_BITS_PER_PIXEL );
244  num_colors = getuint32be( buf + XWD_HOFF_NUM_COLORS );
245  /* colormap_entries = getuint32be( buf + XWD_HOFF_COLORMAP_ENTRIES ); */
246  swap = (getuint32be( buf + XWD_HOFF_BYTEORDER ) == LSBFirst ) ? 1 : 0;
247  palette = NULL;
248 
249  /* check that format is supported and set
250  xwderror = XWD_NO_SUPPORT_ERROR;
251  if problem is detected */
252 
253  /*
254  fprintf( stdout, "xwd image: %dx%d\n", w, h );
255  fprintf( stdout, "bpp: %d pbrgb: %d bpl: %d\n", bits_per_pixel, bits_per_rgb, bytes_per_line );
256  fprintf( stdout, "colors: %d entries: %d\n", num_colors, colormap_entries );
257  fprintf( stdout, "red: %08x green: %08x blue: %08x\n",
258  getuint32be( buf + XWD_HOFF_RED_MASK ),
259  getuint32be( buf + XWD_HOFF_GREEN_MASK ),
260  getuint32be( buf + XWD_HOFF_BLUE_MASK ) );
261  */
262 
263  /* check visual class */
264 
265  /* FIXME:
266  if visual needs palette (I figure it's visual that decides this), read the palette data.
267  leave it at NULL if else, since palette != NULL will lead to palette lookup
268  if ( (palette = (unsigned long *) malloc( sizeof(long) * getuint32be( buf + XWD_HOFF_COLORMAP_ENTRIES ))) == NULL ) {
269  free( buf );
270  free( image );
271  xwderror = XWD_MALLOC_ERROR;
272  xwderrno = errno;
273  return NULL;
274  }
275  ptr = buf + getuint32be( buf + XWD_HOFF_HEADER_SIZE );
276  for ( i = 0; i < num_colors; i++ ) {
277  pixel = getuint32be( ptr + XWD_COFF_PIXEL );
278  red = (getuint16be( ptr + XWD_COFF_RED ) / 256) & 0xff;
279  green = (getuint16be( ptr + XWD_COFF_GREEN ) / 256) & 0xff;
280  blue = (getuint16be( ptr + XWD_COFF_BLUE ) / 256) & 0xff;
281  palette[i] = ((red << 16) | (green << 8) | blue);
282  fprintf( stdout, "color: %08x (pixel) %d (red) %d (green) %d (blue) = %08x\n",
283  pixel, red, green, blue, palette[i] );
284  ptr += XWD_COLOR_SIZE;
285  } */
286 
287  ptr = buf + getuint32be( buf + XWD_HOFF_HEADER_SIZE ) + (num_colors * XWD_COLOR_SIZE);
288  imageptr = image;
289  for ( y = 0; y < h; y++ ) {
290  line = ptr + ((h-(y+1)) * bytes_per_line);
291  got_bits = 0;
292  bits = 0;
293  for ( x = 0; x < w; x++ ) {
294  while ( got_bits < bits_per_pixel ) {
295  bits = (bits << 8) | line[0];
296  line++;
297  got_bits += 8;
298  }
299  if ( got_bits > bits_per_pixel ) {
300  got_bits -= bits_per_pixel;
301  value = bits >> got_bits;
302  bits = bits & ((1 << got_bits) - 1);
303  } else {
304  value = bits;
305  bits = 0;
306  got_bits = 0;
307  }
308  if ( palette != NULL )
309  pixel = palette[value];
310  else if ( swap != 0 )
311  pixel = swap32(value);
312  else
313  pixel = value;
314  /* fprintf( stdout, "pixel (%3d, %3d) [%3d]: %08x\n", x, y, value, pixel ); */
315  /* FIXME - use red/green/blue masks and shift values if it's pixel data */
316  *imageptr++ = (pixel >> 16) & 0xff;
317  *imageptr++ = (pixel >> 8) & 0xff;
318  *imageptr++ = pixel & 0xff;
319  }
320  }
321  free( palette );
322  free( buf );
323  *width = w;
324  *height = h;
325  *components = c;
326  return image;
327 } /* simage_xwd_load() */
328 
329 /* ********************************************************************** */
330 
331 int
333  const char * filename,
334  const unsigned char * bytes,
335  int width,
336  int height,
337  int components )
338 {
339  xwderror = XWD_NO_SUPPORT_ERROR;
340  return 0;
341 } /* simage_xwd_save() */
342 
343 #endif /* SIMAGE_XWD_SUPPORT */
344 /* EOF ****************************************************************** */
int simage_xwd_save(const char *filename, const unsigned char *bytes, int width, int height, int numcomponents)
int simage_xwd_identify(const char *filename, const unsigned char *header, int headerlen)
unsigned char * simage_xwd_load(const char *filename, int *width, int *height, int *numcomponents)
int simage_xwd_error(char *buffer, int bufferlen)