code_app/modules/imgfmt/HGTiff.cpp

399 lines
9.4 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_BINARY != imgType && HGBASE_IMGTYPE_GRAY != imgType
&& HGBASE_IMGTYPE_BGR != imgType && HGBASE_IMGTYPE_RGB != imgType
&& HGBASE_IMGTYPE_BGRA != imgType && HGBASE_IMGTYPE_RGBA != 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)
{
imgType = HGBASE_IMGTYPE_RGB;
if (4 == samplesPerPixel)
{
imgType = HGBASE_IMGTYPE_RGBA;
}
else if (1 == samplesPerPixel)
{
if (1 == bitsPerSample)
imgType = HGBASE_IMGTYPE_BINARY;
else
imgType = HGBASE_IMGTYPE_GRAY;
}
}
HGImageInfo tiffImageInfo;
tiffImageInfo.width = width;
tiffImageInfo.height = height;
tiffImageInfo.type = HGBASE_IMGTYPE_RGBA;
tiffImageInfo.widthStep = width * 4;
tiffImageInfo.origin = HGBASE_IMGORIGIN_TOP;
HGImage image2 = NULL;
HGResult ret = HGBase_CreateImageWithData((HGByte*)buffer, &tiffImageInfo, &image2);
if (HGBASE_ERR_OK != ret)
{
free(buffer);
buffer = NULL;
return ret;
}
if (RESUNIT_INCH == resolutionUnit)
{
uint32_t xDpi = (uint32_t)(xResolution + 0.5f);
uint32_t yDpi = (uint32_t)(yResolution + 0.5f);
HGBase_SetImageDpi(image2, xDpi, yDpi);
}
else if (RESUNIT_CENTIMETER == resolutionUnit)
{
uint32_t xDpi = (uint32_t)(xResolution / 0.393700787402 + 0.5);
uint32_t yDpi = (uint32_t)(yResolution / 0.393700787402 + 0.5);
HGBase_SetImageDpi(image2, xDpi, yDpi);
}
ret = HGBase_CloneImage(image2, imgType, imgOrigin, image);
HGBase_DestroyImage(image2);
if (HGBASE_ERR_OK != ret)
{
free(buffer);
buffer = NULL;
return ret;
}
free(buffer);
buffer = NULL;
}
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_LoadTiffImage(const HGChar* fileName, UPTiffLoadInfo* info,
HGUInt imgType, HGUInt imgOrigin, HGImage* image)
{
HGTiffReader reader = NULL;
HGResult ret = HGImgFmt_OpenTiffReader(fileName, &reader);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
ret = HGImgFmt_LoadImageFromTiffReader(reader, 0, info, imgType, imgOrigin, image);
HGImgFmt_CloseTiffReader(reader);
return ret;
}
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)
{
// 判断合法性
}
HGImage image2 = NULL;
HGImageRoi roi;
HGBase_GetImageROI(image, &roi);
HGBase_ResetImageROI(image);
HGImageInfo imgInfo;
HGBase_GetImageInfo(image, &imgInfo);
if (HGBASE_IMGTYPE_BGR == imgInfo.type)
{
if (HGBASE_ERR_OK != HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2))
HGBase_SetImageROI(image, &roi);
}
else if (HGBASE_IMGTYPE_BGRA == imgInfo.type)
{
if (HGBASE_ERR_OK != HGBase_CloneImage(image, HGBASE_IMGTYPE_RGBA, HGBASE_IMGORIGIN_TOP, &image2))
HGBase_SetImageROI(image, &roi);
}
else
{
if (HGBASE_ERR_OK != HGBase_CloneImage(image, imgInfo.type, HGBASE_IMGORIGIN_TOP, &image2))
HGBase_SetImageROI(image, &roi);
}
HGBase_GetImageInfo(image2, &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;
uint8_t* data;
HGBase_GetImageData(image2, &data);
uint8 samplesPerPixel = 0;
uint8 bitsPerSample = 0;
if (HGBASE_IMGTYPE_BINARY == type)
{
samplesPerPixel = 1;
bitsPerSample = 1;
}
else if (HGBASE_IMGTYPE_GRAY == type)
{
samplesPerPixel = 1;
bitsPerSample = 8;
}
else if (HGBASE_IMGTYPE_RGB == type)
{
samplesPerPixel = 3;
bitsPerSample = 8;
}
else if (HGBASE_IMGTYPE_RGBA == type)
{
samplesPerPixel = 4;
bitsPerSample = 8;
}
assert(0 != samplesPerPixel && 0 != bitsPerSample);
TIFF* tif = (TIFF*)writer;
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bitsPerSample);
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);
if (HGBASE_IMGTYPE_BINARY == type)
{
uint16 rTable[2], gTable[2], bTable[2];
//#pragma omp parallel for
for (int32_t i = 0; i < 2; ++i)
{
rTable[i] = i * 255;
gTable[i] = i * 255;
bTable[i] = i * 255;
}
TIFFSetField(tif, TIFFTAG_COLORMAP, rTable, gTable, bTable);
}
else if (HGBASE_IMGTYPE_GRAY == type)
{
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);
}
if (NULL != info)
{
TIFFSetField(tif, TIFFTAG_COMPRESSION, info->compression);
TIFFSetField(tif, TIFFTAG_JPEGQUALITY, info->jpegQuality);
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, info->resolutionUnit);
TIFFSetField(tif, TIFFTAG_XRESOLUTION, info->xResolution);
TIFFSetField(tif, TIFFTAG_YRESOLUTION, info->yResolution);
}
else
{
HGUInt xDpi, yDpi;
HGBase_GetImageDpi(image, &xDpi, &yDpi);
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
TIFFSetField(tif, TIFFTAG_JPEGQUALITY, 80);
TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
TIFFSetField(tif, TIFFTAG_XRESOLUTION, xDpi);
TIFFSetField(tif, TIFFTAG_YRESOLUTION, yDpi);
}
//#pragma omp parallel for
for (int32_t i = 0; i < (int32_t)height; ++i)
{
uint8_t* pEx = data + (HGSize)i * (HGSize)widthStep;
TIFFWriteScanline(tif, pEx, i, 0);
}
HGBase_SetImageROI(image, &roi);
HGBase_DestroyImage(image2);
image2 = NULL;
TIFFWriteDirectory(tif);
return HGBASE_ERR_OK;
}
HGResult HGAPI HGImgFmt_SaveTiffImage(HGImage image, const UPTiffSaveInfo* info, const HGChar* fileName)
{
HGTiffWriter writer = NULL;
HGResult ret = HGImgFmt_OpenTiffWriter(fileName, &writer);
if (HGBASE_ERR_OK != ret)
{
return ret;
}
ret = HGImgFmt_SaveImageToTiffWriter(writer, image, info);
HGImgFmt_CloseTiffWriter(writer);
return ret;
}