Exemple #1
0
PSD
GdDecodePNG(buffer_t * src)
{
	unsigned char hdr[8], **rows;
	png_structp state;
	png_infop pnginfo;
	png_uint_32 width, height;
	int bit_depth, color_type, i;
	double file_gamma;
	int channels, data_format;
	PSD pmd;

	GdImageBufferSeekTo(src, 0UL);

	if(GdImageBufferRead(src, hdr, 8) != 8)
		return NULL;

	if(png_sig_cmp(hdr, 0, 8))
		return NULL;

	if(!(state = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
		goto nomem;

	if(!(pnginfo = png_create_info_struct(state))) {
		png_destroy_read_struct(&state, NULL, NULL);
		goto nomem;
	}

	if(setjmp(png_jmpbuf(state))) {
		png_destroy_read_struct(&state, &pnginfo, NULL);
		return NULL;
	}

	/* Set up the input function */
	png_set_read_fn(state, src, png_read_buffer);
	/* png_init_io(state, src); */

	png_set_sig_bytes(state, 8);

	png_read_info(state, pnginfo);
	png_get_IHDR(state, pnginfo, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

	/* set-up the transformations */
	/* transform paletted images into full-color rgb */
	if (color_type == PNG_COLOR_TYPE_PALETTE)
	    png_set_expand (state);

	/* expand images to bit-depth 8 (only applicable for grayscale images) */
	if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
	    png_set_expand (state);

	/* transform transparency maps into full alpha-channel */
	if (png_get_valid (state, pnginfo, PNG_INFO_tRNS))
	    png_set_expand (state);

	/* downgrade 16-bit images to 8 bit */
	if (bit_depth == 16)
	    png_set_strip_16 (state);

	/* Handle transparency... */
	if (png_get_valid(state, pnginfo, PNG_INFO_tRNS))
	    png_set_tRNS_to_alpha(state);

	/* transform grayscale images into full-color */
	if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
	    png_set_gray_to_rgb (state);

	/* only if file has a file gamma, we do a correction */
	if (png_get_gAMA (state, pnginfo, &file_gamma))
	    png_set_gamma (state, (double) 2.2, file_gamma);

	/* all transformations have been registered; now update pnginfo data,
	 * get rowbytes and channels, and allocate image memory */

	png_read_update_info (state, pnginfo);

	/* get the new color-type and bit-depth (after expansion/stripping) */
	png_get_IHDR (state, pnginfo, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);

	/* calculate new number of channels and store alpha-presence */
	if (color_type == PNG_COLOR_TYPE_RGB)
	    channels = 3;
	else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	    channels = 4;
//	else if (color_type == PNG_COLOR_TYPE_GRAY)
//	    channels = 1;
//	else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
//	    channels = 2;
	else {
	 	/* GdDrawImage currently only supports 32bpp alpha channel*/
		DPRINTF("GdDecodePNG: Gray image type not supported: %d\n", color_type);
		return NULL;
	}

	/* set image data format*/
	data_format = (channels == 4)? MWIF_RGBA8888: MWIF_RGB888;

	//pimage->pitch = width * channels * (bit_depth / 8);
	//bpp = channels * 8;
	pmd = GdCreatePixmap(&scrdev, width, height, data_format, NULL, 0);
	if (!pmd) {
		png_destroy_read_struct(&state, &pnginfo, NULL);
		goto nomem;
    }
//DPRINTF("png %dbpp\n", channels*8);

    if(!(rows = malloc(height * sizeof(unsigned char *)))) {
		png_destroy_read_struct(&state, &pnginfo, NULL);
		goto nomem;
    }
	for(i = 0; i < height; i++)
		rows[i] = ((unsigned char *)pmd->addr) + i * pmd->pitch;

	png_read_image(state, rows);
	png_read_end(state, NULL);
	free(rows);
	png_destroy_read_struct(&state, &pnginfo, NULL);

	return pmd;

nomem:
	EPRINTF("GdDecodePNG: Out of memory\n");
	return NULL;
}
Exemple #2
0
int ExtractBits(PNG_CONST TCHAR *inname, PNG_CONST TCHAR *outname)
{
	static HANDLE fpin;
	static HANDLE fpout;  /* "static" prevents setjmp corruption */
	png_structp read_ptr;
	png_infop read_info_ptr, end_info_ptr;
	png_structp write_ptr = NULL;
	png_infop write_info_ptr = NULL;
	png_infop write_end_info_ptr = NULL;
	png_bytep row_buf;
	png_uint_32 y;
	png_uint_32 width, height;
	int num_pass, pass;
	int bit_depth, color_type;
	char inbuf[256], outbuf[256];
	row_buf = NULL;

	if ((fpin = CreateFile(inname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
	{
		fprintf(STDERR, "Could not find input file %s\n", inname);
		return (1);
	}

	if ((fpout = CreateFile(outname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE)
	{
		fprintf(STDERR, "Could not open output file %s\n", outname);
		FCLOSE(fpin);
		return (1);
	}

	png_debug(0, "Allocating read and write structures");
	read_ptr =
	    png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
	                           png_error_ptr_NULL, png_error_ptr_NULL);
	png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error,
	                 pngtest_warning);
	png_debug(0, "Allocating read_info, write_info and end_info structures");
	read_info_ptr = png_create_info_struct(read_ptr);
	end_info_ptr = png_create_info_struct(read_ptr);
	png_debug(0, "Setting jmpbuf for read struct");

	if (setjmp(png_jmpbuf(read_ptr)))
	{
		fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
		png_free(read_ptr, row_buf);
		row_buf = NULL;
		png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
		FCLOSE(fpin);
		FCLOSE(fpout);
		return (1);
	}

	png_debug(0, "Initializing input and output streams");
	png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);

	if (status_dots_requested == 1)
	{
		png_set_read_status_fn(read_ptr, read_row_callback);
	}
	else
	{
		png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL);
	}

	png_debug(0, "Reading info struct");
	png_read_info(read_ptr, read_info_ptr);
	png_debug(0, "Transferring info struct");
	{
		int interlace_type, compression_type, filter_type;

		if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
		                &color_type, &interlace_type, &compression_type, &filter_type))
		{
			png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
			             color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
		}
	}
	{
		int intent;

		if (png_get_sRGB(read_ptr, read_info_ptr, &intent))
			png_set_sRGB(write_ptr, write_info_ptr, intent);
	}
	{
		png_colorp palette;
		int num_palette;

		if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
			png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
	}
	{
		png_color_8p sig_bit;

		if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
			png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
	}
	{
		png_bytep trans;
		int num_trans;
		png_color_16p trans_values;

		if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans,
		                &trans_values))
		{
			int sample_max = (1 << read_info_ptr->bit_depth);

			/* libpng doesn't reject a tRNS chunk with out-of-range samples */
			if (!((read_info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
			        (int)trans_values->gray > sample_max) ||
			        (read_info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
			         ((int)trans_values->red > sample_max ||
			          (int)trans_values->green > sample_max ||
			          (int)trans_values->blue > sample_max))))
				png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans,
				             trans_values);
		}
	}
	png_debug(0, "Writing row data");
	num_pass = png_set_interlace_handling(read_ptr);

	for(pass = 0; pass < num_pass; pass++)
	{
		png_debug1(0, "Writing row data for pass %d", pass);

		for(y = 0; y < height; y++)
		{
			png_debug2(0, "Allocating row buffer (pass %d, y = %ld)...", pass, y);
			row_buf = (png_bytep)png_malloc(read_ptr,
			                                png_get_rowbytes(read_ptr, read_info_ptr));
			png_debug2(0, "0x%08lx (%ld bytes)", (unsigned long)row_buf,
			           png_get_rowbytes(read_ptr, read_info_ptr));
			png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1);
			png_debug2(0, "Freeing row buffer (pass %d, y = %ld)", pass, y);
			png_free(read_ptr, row_buf);
			row_buf = NULL;
		}
	}

	png_debug(0, "Reading and writing end_info data");
	png_read_end(read_ptr, end_info_ptr);
	{
		png_uint_32 iwidth, iheight;
		iwidth = png_get_image_width(write_ptr, write_info_ptr);
		iheight = png_get_image_height(write_ptr, write_info_ptr);
		fprintf(STDERR, "\n Image width = %lu, height = %lu\n",
		        (unsigned long)iwidth, (unsigned long)iheight);
	}
	png_debug(0, "Destroying data structs");
	png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr");
	png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
	png_debug(0, "Destruction complete.");
	FCLOSE(fpin);
	FCLOSE(fpout);
	png_debug(0, "Opening files for comparison");

	if ((fpin = CreateFile(inname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
	{
		fprintf(STDERR, "Could not find file %s\n", inname);
		return (1);
	}

	if ((fpout = CreateFile(outname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
	{
		fprintf(STDERR, "Could not find file %s\n", outname);
		FCLOSE(fpin);
		return (1);
	}

	for(;;)
	{
		DWORD num_in, num_out;
		READFILE(fpin, inbuf, 1, num_in);
		READFILE(fpout, outbuf, 1, num_out);

		if (num_in != num_out)
		{
			fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
			        inname, outname);

			if (wrote_question == 0)
			{
				fprintf(STDERR,
				        "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
				        inname, PNG_ZBUF_SIZE);
				fprintf(STDERR,
				        "\n   filtering heuristic (libpng default), compression");
				fprintf(STDERR,
				        " level (zlib default),\n   and zlib version (%s)?\n\n",
				        ZLIB_VERSION);
				wrote_question = 1;
			}

			FCLOSE(fpin);
			FCLOSE(fpout);
			return (0);
		}

		if (!num_in)
			break;

		if (png_memcmp(inbuf, outbuf, num_in))
		{
			fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname);

			if (wrote_question == 0)
			{
				fprintf(STDERR,
				        "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
				        inname, PNG_ZBUF_SIZE);
				fprintf(STDERR,
				        "\n   filtering heuristic (libpng default), compression");
				fprintf(STDERR,
				        " level (zlib default),\n   and zlib version (%s)?\n\n",
				        ZLIB_VERSION);
				wrote_question = 1;
			}

			FCLOSE(fpin);
			FCLOSE(fpout);
			return (0);
		}
	}

	FCLOSE(fpin);
	FCLOSE(fpout);
	return (0);
}
Exemple #3
0
int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) {
	GLint pack, unpack;
	unsigned char header[8];
	png_structp png;
	png_infop   info;
	png_infop   endinfo;
	png_bytep   data, data2;
   png_bytep  *row_p;
   double	fileGamma;

	png_uint_32 width, height, rw, rh;
	int depth, color;

	png_uint_32 i;

	fread(header, 1, 8, fp);
	if (!png_check_sig(header, 8)) return 0;

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	info = png_create_info_struct(png);
	endinfo = png_create_info_struct(png);

	// DH: added following lines
	if (setjmp(png->jmpbuf))
	{
		png_destroy_read_struct(&png, &info, &endinfo);
		return 0;
	}
	// ~DH

	png_init_io(png, fp);
	png_set_sig_bytes(png, 8);
	png_read_info(png, info);
	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

	if (pinfo != NULL) {
		pinfo->Width  = width;
		pinfo->Height = height;
		pinfo->Depth  = depth;
	}

	if (MaxTextureSize == 0)
		glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize);

	#ifdef SUPPORTS_PALETTE_EXT
	#ifdef _WIN32
		if (PalettedTextures == -1)
			PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL);

		if (PalettedTextures) {
			if (glColorTableEXT == NULL) {
				glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT");
				if (glColorTableEXT == NULL)
					PalettedTextures = 0;
			}
		}
	#endif
	#endif

	if (PalettedTextures == -1)
		PalettedTextures = 0;

	if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png);

	if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA) {
		png_set_strip_alpha(png);
		color &= ~PNG_COLOR_MASK_ALPHA;
	}

	if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID))
		if (color == PNG_COLOR_TYPE_PALETTE)
			png_set_expand(png);

	/*--GAMMA--*/
	checkForGammaEnv();
	if (png_get_gAMA(png, info, &fileGamma))
		png_set_gamma(png, screenGamma, fileGamma);
	else
		png_set_gamma(png, screenGamma, 1.0/2.2);

	png_read_update_info(png, info);

	data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
	row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);

	for (i = 0; i < height; i++) {
		if (StandardOrientation)
			row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
		else
			row_p[i] = &data[png_get_rowbytes(png, info)*i];
	}

	png_read_image(png, row_p);
	free(row_p);

	rw = SafeSize(width), rh = SafeSize(height);

	if (rw != width || rh != height) {
		const int channels = png_get_rowbytes(png, info)/width;

		data2 = (png_bytep) malloc(rw*rh*channels);

 		/* Doesn't work on certain sizes */
/* 		if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0)
 			return 0;
*/
		Resize(channels, data, width, height, data2, rw, rh);

		width = rw, height = rh;
		free(data);
		data = data2;
	}

	{ /* OpenGL stuff */
		glGetIntegerv(GL_PACK_ALIGNMENT, &pack);
		glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack);
		glPixelStorei(GL_PACK_ALIGNMENT, 1);
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

		#ifdef SUPPORTS_PALETTE_EXT
		if (PalettedTextures && mipmap >= 0 && trans == PNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) {
			png_colorp pal;
			int cols;
			GLint intf;

			if (pinfo != NULL) pinfo->Alpha = 0;
			png_get_PLTE(png, info, &pal, &cols);

			switch (cols) {
				case 1<<1:  intf = GL_COLOR_INDEX1_EXT;  break;
				case 1<<2:  intf = GL_COLOR_INDEX2_EXT;  break;
				case 1<<4:  intf = GL_COLOR_INDEX4_EXT;  break;
				case 1<<8:  intf = GL_COLOR_INDEX8_EXT;  break;
				case 1<<12: intf = GL_COLOR_INDEX12_EXT; break;
				case 1<<16: intf = GL_COLOR_INDEX16_EXT; break;
				default:
					/*printf("Warning: Colour depth %i not recognised\n", cols);*/
					return 0;
			}
			glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, cols, GL_RGB, GL_UNSIGNED_BYTE, pal);
			glTexImage2D(GL_TEXTURE_2D, mipmap, intf, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data);
		}
		else
		#endif
		if (trans == PNG_SOLID || trans == PNG_ALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) {
			GLenum glformat;
			GLint glcomponent;

			switch (color) {
				case PNG_COLOR_TYPE_GRAY:
				case PNG_COLOR_TYPE_RGB:
				case PNG_COLOR_TYPE_PALETTE:
					glformat = GL_RGB;
					glcomponent = 3;
					if (pinfo != NULL) pinfo->Alpha = 0;
					break;

				case PNG_COLOR_TYPE_GRAY_ALPHA:
				case PNG_COLOR_TYPE_RGB_ALPHA:
					glformat = GL_RGBA;
					glcomponent = 4;
					if (pinfo != NULL) pinfo->Alpha = 8;
					break;

				default:
					/*puts("glformat not set");*/
					return 0;
			}

			if (mipmap == PNG_BUILDMIPMAPS)
				Build2DMipmaps(glcomponent, width, height, glformat, data, 1);
			else if (mipmap == PNG_SIMPLEMIPMAPS)
				Build2DMipmaps(glcomponent, width, height, glformat, data, 0);
			else
				glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data);
		}
		else {
			png_bytep p, endp, q;
			int r, g, b, a;

			p = data, endp = p+width*height*3;
			q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4);

			if (pinfo != NULL) pinfo->Alpha = 8;

			#define FORSTART \
				do { \
					r = *p++; /*red  */ \
					g = *p++; /*green*/ \
					b = *p++; /*blue */ \
					*q++ = r; \
					*q++ = g; \
					*q++ = b;

			#define FOREND \
					q++; \
				} while (p != endp);

			#define ALPHA *q

			switch (trans) {
				case PNG_CALLBACK:
					FORSTART
						ALPHA = AlphaCallback((unsigned char) r, (unsigned char) g, (unsigned char) b);
					FOREND
					break;

				case PNG_STENCIL:
					FORSTART
						if (r == StencilRed && g == StencilGreen && b == StencilBlue)
							ALPHA = 0;
						else
							ALPHA = 255;
					FOREND
					break;

				case PNG_BLEND1:
					FORSTART
						a = r+g+b;
						if (a > 255) ALPHA = 255; else ALPHA = a;
					FOREND
					break;

				case PNG_BLEND2:
					FORSTART
						a = r+g+b;
						if (a > 255*2) ALPHA = 255; else ALPHA = a/2;
					FOREND
					break;

				case PNG_BLEND3:
					FORSTART
						ALPHA = (r+g+b)/3;
					FOREND
					break;

				case PNG_BLEND4:
					FORSTART
						a = r*r+g*g+b*b;
						if (a > 255) ALPHA = 255; else ALPHA = a;
					FOREND
					break;

				case PNG_BLEND5:
					FORSTART
						a = r*r+g*g+b*b;
						if (a > 255*2) ALPHA = 255; else ALPHA = a/2;
					FOREND
					break;

				case PNG_BLEND6:
					FORSTART
						a = r*r+g*g+b*b;
						if (a > 255*3) ALPHA = 255; else ALPHA = a/3;
					FOREND
					break;

				case PNG_BLEND7:
					FORSTART
						a = r*r+g*g+b*b;
						if (a > 255*255) ALPHA = 255; else ALPHA = (int) sqrt(a);
					FOREND
					break;
			}

			#undef FORSTART
			#undef FOREND
			#undef ALPHA

			if (mipmap == PNG_BUILDMIPMAPS)
				Build2DMipmaps(4, width, height, GL_RGBA, data2, 1);
			else if (mipmap == PNG_SIMPLEMIPMAPS)
				Build2DMipmaps(4, width, height, GL_RGBA, data2, 0);
			else
				glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2);

			free(data2);
		}

		glPixelStorei(GL_PACK_ALIGNMENT, pack);
		glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
	} /* OpenGL end */

   png_read_end(png, endinfo);
	png_destroy_read_struct(&png, &info, &endinfo);

	free(data);

	return 1;
}
Exemple #4
0
BitmapImage * PNGImageIO_loadPNGData(const void * data, size_t length, int pixelFormat, bool flipVertical) {
	png_byte headerBytes[PNG_HEADER_SIZE];
	png_structp pngReadStruct;
	png_infop pngInfoStruct;
	struct memreadContext readContext;
	unsigned int width, height;
	png_int_32 bitDepth, colorType;
	png_bytep * rows = NULL;
	unsigned char * pixels = NULL;
	unsigned int rowIndex;
	enum BitmapPixelFormat chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGBA_8888;
	BitmapImage * image;
	
	readContext = memreadContextInit(data, length);
	if (!memread(&readContext, PNG_HEADER_SIZE, headerBytes) || png_sig_cmp(headerBytes, 0, PNG_HEADER_SIZE)) {
		return NULL;
	}
	
	pngReadStruct = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	pngInfoStruct = png_create_info_struct(pngReadStruct);
	
	if (setjmp(png_jmpbuf(pngReadStruct))) {
		png_destroy_read_struct(&pngReadStruct, &pngInfoStruct, NULL);
		free(rows);
		free(pixels);
		return NULL;
	}
	
	png_set_read_fn(pngReadStruct, &readContext, pngReadFnMemread);
	png_set_sig_bytes(pngReadStruct, PNG_HEADER_SIZE);
	png_read_info(pngReadStruct, pngInfoStruct);
	
	width = png_get_image_width(pngReadStruct, pngInfoStruct);
	height = png_get_image_height(pngReadStruct, pngInfoStruct);
	bitDepth = png_get_bit_depth(pngReadStruct, pngInfoStruct);
	colorType = png_get_color_type(pngReadStruct, pngInfoStruct);
	
	if (colorType == PNG_COLOR_TYPE_PALETTE) {
		png_set_palette_to_rgb(pngReadStruct);
		colorType = PNG_COLOR_TYPE_RGB;
	}
	if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) {
		png_set_expand_gray_1_2_4_to_8(pngReadStruct);
	}
	if (png_get_valid(pngReadStruct, pngInfoStruct, PNG_INFO_tRNS)) {
		png_set_tRNS_to_alpha(pngReadStruct);
	}
	if (bitDepth == 16) {
		png_set_strip_16(pngReadStruct);
	}
	
	switch (pixelFormat) {
		case PNG_PIXEL_FORMAT_AUTOMATIC:
			switch (colorType) {
				case PNG_COLOR_TYPE_GRAY:
					chosenPixelFormat = BITMAP_PIXEL_FORMAT_GRAY_8;
					break;
					
				case PNG_COLOR_TYPE_GRAY_ALPHA:
					chosenPixelFormat = BITMAP_PIXEL_FORMAT_GRAYALPHA_88;
					break;
					
				case PNG_COLOR_TYPE_RGB:
					chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGB_888;
					break;
					
				case PNG_COLOR_TYPE_RGB_ALPHA:
					chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGBA_8888;
					break;
			}
			png_read_update_info(pngReadStruct, pngInfoStruct);
			break;
			
		case BITMAP_PIXEL_FORMAT_RGBA_8888:
			if (!(colorType & PNG_COLOR_MASK_ALPHA)) {
				png_set_add_alpha(pngReadStruct, 0xFF, PNG_FILLER_AFTER);
			}
			png_read_update_info(pngReadStruct, pngInfoStruct);
			if (!(colorType & PNG_COLOR_MASK_COLOR)) {
				png_set_gray_to_rgb(pngReadStruct);
			}
			chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGBA_8888;
			break;
			
		case BITMAP_PIXEL_FORMAT_RGB_888:
			if (colorType & PNG_COLOR_MASK_ALPHA) {
				png_set_strip_alpha(pngReadStruct);
			}
			png_read_update_info(pngReadStruct, pngInfoStruct);
			if (!(colorType & PNG_COLOR_MASK_COLOR)) {
				png_set_gray_to_rgb(pngReadStruct);
			}
			chosenPixelFormat = BITMAP_PIXEL_FORMAT_RGB_888;
			break;
			
		case BITMAP_PIXEL_FORMAT_GRAYALPHA_88:
			if (!(colorType & PNG_COLOR_MASK_ALPHA)) {
				png_set_add_alpha(pngReadStruct, 0xFF, PNG_FILLER_AFTER);
			}
			png_read_update_info(pngReadStruct, pngInfoStruct);
			if (colorType & PNG_COLOR_MASK_COLOR) {
				png_set_rgb_to_gray(pngReadStruct, 1, (float) 0x55 / 0xFF, (float) 0x55 / 0xFF);
			}
			chosenPixelFormat = BITMAP_PIXEL_FORMAT_GRAYALPHA_88;
			break;
			
		case BITMAP_PIXEL_FORMAT_GRAY_8:
			if (colorType & PNG_COLOR_MASK_ALPHA) {
				png_set_strip_alpha(pngReadStruct);
			}
			png_read_update_info(pngReadStruct, pngInfoStruct);
			if (colorType & PNG_COLOR_MASK_COLOR) {
				png_set_rgb_to_gray(pngReadStruct, 1, (float) 0x55 / 0xFF, (float) 0x55 / 0xFF);
			}
			chosenPixelFormat = BITMAP_PIXEL_FORMAT_GRAY_8;
			break;
	}
	
	pixels = calloc(width * height, BitmapImage_pixelFormatBytes(chosenPixelFormat));
	rows = malloc(sizeof(png_bytep) * height);
	for (rowIndex = 0; rowIndex < height; rowIndex++) {
		rows[rowIndex] = pixels + ((flipVertical ? height - rowIndex - 1 : rowIndex) * width * BitmapImage_pixelFormatBytes(chosenPixelFormat));
	}
	
	png_read_rows(pngReadStruct, rows, NULL, height);
	png_read_end(pngReadStruct, NULL);
	
	png_destroy_read_struct(&pngReadStruct, &pngInfoStruct, NULL);
	free(rows);
	
	image = BitmapImage_createWithPixelsNoCopy(chosenPixelFormat, width, height, width * BitmapImage_pixelFormatBytes(chosenPixelFormat), pixels, true);
	
	return image;
}
Exemple #5
0
int LoadPNG(void *pRaw, int rawlen, unsigned int *puWidth, unsigned int *puHeight, void **ppData)
{
	png_bytep *row_pointers;
	png_uint_32 w, h;
	png_structp png_ptr;
	png_infop info_ptr;
	int bit_depth, color_type, interlace_type;
	int i;
	int number_of_passes;
	void *pixels;
	mypngio_t *pMy;

	png_ptr = NULL; info_ptr = NULL; row_pointers = NULL;

	if( png_sig_cmp((png_bytep)pRaw, 0, 8) != 0 ) {
		goto err_exit;
	}

	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if(!png_ptr) {
		goto err_exit;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if(!info_ptr) {
		goto err_exit;
	}

	if (setjmp (png_jmpbuf (png_ptr))) {
		goto err_exit;
	}

	pMy = (mypngio_t*)calloc(1,sizeof(mypngio_t));
	pMy->pPtr = pRaw;
	pMy->off  = 8;
	png_set_read_fn(png_ptr, (void *)pMy, user_read_fn);
	png_set_sig_bytes(png_ptr, 8);

	png_read_info (png_ptr, info_ptr);
	png_get_IHDR (png_ptr, info_ptr, &w, &h, &bit_depth, &color_type,
		&interlace_type, 0, 0);

	/*** Set up some transformations to get everything in our nice ARGB format. ***/
	/* 8 bits per channel: */
	if (bit_depth == 16)
		png_set_strip_16 (png_ptr);
	/* Convert palette to RGB: */
	if (color_type == PNG_COLOR_TYPE_PALETTE)
		png_set_palette_to_rgb (png_ptr), color_type = PNG_COLOR_TYPE_RGB;
	/* Extract 1/2/4bpp to 8bpp: */
	if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
		png_set_expand_gray_1_2_4_to_8 (png_ptr);
	/* Convert colorkey to alpha: */
	if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_tRNS_to_alpha (png_ptr);
	/* Convert gray to RGB: */
	if (color_type == PNG_COLOR_TYPE_GRAY)
		png_set_gray_to_rgb (png_ptr),
		color_type = PNG_COLOR_TYPE_RGB;

	if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb (png_ptr),
		color_type = PNG_COLOR_TYPE_RGB_ALPHA;

	/* Convert RGB to RGBA */
	if (color_type == PNG_COLOR_TYPE_RGB)
		png_set_add_alpha (png_ptr, 0xff, PNG_FILLER_AFTER);

	//png_set_bgr(png_ptr);
	number_of_passes = png_set_interlace_handling (png_ptr);

	/* Update the info struct. */
	png_read_update_info (png_ptr, info_ptr);

	/* Allocate our surface. */
	pixels = malloc( w * h * 4 );
	if (!pixels) {
		goto err_exit;
	}

	row_pointers = (png_bytep*)malloc (h * sizeof(png_bytep));
	if (!row_pointers) {
		goto err_exit;
	}

	/* Build the array of row pointers. */
	for (i = 0; i < (int)h; i++) {
		row_pointers[i] = (png_bytep)( (unsigned char*)pixels + (i * w * 4) );
	}

	/* Read the thing. */
	png_read_image (png_ptr, row_pointers);

	/* Read the rest. */
	png_read_end (png_ptr, info_ptr);

	if (png_ptr)
		png_destroy_read_struct (&png_ptr, info_ptr? &info_ptr : 0, 0);
	if (row_pointers)
		free (row_pointers);

	*puWidth  = w;
	*puHeight = h;
	*ppData   = pixels;

	return 0;

err_exit:
	if (png_ptr)
		png_destroy_read_struct (&png_ptr, info_ptr? &info_ptr : 0, 0);
	if (row_pointers)
		free (row_pointers);

	return -1;
}
Exemple #6
0
/* This routine is based in part on the Chapter 13 demo code in "PNG: The
 *  Definitive Guide" (http://www.cdrom.com/pub/png/pngbook.html).
 */
gdImagePtr
gdImageCreateFromPngCtx (gdIOCtx * infile)
{
    png_byte sig[8];
    png_structp png_ptr;
    png_infop info_ptr;
    png_uint_32 width, height, rowbytes;
    int bit_depth, color_type, interlace_type;
    int num_palette, num_trans;
    png_colorp palette;
    png_color_16p trans_gray_rgb;
    png_color_16p trans_color_rgb;
    png_bytep trans;
    png_bytep image_data = NULL;
    png_bytepp row_pointers = NULL;
    gdImagePtr im = NULL;
    int i, j, *open = NULL;
    volatile int transparent = -1;
    volatile int palette_allocated = FALSE;

    /* Make sure the signature can't match by dumb luck -- TBB */
    /* GRR: isn't sizeof(infile) equal to the size of the pointer? */
    memset (infile, 0, sizeof (infile));

    /* first do a quick check that the file really is a PNG image; could
     * have used slightly more general png_sig_cmp() function instead */
    gdGetBuf (sig, 8, infile);
    if (!png_check_sig (sig, 8))
        return NULL;		/* bad signature */

#ifndef PNG_SETJMP_NOT_SUPPORTED
    png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct,
                                      gdPngErrorHandler, NULL);
#else
    png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
#endif
    if (png_ptr == NULL)
    {
        fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n");
        return NULL;
    }

    info_ptr = png_create_info_struct (png_ptr);
    if (info_ptr == NULL)
    {
        fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n");
        png_destroy_read_struct (&png_ptr, NULL, NULL);
        return NULL;
    }

    /* we could create a second info struct here (end_info), but it's only
     * useful if we want to keep pre- and post-IDAT chunk info separated
     * (mainly for PNG-aware image editors and converters) */

    /* setjmp() must be called in every non-callback function that calls a
     * PNG-reading libpng function */
#ifndef PNG_SETJMP_NOT_SUPPORTED
    if (setjmp (gdPngJmpbufStruct.jmpbuf))
    {
        fprintf (stderr, "gd-png error: setjmp returns error condition\n");
        png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
        return NULL;
    }
#endif

    png_set_sig_bytes (png_ptr, 8);	/* we already read the 8 signature bytes */

    png_set_read_fn (png_ptr, (void *) infile, gdPngReadData);
    png_read_info (png_ptr, info_ptr);	/* read all PNG info up to image data */

    png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
                  &interlace_type, NULL, NULL);
    if ((color_type == PNG_COLOR_TYPE_RGB) ||
            (color_type == PNG_COLOR_TYPE_RGB_ALPHA))
    {
        im = gdImageCreateTrueColor ((int) width, (int) height);
    }
    else
    {
        im = gdImageCreate ((int) width, (int) height);
    }
    if (im == NULL)
    {
        fprintf (stderr, "gd-png error: cannot allocate gdImage struct\n");
        png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
        gdFree (image_data);
        gdFree (row_pointers);
        return NULL;
    }

    if (bit_depth == 16)
        png_set_strip_16 (png_ptr);
    else if (bit_depth < 8)
        png_set_packing (png_ptr);	/* expand to 1 byte per pixel */
    switch (color_type)
    {
    case PNG_COLOR_TYPE_PALETTE:
        png_get_PLTE (png_ptr, info_ptr, &palette, &num_palette);
#ifdef DEBUG
        fprintf (stderr, "gd-png color_type is palette, colors: %d\n",
                 num_palette);
#endif /* DEBUG */
        if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
        {
            /* gd 2.0: we support this rather thoroughly now. Grab the
               first fully transparent entry, if any, as the value of
               the simple-transparency index, mostly for backwards
               binary compatibility. The alpha channel is where it's
               really at these days. */
            int firstZero = 1;
            png_get_tRNS (png_ptr, info_ptr, &trans, &num_trans, NULL);
            for (i = 0; i < num_trans; ++i)
            {
                im->alpha[i] = gdAlphaMax - (trans[i] >> 1);
                if ((trans[i] == 0) && (firstZero))
                {
                    /* 2.0.5: long-forgotten patch from Wez Furlong */
                    transparent = i;
                    firstZero = 0;
                }
            }
        }
        break;

    case PNG_COLOR_TYPE_GRAY:
    case PNG_COLOR_TYPE_GRAY_ALPHA:
        /* create a fake palette and check for single-shade transparency */
        if ((palette =
                    (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL)
        {
            fprintf (stderr, "gd-png error: cannot allocate gray palette\n");
            png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
            return NULL;
        }
        palette_allocated = TRUE;
        if (bit_depth < 8)
        {
            num_palette = 1 << bit_depth;
            for (i = 0; i < 256; ++i)
            {
                j = (255 * i) / (num_palette - 1);
                palette[i].red = palette[i].green = palette[i].blue = j;
            }
        }
        else
        {
            num_palette = 256;
            for (i = 0; i < 256; ++i)
            {
                palette[i].red = palette[i].green = palette[i].blue = i;
            }
        }
        if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
        {
            png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb);
            if (bit_depth == 16)	/* png_set_strip_16() not yet in effect */
                transparent = trans_gray_rgb->gray >> 8;
            else
                transparent = trans_gray_rgb->gray;
            /* Note slight error in 16-bit case:  up to 256 16-bit shades
             * may get mapped to a single 8-bit shade, and only one of them
             * is supposed to be transparent.  IOW, both opaque pixels and
             * transparent pixels will be mapped into the transparent entry.
             * There is no particularly good way around this in the case
             * that all 256 8-bit shades are used, but one could write some
             * custom 16-bit code to handle the case where there are gdFree
             * palette entries.  This error will be extremely rare in
             * general, though.  (Quite possibly there is only one such
             * image in existence.) */
        }
        break;

    case PNG_COLOR_TYPE_RGB:
    case PNG_COLOR_TYPE_RGB_ALPHA:
        /* gd 2.0: we now support truecolor. See the comment above
           for a rare situation in which the transparent pixel may not
           work properly with 16-bit channels. */
        if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
        {
            png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_color_rgb);
            if (bit_depth == 16)	/* png_set_strip_16() not yet in effect */
                transparent = gdTrueColor (trans_color_rgb->red >> 8,
                                           trans_color_rgb->green >> 8,
                                           trans_color_rgb->blue >> 8);
            else
                transparent = gdTrueColor (trans_color_rgb->red,
                                           trans_color_rgb->green,
                                           trans_color_rgb->blue);
        }
Exemple #7
0
/* Read a PNG file.  You may want to return an error code if the read
 * fails (depending upon the failure).  There are two "prototypes" given
 * here - one where we are given the filename, and we need to open the
 * file, and the other where we are given an open file (possibly with
 * some or all of the magic bytes read - see comments above).
 */
#ifdef open_file /* prototype 1 */
void read_png(char *file_name)  /* We need to open the file */
{
   png_structp png_ptr;
   png_infop info_ptr;
   unsigned int sig_read = 0;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
   FILE *fp;

   if ((fp = fopen(file_name, "rb")) == NULL)
      return (ERROR);

#else no_open_file /* prototype 2 */
void read_png(FILE *fp, unsigned int sig_read)  /* File is already open */
{
   png_structp png_ptr;
   png_infop info_ptr;
   png_uint_32 width, height;
   int bit_depth, color_type, interlace_type;
#endif no_open_file /* Only use one prototype! */

   /* Create and initialize the png_struct with the desired error handler
    * functions.  If you want to use the default stderr and longjump method,
    * you can supply NULL for the last three parameters.  We also supply the
    * the compiler header file version, so that we know if the application
    * was compiled with a compatible version of the library.  REQUIRED
    */
   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
      png_voidp user_error_ptr, user_error_fn, user_warning_fn);

   if (png_ptr == NULL)
   {
      fclose(fp);
      return (ERROR);
   }

   /* Allocate/initialize the memory for image information.  REQUIRED. */
   info_ptr = png_create_info_struct(png_ptr);
   if (info_ptr == NULL)
   {
      fclose(fp);
      png_destroy_read_struct(&png_ptr, NULL, NULL);
      return (ERROR);
   }

   /* Set error handling if you are using the setjmp/longjmp method (this is
    * the normal method of doing things with libpng).  REQUIRED unless you
    * set up your own error handlers in the png_create_read_struct() earlier.
    */

   if (setjmp(png_jmpbuf(png_ptr)))
   {
      /* Free all of the memory associated with the png_ptr and info_ptr */
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
      fclose(fp);
      /* If we get here, we had a problem reading the file */
      return (ERROR);
   }

   /* One of the following I/O initialization methods is REQUIRED */
#ifdef streams /* PNG file I/O method 1 */
   /* Set up the input control if you are using standard C streams */
   png_init_io(png_ptr, fp);

#else no_streams /* PNG file I/O method 2 */
   /* If you are using replacement read functions, instead of calling
    * png_init_io() here you would call:
    */
   png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
   /* where user_io_ptr is a structure you want available to the callbacks */
#endif no_streams /* Use only one I/O method! */

   /* If we have already read some of the signature */
   png_set_sig_bytes(png_ptr, sig_read);

#ifdef hilevel
   /*
    * If you have enough memory to read in the entire image at once,
    * and you need to specify only transforms that can be controlled
    * with one of the PNG_TRANSFORM_* bits (this presently excludes
    * quantizing, filling, setting background, and doing gamma
    * adjustment), then you can read the entire image (including
    * pixels) into the info structure with this call:
    */
   png_read_png(png_ptr, info_ptr, png_transforms, NULL);

#else
   /* OK, you're doing it the hard way, with the lower-level functions */

   /* The call to png_read_info() gives us all of the information from the
    * PNG file before the first IDAT (image data chunk).  REQUIRED
    */
   png_read_info(png_ptr, info_ptr);

   png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
       &interlace_type, NULL, NULL);

   /* Set up the data transformations you want.  Note that these are all
    * optional.  Only call them if you want/need them.  Many of the
    * transformations only work on specific types of images, and many
    * are mutually exclusive.
    */

   /* Tell libpng to strip 16 bit/color files down to 8 bits/color.
    * Use accurate scaling if it's available, otherwise just chop off the
    * low byte.
    */
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
    png_set_scale_16(png_ptr);
#else
   png_set_strip_16(png_ptr);
#endif

   /* Strip alpha bytes from the input data without combining with the
    * background (not recommended).
    */
   png_set_strip_alpha(png_ptr);

   /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
    * byte into separate bytes (useful for paletted and grayscale images).
    */
   png_set_packing(png_ptr);

   /* Change the order of packed pixels to least significant bit first
    * (not useful if you are using png_set_packing). */
   png_set_packswap(png_ptr);

   /* Expand paletted colors into true RGB triplets */
   if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb(png_ptr);

   /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
   if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
      png_set_expand_gray_1_2_4_to_8(png_ptr);

   /* Expand paletted or RGB images with transparency to full alpha channels
    * so the data will be available as RGBA quartets.
    */
   if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
      png_set_tRNS_to_alpha(png_ptr);

   /* Set the background color to draw transparent and alpha images over.
    * It is possible to set the red, green, and blue components directly
    * for paletted images instead of supplying a palette index.  Note that
    * even if the PNG file supplies a background, you are not required to
    * use it - you should use the (solid) application background if it has one.
    */

   png_color_16 my_background, *image_background;

   if (png_get_bKGD(png_ptr, info_ptr, &image_background))
      png_set_background(png_ptr, image_background,
                         PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
   else
      png_set_background(png_ptr, &my_background,
                         PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);

   /* Some suggestions as to how to get a screen gamma value
    *
    * Note that screen gamma is the display_exponent, which includes
    * the CRT_exponent and any correction for viewing conditions
    */
   if (/* We have a user-defined screen gamma value */)
   {
      screen_gamma = user-defined screen_gamma;
   }
   /* This is one way that applications share the same screen gamma value */
   else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
Exemple #8
0
int loadPNG(const char *filename) {
    GLuint texture;
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    png_bytep *row_pointers = NULL;
    int bitDepth, colourType;
    FILE *pngFile = fopen(filename, "rb");
    if (!pngFile)
        return 0;
    png_byte sig[8];
    fread(&sig, 8, sizeof(png_byte), pngFile);
    rewind(pngFile);
    if (!png_check_sig(sig, 8)) {
        //SDL_Log("png sig failure\n");
        return 0;
    }
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        //SDL_Log("png ptr not created\n");
        return 0;
    }
    if (setjmp(png_jmpbuf(png_ptr))) {
        //SDL_Log("set jmp failed\n");
        return 0;
    }
    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        //SDL_Log("cant get png info ptr\n");
        return 0;
    }
    png_init_io(png_ptr, pngFile);
    png_read_info(png_ptr, info_ptr);
    bitDepth = png_get_bit_depth(png_ptr, info_ptr);
    colourType = png_get_color_type(png_ptr, info_ptr);
    if (colourType == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);
    if (colourType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)
        //png_set_gray_1_2_4_to_8(png_ptr);
        png_set_expand_gray_1_2_4_to_8(png_ptr);  // thanks to Jesse Jaara for bug fix for newer libpng...
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_tRNS_to_alpha(png_ptr);

    if (bitDepth == 16)
        png_set_strip_16(png_ptr);
    else if (bitDepth < 8)
        png_set_packing(png_ptr);

    png_read_update_info(png_ptr, info_ptr);

    png_uint_32 width, height;
    png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colourType, NULL, NULL, NULL);

    int components;		// = GetTextureInfo(colourType);
    switch (colourType) {
    case PNG_COLOR_TYPE_GRAY:
        components = 1;
        break;
    case PNG_COLOR_TYPE_GRAY_ALPHA:
        components = 2;
        break;
    case PNG_COLOR_TYPE_RGB:
        components = 3;
        break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
        components = 4;
        break;
    default:
        components = -1;
    }

    if (components == -1) {
        if (png_ptr)
            png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        //SDL_Log("%s broken?\n", filename);
        return 0;
    }

    GLubyte *pixels =
        (GLubyte *) malloc(sizeof(GLubyte) * (width * height * components));
    row_pointers = (png_bytep *) malloc(sizeof(png_bytep) * height);

    int i = 0;
    for (i = 0; i < height; ++i) {
        row_pointers[i] = (png_bytep) (pixels + (i * width * components));
    }
    png_read_image(png_ptr, row_pointers);
    png_read_end(png_ptr, NULL);

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    GLuint glcolours;
    (components == 4) ? (glcolours = GL_RGBA) : (0);
    (components == 3) ? (glcolours = GL_RGB) : (0);
    (components == 2) ? (glcolours = GL_LUMINANCE_ALPHA) : (0);
    (components == 1) ? (glcolours = GL_LUMINANCE) : (0);

    //SDL_Log("%s has %i colour components\n",filename,components);
    //glTexImage2D(GL_TEXTURE_2D, 0, components, width, height, 0, glcolours, GL_UNSIGNED_BYTE, pixels);
    glTexImage2D(GL_TEXTURE_2D, 0, glcolours, width, height, 0, glcolours, GL_UNSIGNED_BYTE, pixels);
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    fclose(pngFile);
    free(row_pointers);
    free(pixels);
    return texture;
}
Exemple #9
0
void DisplaySplashImage()
{
	FILE *f = FioFOpenFile(SPLASH_IMAGE_FILE);
	if (f == NULL) return;

	png_byte header[8];
	fread(header, sizeof(png_byte), 8, f);
	if (png_sig_cmp(header, 0, 8) != 0) {
		fclose(f);
		return;
	}

	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, png_my_error, png_my_warning);

	if (png_ptr == NULL) {
		fclose(f);
		return;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL) {
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		fclose(f);
		return;
	}

	png_infop end_info = png_create_info_struct(png_ptr);
	if (end_info == NULL) {
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		fclose(f);
		return;
	}

	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(f);
		return;
	}

	png_init_io(png_ptr, f);
	png_set_sig_bytes(png_ptr, 8);

	png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

	uint width      = png_get_image_width(png_ptr, info_ptr);
	uint height     = png_get_image_height(png_ptr, info_ptr);
	uint bit_depth  = png_get_bit_depth(png_ptr, info_ptr);
	uint color_type = png_get_color_type(png_ptr, info_ptr);

	if (color_type != PNG_COLOR_TYPE_PALETTE || bit_depth != 8) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(f);
		return;
	}

	if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(f);
		return;
	}

	png_colorp palette;
	int num_palette;
	png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);

	png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);

	if (width > (uint) _screen.width) width = _screen.width;
	if (height > (uint) _screen.height) height = _screen.height;

	uint xoff = (_screen.width - width) / 2;
	uint yoff = (_screen.height - height) / 2;

	switch (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth()) {
		case 8: {
				uint8 *dst_ptr = (uint8 *)_screen.dst_ptr;
				/* Initialize buffer */
				MemSetT(dst_ptr, 0xff, _screen.pitch * _screen.height);

				for (uint y = 0; y < height; y++) {
					uint8 *src = row_pointers[y];
					uint8 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;

					memcpy(dst, src, width);
				}

				for (int i = 0; i < num_palette; i++) {
					_cur_palette[i].a = i == 0 ? 0 : 0xff;
					_cur_palette[i].r = palette[i].red;
					_cur_palette[i].g = palette[i].green;
					_cur_palette[i].b = palette[i].blue;
				}

				_cur_palette[0xff].a = 0xff;
				_cur_palette[0xff].r = 0;
				_cur_palette[0xff].g = 0;
				_cur_palette[0xff].b = 0;

				_pal_first_dirty = 0;
				_pal_count_dirty = 256;
			}
			break;
		case 32: {
				uint32 *dst_ptr = (uint32 *)_screen.dst_ptr;
				/* Initialize buffer */
				MemSetT(dst_ptr, 0, _screen.pitch * _screen.height);

				for (uint y = 0; y < height; y++) {
					uint8 *src = row_pointers[y];
					uint32 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;

					for (uint x = 0; x < width; x++) {
						dst[x] = palette[src[x]].blue | (palette[src[x]].green << 8) | (palette[src[x]].red << 16) | 0xff000000;
					}
				}
			}
			break;
	}

	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	fclose(f);
	return;
}
/* pngReadImage: Reads an image from a memory buffer.
   Returns: non-zero if successful.
*/
int pngReadImage(int w, int h, int d, char* bits, char *data, int nBytes) {
  png_bytep *row_pointers = NULL;
  pngReadState rs;
  png_structp png_ptr;
  png_infop info_ptr;
  png_uint_32 width, height;
  int bit_depth, color_type, interlace_type;

  DBG("pngReadImage: png_sig_cmp");
  /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. */
  if(png_sig_cmp(data, (png_size_t)0, PNG_BYTES_TO_CHECK)) return 0;

  DBG("pngReadImage: png_create_read_struct");
  /* Create the png_struct */
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  if (png_ptr == NULL) return 0;

  DBG("pngReadImage: png_create_info_struct");
  /* Allocate/initialize the image information data.  REQUIRED */
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
    return 0;
  }

  /* Set error handling.  REQUIRED if you aren't supplying your own
   * error handling functions in the png_create_read_struct() call.
   */
  if (setjmp(png_jmpbuf(png_ptr))) {
    DBG("pngReadImage: triggered png_error");
    /* If we get here, we had a problem reading the file */
    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
    if(row_pointers) free(row_pointers);
    return 0;
  }
  rs.data = data;
  rs.position = 0;
  rs.length = nBytes;
  png_set_read_fn(png_ptr, (void *)&rs, readBytes);


  DBG("pngReadImage: png_read_info");
  /* The call to png_read_info() gives us all of the information from the
   * PNG file before the first IDAT (image data chunk).  REQUIRED
   */
  png_read_info(png_ptr, info_ptr);
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
	       &interlace_type, int_p_NULL, int_p_NULL);

  /* Set up the data transformations you want.  Note that these are all
   * optional.  Only call them if you want/need them.  Many of the
   * transformations only work on specific types of images, and many
   * are mutually exclusive.
   */

  /* tell libpng to strip 16 bit/color files down to 8 bits/color */
  png_set_strip_16(png_ptr);

   /* flip the RGB pixels to BGR (or RGBA to BGRA) */
  if (color_type & PNG_COLOR_MASK_COLOR) {
    DBG("pngReadImage: png_set_bgr");
    png_set_bgr(png_ptr);
  }

  if(d == 32 && color_type == PNG_COLOR_TYPE_RGB) {
    /* Add filler (or alpha) byte (before/after each RGB triplet) */
    DBG("pngReadImage: png_set_filler");
    png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
  }

  if(0) {
    /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
     * byte into separate bytes (useful for paletted and grayscale images).
     */
    png_set_packing(png_ptr);
    
    /* Change the order of packed pixels to least significant bit first
     * (not useful if you are using png_set_packing). */
    png_set_packswap(png_ptr);

    /* Expand paletted colors into true RGB triplets */
    if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb(png_ptr);
  }
  
  /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_gray_1_2_4_to_8(png_ptr);

  /* Expand paletted or RGB images with transparency to full alpha channels
   * so the data will be available as RGBA quartets.
   */
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
    png_set_tRNS_to_alpha(png_ptr);


  if(0) {
    /* Set the background color to draw transparent and alpha images over.
     * It is possible to set the red, green, and blue components directly
     * for paletted images instead of supplying a palette index.  Note that
     * even if the PNG file supplies a background, you are not required to
     * use it - you should use the (solid) application background if it has one
     */

    png_color_16 my_background, *image_background;
  
    if (png_get_bKGD(png_ptr, info_ptr, &image_background))
      png_set_background(png_ptr, image_background,
			 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
    else
      png_set_background(png_ptr, &my_background,
			 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
  }

  if(0) {
   /* Tell libpng to handle the gamma conversion for you.  The final call
    * is a good guess for PC generated images, but it should be configurable
    * by the user at run time by the user.  It is strongly suggested that
    * your application support gamma correction.
    */

    int intent;
    double screen_gamma = 1.2;

    if (png_get_sRGB(png_ptr, info_ptr, &intent))
      png_set_gamma(png_ptr, screen_gamma, 0.45455);
    else {
      double image_gamma;
      if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
	png_set_gamma(png_ptr, screen_gamma, image_gamma);
      else
	png_set_gamma(png_ptr, screen_gamma, 0.45455);
    }
  }

  if(0) {
    /* If you want to shift the pixel values from the range [0,255] or
     * [0,65535] to the original [0,7] or [0,31], or whatever range the
     * colors were originally in:
     */
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) {
      png_color_8p sig_bit;
      png_get_sBIT(png_ptr, info_ptr, &sig_bit);
      png_set_shift(png_ptr, sig_bit);
    }
  }

  if(0) {
    /* flip the RGB pixels to BGR (or RGBA to BGRA) */
    if (color_type & PNG_COLOR_MASK_COLOR)
      png_set_bgr(png_ptr);
    
    /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
    png_set_swap_alpha(png_ptr);
    
    /* swap bytes of 16 bit files to least significant byte first */
    png_set_swap(png_ptr);
  }

  { /* initialize the png row pointers */
    int row, ppw = 32 / d;
    int pitch = ((w + ppw - 1) / ppw) * 4;
    int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

    if(0) {
      char info[100];
      sprintf(info, "Form pitch: %d\nPNG rowbytes: %d",pitch, rowbytes);
      DBG(info);
    }

    /* XXXX: It seems that this test is pretty pointless; PNG appears
       to return the raw rowbytes value, not the padded one.
       A better test is probably to compare the w/h/d values
       of png with the form values to ensure correctness. */
    if(pitch < rowbytes) {
      png_error(png_ptr, "Row bytes mismatch");
    }
    row_pointers = (png_bytep*) calloc(h, sizeof(void*));
    for (row = 0; row < h; row++) {
      row_pointers[row] = bits + (row*pitch);
    }
  }

  DBG("pngReadImage: png_read_image");
  /* Read the entire image in one go */
  png_read_image(png_ptr, row_pointers);

  DBG("pngReadImage: Cleaning up");
  /* clean up after the read, and free any memory allocated - REQUIRED */
  png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);

  if(row_pointers) free(row_pointers);

  return 1;
}
Exemple #11
0
bool PNGLoader::doDecodeImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch) {
#ifndef USE_INTERNAL_PNG_DECODER
	png_structp png_ptr = NULL;
	png_infop   info_ptr = NULL;

	int         bitDepth;
	int         colorType;
	int         interlaceType;
	int         i;

	// Check for valid PNG signature
	if (!doIsCorrectImageFormat(fileDataPtr, fileSize)) {
		error("png_check_sig failed");
	}

	// Die beiden PNG Strukturen erstellen
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		error("Could not create libpng read struct.");
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		error("Could not create libpng info struct.");
	}

	// Alternative Lesefunktion benutzen
	const byte **ref = &fileDataPtr;
	png_set_read_fn(png_ptr, (void *)ref, png_user_read_data);

	// PNG Header einlesen
	png_read_info(png_ptr, info_ptr);

	// PNG Informationen auslesen

	png_uint_32 w, h;
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, &interlaceType, NULL, NULL);
	width = w;
	height = h;

	// Pitch des Ausgabebildes berechnen
	pitch = GraphicEngine::calcPitch(GraphicEngine::CF_ARGB32, width);

	// Speicher für die endgültigen Bilddaten reservieren
	// Dieses geschieht vor dem reservieren von Speicher für temporäre Bilddaten um die Fragmentierung des Speichers gering zu halten
	uncompressedDataPtr = new byte[pitch * height];
	if (!uncompressedDataPtr) {
		error("Could not allocate memory for output image.");
	}

	// Bilder jeglicher Farbformate werden zunächst in ARGB Bilder umgewandelt
	if (bitDepth == 16)
		png_set_strip_16(png_ptr);
	if (colorType == PNG_COLOR_TYPE_PALETTE)
		png_set_expand(png_ptr);
	if (bitDepth < 8)
		png_set_expand(png_ptr);
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
		png_set_expand(png_ptr);
	if (colorType == PNG_COLOR_TYPE_GRAY ||
	        colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
		png_set_gray_to_rgb(png_ptr);

	png_set_bgr(png_ptr);

	if (colorType != PNG_COLOR_TYPE_RGB_ALPHA)
		png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);

	// Nachdem die Transformationen registriert wurden, werden die Bilddaten erneut eingelesen
	png_read_update_info(png_ptr, info_ptr);
	png_get_IHDR(png_ptr, info_ptr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL);
	width = w;
	height = h;

	if (interlaceType == PNG_INTERLACE_NONE) {
		// PNGs without interlacing can simply be read row by row.
		for (i = 0; i < height; i++) {
			png_read_row(png_ptr, uncompressedDataPtr + i * pitch, NULL);
		}
	} else {
		// PNGs with interlacing require us to allocate an auxillary
		// buffer with pointers to all row starts.

		// Allocate row pointer buffer
		png_bytep *pRowPtr = new png_bytep[height];
		if (!pRowPtr) {
			error("Could not allocate memory for row pointers.");
		}

		// Initialize row pointers
		for (i = 0; i < height; i++)
			pRowPtr[i] = uncompressedDataPtr + i * pitch;

		// Read image data
		png_read_image(png_ptr, pRowPtr);

		// Free row pointer buffer
		delete[] pRowPtr;
	}

	// Read additional data at the end.
	png_read_end(png_ptr, NULL);

	// Destroy libpng structures
	png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
