WriteWEBPImage(const ImageInfo *,Image *,ExceptionInfo *);
#endif
\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
+% I s W E B P %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% IsWEBP() returns MagickTrue if the image format type, identified by the
+% magick string, is WebP.
+%
+% The format of the IsWEBP method is:
+%
+% MagickBooleanType IsWEBP(const unsigned char *magick,const size_t length)
+%
+% A description of each parameter follows:
+%
+% o magick: compare image format pattern against these bytes.
+%
+% o length: Specifies the length of the magick string.
+%
+*/
+static MagickBooleanType IsWEBP(const unsigned char *magick,const size_t length)
+{
+ if (length < 12)
+ return(MagickFalse);
+ if (LocaleNCompare((const char *) magick+8,"WEBP",4) == 0)
+ return(MagickTrue);
+ return(MagickFalse);
+}
+\f
#if defined(MAGICKCORE_WEBP_DELEGATE)
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% o exception: return any errors or warnings in this structure.
%
*/
+
+static inline uint32_t ReadWebPLSBWord(const unsigned char *restrict data)
+{
+ register const unsigned char
+ *p;
+
+ register uint32_t
+ value;
+
+ p=data;
+ value=(uint32_t) (*p++);
+ value|=((uint32_t) (*p++)) << 8;
+ value|=((uint32_t) (*p++)) << 16;
+ value|=((uint32_t) (*p++)) << 24;
+ return(value);
+}
+
+static MagickBooleanType IsWEBPImageLossless(const unsigned char *stream,
+ const size_t length)
+{
+#define VP8_CHUNK_INDEX 15
+#define LOSSLESS_FLAG 'L'
+#define EXTENDED_HEADER 'X'
+#define VP8_CHUNK_HEADER "VP8"
+#define VP8_CHUNK_HEADER_SIZE 3
+#define RIFF_HEADER_SIZE 12
+#define VP8X_CHUNK_SIZE 10
+#define TAG_SIZE 4
+#define CHUNK_SIZE_BYTES 4
+#define CHUNK_HEADER_SIZE 8
+#define MAX_CHUNK_PAYLOAD (~0U-CHUNK_HEADER_SIZE-1)
+
+ ssize_t
+ offset;
+
+ /*
+ Read simple header.
+ */
+ if (stream[VP8_CHUNK_INDEX] != EXTENDED_HEADER)
+ return(stream[VP8_CHUNK_INDEX] == LOSSLESS_FLAG ? MagickTrue : MagickFalse);
+ /*
+ Read extended header.
+ */
+ offset=RIFF_HEADER_SIZE+TAG_SIZE+CHUNK_SIZE_BYTES+VP8X_CHUNK_SIZE;
+ while (offset <= length)
+ {
+ uint32_t
+ chunk_size,
+ chunk_size_pad;
+
+ chunk_size=ReadWebPLSBWord(stream+pos+TAG_SIZE);
+ if (chunk_size > MAX_CHUNK_PAYLOAD)
+ break;
+ chunk_size_pad=(CHUNK_HEADER_SIZE+chunk_size+1) & ~1;
+ if (memcmp( stream+offset,VP8_CHUNK_HEADER,VP8_CHUNK_HEADER_SIZE) == 0)
+ return*(stream+offset+VP8_CHUNK_HEADER_SIZE) == LOSSLESS_FLAG ?
+ MagickTrue : MagickFalse);
+ offset+=chunk_size_pad;
+ }
+ return(MagickFalse);
+}
+
static Image *ReadWEBPImage(const ImageInfo *image_info,
ExceptionInfo *exception)
{
configure;
WebPDecBuffer
- *const webp_image = &configure.output;
+ *restrict webp_image = &configure.output;
WebPBitstreamFeatures
- *const features = &configure.input;
+ *restrict features = &configure.input;
/*
Open image file.
image->rows=(size_t) webp_image->height;
image->alpha_trait=features->has_alpha != 0 ? BlendPixelTrait :
UndefinedPixelTrait;
- if ((stream[15] == 'L') || (stream[15] == ' '))
+ if (IsWEBPImageLossless(stream,length) != MagickFalse)
image->quality=100;
p=webp_image->u.RGBA.rgba;
for (y=0; y < (ssize_t) image->rows; y++)
entry->description=ConstantString("WebP Image Format");
entry->adjoin=MagickFalse;
entry->module=ConstantString("WEBP");
+ entry->magick=(IsImageFormatHandler *) IsWEBP;
if (*version != '\0')
entry->version=ConstantString(version);
(void) RegisterMagickInfo(entry);
assert(image->signature == MagickSignature);
if (image->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- if ((image->columns > 16383) || (image->rows > 16383))
+ if ((image->columns > 16383UL) || (image->rows > 16383UL))
ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
if (status == MagickFalse)
configure.lossless=1;
value=GetImageOption(image_info,"webp:lossless");
if (value != (char *) NULL)
- configure.lossess=ParseCommandOption(MagickBooleanOptions,MagickFalse,
+ configure.lossless=ParseCommandOption(MagickBooleanOptions,MagickFalse,
value);
value=GetImageOption(image_info,"webp:method");
if (value != (char *) NULL)
value=GetImageOption(image_info,"webp:image-hint");
if (value != (char *) NULL)
{
- if (LocaleCompare(value,"graph"):
+ if (LocaleCompare(value,"graph") == 0)
configure.image_hint=WEBP_HINT_GRAPH;
- if (LocaleCompare(value,"photo"):
+ if (LocaleCompare(value,"photo") == 0)
configure.image_hint=WEBP_HINT_PHOTO;
- if (LocaleCompare(value,"picture"):
+ if (LocaleCompare(value,"picture") == 0)
configure.image_hint=WEBP_HINT_PICTURE;
}
value=GetImageOption(image_info,"webp:target-size");