📄 tif.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 + -