% Read Microsoft Windows Icon Format %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1992 %
% %
% %
-% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2015 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
#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"
/*
Forward declaractions.
*/
+static Image
+ *AutoResizeImage(const Image *,const char *,MagickOffsetType *,
+ ExceptionInfo *);
+
static MagickBooleanType
WriteICONImage(const ImageInfo *,Image *,ExceptionInfo *);
+
+Image *AutoResizeImage(const Image *image,const char *option,
+ MagickOffsetType *count,ExceptionInfo *exception)
+{
+ #define MAX_SIZES 16
+
+ char
+ *q;
+
+ const char
+ *p;
+
+ Image
+ *resized,
+ *images;
+
+ register ssize_t
+ i;
+
+ size_t
+ sizes[MAX_SIZES]={256,192,128,96,64,48,40,32,24,16};
+
+ images=NULL;
+ *count=0;
+ i=0;
+ p=option;
+ while (*p != '\0' && i < MAX_SIZES)
+ {
+ size_t
+ size;
+
+ while ((isspace((int) ((unsigned char) *p)) != 0))
+ p++;
+
+ size=(size_t)strtol(p,&q,10);
+ if (p == q || size < 16 || size > 256)
+ return((Image *) NULL);
+
+ p=q;
+ sizes[i++]=size;
+
+ while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
+ p++;
+ }
+
+ if (i==0)
+ i=10;
+ *count=i;
+ for (i=0; i < *count; i++)
+ {
+ resized=ResizeImage(image,sizes[i],sizes[i],image->filter,exception);
+ if (resized == (Image *) NULL)
+ return(DestroyImageList(images));
+
+ if (images == (Image *) NULL)
+ images=resized;
+ else
+ AppendImageToList(&images,resized);
+ }
+ return(images);
+}
\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ReadBlobLSBShort(image);
icon_file.directory[i].size=ReadBlobLSBLong(image);
icon_file.directory[i].offset=ReadBlobLSBLong(image);
+ if (EOFBlob(image) != MagickFalse)
+ {
+ ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
+ image->filename);
+ break;
+ }
}
one=1;
for (i=0; i < icon_file.count; i++)
icon_info.height=(unsigned char) ((int) ReadBlobLSBLong(image)/2);
icon_info.planes=ReadBlobLSBShort(image);
icon_info.bits_per_pixel=ReadBlobLSBShort(image);
- if ((icon_info.planes == 18505) && (icon_info.bits_per_pixel == 21060))
+ if (EOFBlob(image) != MagickFalse)
+ {
+ ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
+ image->filename);
+ break;
+ }
+ if (((icon_info.planes == 18505) && (icon_info.bits_per_pixel == 21060)) ||
+ (icon_info.size == 0x474e5089))
{
Image
*icon_image;
png[14]=(unsigned char) icon_info.bits_per_pixel;
png[15]=(unsigned char) (icon_info.bits_per_pixel >> 8);
count=ReadBlob(image,length-16,png+16);
- if (count != (ssize_t) (length-16))
+ icon_image=(Image *) NULL;
+ if (count > 0)
{
- png=(unsigned char *) RelinquishMagickMemory(png);
- ThrowReaderException(CorruptImageError,
- "InsufficientImageDataInFile");
+ read_info=CloneImageInfo(image_info);
+ (void) CopyMagickString(read_info->magick,"PNG",MaxTextExtent);
+ icon_image=BlobToImage(read_info,png,length+16,exception);
+ read_info=DestroyImageInfo(read_info);
}
- read_info=CloneImageInfo(image_info);
- (void) CopyMagickString(read_info->magick,"PNG",MaxTextExtent);
- icon_image=BlobToImage(read_info,png,length+16,exception);
- read_info=DestroyImageInfo(read_info);
png=(unsigned char *) RelinquishMagickMemory(png);
if (icon_image == (Image *) NULL)
{
+ if (count != (ssize_t) (length-16))
+ ThrowReaderException(CorruptImageError,
+ "InsufficientImageDataInFile");
image=DestroyImageList(image);
return((Image *) NULL);
}
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" bpp = %.20g",(double) icon_info.bits_per_pixel);
}
- if ((icon_info.number_colors != 0) || (icon_info.bits_per_pixel <= 16))
+ if ((icon_info.number_colors != 0) || (icon_info.bits_per_pixel <= 16U))
{
image->storage_class=PseudoClass;
image->colors=icon_info.number_colors;
register ssize_t
i;
- size_t
- number_colors,
- one;
-
unsigned char
*icon_colormap;
/*
Read Icon raster colormap.
*/
- one=1;
- number_colors=one << icon_info.bits_per_pixel;
- if (AcquireImageColormap(image,number_colors,exception) == MagickFalse)
+ if (AcquireImageColormap(image,image->colors,exception) ==
+ MagickFalse)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
icon_colormap=(unsigned char *) AcquireQuantumMemory((size_t)
image->colors,4UL*sizeof(*icon_colormap));
(image_info->number_scenes != 0))
if (image->scene >= (image_info->scene+image_info->number_scenes-1))
break;
+ status=SetImageExtent(image,image->columns,image->rows,exception);
+ if (status == MagickFalse)
+ return(DestroyImageList(image));
bytes_per_line=(((image->columns*icon_info.bits_per_pixel)+31) &
~31) >> 3;
(void) bytes_per_line;
entry=SetMagickInfo("CUR");
entry->decoder=(DecodeImageHandler *) ReadICONImage;
entry->encoder=(EncodeImageHandler *) WriteICONImage;
- entry->adjoin=MagickFalse;
- entry->seekable_stream=MagickTrue;
+ entry->flags^=CoderAdjoinFlag;
+ entry->flags|=CoderSeekableStreamFlag;
entry->description=ConstantString("Microsoft icon");
entry->module=ConstantString("CUR");
(void) RegisterMagickInfo(entry);
entry=SetMagickInfo("ICO");
entry->decoder=(DecodeImageHandler *) ReadICONImage;
entry->encoder=(EncodeImageHandler *) WriteICONImage;
- entry->adjoin=MagickTrue;
- entry->seekable_stream=MagickTrue;
+ entry->flags|=CoderSeekableStreamFlag;
entry->description=ConstantString("Microsoft icon");
entry->module=ConstantString("ICON");
(void) RegisterMagickInfo(entry);
entry=SetMagickInfo("ICON");
entry->decoder=(DecodeImageHandler *) ReadICONImage;
entry->encoder=(EncodeImageHandler *) WriteICONImage;
- entry->adjoin=MagickFalse;
- entry->seekable_stream=MagickTrue;
+ entry->flags^=CoderAdjoinFlag;
+ entry->flags|=CoderSeekableStreamFlag;
entry->description=ConstantString("Microsoft icon");
entry->module=ConstantString("ICON");
(void) RegisterMagickInfo(entry);
static MagickBooleanType WriteICONImage(const ImageInfo *image_info,
Image *image,ExceptionInfo *exception)
{
+ const char
+ *option;
+
IconFile
icon_file;
icon_info;
Image
+ *images,
*next;
MagickBooleanType
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;
+ option=GetImageOption(image_info,"icon:auto-resize");
+ if (option != (const char *) NULL)
+ {
+ images=AutoResizeImage(image,option,&scene,exception);
+ if (images == (Image *) NULL)
+ ThrowWriterException(ImageError,"InvalidDimensions");
+ }
+ 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.
*/
(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);
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) &&
write_image=CloneImage(next,0,0,MagickTrue,exception);
if (write_image == (Image *) NULL)
- return(MagickFalse);
+ {
+ images=DestroyImageList(images);
+ return(MagickFalse);
+ }
write_info=CloneImageInfo(image_info);
(void) CopyMagickString(write_info->filename,"PNG:",MaxTextExtent);
write_image=DestroyImage(write_image);
write_info=DestroyImageInfo(write_info);
if (png == (unsigned char *) NULL)
- return(MagickFalse);
+ {
+ images=DestroyImageList(images);
+ return(MagickFalse);
+ }
icon_file.directory[scene].width=0;
icon_file.directory[scene].height=0;
icon_file.directory[scene].colors=0;
/*
Initialize ICON raster file header.
*/
- if (IssRGBCompatibleColorspace(next->colorspace) == MagickFalse)
- (void) TransformImageColorspace(next,sRGBColorspace,exception);
+ (void) TransformImageColorspace(next,sRGBColorspace,exception);
icon_info.file_size=14+12+28;
icon_info.offset_bits=icon_info.file_size;
icon_info.compression=BI_RGB;
pixels=(unsigned char *) AcquireQuantumMemory((size_t)
icon_info.image_size,sizeof(*pixels));
if (pixels == (unsigned char *) NULL)
- ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ {
+ images=DestroyImageList(images);
+ ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ }
(void) ResetMagickMemory(pixels,0,(size_t) icon_info.image_size);
switch (icon_info.bits_per_pixel)
{
*q++=ScaleQuantumToChar(GetPixelBlue(next,p));
*q++=ScaleQuantumToChar(GetPixelGreen(next,p));
*q++=ScaleQuantumToChar(GetPixelRed(next,p));
- if (next->alpha_trait != BlendPixelTrait)
+ if (next->alpha_trait == UndefinedPixelTrait)
*q++=ScaleQuantumToChar(QuantumRange);
else
*q++=ScaleQuantumToChar(GetPixelAlpha(next,p));
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");
+ {
+ images=DestroyImageList(images);
+ ThrowWriterException(ResourceLimitError,
+ "MemoryAllocationFailed");
+ }
q=icon_colormap;
for (i=0; i < (ssize_t) next->colors; i++)
{
for (x=0; x < (ssize_t) next->columns; x++)
{
byte<<=1;
- if ((next->alpha_trait == BlendPixelTrait) &&
+ if ((next->alpha_trait != UndefinedPixelTrait) &&
(GetPixelAlpha(next,p) == (Quantum) TransparentAlpha))
byte|=0x01;
bit++;
}
if (GetNextImageInList(next) == (Image *) NULL)
break;
- next=SyncNextImageInList(next);
status=SetImageProgress(next,SaveImagesTag,scene++,
GetImageListLength(next));
if (status == MagickFalse)
break;
+ next=SyncNextImageInList(next);
} while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
offset=SeekBlob(image,0,SEEK_SET);
(void) offset;
(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);
next=SyncNextImageInList(next);
} while ((next != (Image *) NULL) && (image_info->adjoin != MagickFalse));
(void) CloseBlob(image);
+ images=DestroyImageList(images);
return(MagickTrue);
}