Exemplo n.º 1
0
int
main(int argc, char **argv)
{
    static char *usage="Usage:\n\t%s png__file\n";

    int i;
    FILE *fp_in = NULL;
    png_structp png_p;
    png_infop info_p;
    char header[8];
    int bit_depth;
    int color_type;
    png_color_16p input_backgrd;
    double gammaval;
    int file_width, file_height;
    png_int_32 xoff, yoff;
    png_uint_32 xres, yres;
    int unit_type;
    int rgb_intent;
    double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
    png_timep mod_time;
    png_textp text;
    int num_text;
    unsigned char *image;
    unsigned char **rows;

    if (argc != 2) {
	bu_log(usage, argv[0]);
	bu_exit(EXIT_FAILURE, "Incorrect number of arguments!!\n");
    } else {
	if ((fp_in = fopen(argv[1], "rb")) == NULL) {
	    perror(argv[1]);
	    bu_log("png_onfo: cannot open \"%s\" for reading\n",
		   argv[1]);
	    bu_exit(EXIT_FAILURE, "Cannot open input file\n");
	}
    }

    if (fread(header, 8, 1, fp_in) != 1)
	bu_exit(EXIT_FAILURE, "ERROR: Failed while reading file header!!!\n");

    if (png_sig_cmp((png_bytep)header, 0, 8))
	bu_exit(EXIT_FAILURE, "This is not a PNG file!!!\n");

    png_p = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_p)
	bu_exit(EXIT_FAILURE, "png_create_read_struct() failed!!\n");

    info_p = png_create_info_struct(png_p);
    if (!info_p)
	bu_exit(EXIT_FAILURE, "png_create_info_struct() failed!!\n");

    png_init_io(png_p, fp_in);

    png_set_sig_bytes(png_p, 8);

    png_read_info(png_p, info_p);

    color_type = png_get_color_type(png_p, info_p);

    bit_depth = png_get_bit_depth(png_p, info_p);

    switch (color_type) {
	case PNG_COLOR_TYPE_GRAY:
	    bu_log("color type: b/w (bit depth=%d)\n", bit_depth);
	    break;
	case PNG_COLOR_TYPE_GRAY_ALPHA:
	    bu_log("color type: b/w with alpha channel (bit depth=%d)\n", bit_depth);
	    break;
	case PNG_COLOR_TYPE_PALETTE:
	    bu_log("color type: color palette (bit depth=%d)\n", bit_depth);
	    break;
	case PNG_COLOR_TYPE_RGB:
	    bu_log("color type: RGB (bit depth=%d)\n", bit_depth);
	    break;
	case PNG_COLOR_TYPE_RGB_ALPHA:
	    bu_log("color type: RGB with alpha channel (bit depth=%d)\n", bit_depth);
	    break;
	default:
	    bu_log("Unrecognized color type (bit depth=%d)\n", bit_depth);
	    break;
    }

    file_width = png_get_image_width(png_p, info_p);
    file_height = png_get_image_height(png_p, info_p);

    bu_log("Image size: %d X %d\n", file_width, file_height);

    /* allocate memory for image */
    image = (unsigned char *)bu_calloc(1, file_width*file_height*3, "image");

    /* create rows array */
    rows = (unsigned char **)bu_calloc(file_height, sizeof(unsigned char *), "rows");
    for (i=0; i<file_height; i++)
	rows[file_height-1-i] = image+(i*file_width*3);

    png_read_image(png_p, rows);

    if (png_get_oFFs(png_p, info_p, &xoff, &yoff, &unit_type)) {
	if (unit_type == PNG_OFFSET_PIXEL)
	    bu_log("X Offset: %d pixels\nY Offset: %d pixels\n", (int)xoff, (int)yoff);
	else if (unit_type == PNG_OFFSET_MICROMETER)
	    bu_log("X Offset: %d um\nY Offset: %d um\n", (int)xoff, (int)yoff);
    }

    if (png_get_pHYs(png_p, info_p, &xres, &yres, &unit_type)) {
	if (unit_type == PNG_RESOLUTION_UNKNOWN)
	    bu_log("Aspect ratio: %g (width/height)\n", (double)xres/(double)yres);
	else if (unit_type == PNG_RESOLUTION_METER)
	    bu_log("pixel density:\n\t%d pixels/m horizontal\n\t%d pixels/m vertical\n",
		   (int)xres, (int)yres);
    }

    if (png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE)
	bu_log("not interlaced\n");
    else
	bu_log("interlaced\n");

    if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
	color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	if (png_get_bKGD(png_p, info_p, &input_backgrd))
	    bu_log("background color: %d %d %d\n", input_backgrd->red, input_backgrd->green, input_backgrd->blue);

    if (png_get_sRGB(png_p, info_p, &rgb_intent)) {
	bu_log("rendering intent: ");
	switch (rgb_intent) {
	    case PNG_sRGB_INTENT_SATURATION:
		bu_log("saturation\n");
		break;
	    case PNG_sRGB_INTENT_PERCEPTUAL:
		bu_log("perceptual\n");
		break;
	    case PNG_sRGB_INTENT_ABSOLUTE:
		bu_log("absolute\n");
		break;
	    case PNG_sRGB_INTENT_RELATIVE:
		bu_log("relative\n");
		break;
	}
    }

    if (png_get_gAMA(png_p, info_p, &gammaval))
	bu_log("gamma: %g\n", gammaval);

