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


 

Logo

更多推荐