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
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));
498
if (xwdhdr.l_pixmap_width > GIMP_MAX_IMAGE_SIZE
499
|| xwdhdr.l_bytes_per_line > GIMP_MAX_IMAGE_SIZE * 3)
501
g_message (_("'%s':\nImage width is larger than GIMP can handle"),
502
gimp_filename_to_utf8 (filename));
508
if (xwdhdr.l_pixmap_height <= 0)
510
g_message (_("'%s':\nNo image height specified"),
511
gimp_filename_to_utf8 (filename));
517
if (xwdhdr.l_pixmap_height > GIMP_MAX_IMAGE_SIZE)
519
g_message (_("'%s':\nImage height is larger than GIMP can handle"),
520
gimp_filename_to_utf8 (filename));
526
gimp_progress_init_printf (_("Opening '%s'"),
527
gimp_filename_to_utf8 (filename));
529
depth = xwdhdr.l_pixmap_depth;
530
bpp = xwdhdr.l_bits_per_pixel;
533
switch (xwdhdr.l_pixmap_format)
535
case 0: /* Single plane bitmap */
536
if ((depth == 1) && (bpp == 1))
537
{ /* Can be performed by format 2 loader */
538
image_ID = load_xwd_f2_d1_b1 (filename, ifp, &xwdhdr, xwdcolmap);
542
case 1: /* Single plane pixmap */
543
if ((depth <= 24) && (bpp == 1))
545
image_ID = load_xwd_f1_d24_b1 (filename, ifp, &xwdhdr, xwdcolmap,
550
case 2: /* Multiplane pixmaps */
551
if ((depth == 1) && (bpp == 1))
553
image_ID = load_xwd_f2_d1_b1 (filename, ifp, &xwdhdr, xwdcolmap);
555
else if ((depth <= 8) && (bpp == 8))
557
image_ID = load_xwd_f2_d8_b8 (filename, ifp, &xwdhdr, xwdcolmap);
559
else if ((depth <= 16) && (bpp == 16))
561
image_ID = load_xwd_f2_d16_b16 (filename, ifp, &xwdhdr, xwdcolmap);
563
else if ((depth <= 24) && ((bpp == 24) || (bpp == 32)))
565
image_ID = load_xwd_f2_d24_b32 (filename, ifp, &xwdhdr, xwdcolmap,
570
gimp_progress_update (1.0);
577
if (image_ID == -1 && ! (error && *error))
578
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
579
_("XWD-file %s has format %d, depth %d and bits per pixel %d. "
580
"Currently this is not supported."),
581
gimp_filename_to_utf8 (filename),
582
(gint) xwdhdr.l_pixmap_format, depth, bpp);
588
save_image (const gchar *filename,
594
GimpImageType drawable_type;
597
drawable_type = gimp_drawable_type (drawable_ID);
599
/* Make sure we're not saving an image with an alpha channel */
600
if (gimp_drawable_has_alpha (drawable_ID))
602
g_message (_("Cannot save images with alpha channels."));
606
switch (drawable_type)
608
case GIMP_INDEXED_IMAGE:
609
case GIMP_GRAY_IMAGE:
613
g_message (_("Cannot operate on unknown image types."));
618
/* Open the output file. */
619
ofp = g_fopen (filename, "wb");
622
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
623
_("Could not open '%s' for writing: %s"),
624
gimp_filename_to_utf8 (filename), g_strerror (errno));
628
gimp_progress_init_printf (_("Saving '%s'"),
629
gimp_filename_to_utf8 (filename));
631
switch (drawable_type)
633
case GIMP_INDEXED_IMAGE:
634
retval = save_index (ofp, image_ID, drawable_ID, 0);
636
case GIMP_GRAY_IMAGE:
637
retval = save_index (ofp, image_ID, drawable_ID, 1);
640
retval = save_rgb (ofp, image_ID, drawable_ID);
646
gimp_progress_update (1.0);
655
read_card32 (FILE *ifp,
661
c = (((L_CARD32) (getc (ifp))) << 24);
662
c |= (((L_CARD32) (getc (ifp))) << 16);
663
c |= (((L_CARD32) (getc (ifp))) << 8);
664
c |= ((L_CARD32) (*err = getc (ifp)));
673
read_card16 (FILE *ifp,
679
c = (((L_CARD16) (getc (ifp))) << 8);
680
c |= ((L_CARD16) (*err = getc (ifp)));
689
read_card8 (FILE *ifp,
694
c = ((L_CARD8) (*err = getc (ifp)));
702
write_card32 (FILE *ofp,
705
putc ((int) ((c >> 24) & 0xff), ofp);
706
putc ((int) ((c >> 16) & 0xff), ofp);
707
putc ((int) ((c >> 8) & 0xff), ofp);
708
putc ((int) ((c) & 0xff), ofp);
713
write_card16 (FILE *ofp,
716
putc ((int) ((c >> 8) & 0xff), ofp);
717
putc ((int) ((c) & 0xff), ofp);
722
write_card8 (FILE *ofp,
725
putc ((int) ((c) & 0xff), ofp);
730
read_xwd_header (FILE *ifp,
731
L_XWDFILEHEADER *xwdhdr)
736
cp = (L_CARD32 *) xwdhdr;
738
/* Read in all 32-bit values of the header and check for byte order */
739
for (j = 0; j < sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version); j++)
741
*(cp++) = read_card32 (ifp, &err);
748
xwdhdr->l_file_version = 0; /* Not a valid XWD-file */
752
/* Write out an XWD-fileheader. The header size is calculated here */
754
write_xwd_header (FILE *ofp,
755
L_XWDFILEHEADER *xwdhdr)
758
gint j, hdrpad, hdr_entries;
762
hdr_entries = sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version);
763
xwdhdr->l_header_size = hdr_entries * 4 + hdrpad;
765
cp = (L_CARD32 *) xwdhdr;
767
/* Write out all 32-bit values of the header and check for byte order */
768
for (j = 0; j < sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version); j++)
770
write_card32 (ofp, *(cp++));
773
/* Add padding bytes after XWD header */
774
for (j = 0; j < hdrpad; j++)
775
write_card8 (ofp, (L_CARD32) 0);
780
read_xwd_cols (FILE *ifp,
781
L_XWDFILEHEADER *xwdhdr,
782
L_XWDCOLOR *colormap)
785
gint flag_is_bad, index_is_bad;
786
gint indexed = (xwdhdr->l_pixmap_depth <= 8);
787
glong colmappos = ftell (ifp);
789
/* Read in XWD-Color structures (the usual case) */
790
flag_is_bad = index_is_bad = 0;
791
for (j = 0; j < xwdhdr->l_ncolors; j++)
793
colormap[j].l_pixel = read_card32 (ifp, &err);
795
colormap[j].l_red = read_card16 (ifp, &err);
796
colormap[j].l_green = read_card16 (ifp, &err);
797
colormap[j].l_blue = read_card16 (ifp, &err);
799
colormap[j].l_flags = read_card8 (ifp, &err);
800
colormap[j].l_pad = read_card8 (ifp, &err);
802
if (indexed && (colormap[j].l_pixel > 255))
809
if (err) /* Not a valid XWD-file ? */
810
xwdhdr->l_file_version = 0;
811
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
814
/* Read in XWD-Color structures (with 4 bytes inserted infront of RGB) */
815
fseek (ifp, colmappos, SEEK_SET);
816
flag_is_bad = index_is_bad = 0;
817
for (j = 0; j < xwdhdr->l_ncolors; j++)
819
colormap[j].l_pixel = read_card32 (ifp, &err);
821
read_card32 (ifp, &err); /* Empty bytes on Alpha OSF */
823
colormap[j].l_red = read_card16 (ifp, &err);
824
colormap[j].l_green = read_card16 (ifp, &err);
825
colormap[j].l_blue = read_card16 (ifp, &err);
827
colormap[j].l_flags = read_card8 (ifp, &err);
828
colormap[j].l_pad = read_card8 (ifp, &err);
830
if (indexed && (colormap[j].l_pixel > 255))
837
if (err) /* Not a valid XWD-file ? */
838
xwdhdr->l_file_version = 0;
839
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
842
/* Read in XWD-Color structures (with 2 bytes inserted infront of RGB) */
843
fseek (ifp, colmappos, SEEK_SET);
844
flag_is_bad = index_is_bad = 0;
845
for (j = 0; j < xwdhdr->l_ncolors; j++)
847
colormap[j].l_pixel = read_card32 (ifp, &err);
849
read_card16 (ifp, &err); /* Empty bytes (from where ?) */
851
colormap[j].l_red = read_card16 (ifp, &err);
852
colormap[j].l_green = read_card16 (ifp, &err);
853
colormap[j].l_blue = read_card16 (ifp, &err);
855
colormap[j].l_flags = read_card8 (ifp, &err);
856
colormap[j].l_pad = read_card8 (ifp, &err);
858
/* if ((colormap[j].l_flags == 0) || (colormap[j].l_flags > 7))
861
if (indexed && (colormap[j].l_pixel > 255))
868
if (err) /* Not a valid XWD-file ? */
869
xwdhdr->l_file_version = 0;
870
if (err || ((flag_is_bad == 0) && (index_is_bad == 0)))
873
/* Read in XWD-Color structures (every value is 8 bytes from a CRAY) */
874
fseek (ifp, colmappos, SEEK_SET);
875
flag_is_bad = index_is_bad = 0;
876
for (j = 0; j < xwdhdr->l_ncolors; j++)
878
read_card32 (ifp, &err);
879
colormap[j].l_pixel = read_card32 (ifp, &err);
881
read_card32 (ifp, &err);
882
colormap[j].l_red = read_card32 (ifp, &err);
883
read_card32 (ifp, &err);
884
colormap[j].l_green = read_card32 (ifp, &err);
885
read_card32 (ifp, &err);
886
colormap[j].l_blue = read_card32 (ifp, &err);
888
/* The flag byte is kept in the first byte */
889
colormap[j].l_flags = read_card8 (ifp, &err);
890
colormap[j].l_pad = read_card8 (ifp, &err);
891
read_card16 (ifp, &err);
892
read_card32 (ifp, &err);
894
if (indexed && (colormap[j].l_pixel > 255))
901
if (flag_is_bad || index_is_bad)
903
printf ("xwd: Warning. Error in XWD-color-structure (");
905
if (flag_is_bad) printf ("flag");
906
if (index_is_bad) printf ("index");
912
xwdhdr->l_file_version = 0; /* Not a valid XWD-file */
917
write_xwd_cols (FILE *ofp,
918
L_XWDFILEHEADER *xwdhdr,
919
L_XWDCOLOR *colormap)
924
for (j = 0; j < xwdhdr->l_colormap_entries; j++)
927
write_card32 (ofp, (L_CARD32)0);
928
write_card32 (ofp, colormap[j].l_pixel);
929
write_card32 (ofp, (L_CARD32)0);
930
write_card32 (ofp, (L_CARD32)colormap[j].l_red);
931
write_card32 (ofp, (L_CARD32)0);
932
write_card32 (ofp, (L_CARD32)colormap[j].l_green);
933
write_card32 (ofp, (L_CARD32)0);
934
write_card32 (ofp, (L_CARD32)colormap[j].l_blue);
935
write_card8 (ofp, (L_CARD32)colormap[j].l_flags);
936
write_card8 (ofp, (L_CARD32)colormap[j].l_pad);
937
write_card16 (ofp, (L_CARD32)0);
938
write_card32 (ofp, (L_CARD32)0);
941
write_card32 (ofp, colormap[j].l_pixel);
942
write_card32 (ofp, (L_CARD32)0);
943
write_card16 (ofp, (L_CARD32)colormap[j].l_red);
944
write_card16 (ofp, (L_CARD32)colormap[j].l_green);
945
write_card16 (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);
949
write_card32 (ofp, colormap[j].l_pixel);
950
write_card16 (ofp, (L_CARD32)colormap[j].l_red);
951
write_card16 (ofp, (L_CARD32)colormap[j].l_green);
952
write_card16 (ofp, (L_CARD32)colormap[j].l_blue);
953
write_card8 (ofp, (L_CARD32)colormap[j].l_flags);
954
write_card8 (ofp, (L_CARD32)colormap[j].l_pad);
961
/* Create a map for mapping up to 32 bit pixelvalues to RGB. */
962
/* Returns number of colors kept in the map (up to 256) */
965
set_pixelmap (int ncols,
970
gint i, j, k, maxcols;
973
memset ((gchar *) pixelmap, 0, sizeof (PIXEL_MAP));
977
for (j = 0; j < ncols; j++) /* For each entry of the XWD colormap */
979
pixel_val = xwdcol[j].l_pixel;
980
for (k = 0; k < maxcols; k++) /* Where to insert in list ? */
982
if (pixel_val <= pixelmap->pmap[k].pixel_val)
985
if ((k < maxcols) && (pixel_val == pixelmap->pmap[k].pixel_val))
986
break; /* It was already in list */
991
if (k < maxcols) /* Must move entries to the back ? */
993
for (i = maxcols-1; i >= k; i--)
994
memcpy ((char *)&(pixelmap->pmap[i+1]),(char *)&(pixelmap->pmap[i]),
997
pixelmap->pmap[k].pixel_val = pixel_val;
998
pixelmap->pmap[k].red = xwdcol[j].l_red >> 8;
999
pixelmap->pmap[k].green = xwdcol[j].l_green >> 8;
1000
pixelmap->pmap[k].blue = xwdcol[j].l_blue >> 8;
1001
pixelmap->pixel_in_map[pixel_val & MAPPERMASK] = 1;
1004
pixelmap->npixel = maxcols;
1005
#ifdef XWD_COL_DEBUG
1006
printf ("Colors in pixelmap: %d\n",pixelmap->npixel);
1007
for (j=0; j<pixelmap->npixel; j++)
1008
printf ("Pixelvalue 0x%08lx, 0x%02x 0x%02x 0x%02x\n",
1009
pixelmap->pmap[j].pixel_val,
1010
pixelmap->pmap[j].red,pixelmap->pmap[j].green,
1011
pixelmap->pmap[j].blue);
1012
for (j=0; j<=MAPPERMASK; j++)
1013
printf ("0x%08lx: %d\n",(long)j,pixelmap->pixel_in_map[j]);
1016
return pixelmap->npixel;
1020
/* Search a pixel value in the pixel map. Returns FALSE if the */
1021
/* pixelval was not found in map. Returns TRUE if found. */
1024
get_pixelmap (L_CARD32 pixelval,
1025
PIXEL_MAP *pixelmap,
1031
register PMAP *low, *high, *middle;
1033
if (pixelmap->npixel == 0)
1036
if (!(pixelmap->pixel_in_map[pixelval & MAPPERMASK]))
1039
low = &(pixelmap->pmap[0]);
1040
high = &(pixelmap->pmap[pixelmap->npixel-1]);
1042
/* Do a binary search on the array */
1045
middle = low + ((high - low)/2);
1046
if (pixelval <= middle->pixel_val)
1052
if (pixelval == low->pixel_val)
1054
*red = low->red; *green = low->green; *blue = low->blue;
1063
set_bw_color_table (gint32 image_ID)
1065
static guchar BWColorMap[2*3] = { 255, 255, 255, 0, 0, 0 };
1067
#ifdef XWD_COL_DEBUG
1068
printf ("Set GIMP b/w-colortable:\n");
1071
gimp_image_set_colormap (image_ID, BWColorMap, 2);
1075
/* Initialize an 8-bit colortable from the mask-values of the XWD-header */
1077
init_color_table256 (L_XWDFILEHEADER *xwdhdr,
1081
gint i, j, k, cuind;
1082
gint redshift, greenshift, blueshift;
1083
gint maxred, maxgreen, maxblue;
1085
/* Assume: the bit masks for red/green/blue are grouped together
1086
* Example: redmask = 0xe0, greenmask = 0x1c, bluemask = 0x03
1087
* We need to know where to place the RGB-values (shifting)
1088
* and the maximum value for each component.
1090
redshift = greenshift = blueshift = 0;
1091
if ((maxred = xwdhdr->l_red_mask) == 0)
1094
/* Shift the redmask to the rightmost bit position to get
1095
* maximum value for red.
1097
while ((maxred & 1) == 0)
1103
if ((maxgreen = xwdhdr->l_green_mask) == 0)
1106
while ((maxgreen & 1) == 0)
1112
if ((maxblue = xwdhdr->l_blue_mask) == 0)
1115
while ((maxblue & 1) == 0)
1121
memset ((gchar *) ColorMap, 0, 256 * 3);
1123
for (i = 0; i <= maxred; i++)
1124
for (j = 0; j <= maxgreen; j++)
1125
for (k = 0; k <= maxblue; k++)
1127
cuind = (i << redshift) | (j << greenshift) | (k << blueshift);
1131
ColorMap[cuind*3] = (i * 255)/maxred;
1132
ColorMap[cuind*3+1] = (j * 255)/maxgreen;
1133
ColorMap[cuind*3+2] = (k * 255)/maxblue;
1140
set_color_table (gint32 image_ID,
1141
L_XWDFILEHEADER *xwdhdr,
1142
L_XWDCOLOR *xwdcolmap)
1146
guchar ColorMap[256 * 3];
1148
ncols = xwdhdr->l_colormap_entries;
1149
if (xwdhdr->l_ncolors < ncols)
1150
ncols = xwdhdr->l_ncolors;
1156
/* Initialize color table for all 256 entries from mask-values */
1157
init_color_table256 (xwdhdr, ColorMap);
1159
for (j = 0; j < ncols; j++)
1161
i = xwdcolmap[j].l_pixel;
1162
if ((i >= 0) && (i < 256))
1164
ColorMap[i*3] = (xwdcolmap[j].l_red) >> 8;
1165
ColorMap[i*3+1] = (xwdcolmap[j].l_green) >> 8;
1166
ColorMap[i*3+2] = (xwdcolmap[j].l_blue) >> 8;
1170
#ifdef XWD_COL_DEBUG
1171
printf ("Set GIMP colortable:\n");
1172
for (j = 0; j < 256; j++)
1173
printf ("%3d: 0x%02x 0x%02x 0x%02x\n", j,
1174
ColorMap[j*3], ColorMap[j*3+1], ColorMap[j*3+2]);
1177
gimp_image_set_colormap (image_ID, ColorMap, 256);
1183
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */
1185
create_new_image (const gchar *filename,
1188
GimpImageBaseType type,
1190
GimpDrawable **drawable,
1191
GimpPixelRgn *pixel_rgn)
1194
GimpImageType gdtype;
1199
gdtype = GIMP_GRAY_IMAGE;
1202
gdtype = GIMP_INDEXED_IMAGE;
1205
gdtype = GIMP_RGB_IMAGE;
1208
g_warning ("Unknown image type");
1212
image_ID = gimp_image_new (width, height, type);
1213
gimp_image_set_filename (image_ID, filename);
1215
*layer_ID = gimp_layer_new (image_ID, "Background", width, height,
1216
gdtype, 100, GIMP_NORMAL_MODE);
1217
gimp_image_insert_layer (image_ID, *layer_ID, -1, 0);
1219
*drawable = gimp_drawable_get (*layer_ID);
1220
gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width,
1221
(*drawable)->height, TRUE, FALSE);
1227
/* Load XWD with pixmap_format 2, pixmap_depth 1, bits_per_pixel 1 */
1230
load_xwd_f2_d1_b1 (const gchar *filename,
1232
L_XWDFILEHEADER *xwdhdr,
1233
L_XWDCOLOR *xwdcolmap)
1236
register guchar *dest, *src;
1237
guchar c1, c2, c3, c4;
1238
gint width, height, scan_lines, tile_height;
1241
guchar bit2byte[256 * 8];
1242
guchar *data, *scanline;
1244
gint32 layer_ID, image_ID;
1245
GimpPixelRgn pixel_rgn;
1246
GimpDrawable *drawable;
1249
printf ("load_xwd_f2_d1_b1 (%s)\n", filename);
1252
width = xwdhdr->l_pixmap_width;
1253
height = xwdhdr->l_pixmap_height;
1255
image_ID = create_new_image (filename, width, height, GIMP_INDEXED,
1256
&layer_ID, &drawable, &pixel_rgn);
1258
tile_height = gimp_tile_height ();
1259
data = g_malloc (tile_height * width);
1261
scanline = g_new (guchar, xwdhdr->l_bytes_per_line + 8);
1263
ncols = xwdhdr->l_colormap_entries;
1264
if (xwdhdr->l_ncolors < ncols)
1265
ncols = xwdhdr->l_ncolors;
1268
set_bw_color_table (image_ID);
1270
set_color_table (image_ID, xwdhdr, xwdcolmap);
1272
temp = (gchar *) bit2byte;
1274
/* Get an array for mapping 8 bits in a byte to 8 bytes */
1275
if (!xwdhdr->l_bitmap_bit_order)
1277
for (j = 0; j < 256; j++)
1278
for (i = 0; i < 8; i++)
1279
*(temp++) = ((j & (1 << i)) != 0);
1283
for (j = 0; j < 256; j++)
1284
for (i = 7; i >= 0; i--)
1285
*(temp++) = ((j & (1 << i)) != 0);
1291
for (i = 0; i < height; i++)
1293
if (fread (scanline, xwdhdr->l_bytes_per_line, 1, ifp) != 1)
1299
/* Need to check byte order ? */
1300
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
1303
switch (xwdhdr->l_bitmap_unit)
1306
j = xwdhdr->l_bytes_per_line;
1309
c1 = src[0]; c2 = src[1];
1310
*(src++) = c2; *(src++) = c1;
1316
j = xwdhdr->l_bytes_per_line;
1319
c1 = src[0]; c2 = src[1]; c3 = src[2]; c4 = src[3];
1320
*(src++) = c4; *(src++) = c3; *(src++) = c2; *(src++) = c1;
1331
memcpy (dest, bit2byte + pix8*8, 8);
1338
memcpy (dest, bit2byte + pix8*8, j);
1345
gimp_progress_update ((double)(i+1) / (double)height);
1347
if ((scan_lines == tile_height) || ((i+1) == height))
1349
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1361
g_message (_("EOF encountered on reading"));
1363
gimp_drawable_flush (drawable);
1365
return err ? -1 : image_ID;
1369
/* Load XWD with pixmap_format 2, pixmap_depth 8, bits_per_pixel 8 */
1372
load_xwd_f2_d8_b8 (const gchar *filename,
1374
L_XWDFILEHEADER *xwdhdr,
1375
L_XWDCOLOR *xwdcolmap)
1377
gint width, height, linepad, tile_height, scan_lines;
1380
guchar *dest, *data;
1382
gint32 layer_ID, image_ID;
1383
GimpPixelRgn pixel_rgn;
1384
GimpDrawable *drawable;
1387
printf ("load_xwd_f2_d8_b8 (%s)\n", filename);
1390
width = xwdhdr->l_pixmap_width;
1391
height = xwdhdr->l_pixmap_height;
1393
/* This could also be a grayscale image. Check it */
1395
if ((xwdhdr->l_ncolors == 256) && (xwdhdr->l_colormap_entries == 256))
1397
for (j = 0; j < 256; j++)
1399
if ((xwdcolmap[j].l_pixel != j)
1400
|| ((xwdcolmap[j].l_red >> 8) != j)
1401
|| ((xwdcolmap[j].l_green >> 8) != j)
1402
|| ((xwdcolmap[j].l_blue >> 8) != j))
1406
grayscale = (j == 256);
1409
image_ID = create_new_image (filename, width, height,
1410
grayscale ? GIMP_GRAY : GIMP_INDEXED,
1411
&layer_ID, &drawable, &pixel_rgn);
1413
tile_height = gimp_tile_height ();
1414
data = g_malloc (tile_height * width);
1418
ncols = xwdhdr->l_colormap_entries;
1419
if (xwdhdr->l_ncolors < ncols) ncols = xwdhdr->l_ncolors;
1421
set_bw_color_table (image_ID);
1423
set_color_table (image_ID, xwdhdr, xwdcolmap);
1426
linepad = xwdhdr->l_bytes_per_line - xwdhdr->l_pixmap_width;
1433
for (i = 0; i < height; i++)
1435
if (fread (dest, 1, width, ifp) != width)
1442
for (j = 0; j < linepad; j++)
1448
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
1450
if ((scan_lines == tile_height) || ((i+1) == height))
1452
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1462
g_message (_("EOF encountered on reading"));
1464
gimp_drawable_flush (drawable);
1466
return err ? -1 : image_ID;
1470
/* Load XWD with pixmap_format 2, pixmap_depth up to 16, bits_per_pixel 16 */
1473
load_xwd_f2_d16_b16 (const gchar *filename,
1475
L_XWDFILEHEADER *xwdhdr,
1476
L_XWDCOLOR *xwdcolmap)
1478
register guchar *dest, lsbyte_first;
1479
gint width, height, linepad, i, j, c0, c1, ncols;
1480
gint red, green, blue, redval, greenval, blueval;
1481
gint maxred, maxgreen, maxblue;
1482
gint tile_height, scan_lines;
1483
gulong redmask, greenmask, bluemask;
1484
guint redshift, greenshift, blueshift;
1486
guchar *ColorMap, *cm, *data;
1488
gint32 layer_ID, image_ID;
1489
GimpPixelRgn pixel_rgn;
1490
GimpDrawable *drawable;
1493
printf ("load_xwd_f2_d16_b16 (%s)\n", filename);
1496
width = xwdhdr->l_pixmap_width;
1497
height = xwdhdr->l_pixmap_height;
1499
image_ID = create_new_image (filename, width, height, GIMP_RGB,
1500
&layer_ID, &drawable, &pixel_rgn);
1502
tile_height = gimp_tile_height ();
1503
data = g_malloc (tile_height * width * 3);
1505
/* Get memory for mapping 16 bit XWD-pixel to GIMP-RGB */
1506
maxval = 0x10000 * 3;
1507
ColorMap = g_new0 (guchar, maxval);
1509
redmask = xwdhdr->l_red_mask;
1510
greenmask = xwdhdr->l_green_mask;
1511
bluemask = xwdhdr->l_blue_mask;
1513
/* How to shift RGB to be right aligned ? */
1514
/* (We rely on the the mask bits are grouped and not mixed) */
1515
redshift = greenshift = blueshift = 0;
1517
while (((1 << redshift) & redmask) == 0) redshift++;
1518
while (((1 << greenshift) & greenmask) == 0) greenshift++;
1519
while (((1 << blueshift) & bluemask) == 0) blueshift++;
1521
/* The bits_per_rgb may not be correct. Use redmask instead */
1522
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
1523
maxred = (1 << maxred) - 1;
1525
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
1526
maxgreen = (1 << maxgreen) - 1;
1528
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
1529
maxblue = (1 << maxblue) - 1;
1531
/* Built up the array to map XWD-pixel value to GIMP-RGB */
1532
for (red = 0; red <= maxred; red++)
1534
redval = (red * 255) / maxred;
1535
for (green = 0; green <= maxgreen; green++)
1537
greenval = (green * 255) / maxgreen;
1538
for (blue = 0; blue <= maxblue; blue++)
1540
blueval = (blue * 255) / maxblue;
1541
cm = ColorMap + ((red << redshift) + (green << greenshift)
1542
+ (blue << blueshift)) * 3;
1550
/* Now look what was written to the XWD-Colormap */
1552
ncols = xwdhdr->l_colormap_entries;
1553
if (xwdhdr->l_ncolors < ncols)
1554
ncols = xwdhdr->l_ncolors;
1556
for (j = 0; j < ncols; j++)
1558
cm = ColorMap + xwdcolmap[j].l_pixel * 3;
1559
*(cm++) = (xwdcolmap[j].l_red >> 8);
1560
*(cm++) = (xwdcolmap[j].l_green >> 8);
1561
*cm = (xwdcolmap[j].l_blue >> 8);
1564
/* What do we have to consume after a line has finished ? */
1565
linepad = xwdhdr->l_bytes_per_line
1566
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
1567
if (linepad < 0) linepad = 0;
1569
lsbyte_first = (xwdhdr->l_byte_order == 0);
1574
for (i = 0; i < height; i++)
1576
for (j = 0; j < width; j++)
1587
c0 = c0 | (c1 << 8);
1589
c0 = (c0 << 8) | c1;
1591
cm = ColorMap + c0 * 3;
1592
*(dest++) = *(cm++);
1593
*(dest++) = *(cm++);
1600
for (j = 0; j < linepad; j++)
1606
gimp_progress_update ((double)(i+1) / (double)height);
1608
if ((scan_lines == tile_height) || ((i+1) == height))
1610
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1620
g_message (_("EOF encountered on reading"));
1622
gimp_drawable_flush (drawable);
1624
return err ? -1 : image_ID;
1628
/* Load XWD with pixmap_format 2, pixmap_depth up to 24, bits_per_pixel 24/32 */
1631
load_xwd_f2_d24_b32 (const gchar *filename,
1633
L_XWDFILEHEADER *xwdhdr,
1634
L_XWDCOLOR *xwdcolmap,
1637
register guchar *dest, lsbyte_first;
1638
gint width, height, linepad, i, j, c0, c1, c2, c3;
1639
gint tile_height, scan_lines;
1641
gint red, green, blue, ncols;
1642
gint maxred, maxgreen, maxblue;
1643
gulong redmask, greenmask, bluemask;
1644
guint redshift, greenshift, blueshift;
1645
guchar redmap[256], greenmap[256], bluemap[256];
1647
PIXEL_MAP pixel_map;
1649
gint32 layer_ID, image_ID;
1650
GimpPixelRgn pixel_rgn;
1651
GimpDrawable *drawable;
1654
printf ("load_xwd_f2_d24_b32 (%s)\n", filename);
1657
width = xwdhdr->l_pixmap_width;
1658
height = xwdhdr->l_pixmap_height;
1660
redmask = xwdhdr->l_red_mask;
1661
greenmask = xwdhdr->l_green_mask;
1662
bluemask = xwdhdr->l_blue_mask;
1664
if (redmask == 0) redmask = 0xff0000;
1665
if (greenmask == 0) greenmask = 0x00ff00;
1666
if (bluemask == 0) bluemask = 0x0000ff;
1668
/* How to shift RGB to be right aligned ? */
1669
/* (We rely on the the mask bits are grouped and not mixed) */
1670
redshift = greenshift = blueshift = 0;
1672
while (((1 << redshift) & redmask) == 0) redshift++;
1673
while (((1 << greenshift) & greenmask) == 0) greenshift++;
1674
while (((1 << blueshift) & bluemask) == 0) blueshift++;
1676
/* The bits_per_rgb may not be correct. Use redmask instead */
1678
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
1679
maxred = (1 << maxred) - 1;
1681
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
1682
maxgreen = (1 << maxgreen) - 1;
1684
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
1685
maxblue = (1 << maxblue) - 1;
1687
if (maxred > sizeof (redmap) ||
1688
maxgreen > sizeof (greenmap) ||
1689
maxblue > sizeof (bluemap))
1691
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1692
_("XWD-file %s is corrupt."),
1693
gimp_filename_to_utf8 (filename));
1697
image_ID = create_new_image (filename, width, height, GIMP_RGB,
1698
&layer_ID, &drawable, &pixel_rgn);
1700
tile_height = gimp_tile_height ();
1701
data = g_malloc (tile_height * width * 3);
1703
/* Set map-arrays for red, green, blue */
1704
for (red = 0; red <= maxred; red++)
1705
redmap[red] = (red * 255) / maxred;
1706
for (green = 0; green <= maxgreen; green++)
1707
greenmap[green] = (green * 255) / maxgreen;
1708
for (blue = 0; blue <= maxblue; blue++)
1709
bluemap[blue] = (blue * 255) / maxblue;
1711
ncols = xwdhdr->l_colormap_entries;
1712
if (xwdhdr->l_ncolors < ncols)
1713
ncols = xwdhdr->l_ncolors;
1715
set_pixelmap (ncols, xwdcolmap, &pixel_map);
1717
/* What do we have to consume after a line has finished ? */
1718
linepad = xwdhdr->l_bytes_per_line
1719
- (xwdhdr->l_pixmap_width*xwdhdr->l_bits_per_pixel)/8;
1720
if (linepad < 0) linepad = 0;
1722
lsbyte_first = (xwdhdr->l_byte_order == 0);
1727
if (xwdhdr->l_bits_per_pixel == 32)
1729
for (i = 0; i < height; i++)
1731
for (j = 0; j < width; j++)
1743
pixelval = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
1745
pixelval = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
1747
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
1753
*(dest++) = redmap[(pixelval & redmask) >> redshift];
1754
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
1755
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
1763
for (j = 0; j < linepad; j++)
1767
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
1769
if ((scan_lines == tile_height) || ((i+1) == height))
1771
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1778
else /* 24 bits per pixel */
1780
for (i = 0; i < height; i++)
1782
for (j = 0; j < width; j++)
1793
pixelval = c0 | (c1 << 8) | (c2 << 16);
1795
pixelval = (c0 << 16) | (c1 << 8) | c2;
1797
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
1803
*(dest++) = redmap[(pixelval & redmask) >> redshift];
1804
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
1805
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
1813
for (j = 0; j < linepad; j++)
1817
gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
1819
if ((scan_lines == tile_height) || ((i+1) == height))
1821
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
1832
g_message (_("EOF encountered on reading"));
1834
gimp_drawable_flush (drawable);
1836
return err ? -1 : image_ID;
1840
/* Load XWD with pixmap_format 1, pixmap_depth up to 24, bits_per_pixel 1 */
1843
load_xwd_f1_d24_b1 (const gchar *filename,
1845
L_XWDFILEHEADER *xwdhdr,
1846
L_XWDCOLOR *xwdcolmap,
1849
register guchar *dest, outmask, inmask, do_reverse;
1850
gint width, height, i, j, plane, fromright;
1851
gint tile_height, tile_start, tile_end;
1852
gint indexed, bytes_per_pixel;
1853
gint maxred, maxgreen, maxblue;
1854
gint red, green, blue, ncols, standard_rgb;
1855
glong data_offset, plane_offset, tile_offset;
1856
gulong redmask, greenmask, bluemask;
1857
guint redshift, greenshift, blueshift;
1859
guchar redmap[256], greenmap[256], bluemap[256];
1860
guchar bit_reverse[256];
1861
guchar *xwddata, *xwdin, *data;
1863
PIXEL_MAP pixel_map;
1865
gint32 layer_ID, image_ID;
1866
GimpPixelRgn pixel_rgn;
1867
GimpDrawable *drawable;
1870
printf ("load_xwd_f1_d24_b1 (%s)\n", filename);
1873
xwddata = g_malloc (xwdhdr->l_bytes_per_line);
1874
if (xwddata == NULL)
1877
width = xwdhdr->l_pixmap_width;
1878
height = xwdhdr->l_pixmap_height;
1879
indexed = (xwdhdr->l_pixmap_depth <= 8);
1880
bytes_per_pixel = (indexed ? 1 : 3);
1882
for (j = 0; j < 256; j++) /* Create an array for reversing bits */
1885
for (i = 0; i < 8; i++)
1888
if (j & (1 << i)) inmask |= 1;
1890
bit_reverse[j] = inmask;
1893
redmask = xwdhdr->l_red_mask;
1894
greenmask = xwdhdr->l_green_mask;
1895
bluemask = xwdhdr->l_blue_mask;
1897
if (redmask == 0) redmask = 0xff0000;
1898
if (greenmask == 0) greenmask = 0x00ff00;
1899
if (bluemask == 0) bluemask = 0x0000ff;
1901
standard_rgb = (redmask == 0xff0000) && (greenmask == 0x00ff00)
1902
&& (bluemask == 0x0000ff);
1903
redshift = greenshift = blueshift = 0;
1905
if (!standard_rgb) /* Do we need to re-map the pixel-values ? */
1907
/* How to shift RGB to be right aligned ? */
1908
/* (We rely on the the mask bits are grouped and not mixed) */
1910
while (((1 << redshift) & redmask) == 0) redshift++;
1911
while (((1 << greenshift) & greenmask) == 0) greenshift++;
1912
while (((1 << blueshift) & bluemask) == 0) blueshift++;
1914
/* The bits_per_rgb may not be correct. Use redmask instead */
1916
maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
1917
maxred = (1 << maxred) - 1;
1919
maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
1920
maxgreen = (1 << maxgreen) - 1;
1922
maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
1923
maxblue = (1 << maxblue) - 1;
1925
if (maxred > sizeof (redmap) ||
1926
maxgreen > sizeof (greenmap) ||
1927
maxblue > sizeof (bluemap))
1929
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
1930
_("XWD-file %s is corrupt."),
1931
gimp_filename_to_utf8 (filename));
1935
/* Set map-arrays for red, green, blue */
1936
for (red = 0; red <= maxred; red++)
1937
redmap[red] = (red * 255) / maxred;
1938
for (green = 0; green <= maxgreen; green++)
1939
greenmap[green] = (green * 255) / maxgreen;
1940
for (blue = 0; blue <= maxblue; blue++)
1941
bluemap[blue] = (blue * 255) / maxblue;
1944
image_ID = create_new_image (filename, width, height,
1945
indexed ? GIMP_INDEXED : GIMP_RGB,
1946
&layer_ID, &drawable, &pixel_rgn);
1948
tile_height = gimp_tile_height ();
1949
data = g_malloc (tile_height * width * bytes_per_pixel);
1951
ncols = xwdhdr->l_colormap_entries;
1952
if (xwdhdr->l_ncolors < ncols)
1953
ncols = xwdhdr->l_ncolors;
1958
set_bw_color_table (image_ID);
1960
set_color_table (image_ID, xwdhdr, xwdcolmap);
1964
set_pixelmap (ncols, xwdcolmap, &pixel_map);
1967
do_reverse = !xwdhdr->l_bitmap_bit_order;
1969
/* This is where the image data starts within the file */
1970
data_offset = ftell (ifp);
1972
for (tile_start = 0; tile_start < height; tile_start += tile_height)
1974
memset (data, 0, width*tile_height*bytes_per_pixel);
1976
tile_end = tile_start + tile_height - 1;
1977
if (tile_end >= height)
1978
tile_end = height - 1;
1980
for (plane = 0; plane < xwdhdr->l_pixmap_depth; plane++)
1982
dest = data; /* Position to start of tile within the plane */
1983
plane_offset = data_offset + plane*height*xwdhdr->l_bytes_per_line;
1984
tile_offset = plane_offset + tile_start*xwdhdr->l_bytes_per_line;
1985
fseek (ifp, tile_offset, SEEK_SET);
1987
/* Place the last plane at the least significant bit */
1989
if (indexed) /* Only 1 byte per pixel */
1991
fromright = xwdhdr->l_pixmap_depth-1-plane;
1992
outmask = (1 << fromright);
1994
else /* 3 bytes per pixel */
1996
fromright = xwdhdr->l_pixmap_depth-1-plane;
1997
dest += 2 - fromright/8;
1998
outmask = (1 << (fromright % 8));
2001
for (i = tile_start; i <= tile_end; i++)
2003
if (fread (xwddata,xwdhdr->l_bytes_per_line,1,ifp) != 1)
2010
/* Handle bitmap unit */
2011
if (xwdhdr->l_bitmap_unit == 16)
2013
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
2015
j = xwdhdr->l_bytes_per_line/2;
2018
inmask = xwdin[0]; xwdin[0] = xwdin[1]; xwdin[1] = inmask;
2024
else if (xwdhdr->l_bitmap_unit == 32)
2026
if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
2028
j = xwdhdr->l_bytes_per_line/4;
2031
inmask = xwdin[0]; xwdin[0] = xwdin[3]; xwdin[3] = inmask;
2032
inmask = xwdin[1]; xwdin[1] = xwdin[2]; xwdin[2] = inmask;
2040
for (j = 0; j < width; j++)
2052
dest += bytes_per_pixel;
2059
/* For indexed images, the mapping to colors is done by the color table. */
2060
/* Otherwise we must do the mapping by ourself. */
2064
for (i = tile_start; i <= tile_end; i++)
2066
for (j = 0; j < width; j++)
2068
pixelval = (*dest << 16) | (*(dest+1) << 8) | *(dest+2);
2070
if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2)
2075
else /* We have to map RGB to 0,...,255 */
2077
*(dest++) = redmap[(pixelval & redmask) >> redshift];
2078
*(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
2079
*(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
2085
gimp_progress_update ((gdouble) tile_end / (gdouble) height);
2087
gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, tile_start,
2088
width, tile_end-tile_start+1);
2095
g_message (_("EOF encountered on reading"));
2097
gimp_drawable_flush (drawable);
2099
return err ? -1 : image_ID;
2104
save_index (FILE *ofp,
2109
gint height, width, linepad, tile_height, i, j;
2110
gint ncolors, vclass;
2112
guchar *data, *src, *cmap;
2113
L_XWDFILEHEADER xwdhdr;
2114
L_XWDCOLOR xwdcolmap[256];
2115
GimpPixelRgn pixel_rgn;
2116
GimpDrawable *drawable;
2119
printf ("save_index ()\n");
2122
drawable = gimp_drawable_get (drawable_ID);
2123
width = drawable->width;
2124
height = drawable->height;
2125
tile_height = gimp_tile_height ();
2127
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
2129
/* allocate a buffer for retrieving information from the pixel region */
2130
src = data = g_new (guchar, tile_height * width * drawable->bpp);
2132
linepad = width % 4;
2133
if (linepad) linepad = 4 - linepad;
2135
/* Fill XWD-color map */
2141
for (j = 0; j < ncolors; j++)
2143
xwdcolmap[j].l_pixel = j;
2144
xwdcolmap[j].l_red = (j << 8) | j;
2145
xwdcolmap[j].l_green = (j << 8) | j;
2146
xwdcolmap[j].l_blue = (j << 8) | j;
2147
xwdcolmap[j].l_flags = 7;
2148
xwdcolmap[j].l_pad = 0;
2154
cmap = gimp_image_get_colormap (image_ID, &ncolors);
2156
for (j = 0; j < ncolors; j++)
2158
xwdcolmap[j].l_pixel = j;
2159
xwdcolmap[j].l_red = ((*cmap) << 8) | *cmap; cmap++;
2160
xwdcolmap[j].l_green = ((*cmap) << 8) | *cmap; cmap++;
2161
xwdcolmap[j].l_blue = ((*cmap) << 8) | *cmap; cmap++;
2162
xwdcolmap[j].l_flags = 7;
2163
xwdcolmap[j].l_pad = 0;
2167
/* Fill in the XWD header (header_size is evaluated by write_xwd_hdr ()) */
2168
xwdhdr.l_header_size = 0;
2169
xwdhdr.l_file_version = 7;
2170
xwdhdr.l_pixmap_format = 2;
2171
xwdhdr.l_pixmap_depth = 8;
2172
xwdhdr.l_pixmap_width = width;
2173
xwdhdr.l_pixmap_height = height;
2174
xwdhdr.l_xoffset = 0;
2175
xwdhdr.l_byte_order = 1;
2176
xwdhdr.l_bitmap_unit = 32;
2177
xwdhdr.l_bitmap_bit_order = 1;
2178
xwdhdr.l_bitmap_pad = 32;
2179
xwdhdr.l_bits_per_pixel = 8;
2180
xwdhdr.l_bytes_per_line = width + linepad;
2181
xwdhdr.l_visual_class = vclass;
2182
xwdhdr.l_red_mask = 0x000000;
2183
xwdhdr.l_green_mask = 0x000000;
2184
xwdhdr.l_blue_mask = 0x000000;
2185
xwdhdr.l_bits_per_rgb = 8;
2186
xwdhdr.l_colormap_entries = ncolors;
2187
xwdhdr.l_ncolors = ncolors;
2188
xwdhdr.l_window_width = width;
2189
xwdhdr.l_window_height = height;
2190
xwdhdr.l_window_x = 64;
2191
xwdhdr.l_window_y = 64;
2192
xwdhdr.l_window_bdrwidth = 0;
2194
write_xwd_header (ofp, &xwdhdr);
2195
write_xwd_cols (ofp, &xwdhdr, xwdcolmap);
2197
for (i = 0; i < height; i++)
2199
if ((i % tile_height) == 0) /* Get more data */
2201
gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
2203
gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, i, width, scan_lines);
2207
fwrite (src, width, 1, ofp);
2210
fwrite ((char *)&tmp, linepad, 1, ofp);
2215
gimp_progress_update ((gdouble) i / (gdouble) height);
2220
gimp_drawable_detach (drawable);
2224
g_message (_("Error during writing indexed/gray image"));
2233
save_rgb (FILE *ofp,
2237
gint height, width, linepad, tile_height, i;
2240
L_XWDFILEHEADER xwdhdr;
2241
GimpPixelRgn pixel_rgn;
2242
GimpDrawable *drawable;
2245
printf ("save_rgb ()\n");
2248
drawable = gimp_drawable_get (drawable_ID);
2249
width = drawable->width;
2250
height = drawable->height;
2251
tile_height = gimp_tile_height ();
2253
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
2255
/* allocate a buffer for retrieving information from the pixel region */
2256
src = data = g_new (guchar, tile_height * width * drawable->bpp);
2258
linepad = (width * 3) % 4;
2260
linepad = 4 - linepad;
2262
/* Fill in the XWD header (header_size is evaluated by write_xwd_hdr ()) */
2263
xwdhdr.l_header_size = 0;
2264
xwdhdr.l_file_version = 7;
2265
xwdhdr.l_pixmap_format = 2;
2266
xwdhdr.l_pixmap_depth = 24;
2267
xwdhdr.l_pixmap_width = width;
2268
xwdhdr.l_pixmap_height = height;
2269
xwdhdr.l_xoffset = 0;
2270
xwdhdr.l_byte_order = 1;
2272
xwdhdr.l_bitmap_unit = 32;
2273
xwdhdr.l_bitmap_bit_order = 1;
2274
xwdhdr.l_bitmap_pad = 32;
2275
xwdhdr.l_bits_per_pixel = 24;
2277
xwdhdr.l_bytes_per_line = width * 3 + linepad;
2278
xwdhdr.l_visual_class = 5;
2279
xwdhdr.l_red_mask = 0xff0000;
2280
xwdhdr.l_green_mask = 0x00ff00;
2281
xwdhdr.l_blue_mask = 0x0000ff;
2282
xwdhdr.l_bits_per_rgb = 8;
2283
xwdhdr.l_colormap_entries = 0;
2284
xwdhdr.l_ncolors = 0;
2285
xwdhdr.l_window_width = width;
2286
xwdhdr.l_window_height = height;
2287
xwdhdr.l_window_x = 64;
2288
xwdhdr.l_window_y = 64;
2289
xwdhdr.l_window_bdrwidth = 0;
2291
write_xwd_header (ofp, &xwdhdr);
2293
for (i = 0; i < height; i++)
2295
if ((i % tile_height) == 0) /* Get more data */
2297
gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
2299
gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, i, width, scan_lines);
2303
fwrite (src, width * 3, 1, ofp);
2306
fwrite ((char *)&tmp, linepad, 1, ofp);
2311
gimp_progress_update ((gdouble) i / (gdouble) height);
2316
gimp_drawable_detach (drawable);
2320
g_message (_("Error during writing rgb image"));