Tif文件与JPG文件之间的合并拆分实现(使用LibTIFF与OpenCV)

以下是使用LibTiff与OpenCV在win32控制台程序中实现tif文件与jpg文件之间的转换。

将一个tif文件拆分为一或多张jpg图片:

#include 
#include 
#include "tiffio.h"
#include 
#include 
#include 
#include 
#include 
#include 

void Tiff2JpgByLibtiffAndCV(TIFF *tiff, int pageIndex, const std::string &imgPath)
{
    TIFFSetDirectory(tiff, pageIndex);

    int width = 0;
    int height = 0;
    TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);

    int pixelCount = width*height;
    uint32* srcImg = (uint32*)malloc(pixelCount * sizeof (uint32));
    TIFFReadRGBAImage(tiff, width, height, srcImg, 1);

    //由于tiff格式的图像数据与bmp图存储方式一致,是从下到上,所以读的时候,需要从下往上读
    BYTE* destImg = new BYTE[pixelCount*3];

    uint32 *rowPointerToSrc = srcImg + (height - 1)*width;
    BYTE *rowPointerToDest = destImg;
    for (int y = height - 1; y >= 0; --y)
    {
        uint32 *colPointerToSrc = rowPointerToSrc;
        BYTE *colPointerToDest = rowPointerToDest;
        for (int x = 0; x <= width - 1; ++x)
        {
            colPointerToDest[0] = (BYTE)TIFFGetB(colPointerToSrc[0]);
            colPointerToDest[1] = (BYTE)TIFFGetG(colPointerToSrc[0]);
            colPointerToDest[2] = (BYTE)TIFFGetR(colPointerToSrc[0]);

            colPointerToDest += 3;
            colPointerToSrc++;
        }
        rowPointerToSrc -= width;
        rowPointerToDest += width*3;
    }

    cv::Mat destMat(height, width, CV_8UC3, destImg, width * 3);
    cv::imwrite(imgPath, destMat);

    _TIFFfree(srcImg);
    _TIFFfree(destImg);
}

void Tiff2JpgsByLibtiffAndCV(const std::string &tifPath, const std::string &dirPath)
{
    TIFF* tiff =TIFFOpen(tifPath.c_str(), "r");//打开Tiff文件,得到指针,以后所有的操作都通过指针进行
    if (!tiff)
        return;

    int pageCount = TIFFNumberOfDirectories(tiff);
    for (int i = 0; i < pageCount; ++i)
    {
        std::string imgFullPath = dirPath + std::to_string((long long)i) + ".jpg";
        Tiff2JpgByLibtiffAndCV(tiff, i, imgFullPath);
    }

    TIFFClose(tiff);
}

将多张jpg格式图片合并为一张tif文件:

void Jpg2TiffByLibTiffAndCV(TIFF *tiff, int pageIndex,std::string imgPath)
{
    if(!tiff)
        return;

    cv::Mat firstImg = cv::imread(imgPath);
    cv::cvtColor(firstImg, firstImg, CV_BGR2RGB);
    int firstWidth = firstImg.cols;
    int firstHeight = firstImg.rows;

    TIFFSetDirectory(tiff, pageIndex);

    TIFFSetField(tiff, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
    TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, firstWidth);
    TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, firstHeight);
    TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 3);
    TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
    TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
    TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);

    uchar *firstImgData = firstImg.data;
    for (int i = 0; i < firstHeight; ++i)
    {
        TIFFWriteScanline(tiff, &firstImgData[i * firstWidth * 3], i);
    }

    TIFFWriteDirectory(tiff);
}

void Jpgs2TiffByLibTiffAndCV(std::vector<std::string> vecImgPath, std::string tifPath)
{
    TIFF *tiff = TIFFOpen(tifPath.c_str(), "w");
    if (!tiff)
        return;
    int pageIndex = 0;
    for (auto vecIter = vecImgPath.begin(); vecIter != vecImgPath.end(); ++vecIter)
    {
        Jpg2TiffByLibTiffAndCV(tiff, pageIndex++, *vecIter);
    }   

    TIFFClose(tiff);
}

总结:
之前在网上找了各种实现方式但都不是自己想要的效果,后来自己综合各种方法,使用LibTiff与OpenCV简洁快速地实现普通格式图片与tif文件之间的合并拆分。

你可能感兴趣的:(杂项)