需要将内存中的图像数据保存为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;
}