#else
	Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO);
	Graphics::PNG *png = new Graphics::PNG();
	if (!png->read(fileStr))	// the fileStr pointer, and thus pFileData will be deleted after this is done
		error("Error while reading PNG image");	

	Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
	Graphics::Surface *pngSurface = png->getSurface(format);

	width = pngSurface->w;
	height = pngSurface->h;
	uncompressedDataPtr = new byte[pngSurface->pitch * pngSurface->h];
	memcpy(uncompressedDataPtr, (byte *)pngSurface->pixels, pngSurface->pitch * pngSurface->h);
	pngSurface->free();

	delete pngSurface;
	delete png;

#endif
	// Signal success
	return true;
}
Exemple #12
0
  int naMain(JNIEnv* env, jobject pObj, jstring pCmdStr, jobject pMainActObj) {
	char progBuf[500];
	jmethodID updateProgMID, toStringMID;
	jstring progStr;
	jclass mainActivityClass = (*env)->GetObjectClass(env, pMainActObj);
	cachedMainActObj = (*env)->NewGlobalRef(env, pMainActObj);

//	toStringMID = (*env)->GetMethodID(env, mainActivityClass, "toString", "()Ljava/lang/String;");
//	jstring name = (*env)->CallObjectMethod(env, pMainActObj, toStringMID);
//	const jbyte* nameStr = (*env)->GetStringUTFChars(env, name, NULL);
//	LOGI(2, "toString: %s", nameStr);
//	(*env)->ReleaseStringUTFChars(env, name, nameStr);

	updateProgMID = (*env)->GetMethodID(env, mainActivityClass, "updateProgress", "(Ljava/lang/String;I)V");
	if (NULL == updateProgMID) {
		LOGE(1, "error finding method updateProgress");
		return EXIT_FAILURE;
	}
//	char* test = "test";
//	jstring jtest = (*env)->NewStringUTF(env, test);
//	(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, jtest);

	int argc = 0;
	char** argv = (char**) malloc (sizeof(char*)*4);
	//the first input argument should be the program name itself
	*argv = "fusch";
	char** targv = argv + 1;
	argc++;
	jboolean isCopy;
    char *cmdstr = (*env)->GetStringUTFChars(env, pCmdStr, &isCopy);
    if (NULL == cmdstr) {
    	LOGI(2, "get string failed");
    	return EXIT_FAILURE;
    }
    char* pch;
    pch = strtok(cmdstr, " ");
    while (NULL != pch) {
    	*targv = pch;
    	argc++;
    	targv++;
    	pch = strtok(NULL, " ");
    }
    LOGI(1, "No. of arguments: %d", argc);
    LOGI(1, "%s %s %s %s", argv[0], argv[1], argv[2], argv[3]);
#else
  int main(int argc, char *argv[]) {
#endif
	setlocale(LC_ALL, "");
	setvbuf(stdout, (char*)NULL, _IONBF, 0);

	if(argc != 4) {
		fprintf(stderr, MSG[I_HELP1], argv[0]);
		fputs(MSG[I_HELP2], stderr);
		return EXIT_FAILURE;
	}

	char *inname  = argv[1],
		 *outname = argv[2],
		 *valarg   = argv[3];

	/* Quelldatei oeffnen und auf PNG-Signatur ueberpruefen **********************/

#ifdef ANDROID_BUILD
//	progStr = (*env)->NewStringUTF(env, MSG[I_OPEN]);
//	(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0);
#else
	puts(MSG[I_OPEN]);
#endif

	FILE *f;

	f = fopen(inname, "rb");
	if (f == NULL) {
		fputs(inname, stderr);
		fputs(MSG[E_OPEN], stderr);
		fputc('\n', stderr);
		return EXIT_FAILURE;
	}

	unsigned char sig[SIG_BYTES];
	fread(sig, 1, SIG_BYTES, f);
	if (png_sig_cmp(sig, 0, SIG_BYTES)) {
		fputs(inname, stderr);
		fputs(MSG[E_CORRUPTED], stderr);
		fputc('\n', stderr);
		fclose(f);
		return EXIT_FAILURE;
	}

	/* PNG-Lesevorgang initialisieren *****************************************/

	png_struct *png_ptr;
	png_info *info_ptr, *end_info;

	png_ptr = png_create_read_struct(
		PNG_LIBPNG_VER_STRING,
		(png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL
	);
	if (png_ptr == NULL) {
		fputs(MSG[E_GENERIC], stderr);
		fputc('\n', stderr);
		fclose(f);
		return EXIT_FAILURE;
	}
	
	info_ptr = png_create_info_struct(png_ptr);
	end_info = png_create_info_struct(png_ptr);

	try_png_read(
		(info_ptr == NULL) || (end_info == NULL),
		&png_ptr, &info_ptr, &end_info, f, (char*)NULL
	);

	try_png_read(
		setjmp(png_jmpbuf(png_ptr)),
		&png_ptr, &info_ptr, &end_info, f, MSG[E_READ]
	);

   	png_init_io(png_ptr, f);
	png_set_sig_bytes(png_ptr, SIG_BYTES);

	/* Bildinfo lesen: Bilddimensionen und ggf. Farbpalette.
	 * Palette ggf. konvertieren. *********************************************/

	long int width, height, pwidth, pheight;
//	png_uint_32 width, height, pwidth, pheight;
	comp_t *image, **row, *rwp;

	png_read_info(png_ptr, info_ptr);

	width = info_ptr->width;
	height = info_ptr->height;
	
	const long int original_width = info_ptr->width;

	const int bit_depth = info_ptr->bit_depth,
			 color_type = info_ptr->color_type;
	const bool image_is_pal = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE);
	const bool image_is_gray = (
		(color_type == PNG_COLOR_TYPE_GRAY) ||
		(color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
	);
	const bool alpha = (
		(color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
		(color_type == PNG_COLOR_TYPE_RGB_ALPHA)
	);

	int num_palette = 0;
	png_color *png_pal_got = NULL;

	if (image_is_pal)

		try_png_read(
			!png_get_PLTE(png_ptr, info_ptr, &png_pal_got, &num_palette),
			&png_ptr, &info_ptr, &end_info, f, MSG[E_READPAL]
		);

	png_color   png_pal[num_palette];	
	comp_t     comp_pal[num_palette];	

	if (image_is_pal)
		for (int i = 0; i < num_palette; i++) {
			png_pal[i] = png_pal_got[i];
			comp_t c;
			c = png_pal[i].red;
			c <<= CHAR_BIT;
			c |= png_pal[i].green;
			c <<= CHAR_BIT;
			c |= png_pal[i].blue;
			comp_pal[i] = c;
		}

	png_color_16 *img_bkgd;
	png_color_16 background;
	if (png_get_bKGD(png_ptr, info_ptr, &img_bkgd))
		background = *img_bkgd;

	/* Parameter fuer Groessenaenderung auswerten:
	 * diff: (Seitenlaenge nachher) - (Seitenlaenge vorher),
	 * vert: true <=> Aenderung der Bildhoehe (sonst -breite). ******************/

	long int diff;
	bool vert;

	bool aspp = false,
		 asp2 = false,
		 enlg = false,
		 sign = true;
	
	switch (tolower(*valarg++)) {
		case 'h': vert = false; break;
		case 'v': vert = true;  break;
		case '%': aspp = true;  break;
		case '@': asp2 = true;  break;
		default :
			try_png_read(true, &png_ptr, &info_ptr, &end_info, f, MSG[E_DIM]);
	}

	switch (*valarg) {
		case '+': enlg = true;  break;
		case '-': enlg = false; break;
		default:  sign = false; break;
	}

	diff = atol(valarg);
	bool valargok = !!diff;

	if (aspp || asp2) {
		try_png_read(!sign, &png_ptr, &info_ptr, &end_info, f, MSG[E_SIGN]);

		const float fheight = (float)height,
					fwidth  = (float)width,
					casp =  fheight / fwidth;
		float nasp;
		if (asp2) {
			const char *aspsw = strtok(valarg, ":"),
					   *aspsh = strtok((char*)NULL, ":");
			valargok = ((aspsw != NULL) && (aspsh != NULL));
			const float aspw = valargok? atol(aspsw): 0,
						asph = valargok? atol(aspsh): 0;
						nasp = valargok? fabs(asph / aspw): 0;
		} else
			nasp = ((float)labs(diff) / 100.0f);

		vert = ((nasp < casp) ^ enlg);
		
		diff = valargok? labs(vert?
			(height - (fwidth  * nasp)):
			(width  - (fheight / nasp))
		): 0;
		if (!enlg)
			diff = -diff;
	}

	if (!diff) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(f);
		if (valargok) {
#ifdef ANDROID_BUILD
			progStr = (*env)->NewStringUTF(env, MSG[I_NOTHINGTODO]);
			(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0);
#else
			puts(MSG[I_NOTHINGTODO]);
#endif
//			const char copycmd[] = "copy /b /y";
			const char copycmd[] = "cp";

			char copycmdln[
				strlen(copycmd) + strlen(argv[1]) + strlen(argv[2]) + 7
			];
			sprintf(
				copycmdln, "%s \"%s\" \"%s\"",
				copycmd, argv[1], argv[2]
			);
			return system(copycmdln);
		}
		try_png_read(!valargok, &png_ptr, &info_ptr, &end_info, f, MSG[E_PAR]);
	}

	if (!(aspp || asp2 || sign))
		diff -= vert? height: width;
	
		try_png_read(
			labs(diff) > (vert? height: width),
			&png_ptr, &info_ptr, &end_info, f, MSG[E_SIZE]
		);

	/* Bild- sowie Zeilenzeigerspeicher anfordern und Zeiger setzen. **********/

	image = malloc(width * height * sizeof(comp_t));
	try_png_read(image == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL);
	
	row = malloc(height * sizeof(comp_t*));
	try_png_read(row == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL);
	
	rwp = image;
	for (int i = 0; i < height; i++) {
		row[i] = rwp;
		rwp += width;
	}
	
	/* Bild laden.
	 * Falls Alphakanal vorhanden, Alpha invertieren: hoher Wert => hohe Deckung.
	 * Falls Nicht-Palettenbild ohne Alphakanal (24 bpp) oder Graubild
	 * (8 oder 16 bpp), mit "png_set_filler" die Bilddaten auf 32 bzw. 16 bpp
	 * ausweiten. 32 Bit ist die *  comp_t-Breite. ****************************/
#ifdef ANDROID_BUILD
//	progStr = (*env)->NewStringUTF(env, MSG[I_LOAD]);
//	(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0);
#else
	puts(MSG[I_LOAD]);
#endif

	if (alpha)
		png_set_invert_alpha(png_ptr);
	else if (!image_is_pal)
		png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);

	png_read_image(png_ptr, (void*)row);

	/* Falls 8 oder 16 bpp, Bilddaten auf "Pixel = comp_t-Element" ausweiten. */

//	trw: Temporaere Zeile.
	void *trw = malloc(image_is_gray? (width * 2): width);

	try_png_read(trw == NULL, &png_ptr, &info_ptr, &end_info, f, (char*)NULL);

//	Zunaechst Bildzeile nach Temporaerzeile kopieren, dann Elemente einzeln zurueck.
	if (image_is_pal) {
		for (int i = 0; i < height; i++) {
			uint8_t *trwp = trw;
			rwp = row[i];
			memcpy(trw, row[i], width * sizeof *trwp);
			for (int j = 0; j < width; j++)
				*rwp++ = *trwp++;
		}
	}

	if (image_is_gray) {
		for (int i = 0; i < height; i++) {
			uint16_t *trwp = trw;
			rwp = row[i];
			memcpy(trw, row[i], width * sizeof *trwp);
			for (int j = 0; j < width; j++)
				*rwp++ = *trwp++;
		}
	}

	/* Lesevorgang beenden und Quelldatei schliessen. ************************/
	
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	fclose(f);

#ifdef ANDROID_BUILD
	sprintf(progBuf, "%s: %d*%d > %d*%d: %s %+d",
			MSG[I_MEASURES],
			width, height,
			vert? width: width + diff,
			vert? height + diff: height,
			vert? MSG[I_VERT]: MSG[I_HORI], diff
		);
	progStr = (*env)->NewStringUTF(env, progBuf);
	(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0);
#else
	printf(
		"%s: %d*%d > %d*%d: %s %+d\n",
		MSG[I_MEASURES],
		width, height,
		vert? width: width + diff,
		vert? height + diff: height,
		vert? MSG[I_VERT]: MSG[I_HORI], diff
	);
#endif

	/* Hier kommt Fugenschnitzer zum Einsatz.
	 * diff: (Seitenlaenge nachher) - (Seitenlaenge vorher),
	 * vert: true <=> Aenderung der Bildhoehe (sonst -breite). ****************/

	sc_init();
	sc_load(image, &width, &height, 0);

	const int prep = sc_prepare(
		vert, diff,									// Bild ggf. erweitern
		false,		
		alpha? MARK_ALPHA: MARK_KEEP,				// Ggf. Alpha-Markierung
		(mark_t*)NULL,								// keine Markierung sonst
		&width, &height, &pwidth, &pheight
	);
	
	if (prep < 0) {
		fputs(MSG[E_GENERIC], stderr);
		fputc('\n', stderr);
		free(image);
		free(row);
		return EXIT_FAILURE;
	}
	
	if (prep & 2) {
#ifdef ANDROID_BUILD
		progStr = (*env)->NewStringUTF(env, MSG[E_ALPHA]);
		(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0);
#else
		puts(MSG[E_ALPHA]);
#endif
	}

//	Bildspeicher erweitern, falls das Bild vergroessert wurde:

	if (prep & 1) {
		image = realloc(image, (size_t)width * (size_t)height * sizeof(comp_t));
		if (image == NULL) {
			fputs(MSG[E_GENERIC], stderr);
			fputc('\n', stderr);
			return EXIT_FAILURE;		
		}
		
		if (vert) {
			row = realloc(row, (size_t)height * sizeof(comp_t*));
			if (row == NULL) {
				fputs(MSG[E_GENERIC], stderr);
				fputc('\n', stderr);
				free(image);
				return EXIT_FAILURE;		
			}
		}		
	}

	pthread_t seam_th;
	pthread_create(&seam_th, NULL, seam_progress, (void*)(&diff));
	
//	sc_seam(diff);
	seam_paral(diff);
	
	pthread_join(seam_th, NULL);

#ifdef ANDROID_BUILD
	progStr = (*env)->NewStringUTF(env, MSG[I_RESIZING]);
	(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0);
#else
	putchar('\n');
	printf(MSG[I_RESIZING]);
#endif
	
//	sc_carve(diff, &width, &height, &pwidth, &pheight);

	carve_paral(diff, &width, &height, &pwidth, &pheight);
	sc_fix(
		false,									// Nicht wiederherstellen
		&width, &height, &pwidth, &pheight
	);

	sc_eject(image);

	sc_close();

	/* Das war's mit Fugenschnitzer. -- Zeilenzeiger neu setzen. **************/

	rwp = image;
	for (int i = 0; i < height; i++) {
		row[i] = rwp;
		rwp += width;
	}

    /* Zieldatei oeffnen und Schreibvorgang initialisieren. ********************/
#ifdef ANDROID_BUILD
	progStr = (*env)->NewStringUTF(env, MSG[I_SAVE]);
	(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0);
#else
	putchar('\n');
	printf(MSG[I_SAVE]);
#endif

	f = fopen(outname, "wb");
	if (f == NULL) {
		fputs(outname, stderr);
		fputs(MSG[E_SAVE], stderr);
		fputc('\n', stderr);
		return EXIT_FAILURE;
	}

	png_ptr = png_create_write_struct(
		PNG_LIBPNG_VER_STRING,
		(png_voidp)NULL, (png_error_ptr)NULL, (png_error_ptr)NULL
	);
	if (png_ptr == NULL) {
		fputs(MSG[E_GENERIC], stderr);
		fputc('\n', stderr);
		fclose(f);
		return EXIT_FAILURE;
	}
	
	info_ptr = png_create_info_struct(png_ptr);
	try_png_write(info_ptr == NULL, &png_ptr, &info_ptr, f, (char*)NULL);

	try_png_write(
		setjmp(png_jmpbuf(png_ptr)),
		&png_ptr, &info_ptr, f, MSG[E_WRITE]
	);

   	png_init_io(png_ptr, f);

	/* Bildparameter setzen. **************************************************/

	png_set_IHDR(
		png_ptr, info_ptr, width, height, bit_depth, color_type,
		PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT
	);

	if (image_is_pal)
		png_set_PLTE(png_ptr, info_ptr, png_pal, num_palette);

	if (alpha)
		png_set_bKGD(png_ptr, info_ptr, &background);

	png_write_info(png_ptr, info_ptr);

	/* Falls 8 oder 16 bpp, Bilddaten wieder zusammenschieben. ****************/

	trw = realloc(trw, image_is_gray? (width * 2): width);
	try_png_write(trw == NULL, &png_ptr, &info_ptr, f, (char*)NULL);

	if (image_is_pal) {
		for (int i = 0; i < height; i++) {
			uint8_t *trwp = trw;
			rwp = row[i];
			for (int j = 0; j < width; j++)
				*trwp++ = *rwp++;
			memcpy(row[i], trw, width * sizeof *trwp);
		}
	}

	if (image_is_gray) {
		for (int i = 0; i < height; i++) {
			uint16_t *trwp = trw;
			rwp = row[i];
			for (int j = 0; j < width; j++)
				*trwp++ = *rwp++;
			memcpy(row[i], trw, width * sizeof *trwp);
		}
	}

	/* Bild speichern. Wieder Alpha invertieren (hoher Wert => hohe Transparenz)
	*  sowie mit "png_set_filler" 32/16 bpp => 24/8 bpp setzen. ***************/

	if (alpha)
		png_set_invert_alpha(png_ptr);
	else
		png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);

	png_write_image(png_ptr, (void*)row);
	png_write_end(png_ptr, (png_info*)NULL);

#ifdef ANDROID_BUILD
	progStr = (*env)->NewStringUTF(env, MSG[I_FINISHED]);
	(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 2);
#else
	puts(MSG[I_FINISHED]);
#endif

	/* Schreibvorgang beenden, Datei schliessen, Speicher freigeben, fertig. ***/

	png_destroy_write_struct(&png_ptr, &info_ptr);
	fclose(f);

	free(trw);
	free(image);
	free(row);
#ifdef ANDROID_BUILD
	progStr = (*env)->NewStringUTF(env, MSG[I_COMPLETED]);
	(*env)->CallVoidMethod(env, pMainActObj, updateProgMID, progStr, 0);
#else
	puts(MSG[I_COMPLETED]);
#endif

#ifdef ANDROID_BUILD
    (*env)->ReleaseStringUTFChars(env, pCmdStr, cmdstr);
	(*env)->DeleteGlobalRef(env, cachedMainActObj);
	cachedMainActObj = NULL;
#endif

	return EXIT_SUCCESS;
}
Exemple #13
0
void TextureLoader::loadPNGTexture(std::ifstream& textureFile, unsigned int& width, unsigned int& height, unsigned char*& data) {
	// Read and validate header
	png_byte header[8];
	textureFile.read((char*) header, 8);
	if (png_sig_cmp(header, 0, 8)) {
		return;
	}

	// Create PNG structs
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) {
		return;
	}
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) {
		png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
		return;
	}
	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info) {
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
		return;
	}

	// PNG error handling
	if (setjmp(png_jmpbuf(png_ptr))) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return;
	}

	// Setup stream read function
	png_set_read_fn(png_ptr, (png_voidp)& textureFile, readPNGData);
	
	// Read PNG info
	png_set_sig_bytes(png_ptr, 8);
	png_read_info(png_ptr, info_ptr);

	png_set_strip_16(png_ptr);
	png_set_expand_gray_1_2_4_to_8(png_ptr);
	png_set_palette_to_rgb(png_ptr);
	if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
		png_set_tRNS_to_alpha(png_ptr);
	}
	png_read_update_info(png_ptr, info_ptr);
	
	int channels = png_get_channels(png_ptr, info_ptr);
	if(channels != 4) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return;
	}
	width =  png_get_image_width(png_ptr, info_ptr);
	height = png_get_image_height(png_ptr, info_ptr);

	// Allocate memory for data
	int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
	data = new unsigned char[rowbytes * height];
	png_bytep *row_pointers = new png_bytep[height];
	if (!data || !row_pointers) {
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return;
	}

	// Set up row_pointers to point at the correct offsets of data[]
	for(unsigned int i = 0; i < height; ++i) {
		//row_pointers[height - 1 - i] = data + i * rowbytes; // same thing
		row_pointers[i] = data + (height - 1 - i) * rowbytes;
	}

	// Read the data
	png_read_image(png_ptr, row_pointers);
}
Exemple #14
0
int
read_png (const char *filename,
          char **data,
          unsigned int *width,
          unsigned int *height)
{
    int i;
    FILE *file;
    static const int PNG_SIG_SIZE = 8;
    unsigned char png_sig[PNG_SIG_SIZE];
    int sig_bytes;
    png_struct *png;
    png_info *info;
    png_uint_32 png_width, png_height;
    int depth, color_type, interlace;
    unsigned int pixel_size;
    png_byte **row_pointers;

    file = fopen (filename, "rb");
    if (file == NULL)
      return 1;
    
    sig_bytes = fread (png_sig, 1, PNG_SIG_SIZE, file);
    if (png_check_sig (png_sig, sig_bytes) == 0) {
      fclose (file);
      return 2;
    }

    /* XXX: Perhaps we'll want some other error handlers? */
    png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
                                  NULL,
                                  NULL,
                                  NULL);
    if (png == NULL) {
      fclose (file);
      return 3;
    }

    info = png_create_info_struct (png);
    if (info == NULL) {
      fclose (file);
      png_destroy_read_struct (&png, NULL, NULL);
      return 3;
    }

    png_init_io (png, file);
    png_set_sig_bytes (png, sig_bytes);

    png_read_info (png, info);

    png_get_IHDR (png, info,
                  &png_width, &png_height, &depth,
                  &color_type, &interlace, NULL, NULL);
    *width = png_width;
    *height = png_height;

    /* convert palette/gray image to rgb */
    if (color_type == PNG_COLOR_TYPE_PALETTE)
      png_set_palette_to_rgb (png);

    /* expand gray bit depth if needed */
    if (color_type == PNG_COLOR_TYPE_GRAY && depth < 8)
      png_set_gray_1_2_4_to_8 (png);

    /* transform transparency to alpha */
    if (png_get_valid(png, info, PNG_INFO_tRNS))
      png_set_tRNS_to_alpha (png);

    if (depth == 16)
      png_set_strip_16 (png);

    if (depth < 8)
      png_set_packing (png);

    /* convert grayscale to RGB */
    if (color_type == PNG_COLOR_TYPE_GRAY
        || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
      png_set_gray_to_rgb (png);

    if (interlace != PNG_INTERLACE_NONE)
      png_set_interlace_handling (png);

    png_set_bgr (png);
    png_set_filler (png, 0xff, PNG_FILLER_AFTER);

    png_set_read_user_transform_fn(png, premultiply_data);

    png_read_update_info (png, info);

    pixel_size = 4;
    *data = (char *) malloc (png_width * png_height * pixel_size);
    if (*data == NULL) {
      fclose (file);
      return 3;
    }

    row_pointers = (png_byte **) malloc (png_height * sizeof(char *));
    for (i=0; i < png_height; i++)
      row_pointers[i] = (png_byte *) (*data + i * png_width * pixel_size);
    
    png_read_image (png, row_pointers);
    png_read_end (png, info);

    free (row_pointers);
    fclose (file);

    png_destroy_read_struct (&png, &info, NULL);
    
    return 0;
}
Exemple #15
0
int
read_png(const char *filename, int *width, int *height, unsigned char **rgb,
         unsigned char **alpha)
{
    int ret = 0;

    png_structp png_ptr;
    png_infop info_ptr;
    png_bytepp row_pointers;

    unsigned char *ptr = NULL;
    png_uint_32 w, h;
    int bit_depth, color_type, interlace_type;
    int i;

    FILE *infile = fopen(filename, "rb");
    if (infile == NULL) {
        fprintf(stderr, "Can not fopen file: %s\n",filename);
        return ret;
    }

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                     (png_voidp) NULL,
                                     (png_error_ptr) NULL,
                                     (png_error_ptr) NULL);
    if (!png_ptr)
        goto file_close;

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, (png_infopp) NULL,
                                (png_infopp) NULL);
    }