#if defined(PNG_READ_cHRM_SUPPORTED)
    if (png_get_cHRM(png_p, info_p, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) {
	bu_log("Chromaticity:\n");
	bu_log("\twhite point\t(%g %g)\n\tred\t(%g %g)\n\tgreen\t(%g %g)\n\tblue\t(%g %g)\n",
	       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
    }
#endif

    if (png_get_text(png_p, info_p, &text, &num_text))
	for (i=0; i<num_text; i++)
	    bu_log("%s: %s\n", text[i].key, text[i].text);

    if (png_get_tIME(png_p, info_p, &mod_time))
	bu_log("Last modified: %d/%d/%d %d:%d:%d\n", mod_time->month, mod_time->day,
	       mod_time->year, mod_time->hour, mod_time->minute, mod_time->second);
    return 0;
}
Exemplo n.º 2
0
// Get the chunk information of the PNG file. IDAT is marked as existing, only after decoding or reading the header.
// Bits (if set indicates existence of the chunk):
// 0  - gAMA
// 1  - sBIT
// 2  - cHRM
// 3  - PLTE
// 4  - tRNS
// 5  - bKGD
// 6  - hIST
// 7  - pHYs
// 8  - oFFs
// 9  - tIME
// 10 - pCAL
// 11 - sRGB
// 12 - iCCP
// 13 - sPLT
// 14 - sCAL
// 15 - IDAT
// 16:30 - reserved
be_t<u32> pngDecGetChunkInformation(PStream stream, bool IDAT = false)
{
	// The end result of the chunk information (bigger-endian)
	be_t<u32> chunk_information = 0;

	// Needed pointers for getting the chunk information
	f64 gamma;
	f64 red_x;
	f64 red_y;
	f64 green_x;
	f64 green_y;
	f64 blue_x;
	f64 blue_y;
	f64 white_x;
	f64 white_y;
	f64 width;
	f64 height;
	s32 intent;
	s32 num_trans;
	s32 num_palette;
	s32 unit_type;
	s32 type;
	s32 nparams;
	s32 compression_type;
	s32 unit;
	u16* hist;
	u32 proflen;
	png_bytep profile;
	png_bytep trans_alpha;
	png_charp units;
	png_charp name;
	png_charp purpose;
	png_charpp params;
	png_int_32 X0;
	png_int_32 X1;
	png_int_32 offset_x;
	png_int_32 offset_y;
	png_uint_32 res_x;
	png_uint_32 res_y;
	png_colorp palette;
	png_color_8p sig_bit;
	png_color_16p background;
	png_color_16p trans_color;
	png_sPLT_tp entries;
	png_timep mod_time;

	// Get chunk information and set the appropriate bits
	if (png_get_gAMA(stream->png_ptr, stream->info_ptr, &gamma))
	{
		chunk_information |= 1 << 0; // gAMA
	}

	if (png_get_sBIT(stream->png_ptr, stream->info_ptr, &sig_bit))
	{
		chunk_information |= 1 << 1; // sBIT
	}

	if (png_get_cHRM(stream->png_ptr, stream->info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y))
	{
		chunk_information |= 1 << 2; // cHRM
	}

	if (png_get_PLTE(stream->png_ptr, stream->info_ptr, &palette, &num_palette))
	{
		chunk_information |= 1 << 3; // PLTE
	}

	if (png_get_tRNS(stream->png_ptr, stream->info_ptr, &trans_alpha, &num_trans, &trans_color))
	{
		chunk_information |= 1 << 4; // tRNS
	}

	if (png_get_bKGD(stream->png_ptr, stream->info_ptr, &background))
	{
		chunk_information |= 1 << 5; // bKGD
	}

	if (png_get_hIST(stream->png_ptr, stream->info_ptr, &hist))
	{
		chunk_information |= 1 << 6; // hIST
	}

	if (png_get_pHYs(stream->png_ptr, stream->info_ptr, &res_x, &res_y, &unit_type))
	{
		chunk_information |= 1 << 7; // pHYs
	}

	if (png_get_oFFs(stream->png_ptr, stream->info_ptr, &offset_x, &offset_y, &unit_type))
	{
		chunk_information |= 1 << 8; // oFFs
	}

	if (png_get_tIME(stream->png_ptr, stream->info_ptr, &mod_time))
	{
		chunk_information |= 1 << 9; // tIME
	}

	if (png_get_pCAL(stream->png_ptr, stream->info_ptr, &purpose, &X0, &X1, &type, &nparams, &units, &params))
	{
		chunk_information |= 1 << 10; // pCAL
	}

	if (png_get_sRGB(stream->png_ptr, stream->info_ptr, &intent))
	{
		chunk_information |= 1 << 11; // sRGB
	}

	if (png_get_iCCP(stream->png_ptr, stream->info_ptr, &name, &compression_type, &profile, &proflen))
	{
		chunk_information |= 1 << 12; // iCCP
	}

	if (png_get_sPLT(stream->png_ptr, stream->info_ptr, &entries))
	{
		chunk_information |= 1 << 13; // sPLT
	}

	if (png_get_sCAL(stream->png_ptr, stream->info_ptr, &unit, &width, &height))
	{
		chunk_information |= 1 << 14; // sCAL
	}

	if (IDAT)
	{
		chunk_information |= 1 << 15; // IDAT
	}

	return chunk_information;
}
Exemplo n.º 3
0
int main( int argc, char *argv[] ) {
	int f, rowbytes;
	char buf[256];
	static FILE *fpout;  /* "static" prevents setjmp corruption */
	png_structp write_ptr;
	png_infop write_info_ptr, end_info_ptr;
	png_bytep row_buf, here;
	png_uint_32 y;
	png_textp text_ptr, new_text_ptr;
	int num_text;

	int interlace_type, compression_type, filter_type, bit_depth, color_type;
	int it, ct, ft, bd, clrt;
	png_uint_32 width, height, w, h;

	int duration;

	if( argc < 4 ) {
		printf( "makeanim v0.2\nusage: makeanim <duration in milliseconds> <input files ...> <output file>\n" );
		printf( "example: makeanim 1500 a00.png a01.png a02.png a03.png a04.png a.anim\n" );
		return 1;
		}

	duration = atoi( argv[1] );
	if( duration < 1 ) {
		printf( "duration is incorrect\n" );
		return 1;
		}

	numfiles = argc - 3;
	input = (struct inputstruct *)malloc( sizeof( struct inputstruct ) * numfiles );
	if( !input ) return 1;

	for( f = 0; f < numfiles; f++ ) {
		input[f].name = argv[f + 2];
		printf( "opening file %d, \"%s\"\n", f, input[f].name );

		/* open the file handle */
		input[f].file = fopen( input[f].name, "rb" );
		if( input[f].file == NULL ) {
			printf( "fopen() failed\n" );
			return 1;
			}

		/* check if it's PNG */
		if( fread( buf, 1, 8, input[f].file ) != 8 ) {
			printf( "fread() failed for file \"%s\"\n", input[f].name );
			return 1;
			}
		if( png_sig_cmp( buf, (png_size_t)0, 8 ) ) {
			printf( "not a PNG file\n" );
			return 1;
			}
		fseek( input[f].file, 0, SEEK_SET );

		/* allocate read structure */
		input[f].read_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL );
		if( input[f].read_ptr == NULL ) {
			printf( "png_create_read_struct() failed\n" );
			return 1;
			}
		
		/* allocate read info structure */
		input[f].read_info_ptr = png_create_info_struct( input[f].read_ptr );
		if( input[f].read_info_ptr == NULL ) {
			printf( "png_create_info_struct() failed\n" );
			return 1;
			}


		/* set error handler code */
		if( setjmp( input[f].read_ptr->jmpbuf ) ) {
			printf( "libpng read error\n" );
			return 1;
			}

		/* initialize stream */
		png_init_io( input[f].read_ptr, input[f].file );
		png_set_read_status_fn( input[f].read_ptr, NULL );

		/* read png info struct */
		png_read_info( input[f].read_ptr, input[f].read_info_ptr );

		/* get the info */
		if( !png_get_IHDR( input[f].read_ptr, input[f].read_info_ptr, &w, &h, &bd, &clrt, &it, &ct, &ft ) ) {
			printf( "png_get_IHDR() failed\n" );
			return 1;
			}

		/* save the info of the first frame */
		if( f == 0 ) {
			width = w;
			height = h;
			bit_depth = bd;
			color_type = clrt;
			interlace_type = it;
			compression_type = ct;
			filter_type = ft;
			}
		/* compare all other frames to first frame */
		else if( (w != width) ||
				(h != height) ||
				(bd != bit_depth) ||
				(clrt != color_type) ||
				(it != interlace_type) ||
				(ct != compression_type) ||
				(ft != filter_type) ) {
			if( w != width ) printf( "width is different\n" );
			if( h != height ) printf( "height  is different\n" );
			if( bd != bit_depth ) printf( "bit depth is different\n" );
			if( clrt != color_type ) printf( "color type is different\n" );
			if( it != interlace_type ) printf( "interlace type is different\n" );
			if( ct != compression_type ) printf( "compression type is different\n" );
			if( ft != filter_type ) printf( "filter type is different\n" );
			return 1;
			}
		}
	
	row_buf = (png_bytep)NULL;
	
	/* open output file */
	printf( "opening file \"%s\"\n", argv[numfiles + 2] );
	fpout = fopen( argv[numfiles + 2], "wb" );
	if( fpout == NULL ) {
		printf( "fopen() failed\n" );
		return 1;
		}

	/* allocate write structure */
	write_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, (png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL );

	/* allocate info structures */
	write_info_ptr = png_create_info_struct( write_ptr );
	end_info_ptr = png_create_info_struct( write_ptr );

	/* error handling */
	if( setjmp( write_ptr->jmpbuf ) ) {
		printf( "libpng write error\n" );
		return 1;
		}

	/* initialize output stream */
	png_init_io( write_ptr, fpout );
	png_set_write_status_fn( write_ptr, NULL );

	/* set info */
	png_set_IHDR( write_ptr, write_info_ptr, width * numfiles, height, bit_depth, color_type, PNG_INTERLACE_NONE, compression_type, filter_type);

	/* image characteristics */
	{
		png_color_16p background;
		double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
		double gamma;
		int intent;
		png_uint_16p hist;
		png_uint_32 offset_x, offset_y;
		int unit_type;
		png_charp purpose, units;
		png_charpp params;
		png_int_32 X0, X1;
		int type, nparams;
		png_uint_32 res_x, res_y;
		png_colorp palette;
		int num_palette;
		png_color_8p sig_bit;
		png_bytep trans;
		int num_trans;
		png_color_16p trans_values;

		/* background color */
		if( png_get_bKGD( input[0].read_ptr, input[0].read_info_ptr, &background ) ) {
			png_set_bKGD( write_ptr, write_info_ptr, background );
			}

		if( png_get_cHRM( input[0].read_ptr, input[0].read_info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y ) ) {
			png_set_cHRM( write_ptr, write_info_ptr, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y );
			}

		/* gamma */
		if( png_get_gAMA( input[0].read_ptr, input[0].read_info_ptr, &gamma ) ) {
			png_set_gAMA( write_ptr, write_info_ptr, gamma );
			}

		/* rendering intent */
		if( png_get_sRGB( input[0].read_ptr, input[0].read_info_ptr, &intent ) ) {
			png_set_sRGB( write_ptr, write_info_ptr, intent );
			}

		/* Histogram */
		if( png_get_hIST( input[0].read_ptr, input[0].read_info_ptr, &hist ) ) {
			png_set_hIST( write_ptr, write_info_ptr, hist );
			}

		/* offsets */
		if( png_get_oFFs( input[0].read_ptr, input[0].read_info_ptr, &offset_x, &offset_y, &unit_type ) ) {
			png_set_oFFs( write_ptr, write_info_ptr, offset_x, offset_y, unit_type );
			}

		if( png_get_pCAL( input[0].read_ptr, input[0].read_info_ptr, &purpose, &X0, &X1, &type, &nparams, &units, &params ) ) {
			png_set_pCAL( write_ptr, write_info_ptr, purpose, X0, X1, type, nparams, units, params );
			}

		/* pixel density */
		if( png_get_pHYs( input[0].read_ptr, input[0].read_info_ptr, &res_x, &res_y, &unit_type ) ) {
			png_set_pHYs( write_ptr, write_info_ptr, res_x, res_y, unit_type );
			}

		/* text chunks */
/*		if( png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) > 0 ) {
			printf( "Handling %d tEXt/zTXt chunks\n", num_text );
			png_set_text( write_ptr, write_info_ptr, text_ptr, num_text );
			}
*/
		/* palette */
		if( png_get_PLTE( input[0].read_ptr, input[0].read_info_ptr, &palette, &num_palette ) ) {
			png_set_PLTE( write_ptr, write_info_ptr, palette, num_palette );
			}

		/* significant bits */
		if( png_get_sBIT( input[0].read_ptr, input[0].read_info_ptr, &sig_bit ) ) {
			png_set_sBIT( write_ptr, write_info_ptr, sig_bit );
			}

		/* transparency */
		if( png_get_tRNS( input[0].read_ptr, input[0].read_info_ptr, &trans, &num_trans, &trans_values ) ) {
			png_set_tRNS( write_ptr, write_info_ptr, trans, num_trans, trans_values );
			}
		}

	/* text chunks */
	num_text = 0;
	if( !png_get_text( input[0].read_ptr, input[0].read_info_ptr, &text_ptr, &num_text ) ) num_text = 0;
	new_text_ptr = (struct png_text_struct *)malloc( sizeof( struct png_text_struct ) * num_text + 1 );
	if( !new_text_ptr ) {
		printf( "malloc() failed\n" );
		return 1;
		}
	
	memcpy( new_text_ptr, text_ptr, sizeof( struct png_text_struct ) * num_text );

	snprintf( buf, 255, "SDL_anim %d %d %d", duration, width, numfiles );
	buf[255] = 0;
	new_text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
	new_text_ptr[num_text].key = "format";
	new_text_ptr[num_text].text = buf;
	new_text_ptr[num_text].text_length = strlen( buf );
	num_text++;
	png_set_text( write_ptr, write_info_ptr, new_text_ptr, num_text );

	/* write info */
	png_write_info( write_ptr, write_info_ptr );

	/* allocate buffer */
	rowbytes = png_get_rowbytes( input[0].read_ptr, input[0].read_info_ptr );
	row_buf = (png_bytep)png_malloc( write_ptr, rowbytes * numfiles );
	if( row_buf == NULL ) {
		printf( "png_malloc() failed\n" );
		return 1;
		}

	/* copy raw data */
	for( y = 0; y < height; y++ ) {
		/* grab a scanline from each file */
		here = row_buf;
		for( f = 0; f < numfiles; f++ ) {
			png_read_rows( input[f].read_ptr, (png_bytepp)&here, (png_bytepp)NULL, 1 );
			here += rowbytes;
			}
		/* write the long scanline */
		png_write_rows( write_ptr, (png_bytepp)&row_buf, 1 );
		}

	/* end io */
	for( f = 0; f < numfiles; f++ ) png_read_end( input[f].read_ptr, end_info_ptr );
	png_write_end( write_ptr, end_info_ptr );

	/* cleanup */
	png_free( write_ptr, row_buf );
	for( f = 0; f < numfiles; f++ ) {
		png_destroy_read_struct( &input[f].read_ptr, &input[f].read_info_ptr, &end_info_ptr);
		fclose( input[f].file );
		}
	png_destroy_write_struct( &write_ptr, &write_info_ptr );
	fclose( fpout );

	return 0;
	}
