Added option 'icon:auto-resize' to automatically store multiple sizes in an ico image (requires 256x256 input image).
diff --git a/coders/icon.c b/coders/icon.c
index 035fe22..9bb995e 100644
--- a/coders/icon.c
+++ b/coders/icon.c
@@ -58,6 +58,7 @@
#include "MagickCore/monitor.h"
#include "MagickCore/monitor-private.h"
#include "MagickCore/nt-base-private.h"
+#include "MagickCore/option.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/quantize.h"
#include "MagickCore/quantum-private.h"
@@ -785,6 +786,7 @@
icon_info;
Image
+ *images,
*next;
MagickBooleanType
@@ -829,15 +831,44 @@
status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
if (status == MagickFalse)
return(status);
- scene=0;
- next=image;
- do
- {
- if ((image->columns > 256L) || (image->rows > 256L))
- ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
- scene++;
- next=SyncNextImageInList(next);
- } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
+ images=(Image *) NULL;
+ if (GetImageOption(image_info,"icon:auto-resize") != (const char *) NULL)
+ {
+ size_t
+ sizes[]={192,128,96,64,48,40,32,24,16};
+
+ if ((image->columns != 256L) && (image->rows != 256L))
+ ThrowWriterException(ImageError,"SizeMustBe256x256");
+ if (image->next != (Image *) NULL)
+ ThrowWriterException(ImageError,"OnlyOneImageAllowed");
+ images=CloneImage(image,0,0,MagickTrue,exception);
+ if (images == (Image *) NULL)
+ return(MagickFalse);
+ scene=sizeof(sizes)/sizeof(sizes[0]);
+ for (i=0; i < scene; i++)
+ {
+ next=ResizeImage(image,sizes[i],sizes[i],image->filter,exception);
+ if (next == (Image *) NULL)
+ {
+ images=DestroyImageList(images);
+ return(MagickFalse);
+ }
+ AppendImageToList(&images,next);
+ }
+ scene++;
+ }
+ else
+ {
+ scene=0;
+ next=image;
+ do
+ {
+ if ((image->columns > 256L) || (image->rows > 256L))
+ ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
+ scene++;
+ next=SyncNextImageInList(next);
+ } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
+ }
/*
Dump out a ICON header template to be properly initialized later.
*/
@@ -847,7 +878,7 @@
(void) ResetMagickMemory(&icon_file,0,sizeof(icon_file));
(void) ResetMagickMemory(&icon_info,0,sizeof(icon_info));
scene=0;
- next=image;
+ next=(images != (Image *) NULL) ? images : image;
do
{
(void) WriteBlobByte(image,icon_file.directory[scene].width);
@@ -864,7 +895,7 @@
next=SyncNextImageInList(next);
} while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
scene=0;
- next=image;
+ next=(images != (Image *) NULL) ? images : image;
do
{
if ((next->columns > 255L) && (next->rows > 255L) &&
@@ -884,8 +915,11 @@
*png;
write_image=CloneImage(next,0,0,MagickTrue,exception);
- if (write_image == (Image *) NULL)
- return(MagickFalse);
+ if (write_image == (Image *) NULL)
+ {
+ images=DestroyImageList(images);
+ return(MagickFalse);
+ }
write_info=CloneImageInfo(image_info);
(void) CopyMagickString(write_info->filename,"PNG:",MaxTextExtent);
@@ -899,8 +933,11 @@
exception);
write_image=DestroyImage(write_image);
write_info=DestroyImageInfo(write_info);
- if (png == (unsigned char *) NULL)
- return(MagickFalse);
+ if (png == (unsigned char *) NULL)
+ {
+ images=DestroyImageList(images);
+ return(MagickFalse);
+ }
icon_file.directory[scene].width=0;
icon_file.directory[scene].height=0;
icon_file.directory[scene].colors=0;
@@ -1005,8 +1042,11 @@
*/
pixels=(unsigned char *) AcquireQuantumMemory((size_t)
icon_info.image_size,sizeof(*pixels));
- if (pixels == (unsigned char *) NULL)
- ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ if (pixels == (unsigned char *) NULL)
+ {
+ images=DestroyImageList(images);
+ ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ }
(void) ResetMagickMemory(pixels,0,(size_t) icon_info.image_size);
switch (icon_info.bits_per_pixel)
{
@@ -1186,8 +1226,12 @@
*/
icon_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
(1UL << icon_info.bits_per_pixel),4UL*sizeof(*icon_colormap));
- if (icon_colormap == (unsigned char *) NULL)
- ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ if (icon_colormap == (unsigned char *) NULL)
+ {
+ images=DestroyImageList(images);
+ ThrowWriterException(ResourceLimitError,
+ "MemoryAllocationFailed");
+ }
q=icon_colormap;
for (i=0; i < (ssize_t) next->colors; i++)
{
@@ -1256,7 +1300,7 @@
(void) WriteBlobLSBShort(image,1);
(void) WriteBlobLSBShort(image,(unsigned short) (scene+1));
scene=0;
- next=image;
+ next=(images != (Image *) NULL) ? images : image;
do
{
(void) WriteBlobByte(image,icon_file.directory[scene].width);
@@ -1273,5 +1317,6 @@
next=SyncNextImageInList(next);
} while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
(void) CloseBlob(image);
+ images=DestroyImageList(images);
return(MagickTrue);
}