Reputation: 27729
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
# 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
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);
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:
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