code_app/imgfmt/HGTiff.cpp

408 lines
9.3 KiB
C++

#include "HGTiff.h"
#include "../base/HGInc.h"
#include "tiffio.h"
HGResult HGAPI HGImgFmt_CheckTiffFile(const HGChar* fileName, HGBool* isTiff)
{
if (NULL == fileName || NULL == isTiff)
{
return HGBASE_ERR_INVALIDARG;
}
*isTiff = HGFALSE;
HGTiffReader reader = NULL;
HGImgFmt_OpenTiffReader(fileName, &reader);
if (NULL != reader)
{
*isTiff = HGTRUE;
HGImgFmt_CloseTiffReader(reader);
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_OpenTiffReader(const HGChar* fileName, HGTiffReader* reader)
{
if (NULL == fileName || NULL == reader)
{
return HGBASE_ERR_INVALIDARG;
}
TIFF* tif = TIFFOpen(fileName, "r");
if (NULL == tif)
{
return HGBASE_ERR_ACCESSDENIED;
}
*reader = (HGTiffReader)tif;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_CloseTiffReader(HGTiffReader reader)
{
if (NULL == reader)
{
return HGBASE_ERR_INVALIDARG;
}
TIFF* tif = (TIFF*)reader;
TIFFClose(tif);
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_GetTiffPageCount(HGTiffReader reader, HGUInt* count)
{
if (NULL == reader || NULL == count)
{
return HGBASE_ERR_INVALIDARG;
}
TIFF* tif = (TIFF*)reader;
*count = TIFFNumberOfDirectories(tif);
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_LoadImageFromTiffReader(HGTiffReader reader, HGUInt index, UPTiffLoadInfo* info,
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
{
if (NULL == reader)
{
return HGBASE_ERR_INVALIDARG;
}
if (NULL == image)
{
if (0 != imgType || 0 != imgOrigin)
{
return HGBASE_ERR_INVALIDARG;
}
}
else
{
if (0 != imgType && HGBASE_IMGTYPE_GRAY != imgType && HGBASE_IMGTYPE_RGB != imgType
&& HGBASE_IMGTYPE_RGBA != imgType && HGBASE_IMGTYPE_BGR != imgType
&& HGBASE_IMGTYPE_BGRA != imgType)
{
return HGBASE_ERR_INVALIDARG;
}
if (HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin)
{
return HGBASE_ERR_INVALIDARG;
}
}
TIFF* tif = (TIFF*)reader;
if (0 == TIFFSetDirectory(tif, index))
{
return HGBASE_ERR_FAIL;
}
uint32 width;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
uint32 height;
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
uint16 bitsPerSample;
TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
uint16 samplesPerPixel;
TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
uint16 compression;
TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
uint16 resolutionUnit;
TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &resolutionUnit);
float xResolution;
TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xResolution);
float yResolution;
TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yResolution);
if (NULL != info)
{
info->width = width;
info->height = height;
info->bitsPerSample = bitsPerSample;
info->samplesPerPixel = samplesPerPixel;
info->compression = compression;
info->resolutionUnit = resolutionUnit;
info->xResolution = xResolution;
info->yResolution = yResolution;
}
if (NULL != image)
{
uint32* buffer = (uint32*)malloc(width * height * sizeof(uint32));
if (NULL == buffer)
{
return HGBASE_ERR_FAIL;
}
if (0 == TIFFReadRGBAImageOriented(tif, width, height, buffer, ORIENTATION_TOPLEFT))
{
free(buffer);
buffer = NULL;
return HGBASE_ERR_FAIL;
}
if (0 == imgType)
{
if (4 == samplesPerPixel)
{
imgType = HGBASE_IMGTYPE_RGBA;
}
else
{
imgType = HGBASE_IMGTYPE_RGB;
}
}
HGImage image2 = NULL;
HGResult result = HGBase_CreateImage(width, height, imgType, imgOrigin, &image2);
if (HGBASE_ERR_OK != result)
{
free(buffer);
buffer = NULL;
return HGBASE_ERR_FAIL;
}
if (2 == resolutionUnit)
{
uint32_t xDpi = (uint32_t)(xResolution + 0.5f);
uint32_t yDpi = (uint32_t)(yResolution + 0.5f);
HGBase_SetImageDpi(image2, xDpi, yDpi);
}
uint8_t* data;
HGBase_GetImageData(image2, &data);
HGImageInfo imgInfo;
HGBase_GetImageInfo(image2, &imgInfo);
HGByte* dest = data;
HGSize destStep = (HGSize)imgInfo.widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == imgOrigin)
{
dest = data + (HGUSize)(imgInfo.height - 1) * (HGUSize)imgInfo.widthStep;
destStep = -(HGSize)imgInfo.widthStep;
}
if (HGBASE_IMGTYPE_GRAY == imgType)
{
//#pragma omp parallel for
for (int32 i = 0; i < (int32)height; i++)
{
uint8_t* pEx = (uint8_t*)buffer + (uintptr_t)i * (uintptr_t)width * (uintptr_t)4;
uint8_t* pExEnd = pEx + width * 4;
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
uint8_t value = (pEx[0] * 76 + pEx[1] * 150 + pEx[2] * 30) >> 8;
*pDestEx = value;
pEx += 4;
++pDestEx;
}
}
}
else if (HGBASE_IMGTYPE_RGB == imgType)
{
//#pragma omp parallel for
for (int32 i = 0; i < (int32)height; i++)
{
uint8_t* pEx = (uint8_t*)buffer + (uintptr_t)i * (uintptr_t)width * (uintptr_t)4;
uint8_t* pExEnd = pEx + width * 4;
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
pDestEx[0] = pEx[0];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[2];
pEx += 4;
pDestEx += 3;
}
}
}
else if (HGBASE_IMGTYPE_BGR == imgType)
{
//#pragma omp parallel for
for (int32 i = 0; i < (int32)height; i++)
{
uint8_t* pEx = (uint8_t*)buffer + (uintptr_t)i * (uintptr_t)width * (uintptr_t)4;
uint8_t* pExEnd = pEx + width * 4;
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
pDestEx[0] = pEx[2];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[0];
pEx += 4;
pDestEx += 3;
}
}
}
else if (HGBASE_IMGTYPE_BGRA == imgType)
{
//#pragma omp parallel for
for (int32 i = 0; i < (int32)height; i++)
{
uint8_t* pEx = (uint8_t*)buffer + (uintptr_t)i * (uintptr_t)width * (uintptr_t)4;
uint8_t* pExEnd = pEx + width * 4;
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
while (pEx < pExEnd)
{
pDestEx[0] = pEx[2];
pDestEx[1] = pEx[1];
pDestEx[2] = pEx[0];
pDestEx[3] = pEx[3];
pEx += 4;
pDestEx += 4;
}
}
}
else
{
assert(HGBASE_IMGTYPE_RGBA == imgType);
//#pragma omp parallel for
for (int32 i = 0; i < (int32)height; i++)
{
uint8_t* pEx = (uint8_t*)buffer + (uintptr_t)i * (uintptr_t)width * (uintptr_t)4;
uint8_t* pDestEx = dest + (HGSize)i * (HGSize)destStep;
memcpy(pDestEx, pEx, width * 4);
}
}
free(buffer);
buffer = NULL;
*image = image2;
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_OpenTiffWriter(const HGChar* fileName, HGTiffWriter* writer)
{
if (NULL == fileName || NULL == writer)
{
return HGBASE_ERR_INVALIDARG;
}
TIFF* tif = TIFFOpen(fileName, "w");
if (NULL == tif)
{
return HGBASE_ERR_ACCESSDENIED;
}
*writer = (HGTiffWriter)tif;
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_CloseTiffWriter(HGTiffWriter writer)
{
if (NULL == writer)
{
return HGBASE_ERR_INVALIDARG;
}
TIFF* tif = (TIFF*)writer;
TIFFClose(tif);
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_SaveImageToTiffWriter(HGTiffWriter writer, HGImage image, const UPTiffSaveInfo* info)
{
if (NULL == writer || NULL == image)
{
return HGBASE_ERR_INVALIDARG;
}
if (NULL != info)
{
// 判断合法性
}
HGImageInfo imgInfo;
HGBase_GetImageInfo(image, &imgInfo);
uint32_t width = imgInfo.width;
uint32_t height = imgInfo.height;
uint32_t widthStep = imgInfo.widthStep;
uint32_t type = imgInfo.type;
uint32_t origin = imgInfo.origin;
if (HGBASE_IMGTYPE_GRAY != type && HGBASE_IMGTYPE_RGB != type
&& HGBASE_IMGTYPE_RGBA != type)
{
return HGBASE_ERR_INVALIDARG;
}
uint8_t* data;
HGBase_GetImageData(image, &data);
uint8 samplesPerPixel = 0;
if (HGBASE_IMGTYPE_GRAY == type)
samplesPerPixel = 1;
else if (HGBASE_IMGTYPE_RGB == type)
samplesPerPixel = 3;
else if (HGBASE_IMGTYPE_RGBA == type)
samplesPerPixel = 4;
assert(0 != samplesPerPixel);
TIFF* tif = (TIFF*)writer;
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, samplesPerPixel);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, (1 == samplesPerPixel) ? PHOTOMETRIC_PALETTE : PHOTOMETRIC_RGB);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, height);
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
uint16 rTable[256], gTable[256], bTable[256];
//#pragma omp parallel for
for (int32_t i = 0; i < 256; ++i)
{
rTable[i] = i;
gTable[i] = i;
bTable[i] = i;
}
TIFFSetField(tif, TIFFTAG_COLORMAP, rTable, gTable, bTable);
HGUInt xDpi, yDpi;
HGBase_GetImageDpi(image, &xDpi, &yDpi);
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, 2);
TIFFSetField(tif, TIFFTAG_XRESOLUTION, xDpi);
TIFFSetField(tif, TIFFTAG_YRESOLUTION, yDpi);
if (NULL != info)
{
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, info->resolutionUnit);
TIFFSetField(tif, TIFFTAG_XRESOLUTION, info->xResolution);
TIFFSetField(tif, TIFFTAG_YRESOLUTION, info->yResolution);
}
HGByte* p = data;
HGSize step = (HGSize)widthStep;
if (HGBASE_IMGORIGIN_BOTTOM == origin)
{
p = data + (HGUSize)(height - 1) * (HGUSize)widthStep;
step = -(HGSize)widthStep;
}
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)height; ++i)
{
uint8_t* pEx = p + (HGSize)i * (HGSize)step;
TIFFWriteScanline(tif, pEx, i, 0);
}
TIFFWriteDirectory(tif);
return HGBASE_ERR_OK;
}