/*!
    \internal
*/
bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage)
{
    if (state == Error)
        return false;

    if (state == Ready && !readPngHeader()) {
        state = Error;
        return false;
    }

    row_pointers = 0;
    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        delete [] row_pointers;
        png_ptr = 0;
        state = Error;
        return false;
    }

    setup_qt(*outImage, png_ptr, info_ptr, gamma);

    if (outImage->isNull()) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        delete [] row_pointers;
        png_ptr = 0;
        state = Error;
        return false;
    }

    png_uint_32 width = 0;
    png_uint_32 height = 0;
    png_int_32 offset_x = 0;
    png_int_32 offset_y = 0;
    int bit_depth = 0;
    int color_type = 0;
    int unit_type = PNG_OFFSET_PIXEL;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                 0, 0, 0);
    png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);

    uchar *data = outImage->bits();
    int bpl = outImage->bytesPerLine();
    row_pointers = new png_bytep[height];

    for (uint y = 0; y < height; y++)
        row_pointers[y] = data + y * bpl;

    png_read_image(png_ptr, row_pointers);

#if 0 // libpng takes care of this.
    png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)
        if (outImage->depth()==32 && png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
            QRgb trans = 0xFF000000 | qRgb(
                (info_ptr->trans_values.red << 8 >> bit_depth)&0xff,
                (info_ptr->trans_values.green << 8 >> bit_depth)&0xff,
                (info_ptr->trans_values.blue << 8 >> bit_depth)&0xff);
            for (uint y=0; y<height; y++) {
                for (uint x=0; x<info_ptr->width; x++) {
                    if (((uint**)jt)[y][x] == trans) {
                        ((uint**)jt)[y][x] &= 0x00FFFFFF;
                    } else {
                    }
                }
            }
        }
