From: dirk Date: Thu, 9 Jan 2014 19:29:59 +0000 (+0000) Subject: Added option 'icon:auto-resize' to automatically store multiple sizes in an ico image... X-Git-Tag: 7.0.1-0~2923 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9e137706f4a1f40d099c597992f43cd3fba033a7;p=imagemagick 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 035fe22de..9bb995e74 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 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, icon_info; Image + *images, *next; MagickBooleanType @@ -829,15 +831,44 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, 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 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, (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 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, 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 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, *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 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, 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 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, */ 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 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, */ 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 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, (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 @@ static MagickBooleanType WriteICONImage(const ImageInfo *image_info, next=SyncNextImageInList(next); } while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse)); (void) CloseBlob(image); + images=DestroyImageList(images); return(MagickTrue); }