#include "HGTiff.h" #include "../base/HGInc.h" #include "../base/HGInfo.h" #include "tiffio.h" HGResult HGAPI HGImgFmt_CheckTiffFile(const HGChar* fileName, HGBool* isTiff) { if (NULL == fileName || NULL == isTiff) { return HGBASE_ERR_INVALIDARG; } HGTiffReader reader = NULL; HGResult ret = HGImgFmt_OpenTiffReader(fileName, &reader); if (HGBASE_ERR_OK != ret) { return ret; } *isTiff = HGTRUE; HGImgFmt_CloseTiffReader(reader); return ret; } HGResult HGAPI HGImgFmt_OpenTiffReader(const HGChar* fileName, HGTiffReader* reader) { if (NULL == fileName || NULL == reader) { return HGBASE_ERR_INVALIDARG; } #if defined(HG_CMP_MSC) if (0 != _access(fileName, 0)) #else if (0 != access(fileName, 0)) #endif { return HGBASE_ERR_FILENOTEXIST; } TIFF* tif = TIFFOpen(fileName, "r"); if (NULL == tif) { return HGBASE_ERR_FILEERROR; } *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 (0 != imgOrigin && HGBASE_IMGORIGIN_TOP != imgOrigin && HGBASE_IMGORIGIN_BOTTOM != imgOrigin) { return HGBASE_ERR_INVALIDARG; } } TIFF* tif = (TIFF*)reader; if (0 == TIFFSetDirectory(tif, index)) { return HGIMGFMT_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_OUTOFMEMORY; } if (0 == TIFFReadRGBAImageOriented(tif, width, height, buffer, ORIENTATION_TOPLEFT)) { free(buffer); buffer = NULL; return HGIMGFMT_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; } } if (imgOrigin == 0) { imgOrigin = HGBASE_IMGORIGIN_TOP; } 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) { HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "HGImgFmt_OpenTiffWriter: TIFFOpen fail, %s", fileName); 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) { HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGB, HGBASE_IMGORIGIN_TOP, &image2); if (HGBASE_ERR_OK != ret) { HGBase_SetImageROI(image, &roi); return ret; } } else if (HGBASE_IMGTYPE_BGRA == imgInfo.type) { HGResult ret = HGBase_CloneImage(image, HGBASE_IMGTYPE_RGBA, HGBASE_IMGORIGIN_TOP, &image2); if (HGBASE_ERR_OK != ret) { HGBase_SetImageROI(image, &roi); return ret; } } else { HGResult ret = HGBase_CloneImage(image, imgInfo.type, HGBASE_IMGORIGIN_TOP, &image2); if (HGBASE_ERR_OK != ret) { HGBase_SetImageROI(image, &roi); return ret; } } 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; }