~ubuntu-branches/ubuntu/quantal/gimp/quantal-security

« back to all changes in this revision

Viewing changes to .pc/CVE-2013-1978.patch/plug-ins/common/file-xwd.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2013-12-06 13:27:24 UTC
  • Revision ID: package-import@ubuntu.com-20131206132724-up3ugxo6cflelzt8
Tags: 2.8.2-1ubuntu1.2
* SECURITY UPDATE: denial of service and possible code execution via
  huge color maps in xwd plugin
  - debian/patches/CVE-2013-1913.patch: limit number of color map entries
    in plug-ins/common/file-xwd.c.
  - CVE-2013-1913
* SECURITY UPDATE: denial of service and possible code execution via
  large number of color map entries in xwd plugin
  - debian/patches/CVE-2013-1978.patch: validate number of color map
    entries in plug-ins/common/file-xwd.c
  - CVE-2013-1978

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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)
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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/>.
 
18
 *
 
19
 */
 
20
 
 
21
/*
 
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
 *    ---------------------------------------------
 
28
 *          0       |        1     |       1
 
29
 *          1       |    1,...,24  |       1
 
30
 *          2       |        1     |       1
 
31
 *          2       |    1,...,8   |       8
 
32
 *          2       |    1,...,16  |      16
 
33
 *          2       |    1,...,24  |      24
 
34
 *          2       |    1,...,24  |      32
 
35
 */
 
36
/* Event history:
 
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
 
49
 */
 
50
 
 
51
#include "config.h"
 
52
 
 
53
#include <errno.h>
 
54
#include <string.h>
 
55
 
 
56
#include <glib/gstdio.h>
 
57
 
 
58
#include <libgimp/gimp.h>
 
59
#include <libgimp/gimpui.h>
 
60
 
 
61
#include "libgimp/stdplugins-intl.h"
 
62
 
 
63
 
 
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"
 
68
 
 
69
 
 
70
typedef gulong  L_CARD32;
 
71
typedef gushort L_CARD16;
 
72
typedef guchar  L_CARD8;
 
73
 
 
74
typedef struct
 
75
{
 
76
  L_CARD32 l_header_size;    /* Header size */
 
77
 
 
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 */
 
85
 
 
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 */
 
90
 
 
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 */
 
104
} L_XWDFILEHEADER;
 
105
 
 
106
typedef struct
 
107
{
 
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;
 
111
} L_XWDCOLOR;
 
112
 
 
113
 
 
114
/* Some structures for mapping up to 32bit-pixel */
 
115
/* values which are kept in the XWD-Colormap */
 
116
 
 
117
#define MAPPERBITS 12
 
118
#define MAPPERMASK ((1 << MAPPERBITS)-1)
 
119
 
 
120
typedef struct
 
121
{
 
122
  L_CARD32 pixel_val;
 
123
  guchar   red;
 
124
  guchar   green;
 
125
  guchar   blue;
 
126
} PMAP;
 
127
 
 
128
typedef struct
 
129
{
 
130
  gint   npixel; /* Number of pixel values in map */
 
131
  guchar pixel_in_map[1 << MAPPERBITS];
 
132
  PMAP   pmap[256];
 
133
} PIXEL_MAP;
 
134
 
 
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 */
 
137
 
 
138
/* Declare some local functions.
 
139
 */
 
140
static void   query               (void);
 
141
static void   run                 (const gchar      *name,
 
142
                                   gint              nparams,
 
143
                                   const GimpParam  *param,
 
144
                                   gint             *nreturn_vals,
 
145
                                   GimpParam       **return_vals);
 
146
 
 
147
static gint32 load_image          (const gchar      *filename,
 
148
                                   GError          **error);
 
149
static gint   save_image          (const gchar      *filename,
 
150
                                   gint32            image_ID,
 
151
                                   gint32            drawable_ID,
 
152
                                   GError          **error);
 
153
static gint32 create_new_image    (const gchar      *filename,
 
154
                                   guint             width,
 
155
                                   guint             height,
 
156
                                   GimpImageBaseType type,
 
157
                                   gint32           *layer_ID,
 
158
                                   GimpDrawable    **drawable,
 
159
                                   GimpPixelRgn     *pixel_rgn);
 
160
 
 
161
static int      set_pixelmap      (gint,
 
162
                                   L_XWDCOLOR *,
 
163
                                   PIXEL_MAP *);
 
164
static gboolean get_pixelmap      (L_CARD32,
 
165
                                   PIXEL_MAP *,
 
166
                                   guchar *,
 
167
                                   guchar *,
 
168
                                   guchar *);
 
169
static void   set_bw_color_table  (gint32);
 
170
static void   set_color_table     (gint32,
 
171
                                   L_XWDFILEHEADER *,
 
172
                                   L_XWDCOLOR *);
 
173
 
 
174
static gint32 load_xwd_f2_d1_b1   (const gchar *,
 
175
                                   FILE *,
 
176
                                   L_XWDFILEHEADER *,
 
177
                                   L_XWDCOLOR *);
 
178
static gint32 load_xwd_f2_d8_b8   (const gchar *,
 
179
                                   FILE *,
 
180
                                   L_XWDFILEHEADER *,
 
181
                                   L_XWDCOLOR *);
 
182
static gint32 load_xwd_f2_d16_b16 (const gchar *,
 
183
                                   FILE *,
 
184
                                   L_XWDFILEHEADER *,
 
185
                                   L_XWDCOLOR *);
 
186
static gint32 load_xwd_f2_d24_b32 (const gchar *,
 
187
                                   FILE *,
 
188
                                   L_XWDFILEHEADER *,
 
189
                                   L_XWDCOLOR *,
 
190
                                   GError **);
 
191
static gint32 load_xwd_f1_d24_b1  (const gchar *,
 
192
                                   FILE *,
 
193
                                   L_XWDFILEHEADER *,
 
194
                                   L_XWDCOLOR *,
 
195
                                   GError **);
 
196
 
 
197
static L_CARD32 read_card32  (FILE *,
 
198
                              gint *);
 
199
static L_CARD16 read_card16  (FILE *,
 
200
                              gint *);
 
201
static L_CARD8  read_card8   (FILE *,
 
202
                              gint *);
 
203
 
 
204
static void write_card32     (FILE *,
 
205
                              L_CARD32);
 
206
static void write_card16     (FILE *,
 
207
                              L_CARD32);
 
208
static void write_card8      (FILE *,
 
209
                              L_CARD32);
 
210
 
 
211
static void read_xwd_header  (FILE *,
 
212
                              L_XWDFILEHEADER *);
 
213
static void write_xwd_header (FILE *,
 
214
                              L_XWDFILEHEADER *);
 
215
static void read_xwd_cols    (FILE *,
 
216
                              L_XWDFILEHEADER *,
 
217
                              L_XWDCOLOR *);
 
218
static void write_xwd_cols   (FILE *,
 
219
                              L_XWDFILEHEADER *,
 
220
                              L_XWDCOLOR *);
 
221
 
 
222
static gint save_index       (FILE *,
 
223
                              gint32,
 
224
                              gint32,
 
225
                              gint);
 
226
static gint save_rgb         (FILE *,
 
227
                              gint32,
 
228
                              gint32);
 
229
 
 
230
 
 
231
const GimpPlugInInfo PLUG_IN_INFO =
 
232
{
 
233
  NULL,  /* init_proc  */
 
234
  NULL,  /* quit_proc  */
 
235
  query, /* query_proc */
 
236
  run,   /* run_proc   */
 
237
};
 
238
 
 
239
 
 
240
/* The run mode */
 
241
static GimpRunMode l_run_mode;
 
242
 
 
243
 
 
244
MAIN ()
 
245
 
 
246
 
 
247
static void
 
248
query (void)
 
249
 
 
250
{
 
251
  static const GimpParamDef load_args[] =
 
252
  {
 
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" }
 
256
  };
 
257
 
 
258
  static const GimpParamDef load_return_vals[] =
 
259
  {
 
260
    { GIMP_PDB_IMAGE,  "image",        "Output image" }
 
261
  };
 
262
 
 
263
  static const GimpParamDef save_args[] =
 
264
  {
 
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" }
 
270
  };
 
271
 
 
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",
 
279
                          "1996",
 
280
                          N_("X window dump"),
 
281
                          NULL,
 
282
                          GIMP_PLUGIN,
 
283
                          G_N_ELEMENTS (load_args),
 
284
                          G_N_ELEMENTS (load_return_vals),
 
285
                          load_args, load_return_vals);
 
286
 
 
287
  gimp_register_file_handler_mime (LOAD_PROC, "image/x-xwindowdump");
 
288
  gimp_register_magic_load_handler (LOAD_PROC,
 
289
                                    "xwd",
 
290
                                    "",
 
291
                                    "4,long,0x00000007");
 
292
 
 
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",
 
299
                          "1996",
 
300
                          N_("X window dump"),
 
301
                          "RGB, GRAY, INDEXED",
 
302
                          GIMP_PLUGIN,
 
303
                          G_N_ELEMENTS (save_args), 0,
 
304
                          save_args, NULL);
 
305
 
 
306
  gimp_register_file_handler_mime (SAVE_PROC, "image/x-xwindowdump");
 
307
  gimp_register_save_handler (SAVE_PROC, "xwd", "");
 
308
}
 
309
 
 
310
 
 
311
static void
 
312
run (const gchar      *name,
 
313
     gint              nparams,
 
314
     const GimpParam  *param,
 
315
     gint             *nreturn_vals,
 
316
     GimpParam       **return_vals)
 
