~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to plug-ins/winicon/icoload.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
 
1
/* GIMP - The GNU Image Manipulation Program
2
2
 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
3
3
 *
4
4
 * GIMP Plug-in for Windows Icon files.
23
23
 
24
24
#include <errno.h>
25
25
#include <string.h>
26
 
#include <stdio.h>
 
26
 
 
27
#include <glib/gstdio.h>
27
28
 
28
29
#include <libgimp/gimp.h>
 
30
#include <libgimp/gimpui.h>
 
31
 
 
32
#include <png.h>
29
33
 
30
34
/* #define ICO_DBG */
31
35
 
32
36
#include "main.h"
 
37
#include "icoload.h"
33
38
 
34
39
#include "libgimp/stdplugins-intl.h"
35
40
 
45
50
#define B_VAL_GIMP(p) ((guchar *)(p))[2]
46
51
 
47
52
 
48
 
static gint       ico_read_int8  (FILE *fp, guint8 *data, gint count);
49
 
static gint       ico_read_int16 (FILE *fp, guint16 *data, gint count);
50
 
static gint       ico_read_int32 (FILE *fp, guint32 *data, gint count);
51
 
static gboolean   ico_init       (const gchar *filename, MsIcon *ico);
52
 
static void       ico_read_entry (MsIcon *ico, MsIconEntry* entry);
53
 
static void       ico_read_data  (MsIcon *ico, gint icon_num);
54
 
static void       ico_load       (MsIcon *ico);
55
 
static gint32     ico_to_gimp    (MsIcon *ico);
56
 
 
 
53
static gint       ico_read_int8  (FILE        *fp,
 
54
                                  guint8      *data,
 
55
                                  gint         count);
 
56
static gint       ico_read_int16 (FILE        *fp,
 
57
                                  guint16     *data,
 
58
                                  gint         count);
 
59
static gint       ico_read_int32 (FILE        *fp,
 
60
                                  guint32     *data,
 
61
                                  gint         count);
57
62
 
58
63
static gint
59
 
ico_read_int32 (FILE     *fp,
60
 
                guint32  *data,
61
 
                gint      count)
 
64
ico_read_int32 (FILE    *fp,
 
65
                guint32 *data,
 
66
                gint     count)
62
67
{
63
68
  gint i, total;
64
69
 
75
80
 
76
81
 
77
82
static gint
78
 
ico_read_int16 (FILE     *fp,
79
 
                guint16  *data,
80
 
                gint      count)
 
83
ico_read_int16 (FILE    *fp,
 
84
                guint16 *data,
 
85
                gint     count)
81
86
{
82
87
  gint i, total;
83
88
 
107
112
      bytes = fread ((gchar *) data, sizeof (gchar), count, fp);
108
113
      if (bytes <= 0) /* something bad happened */
109
114
        break;
 
115
 
110
116
      count -= bytes;
111
117
      data += bytes;
112
118
    }
115
121
}
116
122
 
117
123
 
118
 
static gboolean
119
 
ico_init (const gchar *filename,
120
 
          MsIcon      *ico)
121
 
{
122
 
  memset (ico, 0, sizeof (MsIcon));
123
 
 
124
 
  if (! (ico->fp = fopen (filename, "rb")))
125
 
    {
126
 
      g_message (_("Could not open '%s' for reading: %s"),
127
 
                 gimp_filename_to_utf8 (filename), g_strerror (errno));
128
 
      return FALSE;
129
 
    }
130
 
 
131
 
  ico->filename = filename;
132
 
 
133
 
  ico->cp += ico_read_int16 (ico->fp, &ico->reserved, 1);
134
 
  ico->cp += ico_read_int16 (ico->fp, &ico->resource_type, 1);
135
 
 
136
 
  /* Icon files use 1 as resource type, that's  what I wrote this for.
137
 
     From descriptions on the web it seems as if this loader should
138
 
     also be able to handle Win 3.11 - Win 95 cursor files (.cur),
139
 
     which use resource type 2. I haven't tested this though. */
140
 
  if (ico->reserved != 0 ||
141
 
      (ico->resource_type != 1 && ico->resource_type != 2))
142
 
    {
143
 
      ico_cleanup (ico);
144
 
      return FALSE;
145
 
    }
146
 
 
 
124
static guint32
 
125
ico_read_init (FILE *fp)
 
126
{
 
127
  IcoFileHeader header;
 
128
  /* read and check file header */
 
129
  if (!ico_read_int16 (fp, &header.reserved, 1)
 
130
      || !ico_read_int16 (fp, &header.resource_type, 1)
 
131
      || !ico_read_int16 (fp, &header.icon_count, 1)
 
132
      || header.reserved != 0
 
133
      || header.resource_type != 1)
 
134
    {
 
135
      return 0;
 
136
    }
 
137
  return header.icon_count;
 
138
}
 
139
 
 
140
 
 
141
static gboolean
 
142
ico_read_size (FILE        *fp,
 
143
               IcoLoadInfo *info)
 
144
{
 
145
  png_structp png_ptr;
 
146
  png_infop   info_ptr;
 
147
  png_uint_32 w, h;
 
148
  gint32      bpp;
 
149
  gint32      color_type;
 
150
  guint32     magic;
 
151
 
 
152
  if ( fseek (fp, info->offset, SEEK_SET) < 0 )
 
153
    return FALSE;
 
154
 
 
155
  ico_read_int32 (fp, &magic, 1);
 
156
  if (magic == ICO_PNG_MAGIC)
 
157
    {
 
158
      png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL,
 
159
                                        NULL);
 
160
      if ( !png_ptr )
 
161
        return FALSE;
 
162
      info_ptr = png_create_info_struct (png_ptr);
 
163
      if ( !info_ptr )
 
164
        {
 
165
          png_destroy_read_struct (&png_ptr, NULL, NULL);
 
166
          return FALSE;
 
167
        }
 
168
      if (setjmp (png_jmpbuf (png_ptr)))
 
169
        {
 
170
          png_destroy_read_struct (&png_ptr, NULL, NULL);
 
171
          return FALSE;
 
172
        }
 
173
      png_init_io (png_ptr, fp);
 
174
      png_set_sig_bytes (png_ptr, 4);
 
175
      png_read_info (png_ptr, info_ptr);
 
176
      png_get_IHDR (png_ptr, info_ptr, &w, &h, &bpp, &color_type,
 
177
                    NULL, NULL, NULL);
 
178
      png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
 
179
      info->width = w;
 
180
      info->height = h;
 
181
      D(("ico_read_size: PNG: %ix%i\n", info->width, info->height));
 
182
      return TRUE;
 
183
    }
 
184
  else if (magic == 40)
 
185
    {
 
186
      if (ico_read_int32 (fp, &info->width, 1)
 
187
          && ico_read_int32 (fp, &info->height, 1))
 
188
        {
 
189
          info->height /= 2;
 
190
          D(("ico_read_size: ICO: %ix%i\n", info->width, info->height));
 
191
          return TRUE;
 
192
        }
 
193
      else
 
194
        {
 
195
          info->width = 0;
 
196
          info->height = 0;
 
197
          return FALSE;
 
198
        }
 
199
    }
 
200
  return FALSE;
 
201
}
 
