Solid Fluid System Solutions  
Home Software About Hardware Firmware
Document Icon LibPNG
Document Icon Modifications
Current Document Icon ToPNG
Document Icon FromPNG

The ToPNG Function

#include "ImgPNG.h"
#include "ImgAlloc.h"
#include ".\PNG\png.h"
#include ".\PNG\pngbuffersrc.h"
#include ".\PNG\pngbufferdst.h"

void png_ToPNG(void*& pBuf,unsigned long& BufSz,ImgPNGInfo& Info)
{
	png_structp png_ptr;
	png_infop info_ptr;

	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
	if(png_ptr == NULL)
	{
		img_free(pBuf);
		BufSz = 0;
		return;
	}

	info_ptr = png_create_info_struct(png_ptr);
	if (info_ptr == NULL)
	{
		img_free(pBuf);
		BufSz = 0;

		png_destroy_write_struct(&png_ptr,  png_infopp_NULL);

		return;
	}

	buffered_write_info aBWI;
	aBWI.Size = 0;
	aBWI.pBuf = NULL;
	aBWI.Ptr = 0;

	png_set_write_fn(png_ptr,(void*)&aBWI,png_buffered_write_data,png_buffered_flush_data);

	int PngColorType;
	int PngBitDepth;
	void* pPixel = NULL;
	void* pPalette = NULL;
	png_colorp palette = NULL;
	unsigned long PaletteSize;
	switch(Info.BitCount)
	{
		case 1:
		{
			if(Info.PNGColorType == PNG_TYPE_GREY)
			{
				PngColorType = PNG_COLOR_TYPE_GRAY;
				PngBitDepth = 1;
				pPixel = &(((char*)pBuf)[2 * 4]);
			}
			else
			{
				PngColorType = PNG_COLOR_TYPE_PALETTE;
				PngBitDepth = 1;
				pPalette = pBuf;
				pPixel = &(((char*)pBuf)[2 * 4]);
				PaletteSize = 2;
			}
		}
		break;

		case 4:
		{
			if(Info.PNGColorType == PNG_TYPE_GREY)
			{
				PngColorType = PNG_COLOR_TYPE_GRAY;
				PngBitDepth = 4;
				pPixel = &(((char*)pBuf)[16 * 4]);
			}
			else
			{
				PngColorType = PNG_COLOR_TYPE_PALETTE;
				PngBitDepth = 4;
				pPalette = pBuf;
				pPixel = &(((char*)pBuf)[16 * 4]);
				PaletteSize = 16;
			}
		}
		break;

		case 8:
		{
			if(Info.PNGColorType == PNG_TYPE_GREY)
			{
				PngColorType = PNG_COLOR_TYPE_GRAY;
				PngBitDepth = 8;
				pPixel = &(((char*)pBuf)[256 * 4]);
			}
			else
			{
				PngColorType = PNG_COLOR_TYPE_PALETTE;
				PngBitDepth = 8;
				pPalette = pBuf;
				pPixel = &(((char*)pBuf)[256 * 4]);
				PaletteSize = 256;
			}
		}
		break;

		case 24:
		{
			PngColorType = PNG_COLOR_TYPE_RGB;
			PngBitDepth = 8;
			pPixel = pBuf;
		}
		break;

		case 32:
		{
			PngColorType = PNG_COLOR_TYPE_RGB_ALPHA;
			PngBitDepth = 8;
			pPixel = pBuf;
		}
		break;
	}

	if((PngColorType == PNG_COLOR_TYPE_GRAY) || (PngColorType == PNG_COLOR_TYPE_PALETTE))
	{
		if(Info.Trns != PNG_TRNS_INDEX)
		 Info.Trns = PNG_TRNS_NONE;
	}
	else
	if(PngColorType == PNG_COLOR_TYPE_RGB)
	{
		if(Info.Trns != PNG_TRNS_COLOR)
		 Info.Trns = PNG_TRNS_NONE;
	}
	else
	 Info.Trns = PNG_TRNS_NONE;

	if(Info.Trns == PNG_TRNS_INDEX)
	{
		if(PngColorType == PNG_COLOR_TYPE_GRAY)
		{
			png_color_16 trans_values;
			trans_values.gray = Info.TrnsIndex;
			png_set_tRNS(png_ptr,info_ptr,NULL,0,&trans_values);
		}
		else
		{
			int num_trans = (Info.TrnsIndex + 1);
			unsigned char* ptrans = (unsigned char*) img_malloc(num_trans);

			for(int i=0;i<num_trans;i++)
			{
				if(i == (num_trans - 1))
				 ptrans[i] = 0x00;
				else
				 ptrans[i] = 0xFF;
			}

			png_set_tRNS(png_ptr,info_ptr,ptrans,num_trans,NULL);

			img_free(ptrans);
		}
	}
	else
	if(Info.Trns == PNG_TRNS_COLOR)
	{
		png_color_16 trans_values;
		trans_values.red = ((Info.TrnsIndex & 0x00FF0000) >> 16);
		trans_values.green = ((Info.TrnsIndex & 0x0000FF00) >> 8);
		trans_values.blue = (Info.TrnsIndex & 0x0000FF);
		png_set_tRNS(png_ptr,info_ptr,NULL,0,&trans_values);
	}

	png_set_IHDR(
				 png_ptr,
				 info_ptr,
				 Info.XDim,
				 Info.YDim,
				 PngBitDepth,
				 PngColorType,
				 PNG_INTERLACE_NONE,
				 PNG_COMPRESSION_TYPE_BASE,
				 PNG_FILTER_TYPE_BASE
				);

	if(pPalette != NULL)
	{
		palette = (png_colorp) png_malloc(png_ptr,(PaletteSize * png_sizeof(png_color)));

		unsigned long Index;
		for(Index=0;Index<PaletteSize;Index++)
		{
			((unsigned char*)palette)[(Index * 3) + 0] = ((unsigned char*)pPalette)[(Index * 4) + 2];
			((unsigned char*)palette)[(Index * 3) + 1] = ((unsigned char*)pPalette)[(Index * 4) + 1];
			((unsigned char*)palette)[(Index * 3) + 2] = ((unsigned char*)pPalette)[(Index * 4) + 0];
		}

		png_set_PLTE(png_ptr,info_ptr,palette,PaletteSize);
	}

	png_write_info(png_ptr, info_ptr);

	if((PngColorType == PNG_COLOR_TYPE_RGB) || (PngColorType == PNG_COLOR_TYPE_RGB_ALPHA))
	 png_set_bgr(png_ptr);

	if(Info.YDim > PNG_UINT_32_MAX/png_sizeof(png_bytep))
	 png_error(png_ptr,"Image is too tall to process in memory");

	unsigned long row;
	png_bytep* ppRowPtrs = (png_bytep*) img_malloc(sizeof(png_bytep) * Info.YDim);
	for(row=0;row<Info.YDim;row++)
	 ppRowPtrs[(Info.YDim - 1) - row] = &(((unsigned char*)pPixel)[row * Info.LineSize]);

	png_write_image(png_ptr,ppRowPtrs);
	png_write_end(png_ptr,info_ptr);

	img_free(ppRowPtrs);

	if(palette != NULL)
	 png_free(png_ptr,palette);
	palette = NULL;

	png_destroy_write_struct(&png_ptr,&info_ptr);

	img_free(pBuf);
	pBuf = aBWI.pBuf;
	BufSz = aBWI.Size;
}
Copyright © Solid Fluid 2007-2022
Last modified: SolFlu  Sun, 14 Jun 2009 09:23:41 GMT