cxnet 发表于 2025-10-9 09:41:04

如何将Mat转为TIF

在C++ MFC中,要将Mat图像转为TIFF图像格式并依赖libtiff库保存为1位深度和1200分辨率的TIF文件应该怎样写代码

FishC 发表于 2025-10-9 09:42:32

以下是在C++ MFC环境中,使用OpenCV的Mat和libtiff库将图像转换为1位深度、1200 DPI分辨率TIFF文件的示例代码。请确保已正确安装并链接OpenCV和libtiff库。


#include <opencv2/opencv.hpp>
#include <tiffio.h>

// 函数:将Mat转换为1位深度TIFF
bool MatToTiff1Bit(const cv::Mat& inputMat, const char* filename, int dpi = 1200) {
    // 检查输入图像是否有效
    if (inputMat.empty()) {
      AfxMessageBox(_T("输入图像为空!"));
      return false;
    }

    // 转换为灰度图像(如果原图为彩色)
    cv::Mat grayMat;
    if (inputMat.channels() > 1) {
      cv::cvtColor(inputMat, grayMat, cv::COLOR_BGR2GRAY);
    } else {
      grayMat = inputMat.clone();
    }

    // 二值化处理(转换为1位深度)
    cv::Mat binaryMat;
    cv::threshold(grayMat, binaryMat, 128, 255, cv::THRESH_BINARY);

    // 获取图像尺寸
    int width = binaryMat.cols;
    int height = binaryMat.rows;

    // 打开TIFF文件
    TIFF* tif = TIFFOpen(filename, "w");
    if (!tif) {
      AfxMessageBox(_T("无法创建TIFF文件!"));
      return false;
    }

    // 设置TIFF标签
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 1);          // 1位深度
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);      // 单通道
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); // 黑色为0
    TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
    TIFFSetField(tif, TIFFTAG_XRESOLUTION, static_cast<double>(dpi));
    TIFFSetField(tif, TIFFTAG_YRESOLUTION, static_cast<double>(dpi));
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, 0));

    // 准备数据缓冲区(每行字节数需按8位对齐)
    int bytesPerLine = (width + 7) / 8;
    std::vector<uint8_t> buffer(bytesPerLine * height, 0);

    // 将二值图像数据打包为1位格式
    for (int y = 0; y < height; y++) {
      const uint8_t* src = binaryMat.ptr<uint8_t>(y);
      uint8_t* dst = &buffer;
      for (int x = 0; x < width; x++) {
            if (src > 0) {
                dst |= (1 << (7 - (x % 8))); // 设置对应位为1
            }
      }
    }

    // 写入数据到TIFF
    for (int row = 0; row < height; row++) {
      if (TIFFWriteScanline(tif, &buffer, row, 0) < 0) {
            TIFFClose(tif);
            AfxMessageBox(_T("写入TIFF数据失败!"));
            return false;
      }
    }

    // 关闭文件并清理
    TIFFClose(tif);
    return true;
}

// 使用示例(在MFC按钮事件中调用)
void CYourDlg::OnBnClickedSaveTiff() {
    cv::Mat matImage = cv::imread("input.png"); // 替换为您的Mat来源
    if (matImage.empty()) {
      AfxMessageBox(_T("加载图像失败!"));
      return;
    }

    CString filePath = _T("output.tif"); // 指定保存路径
    if (MatToTiff1Bit(matImage, CT2A(filePath), 1200)) {
      AfxMessageBox(_T("TIFF保存成功!"));
    } else {
      AfxMessageBox(_T("保存失败!"));
    }
}


关键步骤说明:
1. 图像预处理:将输入Mat转换为灰度图,再通过阈值处理二值化。
2. 设置TIFF参数:通过 TIFFSetField 指定1位深度、1200 DPI分辨率等。
3. 数据打包:二值图像每个像素占1位,需按字节对齐并逐位填充。
4. 错误处理:添加基础检查确保操作可靠性。

注意事项:
- 确保项目已链接 opencv_world4xx.lib 和 libtiff.lib。
- 分辨率单位默认为英寸(RESUNIT_INCH),1200 DPI通过 XRESOLUTION 和 YRESOLUTION 设置。
- 二值化阈值设为128,可根据实际图像调整。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

小甲鱼的二师兄 发表于 2025-10-10 08:49:17

C++ MFC中使用OpenCV Mat和libtiff库转换:

1. 确保已安装libtiff并链接到项目;

2. 将Mat转换为8位灰度或RGB(如果需要);

3. 使用libtiff函数设置TIFF标签(如分辨率、位深度);

4. 保存为1位深度和1200 DPI。
页: [1]
查看完整版本: 如何将Mat转为TIF