#if PNG_LIBPNG_VER_MAJOR >= 1 && PNG_LIBPNG_VER_MINOR >= 4
    if (setjmp(png_jmpbuf((png_ptr))))
#else
    if (setjmp(png_ptr->jmpbuf))
#endif
        goto png_destroy;

    png_init_io(png_ptr, infile);
    png_read_info(png_ptr, info_ptr);

    png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type,
                 &interlace_type, (int *) NULL, (int *) NULL);

    /* Prevent against integer overflow */
    if(w >= MAX_DIMENSION || h >= MAX_DIMENSION) {
        fprintf(stderr, "Unreasonable dimension found in file: %s\n",filename);
        goto png_destroy;
    }

    *width = (int) w;
    *height = (int) h;

    if (color_type == PNG_COLOR_TYPE_RGB_ALPHA
            || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
        alpha[0] = malloc(*width * *height);
        if (alpha[0] == NULL)
        {
            fprintf(stderr, "Can't allocate memory for alpha channel in PNG file.\n");
            goto png_destroy;
        }
    }

    /* Change a paletted/grayscale image to RGB */
    if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8)
        png_set_expand(png_ptr);

    /* Change a grayscale image to RGB */
    if (color_type == PNG_COLOR_TYPE_GRAY
            || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        png_set_gray_to_rgb(png_ptr);

    /* If the PNG file has 16 bits per channel, strip them down to 8 */
    if (bit_depth == 16)
        png_set_strip_16(png_ptr);

    /* use 1 byte per pixel */
    png_set_packing(png_ptr);

    row_pointers = malloc(*height * sizeof(png_bytep));
    if (row_pointers == NULL) {
        fprintf(stderr, "Can't allocate memory for PNG file.\n");
        goto png_destroy;
    }

    for (i = 0; i < *height; i++) {
        row_pointers[i] = malloc(4 * *width);
        if (row_pointers == NULL) {
            fprintf(stderr, "Can't allocate memory for PNG line.\n");
            goto rows_free;
        }
    }

    png_read_image(png_ptr, row_pointers);

    rgb[0] = malloc(3 * *width * *height);
    if (rgb[0] == NULL) {
        fprintf(stderr, "Can't allocate memory for PNG file.\n");
        goto rows_free;
    }

    if (alpha[0] == NULL)
    {
        ptr = rgb[0];
        for (i = 0; i < *height; i++) {
            memcpy(ptr, row_pointers[i], 3 * *width);
            ptr += 3 * *width;
        }
    } else {
        int j;
        ptr = rgb[0];
        for (i = 0; i < *height; i++) {
            int ipos = 0;
            for (j = 0; j < *width; j++) {
                *ptr++ = row_pointers[i][ipos++];
                *ptr++ = row_pointers[i][ipos++];
                *ptr++ = row_pointers[i][ipos++];
                alpha[0][i * *width + j] = row_pointers[i][ipos++];
            }
        }
    }

    ret = 1; /* data reading is OK */

rows_free:
    for (i = 0; i < *height; i++) {
        if (row_pointers[i] != NULL ) {
            free(row_pointers[i]);
        }
    }

    free(row_pointers);

png_destroy:
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);

