388 lines
9.2 KiB
C++
388 lines
9.2 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, HGTiffLoadInfo* 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, HGTiffLoadInfo* 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 HGTiffSaveInfo* 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)
|
|
{
|
|
HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2);
|
|
}
|
|
else if (HGBASE_IMGTYPE_BGRA == imgInfo.type)
|
|
{
|
|
HGBase_CloneImage(image, HGBASE_IMGTYPE_RGBA, HGBASE_IMGORIGIN_TOP, &image2);
|
|
}
|
|
else
|
|
{
|
|
HGBase_CloneImage(image, imgInfo.type, HGBASE_IMGORIGIN_TOP, &image2);
|
|
}
|
|
|
|
if (NULL == image2)
|
|
{
|
|
HGBase_SetImageROI(image, &roi);
|
|
return HGBASE_ERR_FAIL;
|
|
}
|
|
|
|
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_MINISBLACK : PHOTOMETRIC_RGB);
|
|
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
|
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, height);
|
|
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
|
|
|
|
if (NULL != info)
|
|
{
|
|
if ((HGBASE_IMGTYPE_BINARY == type && HGIMGFMT_TIFFCOMP_JPEG == info->compression)
|
|
|| (HGBASE_IMGTYPE_BINARY != type && HGIMGFMT_TIFFCOMP_CCITTFAX4 == info->compression))
|
|
TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
|
|
else
|
|
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);
|
|
|
|
if (HGIMGFMT_TIFFCOMP_JPEG == info->compression && HGBASE_IMGTYPE_RGB == type)
|
|
{
|
|
TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
|
|
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
|
|
}
|
|
}
|
|
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 HGTiffSaveInfo* 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;
|
|
} |