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 /* a width or height of zero here indicates a width/height of 256 */
186 image->width = width ? width : 256;
187 image->height = height ? height : 256;
188 image->offset = image_offset;
189 image->size = bytes_in_res;
196 =item ico_image_count
198 // number of images in the file
199 count = ico_image_count(file);
205 ico_image_count(ico_reader_t *file) {
212 // type of file - ICON_ICON for icon, ICON_CURSOR for cursor
213 type = ico_type(file);
219 ico_type(ico_reader_t *file) {
226 Read an image from the file given it's index.
232 ico_image_read(ico_reader_t *file, int index, int *error) {
233 io_glue *ig = file->ig;
234 ico_reader_image_entry *im;
235 long bi_size, width, height, planes, bit_count;
238 if (index < 0 || index >= file->count) {
239 *error = ICOERR_Bad_Image_Index;
243 im = file->images + index;
244 if (i_io_seek(ig, im->offset, SEEK_SET) != im->offset) {
245 *error = ICOERR_File_Error;
249 if (!read_packed(ig, "dddww xxxx xxxx xxxx xxxx xxxx xxxx", &bi_size,
250 &width, &height, &planes, &bit_count)) {
251 *error = ICOERR_Short_File;
255 /* the bitmapinfoheader height includes the height of
256 the and and xor masks */
257 if (bi_size != 40 || width != im->width || height != im->height * 2
258 || planes != 1) { /* don't know how to handle planes != 1 */
259 *error = ICOERR_Invalid_File;
263 if (bit_count != 1 && bit_count != 4 && bit_count != 8
264 && bit_count != 24 && bit_count != 32) {
265 *error = ICOERR_Unknown_Bits;
269 result = malloc(sizeof(ico_image_t));
271 *error = ICOERR_Out_Of_Memory;
274 result->width = width;
275 result->height = im->height;
276 result->direct = bit_count > 8;
277 result->bit_count = bit_count;
278 result->palette = NULL;
279 result->image_data = NULL;
280 result->mask_data = NULL;
281 result->hotspot_x = im->hotspot_x;
282 result->hotspot_y = im->hotspot_y;
284 if (bit_count == 32) {
285 result->palette_size = 0;
287 result->image_data = malloc(result->width * result->height * sizeof(ico_color_t));
288 if (!result->image_data) {
290 *error = ICOERR_Out_Of_Memory;
293 if (!read_32bit_data(file, result, error)) {
294 free(result->image_data);
299 else if (bit_count == 24) {
300 result->palette_size = 0;
302 result->image_data = malloc(result->width * result->height * sizeof(ico_color_t));
303 if (!result->image_data) {
305 *error = ICOERR_Out_Of_Memory;
308 if (!read_24bit_data(file, result, error)) {
309 free(result->image_data);
317 result->palette_size = 1 << bit_count;
318 result->palette = malloc(sizeof(ico_color_t) * result->palette_size);
319 if (!result->palette) {
321 *error = ICOERR_Out_Of_Memory;
325 result->image_data = malloc(result->width * result->height);
326 if (!result->image_data) {
327 *error = ICOERR_Out_Of_Memory;
328 free(result->palette);
333 if (!read_palette(file, result, error)) {
334 free(result->palette);
335 free(result->image_data);
342 read_result = read_1bit_data(file, result, error);
346 read_result = read_4bit_data(file, result, error);
350 read_result = read_8bit_data(file, result, error);
354 assert(0); /* this can't happen in theory */
360 free(result->palette);
361 free(result->image_data);
367 result->mask_data = malloc(result->width * result->height);
368 if (!result->mask_data) {
369 *error = ICOERR_Out_Of_Memory;
370 free(result->palette);
371 free(result->image_data);
376 if (!read_mask(file, result, error)) {
377 free(result->mask_data);
378 free(result->palette);
379 free(result->image_data);
388 =item ico_image_release
390 Release an image structure returned by ico_image_read.
396 ico_image_release(ico_image_t *image) {
397 free(image->mask_data);
398 free(image->palette);
399 free(image->image_data);
404 =item ico_reader_close
406 Releases the read file structure.
412 ico_reader_close(ico_reader_t *file) {
413 i_io_close(file->ig);
421 =head1 WRITING ICON FILES
425 =item ico_write(ig, images, image_count, type, &error)
433 io_glue *ig - an Imager IO object. This only needs to implement
434 writing for ico_write()
438 ico_image_t *images - array of images to be written.
442 int image_count - number of images
446 int type - must be ICON_ICON or ICON_CURSOR
450 int *error - set to an error code on failure.
454 Returns non-zero on success.
460 ico_write(i_io_glue_t *ig, ico_image_t const *images, int image_count,
461 int type, int *error) {
463 int start_offset = 6 + 16 * image_count;
464 int current_offset = start_offset;
466 if (type != ICON_ICON && type != ICON_CURSOR) {
467 *error = ICOERR_Bad_File_Type;
471 /* validate the images */
472 if (!ico_write_validate(images, image_count, error))
475 /* write the header */
476 if (!write_packed(ig, "www", 0, type, image_count)) {
477 *error = ICOERR_Write_Failure;
481 /* work out the offsets of each image */
482 for (i = 0; i < image_count; ++i) {
483 ico_image_t const *image = images + i;
485 int size = ico_image_size(image, &bits, &colors);
486 int width_byte = image->width == 256 ? 0 : image->width;
487 int height_byte = image->height == 256 ? 0 : image->height;
489 if (type == ICON_ICON) {
490 if (!write_packed(ig, "bbbbwwdd", width_byte, height_byte,
491 colors, 0, 1, bits, (unsigned long)size,
492 (unsigned long)current_offset)) {
493 *error = ICOERR_Write_Failure;
498 int hotspot_x = image->hotspot_x;
499 int hotspot_y = image->hotspot_y;
503 else if (hotspot_x >= image->width)
504 hotspot_x = image->width - 1;
507 else if (hotspot_y >= image->height)
508 hotspot_y = image->height - 1;
510 if (!write_packed(ig, "bbbbwwdd", width_byte, height_byte,
511 colors, 0, hotspot_x, hotspot_y, (unsigned long)size,
512 (unsigned long)current_offset)) {
513 *error = ICOERR_Write_Failure;
517 current_offset += size;
520 /* write out each image */
521 for (i = 0; i < image_count; ++i) {
522 ico_image_t const *image = images + i;
525 if (!write_32_bit(ig, image, error))
529 if (image->palette_size <= 2) {
530 if (!write_1_bit(ig, image, error))
533 else if (image->palette_size <= 16) {
534 if (!write_4_bit(ig, image, error))
538 if (!write_8_bit(ig, image, error))
542 if (!write_mask(ig, image, error))
552 =head1 ERROR MESSAGES
556 =item ico_error_message
558 Converts an error code into an error message.
564 ico_error_message(int error, char *buffer, size_t buffer_size) {
569 case ICOERR_Short_File:
573 case ICOERR_File_Error:
577 case ICOERR_Write_Failure:
578 msg = "Write failure";
581 case ICOERR_Invalid_File:
582 msg = "Not an icon file";
585 case ICOERR_Unknown_Bits:
586 msg = "Unknown value for bits/pixel";
589 case ICOERR_Bad_Image_Index:
590 msg = "Image index out of range";
593 case ICOERR_Bad_File_Type:
594 msg = "Bad file type parameter";
597 case ICOERR_Invalid_Width:
598 msg = "Invalid image width";
601 case ICOERR_Invalid_Height:
602 msg = "Invalid image height";
605 case ICOERR_Invalid_Palette:
606 msg = "Invalid Palette";
610 msg = "No image data in image supplied to ico_write";
613 case ICOERR_Out_Of_Memory:
614 msg = "Out of memory";
618 msg = "Unknown error code";
622 size = strlen(msg) + 1;
623 if (size > buffer_size)
625 memcpy(buffer, msg, size);
626 buffer[size-1] = '\0';
634 =head1 PRIVATE FUNCTIONS
640 Reads packed data from a stream, unpacking it.
646 int read_packed(io_glue *ig, const char *format, ...) {
647 unsigned char buffer[100];
654 /* read efficiently, work out the size of the buffer */
658 switch (*formatp++) {
660 case 'x': size += 1; break;
661 case 'w': size += 2; break;
662 case 'd': size += 4; break;
663 case ' ': break; /* space to separate components */
665 fprintf(stderr, "invalid unpack char in %s\n", format);
670 if (size > sizeof(buffer)) {
671 /* catch if we need a bigger buffer, but 100 is plenty */
672 fprintf(stderr, "format %s too long for buffer\n", format);
676 if (i_io_read(ig, buffer, size) != size) {
680 va_start(ap, format);
687 p = va_arg(ap, long *);
692 p = va_arg(ap, long *);
693 *p = bufp[0] + (bufp[1] << 8);
698 p = va_arg(ap, long *);
699 *p = bufp[0] + (bufp[1] << 8) + (bufp[2] << 16) + (bufp[3] << 24);
704 ++bufp; /* skip a byte */
719 Reads the palette data for an icon image.
726 read_palette(ico_reader_t *file, ico_image_t *image, int *error) {
727 int palette_bytes = image->palette_size * 4;
728 unsigned char *read_buffer = malloc(palette_bytes);
734 *error = ICOERR_Out_Of_Memory;
738 if (i_io_read(file->ig, read_buffer, palette_bytes) != palette_bytes) {
739 *error = ICOERR_Short_File;
745 outp = image->palette;
746 for (i = 0; i < image->palette_size; ++i) {
760 =item read_32bit_data
762 Reads 32 bit image data.
769 read_32bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
770 int line_bytes = image->width * 4;
771 unsigned char *buffer = malloc(line_bytes);
778 *error = ICOERR_Out_Of_Memory;
782 for (y = image->height - 1; y >= 0; --y) {
783 if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
785 *error = ICOERR_Short_File;
788 outp = image->image_data;
789 outp += y * image->width;
791 for (x = 0; x < image->width; ++x) {
806 =item read_24bit_data
808 Reads 24 bit image data.
815 read_24bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
816 int line_bytes = image->width * 3;
817 unsigned char *buffer;
823 line_bytes = (line_bytes + 3) / 4 * 4;
825 buffer = malloc(line_bytes);
828 *error = ICOERR_Out_Of_Memory;
832 for (y = image->height - 1; y >= 0; --y) {
833 if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
835 *error = ICOERR_Short_File;
838 outp = image->image_data;
839 outp += y * image->width;
841 for (x = 0; x < image->width; ++x) {
858 Reads 8 bit image data.
865 read_8bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
866 int line_bytes = (image->width + 3) / 4 * 4;
867 unsigned char *buffer = malloc(line_bytes);
870 unsigned char *inp, *outp;
873 *error = ICOERR_Out_Of_Memory;
877 for (y = image->height - 1; y >= 0; --y) {
878 outp = image->image_data;
879 outp += y * image->width;
880 if (i_io_read(file->ig, buffer, line_bytes) != line_bytes) {
882 *error = ICOERR_Short_File;
885 for (x = 0, inp = buffer; x < image->width; ++x) {
897 Reads 4 bit image data.
904 read_4bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
905 /* 2 pixels per byte, rounded up to the nearest dword */
906 int line_bytes = ((image->width + 1) / 2 + 3) / 4 * 4;
907 unsigned char *read_buffer = malloc(line_bytes);
910 unsigned char *inp, *outp;
913 *error = ICOERR_Out_Of_Memory;
917 for (y = image->height - 1; y >= 0; --y) {
918 if (i_io_read(file->ig, read_buffer, line_bytes) != line_bytes) {
920 *error = ICOERR_Short_File;
924 outp = image->image_data;
925 outp += y * image->width;
927 for (x = 0; x < image->width; ++x) {
928 /* yes, this is kind of ugly */
930 *outp++ = *inp++ & 0x0F;
945 Reads 1 bit image data.
952 read_1bit_data(ico_reader_t *file, ico_image_t *image, int *error) {
953 /* 8 pixels per byte, rounded up to the nearest dword */
954 int line_bytes = ((image->width + 7) / 8 + 3) / 4 * 4;
955 unsigned char *read_buffer = malloc(line_bytes);
958 unsigned char *inp, *outp;
961 *error = ICOERR_Out_Of_Memory;
965 for (y = image->height - 1; y >= 0; --y) {
966 if (i_io_read(file->ig, read_buffer, line_bytes) != line_bytes) {
968 *error = ICOERR_Short_File;
972 outp = image->image_data;
973 outp += y * image->width;
975 for (x = 0; x < image->width; ++x) {
976 *outp++ = (*inp >> (7 - (x & 7))) & 1;
986 /* this is very similar to the 1 bit reader <sigh> */
990 Reads the AND mask from an icon image.
997 read_mask(ico_reader_t *file, ico_image_t *image, int *error) {
998 /* 8 pixels per byte, rounded up to the nearest dword */
999 int line_bytes = ((image->width + 7) / 8 + 3) / 4 * 4;
1000 unsigned char *read_buffer = malloc(line_bytes);
1004 unsigned char *inp, *outp;
1007 *error = ICOERR_Out_Of_Memory;
1011 for (y = image->height - 1; y >= 0; --y) {
1012 if (i_io_read(file->ig, read_buffer, line_bytes) != line_bytes) {
1014 *error = ICOERR_Short_File;
1018 outp = image->mask_data + y * image->width;
1021 for (x = 0; x < image->width; ++x) {
1022 *outp++ = (*inp & mask) ? 1 : 0;
1036 =item ico_write_validate
1038 Check each image to make sure it can go into an icon file.
1044 ico_write_validate(ico_image_t const *images, int image_count, int *error) {
1047 for (i = 0; i < image_count; ++i) {
1048 ico_image_t const *image = images + i;
1050 if (image->width < 1 || image->width > 256) {
1051 *error = ICOERR_Invalid_Width;
1054 if (image->height < 1 || image->height > 256) {
1055 *error = ICOERR_Invalid_Height;
1058 if (!image->image_data) {
1059 *error = ICOERR_No_Data;
1062 if (!image->direct) {
1063 if (image->palette_size < 0 || image->palette_size > 256
1064 || !image->palette) {
1065 *error = ICOERR_Invalid_Palette;
1075 =item ico_image_size
1077 Calculate how much space the icon takes up in the file.
1083 ico_image_size(ico_image_t const *image, int *bits, int *colors) {
1084 int size = 40; /* start with the BITMAPINFOHEADER */
1086 /* add in the image area */
1087 if (image->direct) {
1090 size += image->width * 4 * image->height;
1093 if (image->palette_size <= 2) {
1097 else if (image->palette_size <= 16) {
1107 size += *colors * 4;
1109 /* image data size */
1110 size += (image->width * *bits + 31) / 32 * 4 * image->height;
1113 /* add in the mask */
1114 size += (image->width + 31) / 32 * 4 * image->height;
1122 Pack numbers given a format to a stream.
1128 write_packed(i_io_glue_t *ig, char const *format, ...) {
1129 unsigned char buffer[100];
1133 const char *formatp;
1134 unsigned char *bufp;
1136 /* write efficiently, work out the size of the buffer */
1140 switch (*formatp++) {
1141 case 'b': size++; break;
1142 case 'w': size += 2; break;
1143 case 'd': size += 4; break;
1144 case ' ': break; /* space to separate components */
1146 fprintf(stderr, "invalid unpack char in %s\n", format);
1151 if (size > sizeof(buffer)) {
1152 /* catch if we need a bigger buffer, but 100 is plenty */
1153 fprintf(stderr, "format %s too long for buffer\n", format);
1157 va_start(ap, format);
1164 p = va_arg(ap, int);
1169 p = va_arg(ap, int);
1171 *bufp++ = (p >> 8) & 0xFF;
1175 p = va_arg(ap, unsigned long);
1177 *bufp++ = (p >> 8) & 0xFF;
1178 *bufp++ = (p >> 16) & 0xFF;
1179 *bufp++ = (p >> 24) & 0xFF;
1189 if (i_io_write(ig, buffer, size) != size)
1198 Write the palette for an icon.
1204 write_palette(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1205 int full_size = image->palette_size;
1206 unsigned char *writebuf, *outp;
1207 ico_color_t *colorp;
1210 if (image->palette_size <= 2)
1212 else if (image->palette_size <= 16)
1217 writebuf = calloc(full_size, 4);
1219 *error = ICOERR_Out_Of_Memory;
1223 colorp = image->palette;
1224 for (i = 0; i < image->palette_size; ++i) {
1225 *outp++ = colorp->b;
1226 *outp++ = colorp->g;
1227 *outp++ = colorp->r;
1231 for (; i < full_size; ++i) {
1238 if (i_io_write(ig, writebuf, full_size * 4) != full_size * 4) {
1239 *error = ICOERR_Write_Failure;
1250 =item write_bitmapinfoheader
1252 Write the BITMAPINFOHEADER for an icon image.
1258 write_bitmapinfoheader(i_io_glue_t *ig, ico_image_t const *image, int *error,
1259 int bit_count, int clr_used) {
1260 if (!write_packed(ig, "d dd w w d d dd dd",
1262 (unsigned long)image->width,
1263 (unsigned long)2 * image->height, /* biWidth/biHeight */
1264 1, bit_count, /* biPlanes, biBitCount */
1265 0UL, 0UL, /* biCompression, biSizeImage */
1266 0UL, 0UL, /* bi(X|Y)PetsPerMeter */
1267 (unsigned long)clr_used, /* biClrUsed */
1268 0UL)) { /* biClrImportant */
1269 *error = ICOERR_Write_Failure;
1279 Write 32-bit image data to the icon.
1285 write_32_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1286 unsigned char *writebuf;
1287 ico_color_t *data = image->image_data, *colorp;
1288 unsigned char *writep;
1291 if (!write_bitmapinfoheader(ig, image, error, 32, 0)) {
1295 writebuf = malloc(image->width * 4);
1297 *error = ICOERR_Out_Of_Memory;
1301 for (y = image->height-1; y >= 0; --y) {
1303 colorp = data + y * image->width;
1304 for (x = 0; x < image->width; ++x) {
1305 *writep++ = colorp->b;
1306 *writep++ = colorp->g;
1307 *writep++ = colorp->r;
1308 *writep++ = colorp->a;
1311 if (i_io_write(ig, writebuf, image->width * 4) != image->width * 4) {
1312 *error = ICOERR_Write_Failure;
1326 Write 8 bit image data.
1332 write_8_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1333 static const unsigned char zeros[3] = { '\0' };
1335 const unsigned char *data = image->image_data;
1336 int zero_count = (0U - (unsigned)image->width) & 3;
1338 if (!write_bitmapinfoheader(ig, image, error, 8, 256)) {
1342 if (!write_palette(ig, image, error))
1345 for (y = image->height-1; y >= 0; --y) {
1346 if (i_io_write(ig, data + y * image->width,
1347 image->width) != image->width) {
1348 *error = ICOERR_Write_Failure;
1352 if (i_io_write(ig, zeros, zero_count) != zero_count) {
1353 *error = ICOERR_Write_Failure;
1365 Write 4 bit image data.
1371 write_4_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1372 int line_size = ((image->width + 1) / 2 + 3) / 4 * 4;
1373 unsigned char *writebuf, *outp;
1375 unsigned char const *data = image->image_data;
1376 unsigned char const *pixelp;
1378 if (!write_bitmapinfoheader(ig, image, error, 4, 16)) {
1382 if (!write_palette(ig, image, error))
1385 writebuf = malloc(line_size);
1387 *error = ICOERR_Out_Of_Memory;
1391 for (y = image->height-1; y >= 0; --y) {
1392 pixelp = data + y * image->width;
1394 memset(writebuf, 0, line_size);
1395 for (x = 0; x < image->width; ++x) {
1397 *outp |= *pixelp++ & 0x0F;
1401 *outp |= *pixelp++ << 4;
1405 if (i_io_write(ig, writebuf, line_size) != line_size) {
1406 *error = ICOERR_Write_Failure;
1420 Write 1 bit image data.
1426 write_1_bit(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1427 int line_size = (image->width + 31) / 32 * 4;
1428 unsigned char *writebuf = malloc(line_size);
1429 unsigned char *outp;
1430 unsigned char const *data, *pixelp;
1434 if (!write_bitmapinfoheader(ig, image, error, 1, 2)) {
1438 if (!write_palette(ig, image, error))
1442 *error = ICOERR_Out_Of_Memory;
1446 data = image->image_data;
1447 for (y = image->height-1; y >= 0; --y) {
1448 memset(writebuf, 0, line_size);
1449 pixelp = data + y * image->width;
1452 for (x = 0; x < image->width; ++x) {
1461 if (i_io_write(ig, writebuf, line_size) != line_size) {
1462 *error = ICOERR_Write_Failure;
1482 write_mask(i_io_glue_t *ig, ico_image_t const *image, int *error) {
1483 int line_size = (image->width + 31) / 32 * 4;
1484 unsigned char *writebuf = malloc(line_size);
1485 unsigned char *outp;
1486 unsigned char const *data, *pixelp;
1491 *error = ICOERR_Out_Of_Memory;
1495 data = image->mask_data;
1497 for (y = image->height-1; y >= 0; --y) {
1498 memset(writebuf, 0, line_size);
1499 pixelp = data + y * image->width;
1502 for (x = 0; x < image->width; ++x) {
1512 if (i_io_write(ig, writebuf, line_size) != line_size) {
1513 *error = ICOERR_Write_Failure;
1520 memset(writebuf, 0, line_size);
1521 for (y = image->height-1; y >= 0; --y) {
1522 if (i_io_write(ig, writebuf, line_size) != line_size) {
1523 *error = ICOERR_Write_Failure;
1540 Tony Cook <tonyc@cpan.org>