~ubuntu-branches/ubuntu/karmic/gimp/karmic-security

« back to all changes in this revision

Viewing changes to plug-ins/bmp/bmpread.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2008-10-06 13:30:41 UTC
  • mfrom: (1.1.15 upstream)
  • Revision ID: james.westby@ubuntu.com-20081006133041-axco233xt49jobn7
Tags: 2.6.0-1ubuntu1
* Sync on debian and new version (lp: #276839)
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch:
  - updated some strings for ubuntu
* debian/rules:
  - updated translation templates

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* bmpread.c    reads any bitmap I could get for testing */
2
 
/* Alexander.Schulz@stud.uni-karlsruhe.de                */
3
 
 
4
 
/*
5
 
 * GIMP - The GNU Image Manipulation Program
6
 
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
7
 
 *
8
 
 * This program is free software; you can redistribute it and/or modify
9
 
 * it under the terms of the GNU General Public License as published by
10
 
 * the Free Software Foundation; either version 2 of the License, or
11
 
 * (at your option) any later version.
12
 
 *
13
 
 * This program is distributed in the hope that it will be useful,
14
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 * GNU General Public License for more details.
17
 
 *
18
 
 * You should have received a copy of the GNU General Public License
19
 
 * along with this program; if not, write to the Free Software
20
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
 
 * ----------------------------------------------------------------------------
22
 
 */
23
 
 
24
 
#include "config.h"
25
 
 
26
 
#include <errno.h>
27
 
#include <string.h>
28
 
 
29
 
#include <glib/gstdio.h>
30
 
 
31
 
#include <libgimp/gimp.h>
32
 
 
33
 
#include "bmp.h"
34
 
 
35
 
#include "libgimp/stdplugins-intl.h"
36
 
 
37
 
 
38
 
#if !defined(WIN32) || defined(__MINGW32__)
39
 
#define BI_RGB          0
40
 
#define BI_RLE8         1
41
 
#define BI_RLE4         2
42
 
#define BI_BITFIELDS    3
43
 
#endif
44
 
 
45
 
static gint32 ReadImage (FILE     *fd,
46
 
                         gint      width,
47
 
                         gint      height,
48
 
                         guchar    cmap[256][3],
49
 
                         gint      ncols,
50
 
                         gint      bpp,
51
 
                         gint      compression,
52
 
                         gint      rowbytes,
53
 
                         gboolean  grey,
54
 
                         const Bitmap_Channel *masks);
55
 
 
56
 
 
57
 
static gint32
58
 
ToL (const guchar *puffer)
59
 
{
60
 
  return (puffer[0] | puffer[1] << 8 | puffer[2] << 16 | puffer[3] << 24);
61
 
}
62
 
 
63
 
static gint16
64
 
ToS (const guchar *puffer)
65
 
{
66
 
  return (puffer[0] | puffer[1] << 8);
67
 
}
68
 
 
69
 
static gboolean
70
 
ReadColorMap (FILE     *fd,
71
 
              guchar    buffer[256][3],
72
 
              gint      number,
73
 
              gint      size,
74
 
              gboolean *grey)
75
 
{
76
 
  gint   i;
77
 
  guchar rgb[4];
78
 
 
79
 
  *grey = (number > 2);
80
 
 
81
 
  for (i = 0; i < number ; i++)
82
 
    {
83
 
      if (!ReadOK (fd, rgb, size))
84
 
        {
85
 
          g_message (_("Bad colormap"));
86
 
          return FALSE;
87
 
        }
88
 
 
89
 
      /* Bitmap save the colors in another order! But change only once! */
90
 
 
91
 
      buffer[i][0] = rgb[2];
92
 
      buffer[i][1] = rgb[1];
93
 
      buffer[i][2] = rgb[0];
94
 
      *grey = ((*grey) && (rgb[0]==rgb[1]) && (rgb[1]==rgb[2]));
95
 
    }
96
 
  return TRUE;
97
 
}
98
 
 
99
 
static gboolean
100
 
ReadChannelMasks (guint32 *tmp, Bitmap_Channel *masks, guint channels)
101
 
{
102
 
  guint32 mask;
103
 
  gint   i, nbits, offset, bit;
104
 
 
105
 
  for (i = 0; i < channels; i++)
106
 
    {
107
 
      mask = tmp[i];
108
 
      masks[i].mask = mask;
109
 
      nbits = 0;
110
 
      offset = -1;
111
 
      for (bit = 0; bit < 32; bit++)
112
 
        {
113
 
          if (mask & 1)
114
 
            {
115
 
              nbits++;
116
 
              if (offset == -1)
117
 
                offset = bit;
118
 
            }
119
 
          mask = mask >> 1;
120
 
        }
121
 
      masks[i].shiftin = offset;
122
 
      masks[i].max_value = (gfloat)((1<<(nbits))-1);
123
 
 
124
 
#ifdef DEBUG
125
 
      g_print ("Channel %d mask %08x in %d max_val %d\n",
126
 
               i, masks[i].mask, masks[i].shiftin, (gint)masks[i].max_value);
127
 
#endif
128
 
    }
129
 
  return TRUE;
130
 
}
131
 
 
132
 
gint32
133
 
ReadBMP (const gchar *name)
134
 
{
135
 
  FILE     *fd;
136
 
  guchar    buffer[64];
137
 
  gint      ColormapSize, rowbytes, Maps;
138
 
  gboolean  Grey = FALSE;
139
 
  guchar    ColorMap[256][3];
140
 
  gint32    image_ID;
141
 
  gchar     magick[2];
142
 
  Bitmap_Channel masks[4];
143
 
 
144
 
  filename = name;
145
 
  fd = g_fopen (filename, "rb");
146
 
 
147
 
  if (!fd)
148
 
    {
149
 
      g_message (_("Could not open '%s' for reading: %s"),
150
 
                 gimp_filename_to_utf8 (filename), g_strerror (errno));
151
 
      return -1;
152
 
    }
153
 
 
154
 
  gimp_progress_init_printf (_("Opening '%s'"),
155
 
                             gimp_filename_to_utf8 (name));
156
 
 
157
 
  /* It is a File. Now is it a Bitmap? Read the shortest possible header */
158
 
 
159
 
  if (!ReadOK (fd, magick, 2) || !(!strncmp (magick, "BA", 2) ||
160
 
     !strncmp (magick, "BM", 2) || !strncmp (magick, "IC", 2) ||
161
 
     !strncmp (magick, "PI", 2) || !strncmp (magick, "CI", 2) ||
162
 
     !strncmp (magick, "CP", 2)))
163
 
    {
164
 
      g_message (_("'%s' is not a valid BMP file"),
165
 
                 gimp_filename_to_utf8 (filename));
166
 
      return -1;
167
 
    }
168
 
 
169
 
  while (!strncmp (magick, "BA", 2))
170
 
    {
171
 
      if (!ReadOK (fd, buffer, 12))
172
 
        {
173
 
          g_message (_("'%s' is not a valid BMP file"),
174
 
                      gimp_filename_to_utf8 (filename));
175
 
          return -1;
176
 
        }
177
 
      if (!ReadOK (fd, magick, 2))
178
 
        {
179
 
          g_message (_("'%s' is not a valid BMP file"),
180
 
                      gimp_filename_to_utf8 (filename));
181
 
          return -1;
182
 
        }
183
 
    }
184
 
 
185
 
  if (!ReadOK (fd, buffer, 12))
186
 
    {
187
 
      g_message (_("'%s' is not a valid BMP file"),
188
 
                  gimp_filename_to_utf8 (filename));
189
 
      return -1;
190
 
    }
191
 
 
192
 
  /* bring them to the right byteorder. Not too nice, but it should work */
193
 
 
194
 
  Bitmap_File_Head.bfSize    = ToL (&buffer[0x00]);
195
 
  Bitmap_File_Head.zzHotX    = ToS (&buffer[0x04]);
196
 
  Bitmap_File_Head.zzHotY    = ToS (&buffer[0x06]);
197
 
  Bitmap_File_Head.bfOffs    = ToL (&buffer[0x08]);
198
 
 
199
 
  if (!ReadOK (fd, buffer, 4))
200
 
    {
201
 
      g_message (_("'%s' is not a valid BMP file"),
202
 
                  gimp_filename_to_utf8 (filename));
203
 
      return -1;
204
 
    }
205
 
 
206
 
  Bitmap_File_Head.biSize    = ToL (&buffer[0x00]);
207
 
 
208
 
  /* What kind of bitmap is it? */
209
 
 
210
 
  if (Bitmap_File_Head.biSize == 12) /* OS/2 1.x ? */
211
 
    {
212
 
      if (!ReadOK (fd, buffer, 8))
213
 
        {
214
 
          g_message (_("Error reading BMP file header from '%s'"),
215
 
                      gimp_filename_to_utf8 (filename));
216
 
          return -1;
217
 
        }
218
 
 
219
 
      Bitmap_Head.biWidth   = ToS (&buffer[0x00]);       /* 12 */
220
 
      Bitmap_Head.biHeight  = ToS (&buffer[0x02]);       /* 14 */
221
 
      Bitmap_Head.biPlanes  = ToS (&buffer[0x04]);       /* 16 */
222
 
      Bitmap_Head.biBitCnt  = ToS (&buffer[0x06]);       /* 18 */
223
 
      Bitmap_Head.biCompr   = 0;
224
 
      Bitmap_Head.biSizeIm  = 0;
225
 
      Bitmap_Head.biXPels   = Bitmap_Head.biYPels = 0;
226
 
      Bitmap_Head.biClrUsed = 0;
227
 
      Bitmap_Head.biClrImp  = 0;
228
 
      Bitmap_Head.masks[0]  = 0;
229
 
      Bitmap_Head.masks[1]  = 0;
230
 
      Bitmap_Head.masks[2]  = 0;
231
 
      Bitmap_Head.masks[3]  = 0;
232
 
 
233
 
      memset(masks, 0, sizeof(masks));
234
 
      Maps = 3;
235
 
    }
236
 
  else if (Bitmap_File_Head.biSize == 40) /* Windows 3.x */
237
 
    {
238
 
      if (!ReadOK (fd, buffer, 36))
239
 
        {
240
 
          g_message (_("Error reading BMP file header from '%s'"),
241
 
                      gimp_filename_to_utf8 (filename));
242
 
          return -1;
243
 
        }
244
 
      Bitmap_Head.biWidth   = ToL (&buffer[0x00]);      /* 12 */
245
 
      Bitmap_Head.biHeight  = ToL (&buffer[0x04]);      /* 16 */
246
 
      Bitmap_Head.biPlanes  = ToS (&buffer[0x08]);       /* 1A */
247
 
      Bitmap_Head.biBitCnt  = ToS (&buffer[0x0A]);      /* 1C */
248
 
      Bitmap_Head.biCompr   = ToL (&buffer[0x0C]);      /* 1E */
249
 
      Bitmap_Head.biSizeIm  = ToL (&buffer[0x10]);      /* 22 */
250
 
      Bitmap_Head.biXPels   = ToL (&buffer[0x14]);      /* 26 */
251
 
      Bitmap_Head.biYPels   = ToL (&buffer[0x18]);      /* 2A */
252
 
      Bitmap_Head.biClrUsed = ToL (&buffer[0x1C]);      /* 2E */
253
 
      Bitmap_Head.biClrImp  = ToL (&buffer[0x20]);      /* 32 */
254
 
      Bitmap_Head.masks[0]  = 0;
255
 
      Bitmap_Head.masks[1]  = 0;
256
 
      Bitmap_Head.masks[2]  = 0;
257
 
      Bitmap_Head.masks[3]  = 0;
258
 
 
259
 
      Maps = 4;
260
 
      memset(masks, 0, sizeof(masks));
261
 
 
262
 
      if (Bitmap_Head.biCompr == BI_BITFIELDS)
263
 
      {
264
 
         if (!ReadOK (fd, buffer, 3 * sizeof (guint32)))
265
 
         {
266
 
            g_message (_("Error reading BMP file header from '%s'"),
267
 
                       gimp_filename_to_utf8 (filename));
268
 
            return -1;
269
 
         }
270
 
         Bitmap_Head.masks[0] = ToL(&buffer[0x00]);
271
 
         Bitmap_Head.masks[1] = ToL(&buffer[0x04]);
272
 
         Bitmap_Head.masks[2] = ToL(&buffer[0x08]);
273
 
         ReadChannelMasks (&Bitmap_Head.masks[0], masks, 3);
274
 
      }
275
 
      else
276
 
         switch (Bitmap_Head.biBitCnt)
277
 
         {
278
 
         case 32:
279
 
            masks[0].mask     = 0x00ff0000;
280
 
            masks[0].shiftin  = 16;
281
 
            masks[0].max_value= (gfloat)255.0;
282
 
            masks[1].mask     = 0x0000ff00;
283
 
            masks[1].shiftin  = 8;
284
 
            masks[1].max_value= (gfloat)255.0;
285
 
            masks[2].mask     = 0x000000ff;
286
 
            masks[2].shiftin  = 0;
287
 
            masks[2].max_value= (gfloat)255.0;
288
 
            masks[3].mask     = 0xff000000;
289
 
            masks[3].shiftin  = 24;
290
 
            masks[3].max_value= (gfloat)255.0;
291
 
            break;
292
 
         case 24:
293
 
            masks[0].mask     = 0xff0000;
294
 
            masks[0].shiftin  = 16;
295
 
            masks[0].max_value= (gfloat)255.0;
296
 
            masks[1].mask     = 0x00ff00;
297
 
            masks[1].shiftin  = 8;
298
 
            masks[1].max_value= (gfloat)255.0;
299
 
            masks[2].mask     = 0x0000ff;
300
 
            masks[2].shiftin  = 0;
301
 
            masks[2].max_value= (gfloat)255.0;
302
 
            masks[3].mask     = 0x0;
303
 
            masks[3].shiftin  = 0;
304
 
            masks[3].max_value= (gfloat)0.0;
305
 
            break;
306
 
         case 16:
307
 
            masks[0].mask     = 0x7c00;
308
 
            masks[0].shiftin  = 10;
309
 
            masks[0].max_value= (gfloat)31.0;
310
 
            masks[1].mask     = 0x03e0;
311
 
            masks[1].shiftin  = 5;
312
 
            masks[1].max_value= (gfloat)31.0;
313
 
            masks[2].mask     = 0x001f;
314
 
            masks[2].shiftin  = 0;
315
 
            masks[2].max_value= (gfloat)31.0;
316
 
            masks[3].mask     = 0x0;
317
 
            masks[3].shiftin  = 0;
318
 
            masks[3].max_value= (gfloat)0.0;
319
 
            break;
320
 
         default:
321
 
            break;
322
 
         }
323
 
    }
324
 
  else if (Bitmap_File_Head.biSize >= 56 && Bitmap_File_Head.biSize <= 64)
325
 
    /* enhanced Windows format with bit masks */
326
 
    {
327
 
      if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4))
328
 
        {
329
 
          g_message (_("Error reading BMP file header from '%s'"),
330
 
                      gimp_filename_to_utf8 (filename));
331
 
          return -1;
332
 
        }
333
 
      Bitmap_Head.biWidth   =ToL (&buffer[0x00]);       /* 12 */
334
 
      Bitmap_Head.biHeight  =ToL (&buffer[0x04]);       /* 16 */
335
 
      Bitmap_Head.biPlanes  =ToS (&buffer[0x08]);       /* 1A */
336
 
      Bitmap_Head.biBitCnt  =ToS (&buffer[0x0A]);       /* 1C */
337
 
      Bitmap_Head.biCompr   =ToL (&buffer[0x0C]);       /* 1E */
338
 
      Bitmap_Head.biSizeIm  =ToL (&buffer[0x10]);       /* 22 */
339
 
      Bitmap_Head.biXPels   =ToL (&buffer[0x14]);       /* 26 */
340
 
      Bitmap_Head.biYPels   =ToL (&buffer[0x18]);       /* 2A */
341
 
      Bitmap_Head.biClrUsed =ToL (&buffer[0x1C]);       /* 2E */
342
 
      Bitmap_Head.biClrImp  =ToL (&buffer[0x20]);       /* 32 */
343
 
      Bitmap_Head.masks[0]  =ToL (&buffer[0x24]);       /* 36 */
344
 
      Bitmap_Head.masks[1]  =ToL (&buffer[0x28]);       /* 3A */
345
 
      Bitmap_Head.masks[2]  =ToL (&buffer[0x2C]);       /* 3E */
346
 
      Bitmap_Head.masks[3]  =ToL (&buffer[0x30]);       /* 42 */
347
 
 
348
 
      Maps = 4;
349
 
      ReadChannelMasks (&Bitmap_Head.masks[0], masks, 4);
350
 
    }
