/* * Reduce the image (bit depth + color type + palette) without * losing any information. The palette (if applicable) and the * image data must be present (e.g. by calling png_set_rows(), * or by loading IDAT). * The parameter reductions indicates the intended reductions. * The function returns the successful reductions. */ png_uint_32 PNGAPI opng_reduce_image(png_structp png_ptr, png_infop info_ptr, png_uint_32 reductions) { unsigned int color_type; png_uint_32 result; png_debug(1, "in opng_reduce_image_type\n"); if (!opng_validate_image(png_ptr, info_ptr)) { png_warning(png_ptr, "Image reduction requires the presence of the critical info"); return OPNG_REDUCE_NONE; } #if 0 /* PNG_INTERLACE must be recognized! */ if (png_ptr->transformations) { png_warning(png_ptr, "Image reduction cannot be applied " "under the presence of transformations"); return OPNG_REDUCE_NONE; } #endif color_type = info_ptr->color_type; /* The reductions below must be applied in the given order. */ /* Try to reduce the high bits and color/alpha channels. */ result = opng_reduce_bits(png_ptr, info_ptr, reductions); /* Try to reduce the palette image. */ if (color_type == PNG_COLOR_TYPE_PALETTE && (reductions & (OPNG_REDUCE_PALETTE_TO_GRAY | OPNG_REDUCE_PALETTE_FAST | OPNG_REDUCE_8_TO_4_2_1))) result |= opng_reduce_palette(png_ptr, info_ptr, reductions); /* Try to reduce RGB to palette or grayscale to palette. */ if (((color_type & ~PNG_COLOR_MASK_ALPHA) == PNG_COLOR_TYPE_GRAY && (reductions & OPNG_REDUCE_GRAY_TO_PALETTE)) || ((color_type & ~PNG_COLOR_MASK_ALPHA) == PNG_COLOR_TYPE_RGB && (reductions & OPNG_REDUCE_RGB_TO_PALETTE))) { if (!(result & OPNG_REDUCE_PALETTE_TO_GRAY)) result |= opng_reduce_to_palette(png_ptr, info_ptr, reductions); } return result; }
/* * Imports an image from an PNG file stream. * The function returns 0 on success or -1 on error. */ int opng_decode_image(struct opng_codec_context *context, FILE *stream, const char *fname, bool force_no_palette) { context->libpng_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, opng_read_error, opng_read_warning); context->info_ptr = png_create_info_struct(context->libpng_ptr); if (!context->libpng_ptr || !context->info_ptr) { opng_error(0, "Out of memory"); png_destroy_read_struct(&context->libpng_ptr, &context->info_ptr, 0); exit(1); } opng_init_image(context->image); const char * volatile err_msg; /* volatile is required by cexcept */ struct opng_encoding_stats * stats = context->stats; opng_init_stats(stats); context->stream = stream; context->fname = fname; if (force_no_palette) { png_set_palette_to_rgb(context->libpng_ptr); } Try { png_set_keep_unknown_chunks(context->libpng_ptr, PNG_HANDLE_CHUNK_ALWAYS, 0, 0); png_set_read_fn(context->libpng_ptr, context, opng_read_data); png_read_png(context->libpng_ptr, context->info_ptr, 0, 0); } Catch (err_msg) { if (opng_validate_image(context->libpng_ptr, context->info_ptr)) { /* The critical image info has already been loaded. * Treat this error as a warning in order to allow data recovery. */ opng_warning(fname, err_msg); } else { opng_error(fname, err_msg); return -1; } } opng_load_image(context->image, context->libpng_ptr, context->info_ptr); return 0; }
/* * Reduce the image (bit depth + color type + palette) without * losing any information. The palette (if applicable) and the * image data must be present, e.g., by calling png_set_rows(), * or by loading IDAT. * The parameter reductions indicates the intended reductions. * The function returns the successful reductions. */ png_uint_32 PNGAPI opng_reduce_image(png_structp png_ptr, png_infop info_ptr, png_uint_32 reductions) { if (!opng_validate_image(png_ptr, info_ptr)) { png_warning(png_ptr, "Image reduction requires the presence of all critical information"); return OPNG_REDUCE_NONE; } int color_type = png_get_color_type(png_ptr, info_ptr); /* The reductions below must be applied in this particular order. */ png_uint_32 result = 0; if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) && (reductions & OPNG_REDUCE_DIRTY_ALPHA) ) {result |= opng_reduce_dirty_alpha(png_ptr, info_ptr);} /* Try to reduce the high bits and color/alpha channels. */ result |= opng_reduce_bits(png_ptr, info_ptr, reductions); /* Try to reduce the palette image. */ if (color_type == PNG_COLOR_TYPE_PALETTE && (reductions & (OPNG_REDUCE_PALETTE_TO_GRAY | OPNG_REDUCE_PALETTE_FAST | OPNG_REDUCE_8_TO_4_2_1))) result |= opng_reduce_palette(png_ptr, info_ptr, reductions); /* Try to reduce RGB to palette or grayscale to palette. */ if (((color_type & ~PNG_COLOR_MASK_ALPHA) == PNG_COLOR_TYPE_GRAY && (reductions & OPNG_REDUCE_GRAY_TO_PALETTE)) || ((color_type & ~PNG_COLOR_MASK_ALPHA) == PNG_COLOR_TYPE_RGB && (reductions & OPNG_REDUCE_RGB_TO_PALETTE))) { if (!(result & OPNG_REDUCE_PALETTE_TO_GRAY)) result |= opng_reduce_to_palette(png_ptr, info_ptr, reductions); } return result; }