% July 1992 %
% %
% %
-% Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2013 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/static.h"
#include "MagickCore/string_.h"
#include "MagickCore/string-private.h"
+#include "MagickCore/token.h"
#include "MagickCore/utility.h"
#include "MagickCore/xml-tree.h"
#include "MagickCore/xml-tree-private.h"
#include <setjmp.h>
#if defined(MAGICKCORE_JPEG_DELEGATE)
#define JPEG_INTERNAL_OPTIONS
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(__MINGW64__)
# define XMD_H 1 /* Avoid conflicting typedef for INT32 */
-typedef unsigned char boolean;
-#define HAVE_BOOLEAN
#endif
#undef HAVE_STDLIB_H
#include "jpeglib.h"
#define ICC_PROFILE "ICC_PROFILE"
#define IPTC_MARKER (JPEG_APP0+13)
#define XML_MARKER (JPEG_APP0+1)
-#define MaxBufferExtent 8192
+#define MaxBufferExtent 16384
\f
/*
Typedef declarations.
MagickBooleanType
finished;
+ StringInfo
+ *profile;
+
jmp_buf
error_recovery;
} ErrorManager;
width,
height;
+ double
+ divisor;
+
unsigned int
- divisor,
*levels;
} QuantizationTable;
\f
MaxBufferExtent,source->buffer);
if (source->manager.bytes_in_buffer == 0)
{
- if (source->start_of_blob != 0)
+ if (source->start_of_blob != FALSE)
ERREXIT(cinfo,JERR_INPUT_EMPTY);
WARNMS(cinfo,JWRN_JPEG_EOF);
source->buffer[0]=(JOCTET) 0xff;
static MagickBooleanType JPEGWarningHandler(j_common_ptr jpeg_info,int level)
{
+#define JPEGExcessiveWarnings 1000
+
char
message[JMSG_LENGTH_MAX];
Process warning message.
*/
(jpeg_info->err->format_message)(jpeg_info,message);
- if ((jpeg_info->err->num_warnings == 0) ||
- (jpeg_info->err->trace_level >= 3))
- ThrowBinaryException(CorruptImageWarning,(char *) message,
- image->filename);
- jpeg_info->err->num_warnings++;
+ if (jpeg_info->err->num_warnings++ > JPEGExcessiveWarnings)
+ JPEGErrorHandler(jpeg_info);
+ ThrowBinaryException(CorruptImageWarning,(char *) message,
+ image->filename);
}
else
if ((image->debug != MagickFalse) &&
static boolean ReadComment(j_decompress_ptr jpeg_info)
{
- char
- *comment;
-
ErrorManager
*error_manager;
Image
*image;
- register char
+ register unsigned char
*p;
register ssize_t
size_t
length;
+ StringInfo
+ *comment;
+
/*
Determine length of comment.
*/
length-=2;
if (length <= 0)
return(MagickTrue);
- comment=(char *) NULL;
- if (~length >= (MaxTextExtent-1))
- comment=(char *) AcquireQuantumMemory(length+MaxTextExtent,
- sizeof(*comment));
- if (comment == (char *) NULL)
+ comment=BlobToStringInfo((const void *) NULL,length);
+ if (comment == (StringInfo *) NULL)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
/*
Read comment.
*/
- i=(ssize_t) length-1;
- for (p=comment; i-- >= 0; p++)
- *p=(char) GetCharacter(jpeg_info);
+ error_manager->profile=comment;
+ p=GetStringInfoDatum(comment);
+ for (i=0; i < (ssize_t) GetStringInfoLength(comment); i++)
+ *p++=(unsigned char) GetCharacter(jpeg_info);
*p='\0';
- (void) SetImageProperty(image,"comment",comment,exception);
- comment=DestroyString(comment);
+ error_manager->profile=NULL;
+ p=GetStringInfoDatum(comment);
+ (void) SetImageProperty(image,"comment",(const char *) p,exception);
+ comment=DestroyStringInfo(comment);
return(MagickTrue);
}
if (profile == (StringInfo *) NULL)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
+ error_manager->profile=profile;
p=GetStringInfoDatum(profile);
for (i=(ssize_t) GetStringInfoLength(profile)-1; i >= 0; i--)
*p++=(unsigned char) GetCharacter(jpeg_info);
+ error_manager->profile=NULL;
icc_profile=(StringInfo *) GetImageProfile(image,"icc");
if (icc_profile != (StringInfo *) NULL)
{
if (profile == (StringInfo *) NULL)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
+ error_manager->profile=profile;
p=GetStringInfoDatum(profile);
for (i=0; i < (ssize_t) GetStringInfoLength(profile); i++)
*p++=(unsigned char) GetCharacter(jpeg_info);
+ error_manager->profile=NULL;
iptc_profile=(StringInfo *) GetImageProfile(image,"8bim");
if (iptc_profile != (StringInfo *) NULL)
{
if (profile == (StringInfo *) NULL)
ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
image->filename);
+ error_manager->profile=profile;
p=GetStringInfoDatum(profile);
for (i=0; i < (ssize_t) GetStringInfoLength(profile); i++)
*p++=(unsigned char) GetCharacter(jpeg_info);
+ error_manager->profile=NULL;
if (marker == 1)
{
p=GetStringInfoDatum(profile);
*image;
JSAMPLE
- *jpeg_pixels;
+ *volatile jpeg_pixels;
JSAMPROW
scanline[1];
if (setjmp(error_manager.error_recovery) != 0)
{
jpeg_destroy_decompress(&jpeg_info);
+ if (error_manager.profile != (StringInfo *) NULL)
+ error_manager.profile=DestroyStringInfo(error_manager.profile);
(void) CloseBlob(image);
number_pixels=(MagickSizeType) image->columns*image->rows;
if (number_pixels != 0)
(image_info->colorspace == Rec601YCbCrColorspace) ||
(image_info->colorspace == Rec709YCbCrColorspace))
jpeg_info.out_color_space=JCS_YCbCr;
- if (IsITUFaxImage(image) != MagickFalse)
- {
- image->colorspace=LabColorspace;
- jpeg_info.out_color_space=JCS_YCbCr;
- }
- else
- if (jpeg_info.out_color_space == JCS_CMYK)
- image->colorspace=CMYKColorspace;
/*
Set image resolution.
*/
jpeg_info.desired_number_of_colors=(int) StringToUnsignedLong(option);
}
option=GetImageOption(image_info,"jpeg:block-smoothing");
- if (option != (const char *) NULL)
- {
- jpeg_info.do_block_smoothing=MagickFalse;
- if (IsMagickTrue(option) != MagickFalse)
- jpeg_info.do_block_smoothing=MagickTrue;
- }
+ jpeg_info.do_block_smoothing=IsStringTrue(option);
jpeg_info.dct_method=JDCT_FLOAT;
option=GetImageOption(image_info,"jpeg:dct-method");
if (option != (const char *) NULL)
}
}
option=GetImageOption(image_info,"jpeg:fancy-upsampling");
- if (option != (const char *) NULL)
- {
- jpeg_info.do_fancy_upsampling=MagickFalse;
- if (IsMagickTrue(option) != MagickFalse)
- jpeg_info.do_fancy_upsampling=MagickTrue;
- }
+ jpeg_info.do_fancy_upsampling=IsStringTrue(option);
(void) jpeg_start_decompress(&jpeg_info);
image->columns=jpeg_info.output_width;
image->rows=jpeg_info.output_height;
image->depth=(size_t) jpeg_info.data_precision;
- if (jpeg_info.out_color_space == JCS_YCbCr)
- image->colorspace=YCbCrColorspace;
- if (jpeg_info.out_color_space == JCS_CMYK)
- image->colorspace=CMYKColorspace;
+ switch (jpeg_info.out_color_space)
+ {
+ case JCS_RGB:
+ default:
+ {
+ (void) SetImageColorspace(image,sRGBColorspace,exception);
+ break;
+ }
+ case JCS_GRAYSCALE:
+ {
+ (void) SetImageColorspace(image,GRAYColorspace,exception);
+ break;
+ }
+ case JCS_YCbCr:
+ {
+ (void) SetImageColorspace(image,YCbCrColorspace,exception);
+ break;
+ }
+ case JCS_CMYK:
+ {
+ (void) SetImageColorspace(image,CMYKColorspace,exception);
+ break;
+ }
+ }
+ if (IsITUFaxImage(image) != MagickFalse)
+ {
+ (void) SetImageColorspace(image,LabColorspace,exception);
+ jpeg_info.out_color_space=JCS_YCbCr;
+ }
option=GetImageOption(image_info,"jpeg:colors");
if (option != (const char *) NULL)
if (AcquireImageColormap(image,StringToUnsignedLong(option),exception)
*/
if (setjmp(error_manager.error_recovery) != 0)
{
- if (jpeg_pixels != (unsigned char *) NULL)
- jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
+ if (jpeg_pixels != (JSAMPLE *) NULL)
+ jpeg_pixels=(JSAMPLE *) RelinquishMagickMemory(jpeg_pixels);
jpeg_destroy_decompress(&jpeg_info);
(void) CloseBlob(image);
number_pixels=(MagickSizeType) image->columns*image->rows;
Free jpeg resources.
*/
jpeg_destroy_decompress(&jpeg_info);
- jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
+ jpeg_pixels=(JSAMPLE *) RelinquishMagickMemory(jpeg_pixels);
(void) CloseBlob(image);
return(GetFirstImageInList(image));
}
xml=DestroyString(xml);
return(table);
}
- table->divisor=(unsigned int) StringToLong(attribute);
- if (table->divisor < 1)
+ table->divisor=InterpretLocaleValue(attribute,(char **) NULL);
+ if (table->divisor == 0.0)
{
(void) ThrowMagickException(exception,GetMagickModule(),OptionError,
"XmlInvalidAttribute", "<levels divisor>, table \"%s\"",slot);
"UnableToAcquireQuantizationTable");
for (i=0; i < (ssize_t) (table->width*table->height); i++)
{
- table->levels[i]=(unsigned int) (InterpretLocaleValue(content,&p)+0.5);
- if (table->divisor != 1)
- table->levels[i]/=table->divisor;
+ table->levels[i]=(unsigned int) (InterpretLocaleValue(content,&p)/
+ table->divisor+0.5);
while (isspace((int) ((unsigned char) *p)) != 0)
p++;
if (*p == ',')
p++;
content=p;
}
- for (j=i; i < 64; i++)
- table->levels[j]=table->levels[j-1];
- value=(double) strtol(content,&p,10);
+ value=InterpretLocaleValue(content,&p);
(void) value;
if (p != content)
{
xml=DestroyString(xml);
return(table);
}
+ for (j=i; j < 64; j++)
+ table->levels[j]=table->levels[j-1];
quantization_tables=DestroyXMLTree(quantization_tables);
xml=DestroyString(xml);
return(table);
quality;
JSAMPLE
- *jpeg_pixels;
+ *volatile jpeg_pixels;
JSAMPROW
scanline[1];
}
default:
{
- if (IsRGBColorspace(image->colorspace) == MagickFalse)
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
(void) TransformImageColorspace(image,sRGBColorspace,exception);
break;
}
jpeg_info.in_color_space=JCS_GRAYSCALE;
}
jpeg_set_defaults(&jpeg_info);
+ if (jpeg_info.in_color_space == JCS_CMYK)
+ jpeg_set_colorspace(&jpeg_info,JCS_YCCK);
if ((jpeg_info.data_precision != 12) && (image->depth <= 8))
jpeg_info.data_precision=8;
else
}
option=GetImageOption(image_info,"jpeg:optimize-coding");
if (option != (const char *) NULL)
- {
- jpeg_info.optimize_coding=MagickFalse;
- if (IsMagickTrue(option) != MagickFalse)
- jpeg_info.optimize_coding=MagickTrue;
- }
+ jpeg_info.optimize_coding=IsStringTrue(option);
else
{
MagickSizeType
Perform optimization only if available memory resources permit it.
*/
status=AcquireMagickResource(MemoryResource,length);
- if (status != MagickFalse)
- jpeg_info.optimize_coding=MagickTrue;
RelinquishMagickResource(MemoryResource,length);
+ jpeg_info.optimize_coding=status;
}
}
#if (JPEG_LIB_VERSION >= 61) && defined(C_PROGRESSIVE_SUPPORTED)
#endif
}
jpeg_set_quality(&jpeg_info,quality,MagickTrue);
+#if (JPEG_LIB_VERSION >= 70)
+ option=GetImageOption(image_info,"quality");
+ if (option != (const char *) NULL)
+ {
+ GeometryInfo
+ geometry_info;
+
+ int
+ flags;
+
+ /*
+ Set quality scaling for luminance and chrominance separately.
+ */
+ flags=ParseGeometry(option,&geometry_info);
+ if (((flags & RhoValue) != 0) && ((flags & SigmaValue) != 0))
+ {
+ jpeg_info.q_scale_factor[0]=jpeg_quality_scaling((int)
+ (geometry_info.rho+0.5));
+ jpeg_info.q_scale_factor[1]=jpeg_quality_scaling((int)
+ (geometry_info.sigma+0.5));
+ jpeg_default_qtables(&jpeg_info,MagickTrue);
+ }
+ }
+#endif
sampling_factor=(const char *) NULL;
- value=GetImageProperty(image,"jpeg:sampling-factor",exception);
+ value=GetImageOption(image_info,"jpeg:sampling-factor");
+ if (value == (char *) NULL)
+ value=GetImageProperty(image,"jpeg:sampling-factor",exception);
if (value != (char *) NULL)
{
sampling_factor=value;
if (setjmp(error_manager.error_recovery) != 0)
{
jpeg_destroy_compress(&jpeg_info);
- if (jpeg_pixels != (unsigned char *) NULL)
- jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
+ if (jpeg_pixels != (JSAMPLE *) NULL)
+ jpeg_pixels=(JSAMPLE *) RelinquishMagickMemory(jpeg_pixels);
(void) CloseBlob(image);
return(MagickFalse);
}
Convert DirectClass packets to contiguous CMYK scanlines.
*/
*q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
- GetPixelRed(image,p))));
+ GetPixelCyan(image,p))));
*q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
- GetPixelGreen(image,p))));
+ GetPixelMagenta(image,p))));
*q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
- GetPixelBlue(image,p))));
+ GetPixelYellow(image,p))));
*q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
GetPixelBlack(image,p))));
p+=GetPixelChannels(image);
Relinquish resources.
*/
jpeg_destroy_compress(&jpeg_info);
- jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
+ jpeg_pixels=(JSAMPLE *) RelinquishMagickMemory(jpeg_pixels);
(void) CloseBlob(image);
return(MagickTrue);
}