351
 
  else
352
 
    {
353
 
      g_message (_("Error reading BMP file header from '%s'"),
354
 
                  gimp_filename_to_utf8 (filename));
355
 
      return -1;
356
 
    }
357
 
 
358
 
  /* Valid bitpdepthis 1, 4, 8, 16, 24, 32 */
359
 
  /* 16 is awful, we should probably shoot whoever invented it */
360
 
 
361
 
  /* There should be some colors used! */
362
 
 
363
 
  ColormapSize =
364
 
    (Bitmap_File_Head.bfOffs - Bitmap_File_Head.biSize - 14) / Maps;
365
 
 
366
 
  if ((Bitmap_Head.biClrUsed == 0) && (Bitmap_Head.biBitCnt <= 8))
367
 
    ColormapSize = Bitmap_Head.biClrUsed = 1 << Bitmap_Head.biBitCnt;
368
 
 
369
 
  if (ColormapSize > 256)
370
 
    ColormapSize = 256;
371
 
 
372
 
  /* Sanity checks */
373
 
 
374
 
  if (Bitmap_Head.biHeight == 0 || Bitmap_Head.biWidth == 0) {
375
 
      g_message (_("Error reading BMP file header from '%s'"),
376
 
                  gimp_filename_to_utf8 (filename));
377
 
      return -1;
378
 
  }