file_close:
    fclose(infile);
    return(ret);
}
Exemple #16
0
void RawImage::loadPNG(FILE* file) throw(ImageException)
{
  png_structp pngData = NULL;
  png_infop pngInfo = NULL;
  unsigned char** rowPtrs = NULL;

  try {
    pngData = png_create_read_struct(PNG_LIBPNG_VER_STRING,
      NULL,   // error_ptr
      NULL,   // error_fn
      NULL    // warn_fn
    );
    pngInfo = png_create_info_struct(pngData);

    unsigned char header[8];
    if (fread(header, 1, 8, file) < 8)
      throw ImageException("Missing PNG header data.");
    if (png_sig_cmp(header, 0, 8) != 0)
      throw ImageException("Not a PNG file!");
    if (setjmp(png_jmpbuf(pngData)))
      throw ImageException("PNG library error.");

    png_init_io(pngData, file);
    png_set_sig_bytes(pngData, 8);
    png_read_info(pngData, pngInfo);

    png_uint_32 width, height;
    int bitDepth, colorType, iMethod, cMethod, fMethod;
    png_get_IHDR(pngData, pngInfo, &width, &height, &bitDepth, &colorType,
        &iMethod, &cMethod, &fMethod);

    int bytesPerChannel = (bitDepth / 8);
    if (bitDepth % 8 != 0)
      ++bytesPerChannel;

    _width = width;
    _height = height;
    switch (colorType) {
      case PNG_COLOR_TYPE_PALETTE:
        png_set_palette_to_rgb(pngData);
        _type = GL_RGB;
        _bytesPerPixel = bytesPerChannel * 3;
        break;
      case PNG_COLOR_TYPE_RGBA:
        _type = GL_RGBA;
        _bytesPerPixel = bytesPerChannel * 4;
        break;
      case PNG_COLOR_TYPE_RGB:
        _type = GL_RGB;
        _bytesPerPixel = bytesPerChannel * 3;
        break;
      case PNG_COLOR_TYPE_GRAY:
        if (bitDepth < 8)
          png_set_gray_1_2_4_to_8(pngData);
        _type = GL_ALPHA;
        _bytesPerPixel = bytesPerChannel;
        break;
      default:
        throw ImageException("Unknown PNG type.");
    }

    _pixels = new unsigned char[_bytesPerPixel * _width * _height];
    rowPtrs = new unsigned char*[_height];
    for (size_t i = 0; i < _height; ++i)
      rowPtrs[i] = &_pixels[_bytesPerPixel * _width * (_height - i - 1)];
    png_read_image(pngData, rowPtrs);

    png_destroy_read_struct(&pngData, &pngInfo, NULL);
    delete[] rowPtrs;
  } catch (ImageException& e) {
    png_destroy_read_struct(&pngData, &pngInfo, NULL);
    if (rowPtrs != NULL)
      delete[] rowPtrs;
    throw e;
  }
}
int readpng2_init(mainprog_info *mainprog_ptr)
{
    png_structp  png_ptr;       /* note:  temporary variables! */
    png_infop  info_ptr;


    /* could also replace libpng warning-handler (final NULL), but no need: */

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
      readpng2_error_handler, readpng2_warning_handler);
    if (!png_ptr)
        return 4;   /* out of memory */

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_read_struct(&png_ptr, NULL, NULL);
        return 4;   /* out of memory */
    }


    /* we could create a second info struct here (end_info), but it's only
     * useful if we want to keep pre- and post-IDAT chunk info separated
     * (mainly for PNG-aware image editors and converters) */


    /* setjmp() must be called in every function that calls a PNG-reading
     * libpng function, unless an alternate error handler was installed--
     * but compatible error handlers must either use longjmp() themselves
     * (as in this program) or exit immediately, so here we are: */

    if (setjmp(mainprog_ptr->jmpbuf)) {
        png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
        return 2;
    }