317
{
 
318
  static GimpParam   values[2];
 
319
  GimpRunMode        run_mode;
 
320
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
 
321
  gint32             image_ID;
 
322
  gint32             drawable_ID;
 
323
  GimpExportReturn   export = GIMP_EXPORT_CANCEL;
 
324
  GError            *error  = NULL;
 
325
 
 
326
  l_run_mode = run_mode = param[0].data.d_int32;
 
327
 
 
328
  INIT_I18N ();
 
329
 
 
330
  *nreturn_vals = 1;
 
331
  *return_vals  = values;
 
332
 
 
333
  values[0].type          = GIMP_PDB_STATUS;
 
334
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
 
335
 
 
336
  if (strcmp (name, LOAD_PROC) == 0)
 
337
    {
 
338
      image_ID = load_image (param[1].data.d_string, &error);
 
339
 
 
340
      if (image_ID != -1)
 
341
        {
 
342
          *nreturn_vals = 2;
 
343
          values[1].type         = GIMP_PDB_IMAGE;
 
344
          values[1].data.d_image = image_ID;
 
345
        }
 
346
      else
 
347
        {
 
348
          status = GIMP_PDB_EXECUTION_ERROR;
 
349
        }
 
350
    }
 
351
  else if (strcmp (name, SAVE_PROC) == 0)
 
352
    {
 
353
      image_ID    = param[1].data.d_int32;
 
354
      drawable_ID = param[2].data.d_int32;
 
355
 
 
356
      /*  eventually export the image */
 
357
      switch (run_mode)
 
358
        {
 
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)
 
367
            {
 
368
              values[0].data.d_status = GIMP_PDB_CANCEL;
 
369
              return;
 
370
            }
 
371
          break;
 
372
 
 
373
        default:
 
374
          break;
 
375
        }
 
376
 
 
377
      switch (run_mode)
 
378
        {
 
379
        case GIMP_RUN_INTERACTIVE:
 
380
        case GIMP_RUN_WITH_LAST_VALS:
 
381
          /* No additional data to retrieve */
 
382
          break;
 
383
 
 
384
        case GIMP_RUN_NONINTERACTIVE:
 
385
          /*  Make sure all the arguments are there!  */
 
386
          if (nparams != 5)
 
387
            status = GIMP_PDB_CALLING_ERROR;
 
388
          break;
 
389
 
 
390
        default:
 
391
          break;
 
392
        }
 
393
 
 
394
      if (status == GIMP_PDB_SUCCESS)
 
395
        {
 
396
          if (! save_image (param[3].data.d_string, image_ID, drawable_ID,
 
397
                            &error))
 
398
            {
 
399
              status = GIMP_PDB_EXECUTION_ERROR;
 
400
            }
 
401
        }
 
402
 
 
403
      if (export == GIMP_EXPORT_EXPORT)
 
404
        gimp_image_delete (image_ID);
 
405
    }
 
406
  else
 
407
    {
 
408
      status = GIMP_PDB_CANCEL;
 
409
    }
 
410
 
 
411
  if (status != GIMP_PDB_SUCCESS && error)
 
412
    {
 
413
      *nreturn_vals = 2;
 
414
      values[1].type          = GIMP_PDB_STRING;
 
415
      values[1].data.d_string = error->message;
 
416
    }
 
417
 
 
418
  values[0].data.d_status = status;
 
419
}
 
420
 
 
421
static gint32
 
422
load_image (const gchar  *filename,
 
423
            GError      **error)
 
424
{
 
425
  FILE            *ifp;
 
426
  gint             depth, bpp;
 
427
  gint32           image_ID;
 
428
  L_XWDFILEHEADER  xwdhdr;
 
429
  L_XWDCOLOR      *xwdcolmap = NULL;
 
430
 
 
431
  ifp = g_fopen (filename, "rb");
 
432
  if (!ifp)
 
433
    {
 
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));
 
437
      return -1;
 
438
    }
 
439
 
 
440
  read_xwd_header (ifp, &xwdhdr);
 
441
  if (xwdhdr.l_file_version != 7)
 
442
    {
 
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));
 
446
      fclose (ifp);
 
447
      return -1;
 
448
    }
 
449
 
 
450
#ifdef XWD_COL_WAIT_DEBUG
 
451
  {
 
452
    int k = 1;
 
453
 
 
454
    while (k)
 
455
      k = k;
 
456
  }
 
457
#endif
 
458
 
 
459
  /* Position to start of XWDColor structures */
 
460
  fseek (ifp, (long)xwdhdr.l_header_size, SEEK_SET);
 
461
 
 
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)
 
465
    {
 
466
      g_message (_("'%s':\nIllegal number of colormap entries: %ld"),
 
467
                 gimp_filename_to_utf8 (filename),
 
468
                 (long)xwdhdr.l_colormap_entries);
 
469
      fclose (ifp);
 
470
      return -1;
 
471
    }
 
472
 
 
473
  if (xwdhdr.l_colormap_entries > 0)
 
474
    {
 
475
      xwdcolmap = g_new (L_XWDCOLOR, xwdhdr.l_colormap_entries);
 
476
 
 
477
      read_xwd_cols (ifp, &xwdhdr, xwdcolmap);
 
478
 
 
479
#ifdef XWD_COL_DEBUG
 
480
      {
 
481
        int j;
 
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);
 
488
      }
 
489
#endif
 
490
 
 
491
      if (xwdhdr.l_file_version != 7)
 
492
        {
 
493
          g_message (_("Can't read color entries"));
 
494
          g_free (xwdcolmap);
 
495
          fclose (ifp);
 
496
          return (-1);
 
497
        }
 
498
    }
 
499
 
 
500
  if (xwdhdr.l_pixmap_width <= 0)
 
501
    {
 
502
      g_message (_("'%s':\nNo image width specified"),
 
503
                 gimp_filename_to_utf8 (filename));
 
504
      g_free (xwdcolmap);
 
505
      fclose (ifp);
 
506
      return (-1);
 
507
    }
 
508
 
 
509
  if (xwdhdr.l_pixmap_width > GIMP_MAX_IMAGE_SIZE
 
510
      || xwdhdr.l_bytes_per_line > GIMP_MAX_IMAGE_SIZE * 3)
 
511
    {
 
512
      g_message (_("'%s':\nImage width is larger than GIMP can handle"),
 
513
                 gimp_filename_to_utf8 (filename));
 
514
      g_free (xwdcolmap);
 
515
      fclose (ifp);
 
516
      return (-1);
 
517
    }
 
518
 
 
519
  if (xwdhdr.l_pixmap_height <= 0)
 
520
    {
 
521
      g_message (_("'%s':\nNo image height specified"),
 
522
                 gimp_filename_to_utf8 (filename));
 
523
      g_free (xwdcolmap);
 
524
      fclose (ifp);
 
525
      return (-1);
 
526
    }
 
527
 
 
528
  if (xwdhdr.l_pixmap_height > GIMP_MAX_IMAGE_SIZE)
 
529
    {
 
530
      g_message (_("'%s':\nImage height is larger than GIMP can handle"),
 
531
                 gimp_filename_to_utf8 (filename));
 
532
      g_free (xwdcolmap);
 
533
      fclose (ifp);
 
534
      return (-1);
 
535
    }
 
536
 
 
537
  gimp_progress_init_printf (_("Opening '%s'"),
 
538
                             gimp_filename_to_utf8 (filename));
 
539
 
 
540
  depth = xwdhdr.l_pixmap_depth;
 
541
  bpp   = xwdhdr.l_bits_per_pixel;
 
542
 
 
543
  image_ID = -1;
 
544
  switch (xwdhdr.l_pixmap_format)
 
545
    {
 
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);
 
550
        }
 
551
      break;
 
552
 
 
553
    case 1:    /* Single plane pixmap */
 
554
      if ((depth <= 24) && (bpp == 1))
 
555
        {
 
556
          image_ID = load_xwd_f1_d24_b1 (filename, ifp, &xwdhdr, xwdcolmap,
 
557
                                         error);
 
558
        }
 
559
      break;
 
560
 
 
561
    case 2:    /* Multiplane pixmaps */
 
562
      if ((depth == 1) && (bpp == 1))
 
563
        {
 
564
          image_ID = load_xwd_f2_d1_b1 (filename, ifp, &xwdhdr, xwdcolmap);
 
565
        }
 
566
      else if ((depth <= 8) && (bpp == 8))
 
567
        {
 
568
          image_ID = load_xwd_f2_d8_b8 (filename, ifp, &xwdhdr, xwdcolmap);
 
569
        }
 
570
      else if ((depth <= 16) && (bpp == 16))
 
571
        {
 
572
          image_ID = load_xwd_f2_d16_b16 (filename, ifp, &xwdhdr, xwdcolmap);
 
573
        }
 
574
      else if ((depth <= 24) && ((bpp == 24) || (bpp == 32)))
 
575
        {
 
576
          image_ID = load_xwd_f2_d24_b32 (filename, ifp, &xwdhdr, xwdcolmap,
 
577
                                          error);
 
578
        }
 
579
      break;
 
580
    }
 
581
  gimp_progress_update (1.0);
 
582
 
 
583
  fclose (ifp);
 
584
 
 
585
  if (xwdcolmap)
 
586
    g_free (xwdcolmap);
 
587
 
 
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);
 
594
 
 
595
  return image_ID;
 
596
}
 
597
 
 
598
static gint
 
599
save_image (const gchar  *filename,
 
600
            gint32        image_ID,
 
601
            gint32        drawable_ID,
 
602
            GError      **error)
 
