|
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;
}
|