379
 
 
380
 
  if (Bitmap_Head.biWidth < 0)
381
 
    {
382
 
      g_message (_("'%s' is not a valid BMP file"),
383
 
                  gimp_filename_to_utf8 (filename));
384
 
      return -1;
385
 
    }
386
 
 
387
 
  if (Bitmap_Head.biPlanes != 1) {
388
 
      g_message (_("Error reading BMP file header from '%s'"),
389
 
                  gimp_filename_to_utf8 (filename));
390
 
      return -1;
391
 
  }
392
 
 
393
 
  if (Bitmap_Head.biClrUsed > 256) {
394
 
      g_message (_("Error reading BMP file header from '%s'"),
395
 
                  gimp_filename_to_utf8 (filename));
396
 
      return -1;
397
 
  }
398
 
 
399
 
  /* Windows and OS/2 declare filler so that rows are a multiple of
400
 
   * word length (32 bits == 4 bytes)
401
 
   */
402
 
 
403
 
  rowbytes= ((Bitmap_Head.biWidth * Bitmap_Head.biBitCnt - 1) / 32) * 4 + 4;
404
 
 
405
 
#ifdef DEBUG
406
 
  printf ("\nSize: %u, Colors: %u, Bits: %u, Width: %u, Height: %u, "
407
 
          "Comp: %u, Zeile: %u\n",
408
 
          Bitmap_File_Head.bfSize,
409
 
          Bitmap_Head.biClrUsed,
410
 
          Bitmap_Head.biBitCnt,
411
 
          Bitmap_Head.biWidth,
412
 
          Bitmap_Head.biHeight,
413
 
          Bitmap_Head.biCompr,
414
 
          rowbytes);