603
{
 
604
  FILE          *ofp;
 
605
  GimpImageType  drawable_type;
 
606
  gint           retval;
 
607
 
 
608
  drawable_type = gimp_drawable_type (drawable_ID);
 
609
 
 
610
  /*  Make sure we're not saving an image with an alpha channel  */
 
611
  if (gimp_drawable_has_alpha (drawable_ID))
 
612
    {
 
613
      g_message (_("Cannot save images with alpha channels."));
 
614
      return FALSE;
 
615
    }
 
616
 
 
617
  switch (drawable_type)
 
618
    {
 
619
    case GIMP_INDEXED_IMAGE:
 
620
    case GIMP_GRAY_IMAGE:
 
621
    case GIMP_RGB_IMAGE:
 
622
      break;
 
623
    default:
 
624
      g_message (_("Cannot operate on unknown image types."));
 
625
      return FALSE;
 
626
      break;
 
627
    }
 
628
 
 
629
  /* Open the output file. */
 
630
  ofp = g_fopen (filename, "wb");
 
631
  if (! ofp)
 
632
    {
 
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));
 
636
      return FALSE;
 
637
    }
 
638
 
 
639
  gimp_progress_init_printf (_("Saving '%s'"),
 
640
                             gimp_filename_to_utf8 (filename));
 
641
 
 
642
  switch (drawable_type)
 
643
    {
 
644
    case GIMP_INDEXED_IMAGE:
 
645
      retval = save_index (ofp, image_ID, drawable_ID, 0);
 
646
      break;
 
647
    case GIMP_GRAY_IMAGE:
 
648
      retval = save_index (ofp, image_ID, drawable_ID, 1);
 
649
      break;
 
650
    case GIMP_RGB_IMAGE:
 
651
      retval = save_rgb (ofp, image_ID, drawable_ID);
 
652
      break;
 
653
    default:
 
654
      retval = FALSE;
 
655
    }
 
656
 
 
657
  gimp_progress_update (1.0);
 
658
 
 
659
  fclose (ofp);
 
660
 
 
661
  return retval;
 
662
}
 
663
 
 
664
 
 
665
static L_CARD32
 
666
read_card32 (FILE *ifp,
 
667
             int  *err)
 
668
 
 
669
{
 
670
  L_CARD32 c;
 
671
 
 
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)));
 
676
 
 
677
  *err = (*err < 0);
 
678
 
 
679
  return c;
 
680
}
 
681
 
 
682
 
 
683
static L_CARD16
 
684
read_card16 (FILE *ifp,
 
685
             int  *err)
 
686
 
 
687
{
 
688
  L_CARD16 c;
 
689
 
 
690
  c =  (((L_CARD16) (getc (ifp))) << 8);
 
691
  c |= ((L_CARD16) (*err = getc (ifp)));
 
692
 
 
693
  *err = (*err < 0);
 
694
 
 
695
  return c;
 
696
}
 
697
 
 
698
 
 
699
static L_CARD8
 
700
read_card8 (FILE *ifp,
 
701
            int  *err)
 
702
{
 
703
  L_CARD8 c;
 
704
 
 
705
  c = ((L_CARD8) (*err = getc (ifp)));
 
706
 
 
707
  *err = (*err < 0);
 
708
 
 
709
  return c;
 
710
}
 
711
 
 
712
static void
 
713
write_card32 (FILE     *ofp,
 
714
              L_CARD32  c)
 
715
{
 
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);
 
720
}
 
721
 
 
722
 
 
723
static void
 
724
write_card16 (FILE     *ofp,
 
725
              L_CARD32  c)
 
726
{
 
727
  putc ((int) ((c >> 8) & 0xff), ofp);
 
728
  putc ((int) ((c) & 0xff), ofp);
 
729
}
 
730
 
 
731
 
 
732
static void
 
733
write_card8 (FILE     *ofp,
 
734
             L_CARD32  c)
 
735
{
 
736
  putc ((int) ((c) & 0xff), ofp);
 
737
}
 
738
 
 
739
 
 
740
static void
 
741
read_xwd_header (FILE            *ifp,
 
742
                 L_XWDFILEHEADER *xwdhdr)
 
743
{
 
744
  gint      j, err;
 
745
  L_CARD32 *cp;
 
746
 
 
747
  cp = (L_CARD32 *) xwdhdr;
 
748
 
 
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++)
 
751
    {
 
752
      *(cp++) = read_card32 (ifp, &err);
 
753
 
 
754
      if (err)
 
755
        break;
 
756
    }
 
757
 
 
758
  if (err)
 
759
    xwdhdr->l_file_version = 0;  /* Not a valid XWD-file */
 
760
}
 
761
 
 
762
 
 
763
/* Write out an XWD-fileheader. The header size is calculated here */
 
764
static void
 
765
write_xwd_header (FILE            *ofp,
 
766
                  L_XWDFILEHEADER *xwdhdr)
 
767
 
 
768
{
 
769
  gint      j, hdrpad, hdr_entries;
 
770
  L_CARD32 *cp;
 
771
 
 
772
  hdrpad = XWDHDR_PAD;
 
773
  hdr_entries = sizeof (L_XWDFILEHEADER) / sizeof(xwdhdr->l_file_version);
 
774
  xwdhdr->l_header_size = hdr_entries * 4 + hdrpad;
 
775
 
 
776
  cp = (L_CARD32 *) xwdhdr;
 
777
 
 
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++)
 
780
    {
 
781
      write_card32 (ofp, *(cp++));
 
782
    }
 
783
 
 
784
  /* Add padding bytes after XWD header */
 
785
  for (j = 0; j < hdrpad; j++)
 
786
    write_card8 (ofp, (L_CARD32) 0);
 
787
}
 
788
 
 
789
 
 
790
static void
 
791
read_xwd_cols (FILE            *ifp,
 
792
               L_XWDFILEHEADER *xwdhdr,
 
793
               L_XWDCOLOR      *colormap)
 
794
{
 
795
  gint  j, err = 0;
 
796
  gint  flag_is_bad, index_is_bad;
 
797
  gint  indexed = (xwdhdr->l_pixmap_depth <= 8);
 
798
  glong colmappos = ftell (ifp);
 
799
 
 
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++)
 
803
    {
 
804
      colormap[j].l_pixel = read_card32 (ifp, &err);
 
805
 
 
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);
 
809
 
 
810
      colormap[j].l_flags = read_card8 (ifp, &err);
 
811
      colormap[j].l_pad   = read_card8 (ifp, &err);
 
812
 
 
813
      if (indexed && (colormap[j].l_pixel > 255))
 
814
        index_is_bad++;
 
815
 
 
816
      if (err)
 
817
        break;
 
818
    }
 
819
 
 
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)))
 
823
    return;
 
824
 
 
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++)
 
829
    {
 
830
      colormap[j].l_pixel = read_card32 (ifp, &err);
 
831
 
 
832
      read_card32 (ifp, &err);  /* Empty bytes on Alpha OSF */
 
833
 
 
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);
 
837
 
 
838
      colormap[j].l_flags = read_card8 (ifp, &err);
 
839
      colormap[j].l_pad   = read_card8 (ifp, &err);
 
840
 
 
841
      if (indexed && (colormap[j].l_pixel > 255))
 
842
        index_is_bad++;
 
843
 
 
844
      if (err)
 
845
        break;
 
846
    }
 
847
 
 
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)))
 
851
    return;
 
852
 
 
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++)
 
857
    {
 
858
      colormap[j].l_pixel = read_card32 (ifp, &err);
 
859
 
 
860
      read_card16 (ifp, &err);  /* Empty bytes (from where ?) */
 
861
 
 
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);
 
865
 
 
866
      colormap[j].l_flags = read_card8 (ifp, &err);
 
867
      colormap[j].l_pad   = read_card8 (ifp, &err);
 
868
 
 
869
      /* if ((colormap[j].l_flags == 0) || (colormap[j].l_flags > 7))
 
870
         flag_is_bad++; */
 
871
 
 
872
      if (indexed && (colormap[j].l_pixel > 255))
 
873
        index_is_bad++;
 
874
 
 
875
      if (err)
 
876
        break;
 
877
    }
 
878
 
 
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)))
 
882
    return;
 
883
 
 
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++)
 
888
    {
 
889
      read_card32 (ifp, &err);
 
890
      colormap[j].l_pixel = read_card32 (ifp, &err);
 
891
 
 
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);
 
898
 
 
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);
 
904
 
 
905
      if (indexed && (colormap[j].l_pixel > 255))
 
906
        index_is_bad++;
 
907
 
 
908
       if (err)
 
909
         break;
 
910
    }
 
911
 
 
912
  if (flag_is_bad || index_is_bad)
 
913
    {
 
914
      printf ("xwd: Warning. Error in XWD-color-structure (");
 
915
 
 
916
      if (flag_is_bad) printf ("flag");
 
917
      if (index_is_bad) printf ("index");
 
918
 
 
919
      printf (")\n");
 
920
    }
 
921
 
 
922
  if (err)
 
923
    xwdhdr->l_file_version = 0;  /* Not a valid XWD-file */
 
924
}
 
925
 
 
926
 
 
927
static void
 
928
write_xwd_cols (FILE            *ofp,
 
929
                L_XWDFILEHEADER *xwdhdr,
 
930
                L_XWDCOLOR      *colormap)
 
931
 
 
932
{
 
933
  int j;
 
934
 
 
935
  for (j = 0; j < xwdhdr->l_colormap_entries; j++)
 
936
    {
 
937
#ifdef CRAY
 
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);
 
950
#else
 
951
#ifdef __alpha
 
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);
 
959
#else
 
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);
 
966
#endif
 
967
#endif
 
968
    }
 
969
}
 
970
 
 
971
 
 
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) */
 
974
 
 
975
static gint
 
976
set_pixelmap (int         ncols,
 
977
              L_XWDCOLOR *xwdcol,
 
978
              PIXEL_MAP  *pixelmap)
 
