]> git.imager.perl.org - imager.git/blobdiff - ICO/msicon.c
use non-deprecated encoding ids for freetype 2
[imager.git] / ICO / msicon.c
index e8e2d89b8827a64a0983b3f5e2d2fa9ffbfdc2f5..327f306bb391e934a39f3eae3914ff6a1c52b239 100644 (file)
@@ -1,3 +1,4 @@
+#include "imext.h"
 #include "msicon.h"
 #include <string.h>
 #include <stdlib.h>
@@ -10,6 +11,8 @@ int read_packed(io_glue *ig, const char *format, ...);
 static int 
 read_palette(ico_reader_t *file, ico_image_t *image, int *error);
 static int 
+read_24bit_data(ico_reader_t *file, ico_image_t *image, int *error);
+static int 
 read_32bit_data(ico_reader_t *file, ico_image_t *image, int *error);
 static int 
 read_8bit_data(ico_reader_t *file, ico_image_t *image, int *error);
@@ -179,8 +182,9 @@ ico_reader_open(i_io_glue_t *ig, int *error) {
       image->hotspot_y = hotspot_y;
     }
 
-    image->width = width;
-    image->height = height;
+    /* a width or height of zero here indicates a width/height of 256 */
+    image->width = width ? width : 256;
+    image->height = height ? height : 256;
     image->offset = image_offset;
     image->size = bytes_in_res;
   }
@@ -256,7 +260,8 @@ ico_image_read(ico_reader_t *file, int index, int *error) {
     return NULL;
   }
 
-  if (bit_count != 1 && bit_count != 4 && bit_count != 8 && bit_count != 32) {
+  if (bit_count != 1 && bit_count != 4 && bit_count != 8
+      && bit_count != 24 && bit_count != 32) {
     *error = ICOERR_Unknown_Bits;
     return 0;
   }
@@ -291,6 +296,21 @@ ico_image_read(ico_reader_t *file, int index, int *error) {
       return NULL;
     }
   }
+  else if (bit_count == 24) {
+    result->palette_size = 0;
+
+    result->image_data = malloc(result->width * result->height * sizeof(ico_color_t));
+    if (!result->image_data) {
+      free(result);
+      *error = ICOERR_Out_Of_Memory;
+      return NULL;
+    }
+    if (!read_24bit_data(file, result, error)) {
+      free(result->image_data);
+      free(result);
+      return NULL;
+    }
+  }
   else {
     int read_result;
 
@@ -463,9 +483,11 @@ ico_write(i_io_glue_t *ig, ico_image_t const *images, int image_count,
     ico_image_t const *image = images + i;
     int bits, colors;
     int size = ico_image_size(image, &bits, &colors);
+    int width_byte = image->width == 256 ? 0 : image->width;
+    int height_byte = image->height == 256 ? 0 : image->height;
 
     if (type == ICON_ICON) {
-      if (!write_packed(ig, "bbbbwwdd", image->width, image->height,
+      if (!write_packed(ig, "bbbbwwdd", width_byte, height_byte,
                        colors, 0, 1, bits, (unsigned long)size, 
                        (unsigned long)current_offset)) {
        *error = ICOERR_Write_Failure;
@@ -485,7 +507,7 @@ ico_write(i_io_glue_t *ig, ico_image_t const *images, int image_count,
       else if (hotspot_y >= image->height)
        hotspot_y = image->height - 1;
 
-      if (!write_packed(ig, "bbbbwwdd", image->width, image->height,
+      if (!write_packed(ig, "bbbbwwdd", width_byte, height_byte,
                        colors, 0, hotspot_x, hotspot_y, (unsigned long)size, 
                        (unsigned long)current_offset)) {
        *error = ICOERR_Write_Failure;
@@ -674,7 +696,7 @@ int read_packed(io_glue *ig, const char *format, ...) {
 
     case 'd':
       p = va_arg(ap, long *);
-      *p = bufp[0] + (bufp[1] << 8) + (bufp[2] << 16) + (bufp[3] << 24);
+      *p = bufp[0] + (bufp[1] << 8) + (bufp[2] << 16) + ((unsigned long)bufp[3] << 24);
       bufp += 4;
       break;
 
@@ -780,6 +802,56 @@ read_32bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
   return 1;
 }
 
+/*
+=item read_24bit_data
+
+Reads 24 bit image data.
+
+=cut
+*/
+
+static
+int
+read_24bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
+  int line_bytes = image->width * 3;
+  unsigned char *buffer;
+  int y;
+  int x;
+  unsigned char *inp;
+  ico_color_t *outp;
+
+  line_bytes = (line_bytes + 3) / 4 * 4;
+
+  buffer = malloc(line_bytes);
+
+  if (!buffer) {
+    *error = ICOERR_Out_Of_Memory;
+    return 0;
+  }
+
+  for (y = image->height - 1; y >= 0; --y) {
+    if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
+      free(buffer);
+      *error = ICOERR_Short_File;
+      return 0;
+    }
+    outp = image->image_data;
+    outp += y * image->width;
+    inp = buffer;
+    for (x = 0; x < image->width; ++x) {
+      outp->b = inp[0];
+      outp->g = inp[1];
+      outp->r = inp[2];
+      outp->a = 255;
+      ++outp;
+      inp += 3;
+    }
+  }
+  free(buffer);
+
+  return 1;
+}
+
 /*
 =item read_8bit_data
 
@@ -975,11 +1047,11 @@ ico_write_validate(ico_image_t const *images, int image_count, int *error) {
   for (i = 0; i < image_count; ++i) {
     ico_image_t const *image = images + i;
 
-    if (image->width < 1 || image->width > 255) {
+    if (image->width < 1 || image->width > 256) {
       *error = ICOERR_Invalid_Width;
       return 0;
     }
-    if (image->height < 1 || image->height > 255) {
+    if (image->height < 1 || image->height > 256) {
       *error = ICOERR_Invalid_Height;
       return 0;
     }
@@ -1353,7 +1425,7 @@ Write 1 bit image data.
 static int
 write_1_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
   int line_size = (image->width + 31) / 32 * 4;
-  unsigned char *writebuf = malloc(line_size);
+  unsigned char *writebuf;
   unsigned char *outp;
   unsigned char const *data, *pixelp;
   int x,y;
@@ -1366,6 +1438,7 @@ write_1_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
   if (!write_palette(ig, image, error))
     return 0;
 
+  writebuf = malloc(line_size);
   if (!writebuf) {
     *error = ICOERR_Out_Of_Memory;
     return 0;
@@ -1465,7 +1538,7 @@ write_mask(i_io_glue_t *ig, ico_image_t const *image, int *error) {
 
 =head1 AUTHOR
 
-Tony Cook <tony@imager.perl.org>
+Tony Cook <tonyc@cpan.org>
 
 =head1 REVISION