% July 1992 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2012 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 declarations.
*/
-#include "magick/studio.h"
-#include "magick/blob.h"
-#include "magick/blob-private.h"
-#include "magick/cache.h"
-#include "magick/color.h"
-#include "magick/color-private.h"
-#include "magick/colormap.h"
-#include "magick/colormap-private.h"
-#include "magick/colorspace.h"
-#include "magick/exception.h"
-#include "magick/exception-private.h"
-#include "magick/image.h"
-#include "magick/image-private.h"
-#include "magick/list.h"
-#include "magick/profile.h"
-#include "magick/magick.h"
-#include "magick/memory_.h"
-#include "magick/monitor.h"
-#include "magick/monitor-private.h"
-#include "magick/option.h"
-#include "magick/property.h"
-#include "magick/quantize.h"
-#include "magick/quantum-private.h"
-#include "magick/static.h"
-#include "magick/string_.h"
-#include "magick/module.h"
+#include "MagickCore/studio.h"
+#include "MagickCore/attribute.h"
+#include "MagickCore/blob.h"
+#include "MagickCore/blob-private.h"
+#include "MagickCore/cache.h"
+#include "MagickCore/color.h"
+#include "MagickCore/color-private.h"
+#include "MagickCore/colormap.h"
+#include "MagickCore/colormap-private.h"
+#include "MagickCore/colorspace.h"
+#include "MagickCore/colorspace-private.h"
+#include "MagickCore/exception.h"
+#include "MagickCore/exception-private.h"
+#include "MagickCore/image.h"
+#include "MagickCore/image-private.h"
+#include "MagickCore/list.h"
+#include "MagickCore/profile.h"
+#include "MagickCore/magick.h"
+#include "MagickCore/memory_.h"
+#include "MagickCore/monitor.h"
+#include "MagickCore/monitor-private.h"
+#include "MagickCore/option.h"
+#include "MagickCore/pixel.h"
+#include "MagickCore/pixel-accessor.h"
+#include "MagickCore/property.h"
+#include "MagickCore/quantize.h"
+#include "MagickCore/quantum-private.h"
+#include "MagickCore/static.h"
+#include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
+#include "MagickCore/module.h"
\f
/*
Define declarations.
GetNextLZWCode(LZWInfo *,const size_t);
static MagickBooleanType
- WriteGIFImage(const ImageInfo *,Image *);
+ WriteGIFImage(const ImageInfo *,Image *,ExceptionInfo *);
static ssize_t
ReadBlobBlock(Image *,unsigned char *);
return(PopLZWStack(lzw_info->stack));
}
-static MagickBooleanType DecodeImage(Image *image,const ssize_t opacity)
+static MagickBooleanType DecodeImage(Image *image,const ssize_t opacity,
+ ExceptionInfo *exception)
{
- ExceptionInfo
- *exception;
+ int
+ c;
- IndexPacket
+ LZWInfo
+ *lzw_info;
+
+ Quantum
index;
- int
- c;
+ size_t
+ pass;
ssize_t
offset,
y;
- LZWInfo
- *lzw_info;
-
unsigned char
data_size;
- size_t
- pass;
-
/*
Allocate decoder tables.
*/
if (lzw_info == (LZWInfo *) NULL)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
- exception=(&image->exception);
pass=0;
offset=0;
for (y=0; y < (ssize_t) image->rows; y++)
{
- register IndexPacket
- *restrict indexes;
-
register ssize_t
x;
- register PixelPacket
+ register Quantum
*restrict q;
q=GetAuthenticPixels(image,0,offset,image->columns,1,exception);
- if (q == (PixelPacket *) NULL)
+ if (q == (Quantum *) NULL)
break;
- indexes=GetAuthenticIndexQueue(image);
for (x=0; x < (ssize_t) image->columns; )
{
c=ReadBlobLZWByte(lzw_info);
if (c < 0)
break;
- index=ConstrainColormapIndex(image,(size_t) c);
- SetIndexPixelComponent(indexes+x,index);
- SetRedPixelComponent(q,image->colormap[(ssize_t) index].red);
- SetGreenPixelComponent(q,image->colormap[(ssize_t) index].green);
- SetBluePixelComponent(q,image->colormap[(ssize_t) index].blue);
- SetOpacityPixelComponent(q,(ssize_t) index == opacity ?
- TransparentOpacity : OpaqueOpacity);
+ index=ConstrainColormapIndex(image,(size_t) c,exception);
+ SetPixelIndex(image,index,q);
+ SetPixelInfoPixel(image,image->colormap+(ssize_t) index,q);
+ SetPixelAlpha(image,(ssize_t) index == opacity ? TransparentAlpha :
+ OpaqueAlpha,q);
x++;
- q++;
+ q+=GetPixelChannels(image);
}
if (x < (ssize_t) image->columns)
break;
%
*/
static MagickBooleanType EncodeImage(const ImageInfo *image_info,Image *image,
- const size_t data_size)
+ const size_t data_size,ExceptionInfo *exception)
{
#define MaxCode(number_bits) ((one << (number_bits))-1)
#define MaxHashTable 5003
} \
}
- IndexPacket
+ Quantum
index;
register ssize_t
waiting_code=0;
for (y=0; y < (ssize_t) image->rows; y++)
{
- register const IndexPacket
- *restrict indexes;
-
- register const PixelPacket
+ register const Quantum
*restrict p;
register ssize_t
x;
- p=GetVirtualPixels(image,0,offset,image->columns,1,&image->exception);
- if (p == (const PixelPacket *) NULL)
+ p=GetVirtualPixels(image,0,offset,image->columns,1,exception);
+ if (p == (const Quantum *) NULL)
break;
- indexes=GetVirtualIndexQueue(image);
if (y == 0)
- waiting_code=(short) (*indexes);
+ {
+ waiting_code=(short) GetPixelIndex(image,p);
+ p+=GetPixelChannels(image);
+ }
for (x=(ssize_t) (y == 0 ? 1 : 0); x < (ssize_t) image->columns; x++)
{
/*
Probe hash table.
*/
- index=(IndexPacket) ((size_t) indexes[x] & 0xff);
- p++;
+ index=(Quantum) ((size_t) GetPixelIndex(image,p) & 0xff);
+ p+=GetPixelChannels(image);
k=(ssize_t) (((size_t) index << (MaxGIFBits-8))+waiting_code);
if (k >= MaxHashTable)
k-=MaxHashTable;
return(y);
}
-static MagickBooleanType PingGIFImage(Image *image)
+static MagickBooleanType PingGIFImage(Image *image,ExceptionInfo *exception)
{
unsigned char
buffer[256],
image_info->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickSignature);
- image=AcquireImage(image_info);
+ image=AcquireImage(image_info,exception);
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
if (status == MagickFalse)
{
/*
GIF Extension block.
*/
-
count=ReadBlob(image,1,&c);
if (count != 1)
{
char
*comments;
+ size_t
+ length;
+
/*
Read comment extension.
*/
comments=AcquireString((char *) NULL);
- for ( ; ; )
+ for (length=0; ; length+=count)
{
count=(ssize_t) ReadBlobBlock(image,header);
if (count == 0)
break;
header[count]='\0';
- (void) ConcatenateString(&comments,(const char *) header);
+ comments=(char *) ResizeQuantumMemory(comments,length+count,
+ sizeof(*comments));
+ if (comments == (char *) NULL)
+ ThrowReaderException(ResourceLimitError,
+ "MemoryAllocationFailed");
+ (void) CopyMagickMemory(comments+length,header,(size_t) count);
}
- (void) SetImageProperty(image,"comment",comments);
+ comments[length+count]='\0';
+ (void) SetImageProperty(image,"comment",comments,exception);
comments=DestroyString(comments);
break;
}
case 0xff:
{
- /* Read GIF application extension */
-
MagickBooleanType
loop;
MagickBooleanType
i8bim,
icc,
- iptc;
+ iptc,
+ magick;
StringInfo
*profile;
/*
Store GIF application extension as a generic profile.
*/
- i8bim=LocaleNCompare((char *) header,"MGK8BIM0000",11) == 0 ?
- MagickTrue : MagickFalse;
icc=LocaleNCompare((char *) header,"ICCRGBG1012",11) == 0 ?
MagickTrue : MagickFalse;
+ magick=LocaleNCompare((char *) header,"ImageMagick",11) == 0 ?
+ MagickTrue : MagickFalse;
+ i8bim=LocaleNCompare((char *) header,"MGK8BIM0000",11) == 0 ?
+ MagickTrue : MagickFalse;
iptc=LocaleNCompare((char *) header,"MGKIPTC0000",11) == 0 ?
MagickTrue : MagickFalse;
number_extensionss++;
" Reading GIF application extension");
info=(unsigned char *) AcquireQuantumMemory(255UL,
sizeof(*info));
+ if (info == (unsigned char *) NULL)
+ ThrowReaderException(ResourceLimitError,
+ "MemoryAllocationFailed");
reserved_length=255;
for (info_length=0; ; )
{
reserved_length+=4096;
info=(unsigned char *) ResizeQuantumMemory(info,
(size_t) reserved_length,sizeof(*info));
+ if (info == (unsigned char *) NULL)
+ ThrowReaderException(ResourceLimitError,
+ "MemoryAllocationFailed");
}
}
- info=(unsigned char *) ResizeQuantumMemory(info,(size_t)
- (info_length+1),sizeof(*info));
- profile=AcquireStringInfo((size_t) info_length);
- SetStringInfoDatum(profile,(const unsigned char *) info);
+ profile=BlobToStringInfo(info,(size_t) info_length);
+ if (profile == (StringInfo *) NULL)
+ ThrowReaderException(ResourceLimitError,
+ "MemoryAllocationFailed");
if (i8bim == MagickTrue)
(void) CopyMagickString(name,"8bim",sizeof(name));
else if (icc == MagickTrue)
(void) CopyMagickString(name,"icc",sizeof(name));
else if (iptc == MagickTrue)
(void) CopyMagickString(name,"iptc",sizeof(name));
+ else if (magick == MagickTrue)
+ {
+ (void) CopyMagickString(name,"magick",sizeof(name));
+ image->gamma=StringToDouble((char *) info+6,(char **) NULL);
+ }
else
- (void) FormatMagickString(name,sizeof(name),"gif:%.11s",
+ (void) FormatLocaleString(name,sizeof(name),"gif:%.11s",
header);
- (void) SetImageProfile(image,name,profile);
info=(unsigned char *) RelinquishMagickMemory(info);
+ if (magick == MagickFalse)
+ (void) SetImageProfile(image,name,profile,exception);
profile=DestroyStringInfo(profile);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" profile name=%s",name);
/*
Allocate next image structure.
*/
- AcquireNextImage(image_info,image);
+ AcquireNextImage(image_info,image,exception);
if (GetNextImageInList(image) == (Image *) NULL)
{
image=DestroyImageList(image);
image->rows=ReadBlobLSBShort(image);
image->depth=8;
flag=(unsigned char) ReadBlobByte(image);
- image->interlace=BitSet((int) flag,0x40) != 0 ? GIFInterlace :
- NoInterlace;
- image->colors=BitSet((int) flag,0x80) == 0 ? global_colors :
- one << ((size_t) (flag & 0x07)+1);
+ image->interlace=BitSet((int) flag,0x40) != 0 ? GIFInterlace : NoInterlace;
+ image->colors=BitSet((int) flag,0x80) == 0 ? global_colors : one <<
+ ((size_t) (flag & 0x07)+1);
if (opacity >= (ssize_t) image->colors)
opacity=(-1);
image->page.width=page.width;
/*
Inititialize colormap.
*/
- if (AcquireImageColormap(image,image->colors) == MagickFalse)
+ if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
{
global_colormap=(unsigned char *) RelinquishMagickMemory(
global_colormap);
p=global_colormap;
for (i=0; i < (ssize_t) image->colors; i++)
{
- image->colormap[i].red=ScaleCharToQuantum(*p++);
- image->colormap[i].green=ScaleCharToQuantum(*p++);
- image->colormap[i].blue=ScaleCharToQuantum(*p++);
+ image->colormap[i].red=(double) ScaleCharToQuantum(*p++);
+ image->colormap[i].green=(double) ScaleCharToQuantum(*p++);
+ image->colormap[i].blue=(double) ScaleCharToQuantum(*p++);
if (i == opacity)
{
- image->colormap[i].opacity=(Quantum) TransparentOpacity;
+ image->colormap[i].alpha=(double) TransparentAlpha;
image->transparent_color=image->colormap[opacity];
}
}
/*
Read local colormap.
*/
- colormap=(unsigned char *) AcquireQuantumMemory(image->colors,
- 3*sizeof(*colormap));
+ colormap=(unsigned char *) AcquireQuantumMemory(image->colors,3*
+ sizeof(*colormap));
if (colormap == (unsigned char *) NULL)
{
global_colormap=(unsigned char *) RelinquishMagickMemory(
p=colormap;
for (i=0; i < (ssize_t) image->colors; i++)
{
- image->colormap[i].red=ScaleCharToQuantum(*p++);
- image->colormap[i].green=ScaleCharToQuantum(*p++);
- image->colormap[i].blue=ScaleCharToQuantum(*p++);
+ image->colormap[i].red=(double) ScaleCharToQuantum(*p++);
+ image->colormap[i].green=(double) ScaleCharToQuantum(*p++);
+ image->colormap[i].blue=(double) ScaleCharToQuantum(*p++);
if (i == opacity)
- image->colormap[i].opacity=(Quantum) TransparentOpacity;
+ image->colormap[i].alpha=(double) TransparentAlpha;
}
colormap=(unsigned char *) RelinquishMagickMemory(colormap);
}
+ if (image->gamma == 1.0)
+ {
+ for (i=0; i < (ssize_t) image->colors; i++)
+ if (IsPixelInfoGray(image->colormap+i) == MagickFalse)
+ break;
+ (void) SetImageColorspace(image,i == (ssize_t) image->colors ?
+ GRAYColorspace : RGBColorspace,exception);
+ }
if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
if (image->scene >= (image_info->scene+image_info->number_scenes-1))
break;
Decode image.
*/
if (image_info->ping != MagickFalse)
- status=PingGIFImage(image);
+ status=PingGIFImage(image,exception);
else
- status=DecodeImage(image,opacity);
+ status=DecodeImage(image,opacity,exception);
if ((image_info->ping == MagickFalse) && (status == MagickFalse))
{
global_colormap=(unsigned char *) RelinquishMagickMemory(
%
% The format of the WriteGIFImage method is:
%
-% MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image)
+% MagickBooleanType WriteGIFImage(const ImageInfo *image_info,
+% Image *image,ExceptionInfo *exception)
%
% A description of each parameter follows.
%
%
% o image: The image.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
-static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image)
+static MagickBooleanType WriteGIFImage(const ImageInfo *image_info,Image *image,
+ ExceptionInfo *exception)
{
- Image
- *next_image;
-
int
c;
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
+ assert(exception != (ExceptionInfo *) NULL);
+ assert(exception->signature == MagickSignature);
+ status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
if (status == MagickFalse)
return(status);
/*
Determine image bounding box.
*/
page.width=image->columns;
+ if (image->page.width > page.width)
+ page.width=image->page.width;
page.height=image->rows;
- page.x=0;
- page.y=0;
- if (write_info->adjoin != MagickFalse)
- for (next_image=image; next_image != (Image *) NULL; )
- {
- page.x=next_image->page.x;
- page.y=next_image->page.y;
- if ((next_image->page.width+page.x) > page.width)
- page.width=next_image->page.width+page.x;
- if ((next_image->page.height+page.y) > page.height)
- page.height=next_image->page.height+page.y;
- next_image=GetNextImageInList(next_image);
- }
+ if (image->page.height > page.height)
+ page.height=image->page.height;
page.x=image->page.x;
page.y=image->page.y;
- if ((image->page.width != 0) && (image->page.height != 0))
- page=image->page;
(void) WriteBlobLSBShort(image,(unsigned short) page.width);
(void) WriteBlobLSBShort(image,(unsigned short) page.height);
/*
one=1;
do
{
- if (image->colorspace != RGBColorspace)
- (void) TransformImageColorspace(image,RGBColorspace);
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
opacity=(-1);
- if (IsOpaqueImage(image,&image->exception) != MagickFalse)
+ if (IsImageOpaque(image,exception) != MagickFalse)
{
if ((image->storage_class == DirectClass) || (image->colors > 256))
- (void) SetImageType(image,PaletteType);
+ (void) SetImageType(image,PaletteType,exception);
}
else
{
Identify transparent colormap index.
*/
if ((image->storage_class == DirectClass) || (image->colors > 256))
- (void) SetImageType(image,PaletteBilevelMatteType);
+ (void) SetImageType(image,PaletteBilevelMatteType,exception);
for (i=0; i < (ssize_t) image->colors; i++)
- if (image->colormap[i].opacity != OpaqueOpacity)
+ if (image->colormap[i].alpha != OpaqueAlpha)
{
if (opacity < 0)
{
opacity=i;
continue;
}
- alpha=(MagickRealType) TransparentOpacity-(MagickRealType)
- image->colormap[i].opacity;
- beta=(MagickRealType) TransparentOpacity-(MagickRealType)
- image->colormap[opacity].opacity;
+ alpha=(MagickRealType) TransparentAlpha-(MagickRealType)
+ image->colormap[i].alpha;
+ beta=(MagickRealType) TransparentAlpha-(MagickRealType)
+ image->colormap[opacity].alpha;
if (alpha < beta)
opacity=i;
}
if (opacity == -1)
{
- (void) SetImageType(image,PaletteBilevelMatteType);
+ (void) SetImageType(image,PaletteBilevelMatteType,exception);
for (i=0; i < (ssize_t) image->colors; i++)
- if (image->colormap[i].opacity != OpaqueOpacity)
+ if (image->colormap[i].alpha != OpaqueAlpha)
{
if (opacity < 0)
{
opacity=i;
continue;
}
- alpha=(Quantum) TransparentOpacity-(MagickRealType)
- image->colormap[i].opacity;
- beta=(Quantum) TransparentOpacity-(MagickRealType)
- image->colormap[opacity].opacity;
+ alpha=(Quantum) TransparentAlpha-(MagickRealType)
+ image->colormap[i].alpha;
+ beta=(Quantum) TransparentAlpha-(MagickRealType)
+ image->colormap[opacity].alpha;
if (alpha < beta)
opacity=i;
}
q=colormap;
for (i=0; i < (ssize_t) image->colors; i++)
{
- *q++=ScaleQuantumToChar(image->colormap[i].red);
- *q++=ScaleQuantumToChar(image->colormap[i].green);
- *q++=ScaleQuantumToChar(image->colormap[i].blue);
+ *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].red));
+ *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].green));
+ *q++=ScaleQuantumToChar(ClampToQuantum(image->colormap[i].blue));
}
for ( ; i < (ssize_t) (one << bits_per_pixel); i++)
{
c|=(bits_per_pixel-1); /* size of global colormap */
(void) WriteBlobByte(image,(unsigned char) c);
for (j=0; j < (ssize_t) image->colors; j++)
- if (IsColorEqual(&image->background_color,image->colormap+j))
+ if (IsPixelInfoEquivalent(&image->background_color,image->colormap+j))
break;
(void) WriteBlobByte(image,(unsigned char)
(j == (ssize_t) image->colors ? 0 : j)); /* background color */
0));
(void) WriteBlobByte(image,(unsigned char) 0x00);
if ((LocaleCompare(write_info->magick,"GIF87") != 0) &&
- (GetImageProperty(image,"comment") != (const char *) NULL))
+ (GetImageProperty(image,"comment",exception) != (const char *) NULL))
{
const char
*value;
- register const char
+ register const char
*p;
size_t
count;
-
+
/*
- Write Comment extension.
+ Write comment extension.
*/
(void) WriteBlobByte(image,(unsigned char) 0x21);
(void) WriteBlobByte(image,(unsigned char) 0xfe);
- value=GetImageProperty(image,"comment");
- p=value;
- while (strlen(p) != 0)
+ value=GetImageProperty(image,"comment",exception);
+ for (p=value; *p != '\0'; )
{
count=MagickMin(strlen(p),255);
(void) WriteBlobByte(image,(unsigned char) count);
(void) WriteBlobLSBShort(image,(unsigned short) image->iterations);
(void) WriteBlobByte(image,(unsigned char) 0x00);
}
+ if ((image->gamma != 1.0f/2.2f))
+ {
+ char
+ attributes[MaxTextExtent];
+
+ ssize_t
+ length;
+
+ /*
+ Write ImageMagick extension.
+ */
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Writing GIF Extension %s","ImageMagick");
+ (void) WriteBlobByte(image,(unsigned char) 0x21);
+ (void) WriteBlobByte(image,(unsigned char) 0xff);
+ (void) WriteBlobByte(image,(unsigned char) 0x0b);
+ (void) WriteBlob(image,11,(unsigned char *) "ImageMagick");
+ length=FormatLocaleString(attributes,MaxTextExtent,"gamma=%g",
+ image->gamma);
+ (void) WriteBlobByte(image,(unsigned char) length);
+ (void) WriteBlob(image,length,(unsigned char *) attributes);
+ (void) WriteBlobByte(image,(unsigned char) 0x00);
+ }
ResetImageProfileIterator(image);
for ( ; ; )
{
/*
Write ICC extension.
*/
- (void) WriteBlob(image,11,(unsigned char *)"ICCRGBG1012");
+ (void) WriteBlob(image,11,(unsigned char *) "ICCRGBG1012");
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing GIF Extension %s","ICCRGBG1012");
}
if ((LocaleCompare(name,"IPTC") == 0))
{
/*
- write IPTC extension.
+ Write IPTC extension.
*/
- (void) WriteBlob(image,11,(unsigned char *)"MGKIPTC0000");
+ (void) WriteBlob(image,11,(unsigned char *) "MGKIPTC0000");
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing GIF Extension %s","MGKIPTC0000");
}
if ((LocaleCompare(name,"8BIM") == 0))
{
/*
- Write 8BIM extension>
+ Write 8BIM extension.
*/
(void) WriteBlob(image,11,(unsigned char *)
"MGK8BIM0000");
char
extension[MaxTextExtent];
- /* write generic extension */
+ /*
+ Write generic extension.
+ */
(void) CopyMagickString(extension,name+4,
sizeof(extension));
(void) WriteBlob(image,11,(unsigned char *) extension);
*/
c=(int) MagickMax(bits_per_pixel,2);
(void) WriteBlobByte(image,(unsigned char) c);
- status=EncodeImage(write_info,image,(size_t) MagickMax(bits_per_pixel,2)+1);
+ status=EncodeImage(write_info,image,(size_t) MagickMax(bits_per_pixel,2)+1,
+ exception);
if (status == MagickFalse)
{
global_colormap=(unsigned char *) RelinquishMagickMemory(