将内存图像数据保存为png及tif方法

时间:2021-08-30 05:42:03

需要将内存中的图像数据保存为tif或者png的格式,就需要用到libpng,libtiff及zlib这三个 库.

 

工程中需要有png.h , tiff.h, tiffio.h

这几个库都是可以用在windows及linux下的,我在这两个系统下都用的下面的方法,无非就是这两种系统下的c++中字符串及对象类型的处理

具体的方法如下:

保存TIF

BOOL ImgToTIF(LPCTSTR strFileName, PVOID pImageData, ULONG _ulWidth, ULONG _ulHeight, ULONG nBit)
{
UINT nLen = _tcsclen(strFileName);
TCHAR strFile[255];
TCHAR ext3[4],ext4[5];
_tcsnccpy(ext3,strFileName+nLen-4,4);
_tcsnccpy(ext4,strFileName+nLen-5,5);

LPCTSTR tPFileName = strFileName;

if(_tcsnccmp(ext3,_T(".tif"),4)!=0 && _tcsnccmp(ext3,_T(".TIF"),4)!=0
&&_tcsnccmp(ext4,_T(".TIFF"),5)!=0 && _tcsnccmp(ext4,_T(".tiff"),5)!=0)
{
_tcscpy(strFile,strFileName);
_tcscpy(strFile+nLen,_T(".tif"));
tPFileName = strFile;
}

BOOL result = FALSE;

BOOL b16Bit = nBit%16==0 ? TRUE:FALSE;

int nChannels = b16Bit ? nBit/16:nBit/8;

int depth = b16Bit?16:8;

if( nBit%16 != 0 && nBit%8 != 0 )
return FALSE;

PUCHAR imgData = (PUCHAR)pImageData;

TIFF* tif = NULL;
#ifdef UNICODE
tif = TIFFOpenW( tPFileName, "w" );
#else
tif = TIFFOpen( tPFileName, "w" );
#endif
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, _ulWidth); // set the width of the image
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, _ulHeight); // set the height of the image
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, nChannels); // set number of channels per pixel
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, depth); // set the size of the channels
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); // set the origin of the image.
// Some other essential fields to set that you do not have to understand for now.
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
uint16 colorMode = nChannels==1 ? PHOTOMETRIC_MINISBLACK:PHOTOMETRIC_RGB;
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, colorMode);
uint16 compression = COMPRESSION_NONE;//
TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);

tsize_t linebytes = nChannels * _ulWidth * depth / 8; // length in memory of one row of pixel in the image.

unsigned char *buf = NULL; // buffer used to store the row of pixel information for writing to file

// Allocating memory to store the pixels of current row
size_t x = TIFFScanlineSize(tif);
if (TIFFScanlineSize(tif)==linebytes)
buf =(unsigned char *)_TIFFmalloc(linebytes);
else
buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif));

// We set the strip size of the file to be size of one row of pixels
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, nChannels * _ulWidth));

//Now writing image to the file one strip at a time
for (uint32 row = 0; row < _ulHeight; row++)
{
memcpy(buf, &imgData[(_ulHeight-row-1)*linebytes], linebytes); // check the index here, and figure out why not using h*linebytes
if (TIFFWriteScanline(tif, buf, row, 0) < 0)
break;
}

TIFFClose(tif);
if (buf)
_TIFFfree(buf);

return TRUE;
}


保存PNG:

BOOL ImgToPNG(LPCTSTR strFileName, PVOID pImageData, ULONG _ulWidth, ULONG _ulHeight, ULONG nBit)
{
UINT nLen = _tcsclen(strFileName);
TCHAR strFile[255];
TCHAR ext3[4],ext4[5];
_tcsnccpy(ext3,strFileName+nLen-4,4);
_tcsnccpy(ext4,strFileName+nLen-5,5);

LPCTSTR tPFileName = strFileName;

if(_tcsnccmp(ext3,_T(".PNG"),4)!=0 && _tcsnccmp(ext3,_T(".png"),4)!=0)
{
_tcscpy(strFile,strFileName);
_tcscpy(strFile+nLen,_T(".png"));
tPFileName = strFile;
}

char filename[255];
#ifdef UNICODE
WideCharToMultiByte(CP_ACP, NULL,tPFileName,-1,filename, 255, NULL, NULL);
#else
_tcscpy(filename,tPFileName);
#endif

png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
png_infop info_ptr = 0;
FILE* f = 0;
uchar** buffer = 0;
PUCHAR imgData = (PUCHAR)pImageData;
int y;
BOOL result = FALSE;

BOOL b16Bit = nBit%16==0 ? TRUE:FALSE;

int nChannels = b16Bit ? nBit/16:nBit/8;

int depth = b16Bit?16:8;

int step = _ulWidth*nChannels*depth/8;

if( nBit%16 != 0 && nBit%8 != 0 )
return FALSE;

if( png_ptr )
{
info_ptr = png_create_info_struct( png_ptr );

if( info_ptr )
{
if( setjmp( png_ptr->jmpbuf ) == 0 )
{
f = fopen( filename, "wb" );

if( f )
{
png_init_io( png_ptr, f );

png_set_compression_mem_level( png_ptr, MAX_MEM_LEVEL );

png_set_IHDR( png_ptr, info_ptr, _ulWidth, _ulHeight, depth,
nChannels == 1 ? PNG_COLOR_TYPE_GRAY :
nChannels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT );

png_write_info( png_ptr, info_ptr );

png_set_bgr( png_ptr );
if( !isBigEndian() )
png_set_swap( png_ptr );

///////////////////////////////////////
//png图像内存的上下位置跟具体图像的数据颠倒
buffer = new uchar*[_ulHeight];
for( y = 0; y < _ulHeight; y++ )
buffer[_ulHeight-y-1] = (uchar*)(imgData + y*step);

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

delete[] buffer;

result = TRUE;
}
}
}
}
png_destroy_write_struct( &png_ptr, &info_ptr );

if(f) fclose( f );

return result;
}