#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
    /* prepare the reader to ignore all recognized chunks whose data won't be
     * used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT,
     * IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */
    {
        /* These byte strings were copied from png.h.  If a future version
         * of readpng2.c recognizes more chunks, add them to this list.
         */
        static PNG_CONST png_byte chunks_to_process[] = {
            98,  75,  71,  68, '\0',  /* bKGD */
           103,  65,  77,  65, '\0',  /* gAMA */
           115,  82,  71,  66, '\0',  /* sRGB */
           };

       /* Ignore all chunks except for IHDR, PLTE, tRNS, IDAT, and IEND */
       png_set_keep_unknown_chunks(png_ptr, -1 /* PNG_HANDLE_CHUNK_NEVER */,
          NULL, -1);

       /* But do not ignore chunks in the "chunks_to_process" list */
       png_set_keep_unknown_chunks(png_ptr,
          0 /* PNG_HANDLE_CHUNK_AS_DEFAULT */, chunks_to_process,
          sizeof(chunks_to_process)/5);
    }
#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */


    /* instead of doing png_init_io() here, now we set up our callback
     * functions for progressive decoding */

    png_set_progressive_read_fn(png_ptr, mainprog_ptr,
      readpng2_info_callback, readpng2_row_callback, readpng2_end_callback);


    /* make sure we save our pointers for use in readpng2_decode_data() */

    mainprog_ptr->png_ptr = png_ptr;
    mainprog_ptr->info_ptr = info_ptr;


    /* and that's all there is to initialization */

    return 0;
}
static void *read_png_raw(const char *fname,
                          size_t * nxp, size_t * nyp, size_t * ncp,
                          int transform, int dtype)
{
    png_byte png_sig[PNG_SIG_LEN];
    png_structp png_ptr;
    png_infop info_ptr;
    png_bytepp row_pointers;
    png_bytep row_ptr;
    /* volatile : because of setjmp/longjmp */
    FILE *volatile fp = NULL;
    void *data = NULL;
    unsigned char *data_u8 = NULL;
    unsigned char *data_u8_ptr = NULL;
    float *data_f32 = NULL;
    float *data_f32_ptr = NULL;
    size_t size;
    size_t i, j, k;

    /* parameters check */
    if (NULL == fname || NULL == nxp || NULL == nyp || NULL == ncp)
        return NULL;
    if (IO_PNG_U8 != dtype && IO_PNG_F32 != dtype)
        return NULL;

    /* open the PNG input file */
    if (0 == strcmp(fname, "-"))
        fp = stdin;
    else if (NULL == (fp = fopen(fname, "rb")))
        return NULL;

    /* read in some of the signature bytes and check this signature */
    if ((PNG_SIG_LEN != fread(png_sig, 1, PNG_SIG_LEN, fp))
        || 0 != png_sig_cmp(png_sig, (png_size_t) 0, PNG_SIG_LEN))
        return read_png_abort(fp, NULL, NULL);

    /*
     * create and initialize the png_struct
     * with the default stderr and error handling
     */
    if (NULL == (png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                                  NULL, NULL, NULL)))
        return read_png_abort(fp, NULL, NULL);

    /* allocate/initialize the memory for image information */
    if (NULL == (info_ptr = png_create_info_struct(png_ptr)))
        return read_png_abort(fp, &png_ptr, NULL);

    /* set error handling */
    if (0 != setjmp(png_jmpbuf(png_ptr)))
        /* if we get here, we had a problem reading the file */
        /* free all of the memory associated with the png_ptr and info_ptr */
        return read_png_abort(fp, &png_ptr, &info_ptr);

    /* set up the input control using standard C streams */
    png_init_io(png_ptr, fp);

    /* let libpng know that some bytes have been read */
    png_set_sig_bytes(png_ptr, PNG_SIG_LEN);

    /*
     * set the read filter transforms, to get 8bit RGB whatever the
     * original file may contain:
     * PNG_TRANSFORM_STRIP_16      strip 16-bit samples to 8 bits
     * PNG_TRANSFORM_PACKING       expand 1, 2 and 4-bit
     *                             samples to bytes
     */
    transform |= (PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING);

    /* read in the entire image at once */
    png_read_png(png_ptr, info_ptr, transform, NULL);

    /* get image informations */
    *nxp = (size_t) png_get_image_width(png_ptr, info_ptr);
    *nyp = (size_t) png_get_image_height(png_ptr, info_ptr);
    *ncp = (size_t) png_get_channels(png_ptr, info_ptr);
    row_pointers = png_get_rows(png_ptr, info_ptr);

    /*
     * allocate the output data RGB array
     * deinterlace and convert png RGB RGB RGB 8bit to RRR GGG BBB
     * the image is deinterlaced layer after layer
     * this generic loop also works for one single channel
     */
    size = *nxp * *nyp * *ncp;
    switch (dtype)
    {
    case IO_PNG_U8:
        if (NULL == (data_u8 =
                     (unsigned char *) malloc(size * sizeof(unsigned char))))
            return read_png_abort(fp, &png_ptr, &info_ptr);
        data = (void *) data_u8;
        for (k = 0; k < *ncp; k++)
        {
            /* channel loop */
            data_u8_ptr = data_u8 + (size_t) (*nxp * *nyp * k);
            for (j = 0; j < *nyp; j++)
            {
                /* row loop */
                row_ptr = row_pointers[j] + k;
                for (i = 0; i < *nxp; i++)
                {
                    /* pixel loop */
                    *data_u8_ptr++ = (unsigned char) *row_ptr;
                    row_ptr += *ncp;
                }
            }
        }
        break;
    case IO_PNG_F32:
        if (NULL == (data_f32 = (float *) malloc(size * sizeof(float))))
            return read_png_abort(fp, &png_ptr, &info_ptr);
        data = (void *) data_f32;
        for (k = 0; k < *ncp; k++)
        {
            /* channel loop */
            data_f32_ptr = data_f32 + (size_t) (*nxp * *nyp * k);
            for (j = 0; j < *nyp; j++)
            {
                /* row loop */
                row_ptr = row_pointers[j] + k;
                for (i = 0; i < *nxp; i++)
                {
                    /* pixel loop */
                    *data_f32_ptr++ = (float) *row_ptr;
                    row_ptr += *ncp;
                }
            }
        }
        break;
    }

    /* clean up and free any memory allocated, close the file */
    (void) read_png_abort(fp, &png_ptr, &info_ptr);

    return data;
}
Exemple #19
0
bool Image::loadPng(const std::string& filename)
{
  // check that the file is a png file
  png_byte buf[8];

  FILE* in = std::fopen(filename.c_str(), "rb");

  if (!in) return false;

  for (int i = 0; i < 8; i++) {
    if (!(buf[i] = fgetc(in))) return false;
  }
  if (png_sig_cmp(buf, 0, 8)) return false;

  png_structp png_ptr =
    png_create_read_struct(PNG_LIBPNG_VER_STRING,
			   0, 0, 0);
  if (!png_ptr) return false;

  png_infop info_ptr = png_create_info_struct(png_ptr);
  if (!info_ptr) {
    png_destroy_read_struct(&png_ptr, 0, 0);
    return false;
  }

  if (setjmp(png_jmpbuf(png_ptr))) {
    png_destroy_read_struct(&png_ptr, 0, 0);
    return false;
  }

  //  png_set_read_fn(png_ptr, reinterpret_cast<void*>(&in), my_istream_read_data);
  png_init_io(png_ptr, in);

  png_set_sig_bytes(png_ptr, 8);

  png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, 0);

  int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  if (bit_depth % 8) {
    png_destroy_read_struct(&png_ptr, 0, 0);
    std::ostringstream os;
    os << "Invalid bit elements " << bit_depth;
    return false;
  }

  int colour_type = png_get_color_type(png_ptr, info_ptr);

  if (colour_type == PNG_COLOR_TYPE_PALETTE) {
    png_set_palette_to_rgb(png_ptr);
    colour_type = PNG_COLOR_TYPE_RGB;
  }

  if (colour_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
    png_set_gray_1_2_4_to_8(png_ptr);
  }

  if (colour_type != PNG_COLOR_TYPE_RGB
      && colour_type != PNG_COLOR_TYPE_GRAY
      && colour_type != PNG_COLOR_TYPE_RGBA) {
    png_destroy_read_struct(&png_ptr, 0, 0);
    return false;
  }

  delete [] m_data;

  m_width = png_get_image_width(png_ptr, info_ptr);
  m_height = png_get_image_height(png_ptr, info_ptr);
  switch (colour_type) {
  case PNG_COLOR_TYPE_RGB:
    m_elements = 3;
    break;
  case PNG_COLOR_TYPE_RGBA:
    m_elements = 4;
    break;
  default:
    m_elements = 1;
    break;
  }

  png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);

  m_data = new double[m_width * m_height * m_elements];

  for (int y = 0; y < m_height; y++) {
    for (int x = 0; x < m_width; x++) {
      for (int i = 0; i < m_elements; i++) {
	png_byte *row = row_pointers[y];
	int index = m_elements * (y * m_width + x) + i;

        long element = 0;
        for (int j = bit_depth/8 - 1; j >= 0; j--) {
          element <<= 8;
          element += row[(x * m_elements + i) * bit_depth/8 + j];
        }

	m_data[index] = element / static_cast<double>((1 << bit_depth) - 1);
      }
    }
  }

  png_destroy_read_struct(&png_ptr, &info_ptr, 0);

  return true;
}
Exemple #20
0
int load_png(char * file_name, int * w, int * h, int * depth, char ** data)
{
#if COMPILE_PNG_CODE
    FILE *fp;
    png_structp png_ptr;
    png_infop info_ptr;
    png_uint_32 width, height;
    int bit_depth, color_type, interlace_type,
        compression_type, filter_type;
    int rowbytes, channels;
    unsigned int i;
    char * buff;
    char ** row_pointers;

    fp = fopen(file_name, "rb");
    if (!fp){
        error_print("Cannot load required png-file (%s). Terminating!",file_name);
        sys_exit(1);
    }

    png_ptr = png_create_read_struct
       (PNG_LIBPNG_VER_STRING, (png_voidp)NULL/*user_error_ptr*/,
        NULL/*user_error_fn*/, NULL/*user_warning_fn*/);
    if (!png_ptr) {
        error_print("Error png-ptr png-file (%s). Terminating!",file_name);
        sys_exit(1);
     }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        error_print("Error create info struct png-file (%s). Terminating!",file_name);
        sys_exit(1);
    }

    png_init_io(png_ptr, fp);

    png_read_info(png_ptr, info_ptr);

    png_get_IHDR(png_ptr, info_ptr, &width, &height,
                 &bit_depth, &color_type, &interlace_type,
                 &compression_type, &filter_type);

    channels = png_get_channels(png_ptr, info_ptr);

    rowbytes = png_get_rowbytes(png_ptr, info_ptr);

    buff         = (char *)  malloc(height*rowbytes);
    row_pointers = (char **) malloc(height*sizeof(char *));
    for(i=0;i<height;i++){
        row_pointers[i]=&buff[rowbytes*i];
    }

    png_read_image(png_ptr, (png_bytepp)row_pointers);

    //fprintf(stderr,"load_png: rgstereo=%d\n",options_rgstereo_on);

    if( options_rgstereo_on ){
        //fprintf(stderr,"load_png: graying out texture\n");
        for(i=0;i<height;i++){
            int j,k,d;
            for(j=0;j<rowbytes;j+=channels){
                d=0;
                for(k=0;k<channels;k++) d+=(unsigned char)row_pointers[i][j+k];
                d/=channels;
                for(k=0;k<channels;k++) row_pointers[i][j+k]=d;
            }
        }
    }

    free(row_pointers);
    free(info_ptr);
    free(png_ptr);
    fclose(fp);

    *data  = buff;
    *w     = width;
    *h     = height;
    *depth = channels*bit_depth;

    return 1;
