https://github.com/libsdl-org/libtiff/commit/f9e12f146a80babab2d1cfab50fa14acf765ef2a
From b0456acbba36927eeb2f937f4abed66deab4a029 Mon Sep 17 00:00:00 2001
From: Even Rouault <[EMAIL REDACTED]>
Date: Wed, 9 Feb 2022 21:53:39 +0100
Subject: [PATCH] Predictor 2 (horizontal differenciation): support 64-bit
There's no reason not to support 64-bit. The TIFF 6 specification
doesn't say anything about that (and even mention 4-bit, which we don't
support)
---
libtiff/tif_predict.c | 90 +++++++++++++++++-
test/CMakeLists.txt | 2 +
test/Makefile.am | 2 +
.../images/test_float64_predictor2_be_lzw.tif | Bin 0 -> 872 bytes
.../images/test_float64_predictor2_le_lzw.tif | Bin 0 -> 887 bytes
5 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 test/images/test_float64_predictor2_be_lzw.tif
create mode 100644 test/images/test_float64_predictor2_le_lzw.tif
diff --git a/libtiff/tif_predict.c b/libtiff/tif_predict.c
index 4aa4af69..ffe7133c 100644
--- a/libtiff/tif_predict.c
+++ b/libtiff/tif_predict.c
@@ -35,13 +35,17 @@
static int horAcc8(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int horAcc16(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int horAcc32(TIFF* tif, uint8_t* cp0, tmsize_t cc);
+static int horAcc64(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int swabHorAcc16(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int swabHorAcc32(TIFF* tif, uint8_t* cp0, tmsize_t cc);
+static int swabHorAcc64(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int horDiff8(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int horDiff16(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int horDiff32(TIFF* tif, uint8_t* cp0, tmsize_t cc);
+static int horDiff64(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int swabHorDiff16(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int swabHorDiff32(TIFF* tif, uint8_t* cp0, tmsize_t cc);
+static int swabHorDiff64(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int fpAcc(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int fpDiff(TIFF* tif, uint8_t* cp0, tmsize_t cc);
static int PredictorDecodeRow(TIFF* tif, uint8_t* op0, tmsize_t occ0, uint16_t s);
@@ -64,7 +68,8 @@ PredictorSetup(TIFF* tif)
case PREDICTOR_HORIZONTAL:
if (td->td_bitspersample != 8
&& td->td_bitspersample != 16
- && td->td_bitspersample != 32) {
+ && td->td_bitspersample != 32
+ && td->td_bitspersample != 64) {
TIFFErrorExt(tif->tif_clientdata, module,
"Horizontal differencing \"Predictor\" not supported with %"PRIu16"-bit samples",
td->td_bitspersample);
@@ -126,6 +131,7 @@ PredictorSetupDecode(TIFF* tif)
case 8: sp->decodepfunc = horAcc8; break;
case 16: sp->decodepfunc = horAcc16; break;
case 32: sp->decodepfunc = horAcc32; break;
+ case 64: sp->decodepfunc = horAcc64; break;
}
/*
* Override default decoding method with one that does the
@@ -155,6 +161,9 @@ PredictorSetupDecode(TIFF* tif)
} else if (sp->decodepfunc == horAcc32) {
sp->decodepfunc = swabHorAcc32;
tif->tif_postdecode = _TIFFNoPostDecode;
+ } else if (sp->decodepfunc == horAcc64) {
+ sp->decodepfunc = swabHorAcc64;
+ tif->tif_postdecode = _TIFFNoPostDecode;
}
}
}
@@ -205,6 +214,7 @@ PredictorSetupEncode(TIFF* tif)
case 8: sp->encodepfunc = horDiff8; break;
case 16: sp->encodepfunc = horDiff16; break;
case 32: sp->encodepfunc = horDiff32; break;
+ case 64: sp->encodepfunc = horDiff64; break;
}
/*
* Override default encoding method with one that does the
@@ -234,6 +244,9 @@ PredictorSetupEncode(TIFF* tif)
} else if (sp->encodepfunc == horDiff32) {
sp->encodepfunc = swabHorDiff32;
tif->tif_postdecode = _TIFFNoPostDecode;
+ } else if (sp->encodepfunc == horDiff64) {
+ sp->encodepfunc = swabHorDiff64;
+ tif->tif_postdecode = _TIFFNoPostDecode;
}
}
}
@@ -403,6 +416,41 @@ horAcc32(TIFF* tif, uint8_t* cp0, tmsize_t cc)
return 1;
}
+static int
+swabHorAcc64(TIFF* tif, uint8_t* cp0, tmsize_t cc)
+{
+ uint64_t* wp = (uint64_t*) cp0;
+ tmsize_t wc = cc / 8;
+
+ TIFFSwabArrayOfLong8(wp, wc);
+ return horAcc64(tif, cp0, cc);
+}
+
+TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
+static int
+horAcc64(TIFF* tif, uint8_t* cp0, tmsize_t cc)
+{
+ tmsize_t stride = PredictorState(tif)->stride;
+ uint64_t* wp = (uint64_t*) cp0;
+ tmsize_t wc = cc / 8;
+
+ if ((cc % (8 * stride)) != 0)
+ {
+ TIFFErrorExt(tif->tif_clientdata, "horAcc64",
+ "%s", "cc%(8*stride))!=0");
+ return 0;
+ }
+
+ if (wc > stride) {
+ wc -= stride;
+ do {
+ REPEAT4(stride, wp[stride] += wp[0]; wp++)
+ wc -= stride;
+ } while (wc > 0);
+ }
+ return 1;
+}
+
/*
* Floating point predictor accumulation routine.
*/
@@ -638,6 +686,46 @@ swabHorDiff32(TIFF* tif, uint8_t* cp0, tmsize_t cc)
return 1;
}
+TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
+static int
+horDiff64(TIFF* tif, uint8_t* cp0, tmsize_t cc)
+{
+ TIFFPredictorState* sp = PredictorState(tif);
+ tmsize_t stride = sp->stride;
+ uint64_t *wp = (uint64_t*) cp0;
+ tmsize_t wc = cc/8;
+
+ if ((cc % (8 * stride)) != 0)
+ {
+ TIFFErrorExt(tif->tif_clientdata, "horDiff64",
+ "%s", "(cc%(8*stride))!=0");
+ return 0;
+ }
+
+ if (wc > stride) {
+ wc -= stride;
+ wp += wc - 1;
+ do {
+ REPEAT4(stride, wp[stride] -= wp[0]; wp--)
+ wc -= stride;
+ } while (wc > 0);
+ }
+ return 1;
+}
+
+static int
+swabHorDiff64(TIFF* tif, uint8_t* cp0, tmsize_t cc)
+{
+ uint64_t* wp = (uint64_t*) cp0;
+ tmsize_t wc = cc / 8;
+
+ if (!horDiff64(tif, cp0, cc))
+ return 0;
+
+ TIFFSwabArrayOfLong8(wp, wc);
+ return 1;
+}
+
/*
* Floating point predictor differencing routine.
*/
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3336b58c..1bdb283e 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -356,6 +356,8 @@ add_convert_test_multi(tiffcp thumbnail "" thumbnail "-c g3:1d" "" ""
"images/miniswhite-1c-1b.tiff" FALSE)
add_convert_test(tiffcp none "-c none" "images/quad-lzw-compat.tiff" FALSE)
add_convert_test(tiffcp noner1 "-c none -r 1" "images/lzw-single-strip.tiff" FALSE)
+add_convert_test(tiffcp float64_lzw_2_le "-c lzw:2 "images/test_float64_predictor2_le_lzw.tif" FALSE)
+add_convert_test(tiffcp float64_lzw_2_be "-c lzw:2 "images/test_float64_predictor2_be_lzw.tif" FALSE)
# tiffdump
add_reader_test(tiffdump "" "images/miniswhite-1c-1b.tiff")
diff --git a/test/Makefile.am b/test/Makefile.am
index cb338884..6c1bae62 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -199,6 +199,8 @@ PNMIMAGES = \
IMAGES_EXTRA_DIST = \
images/README.txt \
images/miniswhite-1c-1b.g3 \
+ images/test_float64_predictor2_le_lzw.tif \
+ images/test_float64_predictor2_be_lzw.tif \
$(PNMIMAGES) \
$(TIFFIMAGES)
diff --git a/test/images/test_float64_predictor2_be_lzw.tif b/test/images/test_float64_predictor2_be_lzw.tif
new file mode 100644
index 0000000000000000000000000000000000000000..7cbbae148974575b57d7055789ee62c01f585fcb
GIT binary patch
literal 872
zcmebEWzb?^VBlcjVPs%n2C^6#M1TY%5}OIib^wYqL)olAHXD=;)W|5vzyj9Gz%Y+d
z6iHkR$_AM!4pYN)ictnhjV+YT1XL3YWrJJ-1Pub*J`5~kJS@#l4hA0He}6c%9CRo+
z(G$YJ*tP%u$BZYD|9*A2IBfLLsdMI>csy|v#~LN2|Mjj7mmFBKv>fz&83ZkBHYw|M
zoL4QXFpxc{U&Eog+5PvkPSyop%hs>hAUEUR@}ti~HL@RV;+o~B9-<MFX0E>`O6h=C
zs+G3!^nI_*Jav~z{pt3~p782SRkA3fTmFYhjGc^GTjC1>vzL@5`p<CPVA0X%_kPlz
z%i1@%V~w7Q9-F`;QN@$`Tdc?X&G#L(MWNGL9_LRC(3K1K>Nxa#$J(WR#`6zJUXk>g
zVx4<*zL(~#JNv%HpSkgV>HDY?(&7u&9&NN_@40jFaNEnDe=7CXcR!o-?2&1XzYxFA
zm*l+x^Ha>;a?NEd7s$$g_iFZrb5+llS!x)4`Devpz_Lt!P1A>S)&jzJnznK3$aU;G
z`AUavPv^=f|D8H_>{-3BFKRQ_g0+|4Gj2Uo9kW)G>(pXyHD4EBu?-mp4F+5KG~cah
z<VvZVwwbTm=<Xr@EnTOMozI>%|KzI2u5w4;Z&p~Pw0`xE-^V7Mno;c*6eY~MbR+X`
zWsga#jJb~o%3L*Z7D%pCbzOd{gh~6u%YRizgsc9nTJ@%-sHuZl`yh*dFw=eUg{Py8
zbv!#(NZJNuuKB65W6Nr#t`nM7cRCt_FMj9SuxU}Y*Wyl-OH)s6oRw{+vF1v{d2It5
zUF{1(#fz@0eSB*3YGwPX>%zNUWPY2=;J3Eh-o>ywm1)7&P1&xt*&HXGmn?r{)xG^g
z=}g1TD{I;{{J5S3FvPr_A~fsVm8UGTcLdD*A9(Y!(PWN=%QveUT)yV=yuc}eWy_Zv
zeI-i_ubjMdrZzf3<xI`_jln;DF8D0uRk_?Dbg%0MF=wBxXO2JJ)*n-Nm8WZW#_FK9
z`6fP`3927*Kk7aa%-tH7F0}P@*Ym8VJmYAdGS@k4w*69Vzg_4Wvf$}2llx1<#Il4M
F8UWR}Up4>$
literal 0
HcmV?d00001
diff --git a/test/images/test_float64_predictor2_le_lzw.tif b/test/images/test_float64_predictor2_le_lzw.tif
new file mode 100644
index 0000000000000000000000000000000000000000..3dd57a5491ea51187543f801ecdff16b1c36b98c
GIT binary patch
literal 887
zcmebD)MDUZU|`^3U|?isU<9&6fS3`9%>-pT0L7W1Y*rwf4ax@T5oBZm>zxN=iz11O
zLD?WP#i43$GBGg7AgQs1vVp=3!B93ckPQM23<?2ij2Vs0jg5)|4m>&x4t4eqa~Nc-
zbeY-?&;O{gr;N>^)?FcoLC4BbsmU|>;!hqcQNDUFpm$87%!TzF9}0S!Y!la?do;1A
zBD#T}Pry#ihl{25vk^mZYVk{1xpu?OW2uFgShdu++6~kVtwi*;a?C!&A=(kU$vvq3
z@}uG?>37pp`)@BOl$f(>yTA(9_W=qb(QFNdehVe6<Jfu2*B;oonX64)lkc?C`w4r_
z^!=4zpRQxh#Cq!_pM!*9fb|jH-vOHsyfxax=4L&&DLe7!4(VolCV^1J$#+V>>F&C8
zW(r$v3^%)YLB8@8&wKyN177<4x*f$Y=ks+%tnN;pP6lDIich^V7ufc7-(<*nTCY*p
zwp#7^gO`)@bXUJ=(mEad<wgS|^BMs?e<`semg^q5J+bh+<nv|*?;*MG#y+bKJ+b4f
z(P6OT7ZT){!;m$h(%ECio^SR6PlDzim{44F+bHX1qs0CfLJtLOw0V+#7<f)(FxcC%
zp`m(Zf|IX`>WMA(T-F60jQoc$mDK#P=4yH<z3r?|x0L0F&PImyMyJ$`jNG?u)mAFl
z;IP9{*r@Kd@`fehR!SF^xSVw6x;?L3Lcq&zhYUB9n1GG&;hev|9Mzwm@~q2VG?PO(
zNY-}o`Id4`r{fF~$1i;Gc6D9Fe`U(T3m&3e?J~SZf^0^w|19<0zrv-QD{$4DNs~j*
zd{JBB6M81<pJS0~z|zYMtgen{Cj^zpZ3_51+5X&wzl<E3d3SZ@UR=s>($jy1Omc=o
z5bLUoCyS$Gi;cx{<l`5WddUahJRv<@Of57w>w&qK_lefq8Gr0`?>VuqEmtT>@|8K2
z&Aq030<-ii0dsd2W%HHdQ+6zTIPs27f?UZ`UY<*@dF=V`80d1A=>{bU1O#bGpKEt$
zXESZs6fA0>kgEAKsqryS=fNraw3=T^Efl%(xis~$$-eI|&bEp=KiWP`YT=o%W6RgR
K`l;;F&;S4%t}{9S
literal 0
HcmV?d00001