Fixed some indentation in coders/png.c and added some whitespace.
diff --git a/coders/png.c b/coders/png.c
index 62e0095..6cb0334 100644
--- a/coders/png.c
+++ b/coders/png.c
@@ -478,17 +478,21 @@
static int
PNG_RenderingIntent_from_Magick_RenderingIntent(const RenderingIntent intent)
-{
+{
switch (intent)
{
case PerceptualIntent:
return 0;
+
case RelativeIntent:
return 1;
+
case SaturationIntent:
return 2;
+
case AbsoluteIntent:
return 3;
+
default:
return -1;
}
@@ -496,17 +500,21 @@
static RenderingIntent
PNG_RenderingIntent_to_Magick_RenderingIntent(const int png_intent)
-{
+{
switch (png_intent)
{
case 0:
return PerceptualIntent;
+
case 1:
return RelativeIntent;
+
case 2:
return SaturationIntent;
+
case 3:
return AbsoluteIntent;
+
default:
return UndefinedIntent;
}
@@ -516,12 +524,14 @@
{
if (x > y)
return(x);
+
return(y);
}
static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
{
if (x < y)
return(x);
+
return(y);
}
@@ -629,11 +639,14 @@
{
if ((p->red != 0) && (p->red != (Quantum) QuantumRange))
return(MagickFalse);
+
if (IsGray(p) == MagickFalse)
return(MagickFalse);
+
if ((p->opacity != OpaqueOpacity) &&
(p->opacity != (Quantum) TransparentOpacity))
return(MagickFalse);
+
p++;
}
}
@@ -672,8 +685,10 @@
{
if (length < 8)
return(MagickFalse);
+
if (memcmp(magick,"\212MNG\r\n\032\n",8) == 0)
return(MagickTrue);
+
return(MagickFalse);
}
@@ -707,8 +722,10 @@
{
if (length < 8)
return(MagickFalse);
+
if (memcmp(magick,"\213JNG\r\n\032\n",8) == 0)
return(MagickTrue);
+
return(MagickFalse);
}
@@ -741,8 +758,10 @@
{
if (length < 8)
return(MagickFalse);
+
if (memcmp(magick,"\211PNG\r\n\032\n",8) == 0)
return(MagickTrue);
+
return(MagickFalse);
}
@@ -967,8 +986,10 @@
if (length)
{
check=(png_size_t) ReadBlob(image,(size_t) length,(char *) data);
+
if (check != length)
png_error(png_ptr,"Read Exception");
+
if (length == 4)
{
if ((data[0] == 0) && (data[1] == 0) && (data[2] == 0) &&
@@ -986,6 +1007,7 @@
mng_info->have_saved_bkgd_index=MagickFalse;
}
}
+
if ((data[0] == 0) && (data[1] == 0) && (data[2] == 0) &&
(data[3] == 1))
{
@@ -1025,6 +1047,7 @@
check;
check=(png_size_t) WriteBlob(image,(size_t) length,data);
+
if (check != length)
png_error(png_ptr,"WriteBlob Failed");
}
@@ -1043,10 +1066,13 @@
if ((a == (Image *) NULL) || (b == (Image *) NULL))
return((int) MagickFalse);
+
if (a->storage_class != PseudoClass || b->storage_class != PseudoClass)
return((int) MagickFalse);
+
if (a->colors != b->colors)
return((int) MagickFalse);
+
for (i=0; i < (ssize_t) a->colors; i++)
{
if ((a->colormap[i].red != b->colormap[i].red) ||
@@ -1054,6 +1080,7 @@
(a->colormap[i].blue != b->colormap[i].blue))
return((int) MagickFalse);
}
+
return((int) MagickTrue);
}
#endif
@@ -1068,10 +1095,12 @@
{
if (mng_info->ob[i]->reference_count > 0)
mng_info->ob[i]->reference_count--;
+
if (mng_info->ob[i]->reference_count == 0)
{
if (mng_info->ob[i]->image != (Image *) NULL)
mng_info->ob[i]->image=DestroyImage(mng_info->ob[i]->image);
+
mng_info->ob[i]=DestroyString(mng_info->ob[i]);
}
}
@@ -1099,9 +1128,11 @@
for (i=1; i < MNG_MAX_OBJECTS; i++)
MngInfoDiscardObject(mng_info,i);
+
if (mng_info->global_plte != (png_colorp) NULL)
mng_info->global_plte=(png_colorp)
RelinquishMagickMemory(mng_info->global_plte);
+
mng_info=(MngInfo *) RelinquishMagickMemory(mng_info);
*have_mng_structure=MagickFalse;
}
@@ -1115,12 +1146,16 @@
box=box1;
if (box.left < box2.left)
box.left=box2.left;
+
if (box.top < box2.top)
box.top=box2.top;
+
if (box.right > box2.right)
box.right=box2.right;
+
if (box.bottom > box2.bottom)
box.bottom=box2.bottom;
+
return box;
}
@@ -1143,6 +1178,7 @@
box.top+=previous_box.top;
box.bottom+=previous_box.bottom;
}
+
return(box);
}
@@ -1156,11 +1192,13 @@
*/
pair.a=(long) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
pair.b=(long) ((p[4] << 24) | (p[5] << 16) | (p[6] << 8) | p[7]);
+
if (delta_type != 0)
{
pair.a+=previous_pair.a;
pair.b+=previous_pair.b;
}
+
return(pair);
}
@@ -1175,11 +1213,14 @@
*image;
image=(Image *) png_get_error_ptr(ping);
+
if (image->debug != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" libpng-%s error: %s", PNG_LIBPNG_VER_STRING,message);
+
(void) ThrowMagickException(&image->exception,GetMagickModule(),CoderError,
message,"`%s'",image->filename);
+
#if PNG_LIBPNG_VER < 10500
longjmp(ping->jmpbuf,1);
#else
@@ -1194,10 +1235,12 @@
if (LocaleCompare(message, "Missing PLTE before tRNS") == 0)
png_error(ping, message);
+
image=(Image *) png_get_error_ptr(ping);
if (image->debug != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" libpng-%s warning: %s", PNG_LIBPNG_VER_STRING,message);
+
(void) ThrowMagickException(&image->exception,GetMagickModule(),CoderWarning,
message,"`%s'",image->filename);
}
@@ -1211,8 +1254,10 @@
png_ptr=png_ptr;
ret=((png_voidp) AcquireMagickMemory((size_t) size));
+
if (ret == NULL)
png_error("Insufficient memory.");
+
return(ret);
#else
png_ptr=png_ptr;
@@ -1267,12 +1312,16 @@
/* look for newline */
while (*sp != '\n')
sp++;
+
/* look for length */
while (*sp == '\0' || *sp == ' ' || *sp == '\n')
sp++;
+
length=(png_uint_32) StringToLong(sp);
+
while (*sp != ' ' && *sp != '\n')
sp++;
+
/* allocate space */
if (length == 0)
{
@@ -1280,7 +1329,9 @@
CoderWarning,"UnableToCopyProfile","`%s'","invalid profile length");
return(MagickFalse);
}
+
profile=AcquireStringInfo(length);
+
if (profile == (StringInfo *) NULL)
{
(void) ThrowMagickException(&image->exception,GetMagickModule(),
@@ -1288,9 +1339,11 @@
"unable to copy profile");
return(MagickFalse);
}
+
/* copy profile, skipping white space and column 1 "=" signs */
dp=GetStringInfoDatum(profile);
nibbles=length*2;
+
for (i=0; i < (ssize_t) nibbles; i++)
{
while (*sp < '0' || (*sp > '9' && *sp < 'a') || *sp > 'f')
@@ -1304,8 +1357,10 @@
}
sp++;
}
+
if (i%2 == 0)
*dp=(unsigned char) (16*unhex[(int) *sp++]);
+
else
(*dp++)+=unhex[(int) *sp++];
}
@@ -1314,8 +1369,10 @@
*/
(void) SetImageProfile(image,&text[ii].key[17],profile);
profile=DestroyStringInfo(profile);
+
if (image_info->verbose)
(void) printf(" Found a generic profile, type %s\n",&text[ii].key[17]);
+
return MagickTrue;
}
@@ -1351,6 +1408,7 @@
image->page.width=(size_t) ((chunk->data[0] << 24) |
(chunk->data[1] << 16) | (chunk->data[2] << 8) | chunk->data[3]);
+
image->page.height=(size_t) ((chunk->data[4] << 24) |
(chunk->data[5] << 16) | (chunk->data[6] << 8) | chunk->data[7]);
@@ -1521,19 +1579,25 @@
#endif
if (ping == (png_struct *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+
ping_info=png_create_info_struct(ping);
+
if (ping_info == (png_info *) NULL)
{
png_destroy_read_struct(&ping,(png_info **) NULL,(png_info **) NULL);
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
}
+
end_info=png_create_info_struct(ping);
+
if (end_info == (png_info *) NULL)
{
png_destroy_read_struct(&ping,&ping_info,(png_info **) NULL);
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
}
+
png_pixels=(unsigned char *) NULL;
+
if (setjmp(png_jmpbuf(ping)))
{
/*
@@ -1546,11 +1610,13 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit ReadOnePNGImage() with error.");
+
if (image != (Image *) NULL)
{
InheritException(exception,&image->exception);
image->columns=0;
}
+
return(GetFirstImageInList(image));
}
/*
@@ -1559,6 +1625,7 @@
mng_info->image_found++;
png_set_sig_bytes(ping,8);
+
if (LocaleCompare(image_info->magick,"MNG") == 0)
{
#if defined(PNG_MNG_FEATURES_SUPPORTED)
@@ -1577,6 +1644,7 @@
#endif
#endif
}
+
else
png_set_read_fn(ping,image,png_get_data);
@@ -1638,12 +1706,15 @@
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" PNG width: %.20g, height: %.20g",
(double) ping_width, (double) ping_height);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" PNG color_type: %d, bit_depth: %d",
ping_color_type, ping_bit_depth);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" PNG compression_method: %d",
ping_compression_method);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" PNG interlace_method: %d, filter_method: %d",
ping_interlace_method,ping_filter_method);
@@ -1664,6 +1735,7 @@
(void) png_get_iCCP(ping,ping_info,&name,(int *) &compression,&info,
&profile_length);
+
if (profile_length != 0)
{
StringInfo
@@ -1687,10 +1759,12 @@
if (mng_info->have_global_srgb)
image->rendering_intent=PNG_RenderingIntent_to_Magick_RenderingIntent(
mng_info->global_srgb_intent);
+
if (png_get_sRGB(ping,ping_info,&intent))
{
image->rendering_intent=PNG_RenderingIntent_to_Magick_RenderingIntent(
intent);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG sRGB chunk: rendering_intent: %d",intent);
@@ -1704,6 +1778,7 @@
if (!png_get_gAMA(ping,ping_info,&file_gamma))
if (mng_info->have_global_gama)
png_set_gAMA(ping,ping_info,mng_info->global_gamma);
+
if (png_get_gAMA(ping,ping_info,&file_gamma))
{
image->gamma=(float) file_gamma;
@@ -1727,6 +1802,7 @@
mng_info->global_chrm.blue_primary.y);
}
}
+
if (png_get_valid(ping,ping_info,PNG_INFO_cHRM))
{
(void) png_get_cHRM(ping,ping_info,
@@ -1738,10 +1814,12 @@
&image->chromaticity.green_primary.y,
&image->chromaticity.blue_primary.x,
&image->chromaticity.blue_primary.y);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG cHRM chunk.");
}
+
if (image->rendering_intent != UndefinedIntent)
{
png_set_sRGB(ping,ping_info,
@@ -1757,6 +1835,7 @@
{
image->page.x=png_get_x_offset_pixels(ping, ping_info);
image->page.y=png_get_y_offset_pixels(ping, ping_info);
+
if (logging != MagickFalse)
if (image->page.x || image->page.y)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -1792,12 +1871,14 @@
&unit_type);
image->x_resolution=(double) x_resolution;
image->y_resolution=(double) y_resolution;
+
if (unit_type == PNG_RESOLUTION_METER)
{
image->units=PixelsPerCentimeterResolution;
image->x_resolution=(double) x_resolution/100.0;
image->y_resolution=(double) y_resolution/100.0;
}
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG pHYs chunk: xres: %.20g, yres: %.20g, units: %d.",
@@ -1813,6 +1894,7 @@
palette;
(void) png_get_PLTE(ping,ping_info,&palette,&number_colors);
+
if ((number_colors == 0) &&
((int) ping_color_type == PNG_COLOR_TYPE_PALETTE))
{
@@ -1820,6 +1902,7 @@
{
png_set_PLTE(ping,ping_info,mng_info->global_plte,
(int) mng_info->global_plte_length);
+
if (!png_get_valid(ping,ping_info,PNG_INFO_tRNS))
if (mng_info->global_trns_length)
{
@@ -1848,12 +1931,16 @@
#endif
if (png_get_valid(ping, ping_info, PNG_INFO_bKGD))
background.index=ping_background->index;
+
background.red=(png_uint_16)
mng_info->global_plte[background.index].red;
+
background.green=(png_uint_16)
mng_info->global_plte[background.index].green;
+
background.blue=(png_uint_16)
mng_info->global_plte[background.index].blue;
+
png_set_bKGD(ping,ping_info,&background);
}
#endif
@@ -1869,6 +1956,7 @@
if (mng_info->have_global_bkgd &&
(!png_get_valid(ping,ping_info,PNG_INFO_bKGD)))
image->background_color=mng_info->mng_global_bkgd;
+
if (png_get_valid(ping,ping_info,PNG_INFO_bKGD))
{
/*
@@ -1877,12 +1965,14 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG bKGD chunk.");
+
if (ping_bit_depth == MAGICKCORE_QUANTUM_DEPTH)
{
image->background_color.red=ping_background->red;
image->background_color.green=ping_background->green;
image->background_color.blue=ping_background->blue;
}
+
else /* Scale background components to 16-bit */
{
unsigned int
@@ -1894,12 +1984,16 @@
ping_background->green,ping_background->blue);
bkgd_scale = 1;
+
if (ping_bit_depth == 1)
bkgd_scale = 255;
+
else if (ping_bit_depth == 2)
bkgd_scale = 85;
+
else if (ping_bit_depth == 4)
bkgd_scale = 17;
+
if (ping_bit_depth <= 8)
bkgd_scale *= 257;
@@ -1911,6 +2005,7 @@
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" bkgd_scale=%d.",bkgd_scale);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" ping_background=(%d,%d,%d).",ping_background->red,
ping_background->green,ping_background->blue);
@@ -1918,10 +2013,13 @@
image->background_color.red=
ScaleShortToQuantum(ping_background->red);
+
image->background_color.green=
ScaleShortToQuantum(ping_background->green);
+
image->background_color.blue=
ScaleShortToQuantum(ping_background->blue);
+
image->background_color.opacity=OpaqueOpacity;
if (logging != MagickFalse)
@@ -1994,6 +2092,7 @@
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Raw tRNS graylevel is %d.",ping_trans_color->gray);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" scaled graylevel is %d.",transparent_color.opacity);
}
@@ -2030,10 +2129,12 @@
mng_info->frame=mng_info->image_box;
mng_info->clip=mng_info->image_box;
}
+
else
{
image->page.y=mng_info->y_off[mng_info->object_id];
}
+
image->compression=ZipCompression;
image->columns=ping_width;
image->rows=ping_height;
@@ -2064,6 +2165,7 @@
(void) png_get_PLTE(ping,ping_info,&palette,&number_colors);
image->colors=(size_t) number_colors;
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG PLTE chunk: number_colors: %d.",number_colors);
@@ -2077,6 +2179,7 @@
*/
if (AcquireImageColormap(image,image->colors) == MagickFalse)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+
if ((int) ping_color_type == PNG_COLOR_TYPE_PALETTE)
{
int
@@ -2086,6 +2189,7 @@
palette;
(void) png_get_PLTE(ping,ping_info,&palette,&number_colors);
+
for (i=0; i < (ssize_t) image->colors; i++)
{
image->colormap[i].red=ScaleCharToQuantum(palette[i].red);
@@ -2093,14 +2197,17 @@
image->colormap[i].blue=ScaleCharToQuantum(palette[i].blue);
}
}
+
else
{
size_t
scale;
scale=(QuantumRange/((1UL << ping_bit_depth)-1));
+
if (scale < 1)
scale=1;
+
for (i=0; i < (ssize_t) image->colors; i++)
{
image->colormap[i].red=(Quantum) (i*scale);
@@ -2114,6 +2221,7 @@
*/
if (image->delay != 0)
mng_info->scenes_found++;
+
if ((mng_info->mng_type == 0 && (image->ping != MagickFalse)) || (
(image_info->number_scenes != 0) && (mng_info->scenes_found > (ssize_t)
(image_info->first_scene+image_info->number_scenes))))
@@ -2129,19 +2237,25 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit ReadOnePNGImage().");
+
return(image);
}
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG IDAT chunk(s)");
+
if (num_passes > 1)
png_pixels=(unsigned char *) AcquireQuantumMemory(image->rows,
ping_rowbytes*sizeof(*png_pixels));
+
else
png_pixels=(unsigned char *) AcquireQuantumMemory(ping_rowbytes,
sizeof(*png_pixels));
+
if (png_pixels == (unsigned char *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Converting PNG pixels to pixel packets");
@@ -2159,21 +2273,28 @@
#endif
if (quantum_info != (QuantumInfo *) NULL)
quantum_info = DestroyQuantumInfo(quantum_info);
+
if (png_pixels != (unsigned char *) NULL)
png_pixels=(unsigned char *) RelinquishMagickMemory(png_pixels);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit ReadOnePNGImage() with error.");
+
if (image != (Image *) NULL)
{
InheritException(exception,&image->exception);
image->columns=0;
}
+
return(GetFirstImageInList(image));
}
+
quantum_info=AcquireQuantumInfo(image_info,image);
+
if (quantum_info == (QuantumInfo *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+
if (image->storage_class == DirectClass)
for (pass=0; pass < num_passes; pass++)
{
@@ -2195,10 +2316,13 @@
{
if (num_passes > 1)
row_offset=ping_rowbytes*y;
+
else
row_offset=0;
+
png_read_row(ping,png_pixels+row_offset,NULL);
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
+
if (q == (PixelPacket *) NULL)
break;
#if (0 && (MAGICKCORE_QUANTUM_DEPTH == 8) && !defined(MAGICKCORE_HDRI_SUPPORT))
@@ -2259,12 +2383,14 @@
*r++=OpaqueOpacity;
}
}
+
else if (ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
for (x=(ssize_t) (4*image->columns); x != 0; x--)
{
*r++=*p++;
p++;
}
+
else if (ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
for (x=(ssize_t) (2*image->columns); x != 0; x--)
{
@@ -2275,6 +2401,7 @@
if (depth == 8 && ping_color_type == PNG_COLOR_TYPE_GRAY)
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
GrayQuantum,png_pixels+row_offset);
+
if (ping_color_type == PNG_COLOR_TYPE_GRAY ||
ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
@@ -2282,9 +2409,11 @@
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
GrayAlphaQuantum,png_pixels+row_offset);
}
+
else if (depth == 8 && ping_color_type == PNG_COLOR_TYPE_RGB)
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
RGBQuantum,png_pixels+row_offset);
+
else if (ping_color_type == PNG_COLOR_TYPE_RGB ||
ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
@@ -2292,22 +2421,28 @@
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
RGBAQuantum,png_pixels+row_offset);
}
+
else if (ping_color_type == PNG_COLOR_TYPE_PALETTE)
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
IndexQuantum,png_pixels+row_offset);
#else /* (MAGICKCORE_QUANTUM_DEPTH != 8) */
+
if ((int) ping_color_type == PNG_COLOR_TYPE_GRAY)
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
GrayQuantum,png_pixels+row_offset,exception);
+
else if ((int) ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
GrayAlphaQuantum,png_pixels+row_offset,exception);
+
else if ((int) ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
RGBAQuantum,png_pixels+row_offset,exception);
+
else if ((int) ping_color_type == PNG_COLOR_TYPE_PALETTE)
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
IndexQuantum,png_pixels+row_offset,exception);
+
else
(void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
RGBQuantum,png_pixels+row_offset,exception);
@@ -2316,12 +2451,14 @@
{
status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
image->rows);
+
if (status == MagickFalse)
break;
}
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
}
+
if ((image->previous == (Image *) NULL) && (num_passes != 1))
{
status=SetImageProgress(image,LoadImageTag,pass,num_passes);
@@ -2329,6 +2466,7 @@
break;
}
}
+
else /* image->storage_class != DirectClass */
for (pass=0; pass < num_passes; pass++)
{
@@ -2343,10 +2481,13 @@
*/
image->matte=ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ?
MagickTrue : MagickFalse;
+
quantum_scanline=(Quantum *) AcquireQuantumMemory(image->columns,
(image->matte ? 2 : 1)*sizeof(*quantum_scanline));
+
if (quantum_scanline == (Quantum *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+
for (y=0; y < (ssize_t) image->rows; y++)
{
if (num_passes > 1)
@@ -2355,8 +2496,10 @@
row_offset=0;
png_read_row(ping,png_pixels+row_offset,NULL);
q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
+
if (q == (PixelPacket *) NULL)
break;
+
indexes=GetAuthenticIndexQueue(image);
p=png_pixels+row_offset;
r=quantum_scanline;
@@ -2373,11 +2516,13 @@
*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:
@@ -2389,11 +2534,13 @@
*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:
@@ -2403,8 +2550,10 @@
*r++=(*p >> 4) & 0x0f;
*r++=(*p++) & 0x0f;
}
+
if ((image->columns % 2) != 0)
*r++=(*p++ >> 4) & 0x0f;
+
break;
}
case 8:
@@ -2421,9 +2570,11 @@
q->opacity=ScaleCharToQuantum((unsigned char) (255-(*p++)));
q++;
}
+
else
for (x=(ssize_t) image->columns-1; x >= 0; x--)
*r++=*p++;
+
break;
}
case 16:
@@ -2436,8 +2587,10 @@
if (image->colors > 256)
*r=((*p++) << 8);
+
else
*r=0;
+
quantum=(*r);
quantum|=(*p++);
*r=(Quantum) quantum;
@@ -2456,12 +2609,15 @@
if (image->colors > 256)
*r=((*p++) << 8);
+
else
*r=0;
+
quantum=(*r);
quantum|=(*p++);
*r=quantum;
r++;
+
if (ping_color_type == 4)
{
q->opacity=(*p << 8) | *(p+1);
@@ -2491,10 +2647,13 @@
Transfer image scanline.
*/
r=quantum_scanline;
+
for (x=0; x < (ssize_t) image->columns; x++)
indexes[x]=(IndexPacket) (*r++);
+
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
+
if ((image->previous == (Image *) NULL) && (num_passes == 1))
{
status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
@@ -2513,6 +2672,7 @@
}
if (quantum_info != (QuantumInfo *) NULL)
quantum_info=DestroyQuantumInfo(quantum_info);
+
if (image->storage_class == PseudoClass)
{
MagickBooleanType
@@ -2554,64 +2714,69 @@
#if 1 /* balfour fix */
/* From imagemagick discourse server, 5 Feb 2010 */
- if (storage_class == PseudoClass)
- {
- if ((int) ping_color_type == PNG_COLOR_TYPE_PALETTE)
- {
- for (x=0; x < ping_num_trans; x++)
- {
- image->colormap[x].opacity =
- ScaleCharToQuantum((unsigned char)(255-ping_trans_alpha[x]));
- }
- }
- else if (ping_color_type == PNG_COLOR_TYPE_GRAY)
- {
- for (x=0; x < (int) image->colors; x++)
- {
- if (ScaleQuantumToShort(image->colormap[x].red) ==
- transparent_color.opacity)
+ if (storage_class == PseudoClass)
+ {
+ if ((int) ping_color_type == PNG_COLOR_TYPE_PALETTE)
{
- image->colormap[x].opacity = (Quantum) TransparentOpacity;
+ for (x=0; x < ping_num_trans; x++)
+ {
+ image->colormap[x].opacity =
+ ScaleCharToQuantum((unsigned char)(255-ping_trans_alpha[x]));
+ }
}
- }
- }
- (void) SyncImage(image);
- }
- else
- {
-
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- image->storage_class=storage_class;
- q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
- if (q == (PixelPacket *) NULL)
- break;
- indexes=GetAuthenticIndexQueue(image);
-
- for (x=(ssize_t) image->columns-1; x >= 0; x--)
+ else if (ping_color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ for (x=0; x < (int) image->colors; x++)
+ {
+ if (ScaleQuantumToShort(image->colormap[x].red) ==
+ transparent_color.opacity)
+ {
+ image->colormap[x].opacity = (Quantum) TransparentOpacity;
+ }
+ }
+ }
+ (void) SyncImage(image);
+ }
+ else
+ {
+ for (y=0; y < (ssize_t) image->rows; y++)
{
- if (ScaleQuantumToShort(q->red) == transparent_color.red &&
- ScaleQuantumToShort(q->green) == transparent_color.green &&
- ScaleQuantumToShort(q->blue) == transparent_color.blue)
- q->opacity=(Quantum) TransparentOpacity;
- else
- SetOpacityPixelComponent(q,OpaqueOpacity);
- q++;
+ image->storage_class=storage_class;
+ q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
+
+ if (q == (PixelPacket *) NULL)
+ break;
+
+ indexes=GetAuthenticIndexQueue(image);
+
+ for (x=(ssize_t) image->columns-1; x >= 0; x--)
+ {
+ if (ScaleQuantumToShort(q->red) == transparent_color.red &&
+ ScaleQuantumToShort(q->green) == transparent_color.green &&
+ ScaleQuantumToShort(q->blue) == transparent_color.blue)
+ q->opacity=(Quantum) TransparentOpacity;
+
+ else
+ SetOpacityPixelComponent(q,OpaqueOpacity);
+
+ q++;
+ }
+
+ if (SyncAuthenticPixels(image,exception) == MagickFalse)
+ break;
}
- if (SyncAuthenticPixels(image,exception) == MagickFalse)
- break;
- }
- }
+ }
#else /* not balfour */
-
for (y=0; y < (ssize_t) image->rows; y++)
{
image->storage_class=storage_class;
q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
+
if (q == (PixelPacket *) NULL)
break;
+
indexes=GetAuthenticIndexQueue(image);
if (storage_class == PseudoClass)
@@ -2623,11 +2788,14 @@
for (x=0; x < (ssize_t) image->columns; x++)
{
indexpacket=indexes[x];
+
if (indexpacket < ping_num_trans)
q->opacity=ScaleCharToQuantum((unsigned char)
(255-ping_trans_alpha[(ssize_t) indexpacket]));
+
else
SetOpacityPixelComponent(q,OpaqueOpacity);
+
q++;
}
else if (ping_color_type == PNG_COLOR_TYPE_GRAY)
@@ -2637,10 +2805,13 @@
q->red=image->colormap[(ssize_t) indexpacket].red;
q->green=q->red;
q->blue=q->red;
+
if (ScaleQuantomToShort(q->red) == transparent_color.opacity)
q->opacity=(Quantum) TransparentOpacity;
+
else
SetOpacityPixelComponent(q,OpaqueOpacity);
+
q++;
}
}
@@ -2651,8 +2822,10 @@
ScaleQuantumToShort(q->green) == transparent_color.green &&
ScaleQuantumToShort(q->blue) == transparent_color.blue)
q->opacity=(Quantum) TransparentOpacity;
+
else
SetOpacityPixelComponent(q,OpaqueOpacity);
+
q++;
}
if (SyncAuthenticPixels(image,exception) == MagickFalse)
@@ -2672,8 +2845,10 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading PNG text chunk");
+
if (memcmp(text[i].key, "Raw profile type ",17) == 0)
(void) png_read_raw_profile(image,image_info,text,(int) i);
+
else
{
char
@@ -2692,9 +2867,11 @@
*value='\0';
(void) ConcatenateMagickString(value,text[i].text,length+2);
(void) SetImageProperty(image,text[i].key,value);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Keyword: %s",text[i].key);
+
value=DestroyString(value);
}
}
@@ -2711,6 +2888,7 @@
*/
mng_info->ob[object_id]=(MngBuffer *)
AcquireMagickMemory(sizeof(MngBuffer));
+
if (mng_info->ob[object_id] != (MngBuffer *) NULL)
{
mng_info->ob[object_id]->image=(Image *) NULL;
@@ -2724,27 +2902,34 @@
(void) ThrowMagickException(&image->exception,GetMagickModule(),
ResourceLimitError,"MemoryAllocationFailed","`%s'",
image->filename);
+
if (mng_info->ob[object_id]->frozen)
(void) ThrowMagickException(&image->exception,GetMagickModule(),
ResourceLimitError,"Cannot overwrite frozen MNG object buffer",
"`%s'",image->filename);
}
+
else
{
if (mng_info->ob[object_id]->image != (Image *) NULL)
mng_info->ob[object_id]->image=DestroyImage
(mng_info->ob[object_id]->image);
+
mng_info->ob[object_id]->image=CloneImage(image,0,0,MagickTrue,
&image->exception);
+
if (mng_info->ob[object_id]->image != (Image *) NULL)
mng_info->ob[object_id]->image->file=(FILE *) NULL;
+
else
(void) ThrowMagickException(&image->exception,GetMagickModule(),
ResourceLimitError,"Cloning image for object buffer failed",
"`%s'",image->filename);
+
if (ping_width > 250000L || ping_height > 250000L)
png_error(ping,"PNG Image dimensions are too large.");
+
mng_info->ob[object_id]->width=ping_width;
mng_info->ob[object_id]->height=ping_height;
mng_info->ob[object_id]->color_type=ping_color_type;
@@ -2753,6 +2938,7 @@
mng_info->ob[object_id]->compression_method=
ping_compression_method;
mng_info->ob[object_id]->filter_method=ping_filter_method;
+
if (png_get_valid(ping,ping_info,PNG_INFO_PLTE))
{
int
@@ -2789,6 +2975,7 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit ReadOnePNGImage()");
+
return(image);
/* end of reading one PNG image */
@@ -2861,12 +3048,15 @@
{
if (previous->signature != MagickSignature)
ThrowReaderException(CorruptImageError,"CorruptImage");
+
(void) CloseBlob(previous);
(void) DestroyImageList(previous);
}
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"exit ReadPNGImage() with error");
+
return((Image *) NULL);
}
(void) CloseBlob(image);
@@ -2875,11 +3065,13 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"exit ReadPNGImage() with error.");
+
ThrowReaderException(CorruptImageError,"CorruptImage");
}
if (LocaleCompare(image_info->magick,"PNG8") == 0)
{
(void) SetImageType(image,PaletteType);
+
if (image->matte != MagickFalse)
{
/* To do: Reduce to binary transparency */
@@ -2890,10 +3082,13 @@
(void) SetImageType(image,TrueColorType);
image->matte=MagickFalse;
}
+
if (LocaleCompare(image_info->magick,"PNG32") == 0)
(void) SetImageType(image,TrueColorMatteType);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadPNGImage()");
+
return(image);
}
@@ -3001,6 +3196,7 @@
" enter ReadOneJNGImage()");
image=mng_info->image;
+
if (GetAuthenticPixelQueue(image) != (PixelPacket *) NULL)
{
/*
@@ -3009,9 +3205,12 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" AcquireNextImage()");
+
AcquireNextImage(image_info,image);
+
if (GetNextImageInList(image) == (Image *) NULL)
return((Image *) NULL);
+
image=SyncNextImageInList(image);
}
mng_info->image=image;
@@ -3039,8 +3238,10 @@
*/
status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
2*GetBlobSize(image));
+
if (status == MagickFalse)
break;
+
type[0]='\0';
(void) ConcatenateMagickString(type,"errr",MaxTextExtent);
length=ReadBlobMSBLong(image);
@@ -3053,15 +3254,19 @@
if (length > PNG_UINT_31_MAX || count == 0)
ThrowReaderException(CorruptImageError,"CorruptImage");
+
p=NULL;
chunk=(unsigned char *) NULL;
if (length)
{
chunk=(unsigned char *) AcquireQuantumMemory(length,sizeof(*chunk));
+
if (chunk == (unsigned char *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+
for (i=0; i < (ssize_t) length; i++)
chunk[i]=(unsigned char) ReadBlobByte(image);
+
p=chunk;
}
(void) ReadBlobMSBLong(image); /* read crc word */
@@ -3144,15 +3349,18 @@
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
GetImageInfo(color_image_info);
color_image=AcquireImage(color_image_info);
+
if (color_image == (Image *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Creating color_blob.");
+
(void) AcquireUniqueFilename(color_image->filename);
status=OpenBlob(color_image_info,color_image,WriteBinaryBlobMode,
exception);
+
if (status == MagickFalse)
return((Image *) NULL);
@@ -3160,24 +3368,31 @@
{
alpha_image_info=(ImageInfo *)
AcquireMagickMemory(sizeof(ImageInfo));
+
if (alpha_image_info == (ImageInfo *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+
GetImageInfo(alpha_image_info);
alpha_image=AcquireImage(alpha_image_info);
+
if (alpha_image == (Image *) NULL)
{
alpha_image=DestroyImage(alpha_image);
ThrowReaderException(ResourceLimitError,
"MemoryAllocationFailed");
}
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Creating alpha_blob.");
+
(void) AcquireUniqueFilename(alpha_image->filename);
status=OpenBlob(alpha_image_info,alpha_image,WriteBinaryBlobMode,
exception);
+
if (status == MagickFalse)
return((Image *) NULL);
+
if (jng_alpha_compression_method == 0)
{
unsigned char
@@ -3186,8 +3401,10 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing IHDR chunk to alpha_blob.");
+
(void) WriteBlob(alpha_image,8,(const unsigned char *)
"\211PNG\r\n\032\n");
+
(void) WriteBlobMSBULong(alpha_image,13L);
PNGType(data,mng_IHDR);
LogPNGChunk((int) logging,mng_IHDR,13L);
@@ -3244,8 +3461,10 @@
(void) WriteBlobMSBULong(alpha_image,
crc32(crc32(0,data,4),chunk,(uInt) length));
}
+
if (length)
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
+
continue;
}
@@ -3263,16 +3482,20 @@
(void) WriteBlob(alpha_image,length,chunk);
}
+
if (length)
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
+
continue;
}
if (memcmp(type,mng_JSEP,4) == 0)
{
read_JSEP=MagickTrue;
+
if (length)
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
+
continue;
}
@@ -3284,12 +3507,14 @@
image->background_color.green=image->background_color.red;
image->background_color.blue=image->background_color.red;
}
+
if (length == 6)
{
image->background_color.red=ScaleCharToQuantum(p[1]);
image->background_color.green=ScaleCharToQuantum(p[3]);
image->background_color.blue=ScaleCharToQuantum(p[5]);
}
+
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
}
@@ -3298,6 +3523,7 @@
{
if (length == 4)
image->gamma=((float) mng_get_long(p))*0.00001;
+
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
}
@@ -3345,6 +3571,7 @@
{
image->page.x=mng_get_long(p);
image->page.y=mng_get_long(&p[4]);
+
if ((int) p[8] != 0)
{
image->page.x/=10000;
@@ -3353,6 +3580,7 @@
}
if (length)
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
+
continue;
}
@@ -3369,6 +3597,7 @@
image->y_resolution=image->y_resolution/100.0f;
}
}
+
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
}
@@ -3379,6 +3608,7 @@
/* To do. */
if (length)
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
+
continue;
}
#endif
@@ -3388,6 +3618,7 @@
if (memcmp(type,mng_IEND,4))
continue;
+
break;
}
@@ -3419,10 +3650,13 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading jng_image from color_blob.");
+
(void) FormatMagickString(color_image_info->filename,MaxTextExtent,"%s",
color_image->filename);
+
color_image_info->ping=MagickFalse; /* To do: avoid this */
jng_image=ReadImage(color_image_info,exception);
+
if (jng_image == (Image *) NULL)
return((Image *) NULL);
@@ -3436,9 +3670,11 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Copying jng_image pixels to main image.");
+
image->rows=jng_height;
image->columns=jng_width;
length=image->columns*sizeof(PixelPacket);
+
for (y=0; y < (ssize_t) image->rows; y++)
{
s=GetVirtualPixels(jng_image,0,y,image->columns,1,&image->exception);
@@ -3447,7 +3683,9 @@
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
}
+
jng_image=DestroyImage(jng_image);
+
if (image_info->ping == MagickFalse)
{
if (jng_color_type >= 12)
@@ -3462,7 +3700,9 @@
(void) WriteBlob(alpha_image,4,data);
(void) WriteBlobMSBULong(alpha_image,crc32(0,data,4));
}
+
(void) CloseBlob(alpha_image);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Reading opacity from alpha_blob.");
@@ -3471,6 +3711,7 @@
"%s",alpha_image->filename);
jng_image=ReadImage(alpha_image_info,exception);
+
if (jng_image != (Image *) NULL)
for (y=0; y < (ssize_t) image->rows; y++)
{
@@ -3480,6 +3721,7 @@
if (image->matte != MagickFalse)
for (x=(ssize_t) image->columns; x != 0; x--,q++,s++)
q->opacity=(Quantum) QuantumRange-s->red;
+
else
for (x=(ssize_t) image->columns; x != 0; x--,q++,s++)
{
@@ -3487,6 +3729,7 @@
if (q->opacity != OpaqueOpacity)
image->matte=MagickTrue;
}
+
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
}
@@ -3506,26 +3749,32 @@
mng_info->mng_width=jng_width;
mng_info->mng_height=jng_height;
}
+
if (image->page.width == 0 && image->page.height == 0)
- {
- image->page.width=jng_width;
- image->page.height=jng_height;
- }
+ {
+ image->page.width=jng_width;
+ image->page.height=jng_height;
+ }
+
if (image->page.x == 0 && image->page.y == 0)
- {
- image->page.x=mng_info->x_off[mng_info->object_id];
- image->page.y=mng_info->y_off[mng_info->object_id];
- }
+ {
+ image->page.x=mng_info->x_off[mng_info->object_id];
+ image->page.y=mng_info->y_off[mng_info->object_id];
+ }
+
else
- {
- image->page.y=mng_info->y_off[mng_info->object_id];
- }
+ {
+ image->page.y=mng_info->y_off[mng_info->object_id];
+ }
+
mng_info->image_found++;
status=SetImageProgress(image,LoadImagesTag,2*TellBlob(image),
2*GetBlobSize(image));
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit ReadOneJNGImage()");
+
return(image);
}
@@ -3594,23 +3843,29 @@
image=AcquireImage(image_info);
mng_info=(MngInfo *) NULL;
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
+
if (status == MagickFalse)
return((Image *) NULL);
+
if (LocaleCompare(image_info->magick,"JNG") != 0)
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+
/*
Verify JNG signature.
*/
count=(size_t) ReadBlob(image,8,(unsigned char *) magic_number);
if (memcmp(magic_number,"\213JNG\r\n\032\n",8) != 0)
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
+
/*
Allocate a MngInfo structure.
*/
have_mng_structure=MagickFalse;
mng_info=(MngInfo *) AcquireMagickMemory(sizeof(*mng_info));
+
if (mng_info == (MngInfo *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+
/*
Initialize members of the MngInfo structure.
*/
@@ -3621,6 +3876,7 @@
previous=image;
image=ReadOneJNGImage(mng_info,image_info,exception);
MngInfoFreeStruct(mng_info,&have_mng_structure);
+
if (image == (Image *) NULL)
{
if (IsImageObject(previous) != MagickFalse)
@@ -3628,9 +3884,11 @@
(void) CloseBlob(previous);
(void) DestroyImageList(previous);
}
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"exit ReadJNGImage() with error");
+
return((Image *) NULL);
}
(void) CloseBlob(image);
@@ -3639,10 +3897,13 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"exit ReadJNGImage() with error");
+
ThrowReaderException(CorruptImageError,"CorruptImage");
}
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit ReadJNGImage()");
+
return(image);
}
#endif
@@ -3749,21 +4010,6 @@
default_fb.right=0;
/*
- Set image_info->type=OptimizeType (new in version 5.4.0) to get the
- following optimizations:
-
- o 16-bit depth is reduced to 8 if all pixels contain samples whose
- high byte and low byte are identical.
- o Opaque matte channel is removed.
- o If matte channel is present but only one transparent color is
- present, RGB+tRNS is written instead of RGBA
- o Grayscale images are reduced to 1, 2, or 4 bit depth if
- this can be done without loss.
- o Palette is sorted to remove unused entries and to put a
- transparent color first, if PNG_SORT_PALETTE is also defined.
- */
-
- /*
Open image file.
*/
assert(image_info != (const ImageInfo *) NULL);
@@ -3775,8 +4021,10 @@
image=AcquireImage(image_info);
mng_info=(MngInfo *) NULL;
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
+
if (status == MagickFalse)
return((Image *) NULL);
+
first_mng_object=MagickFalse;
skipping_loop=(-1);
have_mng_structure=MagickFalse;
@@ -3784,8 +4032,10 @@
Allocate a MngInfo structure.
*/
mng_info=(MngInfo *) AcquireMagickMemory(sizeof(MngInfo));
+
if (mng_info == (MngInfo *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
+
/*
Initialize members of the MngInfo structure.
*/
@@ -3861,10 +4111,13 @@
if (length > PNG_UINT_31_MAX)
status=MagickFalse;
+
if (count == 0)
ThrowReaderException(CorruptImageError,"CorruptImage");
+
p=NULL;
chunk=(unsigned char *) NULL;
+
if (length)
{
chunk=(unsigned char *) AcquireQuantumMemory(length,sizeof(*chunk));
@@ -3874,24 +4127,29 @@
chunk[i]=(unsigned char) ReadBlobByte(image);
p=chunk;
}
+
(void) ReadBlobMSBLong(image); /* read crc word */
#if !defined(JNG_SUPPORTED)
if (memcmp(type,mng_JHDR,4) == 0)
{
skip_to_iend=MagickTrue;
+
if (mng_info->jhdr_warning == 0)
(void) ThrowMagickException(&image->exception,GetMagickModule(),
CoderError,"JNGCompressNotSupported","`%s'",image->filename);
+
mng_info->jhdr_warning++;
}
#endif
if (memcmp(type,mng_DHDR,4) == 0)
{
skip_to_iend=MagickTrue;
+
if (mng_info->dhdr_warning == 0)
(void) ThrowMagickException(&image->exception,GetMagickModule(),
CoderError,"DeltaPNGNotSupported","`%s'",image->filename);
+
mng_info->dhdr_warning++;
}
if (memcmp(type,mng_MEND,4) == 0)
@@ -3900,19 +4158,25 @@
{
if (memcmp(type,mng_IEND,4) == 0)
skip_to_iend=MagickFalse;
+
if (length)
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Skip to IEND.");
+
continue;
}
+
if (memcmp(type,mng_MHDR,4) == 0)
{
mng_info->mng_width=(size_t) ((p[0] << 24) | (p[1] << 16) |
(p[2] << 8) | p[3]);
+
mng_info->mng_height=(size_t) ((p[4] << 24) | (p[5] << 16) |
(p[6] << 8) | p[7]);
+
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -3920,25 +4184,34 @@
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" MNG height: %.20g",(double) mng_info->mng_height);
}
+
p+=8;
mng_info->ticks_per_second=(size_t) mng_get_long(p);
+
if (mng_info->ticks_per_second == 0)
default_frame_delay=0;
+
else
default_frame_delay=1UL*image->ticks_per_second/
mng_info->ticks_per_second;
+
frame_delay=default_frame_delay;
simplicity=0;
+
if (length > 16)
{
p+=16;
simplicity=(size_t) mng_get_long(p);
}
+
mng_type=1; /* Full MNG */
+
if ((simplicity != 0) && ((simplicity | 11) == 11))
mng_type=2; /* LC */
+
if ((simplicity != 0) && ((simplicity | 9) == 9))
mng_type=3; /* VLC */
+
#if defined(MNG_INSERT_LAYERS)
if (mng_type != 3)
insert_layers=MagickTrue;
@@ -3949,8 +4222,10 @@
Allocate next image structure.
*/
AcquireNextImage(image_info,image);
+
if (GetNextImageInList(image) == (Image *) NULL)
return((Image *) NULL);
+
image=SyncNextImageInList(image);
mng_info->image=image;
}
@@ -3958,16 +4233,20 @@
if ((mng_info->mng_width > 65535L) ||
(mng_info->mng_height > 65535L))
ThrowReaderException(ImageError,"WidthOrHeightExceedsLimit");
+
(void) FormatMagickString(page_geometry,MaxTextExtent,
"%.20gx%.20g+0+0",(double) mng_info->mng_width,(double)
mng_info->mng_height);
+
mng_info->frame.left=0;
mng_info->frame.right=(ssize_t) mng_info->mng_width;
mng_info->frame.top=0;
mng_info->frame.bottom=(ssize_t) mng_info->mng_height;
mng_info->clip=default_fb=previous_fb=mng_info->frame;
+
for (i=0; i < MNG_MAX_OBJECTS; i++)
mng_info->object_clip[i]=mng_info->frame;
+
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
}
@@ -3980,24 +4259,31 @@
if (length)
repeat=p[0];
+
if (repeat == 3)
{
final_delay=(png_uint_32) mng_get_long(&p[2]);
mng_iterations=(png_uint_32) mng_get_long(&p[6]);
+
if (mng_iterations == PNG_UINT_31_MAX)
mng_iterations=0;
+
image->iterations=mng_iterations;
term_chunk_found=MagickTrue;
}
+
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" repeat=%d",repeat);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" final_delay=%.20g",(double) final_delay);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" image->iterations=%.20g",(double) image->iterations);
}
+
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
}
@@ -4007,11 +4293,14 @@
(void) ThrowMagickException(&image->exception,GetMagickModule(),
CoderError,"DEFI chunk found in MNG-VLC datastream","`%s'",
image->filename);
+
object_id=(p[0] << 8) | p[1];
+
if (mng_type == 2 && object_id != 0)
(void) ThrowMagickException(&image->exception,GetMagickModule(),
CoderError,"Nonzero object_id in MNG-LC datastream","`%s'",
image->filename);
+
if (object_id > MNG_MAX_OBJECTS)
{
/*
@@ -4022,6 +4311,7 @@
CoderError,"object id too large","`%s'",image->filename);
object_id=MNG_MAX_OBJECTS;
}
+
if (mng_info->exists[object_id])
if (mng_info->frozen[object_id])
{
@@ -4032,50 +4322,63 @@
image->filename);
continue;
}
+
mng_info->exists[object_id]=MagickTrue;
+
if (length > 2)
mng_info->invisible[object_id]=p[2];
+
/*
Extract object offset info.
*/
if (length > 11)
{
- mng_info->x_off[object_id]=(ssize_t) ((p[4] << 24) | (p[5] << 16) |
- (p[6] << 8) | p[7]);
- mng_info->y_off[object_id]=(ssize_t) ((p[8] << 24) | (p[9] << 16) |
- (p[10] << 8) | p[11]);
+ mng_info->x_off[object_id]=(ssize_t) ((p[4] << 24) |
+ (p[5] << 16) | (p[6] << 8) | p[7]);
+
+ mng_info->y_off[object_id]=(ssize_t) ((p[8] << 24) |
+ (p[9] << 16) | (p[10] << 8) | p[11]);
+
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" x_off[%d]: %.20g",object_id,(double)
mng_info->x_off[object_id]);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" y_off[%d]: %.20g",object_id,(double)
mng_info->y_off[object_id]);
}
}
+
/*
Extract object clipping info.
*/
if (length > 27)
mng_info->object_clip[object_id]=mng_read_box(mng_info->frame,0,
&p[12]);
+
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
}
if (memcmp(type,mng_bKGD,4) == 0)
{
mng_info->have_global_bkgd=MagickFalse;
+
if (length > 5)
{
mng_info->mng_global_bkgd.red=
ScaleShortToQuantum((unsigned short) ((p[0] << 8) | p[1]));
+
mng_info->mng_global_bkgd.green=
ScaleShortToQuantum((unsigned short) ((p[2] << 8) | p[3]));
+
mng_info->mng_global_bkgd.blue=
ScaleShortToQuantum((unsigned short) ((p[4] << 8) | p[5]));
+
mng_info->have_global_bkgd=MagickTrue;
}
+
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
}
@@ -4084,18 +4387,24 @@
#if defined(MNG_INSERT_LAYERS)
if (length > 6)
mandatory_back=p[6];
+
else
mandatory_back=0;
+
if (mandatory_back && length > 5)
{
mng_background_color.red=
ScaleShortToQuantum((unsigned short) ((p[0] << 8) | p[1]));
+
mng_background_color.green=
ScaleShortToQuantum((unsigned short) ((p[2] << 8) | p[3]));
+
mng_background_color.blue=
ScaleShortToQuantum((unsigned short) ((p[4] << 8) | p[5]));
+
mng_background_color.opacity=OpaqueOpacity;
}
+
#ifdef MNG_OBJECT_BUFFERS
if (length > 8)
mng_background_object=(p[7] << 8) | p[8];
@@ -4114,12 +4423,14 @@
if (mng_info->global_plte == (png_colorp) NULL)
mng_info->global_plte=(png_colorp) AcquireQuantumMemory(256,
sizeof(*mng_info->global_plte));
+
for (i=0; i < (ssize_t) (length/3); i++)
{
mng_info->global_plte[i].red=p[3*i];
mng_info->global_plte[i].green=p[3*i+1];
mng_info->global_plte[i].blue=p[3*i+2];
}
+
mng_info->global_plte_length=(unsigned int) (length/3);
}
#ifdef MNG_LOOSE
@@ -4129,11 +4440,13 @@
mng_info->global_plte[i].green=i;
mng_info->global_plte[i].blue=i;
}
+
if (length)
mng_info->global_plte_length=256;
#endif
else
mng_info->global_plte_length=0;
+
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
}
@@ -4164,8 +4477,10 @@
mng_info->global_gamma=((float) igamma)*0.00001;
mng_info->have_global_gama=MagickTrue;
}
+
else
mng_info->have_global_gama=MagickFalse;
+
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
}
@@ -4230,17 +4545,21 @@
(void) ThrowMagickException(&image->exception,GetMagickModule(),
CoderError,"FRAM chunk found in MNG-VLC datastream","`%s'",
image->filename);
+
if ((mng_info->framing_mode == 2) || (mng_info->framing_mode == 4))
image->delay=frame_delay;
+
frame_delay=default_frame_delay;
frame_timeout=default_frame_timeout;
fb=default_fb;
if (length)
if (p[0])
mng_info->framing_mode=p[0];
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Framing_mode=%d",mng_info->framing_mode);
+
if (length > 6)
{
/*
@@ -4265,13 +4584,18 @@
{
frame_delay=1UL*image->ticks_per_second*
mng_get_long(p);
+
if (mng_info->ticks_per_second != 0)
frame_delay/=mng_info->ticks_per_second;
+
else
frame_delay=PNG_UINT_31_MAX;
+
if (change_delay == 2)
default_frame_delay=frame_delay;
+
p+=4;
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Framing_delay=%.20g",(double) frame_delay);
@@ -4280,13 +4604,18 @@
{
frame_timeout=1UL*image->ticks_per_second*
mng_get_long(p);
+
if (mng_info->ticks_per_second != 0)
frame_timeout/=mng_info->ticks_per_second;
+
else
frame_timeout=PNG_UINT_31_MAX;
+
if (change_delay == 2)
default_frame_timeout=frame_timeout;
+
p+=4;
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Framing_timeout=%.20g",(double) frame_timeout);
@@ -4296,9 +4625,10 @@
fb=mng_read_box(previous_fb,(char) p[0],&p[1]);
p+=17;
previous_fb=fb;
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Frame_clipping: L=%.20g R=%.20g T=%.20g B=%.20g",
+ " Frame_clip: L=%.20g R=%.20g T=%.20g B=%.20g",
(double) fb.left,(double) fb.right,(double) fb.top,
(double) fb.bottom);
if (change_clipping == 2)
@@ -4308,8 +4638,10 @@
}
mng_info->clip=fb;
mng_info->clip=mng_minimum_box(fb,mng_info->frame);
+
subframe_width=(size_t) (mng_info->clip.right
-mng_info->clip.left);
+
subframe_height=(size_t) (mng_info->clip.bottom
-mng_info->clip.top);
/*
@@ -4320,6 +4652,7 @@
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" subframe_width=%.20g, subframe_height=%.20g",(double)
subframe_width,(double) subframe_height);
+
if (insert_layers && (mng_info->framing_mode == 4) &&
(subframe_width) && (subframe_height))
{
@@ -4337,15 +4670,19 @@
}
image=SyncNextImageInList(image);
}
+
mng_info->image=image;
+
if (term_chunk_found)
{
image->start_loop=MagickTrue;
image->iterations=mng_iterations;
term_chunk_found=MagickFalse;
}
+
else
image->start_loop=MagickFalse;
+
image->columns=subframe_width;
image->rows=subframe_height;
image->page.width=subframe_width;
@@ -4356,9 +4693,10 @@
image->matte=MagickFalse;
image->delay=0;
(void) SetImageBackgroundColor(image);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Inserted background layer, L=%.20g, R=%.20g T=%.20g, B=%.20g",
+ " Insert backgd layer, L=%.20g, R=%.20g T=%.20g, B=%.20g",
(double) mng_info->clip.left,(double) mng_info->clip.right,
(double) mng_info->clip.top,(double) mng_info->clip.bottom);
}
@@ -4402,8 +4740,10 @@
mng_info->ob[i]->frozen=MagickTrue;
#endif
}
+
if (length)
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
+
continue;
}
@@ -4417,6 +4757,7 @@
for (i=1; i < MNG_MAX_OBJECTS; i++)
MngInfoDiscardObject(mng_info,i);
}
+
else
{
register ssize_t
@@ -4428,8 +4769,10 @@
MngInfoDiscardObject(mng_info,i);
}
}
+
if (length)
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
+
continue;
}
if (memcmp(type,mng_MOVE,4) == 0)
@@ -4473,17 +4816,21 @@
Record starting point.
*/
loop_iters=mng_get_long(&chunk[1]);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" LOOP level %.20g has %.20g iterations ",(double) loop_level,
(double) loop_iters);
+
if (loop_iters == 0)
skipping_loop=loop_level;
+
else
{
mng_info->loop_jump[loop_level]=TellBlob(image);
mng_info->loop_count[loop_level]=loop_iters;
}
+
mng_info->loop_iteration[loop_level]=0;
chunk=(unsigned char *) RelinquishMagickMemory(chunk);
continue;
@@ -4508,15 +4855,17 @@
{
mng_info->loop_count[loop_level]--;
mng_info->loop_iteration[loop_level]++;
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " ENDL: LOOP level %.20g has %.20g remaining iterations ",
+ " ENDL: LOOP level %.20g has %.20g remaining iters ",
(double) loop_level,(double)
mng_info->loop_count[loop_level]);
if (mng_info->loop_count[loop_level] != 0)
{
offset=SeekBlob(image,mng_info->loop_jump[loop_level],
SEEK_SET);
+
if (offset < 0)
ThrowReaderException(CorruptImageError,
"ImproperImageHeader");
@@ -4565,10 +4914,13 @@
if (length > 1)
magn_first=(p[0] << 8) | p[1];
+
else
magn_first=0;
+
if (length > 3)
magn_last=(p[2] << 8) | p[3];
+
else
magn_last=magn_first;
#ifndef MNG_OBJECT_BUFFERS
@@ -4866,13 +5218,16 @@
}
image=SyncNextImageInList(image);
}
+
mng_info->image=image;
+
if (term_chunk_found)
{
image->start_loop=MagickTrue;
image->iterations=mng_iterations;
term_chunk_found=MagickFalse;
}
+
else
image->start_loop=MagickFalse;
image->delay=0;
@@ -4885,9 +5240,10 @@
image->background_color=mng_background_color;
image->matte=MagickFalse;
(void) SetImageBackgroundColor(image);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Inserted background layer, L=%.20g, R=%.20g T=%.20g, B=%.20g",
+ " Insert background layer, L=%.20g, R=%.20g T=%.20g, B=%.20g",
(double) mng_info->clip.left,(double) mng_info->clip.right,
(double) mng_info->clip.top,(double) mng_info->clip.bottom);
}
@@ -4910,22 +5266,28 @@
mng_info->image=image;
status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
GetBlobSize(image));
+
if (status == MagickFalse)
break;
+
if (term_chunk_found)
{
image->start_loop=MagickTrue;
term_chunk_found=MagickFalse;
}
+
else
image->start_loop=MagickFalse;
+
if (mng_info->framing_mode == 1 || mng_info->framing_mode == 3)
{
image->delay=frame_delay;
frame_delay=default_frame_delay;
}
+
else
image->delay=0;
+
image->page.width=mng_info->mng_width;
image->page.height=mng_info->mng_height;
image->page.x=mng_info->x_off[object_id];
@@ -4965,6 +5327,7 @@
MngInfoFreeStruct(mng_info,&have_mng_structure);
return((Image *) NULL);
}
+
if (image->columns == 0 || image->rows == 0)
{
(void) CloseBlob(image);
@@ -4972,6 +5335,7 @@
MngInfoFreeStruct(mng_info,&have_mng_structure);
return((Image *) NULL);
}
+
mng_info->image=image;
if (mng_type)
@@ -5550,6 +5914,7 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" No images found. Inserting a background layer.");
+
if (GetAuthenticPixelQueue(image) != (PixelPacket *) NULL)
{
/*
@@ -5575,14 +5940,18 @@
image->page.y=0;
image->background_color=mng_background_color;
image->matte=MagickFalse;
+
if (image_info->ping == MagickFalse)
(void) SetImageBackgroundColor(image);
+
mng_info->image_found++;
}
#endif
image->iterations=mng_iterations;
+
if (mng_iterations == 1)
image->start_loop=MagickTrue;
+
while (GetPreviousImageInList(image) != (Image *) NULL)
{
image_count++;
@@ -5595,7 +5964,9 @@
"`%s'",image_info->filename);
return((Image *) NULL);
}
+
image=GetPreviousImageInList(image);
+
if (GetNextImageInList(image) == (Image *) NULL)
{
if (logging != MagickFalse)
@@ -5632,23 +6003,30 @@
if (mng_info->ticks_per_second)
final_delay=1UL*MagickMax(image->ticks_per_second,1L)*
final_delay/mng_info->ticks_per_second;
+
else
image->start_loop=MagickTrue;
+
/* Find final nonzero image delay */
final_image_delay=0;
+
while (GetNextImageInList(image) != (Image *) NULL)
{
if (image->delay)
final_image_delay=image->delay;
image=GetNextImageInList(image);
}
+
if (final_delay < final_image_delay)
final_delay=final_image_delay;
+
image->delay=final_delay;
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" image->delay=%.20g, final_delay=%.20g",(double) image->delay,
(double) final_delay);
+
if (logging != MagickFalse)
{
int
@@ -6050,9 +6428,10 @@
if (image_info->verbose)
{
- (void) printf("writing raw profile: type=%s, length=%.20g\n",
- (char *) profile_type, (double) length);
+ (void) printf("writing raw profile: type=%s, length=%.20g\n",
+ (char *) profile_type, (double) length);
}
+
text=(png_textp) png_malloc(ping,(png_uint_32) sizeof(png_text));
description_length=(png_uint_32) strlen((const char *) profile_description);
allocated_length=(png_uint_32) (length*2 + (length >> 5) + 20
@@ -6308,10 +6687,13 @@
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" new_number_colors in OptimizePNGColormap=%d",
(int) new_number_colors);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" In OptimizePNGColormap:");
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" i plte_map (red,green,blue,opacity)");
+
for (i=0; i < image->colors; i++)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -6341,14 +6723,14 @@
Eliminate unused colormap entries.
*/
for (i=0; i < number_colors; i++)
- ping_plte_map[i]=i;
+ ping_plte_map[i]=i;
k=0;
for (i=0; i < number_colors; i++)
{
if (marker[i])
{
- ping_plte_map[i]=(IndexPacket) k;
+ ping_plte_map[i]=(IndexPacket) k;
for (j=i+1; j < number_colors; j++)
{
if ((image->colormap[i].opacity == image->colormap[j].opacity) &&
@@ -6362,7 +6744,7 @@
}
}
- if (have_transparency && (image->colormap[0].opacity !=
+ if (have_transparency && (image->colormap[0].opacity !=
(Quantum) TransparentOpacity))
{
/*
@@ -6446,7 +6828,7 @@
colormap[ping_plte_map[i]] = image->colormap[i];
if (ping_plte_map[i] != i)
- remap_needed = MagickTrue;
+ remap_needed = MagickTrue;
if (ping_plte_map[i] >= ping_number_colors)
ping_number_colors=ping_plte_map[i]+1;
@@ -6464,22 +6846,28 @@
for (y=0; y < (ssize_t) image->rows; y++)
{
q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
+
if (q == (PixelPacket *) NULL)
break;
+
pixels=GetAuthenticIndexQueue(image);
+
for (x=0; x < (ssize_t) image->columns; x++)
{
j=(int) pixels[x];
pixels[x]=(IndexPacket) ping_plte_map[j];
}
+
if (SyncAuthenticPixels(image,exception) == MagickFalse)
break;
}
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" After OptimizePNGColormap:");
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" i plte_map (red,green,blue,opacity)");
+
for (i=0; i < image->colors; i++)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -6589,7 +6977,7 @@
matte;
volatile int
- ping_bit_depth,
+ ping_bit_depth,
ping_color_type,
ping_interlace_method,
ping_compression_method,
@@ -6622,7 +7010,7 @@
#endif
/* Initialize some stuff */
- ping_bit_depth=0,
+ ping_bit_depth=0,
ping_color_type=0,
ping_interlace_method=0,
ping_compression_method=0,
@@ -6657,7 +7045,8 @@
if (image->colorspace != RGBColorspace)
(void) TransformImageColorspace(image,RGBColorspace);
- mng_info->IsPalette=image->storage_class == PseudoClass &&
+
+ mng_info->IsPalette=image->storage_class == PseudoClass &&
image_colors <= 256 && !IsOpaqueImage(image,&image->exception);
/*
@@ -6667,18 +7056,23 @@
ping=png_create_write_struct_2(PNG_LIBPNG_VER_STRING,image,
PNGErrorHandler,PNGWarningHandler,(void *) NULL,
(png_malloc_ptr) png_IM_malloc,(png_free_ptr) png_IM_free);
+
#else
ping=png_create_write_struct(PNG_LIBPNG_VER_STRING,image,
PNGErrorHandler,PNGWarningHandler);
+
#endif
if (ping == (png_struct *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+
ping_info=png_create_info_struct(ping);
+
if (ping_info == (png_info *) NULL)
{
png_destroy_write_struct(&ping,(png_info **) NULL);
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
}
+
png_set_write_fn(ping,image,png_put_data,png_flush_data);
png_pixels=(unsigned char *) NULL;
@@ -6714,15 +7108,20 @@
ping_height=(png_uint_32) image->rows;
if (mng_info->write_png8 || mng_info->write_png24 || mng_info->write_png32)
image_depth=8;
+
if (mng_info->write_png_depth != 0)
image_depth=mng_info->write_png_depth;
+
/* Adjust requested depth to next higher valid depth if necessary */
if (image_depth > 8)
image_depth=16;
+
if ((image_depth > 4) && (image_depth < 8))
image_depth=8;
+
if (image_depth == 3)
image_depth=4;
+
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -6743,7 +7142,7 @@
if ((image->x_resolution != 0) && (image->y_resolution != 0) &&
(!mng_info->write_mng || !mng_info->equal_physs))
{
- if (logging != MagickFalse)
+ if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Setting up pHYs chunk");
@@ -6780,225 +7179,262 @@
mask=0xffff;
if (ping_bit_depth == 8)
mask=0x00ff;
+
if (ping_bit_depth == 4)
mask=0x000f;
+
if (ping_bit_depth == 2)
mask=0x0003;
+
if (ping_bit_depth == 1)
mask=0x0001;
+
ping_background.red=(png_uint_16)
(ScaleQuantumToShort(image->background_color.red) & mask);
+
ping_background.green=(png_uint_16)
(ScaleQuantumToShort(image->background_color.green) & mask);
+
ping_background.blue=(png_uint_16)
(ScaleQuantumToShort(image->background_color.blue) & mask);
- }
+ }
- if (logging != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Setting up bKGd chunk");
- ping_have_bKGD = MagickTrue;
+ if (logging != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Setting up bKGd chunk");
+
+ ping_have_bKGD = MagickTrue;
+
/*
Select the color type.
*/
matte=image_matte;
old_bit_depth=0;
+
if ((mng_info->write_png_colortype-1) == PNG_COLOR_TYPE_PALETTE)
mng_info->write_png8=MagickTrue;
+
if (mng_info->write_png8)
{
+ QuantizeInfo
+ quantize_info;
+
+ /* TO DO: make this a function cause it's used twice, except
+ for reducing the sample depth from 8. */
+
ping_color_type=(png_byte) PNG_COLOR_TYPE_PALETTE;
ping_bit_depth=8;
image_depth=ping_bit_depth;
+
+ number_colors=image_colors;
+ if ((image->storage_class == DirectClass) || (number_colors > 256))
{
- /* TO DO: make this a function cause it's used twice, except
- for reducing the sample depth from 8. */
-
- QuantizeInfo
- quantize_info;
-
+ GetQuantizeInfo(&quantize_info);
+ quantize_info.dither=IsPaletteImage(image,&image->exception) ==
+ MagickFalse ? MagickTrue : MagickFalse;
+ quantize_info.number_colors= (matte != MagickFalse ? 255UL :
+ 256UL);
+ (void) QuantizeImage(&quantize_info,image);
number_colors=image_colors;
- if ((image->storage_class == DirectClass) || (number_colors > 256))
- {
- GetQuantizeInfo(&quantize_info);
- quantize_info.dither=IsPaletteImage(image,&image->exception) ==
- MagickFalse ? MagickTrue : MagickFalse;
- quantize_info.number_colors= (matte != MagickFalse ? 255UL :
- 256UL);
- (void) QuantizeImage(&quantize_info,image);
- number_colors=image_colors;
- (void) SyncImage(image);
- if (logging != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Colors quantized to %.20g",(double) number_colors);
- }
- if (matte)
- ping_have_tRNS=MagickFalse;
- /*
- Set image palette.
- */
- ping_color_type=(png_byte) PNG_COLOR_TYPE_PALETTE;
- if (CompressColormapTransFirst(image) == MagickFalse)
- ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
- number_colors=image->colors;
- image_colors=number_colors;
+ (void) SyncImage(image);
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Setting up PLTE chunk with %d colors (%d)",
- (int) number_colors, (int) image_colors);
- for (i=0; i < (ssize_t) number_colors; i++)
- {
- palette[i].red=ScaleQuantumToChar(image->colormap[i].red);
- palette[i].green=ScaleQuantumToChar(image->colormap[i].green);
- palette[i].blue=ScaleQuantumToChar(image->colormap[i].blue);
- if (logging != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-#if MAGICKCORE_QUANTUM_DEPTH == 8
- " %3ld (%3d,%3d,%3d)",
-#else
- " %5ld (%5d,%5d,%5d)",
-#endif
- (long) i,palette[i].red,palette[i].green,palette[i].blue);
-
- }
- if (matte)
- {
- number_colors++;
- palette[i].red=ScaleQuantumToChar((Quantum) QuantumRange);
- palette[i].green=ScaleQuantumToChar((Quantum) QuantumRange);
- palette[i].blue=ScaleQuantumToChar((Quantum) QuantumRange);
- }
- ping_have_PLTE=MagickTrue;
- image_depth=ping_bit_depth;
- ping_num_trans=0;
- if (matte)
- {
- ExceptionInfo
- *exception;
-
- int
- trans_alpha[256];
-
- /*
- Identify which colormap entry is transparent.
- */
- assert(number_colors <= 256);
- for (i=0; i < (ssize_t) number_colors; i++)
- trans_alpha[i]=255;
- exception=(&image->exception);
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- register const PixelPacket
- *p;
-
- p=GetVirtualPixels(image,0,y,image->columns,1,exception);
- if (p == (PixelPacket *) NULL)
- break;
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- if (p->opacity != OpaqueOpacity)
- {
- trans_alpha[(ssize_t) number_colors-1]=(png_byte) (255-
- ScaleQuantumToChar(GetOpacityPixelComponent(p)));
- }
- p++;
- }
- }
- for (i=0; i < (ssize_t) number_colors; i++)
- if (trans_alpha[i] != 255)
- ping_num_trans=(unsigned short) (i+1);
-
- if (ping_num_trans == 0)
- ping_have_tRNS=MagickFalse;
- if (ping_have_tRNS==MagickFalse)
- ping_num_trans=0;
- if (ping_num_trans != 0)
- {
- for (i=0; i<256; i++)
- ping_trans_alpha[i]=(png_byte) trans_alpha[i];
- }
-
- ping_have_tRNS=MagickTrue;
- }
- /*
- Identify which colormap entry is the background color.
- */
- for (i=0; i < (ssize_t) MagickMax(1L*number_colors-1L,1L); i++)
- if (IsPNGColorEqual(ping_background,image->colormap[i]))
- break;
- ping_background.index=(png_byte) i;
+ " Colors quantized to %.20g",(double) number_colors);
}
+
+ if (matte)
+ ping_have_tRNS=MagickFalse;
+
+ /*
+ Set image palette.
+ */
+ ping_color_type=(png_byte) PNG_COLOR_TYPE_PALETTE;
+
+ if (CompressColormapTransFirst(image) == MagickFalse)
+ ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+
+ number_colors=image->colors;
+ image_colors=number_colors;
+
+ if (logging != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Setting up PLTE chunk with %d colors (%d)",
+ (int) number_colors, (int) image_colors);
+
+ for (i=0; i < (ssize_t) number_colors; i++)
+ {
+ palette[i].red=ScaleQuantumToChar(image->colormap[i].red);
+ palette[i].green=ScaleQuantumToChar(image->colormap[i].green);
+ palette[i].blue=ScaleQuantumToChar(image->colormap[i].blue);
+ if (logging != MagickFalse)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+#if MAGICKCORE_QUANTUM_DEPTH == 8
+ " %3ld (%3d,%3d,%3d)",
+#else
+ " %5ld (%5d,%5d,%5d)",
+#endif
+ (long) i,palette[i].red,palette[i].green,palette[i].blue);
+
+ }
+ if (matte)
+ {
+ number_colors++;
+ palette[i].red=ScaleQuantumToChar((Quantum) QuantumRange);
+ palette[i].green=ScaleQuantumToChar((Quantum) QuantumRange);
+ palette[i].blue=ScaleQuantumToChar((Quantum) QuantumRange);
+ }
+ ping_have_PLTE=MagickTrue;
+ image_depth=ping_bit_depth;
+ ping_num_trans=0;
+ if (matte)
+ {
+ ExceptionInfo
+ *exception;
+
+ int
+ trans_alpha[256];
+
+ /*
+ Identify which colormap entry is transparent.
+ */
+ assert(number_colors <= 256);
+
+ for (i=0; i < (ssize_t) number_colors; i++)
+ trans_alpha[i]=255;
+
+ exception=(&image->exception);
+
+ for (y=0; y < (ssize_t) image->rows; y++)
+ {
+ register const PixelPacket
+ *p;
+
+ p=GetVirtualPixels(image,0,y,image->columns,1,exception);
+
+ if (p == (PixelPacket *) NULL)
+ break;
+
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ if (p->opacity != OpaqueOpacity)
+ {
+ trans_alpha[(ssize_t) number_colors-1]=(png_byte) (255-
+ ScaleQuantumToChar(GetOpacityPixelComponent(p)));
+ }
+ p++;
+ }
+ }
+ for (i=0; i < (ssize_t) number_colors; i++)
+ if (trans_alpha[i] != 255)
+ ping_num_trans=(unsigned short) (i+1);
+
+ if (ping_num_trans == 0)
+ ping_have_tRNS=MagickFalse;
+
+ if (ping_have_tRNS==MagickFalse)
+ ping_num_trans=0;
+
+ if (ping_num_trans != 0)
+ {
+ for (i=0; i<256; i++)
+ ping_trans_alpha[i]=(png_byte) trans_alpha[i];
+ }
+
+ ping_have_tRNS=MagickTrue;
+ }
+
+ /*
+ Identify which colormap entry is the background color.
+ */
+ for (i=0; i < (ssize_t) MagickMax(1L*number_colors-1L,1L); i++)
+ if (IsPNGColorEqual(ping_background,image->colormap[i]))
+ break;
+
+ ping_background.index=(png_byte) i;
+
if (image_matte != MagickFalse)
{
/* TO DO: reduce to binary transparency */
}
} /* end of write_png8 */
+
else if (mng_info->write_png24)
{
image_matte=MagickFalse;
ping_color_type=(png_byte) PNG_COLOR_TYPE_RGB;
}
+
else if (mng_info->write_png32)
{
image_matte=MagickTrue;
ping_color_type=(png_byte) PNG_COLOR_TYPE_RGB_ALPHA;
}
+
else
{
image_depth=ping_bit_depth;
+
if (mng_info->write_png_colortype)
{
ping_color_type=(png_byte) mng_info->write_png_colortype-1;
image_matte=MagickFalse;
+
if (ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
image_matte=MagickTrue;
}
+
else
{
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"Selecting PNG colortype");
+
ping_color_type=(png_byte) ((matte == MagickTrue)?
PNG_COLOR_TYPE_RGB_ALPHA:PNG_COLOR_TYPE_RGB);
+
if(image_info->type == TrueColorType)
{
ping_color_type=(png_byte) PNG_COLOR_TYPE_RGB;
image_matte=MagickFalse;
}
+
if(image_info->type == TrueColorMatteType)
{
ping_color_type=(png_byte) PNG_COLOR_TYPE_RGB_ALPHA;
image_matte=MagickTrue;
}
- if ((image_info->type == UndefinedType ||
- image_info->type == OptimizeType ||
+
+ if ((image_info->type == UndefinedType ||
+ image_info->type == OptimizeType ||
image_info->type == GrayscaleType) &&
image_matte == MagickFalse && ImageIsGray(image))
{
ping_color_type=(png_byte) PNG_COLOR_TYPE_GRAY;
image_matte=MagickFalse;
}
+
if ((image_info->type == UndefinedType ||
- image_info->type == OptimizeType ||
+ image_info->type == OptimizeType ||
image_info->type == GrayscaleMatteType) &&
image_matte == MagickTrue && ImageIsGray(image))
{
ping_color_type=(png_byte) PNG_COLOR_TYPE_GRAY_ALPHA;
image_matte=MagickTrue;
- }
+ }
}
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
"Selected PNG colortype=%d",ping_color_type);
if (ping_bit_depth < 8)
- {
- if (ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
- ping_color_type == PNG_COLOR_TYPE_RGB ||
- ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- ping_bit_depth=8;
- }
+ {
+ if (ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
+ ping_color_type == PNG_COLOR_TYPE_RGB ||
+ ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ ping_bit_depth=8;
+ }
if (ping_color_type == PNG_COLOR_TYPE_GRAY)
{
@@ -7007,6 +7443,7 @@
if (ImageIsMonochrome(image))
{
ping_bit_depth=1;
+
if (ping_bit_depth < (int)mng_info->write_png_depth)
ping_bit_depth = mng_info->write_png_depth;
}
@@ -7019,7 +7456,7 @@
if (image->colors == 0)
{
- /* DO SOMETHING */
+ /* DO SOMETHING */
(void) ThrowMagickException(&image->exception,
GetMagickModule(),CoderError,
"image has 0 colors", "`%s'","");
@@ -7028,6 +7465,7 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" SyncImage.2.");
+
while ((int) (one << ping_bit_depth) < (ssize_t) image_colors)
ping_bit_depth <<= 1;
@@ -7035,17 +7473,21 @@
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Number of colors: %.20g",(double) image_colors);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Tentative PNG bit depth: %d",ping_bit_depth);
}
+
if (mng_info->write_png_depth)
{
old_bit_depth=ping_bit_depth;
if (ping_bit_depth < (int)mng_info->write_png_depth)
{
ping_bit_depth = mng_info->write_png_depth;
+
if (ping_bit_depth > 8)
ping_bit_depth = 8;
+
if (ping_bit_depth != (int) old_bit_depth)
{
if (logging != MagickFalse)
@@ -7062,10 +7504,13 @@
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Tentative PNG color type: %.20g",(double) ping_color_type);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" image_info->type: %.20g",(double) image_info->type);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" image_depth: %.20g",(double) image_depth);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" ping_bit_depth: %.20g",(double) ping_bit_depth);
}
@@ -7082,6 +7527,7 @@
p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
if (p == (const PixelPacket *) NULL)
break;
+
for (x=(ssize_t) image->columns-1; x >= 0; x--)
{
if (IsGray(p) == MagickFalse)
@@ -7098,17 +7544,21 @@
for (y=0; y < (ssize_t) image->rows; y++)
{
p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+
if (p == (const PixelPacket *) NULL)
break;
+
for (x=(ssize_t) image->columns-1; x >= 0; x--)
{
if (p->opacity != OpaqueOpacity)
break;
p++;
}
+
if (x != 0)
break;
}
+
if ((y == (ssize_t) image->rows) && (x == (ssize_t) image->columns))
{
/*
@@ -7117,32 +7567,44 @@
image_matte=MagickFalse;
ping_color_type&=0x03;
}
+
else
{
unsigned int
mask;
mask=0xffff;
+
if (ping_bit_depth == 8)
mask=0x00ff;
+
if (ping_bit_depth == 4)
mask=0x000f;
+
if (ping_bit_depth == 2)
mask=0x0003;
+
if (ping_bit_depth == 1)
mask=0x0001;
+
ping_trans_color.red=(png_uint_16)
(ScaleQuantumToShort(GetRedPixelComponent(p)) & mask);
+
ping_trans_color.green=(png_uint_16)
(ScaleQuantumToShort(GetGreenPixelComponent(p)) & mask);
+
ping_trans_color.blue=(png_uint_16)
(ScaleQuantumToShort(GetBluePixelComponent(p)) & mask);
+
ping_trans_color.gray=(png_uint_16)
(ScaleQuantumToShort(PixelIntensityToQuantum(p)) & mask);
+
ping_trans_color.index=(png_byte)
(ScaleQuantumToChar((Quantum) (GetAlphaPixelComponent(p))));
+
ping_have_tRNS=MagickTrue;
}
+
if (ping_have_tRNS != MagickFalse)
{
/*
@@ -7154,23 +7616,27 @@
p=GetVirtualPixels(image,0,y,image->columns,1,
&image->exception);
x=0;
+
if (p == (const PixelPacket *) NULL)
break;
+
for (x=(ssize_t) image->columns-1; x >= 0; x--)
{
if (p->opacity != OpaqueOpacity)
{
if (IsPNGColorEqual(ping_trans_color,*p) == 0)
- {
- break; /* Can't use RGB + tRNS for multiple
- transparent colors. */
- }
+ {
+ break; /* Can't use RGB + tRNS for multiple
+ transparent colors. */
+ }
+
if (p->opacity != (Quantum) TransparentOpacity)
- {
- break; /* Can't use RGB + tRNS for
- semitransparency. */
- }
+ {
+ break; /* Can't use RGB + tRNS for
+ semitransparency. */
+ }
}
+
else
{
if (IsPNGColorEqual(ping_trans_color,*p))
@@ -7189,6 +7655,7 @@
if (ping_have_tRNS != MagickFalse)
{
ping_color_type &= 0x03; /* changes 4 or 6 to 0 or 2 */
+
if (image_depth == 8)
{
ping_trans_color.red&=0xff;
@@ -7199,27 +7666,35 @@
}
}
matte=image_matte;
+
if (ping_have_tRNS != MagickFalse)
image_matte=MagickFalse;
+
if ((mng_info->IsPalette) &&
mng_info->write_png_colortype-1 != PNG_COLOR_TYPE_PALETTE &&
ImageIsGray(image) && (!image_matte || image_depth >= 8))
{
size_t one=1;
+
if (image_matte != MagickFalse)
ping_color_type=PNG_COLOR_TYPE_GRAY_ALPHA;
+
else
{
ping_color_type=PNG_COLOR_TYPE_GRAY;
if (save_image_depth == 16 && image_depth == 8)
ping_trans_color.gray*=0x0101;
}
+
if (image_depth > MAGICKCORE_QUANTUM_DEPTH)
image_depth=MAGICKCORE_QUANTUM_DEPTH;
+
if (image_colors == 0 || image_colors-1 > MaxColormapSize)
image_colors=one << image_depth;
+
if (image_depth > 8)
ping_bit_depth=16;
+
else
{
ping_bit_depth=8;
@@ -7228,13 +7703,14 @@
if(!mng_info->write_png_depth)
{
ping_bit_depth=1;
+
while ((int) (one << ping_bit_depth)
< (ssize_t) image_colors)
ping_bit_depth <<= 1;
}
}
- else if (ping_color_type ==
- PNG_COLOR_TYPE_GRAY && image_colors < 17 &&
+ else if (ping_color_type ==
+ PNG_COLOR_TYPE_GRAY && image_colors < 17 &&
mng_info->IsPalette)
{
@@ -7253,22 +7729,28 @@
if ((intensity & 0x0f) != ((intensity & 0xf0) >> 4))
depth_4_ok=depth_2_ok=depth_1_ok=MagickFalse;
+
else if ((intensity & 0x03) != ((intensity & 0x0c) >> 2))
depth_2_ok=depth_1_ok=MagickFalse;
+
else if ((intensity & 0x01) != ((intensity & 0x02) >> 1))
depth_1_ok=MagickFalse;
}
if (depth_1_ok && mng_info->write_png_depth <= 1)
ping_bit_depth=1;
+
else if (depth_2_ok && mng_info->write_png_depth <= 2)
ping_bit_depth=2;
+
else if (depth_4_ok && mng_info->write_png_depth <= 4)
ping_bit_depth=4;
}
}
image_depth=ping_bit_depth;
}
+
else
+
if (mng_info->IsPalette)
{
number_colors=image_colors;
@@ -7279,13 +7761,16 @@
Set image palette.
*/
ping_color_type=(png_byte) PNG_COLOR_TYPE_PALETTE;
+
if (mng_info->have_write_global_plte && !matte)
{
png_set_PLTE(ping,ping_info,NULL,0);
+
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Setting up empty PLTE chunk");
}
+
else
{
if (CompressColormapTransFirst(image) == MagickFalse)
@@ -7293,18 +7778,22 @@
"MemoryAllocationFailed");
number_colors=image->colors;
image_colors=number_colors;
+
for (i=0; i < (ssize_t) number_colors; i++)
{
palette[i].red=ScaleQuantumToChar(image->colormap[i].red);
palette[i].green=ScaleQuantumToChar(image->colormap[i].green);
palette[i].blue=ScaleQuantumToChar(image->colormap[i].blue);
}
+
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Setting up PLTE chunk with %d colors",
(int) number_colors);
+
ping_have_PLTE=MagickTrue;
}
+
/* color_type is PNG_COLOR_TYPE_PALETTE */
if (!mng_info->write_png_depth)
{
@@ -7313,105 +7802,126 @@
ping_bit_depth=1;
one=1;
+
while ((one << ping_bit_depth) < number_colors)
ping_bit_depth <<= 1;
}
+
ping_num_trans=0;
+
if (matte)
- {
- ExceptionInfo
- *exception;
-
- register const PixelPacket
- *p;
-
- int
- trans[256];
-
- register const IndexPacket
- *packet_indexes;
-
- /*
- Identify which colormap entry is transparent.
- */
- assert(number_colors <= 256);
- for (i=0; i < (ssize_t) number_colors; i++)
- trans[i]=256;
- exception=(&image->exception);
- for (y=0; y < (ssize_t) image->rows; y++)
{
- p=GetVirtualPixels(image,0,y,image->columns,1,exception);
- if (p == (const PixelPacket *) NULL)
- break;
- packet_indexes=GetVirtualIndexQueue(image);
- for (x=0; x < (ssize_t) image->columns; x++)
- {
- if (p->opacity != OpaqueOpacity)
- {
- IndexPacket
- packet_index;
+ ExceptionInfo
+ *exception;
- packet_index=packet_indexes[x];
- if((size_t) packet_index >= number_colors)
- (void) LogMagickEvent(CoderEvent, GetMagickModule(),
- "packet_index=%d, number_colors=%d",
- (int) packet_index, (int) number_colors);
- assert((size_t) packet_index < number_colors);
- if (trans[(ssize_t) packet_index] != 256)
- {
- if (trans[(ssize_t) packet_index] != (png_byte) (255-
- ScaleQuantumToChar(GetOpacityPixelComponent(p))))
- {
- ping_color_type=(png_byte)
- PNG_COLOR_TYPE_RGB_ALPHA;
- break;
- }
- }
- trans[(ssize_t) packet_index]=(png_byte) (255-
- ScaleQuantumToChar(GetOpacityPixelComponent(p)));
- }
- p++;
- }
- if ((int) ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- {
- ping_num_trans=0;
- ping_have_tRNS=MagickFalse;
- ping_have_PLTE=MagickFalse;
- mng_info->IsPalette=MagickFalse;
- (void) SyncImage(image);
- if (logging)
- (void) LogMagickEvent(CoderEvent, GetMagickModule(),
- " Cannot write image as indexed PNG, writing RGBA.");
- break;
- }
- }
- if (ping_have_tRNS != MagickFalse)
- {
+ register const PixelPacket
+ *p;
+
+ int
+ trans[256];
+
+ register const IndexPacket
+ *packet_indexes;
+
+ /*
+ Identify which colormap entry is transparent.
+ */
+ assert(number_colors <= 256);
+
for (i=0; i < (ssize_t) number_colors; i++)
+ trans[i]=256;
+
+ exception=(&image->exception);
+
+ for (y=0; y < (ssize_t) image->rows; y++)
{
- if (trans[i] == 256)
- trans[i]=255;
- if (trans[i] != 255)
- ping_num_trans=(unsigned short) (i+1);
+ p=GetVirtualPixels(image,0,y,image->columns,1,exception);
+
+ if (p == (const PixelPacket *) NULL)
+ break;
+
+ packet_indexes=GetVirtualIndexQueue(image);
+
+ for (x=0; x < (ssize_t) image->columns; x++)
+ {
+ if (p->opacity != OpaqueOpacity)
+ {
+ IndexPacket
+ packet_index;
+
+ packet_index=packet_indexes[x];
+
+ if((size_t) packet_index >= number_colors)
+ (void) LogMagickEvent(CoderEvent, GetMagickModule(),
+ "packet_index=%d, number_colors=%d",
+ (int) packet_index, (int) number_colors);
+
+ assert((size_t) packet_index < number_colors);
+
+ if (trans[(ssize_t) packet_index] != 256)
+ {
+ if (trans[(ssize_t) packet_index] != (png_byte) (255-
+ ScaleQuantumToChar(GetOpacityPixelComponent(p))))
+ {
+ ping_color_type=(png_byte)
+ PNG_COLOR_TYPE_RGB_ALPHA;
+ break;
+ }
+ }
+
+ trans[(ssize_t) packet_index]=(png_byte) (255-
+ ScaleQuantumToChar(GetOpacityPixelComponent(p)));
+ }
+ p++;
+ }
+
+ if ((int) ping_color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ ping_num_trans=0;
+ ping_have_tRNS=MagickFalse;
+ ping_have_PLTE=MagickFalse;
+ mng_info->IsPalette=MagickFalse;
+ (void) SyncImage(image);
+
+ if (logging)
+ (void) LogMagickEvent(CoderEvent, GetMagickModule(),
+ " Cannot write image as indexed PNG, writing RGBA.");
+ break;
+ }
}
- }
- if (ping_num_trans == 0)
- ping_have_tRNS=MagickFalse;
- if (ping_have_tRNS == MagickFalse)
- ping_num_trans=0;
- if (ping_num_trans != 0)
+
+ if (ping_have_tRNS != MagickFalse)
{
for (i=0; i < (ssize_t) number_colors; i++)
- ping_trans_alpha[i]=(png_byte) trans[i];
- }
- }
+ {
+ if (trans[i] == 256)
+ trans[i]=255;
+ if (trans[i] != 255)
+ ping_num_trans=(unsigned short) (i+1);
+ }
+ }
+
+ if (ping_num_trans == 0)
+ ping_have_tRNS=MagickFalse;
+
+ if (ping_have_tRNS == MagickFalse)
+ ping_num_trans=0;
+
+ if (ping_num_trans != 0)
+ {
+ for (i=0; i < (ssize_t) number_colors; i++)
+ ping_trans_alpha[i]=(png_byte) trans[i];
+ }
+ }
}
}
+
else
{
if (image_depth < 8)
image_depth=8;
+
if ((save_image_depth == 16) && (image_depth == 8))
{
ping_trans_color.red*=0x0101;
@@ -7463,23 +7973,23 @@
ping_background.index=(png_byte) i;
if (logging)
- {
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Setting up bKGD chunk with index=%d",(int) i);
- }
-
- if (i < number_colors)
- {
- ping_have_bKGD = MagickTrue;
- if (logging)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " background =(%d,%d,%d)",
- (int) ping_background.red,
- (int) ping_background.green,
- (int) ping_background.blue);
+ " Setting up bKGD chunk with index=%d",(int) i);
}
- }
+
+ if (i < number_colors)
+ {
+ ping_have_bKGD = MagickTrue;
+ if (logging)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " background =(%d,%d,%d)",
+ (int) ping_background.red,
+ (int) ping_background.green,
+ (int) ping_background.blue);
+ }
+ }
else
ping_have_bKGD = MagickFalse;
@@ -7492,36 +8002,48 @@
Initialize compression level and filtering.
*/
if (logging != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Setting up deflate compression");
- if (logging != MagickFalse)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Compression buffer size: 32768");
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Setting up deflate compression");
+
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Compression buffer size: 32768");
+ }
+
png_set_compression_buffer_size(ping,32768L);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Compression mem level: 9");
+
png_set_compression_mem_level(ping, 9);
+
quality=image->quality == UndefinedCompressionQuality ? 75UL :
image->quality;
+
if (quality > 9)
{
int
level;
level=(int) MagickMin((ssize_t) quality/10,9);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Compression level: %d",level);
+
png_set_compression_level(ping,level);
}
+
else
{
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Compression strategy: Z_HUFFMAN_ONLY");
+
png_set_compression_strategy(ping, Z_HUFFMAN_ONLY);
}
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Setting up filtering");
@@ -7533,8 +8055,10 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Filter_type: PNG_INTRAPIXEL_DIFFERENCING");
+
ping_filter_method=PNG_INTRAPIXEL_DIFFERENCING;
}
+
else
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -7546,16 +8070,20 @@
if ((quality % 10) > 5)
base_filter=PNG_ALL_FILTERS;
+
else
if ((quality % 10) != 5)
base_filter=(int) quality % 10;
+
else
if (((int) ping_color_type == PNG_COLOR_TYPE_GRAY) ||
((int) ping_color_type == PNG_COLOR_TYPE_PALETTE) ||
(quality < 50))
base_filter=PNG_NO_FILTERS;
+
else
base_filter=PNG_ALL_FILTERS;
+
if (logging != MagickFalse)
{
if (base_filter == PNG_ALL_FILTERS)
@@ -7577,9 +8105,11 @@
#ifdef PNG_WRITE_iCCP_SUPPORTED
if ((LocaleCompare(name,"ICC") == 0) ||
(LocaleCompare(name,"ICM") == 0))
+
png_set_iCCP(ping,ping_info,(const png_charp) name,0,(png_charp)
GetStringInfoDatum(profile),
(png_uint_32) GetStringInfoLength(profile));
+
else
#endif
png_write_raw_profile(image_info,ping,ping_info,(unsigned char *)
@@ -7589,6 +8119,7 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Setting up text chunk with %s profile",name);
+
name=GetNextImageProfile(image);
}
@@ -7603,9 +8134,11 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Setting up sRGB chunk");
+
(void) png_set_sRGB(ping,ping_info,(
PNG_RenderingIntent_from_Magick_RenderingIntent(
image->rendering_intent)));
+
png_set_gAMA(ping,ping_info,0.45455);
}
if ((!mng_info->write_mng) || (!png_get_valid(ping,ping_info,PNG_INFO_sRGB)))
@@ -7664,7 +8197,7 @@
if (ping_bit_depth < 8)
ping_bit_depth=8;
}
-
+
if (mng_info->write_png_colortype-1 == PNG_COLOR_TYPE_GRAY_ALPHA)
if (ImageIsGray(image) == MagickFalse)
ping_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
@@ -7703,6 +8236,7 @@
/* Add an opaque matte channel */
image->matte = MagickTrue;
(void) SetImageOpacity(image,0);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Added an opaque matte channel");
@@ -7727,27 +8261,28 @@
if (ping_color_type == 3 && ping_have_PLTE != MagickFalse)
{
png_set_PLTE(ping,ping_info,palette,(int) number_colors);
+
if (logging)
- {
- for (i=0; i< number_colors; i++)
{
- if (ping_num_trans != 0)
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " PLTE[%d] + tRNS[%d] =(%d,%d,%d,%d)",
- (int) i,(int) i,
- (int) palette[i].red,
- (int) palette[i].green,
- (int) palette[i].blue,
- (int) ping_trans_alpha[i]);
- else
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " PLTE[%d] =(%d,%d,%d)",
- (int) i,
- (int) palette[i].red,
- (int) palette[i].green,
- (int) palette[i].blue);
+ for (i=0; i< number_colors; i++)
+ {
+ if (ping_num_trans != 0)
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " PLTE[%d] + tRNS[%d] =(%d,%d,%d,%d)",
+ (int) i,(int) i,
+ (int) palette[i].red,
+ (int) palette[i].green,
+ (int) palette[i].blue,
+ (int) ping_trans_alpha[i]);
+ else
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " PLTE[%d] =(%d,%d,%d)",
+ (int) i,
+ (int) palette[i].red,
+ (int) palette[i].green,
+ (int) palette[i].blue);
+ }
}
- }
}
if (ping_have_bKGD != MagickFalse)
@@ -7777,36 +8312,37 @@
png_write_info_before_PLTE(ping, ping_info);
if (ping_have_tRNS != MagickFalse && ping_color_type < 4)
- {
- if (logging)
{
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " Calling png_set_tRNS with num_trans=%d",ping_num_trans);
+ if (logging)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " Calling png_set_tRNS with num_trans=%d",ping_num_trans);
+ }
+
+ if (ping_color_type == 3)
+ (void) png_set_tRNS(ping, ping_info,
+ ping_trans_alpha,
+ ping_num_trans,
+ NULL);
+
+ else
+ {
+ (void) png_set_tRNS(ping, ping_info,
+ NULL,
+ 0,
+ &ping_trans_color);
+
+ if (logging)
+ {
+ (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+ " background =(%d,%d,%d)",
+ (int) ping_trans_color.red,
+ (int) ping_trans_color.green,
+ (int) ping_trans_color.blue);
+ }
+ }
}
- if (ping_color_type == 3)
- (void) png_set_tRNS(ping, ping_info,
- ping_trans_alpha,
- ping_num_trans,
- NULL);
-
- else
- {
- (void) png_set_tRNS(ping, ping_info,
- NULL,
- 0,
- &ping_trans_color);
- if (logging)
- {
- (void) LogMagickEvent(CoderEvent,GetMagickModule(),
- " background =(%d,%d,%d)",
- (int) ping_trans_color.red,
- (int) ping_trans_color.green,
- (int) ping_trans_color.blue);
- }
- }
- }
-
/* write any png-chunk-b profiles */
(void) png_write_chunk_from_profile(image,"PNG-chunk-b",(int) logging);
png_write_info(ping,ping_info);
@@ -7848,12 +8384,15 @@
case PNG_COLOR_TYPE_RGB:
rowbytes*=3;
break;
+
case PNG_COLOR_TYPE_GRAY_ALPHA:
rowbytes*=2;
break;
+
case PNG_COLOR_TYPE_RGBA:
rowbytes*=4;
break;
+
default:
break;
}
@@ -7861,13 +8400,16 @@
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing PNG image data");
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Allocating %.20g bytes of memory for pixels",(double) rowbytes);
}
png_pixels=(unsigned char *) AcquireQuantumMemory(rowbytes,
sizeof(*png_pixels));
+
if (png_pixels == (unsigned char *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+
/*
Initialize image scanlines.
*/
@@ -7904,7 +8446,7 @@
{
register const PixelPacket
*p;
-
+
quantum_info->depth=8;
for (pass=0; pass < num_passes; pass++)
{
@@ -7918,8 +8460,10 @@
" Writing row of pixels (0)");
p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+
if (p == (const PixelPacket *) NULL)
break;
+
if (mng_info->IsPalette)
{
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
@@ -7934,18 +8478,22 @@
>> (8-old_bit_depth));
}
}
+
else
{
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,RedQuantum,png_pixels,&image->exception);
}
+
if (mng_info->write_png_colortype-1 != PNG_COLOR_TYPE_PALETTE)
for (i=0; i < (ssize_t) image->columns; i++)
*(png_pixels+i)=(unsigned char) ((*(png_pixels+i) > 127) ?
255 : 0);
+
if (logging && y == 0)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing row of pixels (1)");
+
png_write_row(ping,png_pixels);
}
if (image->previous == (Image *) NULL)
@@ -7956,13 +8504,14 @@
}
}
}
+
else
for (pass=0; pass < num_passes; pass++)
{
register const PixelPacket
*p;
- if ((!mng_info->write_png8 && !mng_info->write_png24 &&
+ if ((!mng_info->write_png8 && !mng_info->write_png24 &&
!mng_info->write_png32) &&
(image_matte ||
(ping_bit_depth >= MAGICKCORE_QUANTUM_DEPTH)) &&
@@ -7971,33 +8520,41 @@
for (y=0; y < (ssize_t) image->rows; y++)
{
p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+
if (p == (const PixelPacket *) NULL)
break;
+
if (ping_color_type == PNG_COLOR_TYPE_GRAY)
{
if (mng_info->IsPalette)
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,GrayQuantum,png_pixels,&image->exception);
+
else
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,RedQuantum,png_pixels,&image->exception);
+
if (logging && y == 0)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing GRAY PNG pixels (2)");
}
+
else /* PNG_COLOR_TYPE_GRAY_ALPHA */
{
if (logging && y == 0)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing GRAY_ALPHA PNG pixels (2)");
+
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,GrayAlphaQuantum,png_pixels,&image->exception);
}
if (logging && y == 0)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing row of pixels (2)");
+
png_write_row(ping,png_pixels);
}
+
if (image->previous == (Image *) NULL)
{
status=SetImageProgress(image,LoadImageTag,pass,num_passes);
@@ -8014,36 +8571,46 @@
for (y=0; y < (ssize_t) image->rows; y++)
{
p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+
if (p == (const PixelPacket *) NULL)
break;
+
if (ping_color_type == PNG_COLOR_TYPE_GRAY)
{
if (image->storage_class == DirectClass)
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,RedQuantum,png_pixels,&image->exception);
+
else
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,GrayQuantum,png_pixels,&image->exception);
}
+
else if (ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,GrayAlphaQuantum,png_pixels,&image->exception);
+
if (logging && y == 0)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing GRAY_ALPHA PNG pixels (3)");
}
+
else if (image_matte != MagickFalse)
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,RGBAQuantum,png_pixels,&image->exception);
+
else
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,RGBQuantum,png_pixels,&image->exception);
+
if (logging && y == 0)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing row of pixels (3)");
+
png_write_row(ping,png_pixels);
}
+
else
/* not ((image_depth > 8) || (mng_info->write_png24 ||
mng_info->write_png32 ||
@@ -8055,6 +8622,7 @@
if (logging)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" pass %d, Image Is not GRAY or GRAY_ALPHA",pass);
+
quantum_info->depth=8;
image_depth=8;
}
@@ -8063,27 +8631,35 @@
if (logging && y == 0)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" pass %d, Image Is RGB, 16-bit GRAY, or GRAY_ALPHA",pass);
+
p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
+
if (p == (const PixelPacket *) NULL)
break;
+
if (ping_color_type == PNG_COLOR_TYPE_GRAY)
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,GrayQuantum,png_pixels,&image->exception);
+
else if (ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
if (logging && y == 0)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing GRAY_ALPHA PNG pixels (4)");
+
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,GrayAlphaQuantum,png_pixels,&image->exception);
}
+
else
(void) ExportQuantumPixels(image,(const CacheView *) NULL,
quantum_info,IndexQuantum,png_pixels,&image->exception);
+
if (logging && y <= 2)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing row of pixels (4)");
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" png_pixels[0]=%d,png_pixels[1]=%d",
(int)png_pixels[0],(int)png_pixels[1]);
@@ -8106,24 +8682,31 @@
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Wrote PNG image data");
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Width: %.20g",(double) ping_width);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Height: %.20g",(double) ping_height);
+
if (mng_info->write_png_depth)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Defined PNG:bit-depth: %d",mng_info->write_png_depth);
}
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" PNG bit-depth written: %d",ping_bit_depth);
+
if (mng_info->write_png_colortype)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Defined PNG:color-type: %d",mng_info->write_png_colortype-1);
}
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" PNG color-type written: %d",ping_color_type);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" PNG Interlace method: %d",ping_interlace_method);
}
@@ -8147,13 +8730,16 @@
text[0].compression=image_info->compression == NoCompression ||
(image_info->compression == UndefinedCompression &&
text[0].text_length < 128) ? -1 : 0;
+
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Setting up text chunk");
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" keyword: %s",text[0].key);
}
+
png_set_text(ping,ping_info,text,1);
png_free(ping,text);
}
@@ -8166,7 +8752,9 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Writing PNG end info");
+
png_write_end(ping,ping_info);
+
if (mng_info->need_fram && (int) image->dispose == BackgroundDispose)
{
if (mng_info->page.x || mng_info->page.y ||
@@ -8201,6 +8789,7 @@
mng_info->old_framing_mode=4;
mng_info->framing_mode=1;
}
+
else
mng_info->framing_mode=3;
}
@@ -8209,6 +8798,7 @@
(void) ThrowMagickException(&image->exception,GetMagickModule(),
CoderError,"Cannot convert GIF with disposal method 3 to MNG-LC",
"`%s'",image->filename);
+
image_depth=save_image_depth;
/* Save depth actually written */
@@ -8233,6 +8823,7 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit WriteOnePNGImage()");
+
return(MagickTrue);
/* End write one PNG image */
}
@@ -8286,7 +8877,7 @@
% o PNG32: An 8-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 255. The alpha
-% channel is present even if the image is fully opaque.
+% channel is present even if the image is fully opaque.
%
% o -define: For more precise control of the PNG output, you can use the
% Image options "png:bit-depth" and "png:color-type". These
@@ -8345,6 +8936,25 @@
%
% -profile PNG-chunk-b01:file01 -profile PNG-chunk-b02:file02
%
+% Set image_info->type=OptimizeType (new in version 5.4.0) to get the
+% following optimizations:
+%
+% o 16-bit depth is reduced to 8 if all pixels contain samples whose
+% high byte and low byte are identical.
+% o Opaque matte channel is removed.
+% o If matte channel is present but only one transparent color is
+% present, RGB+tRNS is written instead of RGBA
+% o Grayscale images are reduced to 1, 2, or 4 bit depth if
+% this can be done without loss.
+%
+% TO DO: Always do the above.
+%
+% As of version 6.6.5 the following optimizations are always done:
+%
+% o Palette is sorted to remove unused entries and to put a
+% transparent color first, if PNG_SORT_PALETTE is defined.
+% o Opaque matte channel is removed when writing an indexed PNG.
+%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
*/
static MagickBooleanType WritePNGImage(const ImageInfo *image_info,
@@ -8382,8 +8992,10 @@
*/
have_mng_structure=MagickFalse;
mng_info=(MngInfo *) AcquireMagickMemory(sizeof(MngInfo));
+
if (mng_info == (MngInfo *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+
/*
Initialize members of the MngInfo structure.
*/
@@ -8406,8 +9018,10 @@
#if 0 /* this does not work */
if (image->matte == MagickTrue)
(void) SetImageType(image,PaletteMatteType);
+
else
(void) SetImageType(image,PaletteType);
+
(void) SyncImage(image);
#endif
}
@@ -8417,10 +9031,13 @@
mng_info->write_png_colortype = /* 2 */ 3;
mng_info->write_png_depth = 8;
image->depth = 8;
+
if (image->matte == MagickTrue)
(void) SetImageType(image,TrueColorMatteType);
+
else
(void) SetImageType(image,TrueColorType);
+
(void) SyncImage(image);
}
@@ -8429,10 +9046,13 @@
mng_info->write_png_colortype = /* 6 */ 7;
mng_info->write_png_depth = 8;
image->depth = 8;
+
if (image->matte == MagickTrue)
(void) SetImageType(image,TrueColorMatteType);
+
else
(void) SetImageType(image,TrueColorType);
+
(void) SyncImage(image);
}
@@ -8441,14 +9061,19 @@
{
if (LocaleCompare(value,"1") == 0)
mng_info->write_png_depth = 1;
+
else if (LocaleCompare(value,"2") == 0)
mng_info->write_png_depth = 2;
+
else if (LocaleCompare(value,"4") == 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;
+
else
(void) ThrowMagickException(&image->exception,
GetMagickModule(),CoderWarning,
@@ -8459,20 +9084,27 @@
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" png:bit-depth=%d was defined.\n",mng_info->write_png_depth);
}
+
value=GetImageOption(image_info,"png:color-type");
+
if (value != (char *) NULL)
{
/* We must store colortype+1 because 0 is a valid colortype */
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;
+
else
(void) ThrowMagickException(&image->exception,
GetMagickModule(),CoderWarning,
@@ -8489,8 +9121,10 @@
(void) CloseBlob(image);
MngInfoFreeStruct(mng_info,&have_mng_structure);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit WritePNGImage()");
+
return(status);
}
@@ -8553,27 +9187,37 @@
if (transparent)
{
jng_color_type=14;
+
/* Create JPEG blob, image, and image_info */
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Creating jpeg_image_info for opacity.");
+
jpeg_image_info=(ImageInfo *) CloneImageInfo(image_info);
+
if (jpeg_image_info == (ImageInfo *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Creating jpeg_image.");
+
jpeg_image=CloneImage(image,0,0,MagickTrue,&image->exception);
+
if (jpeg_image == (Image *) NULL)
ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
+
(void) CopyMagickString(jpeg_image->magick,"JPEG",MaxTextExtent);
status=SeparateImageChannel(jpeg_image,OpacityChannel);
status=NegateImage(jpeg_image,MagickFalse);
jpeg_image->matte=MagickFalse;
+
if (jng_quality >= 1000)
jpeg_image_info->quality=jng_quality/1000;
+
else
jpeg_image_info->quality=jng_quality;
+
jpeg_image_info->type=GrayscaleType;
(void) SetImageType(jpeg_image,GrayscaleType);
(void) AcquireUniqueFilename(jpeg_image->filename);
@@ -8631,6 +9275,7 @@
blob=ImageToBlob(jpeg_image_info,jpeg_image,&length,
&image->exception);
jng_alpha_sample_depth=8;
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Successfully read jpeg_image into a blob, length=%.20g.",
@@ -8663,27 +9308,36 @@
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG width:%15lu",(unsigned long) image->columns);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG height:%14lu",(unsigned long) image->rows);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG color type:%10d",jng_color_type);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG sample depth:%8d",8);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG compression:%9d",8);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG interlace:%11d",0);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG alpha depth:%9d",jng_alpha_sample_depth);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG alpha compression:%3d",jng_alpha_compression_method);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG alpha filter:%8d",0);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" JNG alpha interlace:%5d",0);
}
- /* Write any JNG-chunk-b profiles */
+ /* Write any JNG-chunk-b profiles */
(void) png_write_chunk_from_profile(image,"JNG-chunk-b",(int) logging);
/*
@@ -8732,14 +9386,17 @@
(void) WriteBlobMSBULong(image,1L);
PNGType(chunk,mng_sRGB);
LogPNGChunk((int) logging,mng_sRGB,1L);
+
if (image->rendering_intent != UndefinedIntent)
chunk[4]=(unsigned char)
PNG_RenderingIntent_from_Magick_RenderingIntent(
(image->rendering_intent));
+
else
chunk[4]=(unsigned char)
PNG_RenderingIntent_from_Magick_RenderingIntent(
(PerceptualIntent));
+
(void) WriteBlob(image,5,chunk);
(void) WriteBlobMSBULong(image,crc32(0,chunk,5));
}
@@ -8757,6 +9414,7 @@
(void) WriteBlob(image,8,chunk);
(void) WriteBlobMSBULong(image,crc32(0,chunk,8));
}
+
if ((mng_info->equal_chrms == MagickFalse) &&
(image->chromaticity.red_primary.x != 0.0))
{
@@ -8785,6 +9443,7 @@
(void) WriteBlobMSBULong(image,crc32(0,chunk,36));
}
}
+
if (image->x_resolution && image->y_resolution && !mng_info->equal_physs)
{
/*
@@ -8797,20 +9456,26 @@
{
PNGLong(chunk+4,(png_uint_32)
(image->x_resolution*100.0/2.54+0.5));
+
PNGLong(chunk+8,(png_uint_32)
(image->y_resolution*100.0/2.54+0.5));
+
chunk[12]=1;
}
+
else
{
if (image->units == PixelsPerCentimeterResolution)
{
PNGLong(chunk+4,(png_uint_32)
(image->x_resolution*100.0+0.5));
+
PNGLong(chunk+8,(png_uint_32)
(image->y_resolution*100.0+0.5));
+
chunk[12]=1;
}
+
else
{
PNGLong(chunk+4,(png_uint_32) (image->x_resolution+0.5));
@@ -8872,6 +9537,7 @@
{
len=(*p<<24)|((*(p+1))<<16)|((*(p+2))<<8)|(*(p+3));
p+=4;
+
if (*(p)==73 && *(p+1)==68 && *(p+2)==65 && *(p+3)==84) /* IDAT */
{
/* Found an IDAT chunk. */
@@ -8881,6 +9547,7 @@
(void) WriteBlobMSBULong(image,
crc32(0,p,(uInt) len+4));
}
+
else
{
if (logging != MagickFalse)
@@ -8940,13 +9607,17 @@
if (jng_color_type == 8 || jng_color_type == 12)
jpeg_image_info->type=GrayscaleType;
+
jpeg_image_info->quality=jng_quality % 1000;
(void) CopyMagickString(jpeg_image_info->magick,"JPEG",MaxTextExtent);
(void) CopyMagickString(jpeg_image->magick,"JPEG",MaxTextExtent);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Creating blob.");
+
blob=ImageToBlob(jpeg_image_info,jpeg_image,&length,&image->exception);
+
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -8956,6 +9627,7 @@
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Write JDAT chunk, length=%.20g.",(double) length);
}
+
/* Write JDAT chunk(s) */
(void) WriteBlobMSBULong(image,(size_t) length);
PNGType(chunk,mng_JDAT);
@@ -8982,6 +9654,7 @@
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" exit WriteOneJNGImage()");
+
return(status);
}
@@ -9175,6 +9848,7 @@
if (mng_info->write_png8 || mng_info->write_png24 || mng_info->write_png32)
optimize=MagickFalse;
+
else
optimize=(image_info->type == OptimizeType || image_info->type ==
UndefinedType);
@@ -9187,14 +9861,18 @@
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Checking input image(s)");
+
if (optimize)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Optimize: TRUE");
+
else
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Optimize: FALSE");
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Image_info depth: %.20g",(double) image_info->depth);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Type: %d",image_info->type);
@@ -9203,26 +9881,34 @@
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Scene: %.20g",(double) scene++);
+
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Image depth: %.20g",(double) p->depth);
+
if (p->matte)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Matte: True");
+
else
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Matte: False");
+
if (p->storage_class == PseudoClass)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Storage class: PseudoClass");
+
else
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Storage class: DirectClass");
+
if (p->colors)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Number of colors: %.20g",(double) p->colors);
+
else
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Number of colors: unspecified");
+
if (mng_info->adjoin == MagickFalse)
break;
}
@@ -9240,6 +9926,7 @@
{
if (p->taint && p->storage_class == PseudoClass)
(void) SyncImage(p);
+
if (mng_info->adjoin == MagickFalse)
break;
}
@@ -9263,8 +9950,10 @@
if (p->colors <= 256)
{
p->colors=0;
+
if (p->matte != MagickFalse)
(void) SetImageType(p,PaletteMatteType);
+
else
(void) SetImageType(p,PaletteType);
}
@@ -9332,24 +10021,32 @@
{
if ((next_image->columns+next_image->page.x) > mng_info->page.width)
mng_info->page.width=next_image->columns+next_image->page.x;
+
if ((next_image->rows+next_image->page.y) > mng_info->page.height)
mng_info->page.height=next_image->rows+next_image->page.y;
}
+
if (next_image->page.x || next_image->page.y)
need_defi=MagickTrue;
+
if (next_image->matte)
need_matte=MagickTrue;
+
if ((int) next_image->dispose >= BackgroundDispose)
if (next_image->matte || 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;
+
if (next_image->iterations)
need_iterations=MagickTrue;
+
final_delay=next_image->delay;
+
if (final_delay != initial_delay || final_delay > 1UL*
next_image->ticks_per_second)
mng_info->need_fram=1;
+
#if defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) || \
defined(PNG_MNG_FEATURES_SUPPORTED)
/*
@@ -9357,6 +10054,7 @@
*/
if (image->matte != MagickFalse)
need_local_plte=MagickTrue;
+
if (need_local_plte == 0)
{
if (ImageIsGray(image) == MagickFalse)
@@ -9376,15 +10074,19 @@
next_image->background_color.blue !=
next_image->next->background_color.blue)
mng_info->equal_backgrounds=MagickFalse;
+
if (next_image->gamma != next_image->next->gamma)
mng_info->equal_gammas=MagickFalse;
+
if (next_image->rendering_intent !=
next_image->next->rendering_intent)
mng_info->equal_srgbs=MagickFalse;
+
if ((next_image->units != next_image->next->units) ||
(next_image->x_resolution != next_image->next->x_resolution) ||
(next_image->y_resolution != next_image->next->y_resolution))
mng_info->equal_physs=MagickFalse;
+
if (mng_info->equal_chrms)
{
if (next_image->chromaticity.red_primary.x !=
@@ -9422,6 +10124,7 @@
#endif
need_iterations=MagickFalse;
}
+
if (mng_info->need_fram == MagickFalse)
{
/*
@@ -9451,16 +10154,20 @@
mng_info->ticks_per_second=(png_uint_32) (image->ticks_per_second/final_delay);
if (final_delay > 50)
mng_info->ticks_per_second=2;
+
if (final_delay > 75)
mng_info->ticks_per_second=1;
+
if (final_delay > 125)
mng_info->need_fram=MagickTrue;
+
if (need_defi && final_delay > 2 && (final_delay != 4) &&
(final_delay != 5) && (final_delay != 10) && (final_delay != 20) &&
(final_delay != 25) && (final_delay != 50) && (final_delay !=
1UL*image->ticks_per_second))
mng_info->need_fram=MagickTrue; /* make it exact; cannot be VLC */
}
+
if (mng_info->need_fram != MagickFalse)
mng_info->ticks_per_second=1UL*image->ticks_per_second;
/*
@@ -9487,30 +10194,37 @@
{
if (need_defi || mng_info->need_fram || use_global_plte)
PNGLong(chunk+28,27L); /* simplicity=LC+JNG */
+
else
PNGLong(chunk+28,25L); /* simplicity=VLC+JNG */
}
+
else
{
if (need_defi || mng_info->need_fram || use_global_plte)
PNGLong(chunk+28,19L); /* simplicity=LC+JNG, no transparency */
+
else
PNGLong(chunk+28,17L); /* simplicity=VLC+JNG, no transparency */
}
}
+
else
{
if (need_matte)
{
if (need_defi || mng_info->need_fram || use_global_plte)
PNGLong(chunk+28,11L); /* simplicity=LC */
+
else
PNGLong(chunk+28,9L); /* simplicity=VLC */
}
+
else
{
if (need_defi || mng_info->need_fram || use_global_plte)
PNGLong(chunk+28,3L); /* simplicity=LC, no transparency */
+
else
PNGLong(chunk+28,1L); /* simplicity=VLC, no transparency */
}
@@ -9548,18 +10262,23 @@
chunk[5]=0; /* show last frame when done */
PNGLong(chunk+6,(png_uint_32) (mng_info->ticks_per_second*
final_delay/MagickMax(image->ticks_per_second,1)));
+
if (image->iterations == 0)
PNGLong(chunk+10,PNG_UINT_31_MAX);
+
else
PNGLong(chunk+10,(png_uint_32) image->iterations);
+
if (logging != MagickFalse)
{
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" TERM delay: %.20g",(double) (mng_info->ticks_per_second*
final_delay/MagickMax(image->ticks_per_second,1)));
+
if (image->iterations == 0)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" TERM iterations: %.20g",(double) PNG_UINT_31_MAX);
+
else
(void) LogMagickEvent(CoderEvent,GetMagickModule(),
" Image iterations: %.20g",(double) image->iterations);
@@ -9579,18 +10298,22 @@
(void) WriteBlobMSBULong(image,1L);
PNGType(chunk,mng_sRGB);
LogPNGChunk((int) logging,mng_sRGB,1L);
+
if (image->rendering_intent != UndefinedIntent)
chunk[4]=(unsigned char)
PNG_RenderingIntent_from_Magick_RenderingIntent(
(image->rendering_intent));
+
else
chunk[4]=(unsigned char)
PNG_RenderingIntent_from_Magick_RenderingIntent(
(PerceptualIntent));
+
(void) WriteBlob(image,5,chunk);
(void) WriteBlobMSBULong(image,crc32(0,chunk,5));
mng_info->have_write_global_srgb=MagickTrue;
}
+
else
{
if (image->gamma && mng_info->equal_gammas)
@@ -9642,24 +10365,31 @@
(void) WriteBlobMSBULong(image,9L);
PNGType(chunk,mng_pHYs);
LogPNGChunk((int) logging,mng_pHYs,9L);
+
if (image->units == PixelsPerInchResolution)
{
PNGLong(chunk+4,(png_uint_32)
(image->x_resolution*100.0/2.54+0.5));
+
PNGLong(chunk+8,(png_uint_32)
(image->y_resolution*100.0/2.54+0.5));
+
chunk[12]=1;
}
+
else
{
if (image->units == PixelsPerCentimeterResolution)
{
PNGLong(chunk+4,(png_uint_32)
(image->x_resolution*100.0+0.5));
+
PNGLong(chunk+8,(png_uint_32)
(image->y_resolution*100.0+0.5));
+
chunk[12]=1;
}
+
else
{
PNGLong(chunk+4,(png_uint_32) (image->x_resolution+0.5));
@@ -9716,12 +10446,14 @@
(void) WriteBlobMSBULong(image,data_length);
PNGType(chunk,mng_PLTE);
LogPNGChunk((int) logging,mng_PLTE,data_length);
+
for (i=0; i < (ssize_t) image->colors; i++)
{
chunk[4+i*3]=ScaleQuantumToChar(image->colormap[i].red) & 0xff;
chunk[5+i*3]=ScaleQuantumToChar(image->colormap[i].green) & 0xff;
chunk[6+i*3]=ScaleQuantumToChar(image->colormap[i].blue) & 0xff;
}
+
(void) WriteBlob(image,data_length+4,chunk);
(void) WriteBlobMSBULong(image,crc32(0,chunk,(uInt) (data_length+4)));
mng_info->have_write_global_plte=MagickTrue;
@@ -9766,12 +10498,14 @@
(void) WriteBlobMSBULong(image,data_length);
PNGType(chunk,mng_PLTE);
LogPNGChunk((int) logging,mng_PLTE,data_length);
+
for (i=0; i < (ssize_t) image->colors; i++)
{
chunk[4+i*3]=ScaleQuantumToChar(image->colormap[i].red);
chunk[5+i*3]=ScaleQuantumToChar(image->colormap[i].green);
chunk[6+i*3]=ScaleQuantumToChar(image->colormap[i].blue);
}
+
(void) WriteBlob(image,data_length+4,chunk);
(void) WriteBlobMSBULong(image,crc32(0,chunk,
(uInt) (data_length+4)));
@@ -9898,9 +10632,12 @@
image=SyncNextImageInList(image);
status=SetImageProgress(image,SaveImagesTag,scene++,
GetImageListLength(image));
+
if (status == MagickFalse)
break;
+
} while (mng_info->adjoin);
+
if (write_mng)
{
while (GetPreviousImageInList(image) != (Image *) NULL)
@@ -9919,8 +10656,10 @@
*/
(void) CloseBlob(image);
MngInfoFreeStruct(mng_info,&have_mng_structure);
+
if (logging != MagickFalse)
(void) LogMagickEvent(CoderEvent,GetMagickModule(),"exit WriteMNGImage()");
+
return(MagickTrue);
}
#else /* PNG_LIBPNG_VER > 10011 */
@@ -9930,6 +10669,7 @@
image=image;
printf("Your PNG library is too old: You have libpng-%s\n",
PNG_LIBPNG_VER_STRING);
+
ThrowBinaryException(CoderError,"PNG library is too old",
image_info->filename);
}