9 int read_packed(io_glue *ig, const char *format, ...);
11 read_palette(ico_reader_t *file, ico_image_t *image, int *error);
13 read_24bit_data(ico_reader_t *file, ico_image_t *image, int *error);
15 read_32bit_data(ico_reader_t *file, ico_image_t *image, int *error);
17 read_8bit_data(ico_reader_t *file, ico_image_t *image, int *error);
19 read_4bit_data(ico_reader_t *file, ico_image_t *image, int *error);
21 read_1bit_data(ico_reader_t *file, ico_image_t *image, int *error);
23 read_mask(ico_reader_t *file, ico_image_t *image, int *error);
25 ico_write_validate(ico_image_t const *images, int image_count, int *error);
27 ico_image_size(ico_image_t const *image, int *bits, int *colors);
29 write_packed(i_io_glue_t *ig, char const *format, ...);
31 write_palette(i_io_glue_t *ig, ico_image_t const *image, int *error);
33 write_32_bit(i_io_glue_t *ig, ico_image_t const *image, int *error);
35 write_8_bit(i_io_glue_t *ig, ico_image_t const *image, int *error);
37 write_4_bit(i_io_glue_t *ig, ico_image_t const *image, int *error);
39 write_1_bit(i_io_glue_t *ig, ico_image_t const *image, int *error);
41 write_mask(i_io_glue_t *ig, ico_image_t const *image, int *error);
48 int hotspot_x, hotspot_y;
49 } ico_reader_image_entry;
51 /* this was previously declared, now define it */
52 struct ico_reader_tag {
53 /* the file we're dealing with */
56 /* number of images in the file */
59 /* type of resource - 1=icon, 2=cursor */
62 /* image information from the header */
63 ico_reader_image_entry *images;
69 msicon.c - functions for working with .ICO files.
75 ico_reader_t *file = ico_reader_open(ig, &error);
78 ico_error_message(error, buffer, sizeof(buffer));
79 fputs(buffer, stderr);
82 int count = ico_image_count(file);
83 for (i = 0; i < count; ++i) {
84 ico_image_t *im = ico_image_read(file, index);
85 printf("%d x %d image %d\n", im->width, im->height,
86 im->direct ? "direct" : "paletted");
87 ico_image_release(im);
89 ico_reader_close(file);
93 This is intended as a general interface to reading MS Icon files, and
94 is written to be independent of Imager, even though it is part of
95 Imager. You just need to supply something that acts like Imager's
98 It relies on icon images being generally small, and reads the entire
99 image into memory when reading.
101 =head1 READING ICON FILES
105 =item ico_reader_open(ig, &error)
113 io_glue *ig - an Imager IO object. This must be seekable.
117 int *error - pointer to an integer which an error code will be
118 returned in on failure.
126 ico_reader_open(i_io_glue_t *ig, int *error) {
127 long res1, type, count;
128 ico_reader_t *file = NULL;
131 if (!read_packed(ig, "www", &res1, &type, &count)) {
132 *error = ICOERR_Short_File;
135 if (res1 != 0 || (type != 1 && type != 2) || count == 0) {
136 *error = ICOERR_Invalid_File;
140 file = malloc(sizeof(ico_reader_t));
142 *error = ICOERR_Out_Of_Memory;
148 file->images = malloc(sizeof(ico_reader_image_entry) * count);
149 if (file->images == NULL) {
150 *error = ICOERR_Out_Of_Memory;
155 for (i = 0; i < count; ++i) {
156 long width, height, bytes_in_res, image_offset;
158 ico_reader_image_entry *image = file->images + i;
159 if (type == ICON_ICON) {
160 if (!read_packed(ig, "bb xxxxxx dd", &width, &height, &bytes_in_res,
164 *error = ICOERR_Short_File;
167 image->hotspot_x = image->hotspot_y = 0;
170 long hotspot_x, hotspot_y;
172 if (!read_packed(ig, "bb xx ww dd", &width, &height,
173 &hotspot_x, &hotspot_y, &bytes_in_res,
177 *error = ICOERR_Short_File;
180 image->hotspot_x = hotspot_x;
181 image->hotspot_y = hotspot_y;
184 image->width = width;
185 image->height = height;
186 image->offset = image_offset;
187 image->size = bytes_in_res;
194 =item ico_image_count
196 // number of images in the file
197 count = ico_image_count(file);
203 ico_image_count(ico_reader_t *file) {
210 // type of file - ICON_ICON for icon, ICON_CURSOR for cursor
211 type = ico_type(file);
217 ico_type(ico_reader_t *file) {
224 Read an image from the file given it's index.
230 ico_image_read(ico_reader_t *file, int index, int *error) {
231 io_glue *ig = file->ig;
232 ico_reader_image_entry *im;
233 long bi_size, width, height, planes, bit_count;
236 if (index < 0 || index >= file->count) {
237 *error = ICOERR_Bad_Image_Index;
241 im = file->images + index;
242 if (i_io_seek(ig, im->offset, SEEK_SET) != im->offset) {
243 *error = ICOERR_File_Error;
247 if (!read_packed(ig, "dddww xxxx xxxx xxxx xxxx xxxx xxxx", &bi_size,
248 &width, &height, &planes, &bit_count)) {
249 *error = ICOERR_Short_File;
253 /* the bitmapinfoheader height includes the height of
254 the and and xor masks */
255 if (bi_size != 40 || width != im->width || height != im->height * 2
256 || planes != 1) { /* don't know how to handle planes != 1 */
257 *error = ICOERR_Invalid_File;
261 if (bit_count != 1 && bit_count != 4 && bit_count != 8
262 && bit_count != 24 && bit_count != 32) {
263 *error = ICOERR_Unknown_Bits;
267 result = malloc(sizeof(ico_image_t));
269 *error = ICOERR_Out_Of_Memory;
272 result->width = width;
273 result->height = im->height;
274 result->direct = bit_count > 8;
275 result->bit_count = bit_count;
276 result->palette = NULL;
277 result->image_data = NULL;
278 result->mask_data = NULL;
279 result->hotspot_x = im->hotspot_x;
280 result->hotspot_y = im->hotspot_y;
282 if (bit_count == 32) {
283 result->palette_size = 0;
285 result->image_data = malloc(result->width * result->height * sizeof(ico_color_t));
286 if (!result->image_data) {
288 *error = ICOERR_Out_Of_Memory;
291 if (!read_32bit_data(file, result, error)) {
292 free(result->image_data);
297 else if (bit_count == 24) {
298 result->palette_size = 0;
300 result->image_data = malloc(result->width * result->height * sizeof(ico_color_t));
301 if (!result->image_data) {
303 *error = ICOERR_Out_Of_Memory;
306 if (!read_24bit_data(file, result, error)) {
307 free(result->image_data);
315 result->palette_size = 1 << bit_count;
316 result->palette = malloc(sizeof(ico_color_t) * result->palette_size);
317 if (!result->palette) {
319 *error = ICOERR_Out_Of_Memory;
323 result->image_data = malloc(result->width * result->height);
324 if (!result->image_data) {
325 *error = ICOERR_Out_Of_Memory;
326 free(result->palette);
331 if (!read_palette(file, result, error)) {
332 free(result->palette);
333 free(result->image_data);
340 read_result = read_1bit_data(file, result, error);
344 read_result = read_4bit_data(file, result, error);
348 read_result = read_8bit_data(file, result, error);
352 assert(0); /* this can't happen in theory */
358 free(result->palette);
359 free(result->image_data);
365 result->mask_data = malloc(result->width * result->height);
366 if (!result->mask_data) {
367 *error = ICOERR_Out_Of_Memory;
368 free(result->palette);
369 free(result->image_data);
374 if (!read_mask(file, result, error)) {
375 free(result->mask_data);
376 free(result->palette);
377 free(result->image_data);
386 =item ico_image_release
388 Release an image structure returned by ico_image_read.
394 ico_image_release(ico_image_t *image) {
395 free(image->mask_data);
396 free(image->palette);
397 free(image->image_data);
402 =item ico_reader_close
404 Releases the read file structure.
410 ico_reader_close(ico_reader_t *file) {
411 i_io_close(file->ig);
419 =head1 WRITING ICON FILES
423 =item ico_write(ig, images, image_count, type, &error)
431 io_glue *ig - an Imager IO object. This only needs to implement
432 writing for ico_write()
436 ico_image_t *images - array of images to be written.
440 int image_count - number of images
444 int type - must be ICON_ICON or ICON_CURSOR
448 int *error - set to an error code on failure.
452 Returns non-zero on success.
458 ico_write(i_io_glue_t *ig, ico_image_t const *images, int image_count,
459 int type, int *error) {
461 int start_offset = 6 + 16 * image_count;
462 int current_offset = start_offset;
464 if (type != ICON_ICON && type != ICON_CURSOR) {
465 *error = ICOERR_Bad_File_Type;
469 /* validate the images */
470 if (!ico_write_validate(images, image_count, error))
473 /* write the header */
474 if (!write_packed(ig, "www", 0, type, image_count)) {
475 *error = ICOERR_Write_Failure;
479 /* work out the offsets of each image */
480 for (i = 0; i < image_count; ++i) {
481 ico_image_t const *image = images + i;
483 int size = ico_image_size(image, &bits, &colors);
485 if (type == ICON_ICON) {
486 if (!write_packed(ig, "bbbbwwdd", image->width, image->height,
487 colors, 0, 1, bits, (unsigned long)size,
488 (unsigned long)current_offset)) {
489 *error = ICOERR_Write_Failure;
494 int hotspot_x = image->hotspot_x;
495 int hotspot_y = image->hotspot_y;
499 else if (hotspot_x >= image->width)
500 hotspot_x = image->width - 1;
503 else if (hotspot_y >= image->height)
504 hotspot_y = image->height - 1;
506 if (!write_packed(ig, "bbbbwwdd", image->width, image->height,
507 colors, 0, hotspot_x, hotspot_y, (unsigned long)size,
508 (unsigned long)current_offset)) {
509 *error = ICOERR_Write_Failure;
513 current_offset += size;
516 /* write out each image */
517 for (i = 0; i < image_count; ++i) {
518 ico_image_t const *image = images + i;
521 if (!write_32_bit(ig, image, error))
525 if (image->palette_size <= 2) {
526 if (!write_1_bit(ig, image, error))
529 else if (image->palette_size <= 16) {
530 if (!write_4_bit(ig, image, error))
534 if (!write_8_bit(ig, image, error))
538 if (!write_mask(ig, image, error))
548 =head1 ERROR MESSAGES
552 =item ico_error_message
554 Converts an error code into an error message.
560 ico_error_message(int error, char *buffer, size_t buffer_size) {
565 case ICOERR_Short_File:
569 case ICOERR_File_Error:
573 case ICOERR_Write_Failure:
574 msg = "Write failure";
577 case ICOERR_Invalid_File:
578 msg = "Not an icon file";
581 case ICOERR_Unknown_Bits:
582 msg = "Unknown value for bits/pixel";
585 case ICOERR_Bad_Image_Index:
586 msg = "Image index out of range";
589 case ICOERR_Bad_File_Type:
590 msg = "Bad file type parameter";
593 case ICOERR_Invalid_Width:
594 msg = "Invalid image width";
597 case ICOERR_Invalid_Height:
598 msg = "Invalid image height";
601 case ICOERR_Invalid_Palette:
602 msg = "Invalid Palette";
606 msg = "No image data in image supplied to ico_write";
609 case ICOERR_Out_Of_Memory:
610 msg = "Out of memory";
614 msg = "Unknown error code";
618 size = strlen(msg) + 1;
619 if (size > buffer_size)
621 memcpy(buffer, msg, size);
622 buffer[size-1] = '\0';
630 =head1 PRIVATE FUNCTIONS
636 Reads packed data from a stream, unpacking it.
642 int read_packed(io_glue *ig, const char *format, ...) {
643 unsigned char buffer[100];
650 /* read efficiently, work out the size of the buffer */
654 switch (*formatp++) {
656 case 'x': size += 1; break;
657 case 'w': size += 2; break;
658 case 'd': size += 4; break;
659 case ' ': break; /* space to separate components */
661 fprintf(stderr, "invalid unpack char in %s\n", format);
666 if (size > sizeof(buffer)) {
667 /* catch if we need a bigger buffer, but 100 is plenty */
668 fprintf(stderr, "format %s too long for buffer\n", format);
672 if (i_io_read(ig, buffer, size) != size) {
676 va_start(ap, format);
683 p = va_arg(ap, long *);
688 p = va_arg(ap, long *);
689 *p = bufp[0] + (bufp[1] << 8);
694 p = va_arg(ap, long *);
695 *p = bufp[0] + (bufp[1] << 8) + (bufp[2] << 16) + (bufp[3] << 24);
700 ++bufp; /* skip a byte */
715 Reads the palette data for an icon image.
722 read_palette(ico_reader_t *file, ico_image_t *image, int *error) {
723 int palette_bytes = image->palette_size * 4;
724 unsigned char *read_buffer = malloc(palette_bytes);
730 *error = ICOERR_Out_Of_Memory;
734 if (i_io_read(file->ig, read_buffer, palette_bytes) != palette_bytes) {
735 *error = ICOERR_Short_File;
741 outp = image->palette;
742 for (i = 0; i < image->palette_size; ++i) {
756 =item read_32bit_data
758 Reads 32 bit image data.
765 read_32bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
766 int line_bytes = image->width * 4;
767 unsigned char *buffer = malloc(line_bytes);
774 *error = ICOERR_Out_Of_Memory;
778 for (y = image->height - 1; y >= 0; --y) {
779 if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
781 *error = ICOERR_Short_File;
784 outp = image->image_data;
785 outp += y * image->width;
787 for (x = 0; x < image->width; ++x) {
802 =item read_24bit_data
804 Reads 24 bit image data.
811 read_24bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
812 int line_bytes = image->width * 3;
813 unsigned char *buffer;
819 line_bytes = (line_bytes + 3) / 4 * 4;
821 buffer = malloc(line_bytes);
824 *error = ICOERR_Out_Of_Memory;
828 for (y = image->height - 1; y >= 0; --y) {
829 if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
831 *error = ICOERR_Short_File;
834 outp = image->image_data;
835 outp += y * image->width;
837 for (x = 0; x < image->width; ++x) {
854 Reads 8 bit image data.
861 read_8bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
862 int line_bytes = (image->width + 3) / 4 * 4;
863 unsigned char *buffer = malloc(line_bytes);
866 unsigned char *inp, *outp;
869 *error = ICOERR_Out_Of_Memory;
873 for (y = image->height - 1; y >= 0; --y) {
874 outp = image->image_data;
875 outp += y * image->width;
876 if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
878 *error = ICOERR_Short_File;
881 for (x = 0, inp = buffer; x < image->width; ++x) {
893 Reads 4 bit image data.
900 read_4bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
901 /* 2 pixels per byte, rounded up to the nearest dword */
902 int line_bytes = ((image->width + 1) / 2 + 3) / 4 * 4;
903 unsigned char *read_buffer = malloc(line_bytes);
906 unsigned char *inp, *outp;
909 *error = ICOERR_Out_Of_Memory;
913 for (y = image->height - 1; y >= 0; --y) {
914 if (i_io_read(file->ig, read_buffer, line_bytes) != line_bytes) {
916 *error = ICOERR_Short_File;
920 outp = image->image_data;
921 outp += y * image->width;
923 for (x = 0; x < image->width; ++x) {
924 /* yes, this is kind of ugly */
926 *outp++ = *inp++ & 0x0F;
941 Reads 1 bit image data.
948 read_1bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
949 /* 8 pixels per byte, rounded up to the nearest dword */
950 int line_bytes = ((image->width + 7) / 8 + 3) / 4 * 4;
951 unsigned char *read_buffer = malloc(line_bytes);
954 unsigned char *inp, *outp;
957 *error = ICOERR_Out_Of_Memory;
961 for (y = image->height - 1; y >= 0; --y) {
962 if (i_io_read(file->ig, read_buffer, line_bytes) != line_bytes) {
964 *error = ICOERR_Short_File;
968 outp = image->image_data;
969 outp += y * image->width;
971 for (x = 0; x < image->width; ++x) {
972 *outp++ = (*inp >> (7 - (x & 7))) & 1;
982 /* this is very similar to the 1 bit reader <sigh> */
986 Reads the AND mask from an icon image.
993 read_mask(ico_reader_t *file, ico_image_t *image, int *error) {
994 /* 8 pixels per byte, rounded up to the nearest dword */
995 int line_bytes = ((image->width + 7) / 8 + 3) / 4 * 4;
996 unsigned char *read_buffer = malloc(line_bytes);
1000 unsigned char *inp, *outp;
1003 *error = ICOERR_Out_Of_Memory;
1007 for (y = image->height - 1; y >= 0; --y) {
1008 if (i_io_read(file->ig, read_buffer, line_bytes) != line_bytes) {
1010 *error = ICOERR_Short_File;
1014 outp = image->mask_data + y * image->width;
1017 for (x = 0; x < image->width; ++x) {
1018 *outp++ = (*inp & mask) ? 1 : 0;
1032 =item ico_write_validate
1034 Check each image to make sure it can go into an icon file.
1040 ico_write_validate(ico_image_t const *images, int image_count, int *error) {
1043 for (i = 0; i < image_count; ++i) {
1044 ico_image_t const *image = images + i;
1046 if (image->width < 1 || image->width > 255) {
1047 *error = ICOERR_Invalid_Width;
1050 if (image->height < 1 || image->height > 255) {
1051 *error = ICOERR_Invalid_Height;
1054 if (!image->image_data) {
1055 *error = ICOERR_No_Data;
1058 if (!image->direct) {
1059 if (image->palette_size < 0 || image->palette_size > 256
1060 || !image->palette) {
1061 *error = ICOERR_Invalid_Palette;
1071 =item ico_image_size
1073 Calculate how much space the icon takes up in the file.
1079 ico_image_size(ico_image_t const *image, int *bits, int *colors) {
1080 int size = 40; /* start with the BITMAPINFOHEADER */
1082 /* add in the image area */
1083 if (image->direct) {
1086 size += image->width * 4 * image->height;
1089 if (image->palette_size <= 2) {
1093 else if (image->palette_size <= 16) {
1103 size += *colors * 4;
1105 /* image data size */
1106 size += (image->width * *bits + 31) / 32 * 4 * image->height;
1109 /* add in the mask */
1110 size += (image->width + 31) / 32 * 4 * image->height;
1118 Pack numbers given a format to a stream.
1124 write_packed(i_io_glue_t *ig, char const *format, ...) {
1125 unsigned char buffer[100];
1129 const char *formatp;
1130 unsigned char *bufp;
1132 /* write efficiently, work out the size of the buffer */
1136 switch (*formatp++) {
1137 case 'b': size++; break;
1138 case 'w': size += 2; break;
1139 case 'd': size += 4; break;
1140 case ' ': break; /* space to separate components */
1142 fprintf(stderr, "invalid unpack char in %s\n", format);
1147 if (size > sizeof(buffer)) {
1148 /* catch if we need a bigger buffer, but 100 is plenty */
1149 fprintf(stderr, "format %s too long for buffer\n", format);
1153 va_start(ap, format);
1160 p = va_arg(ap, int);
1165 p = va_arg(ap, int);
1167 *bufp++ = (p >> 8) & 0xFF;
1171 p = va_arg(ap, unsigned long);
1173 *bufp++ = (p >> 8) & 0xFF;
1174 *bufp++ = (p >> 16) & 0xFF;
1175 *bufp++ = (p >> 24) & 0xFF;
1185 if (i_io_write(ig, buffer, size) != size)
1194 Write the palette for an icon.
1200 write_palette(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1201 int full_size = image->palette_size;
1202 unsigned char *writebuf, *outp;
1203 ico_color_t *colorp;
1206 if (image->palette_size <= 2)
1208 else if (image->palette_size <= 16)
1213 writebuf = calloc(full_size, 4);
1215 *error = ICOERR_Out_Of_Memory;
1219 colorp = image->palette;
1220 for (i = 0; i < image->palette_size; ++i) {
1221 *outp++ = colorp->b;
1222 *outp++ = colorp->g;
1223 *outp++ = colorp->r;
1227 for (; i < full_size; ++i) {
1234 if (i_io_write(ig, writebuf, full_size * 4) != full_size * 4) {
1235 *error = ICOERR_Write_Failure;
1246 =item write_bitmapinfoheader
1248 Write the BITMAPINFOHEADER for an icon image.
1254 write_bitmapinfoheader(i_io_glue_t *ig, ico_image_t const *image, int *error,
1255 int bit_count, int clr_used) {
1256 if (!write_packed(ig, "d dd w w d d dd dd",
1258 (unsigned long)image->width,
1259 (unsigned long)2 * image->height, /* biWidth/biHeight */
1260 1, bit_count, /* biPlanes, biBitCount */
1261 0UL, 0UL, /* biCompression, biSizeImage */
1262 0UL, 0UL, /* bi(X|Y)PetsPerMeter */
1263 (unsigned long)clr_used, /* biClrUsed */
1264 0UL)) { /* biClrImportant */
1265 *error = ICOERR_Write_Failure;
1275 Write 32-bit image data to the icon.
1281 write_32_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1282 unsigned char *writebuf;
1283 ico_color_t *data = image->image_data, *colorp;
1284 unsigned char *writep;
1287 if (!write_bitmapinfoheader(ig, image, error, 32, 0)) {
1291 writebuf = malloc(image->width * 4);
1293 *error = ICOERR_Out_Of_Memory;
1297 for (y = image->height-1; y >= 0; --y) {
1299 colorp = data + y * image->width;
1300 for (x = 0; x < image->width; ++x) {
1301 *writep++ = colorp->b;
1302 *writep++ = colorp->g;
1303 *writep++ = colorp->r;
1304 *writep++ = colorp->a;
1307 if (i_io_write(ig, writebuf, image->width * 4) != image->width * 4) {
1308 *error = ICOERR_Write_Failure;
1322 Write 8 bit image data.
1328 write_8_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1329 static const unsigned char zeros[3] = { '\0' };
1331 const unsigned char *data = image->image_data;
1332 int zero_count = (0U - (unsigned)image->width) & 3;
1334 if (!write_bitmapinfoheader(ig, image, error, 8, 256)) {
1338 if (!write_palette(ig, image, error))
1341 for (y = image->height-1; y >= 0; --y) {
1342 if (i_io_write(ig, data + y * image->width,
1343 image->width) != image->width) {
1344 *error = ICOERR_Write_Failure;
1348 if (i_io_write(ig, zeros, zero_count) != zero_count) {
1349 *error = ICOERR_Write_Failure;
1361 Write 4 bit image data.
1367 write_4_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1368 int line_size = ((image->width + 1) / 2 + 3) / 4 * 4;
1369 unsigned char *writebuf, *outp;
1371 unsigned char const *data = image->image_data;
1372 unsigned char const *pixelp;
1374 if (!write_bitmapinfoheader(ig, image, error, 4, 16)) {
1378 if (!write_palette(ig, image, error))
1381 writebuf = malloc(line_size);
1383 *error = ICOERR_Out_Of_Memory;
1387 for (y = image->height-1; y >= 0; --y) {
1388 pixelp = data + y * image->width;
1390 memset(writebuf, 0, line_size);
1391 for (x = 0; x < image->width; ++x) {
1393 *outp |= *pixelp++ & 0x0F;
1397 *outp |= *pixelp++ << 4;
1401 if (i_io_write(ig, writebuf, line_size) != line_size) {
1402 *error = ICOERR_Write_Failure;
1416 Write 1 bit image data.
1422 write_1_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1423 int line_size = (image->width + 31) / 32 * 4;
1424 unsigned char *writebuf = malloc(line_size);
1425 unsigned char *outp;
1426 unsigned char const *data, *pixelp;
1430 if (!write_bitmapinfoheader(ig, image, error, 1, 2)) {
1434 if (!write_palette(ig, image, error))
1438 *error = ICOERR_Out_Of_Memory;
1442 data = image->image_data;
1443 for (y = image->height-1; y >= 0; --y) {
1444 memset(writebuf, 0, line_size);
1445 pixelp = data + y * image->width;
1448 for (x = 0; x < image->width; ++x) {
1457 if (i_io_write(ig, writebuf, line_size) != line_size) {
1458 *error = ICOERR_Write_Failure;
1478 write_mask(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1479 int line_size = (image->width + 31) / 32 * 4;
1480 unsigned char *writebuf = malloc(line_size);
1481 unsigned char *outp;
1482 unsigned char const *data, *pixelp;
1487 *error = ICOERR_Out_Of_Memory;
1491 data = image->mask_data;
1493 for (y = image->height-1; y >= 0; --y) {
1494 memset(writebuf, 0, line_size);
1495 pixelp = data + y * image->width;
1498 for (x = 0; x < image->width; ++x) {
1508 if (i_io_write(ig, writebuf, line_size) != line_size) {
1509 *error = ICOERR_Write_Failure;
1516 memset(writebuf, 0, line_size);
1517 for (y = image->height-1; y >= 0; --y) {
1518 if (i_io_write(ig, writebuf, line_size) != line_size) {
1519 *error = ICOERR_Write_Failure;
1536 Tony Cook <tony@imager.perl.org>