979
 
 
980
{
 
981
  gint     i, j, k, maxcols;
 
982
  L_CARD32 pixel_val;
 
983
 
 
984
  memset ((gchar *) pixelmap, 0, sizeof (PIXEL_MAP));
 
985
 
 
986
  maxcols = 0;
 
987
 
 
988
  for (j = 0; j < ncols; j++) /* For each entry of the XWD colormap */
 
989
    {
 
990
      pixel_val = xwdcol[j].l_pixel;
 
991
      for (k = 0; k < maxcols; k++)  /* Where to insert in list ? */
 
992
        {
 
993
          if (pixel_val <= pixelmap->pmap[k].pixel_val)
 
994
            break;
 
995
        }
 
996
      if ((k < maxcols) && (pixel_val == pixelmap->pmap[k].pixel_val))
 
997
        break;   /* It was already in list */
 
998
 
 
999
      if (k >= 256)
 
1000
        break;
 
1001
 
 
1002
      if (k < maxcols)   /* Must move entries to the back ? */
 
1003
        {
 
1004
          for (i = maxcols-1; i >= k; i--)
 
1005
            memcpy ((char *)&(pixelmap->pmap[i+1]),(char *)&(pixelmap->pmap[i]),
 
1006
                    sizeof (PMAP));
 
1007
        }
 
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;
 
1013
      maxcols++;
 
1014
    }
 
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]);
 
1025
#endif
 
1026
 
 
1027
  return pixelmap->npixel;
 
1028
}
 
1029
 
 
1030
 
 
1031
/* Search a pixel value in the pixel map. Returns FALSE if the */
 
1032
/* pixelval was not found in map. Returns TRUE if found. */
 
1033
 
 
1034
static gboolean
 
1035
get_pixelmap (L_CARD32   pixelval,
 
1036
              PIXEL_MAP *pixelmap,
 
1037
              guchar    *red,
 
1038
              guchar    *green,
 
1039
              guchar    *blue)
 
1040
 
 
1041
{
 
1042
  register PMAP *low, *high, *middle;
 
1043
 
 
1044
  if (pixelmap->npixel == 0)
 
1045
    return FALSE;
 
1046
 
 
1047
  if (!(pixelmap->pixel_in_map[pixelval & MAPPERMASK]))
 
1048
    return FALSE;
 
1049
 
 
1050
  low =  &(pixelmap->pmap[0]);
 
1051
  high = &(pixelmap->pmap[pixelmap->npixel-1]);
 
1052
 
 
1053
  /* Do a binary search on the array */
 
1054
  while (low < high)
 
1055
    {
 
1056
      middle = low + ((high - low)/2);
 
1057
      if (pixelval <= middle->pixel_val)
 
1058
        high = middle;
 
1059
      else
 
1060
        low = middle+1;
 
1061
    }
 
1062
 
 
1063
  if (pixelval == low->pixel_val)
 
1064
    {
 
1065
      *red = low->red; *green = low->green; *blue = low->blue;
 
1066
      return TRUE;
 
1067
    }
 
1068
 
 
1069
  return FALSE;
 
1070
}
 
1071
 
 
1072
 
 
1073
static void
 
1074
set_bw_color_table (gint32 image_ID)
 
1075
{
 
1076
  static guchar BWColorMap[2*3] = { 255, 255, 255, 0, 0, 0 };
 
1077
 
 
1078
#ifdef XWD_COL_DEBUG
 
1079
  printf ("Set GIMP b/w-colortable:\n");
 
1080
#endif
 
1081
 
 
1082
  gimp_image_set_colormap (image_ID, BWColorMap, 2);
 
1083
}
 
1084
 
 
1085
 
 
1086
/* Initialize an 8-bit colortable from the mask-values of the XWD-header */
 
1087
static void
 
1088
init_color_table256 (L_XWDFILEHEADER *xwdhdr,
 
1089
                     guchar          *ColorMap)
 
1090
 
 
1091
{
 
1092
  gint i, j, k, cuind;
 
1093
  gint redshift, greenshift, blueshift;
 
1094
  gint maxred, maxgreen, maxblue;
 
1095
 
 
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.
 
1100
   */
 
1101
  redshift = greenshift = blueshift = 0;
 
1102
  if ((maxred = xwdhdr->l_red_mask) == 0)
 
1103
    return;
 
1104
 
 
1105
  /* Shift the redmask to the rightmost bit position to get
 
1106
   * maximum value for red.
 
1107
   */
 
1108
  while ((maxred & 1) == 0)
 
1109
    {
 
1110
      redshift++;
 
1111
      maxred >>= 1;
 
1112
    }
 
1113
 
 
1114
  if ((maxgreen = xwdhdr->l_green_mask) == 0)
 
1115
    return;
 
1116
 
 
1117
  while ((maxgreen & 1) == 0)
 
1118
    {
 
1119
      greenshift++;
 
1120
      maxgreen >>= 1;
 
1121
    }
 
1122
 
 
1123
  if ((maxblue = xwdhdr->l_blue_mask) == 0)
 
1124
    return;
 
1125
 
 
1126
  while ((maxblue & 1) == 0)
 
1127
    {
 
1128
      blueshift++;
 
1129
      maxblue >>= 1;
 
1130
    }
 
1131
 
 
1132
  memset ((gchar *) ColorMap, 0, 256 * 3);
 
1133
 
 
1134
  for (i = 0; i <= maxred; i++)
 
1135
    for (j = 0; j <= maxgreen; j++)
 
1136
      for (k = 0; k <= maxblue; k++)
 
1137
        {
 
1138
          cuind = (i << redshift) | (j << greenshift) | (k << blueshift);
 
1139
 
 
1140
          if (cuind < 256)
 
1141
            {
 
1142
              ColorMap[cuind*3]   = (i * 255)/maxred;
 
1143
              ColorMap[cuind*3+1] = (j * 255)/maxgreen;
 
1144
              ColorMap[cuind*3+2] = (k * 255)/maxblue;
 
1145
            }
 
1146
        }
 
1147
}
 
1148
 
 
1149
 
 
1150
static void
 
1151
set_color_table (gint32           image_ID,
 
1152
                 L_XWDFILEHEADER *xwdhdr,
 
1153
                 L_XWDCOLOR      *xwdcolmap)
 
1154
 
 
1155
{
 
1156
  gint   ncols, i, j;
 
1157
  guchar ColorMap[256 * 3];
 
1158
 
 
1159
  ncols = xwdhdr->l_colormap_entries;
 
1160
  if (xwdhdr->l_ncolors < ncols)
 
1161
    ncols = xwdhdr->l_ncolors;
 
1162
  if (ncols <= 0)
 
1163
    return;
 
1164
  if (ncols > 256)
 
1165
    ncols = 256;
 
1166
 
 
1167
  /* Initialize color table for all 256 entries from mask-values */
 
1168
  init_color_table256 (xwdhdr, ColorMap);
 
1169
 
 
1170
  for (j = 0; j < ncols; j++)
 
1171
    {
 
1172
      i = xwdcolmap[j].l_pixel;
 
1173
      if ((i >= 0) && (i < 256))
 
1174
        {
 
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;
 
1178
        }
 
1179
    }
 
1180
 
 
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]);
 
1186
#endif
 
1187
 
 
1188
  gimp_image_set_colormap (image_ID, ColorMap, 256);
 
1189
}
 
1190
 
 
1191
 
 
1192
 
 
1193
 
 
1194
/* Create an image. Sets layer_ID, drawable and rgn. Returns image_ID */
 
1195
static gint32
 
1196
create_new_image (const gchar         *filename,
 
1197
                  guint                width,
 
1198
                  guint                height,
 
1199
                  GimpImageBaseType    type,
 
1200
                  gint32              *layer_ID,
 
1201
                  GimpDrawable       **drawable,
 
1202
                  GimpPixelRgn        *pixel_rgn)
 
1203
{
 
1204
  gint32        image_ID;
 
1205
  GimpImageType gdtype;
 
1206
 
 
1207
  switch (type)
 
1208
    {
 
1209
    case GIMP_GRAY:
 
1210
      gdtype = GIMP_GRAY_IMAGE;
 
1211
      break;
 
1212
    case GIMP_INDEXED:
 
1213
      gdtype = GIMP_INDEXED_IMAGE;
 
1214
      break;
 
1215
    case GIMP_RGB:
 
1216
      gdtype = GIMP_RGB_IMAGE;
 
1217
      break;
 
1218
    default:
 
1219
      g_warning ("Unknown image type");
 
1220
      return -1;
 
1221
    }
 
1222
 
 
1223
  image_ID = gimp_image_new (width, height, type);
 
1224
  gimp_image_set_filename (image_ID, filename);
 
1225
 
 
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);
 
1229
 
 
1230
  *drawable = gimp_drawable_get (*layer_ID);
 
1231
  gimp_pixel_rgn_init (pixel_rgn, *drawable, 0, 0, (*drawable)->width,
 
1232
                       (*drawable)->height, TRUE, FALSE);
 
1233
 
 
1234
  return image_ID;
 
1235
}
 
1236
 
 
1237
 
 
1238
/* Load XWD with pixmap_format 2, pixmap_depth 1, bits_per_pixel 1 */
 
1239
 
 
1240
static gint32
 
1241
load_xwd_f2_d1_b1 (const gchar     *filename,
 
1242
                   FILE            *ifp,
 
1243
                   L_XWDFILEHEADER *xwdhdr,
 
1244
                   L_XWDCOLOR      *xwdcolmap)
 
