Bug 454116 - Enable legacy JPEG compression for libtiff
Summary: Enable legacy JPEG compression for libtiff
Status: RESOLVED FIXED
Alias: None
Product: krita
Classification: Applications
Component: File formats (show other bugs)
Version: 5.0.6
Platform: Compiled Sources Microsoft Windows
: NOR normal
Target Milestone: ---
Assignee: amyspark
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-05-20 21:43 UTC by amyspark
Modified: 2022-06-28 17:31 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description amyspark 2022-05-20 21:43:15 UTC
SUMMARY
***
NOTE: If you are reporting a crash, please try to attach a backtrace with debug symbols.
See https://community.kde.org/Guidelines_and_HOWTOs/Debugging/How_to_create_useful_crash_reports
***

Alvin found that quad-jpeg.tif was never tested as part of the standard tiff test suite. This is probably because it's a legacy YCbCr, JPEG-compressed file.

Opening it manually in Krita reveals significant corruption, probably because of the obviously mismatched codecs.

STEPS TO REPRODUCE
1. 
2. 
3. 

OBSERVED RESULT


EXPECTED RESULT


SOFTWARE/OS VERSIONS
Windows: 
macOS: 
Linux/KDE Plasma: 
(available in About System)
KDE Plasma Version: 
KDE Frameworks Version: 
Qt Version: 

ADDITIONAL INFORMATION
Comment 1 amyspark 2022-06-28 17:05:02 UTC
Git commit dd4d2b4b793a42b2c7406dfc63fc108ea8905ec5 by L. E. Segovia.
Committed on 28/06/2022 at 16:01.
Pushed by lsegovia into branch 'master'.

tiff: support YCbCr + JPEG imports

This commit enables reading JPEG-compressed TIFFs that use the YCbCr
colour space. This is not possible to do with the standard libtiff API
because of Very Bad Decisions :tm: that were taken in the past, both
during the 6.0 standardization [1] and its implementation [2].

To do so, I've implemented a custom made strip decoder that, when the
combination of COMPRESSION_JPEG and PHOTOMETRIC_YCBCR is detected,
redirects to a (also custom made) buffer stream that performs automatic
interleaving and upsampling of the image planes. This data is shaped
into the form specified in the TIFF 6.0 Specification [3], then fed
to the existing YCbCr readers. The planes are decoded using
libjpeg-turbo (to avoid the mindbending API of libjpeg) into three
separate planes without upsampling.

There's a catch, however. Unlike libjpeg-turbo, libjpeg provides a
direct API to prime the decoder with the coefficient tables that are
provided in TIFFTAG_JPEGTABLES, and which libtiff uses as part of
TIFFjpeg_read_header. To remediate this, I've patched libtiff-turbo to
add a tjReadCoefficientTables API, that takes a reference to the tables
and forwards it to the decoder.

CCMAIL: kimageshop@kde.org

[1]: DRAFT TIFF Technical Note #2, 17-Mar-95.
<http://libtiff.maptools.org/TIFFTechNote2.html>

[2]: 2022.06.11 07:23 "Re: [Tiff] How to read JPEG-compressed YCbCr
TIFFs", by Joris Van Damme. <https://www.asmail.be/msg0054881320.html>

[3]: "Ordering of Component Samples". In: TIFF Revision 6.0 Final. June
3, 1992: Adobe Developers Association, pp. 93-94.

M  +4    -4    3rdparty/ext_jpeg/CMakeLists.txt
M  +14   -0    CMakeLists.txt
A  +4    -0    config-jpeg.h.cmake
M  +1    -1    plugins/impex/tiff/CMakeLists.txt
M  +138  -2    plugins/impex/tiff/kis_buffer_stream.cc
M  +57   -1    plugins/impex/tiff/kis_buffer_stream.h
M  +177  -6    plugins/impex/tiff/kis_tiff_import.cc
M  +1    -0    plugins/impex/tiff/kis_tiff_import.h
D  +-    --    plugins/impex/tiff/tests/data/quad-jpeg.tif.png
A  +-    --    plugins/impex/tiff/tests/data/results/quad-jpeg.tif.png
R  +-    --    plugins/impex/tiff/tests/data/sources/quad-jpeg.tif [from: plugins/impex/tiff/tests/data/quad-jpeg.tif - 100% similarity]

https://invent.kde.org/graphics/krita/commit/dd4d2b4b793a42b2c7406dfc63fc108ea8905ec5
Comment 2 amyspark 2022-06-28 17:31:09 UTC
Git commit ef9493c8b2df0f74e70e72e4c76981a9bfe10b2e by L. E. Segovia.
Committed on 28/06/2022 at 17:29.
Pushed by lsegovia into branch 'krita/5.1'.

tiff: support YCbCr + JPEG imports

This commit enables reading JPEG-compressed TIFFs that use the YCbCr
colour space. This is not possible to do with the standard libtiff API
because of Very Bad Decisions :tm: that were taken in the past, both
during the 6.0 standardization [1] and its implementation [2].

To do so, I've implemented a custom made strip decoder that, when the
combination of COMPRESSION_JPEG and PHOTOMETRIC_YCBCR is detected,
redirects to a (also custom made) buffer stream that performs automatic
interleaving and upsampling of the image planes. This data is shaped
into the form specified in the TIFF 6.0 Specification [3], then fed
to the existing YCbCr readers. The planes are decoded using
libjpeg-turbo (to avoid the mindbending API of libjpeg) into three
separate planes without upsampling.

There's a catch, however. Unlike libjpeg-turbo, libjpeg provides a
direct API to prime the decoder with the coefficient tables that are
provided in TIFFTAG_JPEGTABLES, and which libtiff uses as part of
TIFFjpeg_read_header. To remediate this, I've patched libtiff-turbo to
add a tjReadCoefficientTables API, that takes a reference to the tables
and forwards it to the decoder.

CCMAIL: kimageshop@kde.org

[1]: DRAFT TIFF Technical Note #2, 17-Mar-95.
<http://libtiff.maptools.org/TIFFTechNote2.html>

[2]: 2022.06.11 07:23 "Re: [Tiff] How to read JPEG-compressed YCbCr
TIFFs", by Joris Van Damme. <https://www.asmail.be/msg0054881320.html>

[3]: "Ordering of Component Samples". In: TIFF Revision 6.0 Final. June
3, 1992: Adobe Developers Association, pp. 93-94.

(cherry picked from commit dd4d2b4b793a42b2c7406dfc63fc108ea8905ec5)

M  +4    -4    3rdparty/ext_jpeg/CMakeLists.txt
M  +14   -0    CMakeLists.txt
A  +4    -0    config-jpeg.h.cmake
M  +1    -1    plugins/impex/tiff/CMakeLists.txt
M  +138  -2    plugins/impex/tiff/kis_buffer_stream.cc
M  +57   -1    plugins/impex/tiff/kis_buffer_stream.h
M  +177  -6    plugins/impex/tiff/kis_tiff_import.cc
M  +1    -0    plugins/impex/tiff/kis_tiff_import.h
D  +-    --    plugins/impex/tiff/tests/data/quad-jpeg.tif.png
A  +-    --    plugins/impex/tiff/tests/data/results/quad-jpeg.tif.png
R  +-    --    plugins/impex/tiff/tests/data/sources/quad-jpeg.tif [from: plugins/impex/tiff/tests/data/quad-jpeg.tif - 100% similarity]

https://invent.kde.org/graphics/krita/commit/ef9493c8b2df0f74e70e72e4c76981a9bfe10b2e