#else
    *data  = 0;
    *w     = 0;
    *h     = 0;
    *depth = 0;
    return 1;
#endif
}
Exemple #21
0
/**
 * loadTexture takes a filename and returns a Texture pointer to the texture place in memory
 */
Texture *Graphics::loadTexture(const char *filename)
{
	// log it out
	Log::info("Loading texture \"%s\"...", filename);

	// header for testing if it is a png
	png_byte header[8];

	// open file as binary
	FILE *fp = fopen(filename, "rb");
	if (!fp)
	{	
		Log::error("File failed to load!");
		return NULL;
	}

	// read the header
	fread(header, 1, 8, fp);

	// test if png
	int is_png = !png_sig_cmp(header, 0, 8);
	if (!is_png) 
	{
		Log::error("Image is not a PNG!");
		fclose(fp);
		return NULL;
	}

	// create png struct
	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	if (!png_ptr) 
	{
		Log::error("png_ptr failed to create read struct!");
		fclose(fp);
		return NULL;
	}

	// create png info struct
	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr) 
	{
		Log::error("info_ptr failed to create struct!");
		png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
		fclose(fp);
		return NULL;
	}

	// create png info struct
	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info) 
	{
		Log::error("end_info failed to create struct!");
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
		fclose(fp);
		return NULL;
	}

	// png error stuff, not sure libpng man suggests this.
	if (setjmp(png_jmpbuf(png_ptr))) 
	{
		Log::error("png_jumpbuf overflow!");
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(fp);
		return NULL;
	}

	// init png reading
	png_init_io(png_ptr, fp);

	//let libpng know you already read the first 8 bytes
	png_set_sig_bytes(png_ptr, 8);

	// read all the info up to the image data
	png_read_info(png_ptr, info_ptr);

	//variables to pass to get info
	int bit_depth, color_type;
	png_uint_32 twidth, theight;

	// get info about png
	png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL);

	// update width and height based on png info
	int width = twidth;
	int height = theight;

	// update the png info struct.
	png_read_update_info(png_ptr, info_ptr);

	// row size in bytes.
	int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

	// allocate the image_data as a big block, to be given to opengl
	png_byte *image_data = new png_byte[rowbytes * height];
	if (!image_data) 
	{
		Log::error("image_data failed to create a new png_byte!");
		//clean up memory and close stuff
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(fp);
		return NULL;
	}

	// row_pointers is for pointing to image_data for reading the png with libpng
	png_bytep *row_pointers = new png_bytep[height];
	if (!row_pointers) 
	{
		Log::error("row_pointers failed to create a new png_bytep!");
		//clean up memory and close stuff
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		delete[] image_data;
		fclose(fp);
		return NULL;
	}

	// set the individual row_pointers to point at the correct offsets of image_data
	for (int i = 0; i < height; ++i)
		row_pointers[height - 1 - i] = image_data + i * rowbytes;

	//read the png into image_data through row_pointers
	png_read_image(png_ptr, row_pointers);

	// now generate the OpenGL texture object
	GLuint texture;
	glGenTextures(1, &texture);
	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
	// gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image_data);

	//clean up memory and close stuff
	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
	delete[] image_data;
	delete[] row_pointers;
	fclose(fp);

	// create the texture struct
	Texture *_texture = new Texture;
	_texture->texture = texture;
	_texture->width = width;
	_texture->height = height;

	// store the texture in the vector
	this->texturePile.push_back(_texture);

	// log the texture being loaded
	Log::info("Loaded texture \"%s\" at %i...", filename, _texture->texture);

	// return the texture
	return this->texturePile.at(texture - 1);
}
Exemple #22
0
void PNGCodec::decode(std::vector<uint8_t> &in,
	std::vector<uint8_t> *out, unsigned int *width, 
	unsigned int *height, ColorFormat *format, uint8_t level)
{
	if (level != 0)
	{
		// TODO: Error handling.
		return;
	}

	if (png_check_sig(in.data(), SIGNATURE_LENGTH) == false)
	{
		// TODO: Error handling.
		return;
	}

	png_structp pngPtr = png_create_read_struct(
		PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);

	if (pngPtr == nullptr)
	{
		// TODO: Error handling.
		return;
	}

	png_infop pngInfoPtr = png_create_info_struct(pngPtr);

	if (pngInfoPtr == nullptr)
	{
		// TODO: Error handling.
		png_destroy_read_struct(&pngPtr, nullptr, nullptr);
		return;
	}

	PNGVectorStream stream;
	stream.vec = &in;
	stream.offset = 0;

	png_set_read_fn(pngPtr, &stream, PNGReadCallback);
	png_read_info(pngPtr, pngInfoPtr);

	int bitDepth = 0;
	int colorType = -1;
	png_uint_32 retval = png_get_IHDR(pngPtr, pngInfoPtr,
		width,
		height,
		&bitDepth,
		&colorType,
		nullptr, nullptr, nullptr);

	if (retval != 1)
	{
		// TODO: Error handling.
		png_destroy_read_struct(&pngPtr, &pngInfoPtr, nullptr);
		return;
	}

	switch (colorType)
	{
	case PNG_COLOR_TYPE_RGB:
		*format = ColorFormat::RGB;
		break;

	case PNG_COLOR_TYPE_RGBA:
		*format = ColorFormat::RGBA;
		break;

	default:
		// TODO: Error handling.
		png_destroy_read_struct(&pngPtr, &pngInfoPtr, nullptr);
		return;
	}

	out->resize((*width) * (*height) * static_cast<unsigned int>(*format));

	for (unsigned int i = 0; i < *height; ++i)
		png_read_row(pngPtr, 
			&(*out)[i * (*width) * static_cast<unsigned int>(*format)], nullptr);

	png_destroy_read_struct(&pngPtr, &pngInfoPtr, nullptr);
}
GLubyte* 
glmReadPNG(const char* filename, GLboolean alpha, int* width_ret, int* height_ret, int* type_ret)
{
  png_structp png_ptr;
  png_infop info_ptr;
  png_uint_32 width, height;
  
  int bit_depth, color_type, interlace_type;
  FILE *fp;
  unsigned char *buffer;
  int y, bytes_per_row;
  int channels;
  int format;
  png_bytepp row_pointers;

  if ((fp = fopen(filename, "rb")) == NULL) {
    pngerror = ERR_OPEN;
    return NULL;
  }

  /* Create and initialize the png_struct with the desired error handler
   * functions.  If you want to use the default stderr and longjump method,
   * you can supply NULL for the last three parameters.  We also supply the
   * the compiler header file version, so that we know if the application
   * was compiled with a compatible version of the library.  REQUIRED
   */
  /*png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
      (void *)user_error_ptr, user_error_fn, user_warning_fn);*/

  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
				   NULL, err_callback, warn_callback);
  
  if (png_ptr == NULL) {
    pngerror = ERR_MEM;
    fclose(fp);
    return 0;
  }

  /* Allocate/initialize the memory for image information.  REQUIRED. */
  info_ptr = png_create_info_struct(png_ptr);
  if (info_ptr == NULL) {
    pngerror = ERR_MEM;
    fclose(fp);
    png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
    return 0;
  }
  
  /* Set error handling if you are using the setjmp/longjmp method (this is
   * the normal method of doing things with libpng).  REQUIRED unless you
   * set up your own error handlers in the png_create_read_struct() earlier.
   */

  buffer = NULL;

  if (setjmp(setjmp_buffer)) {
    pngerror = ERR_PNGLIB;
    /* Free all of the memory associated with the png_ptr and info_ptr */
    png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
    fclose(fp);
    /* If we get here, we had a problem reading the file */

    if (buffer) free(buffer);
    return NULL;
  }
  
  /* Set up the input control if you are using standard C streams */
  png_init_io(png_ptr, fp);

  /* The call to png_read_info() gives us all of the information from the
   * PNG file before the first IDAT (image data chunk).  REQUIRED
   */
  png_read_info(png_ptr, info_ptr);

  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
	       &interlace_type, NULL, NULL);

  /**** Set up the data transformations you want.  Note that these are all
  **** optional.  Only call them if you want/need them.  Many of the
  **** transformations only work on specific types of images, and many
  **** are mutually exclusive.
  ****/

  /* tell libpng to strip 16 bit/color files down to 8 bits/color */
  png_set_strip_16(png_ptr);

  /* strip alpha bytes from the input data without combining with th
   * background (not recommended) */
  /* png_set_strip_alpha(png_ptr); */
  
  /* extract multiple pixels with bit depths of 1, 2, and 4 from a single
   * byte into separate bytes (useful for paletted and grayscale images).
   */
  /* png_set_packing(png_ptr); */

  /* change the order of packed pixels to least significant bit first
   * (not useful if you are using png_set_packing). */
  /* png_set_packswap(png_ptr); */
  
  /* expand paletted colors into true RGB triplets */
  if (color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_expand(png_ptr);

  /* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_expand(png_ptr);
  
  /* expand paletted or RGB images with transparency to full alpha channels
   * so the data will be available as RGBA quartets */
  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
    png_set_expand(png_ptr);
  
  /* Add filler (or alpha) byte (before/after each RGB triplet) */
  /* png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); */

  png_read_update_info(png_ptr, info_ptr);

  channels = png_get_channels(png_ptr, info_ptr);

  /* allocate the memory to hold the image using the fields of info_ptr. */
  
  bytes_per_row = png_get_rowbytes(png_ptr, info_ptr);

  
  buffer = (unsigned char*) malloc(bytes_per_row*height);

  format = channels;

  row_pointers = (png_bytepp) malloc(height*sizeof(png_bytep));
  for (y = 0; y < height; y++) {
    row_pointers[height-y-1] = buffer + y*bytes_per_row;
  }
  
  png_read_image(png_ptr, row_pointers);
  png_read_end(png_ptr, info_ptr);
  
  free(row_pointers);

  /* clean up after the read, and free any memory allocated - REQUIRED */
  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);

  /* close the file */
  fclose(fp);

  /* that's it */
  if (buffer) {
    *width_ret = width;
    *height_ret = height;
    switch(format) {
    case 1:
	*type_ret = GL_LUMINANCE;
	break;
    case 2:
	*type_ret = GL_LUMINANCE_ALPHA;
	break;
    case 3:
	*type_ret = GL_RGB;
	break;
    case 4:
	*type_ret = GL_RGBA;
	break;
    }
    pngerror = ERR_NO_ERROR;
  }
  else {
    pngerror = ERR_MEM;
  }
  return buffer;
}
Exemple #24
0
int loadPNG(ePtr<gPixmap> &result, const char *filename)
{
	__u8 header[8];
	FILE *fp=fopen(filename, "rb");
	
	if (!fp)
	{
//		eDebug("couldn't open %s", filename );
		return 0;
	}
	if (!fread(header, 8, 1, fp))
	{
		eDebug("couldn't read");
		fclose(fp);
		return 0;
	}
	if (png_sig_cmp(header, 0, 8))
	{
		fclose(fp);
		return 0;
	}
	png_structp png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
	if (!png_ptr)
	{
		eDebug("no pngptr");
		fclose(fp);
		return 0;
	}
	png_infop info_ptr=png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		eDebug("no info ptr");
		png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0);
		fclose(fp);
		return 0;
	}
	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info)
	{
		eDebug("no end");
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		fclose(fp);
		return 0;
	 }
	if (setjmp(png_ptr->jmpbuf))
	{
		eDebug("das war wohl nix");
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		fclose(fp);
		result = 0;
		return 0;
	}
	png_init_io(png_ptr, fp);
	png_set_sig_bytes(png_ptr, 8);
	png_set_invert_alpha(png_ptr);
	png_read_info(png_ptr, info_ptr);
	
	png_uint_32 width, height;
	int bit_depth;
	int color_type;
	
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, 0, 0, 0);
	
	if (color_type == PNG_COLOR_TYPE_GRAY || color_type & PNG_COLOR_MASK_PALETTE)
	{
		result=new gPixmap(eSize(width, height), bit_depth);
		gSurface *surface = result->surface;
	
		png_bytep *rowptr=new png_bytep[height];
	
		for (unsigned int i=0; i<height; i++)
			rowptr[i]=((png_byte*)(surface->data))+i*surface->stride;
		png_read_rows(png_ptr, rowptr, 0, height);
	
		delete [] rowptr;
	
		if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))
		{
			png_color *palette;
			int num_palette;
			png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
			if (num_palette)
				surface->clut.data=new gRGB[num_palette];
			else
				surface->clut.data=0;
			surface->clut.colors=num_palette;
			
			for (int i=0; i<num_palette; i++)
			{
				surface->clut.data[i].a=0;
				surface->clut.data[i].r=palette[i].red;
				surface->clut.data[i].g=palette[i].green;
				surface->clut.data[i].b=palette[i].blue;
			}
			if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
			{
				png_byte *trans;
				png_get_tRNS(png_ptr, info_ptr, &trans, &num_palette, 0);
				for (int i=0; i<num_palette; i++)
					surface->clut.data[i].a=255-trans[i];
			}
		} else
		{
			surface->clut.data=0;
			surface->clut.colors=0;
		}
		surface->clut.start=0;
		png_read_end(png_ptr, end_info);
	} else {
		result=0;
		eDebug("%s: %dx%dx%d png, %d", filename, (int)width, (int)height, (int)bit_depth, color_type);
	}

	png_destroy_read_struct(&png_ptr, &info_ptr,&end_info);
	fclose(fp);
	return 0;
}
Exemple #25
0
GLuint png_texture_load(const char * file_name, int * width, int * height)
{
    png_byte header[8];

    FILE *fp = fopen(file_name, "rb");
    if (fp == 0)
    {
        perror(file_name);
        return 0;
    }

    // read the header
    fread(header, 1, 8, fp);

    if (png_sig_cmp(header, 0, 8))
    {
        fprintf(stderr, "error: %s is not a PNG.\n", file_name);
        fclose(fp);
        return 0;
    }

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr)
    {
        fprintf(stderr, "error: png_create_read_struct returned 0.\n");
        fclose(fp);
        return 0;
    }

    // create png info struct
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
    {
        fprintf(stderr, "error: png_create_info_struct returned 0.\n");
        png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
        fclose(fp);
        return 0;
    }

    // create png info struct
    png_infop end_info = png_create_info_struct(png_ptr);
    if (!end_info)
    {
        fprintf(stderr, "error: png_create_info_struct returned 0.\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
        fclose(fp);
        return 0;
    }

    // the code in this if statement gets called if libpng encounters an error
    if (setjmp(png_jmpbuf(png_ptr))) {
        fprintf(stderr, "error from libpng\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fp);
        return 0;
    }

    // init png reading
    png_init_io(png_ptr, fp);

    // let libpng know you already read the first 8 bytes
    png_set_sig_bytes(png_ptr, 8);

    // read all the info up to the image data
    png_read_info(png_ptr, info_ptr);

    // variables to pass to get info
    int bit_depth, color_type;
    png_uint_32 temp_width, temp_height;

    // get info about png
    png_get_IHDR(png_ptr, info_ptr, &temp_width, &temp_height, &bit_depth, &color_type,
        NULL, NULL, NULL);

    if (width){ *width = temp_width; }
    if (height){ *height = temp_height; }

    //printf("%s: %lux%lu %d\n", file_name, temp_width, temp_height, color_type);

    if (bit_depth != 8)
    {
        fprintf(stderr, "%s: Unsupported bit depth %d.  Must be 8.\n", file_name, bit_depth);
        return 0;
    }

    GLint format;
    switch(color_type)
    {
    case PNG_COLOR_TYPE_RGB:
        format = GL_RGB;
        break;
    case PNG_COLOR_TYPE_RGB_ALPHA:
        format = GL_RGBA;
        break;
    default:
        fprintf(stderr, "%s: Unknown libpng color type %d.\n", file_name, color_type);
        return 0;
    }

    // Update the png info struct.
    png_read_update_info(png_ptr, info_ptr);

    // Row size in bytes.
    int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

    // glTexImage2d requires rows to be 4-byte aligned
    rowbytes += 3 - ((rowbytes-1) % 4);

    // Allocate the image_data as a big block, to be given to opengl
    png_byte * image_data = (png_byte *)malloc(rowbytes * temp_height * sizeof(png_byte)+15);
    if (image_data == NULL)
    {
        fprintf(stderr, "error: could not allocate memory for PNG image data\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        fclose(fp);
        return 0;
    }

    // row_pointers is for pointing to image_data for reading the png with libpng
    png_byte ** row_pointers = (png_byte **)malloc(temp_height * sizeof(png_byte *));
    if (row_pointers == NULL)
    {
        fprintf(stderr, "error: could not allocate memory for PNG row pointers\n");
        png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
        free(image_data);
        fclose(fp);
        return 0;
    }

    // set the individual row_pointers to point at the correct offsets of image_data
    for (unsigned int i = 0; i < temp_height; i++)
    {
        row_pointers[temp_height - 1 - i] = image_data + i * rowbytes;
    }

    // read the png into image_data through row_pointers
    png_read_image(png_ptr, row_pointers);

    // Generate the OpenGL texture object
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, format, temp_width, temp_height, 0, format, GL_UNSIGNED_BYTE, image_data);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    // clean up
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    free(image_data);
    free(row_pointers);
    fclose(fp);
    return texture;
}
Exemple #26
0
void* replaceBootImage(AbstractFile* imageWrapper, const unsigned int* key, const unsigned int* iv, AbstractFile* png, size_t *fileSize) {
	AbstractFile* imageFile;
	unsigned char header[8];
	InfoIBootIM* info;
	png_uint_32 i;
	png_bytepp row_pointers;
	
	uint8_t* imageBuffer;
	void* buffer;

	png->read(png, header, 8);
	if(png_sig_cmp(header, 0, 8) != 0) {
		XLOG(0, "error: not a valid png file\n");
		return NULL;
	}
	png->seek(png, 0);

	png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, pngError, pngWarn);
	if (!png_ptr) {
		return NULL;
	}

	png_infop info_ptr = png_create_info_struct(png_ptr);
	if (!info_ptr)
	{
		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
		return NULL;
	}

	png_infop end_info = png_create_info_struct(png_ptr);
	if (!end_info)
	{
		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
		return NULL;
	}

	if (setjmp(png_jmpbuf(png_ptr)))
	{
		XLOG(0, "error reading png\n");
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		free(buffer);
		return NULL;
	}

	png_set_read_fn(png_ptr, png, pngRead);

	png_read_info(png_ptr, info_ptr);
	
	if(info_ptr->bit_depth > 8) {
		XLOG(0, "warning: bit depth per channel is greater than 8 (%d). Attempting to strip, but image quality will be degraded.\n", info_ptr->bit_depth);
	}
	
	if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) {
		XLOG(0, "notice: attempting to add dummy transparency channel\n");
	}
	
	if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
		XLOG(0, "notice: attempting to expand palette into full rgb\n");
	}
	
	png_set_expand(png_ptr);
	png_set_strip_16(png_ptr);
	png_set_bgr(png_ptr);
	png_set_add_alpha(png_ptr, 0x0, PNG_FILLER_AFTER);
	png_set_invert_alpha(png_ptr);
	
	png_read_update_info(png_ptr, info_ptr);
	

	if(info_ptr->width > 320 || info_ptr->height > 480) {
		XLOG(0, "error: dimensions out of range, must be within 320x480, not %lux%lu\n", info_ptr->width, info_ptr->height);
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return NULL;
	}

	if(info_ptr->bit_depth != 8) {
		XLOG(0, "error: bit depth per channel must be 8 not %d!\n", info_ptr->bit_depth);
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
		return NULL;
	}

	if(info_ptr->color_type != PNG_COLOR_TYPE_GRAY_ALPHA && info_ptr->color_type != PNG_COLOR_TYPE_RGB_ALPHA) {
		XLOG(0, "error: incorrect color type, must be greyscale with alpha, or rgb with alpha\n");
		if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY || info_ptr->color_type == PNG_COLOR_TYPE_RGB) {
			XLOG(0, "It appears you're missing an alpha channel. Add transparency to your image\n");
		}
		if(info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
			XLOG(0, "This PNG is saved with the palette color type rather than ARGB.\n");
		}
		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

		return NULL;
	}

	row_pointers = (png_bytepp) malloc(sizeof(png_bytep) * info_ptr->height);
	imageBuffer = malloc(info_ptr->height * info_ptr->rowbytes);
	for(i = 0; i < info_ptr->height; i++) {
		row_pointers[i] = imageBuffer + (info_ptr->rowbytes * i);
	}

	png_read_image(png_ptr, row_pointers);
	png_read_end(png_ptr, end_info);
	
	buffer = malloc(1);
	*fileSize = 0;

	if(key != NULL) {
		imageFile = duplicateAbstractFile2(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize), key, iv, NULL);
	} else {	
		imageFile = duplicateAbstractFile(imageWrapper, createAbstractFileFromMemoryFile((void**)&buffer, fileSize));
	}
	info = (InfoIBootIM*) (imageFile->data);
	
	info->header.width = (uint16_t) info_ptr->width;
	info->header.height = (uint16_t) info_ptr->height;
	if(info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
		info->header.format = IBOOTIM_GREY;
	} else {
		info->header.format = IBOOTIM_ARGB;
	}
	
	imageFile->write(imageFile, imageBuffer, info_ptr->height * info_ptr->rowbytes);
	
	imageFile->close(imageFile);

	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);

	png->close(png);
	
	free(row_pointers);

	free(imageBuffer);

	return buffer;
}
Exemple #27
0
int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) {
	unsigned char header[8];
	png_structp png;
	png_infop   info;
	png_infop   endinfo;
	png_bytep   data;
   png_bytep  *row_p;
   double	fileGamma;

	png_uint_32 width, height;
	int depth, color;

	png_uint_32 i;

	if (pinfo == NULL) return 0;

	fread(header, 1, 8, fp);
	if (!png_check_sig(header, 8)) return 0;

	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	info = png_create_info_struct(png);
	endinfo = png_create_info_struct(png);

	// DH: added following lines
	if (setjmp(png->jmpbuf))
	{
		png_destroy_read_struct(&png, &info, &endinfo);
		return 0;
	}
	// ~DH

	png_init_io(png, fp);
	png_set_sig_bytes(png, 8);
	png_read_info(png, info);
	png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL);

	pinfo->Width  = width;
	pinfo->Height = height;
	pinfo->Depth  = depth;

	/*--GAMMA--*/
	checkForGammaEnv();
	if (png_get_gAMA(png, info, &fileGamma))
		png_set_gamma(png, screenGamma, fileGamma);
	else
		png_set_gamma(png, screenGamma, 1.0/2.2);

	png_read_update_info(png, info);

	data = (png_bytep) malloc(png_get_rowbytes(png, info)*height);
	row_p = (png_bytep *) malloc(sizeof(png_bytep)*height);

	for (i = 0; i < height; i++) {
		if (StandardOrientation)
			row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i];
		else
			row_p[i] = &data[png_get_rowbytes(png, info)*i];
	}

	png_read_image(png, row_p);
	free(row_p);

	if (color == PNG_COLOR_TYPE_PALETTE) {
		int cols;
		png_get_PLTE(png, info, (png_colorp *) &pinfo->Palette, &cols);
	}
	else {
		pinfo->Palette = NULL;
	}

	if (color&PNG_COLOR_MASK_ALPHA) {
		if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA)
			pinfo->Components = 2;
		else
			pinfo->Components = 4;
		pinfo->Alpha = 8;
	}
	else {
		if (color&PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY)
			pinfo->Components = 1;
		else
			pinfo->Components = 3;
		pinfo->Alpha = 0;
	}

	pinfo->Data = data;

   png_read_end(png, endinfo);
	png_destroy_read_struct(&png, &info, &endinfo);

	return 1;
}
Exemple #28
0
Canvas *
read_png(char * file_name) {
    
    unsigned char header[8];    // 8 is the maximum size that can be checked
    
    // open file and test for it being a png
    FILE *fp = fopen(file_name, "rb");
    if (!fp)
        abort_("[read_png_file] File %s could not be opened for reading", file_name);
    fread(header, 1, 8, fp);
    if (png_sig_cmp(header, 0, 8))
        abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);
    
    
    // initialize stuff
    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    
    if (!png_ptr)
        abort_("[read_png_file] png_create_read_struct failed");
    
    png_infop info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
        abort_("[read_png_file] png_create_info_struct failed");
    
    if (setjmp(png_jmpbuf(png_ptr)))
        abort_("[read_png_file] Error during init_io");
    
    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, 8);
    
    png_read_info(png_ptr, info_ptr);
    
    int width = png_get_image_width(png_ptr, info_ptr);
    int height = png_get_image_height(png_ptr, info_ptr);
    
    png_set_interlace_handling(png_ptr);
    png_read_update_info(png_ptr, info_ptr);
    
    
    // read file
    if (setjmp(png_jmpbuf(png_ptr)))
        abort_("[read_png_file] Error during read_image");
    
    png_bytep * row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
    int y;
    for (y = 0; y < height; y++)
        row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
    
    png_read_image(png_ptr, row_pointers);
    
    Canvas * canvas = new_canvas(width, height);
    int x;
    for (y=0; y < canvas->h; y++) {
        png_byte * row = row_pointers[y];
        for(x = 0; x < canvas->w; x++) {
            png_byte * ptr = &(row[x * 3]);
            
            set_pixel(x, y, rgb(ptr[0], ptr[1], ptr[2]), canvas);
        }
    }
    
    
    // cleanup heap allocation
    for (y=0; y < canvas->h; y++)
        free(row_pointers[y]);
    free(row_pointers);
    
    fclose(fp);
    
    return canvas;
}
Exemple #29
0
BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file,
    volatile BOOL raw, BOOL alpha)
{
  png_struct    *png_ptr = NULL;
  png_info        *info_ptr = NULL;
  png_byte      buf[8];
  png_byte      *png_pixels = NULL;
  png_byte      **row_pointers = NULL;
  png_byte      *pix_ptr = NULL;
  png_uint_32   row_bytes;

  png_uint_32   width;
  png_uint_32   height;
  int           bit_depth;
  int           channels;
  int           color_type;
  int           alpha_present;
  int           row, col;
  int           ret;
  int           i;
  long          dep_16;

  /* read and check signature in PNG file */
  ret = fread (buf, 1, 8, png_file);
  if (ret != 8)
    return FALSE;

  ret = png_sig_cmp (buf, 0, 8);
  if (ret)
    return FALSE;

  /* create png and info structures */

  png_ptr = png_create_read_struct (png_get_libpng_ver(NULL),
    NULL, NULL, NULL);
  if (!png_ptr)
    return FALSE;   /* out of memory */

  info_ptr = png_create_info_struct (png_ptr);
  if (!info_ptr)
  {
    png_destroy_read_struct (&png_ptr, NULL, NULL);
    return FALSE;   /* out of memory */
  }

  if (setjmp (png_jmpbuf(png_ptr)))
  {
    png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
    return FALSE;
  }

  /* set up the input control for C streams */
  png_init_io (png_ptr, png_file);
  png_set_sig_bytes (png_ptr, 8);  /* we already read the 8 signature bytes */

  /* read the file information */
  png_read_info (png_ptr, info_ptr);

  /* get size and bit-depth of the PNG-image */
  png_get_IHDR (png_ptr, info_ptr,
    &width, &height, &bit_depth, &color_type,
    NULL, NULL, NULL);

  /* set-up the transformations */

  /* transform paletted images into full-color rgb */
  if (color_type == PNG_COLOR_TYPE_PALETTE)
    png_set_expand (png_ptr);
  /* expand images to bit-depth 8 (only applicable for grayscale images) */
  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
    png_set_expand (png_ptr);
  /* transform transparency maps into full alpha-channel */
  if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
    png_set_expand (png_ptr);

#ifdef NJET
  /* downgrade 16-bit images to 8-bit */
  if (bit_depth == 16)
    png_set_strip_16 (png_ptr);
  /* transform grayscale images into full-color */
  if (color_type == PNG_COLOR_TYPE_GRAY ||
    color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    png_set_gray_to_rgb (png_ptr);
  /* only if file has a file gamma, we do a correction */
  if (png_get_gAMA (png_ptr, info_ptr, &file_gamma))
    png_set_gamma (png_ptr, (double) 2.2, file_gamma);
#endif

  /* all transformations have been registered; now update info_ptr data,
   * get rowbytes and channels, and allocate image memory */

  png_read_update_info (png_ptr, info_ptr);

  /* get the new color-type and bit-depth (after expansion/stripping) */
  png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
    NULL, NULL, NULL);

  /* check for 16-bit files */
  if (bit_depth == 16)
  {
    raw = FALSE;
#ifdef __TURBOC__
    pnm_file->flags &= ~((unsigned) _F_BIN);
#endif
  }

  /* calculate new number of channels and store alpha-presence */
  if (color_type == PNG_COLOR_TYPE_GRAY)
    channels = 1;
  else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
    channels = 2;
  else if (color_type == PNG_COLOR_TYPE_RGB)
    channels = 3;
  else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
    channels = 4;
  else
    channels = 0; /* should never happen */
  alpha_present = (channels - 1) % 2;

  /* check if alpha is expected to be present in file */
  if (alpha && !alpha_present)
  {
    fprintf (stderr, "PNG2PNM\n");
    fprintf (stderr, "Error:  PNG-file doesn't contain alpha channel\n");
    exit (1);
  }

  /* row_bytes is the width x number of channels x (bit-depth / 8) */
  row_bytes = png_get_rowbytes (png_ptr, info_ptr);

  if ((png_pixels = (png_byte *)
     malloc (row_bytes * height * sizeof (png_byte))) == NULL) {
    png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
    return FALSE;
  }

  if ((row_pointers = (png_byte **)
     malloc (height * sizeof (png_bytep))) == NULL)
  {
    png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
    free (png_pixels);
    png_pixels = NULL;
    return FALSE;
  }

  /* set the individual row_pointers to point at the correct offsets */
  for (i = 0; i < ((int) height); i++)
    row_pointers[i] = png_pixels + i * row_bytes;

  /* now we can go ahead and just read the whole image */
  png_read_image (png_ptr, row_pointers);

  /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
  png_read_end (png_ptr, info_ptr);

  /* clean up after the read, and free any memory allocated - REQUIRED */
  png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);

  /* write header of PNM file */

  if ((color_type == PNG_COLOR_TYPE_GRAY) ||
      (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
  {
    fprintf (pnm_file, "%s\n", (raw) ? "P5" : "P2");
    fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
    fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
  }
  else if ((color_type == PNG_COLOR_TYPE_RGB) ||
           (color_type == PNG_COLOR_TYPE_RGB_ALPHA))
  {
    fprintf (pnm_file, "%s\n", (raw) ? "P6" : "P3");
    fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
    fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
  }

  /* write header of PGM file with alpha channel */

  if ((alpha) &&
      ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
       (color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
  {
    fprintf (alpha_file, "%s\n", (raw) ? "P5" : "P2");
    fprintf (alpha_file, "%d %d\n", (int) width, (int) height);
    fprintf (alpha_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
  }

  /* write data to PNM file */
  pix_ptr = png_pixels;

  for (row = 0; row < (int) height; row++)
  {
    for (col = 0; col < (int) width; col++)
    {
      for (i = 0; i < (channels - alpha_present); i++)
      {
        if (raw)
          fputc ((int) *pix_ptr++ , pnm_file);
        else
          if (bit_depth == 16){
            dep_16 = (long) *pix_ptr++;
            fprintf (pnm_file, "%ld ", (dep_16 << 8) + ((long) *pix_ptr++));
          }
          else
            fprintf (pnm_file, "%ld ", (long) *pix_ptr++);
      }
      if (alpha_present)
      {
        if (!alpha)
        {
          pix_ptr++; /* alpha */
          if (bit_depth == 16)
            pix_ptr++;
        }
        else /* output alpha-channel as pgm file */
        {
          if (raw)
            fputc ((int) *pix_ptr++ , alpha_file);
          else
            if (bit_depth == 16){
              dep_16 = (long) *pix_ptr++;
              fprintf (alpha_file, "%ld ", (dep_16 << 8) + (long) *pix_ptr++);
            }
            else
              fprintf (alpha_file, "%ld ", (long) *pix_ptr++);
        }
      } /* if alpha_present */

      if (!raw)
        if (col % 4 == 3)
          fprintf (pnm_file, "\n");
    } /* end for col */

    if (!raw)
      if (col % 4 != 0)
        fprintf (pnm_file, "\n");
  } /* end for row */

  if (row_pointers != (unsigned char**) NULL)
    free (row_pointers);
  if (png_pixels != (unsigned char*) NULL)
    free (png_pixels);

  return TRUE;

} /* end of source */
FloatPixMapRef FPMCreateWithPNGCustom(png_voidp ioPtr, png_rw_ptr readDataFn, FPMGammaFactor desiredGamma, FPMPNGErrorHandler errorHandler)
{
	png_structp			png = NULL;
	png_infop			pngInfo = NULL;
	png_infop			pngEndInfo = NULL;
	FloatPixMapRef		result = NULL;
	png_uint_32			i, width, height, rowBytes;
	int					depth, colorType;
	png_bytepp			rows = NULL;
	void				*data = NULL;
	
	png = png_create_read_struct(PNG_LIBPNG_VER_STRING, errorHandler, PNGError, PNGWarning);
	if (png == NULL)  goto FAIL;
	
	pngInfo = png_create_info_struct(png);
	if (pngInfo == NULL)  goto FAIL;
	
	pngEndInfo = png_create_info_struct(png);
	if (pngEndInfo == NULL)  goto FAIL;
	
	if (setjmp(png_jmpbuf(png)))
	{
		// libpng will jump here on error.
		goto FAIL;
	}
	
	png_set_read_fn(png, ioPtr, readDataFn);
	
	png_read_info(png, pngInfo);
	if (!png_get_IHDR(png, pngInfo, &width, &height, &depth, &colorType, NULL, NULL, NULL))  goto FAIL;
	
#if __LITTLE_ENDIAN__
	if (depth == 16)  png_set_swap(png);
#endif
	if (depth <= 8 && !(colorType & PNG_COLOR_MASK_ALPHA))
	{
		png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
	}
	png_set_gray_to_rgb(png);
	if (depth < 8)
	{
		png_set_packing(png);
		png_set_expand(png);
	}
	
	png_read_update_info(png, pngInfo);
	rowBytes = png_get_rowbytes(png, pngInfo);
	
	rows = malloc(sizeof *rows * height);
	data = malloc(rowBytes * height);
	if (rows == NULL || data == NULL)  goto FAIL;
	
	// Set up row pointers.
	for (i = 0; i < height; i++)
	{
		rows[i] = (png_bytep)data + i * rowBytes;
	}
	
	png_read_image(png, rows);
	png_read_end(png, pngEndInfo);
	
	free(rows);
	
	result = ConvertPNGData(data, width, height, rowBytes, pngInfo->bit_depth, pngInfo->color_type);
	
	if (result != NULL)
	{
		double invGamma = 1.0/kFPMGammaSRGB;
		png_get_gAMA(png, pngInfo, &invGamma);
		FPMApplyGamma(result, 1.0/invGamma, desiredGamma, pngInfo->bit_depth == 16 ? 65536 : 256);
	}
	
	png_destroy_read_struct(&png, &pngInfo, &pngEndInfo);
	free(data);
	
	return result;
	
FAIL:
	FPMRelease(&result);
	if (png != NULL)  png_destroy_read_struct(&png, &pngInfo, &pngEndInfo);
	free(rows);
	free(data);
	
	return NULL;
}