1245
{
 
1246
  register int     pix8;
 
1247
  register guchar *dest, *src;
 
1248
  guchar           c1, c2, c3, c4;
 
1249
  gint             width, height, scan_lines, tile_height;
 
1250
  gint             i, j, ncols;
 
1251
  gchar           *temp;
 
1252
  guchar           bit2byte[256 * 8];
 
1253
  guchar          *data, *scanline;
 
1254
  gint             err = 0;
 
1255
  gint32           layer_ID, image_ID;
 
1256
  GimpPixelRgn     pixel_rgn;
 
1257
  GimpDrawable    *drawable;
 
1258
 
 
1259
#ifdef XWD_DEBUG
 
1260
  printf ("load_xwd_f2_d1_b1 (%s)\n", filename);
 
1261
#endif
 
1262
 
 
1263
  width  = xwdhdr->l_pixmap_width;
 
1264
  height = xwdhdr->l_pixmap_height;
 
1265
 
 
1266
  image_ID = create_new_image (filename, width, height, GIMP_INDEXED,
 
1267
                               &layer_ID, &drawable, &pixel_rgn);
 
1268
 
 
1269
  tile_height = gimp_tile_height ();
 
1270
  data = g_malloc (tile_height * width);
 
1271
 
 
1272
  scanline = g_new (guchar, xwdhdr->l_bytes_per_line + 8);
 
1273
 
 
1274
  ncols = xwdhdr->l_colormap_entries;
 
1275
  if (xwdhdr->l_ncolors < ncols)
 
1276
    ncols = xwdhdr->l_ncolors;
 
1277
 
 
1278
  if (ncols < 2)
 
1279
    set_bw_color_table (image_ID);
 
1280
  else
 
1281
    set_color_table (image_ID, xwdhdr, xwdcolmap);
 
1282
 
 
1283
  temp = (gchar *) bit2byte;
 
1284
 
 
1285
  /* Get an array for mapping 8 bits in a byte to 8 bytes */
 
1286
  if (!xwdhdr->l_bitmap_bit_order)
 
1287
    {
 
1288
      for (j = 0; j < 256; j++)
 
1289
        for (i = 0; i < 8; i++)
 
1290
          *(temp++) = ((j & (1 << i)) != 0);
 
1291
    }
 
1292
  else
 
1293
    {
 
1294
      for (j = 0; j < 256; j++)
 
1295
        for (i = 7; i >= 0; i--)
 
1296
          *(temp++) = ((j & (1 << i)) != 0);
 
1297
    }
 
1298
 
 
1299
  dest = data;
 
1300
  scan_lines = 0;
 
1301
 
 
1302
  for (i = 0; i < height; i++)
 
1303
    {
 
1304
      if (fread (scanline, xwdhdr->l_bytes_per_line, 1, ifp) != 1)
 
1305
        {
 
1306
          err = 1;
 
1307
          break;
 
1308
        }
 
1309
 
 
1310
      /* Need to check byte order ? */
 
1311
      if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
 
1312
        {
 
1313
          src = scanline;
 
1314
          switch (xwdhdr->l_bitmap_unit)
 
1315
            {
 
1316
            case 16:
 
1317
              j = xwdhdr->l_bytes_per_line;
 
1318
              while (j > 0)
 
1319
                {
 
1320
                  c1 = src[0]; c2 = src[1];
 
1321
                  *(src++) = c2; *(src++) = c1;
 
1322
                  j -= 2;
 
1323
                }
 
1324
              break;
 
1325
 
 
1326
            case 32:
 
1327
              j = xwdhdr->l_bytes_per_line;
 
1328
              while (j > 0)
 
1329
                {
 
1330
                  c1 = src[0]; c2 = src[1]; c3 = src[2]; c4 = src[3];
 
1331
                  *(src++) = c4; *(src++) = c3; *(src++) = c2; *(src++) = c1;
 
1332
                  j -= 4;
 
1333
                }
 
1334
              break;
 
1335
            }
 
1336
        }
 
1337
      src = scanline;
 
1338
      j = width;
 
1339
      while (j >= 8)
 
1340
        {
 
1341
          pix8 = *(src++);
 
1342
          memcpy (dest, bit2byte + pix8*8, 8);
 
1343
          dest += 8;
 
1344
          j -= 8;
 
1345
        }
 
1346
      if (j > 0)
 
1347
        {
 
1348
          pix8 = *(src++);
 
1349
          memcpy (dest, bit2byte + pix8*8, j);
 
1350
          dest += j;
 
1351
        }
 
1352
 
 
1353
      scan_lines++;
 
1354
 
 
1355
      if ((i % 20) == 0)
 
1356
        gimp_progress_update ((double)(i+1) / (double)height);
 
1357
 
 
1358
      if ((scan_lines == tile_height) || ((i+1) == height))
 
1359
        {
 
1360
          gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
 
1361
                                   width, scan_lines);
 
1362
          scan_lines = 0;
 
1363
          dest = data;
 
1364
        }
 
1365
      if (err) break;
 
1366
    }
 
1367
 
 
1368
  g_free (data);
 
1369
  g_free (scanline);
 
1370
 
 
1371
  if (err)
 
1372
    g_message (_("EOF encountered on reading"));
 
1373
 
 
1374
  gimp_drawable_flush (drawable);
 
1375
 
 
1376
  return err ? -1 : image_ID;
 
1377
}
 
1378
 
 
1379
 
 
1380
/* Load XWD with pixmap_format 2, pixmap_depth 8, bits_per_pixel 8 */
 
1381
 
 
1382
static gint32
 
1383
load_xwd_f2_d8_b8 (const gchar     *filename,
 
1384
                   FILE            *ifp,
 
1385
                   L_XWDFILEHEADER *xwdhdr,
 
1386
                   L_XWDCOLOR      *xwdcolmap)
 
1387
{
 
1388
  gint          width, height, linepad, tile_height, scan_lines;
 
1389
  gint          i, j, ncols;
 
1390
  gint          grayscale;
 
1391
  guchar       *dest, *data;
 
1392
  gint          err = 0;
 
1393
  gint32        layer_ID, image_ID;
 
1394
  GimpPixelRgn  pixel_rgn;
 
1395
  GimpDrawable *drawable;
 
1396
 
 
1397
#ifdef XWD_DEBUG
 
1398
  printf ("load_xwd_f2_d8_b8 (%s)\n", filename);
 
1399
#endif
 
1400
 
 
1401
  width  = xwdhdr->l_pixmap_width;
 
1402
  height = xwdhdr->l_pixmap_height;
 
1403
 
 
1404
  /* This could also be a grayscale image. Check it */
 
1405
  grayscale = 0;
 
1406
  if ((xwdhdr->l_ncolors == 256) && (xwdhdr->l_colormap_entries == 256))
 
1407
    {
 
1408
      for (j = 0; j < 256; j++)
 
1409
        {
 
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))
 
1414
            break;
 
1415
        }
 
1416
 
 
1417
      grayscale = (j == 256);
 
1418
    }
 
1419
 
 
1420
  image_ID = create_new_image (filename, width, height,
 
1421
                               grayscale ? GIMP_GRAY : GIMP_INDEXED,
 
1422
                               &layer_ID, &drawable, &pixel_rgn);
 
1423
 
 
1424
  tile_height = gimp_tile_height ();
 
1425
  data = g_malloc (tile_height * width);
 
1426
 
 
1427
  if (!grayscale)
 
1428
    {
 
1429
      ncols = xwdhdr->l_colormap_entries;
 
1430
      if (xwdhdr->l_ncolors < ncols) ncols = xwdhdr->l_ncolors;
 
1431
      if (ncols < 2)
 
1432
        set_bw_color_table (image_ID);
 
1433
      else
 
1434
        set_color_table (image_ID, xwdhdr, xwdcolmap);
 
1435
    }
 
1436
 
 
1437
  linepad = xwdhdr->l_bytes_per_line - xwdhdr->l_pixmap_width;
 
1438
  if (linepad < 0)
 
1439
    linepad = 0;
 
1440
 
 
1441
  dest = data;
 
1442
  scan_lines = 0;
 
1443
 
 
1444
  for (i = 0; i < height; i++)
 
1445
    {
 
1446
      if (fread (dest, 1, width, ifp) != width)
 
1447
        {
 
1448
          err = 1;
 
1449
          break;
 
1450
        }
 
1451
      dest += width;
 
1452
 
 
1453
      for (j = 0; j < linepad; j++)
 
1454
        getc (ifp);
 
1455
 
 
1456
      scan_lines++;
 
1457
 
 
1458
      if ((i % 20) == 0)
 
1459
        gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
 
1460
 
 
1461
      if ((scan_lines == tile_height) || ((i+1) == height))
 
1462
        {
 
1463
          gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
 
1464
                                   width, scan_lines);
 
1465
          scan_lines = 0;
 
1466
          dest = data;
 
1467
        }
 
1468
    }
 
1469
 
 
1470
  g_free (data);
 
1471
 
 
1472
  if (err)
 
1473
    g_message (_("EOF encountered on reading"));
 
1474
 
 
1475
  gimp_drawable_flush (drawable);
 
1476
 
 
1477
  return err ? -1 : image_ID;
 
1478
}
 
1479
 
 
1480
 
 
1481
/* Load XWD with pixmap_format 2, pixmap_depth up to 16, bits_per_pixel 16 */
 
1482
 
 
1483
static gint32
 
1484
load_xwd_f2_d16_b16 (const gchar     *filename,
 
1485
                     FILE            *ifp,
 
1486
                     L_XWDFILEHEADER *xwdhdr,
 
1487
                     L_XWDCOLOR      *xwdcolmap)
 
