1
/* GIMP - The GNU Image Manipulation Program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
* XWD reading and writing code Copyright (C) 1996 Peter Kirchgessner
4
* (email: peter@kirchgessner.net, WWW: http://www.kirchgessner.net)
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
* XWD-input/output was written by Peter Kirchgessner (peter@kirchgessner.net)
24
* Examples from mainly used UNIX-systems have been used for testing.
25
* If a file does not work, please return a small (!!) compressed example.
26
* Currently the following formats are supported:
27
* pixmap_format | pixmap_depth | bits_per_pixel
28
* ---------------------------------------------
38
* PK = Peter Kirchgessner, ME = Mattias Engdeg�rd
39
* V 1.00, PK, xx-Aug-96: First try
40
* V 1.01, PK, 03-Sep-96: Check for bitmap_bit_order
41
* V 1.90, PK, 17-Mar-97: Upgrade to work with GIMP V0.99
42
* Use visual class 3 to write indexed image
43
* Set gimp b/w-colormap if no xwdcolormap present
44
* V 1.91, PK, 05-Apr-97: Return all arguments, even in case of an error
45
* V 1.92, PK, 12-Oct-97: No progress bars for non-interactive mode
46
* V 1.93, PK, 11-Apr-98: Fix problem with overwriting memory
47
* V 1.94, ME, 27-Feb-00: Remove superfluous little-endian support (format is
48
specified as big-endian). Trim magic header
49
* V 1.95, PK, 02-Jul-01: Fix problem with 8 bit image
57
#include <glib/gstdio.h>
59
#include <libgimp/gimp.h>
60
#include <libgimp/gimpui.h>
62
#include "libgimp/stdplugins-intl.h"
65
#define LOAD_PROC "file-xwd-load"
66
#define SAVE_PROC "file-xwd-save"
67
#define PLUG_IN_BINARY "file-xwd"
70
typedef gulong L_CARD32;
71
typedef gushort L_CARD16;
72
typedef guchar L_CARD8;
76
L_CARD32 l_header_size; /* Header size */
78
L_CARD32 l_file_version; /* File version (7) */
79
L_CARD32 l_pixmap_format; /* Image type */
80
L_CARD32 l_pixmap_depth; /* Number of planes */
81
L_CARD32 l_pixmap_width; /* Image width */
82
L_CARD32 l_pixmap_height; /* Image height */
83
L_CARD32 l_xoffset; /* x-offset (0 ?) */
84
L_CARD32 l_byte_order; /* Byte ordering */
86
L_CARD32 l_bitmap_unit;
87
L_CARD32 l_bitmap_bit_order; /* Bit order */
88
L_CARD32 l_bitmap_pad;
89
L_CARD32 l_bits_per_pixel; /* Number of bits per pixel */
91
L_CARD32 l_bytes_per_line; /* Number of bytes per scanline */
92
L_CARD32 l_visual_class; /* Visual class */
93
L_CARD32 l_red_mask; /* Red mask */
94
L_CARD32 l_green_mask; /* Green mask */
95
L_CARD32 l_blue_mask; /* Blue mask */
96
L_CARD32 l_bits_per_rgb; /* Number of bits per RGB-part */
97
L_CARD32 l_colormap_entries; /* Number of colors in color table (?) */
98
L_CARD32 l_ncolors; /* Number of xwdcolor structures */
99
L_CARD32 l_window_width; /* Window width */
100
L_CARD32 l_window_height; /* Window height */
101
L_CARD32 l_window_x; /* Window position x */
102
L_CARD32 l_window_y; /* Window position y */
103
L_CARD32 l_window_bdrwidth;/* Window border width */
108
L_CARD32 l_pixel; /* Color index */
109
L_CARD16 l_red, l_green, l_blue; /* RGB-values */
110
L_CARD8 l_flags, l_pad;
114
/* Some structures for mapping up to 32bit-pixel */
115
/* values which are kept in the XWD-Colormap */
117
#define MAPPERBITS 12
118
#define MAPPERMASK ((1 << MAPPERBITS)-1)
130
gint npixel; /* Number of pixel values in map */
131
guchar pixel_in_map[1 << MAPPERBITS];
135
#define XWDHDR_PAD 0 /* Total number of padding bytes for XWD header */
136
#define XWDCOL_PAD 0 /* Total number of padding bytes for each XWD color */
138
/* Declare some local functions.
140
static void query (void);
141
static void run (const gchar *name,
143
const GimpParam *param,
145
GimpParam **return_vals);
147
static gint32 load_image (const gchar *filename,
149
static gint save_image (const gchar *filename,
153
static gint32 create_new_image (const gchar *filename,
156
GimpImageBaseType type,
158
GimpDrawable **drawable,
159
GimpPixelRgn *pixel_rgn);
161
static int set_pixelmap (gint,
164
static gboolean get_pixelmap (L_CARD32,
169
static void set_bw_color_table (gint32);
170
static void set_color_table (gint32,
174
static gint32 load_xwd_f2_d1_b1 (const gchar *,
178
static gint32 load_xwd_f2_d8_b8 (const gchar *,
182
static gint32 load_xwd_f2_d16_b16 (const gchar *,
186
static gint32 load_xwd_f2_d24_b32 (const gchar *,
191
static gint32 load_xwd_f1_d24_b1 (const gchar *,
197
static L_CARD32 read_card32 (FILE *,
199
static L_CARD16 read_card16 (FILE *,
201
static L_CARD8 read_card8 (FILE *,
204
static void write_card32 (FILE *,
206
static void write_card16 (FILE *,
208
static void write_card8 (FILE *,
211
static void read_xwd_header (FILE *,
213
static void write_xwd_header (FILE *,
215
static void read_xwd_cols (FILE *,
218
static void write_xwd_cols (FILE *,
222
static gint save_index (FILE *,
226
static gint save_rgb (FILE *,
231
const GimpPlugInInfo PLUG_IN_INFO =
233
NULL, /* init_proc */
234
NULL, /* quit_proc */
235
query, /* query_proc */
241
static GimpRunMode l_run_mode;
251
static const GimpParamDef load_args[] =
253
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
254
{ GIMP_PDB_STRING, "filename", "The name of the file to load" },
255
{ GIMP_PDB_STRING, "raw-filename", "The name of the file to load" }
258
static const GimpParamDef load_return_vals[] =
260
{ GIMP_PDB_IMAGE, "image", "Output image" }
263
static const GimpParamDef save_args[] =
265
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
266
{ GIMP_PDB_IMAGE, "image", "Input image" },
267
{ GIMP_PDB_DRAWABLE, "drawable", "Drawable to save" },
268
{ GIMP_PDB_STRING, "filename", "The name of the file to save the image in" },
269
{ GIMP_PDB_STRING, "raw-filename", "The name of the file to save the image in" }
272
gimp_install_procedure (LOAD_PROC,
273
"Loads files in the XWD (X Window Dump) format",
274
"Loads files in the XWD (X Window Dump) format. "
275
"XWD image files are produced by the program xwd. "
276
"Xwd is an X Window System window dumping utility.",
277
"Peter Kirchgessner",
278
"Peter Kirchgessner",
283
G_N_ELEMENTS (load_args),
284
G_N_ELEMENTS (load_return_vals),
285
load_args, load_return_vals);
287
gimp_register_file_handler_mime (LOAD_PROC, "image/x-xwindowdump");
288
gimp_register_magic_load_handler (LOAD_PROC,
291
"4,long,0x00000007");
293
gimp_install_procedure (SAVE_PROC,
294
"Saves files in the XWD (X Window Dump) format",
295
"XWD saving handles all image types except "
296
"those with alpha channels.",
297
"Peter Kirchgessner",
298
"Peter Kirchgessner",
301
"RGB, GRAY, INDEXED",
303
G_N_ELEMENTS (save_args), 0,
306
gimp_register_file_handler_mime (SAVE_PROC, "image/x-xwindowdump");
307
gimp_register_save_handler (SAVE_PROC, "xwd", "");
312
run (const gchar *name,
314
const GimpParam *param,
316
GimpParam **return_vals)
318
static GimpParam values[2];
319
GimpRunMode run_mode;
320
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
323
GimpExportReturn export = GIMP_EXPORT_CANCEL;
324
GError *error = NULL;
326
l_run_mode = run_mode = param[0].data.d_int32;
331
*return_vals = values;
333
values[0].type = GIMP_PDB_STATUS;
334
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
336
if (strcmp (name, LOAD_PROC) == 0)
338
image_ID = load_image (param[1].data.d_string, &error);
343
values[1].type = GIMP_PDB_IMAGE;
344
values[1].data.d_image = image_ID;
348
status = GIMP_PDB_EXECUTION_ERROR;
351
else if (strcmp (name, SAVE_PROC) == 0)
353
image_ID = param[1].data.d_int32;
354
drawable_ID = param[2].data.d_int32;
356
/* eventually export the image */
359
case GIMP_RUN_INTERACTIVE:
360
case GIMP_RUN_WITH_LAST_VALS:
361
gimp_ui_init (PLUG_IN_BINARY, FALSE);
362
export = gimp_export_image (&image_ID, &drawable_ID, "XWD",
363
(GIMP_EXPORT_CAN_HANDLE_RGB |
364
GIMP_EXPORT_CAN_HANDLE_GRAY |
365
GIMP_EXPORT_CAN_HANDLE_INDEXED));
366
if (export == GIMP_EXPORT_CANCEL)
368
values[0].data.d_status = GIMP_PDB_CANCEL;
379
case GIMP_RUN_INTERACTIVE:
380
case GIMP_RUN_WITH_LAST_VALS:
381
/* No additional data to retrieve */
384
case GIMP_RUN_NONINTERACTIVE:
385
/* Make sure all the arguments are there! */
387
status = GIMP_PDB_CALLING_ERROR;
394
if (status == GIMP_PDB_SUCCESS)
396
if (! save_image (param[3].data.d_string, image_ID, drawable_ID,
399
status = GIMP_PDB_EXECUTION_ERROR;
403
if (export == GIMP_EXPORT_EXPORT)
404
gimp_image_delete (image_ID);
408
status = GIMP_PDB_CANCEL;
411
if (status != GIMP_PDB_SUCCESS && error)
414
values[1].type = GIMP_PDB_STRING;
415
values[1].data.d_string = error->message;
418
values[0].data.d_status = status;
422
load_image (const gchar *filename,
428
L_XWDFILEHEADER xwdhdr;
429
L_XWDCOLOR *xwdcolmap = NULL;
431
ifp = g_fopen (filename, "rb");
434
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
435
_("Could not open '%s' for reading: %s"),
436
gimp_filename_to_utf8 (filename), g_strerror (errno));
440
read_xwd_header (ifp, &xwdhdr);
441
if (xwdhdr.l_file_version != 7)
443
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
444
_("Could not read XWD header from '%s'"),
445
gimp_filename_to_utf8 (filename));
450
#ifdef XWD_COL_WAIT_DEBUG
459
/* Position to start of XWDColor structures */
460
fseek (ifp, (long)xwdhdr.l_header_size, SEEK_SET);
462
if (xwdhdr.l_colormap_entries > 0)
464
xwdcolmap = g_new (L_XWDCOLOR, xwdhdr.l_colormap_entries);
466
read_xwd_cols (ifp, &xwdhdr, xwdcolmap);
471
printf ("File %s\n",filename);
472
for (j = 0; j < xwdhdr.l_colormap_entries; j++)
473
printf ("Entry 0x%08lx: 0x%04lx, 0x%04lx, 0x%04lx, %d\n",
474
(long)xwdcolmap[j].l_pixel,(long)xwdcolmap[j].l_red,
475
(long)xwdcolmap[j].l_green,(long)xwdcolmap[j].l_blue,
476
(int)xwdcolmap[j].l_flags);
480
if (xwdhdr.l_file_version != 7)
482
g_message (_("Can't read color entries"));
489
if (xwdhdr.l_pixmap_width <= 0)
491
g_message (_("'%s':\nNo image width specified"),
492
gimp_filename_to_utf8 (filename));
497
if (xwdhdr.l_pixmap_width > GIMP_MAX_IMAGE_SIZE
498
|| xwdhdr.l_bytes_per_line > GIMP_MAX_IMAGE_SIZE * 3)
500
g_message (_("'%s':\nImage width is larger than GIMP can handle"),
501
gimp_filename_to_utf8 (filename));
506
if (xwdhdr.l_pixmap_height <= 0)
508
g_message (_("'%s':\nNo image height specified"),
509
gimp_filename_to_utf8 (filename));
514
if (xwdhdr.l_pixmap_height > GIMP_MAX_IMAGE_SIZE)
516
g_message (_("'%s':\nImage height is larger than GIMP can handle"),
517
gimp_filename_to_utf8 (filename));
522
gimp_progress_init_printf (_("Opening '%s'"),
523
gimp_filename_to_utf8 (filename));
525
depth = xwdhdr.l_pixmap_depth;
526
bpp = xwdhdr.l_bits_per_pixel;
529
switch (xwdhdr.l_pixmap_format)
531
case 0: /* Single plane bitmap */
532
if ((depth == 1) && (bpp == 1))
533
{ /* Can be performed by format 2 loader */
534
image_ID = load_xwd_f2_d1_b1 (filename, ifp, &xwdhdr, xwdcolmap);
538
case 1: /* Single plane pixmap */
539
if ((depth <= 24) && (bpp == 1))
541
image_ID = load_xwd_f1_d24_b1 (filename, ifp, &xwdhdr, xwdcolmap,
546
case 2: /* Multiplane pixmaps */
547
if ((depth == 1) && (bpp == 1))
549
image_ID = load_xwd_f2_d1_b1 (filename, ifp, &xwdhdr, xwdcolmap);
551
else if ((depth <= 8) && (bpp == 8))
553
image_ID = load_xwd_f2_d8_b8 (filename, ifp, &xwdhdr, xwdcolmap);
555
else if ((depth <= 16) && (bpp == 16))
557
image_ID = load_xwd_f2_d16_b16 (filename, ifp, &xwdhdr, xwdcolmap);
559
else if ((depth <= 24) && ((bpp == 24) || (bpp == 32)))
561
image_ID = load_xwd_f2_d24_b32 (filename, ifp, &xwdhdr, xwdcolmap,
572
if (image_ID == -1 && ! (error && *error))
573
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
574
_("XWD-file %s has format %d, depth %d and bits per pixel %d. "
575
"Currently this is not supported."),
576
gimp_filename_to_utf8 (filename),
577
(gint) xwdhdr.l_pixmap_format, depth, bpp);
583
save_image (const gchar *filename,
589
GimpImageType drawable_type;
592
drawable_type = gimp_drawable_type (drawable_ID);
594
/* Make sure we're not saving an image with an alpha channel */
595
if (gimp_drawable_has_alpha (drawable_ID))
597
g_message (_("Cannot save images with alpha channels."));
601
switch (drawable_type)
603
case GIMP_INDEXED_IMAGE:
604
case GIMP_GRAY_IMAGE:
608
g_message (_("Cannot operate on unknown image types."));
613
/* Open the output file. */
614
ofp = g_fopen (filename, "wb");
617
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
618
_("Could not open '%s' for writing: %s"),
619
gimp_filename_to_utf8 (filename), g_strerror (errno));
623
gimp_progress_init_printf (_("Saving '%s'"),
624
gimp_filename_to_utf8 (filename));
626
if (drawable_type == GIMP_INDEXED_IMAGE)
627
retval = save_index (ofp, image_ID, drawable_ID, 0);
628
else if (drawable_type == GIMP_GRAY_IMAGE)
629
retval = save_index (ofp, image_ID, drawable_ID, 1);
630
else if (drawable_type == GIMP_RGB_IMAGE)
631
retval = save_rgb (ofp, image_ID, drawable_ID);
642
read_card32 (FILE *ifp,
648
c = (((L_CARD32) (getc (ifp))) << 24);
649
c |= (((L_CARD32) (getc (ifp))) << 16);
650
c |= (((L_CARD32) (getc (ifp))) << 8);
651
c |= ((L_CARD32) (*err = getc (ifp)));
660
read_card16 (FILE *ifp,
666
c = (((L_CARD16) (getc (ifp))) << 8);
667
c |= ((L_CARD16) (*err = getc (ifp)));
676
read_card8 (FILE *ifp,
681
c = ((L_CARD8) (*err = getc (ifp)));
689
write_card32 (FILE *ofp,
692
putc ((int) ((c >> 24) & 0xff), ofp);
693
putc ((int) ((c >> 16) & 0xff), ofp);
694
putc ((int) ((c >> 8) & 0xff), ofp);
695
putc ((int) ((c) & 0xff), ofp);
700
write_card16 (FILE *ofp,
703
putc ((int) ((c >> 8) & 0xff), ofp);
704
putc ((int) ((c) & 0xff), ofp);
709
write_card8 (FILE *ofp,
712
putc ((int) ((c) & 0xff), ofp);
717
read_xwd_header (FILE *ifp,
718
L_XWDFILEHEADER *xwdhdr)
723
cp = (L_CARD32 *) xwdhdr;
725
/* Read in all 32-bit values of the header and check for byte order */
726
for (j = 0; j < sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version); j++)
728
*(cp++) = read_card32 (ifp, &err);
735
xwdhdr->l_file_version = 0; /* Not a valid XWD-file */
739
/* Write out an XWD-fileheader. The header size is calculated here */
741
write_xwd_header (FILE *ofp,
742
L_XWDFILEHEADER *xwdhdr)
745
gint j, hdrpad, hdr_entries;
749
hdr_entries = sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version);
750
xwdhdr->l_header_size = hdr_entries * 4 + hdrpad;
752
cp = (L_CARD32 *) xwdhdr;
754
/* Write out all 32-bit values of the header and check for byte order */
755
for (j = 0; j < sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version); j++)
757
write_card32 (ofp, *(cp++));
760
/* Add padding bytes after XWD header */
761
for (j = 0; j < hdrpad; j++)
762
write_card8 (ofp, (L_CARD32) 0);
767
read_xwd_cols (FILE *ifp,
768
L_XWDFILEHEADER *xwdhdr,
769
L_XWDCOLOR *colormap)
772
gint flag_is_bad, index_is_bad;
773
gint indexed = (xwdhdr->l_pixmap_depth <= 8);
774
glong colmappos = ftell (ifp);
776
/* Read in XWD-Color structures (the usual case) */
777
flag_is_bad = index_is_bad = 0;
778
for (j = 0; j < xwdhdr->l_ncolors; j++)
780
colormap[j].l_pixel = read_card32 (ifp, &err);
782
colormap[j].l_red = read_card16 (ifp, &err);
783
colormap[j].l_green = read_card16 (ifp, &err);
784
colormap[j].l_blue = read_card16 (ifp, &err);
786
colormap[j].l_flags = read_card8 (ifp, &err);
787
colormap[j].l_pad = read_card8 (ifp, &err);
789
if (indexed && (colormap[j].l_pixel > 255))
796
if (err) /* Not a valid XWD-file ? */
797
xwdhdr->l_file_version = 0;
798
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
801
/* Read in XWD-Color structures (with 4 bytes inserted infront of RGB) */
802
fseek (ifp, colmappos, SEEK_SET);
803
flag_is_bad = index_is_bad = 0;
804
for (j = 0; j < xwdhdr->l_ncolors; j++)
806
colormap[j].l_pixel = read_card32 (ifp, &err);
808
read_card32 (ifp, &err); /* Empty bytes on Alpha OSF */
810
colormap[j].l_red = read_card16 (ifp, &err);
811
colormap[j].l_green = read_card16 (ifp, &err);
812
colormap[j].l_blue = read_card16 (ifp, &err);
814
colormap[j].l_flags = read_card8 (ifp, &err);
815
colormap[j].l_pad = read_card8 (ifp, &err);
817
if (indexed && (colormap[j].l_pixel > 255))
824
if (err) /* Not a valid XWD-file ? */
825
xwdhdr->l_file_version = 0;
826
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
829
/* Read in XWD-Color structures (with 2 bytes inserted infront of RGB) */
830
fseek (ifp, colmappos, SEEK_SET);
831
flag_is_bad = index_is_bad = 0;
832
for (j = 0; j < xwdhdr->l_ncolors; j++)
834
colormap[j].l_pixel = read_card32 (ifp, &err);
836
read_card16 (ifp, &err); /* Empty bytes (from where ?) */
838
colormap[j].l_red = read_card16 (ifp, &err);
839
colormap[j].l_green = read_card16 (ifp, &err);
840
colormap[j].l_blue = read_card16 (ifp, &err);
842
colormap[j].l_flags = read_card8 (ifp, &err);
843
colormap[j].l_pad = read_card8 (ifp, &err);
845
/* if ((colormap[j].l_flags == 0) || (colormap[j].l_flags > 7))
848
if (indexed && (colormap[j].l_pixel > 255))
855
if (err) /* Not a valid XWD-file ? */
856
xwdhdr->l_file_version = 0;
857
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
860
/* Read in XWD-Color structures (every value is 8 bytes from a CRAY) */
861
fseek (ifp, colmappos, SEEK_SET);
862
flag_is_bad = index_is_bad = 0;
863
for (j = 0; j < xwdhdr->l_ncolors; j++)
865
read_card32 (ifp, &err);
866
colormap[j].l_pixel = read_card32 (ifp, &err);
868
read_card32 (ifp, &err);
869
colormap[j].l_red = read_card32 (ifp, &err);
870
read_card32 (ifp, &err);
871
colormap[j].l_green = read_card32 (ifp, &err);
872
read_card32 (ifp, &err);
873
colormap[j].l_blue = read_card32 (ifp, &err);
875
/* The flag byte is kept in the first byte */
876
colormap[j].l_flags = read_card8 (ifp, &err);
877
colormap[j].l_pad = read_card8 (ifp, &err);
878
read_card16 (ifp, &err);
879
read_card32 (ifp, &err);
881
if (indexed && (colormap[j].l_pixel > 255))
888
if (flag_is_bad || index_is_bad)
890
printf ("xwd: Warning. Error in XWD-color-structure (");
892
if (flag_is_bad) printf ("flag");
893
if (index_is_bad) printf ("index");
899
xwdhdr->l_file_version = 0; /* Not a valid XWD-file */
904
write_xwd_cols (FILE *ofp,
905
L_XWDFILEHEADER *xwdhdr,
906
L_XWDCOLOR *colormap)
911
for (j = 0; j < xwdhdr->l_colormap_entries; j++)
914
write_card32 (ofp, (L_CARD32)0);
915
write_card32 (ofp, colormap[j].l_pixel);
916
write_card32 (ofp, (L_CARD32)0);
917
write_card32 (ofp, (L_CARD32)colormap[j].l_red);
918
write_card32 (ofp, (L_CARD32)0);
919
write_card32 (ofp, (L_CARD32)colormap[j].l_green);
920
write_card32 (ofp, (L_CARD32)0);
921
write_card32 (ofp, (L_CARD32)colormap[j].l_blue);
922
write_card8 (ofp, (L_CARD32)colormap[j].l_flags);
923
write_card8 (ofp, (L_CARD32)colormap[j].l_pad);
924
write_card16 (ofp, (L_CARD32)0);
925
write_card32 (ofp, (L_CARD32)0);
928
write_card32 (ofp, colormap[j].l_pixel);
929
write_card32 (ofp, (L_CARD32)0);
930
write_card16 (ofp, (L_CARD32)colormap[j].l_red);
931
write_card16 (ofp, (L_CARD32)colormap[j].l_green);
932
write_card16 (ofp, (L_CARD32)colormap[j].l_blue);
933
write_card8 (ofp, (L_CARD32)colormap[j].l_flags);
934
write_card8 (ofp, (L_CARD32)colormap[j].l_pad);
936
write_card32 (ofp, colormap[j].l_pixel);
937
write_card16 (ofp, (L_CARD32)colormap[j].l_red);
938
write_card16 (ofp, (L_CARD32)colormap[j].l_green);
939
write_card16 (ofp, (L_CARD32)colormap[j].l_blue);
940
write_card8 (ofp, (L_CARD32)colormap[j].l_flags);
941
write_card8 (ofp, (L_CARD32)colormap[j].l_pad);
948
/* Create a map for mapping up to 32 bit pixelvalues to RGB. */
949
/* Returns number of colors kept in the map (up to 256) */
952
set_pixelmap (int ncols,
957
gint i, j, k, maxcols;
960
memset ((gchar *) pixelmap, 0, sizeof (PIXEL_MAP));
964
for (j = 0; j < ncols; j++) /* For each entry of the XWD colormap */
966
pixel_val = xwdcol[j].l_pixel;
967
for (k = 0; k < maxcols; k++) /* Where to insert in list ? */
969
if (pixel_val <= pixelmap->pmap[k].pixel_val)
972
if ((k < maxcols) && (pixel_val == pixelmap->pmap[k].pixel_val))
973
break; /* It was already in list */
978
if (k < maxcols) /* Must move entries to the back ? */
980
for (i = maxcols-1; i >= k; i--)
981
memcpy ((char *)&(pixelmap->pmap[i+1]),(char *)&(pixelmap->pmap[i]),
984
pixelmap->pmap[k].pixel_val = pixel_val;
985
pixelmap->pmap[k].red = xwdcol[j].l_red >> 8;
986
pixelmap->pmap[k].green = xwdcol[j].l_green >> 8;
987
pixelmap->pmap[k].blue = xwdcol[j].l_blue >> 8;
988
pixelmap->pixel_in_map[pixel_val & MAPPERMASK] = 1;
991
pixelmap->npixel = maxcols;
993
printf ("Colors in pixelmap: %d\n",pixelmap->npixel);
994
for (j=0; j<pixelmap->npixel; j++)
995
printf ("Pixelvalue 0x%08lx, 0x%02x 0x%02x 0x%02x\n",
996
pixelmap->pmap[j].pixel_val,
997
pixelmap->pmap[j].red,pixelmap->pmap[j].green,
998
pixelmap->pmap[j].blue);
999
for (j=0; j<=MAPPERMASK; j++)
1000
printf ("0x%08lx: %d\n",(long)j,pixelmap->pixel_in_map[j]);
1003
return pixelmap->npixel;
1007
/* Search a pixel value in the pixel map. Returns FALSE if the */
1008
/* pixelval was not found in map. Returns TRUE if found. */
1011
get_pixelmap (L_CARD32 pixelval,
1012
PIXEL_MAP *pixelmap,
1018
register PMAP *low, *high, *middle;
1020
if (pixelmap->npixel == 0)
1023
if (!(pixelmap->pixel_in_map[pixelval & MAPPERMASK]))
1026
low = &(pixelmap->pmap[0]);
1027
high = &(pixelmap->pmap[pixelmap->npixel-1]);
1029
/* Do a binary search on the array */
1032
middle = low + ((high - low)/2);
1033
if (pixelval <= middle->pixel_val)
1039
if (pixelval == low->pixel_val)
1041
*red = low->red; *green = low->green; *blue = low->blue;
1050
set_bw_color_table (gint32 image_ID)
1052
static guchar BWColorMap[2*3] = { 255, 255, 255, 0, 0, 0 };
1054
#ifdef XWD_COL_DEBUG
1055
printf ("Set GIMP b/w-colortable:\n");
1058
gimp_image_set_colormap (image_ID, BWColorMap, 2);
1062
/* Initialize an 8-bit colortable from the mask-values of the XWD-header */
1064
init_color_table256 (L_XWDFILEHEADER *xwdhdr,
1068
gint i, j, k, cuind;
1069
gint redshift, greenshift, blueshift;
1070
gint maxred, maxgreen, maxblue;
1072
/* Assume: the bit masks for red/green/blue are grouped together
1073
* Example: redmask = 0xe0, greenmask = 0x1c, bluemask = 0x03
1074
* We need to know where to place the RGB-values (shifting)
1075
* and the maximum value for each component.
1077
redshift = greenshift = blueshift = 0;
1078
if ((maxred = xwdhdr->l_red_mask) == 0)
1081
/* Shift the redmask to the rightmost bit position to get
1082
* maximum value for red.
1084
while ((maxred & 1) == 0)
1090
if ((maxgreen = xwdhdr->l_green_mask) == 0)
1093
while ((maxgreen & 1) == 0)
1099
if ((maxblue = xwdhdr->l_blue_mask) == 0)
1102
while ((maxblue & 1) == 0)
1108
memset ((gchar *) ColorMap, 0, 256 * 3);
1110
for (i = 0; i <= maxred; i++)
1111
for (j = 0; j <= maxgreen; j++)
1112
for (k = 0; k <= maxblue; k++)
1114
cuind = (i << redshift) | (j << greenshift) | (k << blueshift);
1118
ColorMap[cuind*3] = (i * 255)/maxred;
1119
ColorMap[cuind*3+1] = (j * 255)/maxgreen;
1120
ColorMap[cuind*3+2] = (k * 255)/maxblue;
1127
set_color_table (gint32 image_ID,
1128
L_XWDFILEHEADER *xwdhdr,
1129
L_XWDCOLOR *xwdcolmap)
1133
guchar ColorMap[256 * 3];
1135
ncols = xwdhdr->l_colormap_entries;
1136
if (xwdhdr->l_ncolors < ncols)
1137
ncols = xwdhdr->l_ncolors;
1143
/* Initialize color table for all 256 entries from mask-values */
1144
init_color_table256 (xwdhdr, ColorMap);
1146
for (j = 0; j < ncols; j++)
1148
i = xwdcolmap[j].l_pixel;
1149
if ((i >= 0) && (i < 256))
1151
ColorMap[i*3] = (xwdcolmap[j].l_red) >> 8;
1152
ColorMap[i*3+1] = (xwdcolmap[j].l_green) >> 8;
1153
ColorMap[i*3+2] = (xwdcolmap[j].l_blue) >> 8;
1157
#ifdef XWD_COL_DEBUG
1158
printf ("Set GIMP colortable:\n");
1159
for (j = 0; j < 256; j++)
1160
printf ("%3d: 0x%02x 0x%02x 0x%02x\n", j,
1161
ColorMap[j*3], ColorMap[j*3+1], ColorMap[j*3+2]);
1164
gimp_image_set_colormap (image_ID, ColorMap, 256);
1170
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */
1172
create_new_image (const gchar *filename,
1175
GimpImageBaseType type,
1177
GimpDrawable **drawable,
1178
GimpPixelRgn *pixel_rgn)
1181
GimpImageType gdtype;
1186
gdtype = GIMP_GRAY_IMAGE;
1189
gdtype = GIMP_INDEXED_IMAGE;
1192
gdtype = GIMP_RGB_IMAGE;
1195
g_warning ("Unknown image type");
1199
image_ID = gimp_image_new (width, height, type);
1200
gimp_image_set_filename (image_ID, filename);
1202
*layer_ID = gimp_layer_new (image_ID, "Background", width, height,
1203
gdtype, 100, GIMP_NORMAL_MODE);
1204
gimp_image_add_layer (image_ID, *layer_ID, 0);
1206
*drawable = gimp_drawable_get (*layer_ID);
1207
gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width,
1208
(*drawable)->height, TRUE, FALSE);
1214
/* Load XWD with pixmap_format 2, pixmap_depth 1, bits_per_pixel 1 */
1217
load_xwd_f2_d1_b1 (const gchar *filename,
1219
L_XWDFILEHEADER *xwdhdr,
1220
L_XWDCOLOR *xwdcolmap)
1223
register guchar *dest, *src;
1224
guchar c1, c2, c3, c4;
1225
gint width, height, linepad, scan_lines, tile_height;
1228
guchar bit2byte[256 * 8];
1229
guchar *data, *scanline;
1231
gint32 layer_ID, image_ID;
1232
GimpPixelRgn pixel_rgn;
1233
GimpDrawable *drawable;
1236
printf ("load_xwd_f2_d1_b1 (%s)\n", filename);
1239
width = xwdhdr->l_pixmap_width;
1240
height = xwdhdr->l_pixmap_height;
1242
image_ID = create_new_image (filename, width, height, GIMP_INDEXED,
1243
&layer_ID, &drawable, &pixel_rgn);
1245
tile_height = gimp_tile_height ();
1246
data = g_malloc (tile_height * width);
1248
scanline = g_new (guchar, xwdhdr->l_bytes_per_line + 8);
1250
ncols = xwdhdr->l_colormap_entries;
1251
if (xwdhdr->l_ncolors < ncols)
1252
ncols = xwdhdr->l_ncolors;
1255
set_bw_color_table (image_ID);
1257
set_color_table (image_ID, xwdhdr, xwdcolmap);
1259
temp = (gchar *) bit2byte;
1261
/* Get an array for mapping 8 bits in a byte to 8 bytes */
1262
if (!xwdhdr->l_bitmap_bit_order)
1264
for (j = 0; j < 256; j++)
1265
for (i = 0; i < 8; i++)
1266
*(temp++) = ((j & (1 << i)) != 0);
1270
for (j = 0; j < 256; j++)
1271
for (i = 7; i >= 0; i--)
1272
*(temp++) = ((j & (1 << i)) != 0);
1275
linepad = xwdhdr->l_bytes_per_line - (xwdhdr->l_pixmap_width+7)/8;
1282
for (i = 0; i < height; i++)
1284
if (fread (scanline, xwdhdr->l_bytes_per_line, 1, ifp) != 1)
1290
/* Need to check byte order ? */
1291
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
1294
switch (xwdhdr->l_bitmap_unit)
1297
j = xwdhdr->l_bytes_per_line;
1300
c1 = src[0]; c2 = src[1];
1301
*(src++) = c2; *(src++) = c1;
1307
j = xwdhdr->l_bytes_per_line;
1310
c1 = src[0]; c2 = src[1]; c3 = src[2]; c4 = src[3];
1311
*(src++) = c4; *(src++) = c3; *(src++) = c2; *(src++) = c1;
1322
memcpy (dest, bit2byte + pix8*8, 8);
1329
memcpy (dest, bit2byte + pix8*8, j);
1336
gimp_progress_update ((double)(i+1) / (double)height);
1338
if ((scan_lines == tile_height) || ((i+1) == height))
1340
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1352
g_message (_("EOF encountered on reading"));
1354
gimp_drawable_flush (drawable);
1356
return err ? -1 : image_ID;
1360
/* Load XWD with pixmap_format 2, pixmap_depth 8, bits_per_pixel 8 */
1363
load_xwd_f2_d8_b8 (const gchar *filename,
1365
L_XWDFILEHEADER *xwdhdr,
1366
L_XWDCOLOR *xwdcolmap)
1368
gint width, height, linepad, tile_height, scan_lines;
1371
guchar *dest, *data;
1373
gint32 layer_ID, image_ID;
1374
GimpPixelRgn pixel_rgn;
1375
GimpDrawable *drawable;
1378
printf ("load_xwd_f2_d8_b8 (%s)\n", filename);
1381
width = xwdhdr->l_pixmap_width;
1382
height = xwdhdr->l_pixmap_height;
1384
/* This could also be a grayscale image. Check it */
1386
if ((xwdhdr->l_ncolors == 256) && (xwdhdr->l_colormap_entries == 256))
1388
for (j = 0; j < 256; j++)
1390
if ((xwdcolmap[j].l_pixel != j)
1391
|| ((xwdcolmap[j].l_red >> 8) != j)
1392
|| ((xwdcolmap[j].l_green >> 8) != j)
1393
|| ((xwdcolmap[j].l_blue >> 8) != j))
1397
grayscale = (j == 256);
1400
image_ID = create_new_image (filename, width, height,
1401
grayscale ? GIMP_GRAY : GIMP_INDEXED,
1402
&layer_ID, &drawable, &pixel_rgn);
1404
tile_height = gimp_tile_height ();
1405
data = g_malloc (tile_height * width);
1409
ncols = xwdhdr->l_colormap_entries;
1410
if (xwdhdr->l_ncolors < ncols) ncols = xwdhdr->l_ncolors;
1412
set_bw_color_table (image_ID);
1414
set_color_table (image_ID, xwdhdr, xwdcolmap);
1417
linepad = xwdhdr->l_bytes_per_line - xwdhdr->l_pixmap_width;
1424
for (i = 0; i < height; i++)
1426
if (fread (dest, 1, width, ifp) != width)
1433
for (j = 0; j < linepad; j++)
1439
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
1441
if ((scan_lines == tile_height) || ((i+1) == height))
1443
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1453
g_message (_("EOF encountered on reading"));
1455
gimp_drawable_flush (drawable);
1457
return err ? -1 : image_ID;
1461
/* Load XWD with pixmap_format 2, pixmap_depth up to 16, bits_per_pixel 16 */
1464
load_xwd_f2_d16_b16 (const gchar *filename,
1466
L_XWDFILEHEADER *xwdhdr,
1467
L_XWDCOLOR *xwdcolmap)
1469
register guchar *dest, lsbyte_first;
1470
gint width, height, linepad, i, j, c0, c1, ncols;
1471
gint red, green, blue, redval, greenval, blueval;
1472
gint maxred, maxgreen, maxblue;
1473
gint tile_height, scan_lines;
1474
gulong redmask, greenmask, bluemask;
1475
guint redshift, greenshift, blueshift;
1477
guchar *ColorMap, *cm, *data;
1479
gint32 layer_ID, image_ID;
1480
GimpPixelRgn pixel_rgn;
1481
GimpDrawable *drawable;
1484
printf ("load_xwd_f2_d16_b16 (%s)\n", filename);
1487
width = xwdhdr->l_pixmap_width;
1488
height = xwdhdr->l_pixmap_height;
1490
image_ID = create_new_image (filename, width, height, GIMP_RGB,
1491
&layer_ID, &drawable, &pixel_rgn);
1493
tile_height = gimp_tile_height ();
1494
data = g_malloc (tile_height * width * 3);
1496
/* Get memory for mapping 16 bit XWD-pixel to GIMP-RGB */
1497
maxval = 0x10000 * 3;
1498
ColorMap = g_new0 (guchar, maxval);
1500
redmask = xwdhdr->l_red_mask;
1501
greenmask = xwdhdr->l_green_mask;
1502
bluemask = xwdhdr->l_blue_mask;
1504
/* How to shift RGB to be right aligned ? */
1505
/* (We rely on the the mask bits are grouped and not mixed) */
1506
redshift = greenshift = blueshift = 0;
1508
while (((1 << redshift) & redmask) == 0) redshift++;
1509
while (((1 << greenshift) & greenmask) == 0) greenshift++;
1510
while (((1 << blueshift) & bluemask) == 0) blueshift++;
1512
/* The bits_per_rgb may not be correct. Use redmask instead */
1513
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
1514
maxred = (1 << maxred) - 1;
1516
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
1517
maxgreen = (1 << maxgreen) - 1;
1519
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
1520
maxblue = (1 << maxblue) - 1;
1522
/* Built up the array to map XWD-pixel value to GIMP-RGB */
1523
for (red = 0; red <= maxred; red++)
1525
redval = (red * 255) / maxred;
1526
for (green = 0; green <= maxgreen; green++)
1528
greenval = (green * 255) / maxgreen;
1529
for (blue = 0; blue <= maxblue; blue++)
1531
blueval = (blue * 255) / maxblue;
1532
cm = ColorMap + ((red << redshift) + (green << greenshift)
1533
+ (blue << blueshift)) * 3;
1541
/* Now look what was written to the XWD-Colormap */
1543
ncols = xwdhdr->l_colormap_entries;
1544
if (xwdhdr->l_ncolors < ncols)
1545
ncols = xwdhdr->l_ncolors;
1547
for (j = 0; j < ncols; j++)
1549
cm = ColorMap + xwdcolmap[j].l_pixel * 3;
1550
*(cm++) = (xwdcolmap[j].l_red >> 8);
1551
*(cm++) = (xwdcolmap[j].l_green >> 8);
1552
*cm = (xwdcolmap[j].l_blue >> 8);
1555
/* What do we have to consume after a line has finished ? */
1556
linepad = xwdhdr->l_bytes_per_line
1557
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
1558
if (linepad < 0) linepad = 0;
1560
lsbyte_first = (xwdhdr->l_byte_order == 0);
1565
for (i = 0; i < height; i++)
1567
for (j = 0; j < width; j++)
1578
c0 = c0 | (c1 << 8);
1580
c0 = (c0 << 8) | c1;
1582
cm = ColorMap + c0 * 3;
1583
*(dest++) = *(cm++);
1584
*(dest++) = *(cm++);
1591
for (j = 0; j < linepad; j++)
1597
gimp_progress_update ((double)(i+1) / (double)height);
1599
if ((scan_lines == tile_height) || ((i+1) == height))
1601
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1611
g_message (_("EOF encountered on reading"));
1613
gimp_drawable_flush (drawable);
1615
return err ? -1 : image_ID;
1619
/* Load XWD with pixmap_format 2, pixmap_depth up to 24, bits_per_pixel 24/32 */
1622
load_xwd_f2_d24_b32 (const gchar *filename,
1624
L_XWDFILEHEADER *xwdhdr,
1625
L_XWDCOLOR *xwdcolmap,
1628
register guchar *dest, lsbyte_first;
1629
gint width, height, linepad, i, j, c0, c1, c2, c3;
1630
gint tile_height, scan_lines;
1632
gint red, green, blue, ncols;
1633
gint maxred, maxgreen, maxblue;
1634
gulong redmask, greenmask, bluemask;
1635
guint redshift, greenshift, blueshift;
1636
guchar redmap[256], greenmap[256], bluemap[256];
1638
PIXEL_MAP pixel_map;
1640
gint32 layer_ID, image_ID;
1641
GimpPixelRgn pixel_rgn;
1642
GimpDrawable *drawable;
1645
printf ("load_xwd_f2_d24_b32 (%s)\n", filename);
1648
width = xwdhdr->l_pixmap_width;
1649
height = xwdhdr->l_pixmap_height;
1651
redmask = xwdhdr->l_red_mask;
1652
greenmask = xwdhdr->l_green_mask;
1653
bluemask = xwdhdr->l_blue_mask;
1655
if (redmask == 0) redmask = 0xff0000;
1656
if (greenmask == 0) greenmask = 0x00ff00;
1657
if (bluemask == 0) bluemask = 0x0000ff;
1659
/* How to shift RGB to be right aligned ? */
1660
/* (We rely on the the mask bits are grouped and not mixed) */
1661
redshift = greenshift = blueshift = 0;
1663
while (((1 << redshift) & redmask) == 0) redshift++;
1664
while (((1 << greenshift) & greenmask) == 0) greenshift++;
1665
while (((1 << blueshift) & bluemask) == 0) blueshift++;
1667
/* The bits_per_rgb may not be correct. Use redmask instead */
1669
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
1670
maxred = (1 << maxred) - 1;
1672
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
1673
maxgreen = (1 << maxgreen) - 1;
1675
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
1676
maxblue = (1 << maxblue) - 1;
1678
if (maxred > sizeof (redmap) ||
1679
maxgreen > sizeof (greenmap) ||
1680
maxblue > sizeof (bluemap))
1682
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1683
_("XWD-file %s is corrupt."),
1684
gimp_filename_to_utf8 (filename));
1688
image_ID = create_new_image (filename, width, height, GIMP_RGB,
1689
&layer_ID, &drawable, &pixel_rgn);
1691
tile_height = gimp_tile_height ();
1692
data = g_malloc (tile_height * width * 3);
1694
/* Set map-arrays for red, green, blue */
1695
for (red = 0; red <= maxred; red++)
1696
redmap[red] = (red * 255) / maxred;
1697
for (green = 0; green <= maxgreen; green++)
1698
greenmap[green] = (green * 255) / maxgreen;
1699
for (blue = 0; blue <= maxblue; blue++)
1700
bluemap[blue] = (blue * 255) / maxblue;
1702
ncols = xwdhdr->l_colormap_entries;
1703
if (xwdhdr->l_ncolors < ncols) ncols = xwdhdr->l_ncolors;
1705
ncols = set_pixelmap (ncols, xwdcolmap, &pixel_map);
1707
/* What do we have to consume after a line has finished ? */
1708
linepad = xwdhdr->l_bytes_per_line
1709
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
1710
if (linepad < 0) linepad = 0;
1712
lsbyte_first = (xwdhdr->l_byte_order == 0);
1717
if (xwdhdr->l_bits_per_pixel == 32)
1719
for (i = 0; i < height; i++)
1721
for (j = 0; j < width; j++)
1733
pixelval = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1735
pixelval = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
1737
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
1743
*(dest++) = redmap[(pixelval & redmask) >> redshift];
1744
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
1745
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
1753
for (j = 0; j < linepad; j++)
1757
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
1759
if ((scan_lines == tile_height) || ((i+1) == height))
1761
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1768
else /* 24 bits per pixel */
1770
for (i = 0; i < height; i++)
1772
for (j = 0; j < width; j++)
1783
pixelval = c0 | (c1 << 8) | (c2 << 16);
1785
pixelval = (c0 << 16) | (c1 << 8) | c2;
1787
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
1793
*(dest++) = redmap[(pixelval & redmask) >> redshift];
1794
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
1795
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
1803
for (j = 0; j < linepad; j++)
1807
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
1809
if ((scan_lines == tile_height) || ((i+1) == height))
1811
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1822
g_message (_("EOF encountered on reading"));
1824
gimp_drawable_flush (drawable);
1826
return err ? -1 : image_ID;
1830
/* Load XWD with pixmap_format 1, pixmap_depth up to 24, bits_per_pixel 1 */
1833
load_xwd_f1_d24_b1 (const gchar *filename,
1835
L_XWDFILEHEADER *xwdhdr,
1836
L_XWDCOLOR *xwdcolmap,
1839
register guchar *dest, outmask, inmask, do_reverse;
1840
gint width, height, linepad, i, j, plane, fromright;
1841
gint tile_height, tile_start, tile_end;
1842
gint indexed, bytes_per_pixel;
1843
gint maxred, maxgreen, maxblue;
1844
gint red, green, blue, ncols, standard_rgb;
1845
glong data_offset, plane_offset, tile_offset;
1846
gulong redmask, greenmask, bluemask;
1847
guint redshift, greenshift, blueshift;
1849
guchar redmap[256], greenmap[256], bluemap[256];
1850
guchar bit_reverse[256];
1851
guchar *xwddata, *xwdin, *data;
1853
PIXEL_MAP pixel_map;
1855
gint32 layer_ID, image_ID;
1856
GimpPixelRgn pixel_rgn;
1857
GimpDrawable *drawable;
1860
printf ("load_xwd_f1_d24_b1 (%s)\n", filename);
1863
xwddata = g_malloc (xwdhdr->l_bytes_per_line);
1864
if (xwddata == NULL)
1867
width = xwdhdr->l_pixmap_width;
1868
height = xwdhdr->l_pixmap_height;
1869
indexed = (xwdhdr->l_pixmap_depth <= 8);
1870
bytes_per_pixel = (indexed ? 1 : 3);
1872
linepad = xwdhdr->l_bytes_per_line
1873
- (xwdhdr->l_pixmap_width+7)/8;
1877
for (j = 0; j < 256; j++) /* Create an array for reversing bits */
1880
for (i = 0; i < 8; i++)
1883
if (j & (1 << i)) inmask |= 1;
1885
bit_reverse[j] = inmask;
1888
redmask = xwdhdr->l_red_mask;
1889
greenmask = xwdhdr->l_green_mask;
1890
bluemask = xwdhdr->l_blue_mask;
1892
if (redmask == 0) redmask = 0xff0000;
1893
if (greenmask == 0) greenmask = 0x00ff00;
1894
if (bluemask == 0) bluemask = 0x0000ff;
1896
standard_rgb = (redmask == 0xff0000) && (greenmask == 0x00ff00)
1897
&& (bluemask == 0x0000ff);
1898
redshift = greenshift = blueshift = 0;
1900
if (!standard_rgb) /* Do we need to re-map the pixel-values ? */
1902
/* How to shift RGB to be right aligned ? */
1903
/* (We rely on the the mask bits are grouped and not mixed) */
1905
while (((1 << redshift) & redmask) == 0) redshift++;
1906
while (((1 << greenshift) & greenmask) == 0) greenshift++;
1907
while (((1 << blueshift) & bluemask) == 0) blueshift++;
1909
/* The bits_per_rgb may not be correct. Use redmask instead */
1911
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
1912
maxred = (1 << maxred) - 1;
1914
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
1915
maxgreen = (1 << maxgreen) - 1;
1917
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
1918
maxblue = (1 << maxblue) - 1;
1920
if (maxred > sizeof (redmap) ||
1921
maxgreen > sizeof (greenmap) ||
1922
maxblue > sizeof (bluemap))
1924
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1925
_("XWD-file %s is corrupt."),
1926
gimp_filename_to_utf8 (filename));
1930
/* Set map-arrays for red, green, blue */
1931
for (red = 0; red <= maxred; red++)
1932
redmap[red] = (red * 255) / maxred;
1933
for (green = 0; green <= maxgreen; green++)
1934
greenmap[green] = (green * 255) / maxgreen;
1935
for (blue = 0; blue <= maxblue; blue++)
1936
bluemap[blue] = (blue * 255) / maxblue;
1939
image_ID = create_new_image (filename, width, height,
1940
indexed ? GIMP_INDEXED : GIMP_RGB,
1941
&layer_ID, &drawable, &pixel_rgn);
1943
tile_height = gimp_tile_height ();
1944
data = g_malloc (tile_height * width * bytes_per_pixel);
1946
ncols = xwdhdr->l_colormap_entries;
1947
if (xwdhdr->l_ncolors < ncols)
1948
ncols = xwdhdr->l_ncolors;
1953
set_bw_color_table (image_ID);
1955
set_color_table (image_ID, xwdhdr, xwdcolmap);
1959
ncols = set_pixelmap (ncols, xwdcolmap, &pixel_map);
1962
do_reverse = !xwdhdr->l_bitmap_bit_order;
1964
/* This is where the image data starts within the file */
1965
data_offset = ftell (ifp);
1967
for (tile_start = 0; tile_start < height; tile_start += tile_height)
1969
memset (data, 0, width*tile_height*bytes_per_pixel);
1971
tile_end = tile_start + tile_height - 1;
1972
if (tile_end >= height)
1973
tile_end = height - 1;
1975
for (plane = 0; plane < xwdhdr->l_pixmap_depth; plane++)
1977
dest = data; /* Position to start of tile within the plane */
1978
plane_offset = data_offset + plane*height*xwdhdr->l_bytes_per_line;
1979
tile_offset = plane_offset + tile_start*xwdhdr->l_bytes_per_line;
1980
fseek (ifp, tile_offset, SEEK_SET);
1982
/* Place the last plane at the least significant bit */
1984
if (indexed) /* Only 1 byte per pixel */
1986
fromright = xwdhdr->l_pixmap_depth-1-plane;
1987
outmask = (1 << fromright);
1989
else /* 3 bytes per pixel */
1991
fromright = xwdhdr->l_pixmap_depth-1-plane;
1992
dest += 2 - fromright/8;
1993
outmask = (1 << (fromright % 8));
1996
for (i = tile_start; i <= tile_end; i++)
1998
if (fread (xwddata,xwdhdr->l_bytes_per_line,1,ifp) != 1)
2005
/* Handle bitmap unit */
2006
if (xwdhdr->l_bitmap_unit == 16)
2008
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
2010
j = xwdhdr->l_bytes_per_line/2;
2013
inmask = xwdin[0]; xwdin[0] = xwdin[1]; xwdin[1] = inmask;
2019
else if (xwdhdr->l_bitmap_unit == 32)
2021
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
2023
j = xwdhdr->l_bytes_per_line/4;
2026
inmask = xwdin[0]; xwdin[0] = xwdin[3]; xwdin[3] = inmask;
2027
inmask = xwdin[1]; xwdin[1] = xwdin[2]; xwdin[2] = inmask;
2035
for (j = 0; j < width; j++)
2047
dest += bytes_per_pixel;
2054
/* For indexed images, the mapping to colors is done by the color table. */
2055
/* Otherwise we must do the mapping by ourself. */
2059
for (i = tile_start; i <= tile_end; i++)
2061
for (j = 0; j < width; j++)
2063
pixelval = (*dest << 16) | (*(dest+1) << 8) | *(dest+2);
2065
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2)
2070
else /* We have to map RGB to 0,...,255 */
2072
*(dest++) = redmap[(pixelval & redmask) >> redshift];
2073
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
2074
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
2080
gimp_progress_update ((gdouble) tile_end / (gdouble) height);
2082
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, tile_start,
2083
width, tile_end-tile_start+1);
2090
g_message (_("EOF encountered on reading"));
2092
gimp_drawable_flush (drawable);
2094
return err ? -1 : image_ID;
2099
save_index (FILE *ofp,
2104
gint height, width, linepad, tile_height, i, j;
2105
gint ncolors, vclass;
2107
guchar *data, *src, *cmap;
2108
L_XWDFILEHEADER xwdhdr;
2109
L_XWDCOLOR xwdcolmap[256];
2110
GimpPixelRgn pixel_rgn;
2111
GimpDrawable *drawable;
2112
GimpImageType drawable_type;
2115
printf ("save_index ()\n");
2118
drawable = gimp_drawable_get (drawable_ID);
2119
drawable_type = gimp_drawable_type (drawable_ID);
2120
width = drawable->width;
2121
height = drawable->height;
2122
tile_height = gimp_tile_height ();
2124
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
2126
/* allocate a buffer for retrieving information from the pixel region */
2127
src = data = g_new (guchar, tile_height * width * drawable->bpp);
2129
linepad = width % 4;
2130
if (linepad) linepad = 4 - linepad;
2132
/* Fill XWD-color map */
2138
for (j = 0; j < ncolors; j++)
2140
xwdcolmap[j].l_pixel = j;
2141
xwdcolmap[j].l_red = (j << 8) | j;
2142
xwdcolmap[j].l_green = (j << 8) | j;
2143
xwdcolmap[j].l_blue = (j << 8) | j;
2144
xwdcolmap[j].l_flags = 7;
2145
xwdcolmap[j].l_pad = 0;
2151
cmap = gimp_image_get_colormap (image_ID, &ncolors);
2153
for (j = 0; j < ncolors; j++)
2155
xwdcolmap[j].l_pixel = j;
2156
xwdcolmap[j].l_red = ((*cmap) << 8) | *cmap; cmap++;
2157
xwdcolmap[j].l_green = ((*cmap) << 8) | *cmap; cmap++;
2158
xwdcolmap[j].l_blue = ((*cmap) << 8) | *cmap; cmap++;
2159
xwdcolmap[j].l_flags = 7;
2160
xwdcolmap[j].l_pad = 0;
2164
/* Fill in the XWD header (header_size is evaluated by write_xwd_hdr ()) */
2165
xwdhdr.l_header_size = 0;
2166
xwdhdr.l_file_version = 7;
2167
xwdhdr.l_pixmap_format = 2;
2168
xwdhdr.l_pixmap_depth = 8;
2169
xwdhdr.l_pixmap_width = width;
2170
xwdhdr.l_pixmap_height = height;
2171
xwdhdr.l_xoffset = 0;
2172
xwdhdr.l_byte_order = 1;
2173
xwdhdr.l_bitmap_unit = 32;
2174
xwdhdr.l_bitmap_bit_order = 1;
2175
xwdhdr.l_bitmap_pad = 32;
2176
xwdhdr.l_bits_per_pixel = 8;
2177
xwdhdr.l_bytes_per_line = width + linepad;
2178
xwdhdr.l_visual_class = vclass;
2179
xwdhdr.l_red_mask = 0x000000;
2180
xwdhdr.l_green_mask = 0x000000;
2181
xwdhdr.l_blue_mask = 0x000000;
2182
xwdhdr.l_bits_per_rgb = 8;
2183
xwdhdr.l_colormap_entries = ncolors;
2184
xwdhdr.l_ncolors = ncolors;
2185
xwdhdr.l_window_width = width;
2186
xwdhdr.l_window_height = height;
2187
xwdhdr.l_window_x = 64;
2188
xwdhdr.l_window_y = 64;
2189
xwdhdr.l_window_bdrwidth = 0;
2191
write_xwd_header (ofp, &xwdhdr);
2192
write_xwd_cols (ofp, &xwdhdr, xwdcolmap);
2194
for (i = 0; i < height; i++)
2196
if ((i % tile_height) == 0) /* Get more data */
2198
gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
2200
gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, i, width, scan_lines);
2204
fwrite (src, width, 1, ofp);
2207
fwrite ((char *)&tmp, linepad, 1, ofp);
2212
gimp_progress_update ((gdouble) i / (gdouble) height);
2217
gimp_drawable_detach (drawable);
2221
g_message (_("Error during writing indexed/gray image"));
2230
save_rgb (FILE *ofp,
2234
gint height, width, linepad, tile_height, i;
2237
L_XWDFILEHEADER xwdhdr;
2238
GimpPixelRgn pixel_rgn;
2239
GimpDrawable *drawable;
2240
GimpImageType drawable_type;
2243
printf ("save_rgb ()\n");
2246
drawable = gimp_drawable_get (drawable_ID);
2247
drawable_type = gimp_drawable_type (drawable_ID);
2248
width = drawable->width;
2249
height = drawable->height;
2250
tile_height = gimp_tile_height ();
2252
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
2254
/* allocate a buffer for retrieving information from the pixel region */
2255
src = data = g_new (guchar, tile_height * width * drawable->bpp);
2257
linepad = (width * 3) % 4;
2259
linepad = 4 - linepad;
2261
/* Fill in the XWD header (header_size is evaluated by write_xwd_hdr ()) */
2262
xwdhdr.l_header_size = 0;
2263
xwdhdr.l_file_version = 7;
2264
xwdhdr.l_pixmap_format = 2;
2265
xwdhdr.l_pixmap_depth = 24;
2266
xwdhdr.l_pixmap_width = width;
2267
xwdhdr.l_pixmap_height = height;
2268
xwdhdr.l_xoffset = 0;
2269
xwdhdr.l_byte_order = 1;
2271
xwdhdr.l_bitmap_unit = 32;
2272
xwdhdr.l_bitmap_bit_order = 1;
2273
xwdhdr.l_bitmap_pad = 32;
2274
xwdhdr.l_bits_per_pixel = 24;
2276
xwdhdr.l_bytes_per_line = width * 3 + linepad;
2277
xwdhdr.l_visual_class = 5;
2278
xwdhdr.l_red_mask = 0xff0000;
2279
xwdhdr.l_green_mask = 0x00ff00;
2280
xwdhdr.l_blue_mask = 0x0000ff;
2281
xwdhdr.l_bits_per_rgb = 8;
2282
xwdhdr.l_colormap_entries = 0;
2283
xwdhdr.l_ncolors = 0;
2284
xwdhdr.l_window_width = width;
2285
xwdhdr.l_window_height = height;
2286
xwdhdr.l_window_x = 64;
2287
xwdhdr.l_window_y = 64;
2288
xwdhdr.l_window_bdrwidth = 0;
2290
write_xwd_header (ofp, &xwdhdr);
2292
for (i = 0; i < height; i++)
2294
if ((i % tile_height) == 0) /* Get more data */
2296
gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
2298
gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, i, width, scan_lines);
2302
fwrite (src, width * 3, 1, ofp);
2305
fwrite ((char *)&tmp, linepad, 1, ofp);
2310
gimp_progress_update ((gdouble) i / (gdouble) height);
2315
gimp_drawable_detach (drawable);
2319
g_message (_("Error during writing rgb image"));