202
 
 
203
static IcoLoadInfo*
 
204
ico_read_info (FILE *fp,
 
205
               gint  icon_count)
 
206
{
 
207
  gint            i;
 
208
  IcoFileEntry   *entries;
 
209
  IcoLoadInfo    *info;
 
210
 
 
211
  /* read icon entries */
 
212
  entries = g_new (IcoFileEntry, icon_count);
 
213
  if ( fread (entries, sizeof(IcoFileEntry), icon_count, fp) <= 0 )
 
214
    {
 
215
      g_free (entries);
 
216
      return NULL;
 
217
    }
 
218
 
 
219
  info = g_new (IcoLoadInfo, icon_count);
 
220
  for (i = 0; i < icon_count; i++)
 
221
    {
 
222
      info[i].width = entries[i].width;
 
223
      info[i].height = entries[i].height;
 
224
      info[i].bpp = GUINT16_FROM_LE (entries[i].bpp);
 
225
      info[i].size = GUINT32_FROM_LE (entries[i].size);
 
226
      info[i].offset = GUINT32_FROM_LE (entries[i].offset);
 
227
 
 
228
      if (info[i].width == 0 || info[i].height == 0)
 
229
        {
 
230
          ico_read_size (fp, info+i);
 
231
        }
 
232
 
 
233
      D(("ico_read_info: %ix%i (%i bits, size: %i, offset: %i)\n",
 
234
         info[i].width, info[i].height, info[i].bpp,
 
235
         info[i].size, info[i].offset));
 
236
    }
 
237
 
 
238
  g_free (entries);
 
239
  return info;
 
240
}
 
241
 
 
242
static gboolean
 
243
ico_read_png (FILE    *fp,
 
244
              guint32  header,
 
245
              guchar  *buffer,
 
246
              gint     maxsize,
 
247
              gint    *width,
 
248
              gint    *height)
 
249
{
 
250
  png_structp   png_ptr;
 
251
  png_infop     info;
 
252
  png_uint_32   w;
 
253
  png_uint_32   h;
 
254
  gint32        bit_depth;
 
255
  gint32        color_type;
 
256
  guint32     **rows;
 
257
  gint          i;
 
258
 
 
259
  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 
260
  if ( !png_ptr )
 
261
    return FALSE;
 
262
  info = png_create_info_struct (png_ptr);
 
263
  if ( !info )
 
264
    {
 
265
      png_destroy_read_struct (&png_ptr, NULL, NULL);
 
266
      return FALSE;
 
267
    }
 
268
 
 
269
  if (setjmp (png_jmpbuf (png_ptr)))
 
270
    {
 
271
      png_destroy_read_struct (&png_ptr, &info, NULL);
 
272
      return FALSE;
 
273
    }
 
274
 
 
275
  png_init_io (png_ptr, fp);
 
276
  png_set_sig_bytes (png_ptr, 4);
 
277
  png_read_info (png_ptr, info);
 
278
  png_get_IHDR (png_ptr, info, &w, &h, &bit_depth, &color_type,
 
279
                NULL, NULL, NULL);
 
280
  if (w*h*4 > maxsize)
 
281
    {
 
282
      png_destroy_read_struct (&png_ptr, &info, NULL);
 
283
      return FALSE;
 
284
    }
 
285
  D(("ico_read_png: %ix%i, %i bits, %i type\n", (gint)w, (gint)h,
 
286
     bit_depth, color_type));
 
287
  switch (color_type)
 
288
    {
 
289
    case PNG_COLOR_TYPE_GRAY:
 
290
      png_set_gray_1_2_4_to_8 (png_ptr);
 
291
      if ( bit_depth == 16 )
 
292
        png_set_strip_16 (png_ptr);
 
293
      png_set_gray_to_rgb (png_ptr);
 
294
      png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER);
 
295
      break;
 
296
    case PNG_COLOR_TYPE_GRAY_ALPHA:
 
297
      png_set_gray_1_2_4_to_8 (png_ptr);
 
298
      if ( bit_depth == 16 )
 
299
        png_set_strip_16 (png_ptr);
 
300
      png_set_gray_to_rgb (png_ptr);
 
301
      break;
 
302
    case PNG_COLOR_TYPE_PALETTE:
 
303
      png_set_palette_to_rgb (png_ptr);
 
304
      if (png_get_valid (png_ptr, info, PNG_INFO_tRNS))
 
305
        png_set_tRNS_to_alpha (png_ptr);
 
306
      else
 
307
        png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER);
 
