10 int read_packed(io_glue *ig, const char *format, ...);
12 read_palette(ico_reader_t *file, ico_image_t *image, int *error);
14 read_24bit_data(ico_reader_t *file, ico_image_t *image, int *error);
16 read_32bit_data(ico_reader_t *file, ico_image_t *image, int *error);
18 read_8bit_data(ico_reader_t *file, ico_image_t *image, int *error);
20 read_4bit_data(ico_reader_t *file, ico_image_t *image, int *error);
22 read_1bit_data(ico_reader_t *file, ico_image_t *image, int *error);
24 read_mask(ico_reader_t *file, ico_image_t *image, int *error);
26 ico_write_validate(ico_image_t const *images, int image_count, int *error);
28 ico_image_size(ico_image_t const *image, int *bits, int *colors);
30 write_packed(i_io_glue_t *ig, char const *format, ...);
32 write_palette(i_io_glue_t *ig, ico_image_t const *image, int *error);
34 write_32_bit(i_io_glue_t *ig, ico_image_t const *image, int *error);
36 write_8_bit(i_io_glue_t *ig, ico_image_t const *image, int *error);
38 write_4_bit(i_io_glue_t *ig, ico_image_t const *image, int *error);
40 write_1_bit(i_io_glue_t *ig, ico_image_t const *image, int *error);
42 write_mask(i_io_glue_t *ig, ico_image_t const *image, int *error);
49 int hotspot_x, hotspot_y;
50 } ico_reader_image_entry;
52 /* this was previously declared, now define it */
53 struct ico_reader_tag {
54 /* the file we're dealing with */
57 /* number of images in the file */
60 /* type of resource - 1=icon, 2=cursor */
63 /* image information from the header */
64 ico_reader_image_entry *images;
70 msicon.c - functions for working with .ICO files.
76 ico_reader_t *file = ico_reader_open(ig, &error);
79 ico_error_message(error, buffer, sizeof(buffer));
80 fputs(buffer, stderr);
83 int count = ico_image_count(file);
84 for (i = 0; i < count; ++i) {
85 ico_image_t *im = ico_image_read(file, index);
86 printf("%d x %d image %d\n", im->width, im->height,
87 im->direct ? "direct" : "paletted");
88 ico_image_release(im);
90 ico_reader_close(file);
94 This is intended as a general interface to reading MS Icon files, and
95 is written to be independent of Imager, even though it is part of
96 Imager. You just need to supply something that acts like Imager's
99 It relies on icon images being generally small, and reads the entire
100 image into memory when reading.
102 =head1 READING ICON FILES
106 =item ico_reader_open(ig, &error)
114 io_glue *ig - an Imager IO object. This must be seekable.
118 int *error - pointer to an integer which an error code will be
119 returned in on failure.
127 ico_reader_open(i_io_glue_t *ig, int *error) {
128 long res1, type, count;
129 ico_reader_t *file = NULL;
132 if (!read_packed(ig, "www", &res1, &type, &count)) {
133 *error = ICOERR_Short_File;
136 if (res1 != 0 || (type != 1 && type != 2) || count == 0) {
137 *error = ICOERR_Invalid_File;
141 file = malloc(sizeof(ico_reader_t));
143 *error = ICOERR_Out_Of_Memory;
149 file->images = malloc(sizeof(ico_reader_image_entry) * count);
150 if (file->images == NULL) {
151 *error = ICOERR_Out_Of_Memory;
156 for (i = 0; i < count; ++i) {
157 long width, height, bytes_in_res, image_offset;
159 ico_reader_image_entry *image = file->images + i;
160 if (type == ICON_ICON) {
161 if (!read_packed(ig, "bb xxxxxx dd", &width, &height, &bytes_in_res,
165 *error = ICOERR_Short_File;
168 image->hotspot_x = image->hotspot_y = 0;
171 long hotspot_x, hotspot_y;
173 if (!read_packed(ig, "bb xx ww dd", &width, &height,
174 &hotspot_x, &hotspot_y, &bytes_in_res,
178 *error = ICOERR_Short_File;
181 image->hotspot_x = hotspot_x;
182 image->hotspot_y = hotspot_y;
185 image->width = width;
186 image->height = height;
187 image->offset = image_offset;
188 image->size = bytes_in_res;
195 =item ico_image_count
197 // number of images in the file
198 count = ico_image_count(file);
204 ico_image_count(ico_reader_t *file) {
211 // type of file - ICON_ICON for icon, ICON_CURSOR for cursor
212 type = ico_type(file);
218 ico_type(ico_reader_t *file) {
225 Read an image from the file given it's index.
231 ico_image_read(ico_reader_t *file, int index, int *error) {
232 io_glue *ig = file->ig;
233 ico_reader_image_entry *im;
234 long bi_size, width, height, planes, bit_count;
237 if (index < 0 || index >= file->count) {
238 *error = ICOERR_Bad_Image_Index;
242 im = file->images + index;
243 if (i_io_seek(ig, im->offset, SEEK_SET) != im->offset) {
244 *error = ICOERR_File_Error;
248 if (!read_packed(ig, "dddww xxxx xxxx xxxx xxxx xxxx xxxx", &bi_size,
249 &width, &height, &planes, &bit_count)) {
250 *error = ICOERR_Short_File;
254 /* the bitmapinfoheader height includes the height of
255 the and and xor masks */
256 if (bi_size != 40 || width != im->width || height != im->height * 2
257 || planes != 1) { /* don't know how to handle planes != 1 */
258 *error = ICOERR_Invalid_File;
262 if (bit_count != 1 && bit_count != 4 && bit_count != 8
263 && bit_count != 24 && bit_count != 32) {
264 *error = ICOERR_Unknown_Bits;
268 result = malloc(sizeof(ico_image_t));
270 *error = ICOERR_Out_Of_Memory;
273 result->width = width;
274 result->height = im->height;
275 result->direct = bit_count > 8;
276 result->bit_count = bit_count;
277 result->palette = NULL;
278 result->image_data = NULL;
279 result->mask_data = NULL;
280 result->hotspot_x = im->hotspot_x;
281 result->hotspot_y = im->hotspot_y;
283 if (bit_count == 32) {
284 result->palette_size = 0;
286 result->image_data = malloc(result->width * result->height * sizeof(ico_color_t));
287 if (!result->image_data) {
289 *error = ICOERR_Out_Of_Memory;
292 if (!read_32bit_data(file, result, error)) {
293 free(result->image_data);
298 else if (bit_count == 24) {
299 result->palette_size = 0;
301 result->image_data = malloc(result->width * result->height * sizeof(ico_color_t));
302 if (!result->image_data) {
304 *error = ICOERR_Out_Of_Memory;
307 if (!read_24bit_data(file, result, error)) {
308 free(result->image_data);
316 result->palette_size = 1 << bit_count;
317 result->palette = malloc(sizeof(ico_color_t) * result->palette_size);
318 if (!result->palette) {
320 *error = ICOERR_Out_Of_Memory;
324 result->image_data = malloc(result->width * result->height);
325 if (!result->image_data) {
326 *error = ICOERR_Out_Of_Memory;
327 free(result->palette);
332 if (!read_palette(file, result, error)) {
333 free(result->palette);
334 free(result->image_data);
341 read_result = read_1bit_data(file, result, error);
345 read_result = read_4bit_data(file, result, error);
349 read_result = read_8bit_data(file, result, error);
353 assert(0); /* this can't happen in theory */
359 free(result->palette);
360 free(result->image_data);
366 result->mask_data = malloc(result->width * result->height);
367 if (!result->mask_data) {
368 *error = ICOERR_Out_Of_Memory;
369 free(result->palette);
370 free(result->image_data);
375 if (!read_mask(file, result, error)) {
376 free(result->mask_data);
377 free(result->palette);
378 free(result->image_data);
387 =item ico_image_release
389 Release an image structure returned by ico_image_read.
395 ico_image_release(ico_image_t *image) {
396 free(image->mask_data);
397 free(image->palette);
398 free(image->image_data);
403 =item ico_reader_close
405 Releases the read file structure.
411 ico_reader_close(ico_reader_t *file) {
412 i_io_close(file->ig);
420 =head1 WRITING ICON FILES
424 =item ico_write(ig, images, image_count, type, &error)
432 io_glue *ig - an Imager IO object. This only needs to implement
433 writing for ico_write()
437 ico_image_t *images - array of images to be written.
441 int image_count - number of images
445 int type - must be ICON_ICON or ICON_CURSOR
449 int *error - set to an error code on failure.
453 Returns non-zero on success.
459 ico_write(i_io_glue_t *ig, ico_image_t const *images, int image_count,
460 int type, int *error) {
462 int start_offset = 6 + 16 * image_count;
463 int current_offset = start_offset;
465 if (type != ICON_ICON && type != ICON_CURSOR) {
466 *error = ICOERR_Bad_File_Type;
470 /* validate the images */
471 if (!ico_write_validate(images, image_count, error))
474 /* write the header */
475 if (!write_packed(ig, "www", 0, type, image_count)) {
476 *error = ICOERR_Write_Failure;
480 /* work out the offsets of each image */
481 for (i = 0; i < image_count; ++i) {
482 ico_image_t const *image = images + i;
484 int size = ico_image_size(image, &bits, &colors);
486 if (type == ICON_ICON) {
487 if (!write_packed(ig, "bbbbwwdd", image->width, image->height,
488 colors, 0, 1, bits, (unsigned long)size,
489 (unsigned long)current_offset)) {
490 *error = ICOERR_Write_Failure;
495 int hotspot_x = image->hotspot_x;
496 int hotspot_y = image->hotspot_y;
500 else if (hotspot_x >= image->width)
501 hotspot_x = image->width - 1;
504 else if (hotspot_y >= image->height)
505 hotspot_y = image->height - 1;
507 if (!write_packed(ig, "bbbbwwdd", image->width, image->height,
508 colors, 0, hotspot_x, hotspot_y, (unsigned long)size,
509 (unsigned long)current_offset)) {
510 *error = ICOERR_Write_Failure;
514 current_offset += size;
517 /* write out each image */
518 for (i = 0; i < image_count; ++i) {
519 ico_image_t const *image = images + i;
522 if (!write_32_bit(ig, image, error))
526 if (image->palette_size <= 2) {
527 if (!write_1_bit(ig, image, error))
530 else if (image->palette_size <= 16) {
531 if (!write_4_bit(ig, image, error))
535 if (!write_8_bit(ig, image, error))
539 if (!write_mask(ig, image, error))
549 =head1 ERROR MESSAGES
553 =item ico_error_message
555 Converts an error code into an error message.
561 ico_error_message(int error, char *buffer, size_t buffer_size) {
566 case ICOERR_Short_File:
570 case ICOERR_File_Error:
574 case ICOERR_Write_Failure:
575 msg = "Write failure";
578 case ICOERR_Invalid_File:
579 msg = "Not an icon file";
582 case ICOERR_Unknown_Bits:
583 msg = "Unknown value for bits/pixel";
586 case ICOERR_Bad_Image_Index:
587 msg = "Image index out of range";
590 case ICOERR_Bad_File_Type:
591 msg = "Bad file type parameter";
594 case ICOERR_Invalid_Width:
595 msg = "Invalid image width";
598 case ICOERR_Invalid_Height:
599 msg = "Invalid image height";
602 case ICOERR_Invalid_Palette:
603 msg = "Invalid Palette";
607 msg = "No image data in image supplied to ico_write";
610 case ICOERR_Out_Of_Memory:
611 msg = "Out of memory";
615 msg = "Unknown error code";
619 size = strlen(msg) + 1;
620 if (size > buffer_size)
622 memcpy(buffer, msg, size);
623 buffer[size-1] = '\0';
631 =head1 PRIVATE FUNCTIONS
637 Reads packed data from a stream, unpacking it.
643 int read_packed(io_glue *ig, const char *format, ...) {
644 unsigned char buffer[100];
651 /* read efficiently, work out the size of the buffer */
655 switch (*formatp++) {
657 case 'x': size += 1; break;
658 case 'w': size += 2; break;
659 case 'd': size += 4; break;
660 case ' ': break; /* space to separate components */
662 fprintf(stderr, "invalid unpack char in %s\n", format);
667 if (size > sizeof(buffer)) {
668 /* catch if we need a bigger buffer, but 100 is plenty */
669 fprintf(stderr, "format %s too long for buffer\n", format);
673 if (i_io_read(ig, buffer, size) != size) {
677 va_start(ap, format);
684 p = va_arg(ap, long *);
689 p = va_arg(ap, long *);
690 *p = bufp[0] + (bufp[1] << 8);
695 p = va_arg(ap, long *);
696 *p = bufp[0] + (bufp[1] << 8) + (bufp[2] << 16) + (bufp[3] << 24);
701 ++bufp; /* skip a byte */
716 Reads the palette data for an icon image.
723 read_palette(ico_reader_t *file, ico_image_t *image, int *error) {
724 int palette_bytes = image->palette_size * 4;
725 unsigned char *read_buffer = malloc(palette_bytes);
731 *error = ICOERR_Out_Of_Memory;
735 if (i_io_read(file->ig, read_buffer, palette_bytes) != palette_bytes) {
736 *error = ICOERR_Short_File;
742 outp = image->palette;
743 for (i = 0; i < image->palette_size; ++i) {
757 =item read_32bit_data
759 Reads 32 bit image data.
766 read_32bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
767 int line_bytes = image->width * 4;
768 unsigned char *buffer = malloc(line_bytes);
775 *error = ICOERR_Out_Of_Memory;
779 for (y = image->height - 1; y >= 0; --y) {
780 if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
782 *error = ICOERR_Short_File;
785 outp = image->image_data;
786 outp += y * image->width;
788 for (x = 0; x < image->width; ++x) {
803 =item read_24bit_data
805 Reads 24 bit image data.
812 read_24bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
813 int line_bytes = image->width * 3;
814 unsigned char *buffer;
820 line_bytes = (line_bytes + 3) / 4 * 4;
822 buffer = malloc(line_bytes);
825 *error = ICOERR_Out_Of_Memory;
829 for (y = image->height - 1; y >= 0; --y) {
830 if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
832 *error = ICOERR_Short_File;
835 outp = image->image_data;
836 outp += y * image->width;
838 for (x = 0; x < image->width; ++x) {
855 Reads 8 bit image data.
862 read_8bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
863 int line_bytes = (image->width + 3) / 4 * 4;
864 unsigned char *buffer = malloc(line_bytes);
867 unsigned char *inp, *outp;
870 *error = ICOERR_Out_Of_Memory;
874 for (y = image->height - 1; y >= 0; --y) {
875 outp = image->image_data;
876 outp += y * image->width;
877 if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
879 *error = ICOERR_Short_File;
882 for (x = 0, inp = buffer; x < image->width; ++x) {
894 Reads 4 bit image data.
901 read_4bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
902 /* 2 pixels per byte, rounded up to the nearest dword */
903 int line_bytes = ((image->width + 1) / 2 + 3) / 4 * 4;
904 unsigned char *read_buffer = malloc(line_bytes);
907 unsigned char *inp, *outp;
910 *error = ICOERR_Out_Of_Memory;
914 for (y = image->height - 1; y >= 0; --y) {
915 if (i_io_read(file->ig, read_buffer, line_bytes) != line_bytes) {
917 *error = ICOERR_Short_File;
921 outp = image->image_data;
922 outp += y * image->width;
924 for (x = 0; x < image->width; ++x) {
925 /* yes, this is kind of ugly */
927 *outp++ = *inp++ & 0x0F;
942 Reads 1 bit image data.
949 read_1bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
950 /* 8 pixels per byte, rounded up to the nearest dword */
951 int line_bytes = ((image->width + 7) / 8 + 3) / 4 * 4;
952 unsigned char *read_buffer = malloc(line_bytes);
955 unsigned char *inp, *outp;
958 *error = ICOERR_Out_Of_Memory;
962 for (y = image->height - 1; y >= 0; --y) {
963 if (i_io_read(file->ig, read_buffer, line_bytes) != line_bytes) {
965 *error = ICOERR_Short_File;
969 outp = image->image_data;
970 outp += y * image->width;
972 for (x = 0; x < image->width; ++x) {
973 *outp++ = (*inp >> (7 - (x & 7))) & 1;
983 /* this is very similar to the 1 bit reader <sigh> */
987 Reads the AND mask from an icon image.
994 read_mask(ico_reader_t *file, ico_image_t *image, int *error) {
995 /* 8 pixels per byte, rounded up to the nearest dword */
996 int line_bytes = ((image->width + 7) / 8 + 3) / 4 * 4;
997 unsigned char *read_buffer = malloc(line_bytes);
1001 unsigned char *inp, *outp;
1004 *error = ICOERR_Out_Of_Memory;
1008 for (y = image->height - 1; y >= 0; --y) {
1009 if (i_io_read(file->ig, read_buffer, line_bytes) != line_bytes) {
1011 *error = ICOERR_Short_File;
1015 outp = image->mask_data + y * image->width;
1018 for (x = 0; x < image->width; ++x) {
1019 *outp++ = (*inp & mask) ? 1 : 0;
1033 =item ico_write_validate
1035 Check each image to make sure it can go into an icon file.
1041 ico_write_validate(ico_image_t const *images, int image_count, int *error) {
1044 for (i = 0; i < image_count; ++i) {
1045 ico_image_t const *image = images + i;
1047 if (image->width < 1 || image->width > 255) {
1048 *error = ICOERR_Invalid_Width;
1051 if (image->height < 1 || image->height > 255) {
1052 *error = ICOERR_Invalid_Height;
1055 if (!image->image_data) {
1056 *error = ICOERR_No_Data;
1059 if (!image->direct) {
1060 if (image->palette_size < 0 || image->palette_size > 256
1061 || !image->palette) {
1062 *error = ICOERR_Invalid_Palette;
1072 =item ico_image_size
1074 Calculate how much space the icon takes up in the file.
1080 ico_image_size(ico_image_t const *image, int *bits, int *colors) {
1081 int size = 40; /* start with the BITMAPINFOHEADER */
1083 /* add in the image area */
1084 if (image->direct) {
1087 size += image->width * 4 * image->height;
1090 if (image->palette_size <= 2) {
1094 else if (image->palette_size <= 16) {
1104 size += *colors * 4;
1106 /* image data size */
1107 size += (image->width * *bits + 31) / 32 * 4 * image->height;
1110 /* add in the mask */
1111 size += (image->width + 31) / 32 * 4 * image->height;
1119 Pack numbers given a format to a stream.
1125 write_packed(i_io_glue_t *ig, char const *format, ...) {
1126 unsigned char buffer[100];
1130 const char *formatp;
1131 unsigned char *bufp;
1133 /* write efficiently, work out the size of the buffer */
1137 switch (*formatp++) {
1138 case 'b': size++; break;
1139 case 'w': size += 2; break;
1140 case 'd': size += 4; break;
1141 case ' ': break; /* space to separate components */
1143 fprintf(stderr, "invalid unpack char in %s\n", format);
1148 if (size > sizeof(buffer)) {
1149 /* catch if we need a bigger buffer, but 100 is plenty */
1150 fprintf(stderr, "format %s too long for buffer\n", format);
1154 va_start(ap, format);
1161 p = va_arg(ap, int);
1166 p = va_arg(ap, int);
1168 *bufp++ = (p >> 8) & 0xFF;
1172 p = va_arg(ap, unsigned long);
1174 *bufp++ = (p >> 8) & 0xFF;
1175 *bufp++ = (p >> 16) & 0xFF;
1176 *bufp++ = (p >> 24) & 0xFF;
1186 if (i_io_write(ig, buffer, size) != size)
1195 Write the palette for an icon.
1201 write_palette(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1202 int full_size = image->palette_size;
1203 unsigned char *writebuf, *outp;
1204 ico_color_t *colorp;
1207 if (image->palette_size <= 2)
1209 else if (image->palette_size <= 16)
1214 writebuf = calloc(full_size, 4);
1216 *error = ICOERR_Out_Of_Memory;
1220 colorp = image->palette;
1221 for (i = 0; i < image->palette_size; ++i) {
1222 *outp++ = colorp->b;
1223 *outp++ = colorp->g;
1224 *outp++ = colorp->r;
1228 for (; i < full_size; ++i) {
1235 if (i_io_write(ig, writebuf, full_size * 4) != full_size * 4) {
1236 *error = ICOERR_Write_Failure;
1247 =item write_bitmapinfoheader
1249 Write the BITMAPINFOHEADER for an icon image.
1255 write_bitmapinfoheader(i_io_glue_t *ig, ico_image_t const *image, int *error,
1256 int bit_count, int clr_used) {
1257 if (!write_packed(ig, "d dd w w d d dd dd",
1259 (unsigned long)image->width,
1260 (unsigned long)2 * image->height, /* biWidth/biHeight */
1261 1, bit_count, /* biPlanes, biBitCount */
1262 0UL, 0UL, /* biCompression, biSizeImage */
1263 0UL, 0UL, /* bi(X|Y)PetsPerMeter */
1264 (unsigned long)clr_used, /* biClrUsed */
1265 0UL)) { /* biClrImportant */
1266 *error = ICOERR_Write_Failure;
1276 Write 32-bit image data to the icon.
1282 write_32_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1283 unsigned char *writebuf;
1284 ico_color_t *data = image->image_data, *colorp;
1285 unsigned char *writep;
1288 if (!write_bitmapinfoheader(ig, image, error, 32, 0)) {
1292 writebuf = malloc(image->width * 4);
1294 *error = ICOERR_Out_Of_Memory;
1298 for (y = image->height-1; y >= 0; --y) {
1300 colorp = data + y * image->width;
1301 for (x = 0; x < image->width; ++x) {
1302 *writep++ = colorp->b;
1303 *writep++ = colorp->g;
1304 *writep++ = colorp->r;
1305 *writep++ = colorp->a;
1308 if (i_io_write(ig, writebuf, image->width * 4) != image->width * 4) {
1309 *error = ICOERR_Write_Failure;
1323 Write 8 bit image data.
1329 write_8_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1330 static const unsigned char zeros[3] = { '\0' };
1332 const unsigned char *data = image->image_data;
1333 int zero_count = (0U - (unsigned)image->width) & 3;
1335 if (!write_bitmapinfoheader(ig, image, error, 8, 256)) {
1339 if (!write_palette(ig, image, error))
1342 for (y = image->height-1; y >= 0; --y) {
1343 if (i_io_write(ig, data + y * image->width,
1344 image->width) != image->width) {
1345 *error = ICOERR_Write_Failure;
1349 if (i_io_write(ig, zeros, zero_count) != zero_count) {
1350 *error = ICOERR_Write_Failure;
1362 Write 4 bit image data.
1368 write_4_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1369 int line_size = ((image->width + 1) / 2 + 3) / 4 * 4;
1370 unsigned char *writebuf, *outp;
1372 unsigned char const *data = image->image_data;
1373 unsigned char const *pixelp;
1375 if (!write_bitmapinfoheader(ig, image, error, 4, 16)) {
1379 if (!write_palette(ig, image, error))
1382 writebuf = malloc(line_size);
1384 *error = ICOERR_Out_Of_Memory;
1388 for (y = image->height-1; y >= 0; --y) {
1389 pixelp = data + y * image->width;
1391 memset(writebuf, 0, line_size);
1392 for (x = 0; x < image->width; ++x) {
1394 *outp |= *pixelp++ & 0x0F;
1398 *outp |= *pixelp++ << 4;
1402 if (i_io_write(ig, writebuf, line_size) != line_size) {
1403 *error = ICOERR_Write_Failure;
1417 Write 1 bit image data.
1423 write_1_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1424 int line_size = (image->width + 31) / 32 * 4;
1425 unsigned char *writebuf = malloc(line_size);
1426 unsigned char *outp;
1427 unsigned char const *data, *pixelp;
1431 if (!write_bitmapinfoheader(ig, image, error, 1, 2)) {
1435 if (!write_palette(ig, image, error))
1439 *error = ICOERR_Out_Of_Memory;
1443 data = image->image_data;
1444 for (y = image->height-1; y >= 0; --y) {
1445 memset(writebuf, 0, line_size);
1446 pixelp = data + y * image->width;
1449 for (x = 0; x < image->width; ++x) {
1458 if (i_io_write(ig, writebuf, line_size) != line_size) {
1459 *error = ICOERR_Write_Failure;
1479 write_mask(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1480 int line_size = (image->width + 31) / 32 * 4;
1481 unsigned char *writebuf = malloc(line_size);
1482 unsigned char *outp;
1483 unsigned char const *data, *pixelp;
1488 *error = ICOERR_Out_Of_Memory;
1492 data = image->mask_data;
1494 for (y = image->height-1; y >= 0; --y) {
1495 memset(writebuf, 0, line_size);
1496 pixelp = data + y * image->width;
1499 for (x = 0; x < image->width; ++x) {
1509 if (i_io_write(ig, writebuf, line_size) != line_size) {
1510 *error = ICOERR_Write_Failure;
1517 memset(writebuf, 0, line_size);
1518 for (y = image->height-1; y >= 0; --y) {
1519 if (i_io_write(ig, writebuf, line_size) != line_size) {
1520 *error = ICOERR_Write_Failure;
1537 Tony Cook <tonyc@cpan.org>