⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tif.cpp

📁 一个国人自己实现图像库的程序(有参考价值)
💻 CPP
字号:
#include "stdafx.h"
#include "..\..\Include\Pic\Image.h"

#define CVT(x)			(((x) * 255L) / ((1L<<16)-1))
#define	SCALE(x)		(((x)*((1L<<16)-1))/255)
#define CalculateLine(width,bitdepth)	(((width * bitdepth) + 7) / 8)
#define CalculatePitch(line)	(line + 3 & ~3)

//===================================================================
BOOL  FCImage::LoadTif (BYTE * pStart, int iFileSize)
{
	BOOL	bRet = FALSE ;
	DWORD	pParam[4] = {(DWORD)iFileSize, (DWORD)pStart, (DWORD)pStart, 1} ;

	TIFFSetErrorHandler (NULL) ;
	TIFF	* m_tif = TIFFFdOpen ((int)pParam, "TIFF IMAGE", "rb") ;
	// check if it's a tiff file
	if (m_tif == NULL)
		return FALSE ;

	__try
	{
		if (!TIFFSetDirectory (m_tif, (uint16)0)) // first page
		{
			::MessageBox (NULL, TEXT("This TIFF file not include page"), TEXT("error!"), MB_OK) ;
			__leave ;
		}

		// get image info
		uint32		height = 0, width = 0 ;
		uint32		rowsperstrip = (DWORD)-1 ;
		uint16		compression = 1 ; // none
		uint16		bitspersample=1 ;
		uint16		samplesperpixel = 1 ;
		uint16		photometric = 0 ;
		uint16		orientation ;
		TIFFGetField (m_tif, TIFFTAG_COMPRESSION, &compression) ;
		TIFFGetField (m_tif, TIFFTAG_IMAGEWIDTH, &width) ;
		TIFFGetField (m_tif, TIFFTAG_IMAGELENGTH, &height) ;
		TIFFGetField (m_tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel) ;
		TIFFGetField (m_tif, TIFFTAG_BITSPERSAMPLE, &bitspersample) ;
		TIFFGetField (m_tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip) ;   
		TIFFGetField (m_tif, TIFFTAG_PHOTOMETRIC, &photometric) ;
		TIFFGetField (m_tif, TIFFTAG_ORIENTATION, &orientation) ;
		if (bitspersample == 16)
			__leave ;

		BOOL	isRGB = (bitspersample >= 8) && (photometric == PHOTOMETRIC_RGB) || (photometric == PHOTOMETRIC_YCBCR) ||
						(photometric == PHOTOMETRIC_SEPARATED) || (photometric == PHOTOMETRIC_LOGLUV) ;

		int		nColorBits = bitspersample ;
		if (isRGB)
			nColorBits = 24 ;

		// create DIB
		if (samplesperpixel == 4) // alpha channel for 32bpp tiffs
			nColorBits = 32 ;
		if (!this->Create (width, height, nColorBits))
			__leave ;

		if (isRGB)
		{
			// Read the whole image into one big RGBA buffer using
			uint32	* raster = (uint32*) _TIFFmalloc (width * height * sizeof (uint32)) ; // retrieve RGBA image
			if (raster == NULL)
				__leave ;

			// Read whole image in one chunk into an RGBA array
			if (!TIFFReadRGBAImage (m_tif, width, height, raster, 1))
			{
				_TIFFfree (raster) ;
				::MessageBox (NULL, TEXT("Corrupted TIFF file!"), TEXT("error!"), MB_OK) ;
				__leave ;
			}

			// read the raster lines and save them in the DIB, we have to change the order of the 3 samples RGB
			uint32	* row = raster ;
			for (uint32 y = 0 ; y < height ; y++)
			{
				BYTE	* bits = this->GetBits (height - 1 - y) ;
				for (uint32 x = 0 ; x < width ; x++)
				{
					*bits++ = (BYTE)TIFFGetB (row[x]) ;
					*bits++ = (BYTE)TIFFGetG (row[x]) ;
					*bits++ = (BYTE)TIFFGetR (row[x]) ;
					if (this->ColorBits() == 32)
						*bits++ = (BYTE)TIFFGetA (row[x]) ;
				}
				row += width ;
			}
			_TIFFfree (raster) ;
		}
		else
		{
			BOOL	Palette16Bits = FALSE ;

			// set palette
			if ((photometric == PHOTOMETRIC_MINISBLACK) || (photometric == PHOTOMETRIC_MINISWHITE))
				if (bitspersample == 1) // Monochrome image
				{
					RGBQUAD		pal[2] = {0, 0} ;
					if (photometric == PHOTOMETRIC_MINISBLACK)
						::FillMemory (&pal[1], 3, 0xFF) ;
					else
						::FillMemory (&pal[0], 3, 0xFF) ;
					this->SetColorTable (0, 2, pal) ;
				}
				else
				{
					int			nNum = 1 << this->ColorBits() ;
					int			nSpan = 255 / (nNum - 1) ;
					RGBQUAD		* palette = new RGBQUAD[nNum] ;
					for (int i=0 ; i < nNum ; i++)
						palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = (photometric == PHOTOMETRIC_MINISBLACK) ? nSpan*i : nSpan*(nNum-1-i) ;
					this->SetColorTable (0, nNum, palette) ;
					delete[] palette ;
				}


			// set up the colormap based on photometric	
			if (photometric == PHOTOMETRIC_PALETTE) // color map indexed
			{
				RGBQUAD		* pal = new RGBQUAD[256] ;
				uint16		* red, * green, * blue ;
				TIFFGetField (m_tif, TIFFTAG_COLORMAP, &red, &green, &blue) ;

				// Is the palette is 16 or 8 bits
				int n = 1 << bitspersample ;
				while (n-- > 0)
					if (red[n] >= 256 || green[n] >= 256 || blue[n] >= 256)
					{
						Palette16Bits = TRUE ;
						break ;
					}

				// load the palette to the DIB
				for (int i = (1 << this->ColorBits()) - 1 ; i >= 0 ; i--)
					if (Palette16Bits)
					{
						pal[i].rgbRed = (BYTE) CVT(red[i]) ;
						pal[i].rgbGreen = (BYTE) CVT(green[i]) ;
						pal[i].rgbBlue = (BYTE) CVT(blue[i]) ;
					}
					else
					{
						pal[i].rgbRed = (BYTE) red[i] ;
						pal[i].rgbGreen = (BYTE) green[i] ;
						pal[i].rgbBlue = (BYTE) blue[i] ;
					}
				this->SetColorTable (0, 1<<this->ColorBits(), pal) ;
				delete[] pal ;
			}

			// read the tiff lines and save them in the DIB
			int		line = CalculateLine (width, bitspersample * samplesperpixel) ;
			//verify bitsize: could be wrong if StripByteCounts is missing.
			long	bitsize= min (TIFFStripSize (m_tif), this->GetPitch () * height) ;
			BYTE	* bits = new BYTE[bitsize] ;
			if (bits == NULL)
				__leave ;
			for (uint32 ys = 0 ; ys < height ; ys += rowsperstrip)
			{
				uint32	nrow = (ys + rowsperstrip > height ? height - ys : rowsperstrip) ;
				if (TIFFReadEncodedStrip (m_tif, TIFFComputeStrip (m_tif, ys, 0), bits, nrow * line) == -1)
				{
					delete[] bits ;
					__leave ;
				}
				BYTE	* pline = bits ;
				for (uint32 y = 0; y < nrow; y++, pline += line)
					memcpy (this->GetBits (ys+y), pline, line) ;
			}
			delete[] bits ;
		}
		switch(orientation)
		{
			case ORIENTATION_TOPRIGHT: /* row 0 top, col 0 rhs */
				Mirror() ;
				break;
			case ORIENTATION_BOTRIGHT: /* row 0 bottom, col 0 rhs */
				Flip() ;
				Mirror() ;
				break;
			case ORIENTATION_BOTLEFT: /* row 0 bottom, col 0 lhs */
				Flip() ;
				break;
			case ORIENTATION_LEFTTOP: /* row 0 lhs, col 0 top */
				this->Rotate90 () ;
				Mirror() ;
				break;
			case ORIENTATION_RIGHTTOP: /* row 0 rhs, col 0 top */
				this->Rotate270 () ;
				break;
			case ORIENTATION_RIGHTBOT: /* row 0 rhs, col 0 bottom */
				this->Rotate270 () ;
				Mirror() ;
				break;
			case ORIENTATION_LEFTBOT: /* row 0 lhs, col 0 bottom */
				this->Rotate90 () ;
				break;
		}
		bRet = TRUE ;
	}
	__finally
	{
		if (m_tif != NULL)
			TIFFClose (m_tif) ;
		if (!bRet)
			this->Unload () ;
	}
	return bRet ;
}
//===================================================================
BOOL  FCImage::LoadTif (PCTSTR resName, PCTSTR resType)
{
	HRSRC	res = ::FindResource (NULL, resName, resType) ;
	HGLOBAL	gol = ::LoadResource (NULL, res) ;
	BYTE	* pTifData = (BYTE *) ::LockResource (gol) ;
	return (pTifData == NULL) ? FALSE : this->LoadTif (pTifData, ::SizeofResource (NULL, res)) ;
}
//===================================================================
BOOL  FCImage::LoadTif (PCTSTR szFileName)
{
	BOOL			bRet = FALSE ;
	BYTE			* pStart = NULL ;
	HANDLE			hMap = NULL ;
	HANDLE			hFile = INVALID_HANDLE_VALUE ;

	if (pFooDib->hBitmap != NULL)
		this->Unload () ;

	// mapping the image file
	pStart = this->__fooImageReadFile (szFileName, &hFile, &hMap) ;
	if (pStart != NULL)
		bRet = this->LoadTif (pStart, ::GetFileSize(hFile, NULL)) ; // 读文件
	this->__fooImageUnmapFile ((BYTE *)pStart, hMap, hFile) ;
	return bRet ;
}
//===================================================================
BOOL  FCImage::SaveTif (PCTSTR szFileName, int nEncodeMode)
{
	// can't save 16 bits color DIB
	if ((this->GetHandle() == NULL) || (this->ColorBits() == 16))
		return FALSE ;

	// compression tag check
	uint16		compression = (uint16)nEncodeMode ;
	if (this->ColorBits() == 1)
		compression = COMPRESSION_CCITTFAX3 ; // COMPRESSION_CCITTFAX4
	else // 4,8,24,32
	{
		switch (compression)
		{
			case COMPRESSION_PACKBITS :
			case COMPRESSION_NONE :
			case COMPRESSION_LZW :
				break ;
			case COMPRESSION_JPEG :
				if ((this->ColorBits() >= 24) || ((this->ColorBits() == 8) && (this->IsGrayPalette ())))
					break ;
				else
					return FALSE ;
			default :
				compression = COMPRESSION_NONE ;
		}
	}

	// create file
	BYTE	  * pStart = NULL ;
	HANDLE		hMap = NULL ;
	HANDLE		hFile = INVALID_HANDLE_VALUE ;
	int			iMaxFileSize = 32*1024 + this->GetPitch()*this->Height()*2 ;
	pStart = (BYTE *) this->__fooImageSaveFile (szFileName, &hFile, &hMap, iMaxFileSize) ;
	if (pStart == NULL)
	{
		this->__fooImageUnmapFile (pStart, hMap, hFile) ;
		return FALSE ;
	}
	DWORD	pParam[4] = {0, (DWORD)pStart, (DWORD)pStart, 0} ;
	TIFF	* m_tif = TIFFFdOpen ((int)pParam, "TIFF IMAGE", "wb") ;
	if (m_tif == NULL)
	{
		this->__fooImageUnmapFile (pStart, hMap, hFile) ;
		return FALSE ;
	}

	uint32		height = this->Height(), width = this->Width() ;
	uint16		bitspersample = this->ColorBits() ;
	uint16		photometric = 0 ;
	uint16		samplesperpixel = (bitspersample == 24) ? 3 : 1 ;
	if (bitspersample == 32)
		samplesperpixel = 4 ;

	//set the PHOTOMETRIC tag
	RGBQUAD		* pal = NULL ;
	int			nColorNum = 1 << this->ColorBits() ;
	if (this->ColorBits() <= 8)
	{
		pal = new RGBQUAD[nColorNum] ;
		this->GetColorTable (0, nColorNum, pal) ;
	}
	switch (bitspersample)
	{
		case 1 : photometric = (FCDib::fooGetGrayscale (pal[0]) < FCDib::fooGetGrayscale (pal[1])) ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_MINISWHITE ;
			break ;
		case 4:	// Check if the DIB has a greyscale palette
		case 8: photometric = this->IsGrayPalette () ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_PALETTE ;
			break ;
		case 24 :
		case 32 :
			photometric = PHOTOMETRIC_RGB ;
			break ;
	}

	// swap the palette's blue and red components
	if (this->ColorBits() <= 8)
		for(int i=0 ; i < nColorNum ; i++)
			FCDib::fooSwapRGB ((BYTE *)&pal[i]) ;

	// set standard width/height/bpp stuff
	TIFFSetField (m_tif, TIFFTAG_IMAGEWIDTH, width) ;
	TIFFSetField (m_tif, TIFFTAG_IMAGELENGTH, height) ;
	TIFFSetField (m_tif, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel) ;
	TIFFSetField (m_tif, TIFFTAG_BITSPERSAMPLE, bitspersample / samplesperpixel) ;
	TIFFSetField (m_tif, TIFFTAG_PHOTOMETRIC, photometric) ;
	TIFFSetField (m_tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) ; // single image plane 
	TIFFSetField (m_tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT) ;
	TIFFSetField (m_tif, TIFFTAG_ROWSPERSTRIP, 1) ;
	// set metrics
	TIFFSetField (m_tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH) ;
	TIFFSetField (m_tif, TIFFTAG_XRESOLUTION, (float)0) ;
	TIFFSetField (m_tif, TIFFTAG_YRESOLUTION, (float)0) ;
	TIFFSetField (m_tif, TIFFTAG_XPOSITION, (float)96) ;
	TIFFSetField (m_tif, TIFFTAG_YPOSITION, (float)96) ;
	// single page
	TIFFSetField (m_tif, TIFFTAG_SUBFILETYPE, 0) ;
	// encode mode
	TIFFSetField (m_tif, TIFFTAG_COMPRESSION, compression) ;
	if (bitspersample >= 8)
		if (nEncodeMode == COMPRESSION_JPEG)
		{
			TIFFSetField (m_tif, TIFFTAG_JPEGQUALITY, 85) ; // default quality 85
			TIFFSetField (m_tif, TIFFTAG_ROWSPERSTRIP, 8) ; // needed for COMPRESSION_JPEG
		}

	// palettes (image colormaps are automatically scaled to 16-bits)
	if (photometric == PHOTOMETRIC_PALETTE)
	{
		uint16		* r, * g, * b ;
		r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * 256) ;
		g = r + 256 ;
		b = g + 256 ;
		for (int i = 255; i >= 0; i--)
		{
			b[i] = (uint16)SCALE((uint16)pal[i].rgbRed) ;
			g[i] = (uint16)SCALE((uint16)pal[i].rgbGreen) ;
			r[i] = (uint16)SCALE((uint16)pal[i].rgbBlue) ;
		}
		TIFFSetField (m_tif, TIFFTAG_COLORMAP, r, g, b) ;
		_TIFFfree(r) ;
	}

	// read the DIB lines from bottom to top and save them in the TIF
	uint32		x, y ;
	DWORD		dwPitch = this->GetPitch() ;
	switch (bitspersample)
	{
		case 1 :
		case 4 :
		case 8 :
			for (y=0 ; y < height ; y++)
				TIFFWriteScanline (m_tif, this->GetBits(y), y, 0) ;
			break;
		case 24 :
			for (y = 0 ; y < height ; y++)
				TIFFWriteScanline (m_tif, this->GetBits(y), y, 0) ;
			break ;
		case 32 :
			BYTE	* buffer = new BYTE [dwPitch] ;
			for (y = 0 ; y < height ; y++)
			{
				CopyMemory (buffer, this->GetBits(y), dwPitch) ;
				// TIFFs store color data RGBA instead of BGRA
				BYTE	* pBuf = buffer ;
				for (x = 0 ; x < width ; x++, pBuf += 4)
					FCDib::fooSwapRGB (pBuf) ;
				// write the scanline to disc
				TIFFWriteScanline (m_tif, buffer, y, 0) ;
			}
			delete[] buffer ;
			break ;
	}
	TIFFClose (m_tif) ;
	if (pStart != NULL)	::UnmapViewOfFile (pStart) ;
	if (hMap != NULL)
	{
		::CloseHandle (hMap) ;
		::SetFilePointer (hFile, pParam[0], NULL, FILE_BEGIN) ;
		::SetEndOfFile (hFile) ; // 设置文件大小
	}
	if (hFile != INVALID_HANDLE_VALUE)	::CloseHandle (hFile) ;
	return TRUE ;
}
//===================================================================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -