2014.12.29 22:42 "[Tiff] [PATCH] tiffcp: use buffered by-strip conversion for jbig instead of by-scanline (was: TIFF JBIG writer and scanlines)", by Yuriy M. Kaminskiy
Today I encountered this:
% tiffcp -r -1 -c jbig golfer-150-bilevel.tiff golfer-150-bilevel-jbig.tiff golfer-150-bilevel-jbig.tiff: ISO JBIG scanline encoding is not implemented.
golfer-150-bilevel-jbig.tiff: Error, can't write scanline 0.
This was due to a GraphicsMagick user reporting that scanline reading sometimes fails due to libtiff's JBIG support reporting that reading via scanlines is not supported. I used the tiffcp incantation he provided and encountered the same error as when GraphicsMagick tries to write via its scanline writer.
This is using jbigkit-2.0. I tried on a machine with jbigkit-1.6 and it worked.
Ideas?
Apparently, it fails when source has more than one strip.
Working:
Image Width: 1100 Image Length: 1600
Rows/Strip: 1600
Failing:
Image Width: 1100 Image Length: 1600
Rows/Strip: 256
Conversion in two steps works:
tiffcp -r -1 in.tiff temp.tiff # convert to single strip
tiffcp -c jbig temp.tiff out.tiff # compress to jbig
Attached patch should solve this.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
NotDashEscaped: You need GnuPG to verify this message
From: Yuriy M. Kaminskiy <yumkam@gmail.com>
Subject: tiffcp: use buffered by-strip conversion for jbig instead of by-scanline
LibTiff JBIG encoder only supports by-strip encoding/decoding.
Index: tiff-3.9.4/tools/tiffcp.c
===================================================================
--- tiff-3.9.4.orig/tools/tiffcp.c 2014-12-23 18:42:25.680097625 +0300
+++ tiff-3.9.4/tools/tiffcp.c 2014-12-23 18:57:45.680096066 +0300
@@ -1542,6 +1542,50 @@ DECLAREcpFunc(cpContigStrips2SeparateTil
}
/*
+ * Contig strips -> contig strips (change chunk & jbig).
+ */
+DECLAREcpFunc(cpContigStrips2ContigStrips)
+{
+ return cpImage(in, out,
+ readContigStripsIntoBuffer,
+ writeBufferToContigStrips,
+ imagelength, imagewidth, spp);
+}
+
+/*
+ * Contig strips -> separate strips (change chunk & jbig).
+ */
+DECLAREcpFunc(cpContigStrips2SeparateStrips)
+{
+ return cpImage(in, out,
+ readContigStripsIntoBuffer,
+ writeBufferToSeparateStrips,
+ imagelength, imagewidth, spp);
+}
+
+/*
+ * Separate strips -> contig strips (change chunk & jbig).
+ */
+DECLAREcpFunc(cpSeparateStrips2ContigStrips)
+{
+ return cpImage(in, out,
+ readSeparateStripsIntoBuffer,
+ writeBufferToContigStrips,
+ imagelength, imagewidth, spp);
+}
+
+/*
+ * Separate strips -> separate strips (change chunk & jbig).
+ */
+DECLAREcpFunc(cpSeparateStrips2SeparateStrips)
+{
+ return cpImage(in, out,
+ readSeparateStripsIntoBuffer,
+ writeBufferToSeparateStrips,
+ imagelength, imagewidth, spp);
+}
+
+/*
* Separate strips -> contig tiles.
*/
DECLAREcpFunc(cpSeparateStrips2ContigTiles)
@@ -1660,6 +1704,7 @@ pickCopyFunc(TIFF* in, TIFF* out, uint16
uint16 shortv;
uint32 w, l, tw, tl;
int bychunk;
+ uint16 input_compression, output_compression;
(void) TIFFGetField(in, TIFFTAG_PLANARCONFIG, &shortv);
if (shortv != config && bitspersample != 8 && samplesperpixel > 1) {
@@ -1694,6 +1739,8 @@ pickCopyFunc(TIFF* in, TIFF* out, uint16
bychunk = (tw == w && tl == rowsperstrip);
}
}
+ TIFFGetFieldDefaulted(in, TIFFTAG_COMPRESSION, &input_compression);
+ TIFFGetFieldDefaulted(out, TIFFTAG_COMPRESSION, &output_compression);
#define T 1
#define F 0
#define pack(a,b,c,d,e) ((long)(((a)<<11)|((b)<<3)|((c)<<2)|((d)<<1)|(e)))
@@ -1739,17 +1786,32 @@ pickCopyFunc(TIFF* in, TIFF* out, uint16
return cpSeparateTiles2SeparateStrips;
/* Strips -> Strips */
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_CONTIG, F,F,F):
+ if (input_compression == COMPRESSION_JBIG ||
+ output_compression == COMPRESSION_JBIG)
+ return cpContigStrips2ContigStrips;
return bias ? cpBiasedContig2Contig : cpContig2ContigByRow;
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_CONTIG, F,F,T):
+ if (input_compression == COMPRESSION_JBIG ||
+ output_compression == COMPRESSION_JBIG)
+ return cpContigStrips2ContigStrips;
return cpDecodedStrips;
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE, F,F,F):
case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE, F,F,T):
+ if (input_compression == COMPRESSION_JBIG ||
+ output_compression == COMPRESSION_JBIG)
+ return cpContigStrips2SeparateStrips;
return cpContig2SeparateByRow;
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG, F,F,F):
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG, F,F,T):
+ if (input_compression == COMPRESSION_JBIG ||
+ output_compression == COMPRESSION_JBIG)
+ return cpSeparateStrips2ContigStrips;
return cpSeparate2ContigByRow;
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,F):
case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE, F,F,T):
+ if (input_compression == COMPRESSION_JBIG ||
+ output_compression == COMPRESSION_JBIG)
+ return cpSeparateStrips2SeparateStrips;
return cpSeparate2SeparateByRow;
}
#undef pack
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
iF4EAREIAAYFAlSh1/EACgkQKZn9iF16KMNk4gD/SAhCyNaloRX6ChEDQQGfkGYz
3kP5RF0qNANiqOgqtxsA/2ahdZW2JBdW65j5Cw1nG2usUqCYUCYKTc/4pd6lE0B8
=+t36
-----END PGP SIGNATURE-----