Exemplo n.º 5
0
bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage)
{
    if (state == Error)
        return false;

    if (state == Ready && !readPngHeader()) {
        state = Error;
        return false;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        png_ptr = 0;
        amp.deallocate();
        state = Error;
        return false;
    }

    bool doScaledRead = false;
    setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma, fileGamma);

    if (outImage->isNull()) {
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        png_ptr = 0;
        amp.deallocate();
        state = Error;
        return false;
    }

    if (doScaledRead) {
        read_image_scaled(outImage, png_ptr, info_ptr, amp, scaledSize);
    } else {
        png_uint_32 width = 0;
        png_uint_32 height = 0;
        png_int_32 offset_x = 0;
        png_int_32 offset_y = 0;

        int bit_depth = 0;
        int color_type = 0;
        int unit_type = PNG_OFFSET_PIXEL;
        png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
        png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);
        uchar *data = outImage->bits();
        int bpl = outImage->bytesPerLine();
        amp.row_pointers = new png_bytep[height];

        for (uint y = 0; y < height; y++)
            amp.row_pointers[y] = data + y * bpl;

        png_read_image(png_ptr, amp.row_pointers);
        amp.deallocate();

        outImage->setDotsPerMeterX(png_get_x_pixels_per_meter(png_ptr,info_ptr));
        outImage->setDotsPerMeterY(png_get_y_pixels_per_meter(png_ptr,info_ptr));

        if (unit_type == PNG_OFFSET_PIXEL)
            outImage->setOffset(QPoint(offset_x, offset_y));

        // sanity check palette entries
        if (color_type == PNG_COLOR_TYPE_PALETTE && outImage->format() == QImage::Format_Indexed8) {
            int color_table_size = outImage->colorCount();
            for (int y=0; y<(int)height; ++y) {
                uchar *p = FAST_SCAN_LINE(data, bpl, y);
                uchar *end = p + width;
                while (p < end) {
                    if (*p >= color_table_size)
                        *p = 0;
                    ++p;
                }
            }
        }
    }

    state = ReadingEnd;
    png_read_end(png_ptr, end_info);

    readPngTexts(end_info);
    for (int i = 0; i < readTexts.size()-1; i+=2)
        outImage->setText(readTexts.at(i), readTexts.at(i+1));

    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    png_ptr = 0;
    amp.deallocate();
    state = Ready;

    if (scaledSize.isValid() && outImage->size() != scaledSize)
        *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

    return true;
}
Exemplo n.º 6
0
static void read_image_scaled(QImage *outImage, png_structp png_ptr, png_infop info_ptr,
                              QPngHandlerPrivate::AllocatedMemoryPointers &amp, QSize scaledSize)
{

    png_uint_32 width = 0;
    png_uint_32 height = 0;
    png_int_32 offset_x = 0;
    png_int_32 offset_y = 0;

    int bit_depth = 0;
    int color_type = 0;
    int unit_type = PNG_OFFSET_PIXEL;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
    png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);
    uchar *data = outImage->bits();
    int bpl = outImage->bytesPerLine();

    if (scaledSize.isEmpty() || !width || !height)
        return;

    const quint32 iysz = height;
    const quint32 ixsz = width;
    const quint32 oysz = scaledSize.height();
    const quint32 oxsz = scaledSize.width();
    const quint32 ibw = 4*width;
    amp.accRow = new quint32[ibw];
    memset(amp.accRow, 0, ibw*sizeof(quint32));
    amp.inRow = new png_byte[ibw];
    memset(amp.inRow, 0, ibw*sizeof(png_byte));
    amp.outRow = new uchar[ibw];
    memset(amp.outRow, 0, ibw*sizeof(uchar));
    qint32 rval = 0;
    for (quint32 oy=0; oy<oysz; oy++) {
        // Store the rest of the previous input row, if any
        for (quint32 i=0; i < ibw; i++)
            amp.accRow[i] = rval*amp.inRow[i];
        // Accumulate the next input rows
        for (rval = iysz-rval; rval > 0; rval-=oysz) {
            png_read_row(png_ptr, amp.inRow, NULL);
            quint32 fact = qMin(oysz, quint32(rval));
            for (quint32 i=0; i < ibw; i++)
                amp.accRow[i] += fact*amp.inRow[i];
        }
        rval *= -1;

        // We have a full output row, store it
        for (quint32 i=0; i < ibw; i++)
            amp.outRow[i] = uchar(amp.accRow[i]/iysz);

        quint32 a[4] = {0, 0, 0, 0};
        qint32 cval = oxsz;
        quint32 ix = 0;
        for (quint32 ox=0; ox<oxsz; ox++) {
            for (quint32 i=0; i < 4; i++)
                a[i] = cval * amp.outRow[ix+i];
            for (cval = ixsz - cval; cval > 0; cval-=oxsz) {
                ix += 4;
                if (ix >= ibw)
                    break;            // Safety belt, should not happen
                quint32 fact = qMin(oxsz, quint32(cval));
                for (quint32 i=0; i < 4; i++)
                    a[i] += fact * amp.outRow[ix+i];
            }
            cval *= -1;
            for (quint32 i=0; i < 4; i++)
                data[(4*ox)+i] = uchar(a[i]/ixsz);
        }
        data += bpl;
    }
    amp.deallocate();

    outImage->setDotsPerMeterX((png_get_x_pixels_per_meter(png_ptr,info_ptr)*oxsz)/ixsz);
    outImage->setDotsPerMeterY((png_get_y_pixels_per_meter(png_ptr,info_ptr)*oysz)/iysz);

    if (unit_type == PNG_OFFSET_PIXEL)
        outImage->setOffset(QPoint(offset_x*oxsz/ixsz, offset_y*oysz/iysz));

}
Exemplo n.º 7
0
//---------------------------------------------------------------------------
void __fastcall TDeePNG::LoadFromStream(Classes::TStream * Stream)
{
	// LoadFromStream

	png_structp png_ptr = NULL;
	png_infop info_ptr = NULL;
	png_infop end_info = NULL;

	png_bytep *row_pointers = NULL;
	BYTE *image = NULL;

	png_uint_32 i;

	try
	{
		// create png_struct
		png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING,
			(png_voidp)this, DeePNG_error, DeePNG_warning,
			(png_voidp)this, DeePNG_malloc, DeePNG_free);

		// set read_chunk_callback
		png_set_read_user_chunk_fn(png_ptr,
			reinterpret_cast<void*>(this),
			PNG_read_chunk_callback);
		png_set_keep_unknown_chunks(png_ptr, 2, NULL, 0);
			// keep only if safe-to-copy chunks, for all unknown chunks

		// create png_info
		info_ptr = png_create_info_struct(png_ptr);

		// create end_info
		end_info = png_create_info_struct(png_ptr);

		// set stream input functions
		png_set_read_fn(png_ptr, (voidp)Stream, DeePNG_read_data);

		// set read_row_callback
		png_set_read_status_fn(png_ptr, DeePNG_read_row_callback);

		// call png_read_info
		png_read_info(png_ptr, info_ptr);

		// retrieve IHDR
		png_uint_32 width, height;
		int bit_depth, color_type, interlace_type, compression_type, filter_type;
		png_get_IHDR(png_ptr,info_ptr, &width, &height, &bit_depth, &color_type,
			&interlace_type, &compression_type, &filter_type);

		// expand palletted image which has transparent color, to 32bpp
		if (png_get_valid(png_ptr, info_ptr,PNG_INFO_tRNS))
		{
			png_set_expand(png_ptr);
			color_type=PNG_COLOR_TYPE_RGB_ALPHA;
		}

		// analyse IHDR ( color_type )
		switch(color_type)
		{
		case PNG_COLOR_TYPE_GRAY_ALPHA:
			PixelFormat=pf32bit;
			break;
		case PNG_COLOR_TYPE_GRAY:
			// w/b
			SetGrayscalePalette(this,bit_depth);
			break;
		case PNG_COLOR_TYPE_PALETTE:
			SetColorDepth(this,bit_depth);
			break;
		case PNG_COLOR_TYPE_RGB_ALPHA:
			PixelFormat=pf32bit;
			break;
		case PNG_COLOR_TYPE_RGB:
			PixelFormat=pf24bit;
			break;
		default:
			throw EDeePNG("EDeePNG : Non-supported color type.");
		}

		// retrieve offset information
		png_int_32 offset_x, offset_y;
		int offset_unit_type;
		if(png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &offset_unit_type))
		{
			ofs_x = offset_x;
			ofs_y = offset_y;
			ofs_unit = offset_unit_type;
			ofs_set = true;
		}
		else
		{
			ofs_set = false;
		}

		// check size
		if(width>=65536 || height>=65536)
		{
			throw EDeePNG("EDeePNG : Too large image size.");
		}


		// retrieve palette
		if(color_type == PNG_COLOR_TYPE_PALETTE)
		{
			int num_palette;
			png_color *palette = NULL;
			png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);

			int i;
		#pragma pack(push, 1)
			struct
			{
				WORD	palVersion;
				WORD	palNumEntries;
				PALETTEENTRY entry[256];
			} pal;
		#pragma pack(pop)
			pal.palVersion = 0x300;
			pal.palNumEntries = num_palette;
			for(i = 0; i < num_palette; i++)
			{
				pal.entry[i].peRed = palette[i].red;
				pal.entry[i].peGreen = palette[i].green;
				pal.entry[i].peBlue = palette[i].blue;
				pal.entry[i].peFlags = 0;
			}
			Palette = CreatePalette((const LOGPALETTE*)&pal);
		}

		// collapse 16bit precision data to 8bit
		if(bit_depth == 16) png_set_strip_16(png_ptr);

		// change color component order
		if (color_type == PNG_COLOR_TYPE_RGB ||
			color_type == PNG_COLOR_TYPE_RGB_ALPHA)
				png_set_bgr(png_ptr);

		// call png_read_update_info ...
		png_read_update_info(png_ptr, info_ptr);

		// set size
		Width=width, Height=height;

		// allocate memory for row_pointers
		row_pointers = new png_bytep[height];
		png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
		image = new BYTE[rowbytes*height];
		for(i = 0;i < height; i++)
		{
			row_pointers[i] = image + i*rowbytes;
		}

		// load image
		png_read_image(png_ptr, row_pointers);

		// finish loading image
		png_read_end(png_ptr, info_ptr);

		// set image to ScanLines

		BYTE *imageptr = image;
		if(color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		{
			// IA IA IA ....

			for(i = 0; i < height; i++)
			{
				BYTE *scanptr = (BYTE*)ScanLine[i];
				png_uint_32 j;
				for(j = 0; j < width; j++)
				{
					BYTE i = *(imageptr++);
					scanptr[0] = i;
					scanptr[1] = i;
					scanptr[2] = i;
					scanptr[3] = *(imageptr++);
					scanptr += 4;
				}
			}
		}
		else
		{
			// intact copy

			for(i = 0; i < height; i++)
			{
				BYTE *scanptr = (BYTE*)ScanLine[i];
				memcpy(scanptr, imageptr, rowbytes);
				imageptr += rowbytes;
			}


		}
	}
	catch(...)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		if(row_pointers) delete [] row_pointers;
		if(image) delete [] image;
		throw;
	}

	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	if(row_pointers) delete [] row_pointers;
	if(image) delete [] image;
}