1488
{
 
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;
 
1496
  gulong           maxval;
 
1497
  guchar          *ColorMap, *cm, *data;
 
1498
  gint             err = 0;
 
1499
  gint32           layer_ID, image_ID;
 
1500
  GimpPixelRgn     pixel_rgn;
 
1501
  GimpDrawable    *drawable;
 
1502
 
 
1503
#ifdef XWD_DEBUG
 
1504
  printf ("load_xwd_f2_d16_b16 (%s)\n", filename);
 
1505
#endif
 
1506
 
 
1507
  width  = xwdhdr->l_pixmap_width;
 
1508
  height = xwdhdr->l_pixmap_height;
 
1509
 
 
1510
  image_ID = create_new_image (filename, width, height, GIMP_RGB,
 
1511
                               &layer_ID, &drawable, &pixel_rgn);
 
1512
 
 
1513
  tile_height = gimp_tile_height ();
 
1514
  data = g_malloc (tile_height * width * 3);
 
1515
 
 
1516
  /* Get memory for mapping 16 bit XWD-pixel to GIMP-RGB */
 
1517
  maxval = 0x10000 * 3;
 
1518
  ColorMap = g_new0 (guchar, maxval);
 
1519
 
 
1520
  redmask   = xwdhdr->l_red_mask;
 
1521
  greenmask = xwdhdr->l_green_mask;
 
1522
  bluemask  = xwdhdr->l_blue_mask;
 
1523
 
 
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;
 
1527
 
 
1528
  while (((1 << redshift)   & redmask)   == 0) redshift++;
 
1529
  while (((1 << greenshift) & greenmask) == 0) greenshift++;
 
1530
  while (((1 << blueshift)  & bluemask)  == 0) blueshift++;
 
1531
 
 
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;
 
1535
 
 
1536
  maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
 
1537
  maxgreen = (1 << maxgreen) - 1;
 
1538
 
 
1539
  maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
 
1540
  maxblue = (1 << maxblue) - 1;
 
1541
 
 
1542
  /* Built up the array to map XWD-pixel value to GIMP-RGB */
 
1543
  for (red = 0; red <= maxred; red++)
 
1544
    {
 
1545
      redval = (red * 255) / maxred;
 
1546
      for (green = 0; green <= maxgreen; green++)
 
1547
        {
 
1548
          greenval = (green * 255) / maxgreen;
 
1549
          for (blue = 0; blue <= maxblue; blue++)
 
1550
            {
 
1551
              blueval = (blue * 255) / maxblue;
 
1552
              cm = ColorMap + ((red << redshift) + (green << greenshift)
 
1553
                               + (blue << blueshift)) * 3;
 
1554
              *(cm++) = redval;
 
1555
              *(cm++) = greenval;
 
1556
              *cm = blueval;
 
1557
            }
 
1558
        }
 
1559
    }
 
1560
 
 
1561
  /* Now look what was written to the XWD-Colormap */
 
1562
 
 
1563
  ncols = xwdhdr->l_colormap_entries;
 
1564
  if (xwdhdr->l_ncolors < ncols)
 
1565
    ncols = xwdhdr->l_ncolors;
 
1566
 
 
1567
  for (j = 0; j < ncols; j++)
 
1568
    {
 
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);
 
1573
    }
 
1574
 
 
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;
 
1579
 
 
1580
  lsbyte_first = (xwdhdr->l_byte_order == 0);
 
1581
 
 
1582
  dest = data;
 
1583
  scan_lines = 0;
 
1584
 
 
1585
  for (i = 0; i < height; i++)
 
1586
    {
 
1587
      for (j = 0; j < width; j++)
 
1588
        {
 
1589
          c0 = getc (ifp);
 
1590
          c1 = getc (ifp);
 
1591
          if (c1 < 0)
 
1592
            {
 
1593
              err = 1;
 
1594
              break;
 
1595
            }
 
1596
 
 
1597
          if (lsbyte_first)
 
1598
            c0 = c0 | (c1 << 8);
 
1599
          else
 
1600
            c0 = (c0 << 8) | c1;
 
1601
 
 
1602
          cm = ColorMap + c0 * 3;
 
1603
          *(dest++) = *(cm++);
 
1604
          *(dest++) = *(cm++);
 
1605
          *(dest++) = *cm;
 
1606
        }
 
1607
 
 
1608
      if (err)
 
1609
        break;
 
1610
 
 
1611
      for (j = 0; j < linepad; j++)
 
1612
        getc (ifp);
 
1613
 
 
1614
      scan_lines++;
 
1615
 
 
1616
      if ((i % 20) == 0)
 
1617
        gimp_progress_update ((double)(i+1) / (double)height);
 
1618
 
 
1619
      if ((scan_lines == tile_height) || ((i+1) == height))
 
1620
        {
 
1621
          gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
 
1622
                                   width, scan_lines);
 
1623
          scan_lines = 0;
 
1624
          dest = data;
 
1625
        }
 
1626
    }
 
1627
  g_free (data);
 
1628
  g_free (ColorMap);
 
1629
 
 
1630
  if (err)
 
1631
    g_message (_("EOF encountered on reading"));
 
1632
 
 
1633
  gimp_drawable_flush (drawable);
 
1634
 
 
1635
  return err ? -1 : image_ID;
 
1636
}
 
1637
 
 
1638
 
 
1639
/* Load XWD with pixmap_format 2, pixmap_depth up to 24, bits_per_pixel 24/32 */
 
1640
 
 
1641
static gint32
 
1642
load_xwd_f2_d24_b32 (const gchar      *filename,
 
1643
                     FILE             *ifp,
 
1644
                     L_XWDFILEHEADER  *xwdhdr,
 
1645
                     L_XWDCOLOR       *xwdcolmap,
 
1646
                     GError          **error)
 
1647
{
 
1648
  register guchar *dest, lsbyte_first;
 
1649
  gint             width, height, linepad, i, j, c0, c1, c2, c3;
 
1650
  gint             tile_height, scan_lines;
 
1651
  L_CARD32         pixelval;
 
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];
 
1657
  guchar          *data;
 
1658
  PIXEL_MAP        pixel_map;
 
1659
  gint             err = 0;
 
1660
  gint32           layer_ID, image_ID;
 
1661
  GimpPixelRgn     pixel_rgn;
 
1662
  GimpDrawable    *drawable;
 
1663
 
 
1664
#ifdef XWD_DEBUG
 
1665
  printf ("load_xwd_f2_d24_b32 (%s)\n", filename);
 
1666
#endif
 
1667
 
 
1668
  width  = xwdhdr->l_pixmap_width;
 
1669
  height = xwdhdr->l_pixmap_height;
 
1670
 
 
1671
  redmask   = xwdhdr->l_red_mask;
 
1672
  greenmask = xwdhdr->l_green_mask;
 
1673
  bluemask  = xwdhdr->l_blue_mask;
 
1674
 
 
1675
  if (redmask   == 0) redmask   = 0xff0000;
 
1676
  if (greenmask == 0) greenmask = 0x00ff00;
 
1677
  if (bluemask  == 0) bluemask  = 0x0000ff;
 
1678
 
 
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;
 
1682
 
 
1683
  while (((1 << redshift)   & redmask)   == 0) redshift++;
 
1684
  while (((1 << greenshift) & greenmask) == 0) greenshift++;
 
1685
  while (((1 << blueshift)  & bluemask)  == 0) blueshift++;
 
1686
 
 
1687
  /* The bits_per_rgb may not be correct. Use redmask instead */
 
1688
 
 
1689
  maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
 
1690
  maxred = (1 << maxred) - 1;
 
1691
 
 
1692
  maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
 
1693
  maxgreen = (1 << maxgreen) - 1;
 
1694
 
 
1695
  maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
 
1696
  maxblue = (1 << maxblue) - 1;
 
1697
 
 
1698
  if (maxred   > sizeof (redmap)   ||
 
1699
      maxgreen > sizeof (greenmap) ||
 
1700
      maxblue  > sizeof (bluemap))
 
1701
    {
 
1702
      g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
 
1703
                   _("XWD-file %s is corrupt."),
 
1704
                   gimp_filename_to_utf8 (filename));
 
1705
      return -1;
 
1706
    }
 
1707
 
 
1708
  image_ID = create_new_image (filename, width, height, GIMP_RGB,
 
1709
                               &layer_ID, &drawable, &pixel_rgn);
 
1710
 
 
1711
  tile_height = gimp_tile_height ();
 
1712
  data = g_malloc (tile_height * width * 3);
 
1713
 
 
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;
 
1721
 
 
1722
  ncols = xwdhdr->l_colormap_entries;
 
1723
  if (xwdhdr->l_ncolors < ncols)
 
1724
    ncols = xwdhdr->l_ncolors;
 
1725
 
 
1726
  set_pixelmap (ncols, xwdcolmap, &pixel_map);
 
1727
 
 
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;
 
1732
 
 
1733
  lsbyte_first = (xwdhdr->l_byte_order == 0);
 
1734
 
 
1735
  dest = data;
 
1736
  scan_lines = 0;
 
1737
 
 
1738
  if (xwdhdr->l_bits_per_pixel == 32)
 