415
 
#endif
416
 
 
417
 
  if (Bitmap_Head.biBitCnt <= 8)
418
 
    {
419
 
#ifdef DEBUG
420
 
      printf ("Colormap read\n");
421
 
#endif
422
 
      /* Get the Colormap */
423
 
      if (!ReadColorMap (fd, ColorMap, ColormapSize, Maps, &Grey))
424
 
        return -1;
425
 
    }
426
 
 
427
 
  fseek (fd, Bitmap_File_Head.bfOffs, SEEK_SET);
428
 
 
429
 
  /* Get the Image and return the ID or -1 on error*/
430
 
  image_ID = ReadImage (fd,
431
 
                        Bitmap_Head.biWidth,
432
 
                        ABS (Bitmap_Head.biHeight),
433
 
                        ColorMap,
434
 
                        Bitmap_Head.biClrUsed,
435
 
                        Bitmap_Head.biBitCnt,
436
 
                        Bitmap_Head.biCompr,
437
 
                        rowbytes,
438
 
                        Grey,
439
 
                        masks);
440
 
 
441
 
  if (image_ID < 0)
442
 
    return -1;
443
 
 
444
 
  if (Bitmap_Head.biXPels > 0 && Bitmap_Head.biYPels > 0)
445
 
    {
446
 
      /* Fixed up from scott@asofyet's changes last year, njl195 */
447
 
      gdouble xresolution;
448
 
      gdouble yresolution;
449
 
 
450
 
      /* I don't agree with scott's feeling that Gimp should be
451
 
       * trying to "fix" metric resolution translations, in the
452
 
       * long term Gimp should be SI (metric) anyway, but we
453
 
       * haven't told the Americans that yet  */
454
 
 
455
 
      xresolution = Bitmap_Head.biXPels * 0.0254;
456
 
      yresolution = Bitmap_Head.biYPels * 0.0254;
457
 
 
458
 
      gimp_image_set_resolution (image_ID, xresolution, yresolution);
459
 
    }
