#include "MagickCore/blob.h"
#include "MagickCore/blob-private.h"
#include "MagickCore/cache.h"
+#include "MagickCore/channel.h"
#include "MagickCore/color.h"
#include "MagickCore/color-private.h"
#include "MagickCore/colormap.h"
#define PNG_SETJMP_NOT_THREAD_SAFE
#endif
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
static SemaphoreInfo
*ping_semaphore = (SemaphoreInfo *) NULL;
#endif
}
#endif /* MAGICKCORE_QUANTUM_DEPTH >= 16 */
+static const char* PngColorTypeToString(const unsigned int color_type)
+{
+ const char
+ *result = "Unknown";
+
+ switch (color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ result = "Gray";
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ result = "Gray+Alpha";
+ break;
+ case PNG_COLOR_TYPE_PALETTE:
+ result = "Palette";
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ result = "RGB";
+ break;
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ result = "RGB+Alpha";
+ break;
+ }
+
+ return result;
+}
+
static int
Magick_RenderingIntent_to_PNG_RenderingIntent(const RenderingIntent intent)
{
return(y);
}
-static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
+static const char *
+Magick_ColorType_from_PNG_ColorType(const int ping_colortype)
{
- if (x < y)
- return(x);
+ switch (ping_colortype)
+ {
+ case 0:
+ return "Grayscale";
- return(y);
-}
+ case 2:
+ return "Truecolor";
-\f
-/*
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% %
-% %
-% I m a g e I s G r a y %
-% %
-% %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% Like IsImageGray except does not change DirectClass to PseudoClass %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-*/
-static MagickBooleanType ImageIsGray(Image *image,ExceptionInfo *exception)
-{
- register const Quantum
- *p;
+ case 3:
+ return "Indexed";
- register ssize_t
- i,
- x,
- y;
+ case 4:
+ return "GrayAlpha";
- assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ case 6:
+ return "RGBA";
- if (image->storage_class == PseudoClass)
- {
- for (i=0; i < (ssize_t) image->colors; i++)
- if (IsPixelInfoGray(image->colormap+i) == MagickFalse)
- return(MagickFalse);
- return(MagickTrue);
- }
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- p=GetVirtualPixels(image,0,y,image->columns,1,exception);
- if (p == (const Quantum *) NULL)
- return(MagickFalse);
- for (x=(ssize_t) image->columns-1; x >= 0; x--)
- {
- if (IsPixelGray(image,p) == MagickFalse)
- return(MagickFalse);
- p+=GetPixelChannels(image);
+ default:
+ return "UndefinedColorType";
}
- }
- return(MagickTrue);
+}
+
+
+static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
+{
+ if (x < y)
+ return(x);
+
+ return(y);
}
#endif /* PNG_LIBPNG_VER > 10011 */
#endif /* MAGICKCORE_PNG_DELEGATE */
#ifdef PNG_USER_MEM_SUPPORTED
static png_voidp Magick_png_malloc(png_structp png_ptr,png_uint_32 size)
{
-#if (PNG_LIBPNG_VER < 10011)
- png_voidp
- ret;
-
- (void) png_ptr;
- ret=((png_voidp) AcquireMagickMemory((size_t) size));
-
- if (ret == NULL)
- png_error("Insufficient memory.");
-
- return(ret);
-#else
(void) png_ptr;
return((png_voidp) AcquireMagickMemory((size_t) size));
-#endif
}
/*
#endif
static int
-Magick_png_read_raw_profile(Image *image, const ImageInfo *image_info,
- png_textp text,int ii,ExceptionInfo *exception)
+Magick_png_read_raw_profile(png_struct *ping,Image *image,
+ const ImageInfo *image_info, png_textp text,int ii,ExceptionInfo *exception)
{
register ssize_t
i;
/* allocate space */
if (length == 0)
{
- (void) ThrowMagickException(exception,GetMagickModule(),
- CoderWarning,"UnableToCopyProfile","`%s'","invalid profile length");
+ png_warning(ping,"invalid profile length");
return(MagickFalse);
}
if (profile == (StringInfo *) NULL)
{
- (void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"MemoryAllocationFailed","`%s'",
- "unable to copy profile");
+ png_warning(ping, "unable to copy profile");
return(MagickFalse);
}
{
if (*sp == '\0')
{
- (void) ThrowMagickException(exception,GetMagickModule(),
- CoderWarning,"UnableToCopyProfile","`%s'","ran out of data");
+ png_warning(ping, "ran out of profile data");
profile=DestroyStringInfo(profile);
return(MagickFalse);
}
num_text,
num_text_total,
num_passes,
+ number_colors,
pass,
ping_bit_depth,
ping_color_type,
ssize_t
j;
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
png_byte unused_chunks[]=
{
104, 73, 83, 84, (png_byte) '\0', /* hIST */
115, 67, 65, 76, (png_byte) '\0', /* sCAL */
115, 80, 76, 84, (png_byte) '\0', /* sPLT */
116, 73, 77, 69, (png_byte) '\0', /* tIME */
+#ifdef PNG_APNG_SUPPORTED /* libpng was built with APNG patch; */
+ /* ignore the APNG chunks */
+ 97, 99, 84, 76, (png_byte) '\0', /* acTL */
+ 102, 99, 84, 76, (png_byte) '\0', /* fcTL */
+ 102, 100, 65, 84, (png_byte) '\0', /* fdAT */
+#endif
};
#endif
logging=LogMagickEvent(CoderEvent,GetMagickModule(),
" Enter ReadOnePNGImage()");
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
- LockSemaphoreInfo(ping_semaphore);
-#endif
-
#if (PNG_LIBPNG_VER < 10200)
if (image_info->verbose)
printf("Your PNG library (libpng-%s) is rather old.\n",
transparent_color.blue=65537;
transparent_color.alpha=65537;
+ number_colors=0;
num_text = 0;
num_text_total = 0;
num_raw_profiles = 0;
PNG image is corrupt.
*/
png_destroy_read_struct(&ping,&ping_info,&end_info);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
UnlockSemaphoreInfo(ping_semaphore);
#endif
+
+ if (ping_pixels != (unsigned char *) NULL)
+ ping_pixels=(unsigned char *) RelinquishMagickMemory(ping_pixels);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit ReadOnePNGImage() with error.");
return(GetFirstImageInList(image));
}
+
+ /* { For navigation to end of SETJMP-protected block. Within this
+ * block, use png_error() instead of Throwing an Exception, to ensure
+ * that libpng is able to clean up, and that the semaphore is unlocked.
+ */
+
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
+ LockSemaphoreInfo(ping_semaphore);
+#endif
+
/*
Prepare PNG for reading.
*/
png_set_read_user_chunk_fn(ping, image, read_vpag_chunk_callback);
#endif
+#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Disable new libpng-1.5.10 feature */
+ png_set_check_for_invalid_index (ping, 0);
+#endif
+
#if (PNG_LIBPNG_VER < 10400)
# if defined(PNG_USE_PNGGCCRD) && defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \
(PNG_LIBPNG_VER >= 10200) && (PNG_LIBPNG_VER < 10220) && defined(__i386__)
image->depth=ping_bit_depth;
image->depth=GetImageQuantumDepth(image,MagickFalse);
image->interlace=ping_interlace_method != 0 ? PNGInterlace : NoInterlace;
+ if (((int) ping_color_type == PNG_COLOR_TYPE_GRAY) ||
+ ((int) ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ {
+ image->rendering_intent=UndefinedIntent;
+ image->gamma=1.000;
+ (void) ResetMagickMemory(&image->chromaticity,0,
+ sizeof(image->chromaticity));
+ }
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG iCCP chunk.");
profile=BlobToStringInfo(info,profile_length);
if (profile == (StringInfo *) NULL)
- {
- (void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"MemoryAllocationFailed","`%s'",
- "unable to copy profile");
- return((Image *) NULL);
- }
- SetStringInfoDatum(profile,(const unsigned char *) info);
- (void) SetImageProfile(image,"icc",profile,exception);
- profile=DestroyStringInfo(profile);
+ {
+ png_warning(ping, "ICC profile is NULL");
+ profile=DestroyStringInfo(profile);
+ }
+ else
+ {
+ (void) SetImageProfile(image,"icc",profile,exception);
+ profile=DestroyStringInfo(profile);
+ }
}
}
#endif
#if defined(PNG_READ_sRGB_SUPPORTED)
{
if (mng_info->have_global_srgb)
- image->rendering_intent=Magick_RenderingIntent_from_PNG_RenderingIntent
- (mng_info->global_srgb_intent);
+ {
+ image->rendering_intent=Magick_RenderingIntent_from_PNG_RenderingIntent
+ (mng_info->global_srgb_intent);
+ }
if (png_get_sRGB(ping,ping_info,&intent))
{
png_set_sRGB(ping,ping_info,
Magick_RenderingIntent_to_PNG_RenderingIntent
(image->rendering_intent));
- png_set_gAMA(ping,ping_info,0.45455f);
+ png_set_gAMA(ping,ping_info,1.000f/2.200f);
png_set_cHRM(ping,ping_info,
0.6400f, 0.3300f, 0.3000f, 0.6000f,
0.1500f, 0.0600f, 0.3127f, 0.3290f);
if (png_get_valid(ping,ping_info,PNG_INFO_PLTE))
{
- int
- number_colors;
-
png_colorp
palette;
(int) mng_info->global_plte_length);
if (!png_get_valid(ping,ping_info,PNG_INFO_tRNS))
+ {
if (mng_info->global_trns_length)
{
- if (mng_info->global_trns_length >
- mng_info->global_plte_length)
- (void) ThrowMagickException(exception,
- GetMagickModule(),CoderError,
- "global tRNS has more entries than global PLTE",
- "`%s'",image_info->filename);
- png_set_tRNS(ping,ping_info,mng_info->global_trns,
- (int) mng_info->global_trns_length,NULL);
+ png_warning(ping,
+ "global tRNS has more entries than global PLTE");
}
+ else
+ {
+ png_set_tRNS(ping,ping_info,mng_info->global_trns,
+ (int) mng_info->global_trns_length,NULL);
+ }
+ }
#ifdef PNG_READ_bKGD_SUPPORTED
if (
#ifndef PNG_READ_EMPTY_PLTE_SUPPORTED
#endif
}
else
- (void) ThrowMagickException(exception,GetMagickModule(),
- CoderError,"No global PLTE in file","`%s'",
- image_info->filename);
+ png_error(ping,"No global PLTE in file");
}
}
image->compression=ZipCompression;
image->columns=ping_width;
image->rows=ping_height;
+
if (((int) ping_color_type == PNG_COLOR_TYPE_GRAY) ||
((int) ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- image->colorspace=GRAYColorspace;
+ {
+ if (!png_get_valid(ping,ping_info,PNG_INFO_gAMA) &&
+ !png_get_valid(ping,ping_info,PNG_INFO_cHRM) &&
+ !png_get_valid(ping,ping_info,PNG_INFO_sRGB))
+ {
+ /* Set image->gamma to 1.0, image->rendering_intent to Undefined,
+ * and reset image->chromaticity.
+ */
+ SetImageColorspace(image,GRAYColorspace,exception);
+ }
+ }
+
if (((int) ping_color_type == PNG_COLOR_TYPE_PALETTE) ||
((int) ping_color_type == PNG_COLOR_TYPE_GRAY))
{
#endif
if ((int) ping_color_type == PNG_COLOR_TYPE_PALETTE)
{
- int
- number_colors;
-
png_colorp
palette;
Initialize image colormap.
*/
if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+ png_error(ping,"Memory allocation failed");
if ((int) ping_color_type == PNG_COLOR_TYPE_PALETTE)
{
- int
- number_colors;
-
png_colorp
palette;
(void) FormatLocaleString(msg,MaxTextExtent,"%d",(int) ping_bit_depth);
(void) SetImageProperty(image,"png:IHDR.bit_depth ",msg,exception);
- (void) FormatLocaleString(msg,MaxTextExtent,"%d",(int) ping_color_type);
+ (void) FormatLocaleString(msg,MaxTextExtent,"%d (%s)",
+ (int) ping_color_type,
+ Magick_ColorType_from_PNG_ColorType((int)ping_color_type));
(void) SetImageProperty(image,"png:IHDR.color_type ",msg,exception);
- (void) FormatLocaleString(msg,MaxTextExtent,"%d",
- (int) ping_interlace_method);
- (void) SetImageProperty(image,"png:IHDR.interlace_method",msg,exception);
+ if (ping_interlace_method == 0)
+ {
+ (void) FormatLocaleString(msg,MaxTextExtent,"%d (Not interlaced)",
+ (int) ping_interlace_method);
+ }
+ else if (ping_interlace_method == 1)
+ {
+ (void) FormatLocaleString(msg,MaxTextExtent,"%d (Adam7 method)",
+ (int) ping_interlace_method);
+ }
+ else
+ {
+ (void) FormatLocaleString(msg,MaxTextExtent,"%d (Unknown method)",
+ (int) ping_interlace_method);
+ }
+ (void) SetImageProperty(image,"png:IHDR.interlace_method",msg,exception);
+
+ if (number_colors != 0)
+ {
+ (void) FormatLocaleString(msg,MaxTextExtent,"%d",
+ (int) number_colors);
+ (void) SetImageProperty(image,"png:PLTE.number_colors ",msg,
+ exception);
+ }
}
/*
(image_info->number_scenes != 0) && (mng_info->scenes_found > (ssize_t)
(image_info->first_scene+image_info->number_scenes))))
{
+ /* This happens later in non-ping decodes */
+ if (png_get_valid(ping,ping_info,PNG_INFO_tRNS))
+ image->storage_class=DirectClass;
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Skipping PNG image data for scene %.20g",(double)
mng_info->scenes_found-1);
png_destroy_read_struct(&ping,&ping_info,&end_info);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
UnlockSemaphoreInfo(ping_semaphore);
#endif
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit ReadOnePNGImage().");
sizeof(*ping_pixels));
if (ping_pixels == (unsigned char *) NULL)
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+ png_error(ping,"Memory allocation failed");
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
/*
Convert PNG pixels to pixel packets.
*/
- if (setjmp(png_jmpbuf(ping)))
- {
- /*
- PNG image is corrupt.
- */
- png_destroy_read_struct(&ping,&ping_info,&end_info);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
- UnlockSemaphoreInfo(ping_semaphore);
-#endif
- if (quantum_info != (QuantumInfo *) NULL)
- quantum_info = DestroyQuantumInfo(quantum_info);
-
- if (ping_pixels != (unsigned char *) NULL)
- ping_pixels=(unsigned char *) RelinquishMagickMemory(ping_pixels);
-
- if (logging != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " exit ReadOnePNGImage() with error.");
-
- if (image != (Image *) NULL)
- {
- InheritException(exception,exception);
- image->columns=0;
- }
-
- return(GetFirstImageInList(image));
- }
-
quantum_info=AcquireQuantumInfo(image_info,image);
if (quantum_info == (QuantumInfo *) NULL)
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+ png_error(ping,"Failed to allocate quantum_info");
{
row_offset=0;
png_read_row(ping,ping_pixels+row_offset,NULL);
- q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
+ q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
(image->matte ? 2 : 1)*sizeof(*quantum_scanline));
if (quantum_scanline == (Quantum *) NULL)
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+ png_error(ping,"Memory allocation failed");
for (y=0; y < (ssize_t) image->rows; y++)
{
ping_pixels=(unsigned char *) RelinquishMagickMemory(ping_pixels);
image->colors=2;
(void) SetImageBackgroundColor(image,exception);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
UnlockSemaphoreInfo(ping_semaphore);
#endif
if (logging != MagickFalse)
if (memcmp(text[i].key, "Raw profile type ",17) == 0)
{
- (void) Magick_png_read_raw_profile(image,image_info,text,(int) i,
- exception);
+ (void) Magick_png_read_raw_profile(ping,image,image_info,text,
+ (int) i,exception);
num_raw_profiles++;
}
sizeof(*value));
if (value == (char *) NULL)
{
- (void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"MemoryAllocationFailed","`%s'",
- image->filename);
+ png_error(ping,"Memory allocation failed");
break;
}
*value='\0';
mng_info->ob[object_id]->frozen)
{
if (mng_info->ob[object_id] == (MngBuffer *) NULL)
- (void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"MemoryAllocationFailed","`%s'",
- image->filename);
+ png_error(ping,"Memory allocation failed");
if (mng_info->ob[object_id]->frozen)
- (void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"Cannot overwrite frozen MNG object buffer",
- "`%s'",image->filename);
+ png_error(ping,"Cannot overwrite frozen MNG object buffer");
}
else
mng_info->ob[object_id]->image->file=(FILE *) NULL;
else
- (void) ThrowMagickException(exception,GetMagickModule(),
- ResourceLimitError,"Cloning image for object buffer failed",
- "`%s'",image->filename);
+ png_error(ping, "Cloning image for object buffer failed");
if (ping_width > 250000L || ping_height > 250000L)
png_error(ping,"PNG Image dimensions are too large.");
if (png_get_valid(ping,ping_info,PNG_INFO_PLTE))
{
- int
- number_colors;
-
png_colorp
plte;
if (png_get_valid(ping,ping_info,PNG_INFO_sRGB))
{
(void) FormatLocaleString(msg,MaxTextExtent,
- "intent=%d (See Rendering intent)",
- (int) intent);
+ "intent=%d (See Rendering intent)", (int) intent);
(void) SetImageProperty(image,"png:sRGB ",msg,
- exception);
+ exception);
}
#endif
png_destroy_read_struct(&ping,&ping_info,&end_info);
ping_pixels=(unsigned char *) RelinquishMagickMemory(ping_pixels);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
- UnlockSemaphoreInfo(ping_semaphore);
-#endif
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit ReadOnePNGImage()");
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
+ UnlockSemaphoreInfo(ping_semaphore);
+#endif
+
+ /* } for navigation to beginning of SETJMP-protected block, revert to
+ * Throwing an Exception when an error occurs.
+ */
+
return(image);
/* end of reading one PNG image */
ThrowReaderException(CorruptImageError,"CorruptImage");
}
+ if ((IssRGBColorspace(image->colorspace) != MagickFalse) &&
+ (image->gamma == 1.0))
+ SetImageColorspace(image,RGBColorspace,exception);
+
if (LocaleCompare(image_info->magick,"PNG24") == 0)
{
(void) SetImageType(image,TrueColorType,exception);
{
image->rendering_intent=
Magick_RenderingIntent_from_PNG_RenderingIntent(p[0]);
- image->gamma=0.45455f;
+ image->gamma=1.000f/2.200f;
image->chromaticity.red_primary.x=0.6400f;
image->chromaticity.red_primary.y=0.3300f;
image->chromaticity.green_primary.x=0.3000f;
if (object_id > MNG_MAX_OBJECTS)
{
/*
- Instead ofsuing a warning we should allocate a larger
+ Instead of using a warning we should allocate a larger
MngInfo structure and continue.
*/
(void) ThrowMagickException(exception,GetMagickModule(),
entry->note=ConstantString(JNGNote);
(void) RegisterMagickInfo(entry);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
ping_semaphore=AllocateSemaphoreInfo();
#endif
(void) UnregisterMagickInfo("PNG32");
(void) UnregisterMagickInfo("JNG");
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
if (ping_semaphore != (SemaphoreInfo *) NULL)
DestroySemaphoreInfo(&ping_semaphore);
#endif
if (image_info == (ImageInfo *) NULL)
ThrowWriterException(ResourceLimitError, "MemoryAllocationFailed");
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
- LockSemaphoreInfo(ping_semaphore);
-#endif
-
/* Initialize some stuff */
ping_bit_depth=0,
ping_color_type=0,
" storage_class=PseudoClass");
}
- if (image->storage_class == PseudoClass &&
+ if (image->storage_class == PseudoClass &&
(mng_info->write_png8 || mng_info->write_png24 || mng_info->write_png32 ||
(mng_info->write_png_colortype != 0 &&
mng_info->write_png_colortype != 4)))
}
}
- if (IsRGBColorspace(image->colorspace) == MagickFalse)
- (void) TransformImageColorspace(image,RGBColorspace,exception);
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ (void) TransformImageColorspace(image,sRGBColorspace,exception);
/*
Sometimes we get PseudoClass images whose RGB values don't match
{
opaque[i] = image->background_color;
ping_background.index = i;
+ number_opaque++;
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
if (mng_info->write_png_colortype != 7) /* We won't need this info */
{
ping_have_color=MagickFalse;
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ ping_have_color=MagickTrue;
ping_have_non_bw=MagickFalse;
if(image_colors > 256)
(void) ThrowMagickException(exception,GetMagickModule(),CoderError,
"Cannot write PNG8 or color-type 3; colormap is NULL",
"`%s'",IMimage->filename);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
- UnlockSemaphoreInfo(ping_semaphore);
-#endif
return(MagickFalse);
}
(void) printf("PNG write has failed.\n");
#endif
png_destroy_write_struct(&ping,&ping_info);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
UnlockSemaphoreInfo(ping_semaphore);
#endif
+
+ if (ping_pixels != (unsigned char *) NULL)
+ ping_pixels=(unsigned char *) RelinquishMagickMemory(ping_pixels);
+
+ if (quantum_info != (QuantumInfo *) NULL)
+ quantum_info=DestroyQuantumInfo(quantum_info);
+
if (ping_have_blob != MagickFalse)
(void) CloseBlob(image);
image_info=DestroyImageInfo(image_info);
image=DestroyImage(image);
return(MagickFalse);
}
+
+ /* { For navigation to end of SETJMP-protected block. Within this
+ * block, use png_error() instead of Throwing an Exception, to ensure
+ * that libpng is able to clean up, and that the semaphore is unlocked.
+ */
+
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
+ LockSemaphoreInfo(ping_semaphore);
+#endif
+
/*
Prepare PNG for writing.
*/
+
#if defined(PNG_MNG_FEATURES_SUPPORTED)
if (mng_info->write_mng)
+ {
(void) png_permit_mng_features(ping,PNG_ALL_MNG_FEATURES);
+# ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Disable new libpng-1.5.10 feature when writing a MNG because
+ * zero-length PLTE is OK
+ */
+ png_set_check_for_invalid_index (ping, 0);
+# endif
+ }
#else
# ifdef PNG_WRITE_EMPTY_PLTE_SUPPORTED
if (image->colors == 0)
{
/* DO SOMETHING */
- (void) ThrowMagickException(exception,
- GetMagickModule(),CoderError,
- "image has 0 colors", "`%s'","");
+ png_error(ping,"image has 0 colors");
}
while ((int) (one << ping_bit_depth) < (ssize_t) image_colors)
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Tentative PNG color type: %.20g",(double) ping_color_type);
+ " Tentative PNG color type: %s (%.20g)",
+ PngColorTypeToString(ping_color_type),
+ (double) ping_color_type);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" image_info->type: %.20g",(double) image_info->type);
for (i=0; i < ping_num_trans; i++)
{
- ping_trans_alpha[i]= (png_byte)
+ ping_trans_alpha[i]= (png_byte)
ScaleQuantumToChar(image->colormap[i].alpha);
}
}
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " PNG color type: %d",ping_color_type);
+ " PNG color type: %s (%d)", PngColorTypeToString(ping_color_type),
+ ping_color_type);
/*
Initialize compression level and filtering.
*/
5: libpng adaptive filtering if compression level > 5
libpng filter type "none" if compression level <= 5
or if image is grayscale or palette
-
+
6: libpng adaptive filtering
7: "LOCO" filtering (intrapixel differing) if writing
if (mng_info->write_png_compression_strategy == 0)
mng_info->write_png_compression_strategy = Z_HUFFMAN_ONLY+1;
}
-
+
else if (mng_info->write_png_compression_level == 0)
{
int
if (mng_info->write_png_compression_strategy == 0)
{
if ((quality %10) == 8 || (quality %10) == 9)
- mng_info->write_png_compression_strategy=Z_RLE;
+#ifdef Z_RLE /* Z_RLE was added to zlib-1.2.0 */
+ mng_info->write_png_compression_strategy=Z_RLE+1;
+#else
+ mng_info->write_png_compression_strategy = Z_DEFAULT_STRATEGY+1;
+#endif
}
if (mng_info->write_png_compression_filter == 0)
#if defined(PNG_WRITE_sRGB_SUPPORTED)
if ((mng_info->have_write_global_srgb == 0) &&
- ((image->rendering_intent != UndefinedIntent) ||
- (image->colorspace == sRGBColorspace)))
+ (image->rendering_intent != UndefinedIntent))
{
if (ping_exclude_sRGB == MagickFalse)
{
sizeof(*ping_pixels));
if (ping_pixels == (unsigned char *) NULL)
- ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ png_error(ping,"Allocation of memory for pixels failed");
/*
Initialize image scanlines.
*/
- if (setjmp(png_jmpbuf(ping)))
- {
- /*
- PNG write failed.
- */
-#ifdef PNG_DEBUG
- if (image_info->verbose)
- (void) printf("PNG write has failed.\n");
-#endif
- png_destroy_write_struct(&ping,&ping_info);
- if (quantum_info != (QuantumInfo *) NULL)
- quantum_info=DestroyQuantumInfo(quantum_info);
- if (ping_pixels != (unsigned char *) NULL)
- ping_pixels=(unsigned char *) RelinquishMagickMemory(ping_pixels);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
- UnlockSemaphoreInfo(ping_semaphore);
-#endif
- if (ping_have_blob != MagickFalse)
- (void) CloseBlob(image);
- image_info=DestroyImageInfo(image_info);
- image=DestroyImage(image);
- return(MagickFalse);
- }
quantum_info=AcquireQuantumInfo(image_info,image);
if (quantum_info == (QuantumInfo *) NULL)
- ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+ png_error(ping,"Memory allocation for quantum_info failed");
quantum_info->format=UndefinedQuantumFormat;
quantum_info->depth=image_depth;
num_passes=png_set_interlace_handling(ping);
{
for (y=0; y < (ssize_t) image->rows; y++)
{
- p=GetVirtualPixels(image,0,y,image->columns,1,
- exception);
+ p=GetVirtualPixels(image,0,y,image->columns,1, exception);
if (p == (const Quantum *) NULL)
break;
}
if (mng_info->write_mng && !mng_info->need_fram &&
((int) image->dispose == 3))
- (void) ThrowMagickException(exception,GetMagickModule(),
- CoderError,"Cannot convert GIF with disposal method 3 to MNG-LC",
- "`%s'",image->filename);
+ png_error(ping, "Cannot convert GIF with disposal method 3 to MNG-LC");
/*
Free PNG resources.
ping_pixels=(unsigned char *) RelinquishMagickMemory(ping_pixels);
-#if defined(PNG_SETJMP_NOT_THREAD_SAFE)
- UnlockSemaphoreInfo(ping_semaphore);
-#endif
-
if (ping_have_blob != MagickFalse)
(void) CloseBlob(image);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit WriteOnePNGImage()");
+#ifdef PNG_SETJMP_NOT_THREAD_SAFE
+ UnlockSemaphoreInfo(ping_semaphore);
+#endif
+
+ /* } for navigation to beginning of SETJMP-protected block. Revert to
+ * Throwing an Exception when an error occurs.
+ */
+
return(MagickTrue);
/* End write one PNG image */
+
}
/*
mng_info->write_png24=LocaleCompare(image_info->magick,"PNG24") == 0;
mng_info->write_png32=LocaleCompare(image_info->magick,"PNG32") == 0;
+ value=GetImageOption(image_info,"png:format");
+
+ if (value != (char *) NULL)
+ {
+ if (LocaleCompare(value,"png8") == 0)
+ {
+ mng_info->write_png8 = MagickTrue;
+ mng_info->write_png24 = MagickFalse;
+ mng_info->write_png32 = MagickFalse;
+ }
+
+ else if (LocaleCompare(value,"png24") == 0)
+ {
+ mng_info->write_png8 = MagickFalse;
+ mng_info->write_png24 = MagickTrue;
+ mng_info->write_png32 = MagickFalse;
+ }
+
+ else if (LocaleCompare(value,"png32") == 0)
+ {
+ mng_info->write_png8 = MagickFalse;
+ mng_info->write_png24 = MagickFalse;
+ mng_info->write_png32 = MagickTrue;
+ }
+ }
if (mng_info->write_png8)
{
mng_info->write_png_colortype = /* 3 */ 4;
if (LocaleCompare(value,"0") == 0)
mng_info->write_png_colortype = 1;
+ else if (LocaleCompare(value,"1") == 0)
+ mng_info->write_png_colortype = 2;
+
else if (LocaleCompare(value,"2") == 0)
mng_info->write_png_colortype = 3;
jng_alpha_compression_method=image->compression==JPEGCompression? 8 : 0;
- jng_alpha_quality=image_info->quality == 0UL ? 75UL :
+ jng_alpha_quality=image_info->quality == 0UL ? 75UL :
image_info->quality;
if (jng_alpha_quality >= 1000)
/* Check if image is grayscale. */
if (image_info->type != TrueColorMatteType && image_info->type !=
- TrueColorType && ImageIsGray(image,exception))
+ TrueColorType && IsImageGray(image,exception))
jng_color_type-=2;
if (logging != MagickFalse)
if (need_local_plte == 0)
{
- if (ImageIsGray(image,exception) == MagickFalse)
+ if (IsImageGray(image,exception) == MagickFalse)
all_images_are_gray=MagickFalse;
mng_info->equal_palettes=PalettesAreEqual(image,next_image);
if (use_global_plte == 0)