From 15df8261bec5c0a8657d920d532edbccd1e8fc57 Mon Sep 17 00:00:00 2001 From: Mark Reid Date: Sat, 1 Oct 2022 16:05:12 -0700 Subject: [PATCH] avcodec/tiff: add read support for compressed rgb floating point formats floating point uses a slightly different predictor technique describe here http://chriscox.org/TIFFTN3d1.pdf Signed-off-by: Anton Khirnov --- libavcodec/tiff.c | 68 ++++++++++++++++++++++ tests/fate/image.mak | 20 ++++++- tests/ref/fate/tiff-lzw-rgbaf32le | 6 ++ tests/ref/fate/tiff-lzw-rgbf32le | 6 ++ tests/ref/fate/tiff-uncompressed-rgbaf32le | 6 ++ tests/ref/fate/tiff-uncompressed-rgbf32le | 6 ++ tests/ref/fate/tiff-zip-rgbaf32le | 6 ++ tests/ref/fate/tiff-zip-rgbf32le | 6 ++ 8 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 tests/ref/fate/tiff-lzw-rgbaf32le create mode 100644 tests/ref/fate/tiff-lzw-rgbf32le create mode 100644 tests/ref/fate/tiff-uncompressed-rgbaf32le create mode 100644 tests/ref/fate/tiff-uncompressed-rgbf32le create mode 100644 tests/ref/fate/tiff-zip-rgbaf32le create mode 100644 tests/ref/fate/tiff-zip-rgbf32le diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index fd9db18c0b..5b56892071 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -2244,6 +2244,74 @@ again: } } + /* Floating point predictor + TIFF Technical Note 3 http://chriscox.org/TIFFTN3d1.pdf */ + if (s->predictor == 3) { + int channels = s->bppcount; + int group_size; + uint8_t *tmpbuf; + int bpc; + + dst = five_planes ? five_planes : p->data[plane]; + soff = s->bpp >> 3; + if (s->planar) { + soff = FFMAX(soff / s->bppcount, 1); + channels = 1; + } + ssize = s->width * soff; + bpc = FFMAX(soff / s->bppcount, 1); /* Bytes per component */ + group_size = s->width * channels; + + tmpbuf = av_malloc(ssize); + if (!tmpbuf) + return AVERROR(ENOMEM); + + if (s->avctx->pix_fmt == AV_PIX_FMT_RGBF32LE || + s->avctx->pix_fmt == AV_PIX_FMT_RGBAF32LE) { + for (i = 0; i < decoded_height; i++) { + /* Copy first sample byte for each channel */ + for (j = 0; j < channels; j++) + tmpbuf[j] = dst[j]; + + /* Decode horizontal differences */ + for (j = channels; j < ssize; j++) + tmpbuf[j] = dst[j] + tmpbuf[j-channels]; + + /* Combine shuffled bytes from their separate groups. Each + byte of every floating point value in a row of pixels is + split and combined into separate groups. A group of all + the sign/exponents bytes in the row and groups for each + of the upper, mid, and lower mantissa bytes in the row. */ + for (j = 0; j < group_size; j++) { + for (int k = 0; k < bpc; k++) { + dst[bpc * j + k] = tmpbuf[(bpc - k - 1) * group_size + j]; + } + } + dst += stride; + } + } else if (s->avctx->pix_fmt == AV_PIX_FMT_RGBF32BE || + s->avctx->pix_fmt == AV_PIX_FMT_RGBAF32BE) { + /* Same as LE only the shuffle at the end is reversed */ + for (i = 0; i < decoded_height; i++) { + for (j = 0; j < channels; j++) + tmpbuf[j] = dst[j]; + + for (j = channels; j < ssize; j++) + tmpbuf[j] = dst[j] + tmpbuf[j-channels]; + + for (j = 0; j < group_size; j++) { + for (int k = 0; k < bpc; k++) { + dst[bpc * j + k] = tmpbuf[k * group_size + j]; + } + } + dst += stride; + } + } else { + av_log(s->avctx, AV_LOG_ERROR, "unsupported floating point pixel format\n"); + } + av_free(tmpbuf); + } + if (s->photometric == TIFF_PHOTOMETRIC_WHITE_IS_ZERO) { int c = (s->avctx->pix_fmt == AV_PIX_FMT_PAL8 ? (1<bpp) - 1 : 255); dst = p->data[plane]; diff --git a/tests/fate/image.mak b/tests/fate/image.mak index 03e794dc48..167c8ccf2c 100644 --- a/tests/fate/image.mak +++ b/tests/fate/image.mak @@ -501,7 +501,25 @@ fate-tiff-fax-g3: CMD = framecrc -i $(TARGET_SAMPLES)/CCITT_fax/G31D.TIF FATE_TIFF += fate-tiff-fax-g3s fate-tiff-fax-g3s: CMD = framecrc -i $(TARGET_SAMPLES)/CCITT_fax/G31DS.TIF -FATE_TIFF-$(call DEMDEC, IMAGE2, TIFF) += $(FATE_TIFF) +FATE_TIFF += fate-tiff-uncompressed-rgbf32le +fate-tiff-uncompressed-rgbf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/uncompressed_rgbf32le.tif + +FATE_TIFF += fate-tiff-uncompressed-rgbaf32le +fate-tiff-uncompressed-rgbaf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/uncompressed_rgbaf32le.tif + +FATE_TIFF += fate-tiff-lzw-rgbf32le +fate-tiff-lzw-rgbf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/lzw_rgbf32le.tif + +FATE_TIFF += fate-tiff-lzw-rgbaf32le +fate-tiff-lzw-rgbaf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/lzw_rgbaf32le.tif + +FATE_TIFF += fate-tiff-zip-rgbf32le +fate-tiff-zip-rgbf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/zip_rgbf32le.tif + +FATE_TIFF += fate-tiff-zip-rgbaf32le +fate-tiff-zip-rgbaf32le: CMD = framecrc -i $(TARGET_SAMPLES)/tiff/zip_rgbaf32le.tif + +FATE_TIFF-$(call FRAMECRC, IMAGE2, TIFF) += $(FATE_TIFF) FATE_IMAGE_FRAMECRC += $(FATE_TIFF-yes) fate-tiff: $(FATE_TIFF-yes) diff --git a/tests/ref/fate/tiff-lzw-rgbaf32le b/tests/ref/fate/tiff-lzw-rgbaf32le new file mode 100644 index 0000000000..c99aa02ef0 --- /dev/null +++ b/tests/ref/fate/tiff-lzw-rgbaf32le @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 8x8 +#sar 0: 0/1 +0, 0, 0, 1, 1024, 0x877e1d5f diff --git a/tests/ref/fate/tiff-lzw-rgbf32le b/tests/ref/fate/tiff-lzw-rgbf32le new file mode 100644 index 0000000000..a6d3fabfda --- /dev/null +++ b/tests/ref/fate/tiff-lzw-rgbf32le @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 8x8 +#sar 0: 0/1 +0, 0, 0, 1, 768, 0xad26ed90 diff --git a/tests/ref/fate/tiff-uncompressed-rgbaf32le b/tests/ref/fate/tiff-uncompressed-rgbaf32le new file mode 100644 index 0000000000..c99aa02ef0 --- /dev/null +++ b/tests/ref/fate/tiff-uncompressed-rgbaf32le @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 8x8 +#sar 0: 0/1 +0, 0, 0, 1, 1024, 0x877e1d5f diff --git a/tests/ref/fate/tiff-uncompressed-rgbf32le b/tests/ref/fate/tiff-uncompressed-rgbf32le new file mode 100644 index 0000000000..a6d3fabfda --- /dev/null +++ b/tests/ref/fate/tiff-uncompressed-rgbf32le @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 8x8 +#sar 0: 0/1 +0, 0, 0, 1, 768, 0xad26ed90 diff --git a/tests/ref/fate/tiff-zip-rgbaf32le b/tests/ref/fate/tiff-zip-rgbaf32le new file mode 100644 index 0000000000..c99aa02ef0 --- /dev/null +++ b/tests/ref/fate/tiff-zip-rgbaf32le @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 8x8 +#sar 0: 0/1 +0, 0, 0, 1, 1024, 0x877e1d5f diff --git a/tests/ref/fate/tiff-zip-rgbf32le b/tests/ref/fate/tiff-zip-rgbf32le new file mode 100644 index 0000000000..a6d3fabfda --- /dev/null +++ b/tests/ref/fate/tiff-zip-rgbf32le @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 8x8 +#sar 0: 0/1 +0, 0, 0, 1, 768, 0xad26ed90