1739
    {
 
1740
      for (i = 0; i < height; i++)
 
1741
        {
 
1742
          for (j = 0; j < width; j++)
 
1743
            {
 
1744
              c0 = getc (ifp);
 
1745
              c1 = getc (ifp);
 
1746
              c2 = getc (ifp);
 
1747
              c3 = getc (ifp);
 
1748
              if (c3 < 0)
 
1749
                {
 
1750
                  err = 1;
 
1751
                  break;
 
1752
                }
 
1753
              if (lsbyte_first)
 
1754
                pixelval = c0 | (c1 << 8) | (c2 << 16) | (c3 << 24);
 
1755
              else
 
1756
                pixelval = (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
 
1757
 
 
1758
              if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
 
1759
                {
 
1760
                  dest += 3;
 
1761
                }
 
1762
              else
 
1763
                {
 
1764
                  *(dest++) = redmap[(pixelval & redmask) >> redshift];
 
1765
                  *(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
 
1766
                  *(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
 
1767
                }
 
1768
            }
 
1769
          scan_lines++;
 
1770
 
 
1771
          if (err)
 
1772
            break;
 
1773
 
 
1774
          for (j = 0; j < linepad; j++)
 
1775
            getc (ifp);
 
1776
 
 
1777
          if ((i % 20) == 0)
 
1778
            gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
 
1779
 
 
1780
          if ((scan_lines == tile_height) || ((i+1) == height))
 
1781
            {
 
1782
              gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
 
1783
                                       width, scan_lines);
 
1784
              scan_lines = 0;
 
1785
              dest = data;
 
1786
            }
 
1787
        }
 
1788
    }
 
1789
  else    /* 24 bits per pixel */
 
1790
    {
 
1791
      for (i = 0; i < height; i++)
 
1792
        {
 
1793
          for (j = 0; j < width; j++)
 
1794
            {
 
1795
              c0 = getc (ifp);
 
1796
              c1 = getc (ifp);
 
1797
              c2 = getc (ifp);
 
1798
              if (c2 < 0)
 
1799
                {
 
1800
                  err = 1;
 
1801
                  break;
 
1802
                }
 
1803
              if (lsbyte_first)
 
1804
                pixelval = c0 | (c1 << 8) | (c2 << 16);
 
1805
              else
 
1806
                pixelval = (c0 << 16) | (c1 << 8) | c2;
 
1807
 
 
1808
              if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2))
 
1809
                {
 
1810
                  dest += 3;
 
1811
                }
 
1812
              else
 
1813
                {
 
1814
                  *(dest++) = redmap[(pixelval & redmask) >> redshift];
 
1815
                  *(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
 
1816
                  *(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
 
1817
                }
 
1818
            }
 
1819
          scan_lines++;
 
1820
 
 
1821
          if (err)
 
1822
            break;
 
1823
 
 
1824
          for (j = 0; j < linepad; j++)
 
1825
            getc (ifp);
 
1826
 
 
1827
          if ((i % 20) == 0)
 
1828
            gimp_progress_update ((gdouble) (i + 1) / (gdouble) height);
 
1829
 
 
1830
          if ((scan_lines == tile_height) || ((i+1) == height))
 
1831
            {
 
1832
              gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, i-scan_lines+1,
 
1833
                                       width, scan_lines);
 
1834
              scan_lines = 0;
 
1835
              dest = data;
 
1836
            }
 
1837
        }
 
1838
    }
 
1839
 
 
1840
  g_free (data);
 
1841
 
 
1842
  if (err)
 
1843
    g_message (_("EOF encountered on reading"));
 
1844
 
 
1845
  gimp_drawable_flush (drawable);
 
1846
 
 
1847
  return err ? -1 : image_ID;
 
1848
}
 
1849
 
 
1850
 
 
1851
/* Load XWD with pixmap_format 1, pixmap_depth up to 24, bits_per_pixel 1 */
 
1852
 
 
1853
static gint32
 
1854
load_xwd_f1_d24_b1 (const gchar      *filename,
 
1855
                    FILE             *ifp,
 
1856
                    L_XWDFILEHEADER  *xwdhdr,
 
1857
                    L_XWDCOLOR       *xwdcolmap,
 
1858
                    GError          **error)
 
1859
{
 
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;
 
1869
  gulong           g;
 
1870
  guchar           redmap[256], greenmap[256], bluemap[256];
 
1871
  guchar           bit_reverse[256];
 
1872
  guchar          *xwddata, *xwdin, *data;
 
1873
  L_CARD32         pixelval;
 
1874
  PIXEL_MAP        pixel_map;
 
1875
  gint             err = 0;
 
1876
  gint32           layer_ID, image_ID;
 
1877
  GimpPixelRgn     pixel_rgn;
 
1878
  GimpDrawable    *drawable;
 
1879
 
 
1880
#ifdef XWD_DEBUG
 
1881
  printf ("load_xwd_f1_d24_b1 (%s)\n", filename);
 
1882
#endif
 
1883
 
 
1884
  xwddata = g_malloc (xwdhdr->l_bytes_per_line);
 
1885
  if (xwddata == NULL)
 
1886
    return -1;
 
1887
 
 
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);
 
1892
 
 
1893
  for (j = 0; j < 256; j++)   /* Create an array for reversing bits */
 
1894
    {
 
1895
      inmask = 0;
 
1896
      for (i = 0; i < 8; i++)
 
1897
        {
 
1898
          inmask <<= 1;
 
1899
          if (j & (1 << i)) inmask |= 1;
 
1900
        }
 
1901
      bit_reverse[j] = inmask;
 
1902
    }
 
1903
 
 
1904
  redmask   = xwdhdr->l_red_mask;
 
1905
  greenmask = xwdhdr->l_green_mask;
 
1906
  bluemask  = xwdhdr->l_blue_mask;
 
1907
 
 
1908
  if (redmask   == 0) redmask   = 0xff0000;
 
1909
  if (greenmask == 0) greenmask = 0x00ff00;
 
1910
  if (bluemask  == 0) bluemask  = 0x0000ff;
 
1911
 
 
1912
  standard_rgb =    (redmask == 0xff0000) && (greenmask == 0x00ff00)
 
1913
    && (bluemask == 0x0000ff);
 
1914
  redshift = greenshift = blueshift = 0;
 
1915
 
 
1916
  if (!standard_rgb)   /* Do we need to re-map the pixel-values ? */
 
1917
    {
 
1918
      /* How to shift RGB to be right aligned ? */
 
1919
      /* (We rely on the the mask bits are grouped and not mixed) */
 
1920
 
 
1921
      while (((1 << redshift)   & redmask)   == 0) redshift++;
 
1922
      while (((1 << greenshift) & greenmask) == 0) greenshift++;
 
1923
      while (((1 << blueshift)  & bluemask)  == 0) blueshift++;
 
1924
 
 
1925
      /* The bits_per_rgb may not be correct. Use redmask instead */
 
1926
 
 
1927
      maxred = 0; while (redmask >> (redshift + maxred)) maxred++;
 
1928
      maxred = (1 << maxred) - 1;
 
1929
 
 
1930
      maxgreen = 0; while (greenmask >> (greenshift + maxgreen)) maxgreen++;
 
1931
      maxgreen = (1 << maxgreen) - 1;
 
1932
 
 
1933
      maxblue = 0; while (bluemask >> (blueshift + maxblue)) maxblue++;
 
1934
      maxblue = (1 << maxblue) - 1;
 
1935
 
 
1936
      if (maxred   > sizeof (redmap)   ||
 
1937
          maxgreen > sizeof (greenmap) ||
 
1938
          maxblue  > sizeof (bluemap))
 
1939
        {
 
1940
          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
 
1941
                       _("XWD-file %s is corrupt."),
 
1942
                       gimp_filename_to_utf8 (filename));
 
1943
          return -1;
 
1944
        }
 
1945
 
 
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;
 
1953
    }
 
1954
 
 
1955
  image_ID = create_new_image (filename, width, height,
 
1956
                               indexed ? GIMP_INDEXED : GIMP_RGB,
 
1957
                               &layer_ID, &drawable, &pixel_rgn);
 
1958
 
 
1959
  tile_height = gimp_tile_height ();
 
1960
  data = g_malloc (tile_height * width * bytes_per_pixel);
 
1961
 
 
1962
  ncols = xwdhdr->l_colormap_entries;
 
1963
  if (xwdhdr->l_ncolors < ncols)
 
1964
    ncols = xwdhdr->l_ncolors;
 
1965
 
 
1966
  if (indexed)
 
1967
    {
 
1968
      if (ncols < 2)
 
1969
        set_bw_color_table (image_ID);
 
1970
      else
 
1971
        set_color_table (image_ID, xwdhdr, xwdcolmap);
 
1972
    }
 
1973
  else
 
1974
    {
 
1975
      set_pixelmap (ncols, xwdcolmap, &pixel_map);
 
1976
    }
 
1977
 
 
1978
  do_reverse = !xwdhdr->l_bitmap_bit_order;
 
1979
 
 
1980
  /* This is where the image data starts within the file */
 
1981
  data_offset = ftell (ifp);
 
1982
 
 
1983
  for (tile_start = 0; tile_start < height; tile_start += tile_height)
 
