% November 1997 %
% %
% %
-% 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 %
}
#define LBR01PixelRed(pixel) \
- (ScaleQuantumToChar(GetPixelRed(image,(pixel))) < 0x10 ? \
- 0 : QuantumRange);
+ (SetPixelRed(image, \
+ ScaleQuantumToChar(GetPixelRed(image,(pixel))) < 0x10 ? \
+ 0 : QuantumRange,(pixel)));
#define LBR01PixelGreen(pixel) \
- (ScaleQuantumToChar(GetPixelGreen(image,(pixel))) < 0x10 ? \
- 0 : QuantumRange);
+ (SetPixelGreen(image, \
+ ScaleQuantumToChar(GetPixelGreen(image,(pixel))) < 0x10 ? \
+ 0 : QuantumRange,(pixel)));
#define LBR01PixelBlue(pixel) \
- (ScaleQuantumToChar(GetPixelBlue(image,(pixel))) < 0x10 ? \
- 0 : QuantumRange);
+ (SetPixelBlue(image, \
+ ScaleQuantumToChar(GetPixelBlue(image,(pixel))) < 0x10 ? \
+ 0 : QuantumRange,(pixel)));
#define LBR01PixelAlpha(pixel) \
- (ScaleQuantumToChar(GetPixelAlpha(image,(pixel))) < 0x10 ? \
- 0 : QuantumRange);
+ (SetPixelAlpha(image, \
+ ScaleQuantumToChar(GetPixelAlpha(image,(pixel))) < 0x10 ? \
+ 0 : QuantumRange,(pixel)));
#define LBR01PixelRGB(pixel) \
{ \
}
+#if MAGICKCORE_QUANTUM_DEPTH > 8
/* LBR08: Replicate top 8 bits */
#define LBR08PacketRed(pixelpacket) \
LBR08PixelRGB((pixel)); \
LBR08PixelAlpha((pixel)); \
}
+#endif /* MAGICKCORE_QUANTUM_DEPTH > 8 */
+#if MAGICKCORE_QUANTUM_DEPTH > 16
/* LBR16: Replicate top 16 bits */
#define LBR16PacketRed(pixelpacket) \
LBR16PixelRGB((pixel)); \
LBR16PixelAlpha((pixel)); \
}
+#endif /* MAGICKCORE_QUANTUM_DEPTH > 16 */
/*
Establish thread safety.
write_png_compression_filter,
write_png8,
write_png24,
- write_png32;
+ write_png32,
+ write_png48,
+ write_png64;
#ifdef MNG_BASI_SUPPORTED
size_t
}
}
-static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
+static const char *
+Magick_RenderingIntentString_from_PNG_RenderingIntent(const int ping_intent)
{
- if (x > y)
- return(x);
+ switch (ping_intent)
+ {
+ case 0:
+ return "Perceptual Intent";
- return(y);
+ case 1:
+ return "Relative Intent";
+
+ case 2:
+ return "Saturation Intent";
+
+ case 3:
+ return "Absolute Intent";
+
+ default:
+ return "Undefined Intent";
+ }
}
-static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
+static inline ssize_t MagickMax(const ssize_t x,const ssize_t y)
{
- if (x < y)
+ if (x > y)
return(x);
return(y);
}
-\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)
+static const char *
+Magick_ColorType_from_PNG_ColorType(const int ping_colortype)
{
- register const Quantum
- *p;
+ switch (ping_colortype)
+ {
+ case 0:
+ return "Grayscale";
- register ssize_t
- i,
- x,
- y;
+ case 2:
+ return "Truecolor";
- assert(image != (Image *) NULL);
- assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ case 3:
+ return "Indexed";
- 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);
+ case 4:
+ return "GrayAlpha";
+
+ case 6:
+ return "RGBA";
+
+ 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 >= 14000
+static png_voidp Magick_png_malloc(png_structp png_ptr,png_alloc_size_t size)
+#else
+static png_voidp Magick_png_malloc(png_structp png_ptr,png_size_t size)
+#endif
{
(void) png_ptr;
return((png_voidp) AcquireMagickMemory((size_t) size));
*image;
int
- intent,
+ intent, /* "PNG Rendering intent", which is ICC intent + 1 */
num_raw_profiles,
num_text,
num_text_total,
num_passes,
+ number_colors,
pass,
ping_bit_depth,
ping_color_type,
+ ping_file_depth,
ping_interlace_method,
ping_compression_method,
ping_filter_method,
MagickBooleanType
logging,
+ ping_found_cHRM,
+ ping_found_gAMA,
+ ping_found_iCCP,
+ ping_found_sRGB,
status;
PixelInfo
QuantumInfo
*quantum_info;
- unsigned char
- *ping_pixels;
-
ssize_t
ping_rowbytes,
y;
ssize_t
j;
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+ unsigned char
+ *volatile ping_pixels;
+
+#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
image=mng_info->image;
if (logging != MagickFalse)
+ {
+ (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+ " image->alpha_trait=%d",(int) image->alpha_trait);
+
(void)LogMagickEvent(CoderEvent,GetMagickModule(),
- " image->matte=%d",(int) image->matte);
+ " image->rendering_intent=%d",(int) image->rendering_intent);
+
+ (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+ " image->colorspace=%d",(int) image->colorspace);
+ }
+ intent=Magick_RenderingIntent_to_PNG_RenderingIntent(image->rendering_intent);
/* Set to an out-of-range color unless tRNS chunk is present */
transparent_color.red=65537;
transparent_color.blue=65537;
transparent_color.alpha=65537;
+ number_colors=0;
num_text = 0;
num_text_total = 0;
num_raw_profiles = 0;
+ ping_found_cHRM = MagickFalse;
+ ping_found_gAMA = MagickFalse;
+ ping_found_iCCP = MagickFalse;
+ ping_found_sRGB = MagickFalse;
+
/*
Allocate the PNG structures
*/
png_set_read_user_chunk_fn(ping, image, read_vpag_chunk_callback);
#endif
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+# if (PNG_LIBPNG_VER >= 10400)
+ /* Limit the size of the chunk storage cache used for sPLT, text,
+ * and unknown chunks.
+ */
+ png_set_chunk_cache_max(ping, 32767);
+# endif
+#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__)
&ping_interlace_method,&ping_compression_method,
&ping_filter_method);
+ ping_file_depth = ping_bit_depth;
+
+ /* Save bit-depth and color-type in case we later want to write a PNG00 */
+ {
+ char
+ msg[MaxTextExtent];
+
+ (void) FormatLocaleString(msg,MaxTextExtent,"%d",(int) ping_color_type);
+ (void) SetImageProperty(image,"png:IHDR.color-type-orig ",msg,exception);
+
+ (void) FormatLocaleString(msg,MaxTextExtent,"%d",(int) ping_bit_depth);
+ (void) SetImageProperty(image,"png:IHDR.bit-depth-orig ",msg,exception);
+ }
+
(void) png_get_tRNS(ping, ping_info, &ping_trans_alpha, &ping_num_trans,
&ping_trans_color);
if (ping_bit_depth < 8)
{
- if (((int) ping_color_type == PNG_COLOR_TYPE_PALETTE))
- {
- png_set_packing(ping);
- ping_bit_depth = 8;
- }
+ png_set_packing(ping);
+ ping_bit_depth = 8;
}
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;
+ intent=Magick_RenderingIntent_to_PNG_RenderingIntent(UndefinedIntent);
+ image->gamma=1.000;
+ (void) ResetMagickMemory(&image->chromaticity,0,
+ sizeof(image->chromaticity));
+ }
+
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
ping_interlace_method,ping_filter_method);
}
+ if (png_get_valid(ping,ping_info,PNG_INFO_gAMA))
+ {
+ ping_found_gAMA=MagickTrue;
+ if (logging != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Found PNG gAMA chunk.");
+ }
+
+ if (png_get_valid(ping,ping_info,PNG_INFO_cHRM))
+ {
+ ping_found_cHRM=MagickTrue;
+ if (logging != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Found PNG cHRM chunk.");
+ }
+
+ if (png_get_valid(ping,ping_info,PNG_INFO_iCCP))
+ {
+ ping_found_iCCP=MagickTrue;
+ if (logging != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Found PNG iCCP chunk.");
+ }
+
+ if (png_get_valid(ping,ping_info,PNG_INFO_sRGB))
+ {
+ ping_found_sRGB=MagickTrue;
+ if (logging != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Found PNG sRGB chunk.");
+ }
+
#ifdef PNG_READ_iCCP_SUPPORTED
if (png_get_valid(ping,ping_info,PNG_INFO_iCCP))
{
" Reading PNG gAMA chunk: gamma: %f",file_gamma);
}
}
+
if (!png_get_valid(ping,ping_info,PNG_INFO_cHRM))
{
if (mng_info->have_global_chrm != MagickFalse)
&image->chromaticity.blue_primary.x,
&image->chromaticity.blue_primary.y);
- if (logging != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Reading PNG cHRM chunk.");
+ ping_found_cHRM=MagickTrue;
}
if (image->rendering_intent != UndefinedIntent)
{
- png_set_sRGB(ping,ping_info,
- Magick_RenderingIntent_to_PNG_RenderingIntent
- (image->rendering_intent));
- 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 (ping_found_sRGB != MagickTrue)
+ {
+ png_set_sRGB(ping,ping_info,
+ Magick_RenderingIntent_to_PNG_RenderingIntent
+ (image->rendering_intent));
+ png_set_gAMA(ping,ping_info,1.000f/2.200f);
+ file_gamma=1.000f/2.200f;
+ ping_found_sRGB=MagickTrue;
+ ping_found_cHRM=MagickTrue;
+ }
}
+
#if defined(PNG_oFFs_SUPPORTED)
if (png_get_valid(ping,ping_info,PNG_INFO_oFFs))
{
if (png_get_valid(ping,ping_info,PNG_INFO_PLTE))
{
- int
- number_colors;
-
png_colorp
palette;
bkgd_scale = 1;
- if (ping_bit_depth == 1)
+ if (ping_file_depth == 1)
bkgd_scale = 255;
- else if (ping_bit_depth == 2)
+ else if (ping_file_depth == 2)
bkgd_scale = 85;
- else if (ping_bit_depth == 4)
+ else if (ping_file_depth == 4)
bkgd_scale = 17;
- if (ping_bit_depth <= 8)
+ if (ping_file_depth <= 8)
bkgd_scale *= 257;
ping_background->red *= bkgd_scale;
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG tRNS chunk.");
- max_sample = (int) ((one << ping_bit_depth) - 1);
+ max_sample = (int) ((one << ping_file_depth) - 1);
if ((ping_color_type == PNG_COLOR_TYPE_GRAY &&
(int)ping_trans_color->gray > max_sample) ||
" Ignoring PNG tRNS chunk with out-of-range sample.");
png_free_data(ping, ping_info, PNG_FREE_TRNS, 0);
png_set_invalid(ping,ping_info,PNG_INFO_tRNS);
- image->matte=MagickFalse;
+ image->alpha_trait=UndefinedPixelTrait;
}
else
{
int
scale_to_short;
- scale_to_short = 65535L/((1UL << ping_bit_depth)-1);
+ scale_to_short = 65535L/((1UL << ping_file_depth)-1);
/* Scale transparent_color to short */
transparent_color.red= scale_to_short*ping_trans_color->red;
image->columns=ping_width;
image->rows=ping_height;
- /* Note that the following sets image->gamma to 1.0, image->rendering_intent
- to Undefined, and resets image->chromaticity, overriding any ancillary
- chunk data from the PNG file.
- */
if (((int) ping_color_type == PNG_COLOR_TYPE_GRAY) ||
((int) ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- SetImageColorspace(image,GRAYColorspace,exception);
+ {
+ if ((!png_get_valid(ping,ping_info,PNG_INFO_gAMA) ||
+ image->gamma == 1.0) &&
+ ping_found_cHRM != MagickTrue && ping_found_sRGB != MagickTrue)
+ {
+ /* Set image->gamma to 1.0, image->rendering_intent to Undefined,
+ * image->colorspace to GRAY, and reset image->chromaticity.
+ */
+ SetImageColorspace(image,GRAYColorspace,exception);
+ }
+ }
+
+ (void)LogMagickEvent(CoderEvent,GetMagickModule(),
+ " image->colorspace=%d",(int) image->colorspace);
if (((int) ping_color_type == PNG_COLOR_TYPE_PALETTE) ||
- ((int) ping_color_type == PNG_COLOR_TYPE_GRAY))
+ ((int) ping_bit_depth < 16 &&
+ (int) ping_color_type == PNG_COLOR_TYPE_GRAY))
{
size_t
one;
image->storage_class=PseudoClass;
one=1;
- image->colors=one << ping_bit_depth;
+ image->colors=one << ping_file_depth;
#if (MAGICKCORE_QUANTUM_DEPTH == 8)
if (image->colors > 256)
image->colors=256;
#endif
if ((int) ping_color_type == PNG_COLOR_TYPE_PALETTE)
{
- int
- number_colors;
-
png_colorp
palette;
if ((int) ping_color_type == PNG_COLOR_TYPE_PALETTE)
{
- int
- number_colors;
-
png_colorp
palette;
size_t
scale;
- scale=(QuantumRange/((1UL << ping_bit_depth)-1));
+ scale=(QuantumRange/((1UL << ping_file_depth)-1));
if (scale < 1)
scale=1;
char
msg[MaxTextExtent];
- /* encode ping_width, ping_height, ping_bit_depth, ping_color_type,
+ /* encode ping_width, ping_height, ping_file_depth, ping_color_type,
ping_interlace_method in value */
(void) FormatLocaleString(msg,MaxTextExtent,
"%d, %d",(int) ping_width, (int) ping_height);
(void) SetImageProperty(image,"png:IHDR.width,height ",msg,exception);
- (void) FormatLocaleString(msg,MaxTextExtent,"%d",(int) ping_bit_depth);
+ (void) FormatLocaleString(msg,MaxTextExtent,"%d",(int) ping_file_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);
+ }
}
/*
if (quantum_info == (QuantumInfo *) NULL)
png_error(ping,"Failed to allocate quantum_info");
+ (void) SetQuantumEndian(image,quantum_info,MSBEndian);
+
{
MagickBooleanType
/*
Convert image to DirectClass pixel packets.
*/
-#if (MAGICKCORE_QUANTUM_DEPTH == 8)
- int
- depth;
-
- depth=(ssize_t) ping_bit_depth;
-#endif
- image->matte=(((int) ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA) ||
+ image->alpha_trait=(((int) ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA) ||
((int) ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
(png_get_valid(ping,ping_info,PNG_INFO_tRNS))) ?
- MagickTrue : MagickFalse;
+ BlendPixelTrait : UndefinedPixelTrait;
for (y=0; y < (ssize_t) image->rows; y++)
{
row_offset=0;
png_read_row(ping,ping_pixels+row_offset,NULL);
- q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
+
+ if (pass < num_passes-1)
+ continue;
+
+ q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Converting grayscale pixels to pixel packets");
- image->matte=ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ?
- MagickTrue : MagickFalse;
+ image->alpha_trait=ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ?
+ BlendPixelTrait : UndefinedPixelTrait;
quantum_scanline=(Quantum *) AcquireQuantumMemory(image->columns,
- (image->matte ? 2 : 1)*sizeof(*quantum_scanline));
+ (image->alpha_trait == BlendPixelTrait? 2 : 1)*
+ sizeof(*quantum_scanline));
if (quantum_scanline == (Quantum *) NULL)
png_error(ping,"Memory allocation failed");
for (y=0; y < (ssize_t) image->rows; y++)
{
+ Quantum
+ alpha;
+
if (num_passes > 1)
row_offset=ping_rowbytes*y;
row_offset=0;
png_read_row(ping,ping_pixels+row_offset,NULL);
- q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
+
+ if (pass < num_passes-1)
+ continue;
+
+ q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
switch (ping_bit_depth)
{
- case 1:
- {
- register ssize_t
- bit;
-
- for (x=(ssize_t) image->columns-7; x > 0; x-=8)
- {
- for (bit=7; bit >= 0; bit--)
- *r++=(Quantum) ((*p) & (0x01 << bit) ? 0x01 : 0x00);
- p++;
- }
-
- if ((image->columns % 8) != 0)
- {
- for (bit=7; bit >= (ssize_t) (8-(image->columns % 8)); bit--)
- *r++=(Quantum) ((*p) & (0x01 << bit) ? 0x01 : 0x00);
- }
-
- break;
- }
-
- case 2:
- {
- for (x=(ssize_t) image->columns-3; x > 0; x-=4)
- {
- *r++=(*p >> 6) & 0x03;
- *r++=(*p >> 4) & 0x03;
- *r++=(*p >> 2) & 0x03;
- *r++=(*p++) & 0x03;
- }
-
- if ((image->columns % 4) != 0)
- {
- for (i=3; i >= (ssize_t) (4-(image->columns % 4)); i--)
- *r++=(Quantum) ((*p >> (i*2)) & 0x03);
- }
-
- break;
- }
-
- case 4:
- {
- for (x=(ssize_t) image->columns-1; x > 0; x-=2)
- {
- *r++=(*p >> 4) & 0x0f;
- *r++=(*p++) & 0x0f;
- }
-
- if ((image->columns % 2) != 0)
- *r++=(*p++ >> 4) & 0x0f;
-
- break;
- }
-
case 8:
{
+
if (ping_color_type == 4)
for (x=(ssize_t) image->columns-1; x >= 0; x--)
{
*r++=*p++;
- SetPixelAlpha(image,ScaleCharToQuantum((unsigned char) *p++),q);
- if (GetPixelAlpha(image,q) != OpaqueAlpha)
+
+ alpha=ScaleCharToQuantum((unsigned char)*p++);
+
+ SetPixelAlpha(image,alpha,q);
+
+ if (alpha != OpaqueAlpha)
found_transparent_pixel = MagickTrue;
+
q+=GetPixelChannels(image);
}
quantum=0;
quantum|=(*p++);
- SetPixelAlpha(image,ScaleShortToQuantum(quantum),q);
- if (GetPixelAlpha(image,q) != OpaqueAlpha)
+
+ alpha=ScaleShortToQuantum(quantum);
+ SetPixelAlpha(image,alpha,q);
+
+ if (alpha != OpaqueAlpha)
found_transparent_pixel = MagickTrue;
+
q+=GetPixelChannels(image);
}
if (ping_color_type == 4)
{
SetPixelAlpha(image,*p++,q);
+
if (GetPixelAlpha(image,q) != OpaqueAlpha)
found_transparent_pixel = MagickTrue;
+
p++;
q+=GetPixelChannels(image);
}
quantum_scanline=(Quantum *) RelinquishMagickMemory(quantum_scanline);
}
- image->matte=found_transparent_pixel;
+ image->alpha_trait=found_transparent_pixel ? BlendPixelTrait :
+ UndefinedPixelTrait;
if (logging != MagickFalse)
{
if (image->storage_class == PseudoClass)
{
- MagickBooleanType
- matte;
+ PixelTrait
+ alpha_trait;
- matte=image->matte;
- image->matte=MagickFalse;
+ alpha_trait=image->alpha_trait;
+ image->alpha_trait=UndefinedPixelTrait;
(void) SyncImage(image,exception);
- image->matte=matte;
+ image->alpha_trait=alpha_trait;
}
png_read_end(ping,end_info);
Image has a transparent background.
*/
storage_class=image->storage_class;
- image->matte=MagickTrue;
+ image->alpha_trait=BlendPixelTrait;
/* Balfour fix from imagemagick discourse server, 5 Feb 2010 */
{
for (x=0; x < ping_num_trans; x++)
{
- image->colormap[x].matte=MagickTrue;
+ image->colormap[x].alpha_trait=BlendPixelTrait;
image->colormap[x].alpha =
ScaleCharToQuantum((unsigned char)ping_trans_alpha[x]);
}
if (ScaleQuantumToShort(image->colormap[x].red) ==
transparent_color.alpha)
{
- image->colormap[x].matte=MagickTrue;
+ image->colormap[x].alpha_trait=BlendPixelTrait;
image->colormap[x].alpha = (Quantum) TransparentAlpha;
}
}
if (png_get_valid(ping,ping_info,PNG_INFO_PLTE))
{
- int
- number_colors;
-
png_colorp
plte;
}
#endif
- /* Set image->matte to MagickTrue if the input colortype supports
+ /* Set image->alpha_trait to MagickTrue if the input colortype supports
* alpha or if a valid tRNS chunk is present, no matter whether there
* is actual transparency present.
*/
- image->matte=(((int) ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA) ||
+ image->alpha_trait=(((int) ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA) ||
((int) ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
(png_get_valid(ping,ping_info,PNG_INFO_tRNS))) ?
- MagickTrue : MagickFalse;
+ BlendPixelTrait : UndefinedPixelTrait;
+
+#if 0 /* I'm not sure what's wrong here but it does not work. */
+ if (image->alpha_trait == BlendPixelTrait)
+ {
+ if (ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ (void) SetImageType(image,GrayscaleMatteType,exception);
+
+ else if (ping_color_type == PNG_COLOR_TYPE_PALETTE)
+ (void) SetImageType(image,PaletteMatteType,exception);
+
+ else
+ (void) SetImageType(image,TrueColorMatteType,exception);
+ }
+
+ else
+ {
+ if (ping_color_type == PNG_COLOR_TYPE_GRAY)
+ (void) SetImageType(image,GrayscaleType,exception);
+
+ else if (ping_color_type == PNG_COLOR_TYPE_PALETTE)
+ (void) SetImageType(image,PaletteType,exception);
+
+ else
+ (void) SetImageType(image,TrueColorType,exception);
+ }
+#endif
/* Set more properties for identify to retrieve */
{
exception);
}
- if (png_get_valid(ping,ping_info,PNG_INFO_cHRM))
+ if (ping_found_cHRM != MagickFalse)
{
(void) FormatLocaleString(msg,MaxTextExtent,"%s",
"chunk was found (see Chromaticity, above)");
(void) FormatLocaleString(msg,MaxTextExtent,"%s",
"chunk was found");
- if (png_get_valid(ping,ping_info,PNG_INFO_iCCP))
+#if defined(PNG_iCCP_SUPPORTED)
+ if (ping_found_iCCP != MagickFalse)
(void) SetImageProperty(image,"png:iCCP ",msg,
exception);
+#endif
if (png_get_valid(ping,ping_info,PNG_INFO_tRNS))
(void) SetImageProperty(image,"png:tRNS ",msg,
exception);
#if defined(PNG_sRGB_SUPPORTED)
- if (png_get_valid(ping,ping_info,PNG_INFO_sRGB))
+ if (ping_found_sRGB != MagickFalse)
{
(void) FormatLocaleString(msg,MaxTextExtent,
- "intent=%d (See Rendering intent)", (int) intent);
+ "intent=%d (%s)",
+ (int) intent,
+ Magick_RenderingIntentString_from_PNG_RenderingIntent(intent));
(void) SetImageProperty(image,"png:sRGB ",msg,
- exception);
+ exception);
}
#endif
- if (png_get_valid(ping,ping_info,PNG_INFO_gAMA))
+ if (ping_found_gAMA != MagickFalse)
{
(void) FormatLocaleString(msg,MaxTextExtent,
"gamma=%.8g (See Gamma, above)",
ThrowReaderException(CorruptImageError,"CorruptImage");
}
- if (LocaleCompare(image_info->magick,"PNG24") == 0)
- {
- (void) SetImageType(image,TrueColorType,exception);
- image->matte=MagickFalse;
- }
-
- if (LocaleCompare(image_info->magick,"PNG32") == 0)
- (void) SetImageType(image,TrueColorMatteType,exception);
+ if ((IssRGBColorspace(image->colorspace) != MagickFalse) &&
+ ((image->gamma < .45) || (image->gamma > .46)))
+ SetImageColorspace(image,RGBColorspace,exception);
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
exception);
q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
- if (image->matte != MagickFalse)
+ if (image->alpha_trait == BlendPixelTrait)
for (x=(ssize_t) image->columns; x != 0; x--)
{
SetPixelAlpha(image,GetPixelRed(jng_image,s),q);
{
SetPixelAlpha(image,GetPixelRed(jng_image,s),q);
if (GetPixelAlpha(image,q) != OpaqueAlpha)
- image->matte=MagickTrue;
+ image->alpha_trait=BlendPixelTrait;
q+=GetPixelChannels(image);
s+=GetPixelChannels(jng_image);
}
image->page.x=mng_info->clip.left;
image->page.y=mng_info->clip.top;
image->background_color=mng_background_color;
- image->matte=MagickFalse;
+ image->alpha_trait=UndefinedPixelTrait;
image->delay=0;
(void) SetImageBackgroundColor(image,exception);
image->page.x=mng_info->clip.left;
image->page.y=mng_info->clip.top;
image->background_color=mng_background_color;
- image->matte=MagickFalse;
+ image->alpha_trait=UndefinedPixelTrait;
(void) SetImageBackgroundColor(image,exception);
if (logging != MagickFalse)
#define QM Quantum
#endif
- if (image->matte != MagickFalse)
+ if (image->alpha_trait == BlendPixelTrait)
(void) SetImageBackgroundColor(large_image,exception);
else
((ssize_t) (m*2))
+GetPixelBlue(image,pixels)))),q);
- if (image->matte != MagickFalse)
+ if (image->alpha_trait == BlendPixelTrait)
SetPixelAlpha(large_image, ((QM) (((ssize_t)
(2*i*(GetPixelAlpha(image,n)
-GetPixelAlpha(image,pixels)+m))
-GetPixelBlue(image,pixels))+m)
/((ssize_t) (m*2))+
GetPixelBlue(image,pixels)),q);
- if (image->matte != MagickFalse)
+ if (image->alpha_trait == BlendPixelTrait)
SetPixelAlpha(image,(QM) ((2*i*(
GetPixelAlpha(image,n)
-GetPixelAlpha(image,pixels))+m)
image->page.x=0;
image->page.y=0;
image->background_color=mng_background_color;
- image->matte=MagickFalse;
+ image->alpha_trait=UndefinedPixelTrait;
if (image_info->ping == MagickFalse)
(void) SetImageBackgroundColor(image,exception);
entry->magick=(IsImageFormatHandler *) IsPNG;
entry->adjoin=MagickFalse;
- entry->description=ConstantString("opaque 24-bit RGB");
+ entry->description=ConstantString("opaque or binary transparent 24-bit RGB");
entry->module=ConstantString("PNG");
(void) RegisterMagickInfo(entry);
entry->module=ConstantString("PNG");
(void) RegisterMagickInfo(entry);
+ entry=SetMagickInfo("PNG48");
+
+#if defined(MAGICKCORE_PNG_DELEGATE)
+ entry->decoder=(DecodeImageHandler *) ReadPNGImage;
+ entry->encoder=(EncodeImageHandler *) WritePNGImage;
+#endif
+
+ entry->magick=(IsImageFormatHandler *) IsPNG;
+ entry->adjoin=MagickFalse;
+ entry->description=ConstantString("opaque or binary transparent 48-bit RGB");
+ entry->module=ConstantString("PNG");
+ (void) RegisterMagickInfo(entry);
+
+ entry=SetMagickInfo("PNG64");
+
+#if defined(MAGICKCORE_PNG_DELEGATE)
+ entry->decoder=(DecodeImageHandler *) ReadPNGImage;
+ entry->encoder=(EncodeImageHandler *) WritePNGImage;
+#endif
+
+ entry->magick=(IsImageFormatHandler *) IsPNG;
+ entry->adjoin=MagickFalse;
+ entry->description=ConstantString("opaque or transparent 64-bit RGBA");
+ entry->module=ConstantString("PNG");
+ (void) RegisterMagickInfo(entry);
+
+ entry=SetMagickInfo("PNG00");
+
+#if defined(MAGICKCORE_PNG_DELEGATE)
+ entry->decoder=(DecodeImageHandler *) ReadPNGImage;
+ entry->encoder=(EncodeImageHandler *) WritePNGImage;
+#endif
+
+ entry->magick=(IsImageFormatHandler *) IsPNG;
+ entry->adjoin=MagickFalse;
+ entry->description=ConstantString("PNG inheriting subformat from original");
+ entry->module=ConstantString("PNG");
+ (void) RegisterMagickInfo(entry);
+
entry=SetMagickInfo("JNG");
#if defined(JNG_SUPPORTED)
(void) UnregisterMagickInfo("PNG8");
(void) UnregisterMagickInfo("PNG24");
(void) UnregisterMagickInfo("PNG32");
+ (void) UnregisterMagickInfo("PNG48");
+ (void) UnregisterMagickInfo("PNG64");
+ (void) UnregisterMagickInfo("PNG00");
(void) UnregisterMagickInfo("JNG");
#ifdef PNG_SETJMP_NOT_THREAD_SAFE
(char *) profile_type, (double) length);
}
- text=(png_textp) png_malloc(ping,(png_uint_32) sizeof(png_text));
+#if PNG_LIBPNG_VER >= 14000
+ text=(png_textp) png_malloc(ping,(png_alloc_size_t) sizeof(png_text));
+#else
+ text=(png_textp) png_malloc(ping,(png_size_t) sizeof(png_text));
+#endif
description_length=(png_uint_32) strlen((const char *) profile_description);
allocated_length=(png_uint_32) (length*2 + (length >> 5) + 20
+ description_length);
- text[0].text=(png_charp) png_malloc(ping,allocated_length);
- text[0].key=(png_charp) png_malloc(ping, (png_uint_32) 80);
+#if PNG_LIBPNG_VER >= 14000
+ text[0].text=(png_charp) png_malloc(ping,
+ (png_alloc_size_t) allocated_length);
+ text[0].key=(png_charp) png_malloc(ping, (png_alloc_size_t) 80);
+#else
+ text[0].text=(png_charp) png_malloc(ping, (png_size_t) allocated_length);
+ text[0].key=(png_charp) png_malloc(ping, (png_size_t) 80);
+#endif
text[0].key[0]='\0';
(void) ConcatenateMagickString(text[0].key,
"Raw profile type ",MaxTextExtent);
x;
unsigned char
- *ping_pixels;
+ *volatile ping_pixels;
volatile int
image_colors,
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)))
+ mng_info->write_png48 || mng_info->write_png64 ||
+ (mng_info->write_png_colortype != 1 &&
+ mng_info->write_png_colortype != 5)))
{
(void) SyncImage(image,exception);
image->storage_class = DirectClass;
}
}
- if (IssRGBColorspace(image->colorspace) == MagickFalse)
+ if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
(void) TransformImageColorspace(image,sRGBColorspace,exception);
/*
image->depth = 8;
#endif
- /* Normally we run this just once, but in the case of writing PNG8
+ if (image->storage_class != PseudoClass && mng_info->write_png_colortype &&
+ (mng_info->write_png_colortype > 4 || (mng_info->write_png_depth >= 8 &&
+ mng_info->write_png_colortype < 4 &&
+ image->alpha_trait != BlendPixelTrait)))
+ {
+ /* Avoid the expensive BUILD_PALETTE operation if we're sure that we
+ * are not going to need the result.
+ */
+ image_colors = (int) image->colors;
+ number_opaque = (int) image->colors;
+ if (mng_info->write_png_colortype == 1 ||
+ mng_info->write_png_colortype == 5)
+ ping_have_color=MagickFalse;
+ else
+ ping_have_color=MagickTrue;
+ ping_have_non_bw=MagickFalse;
+
+ if (image->alpha_trait == BlendPixelTrait)
+ {
+ number_transparent = 2;
+ number_semitransparent = 1;
+ }
+
+ else
+ {
+ number_transparent = 0;
+ number_semitransparent = 0;
+ }
+ }
+
+ else
+ {
+ /* BUILD_PALETTE
+ *
+ * Normally we run this just once, but in the case of writing PNG8
* we reduce the transparency to binary and run again, then if there
* are still too many colors we reduce to a simple 4-4-4-1, then 3-3-3-1
* RGBA palette and run again, and then to a simple 3-3-2-1 RGBA
for (j=0; j<6; j++)
{
- /* BUILD_PALETTE
- *
+ /*
* Sometimes we get DirectClass images that have 256 colors or fewer.
* This code will build a colormap.
*
* This code will delete the colormap and change the image to
* DirectClass.
*
- * If image->matte is MagickFalse, we ignore the alpha channel
+ * If image->alpha_trait is MagickFalse, we ignore the alpha channel
* even though it sometimes contains left-over non-opaque values.
*
* Also we gather some information (number of opaque, transparent,
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" image->rows=%.20g",(double) image->rows);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " image->matte=%.20g",(double) image->matte);
+ " image->alpha_trait=%.20g",(double) image->alpha_trait);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" image->depth=%.20g",(double) image->depth);
for (x=0; x < (ssize_t) image->columns; x++)
{
- if (image->matte == MagickFalse ||
+ if (image->alpha_trait != BlendPixelTrait ||
GetPixelAlpha(image,q) == OpaqueAlpha)
{
if (number_opaque < 259)
ping_trans_color.blue=(unsigned short)
GetPixelBlue(image,q);
ping_trans_color.gray=(unsigned short)
- GetPixelRed(image,q);
+ GetPixelGray(image,q);
number_transparent = 1;
}
{
opaque[i] = image->background_color;
ping_background.index = i;
+ number_opaque++;
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
ping_have_color=MagickFalse;
ping_have_non_bw=MagickFalse;
+ if ((IssRGBCompatibleColorspace(image->colorspace) == MagickFalse) ||
+ (IssRGBColorspace(image->colorspace) != MagickFalse))
+ {
+ ping_have_color=MagickTrue;
+ ping_have_non_bw=MagickTrue;
+ }
+
if(image_colors > 256)
{
for (y=0; y < (ssize_t) image->rows; y++)
{
for (i=0; i< (ssize_t) image_colors; i++)
{
- if ((image->matte == MagickFalse ||
+ if ((image->alpha_trait != BlendPixelTrait ||
image->colormap[i].alpha == GetPixelAlpha(image,q)) &&
image->colormap[i].red == GetPixelRed(image,q) &&
image->colormap[i].green == GetPixelGreen(image,q) &&
}
}
}
+ }
/* END OF BUILD_PALETTE */
/* If we are excluding the tRNS chunk and there is transparency,
quantum_info = (QuantumInfo *) NULL;
number_colors=0;
image_colors=(int) image->colors;
- image_matte=image->matte;
+ image_matte=image->alpha_trait == BlendPixelTrait ? MagickTrue : MagickFalse;
mng_info->IsPalette=image->storage_class == PseudoClass &&
image_colors <= 256 && image->colormap != NULL;
/*
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 (mng_info->write_png8 || mng_info->write_png24 || mng_info->write_png32)
image_depth=8;
+ if (mng_info->write_png48 || mng_info->write_png64)
+ image_depth=16;
+
if (mng_info->write_png_depth != 0)
image_depth=mng_info->write_png_depth;
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" height=%.20g",(double) ping_height);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " image_matte=%.20g",(double) image->matte);
+ " image_matte=%.20g",(double) image->alpha_trait);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" image->depth=%.20g",(double) image->depth);
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
}
} /* end of write_png8 */
- else if (mng_info->write_png24 || mng_info->write_png_colortype == 3)
+ else if (mng_info->write_png_colortype == 1)
+ {
+ image_matte=MagickFalse;
+ ping_color_type=(png_byte) PNG_COLOR_TYPE_GRAY;
+ }
+
+ else if (mng_info->write_png24 || mng_info->write_png48 ||
+ mng_info->write_png_colortype == 3)
{
image_matte=MagickFalse;
ping_color_type=(png_byte) PNG_COLOR_TYPE_RGB;
}
- else if (mng_info->write_png32 || mng_info->write_png_colortype == 7)
+ else if (mng_info->write_png32 || mng_info->write_png64 ||
+ mng_info->write_png_colortype == 7)
{
image_matte=MagickTrue;
ping_color_type=(png_byte) PNG_COLOR_TYPE_RGB_ALPHA;
if (ping_color_type == PNG_COLOR_TYPE_GRAY)
{
- if (image->matte == MagickFalse && ping_have_non_bw == MagickFalse)
+ if (image->alpha_trait != BlendPixelTrait && ping_have_non_bw == MagickFalse)
ping_bit_depth=1;
}
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)
"Cannot write image with defined png:bit-depth or png:color-type.");
}
- if (image_matte != MagickFalse && image->matte == MagickFalse)
+ if (image_matte != MagickFalse && image->alpha_trait != BlendPixelTrait)
{
/* Add an opaque matte channel */
- image->matte = MagickTrue;
+ image->alpha_trait = BlendPixelTrait;
(void) SetImageAlpha(image,OpaqueAlpha,exception);
if (logging != MagickFalse)
png_error(ping,"Memory allocation for quantum_info failed");
quantum_info->format=UndefinedQuantumFormat;
quantum_info->depth=image_depth;
+ (void) SetQuantumEndian(image,quantum_info,MSBEndian);
num_passes=png_set_interlace_handling(ping);
if ((!mng_info->write_png8 && !mng_info->write_png24 &&
+ !mng_info->write_png48 && !mng_info->write_png64 &&
!mng_info->write_png32) &&
(mng_info->IsPalette ||
(image_info->type == BilevelType)) &&
else /* Not Palette, Bilevel, or Opaque Monochrome */
{
if ((!mng_info->write_png8 && !mng_info->write_png24 &&
- !mng_info->write_png32) &&
- (image_matte != MagickFalse ||
- (ping_bit_depth >= MAGICKCORE_QUANTUM_DEPTH)) &&
- (mng_info->IsPalette) && ping_have_color == MagickFalse)
+ !mng_info->write_png48 && !mng_info->write_png64 &&
+ !mng_info->write_png32) && (image_matte != MagickFalse ||
+ (ping_bit_depth >= MAGICKCORE_QUANTUM_DEPTH)) &&
+ (mng_info->IsPalette) && ping_have_color == MagickFalse)
{
register const Quantum
*p;
for (pass=0; pass < num_passes; pass++)
{
- if ((image_depth > 8) || (mng_info->write_png24 ||
+ if ((image_depth > 8) ||
+ mng_info->write_png24 ||
mng_info->write_png32 ||
- (!mng_info->write_png8 && !mng_info->IsPalette)))
+ mng_info->write_png48 ||
+ mng_info->write_png64 ||
+ (!mng_info->write_png8 && !mng_info->IsPalette))
{
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;
}
else
- /* not ((image_depth > 8) || (mng_info->write_png24 ||
- mng_info->write_png32 ||
- (!mng_info->write_png8 && !mng_info->IsPalette))) */
+ /* not ((image_depth > 8) ||
+ mng_info->write_png24 || mng_info->write_png32 ||
+ mng_info->write_png48 || mng_info->write_png64 ||
+ (!mng_info->write_png8 && !mng_info->IsPalette))
+ */
{
if ((ping_color_type != PNG_COLOR_TYPE_GRAY) &&
(ping_color_type != PNG_COLOR_TYPE_GRAY_ALPHA))
{
if (value != (const char *) NULL)
{
- text=(png_textp) png_malloc(ping,(png_uint_32) sizeof(png_text));
+
+#if PNG_LIBPNG_VER >= 14000
+ text=(png_textp) png_malloc(ping,
+ (png_alloc_size_t) sizeof(png_text));
+#else
+ text=(png_textp) png_malloc(ping,(png_size_t) sizeof(png_text));
+#endif
text[0].key=(char *) property;
text[0].text=(char *) value;
text[0].text_length=strlen(value);
" Setting up text chunk");
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " keyword: %s",text[0].key);
+ " keyword: '%s'",text[0].key);
}
png_set_text(ping,ping_info,text,1);
% The only loss in data is the reduction of the sample depth
% to 8.
%
+% o PNG48: A 16-bit per sample RGB PNG datastream is written. The tRNS
+% chunk can be present to convey binary transparency by naming
+% one of the colors as transparent. If the image has more
+% than one transparent color, has semitransparent pixels, or
+% has an opaque pixel with the same RGB components as the
+% transparent color, an image is not written.
+%
+% o PNG64: A 16-bit per sample RGBA PNG is written. Partial
+% transparency is permitted, i.e., the alpha sample for
+% each pixel can have any value from 0 to 65535. The alpha
+% channel is present even if the image is fully opaque.
+%
+% o PNG00: A PNG that inherits its colortype and bit-depth from the input
+% image, if the input was a PNG, is written. If these values
+% cannot be found, then "PNG00" falls back to the regular "PNG"
+% format.
+%
% o -define: For more precise control of the PNG output, you can use the
% Image options "png:bit-depth" and "png:color-type". These
% can be set from the commandline with "-define" and also
% When png:color-type is 4 (Gray-Matte) or 6 (RGB-Matte),
% png:bit-depth can be 8 or 16.
%
-% If the image cannot be written without loss with the requested bit-depth
-% and color-type, a PNG file will not be written, and the encoder will
-% return MagickFalse.
+% If the image cannot be written without loss with the
+% requested bit-depth and color-type, a PNG file will not
+% be written, a warning will be issued, and the encoder will
+% return MagickFalse.
%
% Since image encoders should not be responsible for the "heavy lifting",
% the user should make sure that ImageMagick has already reduced the
mng_info->write_png8=LocaleCompare(image_info->magick,"PNG8") == 0;
mng_info->write_png24=LocaleCompare(image_info->magick,"PNG24") == 0;
mng_info->write_png32=LocaleCompare(image_info->magick,"PNG32") == 0;
+ mng_info->write_png48=LocaleCompare(image_info->magick,"PNG48") == 0;
+ mng_info->write_png64=LocaleCompare(image_info->magick,"PNG64") == 0;
value=GetImageOption(image_info,"png:format");
if (value != (char *) NULL)
{
+ mng_info->write_png8 = MagickFalse;
+ mng_info->write_png24 = MagickFalse;
+ mng_info->write_png32 = MagickFalse;
+ mng_info->write_png48 = MagickFalse;
+ mng_info->write_png64 = MagickFalse;
+
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;
+
+ else if (LocaleCompare(value,"png48") == 0)
+ mng_info->write_png48 = MagickTrue;
+
+ else if (LocaleCompare(value,"png64") == 0)
+ mng_info->write_png64 = MagickTrue;
+ }
+
+ if (LocaleCompare(value,"png00") == 0)
+ {
+ /* Retrieve png:IHDR.bit-depth-orig and png:IHDR.color-type-orig
+ Note that whitespace at the end of the property names must match
+ that in the corresponding SetImageProperty() calls.
+ */
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Format=%s",value);
+
+ value=GetImageProperty(image,"png:IHDR.bit-depth-orig ",exception);
+
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " png00 inherited bit depth=%s",value);
+
+ if (value != (char *) NULL)
+ {
+ if (LocaleCompare(value,"1") == 0)
+ mng_info->write_png_depth = 1;
+
+ else if (LocaleCompare(value,"1") == 0)
+ mng_info->write_png_depth = 2;
+
+ else if (LocaleCompare(value,"2") == 0)
+ mng_info->write_png_depth = 4;
+
+ else if (LocaleCompare(value,"8") == 0)
+ mng_info->write_png_depth = 8;
+
+ else if (LocaleCompare(value,"16") == 0)
+ mng_info->write_png_depth = 16;
+ }
+
+ value=GetImageProperty(image,"png:IHDR.color-type-orig ",exception);
+
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " png00 inherited color type=%s",value);
+
+ if (value != (char *) NULL)
+ {
+ if (LocaleCompare(value,"0") == 0)
+ mng_info->write_png_colortype = 1;
+
+ else if (LocaleCompare(value,"2") == 0)
+ mng_info->write_png_colortype = 3;
+
+ else if (LocaleCompare(value,"3") == 0)
+ mng_info->write_png_colortype = 4;
+
+ else if (LocaleCompare(value,"4") == 0)
+ mng_info->write_png_colortype = 5;
+
+ else if (LocaleCompare(value,"6") == 0)
+ mng_info->write_png_colortype = 7;
}
}
+
if (mng_info->write_png8)
{
mng_info->write_png_colortype = /* 3 */ 4;
mng_info->write_png_depth = 8;
image->depth = 8;
- if (image->matte == MagickTrue)
+ if (image->alpha_trait == BlendPixelTrait)
(void) SetImageType(image,TrueColorMatteType,exception);
else
mng_info->write_png_depth = 8;
image->depth = 8;
- if (image->matte == MagickTrue)
+ if (image->alpha_trait == BlendPixelTrait)
+ (void) SetImageType(image,TrueColorMatteType,exception);
+
+ else
+ (void) SetImageType(image,TrueColorType,exception);
+
+ (void) SyncImage(image,exception);
+ }
+
+ if (mng_info->write_png48)
+ {
+ mng_info->write_png_colortype = /* 2 */ 3;
+ mng_info->write_png_depth = 16;
+ image->depth = 16;
+
+ if (image->alpha_trait == BlendPixelTrait)
+ (void) SetImageType(image,TrueColorMatteType,exception);
+
+ else
+ (void) SetImageType(image,TrueColorType,exception);
+
+ (void) SyncImage(image,exception);
+ }
+
+ if (mng_info->write_png64)
+ {
+ mng_info->write_png_colortype = /* 6 */ 7;
+ mng_info->write_png_depth = 16;
+ image->depth = 16;
+
+ if (image->alpha_trait == BlendPixelTrait)
(void) SetImageType(image,TrueColorMatteType,exception);
else
if (LocaleCompare(value,"0") == 0)
mng_info->write_png_compression_filter = 1;
- if (LocaleCompare(value,"1") == 0)
+ else if (LocaleCompare(value,"1") == 0)
mng_info->write_png_compression_filter = 2;
else if (LocaleCompare(value,"2") == 0)
status=MagickTrue;
transparent=image_info->type==GrayscaleMatteType ||
- image_info->type==TrueColorMatteType || image->matte != MagickFalse;
+ image_info->type==TrueColorMatteType || image->alpha_trait == BlendPixelTrait;
jng_quality=image_info->quality == 0UL ? 75UL : image_info->quality%1000;
if (jpeg_image == (Image *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
(void) CopyMagickString(jpeg_image->magick,"JPEG",MaxTextExtent);
- jpeg_image->matte=MagickFalse;
+ jpeg_image->alpha_trait=UndefinedPixelTrait;
jpeg_image->quality=jng_alpha_quality;
jpeg_image_info->type=GrayscaleType;
(void) SetImageType(jpeg_image,GrayscaleType,exception);
/* 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)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Image depth: %.20g",(double) p->depth);
- if (p->matte)
+ if (p->alpha_trait == BlendPixelTrait)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Matte: True");
if (next_image->page.x || next_image->page.y)
need_defi=MagickTrue;
- if (next_image->matte)
+ if (next_image->alpha_trait == BlendPixelTrait)
need_matte=MagickTrue;
if ((int) next_image->dispose >= BackgroundDispose)
- if (next_image->matte || next_image->page.x || next_image->page.y ||
+ if ((next_image->alpha_trait == BlendPixelTrait) ||
+ next_image->page.x || next_image->page.y ||
((next_image->columns < mng_info->page.width) &&
(next_image->rows < mng_info->page.height)))
mng_info->need_fram=MagickTrue;
/*
check for global palette possibility.
*/
- if (image->matte != MagickFalse)
+ if (image->alpha_trait == BlendPixelTrait)
need_local_plte=MagickTrue;
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)
Write MNG BACK chunk and global bKGD chunk, if the image is transparent
or does not cover the entire frame.
*/
- if (write_mng && (image->matte || image->page.x > 0 ||
- image->page.y > 0 || (image->page.width &&
+ if (write_mng && ((image->alpha_trait == BlendPixelTrait) ||
+ image->page.x > 0 || image->page.y > 0 || (image->page.width &&
(image->page.width+image->page.x < mng_info->page.width))
|| (image->page.height && (image->page.height+image->page.y
< mng_info->page.height))))