- 2014.12.27 22:30 "[Tiff] [PATCH] tiff2pdf fixes for grayscale (min-is-white/black) and alpha", by Yuriy M. Kaminskiy
- 2014.12.29 22:29 "[Tiff] [PATCH] Signal error on unsupported sample/bit-depth in jbig codec instead of silently producing garbage", by Yuriy M. Kaminskiy
-
2014.12.30 20:41 "[Tiff] [PATCH] tif_luv, tif_pixarlog, ppm2tiff: get rid of duplicates of TIFFSafeMultiply", by Yuriy M. Kaminskiy
-
2014.12.30 20:55 "Re: [Tiff] [PATCH] tif_luv, tif_pixarlog, ppm2tiff: get rid of duplicates of TIFFSafeMultiply", by Jürgen_Buchmüller
- 2014.12.30 21:45 "Re: [Tiff] [PATCH] tif_luv, tif_pixarlog, ppm2tiff: get rid of duplicates of TIFFSafeMultiply", by Yuriy M. Kaminskiy
- 2014.12.31 14:33 "Re: [Tiff] [PATCH] tif_luv, tif_pixarlog, ppm2tiff: get rid of duplicates of TIFFSafeMultiply", by Olivier Paquet
- 2015.01.04 23:02 "Re: [Tiff] [PATCH] tif_luv, tif_pixarlog, ppm2tiff: get rid of duplicates of TIFFSafeMultiply", by Yuriy M. Kaminskiy
- 2014.12.31 09:36 "Re: [Tiff] [PATCH] tif_luv, tif_pixarlog, ppm2tiff: get rid of duplicates of TIFFSafeMultiply", by Jürgen_Buchmüller
-
2014.12.30 20:55 "Re: [Tiff] [PATCH] tif_luv, tif_pixarlog, ppm2tiff: get rid of duplicates of TIFFSafeMultiply", by Jürgen_Buchmüller
- 2015.01.25 16:56 "[Tiff] [security][PATCH] tiff2pdf: fix snprintf return value misuse", by Yuriy M. Kaminskiy
2014.12.27 22:30 "[Tiff] [PATCH] tiff2pdf fixes for grayscale (min-is-white/black) and alpha", by Yuriy M. Kaminskiy
Samples to test:
https://bugs.debian.org/cgi-bin/bugreport.cgi?msg=21;filename=test1s3.tiff;att=1;bug=611141
(from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=611141)
and
https://bugs.debian.org/cgi-bin/bugreport.cgi?msg=5;filename=doc673.tif.126;att=5;bug=552382
(from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=552382)
(both bugs are about tiff2ps [patch will be posted separately], but also exposes
bug in tiff2pdf).
From: Yuriy M. Kaminskiy <yumkam@gmail.com>
Subject: Disable compression passthrough when sample conversion requested
It is not possible to use passthrough compression when
conversion from separate to contig or drop alpha is requested.
Index: tiff-3.9.4/tools/tiff2pdf.c
===================================================================
--- tiff-3.9.4.orig/tools/tiff2pdf.c 2014-12-27 19:36:10.552594211 +0300
+++ tiff-3.9.4/tools/tiff2pdf.c 2014-12-27 23:40:32.708095195 +0300
@@ -1700,7 +1700,7 @@ void t2p_read_tiff_data(T2P* t2p, TIFF*
t2p_compose_pdf_page(t2p);
t2p->pdf_transcode = T2P_TRANSCODE_ENCODE;
- if(t2p->pdf_nopassthrough==0){
+ if(t2p->pdf_nopassthrough==0 && t2p->pdf_sample == T2P_SAMPLE_NOTHING){
#ifdef CCITT_SUPPORT
if(t2p->tiff_compression==COMPRESSION_CCITTFAX4
){
Yuriy M. Kaminskiy <yumkam@gmail.com>
Subject: tiff2pdf: fix combination of SEPARATE to CONTIG conversion with other sample format conversions (dropping alpha/etc)
Index: tiff-3.9.4/tools/tiff2pdf.c
===================================================================
--- tiff-3.9.4.orig/tools/tiff2pdf.c 2014-12-27 19:36:10.552594211 +0300
+++ tiff-3.9.4/tools/tiff2pdf.c 2014-12-27 23:40:32.708095195 +0300
@@ -1649,7 +1649,7 @@ void t2p_read_tiff_data(T2P* t2p, TIFF*
case PLANARCONFIG_CONTIG:
break;
case PLANARCONFIG_SEPARATE:
- t2p->pdf_sample=T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG;
+ t2p->pdf_sample |= T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG;
if(t2p->tiff_bitspersample!=8){
TIFFError(
TIFF2PDF_MODULE,
@@ -2898,7 +2962,7 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P
} else {
- if(t2p->pdf_sample == T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG){
+ if(t2p->pdf_sample & T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG){
septilesize=TIFFTileSize(input);
septilecount=TIFFNumberOfTiles(input);
tilesize=septilesize*t2p->tiff_samplesperpixel;
Yuriy M. Kaminskiy <yumkam@gmail.com>
Subject: tiff2pdf: fix/add support for grayscale-alpha formats
Index: tiff-3.9.4/tools/tiff2pdf.c
===================================================================
--- tiff-3.9.4.orig/tools/tiff2pdf.c 2014-12-27 19:36:10.552594211 +0300
+++ tiff-3.9.4/tools/tiff2pdf.c 2014-12-27 23:40:32.708095195 +0300
@@ -94,6 +94,8 @@ typedef enum{
T2P_SAMPLE_ABGR_TO_RGB=0x0001, /* The unencoded samples are the result of ReadRGBAImage */
T2P_SAMPLE_RGBA_TO_RGB=0x0002, /* The unencoded samples are contiguous RGBA */
T2P_SAMPLE_RGBAA_TO_RGB=0x0004, /* The unencoded samples are RGBA with premultiplied alpha */
+ T2P_SAMPLE_GRAYA_TO_GRAY=0x0200, /* The unencoded samples are contiguous Min-is-* */
+ T2P_SAMPLE_GRAYAA_TO_GRAY=0x0400, /* The unencoded samples are Min-is-* with premultiplied alpha */
T2P_SAMPLE_YCBCR_TO_RGB=0x0008,
T2P_SAMPLE_YCBCR_TO_LAB=0x0010,
T2P_SAMPLE_REALIZE_PALETTE=0x0020, /* The unencoded samples are indexes into the color map */
@@ -274,6 +277,8 @@ tsize_t t2p_sample_realize_palette(T2P*,
tsize_t t2p_sample_abgr_to_rgb(tdata_t, uint32);
tsize_t t2p_sample_rgba_to_rgb(tdata_t, uint32);
tsize_t t2p_sample_rgbaa_to_rgb(tdata_t, uint32);
+tsize_t t2p_sample_graya_to_gray(tdata_t, uint32);
+tsize_t t2p_sample_grayaa_to_gray(tdata_t, uint32);
tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t, uint32);
tsize_t t2p_write_pdf_header(T2P*, TIFF*);
tsize_t t2p_write_pdf_obj_start(uint32, TIFF*);
@@ -1415,6 +1425,32 @@ void t2p_read_tiff_data(T2P* t2p, TIFF*
t2p->pdf_switchdecode
^= 1;
}
}
+ if(t2p->tiff_samplesperpixel == 1){
+ break;
+ }
+ if(t2p->tiff_samplesperpixel > 1) {
+ if(t2p->tiff_samplesperpixel == 2) {
+ if(TIFFGetField(input,
+ TIFFTAG_EXTRASAMPLES,
+ &xuint16, &xuint16p)
+ && xuint16 == 1) {
+ if(xuint16p[0] == EXTRASAMPLE_ASSOCALPHA){
+ t2p->pdf_sample=T2P_SAMPLE_GRAYAA_TO_GRAY;
+ break;
+ }
+ if(xuint16p[0] == EXTRASAMPLE_UNASSALPHA){
+ t2p->pdf_sample=T2P_SAMPLE_GRAYA_TO_GRAY;
+ break;
+ }
+ }
+ }
+ }
+ TIFFError(
+ TIFF2PDF_MODULE,
+ "No support for grayscale image %s with %u samples per pixel",
+ TIFFFileName(input),
+ t2p->tiff_samplesperpixel);
+ t2p->t2p_error = T2P_ERR_ERROR;
break;
case PHOTOMETRIC_RGB:
t2p->pdf_colorspace=T2P_CS_RGB;
@@ -2536,6 +2588,18 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p
t2p->tiff_width*t2p->tiff_length);
}
+ if(t2p->pdf_sample & T2P_SAMPLE_GRAYA_TO_GRAY){
+ t2p->tiff_datasize=t2p_sample_graya_to_gray(
+ (tdata_t)buffer,
+ t2p->tiff_width*t2p->tiff_length);
+ }
+
+ if(t2p->pdf_sample & T2P_SAMPLE_GRAYAA_TO_GRAY){
+ t2p->tiff_datasize=t2p_sample_grayaa_to_gray(
+ (tdata_t)buffer,
+ t2p->tiff_width*t2p->tiff_length);
+ }
+
if(t2p->pdf_sample & T2P_SAMPLE_YCBCR_TO_RGB){
samplebuffer=(unsigned char*)_TIFFrealloc(
(tdata_t)buffer,
@@ -2992,6 +3056,20 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P
*t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
}
+ if(t2p->pdf_sample & T2P_SAMPLE_GRAYA_TO_GRAY){
+ t2p->tiff_datasize=t2p_sample_graya_to_gray(
+ (tdata_t)buffer,
+ t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth
+ *t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
+ }
+
+ if(t2p->pdf_sample & T2P_SAMPLE_GRAYAA_TO_GRAY){
+ t2p->tiff_datasize=t2p_sample_grayaa_to_gray(
+ (tdata_t)buffer,
+ t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth
+ *t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength);
+ }
+
if(t2p->pdf_sample & T2P_SAMPLE_YCBCR_TO_RGB){
TIFFError(TIFF2PDF_MODULE,
"No support for YCbCr to RGB in tile for %s",
@@ -3649,6 +3727,41 @@ t2p_sample_rgba_to_rgb(tdata_t data, uin
}
/*
+ * This functions converts in place a buffer of GRAYA interleaved data
+ * into GRAY interleaved data, discarding A.
+ */
+
+tsize_t
+t2p_sample_grayaa_to_gray(tdata_t data, uint32 samplecount)
+{
+ uint32 i;
+
+ for(i = 0; i < samplecount; i++)
+ ((uint8 *)data)[i] = ((uint8*)data)[i*2];
+
+ return i;
+}
+
+/*
+ * This functions converts in place a buffer of GRAYA interleaved data
+ * into GRAY interleaved data, adding 255-A to each component sample.
+ */
+
+tsize_t
+t2p_sample_graya_to_gray(tdata_t data, uint32 samplecount)
+{
+ uint32 i = 0;
+ uint8 alpha = 0;
+
+ for (i = 0; i < samplecount; i++) {
+ alpha= 255 - (((uint8 *)data)[i*2+1] & 0xff);
+ ((uint8 *)data)[i] = (((uint8 *)data)[i*2] & 0xff) + alpha;
+ }
+
+ return i;
+}
+
+/*
This function converts the a and b samples of Lab data from signed
to unsigned.
*/
Yuriy M. Kaminskiy <yumkam@gmail.com>
Subject: tiff2pdf: fix number of decoded components
/Decode array was incorrect for case when alpha was cropped.
Index: tiff-3.9.4/tools/tiff2pdf.c
===================================================================
--- tiff-3.9.4.orig/tools/tiff2pdf.c 2014-12-27 19:36:10.552594211 +0300
+++ tiff-3.9.4/tools/tiff2pdf.c 2014-12-27 23:40:32.708095195 +0300
@@ -5078,10 +5191,15 @@ tsize_t t2p_write_pdf_xobject_palettecs_ tsize_t t2p_write_pdf_xobject_decode(T2P* t2p, TIFF* output){
tsize_t written=0;
- int i=0;
+ int i=t2p->tiff_samplesperpixel;
+ if ((t2p->pdf_sample & (T2P_SAMPLE_GRAYA_TO_GRAY |
+ T2P_SAMPLE_GRAYAA_TO_GRAY |
+ T2P_SAMPLE_RGBA_TO_RGB |
+ T2P_SAMPLE_RGBAA_TO_RGB)))
+ i--;
written += t2pWriteFile(output, (tdata_t) "/Decode [ ", 10);
- for (i=0;i<t2p->tiff_samplesperpixel;i++){
+ while(i-- > 0){
written += t2pWriteFile(output, (tdata_t) "1 0 ", 4);
}
written += t2pWriteFile(output, (tdata_t) "]\n", 2);
Yuriy M. Kaminskiy <yumkam@gmail.com>
Subject: tiff2pdf: short-circuit unassociated alpha cropping and PLANARCONFIG_SEPARATE decoding
In grayscale case, it is possible to completely avoid decoding and enables use of passthrough compression.
In RGB case, just integrate alpha dropping into separate->contig step
Index: tiff-3.9.4/tools/tiff2pdf.c
===================================================================
--- tiff-4.0.x-20141215.orig/tools/tiff2pdf.c 2014-12-27 19:36:10.552594211 +0300
+++ tiff-4.0.x-20141215/tools/tiff2pdf.c 2014-12-27 23:40:32.708095195 +0300
@@ -153,6 +155,7 @@ typedef struct {
uint16 tiff_fillorder;
uint16 tiff_bitspersample;
uint16 tiff_samplesperpixel;
+ uint16 tiff_strips;
uint16 tiff_planar;
uint32 tiff_width;
uint32 tiff_length;
@@ -1179,7 +1184,7 @@ void t2p_read_tiff_init(T2P* t2p, TIFF*
if( (xuint16== COMPRESSION_DEFLATE ||
xuint16==
COMPRESSION_ADOBE_DEFLATE) &&
((t2p->tiff_pages[i].page_tilecount
!= 0)
- || TIFFNumberOfStrips(input)==1) &&
+ || t2p->tiff_strips==1) &&
(t2p->pdf_nopassthrough==0)
){
if(t2p->pdf_minorversion<2){t2p->pdf_minorversion=2;}
}
@@ -1400,7 +1405,12 @@ void t2p_read_tiff_data(T2P* t2p, TIFF*
return;
}
+ if (TIFFIsTiled(input))
+ t2p->tiff_strips = 1;
+ else
+ t2p->tiff_strips = TIFFNumberOfStrips(input);
+
switch(t2p->tiff_photometric){
case PHOTOMETRIC_MINISWHITE:
case PHOTOMETRIC_MINISBLACK:
@@ -1649,7 +1685,23 @@ void t2p_read_tiff_data(T2P* t2p, TIFF*
case PLANARCONFIG_CONTIG:
break;
case PLANARCONFIG_SEPARATE:
+ if (t2p->tiff_planar == PLANARCONFIG_SEPARATE
+ && (t2p->pdf_sample & (T2P_SAMPLE_RGBA_TO_RGB | T2P_SAMPLE_GRAYA_TO_GRAY))) {
+ /* just crop alpha strip/tile */
+ if (TIFFIsTiled(input))
+ t2p->tiff_pages[t2p->pdf_page].page_tilecount = (t2p->tiff_pages[t2p->pdf_page].page_tilecount/t2p->tiff_samplesperpixel) * (t2p->tiff_samplesperpixel - 1);
+ else
+ t2p->tiff_strips = (t2p->tiff_strips / t2p->tiff_samplesperpixel) * (t2p->tiff_samplesperpixel - 1);
+ t2p->tiff_samplesperpixel--;
+ if ((t2p->pdf_sample & T2P_SAMPLE_GRAYA_TO_GRAY)) {
+ /* skip conversion to GRAY */
+ t2p->tiff_planar = PLANARCONFIG_CONTIG;
+ t2p->pdf_sample &= ~T2P_SAMPLE_GRAYA_TO_GRAY;
+ break;
+ }
+ t2p->pdf_sample &= ~T2P_SAMPLE_RGBA_TO_RGB;
+ }
t2p->pdf_sample |= T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG;
if(t2p->tiff_bitspersample!=8){
TIFFError(
TIFF2PDF_MODULE,
@@ -1705,6 +1757,6 @@ void t2p_read_tiff_data(T2P* t2p, TIFF*
if(t2p->tiff_compression==COMPRESSION_CCITTFAX4
){
- if(TIFFIsTiled(input) || (TIFFNumberOfStrips(input)==1) ){
+ if(/*TIFFIsTiled(input) || */(t2p->tiff_strips==1) ){
t2p->pdf_transcode
= T2P_TRANSCODE_RAW;
t2p->pdf_compression=T2P_COMPRESS_G4;
}
@@ -1713,7 +1765,7 @@ void t2p_read_tiff_data(T2P* t2p, TIFF*
#ifdef ZIP_SUPPORT
if(t2p->tiff_compression== COMPRESSION_ADOBE_DEFLATE
|| t2p->tiff_compression==COMPRESSION_DEFLATE){
- if(TIFFIsTiled(input) || (TIFFNumberOfStrips(input)==1) ){
+ if(/*TIFFIsTiled(input) || */(t2p->tiff_strips==1) ){
t2p->pdf_transcode
= T2P_TRANSCODE_RAW;
t2p->pdf_compression=T2P_COMPRESS_ZIP;
}
@@ -1884,7 +1936,7 @@ void t2p_read_tiff_size(T2P* t2p, TIFF*
t2p->t2p_error
= T2P_ERR_ERROR;
return;
}
- stripcount=TIFFNumberOfStrips(input);
+ stripcount=t2p->tiff_strips;
for(i=0;i<stripcount;i++){
k
= checkAdd64(k, sbc[i], t2p);
}
@@ -1939,7 +1991,7 @@ void t2p_read_tiff_size(T2P* t2p, TIFF*
} else {
k
= 2; /* SOI for first strip */
}
- stripcount=TIFFNumberOfStrips(input);
+ stripcount=t2p->tiff_strips;
if(!TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS,
&sbc)){
TIFFError(TIFF2PDF_MODULE,
"Input
file %s missing field: TIFFTAG_STRIPBYTECOUNTS",
@@ -2258,7 +2310,7 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p
ri*=(rows+v_samp-1)/v_samp;
buffer[bufferoffset++]=
(ri>>8) & 0xff;
buffer[bufferoffset++]= ri & 0xff;
- stripcount=TIFFNumberOfStrips(input);
+ stripcount=t2p->tiff_strips;
for(i=0;i<stripcount;i++){
if(i
!= 0 ){
buffer[bufferoffset++]=0xff;
@@ -2294,7 +2346,7 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p
memset(buffer,
0, t2p->tiff_datasize);
_TIFFmemcpy(buffer,
t2p->pdf_ojpegdata, t2p->pdf_ojpegdatalength);
bufferoffset=t2p->pdf_ojpegdatalength;
- stripcount=TIFFNumberOfStrips(input);
+ stripcount=t2p->tiff_strips;
for(i=0;i<stripcount;i++){
if(i
!= 0){
buffer[bufferoffset++]=0xff;
@@ -2341,7 +2393,7 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p
bufferoffset
+= count - 2;
}
}
- stripcount=TIFFNumberOfStrips(input);
+ stripcount=t2p->tiff_strips;
TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS,
&sbc);
for(i=0;i<stripcount;i++){
if(sbc[i]>max_striplength)
max_striplength=sbc[i];
@@ -2398,7 +2450,7 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p
}
memset(buffer, 0, t2p->tiff_datasize);
stripsize=TIFFStripSize(input);
- stripcount=TIFFNumberOfStrips(input);
+ stripcount=t2p->tiff_strips;
for(i=0;i<stripcount;i++){
read =
TIFFReadEncodedStrip(input,
@@ -2420,7 +2472,7 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p
if(t2p->pdf_sample & T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG){
sepstripsize=TIFFStripSize(input);
- sepstripcount=TIFFNumberOfStrips(input);
+ sepstripcount=t2p->tiff_strips;
stripsize=sepstripsize*t2p->tiff_samplesperpixel;
stripcount=sepstripcount/t2p->tiff_samplesperpixel;
@@ -2485,7 +2537,7 @@ tsize_t t2p_readwrite_pdf_image(T2P* t2p
}
memset(buffer, 0, t2p->tiff_datasize);
stripsize=TIFFStripSize(input);
- stripcount=TIFFNumberOfStrips(input);
+ stripcount=t2p->tiff_strips;
for(i=0;i<stripcount;i++){
read =
TIFFReadEncodedStrip(input,
@@ -2898,7 +2962,7 @@ tsize_t t2p_readwrite_pdf_image_tile(T2P
if(t2p->pdf_sample & T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG){
septilesize=TIFFTileSize(input);
- septilecount=TIFFNumberOfTiles(input);
+ septilecount=t2p->tiff_pages[t2p->pdf_page].page_tilecount;
/* tilesize=septilesize*t2p->tiff_samplesperpixel; */
tilecount=septilecount/t2p->tiff_samplesperpixel;
buffer = (unsigned char*)
_TIFFmalloc(t2p->tiff_datasize);
@@ -3342,7 +3420,7 @@ int t2p_process_ojpeg_tables(T2P* t2p, T
t2p->pdf_ojpegdatalength+=code_count;
}
}
- if(TIFFNumberOfStrips(input)>1){
+ if(t2p->tiff_strips>1){
ojpegdata[t2p->pdf_ojpegdatalength++]=0xff;
ojpegdata[t2p->pdf_ojpegdatalength++]=0xdd;
ojpegdata[t2p->pdf_ojpegdatalength++]=0x00;
Yuriy M. Kaminskiy <yumkam@gmail.com>
Subject: tiff2pdf: move/simplify pdf_switchdecode toggle
Index: tiff-3.9.4/tools/tiff2pdf.c
===================================================================
--- tiff-3.9.4.orig/tools/tiff2pdf.c 2014-12-28 00:58:45.560598630 +0300
+++ tiff-3.9.4/tools/tiff2pdf.c 2014-12-28 01:01:33.744598722 +0300
@@ -1413,17 +1413,13 @@ void t2p_read_tiff_data(T2P* t2p, TIFF*
switch(t2p->tiff_photometric){
case PHOTOMETRIC_MINISWHITE:
+ t2p->pdf_switchdecode ^= 1;
+ /* fallthrough */
case PHOTOMETRIC_MINISBLACK:
if (t2p->tiff_bitspersample==1){
t2p->pdf_colorspace=T2P_CS_BILEVEL;
- if(t2p->tiff_photometric==PHOTOMETRIC_MINISWHITE){
- t2p->pdf_switchdecode ^= 1;
- }
} else {
t2p->pdf_colorspace=T2P_CS_GRAY;
- if(t2p->tiff_photometric==PHOTOMETRIC_MINISWHITE){
- t2p->pdf_switchdecode ^= 1;
- }
}
if(t2p->tiff_samplesperpixel == 1){
break;