/* Set the action on getting a CRC error for an ancillary or critical chunk. */ void PNGAPI
png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
{
png_debug(1, "in png_set_crc_action");
if (png_ptr == NULL) return;
/* Tell libpng how we react to CRC errors in critical chunks */ switch (crit_action)
{ case PNG_CRC_NO_CHANGE: /* Leave setting as is */ break;
case PNG_CRC_WARN_USE: /* Warn/use data */
png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; break;
case PNG_CRC_QUIET_USE: /* Quiet/use data */
png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
PNG_FLAG_CRC_CRITICAL_IGNORE; break;
case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */
png_warning(png_ptr, "Can't discard critical data on CRC error"); /* FALLTHROUGH */ case PNG_CRC_ERROR_QUIT: /* Error/quit */
case PNG_CRC_DEFAULT: default:
png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; break;
}
/* Tell libpng how we react to CRC errors in ancillary chunks */ switch (ancil_action)
{ case PNG_CRC_NO_CHANGE: /* Leave setting as is */ break;
case PNG_CRC_WARN_USE: /* Warn/use data */
png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; break;
case PNG_CRC_QUIET_USE: /* Quiet/use data */
png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
PNG_FLAG_CRC_ANCILLARY_NOWARN; break;
case PNG_CRC_WARN_DISCARD: /* Warn/discard data */
case PNG_CRC_DEFAULT: default:
png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; break;
}
}
#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Is it OK to set a transformation now? Only if png_start_read_image or *png_read_update_infohavenotbeencalled.ItisnotnecessaryfortheIHDR *tohavebeenreadinallcases;theneed_IHDRparameterallowsforthis *checktoo.
*/ staticint
png_rtran_ok(png_structrp png_ptr, int need_IHDR)
{ if (png_ptr != NULL)
{ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
png_app_error(png_ptr, "invalid after png_start_read_image or png_read_update_info");
elseif (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_app_error(png_ptr, "invalid before the PNG header has been read");
else
{ /* Turn on failure to initialize correctly for all transforms. */
png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
return1; /* Ok */
}
}
return0; /* no png_error possible! */
} #endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED /* Handle alpha and tRNS via a background color */ void PNGFAPI
png_set_background_fixed(png_structrp png_ptr,
png_const_color_16p background_color, int background_gamma_code, int need_expand, png_fixed_point background_gamma)
{
png_debug(1, "in png_set_background_fixed");
if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL) return;
if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
{
png_warning(png_ptr, "Application must supply a known background gamma"); return;
}
/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the *onethatpngrtrandoesfirst(scale)happens.Thisisnecessarytoallowthe *TRANSFORMandAPIbehaviortobesomewhatconsistent,andit'ssimpler.
*/ #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED void PNGAPI
png_set_scale_16(png_structrp png_ptr)
{
png_debug(1, "in png_set_scale_16");
staticint
unsupported_gamma(png_structrp png_ptr, png_fixed_point gamma, int warn)
{ /* Validate a gamma value to ensure it is in a reasonable range. The value *isexpectedtobe1orgreater,butthisrangetestallowsforsome *viewingcorrectionvalues.TheintentistoweedouttheAPIusers *whomightusetheinverseofthegammavalueaccidentally! * *1.6.47:applythetestinpng_set_gammaaswellbutonlywarnandreturn *falseifitfires. * *TODO:1.8:makethisanapp_errorinpng_set_gammaaswell.
*/ if (gamma < PNG_LIB_GAMMA_MIN || gamma > PNG_LIB_GAMMA_MAX)
{ # define msg "gamma out of supported range" if (warn)
png_app_warning(png_ptr, msg); else
png_app_error(png_ptr, msg); return1; # undef msg
}
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED void PNGFAPI
png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
png_fixed_point output_gamma)
{
png_fixed_point file_gamma; int compose = 0;
png_debug(1, "in png_set_alpha_mode_fixed");
if (png_rtran_ok(png_ptr, 0) == 0) return;
output_gamma = translate_gamma_flags(output_gamma, 1/*screen*/); if (unsupported_gamma(png_ptr, output_gamma, 0/*error*/)) return;
/* The default file gamma is the inverse of the output gamma; the output *gammamaybechangedbelowsogetthefilevaluefirst.Thedefault_gamma *issethereandfromthesimplifiedAPI(whichusesadifferentalgorithm) *sodon'toverwriteasetvalue:
*/
file_gamma = png_ptr->default_gamma; if (file_gamma == 0)
{
file_gamma = png_reciprocal(output_gamma);
png_ptr->default_gamma = file_gamma;
}
/* There are really 8 possibilities here, composed of any combination *of: * *premultiplythecolorchannels *donotencodenon-opaquepixels *encodethealphaaswellasthecolorchannels * *Thedifferencesdisappeariftheinput/output('screen')gammais1.0, *becausethentheencodingisano-opandthereisonlythechoiceof *premultiplyingthecolorchannelsornot. * *png_set_alpha_modeandpng_set_backgroundinteractbecausebothuse *png_composetodothework.Callingbothisonlyusefulwhen *png_set_alpha_modeisusedtosetthedefaultmode-PNG_ALPHA_PNG-along *withadefaultgammavalue.OtherwisePNG_COMPOSEmustnotbeset.
*/ switch (mode)
{ case PNG_ALPHA_PNG: /* default: png standard */ /* No compose, but it may be set by png_set_background! */
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; break;
case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
compose = 1;
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; /* The output is linear: */
output_gamma = PNG_FP_1; break;
case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */
compose = 1;
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; /* output_gamma records the encoding of opaque pixels! */ break;
/* Set the screen gamma values: */
png_ptr->screen_gamma = output_gamma;
/* Finally, if pre-multiplying, set the background fields to achieve the *desiredresult.
*/ if (compose != 0)
{ /* And obtain alpha pre-multiplication by composing on black: */
memset(&png_ptr->background, 0, (sizeof png_ptr->background));
png_ptr->background_gamma = file_gamma; /* just in case */
png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
if ((png_ptr->transformations & PNG_COMPOSE) != 0)
png_error(png_ptr, "conflicting calls to set alpha mode and background");
#ifdef PNG_READ_QUANTIZE_SUPPORTED /* Dither file to 8-bit. Supply a palette, the current number *ofelementsinthepalette,themaximumnumberofelements *allowed,andahistogramifpossible.Ifthecurrentnumber *ofcolorsisgreaterthanthemaximumnumber,thepalettewillbe *modifiedtofitinthemaximumnumber."full_quantize"indicates *whetherweneedaquantizingcubesetupforRGBimages,orifwe *simplyarereducingthenumberofcolorsinapalettedimage.
*/
void PNGAPI
png_set_quantize(png_structrp png_ptr, png_colorp palette, int num_palette, int maximum_colors, png_const_uint_16p histogram, int full_quantize)
{
png_debug(1, "in png_set_quantize");
if (png_rtran_ok(png_ptr, 0) == 0) return;
if (palette == NULL) return;
png_ptr->transformations |= PNG_QUANTIZE;
if (full_quantize == 0)
{ int i;
/* Initialize the array to index colors. * *Ensurequantize_indexcanfit256elements(PNG_MAX_PALETTE_LENGTH) *ratherthannum_paletteelements.Thisistopreventbufferoverflows *causedbymalformedPNGfileswithout-of-rangepaletteindices. * *Becarefultoavoidleakingmemory.Applicationsareallowedtocall *thisfunctionmorethanonceperpng_struct.
*/
png_free(png_ptr, png_ptr->quantize_index);
png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
PNG_MAX_PALETTE_LENGTH); for (i = 0; i < PNG_MAX_PALETTE_LENGTH; i++)
png_ptr->quantize_index[i] = (png_byte)i;
}
if (num_palette > maximum_colors)
{ if (histogram != NULL)
{ /* This is easy enough, just throw out the least used colors. *Perhapsnotthebestsolution,butgoodenough.
*/
png_bytep quantize_sort; int i, j;
/* Initialize the local array to sort colors. */
quantize_sort = (png_bytep)png_malloc(png_ptr,
(png_alloc_size_t)num_palette); for (i = 0; i < num_palette; i++)
quantize_sort[i] = (png_byte)i;
/* Find the least used palette entries by starting a *bubblesort,andrunningituntilwehavesorted *outenoughcolors.Notethatwedon'tcareabout *sortingallthecolors,justfindingwhichare *leastused.
*/
for (i = num_palette - 1; i >= maximum_colors; i--)
{ int done; /* To stop early if the list is pre-sorted */
/* Swap the palette around, and set up a table, if necessary */ if (full_quantize != 0)
{
j = num_palette;
/* Put all the useful colors within the max, but don't *movetheothers.
*/ for (i = 0; i < maximum_colors; i++)
{ if ((int)quantize_sort[i] >= maximum_colors)
{ do
j--; while ((int)quantize_sort[j] >= maximum_colors);
/* Move all the used colors inside the max limit, and *developatranslationtable.
*/ for (i = 0; i < maximum_colors; i++)
{ /* Only move the colors we need to */ if ((int)quantize_sort[i] >= maximum_colors)
{
png_color tmp_color;
do
j--; while ((int)quantize_sort[j] >= maximum_colors);
tmp_color = palette[j];
palette[j] = palette[i];
palette[i] = tmp_color; /* Indicate where the color went */
png_ptr->quantize_index[j] = (png_byte)i;
png_ptr->quantize_index[i] = (png_byte)j;
}
}
/* Find closest color for those colors we are not using */ for (i = 0; i < num_palette; i++)
{ if ((int)png_ptr->quantize_index[i] >= maximum_colors)
{ int min_d, k, min_k, d_index;
/* Find the closest color to one we threw out */
d_index = png_ptr->quantize_index[i];
min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); for (k = 1, min_k = 0; k < maximum_colors; k++)
{ int d;
d = PNG_COLOR_DIST(palette[d_index], palette[k]);
if (d < min_d)
{
min_d = d;
min_k = k;
}
} /* Point to closest color */
png_ptr->quantize_index[i] = (png_byte)min_k;
}
}
}
png_free(png_ptr, quantize_sort);
} else
{ /* This is much harder to do simply (and quickly). Perhaps *weneedtogothroughamediancutroutine,butthose *don'talwaysbehavethemselveswithonlyafewcolors *asinput.Sowewilljustfindtheclosesttwocolors, *andthrowoutoneofthem(chosensomewhatrandomly). *[Wedon'tunderstandthisatall,soifsomeonewantsto *workonimprovingit,beourguest-AED,GRP]
*/ int i; int max_d; int num_new_palette;
png_dsortp t;
png_dsortpp hash;
for (i = 0; i < num_palette; i++)
{ int ir, ig, ib; int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
for (ir = 0; ir < num_red; ir++)
{ /* int dr = abs(ir - r); */ int dr = ((ir > r) ? ir - r : r - ir); int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
PNG_QUANTIZE_GREEN_BITS));
for (ig = 0; ig < num_green; ig++)
{ /* int dg = abs(ig - g); */ int dg = ((ig > g) ? ig - g : g - ig); int dt = dr + dg; int dm = ((dr > dg) ? dr : dg); int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
for (ib = 0; ib < num_blue; ib++)
{ int d_index = index_g | ib; /* int db = abs(ib - b); */ int db = ((ib > b) ? ib - b : b - ib); int dmax = ((dm > db) ? dm : db); int d = dmax + dt + db;
/* New in libpng-1.5.4 - reserve particular negative values as flags. */
scrn_gamma = translate_gamma_flags(scrn_gamma, 1/*screen*/);
file_gamma = translate_gamma_flags(file_gamma, 0/*file*/);
/* Checking the gamma values for being >0 was added in 1.5.4 along with the *premultipliedalphasupport;thisactuallyhidesanundocumentedfeature *ofthepreviousimplementationwhichallowedgammaprocessingtobe *disabledinbackgroundhandling.Thereisnoevidence(sofar)thatthis *wasbeingused;however,png_set_backgrounditselfacceptedandmuststill *accept'0'forthegammavalueittakes,becauseitisn'talwaysused. * *SincethisisanAPIchange(albeitaveryminoronethatremovesan *undocumentedAPIfeature)thefollowingcheckswereonlyenabledin *libpng-1.6.0.
*/ if (file_gamma <= 0)
png_app_error(png_ptr, "invalid file gamma in png_set_gamma"); if (scrn_gamma <= 0)
png_app_error(png_ptr, "invalid screen gamma in png_set_gamma");
if (unsupported_gamma(png_ptr, file_gamma, 1/*warn*/) ||
unsupported_gamma(png_ptr, scrn_gamma, 1/*warn*/)) return;
/* 1.6.47: png_struct::file_gamma and png_struct::screen_gamma are now only *writtenbythisAPI.ThisremovesdependenciesontheorderofAPIcalls *andallowsthecomplexgammacheckstobedelayeduntilneeded.
*/
png_ptr->file_gamma = file_gamma;
png_ptr->screen_gamma = scrn_gamma;
}
/* Expand grayscale images of less than 8-bit depth to 8 bits. */ void PNGAPI
png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
{
png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
if (png_rtran_ok(png_ptr, 0) == 0) return;
png_ptr->transformations |= PNG_EXPAND;
}
/* Expand tRNS chunks to alpha channels. */ void PNGAPI
png_set_tRNS_to_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_tRNS_to_alpha");
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED void PNGAPI
png_set_gray_to_rgb(png_structrp png_ptr)
{
png_debug(1, "in png_set_gray_to_rgb");
if (png_rtran_ok(png_ptr, 0) == 0) return;
/* Because rgb must be 8 bits or more: */
png_set_expand_gray_1_2_4_to_8(png_ptr);
png_ptr->transformations |= PNG_GRAY_TO_RGB;
} #endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED void PNGFAPI
png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
png_fixed_point red, png_fixed_point green)
{
png_debug(1, "in png_set_rgb_to_gray_fixed");
/* Need the IHDR here because of the check on color_type below. */ /* TODO: fix this */ if (png_rtran_ok(png_ptr, 1) == 0) return;
switch (error_action)
{ case PNG_ERROR_ACTION_NONE:
png_ptr->transformations |= PNG_RGB_TO_GRAY; break;
case PNG_ERROR_ACTION_WARN:
png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; break;
case PNG_ERROR_ACTION_ERROR:
png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; break;
default:
png_error(png_ptr, "invalid error action to rgb_to_gray");
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) #ifdef PNG_READ_EXPAND_SUPPORTED
png_ptr->transformations |= PNG_EXPAND; #else
{ /* Make this an error in 1.6 because otherwise the application may assume *thatitjustworkedandgetamemoryoverwrite.
*/
png_error(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
/* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
} #endif
{ if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
{
png_uint_16 red_int, green_int;
/* NOTE: this calculation does not round, but this behavior is retained *forconsistency;theinaccuracyisverysmall.Thecodeherealways *overwritesthecoefficients,regardlessofwhethertheyhavebeen *defaultedorsetalready.
*/
red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
elseif (red >= 0 && green >= 0)
png_app_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
}
}
#ifdef PNG_FLOATING_POINT_SUPPORTED /* Convert a RGB image to a grayscale of the same width. This allows us, *forexample,toconverta24bppRGBimageintoan8bppgrayscaleimage.
*/
void PNGAPI
png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, double green)
{
png_set_rgb_to_gray_fixed(png_ptr, error_action,
png_fixed(png_ptr, red, "rgb to gray red coefficient"),
png_fixed(png_ptr, green, "rgb to gray green coefficient"));
} #endif/* FLOATING POINT */
#ifdef PNG_READ_TRANSFORMS_SUPPORTED #ifdef PNG_READ_GAMMA_SUPPORTED /* In the case of gamma transformations only do transformations on images where *the[file]gammaandscreen_gammaarenotclosereciprocals,otherwiseit *slowsthingsdownslightly,andalsoneedlesslyintroducessmallerrors.
*/ staticint/* PRIVATE */
png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
{ /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma *correctionasadifferenceoftheoveralltransformfrom1.0 * *Wewanttocomparethethresholdwiths*f-1,ifweget *overflowhereitisbecauseofwackygammavaluessowe *turnonprocessinganyway.
*/
png_fixed_point gtest; return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) ||
png_gamma_significant(gtest);
} #endif
/* Initialize everything needed for the read. This includes modifying *thepalette.
*/
/* For the moment 'png_init_palette_transformations' and *'png_init_rgb_transformations'onlydosomeflagcancelingoptimizations. *Theintentisthatthesetworoutinesshouldhavepaletteorrgboperations *extractedfrom'png_init_read_transformations'.
*/ staticvoid/* PRIVATE */
png_init_palette_transformations(png_structrp png_ptr)
{ /* Called to handle the (input) palette case. In png_do_read_transformations *thefirststepistoexpandthepaletteifrequested,sothiscodemust *takecaretoonlymakechangesthatareinvariantwithrespecttothe *paletteexpansion,oronlydothemifthereisnoexpansion. * *STRIP_ALPHAhasalreadybeenhandledinthecaller(bysettingnum_trans *to0.)
*/ int input_has_alpha = 0; int input_has_transparency = 0;
if (png_ptr->num_trans > 0)
{ int i;
/* Ignore if all the entries are opaque (unlikely!) */ for (i=0; i<png_ptr->num_trans; ++i)
{ if (png_ptr->trans_alpha[i] == 255) continue; elseif (png_ptr->trans_alpha[i] == 0)
input_has_transparency = 1; else
{
input_has_transparency = 1;
input_has_alpha = 1; break;
}
}
}
/* If no alpha we can optimize. */ if (input_has_alpha == 0)
{ /* Any alpha means background and associative alpha processing is *required,howeverifthealphais0or1throughoutOPTIMIZE_ALPHA *andENCODE_ALPHAareirrelevant.
*/
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
if (input_has_transparency == 0)
png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
}
#ifdefined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) /* png_set_background handling - deals with the complexity of whether the *backgroundcolorisinthefileformatorthescreenformatinthecase *wherean'expand'willhappen.
*/
/* The following code cannot be entered in the alpha pre-multiplication case *becausePNG_BACKGROUND_EXPANDiscancelledbelow.
*/ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
(png_ptr->transformations & PNG_EXPAND) != 0)
{
{
png_ptr->background.red =
png_ptr->palette[png_ptr->background.index].red;
png_ptr->background.green =
png_ptr->palette[png_ptr->background.index].green;
png_ptr->background.blue =
png_ptr->palette[png_ptr->background.index].blue;
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
{ if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
{ /* Invert the alpha channel (in tRNS) unless the pixels are *goingtobeexpanded,inwhichcaseleaveitforlater
*/ int i, istop = png_ptr->num_trans;
for (i = 0; i < istop; i++)
png_ptr->trans_alpha[i] =
(png_byte)(255 - png_ptr->trans_alpha[i]);
}
} #endif/* READ_INVERT_ALPHA */
}
} /* background expand and (therefore) no alpha association. */ #endif/* READ_EXPAND && READ_BACKGROUND */
}
staticvoid/* PRIVATE */
png_init_rgb_transformations(png_structrp png_ptr)
{ /* Added to libpng-1.5.4: check the color type to determine whether there *isanyalphaortransparencyintheimageandsimplycancelthe *backgroundandalphamodestuffifthereisn't.
*/ int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; int input_has_transparency = png_ptr->num_trans > 0;
/* If no alpha we can optimize. */ if (input_has_alpha == 0)
{ /* Any alpha means background and associative alpha processing is *required,howeverifthealphais0or1throughoutOPTIMIZE_ALPHA *andENCODE_ALPHAareirrelevant.
*/ # ifdef PNG_READ_ALPHA_MODE_SUPPORTED
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; # endif
if (input_has_transparency == 0)
png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
}
#ifdefined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) /* png_set_background handling - deals with the complexity of whether the *backgroundcolorisinthefileformatorthescreenformatinthecase *wherean'expand'willhappen.
*/
/* The following code cannot be entered in the alpha pre-multiplication case *becausePNG_BACKGROUND_EXPANDiscancelledbelow.
*/ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
(png_ptr->transformations & PNG_EXPAND) != 0 &&
(png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* i.e., GRAY or GRAY_ALPHA */
{
{ /* Expand background and tRNS chunks */ int gray = png_ptr->background.gray; int trans_gray = png_ptr->trans_color.gray;
/* The file gamma is determined by these precedence rules, in this order *(i.e.usethefirstvaluefound): * *png_set_gamma;png_struct::file_gammmaifnotzero,then: *png_struct::chunk_gammaifnot0(determinedthePNGv3rules),then: *png_set_gamma;1/png_struct::screen_gammaifnotzero * *0(i.e.donogammahandling)
*/
file_gamma = png_ptr->file_gamma; if (file_gamma != 0) return file_gamma;
file_gamma = png_ptr->chunk_gamma; if (file_gamma != 0) return file_gamma;
file_gamma = png_ptr->default_gamma; if (file_gamma != 0) return file_gamma;
/* If png_reciprocal overflows, it returns 0, indicating to the caller that *thereisnousablefilegamma.(Thechecksaddedtopng_set_gammaand *png_set_alpha_modeshouldpreventascreen_gammawhichwouldoverflow.)
*/ if (png_ptr->screen_gamma != 0)
file_gamma = png_reciprocal(png_ptr->screen_gamma);
return file_gamma;
}
staticint
png_init_gamma_values(png_structrp png_ptr)
{ /* The following temporary indicates if overall gamma correction is *required.
*/ int gamma_correction = 0;
png_fixed_point file_gamma, screen_gamma;
/* Resolve the file_gamma. See above: if png_ptr::screen_gamma is set *file_gammawillalwaysbesethere:
*/
file_gamma = png_resolve_file_gamma(png_ptr);
screen_gamma = png_ptr->screen_gamma;
if (file_gamma > 0) /* file has been set */
{ if (screen_gamma > 0) /* screen set too */
gamma_correction = png_gamma_threshold(file_gamma, screen_gamma);
else /* Assume the output matches the input; a long time default behavior *oflibpng,althoughthestandardhasnothingtosayaboutthis.
*/
screen_gamma = png_reciprocal(file_gamma);
}
void/* PRIVATE */
png_init_read_transformations(png_structrp png_ptr)
{
png_debug(1, "in png_init_read_transformations");
/* This internal function is called from png_read_start_row in pngrutil.c *anditiscalledbeforethe'rowbytes'calculationisdone,sothecode *inherecanchangeorupdatethetransformationsflags. * *FirstdoupdatesthatdonotdependonthedetailsofthePNGimagedata *beingprocessed.
*/
#ifdef PNG_READ_GAMMA_SUPPORTED /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds *png_set_alpha_modeandthisisanothersourceforadefaultfilegammaso *thetestneedstobeperformedlater-here.Inadditionpriorto1.5.4 *thetestswererepeatedforthePALETTEcolortypehere-thisisno *longernecessary(anddoesn'tseemtohavebeennecessarybefore.) * *PNGv3:thenewmandatoryprecedence/priorityrulesforcolourspacechunks *arehandledhere(bycallingtheabovefunction). * *Turnthegammatransformationonoroffasappropriate.Noticethat *PNG_GAMMAjustreferstothefile->screencorrection.Alphacomposition *mayindependentlycausegammacorrectionbecauseitneedslineardata *(e.g.ifthefilehasagAMAchunkbutthescreengammahasn'tbeen *specified.)Inanycasethisflagmaygetturnedoffinthecode *immediatelybelowifthetransformcanbehandledoutsidetherowloop.
*/ if (png_init_gamma_values(png_ptr) != 0)
png_ptr->transformations |= PNG_GAMMA;
/* Certain transformations have the effect of preventing other *transformationsthathappenafterwardinpng_do_read_transformations; *resolvetheinterdependencieshere.Fromthecodeof *png_do_read_transformationstheorderis: * *1)PNG_EXPAND(includingPNG_EXPAND_tRNS) *2)PNG_STRIP_ALPHA(ifnocompose) *3)PNG_RGB_TO_GRAY *4)PNG_GRAY_TO_RGBiff!PNG_BACKGROUND_IS_GRAY *5)PNG_COMPOSE *6)PNG_GAMMA *7)PNG_STRIP_ALPHA(ifcompose) *8)PNG_ENCODE_ALPHA *9)PNG_SCALE_16_TO_8 *10)PNG_16_TO_8 *11)PNG_QUANTIZE(convertstopalette) *12)PNG_EXPAND_16 *13)PNG_GRAY_TO_RGBiffPNG_BACKGROUND_IS_GRAY *14)PNG_INVERT_MONO *15)PNG_INVERT_ALPHA *16)PNG_SHIFT *17)PNG_PACK *18)PNG_BGR *19)PNG_PACKSWAP *20)PNG_FILLER(includesPNG_ADD_ALPHA) *21)PNG_SWAP_ALPHA *22)PNG_SWAP_BYTES *23)PNG_USER_TRANSFORM[mustbelast]
*/ #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
(png_ptr->transformations & PNG_COMPOSE) == 0)
{ /* Stripping the alpha channel happens immediately after the 'expand' *transformations,beforeallothertransformation,soitcancelsout *thealphahandling.Ithasthesideeffectnegatingtheeffectof *PNG_EXPAND_tRNStoo:
*/
png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
PNG_EXPAND_tRNS);
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
/* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen *sotransparencyinformationwouldremainjustsolongasitwasn't *expanded.ThisproducesunexpectedAPIchangesifthesetofthings *thatdoPNG_EXPAND_tRNSchanges(perfectlypossiblegiventhe *documentation-whichsaysaskforwhatyouwant,acceptwhatyou *get.)Thismakesthebehaviorconsistentfrom1.5.4:
*/
png_ptr->num_trans = 0;
} #endif/* STRIP_ALPHA supported, no COMPOSE */
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA *settingswillhavenoeffect.
*/ if (png_gamma_significant(png_ptr->screen_gamma) == 0)
{
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
} #endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED /* Make sure the coefficients for the rgb to gray conversion are set *appropriately.
*/ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
png_set_rgb_coefficients(png_ptr); #endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED #ifdefined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) /* Detect gray background and attempt to enable optimization for *gray-->RGBcase. * *Note:ifPNG_BACKGROUND_EXPANDissetandcolor_typeiseitherRGBor *RGB_ALPHA(inwhichcaseneed_expandissuperfluousanyway),the *backgroundcolormightactuallybegrayyetnotbeflaggedassuch. *Thisisnotaproblemforthecurrentcode,whichuses *PNG_BACKGROUND_IS_GRAYonlytodecidewhentodothe *png_do_gray_to_rgb()transformation. * *TODO:thiscodeneedstoberevisedtoavoidthecomplexityand *interdependencies.Thecolortypeofthebackgroundshouldberecordedin *png_set_background,alongwiththebitdepth,thenthecodehasarecord *ofexactlywhatcolorspacethebackgroundiscurrentlyin.
*/ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
{ /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if *thefilewasgrayscalethebackgroundvalueisgray.
*/ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
}
/* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations *canbeperformeddirectlyonthepalette,andsome(suchasrgbtogray) *canbeoptimizedinsidethepalette.Thisisparticularlytrueofthe *composite(backgroundandalpha)stuff,whichcanbeprettymuchalldone *inthepaletteeveniftheresultisexpandedtoRGBorgrayafterward. * *NOTE:thisisNotYetImplemented,thecodebehavesasin1.5.1and *earlierandthepalettestuffisactuallyhandledonthefirstrow.This *leadstothereportedbugthatthepalettereturnedbypng_get_PLTEisnot *updated.
*/ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
png_init_palette_transformations(png_ptr);
else
png_init_rgb_transformations(png_ptr);
#ifdefined(PNG_READ_BACKGROUND_SUPPORTED) && \ defined(PNG_READ_EXPAND_16_SUPPORTED) if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
(png_ptr->transformations & PNG_COMPOSE) != 0 &&
(png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
png_ptr->bit_depth != 16)
{ /* TODO: fix this. Because the expand_16 operation is after the compose *handlingthebackgroundcolormustbe8,not16,bitsdeep,butthe *applicationwillsupplya16-bitvaluesoreduceithere. * *ThePNG_BACKGROUND_EXPANDcodeabovedoesnotexpandto16bitsat *present,sothatcaseisok(untildo_expand_16ismoved.) * *NOTE:thisdiscardsthelow16bitsoftheusersuppliedbackground *color,butuntilexpand_16worksproperlythereisnochoice!
*/ # define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
CHOP(png_ptr->background.red);
CHOP(png_ptr->background.green);
CHOP(png_ptr->background.blue);
CHOP(png_ptr->background.gray); # undef CHOP
} #endif/* READ_BACKGROUND && READ_EXPAND_16 */
#ifdefined(PNG_READ_BACKGROUND_SUPPORTED) && \
(defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
(png_ptr->transformations & PNG_COMPOSE) != 0 &&
(png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
png_ptr->bit_depth == 16)
{ /* On the other hand, if a 16-bit file is to be reduced to 8-bits per *componentthiswillalsohappenafterPNG_COMPOSEandsothebackground *colormustbepre-expandedhere. * *TODO:fixthistoo.
*/
png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
png_ptr->background.green =
(png_uint_16)(png_ptr->background.green * 257);
png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
} #endif
/* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the *backgroundsupport(seethecommentsinscripts/pnglibconf.dfa),this *allowspre-multiplicationofthealphachanneltobeimplementedas *compositingonblack.Thisisprobablysub-optimalandhasbeendonein *1.5.4betassimplytoenableexternalcritiqueandtesting(i.e.to *implementthenewAPIquickly,withoutlotsofinternalchanges.)
*/
/* This needs to change - in the palette image case a whole set of tables are *builtwhenitwouldbequickertojustcalculatethecorrectvaluefor *eachpaletteentrydirectly.Also,thetestistootricky-whycheck *PNG_RGB_TO_GRAYifPNG_GAMMAisnotset?Theanswerseemstobethat *PNG_GAMMAiscancelledevenifthegammaisknown?Thetestexcludesthe *PNG_COMPOSEcase,soapparentlyifthereisno*overall*gammacorrection *thegammatableswillnotbebuiltevenifcompositionisrequiredona *gammaencodedvalue. * *In1.5.4thisisaddressedbelowbyanadditionalcheckontheindividual *filegamma-ifitisnot1.0bothRGB_TO_GRAYandCOMPOSEneedthe *tables.
*/ if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
(png_gamma_significant(png_ptr->file_gamma) != 0 ||
png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
((png_ptr->transformations & PNG_COMPOSE) != 0 &&
(png_gamma_significant(png_ptr->file_gamma) != 0 ||
png_gamma_significant(png_ptr->screen_gamma) != 0 # ifdef PNG_READ_BACKGROUND_SUPPORTED
|| (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
png_gamma_significant(png_ptr->background_gamma) != 0) # endif
)) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
png_gamma_significant(png_ptr->screen_gamma) != 0))
{
png_build_gamma_table(png_ptr, png_ptr->bit_depth);
#ifdef PNG_READ_BACKGROUND_SUPPORTED if ((png_ptr->transformations & PNG_COMPOSE) != 0)
{ /* Issue a warning about this combination: because RGB_TO_GRAY is *optimizedtodothegammatransformifpresentyetdo_backgroundhas *todothesamethingifbothoptionsareseta *double-gamma-correctionhappens.Thisistrueinallversionsof *libpngtodate.
*/ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
png_warning(png_ptr, "libpng does not support gamma+background+rgb_to_gray");
if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
{ /* We don't get to here unless there is a tRNS chunk with non-opaque *entries-seethecheckingcodeatthestartofthisfunction.
*/
png_color back, back_1;
png_colorp palette = png_ptr->palette; int num_palette = png_ptr->num_palette; int i; if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
{
/* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ else/* color_type != PNG_COLOR_TYPE_PALETTE */
{ int gs_sig, g_sig;
png_fixed_point g = PNG_FP_1; /* Correction to linear */
png_fixed_point gs = PNG_FP_1; /* Correction to screen */
switch (png_ptr->background_gamma_type)
{ case PNG_BACKGROUND_GAMMA_SCREEN:
g = png_ptr->screen_gamma; /* gs = PNG_FP_1; */ break;
case PNG_BACKGROUND_GAMMA_FILE:
g = png_reciprocal(png_ptr->file_gamma);
gs = png_reciprocal2(png_ptr->file_gamma,
png_ptr->screen_gamma); break;
case PNG_BACKGROUND_GAMMA_UNIQUE:
g = png_reciprocal(png_ptr->background_gamma);
gs = png_reciprocal2(png_ptr->background_gamma,
png_ptr->screen_gamma); break;
/* The background is now in screen gamma: */
png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
} /* color_type != PNG_COLOR_TYPE_PALETTE */
}/* png_ptr->transformations & PNG_BACKGROUND */
else /* Transformation does not include PNG_BACKGROUND */ #endif/* READ_BACKGROUND */ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
&& ((png_ptr->transformations & PNG_EXPAND) == 0 ||
(png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) #endif
)
{
png_colorp palette = png_ptr->palette; int num_palette = png_ptr->num_palette; int i;
/* NOTE: there are other transformations that should probably be in *heretoo.
*/ for (i = 0; i < num_palette; i++)
{
palette[i].red = png_ptr->gamma_table[palette[i].red];
palette[i].green = png_ptr->gamma_table[palette[i].green];
palette[i].blue = png_ptr->gamma_table[palette[i].blue];
}
for (i = 0; i < istop; i++)
{ if (png_ptr->trans_alpha[i] == 0)
{
palette[i] = back;
}
elseif (png_ptr->trans_alpha[i] != 0xff)
{ /* The png_composite() macro is defined in png.h */
png_composite(palette[i].red, palette[i].red,
png_ptr->trans_alpha[i], back.red);
#ifdef PNG_READ_SHIFT_SUPPORTED if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
(png_ptr->transformations & PNG_EXPAND) == 0 &&
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
{ int i; int istop = png_ptr->num_palette; int shift = 8 - png_ptr->sig_bit.red;
png_ptr->transformations &= ~PNG_SHIFT;
/* significant bits can be in the range 1 to 7 for a meaningful result, if *thenumberofsignificantbitsis0thennoshiftisdone(thisisan *errorconditionwhichissilentlyignored.)
*/ if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
{ int component = png_ptr->palette[i].red;
/* Modify the info structure to reflect the transformations. The *infoshouldbeupdatedsoaPNGfilecouldbewrittenwithit, *assumingthetransformationsresultinvalidPNGdata.
*/ void/* PRIVATE */
png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
{
png_debug(1, "in png_read_transform_info");
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
info_ptr->palette != NULL && png_ptr->palette != NULL)
{ /* Sync info_ptr->palette with png_ptr->palette, which may *havebeenmodifiedbypng_init_read_transformations *(e.g.forgammacorrectionorbackgroundcompositing).
*/
memcpy(info_ptr->palette, png_ptr->palette,
PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)));
}
#ifdef PNG_READ_EXPAND_SUPPORTED if ((png_ptr->transformations & PNG_EXPAND) != 0)
{ if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{ /* This check must match what actually happens in *png_do_expand_palette;ifiteverchecksthetRNSchunktoseeif *itisallopaquewemustdothesame(atpresentitdoesnot.)
*/ if (png_ptr->num_trans > 0)
info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
else
info_ptr->color_type = PNG_COLOR_TYPE_RGB;
info_ptr->bit_depth = 8;
info_ptr->num_trans = 0;
if (png_ptr->palette == NULL)
png_error (png_ptr, "Palette is NULL in indexed image");
} else
{ if (png_ptr->num_trans != 0)
{ if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
} if (info_ptr->bit_depth < 8)
info_ptr->bit_depth = 8;
info_ptr->num_trans = 0;
}
} #endif
#ifdefined(PNG_READ_BACKGROUND_SUPPORTED) ||\ defined(PNG_READ_ALPHA_MODE_SUPPORTED) /* The following is almost certainly wrong unless the background value is in *thescreenspace!
*/ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
info_ptr->background = png_ptr->background; #endif
#ifdef PNG_READ_GAMMA_SUPPORTED /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), *howeveritseemsthatthecodeinpng_init_read_transformations,whichhas *beencalledbeforethisfrompng_read_update_info->png_read_start_row *sometimesdoesthegammatransformandcancelstheflag. * *TODO:thisisconfusing.Itonlychangestheresultofpng_get_gAMAand, *yes,itdoesreturnthevaluethatthetransformeddataeffectivelyhas *butdoesanyappreallyunderstandthis?
*/
info_ptr->gamma = png_ptr->file_gamma; #endif
# else /* No 16-bit support: force chopping 16-bit input down to 8, in this case *theappprogramcanchoseifbothAPIsareavailablebysettingthe *correctscalingtouse.
*/ # ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED /* For compatibility with previous versions use the strip method by *default.ThiscodeworksbecauseifPNG_SCALE_16_TO_8isalready *setthecodebelowwilldothatinpreferencetothechop.
*/
png_ptr->transformations |= PNG_16_TO_8;
info_ptr->bit_depth = 8; # else
/* Adding in 1.5.4: cache the above value in png_struct so that we can later *checkinpng_rowbytesthattheuserbufferwon'tgetoverwritten.Note *thatthefieldisnotalwaysset-ifpng_read_update_infoisn'tcalled *theapplicationhastoeithernotdoanytransformsorgetthecalculation *rightitself.
*/
png_ptr->info_rowbytes = info_ptr->rowbytes;
#ifndef PNG_READ_EXPAND_SUPPORTED if (png_ptr != NULL) return; #endif
}
#ifdef PNG_READ_PACK_SUPPORTED /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, *withoutchangingtheactualvalues.Thus,ifyouhadarowwith *abitdepthof1,youwouldendupwithbytesthatonlycontained *thenumbers0or1.Ifyouwouldrathertheycontain0and255,use *png_do_shift()afterthis.
*/ staticvoid
png_do_unpack(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_unpack");
if (row_info->bit_depth < 8)
{
png_uint_32 i;
png_uint_32 row_width=row_info->width;
for (c = have_shift = 0; c < channels; ++c)
{ /* A shift of more than the bit depth is an error condition but it *getsignoredhere.
*/ if (shift[c] <= 0 || shift[c] >= bit_depth)
shift[c] = 0;
else
have_shift = 1;
}
if (have_shift == 0) return;
}
switch (bit_depth)
{ default: /* Must be 1bpp gray: should not be here! */ /* NOTREACHED */ break;
case2: /* Must be 2bpp gray */ /* assert(channels == 1 && shift[0] == 1) */
{
png_bytep bp = row;
png_bytep bp_end = bp + row_info->rowbytes;
while (bp < bp_end)
{ int b = (*bp >> 1) & 0x55;
*bp++ = (png_byte)b;
} break;
}
case4: /* Must be 4bpp gray */ /* assert(channels == 1) */
{
png_bytep bp = row;
png_bytep bp_end = bp + row_info->rowbytes; int gray_shift = shift[0]; int mask = 0xf >> gray_shift;
mask |= mask << 4;
while (bp < bp_end)
{ int b = (*bp >> gray_shift) & mask;
*bp++ = (png_byte)b;
} break;
}
case8: /* Single byte components, G, GA, RGB, RGBA */
{
png_bytep bp = row;
png_bytep bp_end = bp + row_info->rowbytes; int channel = 0;
while (bp < bp_end)
{ int b = *bp >> shift[channel]; if (++channel >= channels)
channel = 0;
*bp++ = (png_byte)b;
} break;
}
#ifdef PNG_READ_16BIT_SUPPORTED case16: /* Double byte components, G, GA, RGB, RGBA */
{
png_bytep bp = row;
png_bytep bp_end = bp + row_info->rowbytes; int channel = 0;
while (bp < bp_end)
{ int value = (bp[0] << 8) + bp[1];
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* Scale rows of bit depth 16 down to 8 accurately */ staticvoid
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_scale_16_to_8");
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED staticvoid /* Simply discard the low byte. This was the default behavior prior *tolibpng-1.5.4.
*/
png_do_chop(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_chop");
for (i = 0; i < row_width; i++)
{
png_byte red = *(sp++);
png_byte green = *(sp++);
png_byte blue = *(sp++);
if (red != green || red != blue)
{
rgb_error |= 1; /* NOTE: this is the historical approach which simply *truncatestheresults.
*/
*(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
}
for (i = 0; i < row_width; i++)
{
png_uint_16 red, green, blue, gray16;
png_byte hi,lo;
hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));
hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));
if (red != green || red != blue)
rgb_error |= 1;
/* From 1.5.5 in the 16-bit case do the accurate conversion even *inthe'fast'case-thisisbecausethisiswherethecode *endsupwhenhandlinglinear16-bitdata.
*/
gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> 15);
*(dp++) = (png_byte)((gray16 >> 8) & 0xff);
*(dp++) = (png_byte)(gray16 & 0xff);
case PNG_COLOR_TYPE_GRAY_ALPHA:
{ if (row_info->bit_depth == 8)
{
sp = row; for (i = 0; i < row_width; i++)
{
*sp = gamma_table[*sp];
sp += 2;
}
}
else/* if (row_info->bit_depth == 16) */
{
sp = row; for (i = 0; i < row_width; i++)
{
png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
*sp = (png_byte)((v >> 8) & 0xff);
*(sp + 1) = (png_byte)(v & 0xff);
sp += 4;
}
} break;
}
case PNG_COLOR_TYPE_GRAY:
{ if (row_info->bit_depth == 2)
{
sp = row; for (i = 0; i < row_width; i += 4)
{ int a = *sp & 0xc0; int b = *sp & 0x30; int c = *sp & 0x0c; int d = *sp & 0x03;
/* Only get to here if called with a weird row_info; no harm has been done, *sojustissueawarning.
*/
png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
} #endif
#ifdef PNG_READ_EXPAND_SUPPORTED /* Expands a palette row to an RGB or RGBA row depending *uponwhetheryousupplytransandnum_trans.
*/ staticvoid
png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
{ int shift, value;
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width=row_info->width;
png_debug(1, "in png_do_expand_palette");
if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
{ if (row_info->bit_depth < 8)
{ switch (row_info->bit_depth)
{ case1:
{
sp = row + (size_t)((row_width - 1) >> 3);
dp = row + (size_t)row_width - 1;
shift = 7 - (int)((row_width + 7) & 0x07); for (i = 0; i < row_width; i++)
{ if ((*sp >> shift) & 0x01)
*dp = 1;
/* If the bit depth < 8, it is expanded to 8. Also, if the already *expandedtransparencyvalueissupplied,analphachannelisbuilt.
*/ staticvoid
png_do_expand(png_row_infop row_info, png_bytep row,
png_const_color_16p trans_color)
{ int shift, value;
png_bytep sp, dp;
png_uint_32 i;
png_uint_32 row_width=row_info->width;
#ifdef PNG_READ_EXPAND_16_SUPPORTED /* If the bit depth is 8 and the color type is not a palette type expand the *wholerowto16bits.Hasnoeffectotherwise.
*/ staticvoid
png_do_expand_16(png_row_infop row_info, png_bytep row)
{ if (row_info->bit_depth == 8 &&
row_info->color_type != PNG_COLOR_TYPE_PALETTE)
{ /* The row have a sequence of bytes containing [0..255] and we need *toturnitintoanotherrowcontaining[0..65535],todothiswe *calculate: * *(input/255)*65535 * *Whichhappenstobeexactlyinput*257andthiscanbeachieved *simplybybytereplicationinplace(copyingbackwards).
*/
png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ while (dp > sp)
{
dp[-2] = dp[-1] = *--sp; dp -= 2;
}
if (row_info->bit_depth == 8)
{ if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
{ int r, g, b, p;
sp = row;
dp = row; for (i = 0; i < row_width; i++)
{
r = *sp++;
g = *sp++;
b = *sp++;
/* This looks real messy, but the compiler will reduce *itdowntoareasonableformula.Forexample,with *5bitspercolor,weget: *p=(((r>>3)&0x1f)<<10)| *(((g>>3)&0x1f)<<5)| *((b>>3)&0x1f);
*/
p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
(PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
(((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
(PNG_QUANTIZE_BLUE_BITS)) |
((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
for (i = 0; i < row_width; i++, sp++)
{
*sp = quantize_lookup[*sp];
}
}
}
} #endif/* READ_QUANTIZE */
/* Transform the row. The order of transformations is significant, *andisverytouchy.Ifyouaddatransformation,takecareto *decidehowitfitsinwiththeothertransformationshere.
*/ void/* PRIVATE */
png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
{
png_debug(1, "in png_do_read_transformations");
if (png_ptr->row_buf == NULL)
{ /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this *errorisincrediblyrareandincrediblyeasytodebugwithoutthis *information.
*/
png_error(png_ptr, "NULL row buffer");
}
/* The following is debugging; prior to 1.5.4 the code was never compiled in; *in1.5.4PNG_FLAG_DETECT_UNINITIALIZEDwasaddedandthemacro *PNG_WARN_UNINITIALIZED_ROWremoved.In1.6thenewflagissetonlyfor *alltransformations,howeverinpracticetheROW_INITalwaysgetsdoneon *demand,ifnecessary.
*/ if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
(png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
{ /* Application has failed to call either png_read_start_image() or *png_read_update_info()aftersettingtransformsthatexpandpixels. *Thischeckaddedtolibpng-1.2.19(butnotenableduntil1.5.4).
*/
png_error(png_ptr, "Uninitialized row");
}
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
{ int rgb_error =
png_do_rgb_to_gray(png_ptr, row_info,
png_ptr->row_buf + 1);
if (rgb_error != 0)
{
png_ptr->rgb_to_gray_status=1; if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
PNG_RGB_TO_GRAY_WARN)
png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
PNG_RGB_TO_GRAY_ERR)
png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
}
} #endif
/* From Andreas Dilger e-mail to png-implement, 26 March 1998: * *Inmostcases,the"simpletransparency"shouldbedonepriortodoing *gray-to-RGB,oryouwillhavetotest3xasmanybytestocheckifa *pixelistransparent.Youwouldalsoneedtomakesurethatthe *transparencyinformationisupgradedtoRGB. * *Tosummarize,thecurrentflowis: *-Gray+simpletransparency->compare1or2graybytesandcomposite *withbackground"inplace"iftransparent, *converttoRGBifnecessary *-Gray+alpha->compositewithgraybackgroundandremovealphabytes, *converttoRGBifnecessary * *TosupportRGBbackgroundsforgrayimagesweneed: *-Gray+simpletransparency->converttoRGB+simpletransparency, *compare3or6bytesandcompositewith *background"inplace"iftransparent *(3xcompare/pixelcomparedtodoing *compositewithgraybkgrnd) *-Gray+alpha->converttoRGB+alpha,compositewithbackgroundand *removealphabytes(3xfloat *operations/pixelcomparedwithcomposite *ongraybackground) * *Greg'schangewilldothis.Thereasonitwasn'tdonebeforeisfor *performance,asthisincreasestheper-pixeloperations.Ifwewouldcheck *inadvanceifthebackgroundwasgrayorRGB,andpositionthegray-to-RGB *transformappropriately,thenitwouldsavealotofwork/time.
*/
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* If gray -> RGB, do so now only if background is non-gray; else do later *forperformancereasons
*/ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
(png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); #endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED /* There is no harm in doing both of these because only one has any effect, *byputtingthe'scale'optionfirstiftheappasksforscale(eitherby *callingtheAPIorinaTRANSFORMflag)thisiswhathappens.
*/ if ((png_ptr->transformations & PNG_16_TO_8) != 0)
png_do_chop(row_info, png_ptr->row_buf + 1); #endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED /* Do the expansion now, after all the arithmetic has been done. Notice *thatprevioustransformationscanhandlethePNG_EXPAND_16flagifthis *isefficient(particularlytrueinthecaseofgammacorrection,where *betteraccuracyresultsfaster!)
*/ if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
png_do_expand_16(row_info, png_ptr->row_buf + 1); #endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* NOTE: moved here in 1.5.4 (from much later in this list.) */ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
(png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); #endif
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
{ if (png_ptr->read_user_transform_fn != NULL)
(*(png_ptr->read_user_transform_fn)) /* User read transform function */
(png_ptr, /* png_ptr */
row_info, /* row_info: */ /* png_uint_32 width; width of row */ /* size_t rowbytes; number of bytes in row */ /* png_byte color_type; color type of pixels */ /* png_byte bit_depth; bit depth of samples */ /* png_byte channels; number of channels (1-4) */ /* png_byte pixel_depth; bits per pixel (depth*channels) */
png_ptr->row_buf + 1); /* start of pixel data for row */ #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED if (png_ptr->user_transform_depth != 0)
row_info->bit_depth = png_ptr->user_transform_depth;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.