#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; }