/* pngtrans.c - transforms the data in a row (used by both readers and writers) * * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson * Copyright (c) 1996-1997 Andreas Dilger * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h
*/
#ifdefined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) /* Add a filler byte on read, or remove a filler or alpha byte on write. * The filler type has changed in v0.95 to allow future 2-byte fillers * for 48-bit input data, as well as to avoid problems with some compilers * that don't like bytes as parameters.
*/ void PNGAPI
png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_filler");
if (png_ptr == NULL) return;
/* In libpng 1.6 it is possible to determine whether this is a read or write * operation and therefore to do more checking here for a valid call.
*/ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
{ # ifdef PNG_READ_FILLER_SUPPORTED /* On read png_set_filler is always valid, regardless of the base PNG * format, because other transformations can give a format where the * filler code can execute (basically an 8 or 16-bit component RGB or G * format.) * * NOTE: usr_channels is not used by the read code! (This has led to * confusion in the past.) The filler is only used in the read code.
*/
png_ptr->filler = (png_uint_16)filler; # else
png_app_error(png_ptr, "png_set_filler not supported on read");
PNG_UNUSED(filler) /* not used in the write case */ return; # endif
}
else/* write */
{ # ifdef PNG_WRITE_FILLER_SUPPORTED /* On write the usr_channels parameter must be set correctly at the * start to record the number of channels in the app-supplied data.
*/ switch (png_ptr->color_type)
{ case PNG_COLOR_TYPE_RGB:
png_ptr->usr_channels = 4; break;
case PNG_COLOR_TYPE_GRAY: if (png_ptr->bit_depth >= 8)
{
png_ptr->usr_channels = 2; break;
}
else
{ /* There simply isn't any code in libpng to strip out bits * from bytes when the components are less than a byte in * size!
*/
png_app_error(png_ptr, "png_set_filler is invalid for" " low bit depth gray output"); return;
}
default:
png_app_error(png_ptr, "png_set_filler: inappropriate color type"); return;
} # else
png_app_error(png_ptr, "png_set_filler not supported on write"); return; # endif
}
/* Here on success - libpng supports the operation, set the transformation * and the flag to say where the filler channel is.
*/
png_ptr->transformations |= PNG_FILLER;
if (filler_loc == PNG_FILLER_AFTER)
png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
else
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
}
/* Added to libpng-1.2.7 */ void PNGAPI
png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_add_alpha");
if (png_ptr == NULL) return;
png_set_filler(png_ptr, filler, filler_loc); /* The above may fail to do anything. */ if ((png_ptr->transformations & PNG_FILLER) != 0)
png_ptr->transformations |= PNG_ADD_ALPHA;
}
/* Invert monochrome grayscale data */ void/* PRIVATE */
png_do_invert(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_invert");
/* This test removed from libpng version 1.0.13 and 1.2.0: * if (row_info->bit_depth == 1 &&
*/ if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{
png_bytep rp = row;
size_t i;
size_t istop = row_info->rowbytes;
for (i = 0; i < istop; i++)
{
*rp = (png_byte)(~(*rp));
rp++;
}
}
for (rp = row; rp < end; rp++)
*rp = table[*rp];
}
} #endif/* PACKSWAP || WRITE_PACKSWAP */
#ifdefined(PNG_WRITE_FILLER_SUPPORTED) || \ defined(PNG_READ_STRIP_ALPHA_SUPPORTED) /* Remove a channel - this used to be 'png_do_strip_filler' but it used a * somewhat weird combination of flags to determine what to do. All the calls * to png_do_strip_filler are changed in 1.5.2 to call this instead with the * correct arguments. * * The routine isn't general - the channel must be the channel at the start or * end (not in the middle) of each pixel.
*/ void/* PRIVATE */
png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
png_bytep sp = row; /* source pointer */
png_bytep dp = row; /* destination pointer */
png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
png_debug(1, "in png_do_strip_channel");
/* At the start sp will point to the first byte to copy and dp to where * it is copied to. ep always points just beyond the end of the row, so * the loop simply copies (channels-1) channels until sp reaches ep. * * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc. * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
*/
/* GA, GX, XG cases */ if (row_info->channels == 2)
{ if (row_info->bit_depth == 8)
{ if (at_start != 0) /* Skip initial filler */
++sp; else/* Skip initial channel and, for sp, the filler */
{
sp += 2; ++dp;
}
/* For a 1 pixel wide image there is nothing to do */ while (sp < ep)
{
*dp++ = *sp; sp += 2;
}
/* Finally fix the color type if it records an alpha channel */ if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
row_info->color_type = PNG_COLOR_TYPE_GRAY;
}
/* Finally fix the color type if it records an alpha channel */ if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
row_info->color_type = PNG_COLOR_TYPE_RGB;
}
else return; /* The filler channel has gone already */
#ifdefined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) /* Swaps red and blue bytes within a pixel */ void/* PRIVATE */
png_do_bgr(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_bgr");
if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_uint_32 row_width = row_info->width; if (row_info->bit_depth == 8)
{ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
{
png_bytep rp;
png_uint_32 i;
for (i = 0, rp = row; i < row_width; i++, rp += 3)
{
png_byte save = *rp;
*rp = *(rp + 2);
*(rp + 2) = save;
}
}
for (i = 0, rp = row; i < row_width; i++, rp += 8)
{
png_byte save = *rp;
*rp = *(rp + 4);
*(rp + 4) = save;
save = *(rp + 1);
*(rp + 1) = *(rp + 5);
*(rp + 5) = save;
}
}
} #endif
}
} #endif/* READ_BGR || WRITE_BGR */
#ifdefined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \ defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED) /* Added at libpng-1.5.10 */ void/* PRIVATE */
png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
{
png_debug(1, "in png_do_check_palette_indexes");
if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
{ /* Calculations moved outside switch in an attempt to stop different * compiler warnings. 'padding' is in *bits* within the last byte, it is * an 'int' because pixel_depth becomes an 'int' in the expression below, * and this calculation is used because it avoids warnings that other * forms produced on either GCC or MSVC.
*/ int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
switch (row_info->bit_depth)
{ case 1:
{ /* in this case, all bytes must be 0 so we don't need * to unpack the pixels except for the rightmost one.
*/ for (; rp > png_ptr->row_buf; rp--)
{ if ((*rp >> padding) != 0)
png_ptr->num_palette_max = 1;
padding = 0;
}
break;
}
case 2:
{ for (; rp > png_ptr->row_buf; rp--)
{ int i = ((*rp >> padding) & 0x03);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
i = (((*rp >> padding) >> 2) & 0x03);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
i = (((*rp >> padding) >> 4) & 0x03);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
i = (((*rp >> padding) >> 6) & 0x03);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
padding = 0;
}
break;
}
case 4:
{ for (; rp > png_ptr->row_buf; rp--)
{ int i = ((*rp >> padding) & 0x0f);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
i = (((*rp >> padding) >> 4) & 0x0f);
if (i > png_ptr->num_palette_max)
png_ptr->num_palette_max = i;
padding = 0;
}
break;
}
case 8:
{ for (; rp > png_ptr->row_buf; rp--)
{ if (*rp > png_ptr->num_palette_max)
png_ptr->num_palette_max = (int) *rp;
}
/* This function returns a pointer to the user_transform_ptr associated with * the user transform functions. The application should free any memory * associated with this pointer before png_write_destroy and png_read_destroy * are called.
*/ #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
png_voidp PNGAPI
png_get_user_transform_ptr(png_const_structrp png_ptr)
{ if (png_ptr == NULL) return NULL;
return png_ptr->user_transform_ptr;
} #endif
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
png_uint_32 PNGAPI
png_get_current_row_number(png_const_structrp png_ptr)
{ /* See the comments in png.h - this is the sub-image row when reading an * interlaced image.
*/ if (png_ptr != NULL) return png_ptr->row_number;
return PNG_UINT_32_MAX; /* help the app not to fail silently */
}
¤ 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.0.3Bemerkung:
(vorverarbeitet)
¤
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.