1b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* pngimage.c 2b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 3b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Copyright (c) 2014 John Cunningham Bowler 4b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 5b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Last changed in libpng 1.6.10 [March 6, 2014] 6b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 7b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * This code is released under the libpng license. 8b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * For conditions of distribution and use, see the disclaimer 9b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * and license in png.h 10b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 11b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Test the png_read_png and png_write_png interfaces. Given a PNG file load it 12b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * using png_read_png and then write with png_write_png. Test all possible 13b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * transforms. 14b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 15b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#include <stdarg.h> 16b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#include <stdlib.h> 17b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#include <string.h> 18b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#include <errno.h> 19b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#include <stdio.h> 20b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#include <assert.h> 21b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 22b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) 23b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# include <config.h> 24b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 25b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 26b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Define the following to use this test against your installed libpng, rather 27b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * than the one being built here: 28b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 29b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_FREESTANDING_TESTS 30b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# include <png.h> 31b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 32b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# include "../../png.h" 33b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 34b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 35b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifndef PNG_SETJMP_SUPPORTED 36b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# include <setjmp.h> /* because png.h did *not* include this */ 37b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 38b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 39b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(PNG_INFO_IMAGE_SUPPORTED) && defined(PNG_SEQUENTIAL_READ_SUPPORTED) 40b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* If a transform is valid on both read and write this implies that if the 41b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * transform is applied to read it must also be applied on write to produce 42b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * meaningful data. This is because these transforms when performed on read 43b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * produce data with a memory format that does not correspond to a PNG format. 44b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 45b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Most of these transforms are invertible; after applying the transform on 46b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * write the result is the original PNG data that would have would have been 47b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * read if no transform were applied. 48b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 49b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * The exception is _SHIFT, which destroys the low order bits marked as not 50b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * significant in a PNG with the sBIT chunk. 51b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 52b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * The following table lists, for each transform, the conditions under which it 53b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * is expected to do anything. Conditions are defined as follows: 54b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 55b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 1) Color mask bits required - simply a mask to AND with color_type; one of 56b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * these must be present for the transform to fire, except that 0 means 57b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 'always'. 58b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 2) Color mask bits which must be absent - another mask - none of these must 59b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * be present. 60b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 3) Bit depths - a mask of component bit depths for the transform to fire. 61b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 4) 'read' - the transform works in png_read_png. 62b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 5) 'write' - the transform works in png_write_png. 63b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 6) PNG_INFO_chunk; a mask of the chunks that must be present for the 64b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * transform to fire. All must be present - the requirement is that 65b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * png_get_valid() & mask == mask, so if mask is 0 there is no requirement. 66b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 67b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * The condition refers to the original image state - if multiple transforms are 68b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * used together it is possible to cause a transform that wouldn't fire on the 69b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * original image to fire. 70b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 71b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic struct transform_info 72b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 73b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari const char *name; 74b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int transform; 75b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 valid_chunks; 76b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define CHUNK_NONE 0 77b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define CHUNK_sBIT PNG_INFO_sBIT 78b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define CHUNK_tRNS PNG_INFO_tRNS 79b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_byte color_mask_required; 80b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_byte color_mask_absent; 81b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define COLOR_MASK_X 0 82b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define COLOR_MASK_P PNG_COLOR_MASK_PALETTE 83b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define COLOR_MASK_C PNG_COLOR_MASK_COLOR 84b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define COLOR_MASK_A PNG_COLOR_MASK_ALPHA 85b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define COLOR_MASK_ALL (PALETTE+COLOR+ALPHA) /* absent = gray, no alpha */ 86b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_byte bit_depths; 87b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define BD_ALL (1 + 2 + 4 + 8 + 16) 88b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define BD_PAL (1 + 2 + 4 + 8) 89b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define BD_LOW (1 + 2 + 4) 90b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define BD_16 16 91b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define BD_TRUE (8+16) /* i.e. true-color depths */ 92b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_byte when; 93b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_R 1 94b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_W 2 95b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW 3 96b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_byte tested; /* the transform was tested somewhere */ 97b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} transform_info[] = 98b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 99b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* List ALL the PNG_TRANSFORM_ macros here. Check for support using the READ 100b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * macros; even if the transform is supported on write it cannot be tested 101b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * without the read support. 102b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 103b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define T(name,chunk,cm_required,cm_absent,bd,when)\ 104b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { #name, PNG_TRANSFORM_ ## name, CHUNK_ ## chunk,\ 105b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari COLOR_MASK_ ## cm_required, COLOR_MASK_ ## cm_absent, BD_ ## bd,\ 106b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari TRANSFORM_ ## when, 0/*!tested*/ } 107b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 108b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 109b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(STRIP_16, NONE, X, X, 16, R), 110b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* drops the bottom 8 bits when bit depth is 16 */ 111b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 112b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 113b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(STRIP_ALPHA, NONE, A, X, ALL, R), 114b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* removes the alpha channel if present */ 115b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 116b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_PACK_SUPPORTED 117b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_PACK TRANSFORM_RW 118b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 119b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_PACK TRANSFORM_R 120b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 121b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACK_SUPPORTED 122b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(PACKING, NONE, X, X, LOW, RW_PACK), 123b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* unpacks low-bit-depth components into 1 byte per component on read, 124b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * reverses this on write. 125b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 126b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 127b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_PACKSWAP_SUPPORTED 128b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_PACKSWAP TRANSFORM_RW 129b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 130b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_PACKSWAP TRANSFORM_R 131b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 132b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACKSWAP_SUPPORTED 133b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(PACKSWAP, NONE, X, X, LOW, RW_PACKSWAP), 134b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* reverses the order of low-bit-depth components packed into a byte */ 135b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 136b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_EXPAND_SUPPORTED 137b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(EXPAND, NONE, P, X, ALL, R), 138b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* expands PLTE PNG files to RGB (no tRNS) or RGBA (tRNS) * 139b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Note that the 'EXPAND' transform does lots of different things: */ 140b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(EXPAND, NONE, X, C, ALL, R), 141b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* expands grayscale PNG files to RGB, or RGBA */ 142b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(EXPAND, tRNS, X, A, ALL, R), 143b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* expands the tRNS chunk in files without alpha */ 144b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 145b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_INVERT_SUPPORTED 146b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_INVERT TRANSFORM_RW 147b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 148b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_INVERT TRANSFORM_R 149b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 150b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_INVERT_SUPPORTED 151b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(INVERT_MONO, NONE, X, C, ALL, RW_INVERT), 152b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* converts gray-scale components to 1..0 from 0..1 */ 153b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 154b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SHIFT_SUPPORTED 155b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_SHIFT TRANSFORM_RW 156b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 157b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_SHIFT TRANSFORM_R 158b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 159b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SHIFT_SUPPORTED 160b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(SHIFT, sBIT, X, X, ALL, RW_SHIFT), 161b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* reduces component values to the original range based on the sBIT chunk, 162b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * this is only partially reversible - the low bits are lost and cannot be 163b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * recovered on write. In fact write code replicates the bits to generate 164b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * new low-order bits. 165b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 166b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 167b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_BGR_SUPPORTED 168b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_BGR TRANSFORM_RW 169b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 170b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_BGR TRANSFORM_R 171b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 172b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_BGR_SUPPORTED 173b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(BGR, NONE, C, P, TRUE, RW_BGR), 174b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* reverses the rgb component values of true-color pixels */ 175b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 176b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED 177b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_SWAP_ALPHA TRANSFORM_RW 178b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 179b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_SWAP_ALPHA TRANSFORM_R 180b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 181b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 182b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(SWAP_ALPHA, NONE, A, X, TRUE, RW_SWAP_ALPHA), 183b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* swaps the alpha channel of RGBA or GA pixels to the front - ARGB or 184b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * AG, on write reverses the process. 185b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 186b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 187b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SWAP_SUPPORTED 188b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_SWAP TRANSFORM_RW 189b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 190b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_SWAP TRANSFORM_R 191b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 192b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SWAP_SUPPORTED 193b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(SWAP_ENDIAN, NONE, X, P, 16, RW_SWAP), 194b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* byte-swaps 16-bit component values */ 195b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 196b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED 197b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_INVERT_ALPHA TRANSFORM_RW 198b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 199b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define TRANSFORM_RW_INVERT_ALPHA TRANSFORM_R 200b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 201b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 202b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(INVERT_ALPHA, NONE, A, X, TRUE, RW_INVERT_ALPHA), 203b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* converts an alpha channel from 0..1 to 1..0 */ 204b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 205b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_FILLER_SUPPORTED 206b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(STRIP_FILLER_BEFORE, NONE, A, P, TRUE, W), /* 'A' for a filler! */ 207b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* on write skips a leading filler channel; testing requires data with a 208b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * filler channel so this is produced from RGBA or GA images by removing 209b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * the 'alpha' flag from the color type in place. 210b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 211b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(STRIP_FILLER_AFTER, NONE, A, P, TRUE, W), 212b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* on write strips a trailing filler channel */ 213b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 214b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 215b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(GRAY_TO_RGB, NONE, X, C, ALL, R), 216b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* expands grayscale images to RGB, also causes the palette part of 217b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 'EXPAND' to happen. Low bit depth grayscale images are expanded to 218b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 8-bits per component and no attempt is made to convert the image to a 219b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * palette image. While this transform is partially reversible 220b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * png_write_png does not currently support this. 221b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 222b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(GRAY_TO_RGB, NONE, P, X, ALL, R), 223b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* The 'palette' side effect mentioned above; a bit bogus but this is the 224b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * way the libpng code works. 225b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 226b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 227b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_EXPAND_16_SUPPORTED 228b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(EXPAND_16, NONE, X, X, PAL, R), 229b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* expands images to 16-bits per component, as a side effect expands 230b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * palette images to RGB and expands the tRNS chunk if present, so it can 231b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * modify 16-bit per component images as well: 232b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 233b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(EXPAND_16, tRNS, X, A, 16, R), 234b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* side effect of EXPAND_16 - expands the tRNS chunk in an RGB or G 16-bit 235b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * image. 236b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 237b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 238b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 239b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari T(SCALE_16, NONE, X, X, 16, R) 240b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* scales 16-bit components to 8-bits. */ 241b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 242b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 243b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#undef T 244b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari}; 245b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 246b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define ARRAY_SIZE(a) ((sizeof a)/(sizeof a[0])) 247b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define TTABLE_SIZE ARRAY_SIZE(transform_info) 248b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 249b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Some combinations of options that should be reversible are not; these cases 250b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * are bugs. 251b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 252b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int known_bad_combos[][2] = 253b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 254b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* problem, antidote */ 255b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { PNG_TRANSFORM_SHIFT | PNG_TRANSFORM_INVERT_ALPHA, 0/*antidote*/ } 256b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari}; 257b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 258b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int 259b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariis_combo(int transforms) 260b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 261b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return transforms & (transforms-1); /* non-zero if more than one set bit */ 262b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 263b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 264b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int 265b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurarifirst_transform(int transforms) 266b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 267b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return transforms & -transforms; /* lowest set bit */ 268b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 269b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 270b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int 271b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariis_bad_combo(int transforms) 272b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 273b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int i; 274b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 275b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i=0; i<ARRAY_SIZE(known_bad_combos); ++i) 276b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 277b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int combo = known_bad_combos[i][0]; 278b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 279b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((combo & transforms) == combo && 280b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (transforms & known_bad_combos[i][1]) == 0) 281b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 1; 282b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 283b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 284b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 0; /* combo is ok */ 285b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 286b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 287b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic const char * 288b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraritransform_name(int t) 289b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* The name, if 't' has multiple bits set the name of the lowest set bit is 290b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * returned. 291b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 292b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 293b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int i; 294b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 295b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari t &= -t; /* first set bit */ 296b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 297b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i=0; i<TTABLE_SIZE; ++i) 298b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 299b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((transform_info[i].transform & t) != 0) 300b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return transform_info[i].name; 301b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 302b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 303b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return "invalid transform"; 304b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 305b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 306b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Variables calculated by validate_T below and used to record all the supported 307b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * transforms. Need (unsigned int) here because of the places where these 308b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * values are used (unsigned compares in the 'exhaustive' iterator.) 309b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 310b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic unsigned int read_transforms, write_transforms, rw_transforms; 311b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 312b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 313b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurarivalidate_T(void) 314b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Validate the above table - this just builds the above values */ 315b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 316b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int i; 317b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 318b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i=0; i<TTABLE_SIZE; ++i) 319b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 320b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (transform_info[i].when & TRANSFORM_R) 321b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari read_transforms |= transform_info[i].transform; 322b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 323b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (transform_info[i].when & TRANSFORM_W) 324b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari write_transforms |= transform_info[i].transform; 325b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 326b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 327b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Reversible transforms are those which are supported on both read and 328b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * write. 329b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 330b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari rw_transforms = read_transforms & write_transforms; 331b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 332b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 333b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* FILE DATA HANDLING 334b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * The original file is cached in memory. During write the output file is 335b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * written to memory. 336b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 337b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * In both cases the file data is held in a linked list of buffers - not all 338b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * of these are in use at any time. 339b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 340b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristruct buffer_list 341b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 342b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer_list *next; /* next buffer in list */ 343b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_byte buffer[1024]; /* the actual buffer */ 344b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari}; 345b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 346b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristruct buffer 347b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 348b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer_list *last; /* last buffer in use */ 349b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t end_count; /* bytes in the last buffer */ 350b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer_list *current; /* current buffer being read */ 351b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t read_count; /* count of bytes read from current */ 352b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer_list first; /* the very first buffer */ 353b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari}; 354b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 355b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 356b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraribuffer_init(struct buffer *buffer) 357b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Call this only once for a given buffer */ 358b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 359b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->first.next = NULL; 360b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->last = NULL; 361b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->current = NULL; 362b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 363b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 364b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SUPPORTED 365b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 366b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraribuffer_start_write(struct buffer *buffer) 367b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 368b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->last = &buffer->first; 369b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->end_count = 0; 370b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->current = NULL; 371b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 372b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 373b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 374b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 375b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraribuffer_start_read(struct buffer *buffer) 376b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 377b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->current = &buffer->first; 378b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->read_count = 0; 379b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 380b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 381b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef ENOMEM /* required by POSIX 1003.1 */ 382b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define MEMORY ENOMEM 383b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 384b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define MEMORY ERANGE /* required by ANSI-C */ 385b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 386b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic struct buffer * 387b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariget_buffer(png_structp pp) 388b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Used from libpng callbacks to get the current buffer */ 389b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 390b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return (struct buffer*)png_get_io_ptr(pp); 391b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 392b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 393b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define NEW(type) ((type *)malloc(sizeof (type))) 394b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 395b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic struct buffer_list * 396b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraribuffer_extend(struct buffer_list *current) 397b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 398b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer_list *add; 399b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 400b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari assert(current->next == NULL); 401b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 402b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari add = NEW(struct buffer_list); 403b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (add == NULL) 404b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return NULL; 405b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 406b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari add->next = NULL; 407b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari current->next = add; 408b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 409b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return add; 410b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 411b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 412b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Load a buffer from a file; does the equivalent of buffer_start_write. On a 413b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * read error returns an errno value, else returns 0. 414b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 415b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int 416b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraribuffer_from_file(struct buffer *buffer, FILE *fp) 417b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 418b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer_list *last = &buffer->first; 419b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t count = 0; 420b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 421b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (;;) 422b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 423b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t r = fread(last->buffer+count, 1/*size*/, 424b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (sizeof last->buffer)-count, fp); 425b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 426b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (r > 0) 427b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 428b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari count += r; 429b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 430b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (count >= sizeof last->buffer) 431b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 432b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari assert(count == sizeof last->buffer); 433b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari count = 0; 434b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 435b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (last->next == NULL) 436b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 437b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari last = buffer_extend(last); 438b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (last == NULL) 439b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return MEMORY; 440b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 441b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 442b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 443b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari last = last->next; 444b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 445b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 446b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 447b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else /* fread failed - probably end of file */ 448b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 449b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (feof(fp)) 450b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 451b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->last = last; 452b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->end_count = count; 453b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 0; /* no error */ 454b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 455b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 456b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Some kind of funky error; errno should be non-zero */ 457b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return errno == 0 ? ERANGE : errno; 458b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 459b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 460b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 461b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 462b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* This structure is used to control the test of a single file. */ 463b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraritypedef enum 464b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 465b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari VERBOSE, /* switches on all messages */ 466b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari INFORMATION, 467b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari WARNINGS, /* switches on warnings */ 468b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari LIBPNG_WARNING, 469b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari APP_WARNING, 470b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ERRORS, /* just errors */ 471b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari APP_FAIL, /* continuable error - no need to longjmp */ 472b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari LIBPNG_ERROR, /* this and higher cause a longjmp */ 473b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari LIBPNG_BUG, /* erroneous behavior in libpng */ 474b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari APP_ERROR, /* such as out-of-memory in a callback */ 475b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari QUIET, /* no normal messages */ 476b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari USER_ERROR, /* such as file-not-found */ 477b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari INTERNAL_ERROR 478b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} error_level; 479b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define LEVEL_MASK 0xf /* where the level is in 'options' */ 480b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 481b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define EXHAUSTIVE 0x010 /* Test all combinations of active options */ 482b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define STRICT 0x020 /* Fail on warnings as well as errors */ 483b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define LOG 0x040 /* Log pass/fail to stdout */ 484b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define CONTINUE 0x080 /* Continue on APP_FAIL errors */ 485b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define SKIP_BUGS 0x100 /* Skip over known bugs */ 486b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define LOG_SKIPPED 0x200 /* Log skipped bugs */ 487b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define FIND_BAD_COMBOS 0x400 /* Attempt to deduce bad combos */ 488b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 489b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Result masks apply to the result bits in the 'results' field below; these 490b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * bits are simple 1U<<error_level. A pass requires either nothing worse than 491b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * warnings (--relaxes) or nothing worse than information (--strict) 492b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 493b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define RESULT_STRICT(r) (((r) & ~((1U<<WARNINGS)-1)) == 0) 494b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#define RESULT_RELAXED(r) (((r) & ~((1U<<ERRORS)-1)) == 0) 495b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 496b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristruct display 497b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 498b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari jmp_buf error_return; /* Where to go to on error */ 499b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 500b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari const char *filename; /* The name of the original file */ 501b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari const char *operation; /* Operation being performed */ 502b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int transforms; /* Transform used in operation */ 503b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 options; /* See display_log below */ 504b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 results; /* A mask of errors seen */ 505b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 506b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 507b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_structp original_pp; /* used on the original read */ 508b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_infop original_ip; /* set by the original read */ 509b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 510b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_size_t original_rowbytes; /* of the original rows: */ 511b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytepp original_rows; /* from the original read */ 512b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 513b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Original chunks valid */ 514b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 chunks; 515b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 516b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Original IHDR information */ 517b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 width; 518b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 height; 519b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int bit_depth; 520b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int color_type; 521b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int interlace_method; 522b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int compression_method; 523b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int filter_method; 524b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 525b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Derived information for the original image. */ 526b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int active_transforms; /* transforms that do something on read */ 527b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int ignored_transforms; /* transforms that should do nothing */ 528b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 529b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Used on a read, both the original read and when validating a written 530b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * image. 531b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 532b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_structp read_pp; 533b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_infop read_ip; 534b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 535b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_WRITE_SUPPORTED 536b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Used to write a new image (the original info_ptr is used) */ 537b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_structp write_pp; 538b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer written_file; /* where the file gets written */ 539b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 540b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 541b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer original_file; /* Data read from the original file */ 542b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari}; 543b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 544b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 545b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraridisplay_init(struct display *dp) 546b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Call this only once right at the start to initialize the control 547b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * structure, the (struct buffer) lists are maintained across calls - the 548b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * memory is not freed. 549b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 550b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 551b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari memset(dp, 0, sizeof *dp); 552b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->options = WARNINGS; /* default to !verbose, !quiet */ 553b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->filename = NULL; 554b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->operation = NULL; 555b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->original_pp = NULL; 556b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->original_ip = NULL; 557b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->original_rows = NULL; 558b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->read_pp = NULL; 559b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->read_ip = NULL; 560b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer_init(&dp->original_file); 561b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 562b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_WRITE_SUPPORTED 563b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->write_pp = NULL; 564b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer_init(&dp->written_file); 565b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 566b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 567b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 568b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 569b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraridisplay_clean_read(struct display *dp) 570b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 571b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (dp->read_pp != NULL) 572b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_destroy_read_struct(&dp->read_pp, &dp->read_ip, NULL); 573b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 574b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 575b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SUPPORTED 576b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 577b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraridisplay_clean_write(struct display *dp) 578b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 579b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (dp->write_pp != NULL) 580b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_destroy_write_struct(&dp->write_pp, NULL); 581b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 582b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 583b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 584b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 585b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraridisplay_clean(struct display *dp) 586b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 587b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_WRITE_SUPPORTED 588b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_clean_write(dp); 589b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 590b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_clean_read(dp); 591b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 592b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->original_rowbytes = 0; 593b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->original_rows = NULL; 594b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->chunks = 0; 595b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 596b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_destroy_read_struct(&dp->original_pp, &dp->original_ip, NULL); 597b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* leave the filename for error detection */ 598b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->results = 0; /* reset for next time */ 599b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 600b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 601b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic struct display * 602b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariget_dp(png_structp pp) 603b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* The display pointer is always stored in the png_struct error pointer */ 604b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 605b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct display *dp = (struct display*)png_get_error_ptr(pp); 606b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 607b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (dp == NULL) 608b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 609b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fprintf(stderr, "pngimage: internal error (no display)\n"); 610b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari exit(99); /* prevents a crash */ 611b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 612b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 613b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return dp; 614b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 615b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 616b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* error handling */ 617b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef __GNUC__ 618b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define VGATTR __attribute__((__format__ (__printf__,3,4))) 619b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Required to quiet GNUC warnings when the compiler sees a stdarg function 620b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * that calls one of the stdio v APIs. 621b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 622b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 623b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define VGATTR 624b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 625b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void VGATTR 626b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraridisplay_log(struct display *dp, error_level level, const char *fmt, ...) 627b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* 'level' is as above, fmt is a stdio style format string. This routine 628b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * does not return if level is above LIBPNG_WARNING 629b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 630b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 631b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->results |= 1U << level; 632b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 633b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (level > (error_level)(dp->options & LEVEL_MASK)) 634b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 635b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari const char *lp; 636b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari va_list ap; 637b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 638b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari switch (level) 639b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 640b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case INFORMATION: lp = "information"; break; 641b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case LIBPNG_WARNING: lp = "warning(libpng)"; break; 642b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case APP_WARNING: lp = "warning(pngimage)"; break; 643b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case APP_FAIL: lp = "error(continuable)"; break; 644b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case LIBPNG_ERROR: lp = "error(libpng)"; break; 645b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case LIBPNG_BUG: lp = "bug(libpng)"; break; 646b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case APP_ERROR: lp = "error(pngimage)"; break; 647b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case USER_ERROR: lp = "error(user)"; break; 648b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 649b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case INTERNAL_ERROR: /* anything unexpected is an internal error: */ 650b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case VERBOSE: case WARNINGS: case ERRORS: case QUIET: 651b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari default: lp = "bug(pngimage)"; break; 652b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 653b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 654b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fprintf(stderr, "%s: %s: %s", 655b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->filename != NULL ? dp->filename : "<stdin>", lp, dp->operation); 656b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 657b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (dp->transforms != 0) 658b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 659b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int tr = dp->transforms; 660b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 661b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (is_combo(tr)) 662b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fprintf(stderr, "(0x%x)", tr); 663b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 664b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 665b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fprintf(stderr, "(%s)", transform_name(tr)); 666b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 667b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 668b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fprintf(stderr, ": "); 669b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 670b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari va_start(ap, fmt); 671b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari vfprintf(stderr, fmt, ap); 672b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari va_end(ap); 673b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 674b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fputc('\n', stderr); 675b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 676b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* else do not output any message */ 677b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 678b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Errors cause this routine to exit to the fail code */ 679b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (level > APP_FAIL || (level > ERRORS && !(dp->options & CONTINUE))) 680b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari longjmp(dp->error_return, level); 681b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 682b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 683b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* error handler callbacks for libpng */ 684b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void PNGCBAPI 685b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraridisplay_warning(png_structp pp, png_const_charp warning) 686b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 687b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(get_dp(pp), LIBPNG_WARNING, "%s", warning); 688b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 689b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 690b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void PNGCBAPI 691b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraridisplay_error(png_structp pp, png_const_charp error) 692b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 693b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct display *dp = get_dp(pp); 694b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 695b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_ERROR, "%s", error); 696b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 697b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 698b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 699b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraridisplay_cache_file(struct display *dp, const char *filename) 700b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Does the initial cache of the file. */ 701b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 702b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari FILE *fp; 703b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int ret; 704b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 705b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->filename = filename; 706b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 707b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (filename != NULL) 708b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 709b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fp = fopen(filename, "rb"); 710b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (fp == NULL) 711b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, USER_ERROR, "open failed: %s", strerror(errno)); 712b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 713b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 714b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 715b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fp = stdin; 716b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 717b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ret = buffer_from_file(&dp->original_file, fp); 718b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 719b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fclose(fp); 720b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 721b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (ret != 0) 722b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_ERROR, "read failed: %s", strerror(ret)); 723b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 724b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 725b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 726b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraribuffer_read(struct display *dp, struct buffer *bp, png_bytep data, 727b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_size_t size) 728b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 729b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer_list *last = bp->current; 730b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t read_count = bp->read_count; 731b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 732b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari while (size > 0) 733b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 734b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t avail; 735b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 736b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (last == NULL || 737b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (last == bp->last && read_count >= bp->end_count)) 738b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 739b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, USER_ERROR, "file truncated (%lu bytes)", 740b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (unsigned long)size); 741b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /*NOTREACHED*/ 742b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 743b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 744b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 745b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (read_count >= sizeof last->buffer) 746b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 747b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Move to the next buffer: */ 748b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari last = last->next; 749b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari read_count = 0; 750b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bp->current = last; /* Avoid update outside the loop */ 751b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 752b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* And do a sanity check (the EOF case is caught above) */ 753b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (last == NULL) 754b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 755b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, INTERNAL_ERROR, "damaged buffer list"); 756b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /*NOTREACHED*/ 757b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 758b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 759b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 760b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 761b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari avail = (sizeof last->buffer) - read_count; 762b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (avail > size) 763b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari avail = size; 764b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 765b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari memcpy(data, last->buffer + read_count, avail); 766b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari read_count += avail; 767b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size -= avail; 768b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari data += avail; 769b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 770b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 771b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bp->read_count = read_count; 772b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 773b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 774b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void PNGCBAPI 775b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariread_function(png_structp pp, png_bytep data, png_size_t size) 776b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 777b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer_read(get_dp(pp), get_buffer(pp), data, size); 778b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 779b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 780b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 781b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariread_png(struct display *dp, struct buffer *bp, const char *operation, 782b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int transforms) 783b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 784b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_structp pp; 785b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_infop ip; 786b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 787b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* This cleans out any previous read and sets operation and transforms to 788b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * empty. 789b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 790b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_clean_read(dp); 791b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 792b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (operation != NULL) /* else this is a verify and do not overwrite info */ 793b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 794b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->operation = operation; 795b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->transforms = transforms; 796b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 797b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 798b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->read_pp = pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, dp, 799b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_error, display_warning); 800b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (pp == NULL) 801b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_ERROR, "failed to create read struct"); 802b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 803b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* The png_read_png API requires us to make the info struct, but it does the 804b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * call to png_read_info. 805b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 806b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->read_ip = ip = png_create_info_struct(pp); 807b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (ip == NULL) 808b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_ERROR, "failed to create info struct"); 809b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 810b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_SET_USER_LIMITS_SUPPORTED 811b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Remove the user limits, if any */ 812b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_user_limits(pp, 0x7fffffff, 0x7fffffff); 813b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 814b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 815b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Set the IO handling */ 816b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer_start_read(bp); 817b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_read_fn(pp, bp, read_function); 818b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 819b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_read_png(pp, ip, transforms, NULL/*params*/); 820b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 821b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if 0 /* crazy debugging */ 822b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 823b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytep pr = png_get_rows(pp, ip)[0]; 824b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t rb = png_get_rowbytes(pp, ip); 825b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t cb; 826b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari char c = ' '; 827b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 828b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fprintf(stderr, "%.4x %2d (%3lu bytes):", transforms, png_get_bit_depth(pp,ip), (unsigned long)rb); 829b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 830b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (cb=0; cb<rb; ++cb) 831b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fputc(c, stderr), fprintf(stderr, "%.2x", pr[cb]), c='.'; 832b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 833b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fputc('\n', stderr); 834b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 835b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 836b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 837b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 838b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 839b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariupdate_display(struct display *dp) 840b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* called once after the first read to update all the info, original_pp and 841b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * original_ip must have been filled in. 842b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 843b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 844b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_structp pp; 845b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_infop ip; 846b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 847b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Now perform the initial read with a 0 tranform. */ 848b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari read_png(dp, &dp->original_file, "original read", 0/*no transform*/); 849b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 850b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Move the result to the 'original' fields */ 851b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->original_pp = pp = dp->read_pp, dp->read_pp = NULL; 852b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->original_ip = ip = dp->read_ip, dp->read_ip = NULL; 853b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 854b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->original_rowbytes = png_get_rowbytes(pp, ip); 855b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (dp->original_rowbytes == 0) 856b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_BUG, "png_get_rowbytes returned 0"); 857b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 858b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->chunks = png_get_valid(pp, ip, 0xffffffff); 859b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((dp->chunks & PNG_INFO_IDAT) == 0) /* set by png_read_png */ 860b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_BUG, "png_read_png did not set IDAT flag"); 861b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 862b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->original_rows = png_get_rows(pp, ip); 863b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (dp->original_rows == NULL) 864b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_BUG, "png_read_png did not create row buffers"); 865b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 866b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (!png_get_IHDR(pp, ip, 867b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari &dp->width, &dp->height, &dp->bit_depth, &dp->color_type, 868b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari &dp->interlace_method, &dp->compression_method, &dp->filter_method)) 869b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_BUG, "png_get_IHDR failed"); 870b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 871b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* 'active' transforms are discovered based on the original image format; 872b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * running one active transform can activate others. At present the code 873b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * does not attempt to determine the closure. 874b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 875b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 876b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 chunks = dp->chunks; 877b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int active = 0, inactive = 0; 878b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int ct = dp->color_type; 879b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int bd = dp->bit_depth; 880b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int i; 881b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 882b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i=0; i<TTABLE_SIZE; ++i) 883b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 884b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int transform = transform_info[i].transform; 885b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 886b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((transform_info[i].valid_chunks == 0 || 887b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (transform_info[i].valid_chunks & chunks) != 0) && 888b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (transform_info[i].color_mask_required & ct) == 889b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari transform_info[i].color_mask_required && 890b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (transform_info[i].color_mask_absent & ct) == 0 && 891b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (transform_info[i].bit_depths & bd) != 0 && 892b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (transform_info[i].when & TRANSFORM_R) != 0) 893b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari active |= transform; 894b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 895b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if ((transform_info[i].when & TRANSFORM_R) != 0) 896b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari inactive |= transform; 897b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 898b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 899b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Some transforms appear multiple times in the table; the 'active' status 900b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * is the logical OR of these and the inactive status must be adjusted to 901b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * take this into account. 902b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 903b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari inactive &= ~active; 904b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 905b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->active_transforms = active; 906b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->ignored_transforms = inactive; /* excluding write-only transforms */ 907b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 908b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (active == 0) 909b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, INTERNAL_ERROR, "bad transform table"); 910b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 911b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 912b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 913b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int 914b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraricompare_read(struct display *dp, int applied_transforms) 915b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 916b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Compare the png_info from read_ip with original_info */ 917b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t rowbytes; 918b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 width, height; 919b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int bit_depth, color_type; 920b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int interlace_method, compression_method, filter_method; 921b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari const char *e = NULL; 922b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 923b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_get_IHDR(dp->read_pp, dp->read_ip, &width, &height, &bit_depth, 924b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari &color_type, &interlace_method, &compression_method, &filter_method); 925b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 926b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define C(item) if (item != dp->item) \ 927b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_WARNING, "IHDR " #item "(%lu) changed to %lu",\ 928b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (unsigned long)dp->item, (unsigned long)item), e = #item 929b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 930b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* The IHDR should be identical: */ 931b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari C(width); 932b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari C(height); 933b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari C(bit_depth); 934b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari C(color_type); 935b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari C(interlace_method); 936b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari C(compression_method); 937b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari C(filter_method); 938b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 939b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* 'e' remains set to the name of the last thing changed: */ 940b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (e) 941b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_ERROR, "IHDR changed (%s)", e); 942b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 943b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* All the chunks from the original PNG should be preserved in the output PNG 944b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * because the PNG format has not been changed. 945b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 946b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 947b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned long chunks = 948b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_get_valid(dp->read_pp, dp->read_ip, 0xffffffff); 949b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 950b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (chunks != dp->chunks) 951b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_FAIL, "PNG chunks changed from 0x%lx to 0x%lx", 952b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (unsigned long)dp->chunks, chunks); 953b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 954b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 955b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* rowbytes should be the same */ 956b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari rowbytes = png_get_rowbytes(dp->read_pp, dp->read_ip); 957b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 958b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* NOTE: on 64-bit systems this may trash the top bits of rowbytes, 959b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * which could lead to weird error messages. 960b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 961b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (rowbytes != dp->original_rowbytes) 962b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_ERROR, "PNG rowbytes changed from %lu to %lu", 963b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (unsigned long)dp->original_rowbytes, (unsigned long)rowbytes); 964b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 965b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* The rows should be the same too, unless the applied transforms includes 966b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * the shift transform, in which case low bits may have been lost. 967b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 968b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 969b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytepp rows = png_get_rows(dp->read_pp, dp->read_ip); 970b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int mask; /* mask (if not zero) for the final byte */ 971b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 972b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (bit_depth < 8) 973b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 974b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Need the stray bits at the end, this depends only on the low bits 975b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * of the image width; overflow does not matter. If the width is an 976b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * exact multiple of 8 bits this gives a mask of 0, not 0xff. 977b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 978b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari mask = 0xff & (0xff00 >> ((bit_depth * width) & 7)); 979b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 980b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 981b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 982b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari mask = 0; 983b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 984b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (rows == NULL) 985b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_BUG, "png_get_rows returned NULL"); 986b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 987b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((applied_transforms & PNG_TRANSFORM_SHIFT) == 0 || 988b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (dp->active_transforms & PNG_TRANSFORM_SHIFT) == 0 || 989b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari color_type == PNG_COLOR_TYPE_PALETTE) 990b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 991b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned long y; 992b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 993b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (y=0; y<height; ++y) 994b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 995b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytep row = rows[y]; 996b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytep orig = dp->original_rows[y]; 997b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 998b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (memcmp(row, orig, rowbytes-(mask != 0)) != 0 || (mask != 0 && 999b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ((row[rowbytes-1] & mask) != (orig[rowbytes-1] & mask)))) 1000b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1001b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t x; 1002b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1003b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Find the first error */ 1004b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (x=0; x<rowbytes-1; ++x) if (row[x] != orig[x]) 1005b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1006b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1007b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_FAIL, 1008b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari "byte(%lu,%lu) changed 0x%.2x -> 0x%.2x", 1009b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (unsigned long)x, (unsigned long)y, orig[x], row[x]); 1010b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 0; /* don't keep reporting failed rows on 'continue' */ 1011b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1012b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1013b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1014b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1015b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1016b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1017b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned long y; 1018b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int bpp; /* bits-per-pixel then bytes-per-pixel */ 1019b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* components are up to 8 bytes in size */ 1020b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_byte sig_bits[8]; 1021b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_color_8p sBIT; 1022b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1023b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (png_get_sBIT(dp->read_pp, dp->read_ip, &sBIT) != PNG_INFO_sBIT) 1024b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, INTERNAL_ERROR, 1025b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari "active shift transform but no sBIT in file"); 1026b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1027b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari switch (color_type) 1028b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1029b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case PNG_COLOR_TYPE_GRAY: 1030b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[0] = sBIT->gray; 1031b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bpp = bit_depth; 1032b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1033b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1034b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case PNG_COLOR_TYPE_GA: 1035b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[0] = sBIT->gray; 1036b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[1] = sBIT->alpha; 1037b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bpp = 2 * bit_depth; 1038b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1039b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1040b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case PNG_COLOR_TYPE_RGB: 1041b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[0] = sBIT->red; 1042b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[1] = sBIT->green; 1043b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[2] = sBIT->blue; 1044b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bpp = 3 * bit_depth; 1045b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1046b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1047b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case PNG_COLOR_TYPE_RGBA: 1048b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[0] = sBIT->red; 1049b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[1] = sBIT->green; 1050b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[2] = sBIT->blue; 1051b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[3] = sBIT->alpha; 1052b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bpp = 4 * bit_depth; 1053b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1054b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1055b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari default: 1056b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_ERROR, "invalid colour type %d", 1057b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari color_type); 1058b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /*NOTREACHED*/ 1059b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bpp = 0; 1060b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1061b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1062b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1063b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1064b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int b; 1065b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1066b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (b=0; 8*b<bpp; ++b) 1067b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1068b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* libpng should catch this; if not there is a security issue 1069b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * because an app (like this one) may overflow an array. In fact 1070b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * libpng doesn't catch this at present. 1071b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1072b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (sig_bits[b] == 0 || sig_bits[b] > bit_depth/*!palette*/) 1073b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_BUG, 1074b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari "invalid sBIT[%u] value %d returned for PNG bit depth %d", 1075b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari b, sig_bits[b], bit_depth); 1076b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1077b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1078b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1079b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (bpp < 8 && bpp != bit_depth) 1080b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1081b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* sanity check; this is a grayscale PNG; something is wrong in the 1082b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * code above. 1083b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1084b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, INTERNAL_ERROR, "invalid bpp %u for bit_depth %u", 1085b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bpp, bit_depth); 1086b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1087b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1088b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari switch (bit_depth) 1089b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1090b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int b; 1091b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1092b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case 16: /* Two bytes per component, bit-endian */ 1093b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (b = (bpp >> 4); b > 0; ) 1094b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1095b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int sig = (unsigned int)(0xffff0000 >> sig_bits[b]); 1096b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1097b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[2*b+1] = (png_byte)sig; 1098b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[2*b+0] = (png_byte)(sig >> 8); /* big-endian */ 1099b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1100b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1101b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1102b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case 8: /* One byte per component */ 1103b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (b=0; b*8 < bpp; ++b) 1104b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[b] = (png_byte)(0xff00 >> sig_bits[b]); 1105b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1106b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1107b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case 1: /* allowed, but dumb */ 1108b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Value is 1 */ 1109b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[0] = 0xff; 1110b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1111b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1112b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case 2: /* Replicate 4 times */ 1113b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Value is 1 or 2 */ 1114b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari b = 0x3 & ((0x3<<2) >> sig_bits[0]); 1115b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari b |= b << 2; 1116b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari b |= b << 4; 1117b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[0] = (png_byte)b; 1118b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1119b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1120b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case 4: /* Relicate twice */ 1121b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Value is 1, 2, 3 or 4 */ 1122b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari b = 0xf & ((0xf << 4) >> sig_bits[0]); 1123b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari b |= b << 4; 1124b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari sig_bits[0] = (png_byte)b; 1125b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1126b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1127b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari default: 1128b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, LIBPNG_BUG, "invalid bit depth %d", bit_depth); 1129b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 1130b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1131b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1132b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Convert bpp to bytes; this gives '1' for low-bit depth grayscale, 1133b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * where there are multiple pixels per byte. 1134b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1135b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bpp = (bpp+7) >> 3; 1136b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1137b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* The mask can be combined with sig_bits[0] */ 1138b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (mask != 0) 1139b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1140b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari mask &= sig_bits[0]; 1141b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1142b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (bpp != 1 || mask == 0) 1143b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, INTERNAL_ERROR, "mask calculation error %u, %u", 1144b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bpp, mask); 1145b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1146b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1147b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (y=0; y<height; ++y) 1148b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1149b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytep row = rows[y]; 1150b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytep orig = dp->original_rows[y]; 1151b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned long x; 1152b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1153b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (x=0; x<(width-(mask!=0)); ++x) 1154b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1155b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int b; 1156b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1157b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (b=0; b<bpp; ++b) 1158b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1159b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((*row++ & sig_bits[b]) != (*orig++ & sig_bits[b])) 1160b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1161b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_FAIL, 1162b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari "significant bits at (%lu[%u],%lu) changed %.2x->%.2x", 1163b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari x, b, y, orig[-1], row[-1]); 1164b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 0; 1165b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1166b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1167b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1168b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1169b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (mask != 0 && (*row & mask) != (*orig & mask)) 1170b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1171b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_FAIL, 1172b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari "significant bits at (%lu[end],%lu) changed", x, y); 1173b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 0; 1174b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1175b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } /* for y */ 1176b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1177b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1178b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1179b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 1; /* compare succeeded */ 1180b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 1181b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1182b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SUPPORTED 1183b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 1184b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraribuffer_write(struct display *dp, struct buffer *buffer, png_bytep data, 1185b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_size_t size) 1186b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Generic write function used both from the write callback provided to 1187b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * libpng and from the generic read code. 1188b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1189b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 1190b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Write the data into the buffer, adding buffers as required */ 1191b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct buffer_list *last = buffer->last; 1192b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t end_count = buffer->end_count; 1193b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1194b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari while (size > 0) 1195b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1196b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size_t avail; 1197b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1198b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (end_count >= sizeof last->buffer) 1199b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1200b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (last->next == NULL) 1201b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1202b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari last = buffer_extend(last); 1203b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1204b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (last == NULL) 1205b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_ERROR, "out of memory saving file"); 1206b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1207b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1208b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1209b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari last = last->next; 1210b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1211b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->last = last; /* avoid the need to rewrite every time */ 1212b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari end_count = 0; 1213b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1214b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1215b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari avail = (sizeof last->buffer) - end_count; 1216b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (avail > size) 1217b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari avail = size; 1218b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1219b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari memcpy(last->buffer + end_count, data, avail); 1220b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari end_count += avail; 1221b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari size -= avail; 1222b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari data += avail; 1223b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1224b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1225b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer->end_count = end_count; 1226b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 1227b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1228b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void PNGCBAPI 1229b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariwrite_function(png_structp pp, png_bytep data, png_size_t size) 1230b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 1231b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer_write(get_dp(pp), get_buffer(pp), data, size); 1232b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 1233b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1234b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 1235b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariwrite_png(struct display *dp, png_infop ip, int transforms) 1236b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 1237b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_clean_write(dp); /* safety */ 1238b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1239b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari buffer_start_write(&dp->written_file); 1240b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->operation = "write"; 1241b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->transforms = transforms; 1242b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1243b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->write_pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, dp, 1244b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_error, display_warning); 1245b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1246b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (dp->write_pp == NULL) 1247b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, APP_ERROR, "failed to create write png_struct"); 1248b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1249b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_write_fn(dp->write_pp, &dp->written_file, write_function, 1250b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari NULL/*flush*/); 1251b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1252b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_SET_USER_LIMITS_SUPPORTED 1253b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Remove the user limits, if any */ 1254b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_user_limits(dp->write_pp, 0x7fffffff, 0x7fffffff); 1255b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1256b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1257b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Certain transforms require the png_info to be zapped to allow the 1258b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * transform to work correctly. 1259b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1260b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (transforms & (PNG_TRANSFORM_PACKING| 1261b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari PNG_TRANSFORM_STRIP_FILLER| 1262b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari PNG_TRANSFORM_STRIP_FILLER_BEFORE)) 1263b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1264b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int ct = dp->color_type; 1265b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1266b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (transforms & (PNG_TRANSFORM_STRIP_FILLER| 1267b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari PNG_TRANSFORM_STRIP_FILLER_BEFORE)) 1268b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ct &= ~PNG_COLOR_MASK_ALPHA; 1269b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1270b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_IHDR(dp->write_pp, ip, dp->width, dp->height, dp->bit_depth, ct, 1271b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->interlace_method, dp->compression_method, dp->filter_method); 1272b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1273b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1274b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_write_png(dp->write_pp, ip, transforms, NULL/*params*/); 1275b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1276b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Clean it on the way out - if control returns to the caller then the 1277b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * written_file contains the required data. 1278b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1279b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_clean_write(dp); 1280b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 1281b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* WRITE_SUPPORTED */ 1282b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1283b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int 1284b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariskip_transform(struct display *dp, int tr) 1285b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Helper to test for a bad combo and log it if it is skipped */ 1286b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 1287b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((dp->options & SKIP_BUGS) != 0 && is_bad_combo(tr)) 1288b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1289b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Log this to stdout if logging is on, otherwise just do an information 1290b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * display_log. 1291b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1292b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((dp->options & LOG_SKIPPED) != 0) 1293b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1294b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari printf("SKIP: %s transforms ", dp->filename); 1295b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1296b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari while (tr != 0) 1297b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1298b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int next = first_transform(tr); 1299b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari tr &= ~next; 1300b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1301b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari printf("%s", transform_name(next)); 1302b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (tr != 0) 1303b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari putchar('+'); 1304b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1305b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1306b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari putchar('\n'); 1307b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1308b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1309b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1310b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, INFORMATION, "%s: skipped known bad combo 0x%x", 1311b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->filename, tr); 1312b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1313b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 1; /* skip */ 1314b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1315b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1316b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 0; /* don't skip */ 1317b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 1318b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1319b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 1320b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraritest_one_file(struct display *dp, const char *filename) 1321b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 1322b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* First cache the file and update the display original file 1323b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * information for the new file. 1324b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1325b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->operation = "cache file"; 1326b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->transforms = 0; 1327b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_cache_file(dp, filename); 1328b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari update_display(dp); 1329b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1330b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* First test: if there are options that should be ignored for this file 1331b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * verify that they really are ignored. 1332b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1333b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (dp->ignored_transforms != 0) 1334b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1335b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari read_png(dp, &dp->original_file, "ignored transforms", 1336b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->ignored_transforms); 1337b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1338b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* The result should be identical to the original_rows */ 1339b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (!compare_read(dp, 0/*transforms applied*/)) 1340b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return; /* no point testing more */ 1341b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1342b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1343b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SUPPORTED 1344b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Second test: write the original PNG data out to a new file (to test the 1345b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * write side) then read the result back in and make sure that it hasn't 1346b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * changed. 1347b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1348b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->operation = "write"; 1349b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari write_png(dp, dp->original_ip, 0/*transforms*/); 1350b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari read_png(dp, &dp->written_file, NULL, 0/*transforms*/); 1351b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (!compare_read(dp, 0/*transforms applied*/)) 1352b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return; 1353b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 1354b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1355b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Third test: the active options. Test each in turn, or, with the 1356b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * EXHAUSTIVE option, test all possible combinations. 1357b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1358b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1359b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Use unsigned int here because the code below to increment through all 1360b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * the possibilities exhaustively has to use a compare and that must be 1361b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * unsigned, because some transforms are negative on a 16-bit system. 1362b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1363b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int active = dp->active_transforms; 1364b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari const int exhaustive = (dp->options & EXHAUSTIVE) != 0; 1365b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int current = first_transform(active); 1366b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int bad_transforms = 0; 1367b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int bad_combo = ~0U; /* bitwise AND of failing transforms */ 1368b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int bad_combo_list = 0; /* bitwise OR of failures */ 1369b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1370b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (;;) 1371b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1372b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari read_png(dp, &dp->original_file, "active transforms", current); 1373b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1374b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* If this involved any irreversible transformations then if we write 1375b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * it out with just the reversible transformations and read it in again 1376b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * with the same transforms we should get the same thing. At present 1377b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * this isn't done - it just seems like a waste of time and it would 1378b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * require two sets of read png_struct/png_info. 1379b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 1380b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * If there were no irreversible transformations then if we write it 1381b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * out and read it back in again (without the reversible transforms) 1382b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * we should get back to the place where we started. 1383b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1384b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SUPPORTED 1385b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((current & write_transforms) == current) 1386b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1387b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* All transforms reversible: write the PNG with the transformations 1388b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * reversed, then read it back in with no transformations. The 1389b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * result should be the same as the original apart from the loss of 1390b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * low order bits because of the SHIFT/sBIT transform. 1391b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1392b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->operation = "reversible transforms"; 1393b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari write_png(dp, dp->read_ip, current); 1394b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1395b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* And if this is read back in, because all the transformations were 1396b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * reversible, the result should be the same. 1397b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1398b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari read_png(dp, &dp->written_file, NULL, 0); 1399b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (!compare_read(dp, current/*for the SHIFT/sBIT transform*/)) 1400b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1401b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* This set of transforms failed. If a single bit is set - if 1402b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * there is just one transform - don't include this in further 1403b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 'exhaustive' tests. Notice that each transform is tested on 1404b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * its own before testing combos in the exhaustive case. 1405b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1406b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (is_combo(current)) 1407b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1408b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bad_combo &= current; 1409b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bad_combo_list |= current; 1410b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1411b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1412b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1413b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bad_transforms |= current; 1414b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1415b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1416b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 1417b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1418b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Now move to the next transform */ 1419b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (exhaustive) /* all combinations */ 1420b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1421b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int next = current; 1422b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1423b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari do 1424b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1425b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (next == read_transforms) /* Everything tested */ 1426b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari goto combo; 1427b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1428b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ++next; 1429b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } /* skip known bad combos if the relevant option is set; skip 1430b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * combos involving known bad single transforms in all cases. 1431b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1432b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari while ( (next & read_transforms) <= current 1433b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari || (next & active) == 0 /* skip cases that do nothing */ 1434b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari || (next & bad_transforms) != 0 1435b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari || skip_transform(dp, next)); 1436b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1437b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari assert((next & read_transforms) == next); 1438b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari current = next; 1439b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1440b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1441b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else /* one at a time */ 1442b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1443b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari active &= ~current; 1444b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1445b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (active == 0) 1446b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari goto combo; 1447b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1448b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari current = first_transform(active); 1449b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1450b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1451b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1452b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraricombo: 1453b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (dp->options & FIND_BAD_COMBOS) 1454b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1455b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* bad_combos identifies the combos that occur in all failing cases; 1456b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * bad_combo_list identifies transforms that do not prevent the 1457b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * failure. 1458b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1459b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (bad_combo != ~0U) 1460b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari printf("%s[0x%x]: PROBLEM: 0x%x[0x%x] ANTIDOTE: 0x%x\n", 1461b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari dp->filename, active, bad_combo, bad_combo_list, 1462b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari rw_transforms & ~bad_combo_list); 1463b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1464b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1465b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari printf("%s: no %sbad combos found\n", dp->filename, 1466b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (dp->options & SKIP_BUGS) ? "additional " : ""); 1467b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1468b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1469b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 1470b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1471b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int 1472b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurarido_test(struct display *dp, const char *file) 1473b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Exists solely to isolate the setjmp clobbers */ 1474b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 1475b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int ret = setjmp(dp->error_return); 1476b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1477b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (ret == 0) 1478b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1479b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari test_one_file(dp, file); 1480b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 0; 1481b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1482b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1483b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (ret < ERRORS) /* shouldn't longjmp on warnings */ 1484b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_log(dp, INTERNAL_ERROR, "unexpected return code %d", ret); 1485b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1486b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return ret; 1487b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 1488b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1489b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariint 1490b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurarimain(const int argc, const char * const * const argv) 1491b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 1492b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* For each file on the command line test it with a range of transforms */ 1493b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int option_end, ilog = 0; 1494b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari struct display d; 1495b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1496b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari validate_T(); 1497b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_init(&d); 1498b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1499b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (option_end=1; option_end<argc; ++option_end) 1500b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1501b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari const char *name = argv[option_end]; 1502b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1503b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (strcmp(name, "--verbose") == 0) 1504b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options = (d.options & ~LEVEL_MASK) | VERBOSE; 1505b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1506b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--warnings") == 0) 1507b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options = (d.options & ~LEVEL_MASK) | WARNINGS; 1508b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1509b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--errors") == 0) 1510b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options = (d.options & ~LEVEL_MASK) | ERRORS; 1511b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1512b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--quiet") == 0) 1513b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options = (d.options & ~LEVEL_MASK) | QUIET; 1514b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1515b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--exhaustive") == 0) 1516b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options |= EXHAUSTIVE; 1517b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1518b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--fast") == 0) 1519b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options &= ~EXHAUSTIVE; 1520b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1521b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--strict") == 0) 1522b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options |= STRICT; 1523b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1524b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--relaxed") == 0) 1525b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options &= ~STRICT; 1526b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1527b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--log") == 0) 1528b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1529b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ilog = option_end; /* prevent display */ 1530b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options |= LOG; 1531b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1532b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1533b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--nolog") == 0) 1534b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options &= ~LOG; 1535b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1536b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--continue") == 0) 1537b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options |= CONTINUE; 1538b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1539b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--stop") == 0) 1540b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options &= ~CONTINUE; 1541b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1542b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--skip-bugs") == 0) 1543b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options |= SKIP_BUGS; 1544b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1545b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--test-all") == 0) 1546b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options &= ~SKIP_BUGS; 1547b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1548b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--log-skipped") == 0) 1549b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options |= LOG_SKIPPED; 1550b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1551b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--nolog-skipped") == 0) 1552b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options &= ~LOG_SKIPPED; 1553b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1554b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--find-bad-combos") == 0) 1555b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options |= FIND_BAD_COMBOS; 1556b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1557b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (strcmp(name, "--nofind-bad-combos") == 0) 1558b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari d.options &= ~FIND_BAD_COMBOS; 1559b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1560b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (name[0] == '-' && name[1] == '-') 1561b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1562b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fprintf(stderr, "pngimage: %s: unknown option\n", name); 1563b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 99; 1564b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1565b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1566b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1567b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; /* Not an option */ 1568b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1569b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1570b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1571b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int i; 1572b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int errors = 0; 1573b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1574b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i=option_end; i<argc; ++i) 1575b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1576b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1577b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int ret = do_test(&d, argv[i]); 1578b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1579b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (ret > QUIET) /* abort on user or internal error */ 1580b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 99; 1581b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1582b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1583b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Here on any return, including failures, except user/internal issues 1584b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1585b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1586b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari const int pass = (d.options & STRICT) ? 1587b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari RESULT_STRICT(d.results) : RESULT_RELAXED(d.results); 1588b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1589b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (!pass) 1590b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari ++errors; 1591b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1592b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (d.options & LOG) 1593b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1594b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int j; 1595b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1596b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari printf("%s: pngimage ", pass ? "PASS" : "FAIL"); 1597b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1598b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (j=1; j<option_end; ++j) if (j != ilog) 1599b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari printf("%s ", argv[j]); 1600b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1601b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari printf("%s\n", d.filename); 1602b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1603b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1604b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1605b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display_clean(&d); 1606b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1607b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1608b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return errors != 0; 1609b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1610b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 1611b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else /* !PNG_INFO_IMAGE_SUPPORTED || !PNG_READ_SUPPORTED */ 1612b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariint 1613b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurarimain(void) 1614b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 1615b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari fprintf(stderr, "pngimage: no support for png_read/write_image\n"); 1616b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 77; 1617b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 1618b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 1619