in opencv 4.10, we exposed all the compression parameters from libtiff:
cv::Mat1f image;
std::vector<int> compression_params = {
cv::IMWRITE_TIFF_COMPRESSION, cv::IMWRITE_TIFF_COMPRESSION_LZMA
};
cv::imwrite(
out_dir / str(boost::format{"%08d.tif"} % timestamp),
image,
compression_params
);
the resulting file:
01160780.tif: TIFF image data, little-endian, direntries=11, height=76, bps=32, compression=none, PhotometricIntepretation=BlackIsZero, width=228
there is no compression at all.
But I can actually get PIL to compress it.
I also directly tried the libtiff in c++, which works fine too:
#include <iostream>
#include <vector>
#include <tiffio.h>
#include <cstdlib>
#include <ctime>
void generateRandomMatrix(float* matrix, int width, int height) {
for (int i = 0; i < width * height; ++i) {
matrix[i] = static_cast<float>(rand()) / RAND_MAX; // Random float between 0.0 and 1.0
}
}
void generateGradientMatrix(float* matrix, int width, int height) {
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
matrix[y * width + x] = static_cast<float>(x) / (width - 1); // Gradient from 0.0 to 1.0
}
}
}
void saveTiff(
const std::string& filename,
const std::vector<float>& floatMatrix,
const int width,
const int height,
const int compression
) {
TIFF* tif = TIFFOpen(filename.c_str(), "w");
if (!tif) {
std::cerr << "Failed to open TIFF file for writing: " << filename << std::endl;
exit(1);
}
// Set TIFF file parameters for 32-bit floating point
TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); // 32 bits per sample
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); // 1 sample per pixel
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); // grayscale
// Set the data type to floating point
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
// Set compression type
TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
// Write the image data
for (int row = 0; row < height; ++row) {
TIFFWriteScanline(
tif,
const_cast<float*>(floatMatrix.data() + row * width),
row,
0
);
}
// Close TIFF file
TIFFClose(tif);
}
int main() {
srand(static_cast<unsigned>(time(0))); // Seed for random number generation
const int width = 256;
const int height = 256;
const int numPixels = width * height;
// Allocate memory for the float matrix
std::vector<float> floatMatrix(numPixels);
generateGradientMatrix(floatMatrix.data(), width, height);
// Save TIFF with no compression
saveTiff("gradient_float32_no_compression.tif", floatMatrix, width, height, COMPRESSION_NONE);
// Save TIFF with LZMA compression
saveTiff("gradient_float32_lzma.tif", floatMatrix, width, height, COMPRESSION_LZMA);
std::cout << "TIFF image saved successfully!" << std::endl;
return 0;
}
here we can see the compressing: unknown 0xffff886d
file gradient_float32_lzma.tif
gradient_float32_lzma.tif: TIFF image data, little-endian, direntries=11, height=256, bps=32, compression=(unknown 0xffff886d), PhotometricIntepretation=BlackIsZero, orientation=upper-left, width=256
any idea, what might go wrong here?
so for some reason opencv guys artificially imposed this limitation:
case CV_32F:
{
bitsPerChannel = 32;
page_compression = COMPRESSION_NONE;
sample_format = SAMPLEFORMAT_IEEEFP;
break;
}
case CV_64F:
{
bitsPerChannel = 64;
page_compression = COMPRESSION_NONE;
sample_format = SAMPLEFORMAT_IEEEFP;
break;
}
will report to there, to see why they think this is good idea