308
      break;
 
309
    case PNG_COLOR_TYPE_RGB:
 
310
      if (bit_depth == 16)
 
311
        png_set_strip_16 (png_ptr);
 
312
      png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER);
 
313
      break;
 
314
    case PNG_COLOR_TYPE_RGB_ALPHA:
 
315
      if (bit_depth == 16)
 
316
        png_set_strip_16 (png_ptr);
 
317
      break;
 
318
    }
 
319
 
 
320
  *width = w;
 
321
  *height = h;
 
322
  rows = g_new (guint32*, h);
 
323
  rows[0] = (guint32*) buffer;
 
324
  for (i = 1; i < h; i++)
 
325
    rows[i] = rows[i-1] + w;
 
326
  png_read_image (png_ptr, (png_bytepp) rows);
 
327
  png_destroy_read_struct (&png_ptr, &info, NULL);
 
328
  g_free (rows);
147
329
  return TRUE;
148
330
}
149
331
 
150
 
 
151
 
static void
152
 
ico_read_entry (MsIcon      *ico,
153
 
                MsIconEntry *entry)
154
 
{
155
 
  if (!ico || !entry)
156
 
    return;
157
 
 
158
 
  ico->cp += ico_read_int8 (ico->fp, &entry->width, 1);
159
 
  ico->cp += ico_read_int8 (ico->fp, &entry->height, 1);
160
 
  ico->cp += ico_read_int8 (ico->fp, &entry->num_colors, 1);
161
 
  ico->cp += ico_read_int8 (ico->fp, &entry->reserved, 1);
162
 
 
163
 
  ico->cp += ico_read_int16 (ico->fp, &entry->num_planes, 1);
164
 
  ico->cp += ico_read_int16 (ico->fp, &entry->bpp, 1);
165
 
 
166
 
  ico->cp += ico_read_int32 (ico->fp, &entry->size, 1);
167
 
  ico->cp += ico_read_int32 (ico->fp, &entry->offset, 1);
168
 
 
169
 
  D(("Read entry with w: "
170
 
     "%i, h: %i, num_colors: %i, bpp: %i, size %i, offset %i\n",
171
 
     entry->width, entry->height, entry->num_colors, entry->bpp,
172
 
     entry->size, entry->offset));
173
 
}
174
 
 
175
 
 
176
 
static void
177
 
ico_read_data (MsIcon *ico,
178
 
               gint    icon_num)
179
 
{
180
 
  MsIconData *data;
181
 
  MsIconEntry *entry;
182
 
  gint length;
183
 
 
184
 
  if (!ico)
185
 
    return;
186
 
 
187
 
  D(("Reading data for icon %i ------------------------------\n", icon_num));
188
 
 
189
 
  entry = &ico->icon_dir[icon_num];
190
 
  data = &ico->icon_data[icon_num];
191
 
 
192
 
  ico->cp = entry->offset;
193
 
 
194
 
  if (fseek (ico->fp, entry->offset, SEEK_SET) < 0)
195
 
    return;
196
 
 
197
 
  D(("  starting at offset %i\n", entry->offset));
198
 
 
199
 
  ico->cp += ico_read_int32 (ico->fp, &data->header_size, 1);
200
 
  ico->cp += ico_read_int32 (ico->fp, &data->width, 1);
201
 
  ico->cp += ico_read_int32 (ico->fp, &data->height, 1);
202
 
 
203
 
  ico->cp += ico_read_int16 (ico->fp, &data->planes, 1);
204
 
  ico->cp += ico_read_int16 (ico->fp, &data->bpp, 1);
205
 
 
206
 
  ico->cp += ico_read_int32 (ico->fp, &data->compression, 1);
207
 
  ico->cp += ico_read_int32 (ico->fp, &data->image_size, 1);
208
 
  ico->cp += ico_read_int32 (ico->fp, &data->x_res, 1);
209
 
  ico->cp += ico_read_int32 (ico->fp, &data->y_res, 1);
210
 
  ico->cp += ico_read_int32 (ico->fp, &data->used_clrs, 1);
211
 
  ico->cp += ico_read_int32 (ico->fp, &data->important_clrs, 1);
212
 
 
213
 
  D(("  header size %i, "
214
 
     "w %i, h %i, planes %i, size %i, bpp %i, used %i, imp %i.\n",
215
 
     data->header_size, data->width, data->height,
216
 
     data->planes, data->image_size, data->bpp,
217
 
     data->used_clrs, data->important_clrs));
218
 
 
219
 
  if (data->bpp <= 8)
220
 
    {
221
 
      if (data->used_clrs == 0)
222
 
        data->used_clrs = (1 << data->bpp);
223
 
 
224
 
      D(("  allocating a %i-slot palette for %i bpp.\n",
225
 
         data->used_clrs, data->bpp));
226
 
 
227
 
      data->palette = g_new0 (guint32, data->used_clrs);
228
 
      ico->cp += ico_read_int8 (ico->fp,
229
 
                                (guint8 *) data->palette, data->used_clrs * 4);
230
 
    }
231
 
 
232
 
  data->xor_map = ico_alloc_map (entry->width, entry->height,
233
 
                                 data->bpp, &length);
234
 
  ico->cp += ico_read_int8 (ico->fp, data->xor_map, length);
235
 
  D(("  length of xor_map: %i\n", length));
236
 
 
237
 
  /* Read in and_map. It's padded out to 32 bits per line: */
238
 
  data->and_map = ico_alloc_map (entry->width, entry->height, 1, &length);
239
 
  ico->cp += ico_read_int8 (ico->fp, data->and_map, length);
240
 
  D(("  length of and_map: %i\n", length));
241
 
}
242
 
 
243
 
 
244
 
