diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2020-12-29 22:32:01 +0900 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2021-01-06 08:49:53 +0100 |
commit | 94d34e53ac9eb41cba96a56bf715d4b02794a12a (patch) | |
tree | a1f48affddb58477a200a08bc0e7e631ca36cbf7 /filter | |
parent | f1a6d0602e22708c4ec3a2365a154d90255ca2af (diff) |
Move TIFF reader and writer from filter module into VCL
Moving graphicfilter one by one into VCL to get rid of filter_gio
module and all the nonsense of dynamic/static library loading in
"GraphicFilter".
Change-Id: I21ebc0334ee07d36553a88557d33e01d9caec9ee
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/108822
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'filter')
53 files changed, 2 insertions, 4021 deletions
diff --git a/filter/CppunitTest_filter_tiff_test.mk b/filter/CppunitTest_filter_tiff_test.mk deleted file mode 100644 index 23a7bbf9ccac..000000000000 --- a/filter/CppunitTest_filter_tiff_test.mk +++ /dev/null @@ -1,38 +0,0 @@ -# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- -# -# This file is part of the LibreOffice project. -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -# - -$(eval $(call gb_CppunitTest_CppunitTest,filter_tiff_test)) - -$(eval $(call gb_CppunitTest_use_external,filter_tiff_test,boost_headers)) - -$(eval $(call gb_CppunitTest_add_exception_objects,filter_tiff_test, \ - filter/qa/cppunit/filters-tiff-test \ -)) - -$(eval $(call gb_CppunitTest_use_libraries,filter_tiff_test, \ - gie \ - sal \ - test \ - tl \ - unotest \ - vcl \ -)) - -$(eval $(call gb_CppunitTest_use_sdk_api,filter_tiff_test)) - -$(eval $(call gb_CppunitTest_use_ure,filter_tiff_test)) -$(eval $(call gb_CppunitTest_use_vcl,filter_tiff_test)) - -$(eval $(call gb_CppunitTest_use_components,filter_tiff_test,\ - configmgr/source/configmgr \ -)) - -$(eval $(call gb_CppunitTest_use_configuration,filter_tiff_test)) - -# vim: set noet sw=4 ts=4: diff --git a/filter/Library_gie.mk b/filter/Library_gie.mk index 2dcab32717b6..8c0cbd46b9b9 100644 --- a/filter/Library_gie.mk +++ b/filter/Library_gie.mk @@ -50,12 +50,8 @@ $(eval $(call gb_Library_use_libraries,gie,\ $(eval $(call gb_Library_add_exception_objects,gie,\ filter/source/graphicfilter/egif/egif \ - filter/source/graphicfilter/etiff/etiff \ filter/source/graphicfilter/eps/eps \ filter/source/graphicfilter/egif/giflzwc \ - filter/source/graphicfilter/itiff/ccidecom \ - filter/source/graphicfilter/itiff/itiff \ - filter/source/graphicfilter/itiff/lzwdecom \ filter/source/graphicfilter/ipict/ipict \ filter/source/graphicfilter/ipict/shape \ filter/source/graphicfilter/ipcx/ipcx \ diff --git a/filter/Module_filter.mk b/filter/Module_filter.mk index 6ac173e45859..898ac710db8a 100644 --- a/filter/Module_filter.mk +++ b/filter/Module_filter.mk @@ -64,7 +64,6 @@ $(eval $(call gb_Module_add_check_targets,filter,\ CppunitTest_filter_ppm_test \ CppunitTest_filter_psd_test \ CppunitTest_filter_ras_test \ - CppunitTest_filter_tiff_test \ CppunitTest_filter_tga_test \ CppunitTest_filter_svg \ )) diff --git a/filter/qa/cppunit/data/tiff/fail/.gitignore b/filter/qa/cppunit/data/tiff/fail/.gitignore deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/.gitignore +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/BID-51132-1.tiff b/filter/qa/cppunit/data/tiff/fail/BID-51132-1.tiff Binary files differdeleted file mode 100644 index 929ac15f16ea..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/BID-51132-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2006-3459-1.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2006-3459-1.tiff Binary files differdeleted file mode 100644 index 323fb176199c..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2006-3459-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2009-2285-1.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2009-2285-1.tiff Binary files differdeleted file mode 100644 index 896de2b7b0a3..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2009-2285-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2010-2482-1.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2010-2482-1.tiff Binary files differdeleted file mode 100644 index 59e3c7ed6f57..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2010-2482-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2012-0276-1.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2012-0276-1.tiff Binary files differdeleted file mode 100644 index ea6dd77bb3f9..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2012-0276-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2012-0276-2.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2012-0276-2.tiff Binary files differdeleted file mode 100644 index a66476b7daa5..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2012-0276-2.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2012-2027-1.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2012-2027-1.tiff Binary files differdeleted file mode 100644 index ea6dd77bb3f9..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2012-2027-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2013-3906-1.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2013-3906-1.tiff Binary files differdeleted file mode 100644 index a7704996cb37..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2013-3906-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2017-10688-1.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2017-10688-1.tiff Binary files differdeleted file mode 100644 index a41eb50b98b6..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2017-10688-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2017-9147-1.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2017-9147-1.tiff Binary files differdeleted file mode 100644 index d59119e4f48a..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2017-9147-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/CVE-2017-9936-1.tiff b/filter/qa/cppunit/data/tiff/fail/CVE-2017-9936-1.tiff Binary files differdeleted file mode 100644 index 372a33b6f166..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/CVE-2017-9936-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/EBD-22681-1.tiff b/filter/qa/cppunit/data/tiff/fail/EBD-22681-1.tiff Binary files differdeleted file mode 100644 index 614051dd748b..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/EBD-22681-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/EDB-24743-5.tiff b/filter/qa/cppunit/data/tiff/fail/EDB-24743-5.tiff Binary files differdeleted file mode 100644 index 5f5feed59ff3..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/EDB-24743-5.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-crash-1.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-crash-1.tiff Binary files differdeleted file mode 100644 index 9e9d192f9c9c..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-crash-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-crash-2.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-crash-2.tiff Binary files differdeleted file mode 100644 index 8aaede4a7aa3..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-crash-2.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-crash-3.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-crash-3.tiff Binary files differdeleted file mode 100644 index 712e780a94c1..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-crash-3.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-crash-4.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-crash-4.tiff Binary files differdeleted file mode 100644 index 7c5402e76fb8..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-crash-4.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-crash-5.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-crash-5.tiff Binary files differdeleted file mode 100644 index 97433c354518..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-crash-5.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-crash-6.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-crash-6.tiff Binary files differdeleted file mode 100644 index 2b2846df0c01..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-crash-6.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-crash-7.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-crash-7.tiff Binary files differdeleted file mode 100644 index 0ca75a0a7938..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-crash-7.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-1.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-1.tiff Binary files differdeleted file mode 100644 index 5b5b72d4a05c..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-10.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-10.tiff Binary files differdeleted file mode 100644 index ad722fc5c930..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-10.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-2.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-2.tiff Binary files differdeleted file mode 100644 index 9924b3898133..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-2.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-3.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-3.tiff Binary files differdeleted file mode 100644 index 8de41b59f267..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-3.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-4.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-4.tiff Binary files differdeleted file mode 100644 index e51e3919221e..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-4.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-5.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-5.tiff Binary files differdeleted file mode 100644 index 1123daceebfc..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-5.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-6.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-6.tiff Binary files differdeleted file mode 100644 index fc65d92d272d..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-6.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-7.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-7.tiff Binary files differdeleted file mode 100644 index cbac073268e6..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-7.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-8.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-8.tiff Binary files differdeleted file mode 100644 index 2ee04554daf3..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-8.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/fail/RC4-hang-9.tiff b/filter/qa/cppunit/data/tiff/fail/RC4-hang-9.tiff Binary files differdeleted file mode 100644 index 719f5931c304..000000000000 --- a/filter/qa/cppunit/data/tiff/fail/RC4-hang-9.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/indeterminate/.gitignore b/filter/qa/cppunit/data/tiff/indeterminate/.gitignore deleted file mode 100644 index 9c056f0969e1..000000000000 --- a/filter/qa/cppunit/data/tiff/indeterminate/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.tiff-* -*.tif-* diff --git a/filter/qa/cppunit/data/tiff/pass/.gitignore b/filter/qa/cppunit/data/tiff/pass/.gitignore deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/filter/qa/cppunit/data/tiff/pass/.gitignore +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/pass/CVE-2005-1544-1.tiff b/filter/qa/cppunit/data/tiff/pass/CVE-2005-1544-1.tiff Binary files differdeleted file mode 100644 index a985d63d7196..000000000000 --- a/filter/qa/cppunit/data/tiff/pass/CVE-2005-1544-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/pass/CVE-2006-2656-1.tiff b/filter/qa/cppunit/data/tiff/pass/CVE-2006-2656-1.tiff Binary files differdeleted file mode 100644 index c61878e9b681..000000000000 --- a/filter/qa/cppunit/data/tiff/pass/CVE-2006-2656-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/pass/CVE-2007-2217-1.tiff b/filter/qa/cppunit/data/tiff/pass/CVE-2007-2217-1.tiff Binary files differdeleted file mode 100644 index e078b73d0bbc..000000000000 --- a/filter/qa/cppunit/data/tiff/pass/CVE-2007-2217-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/pass/CVE-2013-5575-1.tiff b/filter/qa/cppunit/data/tiff/pass/CVE-2013-5575-1.tiff Binary files differdeleted file mode 100644 index ae3cee16c000..000000000000 --- a/filter/qa/cppunit/data/tiff/pass/CVE-2013-5575-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/pass/multi-page-1.tiff b/filter/qa/cppunit/data/tiff/pass/multi-page-1.tiff Binary files differdeleted file mode 100644 index 8eb7c8078054..000000000000 --- a/filter/qa/cppunit/data/tiff/pass/multi-page-1.tiff +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/tdf115863.tif b/filter/qa/cppunit/data/tiff/tdf115863.tif Binary files differdeleted file mode 100644 index b5e2dd9e4bcd..000000000000 --- a/filter/qa/cppunit/data/tiff/tdf115863.tif +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/tdf126460.tif b/filter/qa/cppunit/data/tiff/tdf126460.tif Binary files differdeleted file mode 100644 index ffdf6a1d56b8..000000000000 --- a/filter/qa/cppunit/data/tiff/tdf126460.tif +++ /dev/null diff --git a/filter/qa/cppunit/data/tiff/tdf138818.tif b/filter/qa/cppunit/data/tiff/tdf138818.tif Binary files differdeleted file mode 100644 index bb3e51011b25..000000000000 --- a/filter/qa/cppunit/data/tiff/tdf138818.tif +++ /dev/null diff --git a/filter/qa/cppunit/filters-tiff-test.cxx b/filter/qa/cppunit/filters-tiff-test.cxx deleted file mode 100644 index a1ce322a4614..000000000000 --- a/filter/qa/cppunit/filters-tiff-test.cxx +++ /dev/null @@ -1,134 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include <unotest/filters-test.hxx> -#include <test/bootstrapfixture.hxx> -#include <vcl/FilterConfigItem.hxx> -#include <tools/stream.hxx> -#include <vcl/graph.hxx> -#include <vcl/graphicfilter.hxx> - -extern "C" -{ - SAL_DLLPUBLIC_EXPORT bool SAL_CALL - itiGraphicImport(SvStream & rStream, Graphic & rGraphic, - FilterConfigItem*); -} - -using namespace ::com::sun::star; - -/* Implementation of Filters test */ - -class TiffFilterTest - : public test::FiltersTest - , public test::BootstrapFixture -{ -public: - TiffFilterTest() : BootstrapFixture(true, false) {} - - virtual bool load(const OUString &, - const OUString &rURL, const OUString &, - SfxFilterFlags, SotClipboardFormatId, unsigned int) override; - - OUString getUrl() - { - return m_directories.getURLFromSrc(u"/filter/qa/cppunit/data/tiff/"); - } - - /** - * Ensure CVEs remain unbroken - */ - void testCVEs(); - void testTdf126460(); - void testTdf115863(); - void testTdf138818(); - - CPPUNIT_TEST_SUITE(TiffFilterTest); - CPPUNIT_TEST(testCVEs); - CPPUNIT_TEST(testTdf126460); - CPPUNIT_TEST(testTdf115863); - CPPUNIT_TEST(testTdf138818); - CPPUNIT_TEST_SUITE_END(); -}; - -bool TiffFilterTest::load(const OUString &, - const OUString &rURL, const OUString &, - SfxFilterFlags, SotClipboardFormatId, unsigned int) -{ - SvFileStream aFileStream(rURL, StreamMode::READ); - Graphic aGraphic; - return itiGraphicImport(aFileStream, aGraphic, nullptr); -} - -void TiffFilterTest::testCVEs() -{ - testDir(OUString(), - getUrl()); -} - -void TiffFilterTest::testTdf126460() -{ - OUString aURL = getUrl() + "tdf126460.tif"; - SvFileStream aFileStream(aURL, StreamMode::READ); - Graphic aGraphic; - GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); - - ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream); - - CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult); - - // Without the fix in place, the following asserts would have failed - CPPUNIT_ASSERT(aGraphic.IsAlpha()); - CPPUNIT_ASSERT(aGraphic.IsTransparent()); -} - -void TiffFilterTest::testTdf115863() -{ - OUString aURL = getUrl() + "tdf115863.tif"; - SvFileStream aFileStream(aURL, StreamMode::READ); - Graphic aGraphic; - GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); - - ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream); - - // Without the fix in place, this test would have failed with - // - Expected: 0x0(Error Area:Io Class:NONE Code:0) - // - Actual : 0x8203(Error Area:Vcl Class:General Code:3) - CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult); - - Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap(); - Size aSize = aBitmap.GetSizePixel(); - CPPUNIT_ASSERT_EQUAL(tools::Long(528), aSize.Width()); - CPPUNIT_ASSERT_EQUAL(tools::Long(618), aSize.Height()); - -} - -void TiffFilterTest::testTdf138818() -{ - OUString aURL = getUrl() + "tdf138818.tif"; - SvFileStream aFileStream(aURL, StreamMode::READ); - Graphic aGraphic; - GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter(); - - ErrCode bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream); - - CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, bResult); - - // Without the fix in place, this test would have failed with - // - Expected: 46428 - // - Actual : 45951 - CPPUNIT_ASSERT_EQUAL(sal_uInt32(46428), aGraphic.GetGfxLink().GetDataSize()); - -} - -CPPUNIT_TEST_SUITE_REGISTRATION(TiffFilterTest); - -CPPUNIT_PLUGIN_IMPLEMENT(); - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/config/fragments/internalgraphicfilters/tif_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/tif_Export.xcu index c83701d2df88..6fc07ec7231f 100644 --- a/filter/source/config/fragments/internalgraphicfilters/tif_Export.xcu +++ b/filter/source/config/fragments/internalgraphicfilters/tif_Export.xcu @@ -17,7 +17,7 @@ --> <node oor:name="tif_Export" oor:op="replace" > <prop oor:name="Type"><value>tif_Tag_Image_File</value></prop> - <prop oor:name="FormatName"><value>eti</value></prop> + <prop oor:name="FormatName"><value>SVTIFF</value></prop> <prop oor:name="RealFilterName"/> <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop> <prop oor:name="UIName"> diff --git a/filter/source/config/fragments/internalgraphicfilters/tif_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/tif_Import.xcu index 8d4b32296bd3..b77e6e6d62a1 100644 --- a/filter/source/config/fragments/internalgraphicfilters/tif_Import.xcu +++ b/filter/source/config/fragments/internalgraphicfilters/tif_Import.xcu @@ -17,7 +17,7 @@ --> <node oor:name="tif_Import" oor:op="replace" > <prop oor:name="Type"><value>tif_Tag_Image_File</value></prop> - <prop oor:name="FormatName"><value>iti</value></prop> + <prop oor:name="FormatName"><value>SVTIFF</value></prop> <prop oor:name="RealFilterName"><value>TIF - Tag Image File</value></prop> <prop oor:name="UIComponent"/> <prop oor:name="UIName"> diff --git a/filter/source/graphicfilter/etiff/etiff.cxx b/filter/source/graphicfilter/etiff/etiff.cxx deleted file mode 100644 index 80c185e1ea5b..000000000000 --- a/filter/source/graphicfilter/etiff/etiff.cxx +++ /dev/null @@ -1,587 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include <tools/stream.hxx> -#include <vcl/graph.hxx> -#include <vcl/outdev.hxx> -#include <vcl/BitmapReadAccess.hxx> -#include <vcl/FilterConfigItem.hxx> -#include <com/sun/star/task/XStatusIndicator.hpp> - -#define NewSubfileType 254 -#define ImageWidth 256 -#define ImageLength 257 -#define BitsPerSample 258 -#define Compression 259 -#define PhotometricInterpretation 262 -#define StripOffsets 273 -#define SamplesPerPixel 277 -#define RowsPerStrip 278 -#define StripByteCounts 279 -#define XResolution 282 -#define YResolution 283 -#define PlanarConfiguration 284 -#define ResolutionUnit 296 -#define ColorMap 320 - -namespace { - -struct TIFFLZWCTreeNode -{ - - TIFFLZWCTreeNode* pBrother; // next node with the same father - TIFFLZWCTreeNode* pFirstChild; // first son - sal_uInt16 nCode; // The code for the string of pixel values, which arises if... <missing comment> - sal_uInt16 nValue; // pixel value -}; - - -class TIFFWriter -{ -private: - - SvStream& m_rOStm; - sal_uInt32 mnStreamOfs; - - bool mbStatus; - BitmapReadAccess* mpAcc; - - sal_uInt32 mnWidth, mnHeight, mnColors; - sal_uInt32 mnCurAllPictHeight; - sal_uInt32 mnSumOfAllPictHeight; - sal_uInt32 mnBitsPerPixel; - sal_uInt32 mnLastPercent; - - sal_uInt32 mnLatestIfdPos; - sal_uInt16 mnTagCount; // number of tags already written - sal_uInt32 mnCurrentTagCountPos; // offset to the position where the current - // tag count is to insert - - sal_uInt32 mnXResPos; // if != 0 this DWORDs stores the - sal_uInt32 mnYResPos; // actual streamposition of the - sal_uInt32 mnPalPos; // Tag Entry - sal_uInt32 mnBitmapPos; - sal_uInt32 mnStripByteCountPos; - - std::unique_ptr<TIFFLZWCTreeNode[]> pTable; - TIFFLZWCTreeNode* pPrefix; - sal_uInt16 nDataSize; - sal_uInt16 nClearCode; - sal_uInt16 nEOICode; - sal_uInt16 nTableSize; - sal_uInt16 nCodeSize; - sal_uInt32 nOffset; - sal_uInt32 dwShift; - - css::uno::Reference< css::task::XStatusIndicator > xStatusIndicator; - - void ImplCallback( sal_uInt32 nPercent ); - bool ImplWriteHeader( bool bMultiPage ); - void ImplWritePalette(); - void ImplWriteBody(); - void ImplWriteTag( sal_uInt16 TagID, sal_uInt16 DataType, sal_uInt32 NumberOfItems, sal_uInt32 Value); - void ImplWriteResolution( sal_uInt64 nStreamPos, sal_uInt32 nResolutionUnit ); - void StartCompression(); - void Compress( sal_uInt8 nSrc ); - void EndCompression(); - inline void WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen ); - -public: - - explicit TIFFWriter(SvStream &rStream); - - bool WriteTIFF( const Graphic& rGraphic, FilterConfigItem const * pFilterConfigItem ); -}; - -} - -TIFFWriter::TIFFWriter(SvStream &rStream) - : m_rOStm(rStream) - , mnStreamOfs(0) - , mbStatus(true) - , mpAcc(nullptr) - , mnWidth(0) - , mnHeight(0) - , mnColors(0) - , mnCurAllPictHeight(0) - , mnSumOfAllPictHeight(0) - , mnBitsPerPixel(0) - , mnLastPercent(0) - , mnLatestIfdPos(0) - , mnTagCount(0) - , mnCurrentTagCountPos(0) - , mnXResPos(0) - , mnYResPos(0) - , mnPalPos(0) - , mnBitmapPos(0) - , mnStripByteCountPos(0) - , pPrefix(nullptr) - , nDataSize(0) - , nClearCode(0) - , nEOICode(0) - , nTableSize(0) - , nCodeSize(0) - , nOffset(0) - , dwShift(0) -{ -} - - -bool TIFFWriter::WriteTIFF( const Graphic& rGraphic, FilterConfigItem const * pFilterConfigItem) -{ - if ( pFilterConfigItem ) - { - xStatusIndicator = pFilterConfigItem->GetStatusIndicator(); - if ( xStatusIndicator.is() ) - { - xStatusIndicator->start( OUString(), 100 ); - } - } - - const SvStreamEndian nOldFormat = m_rOStm.GetEndian(); - mnStreamOfs = m_rOStm.Tell(); - - // we will use the BIG Endian Mode - // TIFF header - m_rOStm.SetEndian( SvStreamEndian::BIG ); - m_rOStm.WriteUInt32( 0x4d4d002a ); // TIFF identifier - mnLatestIfdPos = m_rOStm.Tell(); - m_rOStm.WriteUInt32( 0 ); - - if( mbStatus ) - { - Animation aAnimation = rGraphic.IsAnimated() ? rGraphic.GetAnimation() : Animation(); - if (!rGraphic.IsAnimated()) - aAnimation.Insert(AnimationBitmap(rGraphic.GetBitmapEx(), Point(), Size())); - - for (size_t i = 0; i < aAnimation.Count(); ++i) - mnSumOfAllPictHeight += aAnimation.Get(i).maBitmapEx.GetSizePixel().Height(); - - for (size_t i = 0; mbStatus && i < aAnimation.Count(); ++i) - { - mnPalPos = 0; - const AnimationBitmap& rAnimationBitmap = aAnimation.Get( i ); - Bitmap aBmp = rAnimationBitmap.maBitmapEx.GetBitmap(); - mpAcc = aBmp.AcquireReadAccess(); - if ( mpAcc ) - { - mnBitsPerPixel = aBmp.GetBitCount(); - - // export code below only handles four discrete cases - mnBitsPerPixel = - mnBitsPerPixel <= 1 ? 1 : mnBitsPerPixel <= 4 ? 4 : mnBitsPerPixel <= 8 ? 8 : 24; - - if ( ImplWriteHeader( aAnimation.Count() > 0 ) ) - { - Size aDestMapSize( 300, 300 ); - const MapMode& aMapMode( aBmp.GetPrefMapMode() ); - if ( aMapMode.GetMapUnit() != MapUnit::MapPixel ) - { - const Size aPrefSize( rGraphic.GetPrefSize() ); - aDestMapSize = OutputDevice::LogicToLogic(aPrefSize, aMapMode, MapMode(MapUnit::MapInch)); - } - ImplWriteResolution( mnXResPos, aDestMapSize.Width() ); - ImplWriteResolution( mnYResPos, aDestMapSize.Height() ); - if ( mnPalPos ) - ImplWritePalette(); - ImplWriteBody(); - } - sal_uInt32 nCurPos = m_rOStm.Tell(); - m_rOStm.Seek( mnCurrentTagCountPos ); - m_rOStm.WriteUInt16( mnTagCount ); - m_rOStm.Seek( nCurPos ); - - Bitmap::ReleaseAccess( mpAcc ); - } - else - mbStatus = false; - } - } - m_rOStm.SetEndian( nOldFormat ); - - if ( xStatusIndicator.is() ) - xStatusIndicator->end(); - - return mbStatus; -} - - -void TIFFWriter::ImplCallback( sal_uInt32 nPercent ) -{ - if ( xStatusIndicator.is() ) - { - if( nPercent >= mnLastPercent + 3 ) - { - mnLastPercent = nPercent; - if ( nPercent <= 100 ) - xStatusIndicator->setValue( nPercent ); - } - } -} - - -bool TIFFWriter::ImplWriteHeader( bool bMultiPage ) -{ - mnTagCount = 0; - mnWidth = mpAcc->Width(); - mnHeight = mpAcc->Height(); - - if ( mnWidth && mnHeight && mnBitsPerPixel && mbStatus ) - { - sal_uInt32 nCurrentPos = m_rOStm.Tell(); - m_rOStm.Seek( mnLatestIfdPos ); - m_rOStm.WriteUInt32( nCurrentPos - mnStreamOfs ); // offset to the IFD - m_rOStm.Seek( nCurrentPos ); - - // (OFS8) TIFF image file directory (IFD) - mnCurrentTagCountPos = m_rOStm.Tell(); - m_rOStm.WriteUInt16( 0 ); // the number of tangents to insert later - - sal_uInt32 nSubFileFlags = 0; - if ( bMultiPage ) - nSubFileFlags |= 2; - ImplWriteTag( NewSubfileType, 4, 1, nSubFileFlags ); - ImplWriteTag( ImageWidth, 4, 1, mnWidth ); - ImplWriteTag( ImageLength, 4, 1, mnHeight); - ImplWriteTag( BitsPerSample, 3, 1, ( mnBitsPerPixel == 24 ) ? 8 : mnBitsPerPixel ); - ImplWriteTag( Compression, 3, 1, 5 ); - sal_uInt8 nTemp; - switch ( mnBitsPerPixel ) - { - case 1 : - nTemp = 1; - break; - case 4 : - case 8 : - nTemp = 3; - break; - case 24: - nTemp = 2; - break; - default: - nTemp = 0; // -Wall set a default... - break; - } - ImplWriteTag( PhotometricInterpretation, 3, 1, nTemp ); - mnBitmapPos = m_rOStm.Tell(); - ImplWriteTag( StripOffsets, 4, 1, 0 ); - ImplWriteTag( SamplesPerPixel, 3, 1, ( mnBitsPerPixel == 24 ) ? 3 : 1 ); - ImplWriteTag( RowsPerStrip, 4, 1, mnHeight ); - mnStripByteCountPos = m_rOStm.Tell(); - ImplWriteTag( StripByteCounts, 4, 1, ( ( mnWidth * mnBitsPerPixel * mnHeight ) + 7 ) >> 3 ); - mnXResPos = m_rOStm.Tell(); - ImplWriteTag( XResolution, 5, 1, 0 ); - mnYResPos = m_rOStm.Tell(); - ImplWriteTag( YResolution, 5, 1, 0 ); - if ( mnBitsPerPixel != 1 ) - ImplWriteTag( PlanarConfiguration, 3, 1, 1 ); // ( RGB ORDER ) - ImplWriteTag( ResolutionUnit, 3, 1, 2); // Resolution Unit is Inch - if ( ( mnBitsPerPixel == 4 ) || ( mnBitsPerPixel == 8 ) ) - { - mnColors = mpAcc->GetPaletteEntryCount(); - mnPalPos = m_rOStm.Tell(); - ImplWriteTag( ColorMap, 3, 3 * mnColors, 0 ); - } - - // and last we write zero to close the num dir entries list - mnLatestIfdPos = m_rOStm.Tell(); - m_rOStm.WriteUInt32( 0 ); // there are no more IFD - } - else - mbStatus = false; - - return mbStatus; -} - - -void TIFFWriter::ImplWritePalette() -{ - sal_uInt64 nCurrentPos = m_rOStm.Tell(); - m_rOStm.Seek( mnPalPos + 8 ); // the palette tag entry needs the offset - m_rOStm.WriteUInt32( nCurrentPos - mnStreamOfs ); // to the palette colors - m_rOStm.Seek( nCurrentPos ); - - for ( sal_uInt32 i = 0; i < mnColors; i++ ) - { - const BitmapColor& rColor = mpAcc->GetPaletteColor( i ); - m_rOStm.WriteUInt16( rColor.GetRed() << 8 ); - } - for ( sal_uInt32 i = 0; i < mnColors; i++ ) - { - const BitmapColor& rColor = mpAcc->GetPaletteColor( i ); - m_rOStm.WriteUInt16( rColor.GetGreen() << 8 ); - } - for ( sal_uInt32 i = 0; i < mnColors; i++ ) - { - const BitmapColor& rColor = mpAcc->GetPaletteColor( i ); - m_rOStm.WriteUInt16( rColor.GetBlue() << 8 ); - } -} - - -void TIFFWriter::ImplWriteBody() -{ - sal_uInt8 nTemp = 0; - sal_uInt8 nShift; - sal_uInt32 j, x, y; - - sal_uInt64 nGfxBegin = m_rOStm.Tell(); - m_rOStm.Seek( mnBitmapPos + 8 ); // the strip offset tag entry needs the offset - m_rOStm.WriteUInt32( nGfxBegin - mnStreamOfs ); // to the bitmap data - m_rOStm.Seek( nGfxBegin ); - - StartCompression(); - - switch( mnBitsPerPixel ) - { - case 24 : - { - for ( y = 0; y < mnHeight; y++, mnCurAllPictHeight++ ) - { - ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight ); - Scanline pScanline = mpAcc->GetScanline( y ); - for ( x = 0; x < mnWidth; x++ ) - { - const BitmapColor& rColor = mpAcc->GetPixelFromData( pScanline, x ); - Compress( rColor.GetRed() ); - Compress( rColor.GetGreen() ); - Compress( rColor.GetBlue() ); - } - } - } - break; - - case 8 : - { - for ( y = 0; y < mnHeight; y++, mnCurAllPictHeight++ ) - { - ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight ); - Scanline pScanline = mpAcc->GetScanline( y ); - for ( x = 0; x < mnWidth; x++ ) - { - Compress( mpAcc->GetIndexFromData( pScanline, x ) ); - } - } - } - break; - - case 4 : - { - for ( nShift = 0, y = 0; y < mnHeight; y++, mnCurAllPictHeight++ ) - { - ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight ); - Scanline pScanline = mpAcc->GetScanline( y ); - for ( x = 0; x < mnWidth; x++, nShift++ ) - { - if (!( nShift & 1 )) - nTemp = ( mpAcc->GetIndexFromData( pScanline, x ) << 4 ); - else - Compress( static_cast<sal_uInt8>( nTemp | ( mpAcc->GetIndexFromData( pScanline, x ) & 0xf ) ) ); - } - if ( nShift & 1 ) - Compress( nTemp ); - } - } - break; - - case 1 : - { - j = 1; - for ( y = 0; y < mnHeight; y++, mnCurAllPictHeight++ ) - { - ImplCallback( 100 * mnCurAllPictHeight / mnSumOfAllPictHeight ); - Scanline pScanline = mpAcc->GetScanline( y ); - for ( x = 0; x < mnWidth; x++) - { - j <<= 1; - j |= ( ( ~mpAcc->GetIndexFromData( pScanline, x ) ) & 1 ); - if ( j & 0x100 ) - { - Compress( static_cast<sal_uInt8>(j) ); - j = 1; - } - } - if ( j != 1 ) - { - Compress( static_cast<sal_uInt8>(j << ( ( ( x & 7) ^ 7 ) + 1 ) ) ); - j = 1; - } - } - } - break; - - default: - { - mbStatus = false; - } - break; - } - - EndCompression(); - - if ( mnStripByteCountPos && mbStatus ) - { - sal_uInt64 nGfxEnd = m_rOStm.Tell(); - m_rOStm.Seek( mnStripByteCountPos + 8 ); - m_rOStm.WriteUInt32( nGfxEnd - nGfxBegin ); // mnStripByteCountPos needs the size of the compression data - m_rOStm.Seek( nGfxEnd ); - } -} - - -void TIFFWriter::ImplWriteResolution( sal_uInt64 nStreamPos, sal_uInt32 nResolutionUnit ) -{ - sal_uInt64 nCurrentPos = m_rOStm.Tell(); - m_rOStm.Seek( nStreamPos + 8 ); - m_rOStm.WriteUInt32( nCurrentPos - mnStreamOfs ); - m_rOStm.Seek( nCurrentPos ); - m_rOStm.WriteUInt32( 1 ); - m_rOStm.WriteUInt32( nResolutionUnit ); -} - - -void TIFFWriter::ImplWriteTag( sal_uInt16 nTagID, sal_uInt16 nDataType, sal_uInt32 nNumberOfItems, sal_uInt32 nValue) -{ - mnTagCount++; - - m_rOStm.WriteUInt16( nTagID ); - m_rOStm.WriteUInt16( nDataType ); - m_rOStm.WriteUInt32( nNumberOfItems ); - if ( nDataType == 3 ) - nValue <<=16; // in Big Endian Mode WORDS needed to be shifted to a DWORD - m_rOStm.WriteUInt32( nValue ); -} - - -inline void TIFFWriter::WriteBits( sal_uInt16 nCode, sal_uInt16 nCodeLen ) -{ - dwShift |= ( nCode << ( nOffset - nCodeLen ) ); - nOffset -= nCodeLen; - while ( nOffset < 24 ) - { - m_rOStm.WriteUChar( dwShift >> 24 ); - dwShift <<= 8; - nOffset += 8; - } - if ( nCode == 257 && nOffset != 32 ) - { - m_rOStm.WriteUChar( dwShift >> 24 ); - } -} - - -void TIFFWriter::StartCompression() -{ - sal_uInt16 i; - nDataSize = 8; - - nClearCode = 1 << nDataSize; - nEOICode = nClearCode + 1; - nTableSize = nEOICode + 1; - nCodeSize = nDataSize + 1; - - nOffset = 32; // number of free bits in dwShift - dwShift = 0; - - pTable.reset(new TIFFLZWCTreeNode[ 4096 ]); - - for ( i = 0; i < 4096; i++) - { - pTable[ i ].pBrother = pTable[ i ].pFirstChild = nullptr; - pTable[ i ].nCode = i; - pTable[ i ].nValue = static_cast<sal_uInt8>( i ); - } - - pPrefix = nullptr; - WriteBits( nClearCode, nCodeSize ); -} - - -void TIFFWriter::Compress( sal_uInt8 nCompThis ) -{ - TIFFLZWCTreeNode* p; - sal_uInt16 i; - sal_uInt8 nV; - - if( !pPrefix ) - { - pPrefix = &pTable[nCompThis]; - } - else - { - nV = nCompThis; - for( p = pPrefix->pFirstChild; p != nullptr; p = p->pBrother ) - { - if ( p->nValue == nV ) - break; - } - - if( p ) - pPrefix = p; - else - { - WriteBits( pPrefix->nCode, nCodeSize ); - - if ( nTableSize == 409 ) - { - WriteBits( nClearCode, nCodeSize ); - - for ( i = 0; i < nClearCode; i++ ) - pTable[ i ].pFirstChild = nullptr; - - nCodeSize = nDataSize + 1; - nTableSize = nEOICode + 1; - } - else - { - if( nTableSize == static_cast<sal_uInt16>( ( 1 << nCodeSize ) - 1 ) ) - nCodeSize++; - - p = &pTable[ nTableSize++ ]; - p->pBrother = pPrefix->pFirstChild; - pPrefix->pFirstChild = p; - p->nValue = nV; - p->pFirstChild = nullptr; - } - - pPrefix = &pTable[nV]; - } - } -} - - -void TIFFWriter::EndCompression() -{ - if( pPrefix ) - WriteBits( pPrefix->nCode, nCodeSize ); - - WriteBits( nEOICode, nCodeSize ); - pTable.reset(); -} - - -extern "C" SAL_DLLPUBLIC_EXPORT bool -etiGraphicExport( SvStream& rStream, Graphic& rGraphic, FilterConfigItem* pFilterConfigItem ) -{ - TIFFWriter aWriter(rStream); - return aWriter.WriteTIFF( rGraphic, pFilterConfigItem ); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/graphicfilter/itiff/ccidecom.cxx b/filter/source/graphicfilter/itiff/ccidecom.cxx deleted file mode 100644 index 407aab17d669..000000000000 --- a/filter/source/graphicfilter/itiff/ccidecom.cxx +++ /dev/null @@ -1,1100 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "ccidecom.hxx" -#include <tools/stream.hxx> - -//=============================== Huffman tables ======================== - -//---------------------------- White-Run ------------------------------ - -#define CCIWhiteTableSize 105 - -const CCIHuffmanTableEntry CCIWhiteTable[CCIWhiteTableSize]={ - { 0, 0x0035, 8 }, - { 1, 0x0007, 6 }, - { 2, 0x0007, 4 }, - { 3, 0x0008, 4 }, - { 4, 0x000b, 4 }, - { 5, 0x000c, 4 }, - { 6, 0x000e, 4 }, - { 7, 0x000f, 4 }, - { 8, 0x0013, 5 }, - { 9, 0x0014, 5 }, - { 10, 0x0007, 5 }, - { 11, 0x0008, 5 }, - { 12, 0x0008, 6 }, - { 13, 0x0003, 6 }, - { 14, 0x0034, 6 }, - { 15, 0x0035, 6 }, - { 16, 0x002a, 6 }, - { 17, 0x002b, 6 }, - { 18, 0x0027, 7 }, - { 19, 0x000c, 7 }, - { 20, 0x0008, 7 }, - { 21, 0x0017, 7 }, - { 22, 0x0003, 7 }, - { 23, 0x0004, 7 }, - { 24, 0x0028, 7 }, - { 25, 0x002b, 7 }, - { 26, 0x0013, 7 }, - { 27, 0x0024, 7 }, - { 28, 0x0018, 7 }, - { 29, 0x0002, 8 }, - { 30, 0x0003, 8 }, - { 31, 0x001a, 8 }, - { 32, 0x001b, 8 }, - { 33, 0x0012, 8 }, - { 34, 0x0013, 8 }, - { 35, 0x0014, 8 }, - { 36, 0x0015, 8 }, - { 37, 0x0016, 8 }, - { 38, 0x0017, 8 }, - { 39, 0x0028, 8 }, - { 40, 0x0029, 8 }, - { 41, 0x002a, 8 }, - { 42, 0x002b, 8 }, - { 43, 0x002c, 8 }, - { 44, 0x002d, 8 }, - { 45, 0x0004, 8 }, - { 46, 0x0005, 8 }, - { 47, 0x000a, 8 }, - { 48, 0x000b, 8 }, - { 49, 0x0052, 8 }, - { 50, 0x0053, 8 }, - { 51, 0x0054, 8 }, - { 52, 0x0055, 8 }, - { 53, 0x0024, 8 }, - { 54, 0x0025, 8 }, - { 55, 0x0058, 8 }, - { 56, 0x0059, 8 }, - { 57, 0x005a, 8 }, - { 58, 0x005b, 8 }, - { 59, 0x004a, 8 }, - { 60, 0x004b, 8 }, - { 61, 0x0032, 8 }, - { 62, 0x0033, 8 }, - { 63, 0x0034, 8 }, - { 64, 0x001b, 5 }, - { 128, 0x0012, 5 }, - { 192, 0x0017, 6 }, - { 256, 0x0037, 7 }, - { 320, 0x0036, 8 }, - { 384, 0x0037, 8 }, - { 448, 0x0064, 8 }, - { 512, 0x0065, 8 }, - { 576, 0x0068, 8 }, - { 640, 0x0067, 8 }, - { 704, 0x00cc, 9 }, - { 768, 0x00cd, 9 }, - { 832, 0x00d2, 9 }, - { 896, 0x00d3, 9 }, - { 960, 0x00d4, 9 }, - { 1024, 0x00d5, 9 }, - { 1088, 0x00d6, 9 }, - { 1152, 0x00d7, 9 }, - { 1216, 0x00d8, 9 }, - { 1280, 0x00d9, 9 }, - { 1344, 0x00da, 9 }, - { 1408, 0x00db, 9 }, - { 1472, 0x0098, 9 }, - { 1536, 0x0099, 9 }, - { 1600, 0x009a, 9 }, - { 1664, 0x0018, 6 }, - { 1728, 0x009b, 9 }, - { 1792, 0x0008, 11 }, - { 1856, 0x000c, 11 }, - { 1920, 0x000d, 11 }, - { 1984, 0x0012, 12 }, - { 2048, 0x0013, 12 }, - { 2112, 0x0014, 12 }, - { 2176, 0x0015, 12 }, - { 2240, 0x0016, 12 }, - { 2304, 0x0017, 12 }, - { 2368, 0x001c, 12 }, - { 2432, 0x001d, 12 }, - { 2496, 0x001e, 12 }, - { 2560, 0x001f, 12 }, - { 9999, 0x0001, 12 } // EOL -}; - -//---------------------------- Black-Run ------------------------------ - -#define CCIBlackTableSize 105 - -const CCIHuffmanTableEntry CCIBlackTable[CCIBlackTableSize]={ - { 0, 0x0037, 10 }, - { 1, 0x0002, 3 }, - { 2, 0x0003, 2 }, - { 3, 0x0002, 2 }, - { 4, 0x0003, 3 }, - { 5, 0x0003, 4 }, - { 6, 0x0002, 4 }, - { 7, 0x0003, 5 }, - { 8, 0x0005, 6 }, - { 9, 0x0004, 6 }, - { 10, 0x0004, 7 }, - { 11, 0x0005, 7 }, - { 12, 0x0007, 7 }, - { 13, 0x0004, 8 }, - { 14, 0x0007, 8 }, - { 15, 0x0018, 9 }, - { 16, 0x0017, 10 }, - { 17, 0x0018, 10 }, - { 18, 0x0008, 10 }, - { 19, 0x0067, 11 }, - { 20, 0x0068, 11 }, - { 21, 0x006c, 11 }, - { 22, 0x0037, 11 }, - { 23, 0x0028, 11 }, - { 24, 0x0017, 11 }, - { 25, 0x0018, 11 }, - { 26, 0x00ca, 12 }, - { 27, 0x00cb, 12 }, - { 28, 0x00cc, 12 }, - { 29, 0x00cd, 12 }, - { 30, 0x0068, 12 }, - { 31, 0x0069, 12 }, - { 32, 0x006a, 12 }, - { 33, 0x006b, 12 }, - { 34, 0x00d2, 12 }, - { 35, 0x00d3, 12 }, - { 36, 0x00d4, 12 }, - { 37, 0x00d5, 12 }, - { 38, 0x00d6, 12 }, - { 39, 0x00d7, 12 }, - { 40, 0x006c, 12 }, - { 41, 0x006d, 12 }, - { 42, 0x00da, 12 }, - { 43, 0x00db, 12 }, - { 44, 0x0054, 12 }, - { 45, 0x0055, 12 }, - { 46, 0x0056, 12 }, - { 47, 0x0057, 12 }, - { 48, 0x0064, 12 }, - { 49, 0x0065, 12 }, - { 50, 0x0052, 12 }, - { 51, 0x0053, 12 }, - { 52, 0x0024, 12 }, - { 53, 0x0037, 12 }, - { 54, 0x0038, 12 }, - { 55, 0x0027, 12 }, - { 56, 0x0028, 12 }, - { 57, 0x0058, 12 }, - { 58, 0x0059, 12 }, - { 59, 0x002b, 12 }, - { 60, 0x002c, 12 }, - { 61, 0x005a, 12 }, - { 62, 0x0066, 12 }, - { 63, 0x0067, 12 }, - { 64, 0x000f, 10 }, - { 128, 0x00c8, 12 }, - { 192, 0x00c9, 12 }, - { 256, 0x005b, 12 }, - { 320, 0x0033, 12 }, - { 384, 0x0034, 12 }, - { 448, 0x0035, 12 }, - { 512, 0x006c, 13 }, - { 576, 0x006d, 13 }, - { 640, 0x004a, 13 }, - { 704, 0x004b, 13 }, - { 768, 0x004c, 13 }, - { 832, 0x004d, 13 }, - { 896, 0x0072, 13 }, - { 960, 0x0073, 13 }, - { 1024, 0x0074, 13 }, - { 1088, 0x0075, 13 }, - { 1152, 0x0076, 13 }, - { 1216, 0x0077, 13 }, - { 1280, 0x0052, 13 }, - { 1344, 0x0053, 13 }, - { 1408, 0x0054, 13 }, - { 1472, 0x0055, 13 }, - { 1536, 0x005a, 13 }, - { 1600, 0x005b, 13 }, - { 1664, 0x0064, 13 }, - { 1728, 0x0065, 13 }, - { 1792, 0x0008, 11 }, - { 1856, 0x000c, 11 }, - { 1920, 0x000d, 11 }, - { 1984, 0x0012, 12 }, - { 2048, 0x0013, 12 }, - { 2112, 0x0014, 12 }, - { 2176, 0x0015, 12 }, - { 2240, 0x0016, 12 }, - { 2304, 0x0017, 12 }, - { 2368, 0x001c, 12 }, - { 2432, 0x001d, 12 }, - { 2496, 0x001e, 12 }, - { 2560, 0x001f, 12 }, - { 9999, 0x0001, 12 } // EOL -}; - - -//---------------------------- 2D-Mode -------------------------------- - -#define CCI2DMODE_UNCOMP 0 -#define CCI2DMODE_PASS 1 -#define CCI2DMODE_HORZ 2 -#define CCI2DMODE_VERT_L3 3 -#define CCI2DMODE_VERT_L2 4 -#define CCI2DMODE_VERT_L1 5 -#define CCI2DMODE_VERT_0 6 -#define CCI2DMODE_VERT_R1 7 -#define CCI2DMODE_VERT_R2 8 -#define CCI2DMODE_VERT_R3 9 - -#define CCI2DModeTableSize 10 - -const CCIHuffmanTableEntry CCI2DModeTable[CCI2DModeTableSize]={ - { CCI2DMODE_UNCOMP , 0x000f, 10 }, - { CCI2DMODE_PASS , 0x0001, 4 }, - { CCI2DMODE_HORZ , 0x0001, 3 }, - { CCI2DMODE_VERT_L3, 0x0002, 7 }, - { CCI2DMODE_VERT_L2, 0x0002, 6 }, - { CCI2DMODE_VERT_L1, 0x0002, 3 }, - { CCI2DMODE_VERT_0 , 0x0001, 1 }, - { CCI2DMODE_VERT_R1, 0x0003, 3 }, - { CCI2DMODE_VERT_R2, 0x0003, 6 }, - { CCI2DMODE_VERT_R3, 0x0003, 7 } -}; - - -//-------------------------- 2D-Uncompressed-Mode ---------------------- - -#define CCIUNCOMP_0White_1Black 0 -#define CCIUNCOMP_1White_1Black 1 -#define CCIUNCOMP_2White_1Black 2 -#define CCIUNCOMP_3White_1Black 3 -#define CCIUNCOMP_4White_1Black 4 -#define CCIUNCOMP_5White 5 -#define CCIUNCOMP_0White_End 6 -#define CCIUNCOMP_1White_End 7 -#define CCIUNCOMP_2White_End 8 -#define CCIUNCOMP_3White_End 9 -#define CCIUNCOMP_4White_End 10 - -#define CCIUncompTableSize 11 - -const CCIHuffmanTableEntry CCIUncompTable[CCIUncompTableSize]={ - { CCIUNCOMP_0White_1Black, 0x0001, 1 }, - { CCIUNCOMP_1White_1Black, 0x0001, 2 }, - { CCIUNCOMP_2White_1Black, 0x0001, 3 }, - { CCIUNCOMP_3White_1Black, 0x0001, 4 }, - { CCIUNCOMP_4White_1Black, 0x0001, 5 }, - { CCIUNCOMP_5White , 0x0001, 6 }, - { CCIUNCOMP_0White_End , 0x0001, 7 }, - { CCIUNCOMP_1White_End , 0x0001, 8 }, - { CCIUNCOMP_2White_End , 0x0001, 9 }, - { CCIUNCOMP_3White_End , 0x0001, 10 }, - { CCIUNCOMP_4White_End , 0x0001, 11 } -}; - - -//================== backup of the Huffman tables ============================ -// To make sure that the Huffman tables do not contain errors they were entered -// from two different sources (Phew) and compared. -// Since an error could creep into the source code while maintaining it -// (e.g. an accidental key press in the editor) the tables are listed twice -// and are compared during runtime. (If the comparison fails CCIDcompressor -// throws an error) The whole thing may appear insane, but an error within the -// tables would otherwise be really hard to discover and it's very unlikely that -// one or more sample files run through all codes. - -const CCIHuffmanTableEntry CCIWhiteTableSave[CCIWhiteTableSize]={ - { 0, 0x0035, 8 }, - { 1, 0x0007, 6 }, - { 2, 0x0007, 4 }, - { 3, 0x0008, 4 }, - { 4, 0x000b, 4 }, - { 5, 0x000c, 4 }, - { 6, 0x000e, 4 }, - { 7, 0x000f, 4 }, - { 8, 0x0013, 5 }, - { 9, 0x0014, 5 }, - { 10, 0x0007, 5 }, - { 11, 0x0008, 5 }, - { 12, 0x0008, 6 }, - { 13, 0x0003, 6 }, - { 14, 0x0034, 6 }, - { 15, 0x0035, 6 }, - { 16, 0x002a, 6 }, - { 17, 0x002b, 6 }, - { 18, 0x0027, 7 }, - { 19, 0x000c, 7 }, - { 20, 0x0008, 7 }, - { 21, 0x0017, 7 }, - { 22, 0x0003, 7 }, - { 23, 0x0004, 7 }, - { 24, 0x0028, 7 }, - { 25, 0x002b, 7 }, - { 26, 0x0013, 7 }, - { 27, 0x0024, 7 }, - { 28, 0x0018, 7 }, - { 29, 0x0002, 8 }, - { 30, 0x0003, 8 }, - { 31, 0x001a, 8 }, - { 32, 0x001b, 8 }, - { 33, 0x0012, 8 }, - { 34, 0x0013, 8 }, - { 35, 0x0014, 8 }, - { 36, 0x0015, 8 }, - { 37, 0x0016, 8 }, - { 38, 0x0017, 8 }, - { 39, 0x0028, 8 }, - { 40, 0x0029, 8 }, - { 41, 0x002a, 8 }, - { 42, 0x002b, 8 }, - { 43, 0x002c, 8 }, - { 44, 0x002d, 8 }, - { 45, 0x0004, 8 }, - { 46, 0x0005, 8 }, - { 47, 0x000a, 8 }, - { 48, 0x000b, 8 }, - { 49, 0x0052, 8 }, - { 50, 0x0053, 8 }, - { 51, 0x0054, 8 }, - { 52, 0x0055, 8 }, - { 53, 0x0024, 8 }, - { 54, 0x0025, 8 }, - { 55, 0x0058, 8 }, - { 56, 0x0059, 8 }, - { 57, 0x005a, 8 }, - { 58, 0x005b, 8 }, - { 59, 0x004a, 8 }, - { 60, 0x004b, 8 }, - { 61, 0x0032, 8 }, - { 62, 0x0033, 8 }, - { 63, 0x0034, 8 }, - { 64, 0x001b, 5 }, - { 128, 0x0012, 5 }, - { 192, 0x0017, 6 }, - { 256, 0x0037, 7 }, - { 320, 0x0036, 8 }, - { 384, 0x0037, 8 }, - { 448, 0x0064, 8 }, - { 512, 0x0065, 8 }, - { 576, 0x0068, 8 }, - { 640, 0x0067, 8 }, - { 704, 0x00cc, 9 }, - { 768, 0x00cd, 9 }, - { 832, 0x00d2, 9 }, - { 896, 0x00d3, 9 }, - { 960, 0x00d4, 9 }, - { 1024, 0x00d5, 9 }, - { 1088, 0x00d6, 9 }, - { 1152, 0x00d7, 9 }, - { 1216, 0x00d8, 9 }, - { 1280, 0x00d9, 9 }, - { 1344, 0x00da, 9 }, - { 1408, 0x00db, 9 }, - { 1472, 0x0098, 9 }, - { 1536, 0x0099, 9 }, - { 1600, 0x009a, 9 }, - { 1664, 0x0018, 6 }, - { 1728, 0x009b, 9 }, - { 1792, 0x0008, 11 }, - { 1856, 0x000c, 11 }, - { 1920, 0x000d, 11 }, - { 1984, 0x0012, 12 }, - { 2048, 0x0013, 12 }, - { 2112, 0x0014, 12 }, - { 2176, 0x0015, 12 }, - { 2240, 0x0016, 12 }, - { 2304, 0x0017, 12 }, - { 2368, 0x001c, 12 }, - { 2432, 0x001d, 12 }, - { 2496, 0x001e, 12 }, - { 2560, 0x001f, 12 }, - { 9999, 0x0001, 12 } // EOL -}; - -const CCIHuffmanTableEntry CCIBlackTableSave[CCIBlackTableSize]={ - { 0, 0x0037, 10 }, - { 1, 0x0002, 3 }, - { 2, 0x0003, 2 }, - { 3, 0x0002, 2 }, - { 4, 0x0003, 3 }, - { 5, 0x0003, 4 }, - { 6, 0x0002, 4 }, - { 7, 0x0003, 5 }, - { 8, 0x0005, 6 }, - { 9, 0x0004, 6 }, - { 10, 0x0004, 7 }, - { 11, 0x0005, 7 }, - { 12, 0x0007, 7 }, - { 13, 0x0004, 8 }, - { 14, 0x0007, 8 }, - { 15, 0x0018, 9 }, - { 16, 0x0017, 10 }, - { 17, 0x0018, 10 }, - { 18, 0x0008, 10 }, - { 19, 0x0067, 11 }, - { 20, 0x0068, 11 }, - { 21, 0x006c, 11 }, - { 22, 0x0037, 11 }, - { 23, 0x0028, 11 }, - { 24, 0x0017, 11 }, - { 25, 0x0018, 11 }, - { 26, 0x00ca, 12 }, - { 27, 0x00cb, 12 }, - { 28, 0x00cc, 12 }, - { 29, 0x00cd, 12 }, - { 30, 0x0068, 12 }, - { 31, 0x0069, 12 }, - { 32, 0x006a, 12 }, - { 33, 0x006b, 12 }, - { 34, 0x00d2, 12 }, - { 35, 0x00d3, 12 }, - { 36, 0x00d4, 12 }, - { 37, 0x00d5, 12 }, - { 38, 0x00d6, 12 }, - { 39, 0x00d7, 12 }, - { 40, 0x006c, 12 }, - { 41, 0x006d, 12 }, - { 42, 0x00da, 12 }, - { 43, 0x00db, 12 }, - { 44, 0x0054, 12 }, - { 45, 0x0055, 12 }, - { 46, 0x0056, 12 }, - { 47, 0x0057, 12 }, - { 48, 0x0064, 12 }, - { 49, 0x0065, 12 }, - { 50, 0x0052, 12 }, - { 51, 0x0053, 12 }, - { 52, 0x0024, 12 }, - { 53, 0x0037, 12 }, - { 54, 0x0038, 12 }, - { 55, 0x0027, 12 }, - { 56, 0x0028, 12 }, - { 57, 0x0058, 12 }, - { 58, 0x0059, 12 }, - { 59, 0x002b, 12 }, - { 60, 0x002c, 12 }, - { 61, 0x005a, 12 }, - { 62, 0x0066, 12 }, - { 63, 0x0067, 12 }, - { 64, 0x000f, 10 }, - { 128, 0x00c8, 12 }, - { 192, 0x00c9, 12 }, - { 256, 0x005b, 12 }, - { 320, 0x0033, 12 }, - { 384, 0x0034, 12 }, - { 448, 0x0035, 12 }, - { 512, 0x006c, 13 }, - { 576, 0x006d, 13 }, - { 640, 0x004a, 13 }, - { 704, 0x004b, 13 }, - { 768, 0x004c, 13 }, - { 832, 0x004d, 13 }, - { 896, 0x0072, 13 }, - { 960, 0x0073, 13 }, - { 1024, 0x0074, 13 }, - { 1088, 0x0075, 13 }, - { 1152, 0x0076, 13 }, - { 1216, 0x0077, 13 }, - { 1280, 0x0052, 13 }, - { 1344, 0x0053, 13 }, - { 1408, 0x0054, 13 }, - { 1472, 0x0055, 13 }, - { 1536, 0x005a, 13 }, - { 1600, 0x005b, 13 }, - { 1664, 0x0064, 13 }, - { 1728, 0x0065, 13 }, - { 1792, 0x0008, 11 }, - { 1856, 0x000c, 11 }, - { 1920, 0x000d, 11 }, - { 1984, 0x0012, 12 }, - { 2048, 0x0013, 12 }, - { 2112, 0x0014, 12 }, - { 2176, 0x0015, 12 }, - { 2240, 0x0016, 12 }, - { 2304, 0x0017, 12 }, - { 2368, 0x001c, 12 }, - { 2432, 0x001d, 12 }, - { 2496, 0x001e, 12 }, - { 2560, 0x001f, 12 }, - { 9999, 0x0001, 12 } // EOL -}; - - -const CCIHuffmanTableEntry CCI2DModeTableSave[CCI2DModeTableSize]={ - { CCI2DMODE_UNCOMP , 0x000f, 10 }, - { CCI2DMODE_PASS , 0x0001, 4 }, - { CCI2DMODE_HORZ , 0x0001, 3 }, - { CCI2DMODE_VERT_L3, 0x0002, 7 }, - { CCI2DMODE_VERT_L2, 0x0002, 6 }, - { CCI2DMODE_VERT_L1, 0x0002, 3 }, - { CCI2DMODE_VERT_0 , 0x0001, 1 }, - { CCI2DMODE_VERT_R1, 0x0003, 3 }, - { CCI2DMODE_VERT_R2, 0x0003, 6 }, - { CCI2DMODE_VERT_R3, 0x0003, 7 } -}; - - -const CCIHuffmanTableEntry CCIUncompTableSave[CCIUncompTableSize]={ - { CCIUNCOMP_0White_1Black, 0x0001, 1 }, - { CCIUNCOMP_1White_1Black, 0x0001, 2 }, - { CCIUNCOMP_2White_1Black, 0x0001, 3 }, - { CCIUNCOMP_3White_1Black, 0x0001, 4 }, - { CCIUNCOMP_4White_1Black, 0x0001, 5 }, - { CCIUNCOMP_5White , 0x0001, 6 }, - { CCIUNCOMP_0White_End , 0x0001, 7 }, - { CCIUNCOMP_1White_End , 0x0001, 8 }, - { CCIUNCOMP_2White_End , 0x0001, 9 }, - { CCIUNCOMP_3White_End , 0x0001, 10 }, - { CCIUNCOMP_4White_End , 0x0001, 11 } -}; - - -CCIDecompressor::CCIDecompressor( sal_uInt32 nOpts, sal_uInt32 nImageWidth ) : - bTableBad ( false ), - bStatus ( false ), - pIStream ( nullptr ), - nEOLCount ( 0 ), - nWidth ( nImageWidth ), - nOptions ( nOpts ), - bFirstEOL ( false ), - nInputBitsBuf( 0 ), - nInputBitsBufSize( 0 ), - nLastLineSize( 0 ) -{ - if ( nOpts & CCI_OPTION_INVERSEBITORDER ) - { - pByteSwap.reset( new sal_uInt8[ 256 ] ); - for ( int i = 0; i < 256; i++ ) - { - pByteSwap[ i ] = sal::static_int_cast< sal_uInt8 >( - ( i << 7 ) | ( ( i & 2 ) << 5 ) | ( ( i & 4 ) << 3 ) | ( ( i & 8 ) << 1 ) | - ( ( i & 16 ) >> 1 ) | ( ( i & 32 ) >> 3 ) | ( ( i & 64 ) >> 5 ) | ( ( i & 128 ) >> 7 )); - } - } - - MakeLookUp(CCIWhiteTable,CCIWhiteTableSave,pWhiteLookUp.data(),CCIWhiteTableSize,13); - MakeLookUp(CCIBlackTable,CCIBlackTableSave,pBlackLookUp.data(),CCIBlackTableSize,13); - MakeLookUp(CCI2DModeTable,CCI2DModeTableSave,p2DModeLookUp.data(),CCI2DModeTableSize,10); - MakeLookUp(CCIUncompTable,CCIUncompTableSave,pUncompLookUp.data(),CCIUncompTableSize,11); -} - - -CCIDecompressor::~CCIDecompressor() -{ -} - - -void CCIDecompressor::StartDecompression( SvStream & rIStream ) -{ - pIStream = &rIStream; - nInputBitsBufSize = 0; - bFirstEOL = true; - bStatus = true; - nEOLCount = 0; - - if ( bTableBad ) - return; -} - -DecompressStatus CCIDecompressor::DecompressScanline( sal_uInt8 * pTarget, sal_uInt64 nTargetBits, bool bLastLine ) -{ - //Read[1|2]DScanlineData take a sal_uInt16, so its either limit here or expand there - if (nTargetBits > SAL_MAX_UINT16) - return DecompressStatus(false, true); - - if ( nEOLCount >= 5 ) // RTC (Return To Controller) - return DecompressStatus(true, true); - - if ( !bStatus ) - return DecompressStatus(false, true); - - // If EOL-Codes exist, the EOL-Code also appeared in front of the first line. - // (and I thought it means 'End of Line'...) - // Therefore we read the EOL-Code always at the beginning of each line first: - if ( nOptions & CCI_OPTION_EOL ) - { - if ( bFirstEOL ) - { - sal_uInt32 nCurPos = pIStream->Tell(); - sal_uInt16 nOldInputBitsBufSize = nInputBitsBufSize; - sal_uInt32 nOldInputBitsBuf = nInputBitsBuf; - if ( !ReadEOL() ) - { - nInputBitsBufSize = nOldInputBitsBufSize; - nInputBitsBuf = nOldInputBitsBuf; - pIStream->Seek( nCurPos ); - nOptions &=~ CCI_OPTION_EOL; // CCITT Group 3 - Compression Type 2 - } - bFirstEOL = false; - } - else - { - if ( !ReadEOL() ) - { - return DecompressStatus(bStatus, true); - } - } - } - - if ( nEOLCount >= 5 ) // RTC (Return To Controller) - return DecompressStatus(true, true); - - // should the situation arise, generate a white previous line for 2D: - if ( nOptions & CCI_OPTION_2D ) - { - if ( pLastLine == nullptr || nLastLineSize != ( ( nTargetBits + 7 ) >> 3 ) ) - { - nLastLineSize = ( nTargetBits + 7 ) >> 3; - pLastLine.reset( new sal_uInt8[ nLastLineSize ] ); - memset(pLastLine.get(), 0, nLastLineSize); - } - } - // conditionally align start of line to next byte: - if ( nOptions & CCI_OPTION_BYTEALIGNROW ) - nInputBitsBufSize &= 0xfff8; - - bool b2D; - // is it a 2D row? - if ( nOptions & CCI_OPTION_2D ) - { - if ( nOptions & CCI_OPTION_EOL ) - b2D = Read2DTag(); - else - b2D = true; - } - else - b2D = false; - - bool bUnchanged; - // read scanline: - if ( b2D ) - bUnchanged = Read2DScanlineData(pTarget, nTargetBits); - else - bUnchanged = Read1DScanlineData(pTarget, nTargetBits); - - // if we're in 2D mode we have to remember the line: - if ( nOptions & CCI_OPTION_2D && bStatus ) - { - memcpy(pLastLine.get(), pTarget, nLastLineSize); - } - - // #i122984# - if( !bStatus && bLastLine ) - { - bStatus = true; - } - - if ( pIStream->GetError() ) - bStatus = false; - - return DecompressStatus(bStatus, bUnchanged); -} - - -void CCIDecompressor::MakeLookUp(const CCIHuffmanTableEntry * pHufTab, - const CCIHuffmanTableEntry * pHufTabSave, - CCILookUpTableEntry * pLookUp, - sal_uInt16 nHuffmanTableSize, - sal_uInt16 nMaxCodeBits) -{ - sal_uInt16 nLookUpSize = 1 << nMaxCodeBits; - memset(pLookUp, 0, nLookUpSize * sizeof(CCILookUpTableEntry)); - - if (bTableBad) - return; - - sal_uInt16 nMask = 0xffff >> (16-nMaxCodeBits); - - for (sal_uInt16 i = 0; i < nHuffmanTableSize; ++i) - { - if ( pHufTab[i].nValue!=pHufTabSave[i].nValue || - pHufTab[i].nCode!=pHufTabSave[i].nCode || - pHufTab[i].nCodeBits!=pHufTabSave[i].nCodeBits || - pHufTab[i].nCodeBits==0 || - pHufTab[i].nCodeBits>nMaxCodeBits ) - { - bTableBad=true; - return; - } - sal_uInt16 nMinCode = nMask & (pHufTab[i].nCode << (nMaxCodeBits-pHufTab[i].nCodeBits)); - sal_uInt16 nMaxCode = nMinCode | (nMask >> pHufTab[i].nCodeBits); - for (sal_uInt16 j=nMinCode; j<=nMaxCode; ++j) - { - if (pLookUp[j].nCodeBits!=0) - { - bTableBad=true; - return; - } - pLookUp[j].nValue=pHufTab[i].nValue; - pLookUp[j].nCodeBits=pHufTab[i].nCodeBits; - } - } -} - - -bool CCIDecompressor::ReadEOL() -{ - sal_uInt16 nCode; - sal_uInt8 nByte; - - // if (nOptions&CCI_OPTION_BYTEALIGNEOL) nMaxFillBits=7; else nMaxFillBits=0; - // D'oh: Either the option in itiff.cxx is not set correctly (-> error in documentation) - // or there exist some nasty export filter who always do align. - // In addition files were found in which more than the necessary maximum of 7 filling - // bits were found. Therefore we now generally accept up to 32 nonsense bits in front of the EOL-Code: - // And I found a file in which up to ??? nonsense bits are written. Furthermore the byte order is switched in it. (SJ) - - sal_uInt32 nMaxPos = pIStream->Tell(); - nMaxPos += nWidth >> 3; - - for ( ;; ) - { - while ( nInputBitsBufSize < 12 ) - { - pIStream->ReadUChar( nByte ); - if (!pIStream->good()) - return false; - if ( pIStream->Tell() > nMaxPos ) - return false; - - if ( nOptions & CCI_OPTION_INVERSEBITORDER ) - nByte = pByteSwap[ nByte ]; - nInputBitsBuf=(nInputBitsBuf<<8) | static_cast<sal_uInt64>(nByte); - nInputBitsBufSize += 8; - } - nCode = static_cast<sal_uInt16>( ( nInputBitsBuf >> ( nInputBitsBufSize - 12 ) ) & 0x0fff ); - if ( nCode == 0x0001 ) - { - nEOLCount++; - nInputBitsBufSize -= 12; - break; - } - else - nInputBitsBufSize--; - } - return true; -} - - -bool CCIDecompressor::Read2DTag() -{ - // read a bit and return sal_True if it's 0, otherwise return sal_False - if (nInputBitsBufSize==0) { - sal_uInt8 nByte; - pIStream->ReadUChar( nByte ); - if ( nOptions & CCI_OPTION_INVERSEBITORDER ) - nByte = pByteSwap[ nByte ]; - nInputBitsBuf = nByte; - nInputBitsBufSize=8; - } - nInputBitsBufSize--; - return ((nInputBitsBuf>>nInputBitsBufSize)&0x0001) == 0; -} - - -sal_uInt8 CCIDecompressor::ReadBlackOrWhite() -{ - // read a bit and deliver 0x00 if it's 0, otherwise 0xff - if (nInputBitsBufSize==0) { - sal_uInt8 nByte; - pIStream->ReadUChar( nByte ); - if ( nOptions & CCI_OPTION_INVERSEBITORDER ) - nByte = pByteSwap[ nByte ]; - nInputBitsBuf = nByte; - nInputBitsBufSize=8; - } - nInputBitsBufSize--; - if ( (nInputBitsBuf>>nInputBitsBufSize) & 0x0001 ) return 0xff; - else return 0x00; -} - - -sal_uInt16 CCIDecompressor::ReadCodeAndDecode(const CCILookUpTableEntry * pLookUp, - sal_uInt16 nMaxCodeBits) -{ - // read a Huffman code and decode it: - while (nInputBitsBufSize<nMaxCodeBits) - { - sal_uInt8 nByte(0); - pIStream->ReadUChar( nByte ); - if ( nOptions & CCI_OPTION_INVERSEBITORDER ) - nByte = pByteSwap[ nByte ]; - nInputBitsBuf=(nInputBitsBuf<<8) | static_cast<sal_uInt64>(nByte); - nInputBitsBufSize+=8; - } - sal_uInt16 nCode = static_cast<sal_uInt16>((nInputBitsBuf>>(nInputBitsBufSize-nMaxCodeBits)) - &(0xffff>>(16-nMaxCodeBits))); - sal_uInt16 nCodeBits = pLookUp[nCode].nCodeBits; - if (nCodeBits==0) bStatus=false; - nInputBitsBufSize = nInputBitsBufSize - nCodeBits; - return pLookUp[nCode].nValue; -} - - -void CCIDecompressor::FillBits(sal_uInt8 * pTarget, sal_uInt16 nTargetBits, - sal_uInt16 nBitPos, sal_uInt16 nNumBits, - sal_uInt8 nBlackOrWhite) -{ - if ( nBitPos >= nTargetBits ) - return; - if ( nBitPos + nNumBits > nTargetBits ) - nNumBits = nTargetBits - nBitPos; - - pTarget+=nBitPos>>3; - nBitPos&=7; - - if (nBlackOrWhite==0x00) *pTarget &= 0xff << (8-nBitPos); - else *pTarget |= 0xff >> nBitPos; - if (nNumBits>8-nBitPos) { - nNumBits-=8-nBitPos; - while (nNumBits>=8) { - *(++pTarget)=nBlackOrWhite; - nNumBits-=8; - } - if (nNumBits>0) *(++pTarget)=nBlackOrWhite; - } -} - -sal_uInt16 CCIDecompressor::CountBits(const sal_uInt8 * pData, sal_uInt16 nDataSizeBits, - sal_uInt16 nBitPos, sal_uInt8 nBlackOrWhite) -{ - // here the number of bits belonging together is being counted - // which all have the color nBlackOrWhite (0xff or 0x00) - // from the position nBitPos on - sal_uInt32 nPos = nBitPos; - for (;;) - { - if (nPos>=nDataSizeBits) - { - nPos=nDataSizeBits; - break; - } - sal_uInt8 nData = pData[nPos>>3]; - sal_uInt16 nLo = nPos & 7; - if (nLo==0 && nData==nBlackOrWhite) - { - nPos+=8; - } - else - { - if ( ((nData^nBlackOrWhite) & (0x80 >> nLo))!=0) - break; - ++nPos; - } - } - return nPos-nBitPos; -} - -bool CCIDecompressor::Read1DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nBitsToRead) -{ - sal_uInt16 nTargetBits = nBitsToRead; - sal_uInt16 nCode,nCodeBits,nDataBits,nTgtFreeByteBits; - sal_uInt8 nByte; - sal_uInt8 nBlackOrWhite; // is 0xff for black or 0x00 for white - bool bTerminatingCode; - - // the first code is always a "white-code": - nBlackOrWhite=0x00; - - // number of bits that aren't written in the byte *pTarget yet: - nTgtFreeByteBits=8; - - // loop through codes from the input stream: - do { - - // fetch next 13 bits into nCodem but don't remove them from - // the input buffer: - while (nInputBitsBufSize<13) { - pIStream->ReadUChar( nByte ); - if ( nOptions & CCI_OPTION_INVERSEBITORDER ) - nByte = pByteSwap[ nByte ]; - nInputBitsBuf=(nInputBitsBuf<<8) | static_cast<sal_uInt64>(nByte); - nInputBitsBufSize+=8; - } - nCode=static_cast<sal_uInt16>((nInputBitsBuf>>(nInputBitsBufSize-13))&0x1fff); - - // determine the number of DataBits CodeBits: - if (nBlackOrWhite) { - nCodeBits=pBlackLookUp[nCode].nCodeBits; - nDataBits=pBlackLookUp[nCode].nValue; - } - else { - nCodeBits=pWhiteLookUp[nCode].nCodeBits; - nDataBits=pWhiteLookUp[nCode].nValue; - } - // is that an invalid code? - if ( nDataBits == 9999 ) - { - return nTargetBits == nBitsToRead; - } - if ( nCodeBits == 0 ) - { - return nTargetBits == nBitsToRead; // could be filling bits now - } - nEOLCount = 0; - // too much data? - if (nDataBits>nTargetBits) { - // Yes, could be a subsequent error cause by an invalid code - // Therefore continue anyhow: - nDataBits=nTargetBits; - } - - // is that a 'Terminating-Code'? - bTerminatingCode = nDataBits<64; - - // remove the read bits from the input buffer: - nInputBitsBufSize = nInputBitsBufSize - nCodeBits; - - // write the number of data bits into the scanline: - if (nDataBits>0) { - nTargetBits = nTargetBits - nDataBits; - if (nBlackOrWhite==0x00) *pTarget &= 0xff << nTgtFreeByteBits; - else *pTarget |= 0xff >> (8-nTgtFreeByteBits); - if (nDataBits<=nTgtFreeByteBits) { - if (nDataBits==nTgtFreeByteBits) { - pTarget++; - nTgtFreeByteBits=8; - } - else nTgtFreeByteBits = nTgtFreeByteBits - nDataBits; - } - else { - nDataBits = nDataBits - nTgtFreeByteBits; - pTarget++; - nTgtFreeByteBits=8; - if (nDataBits >= 8) - { - const sal_uInt16 nDataBytes = nDataBits / 8; - memset(pTarget, nBlackOrWhite, nDataBytes); - pTarget += nDataBytes; - nDataBits -= nDataBytes * 8; - } - - if (nDataBits>0) { - *pTarget=nBlackOrWhite; - nTgtFreeByteBits = nTgtFreeByteBits - nDataBits; - } - } - } - - // should the situation arise, switch Black <-> White: - if (bTerminatingCode) nBlackOrWhite = ~nBlackOrWhite; - - } while (nTargetBits>0 || !bTerminatingCode); - - return nTargetBits == nBitsToRead; -} - -bool CCIDecompressor::Read2DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits) -{ - sal_uInt16 n2DMode,nBitPos,nUncomp,nRun,nRun2,nt; - sal_uInt8 nBlackOrWhite; - - nBlackOrWhite=0x00; - nBitPos=0; - - while (nBitPos<nTargetBits && bStatus) { - - n2DMode=ReadCodeAndDecode(p2DModeLookUp.data(),10); - if (!bStatus) - return nBitPos == 0; - - if (n2DMode==CCI2DMODE_UNCOMP) { - for (;;) { - nUncomp=ReadCodeAndDecode(pUncompLookUp.data(),11); - if (!bStatus) - break; - if ( nUncomp <= CCIUNCOMP_4White_1Black ) { - nRun=nUncomp-CCIUNCOMP_0White_1Black; - FillBits(pTarget,nTargetBits,nBitPos,nRun,0x00); - nBitPos = nBitPos + nRun; - FillBits(pTarget,nTargetBits,nBitPos,1,0xff); - nBitPos++; - } - else if ( nUncomp == CCIUNCOMP_5White ) { - FillBits(pTarget,nTargetBits,nBitPos,5,0x00); - nBitPos = nBitPos + 5; - } - else { - nRun=nUncomp-CCIUNCOMP_0White_End; - FillBits(pTarget,nTargetBits,nBitPos,nRun,0x00); - nBitPos = nBitPos + nRun; - nBlackOrWhite=ReadBlackOrWhite(); - break; - } - } - } - - else if (n2DMode==CCI2DMODE_PASS) { - if (nBitPos==0 && nBlackOrWhite==0x00 && CountBits(pLastLine.get(), nTargetBits, 0, 0xff)!=0) nRun=0; - else { - nRun = CountBits(pLastLine.get(), nTargetBits, nBitPos, ~nBlackOrWhite); - nRun = nRun + CountBits(pLastLine.get(), nTargetBits, nBitPos + nRun, nBlackOrWhite); - } - nRun = nRun + CountBits(pLastLine.get(), nTargetBits, nBitPos + nRun, ~nBlackOrWhite); - FillBits(pTarget,nTargetBits,nBitPos,nRun,nBlackOrWhite); - nBitPos = nBitPos + nRun; - } - - else if (n2DMode==CCI2DMODE_HORZ) { - if (nBlackOrWhite==0x00) { - nRun=0; - do { - nt=ReadCodeAndDecode(pWhiteLookUp.data(),13); - nRun = nRun + nt; - } while (nt>=64); - nRun2=0; - do { - nt=ReadCodeAndDecode(pBlackLookUp.data(),13); - nRun2 = nRun2 + nt; - } while (nt>=64); - } - else { - nRun=0; - do { - nt=ReadCodeAndDecode(pBlackLookUp.data(),13); - nRun = nRun + nt; - } while (nt>=64); - nRun2=0; - do { - nt=ReadCodeAndDecode(pWhiteLookUp.data(),13); - nRun2 = nRun2 + nt; - } while (nt>=64); - } - FillBits(pTarget,nTargetBits,nBitPos,nRun,nBlackOrWhite); - nBitPos = nBitPos + nRun; - FillBits(pTarget,nTargetBits,nBitPos,nRun2,~nBlackOrWhite); - nBitPos = nBitPos + nRun2; - } - - else { // it's one of the modes CCI2DMODE_VERT_... - if (nBitPos==0 && nBlackOrWhite==0x00 && CountBits(pLastLine.get(), nTargetBits, 0, 0xff)!=0) nRun=0; - else { - nRun = CountBits(pLastLine.get(), nTargetBits, nBitPos, ~nBlackOrWhite); - nRun = nRun + CountBits(pLastLine.get(), nTargetBits, nBitPos + nRun, nBlackOrWhite); - } - nRun+=n2DMode-CCI2DMODE_VERT_0; - FillBits(pTarget,nTargetBits,nBitPos,nRun,nBlackOrWhite); - nBitPos = nBitPos + nRun; - nBlackOrWhite=~nBlackOrWhite; - } - } - - return nBitPos == 0; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/graphicfilter/itiff/ccidecom.hxx b/filter/source/graphicfilter/itiff/ccidecom.hxx deleted file mode 100644 index 89e23656b150..000000000000 --- a/filter/source/graphicfilter/itiff/ccidecom.hxx +++ /dev/null @@ -1,129 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_FILTER_SOURCE_GRAPHICFILTER_ITIFF_CCIDECOM_HXX -#define INCLUDED_FILTER_SOURCE_GRAPHICFILTER_ITIFF_CCIDECOM_HXX - -#include <sal/types.h> -#include <array> -#include <memory> - -#define CCI_OPTION_2D 1 // 2D compression (instead of 1D) -#define CCI_OPTION_EOL 2 // There are EOL-Codes at the end of each line. -#define CCI_OPTION_BYTEALIGNEOL 4 // Filling bits before each EOL-Code, so that - // the end of EOL is bytes aligned -#define CCI_OPTION_BYTEALIGNROW 8 // Rows always start byte aligned -#define CCI_OPTION_INVERSEBITORDER 16 - -// Entry in the Huffman table: -struct CCIHuffmanTableEntry { - sal_uInt16 nValue; // The data value. - sal_uInt16 nCode; // The code through which the data value is represented. - sal_uInt16 nCodeBits; // Size of the code in bits. -}; - -// Entry in a hash table for daft decoding. -struct CCILookUpTableEntry { - sal_uInt16 nValue; - sal_uInt16 nCodeBits; -}; - -class SvStream; - -struct DecompressStatus -{ - bool m_bSuccess; - bool m_bBufferUnchanged; - DecompressStatus(bool bSuccess, bool bBufferUnchanged) - : m_bSuccess(bSuccess), m_bBufferUnchanged(bBufferUnchanged) - { - } -}; - -class CCIDecompressor { - -public: - - CCIDecompressor( sal_uInt32 nOptions, sal_uInt32 nImageWidth ); - ~CCIDecompressor(); - - void StartDecompression( SvStream & rIStream ); - - DecompressStatus DecompressScanline(sal_uInt8 * pTarget, sal_uInt64 nTargetBits, bool bLastLine); - -private: - - void MakeLookUp(const CCIHuffmanTableEntry * pHufTab, - const CCIHuffmanTableEntry * pHufTabSave, - CCILookUpTableEntry * pLookUp, - sal_uInt16 nHuffmanTableSize, - sal_uInt16 nMaxCodeBits); - - bool ReadEOL(); - - bool Read2DTag(); - - sal_uInt8 ReadBlackOrWhite(); - - sal_uInt16 ReadCodeAndDecode(const CCILookUpTableEntry * pLookUp, - sal_uInt16 nMaxCodeBits); - - static void FillBits(sal_uInt8 * pTarget, sal_uInt16 nTargetBits, - sal_uInt16 nBitPos, sal_uInt16 nNumBits, - sal_uInt8 nBlackOrWhite); - - static sal_uInt16 CountBits(const sal_uInt8 * pData, sal_uInt16 nDataSizeBits, - sal_uInt16 nBitPos, sal_uInt8 nBlackOrWhite); - - //returns true if pTarget was unmodified - bool Read1DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits); - bool Read2DScanlineData(sal_uInt8 * pTarget, sal_uInt16 nTargetBits); - - bool bTableBad; - - bool bStatus; - - std::unique_ptr<sal_uInt8[]> pByteSwap; - - SvStream * pIStream; - - sal_uInt32 nEOLCount; - - sal_uInt32 nWidth; - - sal_uInt32 nOptions; - - bool bFirstEOL; - - std::array<CCILookUpTableEntry, 1<<13> pWhiteLookUp; - std::array<CCILookUpTableEntry, 1<<13> pBlackLookUp; - std::array<CCILookUpTableEntry, 1<<10> p2DModeLookUp; - std::array<CCILookUpTableEntry, 1<<11> pUncompLookUp; - - sal_uInt32 nInputBitsBuf; - sal_uInt16 nInputBitsBufSize; - - std::unique_ptr<sal_uInt8[]> pLastLine; - sal_uInt64 nLastLineSize; -}; - - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/graphicfilter/itiff/itiff.cxx b/filter/source/graphicfilter/itiff/itiff.cxx deleted file mode 100644 index f07e496bc347..000000000000 --- a/filter/source/graphicfilter/itiff/itiff.cxx +++ /dev/null @@ -1,1734 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include <sal/config.h> -#include <sal/log.hxx> - -#include <unotools/configmgr.hxx> -#include <vcl/FilterConfigItem.hxx> -#include <vcl/graph.hxx> -#include <vcl/BitmapTools.hxx> -#include <vcl/animate/Animation.hxx> -#include <tools/fract.hxx> -#include <tools/stream.hxx> -#include "lzwdecom.hxx" -#include "ccidecom.hxx" - -namespace { - -template< typename T > T BYTESWAP(T nByte) { - return ( nByte << 7 ) | ( ( nByte & 2 ) << 5 ) | ( ( nByte & 4 ) << 3 ) | - ( ( nByte & 8 ) << 1 ) | ( ( nByte & 16 ) >> 1 ) | - ( ( nByte & 32 ) >> 3 ) | ( ( nByte & 64 ) >> 5 ) | - ( ( nByte & 128 ) >> 7 ); -} - -//============================ TIFFReader ================================== - -class TIFFReader -{ - -private: - - bool bStatus; // Whether until now no error occurred - Animation aAnimation; - - SvStream* pTIFF; // the TIFF file that should be read - std::vector<sal_uInt8> maBitmap; - Size maBitmapPixelSize; - std::vector<Color> mvPalette; - MapMode maBitmapPrefMapMode; - Size maBitmapPrefSize; - sal_uInt16 nDstBitsPerPixel; - int nLargestPixelIndex; - - sal_uInt64 nOrigPos; // start position in pTIFF - sal_uInt64 nEndOfFile; // end of file position in pTIFF - - - sal_uInt16 nDataType; - // Data taken from the TIFF tags: - bool bByteSwap; // sal_True if bits 0..7 -> 7..0 should get converted ( FILLORDER = 2 ); - - sal_uInt32 nNewSubFile; - sal_uInt32 nSubFile; - sal_Int32 nImageWidth; // picture width in pixels - sal_Int32 nImageLength; // picture height in pixels - sal_uInt32 nBitsPerSample; // bits per pixel per layer - sal_uInt32 nCompression; // kind of compression - sal_uInt32 nPhotometricInterpretation; - sal_uInt32 nThresholding; - sal_uInt32 nCellWidth; - sal_uInt32 nCellLength; - sal_uInt32 nFillOrder; - std::vector<sal_uInt64> aStripOffsets; // field of offsets to the Bitmap-Data-"Strips" - sal_uInt32 nOrientation; - sal_uInt32 nSamplesPerPixel; // number of layers - sal_uInt32 nRowsPerStrip; // if it's not compressed: number of rows per Strip - std::vector<sal_uInt32> aStripByteCounts; // if compressed (in a certain way): size of the strips - sal_uInt32 nMinSampleValue; - sal_uInt32 nMaxSampleValue; - double fXResolution; // X-resolution or 0.0 - double fYResolution; // Y-resolution or 0.0 - sal_uInt32 nPlanarConfiguration; - sal_uInt32 nGroup3Options; - sal_uInt32 nGroup4Options; - sal_uInt32 nResolutionUnit; // unit of fX/YResolution: 1=unknown, 2(default)=inch, 3=cm - sal_uInt32 nPredictor; - std::vector<sal_uInt32> aColorMap; // color palette - sal_uInt32 nNumColors; // number of colors within the color palette - - sal_uInt32 nPlanes; // number of layers within the Tiff file - sal_uInt32 nStripsPerPlane; // number of Strips per layer - sal_uInt32 nBytesPerRow; // Bytes per line per Layer in the Tiff file ( uncompressed ) - std::vector<sal_uInt8> aMap[4]; // temporary Scanline - - - sal_uInt32 DataTypeSize(); - sal_uInt32 ReadIntData(); - double ReadDoubleData(); - - void ReadHeader(); - void ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen ); - - sal_uInt8* getMapData(sal_uInt32 np); - - bool ReadMap(); - // reads/decompress the bitmap data and fills aMap - - sal_uInt32 GetBits(const sal_uInt8 * pSrc, sal_uInt32 nBitsPos, sal_uInt32 nBitsCount); - // fetches BitsCount bits from pSrc[..] at the position nBitsPos - - void MakePalCol(); - // Create the bitmap from the temporary bitmap aMap - // and partly deletes aMap while doing this. - - bool ConvertScanline(sal_Int32 nY); - // converts a Scanline to the Windows-BMP format - - bool HasAlphaChannel() const; - - void SetPixel(tools::Long nY, tools::Long nX, sal_uInt8 cIndex); - void SetPixel(tools::Long nY, tools::Long nX, Color c); - void SetPixelAlpha(tools::Long nY, tools::Long nX, sal_uInt8 nAlpha); - -public: - - TIFFReader() - : bStatus(false) - , pTIFF(nullptr) - , nDstBitsPerPixel(0) - , nLargestPixelIndex(-1) - , nOrigPos(0) - , nEndOfFile(0) - , nDataType(0) - , bByteSwap(false) - , nNewSubFile(0) - , nSubFile(0) - , nImageWidth(0) - , nImageLength(0) - , nBitsPerSample(1) - , nCompression(1) - , nPhotometricInterpretation(0) - , nThresholding(1) - , nCellWidth(1) - , nCellLength(1) - , nFillOrder(1) - , nOrientation(1) - , nSamplesPerPixel(1) - , nRowsPerStrip(0xffffffff) - , nMinSampleValue(0) - , nMaxSampleValue(0) - , fXResolution(0.0) - , fYResolution(0.0) - , nPlanarConfiguration(1) - , nGroup3Options(0) - , nGroup4Options(0) - , nResolutionUnit(2) - , nPredictor(0) - , nNumColors(0) - , nPlanes(0) - , nStripsPerPlane(0) - , nBytesPerRow(0) - { - } - - sal_uInt32 GetRowsPerStrip() const - { - //Rows Per Strip: - // - //(TIFF format only) The number of rows of pixels per strip to use for - //encoding the TIFF image. A value greater than zero specifies the - //number of rows per strip. A value of 0 sets the rows per strip equal - //to the image length, resulting in a single strip. A value of -1 (the - //default) sets the rows per strip equal to infinity, resulting in a - //single strip. - return nRowsPerStrip == 0 ? nImageLength : nRowsPerStrip; - } - - bool ReadTIFF( SvStream & rTIFF, Graphic & rGraphic ); -}; - -} - -//=================== Methods of TIFFReader ============================== - -sal_uInt32 TIFFReader::DataTypeSize() -{ - sal_uInt32 nSize; - switch ( nDataType ) - { - case 1 : // BYTE - case 2 : // ASCII - case 6 : // SIGNED Byte - case 7 : // UNDEFINED - nSize = 1; - break; - case 3 : // UINT16 - case 8 : // INT16 - nSize = 2; - break; - case 4 : // UINT32 - case 9 : // INT32 - case 11 : // FLOAT - nSize = 4; - break; - case 5 : // RATIONAL - case 10 : // SIGNED RATIONAL - case 12 : // DOUBLE - nSize = 8; - break; - default: - pTIFF->SetError(SVSTREAM_FILEFORMAT_ERROR); - nSize=1; - } - return nSize; -} - -sal_uInt32 TIFFReader::ReadIntData() -{ - double nDOUBLE(0.0); - float nFLOAT(0); - sal_uInt32 nUINT32a(0), nUINT32b(0); - sal_Int32 nINT32(0); - sal_uInt16 nUINT16(0); - sal_Int16 nINT16(0); - sal_uInt8 nBYTE(0); - char nCHAR(0); - - switch( nDataType ) - { - case 0 : //?? - case 1 : - case 2 : - case 7 : - pTIFF->ReadUChar( nBYTE ); - nUINT32a = nBYTE; - break; - case 3 : - pTIFF->ReadUInt16( nUINT16 ); - nUINT32a = nUINT16; - break; - case 9 : - case 4 : - pTIFF->ReadUInt32( nUINT32a ); - break; - case 5 : - pTIFF->ReadUInt32( nUINT32a ).ReadUInt32( nUINT32b ); - if ( nUINT32b != 0 ) - nUINT32a /= nUINT32b; - break; - case 6 : - pTIFF->ReadChar( nCHAR ); - nUINT32a = static_cast<sal_Int32>(nCHAR); - break; - case 8 : - pTIFF->ReadInt16( nINT16 ); - nUINT32a = static_cast<sal_Int32>(nINT16); - break; - case 10 : - pTIFF->ReadUInt32( nUINT32a ).ReadInt32( nINT32 ); - if ( nINT32 != 0 ) - nUINT32a /= nINT32; - break; - case 11 : - pTIFF->ReadFloat( nFLOAT ); - if (!std::isnan(nFLOAT) && nFLOAT > SAL_MIN_INT32 - 1.0 - && nFLOAT < SAL_MAX_INT32 + 1.0) - { - nUINT32a = static_cast<sal_Int32>(nFLOAT); - } - else - { - SAL_INFO("filter.tiff", "float " << nFLOAT << " outsider of sal_Int32 range"); - } - break; - case 12 : - pTIFF->ReadDouble( nDOUBLE ); - if (!std::isnan(nDOUBLE) && nDOUBLE > SAL_MIN_INT32 - 1.0 - && nDOUBLE < SAL_MAX_INT32 + 1.0) - { - nUINT32a = static_cast<sal_Int32>(nDOUBLE); - } - else - { - SAL_INFO("filter.tiff", "double " << nDOUBLE << " outsider of sal_Int32 range"); - } - break; - default: - pTIFF->ReadUInt32( nUINT32a ); - break; - } - return nUINT32a; -} - -double TIFFReader::ReadDoubleData() -{ - switch (nDataType) { - case 5: - { - sal_uInt32 nulong(0); - pTIFF->ReadUInt32( nulong ); - double nd = static_cast<double>(nulong); - nulong = 0; - pTIFF->ReadUInt32( nulong ); - if ( nulong != 0 ) - nd /= static_cast<double>(nulong); - return nd; - } - - case 11: - { - float x = 0; - pTIFF->ReadFloat(x); - return x; - } - - case 12: - { - double x = 0; - pTIFF->ReadDouble(x); - return x; - } - - default: - return static_cast<double>(ReadIntData()); - } -} - -void TIFFReader::ReadTagData( sal_uInt16 nTagType, sal_uInt32 nDataLen) -{ - if ( !bStatus ) - return; - - switch ( nTagType ) - { - case 0x00fe: // New Sub File - nNewSubFile = ReadIntData(); - SAL_INFO("filter.tiff","NewSubFile: " << nNewSubFile); - break; - - case 0x00ff: // Sub File - nSubFile = ReadIntData(); - SAL_INFO("filter.tiff","SubFile: " << nSubFile); - break; - - case 0x0100: // Image Width - nImageWidth = ReadIntData(); - SAL_INFO("filter.tiff","ImageWidth: " << nImageWidth); - break; - - case 0x0101: // Image Length - nImageLength = ReadIntData(); - SAL_INFO("filter.tiff","ImageLength: " << nImageLength); - break; - - case 0x0102: // Bits Per Sample - nBitsPerSample = ReadIntData(); - SAL_INFO("filter.tiff","BitsPerSample: " << nBitsPerSample); - if ( nBitsPerSample >= 32 ) // 32 bit and larger samples are not supported - bStatus = false; - break; - - case 0x0103: // Compression - nCompression = ReadIntData(); - SAL_INFO("filter.tiff","Compression: " << nCompression); - break; - - case 0x0106: // Photometric Interpretation - nPhotometricInterpretation = ReadIntData(); - SAL_INFO("filter.tiff","PhotometricInterpretation: " << nPhotometricInterpretation); - break; - - case 0x0107: // Thresholding - nThresholding = ReadIntData(); - SAL_INFO("filter.tiff","Thresholding: " << nThresholding); - break; - - case 0x0108: // Cell Width - nCellWidth = ReadIntData(); - break; - - case 0x0109: // Cell Length - nCellLength = ReadIntData(); - break; - - case 0x010a: // Fill Order - nFillOrder = ReadIntData(); - SAL_INFO("filter.tiff","FillOrder: " << nFillOrder); - break; - - case 0x0111: { // Strip Offset(s) - size_t nOldNumSO = aStripOffsets.size(); - nDataLen += nOldNumSO; - size_t const nMaxAllocAllowed = SAL_MAX_UINT32 / sizeof(sal_uInt32); - size_t nMaxRecordsAvailable = pTIFF->remainingSize() / DataTypeSize(); - if (nDataLen > nOldNumSO && nDataLen < nMaxAllocAllowed && - (nDataLen - nOldNumSO) <= nMaxRecordsAvailable) - { - try - { - aStripOffsets.resize(nDataLen); - if (nOrigPos) - { - for (size_t i = 0; i < nOldNumSO; ++i) - aStripOffsets[i] += nOrigPos; - } - for (size_t i = nOldNumSO; i < aStripOffsets.size(); ++i) - aStripOffsets[i] = ReadIntData() + nOrigPos; - } - catch (const std::bad_alloc &) - { - aStripOffsets.clear(); - } - } - SAL_INFO("filter.tiff","StripOffsets (Number:) " << nDataLen); - break; - } - case 0x0112: // Orientation - nOrientation = ReadIntData(); - SAL_INFO("filter.tiff","Orientation: " << nOrientation); - break; - - case 0x0115: // Samples Per Pixel - nSamplesPerPixel = ReadIntData(); - SAL_INFO("filter.tiff","SamplesPerPixel: " << nSamplesPerPixel); - - if (nSamplesPerPixel > USHRT_MAX) // ofz#15993 the expected type is SHORT - bStatus = false; - - break; - - case 0x0116: // Rows Per Strip - nRowsPerStrip = ReadIntData(); - SAL_INFO("filter.tiff","RowsPerStrip: " << nRowsPerStrip); - break; - - case 0x0117: { // Strip Byte Counts - size_t nOldNumSBC = aStripByteCounts.size(); - nDataLen += nOldNumSBC; - size_t const nMaxAllocAllowed = SAL_MAX_UINT32 / sizeof(sal_uInt32); - size_t nMaxRecordsAvailable = pTIFF->remainingSize() / DataTypeSize(); - if (nDataLen > nOldNumSBC && nDataLen < nMaxAllocAllowed && - (nDataLen - nOldNumSBC) <= nMaxRecordsAvailable) - { - try - { - aStripByteCounts.resize(nDataLen); - for (size_t i = nOldNumSBC; i < aStripByteCounts.size(); ++i) - aStripByteCounts[i] = ReadIntData(); - } - catch (const std::bad_alloc &) - { - aStripByteCounts.clear(); - } - } - SAL_INFO("filter.tiff","StripByteCounts (Number:) " << nDataLen); - break; - } - case 0x0118: // Min Sample Value - nMinSampleValue = ReadIntData(); - SAL_INFO("filter.tiff","MinSampleValue: " << nMinSampleValue); - break; - - case 0x0119: // Max Sample Value - nMaxSampleValue = ReadIntData(); - SAL_INFO("filter.tiff","MaxSampleValue: " << nMaxSampleValue); - break; - - case 0x011a: // X Resolution - fXResolution = ReadDoubleData(); - break; - - case 0x011b: // Y Resolution - fYResolution = ReadDoubleData(); - break; - - case 0x011c: // Planar Configuration - nPlanarConfiguration = ReadIntData(); - SAL_INFO("filter.tiff","PlanarConfiguration: " << nPlanarConfiguration); - break; - - case 0x0124: // Group 3 Options - nGroup3Options = ReadIntData(); - SAL_INFO("filter.tiff","Group3Options: " << nGroup3Options); - break; - - case 0x0125: // Group 4 Options - nGroup4Options = ReadIntData(); - SAL_INFO("filter.tiff","Group4Options: " << nGroup4Options); - break; - - case 0x0128: // Resolution Unit - nResolutionUnit = ReadIntData(); - break; - - case 0x013d: // Predictor - nPredictor = ReadIntData(); - SAL_INFO("filter.tiff","Predictor: " << nPredictor); - break; - - case 0x0140: { // Color Map - sal_uInt16 nVal; - nNumColors = (sal_uInt32(1) << nBitsPerSample); - if ( nDataType == 3 && nNumColors <= 256) - { - aColorMap.resize(256); - for (sal_uInt32 i = 0; i < nNumColors; ++i) - aColorMap[i] = 0; - for (sal_uInt32 i = 0; i < nNumColors; ++i) - { - pTIFF->ReadUInt16( nVal ); - aColorMap[i] |= ( static_cast<sal_uInt32>(nVal) << 8 ) & 0x00ff0000; - } - for (sal_uInt32 i = 0; i < nNumColors; ++i) - { - pTIFF->ReadUInt16( nVal ); - aColorMap[i] |= static_cast<sal_uInt32>(nVal) & 0x0000ff00; - } - for (sal_uInt32 i = 0; i < nNumColors; ++i) - { - pTIFF->ReadUInt16( nVal ); - aColorMap[i] |= ( static_cast<sal_uInt32>(nVal) >> 8 ) & 0x000000ff; - } - } - else - bStatus = false; - SAL_INFO("filter.tiff","ColorMap (number of colors): " << nNumColors); - break; - } - - case 0x0153: { // SampleFormat - sal_uInt32 nSampleFormat = ReadIntData(); - if ( nSampleFormat == 3 ) // IEEE floating point samples are not supported yet - bStatus = false; - break; - } - } - - if ( pTIFF->GetError() ) - bStatus = false; -} - -sal_uInt8* TIFFReader::getMapData(sal_uInt32 np) -{ - aMap[np].resize(nBytesPerRow); - return aMap[np].data(); -} - -bool TIFFReader::ReadMap() -{ - //when fuzzing with a max len set, max decompress to 250 times that limit - static size_t nMaxAllowedDecompression = [](const char* pEnv) { size_t nRet = pEnv ? std::atoi(pEnv) : 0; return nRet * 250; }(std::getenv("FUZZ_MAX_INPUT_LEN")); - size_t nTotalDataRead = 0; - - if ( nCompression == 1 || nCompression == 32771 ) - { - sal_uInt32 nStripBytesPerRow; - - if ( nCompression == 1 ) - nStripBytesPerRow = nBytesPerRow; - else - nStripBytesPerRow = ( nBytesPerRow + 1 ) & 0xfffffffe; - for (sal_Int32 ny = 0; ny < nImageLength; ++ny) - { - for (sal_uInt32 np = 0; np < nPlanes; ++np) - { - if (np >= SAL_N_ELEMENTS(aMap)) - return false; - sal_uInt32 nStrip = ny / GetRowsPerStrip() + np * nStripsPerPlane; - if ( nStrip >= aStripOffsets.size()) - return false; - pTIFF->Seek( aStripOffsets[ nStrip ] + ( ny % GetRowsPerStrip() ) * nStripBytesPerRow ); - // tdf#126147 allow a short incomplete read - auto pDest = getMapData(np); - auto nRead = pTIFF->ReadBytes(pDest, nBytesPerRow); - if (nRead != nBytesPerRow) - memset(pDest + nRead, 0, nBytesPerRow - nRead); - } - if ( !ConvertScanline( ny ) ) - return false; - } - } - else if ( nCompression == 2 || nCompression == 3 || nCompression == 4 ) - { - sal_uInt32 nOptions; - if ( nCompression == 2 ) - { - nOptions = CCI_OPTION_BYTEALIGNROW; - } - else if ( nCompression == 3 ) - { - nOptions = CCI_OPTION_EOL; - if ( nGroup3Options & 0x00000001 ) - nOptions |= CCI_OPTION_2D; - if ( nGroup3Options & 0x00000004 ) - nOptions |= CCI_OPTION_BYTEALIGNEOL; - if ( nGroup3Options & 0xfffffffa ) - return false; - } - else - { // nCompression==4 - nOptions = CCI_OPTION_2D; - if ( nGroup4Options & 0xffffffff ) - return false; - } - if ( nFillOrder == 2 ) - { - nOptions |= CCI_OPTION_INVERSEBITORDER; - bByteSwap = false; - } - sal_uInt32 nStrip = 0; - if (nStrip >= aStripOffsets.size()) - return false; - sal_uInt64 nOffset = aStripOffsets[nStrip]; - if (nOffset > nEndOfFile) - return false; - pTIFF->Seek(aStripOffsets[nStrip]); - - CCIDecompressor aCCIDecom( nOptions, nImageWidth ); - - aCCIDecom.StartDecompression( *pTIFF ); - - const bool bHasAlphaChannel = HasAlphaChannel(); - for (sal_Int32 ny = 0; ny < nImageLength; ++ny) - { - bool bDifferentToPrev = ny == 0; - for (sal_uInt32 np = 0; np < nPlanes; ++np) - { - if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip ) - { - nStrip=ny/GetRowsPerStrip()+np*nStripsPerPlane; - if (nStrip >= aStripOffsets.size()) - return false; - nOffset = aStripOffsets[nStrip]; - if (nOffset > nEndOfFile) - return false; - pTIFF->Seek(nOffset); - aCCIDecom.StartDecompression( *pTIFF ); - } - if (np >= SAL_N_ELEMENTS(aMap)) - return false; - DecompressStatus aResult = aCCIDecom.DecompressScanline(getMapData(np), nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes, np + 1 == nPlanes); - if (!aResult.m_bSuccess) - return false; - bDifferentToPrev |= !aResult.m_bBufferUnchanged; - if ( pTIFF->GetError() ) - return false; - nTotalDataRead += nBytesPerRow; - if (nMaxAllowedDecompression && nTotalDataRead > nMaxAllowedDecompression) - return false; - } - if (!bDifferentToPrev) - { - //if the buffer for this line didn't change, then just copy the - //previous scanline instead of painfully decoding and setting - //each pixel one by one again - const int nColorSize = bHasAlphaChannel ? 4 : 3; - memcpy( maBitmap.data() + (ny * maBitmapPixelSize.Width()) * nColorSize, - maBitmap.data() + ((ny-1) * maBitmapPixelSize.Width()) * nColorSize, - maBitmapPixelSize.Width() * nColorSize); - } - else - { - if (!ConvertScanline(ny)) - return false; - } - } - } - else if ( nCompression == 5 ) - { - LZWDecompressor aLZWDecom; - sal_uInt32 nStrip(0); - if (nStrip >= aStripOffsets.size()) - return false; - pTIFF->Seek(aStripOffsets[nStrip]); - aLZWDecom.StartDecompression(*pTIFF); - for (sal_Int32 ny = 0; ny < nImageLength; ++ny) - { - for (sal_uInt32 np = 0; np < nPlanes; ++np) - { - if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip ) - { - nStrip = ny / GetRowsPerStrip() + np * nStripsPerPlane; - if (nStrip >= aStripOffsets.size()) - return false; - pTIFF->Seek(aStripOffsets[nStrip]); - aLZWDecom.StartDecompression(*pTIFF); - } - if (np >= SAL_N_ELEMENTS(aMap)) - return false; - if ( ( aLZWDecom.Decompress(getMapData(np), nBytesPerRow) != nBytesPerRow ) || pTIFF->GetError() ) - return false; - } - - nTotalDataRead += nBytesPerRow; - if (nMaxAllowedDecompression && nTotalDataRead > nMaxAllowedDecompression) - return false; - - if ( !ConvertScanline( ny ) ) - return false; - } - } - else if ( nCompression == 32773 ) - { - sal_uInt32 nStrip(0); - if (nStrip >= aStripOffsets.size()) - return false; - pTIFF->Seek(aStripOffsets[nStrip]); - for (sal_Int32 ny = 0; ny < nImageLength; ++ny) - { - for (sal_uInt32 np = 0; np < nPlanes; ++np) - { - if ( ny / GetRowsPerStrip() + np * nStripsPerPlane > nStrip ) - { - nStrip=ny/GetRowsPerStrip()+np*nStripsPerPlane; - if (nStrip >= aStripOffsets.size()) - return false; - pTIFF->Seek(aStripOffsets[nStrip]); - } - sal_uInt32 nRowBytesLeft = nBytesPerRow; - if (np >= SAL_N_ELEMENTS(aMap)) - return false; - sal_uInt8* pdst = getMapData(np); - do - { - sal_uInt8 nRecHeader(0); - pTIFF->ReadUChar(nRecHeader); - sal_uInt32 nRecCount; - if ((nRecHeader&0x80)==0) - { - nRecCount=0x00000001 + static_cast<sal_uInt32>(nRecHeader); - if ( nRecCount > nRowBytesLeft ) - return false; - pTIFF->ReadBytes(pdst, nRecCount); - if (!pTIFF->good()) - return false; - pdst+=nRecCount; - nRowBytesLeft-=nRecCount; - } - else if ( nRecHeader != 0x80 ) - { - nRecCount = 0x000000101 - static_cast<sal_uInt32>(nRecHeader); - if ( nRecCount > nRowBytesLeft ) - { - nRecCount = nRowBytesLeft; - } - sal_uInt8 nRecData(0); - pTIFF->ReadUChar( nRecData ); - for (sal_uInt32 i = 0; i < nRecCount; ++i) - *(pdst++) = nRecData; - nRowBytesLeft -= nRecCount; - } - } while ( nRowBytesLeft != 0 ); - if ( pTIFF->GetError() ) - return false; - } - if ( !ConvertScanline( ny ) ) - return false; - } - } - else - return false; - return true; -} - -sal_uInt32 TIFFReader::GetBits( const sal_uInt8 * pSrc, sal_uInt32 nBitsPos, sal_uInt32 nBitsCount) -{ - sal_uInt32 nRes; - if ( bByteSwap ) - { - pSrc += ( nBitsPos >> 3 ); - nBitsPos &= 7; - sal_uInt8 nDat = *pSrc; - nRes = static_cast<sal_uInt32>( BYTESWAP( nDat ) & ( 0xff >> nBitsPos ) ); - - if ( nBitsCount <= 8 - nBitsPos ) - { - nRes >>= ( 8 - nBitsPos - nBitsCount ); - } - else - { - pSrc++; - nBitsCount -= 8 - nBitsPos; - while ( nBitsCount >= 8 ) - { - nDat = *(pSrc++); - nRes = ( nRes << 8 ) | static_cast<sal_uInt32>(BYTESWAP( nDat )); - nBitsCount -= 8; - } - if ( nBitsCount > 0 ) - { - nDat = *pSrc; - nRes = ( nRes << nBitsCount ) | (static_cast<sal_uInt32>(BYTESWAP(nDat))>>(8-nBitsCount)); - } - } - } - else - { - pSrc += ( nBitsPos >> 3 ); - nBitsPos &= 7; - nRes = static_cast<sal_uInt32>((*pSrc)&(0xff>>nBitsPos)); - if ( nBitsCount <= 8 - nBitsPos ) - { - nRes >>= ( 8 - nBitsPos - nBitsCount ); - } - else - { - pSrc++; - nBitsCount -= 8 - nBitsPos; - while ( nBitsCount >= 8 ) - { - nRes = ( nRes << 8 ) | static_cast<sal_uInt32>(*(pSrc++)); - nBitsCount -= 8; - } - if ( nBitsCount > 0 ) - nRes = ( nRes << nBitsCount ) | (static_cast<sal_uInt32>(*pSrc)>>(8-nBitsCount)); - } - } - return nRes; -} - -void TIFFReader::SetPixel(tools::Long nY, tools::Long nX, sal_uInt8 cIndex) -{ - maBitmap[(maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3)] = cIndex; - nLargestPixelIndex = std::max<int>(nLargestPixelIndex, cIndex); -} - -void TIFFReader::SetPixel(tools::Long nY, tools::Long nX, Color c) -{ - auto p = maBitmap.data() + ((maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3)); - *p = c.GetRed(); - p++; - *p = c.GetGreen(); - p++; - *p = c.GetBlue(); - if (HasAlphaChannel()) - { - p++; - *p = 0xff; // alpha - } -} - -void TIFFReader::SetPixelAlpha(tools::Long nY, tools::Long nX, sal_uInt8 nAlpha) -{ - assert(HasAlphaChannel()); - maBitmap[((maBitmapPixelSize.Width() * nY + nX) * 4) + 3] = nAlpha; -} - -bool TIFFReader::ConvertScanline(sal_Int32 nY) -{ - sal_uInt32 nRed, nGreen, nBlue, ns, nVal; - sal_uInt8 nByteVal; - - if ( nDstBitsPerPixel == 24 ) - { - if ( nBitsPerSample == 8 && nSamplesPerPixel >= 3 && - nPlanes == 1 && nPhotometricInterpretation == 2 ) - { - sal_uInt8* pt = getMapData(0); - - // are the values being saved as difference? - if ( 2 == nPredictor ) - { - sal_uInt8 nLRed = 0; - sal_uInt8 nLGreen = 0; - sal_uInt8 nLBlue = 0; - sal_uInt8 nLAlpha = 0; - for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel) - { - // The following computations rely on sal_uInt8 wrap-around when adding the - // (unsigned) pt deltas; the "& 0xFF" is only conceptual, but helps prevent - // sanitizer warnings: - nLRed = (nLRed + pt[ 0 ]) & 0xFF; - nLGreen = (nLGreen + pt[ 1 ]) & 0xFF; - nLBlue = (nLBlue + pt[ 2 ]) & 0xFF; - SetPixel(nY, nx, Color(nLRed, nLGreen, nLBlue)); - if (HasAlphaChannel()) - { - nLAlpha = (nLAlpha + pt[ 3 ]) & 0xFF; - SetPixelAlpha(nY, nx, ~nLAlpha); - } - } - } - else - { - for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += nSamplesPerPixel) - { - SetPixel(nY, nx, Color(pt[0], pt[1], pt[2])); - if (HasAlphaChannel()) - { - sal_uInt8 nAlpha = pt[3]; - SetPixelAlpha(nY, nx, ~nAlpha); - } - } - } - } - else if ( nPhotometricInterpretation == 2 && nSamplesPerPixel >= 3 ) - { - if ( nMaxSampleValue > nMinSampleValue ) - { - sal_uInt32 nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue ); - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) - { - if ( nPlanes < 3 ) - { - nRed = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample ); - nGreen = GetBits( getMapData(1), ( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample ); - nBlue = GetBits( getMapData(2), ( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample ); - } - else - { - nRed = GetBits( getMapData(0), nx * nBitsPerSample, nBitsPerSample ); - nGreen = GetBits( getMapData(1), nx * nBitsPerSample, nBitsPerSample ); - nBlue = GetBits( getMapData(2), nx * nBitsPerSample, nBitsPerSample ); - } - SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed - nMinMax), static_cast<sal_uInt8>(nGreen - nMinMax), static_cast<sal_uInt8>(nBlue - nMinMax))); - } - } - } - else if ( nPhotometricInterpretation == 5 && nSamplesPerPixel == 3 ) - { - if ( nMaxSampleValue > nMinSampleValue ) - { - sal_uInt32 nMinMax = nMinSampleValue * 255 / ( nMaxSampleValue - nMinSampleValue ); - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) - { - if ( nPlanes < 3 ) - { - nRed = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 0 ) * nBitsPerSample, nBitsPerSample ); - nGreen = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 1 ) * nBitsPerSample, nBitsPerSample ); - nBlue = GetBits( getMapData(0), ( nx * nSamplesPerPixel + 2 ) * nBitsPerSample, nBitsPerSample ); - } - else - { - nRed = GetBits( getMapData(0), nx * nBitsPerSample, nBitsPerSample ); - nGreen = GetBits( getMapData(1), nx * nBitsPerSample, nBitsPerSample ); - nBlue = GetBits( getMapData(2), nx * nBitsPerSample, nBitsPerSample ); - } - nRed = 255 - static_cast<sal_uInt8>( nRed - nMinMax ); - nGreen = 255 - static_cast<sal_uInt8>( nGreen - nMinMax ); - nBlue = 255 - static_cast<sal_uInt8>( nBlue - nMinMax ); - SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed), static_cast<sal_uInt8>(nGreen), static_cast<sal_uInt8>(nBlue))); - } - } - } - else if( nPhotometricInterpretation == 5 && nSamplesPerPixel == 4 ) - { - if ( nMaxSampleValue > nMinSampleValue ) - { - sal_uInt8 nSamp[ 4 ]; - sal_uInt8 nSampLast[ 4 ] = { 0, 0, 0, 0 }; - - for(sal_Int32 nx = 0; nx < nImageWidth; ++nx) - { - // are the values being saved as difference? - if( 2 == nPredictor ) - { - for( ns = 0; ns < 4; ns++ ) - { - if( nPlanes < 3 ) - nSampLast[ ns ] = nSampLast[ ns ] + static_cast<sal_uInt8>(GetBits( getMapData(0), ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample )); - else - nSampLast[ ns ] = nSampLast[ ns ] + static_cast<sal_uInt8>(GetBits( getMapData(ns), nx * nBitsPerSample, nBitsPerSample )); - nSamp[ ns ] = nSampLast[ ns ]; - } - } - else - { - for( ns = 0; ns < 4; ns++ ) - { - if( nPlanes < 3 ) - nSamp[ ns ] = static_cast<sal_uInt8>(GetBits( getMapData(0), ( nx * nSamplesPerPixel + ns ) * nBitsPerSample, nBitsPerSample )); - else - nSamp[ ns ]= static_cast<sal_uInt8>(GetBits( getMapData(ns), nx * nBitsPerSample, nBitsPerSample )); - } - } - const tools::Long nBlack = nSamp[ 3 ]; - nRed = static_cast<sal_uInt8>(std::max<sal_Int32>( 0, 255 - ( ( static_cast<sal_Int32>(nSamp[ 0 ]) + nBlack - static_cast<sal_Int32>(nMinSampleValue << 1U ) ) * - 255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) )); - nGreen = static_cast<sal_uInt8>(std::max<sal_Int32>( 0, 255 - ( ( static_cast<sal_Int32>(nSamp[ 1 ]) + nBlack - static_cast<sal_Int32>(nMinSampleValue << 1U ) ) * - 255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) )); - nBlue = static_cast<sal_uInt8>(std::max<sal_Int32>( 0, 255 - ( ( static_cast<sal_Int32>(nSamp[ 2 ]) + nBlack - static_cast<sal_Int32>(nMinSampleValue << 1U ) ) * - 255L/static_cast<sal_Int32>(nMaxSampleValue-nMinSampleValue) ) )); - SetPixel(nY, nx, Color(static_cast<sal_uInt8>(nRed), static_cast<sal_uInt8>(nGreen), static_cast<sal_uInt8>(nBlue))); - } - } - } - } - else if ( nSamplesPerPixel == 1 && ( nPhotometricInterpretation <= 1 || nPhotometricInterpretation == 3 ) ) - { - if ( nMaxSampleValue > nMinSampleValue ) - { - sal_uInt32 nMinMax = ( ( 1 << nDstBitsPerPixel ) - 1 ) / ( nMaxSampleValue - nMinSampleValue ); - sal_uInt8* pt = getMapData(0); - sal_uInt8* ptend = pt + nBytesPerRow; - sal_uInt8 nShift; - - switch ( nDstBitsPerPixel ) - { - case 8 : - { - if (pt + nImageWidth > ptend) - return false; - - if ( bByteSwap ) - { - if ( nPredictor == 2 ) - { - sal_uInt8 nLast = 0; - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) - { - nLast += nx == 0 ? BYTESWAP( *pt++ ) : *pt++; - SetPixel(nY, nx, nLast); - } - } - else - { - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) - { - sal_uInt8 nLast = *pt++; - SetPixel(nY, nx, static_cast<sal_uInt8>( (BYTESWAP(static_cast<sal_uInt32>(nLast)) - nMinSampleValue) * nMinMax )); - } - } - } - else - { - if ( nPredictor == 2 ) - { - sal_uInt8 nLast = 0; - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) - { - nLast += *pt++; - SetPixel(nY, nx, nLast); - } - } - else - { - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) - { - SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(*pt++) - nMinSampleValue) * nMinMax )); - } - } - } - } - break; - - case 7 : - case 6 : - case 5 : - case 4 : - case 3 : - case 2 : - { - for (sal_Int32 nx = 0; nx < nImageWidth; ++nx) - { - nVal = ( GetBits( pt, nx * nBitsPerSample, nBitsPerSample ) - nMinSampleValue ) * nMinMax; - SetPixel(nY, nx, static_cast<sal_uInt8>(nVal)); - } - } - break; - - case 1 : - { - sal_uInt32 nByteCount = nImageWidth >> 3; - - sal_uInt32 nBytesNeeded = nByteCount; - if (nImageWidth & 7) - ++nBytesNeeded; - if (pt + nBytesNeeded > ptend) - return false; - - if ( bByteSwap ) - { - sal_Int32 nx = 0; - while (nByteCount--) - { - nByteVal = *pt++; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, nx++, nByteVal); - } - if ( nImageWidth & 7 ) - { - nByteVal = *pt++; - while ( nx < nImageWidth ) - { - SetPixel(nY, nx++, nByteVal & 1); - nByteVal >>= 1; - } - } - } - else - { - sal_Int32 nx = 7; - while (nByteCount--) - { - nByteVal = *pt++; - SetPixel(nY, nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal & 1); - nByteVal >>= 1; - SetPixel(nY, --nx, nByteVal); - nx += 15; - } - if ( nImageWidth & 7 ) - { - nx -= 7; - nByteVal = *pt++; - nShift = 7; - while ( nx < nImageWidth ) - { - SetPixel(nY, nx++, ( nByteVal >> nShift ) & 1); - } - } - } - } - break; - - default : - return false; - } - } - } - else if ( ( nSamplesPerPixel == 2 ) && ( nBitsPerSample == 8 ) && - ( nPlanarConfiguration == 1 ) && aColorMap.empty() ) // grayscale + alpha - { - if ( nMaxSampleValue > nMinSampleValue ) - { - sal_uInt8* pt = getMapData(0); - - if (nPredictor == 2) - { - sal_uInt8 nLastPixel = 0; - sal_uInt8 nLastAlpha = 0; - for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += 2) - { - nLastPixel = (nLastPixel + pt[0]) & 0xFF; - SetPixel(nY, nx, nLastPixel); - - nLastAlpha = (nLastAlpha + pt[1]) & 0xFF; - SetPixelAlpha(nY, nx, ~nLastAlpha); - } - } - else - { - sal_uInt32 nMinMax = ( ( 1 << 8 /*nDstBitsPerPixel*/ ) - 1 ) / ( nMaxSampleValue - nMinSampleValue ); - for (sal_Int32 nx = 0; nx < nImageWidth; nx++, pt += 2) - { - SetPixel(nY, nx, static_cast<sal_uInt8>( (static_cast<sal_uInt32>(pt[0]) - nMinSampleValue) * nMinMax )); - sal_uInt8 nAlpha = static_cast<sal_uInt8>( (static_cast<sal_uInt32>(pt[1]) - nMinSampleValue) * nMinMax ); - SetPixelAlpha(nY, nx, ~nAlpha); - } - } - } - } - else - return false; - return true; -} - -void TIFFReader::MakePalCol() -{ - if ( nDstBitsPerPixel <= 8 ) - { - aColorMap.resize(256); - if ( nPhotometricInterpretation <= 1 ) - { - nNumColors = sal_uInt32(1) << nBitsPerSample; - if ( nNumColors > 256 ) - nNumColors = 256; - - if (nLargestPixelIndex >= static_cast<int>(nNumColors)) - { - SAL_WARN("filter.tiff", "palette has less entries that largest index used. Expanding palette to match"); - nNumColors = nLargestPixelIndex + 1; - } - - for (sal_uInt32 i = 0; i < nNumColors; ++i) - { - sal_uInt32 nVal = ( i * 255 / ( nNumColors - 1 ) ) & 0xff; - sal_uInt32 n0RGB = nVal | ( nVal << 8 ) | ( nVal << 16 ); - if ( nPhotometricInterpretation == 1 ) - aColorMap[i] = n0RGB; - else - aColorMap[nNumColors - i - 1] = n0RGB; - } - } - mvPalette.resize(std::max<sal_uInt16>(nNumColors, mvPalette.size())); - for (sal_uInt32 i = 0; i < nNumColors; ++i) - { - mvPalette[i] = Color( static_cast<sal_uInt8>( aColorMap[ i ] >> 16 ), - static_cast<sal_uInt8>( aColorMap[ i ] >> 8 ), static_cast<sal_uInt8>(aColorMap[ i ]) ); - } - } - - if ( !(fXResolution > 1.0 && fYResolution > 1.0 && ( nResolutionUnit == 2 || nResolutionUnit == 3 )) ) - return; - - sal_uInt32 nRX, nRY; - if (nResolutionUnit==2) - { - nRX=static_cast<sal_uInt32>(fXResolution+0.5); - nRY=static_cast<sal_uInt32>(fYResolution+0.5); - } - else - { - nRX=static_cast<sal_uInt32>(fXResolution*2.54+0.5); - nRY=static_cast<sal_uInt32>(fYResolution*2.54+0.5); - } - MapMode aMapMode(MapUnit::MapInch,Point(0,0),Fraction(1,nRX),Fraction(1,nRY)); - maBitmapPrefMapMode = aMapMode; - maBitmapPrefSize = Size(nImageWidth,nImageLength); -} - - -void TIFFReader::ReadHeader() -{ - sal_uInt8 nbyte1(0), nbyte2(0); - sal_uInt16 nushort(0); - - pTIFF->ReadUChar( nbyte1 ); - if ( nbyte1 == 'I' ) - pTIFF->SetEndian( SvStreamEndian::LITTLE ); - else - pTIFF->SetEndian( SvStreamEndian::BIG ); - - pTIFF->ReadUChar( nbyte2 ).ReadUInt16( nushort ); - if ( nbyte1 != nbyte2 || ( nbyte1 != 'I' && nbyte1 != 'M' ) || nushort != 0x002a ) - bStatus = false; -} - -bool TIFFReader::HasAlphaChannel() const -{ - /*There are undoubtedly more variants we could support, but keep it simple for now*/ - bool bRGBA = nDstBitsPerPixel == 24 && - nBitsPerSample == 8 && - nSamplesPerPixel >= 4 && - nPlanes == 1 && - nPhotometricInterpretation == 2; - if (bRGBA) - return true; - - // additionally support the format used in tdf#126460 - bool bGrayScaleAlpha = nDstBitsPerPixel == 8 && - nBitsPerSample == 8 && - nSamplesPerPixel == 2 && - nPlanarConfiguration == 1; - - return bGrayScaleAlpha; -} - -namespace -{ - Color SanitizePaletteIndex(sal_uInt8 nIndex, const std::vector<Color>& rPalette) - { - const size_t nPaletteEntryCount = rPalette.size(); - if (nPaletteEntryCount && nIndex >= nPaletteEntryCount) - { - auto nSanitizedIndex = nIndex % nPaletteEntryCount; - SAL_WARN_IF(nIndex != nSanitizedIndex, "vcl", "invalid colormap index: " - << static_cast<unsigned int>(nIndex) << ", colormap len is: " - << nPaletteEntryCount); - nIndex = nSanitizedIndex; - } - - return rPalette[nIndex]; - } -} - -bool TIFFReader::ReadTIFF(SvStream & rTIFF, Graphic & rGraphic ) -{ - sal_uInt16 i, nNumTags(0), nTagType(0); - sal_uInt32 nFirstIfd(0), nDataLen; - - bStatus = true; - - pTIFF = &rTIFF; - sal_uInt64 nMaxPos = nOrigPos = pTIFF->Tell(); - nEndOfFile = nOrigPos + pTIFF->remainingSize(); - // number format of pTIFF at the beginning - SvStreamEndian nOrigNumberFormat = pTIFF->GetEndian(); - - // read header: - ReadHeader(); - - // read first IFD: - pTIFF->ReadUInt32( nFirstIfd ); - - if( !nFirstIfd || pTIFF->GetError() ) - bStatus = false; - - if ( bStatus ) - { - sal_uInt32 nOffset = nFirstIfd; - - std::vector<sal_uInt32> aSeenOffsets; - // calculate length of TIFF file - do - { - if (std::find(aSeenOffsets.begin(), aSeenOffsets.end(), nOffset) != aSeenOffsets.end()) - { - SAL_WARN("filter.tiff", "Parsing error: " << nOffset << - " already processed, format loop"); - bStatus = false; - break; - } - pTIFF->Seek(nOrigPos + nOffset); - aSeenOffsets.push_back(nOffset); - - if( pTIFF->GetError() ) - { - pTIFF->ResetError(); - break; - } - nMaxPos = std::max( pTIFF->Tell(), nMaxPos ); - - pTIFF->ReadUInt16( nNumTags ); - - const size_t nMinRecordSize = 12; - const size_t nMaxRecords = pTIFF->remainingSize() / nMinRecordSize; - if (nNumTags > nMaxRecords) - { - SAL_WARN("filter.tiff", "Parsing error: " << nMaxRecords << - " max possible entries, but " << nNumTags << " claimed, truncating"); - nNumTags = nMaxRecords; - } - - // loop through tags: - for( i = 0; i < nNumTags; i++ ) - { - nTagType = 0; - nDataType = USHRT_MAX; - nDataLen = 0; - nOffset = 0; - pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen ).ReadUInt32( nOffset ); - - if( DataTypeSize() * nDataLen > 4 ) - nMaxPos = std::max(nOrigPos + nOffset + DataTypeSize() * nDataLen, nMaxPos); - } - pTIFF->ReadUInt32( nOffset ); - if (!pTIFF->good()) - nOffset = 0; - - nMaxPos = std::max( pTIFF->Tell(), nMaxPos ); - if ( !nOffset ) - nMaxPos = std::max( pTIFF->Tell(), nMaxPos ); - } - while( nOffset ); - - std::vector<sal_uInt32> aSeenIfds; - - for ( sal_uInt32 nNextIfd = nFirstIfd; nNextIfd && bStatus; ) - { - if (std::find(aSeenIfds.begin(), aSeenIfds.end(), nNextIfd) != aSeenIfds.end()) - { - SAL_WARN("filter.tiff", "Parsing error: " << nNextIfd << - " already processed, format loop"); - bStatus = false; - break; - } - pTIFF->Seek(nOrigPos + nNextIfd); - aSeenIfds.push_back(nNextIfd); - { - bByteSwap = false; - - nNewSubFile = 0; - nSubFile = 0; - nImageWidth = 0; - nImageLength = 0; - nBitsPerSample = 1; // default value according to the documentation - nCompression = 1; - nPhotometricInterpretation = 0; - nThresholding = 1; // default value according to the documentation - nCellWidth = 1; - nCellLength = 1; - nFillOrder = 1; // default value according to the documentation - nOrientation = 1; - nSamplesPerPixel = 1; // default value according to the documentation - nRowsPerStrip = 0xffffffff; // default value according to the documentation - nMinSampleValue = 0; // default value according to the documentation - nMaxSampleValue = 0; - fXResolution = 0.0; - fYResolution = 0.0; - nPlanarConfiguration = 1; - nGroup3Options = 0; // default value according to the documentation - nGroup4Options = 0; // default value according to the documentation - nResolutionUnit = 2; // default value according to the documentation - nPredictor = 1; - nNumColors = 0; - - aStripOffsets.clear(); - aStripByteCounts.clear(); - for (auto& j : aMap) - j.clear(); - - pTIFF->ReadUInt16( nNumTags ); - sal_uInt64 nPos = pTIFF->Tell(); - - const size_t nMinRecordSize = 8; - const size_t nMaxRecords = pTIFF->remainingSize() / nMinRecordSize; - if (nNumTags > nMaxRecords) - { - SAL_WARN("filter.tiff", "Parsing error: " << nMaxRecords << - " max possible entries, but " << nNumTags << " claimed, truncating"); - nNumTags = nMaxRecords; - } - - for( i = 0; i < nNumTags; i++ ) - { - pTIFF->ReadUInt16( nTagType ).ReadUInt16( nDataType ).ReadUInt32( nDataLen ); - - if( DataTypeSize() * nDataLen > 4 ) - { - pTIFF->ReadUInt32( nOffset ); - if (!checkSeek(*pTIFF, nOrigPos + nOffset)) - { - bStatus = false; - break; - } - } - ReadTagData( nTagType, nDataLen ); - nPos += 12; pTIFF->Seek( nPos ); - - if ( pTIFF->GetError() ) - bStatus = false; - - if ( !bStatus ) - break; - } - pTIFF->ReadUInt32( nNextIfd ); - if (!pTIFF->good()) - nNextIfd = 0; - } - if ( !nBitsPerSample || ( nBitsPerSample > 32 ) ) - bStatus = false; - if (nImageWidth <= 0 || nImageLength <= 0) - bStatus = false; - if ( bStatus ) - { - nLargestPixelIndex = -1; - if ( nMaxSampleValue == 0 ) - { - if ( nBitsPerSample == 32 ) // sj: i93300, compiler bug, 1 << 32 gives 1 one 32bit windows platforms, - nMaxSampleValue = 0xffffffff; // (up from 80286 only the lower 5 bits are used when shifting a 32bit register) - else - { - nMaxSampleValue = (1U << nBitsPerSample) - 1; - } - } - if ( nPhotometricInterpretation == 2 || nPhotometricInterpretation == 5 || nPhotometricInterpretation == 6 ) - nDstBitsPerPixel = 24; - else if ( nBitsPerSample*nSamplesPerPixel <= 1 ) - nDstBitsPerPixel = 1; - else if ( nBitsPerSample*nSamplesPerPixel <= 4 ) - nDstBitsPerPixel = 4; - else - nDstBitsPerPixel = 8; - - if ( nPlanarConfiguration == 1 ) - nPlanes = 1; - else - nPlanes = nSamplesPerPixel; - - bStatus = nPlanes != 0; - } - - sal_uInt32 nDiv = GetRowsPerStrip(); - - if ( bStatus ) - { - bStatus = (nDiv != 0); - } - - if ( bStatus ) - { - if ( ( nFillOrder == 2 ) && ( nCompression != 5 ) ) // in the LZW mode bits are already being inverted - bByteSwap = true; - nStripsPerPlane = ( nImageLength - 1 ) / nDiv + 1; - bStatus = nSamplesPerPixel != 0; - } - - if ( bStatus ) - { - sal_uInt64 nRowSize = (static_cast<sal_uInt64>(nImageWidth) * nSamplesPerPixel / nPlanes * nBitsPerSample + 7) >> 3; - auto nMaxSize = SAL_MAX_INT32 / SAL_N_ELEMENTS(aMap); - if (utl::ConfigManager::IsFuzzing()) - nMaxSize /= 2; - if (nRowSize > nMaxSize) - { - SAL_WARN("filter.tiff", "Ludicrous row size of: " << nRowSize << " required"); - bStatus = false; - } - else - nBytesPerRow = nRowSize; - } - - if (bStatus) - { - //sanity check consider ReadMap condition for last row and - //last plane - if (nCompression == 1 || nCompression == 32771) - { - sal_uInt32 nStripBytesPerRow; - if (nCompression == 1) - nStripBytesPerRow = nBytesPerRow; - else - nStripBytesPerRow = ( nBytesPerRow + 1 ) & 0xfffffffe; - sal_uInt32 np = nPlanes - 1; - if (np >= SAL_N_ELEMENTS(aMap)) - bStatus = false; - sal_Int32 ny = nImageLength - 1; - sal_uInt32 nStrip(0); - nDiv = GetRowsPerStrip(); - if (bStatus) - bStatus = nDiv != 0; - if (bStatus) - { - nStrip = ny / nDiv + np * nStripsPerPlane; - if (nStrip >= aStripOffsets.size()) - bStatus = false; - } - if (bStatus) - { - auto nStart = aStripOffsets[ nStrip ] + ( ny % GetRowsPerStrip() ) * nStripBytesPerRow; - if (nStart > nEndOfFile) - bStatus = false; - } - } - else if (nCompression == 2 || nCompression == 3 || nCompression == 4) - { - if (nCompression == 3 && nGroup3Options & 0xfffffffa) - bStatus = false; - else if (nCompression == 4 && nGroup4Options & 0xffffffff) - bStatus = false; - sal_uInt32 np = nPlanes - 1; - if (np >= SAL_N_ELEMENTS(aMap)) - bStatus = false; - sal_Int32 ny = nImageLength - 1; - sal_uInt32 nStrip(0); - nDiv = GetRowsPerStrip(); - if (bStatus) - bStatus = nDiv != 0; - if (bStatus) - { - nStrip = ny / nDiv + np * nStripsPerPlane; - if (nStrip >= aStripOffsets.size()) - bStatus = false; - } - if (bStatus) - { - auto nStart = aStripOffsets[nStrip]; - if (nStart > nEndOfFile) - bStatus = false; - } - - if (bStatus) - { - sal_uInt64 nTargetBits = nImageWidth * nBitsPerSample * nSamplesPerPixel / nPlanes; - if (nTargetBits > SAL_MAX_UINT16) - bStatus = false; - } - } - else if (nCompression == 5) - { - sal_uInt32 np = nPlanes - 1; - if (np >= SAL_N_ELEMENTS(aMap)) - bStatus = false; - sal_Int32 ny = nImageLength - 1; - sal_uInt32 nStrip(0); - nDiv = GetRowsPerStrip(); - if (bStatus) - bStatus = nDiv != 0; - if (bStatus) - { - nStrip = ny / nDiv + np * nStripsPerPlane; - if (nStrip >= aStripOffsets.size()) - bStatus = false; - } - if (bStatus) - { - auto nStart = aStripOffsets[nStrip]; - if (nStart > nEndOfFile) - bStatus = false; - } - } - else if (nCompression == 32773) - { - } - else - { - bStatus = false; - } - } - - sal_Int32 nImageDataSize(0); - if (bStatus) - { - if (o3tl::checked_multiply<sal_Int32>(nImageWidth, nImageLength, nImageDataSize) || - o3tl::checked_multiply<sal_Int32>(nImageDataSize, (HasAlphaChannel() ? 4 : 3), nImageDataSize) || - nImageDataSize > SAL_MAX_INT32/4) - { - bStatus = false; - } - } - - if (bStatus) - { - sal_Int32 nResult = 0; - if (utl::ConfigManager::IsFuzzing() && (o3tl::checked_multiply(nImageWidth, nImageLength, nResult) || nResult > 4000000)) - bStatus = false; - } - - if ( bStatus ) - { - maBitmapPixelSize = Size(nImageWidth, nImageLength); - maBitmap.resize(nImageDataSize, 0); - - if (bStatus && ReadMap()) - { - nMaxPos = std::max( pTIFF->Tell(), nMaxPos ); - MakePalCol(); - nMaxPos = std::max( pTIFF->Tell(), nMaxPos ); - // convert palette-ized images to 24-bit color - if (!mvPalette.empty()) - { - for (sal_Int32 nY = 0; nY < nImageLength; ++nY) - { - for (sal_Int32 nX = 0; nX < nImageWidth; ++nX) - { - auto p = maBitmap.data() + ((maBitmapPixelSize.Width() * nY + nX) * (HasAlphaChannel() ? 4 : 3)); - auto c = SanitizePaletteIndex(*p, mvPalette); - *p = c.GetRed(); - p++; - *p = c.GetGreen(); - p++; - *p = c.GetBlue(); - } - } - } - } - else - bStatus = false; - - if ( bStatus ) - { - BitmapEx aImage = vcl::bitmap::CreateFromData(maBitmap.data(), nImageWidth, nImageLength, - nImageWidth * (HasAlphaChannel() ? 4 : 3), // scanline bytes - HasAlphaChannel() ? 32 : 24); - aImage.SetPrefMapMode(maBitmapPrefMapMode); - aImage.SetPrefSize(maBitmapPrefSize); - - AnimationBitmap aAnimationBitmap( aImage, Point( 0, 0 ), maBitmapPixelSize, - ANIMATION_TIMEOUT_ON_CLICK, Disposal::Back ); - - aAnimation.Insert( aAnimationBitmap ); - } - } - - // Clean up: - for (auto& j : aMap) - j.clear(); - aColorMap.clear(); - aStripOffsets.clear(); - aStripByteCounts.clear(); - } - } - - // seek to end of TIFF if succeeded - pTIFF->SetEndian( nOrigNumberFormat ); - pTIFF->Seek(bStatus ? STREAM_SEEK_TO_END: nOrigPos); - - if ( aAnimation.Count() ) - { - if ( aAnimation.Count() == 1 ) - rGraphic = aAnimation.GetBitmapEx(); - else - rGraphic = aAnimation; //aBitmap; - - return true; - } - else - return false; -} - - -//================== GraphicImport - the exported function ================ - -extern "C" SAL_DLLPUBLIC_EXPORT bool -itiGraphicImport( SvStream & rStream, Graphic & rGraphic, FilterConfigItem* ) -{ - TIFFReader aTIFFReader; - try - { - return aTIFFReader.ReadTIFF(rStream, rGraphic); - } - catch (const SvStreamEOFException &) - { - return false; - } - catch (const std::bad_alloc &) - { - return false; - } -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/graphicfilter/itiff/lzwdecom.cxx b/filter/source/graphicfilter/itiff/lzwdecom.cxx deleted file mode 100644 index 15784321b92e..000000000000 --- a/filter/source/graphicfilter/itiff/lzwdecom.cxx +++ /dev/null @@ -1,217 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#include "lzwdecom.hxx" -#include <sal/log.hxx> -#include <tools/stream.hxx> - -LZWDecompressor::LZWDecompressor() - : pIStream(nullptr) - , nTableSize(0) - , bEOIFound(false) - , bInvert(false) - , bFirst(true) - , nOldCode(0) - , pOutBufData(nullptr) - , nOutBufDataLen(0) - , nInputBitsBuf(0) - , nInputBitsBufSize(0) -{ - for (sal_uInt16 i=0; i<MAX_TABLE_SIZE; i++) - { - pTable[i].nPrevCode=0; - pTable[i].nDataCount=1; - pTable[i].nData=static_cast<sal_uInt8>(i); - } -} - - -LZWDecompressor::~LZWDecompressor() -{ -} - - -void LZWDecompressor::StartDecompression(SvStream & rIStream) -{ - pIStream=&rIStream; - - nTableSize=258; - - bEOIFound=false; - - nOutBufDataLen=0; - - pIStream->ReadUChar( nInputBitsBuf ); - - nInputBitsBufSize=8; - - if ( bFirst ) - { - bInvert = nInputBitsBuf == 1; - bFirst = false; - } - - if ( bInvert ) - nInputBitsBuf = ( ( nInputBitsBuf & 1 ) << 7 ) | ( ( nInputBitsBuf & 2 ) << 5 ) | ( ( nInputBitsBuf & 4 ) << 3 ) | ( ( nInputBitsBuf & 8 ) << 1 ) | ( ( nInputBitsBuf & 16 ) >> 1 ) | ( ( nInputBitsBuf & 32 ) >> 3 ) | ( ( nInputBitsBuf & 64 ) >> 5 ) | ( (nInputBitsBuf & 128 ) >> 7 ); -} - - -sal_uInt64 LZWDecompressor::Decompress(sal_uInt8 * pTarget, sal_uInt32 nMaxCount) -{ - sal_uInt32 nCount; - - if (pIStream==nullptr) return 0; - - nCount=0; - for (;;) { - - if (pIStream->GetError()) break; - - if (nOutBufDataLen>=nMaxCount) { - nOutBufDataLen = nOutBufDataLen - static_cast<sal_uInt16>(nMaxCount); - nCount+=nMaxCount; - while (nMaxCount>0) { - *(pTarget++)=*(pOutBufData++); - nMaxCount--; - } - break; - } - - nMaxCount-=static_cast<sal_uInt32>(nOutBufDataLen); - nCount+=nOutBufDataLen; - while (nOutBufDataLen>0) { - *(pTarget++)=*(pOutBufData++); - nOutBufDataLen--; - } - - if (bEOIFound) break; - - DecompressSome(); - - } - - return nCount; -} - - -sal_uInt16 LZWDecompressor::GetNextCode() -{ - sal_uInt16 nBits,nCode; - - if (nTableSize<511) nBits=9; - else if (nTableSize<1023) nBits=10; - else if (nTableSize<2047) nBits=11; - else nBits=12; - - nCode=0; - do { - if (nInputBitsBufSize<=nBits) - { - nCode=(nCode<<nInputBitsBufSize) | nInputBitsBuf; - nBits = nBits - nInputBitsBufSize; - pIStream->ReadUChar( nInputBitsBuf ); - if ( bInvert ) - nInputBitsBuf = ( ( nInputBitsBuf & 1 ) << 7 ) | ( ( nInputBitsBuf & 2 ) << 5 ) | ( ( nInputBitsBuf & 4 ) << 3 ) | ( ( nInputBitsBuf & 8 ) << 1 ) | ( ( nInputBitsBuf & 16 ) >> 1 ) | ( ( nInputBitsBuf & 32 ) >> 3 ) | ( ( nInputBitsBuf & 64 ) >> 5 ) | ( (nInputBitsBuf & 128 ) >> 7 ); - nInputBitsBufSize=8; - } - else - { - nCode=(nCode<<nBits) | (nInputBitsBuf>>(nInputBitsBufSize-nBits)); - nInputBitsBufSize = nInputBitsBufSize - nBits; - nInputBitsBuf&=0x00ff>>(8-nInputBitsBufSize); - nBits=0; - } - } while (nBits>0); - - return nCode; -} - - -void LZWDecompressor::AddToTable(sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData) -{ - if (nTableSize >= MAX_TABLE_SIZE) - { - //It might be possible to force emit a 256 to flush the buffer and try - //to continue later? - SAL_WARN("filter.tiff", "Too much data at scanline"); - bEOIFound = true; - return; - } - - unsigned char aSeenIndexes[MAX_TABLE_SIZE] = {0}; - while (pTable[nCodeFirstData].nDataCount>1) - { - if (aSeenIndexes[nCodeFirstData]) - { - SAL_WARN("filter.tiff", "Loop in chain"); - bEOIFound = true; - return; - } - aSeenIndexes[nCodeFirstData] = 1; - nCodeFirstData=pTable[nCodeFirstData].nPrevCode; - } - - pTable[nTableSize].nPrevCode=nPrevCode; - pTable[nTableSize].nDataCount=pTable[nPrevCode].nDataCount+1; - pTable[nTableSize].nData=pTable[nCodeFirstData].nData; - - nTableSize++; -} - - -void LZWDecompressor::DecompressSome() -{ - sal_uInt16 i,nCode; - - nCode=GetNextCode(); - if (nCode==256) - { - nTableSize=258; - nCode=GetNextCode(); - if (nCode==257) - { - bEOIFound=true; - } - } - else if (nCode<nTableSize) - AddToTable(nOldCode,nCode); - else if (nCode==nTableSize) - AddToTable(nOldCode,nOldCode); - else - { - bEOIFound=true; - } - - if (bEOIFound) - return; - - nOldCode=nCode; - - nOutBufDataLen=pTable[nCode].nDataCount; - pOutBufData=pOutBuf.data()+nOutBufDataLen; - for (i=0; i<nOutBufDataLen; i++) - { - *(--pOutBufData)=pTable[nCode].nData; - nCode=pTable[nCode].nPrevCode; - } -} - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/filter/source/graphicfilter/itiff/lzwdecom.hxx b/filter/source/graphicfilter/itiff/lzwdecom.hxx deleted file mode 100644 index 71ec833b21db..000000000000 --- a/filter/source/graphicfilter/itiff/lzwdecom.hxx +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#ifndef INCLUDED_FILTER_SOURCE_GRAPHICFILTER_ITIFF_LZWDECOM_HXX -#define INCLUDED_FILTER_SOURCE_GRAPHICFILTER_ITIFF_LZWDECOM_HXX - -#include <sal/types.h> -#include <array> - -#define MAX_TABLE_SIZE 4096 - -struct LZWTableEntry -{ - sal_uInt16 nPrevCode; - sal_uInt16 nDataCount; - sal_uInt8 nData; -}; - -class SvStream; - -class LZWDecompressor -{ -public: - LZWDecompressor(); - ~LZWDecompressor(); - - void StartDecompression(SvStream& rIStream); - - // Returns the number of written bytes. If < nMaxCount there is - // no more data to be unpacked or an error occurred. - sal_uInt64 Decompress(sal_uInt8* pTarget, sal_uInt32 nMaxCount); - -private: - sal_uInt16 GetNextCode(); - void AddToTable(sal_uInt16 nPrevCode, sal_uInt16 nCodeFirstData); - void DecompressSome(); - - SvStream* pIStream; - - std::array<LZWTableEntry, MAX_TABLE_SIZE> pTable; - sal_uInt16 nTableSize; - - bool bEOIFound, bInvert, bFirst; - - sal_uInt16 nOldCode; - - std::array<sal_uInt8, MAX_TABLE_SIZE> pOutBuf; - sal_uInt8* pOutBufData; - sal_uInt16 nOutBufDataLen; - - sal_uInt8 nInputBitsBuf; - sal_uInt16 nInputBitsBufSize; -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |