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