clarkk
clarkk

Reputation: 27729

OpenCV output monochrome TIFF group 4 compression

Is there a way to output monochrome TIFF files in OpenCV with group 4 compression?

This is the command to do it with imagemagick/graphicsmagick

'gm convert '.$file.' -type bilevel -monochrome -compress group4 '.$output

OpenCV version 4.5.1

update

# g++ -Wall -O3 -std=c++17 main.cpp -o main `pkg-config opencv4 --cflags --libs` -ltiff

find doesn't return anything

root@x:/usr/include/opencv4/opencv2# find . -name "*tif*"

code

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

std::vector<int> params = {cv::IMWRITE_TIFF_COMPRESSION, COMPRESSION_CCITTFAX4};
cv::imwrite(_output, src_bin, params);

error

[ WARN:0] global ../modules/imgcodecs/src/grfmt_tiff.cpp (914) writeLibTiff OpenCV TIFF(line 914): failed TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor) imwrite_('out.tif'): can't write data: OpenCV(4.5.1) ../modules/imgcodecs/src/grfmt_tiff.cpp:914: error: (-2:Unspecified error) OpenCV TIFF: failed TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor) in function 'writeLibTiff'

Upvotes: 1

Views: 1008

Answers (1)

Markus
Markus

Reputation: 6298

OpenCV uses libtiff (link). If you call cv.imwrite (link) you can pass additional parameters.

For group 4 compression the docs say that you have to pass the IMWRITE_TIFF_COMPRESSION flag (link) with value COMPRESSION_CCITTFAX4 (link).

Example:

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

using namespace cv;
using namespace std;

vector<int> params = {IMWRITE_TIFF_COMPRESSION, COMPRESSION_CCITTFAX4};

bool success = imwrite("image.tif", img, params);

Update

Well, this is how it should work. But it seems that opencv4 currently has one or more issues in writing Group 4 TIFF. Btw it's the same when you try the python-lib. This known issue deals with a predictor tag that is wrongly added by opencv. I applied the fix to my local build but after that one more issue came up missing a conversion of the 8bit Mat to 1bit/sample for group4. So my recommendation is:

Workaround

Instead you can use the GraphicsMagick API Magick++.

#include <opencv2/opencv.hpp>
#include <Magick++.h>

using namespace cv;
using namespace Magick;

int main(int argc, char* argv[]) {
        InitializeMagick("");

        Mat img = imread("img.png");
        Image image(img.cols, img.rows, "BGR", CharPixel, (char *)img.data);
        image.compressType(CompressionType::Group4Compression);
        image.write("img.tif");
        return(0);
}

Upvotes: 4

Related Questions