static void
245
 
ico_load (MsIcon *ico)
246
 
{
247
 
  gint i;
248
 
 
249
 
  if (!ico)
250
 
    return;
251
 
 
252
 
  ico->cp += ico_read_int16 (ico->fp, &ico->icon_count, 1);
253
 
  ico->icon_dir  = g_new0 (MsIconEntry, ico->icon_count);
254
 
  ico->icon_data = g_new0 (MsIconData, ico->icon_count);
255
 
 
256
 
  D(("*** %s: Microsoft icon file, containing %i icon(s)\n",
257
 
         ico->filename, ico->icon_count));
258
 
 
259
 
  for (i = 0; i < ico->icon_count; i++)
260
 
    ico_read_entry(ico, &ico->icon_dir[i]);
261
 
 
262
 
  for (i = 0; i < ico->icon_count; i++)
263
 
    ico_read_data(ico, i);
264
 
}
265
 
 
266
 
 
267
332
gint
268
 
ico_get_bit_from_data (guint8 *data,
269
 
                       gint    line_width,
270
 
                       gint    bit)
 
333
ico_get_bit_from_data (const guint8 *data,
 
334
                       gint          line_width,
 
335
                       gint          bit)
271
336
{
272
337
  gint line;
273
338
  gint width32;
286
351
 
287
352
 
288
353
gint
289
 
ico_get_nibble_from_data (guint8 *data,
290
 
                          gint    line_width,
291
 
                          gint    nibble)
 
354
ico_get_nibble_from_data (const guint8 *data,
 
355
                          gint          line_width,
 
356
                          gint          nibble)
292
357
{
293
358
  gint line;
294
359
  gint width32;
300
365
  line = nibble / line_width;
301
366
  offset = nibble % line_width;
302
367
 
303
 
  result = (data[line * width32 * 4 + offset/2] & (0x0F << (4 * (1 - offset % 2))));
 
368
  result =
 
369
    (data[line * width32 * 4 + offset/2] & (0x0F << (4 * (1 - offset % 2))));
304
370
 
305
371
  if (offset % 2 == 0)
306
372
    result = result >> 4;
308
374
  return result;
309
375
}
310
376
 
311
 
 
312
377
gint
313
 
ico_get_byte_from_data (guint8 *data,
314
 
                        gint    line_width,
315
 
                        gint    byte)
 
378
ico_get_byte_from_data (const guint8 *data,
 
379
                        gint          line_width,
 
380
                        gint          byte)
316
381
{
317
382
  gint line;
318
383
  gint width32;
319
384
  gint offset;
320
385
 
321
386
  /* width per line in multiples of 32 bits */
322
 
  width32 = (line_width % 4 == 0 ? line_width/4 : line_width/4 + 1);
 
387
  width32 = (line_width % 4 == 0 ? line_width / 4 : line_width / 4 + 1);
323
388
  line = byte / line_width;
324
389
  offset = byte % line_width;
325
390
 
326
391
  return data[line * width32 * 4 + offset];
327
392
}
328
393
 
 
394
static gboolean
 
395
ico_read_icon (FILE    *fp,
 
396
               guint32  header_size,
 
397
               guchar  *buffer,
 
398
               gint     maxsize,
 
399
               gint    *width,
 
400
               gint    *height)
 
401
{
 
402
  IcoFileDataHeader   data;
 
403
  gint                length;
 
404
  gint                x, y, w, h;
 
405
  guchar             *xor_map, *and_map;
 
406
  guint32            *palette;
 
407
  guint32            *dest_vec;
 
408
  guchar             *row;
 
409
  gint                rowstride;
 
410
 
 
411
  palette = NULL;
 
412
 
 
413
  data.header_size = header_size;
 
414
  ico_read_int32 (fp, &data.width, 1);
 
415
  ico_read_int32 (fp, &data.height, 1);
 
416
  ico_read_int16 (fp, &data.planes, 1);
 
417
  ico_read_int16 (fp, &data.bpp, 1);
 
418
  ico_read_int32 (fp, &data.compression, 1);
 
419
  ico_read_int32 (fp, &data.image_size, 1);
 
420
  ico_read_int32 (fp, &data.x_res, 1);
 
421
  ico_read_int32 (fp, &data.y_res, 1);
 
422
  ico_read_int32 (fp, &data.used_clrs, 1);
 
423
  ico_read_int32 (fp, &data.important_clrs, 1);
 
424
 
 
425
  D(("  header size %i, "
 
426
     "w %i, h %i, planes %i, size %i, bpp %i, used %i, imp %i.\n",
 
427
     data.header_size, data.width, data.height,
 
428
     data.planes, data.image_size, data.bpp,
 
429
     data.used_clrs, data.important_clrs));
 
430
 
 
431
  if (data.planes != 1
 
432
      || data.compression != 0)
 
433
    {
 
434
      D(("skipping image: invalid header\n"));
 
435
      return FALSE;
 
436
    }
 
437
 
 
438
  if (data.bpp != 1 && data.bpp != 4
 
439
      && data.bpp != 8 && data.bpp != 24
 
440
      && data.bpp != 32)
 
441
    {
 
442
      D(("skipping image: invalid depth: %i\n", data.bpp));
 
443
      return FALSE;
 
444
    }
 
445
 
 
446
  if (data.width * data.height * 2 > maxsize)
 
447
    {
 
448
      D(("skipping image: too large\n"));
 
449
      return FALSE;
 
450
    }
 
451
 
 
452
  w = data.width;
 
453
  h = data.height / 2;
 
454
 
 
455
  if (data.bpp <= 8)
 
456
    {
 
457
      if (data.used_clrs == 0)
 
458
        data.used_clrs = (1 << data.bpp);
 
459
 
 
460
      D(("  allocating a %i-slot palette for %i bpp.\n",
 
461
         data.used_clrs, data.bpp));
 
462
 
 
463
      palette = g_new0 (guint32, data.used_clrs);
 
464
      ico_read_int8 (fp, (guint8 *) palette, data.used_clrs * 4);
 
465
    }
 
466
 
 
467
  xor_map = ico_alloc_map (w, h, data.bpp, &length);
 
468
  ico_read_int8 (fp, xor_map, length);
 
469
  D(("  length of xor_map: %i\n", length));
 
470
 
 
471
  /* Read in and_map. It's padded out to 32 bits per line: */
 
472
  and_map = ico_alloc_map (w, h, 1, &length);
 
473
  ico_read_int8 (fp, and_map, length);
 
474
  D(("  length of and_map: %i\n", length));
 
475
 
 
476
  dest_vec = (guint32 *) buffer;
 
477
  switch (data.bpp)
 
478
    {
 
479
    case 1:
 
480
      for (y = 0; y < h; y++)
 
481
        for (x = 0; x < w; x++)
 
482
          {
 
483
            guint32 color = palette[ico_get_bit_from_data (xor_map,
 
484
                                                           w, y * w + x)];
 
485
            guint32 *dest = dest_vec + (h - 1 - y) * w + x;
 
486
 
 
487
            R_VAL_GIMP (dest) = R_VAL (&color);
 
488
            G_VAL_GIMP (dest) = G_VAL (&color);
 
489
            B_VAL_GIMP (dest) = B_VAL (&color);
 
490
 
 
491
            if (ico_get_bit_from_data (and_map, w, y * w + x))
 
492
              A_VAL_GIMP (dest) = 0;
 
493
            else
 
494
              A_VAL_GIMP (dest) = 255;
 
495
          }
 
496
      break;
 
497
 
 
498
    case 4:
 
499
      for (y = 0; y < h; y++)
 
500
        for (x = 0; x < w; x++)
 
501
          {
 
502
            guint32 color = palette[ico_get_nibble_from_data (xor_map,
 
503
                                                              w, y * w + x)];
 
504
            guint32 *dest = dest_vec + (h - 1 - y) * w + x;
 
505
 
 
506
            R_VAL_GIMP (dest) = R_VAL (&color);
 
507
            G_VAL_GIMP (dest) = G_VAL (&color);
 
508
            B_VAL_GIMP (dest) = B_VAL (&color);
 
509
 
 
510
            if (ico_get_bit_from_data (and_map, w, y * w + x))
 
511
              A_VAL_GIMP (dest) = 0;
 
512
            else
 
513
              A_VAL_GIMP (dest) = 255;
 
514
          }
 
515
      break;
 
516
 
 
517
    case 8:
 
518
      for (y = 0; y < h; y++)
 
519
        for (x = 0; x < w; x++)
 
520
          {
 
521
            guint32 color = palette[ico_get_byte_from_data (xor_map,
 
522
                                                            w, y * w + x)];
 
523
            guint32 *dest = dest_vec + (h - 1 - y) * w + x;
 
524
 
 
525
            R_VAL_GIMP (dest) = R_VAL (&color);
 
526
            G_VAL_GIMP (dest) = G_VAL (&color);
 
527
            B_VAL_GIMP (dest) = B_VAL (&color);
 
528
 
 
529
            if (ico_get_bit_from_data (and_map, w, y * w + x))
 
530
              A_VAL_GIMP (dest) = 0;
 
531
            else
 
532
              A_VAL_GIMP (dest) = 255;
 
533
          }
 
534
      break;
 
535
 
 
536
    default:
 
537
      {
 
538
        gint bytespp = data.bpp / 8;
 
539
 
 
540
        rowstride = ico_rowstride (w, data.bpp);
 
541
 
 
542
        for (y = 0; y < h; y++)
 
543
          {
 
544
            row = xor_map + rowstride * y;
 
545
 
 
546
            for (x = 0; x < w; x++)
 
547
              {
 
548
                guint32 *dest = dest_vec + (h - 1 - y) * w + x;
 
549
 
 
550
                B_VAL_GIMP (dest) = row[0];
 
551
                G_VAL_GIMP (dest) = row[1];
 
552
                R_VAL_GIMP (dest) = row[2];
 
553
 
 
554
                if (data.bpp < 32)
 
555
                  {
 
556
                    if (ico_get_bit_from_data (and_map, w, y * w + x))
 
557
                      A_VAL_GIMP (dest) = 0;
 
558
                    else
 
559
                      A_VAL_GIMP (dest) = 255;
 
560
                  }
 
561
                else
 
562
                  {
 
563
                    A_VAL_GIMP (dest) = row[3];
 
564
                  }
 
565
 
 
566
                row += bytespp;
 
567
              }
 
568
          }
 
569
      }
 
570
    }
 
571
  if (palette)
 
572
    g_free (palette);
 
573
  g_free (xor_map);
 
574
  g_free (and_map);
 
575
  *width = w;
 
576
  *height = h;
 
577
  return TRUE;
 
578
}
329
579
 
330
580
static gint32
331
 
ico_to_gimp (MsIcon *ico)
332
 
{
333
 
  gint icon_nr, x, y, w, h, max_w, max_h;
334
 
  guint8         *xor_map;
335
 
  guint8         *and_map;
336
 
  guint32        *palette;
337
 
  MsIconData     *idata;
338
 
  MsIconEntry    *ientry;
339
 
  gint32          image, layer, first_layer = -1;
340
 
  const char     *layer_name = N_("Icon #%i");
341
 
  char            s[MAXLEN];
342
 
  guint32        *dest_vec;
343
 
  GimpDrawable   *drawable;
344
 
 
345
 
  /* Do a quick scan of the icons in the file to find the
346
 
     largest icon contained ... */
347
 
 
348
 
  max_w = 0; max_h = 0;
349
 
 
350
 
  for (icon_nr = 0; icon_nr < ico->icon_count; icon_nr++)
351
 
    {
352
 
      if (ico->icon_dir[icon_nr].width > max_w)
353
 
        max_w = ico->icon_dir[icon_nr].width;
354
 
      if (ico->icon_dir[icon_nr].height > max_h)
355
 
        max_h = ico->icon_dir[icon_nr].height;
356
 
    }
357
 
 
358
 
  /* Allocate the Gimp image */
359
 
 
360
 
  image = gimp_image_new (max_w, max_h, GIMP_RGB);
361
 
  gimp_image_set_filename (image, ico->filename);
362
 
 
363
 
  /* Scan icons again and set up a layer for each icon */
364
 
 
365
 
  for (icon_nr = 0; icon_nr < ico->icon_count; icon_nr++)
366
 
    {
367
 
      GimpPixelRgn pixel_rgn;
368
 
 
369
 
      gimp_progress_update ((gdouble) icon_nr / (gdouble) ico->icon_count);
370
 
 
371
 
      w = ico->icon_dir[icon_nr].width;
372
 
      h = ico->icon_dir[icon_nr].height;
373
 
      palette = ico->icon_data[icon_nr].palette;
374
 
      xor_map = ico->icon_data[icon_nr].xor_map;
375
 
      and_map = ico->icon_data[icon_nr].and_map;
376
 
      idata = &ico->icon_data[icon_nr];
377
 
      ientry = &ico->icon_dir[icon_nr];
378
 
 
379
 
      g_snprintf (s, MAXLEN, gettext (layer_name), icon_nr + 1);
380
 
 
381
 
      layer = gimp_layer_new (image, s, w, h,
382
 
                              GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
383
 
 
384
 
      if (first_layer == -1)
385
 
        first_layer = layer;
386
 
 
387
 
      gimp_image_add_layer (image, layer, icon_nr);
388
 
      drawable = gimp_drawable_get (layer);
389
 
 
390
 
      dest_vec = g_malloc (w * h * 4);
391
 
 
392
 
      switch (idata->bpp)
393
 
        {
394
 
        case 1:
395
 
          for (y = 0; y < h; y++)
396
 
            for (x = 0; x < w; x++)
397
 
              {
398
 
                guint32 color = palette[ico_get_bit_from_data (xor_map,
399
 
                                                               w, y * w + x)];
400
 
                guint32 *dest = &(dest_vec[(h-1-y) * w + x]);
401
 
 
402
 
                R_VAL_GIMP (dest) = R_VAL (&color);
403
 
                G_VAL_GIMP (dest) = G_VAL (&color);
404
 
                B_VAL_GIMP (dest) = B_VAL (&color);
405
 
 
406
 
                if (ico_get_bit_from_data (and_map, w, y*w + x))
407
 
                  A_VAL_GIMP (dest) = 0;
408
 
                else
409
 
                  A_VAL_GIMP (dest) = 255;
410
 
              }
411
 
          break;
412
 
 
413
 
        case 4:
414
 
          for (y = 0; y < h; y++)
415
 
            for (x = 0; x < w; x++)
416
 
              {
417
 
                guint32 color = palette[ico_get_nibble_from_data (xor_map,
418
 
                                                                  w, y * w + x)];
419
 
                guint32 *dest = &(dest_vec[(h-1-y) * w + x]);
420
 
 
421
 
                R_VAL_GIMP (dest) = R_VAL (&color);
422
 
                G_VAL_GIMP (dest) = G_VAL (&color);
423
 
                B_VAL_GIMP (dest) = B_VAL (&color);
424
 
 
425
 
                if (ico_get_bit_from_data (and_map, w, y*w + x))
426
 
                  A_VAL_GIMP (dest) = 0;
427
 
                else
428
 
                  A_VAL_GIMP (dest) = 255;
429
 
              }
430
 
          break;
431
 
 
432
 
        case 8:
433
 
          for (y = 0; y < h; y++)
434
 
            for (x = 0; x < w; x++)
435
 
              {
436
 
                guint32 color = palette[ico_get_byte_from_data (xor_map,
437
 
                                                                w, y * w + x)];
438
 
                guint32 *dest = &(dest_vec[(h-1-y) * w + x]);
439
 
 
440
 
                R_VAL_GIMP (dest) = R_VAL (&color);
441
 
                G_VAL_GIMP (dest) = G_VAL (&color);
442
 
                B_VAL_GIMP (dest) = B_VAL (&color);
443
 
 
444
 
                if (ico_get_bit_from_data (and_map, w, y*w + x))
445
 
                  A_VAL_GIMP (dest) = 0;
446
 
                else
447
 
                  A_VAL_GIMP (dest) = 255;
448
 
              }
449
 
          break;
450
 
 
451
 
        default:
452
 
          {
453
 
            int bytespp = idata->bpp/8;
454
 
 
455
 
            for (y = 0; y < h; y++)
456
 
              for (x = 0; x < w; x++)
457
 
                {
458
 
                  guint32 *dest = &(dest_vec[(h-1-y) * w + x]);
459
 
 
460
 
                  B_VAL_GIMP(dest) = xor_map[(y * w + x) * bytespp];
461
 
                  G_VAL_GIMP(dest) = xor_map[(y * w + x) * bytespp + 1];
462
 
                  R_VAL_GIMP(dest) = xor_map[(y * w + x) * bytespp + 2];
463
 
 
464
 
                  if (idata->bpp < 32)
465
 
                    {
466
 
                      if (ico_get_bit_from_data (and_map, w, y*w + x))
467
 
                        A_VAL_GIMP (dest) = 0;
468
 
                      else
469
 
                        A_VAL_GIMP (dest) = 255;
470
 
                    }
471
 
                  else
472
 
                    {
473
 
                      A_VAL_GIMP (dest) = xor_map[(y * w + x) * bytespp + 3];
474
 
                    }
475
 
                }
476
 
          }
477
 
        }
478
 
 
479
 
      gimp_pixel_rgn_init (&pixel_rgn, drawable,
480
 
                           0, 0, drawable->width, drawable->height,
481
 
                           TRUE, FALSE);
482
 
      gimp_pixel_rgn_set_rect (&pixel_rgn, (guchar*) dest_vec,
483
 
                               0, 0, drawable->width, drawable->height);
484
 
 
485
 
      g_free(dest_vec);
486
 
 
487
 
      gimp_drawable_detach (drawable);
488
 
    }
489
 
 
490
 
  gimp_image_set_active_layer (image, first_layer);
491
 
 
492
 
  gimp_progress_update (1.0);
493
 
 
494
 
  return image;
495
 
}
496
 
 
497
 
 
498
 
gint32
499
 
LoadICO (const gchar *filename)
500
 
{
501
 
  gchar  *temp;
502
 
  gint32  image_ID;
503
 
  MsIcon  ico;
504
 
 
505
 
  temp = g_strdup_printf (_("Opening '%s'..."),
506
 
                          gimp_filename_to_utf8 (filename));
507
 
  gimp_progress_init (temp);
508
 
  g_free (temp);
509
 
 
510
 
  if (! ico_init (filename, &ico))
511
 
    return -1;
512
 
 
513
 
  ico_load (&ico);
514
 
 
515
 
  if ( (image_ID = ico_to_gimp (&ico)) < 0)
516
 
    {
517
 
      ico_cleanup (&ico);
518
 
      return -1;
519
 
    }
520
 
 
521
 
  ico_cleanup (&ico);
522
 
 
523
 
  D(("*** icon successfully loaded.\n\n"));
524
 
 
525
 
  return image_ID;
 
581
ico_load_layer (FILE        *fp,
 
582
                gint32       image,
 
583
                gint32       icon_num,
 
584
                guchar      *buffer,
 
585
                gint         maxsize,
 
586
                IcoLoadInfo *info)
 
587
{
 
588
  gint          width, height;
 
589
  gint32        layer;
 
590
  guint32       first_bytes;
 
591
  GimpDrawable *drawable;
 
592
  GimpPixelRgn  pixel_rgn;
 
593
  gchar         buf [ICO_MAXBUF];
 
594
 
 
595
  if ( fseek (fp, info->offset, SEEK_SET) < 0
 
596
       || !ico_read_int32 (fp, &first_bytes, 1) )
 
597
    return -1;
 
598
 
 
599
  if (first_bytes == ICO_PNG_MAGIC)
 
600
    {
 
601
      if (!ico_read_png (fp, first_bytes, buffer, maxsize, &width, &height))
 
602
        return -1;
 
603
    }
 
604
  else if (first_bytes == 40)
 
605
    {
 
606
      if (!ico_read_icon (fp, first_bytes, buffer, maxsize, &width, &height))
 
607
        return -1;
 
608
    }
 
609
  else
 
610
    {
 
611
      return -1;
 
612
    }
 
613
 
 
614
 
 
615
  /* read successfully. add to image */
 
616
  g_snprintf (buf, sizeof (buf), _("Icon #%i"), icon_num+1);
 
617
  layer = gimp_layer_new (image, buf, width, height,
 
618
                          GIMP_RGBA_IMAGE, 100, GIMP_NORMAL_MODE);
 
619
  gimp_image_add_layer (image, layer, icon_num);
 
620
  drawable = gimp_drawable_get (layer);
 
621
  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
 
622
                       drawable->width, drawable->height, TRUE, FALSE);
 
623
  gimp_pixel_rgn_set_rect (&pixel_rgn, (const guchar*) buffer,
 
624
                           0, 0, drawable->width,
 
625
                           drawable->height);
 
626
  gimp_drawable_detach (drawable);
 
627
 
 
628
  return layer;
 
629
}
 
630
 
 
631
 
 
632
gint32
 
633
ico_load_image (const gchar *filename)
 
634
{
 
635
  FILE        *fp;
 
636
  IcoLoadInfo *info;
 
637
  gint         max_width, max_height;
 
638
  gint         i;
 
639
  gint32       image;
 
640
  gint32       layer;
 
641
  guchar      *buffer;
 
642
  guint        icon_count;
 
643
  gint         maxsize;
 
644
 
 
645
  gimp_progress_init_printf (_("Opening '%s'"),
 
646
                             gimp_filename_to_utf8 (filename));
 
647
 
 
648
  fp = g_fopen (filename, "rb");
 
649
  if ( !fp )
 
650
    {
 
651
      g_message (_("Could not open '%s' for reading: %s"),
 
652
                 gimp_filename_to_utf8 (filename), g_strerror (errno));
 
653
      return -1;
 
654
    }
 
655
 
 
656
  icon_count = ico_read_init (fp);
 
657
  if (!icon_count)
 
658
    {
 
659
      fclose (fp);
 
660
      return -1;
 
661
    }
 
662
 
 
663
  info = ico_read_info (fp, icon_count);
 
664
  if (!info)
 
665
    {
 
666
      fclose (fp);
 
667
      return -1;
 
668
    }
 
669
 
 
670
  /* find width and height of image */
 
671
  max_width = 0;
 
672
  max_height = 0;
 
673
  for (i = 0; i < icon_count; i++)
 
674
    {
 
675
      if ( info[i].width > max_width )
 
676
        max_width = info[i].width;
 
677
      if ( info[i].height > max_height )
 
678
        max_height = info[i].height;
 
679
    }
 
680
  if ( max_width <= 0 || max_height <= 0 )
 
681
    {
 
682
      g_free (info);
 
683
      fclose (fp);
 
684
      return -1;
 
685
    }
 
686
  D(("image size: %ix%i\n", max_width, max_height));
 
687
 
 
688
  image = gimp_image_new (max_width, max_height, GIMP_RGB);
 
689
  gimp_image_set_filename (image, filename);
 
690
 
 
691
  maxsize = max_width * max_height * 4;
 
692
  buffer = g_new (guchar, max_width * max_height * 4);
 
693
  for (i = 0; i < icon_count; i++)
 
694
    {
 
695
      layer = ico_load_layer (fp, image, i, buffer, maxsize, info+i);
 
696
    }
 
697
  g_free (buffer);
 
698
  g_free (info);
 
699
  fclose (fp);
 
700
 
 
701
  gimp_progress_update (1.0);
 
702
 
 
703
  return image;
 
704
}
 
705
 
 
706
gint32
 
707
ico_load_thumbnail_image (const gchar *filename,
 
708
                          gint        *width,
 
709
                          gint        *height)
 
710
{
 
711
  FILE        *fp;
 
712
  IcoLoadInfo *info;
 
713
  gint32       image;
 
714
  gint32       layer;
 
715
  gint         w     = 0;
 
716
  gint         h     = 0;
 
717
  gint         bpp   = 0;
 
718
  gint         match = 0;
 
719
  gint         i, icon_count;
 
720
  guchar      *buffer;
 
721
 
 
722
  gimp_progress_init_printf (_("Opening thumbnail for '%s'"),
 
723
                             gimp_filename_to_utf8 (filename));
 
724
 
 
725
  fp = g_fopen (filename, "rb");
 
726
  if ( !fp )
 
727
    {
 
728
      g_message (_("Could not open '%s' for reading: %s"),
 
729
                 gimp_filename_to_utf8 (filename), g_strerror (errno));
 
730
      return -1;
 
731
    }
 
732
 
 
733
  icon_count = ico_read_init (fp);
 
734
  if ( !icon_count )
 
735
    {
 
736
      fclose (fp);
 
737
      return -1;
 
738
    }
 
739
 
 
740
  D(("*** %s: Microsoft icon file, containing %i icon(s)\n",
 
741
     filename, icon_count));
 
742
 
 
743
  info = ico_read_info (fp, icon_count);
 
744
  if ( !info )
 
745
    {
 
746
      fclose (fp);
 
747
      return -1;
 
748
    }
 
749
 
 
750
  /* Do a quick scan of the icons in the file to find the best match */
 
751
  for (i = 0; i < icon_count; i++)
 
752
    {
 
753
      if ((info[i].width  > w && w < *width) ||
 
754
          (info[i].height > h && h < *height))
 
755
        {
 
756
          w = info[i].width;
 
757
          h = info[i].height;
 
758
          bpp = info[i].bpp;
 
759
 
 
760
          match = i;
 
761
        }
 
762
      else if ( w == info[i].width
 
763
                && h == info[i].height
 
764
                && info[i].bpp > bpp )
 
765
        {
 
766
          /* better quality */
 
767
          bpp = info[i].bpp;
 
768
          match = i;
 
769
        }
 
770
    }
 
771
 
 
772
  if (w <= 0 || h <= 0)
 
773
    return -1;
 
774
 
 
775
  image = gimp_image_new (w, h, GIMP_RGB);
 
776
  buffer = g_new (guchar, w*h*4);
 
777
  layer = ico_load_layer (fp, image, match, buffer, w*h*4, info+match);
 
778
  g_free (buffer);
 
779
 
 
780
  *width  = w;
 
781
  *height = h;
 
782
 
 
783
  D(("*** thumbnail successfully loaded.\n\n"));
 
784
 
 
785
  gimp_progress_update (1.0);
 
786
 
 
787
  g_free (info);
 
788
  fclose (fp);
 
789
 
 
790
  return image;
526
791
}