460
 
 
461
 
  if (Bitmap_Head.biHeight < 0)
462
 
    gimp_image_flip (image_ID, GIMP_ORIENTATION_VERTICAL);
463
 
 
464
 
  return image_ID;
465
 
}
466
 
 
467
 
static gint32
468
 
ReadImage (FILE     *fd,
469
 
           gint      width,
470
 
           gint      height,
471
 
           guchar    cmap[256][3],
472
 
           gint      ncols,
473
 
           gint      bpp,
474
 
           gint      compression,
475
 
           gint      rowbytes,
476
 
           gboolean  grey,
477
 
           const Bitmap_Channel *masks)
478
 
{
479
 
  guchar             v, n;
480
 
  GimpPixelRgn       pixel_rgn;
481
 
  gint               xpos = 0;
482
 
  gint               ypos = 0;
483
 
  gint32             image;
484
 
  gint32             layer;
485
 
  GimpDrawable      *drawable;
486
 
  guchar            *dest, *temp, *buffer;
487
 
  guchar             gimp_cmap[768];
488
 
  gushort            rgb;
489
 
  glong              rowstride, channels;
490
 
  gint               i, i_max, j, cur_progress, max_progress;
491
 
  gint               total_bytes_read;
492
 
  GimpImageBaseType  base_type;
493
 
  GimpImageType      image_type;
494
 
  guint32            px32;
495
 
 
496
 
  if (! (compression == BI_RGB ||
497
 
      (bpp == 8 && compression == BI_RLE8) ||
498
 
      (bpp == 4 && compression == BI_RLE4) ||
499
 
      (bpp == 16 && compression == BI_BITFIELDS) ||
500
 
      (bpp == 32 && compression == BI_BITFIELDS)))
501
 
    {
502
 
      g_message (_("Unrecognized or invalid BMP compression format."));
503
 
      return -1;
504
 
    }
505
 
 
506
 
  /* Make a new image in GIMP */
507
 
 
508
 
  switch (bpp)
509
 
    {
510
 
    case 32:
511
 
    case 24:
512
 
    case 16:
513
 
      base_type = GIMP_RGB;
514
 
      if (masks[3].mask != 0)
515
 
      {
516
 
         image_type = GIMP_RGBA_IMAGE;
517
 
         channels = 4;
518
 
      }
519
 
      else
520
 
      {
521
 
         image_type = GIMP_RGB_IMAGE;
522
 
         channels = 3;
523
 
      }
524
 
      break;
525
 
 
526
 
    case 8:
527
 
    case 4:
528
 
    case 1:
529
 
      if (grey)
530
 
        {
531
 
          base_type = GIMP_GRAY;
532
 
          image_type = GIMP_GRAY_IMAGE;
533
 
        }
534
 
      else
535
 
        {
536
 
          base_type = GIMP_INDEXED;
537
 
          image_type = GIMP_INDEXED_IMAGE;
538
 
        }
539
 
 
540
 
      channels = 1;
541
 
      break;
542
 
 
543
 
    default:
544
 
      g_message (_("Unsupported or invalid bitdepth."));
545
 
      return -1;
546
 
    }
547
 
 
548
 
  if ((width < 0) || (width > GIMP_MAX_IMAGE_SIZE))
549
 
    {
550
 
      g_message (_("Unsupported or invalid image width: %d"), width);
551
 
      return -1;
552
 
    }
553
 
  if ((height < 0) || (height > GIMP_MAX_IMAGE_SIZE))
554
 
    {
555
 
      g_message (_("Unsupported or invalid image height: %d"), height);
556
 
      return -1;
557
 
    }
558
 
  image = gimp_image_new (width, height, base_type);
559
 
  layer = gimp_layer_new (image, _("Background"),
560
 
                          width, height,
561
 
                          image_type, 100, GIMP_NORMAL_MODE);
562
 
 
563
 
  gimp_image_set_filename (image, filename);
564
 
 
565
 
  gimp_image_add_layer (image, layer, 0);
566
 
  drawable = gimp_drawable_get (layer);
567
 
 
568
 
  /* use g_malloc0 to initialize the dest buffer so that unspecified
569
 
     pixels in RLE bitmaps show up as the zeroth element in the palette.
570
 
  */
571
 
  dest      = g_malloc0 (drawable->width * drawable->height * channels);
572
 
  buffer    = g_malloc (rowbytes);
573
 
  rowstride = drawable->width * channels;
574
 
 
575
 
  ypos = height - 1;  /* Bitmaps begin in the lower left corner */
576
 
  cur_progress = 0;
577
 
  max_progress = height;
578
 
 
579
 
  switch (bpp)
580
 
    {
581
 
    case 32:
582
 
      {
583
 
        while (ReadOK (fd, buffer, rowbytes))
584
 
          {
585
 
            temp = dest + (ypos * rowstride);
586
 
            for (xpos= 0; xpos < width; ++xpos)
587
 
              {
588
 
                px32 = ToL(&buffer[xpos*4]);
589
 
                *(temp++)= (guchar)((px32 & masks[0].mask) >> masks[0].shiftin);
590
 
                *(temp++)= (guchar)((px32 & masks[1].mask) >> masks[1].shiftin);
591
 
                *(temp++)= (guchar)((px32 & masks[2].mask) >> masks[2].shiftin);
592
 
                if (channels > 3)
593
 
                  *(temp++)= (guchar)((px32 & masks[3].mask) >> masks[3].shiftin);
594
 
              }
595
 
            if (ypos == 0)
596
 
              break;
597
 
            --ypos; /* next line */
598
 
            cur_progress++;
599
 
            if ((cur_progress % 5) == 0)
600
 
              gimp_progress_update ((gdouble) cur_progress /
601
 
                                    (gdouble) max_progress);
602
 
          }
603
 
 
604
 
        if (channels == 4)
605
 
          {
606
 
            gboolean  has_alpha = FALSE;
607
 
 
608
 
            /* at least one pixel should have nonzero alpha */
609
 
            for (ypos = 0; ypos < height; ypos++)
610
 
              {
611
 
                temp = dest + (ypos * rowstride);
612
 
                for (xpos = 0; xpos < width; xpos++)
613
 
                  {
614
 
                    if (temp[3])
615
 
                      {
616
 
                        has_alpha = TRUE;
617
 
                        break;
618
 
                      }
619
 
                    temp += 4;
620
 
                  }
621
 
                if (has_alpha)
622
 
                  break;
623
 
              }
624
 
 
625
 
            /* workaround unwanted behaviour when all alpha pixels are zero */
626
 
            if (!has_alpha)
627
 
              {
628
 
                for (ypos = 0; ypos < height; ypos++)
629
 
                  {
630
 
                    temp = dest + (ypos * rowstride);
631
 
                    for (xpos = 0; xpos < width; xpos++)
632
 
                      {
633
 
                        temp[3] = 255;
634
 
                        temp += 4;
635
 
                      }
636
 
                  }
637
 
              }
638
 
          }
639
 
      }
640
 
      break;
641
 
 
642
 
    case 24:
643
 
      {
644
 
        while (ReadOK (fd, buffer, rowbytes))
645
 
          {
646
 
            temp = dest + (ypos * rowstride);
647
 
            for (xpos= 0; xpos < width; ++xpos)
648
 
              {
649
 
                *(temp++)= buffer[xpos * 3 + 2];
650
 
                *(temp++)= buffer[xpos * 3 + 1];
651
 
                *(temp++)= buffer[xpos * 3];
652
 
              }
653
 
            if (ypos == 0)
654
 
              break;
655
 
            --ypos; /* next line */
656
 
            cur_progress++;
657
 
            if ((cur_progress % 5) == 0)
658
 
              gimp_progress_update ((gdouble) cur_progress /
659
 
                                    (gdouble) max_progress);
660
 
          }
661
 
      }
662
 
      break;
663
 
 
664
 
    case 16:
665
 
      {
666
 
        while (ReadOK (fd, buffer, rowbytes))
667
 
          {
668
 
            temp = dest + (ypos * rowstride);
669
 
            for (xpos= 0; xpos < width; ++xpos)
670
 
              {
671
 
                rgb= ToS(&buffer[xpos * 2]);
672
 
                *(temp++) = (guchar)(((rgb & masks[0].mask) >> masks[0].shiftin) * 255.0 / masks[0].max_value + 0.5);
673
 
                *(temp++) = (guchar)(((rgb & masks[1].mask) >> masks[1].shiftin) * 255.0 / masks[1].max_value + 0.5);
674
 
                *(temp++) = (guchar)(((rgb & masks[2].mask) >> masks[2].shiftin) * 255.0 / masks[2].max_value + 0.5);
675
 
                if (channels > 3)
676
 
                  *(temp++) = (guchar)(((rgb & masks[3].mask) >> masks[3].shiftin) * 255.0 / masks[3].max_value + 0.5);
677
 
              }
678
 
            if (ypos == 0)
679
 
              break;
680
 
            --ypos; /* next line */
681
 
            cur_progress++;
682
 
            if ((cur_progress % 5) == 0)
683
 
              gimp_progress_update ((gdouble) cur_progress /
684
 
                                    (gdouble) max_progress);
685
 
          }
686
 
      }
687
 
      break;
688
 
 
689
 
    case 8:
690
 
    case 4:
691
 
    case 1:
692
 
      {
693
 
        if (compression == 0)
694
 
          /* no compression */
695
 
          {
696
 
            while (ReadOK (fd, &v, 1))
697
 
              {
698
 
                for (i = 1; (i <= (8 / bpp)) && (xpos < width); i++, xpos++)
699
 
                  {
700
 
                    temp = dest + (ypos * rowstride) + (xpos * channels);
701
 
                    *temp=( v & ( ((1<<bpp)-1) << (8-(i*bpp)) ) ) >> (8-(i*bpp));
702
 
                    if (grey)
703
 
                      *temp = cmap[*temp][0];
704
 
                  }
705
 
                if (xpos == width)
706
 
                  {
707
 
                    fread(buffer, rowbytes - 1 - (width * bpp - 1) / 8, 1, fd);
708
 
                    if (ypos == 0)
709
 
                      break;
710
 
                    ypos--;
711
 
                    xpos = 0;
712
 
 
713
 
                    cur_progress++;
714
 
                    if ((cur_progress % 5) == 0)
715
 
                      gimp_progress_update ((gdouble) cur_progress /
716
 
                                            (gdouble) max_progress);
717
 
                  }
718
 
                if (ypos < 0)
719
 
                  break;
720
 
              }
721
 
            break;
722
 
          }
723
 
        else
724
 
          {
725
 
            /* compressed image (either RLE8 or RLE4) */
726
 
            while (ypos >= 0 && xpos <= width)
727
 
              {
728
 
                if (!ReadOK (fd, buffer, 2))
729
 
                  {
730
 
                    g_message (_("The bitmap ends unexpectedly."));
731
 
                    break;
732
 
                  }
733
 
 
734
 
                if ((guchar) buffer[0] != 0)
735
 
                  /* Count + Color - record */
736
 
                  {
737
 
                    /* encoded mode run -
738
 
                         buffer[0] == run_length
739
 
                         buffer[1] == pixel data
740
 
                    */
741
 
                    for (j = 0;
742
 
                         ((guchar) j < (guchar) buffer[0]) && (xpos < width);)
743
 
                      {
744
 
#ifdef DEBUG2
745
 
                        printf("%u %u | ",xpos,width);
746
 
#endif
747
 
                        for (i = 1;
748
 
                             ((i <= (8 / bpp)) &&
749
 
                              (xpos < width) &&
750
 
                              ((guchar) j < (unsigned char) buffer[0]));
751
 
                             i++, xpos++, j++)
752
 
                          {
753
 
                            temp = dest + (ypos * rowstride) + (xpos * channels);
754
 
                            *temp = (buffer[1] &
755
 
                                     (((1<<bpp)-1) << (8 - (i * bpp)))) >> (8 - (i * bpp));
756
 
                            if (grey)
757
 
                              *temp = cmap[*temp][0];
758
 
                          }
759
 
                      }
760
 
                  }
761
 
                if (((guchar) buffer[0] == 0) && ((guchar) buffer[1] > 2))
762
 
                  /* uncompressed record */
763
 
                  {
764
 
                    n = buffer[1];
765
 
                    total_bytes_read = 0;
766
 
                    for (j = 0; j < n; j += (8 / bpp))
767
 
                      {
768
 
                        /* read the next byte in the record */
769
 
                        if (!ReadOK (fd, &v, 1))
770
 
                          {
771
 
                            g_message (_("The bitmap ends unexpectedly."));
772
 
                            break;
773
 
                          }
774
 
                        total_bytes_read++;
775
 
 
776
 
                        /* read all pixels from that byte */
777
 
                        i_max = 8 / bpp;
778
 
                        if (n - j < i_max)
779
 
                          {
780
 
                            i_max = n - j;
781
 
                          }
782
 
 
783
 
                        i = 1;
784
 
                        while ((i <= i_max) && (xpos < width))
785
 
                          {
786
 
                            temp =
787
 
                              dest + (ypos * rowstride) + (xpos * channels);
788
 
                            *temp = (v >> (8-(i*bpp))) & ((1<<bpp)-1);
789
 
                            if (grey)
790
 
                              *temp = cmap[*temp][0];
791
 
                            i++;
792
 
                            xpos++;
793
 
                          }
794
 
                      }
795
 
 
796
 
                    /* absolute mode runs are padded to 16-bit alignment */
797
 
                    if (total_bytes_read % 2)
798
 
                      fread(&v, 1, 1, fd);
799
 
                  }
800
 
                if (((guchar) buffer[0] == 0) && ((guchar) buffer[1]==0))
801
 
                  /* Line end */
802
 
                  {
803
 
                    ypos--;
804
 
                    xpos = 0;
805
 
 
806
 
                    cur_progress++;
807
 
                    if ((cur_progress % 5) == 0)
808
 
                      gimp_progress_update ((gdouble) cur_progress /
809
 
                                            (gdouble)  max_progress);
810
 
                  }
811
 
                if (((guchar) buffer[0]==0) && ((guchar) buffer[1]==1))
812
 
                  /* Bitmap end */
813
 
                  {
814
 
                    break;
815
 
                  }
816
 
                if (((guchar) buffer[0]==0) && ((guchar) buffer[1]==2))
817
 
                  /* Deltarecord */
818
 
                  {
819
 
                    if (!ReadOK (fd, buffer, 2))
820
 
                      {
821
 
                        g_message (_("The bitmap ends unexpectedly."));
822
 
                        break;
823
 
                      }
824
 
                    xpos += (guchar) buffer[0];
825
 
                    ypos -= (guchar) buffer[1];
826
 
                  }
827
 
              }
828
 
            break;
829
 
          }
830
 
      }
831
 
      break;
832
 
 
833
 
    default:
834
 
      g_assert_not_reached ();
835
 
      break;
836
 
    }
837
 
 
838
 
  fclose (fd);
839
 
  if (bpp <= 8)
840
 
    for (i = 0, j = 0; i < ncols; i++)
841
 
      {
842
 
        gimp_cmap[j++] = cmap[i][0];
843
 
        gimp_cmap[j++] = cmap[i][1];
844
 
        gimp_cmap[j++] = cmap[i][2];
845
 
      }
846
 
 
847
 
  gimp_progress_update (1);
848
 
 
849
 
  gimp_pixel_rgn_init (&pixel_rgn, drawable,
850
 
                       0, 0, drawable->width, drawable->height, TRUE, FALSE);
851
 
  gimp_pixel_rgn_set_rect (&pixel_rgn, dest,
852
 
                           0, 0, drawable->width, drawable->height);
853
 
 
854
 
  if ((!grey) && (bpp<= 8))
855
 
    gimp_image_set_colormap (image, gimp_cmap, ncols);
856
 
 
857
 
  gimp_drawable_flush (drawable);
858
 
  gimp_drawable_detach (drawable);
859
 
  g_free (dest);
860
 
 
861
 
  return image;
862
 
}