1984
    {
 
1985
      memset (data, 0, width*tile_height*bytes_per_pixel);
 
1986
 
 
1987
      tile_end = tile_start + tile_height - 1;
 
1988
      if (tile_end >= height)
 
1989
        tile_end = height - 1;
 
1990
 
 
1991
      for (plane = 0; plane < xwdhdr->l_pixmap_depth; plane++)
 
1992
        {
 
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);
 
1997
 
 
1998
          /* Place the last plane at the least significant bit */
 
1999
 
 
2000
          if (indexed)   /* Only 1 byte per pixel */
 
2001
            {
 
2002
              fromright = xwdhdr->l_pixmap_depth-1-plane;
 
2003
              outmask = (1 << fromright);
 
2004
            }
 
2005
          else           /* 3 bytes per pixel */
 
2006
            {
 
2007
              fromright = xwdhdr->l_pixmap_depth-1-plane;
 
2008
              dest += 2 - fromright/8;
 
2009
              outmask = (1 << (fromright % 8));
 
2010
            }
 
2011
 
 
2012
          for (i = tile_start; i <= tile_end; i++)
 
2013
            {
 
2014
              if (fread (xwddata,xwdhdr->l_bytes_per_line,1,ifp) != 1)
 
2015
                {
 
2016
                  err = 1;
 
2017
                  break;
 
2018
                }
 
2019
              xwdin = xwddata;
 
2020
 
 
2021
              /* Handle bitmap unit */
 
2022
              if (xwdhdr->l_bitmap_unit == 16)
 
2023
                {
 
2024
                  if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
 
2025
                    {
 
2026
                      j = xwdhdr->l_bytes_per_line/2;
 
2027
                      while (j--)
 
2028
                        {
 
2029
                          inmask = xwdin[0]; xwdin[0] = xwdin[1]; xwdin[1] = inmask;
 
2030
                          xwdin += 2;
 
2031
                        }
 
2032
                      xwdin = xwddata;
 
2033
                    }
 
2034
                }
 
2035
              else if (xwdhdr->l_bitmap_unit == 32)
 
2036
                {
 
2037
                  if (xwdhdr->l_bitmap_bit_order != xwdhdr->l_byte_order)
 
2038
                    {
 
2039
                      j = xwdhdr->l_bytes_per_line/4;
 
2040
                      while (j--)
 
2041
                        {
 
2042
                          inmask = xwdin[0]; xwdin[0] = xwdin[3]; xwdin[3] = inmask;
 
2043
                          inmask = xwdin[1]; xwdin[1] = xwdin[2]; xwdin[2] = inmask;
 
2044
                          xwdin += 4;
 
2045
                        }
 
2046
                      xwdin = xwddata;
 
2047
                    }
 
2048
                }
 
2049
 
 
2050
              g = inmask = 0;
 
2051
              for (j = 0; j < width; j++)
 
2052
                {
 
2053
                  if (!inmask)
 
2054
                    {
 
2055
                      g = *(xwdin++);
 
2056
                      if (do_reverse)
 
2057
                        g = bit_reverse[g];
 
2058
                      inmask = 0x80;
 
2059
                    }
 
2060
 
 
2061
                  if (g & inmask)
 
2062
                    *dest |= outmask;
 
2063
                  dest += bytes_per_pixel;
 
2064
 
 
2065
                  inmask >>= 1;
 
2066
                }
 
2067
            }
 
2068
        }
 
2069
 
 
2070
      /* For indexed images, the mapping to colors is done by the color table. */
 
2071
      /* Otherwise we must do the mapping by ourself. */
 
2072
      if (!indexed)
 
2073
        {
 
2074
          dest = data;
 
2075
          for (i = tile_start; i <= tile_end; i++)
 
2076
            {
 
2077
              for (j = 0; j < width; j++)
 
2078
                {
 
2079
                  pixelval = (*dest << 16) | (*(dest+1) << 8) | *(dest+2);
 
2080
 
 
2081
                  if (get_pixelmap (pixelval, &pixel_map, dest, dest+1, dest+2)
 
2082
                      || standard_rgb)
 
2083
                    {
 
2084
                      dest += 3;
 
2085
                    }
 
2086
                  else   /* We have to map RGB to 0,...,255 */
 
2087
                    {
 
2088
                      *(dest++) = redmap[(pixelval & redmask) >> redshift];
 
2089
                      *(dest++) = greenmap[(pixelval & greenmask) >> greenshift];
 
2090
                      *(dest++) = bluemap[(pixelval & bluemask) >> blueshift];
 
2091
                    }
 
2092
                }
 
2093
            }
 
2094
        }
 
2095
 
 
2096
      gimp_progress_update ((gdouble) tile_end / (gdouble) height);
 
2097
 
 
2098
      gimp_pixel_rgn_set_rect (&pixel_rgn, data, 0, tile_start,
 
2099
                               width, tile_end-tile_start+1);
 
2100
    }
 
2101
 
 
2102
  g_free (data);
 
2103
  g_free (xwddata);
 
2104
 
 
2105
  if (err)
 
2106
    g_message (_("EOF encountered on reading"));
 
2107
 
 
2108
  gimp_drawable_flush (drawable);
 
2109
 
 
2110
  return err ? -1 : image_ID;
 
2111
}
 
2112
 
 
2113
 
 
2114
static gint
 
2115
save_index (FILE    *ofp,
 
2116
            gint32   image_ID,
 
2117
            gint32   drawable_ID,
 
2118
            gint     gray)
 
2119
{
 
2120
  gint             height, width, linepad, tile_height, i, j;
 
2121
  gint             ncolors, vclass;
 
2122
  glong            tmp = 0;
 
2123
  guchar          *data, *src, *cmap;
 
2124
  L_XWDFILEHEADER  xwdhdr;
 
2125
  L_XWDCOLOR       xwdcolmap[256];
 
2126
  GimpPixelRgn     pixel_rgn;
 
2127
  GimpDrawable    *drawable;
 
2128
 
 
2129
#ifdef XWD_DEBUG
 
2130
  printf ("save_index ()\n");
 
2131
#endif
 
2132
 
 
2133
  drawable      = gimp_drawable_get (drawable_ID);
 
2134
  width         = drawable->width;
 
2135
  height        = drawable->height;
 
2136
  tile_height   = gimp_tile_height ();
 
2137
 
 
2138
  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
 
2139
 
 
2140
  /* allocate a buffer for retrieving information from the pixel region  */
 
2141
  src = data = g_new (guchar, tile_height * width * drawable->bpp);
 
2142
 
 
2143
  linepad = width % 4;
 
2144
  if (linepad) linepad = 4 - linepad;
 
2145
 
 
2146
  /* Fill XWD-color map */
 
2147
  if (gray)
 
2148
    {
 
2149
      vclass = 0;
 
2150
      ncolors = 256;
 
2151
 
 
2152
      for (j = 0; j < ncolors; j++)
 
2153
        {
 
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;
 
2160
        }
 
2161
    }
 
2162
  else
 
2163
    {
 
2164
      vclass = 3;
 
2165
      cmap = gimp_image_get_colormap (image_ID, &ncolors);
 
2166
 
 
2167
      for (j = 0; j < ncolors; j++)
 
2168
        {
 
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;
 
2175
        }
 
2176
    }
 
2177
 
 
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;
 
2204
 
 
2205
  write_xwd_header (ofp, &xwdhdr);
 
2206
  write_xwd_cols (ofp, &xwdhdr, xwdcolmap);
 
2207
 
 
2208
  for (i = 0; i < height; i++)
 
2209
    {
 
2210
      if ((i % tile_height) == 0)   /* Get more data */
 
2211
        {
 
2212
          gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
 
2213
 
 
2214
          gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, i, width, scan_lines);
 
2215
          src = data;
 
2216
        }
 
2217
 
 
2218
      fwrite (src, width, 1, ofp);
 
2219
 
 
2220
      if (linepad)
 
2221
        fwrite ((char *)&tmp, linepad, 1, ofp);
 
2222
 
 
2223
      src += width;
 
2224
 
 
2225
      if ((i % 20) == 0)
 
2226
        gimp_progress_update ((gdouble) i / (gdouble) height);
 
2227
    }
 
2228
 
 
2229
  g_free (data);
 
2230
 
 
2231
  gimp_drawable_detach (drawable);
 
2232
 
 
2233
  if (ferror (ofp))
 
2234
    {
 
2235
      g_message (_("Error during writing indexed/gray image"));
 
2236
      return FALSE;
 
2237
    }
 
2238
 
 
2239
  return TRUE;
 
2240
}
 
2241
 
 
2242
 
 
2243
static gint
 
2244
save_rgb (FILE   *ofp,
 
2245
          gint32  image_ID,
 
2246
          gint32  drawable_ID)
 
2247
{
 
2248
  gint             height, width, linepad, tile_height, i;
 
2249
  glong            tmp = 0;
 
2250
  guchar          *data, *src;
 
2251
  L_XWDFILEHEADER  xwdhdr;
 
2252
  GimpPixelRgn     pixel_rgn;
 
2253
  GimpDrawable    *drawable;
 
2254
 
 
2255
#ifdef XWD_DEBUG
 
2256
  printf ("save_rgb ()\n");
 
2257
#endif
 
2258
 
 
2259
  drawable      = gimp_drawable_get (drawable_ID);
 
2260
  width         = drawable->width;
 
2261
  height        = drawable->height;
 
2262
  tile_height   = gimp_tile_height ();
 
2263
 
 
2264
  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, width, height, FALSE, FALSE);
 
2265
 
 
2266
  /* allocate a buffer for retrieving information from the pixel region  */
 
2267
  src = data = g_new (guchar, tile_height * width * drawable->bpp);
 
2268
 
 
2269
  linepad = (width * 3) % 4;
 
2270
  if (linepad)
 
2271
    linepad = 4 - linepad;
 
2272
 
 
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;
 
2282
 
 
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;
 
2287
 
 
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;
 
2301
 
 
2302
  write_xwd_header (ofp, &xwdhdr);
 
2303
 
 
2304
  for (i = 0; i < height; i++)
 
2305
    {
 
2306
      if ((i % tile_height) == 0)   /* Get more data */
 
2307
        {
 
2308
          gint scan_lines = (i + tile_height - 1 < height) ? tile_height : (height - i);
 
2309
 
 
2310
          gimp_pixel_rgn_get_rect (&pixel_rgn, data, 0, i, width, scan_lines);
 
2311
          src = data;
 
2312
        }
 
2313
 
 
2314
      fwrite (src, width * 3, 1, ofp);
 
2315
 
 
2316
      if (linepad)
 
2317
        fwrite ((char *)&tmp, linepad, 1, ofp);
 
2318
 
 
2319
      src += width * 3;
 
2320
 
 
2321
      if ((i % 20) == 0)
 
2322
        gimp_progress_update ((gdouble) i / (gdouble) height);
 
2323
    }
 
2324
 
 
2325
  g_free (data);
 
2326
 
 
2327
  gimp_drawable_detach (drawable);
 
2328
 
 
2329
  if (ferror (ofp))
 
2330
    {
 
2331
      g_message (_("Error during writing rgb image"));
 
2332
      return FALSE;
 
2333
    }
 
2334
 
 
2335
  return TRUE;
 
2336
}