visual-studio - 如何在 C++ 中创建 CMYK 模式图像?

标签 visual-studio opencv cmyk libtiff

最近在研究opencv。我需要创建图像垫并将其写入 .tif 图像文件。 .tif 文件在 photoshop 中打开打印时应为 CMYK 模式。

但是当我尝试imread 类型为UNCHANGED 的CMYK 图像文件,然后imwrite 将垫子imwrite 到.tif 文件时,它仍然是RGB photoshop 中的模式。

图像只能通过opencv保存为RGB(或BGR)模式吗? (我找到了一些答案,python有可以选择CMYK模式保存的库。但我想知道在C++中有什么办法可以解决这个问题吗?)


谢谢@马克。 我尝试在 windows10 中编译 libtiff 库时遇到了一些麻烦。

我下载libtiff版本为 tiff-4.0.10.zip。并在vs2017中使用nmake/f makefile.vc编译。 (nmake.opt 没有任何变化)。

然后获取一些.dll .lib 文件。将 libtiff_i.lib 链接到库文件夹和听众文件以将文件夹包含在项目中。

尝试@Mark代码进行测试。然后,我在 vs 中遇到错误(LNK2019),看起来像链接问题。

LNK2019 unresolved external symbol TIFFClose referenced in function "bool __cdecl tiffwrite(char const *,class cv::Mat)" (?tiffwrite@@YA_NPEBDVMat@cv@@@Z)  
LNK2019 unresolved external symbol TIFFSetField referenced in function "bool __cdecl tiffwrite(char const *,class cv::Mat)" (?tiffwrite@@YA_NPEBDVMat@cv@@@Z)       
LNK2019 unresolved external symbol TIFFWriteScanline referenced in function "bool __cdecl tiffwrite(char const *,class cv::Mat)" (?tiffwrite@@YA_NPEBDVMat@cv@@@Z)  
LNK2019 unresolved external symbol TIFFOpen referenced in function "bool __cdecl tiffwrite(char const *,class cv::Mat)" (?tiffwrite@@YA_NPEBDVMat@cv@@@Z)

我不确定是链接问题还是编译文件(libtiff.dll,libtiff_i.lib)问题?

(这里是vs2017中的链接设置:linker lib and include


我通过使用 cmake 编译 libtiff 解决了这个问题。

关注这个Reference可以在 windows(64 位)上获得适用于 vs2017 的正确库。

最佳答案

我认为正确的答案是使用 libtiff 对其进行编码。我不是 libtiff 方面的专家,但这似乎适用于我尝试过的情况:

#include <iostream>
#include <opencv2/opencv.hpp>

extern "C" {
#define uint64 uint64_hack_
#define int64 int64_hack_
#include "tiffio.h"
#undef uint64
#undef uint64
}

using namespace cv;

bool tiffwrite(const char* name, Mat image){

   TIFF* tif = TIFFOpen(name, "w");
   if(tif==NULL){
      std::cerr << "ERROR: Unable to open output file";
      return false;
   }

   int width  = image.cols;
   int height = image.rows;

   // We expect 4 channels
   int channels = image.channels();
   assert(channels==4);

   // We expect 8-bit data
   int bytespersample = image.elemSize1();
   assert(bytespersample == 1);

   TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
   TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
   TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
   TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, channels);
   TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW);
   TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8*bytespersample);
   TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 8);
   TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_SEPARATED);

   // Write to file, 1 scanline at a time
   for (int row = 0; row < height; row++) {
      // std::cerr << "DEBUG: Writing row " << row << std::endl;

      // Get pointer to row
      cv::Vec4b* ptr = image.ptr<cv::Vec4b>(row);

      int ret = TIFFWriteScanline(tif, (unsigned char*)ptr, row, 0);
      if (ret == -1) {
         TIFFClose(tif);
         return false;
      }
   }
   TIFFClose(tif);
   return true;
}

int
main(int argc,char*argv[])
{
    // Create a 4-channel CMYK yellow image
    Mat4b image(480, 640, Vec4b(0,0,255,0));

    // Write as CMYK TIFF
    tiffwrite("result.tif",image);
}

我还提出了一些您可能想尝试的技巧。

第一个也是最简单的 hack,像往常一样用 OpenCV 保存为 JPEG、TIFF 或 PNG,然后使用 system() 函数输出到 ImageMagick 并从那里转换为 CMYK TIFF。

cv2::imwrite("intermediate.jpg",image);

system("...");

在里面你放了相当于:

convert intermediate.jpg -colorspace CMYK result.tif

或者如果使用 v7 的 ImageMagick

magick intermediate.jpg -colorspace CMYK result.tif

第二个 hack,如果你不想安装和依赖 ImageMagick...有一个工具叫做 raw2tifflibtiff 一起提供。您可以将原始文件(无标题)传递给它,它会为您将其转换为 TIFF。因此,您基本上会使用 OpenCV 将原始 C 字节、原始 M 字节、原始 Y 字节和原始 K 字节写入单个文件,并使用 system() 调用该实用程序。我使用了这个命令行:

raw2tiff -w 1024 -l 768 -b 4 -i band -c lzw -p cmyk CMYK result.tif

所以我的图像宽 1024 像素,高 768 像素,由 CMYK 文件中的 4 个波段组成,我想要一个名为 result.tif 的 LZW 压缩 TIFF。在 Photoshop 中打开看起来像这样:

enter image description here

我用 ImageMagick 合成了 C、M、Y 和 K channel ,如下所示:

#!/bin/bash
# Make raw and viewable C channel
convert -size 1024x768 gradient: -depth 8 -write gray:C C.png
# Make raw and viewable M channel
convert -size 1024x768 xc:black  -depth 8 -write gray:M M.png
# Make raw and viewable Y channel
convert -size 768x1024 gradient: -rotate 90 -depth 8 -write gray:Y Y.png
# Make raw and viewable K channel
convert -colorspace RGB -size 400x400 gradient: -gravity center -background black -extent 1024x768 -depth 8 -write gray:K K.png

# Stack side-by-side, just for viewing
convert C.png M.png Y.png K.png  +append CMYK.png

# Concatenate them all together into single file "CMYK" as input file for "raw2tiff"
cat C M Y K > CMYK

这是 4 张图片,左边是 C,然后是 M,然后是 Y,最后是右边的 K。

enter image description here

在您的情况下,您将获得指向您的 Matdata 指针,并简单地将每个 channel 的 height*width 字节写入二进制文件,而不是使用 ImageMagick。您可以在我的回答顶部的 libtiff 示例中看到如何做到这一点。

关键词:TIFF、TIF、图像处理、libtiff、CMYK、分色、分色、Photoshop。

看图像,我想我应该先否定(反转)图像,但这并不难。

关于visual-studio - 如何在 C++ 中创建 CMYK 模式图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58606658/

相关文章:

python - opencv cascade.detectMultiScale 创建错误 : (-215) ! empty()

php - PDF 缩略图总是使用 Imagick 生成为灰度

java - 如何在 Java 中将 RGB 图像转换为 CMYK,反之亦然?

r - 在 R 中创建 EPS 或 TIFF 中的 CMYK 图

visual-studio - 删除自动导入的自定义项目模板

.net - 如何使用Visual Studio解决方案和TFS设置ElasticSearch数据备份?

c# - 从 Sense 查询转移到 Visual Studio 查询

c# - 自定义卸载操作c#

opencv:视频稳定模块示例对于任何具有不同错误的视频都失败

python - 图像大小(Python、OpenCV)