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 3 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, see <http://www.gnu.org/licenses/>.
22
* XWD-input/output was written by Peter Kirchgessner (peter@kirchgessner.net)
23
* Examples from mainly used UNIX-systems have been used for testing.
24
* If a file does not work, please return a small (!!) compressed example.
25
* Currently the following formats are supported:
26
* pixmap_format | pixmap_depth | bits_per_pixel
27
* ---------------------------------------------
37
* PK = Peter Kirchgessner, ME = Mattias Engdeg�rd
38
* V 1.00, PK, xx-Aug-96: First try
39
* V 1.01, PK, 03-Sep-96: Check for bitmap_bit_order
40
* V 1.90, PK, 17-Mar-97: Upgrade to work with GIMP V0.99
41
* Use visual class 3 to write indexed image
42
* Set gimp b/w-colormap if no xwdcolormap present
43
* V 1.91, PK, 05-Apr-97: Return all arguments, even in case of an error
44
* V 1.92, PK, 12-Oct-97: No progress bars for non-interactive mode
45
* V 1.93, PK, 11-Apr-98: Fix problem with overwriting memory
46
* V 1.94, ME, 27-Feb-00: Remove superfluous little-endian support (format is
47
specified as big-endian). Trim magic header
48
* V 1.95, PK, 02-Jul-01: Fix problem with 8 bit image
56
#include <glib/gstdio.h>
58
#include <libgimp/gimp.h>
59
#include <libgimp/gimpui.h>
61
#include "libgimp/stdplugins-intl.h"
64
#define LOAD_PROC "file-xwd-load"
65
#define SAVE_PROC "file-xwd-save"
66
#define PLUG_IN_BINARY "file-xwd"
67
#define PLUG_IN_ROLE "gimp-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", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
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", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" },
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, NULL,
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
/* Guard against insanely huge color maps -- gimp_image_set_colormap() only
463
* accepts colormaps with 0..256 colors anyway. */
464
if (xwdhdr.l_colormap_entries > 256)
466
g_message (_("'%s':\nIllegal number of colormap entries: %ld"),
467
gimp_filename_to_utf8 (filename),
468
(long)xwdhdr.l_colormap_entries);
473
if (xwdhdr.l_colormap_entries > 0)
475
xwdcolmap = g_new (L_XWDCOLOR, xwdhdr.l_colormap_entries);
477
read_xwd_cols (ifp, &xwdhdr, xwdcolmap);
482
printf ("File %s\n",filename);
483
for (j = 0; j < xwdhdr.l_colormap_entries; j++)
484
printf ("Entry 0x%08lx: 0x%04lx, 0x%04lx, 0x%04lx, %d\n",
485
(long)xwdcolmap[j].l_pixel,(long)xwdcolmap[j].l_red,
486
(long)xwdcolmap[j].l_green,(long)xwdcolmap[j].l_blue,
487
(int)xwdcolmap[j].l_flags);
491
if (xwdhdr.l_file_version != 7)
493
g_message (_("Can't read color entries"));
500
if (xwdhdr.l_pixmap_width <= 0)
502
g_message (_("'%s':\nNo image width specified"),
503
gimp_filename_to_utf8 (filename));
509
if (xwdhdr.l_pixmap_width > GIMP_MAX_IMAGE_SIZE
510
|| xwdhdr.l_bytes_per_line > GIMP_MAX_IMAGE_SIZE * 3)
512
g_message (_("'%s':\nImage width is larger than GIMP can handle"),
513
gimp_filename_to_utf8 (filename));
519
if (xwdhdr.l_pixmap_height <= 0)
521
g_message (_("'%s':\nNo image height specified"),
522
gimp_filename_to_utf8 (filename));
528
if (xwdhdr.l_pixmap_height > GIMP_MAX_IMAGE_SIZE)
530
g_message (_("'%s':\nImage height is larger than GIMP can handle"),
531
gimp_filename_to_utf8 (filename));
537
gimp_progress_init_printf (_("Opening '%s'"),
538
gimp_filename_to_utf8 (filename));
540
depth = xwdhdr.l_pixmap_depth;
541
bpp = xwdhdr.l_bits_per_pixel;
544
switch (xwdhdr.l_pixmap_format)
546
case 0: /* Single plane bitmap */
547
if ((depth == 1) && (bpp == 1))
548
{ /* Can be performed by format 2 loader */
549
image_ID = load_xwd_f2_d1_b1 (filename, ifp, &xwdhdr, xwdcolmap);
553
case 1: /* Single plane pixmap */
554
if ((depth <= 24) && (bpp == 1))
556
image_ID = load_xwd_f1_d24_b1 (filename, ifp, &xwdhdr, xwdcolmap,
561
case 2: /* Multiplane pixmaps */
562
if ((depth == 1) && (bpp == 1))
564
image_ID = load_xwd_f2_d1_b1 (filename, ifp, &xwdhdr, xwdcolmap);
566
else if ((depth <= 8) && (bpp == 8))
568
image_ID = load_xwd_f2_d8_b8 (filename, ifp, &xwdhdr, xwdcolmap);
570
else if ((depth <= 16) && (bpp == 16))
572
image_ID = load_xwd_f2_d16_b16 (filename, ifp, &xwdhdr, xwdcolmap);
574
else if ((depth <= 24) && ((bpp == 24) || (bpp == 32)))
576
image_ID = load_xwd_f2_d24_b32 (filename, ifp, &xwdhdr, xwdcolmap,
581
gimp_progress_update (1.0);
588
if (image_ID == -1 && ! (error && *error))
589
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
590
_("XWD-file %s has format %d, depth %d and bits per pixel %d. "
591
"Currently this is not supported."),
592
gimp_filename_to_utf8 (filename),
593
(gint) xwdhdr.l_pixmap_format, depth, bpp);
599
save_image (const gchar *filename,
605
GimpImageType drawable_type;
608
drawable_type = gimp_drawable_type (drawable_ID);
610
/* Make sure we're not saving an image with an alpha channel */
611
if (gimp_drawable_has_alpha (drawable_ID))
613
g_message (_("Cannot save images with alpha channels."));
617
switch (drawable_type)
619
case GIMP_INDEXED_IMAGE:
620
case GIMP_GRAY_IMAGE:
624
g_message (_("Cannot operate on unknown image types."));
629
/* Open the output file. */
630
ofp = g_fopen (filename, "wb");
633
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
634
_("Could not open '%s' for writing: %s"),
635
gimp_filename_to_utf8 (filename), g_strerror (errno));
639
gimp_progress_init_printf (_("Saving '%s'"),
640
gimp_filename_to_utf8 (filename));
642
switch (drawable_type)
644
case GIMP_INDEXED_IMAGE:
645
retval = save_index (ofp, image_ID, drawable_ID, 0);
647
case GIMP_GRAY_IMAGE:
648
retval = save_index (ofp, image_ID, drawable_ID, 1);
651
retval = save_rgb (ofp, image_ID, drawable_ID);
657
gimp_progress_update (1.0);
666
read_card32 (FILE *ifp,
672
c = (((L_CARD32) (getc (ifp))) << 24);
673
c |= (((L_CARD32) (getc (ifp))) << 16);
674
c |= (((L_CARD32) (getc (ifp))) << 8);
675
c |= ((L_CARD32) (*err = getc (ifp)));
684
read_card16 (FILE *ifp,
690
c = (((L_CARD16) (getc (ifp))) << 8);
691
c |= ((L_CARD16) (*err = getc (ifp)));
700
read_card8 (FILE *ifp,
705
c = ((L_CARD8) (*err = getc (ifp)));
713
write_card32 (FILE *ofp,
716
putc ((int) ((c >> 24) & 0xff), ofp);
717
putc ((int) ((c >> 16) & 0xff), ofp);
718
putc ((int) ((c >> 8) & 0xff), ofp);
719
putc ((int) ((c) & 0xff), ofp);
724
write_card16 (FILE *ofp,
727
putc ((int) ((c >> 8) & 0xff), ofp);
728
putc ((int) ((c) & 0xff), ofp);
733
write_card8 (FILE *ofp,
736
putc ((int) ((c) & 0xff), ofp);
741
read_xwd_header (FILE *ifp,
742
L_XWDFILEHEADER *xwdhdr)
747
cp = (L_CARD32 *) xwdhdr;
749
/* Read in all 32-bit values of the header and check for byte order */
750
for (j = 0; j < sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version); j++)
752
*(cp++) = read_card32 (ifp, &err);
759
xwdhdr->l_file_version = 0; /* Not a valid XWD-file */
763
/* Write out an XWD-fileheader. The header size is calculated here */
765
write_xwd_header (FILE *ofp,
766
L_XWDFILEHEADER *xwdhdr)
769
gint j, hdrpad, hdr_entries;
773
hdr_entries = sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version);
774
xwdhdr->l_header_size = hdr_entries * 4 + hdrpad;
776
cp = (L_CARD32 *) xwdhdr;
778
/* Write out all 32-bit values of the header and check for byte order */
779
for (j = 0; j < sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version); j++)
781
write_card32 (ofp, *(cp++));
784
/* Add padding bytes after XWD header */
785
for (j = 0; j < hdrpad; j++)
786
write_card8 (ofp, (L_CARD32) 0);
791
read_xwd_cols (FILE *ifp,
792
L_XWDFILEHEADER *xwdhdr,
793
L_XWDCOLOR *colormap)
796
gint flag_is_bad, index_is_bad;
797
gint indexed = (xwdhdr->l_pixmap_depth <= 8);
798
glong colmappos = ftell (ifp);
800
/* Read in XWD-Color structures (the usual case) */
801
flag_is_bad = index_is_bad = 0;
802
for (j = 0; j < xwdhdr->l_ncolors; j++)
804
colormap[j].l_pixel = read_card32 (ifp, &err);
806
colormap[j].l_red = read_card16 (ifp, &err);
807
colormap[j].l_green = read_card16 (ifp, &err);
808
colormap[j].l_blue = read_card16 (ifp, &err);
810
colormap[j].l_flags = read_card8 (ifp, &err);
811
colormap[j].l_pad = read_card8 (ifp, &err);
813
if (indexed && (colormap[j].l_pixel > 255))
820
if (err) /* Not a valid XWD-file ? */
821
xwdhdr->l_file_version = 0;
822
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
825
/* Read in XWD-Color structures (with 4 bytes inserted infront of RGB) */
826
fseek (ifp, colmappos, SEEK_SET);
827
flag_is_bad = index_is_bad = 0;
828
for (j = 0; j < xwdhdr->l_ncolors; j++)
830
colormap[j].l_pixel = read_card32 (ifp, &err);
832
read_card32 (ifp, &err); /* Empty bytes on Alpha OSF */
834
colormap[j].l_red = read_card16 (ifp, &err);
835
colormap[j].l_green = read_card16 (ifp, &err);
836
colormap[j].l_blue = read_card16 (ifp, &err);
838
colormap[j].l_flags = read_card8 (ifp, &err);
839
colormap[j].l_pad = read_card8 (ifp, &err);
841
if (indexed && (colormap[j].l_pixel > 255))
848
if (err) /* Not a valid XWD-file ? */
849
xwdhdr->l_file_version = 0;
850
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
853
/* Read in XWD-Color structures (with 2 bytes inserted infront of RGB) */
854
fseek (ifp, colmappos, SEEK_SET);
855
flag_is_bad = index_is_bad = 0;
856
for (j = 0; j < xwdhdr->l_ncolors; j++)
858
colormap[j].l_pixel = read_card32 (ifp, &err);
860
read_card16 (ifp, &err); /* Empty bytes (from where ?) */
862
colormap[j].l_red = read_card16 (ifp, &err);
863
colormap[j].l_green = read_card16 (ifp, &err);
864
colormap[j].l_blue = read_card16 (ifp, &err);
866
colormap[j].l_flags = read_card8 (ifp, &err);
867
colormap[j].l_pad = read_card8 (ifp, &err);
869
/* if ((colormap[j].l_flags == 0) || (colormap[j].l_flags > 7))
872
if (indexed && (colormap[j].l_pixel > 255))
879
if (err) /* Not a valid XWD-file ? */
880
xwdhdr->l_file_version = 0;
881
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
884
/* Read in XWD-Color structures (every value is 8 bytes from a CRAY) */
885
fseek (ifp, colmappos, SEEK_SET);
886
flag_is_bad = index_is_bad = 0;
887
for (j = 0; j < xwdhdr->l_ncolors; j++)
889
read_card32 (ifp, &err);
890
colormap[j].l_pixel = read_card32 (ifp, &err);
892
read_card32 (ifp, &err);
893
colormap[j].l_red = read_card32 (ifp, &err);
894
read_card32 (ifp, &err);
895
colormap[j].l_green = read_card32 (ifp, &err);
896
read_card32 (ifp, &err);
897
colormap[j].l_blue = read_card32 (ifp, &err);
899
/* The flag byte is kept in the first byte */
900
colormap[j].l_flags = read_card8 (ifp, &err);
901
colormap[j].l_pad = read_card8 (ifp, &err);
902
read_card16 (ifp, &err);
903
read_card32 (ifp, &err);
905
if (indexed && (colormap[j].l_pixel > 255))
912
if (flag_is_bad || index_is_bad)
914
printf ("xwd: Warning. Error in XWD-color-structure (");
916
if (flag_is_bad) printf ("flag");
917
if (index_is_bad) printf ("index");
923
xwdhdr->l_file_version = 0; /* Not a valid XWD-file */
928
write_xwd_cols (FILE *ofp,
929
L_XWDFILEHEADER *xwdhdr,
930
L_XWDCOLOR *colormap)
935
for (j = 0; j < xwdhdr->l_colormap_entries; j++)
938
write_card32 (ofp, (L_CARD32)0);
939
write_card32 (ofp, colormap[j].l_pixel);
940
write_card32 (ofp, (L_CARD32)0);
941
write_card32 (ofp, (L_CARD32)colormap[j].l_red);
942
write_card32 (ofp, (L_CARD32)0);
943
write_card32 (ofp, (L_CARD32)colormap[j].l_green);
944
write_card32 (ofp, (L_CARD32)0);
945
write_card32 (ofp, (L_CARD32)colormap[j].l_blue);
946
write_card8 (ofp, (L_CARD32)colormap[j].l_flags);
947
write_card8 (ofp, (L_CARD32)colormap[j].l_pad);
948
write_card16 (ofp, (L_CARD32)0);
949
write_card32 (ofp, (L_CARD32)0);
952
write_card32 (ofp, colormap[j].l_pixel);
953
write_card32 (ofp, (L_CARD32)0);
954
write_card16 (ofp, (L_CARD32)colormap[j].l_red);
955
write_card16 (ofp, (L_CARD32)colormap[j].l_green);
956
write_card16 (ofp, (L_CARD32)colormap[j].l_blue);
957
write_card8 (ofp, (L_CARD32)colormap[j].l_flags);
958
write_card8 (ofp, (L_CARD32)colormap[j].l_pad);
960
write_card32 (ofp, colormap[j].l_pixel);
961
write_card16 (ofp, (L_CARD32)colormap[j].l_red);
962
write_card16 (ofp, (L_CARD32)colormap[j].l_green);
963
write_card16 (ofp, (L_CARD32)colormap[j].l_blue);
964
write_card8 (ofp, (L_CARD32)colormap[j].l_flags);
965
write_card8 (ofp, (L_CARD32)colormap[j].l_pad);
972
/* Create a map for mapping up to 32 bit pixelvalues to RGB. */
973
/* Returns number of colors kept in the map (up to 256) */
976
set_pixelmap (int ncols,
981
gint i, j, k, maxcols;
984
memset ((gchar *) pixelmap, 0, sizeof (PIXEL_MAP));
988
for (j = 0; j < ncols; j++) /* For each entry of the XWD colormap */
990
pixel_val = xwdcol[j].l_pixel;
991
for (k = 0; k < maxcols; k++) /* Where to insert in list ? */
993
if (pixel_val <= pixelmap->pmap[k].pixel_val)
996
if ((k < maxcols) && (pixel_val == pixelmap->pmap[k].pixel_val))
997
break; /* It was already in list */
1002
if (k < maxcols) /* Must move entries to the back ? */
1004
for (i = maxcols-1; i >= k; i--)
1005
memcpy ((char *)&(pixelmap->pmap[i+1]),(char *)&(pixelmap->pmap[i]),
1008
pixelmap->pmap[k].pixel_val = pixel_val;
1009
pixelmap->pmap[k].red = xwdcol[j].l_red >> 8;
1010
pixelmap->pmap[k].green = xwdcol[j].l_green >> 8;
1011
pixelmap->pmap[k].blue = xwdcol[j].l_blue >> 8;
1012
pixelmap->pixel_in_map[pixel_val & MAPPERMASK] = 1;
1015
pixelmap->npixel = maxcols;
1016
#ifdef XWD_COL_DEBUG
1017
printf ("Colors in pixelmap: %d\n",pixelmap->npixel);
1018
for (j=0; j<pixelmap->npixel; j++)
1019
printf ("Pixelvalue 0x%08lx, 0x%02x 0x%02x 0x%02x\n",
1020
pixelmap->pmap[j].pixel_val,
1021
pixelmap->pmap[j].red,pixelmap->pmap[j].green,
1022
pixelmap->pmap[j].blue);
1023
for (j=0; j<=MAPPERMASK; j++)
1024
printf ("0x%08lx: %d\n",(long)j,pixelmap->pixel_in_map[j]);
1027
return pixelmap->npixel;
1031
/* Search a pixel value in the pixel map. Returns FALSE if the */
1032
/* pixelval was not found in map. Returns TRUE if found. */
1035
get_pixelmap (L_CARD32 pixelval,
1036
PIXEL_MAP *pixelmap,
1042
register PMAP *low, *high, *middle;
1044
if (pixelmap->npixel == 0)
1047
if (!(pixelmap->pixel_in_map[pixelval & MAPPERMASK]))
1050
low = &(pixelmap->pmap[0]);
1051
high = &(pixelmap->pmap[pixelmap->npixel-1]);
1053
/* Do a binary search on the array */
1056
middle = low + ((high - low)/2);
1057
if (pixelval <= middle->pixel_val)
1063
if (pixelval == low->pixel_val)
1065
*red = low->red; *green = low->green; *blue = low->blue;
1074
set_bw_color_table (gint32 image_ID)
1076
static guchar BWColorMap[2*3] = { 255, 255, 255, 0, 0, 0 };
1078
#ifdef XWD_COL_DEBUG
1079
printf ("Set GIMP b/w-colortable:\n");
1082
gimp_image_set_colormap (image_ID, BWColorMap, 2);
1086
/* Initialize an 8-bit colortable from the mask-values of the XWD-header */
1088
init_color_table256 (L_XWDFILEHEADER *xwdhdr,
1092
gint i, j, k, cuind;
1093
gint redshift, greenshift, blueshift;
1094
gint maxred, maxgreen, maxblue;
1096
/* Assume: the bit masks for red/green/blue are grouped together
1097
* Example: redmask = 0xe0, greenmask = 0x1c, bluemask = 0x03
1098
* We need to know where to place the RGB-values (shifting)
1099
* and the maximum value for each component.
1101
redshift = greenshift = blueshift = 0;
1102
if ((maxred = xwdhdr->l_red_mask) == 0)
1105
/* Shift the redmask to the rightmost bit position to get
1106
* maximum value for red.
1108
while ((maxred & 1) == 0)
1114
if ((maxgreen = xwdhdr->l_green_mask) == 0)
1117
while ((maxgreen & 1) == 0)
1123
if ((maxblue = xwdhdr->l_blue_mask) == 0)
1126
while ((maxblue & 1) == 0)
1132
memset ((gchar *) ColorMap, 0, 256 * 3);
1134
for (i = 0; i <= maxred; i++)
1135
for (j = 0; j <= maxgreen; j++)
1136
for (k = 0; k <= maxblue; k++)
1138
cuind = (i << redshift) | (j << greenshift) | (k << blueshift);
1142
ColorMap[cuind*3] = (i * 255)/maxred;
1143
ColorMap[cuind*3+1] = (j * 255)/maxgreen;
1144
ColorMap[cuind*3+2] = (k * 255)/maxblue;
1151
set_color_table (gint32 image_ID,
1152
L_XWDFILEHEADER *xwdhdr,
1153
L_XWDCOLOR *xwdcolmap)
1157
guchar ColorMap[256 * 3];
1159
ncols = xwdhdr->l_colormap_entries;
1160
if (xwdhdr->l_ncolors < ncols)
1161
ncols = xwdhdr->l_ncolors;
1167
/* Initialize color table for all 256 entries from mask-values */
1168
init_color_table256 (xwdhdr, ColorMap);
1170
for (j = 0; j < ncols; j++)
1172
i = xwdcolmap[j].l_pixel;
1173
if ((i >= 0) && (i < 256))
1175
ColorMap[i*3] = (xwdcolmap[j].l_red) >> 8;
1176
ColorMap[i*3+1] = (xwdcolmap[j].l_green) >> 8;
1177
ColorMap[i*3+2] = (xwdcolmap[j].l_blue) >> 8;
1181
#ifdef XWD_COL_DEBUG
1182
printf ("Set GIMP colortable:\n");
1183
for (j = 0; j < 256; j++)
1184
printf ("%3d: 0x%02x 0x%02x 0x%02x\n", j,
1185
ColorMap[j*3], ColorMap[j*3+1], ColorMap[j*3+2]);
1188
gimp_image_set_colormap (image_ID, ColorMap, 256);
1194
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */
1196
create_new_image (const gchar *filename,
1199
GimpImageBaseType type,
1201
GimpDrawable **drawable,
1202
GimpPixelRgn *pixel_rgn)
1205
GimpImageType gdtype;
1210
gdtype = GIMP_GRAY_IMAGE;
1213
gdtype = GIMP_INDEXED_IMAGE;
1216
gdtype = GIMP_RGB_IMAGE;
1219
g_warning ("Unknown image type");
1223
image_ID = gimp_image_new (width, height, type);
1224
gimp_image_set_filename (image_ID, filename);
1226
*layer_ID = gimp_layer_new (image_ID, "Background", width, height,
1227
gdtype, 100, GIMP_NORMAL_MODE);
1228
gimp_image_insert_layer (image_ID, *layer_ID, -1, 0);
1230
*drawable = gimp_drawable_get (*layer_ID);
1231
gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width,
1232
(*drawable)->height, TRUE, FALSE);
1238
/* Load XWD with pixmap_format 2, pixmap_depth 1, bits_per_pixel 1 */
1241
load_xwd_f2_d1_b1 (const gchar *filename,
1243
L_XWDFILEHEADER *xwdhdr,
1244
L_XWDCOLOR *xwdcolmap)
1247
register guchar *dest, *src;
1248
guchar c1, c2, c3, c4;
1249
gint width, height, scan_lines, tile_height;
1252
guchar bit2byte[256 * 8];
1253
guchar *data, *scanline;
1255
gint32 layer_ID, image_ID;
1256
GimpPixelRgn pixel_rgn;
1257
GimpDrawable *drawable;
1260
printf ("load_xwd_f2_d1_b1 (%s)\n", filename);
1263
width = xwdhdr->l_pixmap_width;
1264
height = xwdhdr->l_pixmap_height;
1266
image_ID = create_new_image (filename, width, height, GIMP_INDEXED,
1267
&layer_ID, &drawable, &pixel_rgn);
1269
tile_height = gimp_tile_height ();
1270
data = g_malloc (tile_height * width);
1272
scanline = g_new (guchar, xwdhdr->l_bytes_per_line + 8);
1274
ncols = xwdhdr->l_colormap_entries;
1275
if (xwdhdr->l_ncolors < ncols)
1276
ncols = xwdhdr->l_ncolors;
1279
set_bw_color_table (image_ID);
1281
set_color_table (image_ID, xwdhdr, xwdcolmap);
1283
temp = (gchar *) bit2byte;
1285
/* Get an array for mapping 8 bits in a byte to 8 bytes */
1286
if (!xwdhdr->l_bitmap_bit_order)
1288
for (j = 0; j < 256; j++)
1289
for (i = 0; i < 8; i++)
1290
*(temp++) = ((j & (1 << i)) != 0);
1294
for (j = 0; j < 256; j++)
1295
for (i = 7; i >= 0; i--)
1296
*(temp++) = ((j & (1 << i)) != 0);
1302
for (i = 0; i < height; i++)
1304
if (fread (scanline, xwdhdr->l_bytes_per_line, 1, ifp) != 1)
1310
/* Need to check byte order ? */
1311
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
1314
switch (xwdhdr->l_bitmap_unit)
1317
j = xwdhdr->l_bytes_per_line;
1320
c1 = src[0]; c2 = src[1];
1321
*(src++) = c2; *(src++) = c1;
1327
j = xwdhdr->l_bytes_per_line;
1330
c1 = src[0]; c2 = src[1]; c3 = src[2]; c4 = src[3];
1331
*(src++) = c4; *(src++) = c3; *(src++) = c2; *(src++) = c1;
1342
memcpy (dest, bit2byte + pix8*8, 8);
1349
memcpy (dest, bit2byte + pix8*8, j);
1356
gimp_progress_update ((double)(i+1) / (double)height);
1358
if ((scan_lines == tile_height) || ((i+1) == height))
1360
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1372
g_message (_("EOF encountered on reading"));
1374
gimp_drawable_flush (drawable);
1376
return err ? -1 : image_ID;
1380
/* Load XWD with pixmap_format 2, pixmap_depth 8, bits_per_pixel 8 */
1383
load_xwd_f2_d8_b8 (const gchar *filename,
1385
L_XWDFILEHEADER *xwdhdr,
1386
L_XWDCOLOR *xwdcolmap)
1388
gint width, height, linepad, tile_height, scan_lines;
1391
guchar *dest, *data;
1393
gint32 layer_ID, image_ID;
1394
GimpPixelRgn pixel_rgn;
1395
GimpDrawable *drawable;
1398
printf ("load_xwd_f2_d8_b8 (%s)\n", filename);
1401
width = xwdhdr->l_pixmap_width;
1402
height = xwdhdr->l_pixmap_height;
1404
/* This could also be a grayscale image. Check it */
1406
if ((xwdhdr->l_ncolors == 256) && (xwdhdr->l_colormap_entries == 256))
1408
for (j = 0; j < 256; j++)
1410
if ((xwdcolmap[j].l_pixel != j)
1411
|| ((xwdcolmap[j].l_red >> 8) != j)
1412
|| ((xwdcolmap[j].l_green >> 8) != j)
1413
|| ((xwdcolmap[j].l_blue >> 8) != j))
1417
grayscale = (j == 256);
1420
image_ID = create_new_image (filename, width, height,
1421
grayscale ? GIMP_GRAY : GIMP_INDEXED,
1422
&layer_ID, &drawable, &pixel_rgn);
1424
tile_height = gimp_tile_height ();
1425
data = g_malloc (tile_height * width);
1429
ncols = xwdhdr->l_colormap_entries;
1430
if (xwdhdr->l_ncolors < ncols) ncols = xwdhdr->l_ncolors;
1432
set_bw_color_table (image_ID);
1434
set_color_table (image_ID, xwdhdr, xwdcolmap);
1437
linepad = xwdhdr->l_bytes_per_line - xwdhdr->l_pixmap_width;
1444
for (i = 0; i < height; i++)
1446
if (fread (dest, 1, width, ifp) != width)
1453
for (j = 0; j < linepad; j++)
1459
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
1461
if ((scan_lines == tile_height) || ((i+1) == height))
1463
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1473
g_message (_("EOF encountered on reading"));
1475
gimp_drawable_flush (drawable);
1477
return err ? -1 : image_ID;
1481
/* Load XWD with pixmap_format 2, pixmap_depth up to 16, bits_per_pixel 16 */
1484
load_xwd_f2_d16_b16 (const gchar *filename,
1486
L_XWDFILEHEADER *xwdhdr,
1487
L_XWDCOLOR *xwdcolmap)
1489
register guchar *dest, lsbyte_first;
1490
gint width, height, linepad, i, j, c0, c1, ncols;
1491
gint red, green, blue, redval, greenval, blueval;
1492
gint maxred, maxgreen, maxblue;
1493
gint tile_height, scan_lines;
1494
gulong redmask, greenmask, bluemask;
1495
guint redshift, greenshift, blueshift;
1497
guchar *ColorMap, *cm, *data;
1499
gint32 layer_ID, image_ID;
1500
GimpPixelRgn pixel_rgn;
1501
GimpDrawable *drawable;
1504
printf ("load_xwd_f2_d16_b16 (%s)\n", filename);
1507
width = xwdhdr->l_pixmap_width;
1508
height = xwdhdr->l_pixmap_height;
1510
image_ID = create_new_image (filename, width, height, GIMP_RGB,
1511
&layer_ID, &drawable, &pixel_rgn);
1513
tile_height = gimp_tile_height ();
1514
data = g_malloc (tile_height * width * 3);
1516
/* Get memory for mapping 16 bit XWD-pixel to GIMP-RGB */
1517
maxval = 0x10000 * 3;
1518
ColorMap = g_new0 (guchar, maxval);
1520
redmask = xwdhdr->l_red_mask;
1521
greenmask = xwdhdr->l_green_mask;
1522
bluemask = xwdhdr->l_blue_mask;
1524
/* How to shift RGB to be right aligned ? */
1525
/* (We rely on the the mask bits are grouped and not mixed) */
1526
redshift = greenshift = blueshift = 0;
1528
while (((1 << redshift) & redmask) == 0) redshift++;
1529
while (((1 << greenshift) & greenmask) == 0) greenshift++;
1530
while (((1 << blueshift) & bluemask) == 0) blueshift++;
1532
/* The bits_per_rgb may not be correct. Use redmask instead */
1533
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
1534
maxred = (1 << maxred) - 1;
1536
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
1537
maxgreen = (1 << maxgreen) - 1;
1539
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
1540
maxblue = (1 << maxblue) - 1;
1542
/* Built up the array to map XWD-pixel value to GIMP-RGB */
1543
for (red = 0; red <= maxred; red++)
1545
redval = (red * 255) / maxred;
1546
for (green = 0; green <= maxgreen; green++)
1548
greenval = (green * 255) / maxgreen;
1549
for (blue = 0; blue <= maxblue; blue++)
1551
blueval = (blue * 255) / maxblue;
1552
cm = ColorMap + ((red << redshift) + (green << greenshift)
1553
+ (blue << blueshift)) * 3;
1561
/* Now look what was written to the XWD-Colormap */
1563
ncols = xwdhdr->l_colormap_entries;
1564
if (xwdhdr->l_ncolors < ncols)
1565
ncols = xwdhdr->l_ncolors;
1567
for (j = 0; j < ncols; j++)
1569
cm = ColorMap + xwdcolmap[j].l_pixel * 3;
1570
*(cm++) = (xwdcolmap[j].l_red >> 8);
1571
*(cm++) = (xwdcolmap[j].l_green >> 8);
1572
*cm = (xwdcolmap[j].l_blue >> 8);
1575
/* What do we have to consume after a line has finished ? */
1576
linepad = xwdhdr->l_bytes_per_line
1577
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
1578
if (linepad < 0) linepad = 0;
1580
lsbyte_first = (xwdhdr->l_byte_order == 0);
1585
for (i = 0; i < height; i++)
1587
for (j = 0; j < width; j++)
1598
c0 = c0 | (c1 << 8);
1600
c0 = (c0 << 8) | c1;
1602
cm = ColorMap + c0 * 3;
1603
*(dest++) = *(cm++);
1604
*(dest++) = *(cm++);
1611
for (j = 0; j < linepad; j++)
1617
gimp_progress_update ((double)(i+1) / (double)height);
1619
if ((scan_lines == tile_height) || ((i+1) == height))
1621
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1631
g_message (_("EOF encountered on reading"));
1633
gimp_drawable_flush (drawable);
1635
return err ? -1 : image_ID;
1639
/* Load XWD with pixmap_format 2, pixmap_depth up to 24, bits_per_pixel 24/32 */
1642
load_xwd_f2_d24_b32 (const gchar *filename,
1644
L_XWDFILEHEADER *xwdhdr,
1645
L_XWDCOLOR *xwdcolmap,
1648
register guchar *dest, lsbyte_first;
1649
gint width, height, linepad, i, j, c0, c1, c2, c3;
1650
gint tile_height, scan_lines;
1652
gint red, green, blue, ncols;
1653
gint maxred, maxgreen, maxblue;
1654
gulong redmask, greenmask, bluemask;
1655
guint redshift, greenshift, blueshift;
1656
guchar redmap[256], greenmap[256], bluemap[256];
1658
PIXEL_MAP pixel_map;
1660
gint32 layer_ID, image_ID;
1661
GimpPixelRgn pixel_rgn;
1662
GimpDrawable *drawable;
1665
printf ("load_xwd_f2_d24_b32 (%s)\n", filename);
1668
width = xwdhdr->l_pixmap_width;
1669
height = xwdhdr->l_pixmap_height;
1671
redmask = xwdhdr->l_red_mask;
1672
greenmask = xwdhdr->l_green_mask;
1673
bluemask = xwdhdr->l_blue_mask;
1675
if (redmask == 0) redmask = 0xff0000;
1676
if (greenmask == 0) greenmask = 0x00ff00;
1677
if (bluemask == 0) bluemask = 0x0000ff;
1679
/* How to shift RGB to be right aligned ? */
1680
/* (We rely on the the mask bits are grouped and not mixed) */
1681
redshift = greenshift = blueshift = 0;
1683
while (((1 << redshift) & redmask) == 0) redshift++;
1684
while (((1 << greenshift) & greenmask) == 0) greenshift++;
1685
while (((1 << blueshift) & bluemask) == 0) blueshift++;
1687
/* The bits_per_rgb may not be correct. Use redmask instead */
1689
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
1690
maxred = (1 << maxred) - 1;
1692
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
1693
maxgreen = (1 << maxgreen) - 1;
1695
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
1696
maxblue = (1 << maxblue) - 1;
1698
if (maxred > sizeof (redmap) ||
1699
maxgreen > sizeof (greenmap) ||
1700
maxblue > sizeof (bluemap))
1702
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1703
_("XWD-file %s is corrupt."),
1704
gimp_filename_to_utf8 (filename));
1708
image_ID = create_new_image (filename, width, height, GIMP_RGB,
1709
&layer_ID, &drawable, &pixel_rgn);
1711
tile_height = gimp_tile_height ();
1712
data = g_malloc (tile_height * width * 3);
1714
/* Set map-arrays for red, green, blue */
1715
for (red = 0; red <= maxred; red++)
1716
redmap[red] = (red * 255) / maxred;
1717
for (green = 0; green <= maxgreen; green++)
1718
greenmap[green] = (green * 255) / maxgreen;
1719
for (blue = 0; blue <= maxblue; blue++)
1720
bluemap[blue] = (blue * 255) / maxblue;
1722
ncols = xwdhdr->l_colormap_entries;
1723
if (xwdhdr->l_ncolors < ncols)
1724
ncols = xwdhdr->l_ncolors;
1726
set_pixelmap (ncols, xwdcolmap, &pixel_map);
1728
/* What do we have to consume after a line has finished ? */
1729
linepad = xwdhdr->l_bytes_per_line
1730
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
1731
if (linepad < 0) linepad = 0;
1733
lsbyte_first = (xwdhdr->l_byte_order == 0);
1738
if (xwdhdr->l_bits_per_pixel == 32)
1740
for (i = 0; i < height; i++)
1742
for (j = 0; j < width; j++)
1754
pixelval = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1756
pixelval = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
1758
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
1764
*(dest++) = redmap[(pixelval & redmask) >> redshift];
1765
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
1766
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
1774
for (j = 0; j < linepad; j++)
1778
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
1780
if ((scan_lines == tile_height) || ((i+1) == height))
1782
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1789
else /* 24 bits per pixel */
1791
for (i = 0; i < height; i++)
1793
for (j = 0; j < width; j++)
1804
pixelval = c0 | (c1 << 8) | (c2 << 16);
1806
pixelval = (c0 << 16) | (c1 << 8) | c2;
1808
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
1814
*(dest++) = redmap[(pixelval & redmask) >> redshift];
1815
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
1816
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
1824
for (j = 0; j < linepad; j++)
1828
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
1830
if ((scan_lines == tile_height) || ((i+1) == height))
1832
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1843
g_message (_("EOF encountered on reading"));
1845
gimp_drawable_flush (drawable);
1847
return err ? -1 : image_ID;
1851
/* Load XWD with pixmap_format 1, pixmap_depth up to 24, bits_per_pixel 1 */
1854
load_xwd_f1_d24_b1 (const gchar *filename,
1856
L_XWDFILEHEADER *xwdhdr,
1857
L_XWDCOLOR *xwdcolmap,
1860
register guchar *dest, outmask, inmask, do_reverse;
1861
gint width, height, i, j, plane, fromright;
1862
gint tile_height, tile_start, tile_end;
1863
gint indexed, bytes_per_pixel;
1864
gint maxred, maxgreen, maxblue;
1865
gint red, green, blue, ncols, standard_rgb;
1866
glong data_offset, plane_offset, tile_offset;
1867
gulong redmask, greenmask, bluemask;
1868
guint redshift, greenshift, blueshift;
1870
guchar redmap[256], greenmap[256], bluemap[256];
1871
guchar bit_reverse[256];
1872
guchar *xwddata, *xwdin, *data;
1874
PIXEL_MAP pixel_map;
1876
gint32 layer_ID, image_ID;
1877
GimpPixelRgn pixel_rgn;
1878
GimpDrawable *drawable;
1881
printf ("load_xwd_f1_d24_b1 (%s)\n", filename);
1884
xwddata = g_malloc (xwdhdr->l_bytes_per_line);
1885
if (xwddata == NULL)
1888
width = xwdhdr->l_pixmap_width;
1889
height = xwdhdr->l_pixmap_height;
1890
indexed = (xwdhdr->l_pixmap_depth <= 8);
1891
bytes_per_pixel = (indexed ? 1 : 3);
1893
for (j = 0; j < 256; j++) /* Create an array for reversing bits */
1896
for (i = 0; i < 8; i++)
1899
if (j & (1 << i)) inmask |= 1;
1901
bit_reverse[j] = inmask;
1904
redmask = xwdhdr->l_red_mask;
1905
greenmask = xwdhdr->l_green_mask;
1906
bluemask = xwdhdr->l_blue_mask;
1908
if (redmask == 0) redmask = 0xff0000;
1909
if (greenmask == 0) greenmask = 0x00ff00;
1910
if (bluemask == 0) bluemask = 0x0000ff;
1912
standard_rgb = (redmask == 0xff0000) && (greenmask == 0x00ff00)
1913
&& (bluemask == 0x0000ff);
1914
redshift = greenshift = blueshift = 0;
1916
if (!standard_rgb) /* Do we need to re-map the pixel-values ? */
1918
/* How to shift RGB to be right aligned ? */
1919
/* (We rely on the the mask bits are grouped and not mixed) */
1921
while (((1 << redshift) & redmask) == 0) redshift++;
1922
while (((1 << greenshift) & greenmask) == 0) greenshift++;
1923
while (((1 << blueshift) & bluemask) == 0) blueshift++;
1925
/* The bits_per_rgb may not be correct. Use redmask instead */
1927
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
1928
maxred = (1 << maxred) - 1;
1930
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
1931
maxgreen = (1 << maxgreen) - 1;
1933
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
1934
maxblue = (1 << maxblue) - 1;
1936
if (maxred > sizeof (redmap) ||
1937
maxgreen > sizeof (greenmap) ||
1938
maxblue > sizeof (bluemap))
1940
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1941
_("XWD-file %s is corrupt."),
1942
gimp_filename_to_utf8 (filename));
1946
/* Set map-arrays for red, green, blue */
1947
for (red = 0; red <= maxred; red++)
1948
redmap[red] = (red * 255) / maxred;
1949
for (green = 0; green <= maxgreen; green++)
1950
greenmap[green] = (green * 255) / maxgreen;
1951
for (blue = 0; blue <= maxblue; blue++)
1952
bluemap[blue] = (blue * 255) / maxblue;
1955
image_ID = create_new_image (filename, width, height,
1956
indexed ? GIMP_INDEXED : GIMP_RGB,
1957
&layer_ID, &drawable, &pixel_rgn);
1959
tile_height = gimp_tile_height ();
1960
data = g_malloc (tile_height * width * bytes_per_pixel);
1962
ncols = xwdhdr->l_colormap_entries;
1963
if (xwdhdr->l_ncolors < ncols)
1964
ncols = xwdhdr->l_ncolors;
1969
set_bw_color_table (image_ID);
1971
set_color_table (image_ID, xwdhdr, xwdcolmap);
1975
set_pixelmap (ncols, xwdcolmap, &pixel_map);
1978
do_reverse = !xwdhdr->l_bitmap_bit_order;
1980
/* This is where the image data starts within the file */
1981
data_offset = ftell (ifp);
1983
for (tile_start = 0; tile_start < height; tile_start += tile_height)
1985
memset (data, 0, width*tile_height*bytes_per_pixel);
1987
tile_end = tile_start + tile_height - 1;
1988
if (tile_end >= height)
1989
tile_end = height - 1;
1991
for (plane = 0; plane < xwdhdr->l_pixmap_depth; plane++)
1993
dest = data; /* Position to start of tile within the plane */
1994
plane_offset = data_offset + plane*height*xwdhdr->l_bytes_per_line;
1995
tile_offset = plane_offset + tile_start*xwdhdr->l_bytes_per_line;
1996
fseek (ifp, tile_offset, SEEK_SET);
1998
/* Place the last plane at the least significant bit */
2000
if (indexed) /* Only 1 byte per pixel */
2002
fromright = xwdhdr->l_pixmap_depth-1-plane;
2003
outmask = (1 << fromright);
2005
else /* 3 bytes per pixel */
2007
fromright = xwdhdr->l_pixmap_depth-1-plane;
2008
dest += 2 - fromright/8;
2009
outmask = (1 << (fromright % 8));
2012
for (i = tile_start; i <= tile_end; i++)
2014
if (fread (xwddata,xwdhdr->l_bytes_per_line,1,ifp) != 1)
2021
/* Handle bitmap unit */
2022
if (xwdhdr->l_bitmap_unit == 16)
2024
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
2026
j = xwdhdr->l_bytes_per_line/2;
2029
inmask = xwdin[0]; xwdin[0] = xwdin[1]; xwdin[1] = inmask;
2035
else if (xwdhdr->l_bitmap_unit == 32)
2037
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
2039
j = xwdhdr->l_bytes_per_line/4;
2042
inmask = xwdin[0]; xwdin[0] = xwdin[3]; xwdin[3] = inmask;
2043
inmask = xwdin[1]; xwdin[1] = xwdin[2]; xwdin[2] = inmask;
2051
for (j = 0; j < width; j++)
2063
dest += bytes_per_pixel;
2070
/* For indexed images, the mapping to colors is done by the color table. */
2071
/* Otherwise we must do the mapping by ourself. */
2075
for (i = tile_start; i <= tile_end; i++)
2077
for (j = 0; j < width; j++)
2079
pixelval = (*dest << 16) | (*(dest+1) << 8) | *(dest+2);
2081
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2)
2086
else /* We have to map RGB to 0,...,255 */
2088
*(dest++) = redmap[(pixelval & redmask) >> redshift];
2089
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
2090
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
2096
gimp_progress_update ((gdouble) tile_end / (gdouble) height);
2098
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, tile_start,
2099
width, tile_end-tile_start+1);
2106
g_message (_("EOF encountered on reading"));
2108
gimp_drawable_flush (drawable);
2110
return err ? -1 : image_ID;
2115
save_index (FILE *ofp,
2120
gint height, width, linepad, tile_height, i, j;
2121
gint ncolors, vclass;
2123
guchar *data, *src, *cmap;
2124
L_XWDFILEHEADER xwdhdr;
2125
L_XWDCOLOR xwdcolmap[256];
2126
GimpPixelRgn pixel_rgn;
2127
GimpDrawable *drawable;
2130
printf ("save_index ()\n");
2133
drawable = gimp_drawable_get (drawable_ID);
2134
width = drawable->width;
2135
height = drawable->height;
2136
tile_height = gimp_tile_height ();
2138
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
2140
/* allocate a buffer for retrieving information from the pixel region */
2141
src = data = g_new (guchar, tile_height * width * drawable->bpp);
2143
linepad = width % 4;
2144
if (linepad) linepad = 4 - linepad;
2146
/* Fill XWD-color map */
2152
for (j = 0; j < ncolors; j++)
2154
xwdcolmap[j].l_pixel = j;
2155
xwdcolmap[j].l_red = (j << 8) | j;
2156
xwdcolmap[j].l_green = (j << 8) | j;
2157
xwdcolmap[j].l_blue = (j << 8) | j;
2158
xwdcolmap[j].l_flags = 7;
2159
xwdcolmap[j].l_pad = 0;
2165
cmap = gimp_image_get_colormap (image_ID, &ncolors);
2167
for (j = 0; j < ncolors; j++)
2169
xwdcolmap[j].l_pixel = j;
2170
xwdcolmap[j].l_red = ((*cmap) << 8) | *cmap; cmap++;
2171
xwdcolmap[j].l_green = ((*cmap) << 8) | *cmap; cmap++;
2172
xwdcolmap[j].l_blue = ((*cmap) << 8) | *cmap; cmap++;
2173
xwdcolmap[j].l_flags = 7;
2174
xwdcolmap[j].l_pad = 0;
2178
/* Fill in the XWD header (header_size is evaluated by write_xwd_hdr ()) */
2179
xwdhdr.l_header_size = 0;
2180
xwdhdr.l_file_version = 7;
2181
xwdhdr.l_pixmap_format = 2;
2182
xwdhdr.l_pixmap_depth = 8;
2183
xwdhdr.l_pixmap_width = width;
2184
xwdhdr.l_pixmap_height = height;
2185
xwdhdr.l_xoffset = 0;
2186
xwdhdr.l_byte_order = 1;
2187
xwdhdr.l_bitmap_unit = 32;
2188
xwdhdr.l_bitmap_bit_order = 1;
2189
xwdhdr.l_bitmap_pad = 32;
2190
xwdhdr.l_bits_per_pixel = 8;
2191
xwdhdr.l_bytes_per_line = width + linepad;
2192
xwdhdr.l_visual_class = vclass;
2193
xwdhdr.l_red_mask = 0x000000;
2194
xwdhdr.l_green_mask = 0x000000;
2195
xwdhdr.l_blue_mask = 0x000000;
2196
xwdhdr.l_bits_per_rgb = 8;
2197
xwdhdr.l_colormap_entries = ncolors;
2198
xwdhdr.l_ncolors = ncolors;
2199
xwdhdr.l_window_width = width;
2200
xwdhdr.l_window_height = height;
2201
xwdhdr.l_window_x = 64;
2202
xwdhdr.l_window_y = 64;
2203
xwdhdr.l_window_bdrwidth = 0;
2205
write_xwd_header (ofp, &xwdhdr);
2206
write_xwd_cols (ofp, &xwdhdr, xwdcolmap);
2208
for (i = 0; i < height; i++)
2210
if ((i % tile_height) == 0) /* Get more data */
2212
gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
2214
gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, i, width, scan_lines);
2218
fwrite (src, width, 1, ofp);
2221
fwrite ((char *)&tmp, linepad, 1, ofp);
2226
gimp_progress_update ((gdouble) i / (gdouble) height);
2231
gimp_drawable_detach (drawable);
2235
g_message (_("Error during writing indexed/gray image"));
2244
save_rgb (FILE *ofp,
2248
gint height, width, linepad, tile_height, i;
2251
L_XWDFILEHEADER xwdhdr;
2252
GimpPixelRgn pixel_rgn;
2253
GimpDrawable *drawable;
2256
printf ("save_rgb ()\n");
2259
drawable = gimp_drawable_get (drawable_ID);
2260
width = drawable->width;
2261
height = drawable->height;
2262
tile_height = gimp_tile_height ();
2264
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
2266
/* allocate a buffer for retrieving information from the pixel region */
2267
src = data = g_new (guchar, tile_height * width * drawable->bpp);
2269
linepad = (width * 3) % 4;
2271
linepad = 4 - linepad;
2273
/* Fill in the XWD header (header_size is evaluated by write_xwd_hdr ()) */
2274
xwdhdr.l_header_size = 0;
2275
xwdhdr.l_file_version = 7;
2276
xwdhdr.l_pixmap_format = 2;
2277
xwdhdr.l_pixmap_depth = 24;
2278
xwdhdr.l_pixmap_width = width;
2279
xwdhdr.l_pixmap_height = height;
2280
xwdhdr.l_xoffset = 0;
2281
xwdhdr.l_byte_order = 1;
2283
xwdhdr.l_bitmap_unit = 32;
2284
xwdhdr.l_bitmap_bit_order = 1;
2285
xwdhdr.l_bitmap_pad = 32;
2286
xwdhdr.l_bits_per_pixel = 24;
2288
xwdhdr.l_bytes_per_line = width * 3 + linepad;
2289
xwdhdr.l_visual_class = 5;
2290
xwdhdr.l_red_mask = 0xff0000;
2291
xwdhdr.l_green_mask = 0x00ff00;
2292
xwdhdr.l_blue_mask = 0x0000ff;
2293
xwdhdr.l_bits_per_rgb = 8;
2294
xwdhdr.l_colormap_entries = 0;
2295
xwdhdr.l_ncolors = 0;
2296
xwdhdr.l_window_width = width;
2297
xwdhdr.l_window_height = height;
2298
xwdhdr.l_window_x = 64;
2299
xwdhdr.l_window_y = 64;
2300
xwdhdr.l_window_bdrwidth = 0;
2302
write_xwd_header (ofp, &xwdhdr);
2304
for (i = 0; i < height; i++)
2306
if ((i % tile_height) == 0) /* Get more data */
2308
gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
2310
gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, i, width, scan_lines);
2314
fwrite (src, width * 3, 1, ofp);
2317
fwrite ((char *)&tmp, linepad, 1, ofp);
2322
gimp_progress_update ((gdouble) i / (gdouble) height);
2327
gimp_drawable_detach (drawable);
2331
g_message (_("Error during writing rgb image"));