diff -Nru djvulibre-3.5.27.1/config/acinclude.m4 djvulibre-3.5.28/config/acinclude.m4 --- djvulibre-3.5.27.1/config/acinclude.m4 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/config/acinclude.m4 2020-11-20 16:57:32.000000000 +0000 @@ -16,8 +16,7 @@ dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License -dnl along with this program; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111 USA +dnl along with this program. If not, see . dnl dnl ------------------------------------------------------- diff -Nru djvulibre-3.5.27.1/config/pkg.m4 djvulibre-3.5.28/config/pkg.m4 --- djvulibre-3.5.27.1/config/pkg.m4 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/config/pkg.m4 2020-11-20 16:57:32.000000000 +0000 @@ -14,8 +14,7 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# along with this program. If not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a diff -Nru djvulibre-3.5.27.1/configure.ac djvulibre-3.5.28/configure.ac --- djvulibre-3.5.27.1/configure.ac 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/configure.ac 2020-11-20 16:57:32.000000000 +0000 @@ -24,7 +24,7 @@ m4_define([v_maj], [3]) m4_define([v_min], [5]) -m4_define([v_mic], [27]) +m4_define([v_mic], [28]) m4_define([v_ver], [v_maj.v_min.v_mic]) m4_define([lt_compat], [21]) @@ -41,7 +41,7 @@ AC_CONFIG_HEADER(config.h:config/config.h.in) AC_CANONICAL_HOST -AM_INIT_AUTOMAKE([1.6 subdir-objects dist-bzip2 dist-xz]) +AM_INIT_AUTOMAKE([1.6 subdir-objects dist-bzip2 dist-xz -Wall]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) @@ -83,6 +83,8 @@ AM_CONDITIONAL([HAVE_OS_WIN32], [test "x${have_os_win32}" = "xyes"]) AC_CHECK_DECL([__APPLE__],[have_os_apple=yes],[have_os_apple=no]) +AM_CONDITIONAL([HAVE_OS_APPLE], [test "x${have_os_apple}" = "xyes"]) + if test x$have_os_apple = xyes && test -d /opt/local ; then CPPFLAGS="$CPPFLAGS -I/opt/local/include" LDFLAGS="$LDFLAGS -L/opt/local/lib" @@ -161,6 +163,7 @@ AC_CHECK_HEADERS(wchar.h wctype.h sys/mman.h iconv.h getopt.h) AC_CHECK_HEADERS(langinfo.h sched.h new.h) AC_CHECK_HEADERS(stdint.h inttypes.h sys/ipc.h sys/shm.h) +AC_CHECK_HEADERS(cpuid.h) # ---------------------------------------- # Types diff -Nru djvulibre-3.5.27.1/COPYING djvulibre-3.5.28/COPYING --- djvulibre-3.5.27.1/COPYING 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/COPYING 2020-11-20 16:57:32.000000000 +0000 @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -15,7 +15,7 @@ General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to +the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not @@ -55,8 +55,8 @@ The precise terms and conditions for copying, distribution and modification follow. - - GNU GENERAL PUBLIC LICENSE + + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -110,7 +110,7 @@ License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) - + These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in @@ -168,7 +168,7 @@ access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. - + 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is @@ -225,7 +225,7 @@ This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. - + 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License @@ -255,7 +255,7 @@ of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -291,7 +291,7 @@ the "copyright" line and a pointer to where the full notice is found. - Copyright (C) 19yy + Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -303,17 +303,16 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: - Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. @@ -336,5 +335,5 @@ This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General +library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. diff -Nru djvulibre-3.5.27.1/debian/changelog djvulibre-3.5.28/debian/changelog --- djvulibre-3.5.27.1/debian/changelog 2015-11-24 15:58:16.000000000 +0000 +++ djvulibre-3.5.28/debian/changelog 2021-05-28 04:59:22.000000000 +0000 @@ -1,3 +1,133 @@ +djvulibre (3.5.28-1ubuntu0.1~16.04.sav0) xenial; urgency=medium + + * Backport to Xenial + * Revert "bump to debhelper 13" (revert debian/rules execute_after_* targets + back to override_* targets to work with compat level < 13) + * debian/control: Set debhelper-compat (= 10) BD (LP highest for Xenial) + + -- Rob Savoury Thu, 27 May 2021 21:59:22 -0700 + +djvulibre (3.5.28-1ubuntu0.1) hirsute-security; urgency=medium + + * SECURITY UPDATE: Stack overflow + - debian/patches/CVE-2021-3500.patch: prevent recursion in + libdjvu/DjVuPort.cpp, libdjvu/DjVuPort.h. + - CVE-2021-3500 + * SECURITY UPDATE: Out of bounds write + - debian/patches/CVE-2021-32490.patch: add checks to + libdjvu/IW44Image.cpp. + - CVE-2021-32490 + * SECURITY UPDATE: Integer overflow + - debian/patches/CVE-2021-32491.patch: check for overflow in + tools/ddjvu.cpp. + - CVE-2021-32491 + * SECURITY UPDATE: Out of bounds read + - debian/patches/CVE-2021-32492.patch: check pool in + libdjvu/DataPool.cpp. + - CVE-2021-32492 + * SECURITY UPDATE: Heap buffer overflow + - debian/patches/CVE-2021-32493.patch: check row size in + libdjvu/GBitmap.cpp. + - CVE-2021-32493 + + -- Marc Deslauriers Mon, 17 May 2021 09:08:32 -0400 + +djvulibre (3.5.28-1) unstable; urgency=medium + + [ Leon Bottou ] + * version number change + + [ Barak A. Pearlmutter ] + * rules does not require root + * version-4 debian/watch uscan support file + + -- Barak A. Pearlmutter Mon, 23 Nov 2020 13:10:15 +0000 + +djvulibre (3.5.27.1-15) unstable; urgency=medium + + * bump to debhelper 13 + * bump policy version + * track upstream including libtiff bug fix (closes: #962779) + + -- Barak A. Pearlmutter Wed, 22 Jul 2020 15:18:20 +0100 + +djvulibre (3.5.27.1-14) unstable; urgency=medium + + * Merge upstream fix for CVE-2019-18804 (closes: #945114) + * bump policy + + -- Barak A. Pearlmutter Thu, 21 Nov 2019 15:30:21 +0000 + +djvulibre (3.5.27.1-13) unstable; urgency=medium + + * track upstream bug fixes + * Run lintian-brush: + - Add missing colon in closes line. + - Set upstream metadata fields: Archive. + + -- Barak A. Pearlmutter Wed, 11 Sep 2019 14:12:18 +0100 + +djvulibre (3.5.27.1-12) unstable; urgency=medium + + * track upstream bug fixes and such + * bump policy + + -- Barak A. Pearlmutter Sat, 10 Aug 2019 13:48:53 +0200 + +djvulibre (3.5.27.1-11) unstable; urgency=medium + + * track upstream bug fixes + * bump policy and debhelper versions + * declare djvulibre-bin multi-arch_foreign (closes: #930064) + + -- Barak A. Pearlmutter Thu, 06 Jun 2019 13:54:10 +0100 + +djvulibre (3.5.27.1-10) unstable; urgency=medium + + [ Ondřej Nový ] + * d/watch: Use https protocol + + [ Barak A. Pearlmutter ] + * track upstream updates + * bump policy, no changes required + + -- Barak A. Pearlmutter Fri, 02 Nov 2018 14:51:55 +0000 + +djvulibre (3.5.27.1-9) unstable; urgency=medium + + * bump to debhelper 11 + * bump policy, no changes required + * stop including mimetype xml file in desktop package, and rename icons. + For details see https://sourceforge.net/p/djvu/bugs/283/ + * adjust to upstream renaming of documentation + + -- Barak A. Pearlmutter Mon, 30 Apr 2018 17:13:35 +0100 + +djvulibre (3.5.27.1-8) unstable; urgency=medium + + * track upstream updates + * bump policy, no changes required + * use dh10 defaults in debian/rules + * remove now-autogenerated debian/control -dbg stanza + * secure repo url + + -- Barak A. Pearlmutter Mon, 09 Oct 2017 13:59:39 +0100 + +djvulibre (3.5.27.1-7) unstable; urgency=medium + + * bump to debhelper 10 + * update any2djvu server URL in any2djvu script (closes: #843009) + + -- Barak A. Pearlmutter Thu, 03 Nov 2016 11:03:32 +0000 + +djvulibre (3.5.27.1-6) unstable; urgency=medium + + * track upstream fixes and updates, including to djvudigital + * bump standards version + * enable hardening + + -- Barak A. Pearlmutter Wed, 17 Aug 2016 22:35:47 +0200 + djvulibre (3.5.27.1-5) unstable; urgency=medium * guard find command in debian/rules (closes: 806017) @@ -230,7 +360,7 @@ djvulibre (3.5.23-6) unstable; urgency=low * tiny patch to libdjvu/miniexp.cpp from Jacob Wilk (closes: #613549) - + -- Barak A. Pearlmutter Wed, 02 Mar 2011 08:47:43 +0000 djvulibre (3.5.23-5) unstable; urgency=low @@ -273,7 +403,7 @@ - locale set internally as appropriate, e.g., PDF output (closes: #562156) also fixes https://bugs.launchpad.net/ubuntu/+source/djvulibre/+bug/499324 - thread-related crash addressed, slightly post 3.5.23 (closes: #582961) - + -- Barak A. Pearlmutter Tue, 07 Sep 2010 17:47:42 +0100 djvulibre (3.5.23-1) unstable; urgency=low @@ -350,7 +480,7 @@ [ Leon Bottou ] * Upstream release candidate - + [ Barak A. Pearlmutter ] -- Barak A. Pearlmutter Tue, 23 Jun 2009 22:53:13 +0200 @@ -359,7 +489,7 @@ * Upstream browser plugin fix to gui/nsdejavu/nsdejavu.c (closes: #504340) * Upstream fix for djvups -text=yes non-ASCII crash (closes: #469122) - + -- Barak A. Pearlmutter Wed, 10 Dec 2008 21:32:00 +0000 djvulibre (3.5.21-2) unstable; urgency=low @@ -433,7 +563,7 @@ * Utilities package now recommends pdf2djvu package, coming soon * Fix update-alternatives in installation scripts (closes: #476444) * Rev deb policy - + -- Barak A. Pearlmutter Fri, 02 May 2008 01:12:15 -0700 djvulibre (3.5.20-7) unstable; urgency=low @@ -766,7 +896,7 @@ djvulibre (3.5.11.2003.06.04-4) unstable; urgency=low - * work around enforcement of C++ horribleness by GCC 3.3.1 (closes #199766) + * work around enforcement of C++ horribleness by GCC 3.3.1 (closes: #199766) -- Barak A. Pearlmutter Tue, 8 Jul 2003 07:57:23 -0600 diff -Nru djvulibre-3.5.27.1/debian/compat djvulibre-3.5.28/debian/compat --- djvulibre-3.5.27.1/debian/compat 2015-02-09 16:31:53.000000000 +0000 +++ djvulibre-3.5.28/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -9 diff -Nru djvulibre-3.5.27.1/debian/control djvulibre-3.5.28/debian/control --- djvulibre-3.5.27.1/debian/control 2015-02-09 16:31:57.000000000 +0000 +++ djvulibre-3.5.28/debian/control 2021-05-28 04:42:20.000000000 +0000 @@ -1,18 +1,19 @@ Source: djvulibre Section: libs Priority: optional -Maintainer: Barak A. Pearlmutter +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Barak A. Pearlmutter Uploaders: Leon Bottou -Build-Depends: dh-autoreconf, - pkg-config, - debhelper (>= 9), +Build-Depends: pkg-config, + debhelper-compat (= 10), libjpeg-dev, libtiff-dev, librsvg2-bin | imagemagick -Vcs-Git: git://anonscm.debian.org/collab-maint/djvulibre.git -Vcs-Browser: http://anonscm.debian.org/gitweb/?p=collab-maint/djvulibre.git +Vcs-Git: https://salsa.debian.org/debian/djvulibre.git +Vcs-Browser: https://salsa.debian.org/debian/djvulibre Homepage: http://djvu.sourceforge.net/ -Standards-Version: 3.9.6 +Standards-Version: 4.5.0 +Rules-Requires-Root: no Package: libdjvulibre-dev Section: libdevel @@ -53,15 +54,6 @@ Description: Linguistic support files for libdjvulibre Runtime linguistic support files for the libdjvulibre library. -Package: djvulibre-dbg -Section: debug -Priority: extra -Architecture: any -Multi-Arch: same -Depends: ${shlibs:Depends}, ${misc:Depends}, libdjvulibre21 (= ${binary:Version}) -Description: Debug symbols for the DjVu image format - DjVu runtime debug symbols. - Package: djvulibre-desktop Architecture: all Depends: ${misc:Depends} @@ -73,21 +65,21 @@ Package: djview Section: graphics -Architecture: any +Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, djview4 | djview3 Description: Transition package, djview3 to djview4 - Ease transition from djview3 to djview4 with this dummy package. + Ease transition from djview or djview3 to djview4 with this dummy package. Package: djview3 Section: graphics -Architecture: any +Architecture: all Depends: ${shlibs:Depends}, ${misc:Depends}, djview4 Description: Transition package, djview3 to djview4 Ease transition from djview3 to djview4 with this dummy package. Package: djvuserve Section: web -Recommends: apache | httpd-cgi | httpd +Recommends: apache2 | apache | httpd-cgi | httpd Conflicts: djvulibre-bin (<< 3.5.9-3) Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} @@ -99,6 +91,7 @@ Package: djvulibre-bin Section: graphics Architecture: any +Multi-Arch: foreign Depends: ${shlibs:Depends}, ${misc:Depends}, curl, libdjvulibre21 (= ${binary:Version}) Recommends: pdf2djvu Suggests: djvulibre-desktop, djview4 | djvu-viewer | evince diff -Nru djvulibre-3.5.27.1/debian/djvulibre-desktop.install djvulibre-3.5.28/debian/djvulibre-desktop.install --- djvulibre-3.5.27.1/debian/djvulibre-desktop.install 2015-02-16 11:02:58.000000000 +0000 +++ djvulibre-3.5.28/debian/djvulibre-desktop.install 2018-04-30 16:50:43.000000000 +0000 @@ -1,2 +1 @@ -usr/share/mime/packages usr/share/icons/hicolor/*/mimetypes diff -Nru djvulibre-3.5.27.1/debian/gbp.conf djvulibre-3.5.28/debian/gbp.conf --- djvulibre-3.5.27.1/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/debian/gbp.conf 2018-06-13 12:41:57.000000000 +0000 @@ -0,0 +1,5 @@ +[DEFAULT] +debian-branch = debian +upstream-tag = 'release.%(version)s' +pristine-tar = True +sign-tags = True diff -Nru djvulibre-3.5.27.1/debian/libdjvulibre-dev.docs djvulibre-3.5.28/debian/libdjvulibre-dev.docs --- djvulibre-3.5.27.1/debian/libdjvulibre-dev.docs 2015-02-09 16:31:53.000000000 +0000 +++ djvulibre-3.5.28/debian/libdjvulibre-dev.docs 2018-06-13 12:41:57.000000000 +0000 @@ -1,6 +1,4 @@ README doc/*.djvu doc/*.txt -doc/DjVmNav* -doc/GMapAreas* debian/tmp/usr/share/djvu/pubtext diff -Nru djvulibre-3.5.27.1/debian/not-installed djvulibre-3.5.28/debian/not-installed --- djvulibre-3.5.27.1/debian/not-installed 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/debian/not-installed 2018-06-13 12:41:57.000000000 +0000 @@ -0,0 +1 @@ +*.la diff -Nru djvulibre-3.5.27.1/debian/patches/CVE-2021-32490.patch djvulibre-3.5.28/debian/patches/CVE-2021-32490.patch --- djvulibre-3.5.27.1/debian/patches/CVE-2021-32490.patch 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/debian/patches/CVE-2021-32490.patch 2021-05-17 13:06:13.000000000 +0000 @@ -0,0 +1,24 @@ +From: "Barak A. Pearlmutter" +Date: Mon, 10 May 2021 15:48:24 +0100 +Subject: djvulibre-fedora Patch8 djvulibre-3.5.27-check-image-size.patch + +--- + libdjvu/IW44Image.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/libdjvu/IW44Image.cpp b/libdjvu/IW44Image.cpp +index e8d4b44..aa3d554 100644 +--- a/libdjvu/IW44Image.cpp ++++ b/libdjvu/IW44Image.cpp +@@ -678,7 +678,11 @@ IW44Image::Map::image(signed char *img8, int rowsize, int pixsep, int fast) + size_t sz = bw * bh; + if (sz / (size_t)bw != (size_t)bh) // multiplication overflow + G_THROW("IW44Image: image size exceeds maximum (corrupted file?)"); ++ if (sz == 0) ++ G_THROW("IW44Image: zero size image (corrupted file?)"); + GPBuffer gdata16(data16,sz); ++ if (data16 == NULL) ++ G_THROW("IW44Image: unable to allocate image data"); + // Copy coefficients + int i; + short *p = data16; diff -Nru djvulibre-3.5.27.1/debian/patches/CVE-2021-32491.patch djvulibre-3.5.28/debian/patches/CVE-2021-32491.patch --- djvulibre-3.5.27.1/debian/patches/CVE-2021-32491.patch 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/debian/patches/CVE-2021-32491.patch 2021-05-17 13:06:20.000000000 +0000 @@ -0,0 +1,31 @@ +From: "Barak A. Pearlmutter" +Date: Mon, 10 May 2021 15:48:53 +0100 +Subject: djvulibre-fedora Patch9 djvulibre-3.5.27-interger-overflow.patch + +--- + tools/ddjvu.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/tools/ddjvu.cpp b/tools/ddjvu.cpp +index 7109952..2f3e0f9 100644 +--- a/tools/ddjvu.cpp ++++ b/tools/ddjvu.cpp +@@ -70,6 +70,7 @@ + #include + #include + #include ++#include + + #ifdef UNIX + # include +@@ -394,7 +395,9 @@ render(ddjvu_page_t *page, int pageno) + rowsize = rrect.w; + else + rowsize = rrect.w * 3; +- if (! (image = (char*)malloc(rowsize * rrect.h))) ++ if ((size_t)rowsize > SIZE_MAX / rrect.h) ++ die(i18n("Integer overflow when allocating image buffer for page %d"), pageno); ++ if (! (image = (char*)malloc((size_t)rowsize * rrect.h))) + die(i18n("Cannot allocate image buffer for page %d"), pageno); + + /* Render */ diff -Nru djvulibre-3.5.27.1/debian/patches/CVE-2021-32492.patch djvulibre-3.5.28/debian/patches/CVE-2021-32492.patch --- djvulibre-3.5.27.1/debian/patches/CVE-2021-32492.patch 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/debian/patches/CVE-2021-32492.patch 2021-05-17 13:06:27.000000000 +0000 @@ -0,0 +1,21 @@ +From: "Barak A. Pearlmutter" +Date: Mon, 10 May 2021 15:49:14 +0100 +Subject: djvulibre-fedora Patch10 djvulibre-3.5.27-check-input-pool.patch + +--- + libdjvu/DataPool.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/libdjvu/DataPool.cpp b/libdjvu/DataPool.cpp +index 5fcbedf..4c2eaf0 100644 +--- a/libdjvu/DataPool.cpp ++++ b/libdjvu/DataPool.cpp +@@ -791,6 +791,8 @@ DataPool::create(const GP & pool, int start, int length) + DEBUG_MSG("DataPool::DataPool: pool=" << (void *)((DataPool *)pool) << " start=" << start << " length= " << length << "\n"); + DEBUG_MAKE_INDENT(3); + ++ if (!pool) G_THROW( ERR_MSG("DataPool.zero_DataPool") ); ++ + DataPool *xpool=new DataPool(); + GP retval=xpool; + xpool->init(); diff -Nru djvulibre-3.5.27.1/debian/patches/CVE-2021-32493.patch djvulibre-3.5.28/debian/patches/CVE-2021-32493.patch --- djvulibre-3.5.27.1/debian/patches/CVE-2021-32493.patch 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/debian/patches/CVE-2021-32493.patch 2021-05-17 13:06:39.000000000 +0000 @@ -0,0 +1,30 @@ +From: "Barak A. Pearlmutter" +Date: Mon, 10 May 2021 15:50:19 +0100 +Subject: djvulibre-fedora Patch12 + djvulibre-3.5.27-unsigned-short-overflow.patch + +--- + libdjvu/GBitmap.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libdjvu/GBitmap.cpp b/libdjvu/GBitmap.cpp +index c2fdbe4..3d552a6 100644 +--- a/libdjvu/GBitmap.cpp ++++ b/libdjvu/GBitmap.cpp +@@ -69,6 +69,7 @@ + #include + #include + #include ++#include + + // - Author: Leon Bottou, 05/1997 + +@@ -1284,6 +1285,8 @@ GBitmap::decode(unsigned char *runs) + // initialize pixel array + if (nrows==0 || ncolumns==0) + G_THROW( ERR_MSG("GBitmap.not_init") ); ++ if (ncolumns > USHRT_MAX - border) ++ G_THROW("GBitmap: row size exceeds maximum (corrupted file?)"); + bytes_per_row = ncolumns + border; + if (runs==0) + G_THROW( ERR_MSG("GBitmap.null_arg") ); diff -Nru djvulibre-3.5.27.1/debian/patches/CVE-2021-3500.patch djvulibre-3.5.28/debian/patches/CVE-2021-3500.patch --- djvulibre-3.5.27.1/debian/patches/CVE-2021-3500.patch 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/debian/patches/CVE-2021-3500.patch 2021-05-17 13:06:33.000000000 +0000 @@ -0,0 +1,46 @@ +From: "Barak A. Pearlmutter" +Date: Mon, 10 May 2021 15:49:55 +0100 +Subject: djvulibre-fedora Patch11 + djvulibre-3.5.27-djvuport-stack-overflow.patch + +--- + libdjvu/DjVuPort.cpp | 9 +++++++++ + libdjvu/DjVuPort.h | 1 + + 2 files changed, 10 insertions(+) + +diff --git a/libdjvu/DjVuPort.cpp b/libdjvu/DjVuPort.cpp +index 2b3e0d2..a377920 100644 +--- a/libdjvu/DjVuPort.cpp ++++ b/libdjvu/DjVuPort.cpp +@@ -507,10 +507,19 @@ GP + DjVuPortcaster::id_to_file(const DjVuPort * source, const GUTF8String &id) + { + GPList list; ++ ++ if (!!opening_id && opening_id == id) ++ G_THROW("DjVuPortcaster: recursive opening of the same file (corrupted file?)"); ++ else ++ opening_id = id; ++ + compute_closure(source, list, true); + GP file; + for(GPosition pos=list;pos;++pos) + if ((file=list[pos]->id_to_file(source, id))) break; ++ ++ opening_id = GUTF8String(); ++ + return file; + } + +diff --git a/libdjvu/DjVuPort.h b/libdjvu/DjVuPort.h +index e2b3125..313dc2b 100644 +--- a/libdjvu/DjVuPort.h ++++ b/libdjvu/DjVuPort.h +@@ -484,6 +484,7 @@ private: + const DjVuPort *dst, int distance); + void compute_closure(const DjVuPort *src, GPList &list, + bool sorted=false); ++ GUTF8String opening_id; + }; + + diff -Nru djvulibre-3.5.27.1/debian/patches/debian-changes djvulibre-3.5.28/debian/patches/debian-changes --- djvulibre-3.5.27.1/debian/patches/debian-changes 2015-11-24 16:04:04.000000000 +0000 +++ djvulibre-3.5.28/debian/patches/debian-changes 1970-01-01 00:00:00.000000000 +0000 @@ -1,502 +0,0 @@ -Description: - TODO: Put a short summary on the line above and replace this paragraph - with a longer explanation of this change. Complete the meta-information - with other relevant fields (see below for details). To make it easier, the - information below has been extracted from the changelog. Adjust it or drop - it. - . - djvulibre (3.5.27.1-5) unstable; urgency=medium - . - * guard find command in debian/rules (closes: 806017) - * merge upstream update which works around qt5 issue (closes: 804888) -Author: Barak A. Pearlmutter -Bug-Debian: https://bugs.debian.org/804888 -Bug-Debian: https://bugs.debian.org/806017 - ---- -The information above should follow the Patch Tagging Guidelines, please -checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here -are templates for supplementary fields that you might want to add: - -Origin: , -Bug: -Bug-Debian: https://bugs.debian.org/ -Bug-Ubuntu: https://launchpad.net/bugs/ -Forwarded: -Reviewed-By: -Last-Update: - ---- djvulibre-3.5.27.1.orig/configure.ac -+++ djvulibre-3.5.27.1/configure.ac -@@ -41,7 +41,7 @@ AC_CONFIG_SRCDIR(libdjvu/ddjvuapi.cpp) - AC_CONFIG_HEADER(config.h:config/config.h.in) - AC_CANONICAL_HOST - --AM_INIT_AUTOMAKE([1.6 subdir-objects dist-bzip2 dist-xz]) -+AM_INIT_AUTOMAKE([1.6 subdir-objects dist-bzip2 dist-xz -Wall]) - m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) - ---- djvulibre-3.5.27.1.orig/desktopfiles/Makefile.am -+++ djvulibre-3.5.27.1/desktopfiles/Makefile.am -@@ -61,7 +61,7 @@ else - endif - - svg_process =\ --cat $< | gzip >$@ -+cat $< | gzip -n >$@ - - svg_verbose = $(svg_verbose_@AM_V@) - svg_verbose_ = $(svg_verbose_@AM_DEFAULT_V@) ---- djvulibre-3.5.27.1.orig/doc/djvuchanges.txt -+++ djvulibre-3.5.27.1/doc/djvuchanges.txt -@@ -39,6 +39,15 @@ To maximize compatibility with earlier v - values different from {1,6,2,5} should be ignored - and interpreted as 1 : rightside up orientation. - -+1.4- ORDERING OF THE DJBZ AND SJBZ CHUNK -+ -+Although the specification does not make it clear, when a FORM:DJVU chunk -+contains a bitonal image represented by a Sjbz chunk that uses a shape -+dictionary represented by a Djbz chunk, the Djbz chunk must appear before the -+Sjbz chunk that references it. This also holds when the chunks is accessed -+indirectly via INCL chunks. For instance, an INCL chunk that refers to a -+shared Djbz shape dictionary must be placed before the corresponding Sjbz -+chunk. - - - 2- ESCAPE SEQUENCES IN ANNOTATION CHUNK STRINGS. ---- djvulibre-3.5.27.1.orig/libdjvu/DjVuDocument.cpp -+++ djvulibre-3.5.27.1/libdjvu/DjVuDocument.cpp -@@ -838,7 +838,12 @@ DjVuDocument::id_to_url(const GUTF8Strin - break; - case OLD_INDEXED: - case SINGLE_PAGE: -- return GURL::UTF8(id,init_url.base()); -+ { -+ GURL url = GURL::UTF8(id,init_url.base()); -+ if (url.fname() == "-") -+ G_THROW("Illegal include chunk (corrupted file?)"); -+ return url; -+ } - break; - } - return GURL(); ---- djvulibre-3.5.27.1.orig/libdjvu/GContainer.h -+++ djvulibre-3.5.27.1/libdjvu/GContainer.h -@@ -848,7 +848,7 @@ GListImpl::newnode(const TI &elt) - { - LNode *n = (LNode *) operator new (sizeof(LNode )); - #if GCONTAINER_ZERO_FILL -- memset(n, 0, sizeof(LNode )); -+ memset((void*)n, 0, sizeof(LNode )); - #endif - new ((void*)&(n->val)) TI(elt); - return (Node*) n; ---- djvulibre-3.5.27.1.orig/libdjvu/GOS.cpp -+++ djvulibre-3.5.27.1/libdjvu/GOS.cpp -@@ -154,13 +154,6 @@ strerror(int errno) - #endif - - --static const char slash='/'; --static const char percent='%'; --static const char backslash='\\'; --static const char colon=':'; --static const char dot='.'; --static const char nillchar=0; -- - - // ----------------------------------------- - // Functions for dealing with filenames -@@ -193,18 +186,18 @@ GOS::basename(const GUTF8String &gfname, - const char *fname=gfname; - #if defined(_WIN32) || defined(OS2) - // Special cases -- if (fname[1] == colon) -+ if (fname[1] == ':') - { - if(!fname[2]) - { - return gfname; - } -- if (!fname[3] && (fname[2]== slash || fname[2]== backslash)) -+ if (!fname[3] && (fname[2]== '/' || fname[2]== '\\')) - { - char string_buffer[4]; - string_buffer[0] = fname[0]; -- string_buffer[1] = colon; -- string_buffer[2] = backslash; -+ string_buffer[1] = ':'; -+ string_buffer[2] = '\\'; - string_buffer[3] = 0; - return string_buffer; - } -@@ -219,7 +212,7 @@ GOS::basename(const GUTF8String &gfname, - // Process suffix - if (suffix) - { -- if (suffix[0]== dot ) -+ if (suffix[0]== '.' ) - suffix ++; - if (suffix[0]) - { -@@ -229,7 +222,7 @@ GOS::basename(const GUTF8String &gfname, - if (s > fname + sl) - { - s = s - (sl + 1); -- if(*s == dot && (GUTF8String(s+1).downcase() == gsuffix.downcase())) -+ if(*s == '.' && (GUTF8String(s+1).downcase() == gsuffix.downcase())) - { - retval.setat((int)((size_t)s-(size_t)fname),0); - } -@@ -335,7 +328,7 @@ GOS::cwd(const GUTF8String &dirname) - char drv[2]; - if (dirname.length() && _chdir(dirname.getUTF82Native())==-1)//MBCS cvt - G_THROW(errmsg()); -- drv[0]= dot ; drv[1]=0; -+ drv[0]= '.' ; drv[1]=0; - char *string_buffer; - GPBuffer gstring_buffer(string_buffer,MAXPATHLEN+1); - char *result = getcwd(string_buffer,MAXPATHLEN); ---- djvulibre-3.5.27.1.orig/libdjvu/GString.cpp -+++ djvulibre-3.5.27.1/libdjvu/GString.cpp -@@ -273,7 +273,9 @@ public: - ~ChangeLocale(); - private: - GUTF8String locale; -+#if DO_CHANGELOCALE - int category; -+#endif - }; - - class GStringRep::Native : public GStringRep -@@ -452,7 +454,9 @@ GStringRep::Native::ncopy( - } - - GStringRep::ChangeLocale::ChangeLocale(const int xcategory, const char xlocale[] ) -+#if DO_CHANGELOCALE - : category(xcategory) -+#endif - { - #if DO_CHANGELOCALE - // This is disabled under UNIX because ---- djvulibre-3.5.27.1.orig/libdjvu/GURL.cpp -+++ djvulibre-3.5.27.1/libdjvu/GURL.cpp -@@ -170,7 +170,6 @@ namespace DJVU { - - static const char djvuopts[]="DJVUOPTS"; - static const char localhost[]="file://localhost/"; --static const char backslash='\\'; - static const char colon=':'; - static const char dot='.'; - static const char filespecslashes[] = "file://"; -@@ -179,13 +178,14 @@ static const char slash='/'; - static const char percent='%'; - static const char localhostspec1[] = "//localhost/"; - static const char localhostspec2[] = "///"; --static const char nillchar=0; - #if defined(UNIX) - static const char tilde='~'; - static const char root[] = "/"; - #elif defined(_WIN32) || defined(OS2) - static const char root[] = "\\"; -+ static const char backslash='\\'; - #elif defined(macintosh) -+ static const char nillchar=0; - static char const * const root = &nillchar; - #else - #error "Define something here for your operating system" ---- djvulibre-3.5.27.1.orig/libdjvu/IW44EncodeCodec.cpp -+++ djvulibre-3.5.27.1/libdjvu/IW44EncodeCodec.cpp -@@ -125,7 +125,7 @@ static const float iw_norm[16] = { - }; - - static const int iw_shift = 6; --static const int iw_round = (1<<(iw_shift-1)); -+// static const int iw_round = (1<<(iw_shift-1)); - - static const struct { int start; int size; } - bandbuckets[] = ---- djvulibre-3.5.27.1.orig/libdjvu/IW44Image.cpp -+++ djvulibre-3.5.27.1/libdjvu/IW44Image.cpp -@@ -125,15 +125,6 @@ static const int iw_quant[16] = { - 0x040000, 0x040000, 0x080000 - }; - --static const float iw_norm[16] = { -- 2.627989e+03F, -- 1.832893e+02F, 1.832959e+02F, 5.114690e+01F, -- 4.583344e+01F, 4.583462e+01F, 1.279225e+01F, -- 1.149671e+01F, 1.149712e+01F, 3.218888e+00F, -- 2.999281e+00F, 2.999476e+00F, 8.733161e-01F, -- 1.074451e+00F, 1.074511e+00F, 4.289318e-01F --}; -- - static const int iw_border = 3; - static const int iw_shift = 6; - static const int iw_round = (1<<(iw_shift-1)); -@@ -604,7 +595,7 @@ IW44Image::Map::Map(int w, int h) - { - bw = (w+0x20-1) & ~0x1f; - bh = (h+0x20-1) & ~0x1f; -- nb = (bw * bh) / (32 * 32); -+ nb = (unsigned int)(bw*bh) / (32 * 32); - blocks = new IW44Image::Block[nb]; - top = IWALLOCSIZE; - } ---- djvulibre-3.5.27.1.orig/libdjvu/ddjvuapi.cpp -+++ djvulibre-3.5.27.1/libdjvu/ddjvuapi.cpp -@@ -1578,6 +1578,12 @@ ddjvu_page_create(ddjvu_document_t *docu - p->img = doc->get_page(GNativeString(pageid), false, job); - else - p->img = doc->get_page(pageno, false, job); -+ // synthetize msgs for pages found in the cache -+ ddjvu_status_t status = p->status(); -+ if (status == DDJVU_JOB_OK) -+ p->notify_redisplay(p->img); -+ if (status >= DDJVU_JOB_OK) -+ p->notify_file_flags_changed(p->img->get_djvu_file(), 0, 0); - } - G_CATCH(ex) - { ---- djvulibre-3.5.27.1.orig/tools/csepdjvu.1 -+++ djvulibre-3.5.27.1/tools/csepdjvu.1 -@@ -244,7 +244,12 @@ When such comments are present in the fi - .BR csepdjvu - produces an navigation chunk with - the specified outline. -- -+.IP "*" 3 -+.BI "# P (" string ")" -+.br -+Provides title -+.I string -+for the current page. - .SH CREDITS - - This program was initially written by L\('eon Bottou ---- djvulibre-3.5.27.1.orig/tools/csepdjvu.cpp -+++ djvulibre-3.5.27.1/tools/csepdjvu.cpp -@@ -1121,6 +1121,7 @@ public: - bool parse_comment_line(BufferByteStream &bs); - void make_chunks(IFFByteStream &iff); - GP get_djvm_nav(); -+ GUTF8String get_pagetitle(); - protected: - int w; - int h; -@@ -1143,6 +1144,7 @@ protected: - }; - GPList links; - GP nav; -+ GUTF8String pagetitle; - protected: - bool allspace(const TxtMark *mark); - void textmark(GP mark); -@@ -1255,6 +1257,15 @@ Comments::parse_comment_line(BufferByteS - nav->append(b); - return true; - } -+ // Page title comment -+ if (c == 'P') -+ { -+ if (pagetitle.length()) -+ G_THROW("csepdjvu: corrupted file (multiple page title comments)"); -+ if (! (bs.skip(" \t") && bs.read_ps_string(pagetitle) )) -+ G_THROW("csepdjvu: corrupted file (syntax error in title comment)"); -+ return true; -+ } - // Unrecognized - bs.unget(c); - return false; -@@ -1487,6 +1498,12 @@ Comments::get_djvm_nav() - return 0; - } - -+GUTF8String -+Comments::get_pagetitle() -+{ -+ return pagetitle; -+} -+ - - // -------------------------------------------------- - // MAIN COMPRESSION ROUTINE -@@ -1500,6 +1517,7 @@ void - csepdjvu_page(BufferByteStream &bs, - GP obs, - GP &nav, -+ GUTF8String &pagetitle, - const csepdjvuopts &opts) - { - // Read rle data from separation file -@@ -1671,7 +1689,8 @@ csepdjvu_page(BufferByteStream &bs, - // -- terminate main composite chunk - coms.make_chunks(iff); - iff.close_chunk(); -- // -- store outline -+ // -- returns page title and outline -+ pagetitle = coms.get_pagetitle(); - if (! nav) - nav = coms.get_djvm_nav(); - } -@@ -1765,6 +1784,7 @@ main(int argc, const char **argv) - { - GP gdoc=DjVmDoc::create(); - GP gnav; -+ GUTF8String pagetitle; - DjVmDoc &doc=*gdoc; - GURL outputurl; - GP goutputpage=ByteStream::create(); -@@ -1821,7 +1841,7 @@ main(int argc, const char **argv) - // Compress page - goutputpage=ByteStream::create(); - ByteStream &outputpage=*goutputpage; -- csepdjvu_page(ibs, goutputpage, gnav, opts); -+ csepdjvu_page(ibs, goutputpage, gnav, pagetitle, opts); - if (opts.verbose) { - DjVuPrintErrorUTF8("csepdjvu: %d bytes for page %d", - outputpage.size(), pageno); -@@ -1834,12 +1854,12 @@ main(int argc, const char **argv) - // Insert page into document - outputpage.seek(0); - doc.insert_file(outputpage, DjVmDir::File::PAGE, -- pagename, pagename); -+ pagename, pagename, pagetitle); - } while (check_for_another_page(ibs, opts)); - } - } - // Save file -- if (pageno == 1 && ! gnav) -+ if (pageno == 1 && ! gnav && ! pagetitle) - { - ByteStream &outputpage=*goutputpage; - // Save as a single page ---- djvulibre-3.5.27.1.orig/tools/djvudigital -+++ djvulibre-3.5.27.1/tools/djvudigital -@@ -97,8 +97,14 @@ checkps2utf8() - if ( "$gsdjvu" 2>&1 -dNODISPLAY -c '(ps2utf8.ps) runlibfile quit' | \ - grep -q WRITESYSTEMDICT ) - then -- djvutext="/tmp/dj$$.ps" -- trap "rm 2>/dev/null $djvutext" 0 -+ # For added security, use mktemp if available. -+ # When using mktemp, do *not* delete the file as that introduces a brief window of vulnerability. -+ if mktemp --dry-run >/dev/null 2>&1; then -+ djvutext=$(mktemp djXXXXXXXXXX.ps) || exit 1 -+ else -+ djvutext="/tmp/dj$$.ps" -+ trap "rm 2>/dev/null $djvutext" 0 -+ fi - cat > $djvutext <<\EOF - (ps2utf8.ps) runlibfile currentglobal /setglobal load true setglobal - .ps2utf8 begin /onpage { } bind def /onfont { pop pop pop } bind def -@@ -351,11 +357,10 @@ case "$infile" in - $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf \ - "-sOutputFile=$backend" $gsarg0 $gsarg1 $gsarg2 -_ -c quit - else -- echo -n gzip -d -c '"'"$infile"'"' '|' "" -- echo -n $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf "" -- echo -n "-sOutputFile=""'""$backend""'" "" -- echo -n $gsarg0 $gsarg1 $gsarg2 -_ -c quit -- echo -+ echo gzip -d -c '"'"$infile"'"' '|' "" \ -+ $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf "" \ -+ "-sOutputFile=""'""$backend""'" "" \ -+ $gsarg0 $gsarg1 $gsarg2 -_ -c quit - fi - ;; - *) -@@ -364,10 +369,9 @@ case "$infile" in - "-sOutputFile=$backend" $gsarg0 $gsarg1 $gsarg2 \ - -f "$infile" -c quit - else -- echo -n $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf "" -- echo -n "-sOutputFile=""'""$backend""'" "" -- echo -n $gsarg0 $gsarg1 $gsarg2 -f '"'"$infile"'"' -c quit -- echo -+ echo $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf "" \ -+ "-sOutputFile=""'""$backend""'" "" \ -+ $gsarg0 $gsarg1 $gsarg2 -f '"'"$infile"'"' -c quit - fi - ;; - esac ---- djvulibre-3.5.27.1.orig/tools/djvuextract.cpp -+++ djvulibre-3.5.27.1/tools/djvuextract.cpp -@@ -208,6 +208,7 @@ main(int argc, char **argv) - GArray dargv(0,argc-1); - for(int i=0;i not found!\n", (const char *)dargv[i]); -+ retcode = 64; - } - else - { -@@ -271,5 +273,5 @@ main(int argc, char **argv) - exit(1); - } - G_ENDCATCH; -- return 0; -+ return retcode; - } ---- djvulibre-3.5.27.1.orig/tools/djvumake.cpp -+++ djvulibre-3.5.27.1/tools/djvumake.cpp -@@ -356,6 +356,8 @@ analyze_jb2_chunk(const GURL &url) - void - analyze_incl_chunk(const GURL &url) - { -+ if (! url.is_file()) -+ return; - GP gbs = ByteStream::create(url,"rb"); - char buffer[24]; - memset(buffer, 0, sizeof(buffer)); -@@ -955,7 +957,7 @@ main(int argc, char **argv) - } - else if (!dargv[i].cmp("INCL=",5)) - { -- create_incl_chunk(iff, "INCL", GURL::Filename::UTF8(5+(const char *)dargv[i]).fname()); -+ create_incl_chunk(iff, "INCL", (const char *)GUTF8String(dargv[i].substr(5,-1))); - flag_contains_incl = 1; - } - else if (!dargv[i].cmp("PPM=",4)) ---- djvulibre-3.5.27.1.orig/win32/djvulibre/djvulibre-install.sh -+++ djvulibre-3.5.27.1/win32/djvulibre/djvulibre-install.sh -@@ -23,7 +23,7 @@ echo ---- DjVuLibre tools - - djexe="bzz.exe c44.exe cjb2.exe cpaldjvu.exe csepdjvu.exe - ddjvu.exe djvm.exe djvmcvt.exe djvudump.exe djvuextract.exe -- djvumake.exe djvups.exe djvused.exe djvuserve.exe djvutoxml.exe -+ djvumake.exe djvups.exe djvused.exe djvutoxml.exe - djvutxt.exe djvuxmlparser.exe" - djdll="libdjvulibre.dll libjpeg.dll libtiff.dll libz.dll" - for n in $djdll $djexe ; do ---- djvulibre-3.5.27.1.orig/win32/djvulibre/djvulibre.nsi -+++ djvulibre-3.5.27.1/win32/djvulibre/djvulibre.nsi -@@ -32,8 +32,8 @@ RequestExecutionLevel admin - !define DJVULIBRE_VERSION "3.5.27" - !define CLASSES "Software\Classes\" - !define DJVIEW_NAME "DjView" --!define DJVIEW_VERSION "4.10" --!define VI_PRODUCT_VERSION "4.10.0.0" -+!define DJVIEW_VERSION "4.10.4" -+!define VI_PRODUCT_VERSION "4.10.4.0" - - !define PRODUCT_NAME "${DJVULIBRE_NAME} ${DJVIEW_NAME}" - !define UNINST_NAME "${DJVULIBRE_NAME}+${DJVIEW_NAME}" ; for uninstaller diff -Nru djvulibre-3.5.27.1/debian/patches/series djvulibre-3.5.28/debian/patches/series --- djvulibre-3.5.27.1/debian/patches/series 2015-11-24 16:04:04.000000000 +0000 +++ djvulibre-3.5.28/debian/patches/series 2021-05-17 13:08:23.000000000 +0000 @@ -1 +1,5 @@ -debian-changes +CVE-2021-32490.patch +CVE-2021-32491.patch +CVE-2021-32492.patch +CVE-2021-3500.patch +CVE-2021-32493.patch diff -Nru djvulibre-3.5.27.1/debian/rules djvulibre-3.5.28/debian/rules --- djvulibre-3.5.27.1/debian/rules 2015-11-24 15:52:32.000000000 +0000 +++ djvulibre-3.5.28/debian/rules 2021-05-28 04:56:10.000000000 +0000 @@ -1,7 +1,9 @@ #!/usr/bin/make -f +export DEB_BUILD_MAINT_OPTIONS = hardening=+all + %: - dh $@ --with autoreconf --parallel + dh $@ # extract library major version from source build system libver0 := $(shell \ @@ -44,8 +46,8 @@ debian/tmp/usr/lib/cgi-bin/djvuserve override_dh_install: - dh_install --list-missing - @echo remove from djvulibre-bin, already in djvuserve + dh_install + @echo "remove from djvulibre-bin, already in djvuserve" if test -d debian/djvulibre-bin; then find debian/djvulibre-bin -name djvuserve\* -print -delete; fi # @echo "remove from djvulibre-bin, not in Debian: needs gsdjvu, direct complaints to AT&T" # find debian/djvulibre-bin -name djvudigital\* -print -delete @@ -56,8 +58,8 @@ override_dh_compress: dh_compress --exclude=.djvu -override_dh_strip: - dh_strip --dbg-package=djvulibre-dbg - override_dh_makeshlibs: dh_makeshlibs --version-info --exclude=/plugins + +override_dh_missing: + dh_missing --list-missing diff -Nru djvulibre-3.5.27.1/debian/upstream/metadata djvulibre-3.5.28/debian/upstream/metadata --- djvulibre-3.5.27.1/debian/upstream/metadata 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/debian/upstream/metadata 2020-11-23 13:08:18.000000000 +0000 @@ -0,0 +1 @@ +Archive: SourceForge diff -Nru djvulibre-3.5.27.1/debian/watch djvulibre-3.5.28/debian/watch --- djvulibre-3.5.27.1/debian/watch 2014-12-08 17:26:44.000000000 +0000 +++ djvulibre-3.5.28/debian/watch 2020-11-23 13:08:18.000000000 +0000 @@ -1,2 +1,2 @@ -version=3 -http://sf.net/djvu/djvulibre-([0-9]+\.[0-9]+\.[0-9]+)\.tar\.gz +version=4 +https://sf.net/djvu/@PACKAGE@-@ANY_VERSION@@ARCHIVE_EXT@ diff -Nru djvulibre-3.5.27.1/desktopfiles/djvulibre-mime.xml djvulibre-3.5.28/desktopfiles/djvulibre-mime.xml --- djvulibre-3.5.27.1/desktopfiles/djvulibre-mime.xml 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/desktopfiles/djvulibre-mime.xml 2020-11-20 16:57:32.000000000 +0000 @@ -5,9 +5,9 @@ - - - + + + diff -Nru djvulibre-3.5.27.1/desktopfiles/Makefile.am djvulibre-3.5.28/desktopfiles/Makefile.am --- djvulibre-3.5.27.1/desktopfiles/Makefile.am 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/desktopfiles/Makefile.am 2020-11-20 16:57:32.000000000 +0000 @@ -3,20 +3,20 @@ #icons SVGICONS = \ -scalable/mimetypes/djvu.svgz +scalable/mimetypes/image-vnd.djvu.svgz PNGICONS = \ -16x16/mimetypes/djvu.png \ -20x20/mimetypes/djvu.png \ -22x22/mimetypes/djvu.png \ -24x24/mimetypes/djvu.png \ -32x32/mimetypes/djvu.png \ -48x48/mimetypes/djvu.png \ -64x64/mimetypes/djvu.png \ -72x72/mimetypes/djvu.png \ -96x96/mimetypes/djvu.png \ -128x128/mimetypes/djvu.png \ -256x256/mimetypes/djvu.png +16x16/mimetypes/image-vnd.djvu.png \ +20x20/mimetypes/image-vnd.djvu.png \ +22x22/mimetypes/image-vnd.djvu.png \ +24x24/mimetypes/image-vnd.djvu.png \ +32x32/mimetypes/image-vnd.djvu.png \ +48x48/mimetypes/image-vnd.djvu.png \ +64x64/mimetypes/image-vnd.djvu.png \ +72x72/mimetypes/image-vnd.djvu.png \ +96x96/mimetypes/image-vnd.djvu.png \ +128x128/mimetypes/image-vnd.djvu.png \ +256x256/mimetypes/image-vnd.djvu.png icons: $(PNGICONS) $(SVGICONS) @@ -61,7 +61,7 @@ endif svg_process =\ -cat $< | gzip >$@ +cat $< | gzip -n >$@ svg_verbose = $(svg_verbose_@AM_V@) svg_verbose_ = $(svg_verbose_@AM_DEFAULT_V@) @@ -76,9 +76,11 @@ nobase_icons_DATA = $(PNGICONS) $(SVGICONS) # mime - -mimedir = $(datadir)/mime/packages -dist_mime_DATA = djvulibre-mime.xml +# | No longer install mime type description +# | because it conflicts with the defaults provided +# | by shared-mime-info. +# mimedir = $(datadir)/mime/packages +# dist_mime_DATA = djvulibre-mime.xml # hooks diff -Nru djvulibre-3.5.27.1/djvulibre.spec djvulibre-3.5.28/djvulibre.spec --- djvulibre-3.5.27.1/djvulibre.spec 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/djvulibre.spec 2020-11-20 16:57:32.000000000 +0000 @@ -1,5 +1,5 @@ %define release 1 -%define version 3.5.27 +%define version 3.5.28 Summary: DjVu viewers, encoders and utilities. Name: djvulibre diff -Nru djvulibre-3.5.27.1/doc/djvuchanges.txt djvulibre-3.5.28/doc/djvuchanges.txt --- djvulibre-3.5.27.1/doc/djvuchanges.txt 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/doc/djvuchanges.txt 2020-11-20 16:57:32.000000000 +0000 @@ -39,9 +39,20 @@ values different from {1,6,2,5} should be ignored and interpreted as 1 : rightside up orientation. +1.4- ORDERING OF THE DJBZ AND SJBZ CHUNK +Although the specification does not make it clear, when a FORM:DJVU chunk +contains a bitonal image represented by a Sjbz chunk that uses a shape +dictionary represented by a Djbz chunk, the Djbz chunk must appear before the +Sjbz chunk that references it. This also holds when the chunks is accessed +indirectly via INCL chunks. For instance, an INCL chunk that refers to a +shared Djbz shape dictionary must be placed before the corresponding Sjbz +chunk. -2- ESCAPE SEQUENCES IN ANNOTATION CHUNK STRINGS. + +2- ANNOTATION CHUNK + +2.1- ESCAPE SEQUENCES IN ANNOTATION CHUNK STRINGS. The treatment of escape sequence in annotation chunk strings has historically been slightly different in Lizardtech DjVu and @@ -76,6 +87,13 @@ with version greater than some constant use the new convention. +2.2- HIGHLIGHT ANNOTATION + +The standard specifies that highlight opacity ranges from 0 to 100 +with a default value of 50. Nothing says however that 100 represents +a completely opaque color. In fact, in djview4, opacities are +recognized up to 200, with 200 representing an opaque color. + 3- PAGE TITLES. @@ -130,7 +148,7 @@ Metadata entries for each page are represent by key/value pairs located in a metadata directive in the annotation chunk. Metadata entries for the document are represented similarly -using the methods described in the next section. +using the methods described in the section 4.3. The metadata directive has the form diff -Nru djvulibre-3.5.27.1/doc/minilisp/minilisp.cpp djvulibre-3.5.28/doc/minilisp/minilisp.cpp --- djvulibre-3.5.27.1/doc/minilisp/minilisp.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/doc/minilisp/minilisp.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -675,10 +675,12 @@ while (i nb) - return 1; - return 0; + return (na < nb) ? -1 : (na > nb) ? +1 : 0; } else if (miniexp_stringp(a) && miniexp_stringp(b)) { - const char *sa = miniexp_to_str(a); - const char *sb = miniexp_to_str(b); - return strcmp(sa, sb); + const char *sa, *sb; + int la = miniexp_to_lstr(a, &sa); + int lb = miniexp_to_lstr(b, &sb); + int r = memcmp(sa, sb, (la < lb) ? la : lb); + if (r == 0) + return (la < lb) ? -1 : (la > lb) ? +1 : 0; + return r; } else error("compare: cannot rank these arguments"); @@ -763,15 +776,14 @@ DEFUN("strlen",strlen,1,1) { if (! miniexp_stringp(argv[0])) error("strlen: string expected", argv[0]); - const char *s = miniexp_to_str(argv[0]); - return miniexp_number(strlen(s)); + return miniexp_number(miniexp_to_lstr(argv[0], 0)); } DEFUN("substr",substr,2,1) { if (! miniexp_stringp(argv[0])) error("substr: string expected", argv[0]); - const char *s = miniexp_to_str(argv[0]); - int l = strlen(s); + const char *s; + int l = miniexp_to_lstr(argv[0], &s); if (! miniexp_numberp(argv[1])) error("substr: integer number expected", argv[1]); int f = miniexp_to_double(argv[1]); @@ -785,7 +797,7 @@ f = miniexp_to_double(argv[2]); l = (f > l) ? l : (f < 0) ? 0 : f; } - return miniexp_substring(s,l); + return miniexp_lstring(l,s); } DEFUN("concat",concat,0,9999) { diff -Nru djvulibre-3.5.27.1/libdjvu/BSEncodeByteStream.cpp djvulibre-3.5.28/libdjvu/BSEncodeByteStream.cpp --- djvulibre-3.5.27.1/libdjvu/BSEncodeByteStream.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/BSEncodeByteStream.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -844,10 +844,12 @@ BitContext *cx = ctx; b = (mtfno==0); zp.encoder(b, cx[ctxid]); - if (b) goto rotate; cx+=CTXIDS; + if (b) goto rotate; + cx+=CTXIDS; b = (mtfno==1); zp.encoder(b, cx[ctxid]); - if (b) goto rotate; cx+=CTXIDS; + if (b) goto rotate; + cx+=CTXIDS; b = (mtfno<4); zp.encoder(b, cx[0]); if (b) { encode_binary(zp,cx+1,1,mtfno-2); goto rotate; } diff -Nru djvulibre-3.5.27.1/libdjvu/ByteStream.cpp djvulibre-3.5.28/libdjvu/ByteStream.cpp --- djvulibre-3.5.27.1/libdjvu/ByteStream.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/ByteStream.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -78,6 +78,9 @@ #if defined(_WIN32) || defined(__CYGWIN32__) # include #endif +#if defined(__APPLE__) +# include +#endif #ifdef UNIX # ifndef HAS_MEMMAP @@ -650,43 +653,84 @@ return retval; } +#ifdef _WIN32 +static wchar_t * +utf8_to_wide(const char *cstr) +{ + int wlen = strlen(cstr) + 1; + wchar_t *wstr = new wchar_t[wlen]; + if (GUTF8String(cstr).ncopy(wstr, wlen) > 0) + return wstr; + delete [] wstr; + return 0; +} +#endif + +#ifdef __APPLE__ +static char * +utf8_to_utf8mac(const char *cstr) +{ + int len = strlen(cstr); + CFStringRef utf8 = CFStringCreateWithCString(NULL, cstr, kCFStringEncodingUTF8); + int buflen = CFStringGetMaximumSizeOfFileSystemRepresentation(utf8); + if (buflen < len+1) buflen = len+1; + char *nfdstr = new char[buflen]; + if (! CFStringGetFileSystemRepresentation(utf8, nfdstr, buflen)) + strcpy(nfdstr, cstr); + return nfdstr; +} +#endif + + static FILE * urlfopen(const GURL &url,const char mode[]) { + FILE *retval = 0; #if defined(_WIN32) - FILE *retval=0; - const GUTF8String filename(url.UTF8Filename()); - wchar_t *wfilename; - const size_t wfilename_size=filename.length()+1; - GPBuffer gwfilename(wfilename,wfilename_size); - if(filename.ncopy(wfilename,wfilename_size) > 0) - { - const GUTF8String gmode(mode); - wchar_t *wmode; - const size_t wmode_size=gmode.length()+1; - GPBuffer gwmode(wmode,wmode_size); - if(gmode.ncopy(wmode,wmode_size) > 0) - { - retval=_wfopen(wfilename,wmode); - } - } - return retval?retval:fopen((const char *)url.NativeFilename(),mode); + // On Win, try to use _wfopen instead of fopen + wchar_t *wstr = utf8_to_wide((const char*)url.UTF8Filename()); + wchar_t *wmode = utf8_to_wide(mode); + if (wstr && wmode) + retval = _wfopen(wstr, wmode); + delete [] wstr; + delete [] wmode; + if (! retval) + retval = fopen((const char *)url.NativeFilename(),mode); #elif defined(__APPLE__) - return fopen((const char *)url.UTF8Filename(),mode); + // On Mac, prefer the NFD version of the UTF8 filename + const char *cnfd = utf8_to_utf8mac((const char*)url.UTF8Filename()); + retval = fopen(cnfd, mode); + delete [] cnfd; + if (! retval) // Otherwise try unnormalized UTF8 + retval = fopen((const char*)url.UTF8Filename(), mode); #else - return fopen((const char *)url.NativeFilename(),mode); + // Unix filesystems are usually in native encoding + retval = fopen((const char *)url.NativeFilename(),mode); + if (! retval) + retval = fopen((const char *)url.UTF8Filename(),mode); #endif + return retval; } #ifdef UNIX static int urlopen(const GURL &url, const int mode, const int perm) { + int retval = -1; #if defined(__APPLE__) - return open((const char *)url.UTF8Filename(),mode,perm); + // see above + const char *cnfd = utf8_to_utf8mac((const char*)url.UTF8Filename()); + retval = open(cnfd, mode, perm); + delete [] cnfd; + if (retval < 0) + retval = open((const char*)url.UTF8Filename(), mode, perm); #else - return open((const char *)url.NativeFilename(),mode,perm); + // see above + retval = open((const char *)url.NativeFilename(),mode,perm); + if (retval < 0) + retval = open((const char *)url.UTF8Filename(),mode,perm); #endif + return retval; } #endif /* UNIX */ diff -Nru djvulibre-3.5.27.1/libdjvu/ByteStream.h djvulibre-3.5.28/libdjvu/ByteStream.h --- djvulibre-3.5.27.1/libdjvu/ByteStream.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/ByteStream.h 2020-11-20 16:57:32.000000000 +0000 @@ -389,6 +389,10 @@ { return bs->seek(offset,whence,nothrow); } virtual void flush(void) { bs->flush(); } +private: + // Cancel C++ default stuff + Wrapper(const Wrapper &); + Wrapper & operator=(const Wrapper &); }; diff -Nru djvulibre-3.5.27.1/libdjvu/DataPool.cpp djvulibre-3.5.28/libdjvu/DataPool.cpp --- djvulibre-3.5.27.1/libdjvu/DataPool.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DataPool.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -1737,7 +1737,7 @@ { case SEEK_CUR: offset+=position; - // fallthrough; + /* FALLTHRU */ case SEEK_SET: if(offsetimg = doc->get_page(GNativeString(pageid), false, job); else p->img = doc->get_page(pageno, false, job); + // synthetize msgs for pages found in the cache + ddjvu_status_t status = p->status(); + if (status == DDJVU_JOB_OK) + p->notify_redisplay(p->img); + if (status >= DDJVU_JOB_OK) + p->notify_file_flags_changed(p->img->get_djvu_file(), 0, 0); } G_CATCH(ex) { @@ -2128,6 +2134,7 @@ case DDJVU_FORMAT_MSBTOLSB: if (!nargs) break; + /* FALLTHRU */ default: return fmt_error(fmt); } @@ -2179,7 +2186,7 @@ fmt_convert_row(const GPixel *p, int w, const ddjvu_format_t *fmt, char *buf) { - const uint32_t (*r)[256] = fmt->rgb; + const uint32_t (&r)[3][256] = fmt->rgb; const uint32_t xorval = fmt->xorval; switch(fmt->style) { @@ -2282,7 +2289,7 @@ fmt_convert_row(unsigned char *p, unsigned char g[256][4], int w, const ddjvu_format_t *fmt, char *buf) { - const uint32_t (*r)[256] = fmt->rgb; + const uint32_t (&r)[3][256] = fmt->rgb; const uint32_t xorval = fmt->xorval; switch(fmt->style) { diff -Nru djvulibre-3.5.27.1/libdjvu/ddjvuapi.h djvulibre-3.5.28/libdjvu/ddjvuapi.h --- djvulibre-3.5.27.1/libdjvu/ddjvuapi.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/ddjvuapi.h 2020-11-20 16:57:32.000000000 +0000 @@ -111,6 +111,9 @@ Version Change ----------------------------- + 24 Added: + miniexp_lstring() + miniexp_to_lstr() 23 Added: miniexp_mutate() 22 Changed diff -Nru djvulibre-3.5.27.1/libdjvu/DjVmDir.cpp djvulibre-3.5.28/libdjvu/DjVmDir.cpp --- djvulibre-3.5.27.1/libdjvu/DjVmDir.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVmDir.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -223,7 +223,6 @@ page2file.resize(-1); name2file.empty(); id2file.empty(); - title2file.empty(); int ver=str.read8(); bool bundled=(ver & 0x80)!=0; @@ -300,36 +299,44 @@ memcpy((char*) strings+strings_size, buffer, length); } DEBUG_MSG("size of decompressed names block=" << strings.size() << "\n"); - - // Copy names into the files + int strings_size=strings.size(); + strings.resize(strings_size+3); + memset((char*) strings+strings_size, 0, 4); + + // Copy names into the files const char * ptr=strings; for(pos=files_list;pos;++pos) { GP file=files_list[pos]; - + if (ptr >= (const char*)strings + strings_size) + G_THROW( ByteStream::EndOfFile ); file->id=ptr; ptr+=file->id.length()+1; if (file->flags & File::HAS_NAME) { - file->name=ptr; - ptr+=file->name.length()+1; - } else + file->name=ptr; + ptr+=file->name.length()+1; + } + else { file->name=file->id; } if (file->flags & File::HAS_TITLE) { - file->title=ptr; - ptr+=file->title.length()+1; - } else - file->title=file->id; - /* msr debug: multipage file, file->title is null. + file->title=ptr; + ptr+=file->title.length()+1; + } + else + { + file->title=file->id; + } + /* msr debug: multipage file, file->title is null. DEBUG_MSG(file->name << ", " << file->id << ", " << file->title << ", " << file->offset << ", " << file->size << ", " << file->is_page() << "\n"); */ } - // Check that there is only one file with SHARED_ANNO flag on + // Check that there is only one file with SHARED_ANNO flag on int shared_anno_cnt=0; for(pos=files_list;pos;++pos) { @@ -375,18 +382,6 @@ G_THROW( ERR_MSG("DjVmDir.dupl_id") "\t" + file->id); id2file[file->id]=file; } - - // Generate title2file map - for(pos=files_list;pos;++pos) - { - GP file=files_list[pos]; - if (file->title.length()) - { - if (title2file.contains(file->title)) - G_THROW( ERR_MSG("DjVmDir.dupl_title") "\t" + file->title); - title2file[file->title]=file; - } - } } } @@ -556,11 +551,19 @@ } GP -DjVmDir::title_to_file(const GUTF8String &title) const +DjVmDir::title_to_file(const GUTF8String &title, GPosition spos) const { - GCriticalSectionLock lock((GCriticalSection *) &class_lock); - GPosition pos; - return (title2file.contains(title, pos))?title2file[pos]:(GP(0)); + if (! title) + return 0; + GCriticalSectionLock lock((GCriticalSection *) &class_lock); + if (! spos) + for (GPosition pos = spos; pos; ++pos) + if (files_list[pos]->is_page() && files_list[pos]->title == title) + return files_list[pos]; + for (GPosition pos = files_list; pos; ++pos) + if (files_list[pos]->is_page() && files_list[pos]->title == title) + return files_list[pos]; + return 0; } GP @@ -661,14 +664,7 @@ G_THROW( ERR_MSG("DjVmDir.dupl_name2") "\t" + file->name); name2file[file->name]=file; id2file[file->id]=file; - if (file->title.length()) - { - if (title2file.contains(file->title)) - // duplicate titles may become ok some day - G_THROW( ERR_MSG("DjVmDir.dupl_title2") "\t" + file->title); - title2file[file->title]=file; - } - + // Make sure that there is no more than one file with shared annotations if (file->is_shared_anno()) { @@ -727,7 +723,6 @@ { name2file.del(f->name); id2file.del(f->id); - title2file.del(f->title); if (f->is_page()) { for(int page=0;page file=id2file[pos]; - title2file.del(file->title); file->title=title; - title2file[title]=file; } GPList diff -Nru djvulibre-3.5.27.1/libdjvu/DjVmDir.h djvulibre-3.5.28/libdjvu/DjVmDir.h --- djvulibre-3.5.27.1/libdjvu/DjVmDir.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVmDir.h 2020-11-20 16:57:32.000000000 +0000 @@ -181,7 +181,8 @@ /** Translates file IDs to file records. */ GP id_to_file(const GUTF8String &id) const; /** Translates file shortcuts to file records. */ - GP title_to_file(const GUTF8String &title) const; + GP title_to_file(const GUTF8String &title, GPosition spos) const; + GP title_to_file(const GUTF8String &title) const; /** Access file record by position. */ GP pos_to_file(int fileno, int *ppageno=0) const; /** Returns position of the file in the directory. */ @@ -216,7 +217,6 @@ GPArray page2file; GPMap name2file; GPMap id2file; - GPMap title2file; private: //dummy stuff static void decode(ByteStream *); static void encode(ByteStream *); @@ -440,6 +440,13 @@ files_list[files_list]->offset==0 ); } +inline GP +DjVmDir::title_to_file(const GUTF8String &title) const +{ + GPosition pos; + return title_to_file(title, pos); +} + // ----- THE END diff -Nru djvulibre-3.5.27.1/libdjvu/DjVuDocument.cpp djvulibre-3.5.28/libdjvu/DjVuDocument.cpp --- djvulibre-3.5.27.1/libdjvu/DjVuDocument.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVuDocument.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -805,11 +805,9 @@ { GP file=djvm_dir->id_to_file(id); if (!file) - { file=djvm_dir->name_to_file(id); - if (!file) - file=djvm_dir->title_to_file(id); - } + if (!file) + file=djvm_dir->title_to_file(id); if (file) return GURL::UTF8(file->get_load_name(),init_url); } @@ -819,11 +817,9 @@ { GP file=djvm_dir->id_to_file(id); if (!file) - { file=djvm_dir->name_to_file(id); - if (!file) - file=djvm_dir->title_to_file(id); - } + if (!file) + file=djvm_dir->title_to_file(id); if (file) return GURL::UTF8(file->get_load_name(),init_url.base()); } @@ -838,7 +834,12 @@ break; case OLD_INDEXED: case SINGLE_PAGE: - return GURL::UTF8(id,init_url.base()); + { + GURL url = GURL::UTF8(id,init_url.base()); + if (url.fname() == "-") + G_THROW("Illegal include chunk (corrupted file?)"); + return url; + } break; } return GURL(); diff -Nru djvulibre-3.5.27.1/libdjvu/DjVuDocument.h djvulibre-3.5.28/libdjvu/DjVuDocument.h --- djvulibre-3.5.27.1/libdjvu/DjVuDocument.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVuDocument.h 2020-11-20 16:57:32.000000000 +0000 @@ -524,7 +524,6 @@ \begin{enumerate} \item File ID from the \Ref{DjVmDir} \item File name from the \Ref{DjVmDir} - \item File title from the \Ref{DjVmDir} \end{enumerate} Then for #BUNDLED# document the URL is obtained by appending the #name# of the found file to the document's diff -Nru djvulibre-3.5.27.1/libdjvu/DjVuDumpHelper.cpp djvulibre-3.5.28/libdjvu/DjVuDumpHelper.cpp --- djvulibre-3.5.27.1/libdjvu/DjVuDumpHelper.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVuDumpHelper.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -336,12 +336,12 @@ size, djvminfo, counters[id]); break; } - // Default display of composite chunk - out_str.format( "\n"); - if (iff.composite()) - display_chunks(out_str, iff, head2, djvminfo); - // Terminate - iff.close_chunk(); + // Default display of composite chunk + out_str.format( "\n"); + if (iff.composite()) + display_chunks(out_str, iff, head2, djvminfo); + // Terminate + iff.close_chunk(); } } diff -Nru djvulibre-3.5.27.1/libdjvu/DjVuFile.cpp djvulibre-3.5.28/libdjvu/DjVuFile.cpp --- djvulibre-3.5.27.1/libdjvu/DjVuFile.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVuFile.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -568,7 +568,7 @@ if (incl_str.length()>0) { - if (strchr(incl_str, '/')) + if (strchr(incl_str,'/') || strchr(incl_str,'\\') || strchr(incl_str,':')) G_THROW( ERR_MSG("DjVuFile.malformed") ); DEBUG_MSG("incl_str='" << incl_str << "'\n"); diff -Nru djvulibre-3.5.27.1/libdjvu/DjVuGlobal.h djvulibre-3.5.28/libdjvu/DjVuGlobal.h --- djvulibre-3.5.27.1/libdjvu/DjVuGlobal.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVuGlobal.h 2020-11-20 16:57:32.000000000 +0000 @@ -70,11 +70,13 @@ # include // try standard c++ anyway! #endif -#ifdef _WIN32 -# ifdef DJVUAPI_EXPORT -# define DJVUAPI __declspec(dllexport) -# else -# define DJVUAPI __declspec(dllimport) +#ifndef DJVUAPI +# ifdef _WIN32 +# ifdef DJVUAPI_EXPORT +# define DJVUAPI __declspec(dllexport) +# else +# define DJVUAPI __declspec(dllimport) +# endif # endif #endif #ifndef DJVUAPI diff -Nru djvulibre-3.5.27.1/libdjvu/DjVuInfo.h djvulibre-3.5.28/libdjvu/DjVuInfo.h --- djvulibre-3.5.27.1/libdjvu/DjVuInfo.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVuInfo.h 2020-11-20 16:57:32.000000000 +0000 @@ -110,6 +110,11 @@ than this macro. If the version field is greater than or equal to this number, the decoder will just throw a \Ref{GException}. */ #define DJVUVERSION_TOO_NEW 50 +#ifndef DJVULIBRE_VERSION +/** DjVu library version string. + This is normally defined by autoconf, except on windows */ +# define DJVULIBRE_VERSION "3.5.28" +#endif //@} diff -Nru djvulibre-3.5.27.1/libdjvu/DjVuMessageLite.h djvulibre-3.5.28/libdjvu/DjVuMessageLite.h --- djvulibre-3.5.27.1/libdjvu/DjVuMessageLite.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVuMessageLite.h 2020-11-20 16:57:32.000000000 +0000 @@ -89,8 +89,8 @@ separator ::= newline | newline | separator - single_message ::= message_ID | - message_ID parameters + single_message ::= CTRLC message_ID | + CTRLC message_ID parameters parameters ::= tab string | tab string parameters diff -Nru djvulibre-3.5.27.1/libdjvu/DjVuPalette.cpp djvulibre-3.5.28/libdjvu/DjVuPalette.cpp --- djvulibre-3.5.27.1/libdjvu/DjVuPalette.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVuPalette.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -89,6 +89,7 @@ #define MAXPALETTESIZE 65535 // Limit for a 16 bit unsigned read. +#define fmin fltmin // clash with existing fmin inline unsigned char umax(unsigned char a, unsigned char b) @@ -99,7 +100,7 @@ { return (a>b) ? b : a; } inline float -fmin(float a, float b) +fmin(float a, float b) { return (a>b) ? b : a; } diff -Nru djvulibre-3.5.27.1/libdjvu/DjVuPort.cpp djvulibre-3.5.28/libdjvu/DjVuPort.cpp --- djvulibre-3.5.27.1/libdjvu/DjVuPort.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/DjVuPort.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -148,7 +148,7 @@ DjVuPortCorpse * corpse; for(corpse=corpse_head;corpse;corpse=corpse->next) if (test_addr==corpse->port) break; - if (!corpse) + if (!corpse) { addr=test_addr; addr_num--; diff -Nru djvulibre-3.5.27.1/libdjvu/GBitmap.cpp djvulibre-3.5.28/libdjvu/GBitmap.cpp --- djvulibre-3.5.27.1/libdjvu/GBitmap.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/GBitmap.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -890,11 +890,13 @@ int c = 0; while (n >= 0) { - bs.read(&h, 1); + if (bs.read(&h, 1) <= 0) + G_THROW( ByteStream::EndOfFile ); int x = h; if (x >= (int)RUNOVERFLOWVALUE) { - bs.read(&h, 1); + if (bs.read(&h, 1) <= 0) + G_THROW( ByteStream::EndOfFile ); x = h + ((x - (int)RUNOVERFLOWVALUE) << 8); } if (c+x > ncolumns) diff -Nru djvulibre-3.5.27.1/libdjvu/GBitmap.h djvulibre-3.5.28/libdjvu/GBitmap.h --- djvulibre-3.5.27.1/libdjvu/GBitmap.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/GBitmap.h 2020-11-20 16:57:32.000000000 +0000 @@ -566,7 +566,7 @@ { if (!bytes) uncompress(); - if (row<0 || row>=nrows) { + if (row<0 || row>=nrows || !bytes) { #ifndef NDEBUG if (zerosize < bytes_per_row + border) G_THROW( ERR_MSG("GBitmap.zero_small") ); @@ -581,7 +581,7 @@ { if (!bytes) ((GBitmap*)this)->uncompress(); - if (row<0 || row>=nrows) { + if (row<0 || row>=nrows || !bytes) { #ifndef NDEBUG if (zerosize < bytes_per_row + border) G_THROW( ERR_MSG("GBitmap.zero_small") ); diff -Nru djvulibre-3.5.27.1/libdjvu/GContainer.h djvulibre-3.5.28/libdjvu/GContainer.h --- djvulibre-3.5.27.1/libdjvu/GContainer.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/GContainer.h 2020-11-20 16:57:32.000000000 +0000 @@ -550,52 +550,61 @@ template void GArrayTemplate::sort(int lo, int hi) { - if (hi <= lo) - return; - if (hi > hibound || lo hibound || lo=lo) && !(data[j]<=tmp)) - data[j+1] = data[j]; - data[j+1] = tmp; + for (int i=lo+1; i<=hi; i++) + { + int j = i; + TYPE tmp = data[i]; + while ((--j>=lo) && !(data[j]<=tmp)) + data[j+1] = data[j]; + data[j+1] = tmp; + } + return; } - return; - } - // -- determine suitable quick-sort pivot - TYPE tmp = data[lo]; - TYPE pivot = data[(lo+hi)/2]; - if (pivot <= tmp) - { tmp = pivot; pivot=data[lo]; } - if (data[hi] <= tmp) - { pivot = tmp; } - else if (data[hi] <= pivot) - { pivot = data[hi]; } - // -- partition set - int h = hi; - int l = lo; - while (l < h) - { - while (! (pivot <= data[l])) l++; - while (! (data[h] <= pivot)) h--; - if (l < h) + // -- determine median-of-three pivot + TYPE tmp = data[lo]; + TYPE pivot = data[(lo+hi)/2]; + if (pivot <= tmp) + { tmp = pivot; pivot=data[lo]; } + if (data[hi] <= tmp) + { pivot = tmp; } + else if (data[hi] <= pivot) + { pivot = data[hi]; } + // -- partition set + int h = hi; + int l = lo; + while (l < h) { - tmp = data[l]; - data[l] = data[h]; - data[h] = tmp; - l = l+1; - h = h-1; + while (! (pivot <= data[l])) l++; + while (! (data[h] <= pivot)) h--; + if (l < h) + { + tmp = data[l]; + data[l] = data[h]; + data[h] = tmp; + l = l+1; + h = h-1; + } + } + // -- recurse, small partition first + // tail-recursion elimination + if (h - lo <= hi - l) { + sort(lo,h); + lo = l; // sort(l,hi) + } else { + sort(l,hi); + hi = h; // sort(lo,h) } } - // -- recursively restart - sort(lo, h); - sort(l, hi); } template inline TYPE& @@ -848,7 +857,7 @@ { LNode *n = (LNode *) operator new (sizeof(LNode )); #if GCONTAINER_ZERO_FILL - memset(n, 0, sizeof(LNode )); + memset((void*)n, 0, sizeof(LNode )); #endif new ((void*)&(n->val)) TI(elt); return (Node*) n; @@ -1161,7 +1170,7 @@ if (m) return m; SNode *n = (SNode*) operator new (sizeof(SNode)); #if GCONTAINER_ZERO_FILL - memset(n, 0, sizeof(SNode)); + memset((void*)n, 0, sizeof(SNode)); #endif new ((void*)&(n->key)) K ( key ); n->hashcode = hash((const K&)(n->key)); @@ -1198,7 +1207,7 @@ if (m) return m; MNode *n = (MNode*) operator new (sizeof(MNode)); #if GCONTAINER_ZERO_FILL - memset(n, 0, sizeof(MNode)); + memset((void*)n, 0, sizeof(MNode)); #endif new ((void*)&(n->key)) K (key); new ((void*)&(n->val)) TI (); diff -Nru djvulibre-3.5.27.1/libdjvu/GOS.cpp djvulibre-3.5.28/libdjvu/GOS.cpp --- djvulibre-3.5.27.1/libdjvu/GOS.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/GOS.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -154,13 +154,6 @@ #endif -static const char slash='/'; -static const char percent='%'; -static const char backslash='\\'; -static const char colon=':'; -static const char dot='.'; -static const char nillchar=0; - // ----------------------------------------- // Functions for dealing with filenames @@ -193,18 +186,18 @@ const char *fname=gfname; #if defined(_WIN32) || defined(OS2) // Special cases - if (fname[1] == colon) + if (fname[1] == ':') { if(!fname[2]) { return gfname; } - if (!fname[3] && (fname[2]== slash || fname[2]== backslash)) + if (!fname[3] && (fname[2]== '/' || fname[2]== '\\')) { char string_buffer[4]; string_buffer[0] = fname[0]; - string_buffer[1] = colon; - string_buffer[2] = backslash; + string_buffer[1] = ':'; + string_buffer[2] = '\\'; string_buffer[3] = 0; return string_buffer; } @@ -219,7 +212,7 @@ // Process suffix if (suffix) { - if (suffix[0]== dot ) + if (suffix[0]== '.' ) suffix ++; if (suffix[0]) { @@ -229,7 +222,7 @@ if (s > fname + sl) { s = s - (sl + 1); - if(*s == dot && (GUTF8String(s+1).downcase() == gsuffix.downcase())) + if(*s == '.' && (GUTF8String(s+1).downcase() == gsuffix.downcase())) { retval.setat((int)((size_t)s-(size_t)fname),0); } @@ -335,7 +328,7 @@ char drv[2]; if (dirname.length() && _chdir(dirname.getUTF82Native())==-1)//MBCS cvt G_THROW(errmsg()); - drv[0]= dot ; drv[1]=0; + drv[0]= '.' ; drv[1]=0; char *string_buffer; GPBuffer gstring_buffer(string_buffer,MAXPATHLEN+1); char *result = getcwd(string_buffer,MAXPATHLEN); diff -Nru djvulibre-3.5.27.1/libdjvu/GPixmap.cpp djvulibre-3.5.28/libdjvu/GPixmap.cpp --- djvulibre-3.5.27.1/libdjvu/GPixmap.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/GPixmap.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -482,6 +482,7 @@ break; case ('P'<<8)+'5': raw = grey = true; + /* FALLTHRU */ case ('P'<<8)+'6': raw = true; break; diff -Nru djvulibre-3.5.27.1/libdjvu/GSmartPointer.cpp djvulibre-3.5.28/libdjvu/GSmartPointer.cpp --- djvulibre-3.5.27.1/libdjvu/GSmartPointer.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/GSmartPointer.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -89,8 +89,10 @@ GPEnabled::~GPEnabled() { +#if DISABLED_BECAUSE_OF_CXX11_DESTRUCTORS_BEING_NOEXCEPT if (count > 0) G_THROW( ERR_MSG("GSmartPointer.suspicious") ); +#endif } void diff -Nru djvulibre-3.5.27.1/libdjvu/GString.cpp djvulibre-3.5.28/libdjvu/GString.cpp --- djvulibre-3.5.27.1/libdjvu/GString.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/GString.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -273,7 +273,9 @@ ~ChangeLocale(); private: GUTF8String locale; +#if DO_CHANGELOCALE int category; +#endif }; class GStringRep::Native : public GStringRep @@ -452,7 +454,9 @@ } GStringRep::ChangeLocale::ChangeLocale(const int xcategory, const char xlocale[] ) +#if DO_CHANGELOCALE : category(xcategory) +#endif { #if DO_CHANGELOCALE // This is disabled under UNIX because @@ -1212,11 +1216,11 @@ GStringRep::getbuf(int n) const { GP retval; - if(n< 0) + if(n < 0) n=strlen(data); - if(n>0) + if(n >= 0) { - retval=blank(n); + retval=blank((n>0) ? n : 1); char *ndata=retval->data; strncpy(ndata,data,n); ndata[n]=0; diff -Nru djvulibre-3.5.27.1/libdjvu/GThreads.cpp djvulibre-3.5.28/libdjvu/GThreads.cpp --- djvulibre-3.5.27.1/libdjvu/GThreads.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/GThreads.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -446,8 +446,10 @@ void GThread::terminate() { +#ifndef __ANDROID__ if (xentry || xarg) pthread_cancel(hthr); +#endif } int diff -Nru djvulibre-3.5.27.1/libdjvu/GURL.cpp djvulibre-3.5.28/libdjvu/GURL.cpp --- djvulibre-3.5.27.1/libdjvu/GURL.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/GURL.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -170,7 +170,6 @@ static const char djvuopts[]="DJVUOPTS"; static const char localhost[]="file://localhost/"; -static const char backslash='\\'; static const char colon=':'; static const char dot='.'; static const char filespecslashes[] = "file://"; @@ -179,13 +178,14 @@ static const char percent='%'; static const char localhostspec1[] = "//localhost/"; static const char localhostspec2[] = "///"; -static const char nillchar=0; #if defined(UNIX) static const char tilde='~'; static const char root[] = "/"; #elif defined(_WIN32) || defined(OS2) static const char root[] = "\\"; + static const char backslash='\\'; #elif defined(macintosh) + static const char nillchar=0; static char const * const root = &nillchar; #else #error "Define something here for your operating system" diff -Nru djvulibre-3.5.27.1/libdjvu/IW44EncodeCodec.cpp djvulibre-3.5.28/libdjvu/IW44EncodeCodec.cpp --- djvulibre-3.5.27.1/libdjvu/IW44EncodeCodec.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/IW44EncodeCodec.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -125,7 +125,7 @@ }; static const int iw_shift = 6; -static const int iw_round = (1<<(iw_shift-1)); +// static const int iw_round = (1<<(iw_shift-1)); static const struct { int start; int size; } bandbuckets[] = @@ -405,7 +405,7 @@ int y = 0; int s = scale*rowsize; int s3 = s+s+s; - h = ((h-1)/scale)+1; + h = (h>0) ? ((h-1)/scale)+1 : 0; y += 1; p += s; while (y-3 < h) diff -Nru djvulibre-3.5.27.1/libdjvu/IW44Image.cpp djvulibre-3.5.28/libdjvu/IW44Image.cpp --- djvulibre-3.5.27.1/libdjvu/IW44Image.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/IW44Image.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -125,15 +125,6 @@ 0x040000, 0x040000, 0x080000 }; -static const float iw_norm[16] = { - 2.627989e+03F, - 1.832893e+02F, 1.832959e+02F, 5.114690e+01F, - 4.583344e+01F, 4.583462e+01F, 1.279225e+01F, - 1.149671e+01F, 1.149712e+01F, 3.218888e+00F, - 2.999281e+00F, 2.999476e+00F, 8.733161e-01F, - 1.074451e+00F, 1.074511e+00F, 4.289318e-01F -}; - static const int iw_border = 3; static const int iw_shift = 6; static const int iw_round = (1<<(iw_shift-1)); @@ -604,7 +595,7 @@ { bw = (w+0x20-1) & ~0x1f; bh = (h+0x20-1) & ~0x1f; - nb = (bw * bh) / (32 * 32); + nb = (unsigned int)(bw*bh) / (32 * 32); blocks = new IW44Image::Block[nb]; top = IWALLOCSIZE; } diff -Nru djvulibre-3.5.27.1/libdjvu/IW44Image.h djvulibre-3.5.28/libdjvu/IW44Image.h --- djvulibre-3.5.27.1/libdjvu/IW44Image.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/IW44Image.h 2020-11-20 16:57:32.000000000 +0000 @@ -593,7 +593,7 @@ void zero(int n); // sparse representation private: - short **(pdata[4]); + short **pdata[4]; }; //--------------------------------------------------------------- diff -Nru djvulibre-3.5.27.1/libdjvu/Makefile.am djvulibre-3.5.28/libdjvu/Makefile.am --- djvulibre-3.5.27.1/libdjvu/Makefile.am 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/Makefile.am 2020-11-20 16:57:32.000000000 +0000 @@ -38,6 +38,10 @@ libdjvulibre_la_LDFLAGS += -Wl,--export-all-symbols endif +if HAVE_OS_APPLE +libdjvulibre_la_LDFLAGS += -framework CoreFoundation +endif + sed_process = $(SED) \ -e 's,@PACKAGE_VERSION\@,$(PACKAGE_VERSION),g' \ -e 's,@prefix\@,$(prefix),g' \ diff -Nru djvulibre-3.5.27.1/libdjvu/miniexp.cpp djvulibre-3.5.28/libdjvu/miniexp.cpp --- djvulibre-3.5.27.1/libdjvu/miniexp.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/miniexp.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -3,8 +3,8 @@ // MiniExp - Library for handling lisp expressions // Copyright (c) 2005 Leon Bottou // -// This software is subject to, and may be distributed under, the -// GNU General Public License, either version 2 of the license +// This software is subject to, and may be distributed under, the GNU +// Lesser General Public License, either Version 2.1 of the license, // or (at your option) any later version. The license should have // accompanied the software or you may obtain a copy of the license // from the Free Software Foundation at http://www.fsf.org . @@ -134,7 +134,7 @@ public: int nelems; int nbuckets; - struct sym { unsigned int h; struct sym *l; char *n; }; + struct sym { unsigned int h; struct sym *l; char *n; miniexp_t v; }; struct sym **buckets; symtable_t(); ~symtable_t(); @@ -201,6 +201,7 @@ r->h = h; r->l = buckets[i]; r->n = new char [1+strlen(n)]; + r->v = (miniexp_t)(((size_t)r)|((size_t)2)); strcpy(r->n, n); buckets[i] = r; if ( 2 * nelems > 3 * nbuckets) @@ -220,7 +221,7 @@ { struct symtable_t::sym *r; r = ((symtable_t::sym*)(((size_t)p)&~((size_t)3))); - return (r) ? r->n : "##(dummy)"; + return (r && r->v == p) ? r->n : "##(dummy)"; } return 0; } @@ -236,7 +237,7 @@ symbols = new symtable_t; } r = symbols->lookup(name, true); - return (miniexp_t)(((size_t)r)|((size_t)2)); + return r->v; } @@ -319,6 +320,7 @@ END_ANONYMOUS_NAMESPACE #if USE_PTHREADS + // Manage thread specific data with pthreads static pthread_key_t gctls_key; static pthread_once_t gctls_once; @@ -353,6 +355,7 @@ # endif #elif USE_WINTHREADS + // Manage thread specific data with win32 #if defined(_MSC_VER) && defined(USE_MSVC_TLS) // -- Pre-vista os sometimes crashes on this. @@ -382,17 +385,24 @@ {CSLOCK(r);TlsFree(tlsIndex);tlsIndex=TLS_OUT_OF_INDEXES;} } # endif -// -- Very black magic to clean tls variables. -# ifdef _M_IX86 -# pragma comment (linker, "/INCLUDE:_tlscb") +// -- Very black magic to clean the TLS variables +# if !defined(_MSC_VER) +# warning "This only works with MSVC. Memory leak otherwise" +# elif !defined(MINILISPAPI_EXPORT) +# pragma message("This only works for a DLL. Memory leak otherwise") # else -# pragma comment (linker, "/INCLUDE:tlscb") -# endif -# pragma const_seg(".CRT$XLB") +# ifdef _M_IX86 +# pragma comment (linker, "/INCLUDE:_tlscb") +# else +# pragma comment (linker, "/INCLUDE:tlscb") +# endif +# pragma const_seg(".CRT$XLB") extern "C" PIMAGE_TLS_CALLBACK tlscb = gctls_cb; -# pragma const_seg() +# pragma const_seg() +# endif #else + // No threads static gctls_t *gctls() { static gctls_t g; @@ -899,6 +909,18 @@ return res; } +bool +miniobj_t::stringp(const char* &, size_t &) const +{ + return false; +} + +bool +miniobj_t::doublep(double&) const +{ + return false; +} + miniexp_t miniexp_object(miniobj_t *obj) { @@ -939,12 +961,13 @@ MINIOBJ_DECLARE(ministring_t,miniobj_t,"string"); public: ~ministring_t(); - ministring_t(const char *s); - ministring_t(char *s, bool steal); + ministring_t(size_t len, const char *s); + ministring_t(size_t len, char *s, bool steal); operator const char*() const { return s; } - virtual char *pname() const; + virtual bool stringp(const char* &s, size_t &l) const; private: char *s; + size_t l; private: ministring_t(const ministring_t &); ministring_t& operator=(const ministring_t &); @@ -957,18 +980,29 @@ delete [] s; } -ministring_t::ministring_t(const char *str) - : s(new char[strlen(str)+1]) +ministring_t::ministring_t(size_t len, const char *str) + : s(0), l(len) { - strcpy(s,str); + s = new char[l+1]; + memcpy(s, str, l); + s[l] = 0; } -ministring_t::ministring_t(char *str, bool steal) - : s(str) +ministring_t::ministring_t(size_t len, char *str, bool steal) + : s(str), l(len) { ASSERT(steal); } +bool +ministring_t::stringp(const char* &rs, size_t &rl) const +{ + rs = s; + rl = l; + return true; +} + + END_ANONYMOUS_NAMESPACE static bool @@ -985,13 +1019,15 @@ } static bool -char_utf8(int &c, const char* &s) +char_utf8(int &c, const char* &s, size_t &len) { if (c < 0xc0) return (c < 0x80); if (c >= 0xf8) return false; int n = (c < 0xe0) ? 1 : (c < 0xf0) ? 2 : 3; + if ((size_t)n > len) + return false; int x = c & (0x3f >> n); for (int i=0; i= 0xd800 && x <= 0xdfff) return false; + len -= n; s += n; c = x; return true; @@ -1019,16 +1056,17 @@ } static int -print_c_string(const char *s, char *d, int flags = 0) +print_c_string(const char *s, char *d, int flags, size_t len) { int c; int n = 0; char_out('\"', d, n); - while ((c = (unsigned char)(*s++))) + while (len-- > 0) { + c = (unsigned char)(*s++); if (char_quoted(c, flags)) { - char buffer[10]; + char buffer[16]; /* 10+1 */ static const char *tr1 = "\"\\tnrbf"; static const char *tr2 = "\"\\\t\n\r\b\f"; buffer[0] = buffer[1] = 0; @@ -1038,7 +1076,7 @@ buffer[0] = tr1[i]; if (buffer[0] == 0 && c >= 0x80 && (flags & (miniexp_io_u4escape | miniexp_io_u6escape)) - && char_utf8(c, s) ) + && char_utf8(c, s, len) ) { if (c <= 0xffff && (flags & miniexp_io_u4escape)) sprintf(buffer,"u%04X", c); @@ -1049,6 +1087,9 @@ 0xd800+(((c-0x10000)>>10)&0x3ff), 0xdc00+(c&0x3ff)); } + if (buffer[0] == 0 && c == 0) + if (*s < '0' || *s > '7') + buffer[0] = '0'; if (buffer[0] == 0) sprintf(buffer, "%03o", c); for (int i=0; buffer[i]; i++) @@ -1062,68 +1103,74 @@ return n; } -char * -ministring_t::pname() const -{ - int n = print_c_string(s, 0); - char *d = new char[n]; - if (d) print_c_string(s, d); - return d; -} - int miniexp_stringp(miniexp_t p) { - return miniexp_isa(p, ministring_t::classname) ? 1 : 0; + const char *s; size_t l; + if (miniexp_objectp(p) && miniexp_to_obj(p)->stringp(s,l)) + return 1; + return 0; } const char * miniexp_to_str(miniexp_t p) { - miniobj_t *obj = miniexp_to_obj(p); - if (miniexp_stringp(p)) - return (const char*) * (ministring_t*) obj; - return 0; + const char *s = 0; + miniexp_to_lstr(p, &s); + return s; } -miniexp_t +size_t +miniexp_to_lstr(miniexp_t p, const char **sp) +{ + const char *s = 0; + size_t l = 0; + if (miniexp_objectp(p)) + miniexp_to_obj(p)->stringp(s,l); + if (sp) + *sp = s; + return l; +} + +miniexp_t miniexp_string(const char *s) { - ministring_t *obj = new ministring_t(s); - return miniexp_object(obj); + return miniexp_lstring(strlen(s), s); } miniexp_t -miniexp_substring(const char *s, int n) +miniexp_lstring(size_t len, const char *s) { - int l = strlen(s); - n = (n < l) ? n : l; - char *b = new char[n+1]; - strncpy(b, s, n); - b[n] = 0; - ministring_t *obj = new ministring_t(b, true); + ministring_t *obj = new ministring_t(len,s); return miniexp_object(obj); } miniexp_t +miniexp_substring(const char *s, int len) +{ + size_t l = strlen(s); + size_t n = (size_t)len; + return miniexp_lstring((l < n) ? l : n, s); +} + +miniexp_t miniexp_concat(miniexp_t p) { miniexp_t l = p; const char *s; - int n = 0; + size_t n = 0; if (miniexp_length(l) < 0) return miniexp_nil; for (p=l; miniexp_consp(p); p=cdr(p)) - if ((s = miniexp_to_str(car(p)))) - n += strlen(s); + n += miniexp_to_lstr(car(p), 0); char *b = new char[n+1]; char *d = b; for (p=l; miniexp_consp(p); p=cdr(p)) - if ((s = miniexp_to_str(car(p)))) { - strcpy(d, s); - d += strlen(d); + if ((n = miniexp_to_lstr(car(p), &s))) { + memcpy(d, s, n); + d += n; } - ministring_t *obj = new ministring_t(b, true); + ministring_t *obj = new ministring_t(d-b, b, true); return miniexp_object(obj); } @@ -1142,6 +1189,7 @@ minifloat_t(double x) : val(x) {} operator double() const { return val; } virtual char *pname() const; + virtual bool doublep(double &d) const { d=val; return true; } private: double val; }; @@ -1164,14 +1212,25 @@ return miniexp_object(obj); } +int +miniexp_doublep(miniexp_t p) +{ + double v = 0.0; + if (miniexp_numberp(p) || + (miniexp_objectp(p) && miniexp_to_obj(p)->doublep(v)) ) + return 1; + return 0; +} + double miniexp_to_double(miniexp_t p) { + double v = 0.0; if (miniexp_numberp(p)) - return (double) miniexp_to_int(p); - else if (miniexp_floatnump(p)) - return (double) * (minifloat_t*) miniexp_to_obj(p); - return 0.0; + v = (double) miniexp_to_int(p); + else if (miniexp_objectp(p)) + miniexp_to_obj(p)->doublep(v); + return v; } miniexp_t @@ -1418,11 +1477,12 @@ } else if (miniexp_stringp(p)) { - const char *s = miniexp_to_str(p); - int n = print_c_string(s, 0, flags); + const char *s; + size_t len = miniexp_to_lstr(p, &s); + int n = print_c_string(s, 0, flags, len); char *d = new char[n]; if (d) - print_c_string(s, d, flags); + print_c_string(s, d, flags, len); mlput(d); delete [] d; } @@ -1644,7 +1704,7 @@ /* ---- INPUT */ static void -grow(char* &s, int &l, int &m) +grow(char* &s, size_t &l, size_t &m) { int nm = ((m<256)?256:m) + ((m>32000)?32000:m); char *ns = new char[nm+1]; @@ -1655,7 +1715,7 @@ } static void -append(int c, char* &s, int &l, int &m) +append(int c, char* &s, size_t &l, size_t &m) { if (l >= m) grow(s, l, m); @@ -1664,7 +1724,7 @@ } static void -append_utf8(int x, char *&s, int &l, int &m) +append_utf8(int x, char *&s, size_t &l, size_t &m) { if (x >= 0 && x <= 0x10ffff) { @@ -1745,8 +1805,8 @@ { miniexp_t r; char *s = 0; - int l = 0; - int m = 0; + size_t l = 0; + size_t m = 0; ASSERT(c == '\"'); c = io->fgetc(io); for(;;) @@ -1819,8 +1879,8 @@ io->ungetc(io, c); c = d; } - static const char *tr1 = "tnrbfva"; - static const char *tr2 = "\t\n\r\b\f\013\007"; + static const char *tr1 = "tnrbfvae?"; + static const char *tr2 = "\t\n\r\b\f\013\007\033?"; for (int i=0; tr1[i]; i++) if (c == tr1[i]) c = tr2[i]; @@ -1829,7 +1889,7 @@ c = io->fgetc(io); } c = io->fgetc(io); - r = miniexp_string(s ? s : ""); + r = miniexp_lstring(l, s); delete [] s; return r; } @@ -1839,8 +1899,8 @@ { miniexp_t r; char *s = 0; - int l = 0; - int m = 0; + size_t l = 0; + size_t m = 0; ASSERT(c == '|'); for(;;) { @@ -1862,8 +1922,8 @@ { miniexp_t r; char *s = 0; - int l = 0; - int m = 0; + size_t l = 0; + size_t m = 0; for(;;) { if (c==EOF || c=='(' || c==')' || c=='|' || c=='\"' @@ -1970,7 +2030,7 @@ if (io->p_diezechar && io->p_macroqueue && nc >= 0 && nc < 128 && io->p_diezechar[nc]) { - miniexp_t p = io->p_macrochar[nc](io); + miniexp_t p = io->p_diezechar[nc](io); if (miniexp_length(p) > 0) *io->p_macroqueue = p; else if (p) diff -Nru djvulibre-3.5.27.1/libdjvu/miniexp.h djvulibre-3.5.28/libdjvu/miniexp.h --- djvulibre-3.5.27.1/libdjvu/miniexp.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/miniexp.h 2020-11-20 16:57:32.000000000 +0000 @@ -3,8 +3,8 @@ // MiniExp - Library for handling lisp expressions // Copyright (c) 2005 Leon Bottou // -// This software is subject to, and may be distributed under, the -// GNU General Public License, either Version 2 of the license, +// This software is subject to, and may be distributed under, the GNU +// Lesser General Public License, either Version 2.1 of the license, // or (at your option) any later version. The license should have // accompanied the software or you may obtain a copy of the license // from the Free Software Foundation at http://www.fsf.org . @@ -269,16 +269,28 @@ MINILISPAPI const char *miniexp_to_str(miniexp_t p); +/* miniexp_to_lstr ---- + Returns the length of the string represented by the expression. + Optionally returns the c string into *sp. + Return 0 and makes *sp null if the expression is not a string. */ + +MINILISPAPI size_t miniexp_to_lstr(miniexp_t p, const char **sp); + /* miniexp_string -- - Constructs a string expression by copying string s. */ + Constructs a string expression by copying zero terminated string s. */ MINILISPAPI miniexp_t miniexp_string(const char *s); +/* miniexp_lstring -- + Constructs a string expression by copying len bytes from s. */ + +MINILISPAPI miniexp_t miniexp_lstring(size_t len, const char *s); + /* miniexp_substring -- - Constructs a string expression by copying - at most n character from string s. */ + Constructs a string expression by copying at most len bytes + from zero terminated string s. */ -MINILISPAPI miniexp_t miniexp_substring(const char *s, int n); +MINILISPAPI miniexp_t miniexp_substring(const char *s, int len); /* miniexp_concat -- Concat all the string expressions in list . */ @@ -304,13 +316,11 @@ Tests if an expression can be converted to a double precision number. */ -static inline int miniexp_doublep(miniexp_t p) { - return miniexp_numberp(p) || miniexp_floatnump(p); -} +MINILISPAPI int miniexp_doublep(miniexp_t p); /* miniexp_to_double -- Returns a double precision number corresponding to - a lisp expression (a number or a floatnum.) */ + a lisp expression. */ MINILISPAPI double miniexp_to_double(miniexp_t p); @@ -368,15 +378,7 @@ s-expressions without modifying them does not need to bother about minivars. - * Only the following miniexp functions can cause a - garbage collection: miniexp_cons(), miniexp_object(), - miniexp_string(), miniexp_substring(), miniexp_pname(), - miniexp_concat(), miniexp_pprin(), miniexp_pprint(), - miniexp_gc(), and minilisp_release_gc_lock(). A - function that does not cause calls to these functions - does not need to bother about minivars. - - * Other functions should make sure that all useful + * Otherwise all functions should make sure that all useful s-expression are directly or indirectly secured by a minivar_t object. In case of doubt, use minivars everywhere. @@ -721,6 +723,11 @@ /* pname: returns a printable name for this object. The caller must deallocate the result with delete[]. */ virtual char *pname() const; + /* stringp, doublep: tells whether this object should be + interpreted/printed as a generic string (for miniexp_strinp) + or a double (for miniexp_doublep). */ + virtual bool stringp(const char* &s, size_t &l) const; + virtual bool doublep(double &d) const; /* mark: calls action() on all member miniexps of the object, for garbage collecting purposes. */ virtual void mark(minilisp_mark_t *action); diff -Nru djvulibre-3.5.27.1/libdjvu/MMX.cpp djvulibre-3.5.28/libdjvu/MMX.cpp --- djvulibre-3.5.27.1/libdjvu/MMX.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/MMX.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -65,6 +65,14 @@ #include #include +#ifdef MMX +# ifdef HAVE_CPUID_H +# include +# endif +# if defined(_MSC_VER) && defined(_WIN32) +# include +# endif +#endif #ifdef HAVE_NAMESPACES namespace DJVU { @@ -132,90 +140,25 @@ int MMXControl::enable_mmx() { - int cpuflags = 0; const char *envvar = getenv("LIBDJVU_DISABLE_MMX"); if (envvar && envvar[0] && envvar[0]!='0') return ((mmxflag = 0)); -#if defined(MMX) && defined(__GNUC__) && defined(__i386__) - // Detection of MMX for GCC - __asm__ volatile ("pushl %%ebx\n\t" - "pushfl\n\t" - "popl %%ecx\n\t" - "xorl %%edx,%%edx\n\t" - // Check that CPUID exists - "movl %%ecx,%%eax\n\t" - "xorl $0x200000,%%eax\n\t" - "pushl %%eax\n\t" - "popfl\n\t" - "pushfl\n\t" - "popl %%eax\n\t" - "xorl %%ecx,%%eax\n\t" - "jz 1f\n\t" - "pushl %%ecx\n\t" - "popfl\n\t" - // Check that CR0:EM is clear - "smsw %%ax\n\t" - "andl $4,%%eax\n\t" - "jnz 1f\n\t" - // Execute CPUID - "movl $1,%%eax\n\t" - "cpuid\n" - // EBX contains magic when -fPIC is on. - "1:\tpopl %%ebx\n\t" - "movl %%edx, %0" - : "=m" (cpuflags) : - : "eax","ecx","edx"); -#endif -#if defined(MMX) && defined(__GNUC__) && defined(__x86_64__) - // Detection of MMX for GCC - __asm__ volatile (// Check that CR0:EM is clear - "xorl %%edx,%%edx\n\t" - "smsw %%ax\n\t" - "andl $4,%%eax\n\t" - "jnz 1f\n\t" - // Execute CPUID - "movl $1,%%eax\n\t" - "cpuid\n" - // Finish - "1:\tmovl %%edx, %0" - : "=m" (cpuflags) : - : "eax","ebx","ecx","edx"); -#endif -#if defined(MMX) && defined(_MSC_VER) && defined(_M_IX86) - // Detection of MMX for MSVC 32 bits - __asm { pushfd - pop ecx - xor edx,edx - ;// Check that CPUID exists - mov eax,ecx - xor eax,0x200000 - push eax - popfd - pushfd - pop eax - xor eax,ecx - jz fini - push ecx - popfd - ;// Check that CR0:EM is zero - smsw ax - and eax,4 - jnz fini - ;// Execute CPUID - mov eax,1 - _emit 0xf - _emit 0xa2 - fini: - mov cpuflags,edx - ;// MSVC determines clobbered registers by scanning the assembly code. - ;// Since it does not know CPUID, it would not know that EBX is clobbered - ;// without the dummy instruction below... - xor ebx,ebx - } +#if defined(MMX) && defined(__GNUC__) && defined(HAVE_CPUID_H) + unsigned int eax,ebx,ecx,edx; + if (__get_cpuid(1,&eax,&ebx,&ecx,&edx)) + if (edx & (1<<23)) + return ((mmxflag = 1)); #endif - mmxflag = !!(cpuflags & 0x800000); - return mmxflag; + +#if defined(MMX) && defined(_MSC_VER) && defined(_WIN32) + int cpuinfo[4]; + __cpuid(cpuinfo, 1); + if (cpuinfo[3] & (1<<23)) + return ((mmxflag = 1)); +#endif + + return ((mmxflag = 0)); } diff -Nru djvulibre-3.5.27.1/libdjvu/UnicodeByteStream.cpp djvulibre-3.5.28/libdjvu/UnicodeByteStream.cpp --- djvulibre-3.5.27.1/libdjvu/UnicodeByteStream.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/libdjvu/UnicodeByteStream.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -280,6 +280,7 @@ break; } } + break; } case 0x003C: { @@ -350,6 +351,7 @@ default: { buffer=GUTF8String::create(buf,sizeof(buf),GStringRep::XUTF8); + break; } } bs=ibs; diff -Nru djvulibre-3.5.27.1/NEWS djvulibre-3.5.28/NEWS --- djvulibre-3.5.27.1/NEWS 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/NEWS 2020-11-20 16:57:32.000000000 +0000 @@ -1,8 +1,29 @@ +NEW IN VERSION 3.5.28 +------------------------ +- ddjvu: tiff generation improvements +- djvumake: security checks on INCL chunks +- all: updated for modern compilers +- win: moved to msvc2019 +- osx: nfd filename normalization +- bugs: fixed several crashes on invalid inputs +- miniexp: fixed escape printout and macrochars +- djvudigital: can use poppler to find text +- csepdjvu: handle T comments for page titles +- bytestream: fixed 2GB limit +- gexception, gthread: cleanup obsolete code + + NEW IN VERSION 3.5.27 ------------------------ - simplified configuration scripts - deadlock fixes - miniexp under win32 uses tlsalloc instead of _thread vars (pb under xp) +- djvudigital can extract text and metadata using pdftotext. +- duplicate page titles are accepted +- bug fixes: overflow in bitmap/pixmap/iw44image sizes +- big fixes: handling INCL chunks in djvumake +- bug fixes: better support for large files (2gb) + NEW IN VERSION 3.5.26 ------------------------ diff -Nru djvulibre-3.5.27.1/README djvulibre-3.5.28/README --- djvulibre-3.5.27.1/README 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/README 2020-11-20 16:57:32.000000000 +0000 @@ -210,7 +210,7 @@ 5 - BUILDING FOR WINDOWS ======================== -5.1- Using Microsoft Visual C++ 2012 +5.1- Using Microsoft Visual C++ 2019 ------------------------------------ See the directory win32. diff -Nru djvulibre-3.5.27.1/share/djvu/osi/en/libdjvu++.xml djvulibre-3.5.28/share/djvu/osi/en/libdjvu++.xml --- djvulibre-3.5.27.1/share/djvu/osi/en/libdjvu++.xml 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/share/djvu/osi/en/libdjvu++.xml 2020-11-20 16:57:32.000000000 +0000 @@ -511,7 +511,7 @@ [1-%0!05u!] Illegal chunk number. -[1-%0!05u!] Malformed INCL chunk. No slashes allowed. +[1-%0!05u!] Malformed INCL chunk. Slashes, backslashes, or colons are not allowed. [1-%0!05u!] Too few chunks. diff -Nru djvulibre-3.5.27.1/tools/any2djvu djvulibre-3.5.28/tools/any2djvu --- djvulibre-3.5.27.1/tools/any2djvu 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/any2djvu 2020-11-20 16:57:32.000000000 +0000 @@ -28,7 +28,7 @@ # TO DO: # - error handling -rurl="http://any2djvu.djvuzone.org" +rurl="http://any2djvu.djvu.org" rcgi="any2djvu.php" res=400 ocr=1 @@ -83,7 +83,7 @@ echo "Examples:" echo " cd ~bap/public_html/foo" echo " # uploads from web-accessible directory" - echo " any2djvu http://www.bcl.hamilton.ie/~barak/papers mesh-preprint.ps.gz" + echo " any2djvu http://barak.pearlmutter.net/papers mesh-preprint.ps.gz" echo " any2djvu http://www.inference.phy.cam.ac.uk/mackay *.ps.gz bar.pdf" echo " # uploads from current directory" echo " any2djvu b*.pdf" diff -Nru djvulibre-3.5.27.1/tools/any2djvu.1 djvulibre-3.5.28/tools/any2djvu.1 --- djvulibre-3.5.27.1/tools/any2djvu.1 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/any2djvu.1 2020-11-20 16:57:32.000000000 +0000 @@ -14,7 +14,7 @@ Non-empty value of DJVU_ONLINE_ACK acknowledges transmission of the documents to the server (so that no warning dialog is displayed). .SH EXAMPLES -any2djvu http://www.bcl.hamilton.ie/~barak/papers mesh-preprint.ps.gz +any2djvu http://barak.pearlmutter.net/papers mesh-preprint.ps.gz .PP any2djvu localfile.pdf .SH AUTHORS diff -Nru djvulibre-3.5.27.1/tools/cjb2.cpp djvulibre-3.5.28/tools/cjb2.cpp --- djvulibre-3.5.27.1/tools/cjb2.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/cjb2.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -744,6 +744,8 @@ readproc, writeproc, seekproc, closeproc, sizeproc, mapproc, unmapproc ); + if (! tiff) + G_THROW("Tiff image is corrupted (cannot open)"); // bitonal uint16 bps = 0, spp = 0; TIFFGetFieldDefaulted(tiff, TIFFTAG_BITSPERSAMPLE, &bps); diff -Nru djvulibre-3.5.27.1/tools/csepdjvu.1 djvulibre-3.5.28/tools/csepdjvu.1 --- djvulibre-3.5.27.1/tools/csepdjvu.1 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/csepdjvu.1 2020-11-20 16:57:32.000000000 +0000 @@ -188,22 +188,21 @@ .SS Comments in separated files -Each page is followed by an arbitrary number of comment lines -starting with character "#" and terminated by a linefeed character. -Comment lines whose first word starts with a capital letter have -special meanings. The following constructs are currently defined: +Each page is followed by an arbitrary number of comment lines starting with +character "#" and terminated by a linefeed character. Certain comment lines +have special meanings. In the following constructs, all the strings are UTF-8 +encoded and represent in the style of Postscript strings, that is, surrounded +with parenthesis and using C-style escape sequences introduced by a backslash. .IP "*" 3 .BI "# T " px ":" py " " dx ":" dy " " w "x" h "+" x "+" y " (" string ")" .br -This constructs indicates that the piece of text +Such a comment line indicates that the piece of text .I string must be associated with an area of size .IR w "x" h at position .IR x "," y relative to the lower left corner of the page. -The string is UTF-8 encoded. Special characters -can be escaped as in PostScript using the backslash character. Integers .IR px ", and " py represent the position of the current point on the text baseline @@ -218,7 +217,7 @@ .IP "*" 3 .BI "# L " w "x" h "+" x "+" y " (" url ")" .br -This construct indicates that an hyperlink to url +Such a comment line indicates that an hyperlink to url .I url should be associated with area of size .IR w "x" h @@ -231,7 +230,7 @@ .IP "*" 3 .BI "# B " count " (" string ") (#" pageno ")" .br -This constructs provides outline information for the document. +Such a comment line provides outline information for the document. An outline entry entitled .I string is associated with page @@ -244,7 +243,12 @@ .BR csepdjvu produces an navigation chunk with the specified outline. - +.IP "*" 3 +.BI "# P (" string ")" +.br +Such a comment line provides a title +.I string +for the current page. .SH CREDITS This program was initially written by L\('eon Bottou diff -Nru djvulibre-3.5.27.1/tools/csepdjvu.cpp djvulibre-3.5.28/tools/csepdjvu.cpp --- djvulibre-3.5.27.1/tools/csepdjvu.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/csepdjvu.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -1121,6 +1121,7 @@ bool parse_comment_line(BufferByteStream &bs); void make_chunks(IFFByteStream &iff); GP get_djvm_nav(); + GUTF8String get_pagetitle(); protected: int w; int h; @@ -1143,6 +1144,7 @@ }; GPList links; GP nav; + GUTF8String pagetitle; protected: bool allspace(const TxtMark *mark); void textmark(GP mark); @@ -1255,6 +1257,15 @@ nav->append(b); return true; } + // Page title comment + if (c == 'P') + { + if (pagetitle.length()) + G_THROW("csepdjvu: corrupted file (multiple page title comments)"); + if (! (bs.skip(" \t") && bs.read_ps_string(pagetitle) )) + G_THROW("csepdjvu: corrupted file (syntax error in title comment)"); + return true; + } // Unrecognized bs.unget(c); return false; @@ -1487,6 +1498,12 @@ return 0; } +GUTF8String +Comments::get_pagetitle() +{ + return pagetitle; +} + // -------------------------------------------------- // MAIN COMPRESSION ROUTINE @@ -1500,6 +1517,7 @@ csepdjvu_page(BufferByteStream &bs, GP obs, GP &nav, + GUTF8String &pagetitle, const csepdjvuopts &opts) { // Read rle data from separation file @@ -1671,7 +1689,8 @@ // -- terminate main composite chunk coms.make_chunks(iff); iff.close_chunk(); - // -- store outline + // -- returns page title and outline + pagetitle = coms.get_pagetitle(); if (! nav) nav = coms.get_djvm_nav(); } @@ -1765,6 +1784,7 @@ { GP gdoc=DjVmDoc::create(); GP gnav; + GUTF8String pagetitle; DjVmDoc &doc=*gdoc; GURL outputurl; GP goutputpage=ByteStream::create(); @@ -1814,14 +1834,14 @@ ByteStream::create(GURL::Filename::UTF8(arg),"rb"); BufferByteStream ibs(*fbs); do { - char pagename[16]; + char pagename[20]; sprintf(pagename, "p%04d.djvu", ++pageno); if (opts.verbose > 1) DjVuPrintErrorUTF8("%s","--------------------\n"); // Compress page goutputpage=ByteStream::create(); ByteStream &outputpage=*goutputpage; - csepdjvu_page(ibs, goutputpage, gnav, opts); + csepdjvu_page(ibs, goutputpage, gnav, pagetitle, opts); if (opts.verbose) { DjVuPrintErrorUTF8("csepdjvu: %d bytes for page %d", outputpage.size(), pageno); @@ -1834,12 +1854,12 @@ // Insert page into document outputpage.seek(0); doc.insert_file(outputpage, DjVmDir::File::PAGE, - pagename, pagename); + pagename, pagename, pagetitle); } while (check_for_another_page(ibs, opts)); } } // Save file - if (pageno == 1 && ! gnav) + if (pageno == 1 && ! gnav && ! pagetitle) { ByteStream &outputpage=*goutputpage; // Save as a single page diff -Nru djvulibre-3.5.27.1/tools/ddjvu.cpp djvulibre-3.5.28/tools/ddjvu.cpp --- djvulibre-3.5.27.1/tools/ddjvu.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/ddjvu.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -279,7 +279,7 @@ prect.h = (ih * 100) / dpi; } /* Process aspect ratio */ - if (flag_aspect <= 0) + if (flag_aspect <= 0 && iw>0 && ih>0) { double dw = (double)iw / prect.w; double dh = (double)ih / prect.h; @@ -691,7 +691,7 @@ args[1] = "-o"; args[2] = filename; if (tiff2pdf(tiff, fout, 3, args) != EXIT_SUCCESS) - die(i18n("Error occured while creating PDF file.")); + die(i18n("Error occurred while creating PDF file.")); TIFFClose(tiff); tiff = 0; #ifndef _WIN32 diff -Nru djvulibre-3.5.27.1/tools/djvu.1 djvulibre-3.5.28/tools/djvu.1 --- djvulibre-3.5.27.1/tools/djvu.1 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/djvu.1 2020-11-20 16:57:32.000000000 +0000 @@ -142,8 +142,7 @@ and .BR image/x-djvu , which may still be encountered. Ideally, clients should be configured -to handle all three. (For web server configuration help, see -.BR http://www.djvuzone.org/support/tutorial/chapter-authoring1.html .) +to handle all three. .SS Bundled multi-page documents Bundled multi-page DjVu document uses a single file to represent the entire @@ -209,14 +208,17 @@ .SH DJVUZONE AND DJVULIBRE The DjVu technology was initially created by a few researchers in AT&T Labs -between 1995 and 1999. Lizardtech, Inc. ( -.B http://www.lizardtech.com -) then obtained a commercial license from AT&T and continued -the development. They have now a variety of solutions for producing -and distributing documents using the DjVu technology. +between 1995 and 1999. Lizardtech, Inc. +then obtained a commercial license from AT&T and continued +the development. The current owner of the DjVu commercial +rights is Cuminas ( +.B https://www.cuminas.jp/en/about_djvu +), offers solutions for producing +and distributing documents using the DjVu technology, +as well as a DjVu viewer packaged as a Chrome extension. .PP -The DjVuZone web site ( -.B http://www.djvuzone.org +The DjVu.org web site ( +.B http://www.djvu.org ) is managed by the few AT&T Labs researchers who created the DjVu technology in the first place. We promote the DjVu technology by providing an independent source of information about DjVu. @@ -338,7 +340,7 @@ Another solution is provided by the compression server at -.BR "" ( "http://any2djvu.djvuzone.org" ). +.BR "" ( "http://any2djvu.djvu.org" ). This machine uses pre-lizardtech prototype encoders from AT&T Labs and performs almost as well as the commercial Lizardtech encoders. Please note that the Any2DjVu compression server comes with no guarantee, that diff -Nru djvulibre-3.5.27.1/tools/djvudigital djvulibre-3.5.28/tools/djvudigital --- djvulibre-3.5.27.1/tools/djvudigital 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/djvudigital 2020-11-20 16:57:32.000000000 +0000 @@ -54,7 +54,18 @@ #C- +------------------------------------------------------------------ #C-------------------------------------------------------------------- -# Step 1 -- utilities + +# Step 1a -- temporary directory + +tempdir=`mktemp -d --tmpdir djXXXXXX 2>/dev/null` || tempdir='' +while [ ! -d "$tempdir" -o ! -r "$tempdir" ] ; do + tempdir="/tmp/dj"`awk 'BEGIN{srand();printf("%d",rand()*100000)}'` + mkdir "$tempdir" || tempdir='' +done +trap 'rm -rf 2>/dev/null "$tempdir"' EXIT INT HUP QUIT + + +# Step 1b -- utilities usage() { @@ -85,10 +96,30 @@ IFS=':' read tmpdir tmpvar <&1 -dNODISPLAY -f psdvifix.ps -c quit | \ + grep -q /undefinedfilename ) + then + psdvifix=no + elif ( "$gsdjvu" 2>&1 -dNODISPLAY -f psdvifix.ps -c quit | \ + grep -q WRITESYSTEMDICT ) + then + psdvifix=no + fi + fi + test "$psdvifix" != no +} + +djvutext= checkps2utf8() { if [ -z "$djvutext" ] @@ -97,8 +128,7 @@ if ( "$gsdjvu" 2>&1 -dNODISPLAY -c '(ps2utf8.ps) runlibfile quit' | \ grep -q WRITESYSTEMDICT ) then - djvutext="/tmp/dj$$.ps" - trap "rm 2>/dev/null $djvutext" 0 + djvutext="$tempdir/djvutext.ps" cat > $djvutext <<\EOF (ps2utf8.ps) runlibfile currentglobal /setglobal load true setglobal .ps2utf8 begin /onpage { } bind def /onfont { pop pop pop } bind def @@ -107,20 +137,26 @@ EOF fi fi - test "$djvutext" != no && test -r "$djvutext" + test "$djvutext" != no } -# Step 1 -- locate gsdjvu executable + + +# Step 2a -- locate gsdjvu executable gsdjvu= -for gs in ${GSDJVU} `pathexpand gs` `pathexpand gsdjvu` +while read gs do if [ -z "$gsdjvu" ] && ( "$gs" -h 2>&1 | grep -q djvusep ) then gsdjvu="$gs" fi -done +done <&1 | grep -q quality ) then csepdjvu="$cs" fi -done +done <&1 | grep -q -i djvulibre ) + then + djvused="$ds" + fi +done <&1 | grep -q foo.pdf ) + ( "$pt" -v 2>&1 | grep -q Poppler ) + then + pdftotext="$pt" + fi +done <&2 "Using: $gsdjvu" echo 1>&2 " and: $csepdjvu" + test -n "$djvused" && echo 1>&2 " and: $djvused" + test -n "$pdftotext" && echo 1>&2 " and: $pdftotext" exit 0 ;; --dpi=[0-9]*) @@ -202,9 +275,10 @@ --verbose|--v) gsverbosity='' csepverbosity='-vv' + dsedverbosity='-v' ;; --dryrun) - run=echo + run="echo +" ;; --sepfile) sepfile=yes @@ -238,22 +312,36 @@ gsepsf="-dEPSCrop" ;; --words) - if checkps2utf8; then + gsarg0="$gsarg0 -dProvideUnicode -dExtractText" + if checkpsdvifix; then + gsarg1="-f $psdvifix" + elif checkps2utf8; then + # Modern gs do not like DELAYBIND gsarg0="$gsarg0 -dDELAYBIND -dWRITESYSTEMDICT" gsarg1="-f $djvutext" - else - gsarg0="$gsarg0 -dProvideUnicode -dExtractText" fi ;; --lines) - if checkps2utf8; then + gsarg0="$gsarg0 -dProvideUnicode -dExtractText" + if checkpsdvifix; then + gsarg1="-f $psdvifix" + elif checkps2utf8; then + # Modern gs do not like DELAYBIND gsarg0="$gsarg0 -dDELAYBIND -dWRITESYSTEMDICT" gsarg1="-f $djvutext" - else - gsarg0="$gsarg0 -dProvideUnicode -dExtractText" fi csepargs="$csepargs -t" ;; + --poppler=*) + for arg in `getargs $n` ; do + case "$arg" in + text) popplertext=1 ;; + meta) popplermeta=1 ;; + *) echo 1>&2 "djvudigital: unrecognized option --poppler=$arg" + usage ;; + esac + done + ;; --pdf=screen) gsprinted="-dPrinted=false" ;; @@ -285,6 +373,7 @@ csepargs="$csepargs `getargs $n`" ;; -*) + echo 1>&2 "djvudigital: unrecognized option $n" usage ;; *) @@ -339,7 +428,7 @@ then backend="$outfile" else - backend="|$csepdjvu -d "'"'"$dpi"'"' + backend="| "'"'"$csepdjvu"'"'" -d $dpi" backend="$backend $csepverbosity $csepargs - "'"'"$outfile"'"' fi @@ -348,26 +437,268 @@ *.gz|*.GZ) if test -z "$run" ; then gzip -d -c "$infile" | \ - $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf \ + "$gsdjvu" "-r$dpi" $gsverbosity $gsprinted $gsepsf \ "-sOutputFile=$backend" $gsarg0 $gsarg1 $gsarg2 -_ -c quit else - echo -n gzip -d -c '"'"$infile"'"' '|' "" - echo -n $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf "" - echo -n "-sOutputFile=""'""$backend""'" "" - echo -n $gsarg0 $gsarg1 $gsarg2 -_ -c quit - echo + $run gzip -d -c '"'"$infile"'"' '|' "" \ + "$gsdjvu" "-r$dpi" $gsverbosity $gsprinted $gsepsf "" \ + "-sOutputFile=""'""$backend""'" "" \ + $gsarg0 $gsarg1 $gsarg2 -_ -c quit fi ;; *) if test -z "$run" ; then - $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf \ + "$gsdjvu" "-r$dpi" $gsverbosity $gsprinted $gsepsf \ "-sOutputFile=$backend" $gsarg0 $gsarg1 $gsarg2 \ -f "$infile" -c quit else - echo -n $gsdjvu "-r$dpi" $gsverbosity $gsprinted $gsepsf "" - echo -n "-sOutputFile=""'""$backend""'" "" - echo -n $gsarg0 $gsarg1 $gsarg2 -f '"'"$infile"'"' -c quit - echo + $run "$gsdjvu" "-r$dpi" $gsverbosity $gsprinted $gsepsf "" \ + "-sOutputFile=""'""$backend""'" "" \ + $gsarg0 $gsarg1 $gsarg2 -f '"'"$infile"'"' -c quit fi ;; esac + + +# Step 6 -- Postprocess djvu file with metadata/text found by poppler + +if ( file "$infile" | grep -q -i pdf ) \ + && test "$popplertext$popplermeta" != "00" +then + + # check for djvused + if [ -z "$djvused" ] + then + cat 1>&2 <<\EOF +djvudigital: cannot locate djvused executable. ++--------------------------------------------------------------------+ +| DjVuDigital was not able to locate the djvulibre tool "djvused". | +| This tool is needed to use the --poppler=(text,data) options. | +| Please make sure that the djvulibre tools are properly installed. | ++--------------------------------------------------------------------+ +EOF + exit 10 + fi + + # check for pdftotext + if [ -z "$pdftotext" ] + then + cat 1>&2 <<\EOF +djvudigital: cannot locate pdftotext executable. ++--------------------------------------------------------------------+ +| DjVuDigital was not able to locate the poppler tool "pdftotext". | +| This tool is needed to use the --poppler=(text,data) options. | +| Please make sure that the poppler tools are properly installed. | ++--------------------------------------------------------------------+ +EOF + exit 10 + fi + + # xml parser for awk :-) + xml2dsed="$tempdir/xml2dsed.awk" + cat > "$xml2dsed" <<\EOF + +# initializations + +function _esc_init() { + _ctrl = "" + for (i=1; i<32; i++) { _ctrl = _ctrl sprintf("%c",i) } + _esc = "[\"\\\\&" _ctrl "]" + _ctrl = "[" _ctrl "]" +} + +function _ord_init() { + for (i=0; i<256; i++) { + _ord[sprintf("%c",i)]=i + } +} + +function _amp_init() { + _amp["&"] = "&" + _amp["<"] = "<" + _amp[">"] = ">" + _amp["'"] = "'" + _amp["""] = "\\\"" +} + +BEGIN { + _esc_init() + _ord_init() + _amp_init() + delete meta + pheight=0 + pwidth=0 + location="" + context="" + content="" + pageno=0 + dpi = 300 # use awk -f xml2dsed.awk dpi=xxx to override + dometa=1 # use awk -f xml2dsed.awk dometa=0 to override + dotext=1 # use awk -f xml2dsed.awk dotext=0 to override + RS=">" # xml parsing wants record delimiter set to ">" +} + +# return character code + +function ord(str) { + return _ord[substr(str,1,1)] +} + +# print properly escaped c string + +function pstr(str,tmp) { + printf("\"") + while (str) { + tmp = match(str,_esc) # char classes do not always work + if (tmp == 0) { + printf("%s",str) + str = "" + } else if (tmp > 1) { + printf("%s",substr(str,1,tmp-1)) + str = substr(str,tmp) + } else { + tmp = match(str,"^&[a-z]*;") + if (tmp != 1) { tmp = "" } + if (tmp) { tmp = _amp[substr(str,RSTART,RLENGTH)] } + if (tmp) { + printf("%s",tmp) + str = substr(str,RLENGTH+1) + } else { + printf("\\%03o", ord(str)) + str = substr(str,2) + } + } + } + printf("\"") +} + +# sax-like callbacks + +function charData(str) { + if (context == "title") { + meta["Title"] = str + } else if (context == "word") { + gsub(_ctrl," ",str) # kill control characters + gsub("\302\240"," ",str) # nbsp in utf-8 + gsub(/ */," ",str) # simplify spaces + gsub(/^ /,"",str) # simplify spaces + gsub(/ $/,"",str) # simplify spaces + if (match(str,/[^ ]/)) { content = str } else { content = "" } + } +} + +function startElement(tag,attrs) { + if (tag=="head" && ! context && dometa) { + context = "head" + } else if (tag=="title" && context=="head") { + context = "title" + } else if (tag=="meta" && attrs["name"] && attrs["content"] ) { + meta[attrs["name"]] = attrs["content"] + } else if (tag=="body" && ! context && dotext) { + context = "body" + } else if (tag=="page" && context == "body") { + pageno = pageno + 1 + pwidth = attrs["width"] * dpi / 72 + pheight = attrs["height"] * dpi / 72 + context = "page" + printf("select %d\n", pageno) + printf("set-txt\n") + printf("(page %d %d %d %d\n", 0, 0, pwidth, pheight) + } else if (tag=="word" && context == "page") { + if (attrs["xMin"] && attrs["xMax"] && attrs["yMin"] && attrs["yMax"]) { + context = "word" + location = sprintf("%d %d %d %d", + attrs["xMin"] * dpi / 72, + pheight - attrs["yMin"] * dpi / 72, + attrs["xMax"] * dpi / 72, + pheight - attrs["yMax"] * dpi / 72 ) + } + } +} + +function endElement(tag) { + if (tag == "title" && context == "title") { + context = "head" + } else if (tag == "head" && context == "head" && length(meta)>0) { + context = "" + printf("create-shared-ant\n") + printf("set-meta\n") + for (i in meta) { + printf("%s\t",i) + pstr(meta[i]) + printf("\n") + } + printf(".\n") + } else if (tag == "page" && context == "page") { + context = "body" + printf(")\n.\n") + } else if (tag == "word" && context == "word" && content) { + context = "page" + printf(" (word %s ", location) + pstr(content) + printf(")\n") + content = "" + } +} + +# xml parser (for pdftotext!) +{ + str = $0 + match(str,/^[ \n\r\t\f]*/) + if (RSTART == 1 && RLENGTH > 0) { + str = substr(str,RLENGTH+1) + } + if (! match(str,/ 1) { + arg = substr(str,1,RSTART-1) + str = substr(str,RSTART) + charData(arg) + } + match(str, "^ "$dsedscript" + else + $run "$pdftotext" -bbox "$infile" "-" \ + \| awk -f $xml2dsed dpi=$dpi dometa=$popplermeta dotext=$popplertext \ + \> "$dsedscript" + fi + + # execute dsed script + $run "$djvused" $dsedverbosity -f "$dsedscript" -s "$outfile" +fi diff -Nru djvulibre-3.5.27.1/tools/djvudigital.1 djvulibre-3.5.28/tools/djvudigital.1 --- djvulibre-3.5.27.1/tools/djvudigital.1 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/djvudigital.1 2020-11-20 16:57:32.000000000 +0000 @@ -158,6 +158,38 @@ program .BR csepdjvu " or " msepdjvu "." .TP +.BI "--poppler=" "keywords" +This option causes +.B djvudigital +to extract additional information from PDF files using the tool +.B pdftotext +that comes bundled with the Poppler library. +Selected information is then added to the djvu file +as a postprocessing step. This option is ignored +when the input file is not a PDF file. +Argument +.I keywords +is a comma separated list of keywords. +When this list contains keyword +.BR meta , +the metadata extracted by +.B pdftotext +is inserted into the djvu file. +When this list contains keyword +.BR text , +the textual information extracted by +.B pdftotext +is inserted into the djvu file, +possibly replacing the information +gathered using the options +.BR --words +or +.BR --lines . +This is useful for instance when a scanned +PDF file contains a hidden text layer that +is not recognized by Ghostscript and therefore +not passed to the djvudigital backend. +.TP .BI "--sepfile" Produces a separated data file instead of a DjVu file. Program .BR csepdjvu @@ -227,6 +259,32 @@ and continues with command line executables named .BR msepdjvu " and " csepdjvu "." +.SH OTHER PROGRAMS + +The option +.BI "--poppler=" "keywords" +relies on the tool +.B pdftotext +that comes with the Poppler library +and the tool +.B djvused +that comes with djvulibre. +Only recent versions of +.B pdftotext +that accept the option +.B -bbox +are supported. +Both tools are searched by first trying +the files specified by the environment variables +.B PDFTOTEXT +and +.BR DJVUSED , +and then trying executables named +.B pdftotext +or +.B djvused +found along the shell executable path. + .SH CREDITS The first version of this converter was written diff -Nru djvulibre-3.5.27.1/tools/djvuextract.cpp djvulibre-3.5.28/tools/djvuextract.cpp --- djvulibre-3.5.27.1/tools/djvuextract.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/djvuextract.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -208,6 +208,7 @@ GArray dargv(0,argc-1); for(int i=0;i not found!\n", (const char *)dargv[i]); + retcode = 64; } else { @@ -271,5 +273,5 @@ exit(1); } G_ENDCATCH; - return 0; + return retcode; } diff -Nru djvulibre-3.5.27.1/tools/djvumake.cpp djvulibre-3.5.28/tools/djvumake.cpp --- djvulibre-3.5.27.1/tools/djvumake.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/djvumake.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -356,6 +356,8 @@ void analyze_incl_chunk(const GURL &url) { + if (! url.is_file()) + return; GP gbs = ByteStream::create(url,"rb"); char buffer[24]; memset(buffer, 0, sizeof(buffer)); @@ -522,6 +524,8 @@ void create_incl_chunk(IFFByteStream &iff, const char *chkid, const char *fileid) { + if (strchr(fileid, '/') || strchr(fileid, '\\') || strchr(fileid, ':')) + G_THROW( ERR_MSG("DjVuFile.malformed") ); iff.put_chunk("INCL"); iff.write(fileid, strlen(fileid)); iff.close_chunk(); @@ -955,7 +959,7 @@ } else if (!dargv[i].cmp("INCL=",5)) { - create_incl_chunk(iff, "INCL", GURL::Filename::UTF8(5+(const char *)dargv[i]).fname()); + create_incl_chunk(iff, "INCL", (const char *)GUTF8String(dargv[i].substr(5,-1))); flag_contains_incl = 1; } else if (!dargv[i].cmp("PPM=",4)) diff -Nru djvulibre-3.5.27.1/tools/djvused.1 djvulibre-3.5.28/tools/djvused.1 --- djvulibre-3.5.27.1/tools/djvused.1 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/djvused.1 2020-11-20 16:57:32.000000000 +0000 @@ -856,6 +856,10 @@ hyperlink areas. The complete area will be highlighted using the specified color at the specified opacity (0-100, default 50). +Some viewers (e.g., +.BR djview4 ) +support opacities in range 0-200 with 200 +representing a fully opaque color. .IP "" 3 .BI "(hilite " color ")" .br diff -Nru djvulibre-3.5.27.1/tools/djvused.cpp djvulibre-3.5.28/tools/djvused.cpp --- djvulibre-3.5.27.1/tools/djvused.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/djvused.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -66,6 +66,7 @@ #include "GString.h" #include "DjVuDocEditor.h" #include "DjVuDumpHelper.h" +#include "DjVuMessageLite.h" #include "BSByteStream.h" #include "DjVuText.h" #include "DjVuAnno.h" @@ -2021,11 +2022,11 @@ { GUTF8String sizestr = pbs.get_token(); if (! sizestr) - sizestr = "128"; + sizestr = "192"; if (! sizestr.is_int() ) verror("expecting integer argument"); int size = atoi(sizestr); - if (size<32 || size >256) + if (size < 32 || size > 512) verror("size should be between 32 and 256 (e.g. 128)"); g().doc->generate_thumbnails(size, callback_thumbnails, NULL); modified = true; @@ -2160,7 +2161,7 @@ " . set-meta [] -- copies into the metadata annotation tag\n" " . set-txt [] -- copies into the hidden text chunk\n" " . set-xmp [] -- copies into the xmp metadata annotation tag\n" - " _ set-outline [] -- sets outline (bootmarks)\n" + " _ set-outline [] -- sets outline (bookmarks)\n" " _ set-thumbnails [] -- generates all thumbnails with given size\n" " set-rotation [+-] -- sets page rotation\n" " set-dpi -- sets page resolution\n" @@ -2315,7 +2316,8 @@ G_CATCH(ex) { vprint("Error (%s): %s", - (const char*)ToNative(token), ex.get_cause()); + (const char*)ToNative(token), + (const char *)DjVuMessageLite::LookUpUTF8(ex.get_cause())); if (! verbose) G_RETHROW; } diff -Nru djvulibre-3.5.27.1/tools/jb2cmp/classify.cpp djvulibre-3.5.28/tools/jb2cmp/classify.cpp --- djvulibre-3.5.27.1/tools/jb2cmp/classify.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/jb2cmp/classify.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -15,8 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program. If not, see . * * * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net) diff -Nru djvulibre-3.5.27.1/tools/jb2cmp/classify.h djvulibre-3.5.28/tools/jb2cmp/classify.h --- djvulibre-3.5.27.1/tools/jb2cmp/classify.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/jb2cmp/classify.h 2020-11-20 16:57:32.000000000 +0000 @@ -15,8 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program. If not, see . * * * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net) diff -Nru djvulibre-3.5.27.1/tools/jb2cmp/cuts.cpp djvulibre-3.5.28/tools/jb2cmp/cuts.cpp --- djvulibre-3.5.27.1/tools/jb2cmp/cuts.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/jb2cmp/cuts.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -15,8 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program. If not, see . * * * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net) diff -Nru djvulibre-3.5.27.1/tools/jb2cmp/frames.cpp djvulibre-3.5.28/tools/jb2cmp/frames.cpp --- djvulibre-3.5.27.1/tools/jb2cmp/frames.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/jb2cmp/frames.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -15,8 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program. If not, see . * * * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net) diff -Nru djvulibre-3.5.27.1/tools/jb2cmp/minidjvu.h djvulibre-3.5.28/tools/jb2cmp/minidjvu.h --- djvulibre-3.5.27.1/tools/jb2cmp/minidjvu.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/jb2cmp/minidjvu.h 2020-11-20 16:57:32.000000000 +0000 @@ -15,8 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program. If not, see . * * * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net) diff -Nru djvulibre-3.5.27.1/tools/jb2cmp/patterns.cpp djvulibre-3.5.28/tools/jb2cmp/patterns.cpp --- djvulibre-3.5.27.1/tools/jb2cmp/patterns.cpp 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/jb2cmp/patterns.cpp 2020-11-20 16:57:32.000000000 +0000 @@ -15,8 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program. If not, see . * * * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net) diff -Nru djvulibre-3.5.27.1/tools/jb2cmp/patterns.h djvulibre-3.5.28/tools/jb2cmp/patterns.h --- djvulibre-3.5.27.1/tools/jb2cmp/patterns.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/jb2cmp/patterns.h 2020-11-20 16:57:32.000000000 +0000 @@ -15,8 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program. If not, see . * * * minidjvu is derived from DjVuLibre (http://djvu.sourceforge.net) diff -Nru djvulibre-3.5.27.1/tools/tiff2pdf.c djvulibre-3.5.28/tools/tiff2pdf.c --- djvulibre-3.5.27.1/tools/tiff2pdf.c 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/tiff2pdf.c 2020-11-20 16:57:32.000000000 +0000 @@ -1,4 +1,4 @@ -/* -*- C -*- +/* -*- mode: C; tab-width: 4; c-basic-offset: 4 -*- //C- ------------------------------------------------------------------- //C- DjView4 //C- Copyright (c) 2006 Leon Bottou @@ -20,8 +20,8 @@ // Changes were made to make it independent from the private // include file tiffiop.h. */ - -/* $Id: tiff2pdf.c,v 1.37.2.7 2009-01-01 00:10:43 bfriesen Exp $ + +/* $Id: tiff2pdf.c,v 1.103 2017-10-29 18:50:41 bfriesen Exp $ * * tiff2pdf - converts a TIFF image to a PDF document * @@ -56,6 +56,8 @@ #include #include #include +#include +#include #if HAVE_UNISTD_H # include @@ -65,10 +67,6 @@ # include #endif -#ifdef HAVE_GETOPT_H -# include -#endif - #if defined(__GNUC__) || defined(HAVE_LONG_LONG_INT) # define uint64 unsigned long long #elif defined(_MSC_VER) @@ -76,6 +74,41 @@ #else # define uint64 size_t #endif +#ifndef TIFFSafeMultiply +# define TIFFSafeMultiply(t,v,m) \ + ((((t)(m)!=(t)0)&&(((t)(((v)*(m))/(m)))==(t)(v)))?(t)((v)*(m)):(t)0) +#endif +#ifndef TIFF_SIZE_FORMAT +# define TIFF_SIZE_T unsigned long +# define TIFF_SIZE_FORMAT "%lu" +#endif +#ifndef TIFFmin +# define TIFFmin(A,B) ((A)<(B)?(A):(B)) +#endif +#ifndef TIFFclip +# define TIFFclip(A,B) ((A)<(0)?(0):((A)>(B)?(B):(A))) +#endif + +#ifdef HAVE_GETOPT_H +# include +#endif + +#if defined(_WIN32) && defined(_MSC_VER) +# ifndef HAVE_SNPRINTF +# define snprintf mysnprintf +static int +snprintf(char* str, size_t size, const char* format, ...) +{ + int count; + va_list ap; + va_start(ap, format); + count = vsnprintf(str, size, format, ap); + va_end(ap); + return count; +} +# endif +#endif + #ifndef HAVE_GETOPT_H /* @@ -195,6 +228,12 @@ } #endif +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +#endif +#ifndef EXIT_FAILURE +# define EXIT_FAILURE 1 +#endif #define TIFF2PDF_MODULE "tiff2pdf" @@ -320,6 +359,7 @@ float pdf_pagelength; float pdf_imagewidth; float pdf_imagelength; + int pdf_image_fillpage; /* 0 (default: no scaling, 1:scale imagesize to pagesize */ T2P_BOX pdf_mediabox; T2P_BOX pdf_imagebox; uint16 pdf_majorversion; @@ -330,13 +370,20 @@ uint32 pdf_palettecs; uint16 pdf_fitwindow; uint32 pdf_startxref; - unsigned char* pdf_fileid; - unsigned char* pdf_datetime; - unsigned char* pdf_creator; - unsigned char* pdf_author; - unsigned char* pdf_title; - unsigned char* pdf_subject; - unsigned char* pdf_keywords; +#define TIFF2PDF_FILEID_SIZE 33 + char pdf_fileid[TIFF2PDF_FILEID_SIZE]; +#define TIFF2PDF_DATETIME_SIZE 17 + char pdf_datetime[TIFF2PDF_DATETIME_SIZE]; +#define TIFF2PDF_CREATOR_SIZE 512 + char pdf_creator[TIFF2PDF_CREATOR_SIZE]; +#define TIFF2PDF_AUTHOR_SIZE 512 + char pdf_author[TIFF2PDF_AUTHOR_SIZE]; +#define TIFF2PDF_TITLE_SIZE 512 + char pdf_title[TIFF2PDF_TITLE_SIZE]; +#define TIFF2PDF_SUBJECT_SIZE 512 + char pdf_subject[TIFF2PDF_SUBJECT_SIZE]; +#define TIFF2PDF_KEYWORDS_SIZE 512 + char pdf_keywords[TIFF2PDF_KEYWORDS_SIZE]; t2p_cs_t pdf_colorspace; uint16 pdf_colorspace_invert; uint16 pdf_switchdecode; @@ -377,7 +424,8 @@ /* These functions are called by main. */ -static int tiff2pdf_match_paper_size(float*, float*, char*); +static +int tiff2pdf_match_paper_size(float*, float*, char*); /* These functions are used to generate a PDF from a TIFF. */ @@ -385,76 +433,143 @@ extern "C" { #endif -static T2P* t2p_init(void); -static void t2p_validate(T2P*); -static tsize_t t2p_write_pdf(T2P*, TIFF*, TIFF*); -static void t2p_free(T2P*); +static +T2P* t2p_init(void); +static +void t2p_validate(T2P*); +static +tsize_t t2p_write_pdf(T2P*, TIFF*, TIFF*); +static +void t2p_free(T2P*); #ifdef __cplusplus } #endif -static void t2p_read_tiff_init(T2P*, TIFF*); -static int t2p_cmp_t2p_page(const void*, const void*); -static void t2p_read_tiff_data(T2P*, TIFF*); -static void t2p_read_tiff_size(T2P*, TIFF*); -static void t2p_read_tiff_size_tile(T2P*, TIFF*, ttile_t); -static int t2p_tile_is_right_edge(T2P_TILES, ttile_t); -static int t2p_tile_is_bottom_edge(T2P_TILES, ttile_t); -/* static int t2p_tile_is_edge(T2P_TILES, ttile_t); */ -/* static int t2p_tile_is_corner_edge(T2P_TILES, ttile_t); */ -static tsize_t t2p_readwrite_pdf_image(T2P*, TIFF*, TIFF*); -static tsize_t t2p_readwrite_pdf_image_tile(T2P*, TIFF*, TIFF*, ttile_t); +static +void t2p_read_tiff_init(T2P*, TIFF*); +static +int t2p_cmp_t2p_page(const void*, const void*); +static +void t2p_read_tiff_data(T2P*, TIFF*); +static +void t2p_read_tiff_size(T2P*, TIFF*); +static +void t2p_read_tiff_size_tile(T2P*, TIFF*, ttile_t); +static +int t2p_tile_is_right_edge(T2P_TILES, ttile_t); +static +int t2p_tile_is_bottom_edge(T2P_TILES, ttile_t); +/* static +int t2p_tile_is_edge(T2P_TILES, ttile_t); */ +/* static +int t2p_tile_is_corner_edge(T2P_TILES, ttile_t); */ +static +tsize_t t2p_readwrite_pdf_image(T2P*, TIFF*, TIFF*); +static +tsize_t t2p_readwrite_pdf_image_tile(T2P*, TIFF*, TIFF*, ttile_t); #ifdef OJPEG_SUPPORT -static int t2p_process_ojpeg_tables(T2P*, TIFF*); +static +int t2p_process_ojpeg_tables(T2P*, TIFF*); #endif #ifdef JPEG_SUPPORT -static int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t*, tstrip_t, uint32); +static +int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t, tsize_t*, tstrip_t, uint32); #endif -static void t2p_tile_collapse_left(tdata_t, tsize_t, uint32, uint32, uint32); -static void t2p_write_advance_directory(T2P*, TIFF*); -static tsize_t t2p_sample_planar_separate_to_contig(T2P*, unsigned char*, unsigned char*, tsize_t); -static tsize_t t2p_sample_realize_palette(T2P*, unsigned char*); -static tsize_t t2p_sample_abgr_to_rgb(tdata_t, uint32); -static tsize_t t2p_sample_rgba_to_rgb(tdata_t, uint32); -static tsize_t t2p_sample_rgbaa_to_rgb(tdata_t, uint32); -static tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t, uint32); -static tsize_t t2p_write_pdf_header(T2P*, TIFF*); -static tsize_t t2p_write_pdf_obj_start(uint32, TIFF*); -static tsize_t t2p_write_pdf_obj_end(TIFF*); -/* static tsize_t t2p_write_pdf_name(unsigned char*, TIFF*); */ -static tsize_t t2p_write_pdf_string(unsigned char*, TIFF*); -static tsize_t t2p_write_pdf_stream(tdata_t, tsize_t, TIFF*); -static tsize_t t2p_write_pdf_stream_start(TIFF*); -static tsize_t t2p_write_pdf_stream_end(TIFF*); -static tsize_t t2p_write_pdf_stream_dict(tsize_t, uint32, TIFF*); -static tsize_t t2p_write_pdf_stream_dict_start(TIFF*); -static tsize_t t2p_write_pdf_stream_dict_end(TIFF*); -static tsize_t t2p_write_pdf_stream_length(tsize_t, TIFF*); -static tsize_t t2p_write_pdf_catalog(T2P*, TIFF*); -static tsize_t t2p_write_pdf_info(T2P*, TIFF*, TIFF*); -static void t2p_pdf_currenttime(T2P*); -static void t2p_pdf_tifftime(T2P*, TIFF*); -static tsize_t t2p_write_pdf_pages(T2P*, TIFF*); -static tsize_t t2p_write_pdf_page(uint32, T2P*, TIFF*); -static void t2p_compose_pdf_page(T2P*); -static void t2p_compose_pdf_page_orient(T2P_BOX*, uint16); -static void t2p_compose_pdf_page_orient_flip(T2P_BOX*, uint16); -/* static tsize_t t2p_write_pdf_page_content(T2P*, TIFF*); */ -static tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t, T2P*, TIFF*); -static tsize_t t2p_write_pdf_xobject_cs(T2P*, TIFF*); -static tsize_t t2p_write_pdf_transfer(T2P*, TIFF*); -static tsize_t t2p_write_pdf_transfer_dict(T2P*, TIFF*, uint16); -static tsize_t t2p_write_pdf_transfer_stream(T2P*, TIFF*, uint16); -static tsize_t t2p_write_pdf_xobject_calcs(T2P*, TIFF*); -static tsize_t t2p_write_pdf_xobject_icccs(T2P*, TIFF*); -static tsize_t t2p_write_pdf_xobject_icccs_dict(T2P*, TIFF*); -static tsize_t t2p_write_pdf_xobject_icccs_stream(T2P*, TIFF*); +static +void t2p_tile_collapse_left(tdata_t, tsize_t, uint32, uint32, uint32); +static +void t2p_write_advance_directory(T2P*, TIFF*); +static +tsize_t t2p_sample_planar_separate_to_contig(T2P*, unsigned char*, unsigned char*, tsize_t); +static +tsize_t t2p_sample_realize_palette(T2P*, unsigned char*); +static +tsize_t t2p_sample_abgr_to_rgb(tdata_t, uint32); +static +tsize_t t2p_sample_rgba_to_rgb(tdata_t, uint32); +static +tsize_t t2p_sample_rgbaa_to_rgb(tdata_t, uint32); +static +tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t, uint32); +static +tsize_t t2p_write_pdf_header(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_obj_start(uint32, TIFF*); +static +tsize_t t2p_write_pdf_obj_end(TIFF*); +/* static +tsize_t t2p_write_pdf_name(unsigned char*, TIFF*); */ +static +tsize_t t2p_write_pdf_string(char*, TIFF*); +static +tsize_t t2p_write_pdf_stream(tdata_t, tsize_t, TIFF*); +static +tsize_t t2p_write_pdf_stream_start(TIFF*); +static +tsize_t t2p_write_pdf_stream_end(TIFF*); +static +tsize_t t2p_write_pdf_stream_dict(tsize_t, uint32, TIFF*); +static +tsize_t t2p_write_pdf_stream_dict_start(TIFF*); +static +tsize_t t2p_write_pdf_stream_dict_end(TIFF*); +static +tsize_t t2p_write_pdf_stream_length(tsize_t, TIFF*); +static +tsize_t t2p_write_pdf_catalog(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_info(T2P*, TIFF*, TIFF*); +static +void t2p_pdf_currenttime(T2P*); +static +void t2p_pdf_tifftime(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_pages(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_page(uint32, T2P*, TIFF*); +static +void t2p_compose_pdf_page(T2P*); +static +void t2p_compose_pdf_page_orient(T2P_BOX*, uint16); +static +void t2p_compose_pdf_page_orient_flip(T2P_BOX*, uint16); +/* static +tsize_t t2p_write_pdf_page_content(T2P*, TIFF*); */ +static +tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t, T2P*, TIFF*); +static +tsize_t t2p_write_pdf_xobject_cs(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_transfer(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_transfer_dict(T2P*, TIFF*, uint16); +static +tsize_t t2p_write_pdf_transfer_stream(T2P*, TIFF*, uint16); +static +tsize_t t2p_write_pdf_xobject_calcs(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_xobject_icccs(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_xobject_icccs_dict(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_xobject_icccs_stream(T2P*, TIFF*); /* static tsize_t t2p_write_pdf_xobject_cs_stream(T2P*, TIFF*); */ -static tsize_t t2p_write_pdf_xobject_decode(T2P*, TIFF*); -static tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t, T2P*, TIFF*); -static tsize_t t2p_write_pdf_xreftable(T2P*, TIFF*); -static tsize_t t2p_write_pdf_trailer(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_xobject_decode(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t, T2P*, TIFF*); +static +tsize_t t2p_write_pdf_xreftable(T2P*, TIFF*); +static +tsize_t t2p_write_pdf_trailer(T2P*, TIFF*); + +#define check_snprintf_ret(t2p, rv, buf) do { \ + if ((rv) < 0) rv = 0; \ + else if((rv) >= (int)sizeof(buf)) (rv) = sizeof(buf) - 1; \ + else break; \ + if ((t2p) != NULL) (t2p)->t2p_error = T2P_ERR_ERROR; \ +} while(0) static void t2p_disable(TIFF *tif) @@ -474,45 +589,47 @@ * Procs for TIFFClientOpen */ -static tsize_t -t2pReadFile(TIFF *tif, tdata_t data, tsize_t size) +#ifdef OJPEG_SUPPORT +static tmsize_t +t2pReadFile(TIFF *tif, tdata_t data, tmsize_t size) { thandle_t client = TIFFClientdata(tif); - TIFFReadWriteProc proc = TIFFGetReadProc(tif); + TIFFReadWriteProc proc = TIFFGetReadProc(tif); if (proc) return proc(client, data, size); return -1; } +#endif /* OJPEG_SUPPORT */ -static tsize_t -t2pWriteFile(TIFF *tif, tdata_t data, tsize_t size) +static tmsize_t +t2pWriteFile(TIFF *tif, tdata_t data, tmsize_t size) { thandle_t client = TIFFClientdata(tif); - TIFFReadWriteProc proc = TIFFGetWriteProc(tif); + TIFFReadWriteProc proc = TIFFGetWriteProc(tif); if (proc) return proc(client, data, size); return -1; } -static toff_t +static uint64 t2pSeekFile(TIFF *tif, toff_t offset, int whence) { thandle_t client = TIFFClientdata(tif); - TIFFSeekProc proc = TIFFGetSeekProc(tif); + TIFFSeekProc proc = TIFFGetSeekProc(tif); if (proc) return proc(client, offset, whence); return -1; } -static tsize_t -t2p_readproc(thandle_t handle, tdata_t data, tsize_t size) +static tmsize_t +t2p_readproc(thandle_t handle, tdata_t data, tmsize_t size) { (void) handle, (void) data, (void) size; return -1; } -static tsize_t -t2p_writeproc(thandle_t handle, tdata_t data, tsize_t size) +static tmsize_t +t2p_writeproc(thandle_t handle, tdata_t data, tmsize_t size) { T2P *t2p = (T2P*) handle; if (t2p->outputdisable <= 0 && t2p->outputfile) { @@ -527,8 +644,13 @@ t2p_seekproc(thandle_t handle, toff_t offset, int whence) { T2P *t2p = (T2P*) handle; - if (t2p->outputdisable <= 0 && t2p->outputfile) - return fseek(t2p->outputfile, offset, whence); + if (t2p->outputdisable <= 0 && t2p->outputfile) { +#if HAVE_FSEEKO + return fseeko(t2p->outputfile, (off_t) offset, whence); +#else + return fseek(t2p->outputfile, (long) offset, whence); +#endif + } return offset; } @@ -536,7 +658,7 @@ t2p_closeproc(thandle_t handle) { (void) handle; - return 0; + return 0; } static toff_t @@ -547,24 +669,25 @@ } static int -t2p_mapproc(thandle_t handle, tdata_t *data, toff_t *offset) +t2p_mapproc(thandle_t handle, void **data, toff_t *offset) { (void) handle, (void) data, (void) offset; return -1; } static void -t2p_unmapproc(thandle_t handle, tdata_t data, toff_t offset) +t2p_unmapproc(thandle_t handle, void *data, toff_t offset) { (void) handle, (void) data, (void) offset; } +#if defined(OJPEG_SUPPORT) || defined(JPEG_SUPPORT) static uint64 checkAdd64(uint64 summand1, uint64 summand2, T2P* t2p) { uint64 bytes = summand1 + summand2; - if (bytes - summand1 != summand2) { + if (bytes < summand1) { TIFFError(TIFF2PDF_MODULE, "Integer overflow"); t2p->t2p_error = T2P_ERR_ERROR; bytes = 0; @@ -572,6 +695,7 @@ return bytes; } +#endif /* defined(OJPEG_SUPPORT) || defined(JPEG_SUPPORT) */ static uint64 checkMultiply64(uint64 first, uint64 second, T2P* t2p) @@ -672,6 +796,7 @@ -l: length in units -r: 'd' for resolution default, 'o' for resolution override -p: paper size, eg "letter", "legal", "a4" + -F: make the tiff fill the PDF page -f: set pdf "fit window" user preference -b: set PDF "Interpolate" user preference -e: date, overrides image or current date/time default, YYYYMMDDHHMMSS @@ -691,17 +816,17 @@ tiff2pdf input.tiff - The above example would generate PDF output from input.tiff and write it + The above example would generate PDF output from input.tiff and write it to standard output. tiff2pdf -j -p letter -o output.pdf input.tiff - The above example would generate the file output.pdf from input.tiff, - putting the image pages on a letter sized page, compressing the output + The above example would generate the file output.pdf from input.tiff, + putting the image pages on a letter sized page, compressing the output with JPEG. Please report bugs through: - + http://bugzilla.remotesensing.org/buglist.cgi?product=libtiff See also libtiff.3t, tiffcp. @@ -710,13 +835,10 @@ int tiff2pdf(TIFF *input, FILE *outputfile, int argc, const char **argv) { - char *outfilename = ""; - T2P *t2p = NULL; - TIFF *output = NULL; - tsize_t written = 0; - int c; - - (void)written; + char *outfilename = ""; + T2P *t2p = NULL; + TIFF *output = NULL; + int c, ret = EXIT_SUCCESS;; t2p = t2p_init(); @@ -727,7 +849,7 @@ while (argv && (c = getopt(argc, (void*)argv, - "o:q:u:x:y:w:l:r:p:e:c:a:t:s:k:jzndifbh")) != -1){ + "o:q:u:x:y:w:l:r:p:e:c:a:t:s:k:jzndifbhF")) != -1){ switch (c) { case 'o': outfilename = optarg; @@ -808,92 +930,43 @@ case 'i': t2p->pdf_colorspace_invert=1; break; + case 'F': + t2p->pdf_image_fillpage = 1; + break; case 'f': t2p->pdf_fitwindow=1; break; case 'e': - t2p->pdf_datetime = - (unsigned char*)_TIFFmalloc(17); - if(t2p->pdf_datetime==NULL){ - TIFFError(TIFF2PDF_MODULE, - "Can't allocate %u bytes of memory for main", - 17); - goto fail; - } - if(strlen(optarg)==0){ - t2p->pdf_datetime[0] = 0; + if (strlen(optarg) == 0) { + t2p->pdf_datetime[0] = '\0'; } else { - if(strlen(optarg)>14){optarg[14]=0;} t2p->pdf_datetime[0] = 'D'; t2p->pdf_datetime[1] = ':'; - strcpy((char *)t2p->pdf_datetime + 2, - optarg); + strncpy(t2p->pdf_datetime + 2, optarg, + sizeof(t2p->pdf_datetime) - 3); + t2p->pdf_datetime[sizeof(t2p->pdf_datetime) - 1] = '\0'; } break; case 'c': - t2p->pdf_creator = (unsigned char *) - _TIFFmalloc(strlen(optarg) + 1); - if(t2p->pdf_creator==NULL){ - TIFFError(TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for main", - (long)strlen(optarg) + 1); - goto fail; - } - strcpy((char *)t2p->pdf_creator, optarg); - t2p->pdf_creator[strlen(optarg)] = 0; + strncpy(t2p->pdf_creator, optarg, sizeof(t2p->pdf_creator) - 1); + t2p->pdf_creator[sizeof(t2p->pdf_creator) - 1] = '\0'; break; case 'a': - t2p->pdf_author = (unsigned char *) - _TIFFmalloc(strlen(optarg) + 1); - if(t2p->pdf_author==NULL){ - TIFFError( - TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for main", - (long)strlen(optarg) + 1); - goto fail; - } - strcpy((char *)t2p->pdf_author, optarg); - t2p->pdf_author[strlen(optarg)]=0; + strncpy(t2p->pdf_author, optarg, sizeof(t2p->pdf_author) - 1); + t2p->pdf_author[sizeof(t2p->pdf_author) - 1] = '\0'; break; case 't': - t2p->pdf_title = (unsigned char*) - _TIFFmalloc(strlen(optarg)+1); - if(t2p->pdf_title==NULL){ - TIFFError( - TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for main", - (long)strlen(optarg) + 1); - goto fail; - } - strcpy((char *)t2p->pdf_title, optarg); - t2p->pdf_title[strlen(optarg)] = 0; + strncpy(t2p->pdf_title, optarg, sizeof(t2p->pdf_title) - 1); + t2p->pdf_title[sizeof(t2p->pdf_title) - 1] = '\0'; break; case 's': - t2p->pdf_subject = (unsigned char*) - _TIFFmalloc(strlen(optarg) + 1); - if(t2p->pdf_subject==NULL){ - TIFFError( - TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for main", - (long)strlen(optarg)+1); - goto fail; - } - strcpy((char *)t2p->pdf_subject, optarg); - t2p->pdf_subject[strlen(optarg)]=0; + strncpy(t2p->pdf_subject, optarg, sizeof(t2p->pdf_subject) - 1); + t2p->pdf_subject[sizeof(t2p->pdf_subject) - 1] = '\0'; break; case 'k': - t2p->pdf_keywords = (unsigned char*) - _TIFFmalloc(strlen(optarg) + 1); - if(t2p->pdf_keywords==NULL){ - TIFFError( - TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for main", - (long)strlen(optarg) + 1); - goto fail; - } - strcpy((char *)t2p->pdf_keywords, optarg); - t2p->pdf_keywords[strlen(optarg)] = 0; - break; + strncpy(t2p->pdf_keywords, optarg, sizeof(t2p->pdf_keywords) - 1); + t2p->pdf_keywords[sizeof(t2p->pdf_keywords) - 1] = '\0'; + break; case 'b': t2p->pdf_image_interpolate = 1; break; @@ -904,12 +977,13 @@ * Output */ t2p->outputdisable = 0; - t2p->outputfile = outputfile; + t2p->outputfile = outputfile; output = TIFFClientOpen(outfilename, "w", (thandle_t) t2p, t2p_readproc, t2p_writeproc, t2p_seekproc, t2p_closeproc, t2p_sizeproc, - t2p_mapproc, t2p_unmapproc ); + t2p_mapproc, t2p_unmapproc); + if (output == NULL) { TIFFError(TIFF2PDF_MODULE, "Can't initialize output descriptor"); @@ -925,33 +999,28 @@ /* * Write */ - written = t2p_write_pdf(t2p, input, output); + t2p_write_pdf(t2p, input, output); if (t2p->t2p_error != 0) { TIFFError(TIFF2PDF_MODULE, "An error occurred creating output PDF file"); goto fail; } -/* success: */ - if (output != NULL) - TIFFClose(output); - if (t2p != NULL) - t2p_free(t2p); - return(EXIT_SUCCESS); - + goto success; fail: - if(input != NULL) - TIFFClose(input); + ret = EXIT_FAILURE; +success: if (output != NULL) TIFFClose(output); if (t2p != NULL) t2p_free(t2p); - return(EXIT_FAILURE); + return ret; } -static int tiff2pdf_match_paper_size(float* width, float* length, char* papersize){ +static +int tiff2pdf_match_paper_size(float* width, float* length, char* papersize){ size_t i, len; const char* sizes[]={ @@ -998,7 +1067,7 @@ len=strlen(papersize); for(i=0;ipdf_xrefoffsets != NULL){ _TIFFfree( (tdata_t) t2p->pdf_xrefoffsets); } @@ -1063,27 +1134,6 @@ if(t2p->pdf_palette != NULL){ _TIFFfree( (tdata_t) t2p->pdf_palette); } - if(t2p->pdf_fileid != NULL){ - _TIFFfree( (tdata_t) t2p->pdf_fileid); - } - if(t2p->pdf_datetime != NULL){ - _TIFFfree( (tdata_t) t2p->pdf_datetime); - } - if(t2p->pdf_creator != NULL){ - _TIFFfree( (tdata_t) t2p->pdf_creator); - } - if(t2p->pdf_author != NULL){ - _TIFFfree( (tdata_t) t2p->pdf_author); - } - if(t2p->pdf_title != NULL){ - _TIFFfree( (tdata_t) t2p->pdf_title); - } - if(t2p->pdf_subject != NULL){ - _TIFFfree( (tdata_t) t2p->pdf_subject); - } - if(t2p->pdf_keywords != NULL){ - _TIFFfree( (tdata_t) t2p->pdf_keywords); - } #ifdef OJPEG_SUPPORT if(t2p->pdf_ojpegdata != NULL){ _TIFFfree( (tdata_t) t2p->pdf_ojpegdata); @@ -1100,7 +1150,8 @@ before calling t2p_write_pdf with it. */ -static void t2p_validate(T2P* t2p){ +static +void t2p_validate(T2P* t2p){ #ifdef JPEG_SUPPORT if(t2p->pdf_defaultcompression==T2P_COMPRESS_JPEG){ @@ -1142,7 +1193,8 @@ with the output of the PDF document as a whole. */ -static void t2p_read_tiff_init(T2P* t2p, TIFF* input){ +static +void t2p_read_tiff_init(T2P* t2p, TIFF* input){ tdir_t directorycount=0; tdir_t i=0; @@ -1151,23 +1203,23 @@ uint16 xuint16=0; directorycount=TIFFNumberOfDirectories(input); - t2p->tiff_pages = (T2P_PAGE*) _TIFFmalloc(directorycount * sizeof(T2P_PAGE)); + t2p->tiff_pages = (T2P_PAGE*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,directorycount,sizeof(T2P_PAGE))); if(t2p->tiff_pages==NULL){ TIFFError( TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for tiff_pages array, %s", - directorycount * (long)sizeof(T2P_PAGE), + "Can't allocate " TIFF_SIZE_FORMAT " bytes of memory for tiff_pages array, %s", + (TIFF_SIZE_T) directorycount * sizeof(T2P_PAGE), TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return; } _TIFFmemset( t2p->tiff_pages, 0x00, directorycount * sizeof(T2P_PAGE)); - t2p->tiff_tiles = (T2P_TILES*) _TIFFmalloc(directorycount * sizeof(T2P_TILES)); + t2p->tiff_tiles = (T2P_TILES*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,directorycount,sizeof(T2P_TILES))); if(t2p->tiff_tiles==NULL){ TIFFError( TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for tiff_tiles array, %s", - directorycount * (long)sizeof(T2P_TILES), + "Can't allocate " TIFF_SIZE_FORMAT " bytes of memory for tiff_tiles array, %s", + (TIFF_SIZE_T) directorycount * sizeof(T2P_TILES), TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return; @@ -1252,8 +1304,10 @@ &(t2p->tiff_transferfunction[0]), &(t2p->tiff_transferfunction[1]), &(t2p->tiff_transferfunction[2]))) { - if(t2p->tiff_transferfunction[1] != - t2p->tiff_transferfunction[0]) { + if((t2p->tiff_transferfunction[1] != (float*) NULL) && + (t2p->tiff_transferfunction[2] != (float*) NULL) && + (t2p->tiff_transferfunction[1] != + t2p->tiff_transferfunction[0])) { t2p->tiff_transferfunctioncount = 3; t2p->tiff_pages[i].page_extra += 4; t2p->pdf_xrefcount += 4; @@ -1280,7 +1334,24 @@ t2p->tiff_pages[i].page_tilecount; if( (TIFFGetField(input, TIFFTAG_PLANARCONFIG, &xuint16) != 0) && (xuint16 == PLANARCONFIG_SEPARATE ) ){ - TIFFGetField(input, TIFFTAG_SAMPLESPERPIXEL, &xuint16); + if( !TIFFGetField(input, TIFFTAG_SAMPLESPERPIXEL, &xuint16) ) + { + TIFFError( + TIFF2PDF_MODULE, + "Missing SamplesPerPixel, %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + if( (t2p->tiff_tiles[i].tiles_tilecount % xuint16) != 0 ) + { + TIFFError( + TIFF2PDF_MODULE, + "Invalid tile count, %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } t2p->tiff_tiles[i].tiles_tilecount/= xuint16; } if( t2p->tiff_tiles[i].tiles_tilecount > 0){ @@ -1293,14 +1364,13 @@ TIFFTAG_TILELENGTH, &( t2p->tiff_tiles[i].tiles_tilelength) ); t2p->tiff_tiles[i].tiles_tiles = - (T2P_TILE*) _TIFFmalloc( - t2p->tiff_tiles[i].tiles_tilecount - * sizeof(T2P_TILE) ); + (T2P_TILE*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->tiff_tiles[i].tiles_tilecount, + sizeof(T2P_TILE)) ); if( t2p->tiff_tiles[i].tiles_tiles == NULL){ TIFFError( TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for t2p_read_tiff_init, %s", - t2p->tiff_tiles[i].tiles_tilecount * (long)sizeof(T2P_TILE), + "Can't allocate " TIFF_SIZE_FORMAT " bytes of memory for t2p_read_tiff_init, %s", + (TIFF_SIZE_T) t2p->tiff_tiles[i].tiles_tilecount * sizeof(T2P_TILE), TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return; @@ -1313,12 +1383,19 @@ /* * This function is used by qsort to sort a T2P_PAGE* array of page structures - * by page number. + * by page number. If the page numbers are the same, we fall back to comparing + * directory numbers to preserve the order of the input file. */ -static int t2p_cmp_t2p_page(const void* e1, const void* e2){ +static +int t2p_cmp_t2p_page(const void* e1, const void* e2){ - return( ((T2P_PAGE*)e1)->page_number - ((T2P_PAGE*)e2)->page_number ); + int d; + d = (int32)(((T2P_PAGE*)e1)->page_number) - (int32)(((T2P_PAGE*)e2)->page_number); + if(d == 0){ + d = (int32)(((T2P_PAGE*)e1)->page_directory) - (int32)(((T2P_PAGE*)e2)->page_directory); + } + return d; } /* @@ -1333,7 +1410,8 @@ requiring transcoding of the image data. */ -static void t2p_read_tiff_data(T2P* t2p, TIFF* input){ +static +void t2p_read_tiff_data(T2P* t2p, TIFF* input){ int i=0; uint16* r; @@ -1496,10 +1574,28 @@ &xuint16, &xuint16p) && xuint16 == 1) { if(xuint16p[0] == EXTRASAMPLE_ASSOCALPHA){ + if( t2p->tiff_bitspersample != 8 ) + { + TIFFError( + TIFF2PDF_MODULE, + "No support for BitsPerSample=%d for RGBA", + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } t2p->pdf_sample=T2P_SAMPLE_RGBAA_TO_RGB; break; } if(xuint16p[0] == EXTRASAMPLE_UNASSALPHA){ + if( t2p->tiff_bitspersample != 8 ) + { + TIFFError( + TIFF2PDF_MODULE, + "No support for BitsPerSample=%d for RGBA", + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } t2p->pdf_sample=T2P_SAMPLE_RGBA_TO_RGB; break; } @@ -1559,7 +1655,7 @@ t2p->pdf_palette=NULL; } t2p->pdf_palette = (unsigned char*) - _TIFFmalloc(t2p->pdf_palettesize*3); + _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->pdf_palettesize,3)); if(t2p->pdf_palette==NULL){ TIFFError( TIFF2PDF_MODULE, @@ -1628,7 +1724,7 @@ t2p->pdf_palette=NULL; } t2p->pdf_palette = (unsigned char*) - _TIFFmalloc(t2p->pdf_palettesize*4); + _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->pdf_palettesize,4)); if(t2p->pdf_palette==NULL){ TIFFError( TIFF2PDF_MODULE, @@ -1661,6 +1757,22 @@ #endif break; case PHOTOMETRIC_CIELAB: + if( t2p->tiff_samplesperpixel != 3){ + TIFFError( + TIFF2PDF_MODULE, + "Unsupported samplesperpixel = %d for CIELAB", + t2p->tiff_samplesperpixel); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + if( t2p->tiff_bitspersample != 8){ + TIFFError( + TIFF2PDF_MODULE, + "Invalid bitspersample = %d for CIELAB", + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } t2p->pdf_labrange[0]= -127; t2p->pdf_labrange[1]= 127; t2p->pdf_labrange[2]= -127; @@ -1676,6 +1788,22 @@ t2p->pdf_colorspace=T2P_CS_LAB; break; case PHOTOMETRIC_ITULAB: + if( t2p->tiff_samplesperpixel != 3){ + TIFFError( + TIFF2PDF_MODULE, + "Unsupported samplesperpixel = %d for ITULAB", + t2p->tiff_samplesperpixel); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + if( t2p->tiff_bitspersample != 8){ + TIFFError( + TIFF2PDF_MODULE, + "Invalid bitspersample = %d for ITULAB", + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } t2p->pdf_labrange[0]=-85; t2p->pdf_labrange[1]=85; t2p->pdf_labrange[2]=-75; @@ -1761,9 +1889,16 @@ } t2p_compose_pdf_page(t2p); + if( t2p->t2p_error == T2P_ERR_ERROR ) + return; t2p->pdf_transcode = T2P_TRANSCODE_ENCODE; - if(t2p->pdf_nopassthrough==0){ + /* It seems that T2P_TRANSCODE_RAW mode doesn't support separate->contig */ + /* conversion. At least t2p_read_tiff_size and t2p_read_tiff_size_tile */ + /* do not take into account the number of samples, and thus */ + /* that can cause heap buffer overflows such as in */ + /* http://bugzilla.maptools.org/show_bug.cgi?id=2715 */ + if(t2p->pdf_nopassthrough==0 && t2p->tiff_planar!=PLANARCONFIG_SEPARATE){ #ifdef CCITT_SUPPORT if(t2p->tiff_compression==COMPRESSION_CCITTFAX4 ){ @@ -1848,8 +1983,10 @@ &(t2p->tiff_transferfunction[0]), &(t2p->tiff_transferfunction[1]), &(t2p->tiff_transferfunction[2]))) { - if(t2p->tiff_transferfunction[1] != - t2p->tiff_transferfunction[0]) { + if((t2p->tiff_transferfunction[1] != (float*) NULL) && + (t2p->tiff_transferfunction[2] != (float*) NULL) && + (t2p->tiff_transferfunction[1] != + t2p->tiff_transferfunction[0])) { t2p->tiff_transferfunctioncount=3; } else { t2p->tiff_transferfunctioncount=1; @@ -1913,9 +2050,10 @@ uncompressed image data from the input TIFF for a page. */ -static void t2p_read_tiff_size(T2P* t2p, TIFF* input){ +static +void t2p_read_tiff_size(T2P* t2p, TIFF* input){ - uint32* sbc=NULL; + uint64* sbc=NULL; #if defined(JPEG_SUPPORT) || defined (OJPEG_SUPPORT) unsigned char* jpt=NULL; tstrip_t i=0; @@ -1927,14 +2065,22 @@ #ifdef CCITT_SUPPORT if(t2p->pdf_compression == T2P_COMPRESS_G4 ){ TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc); - t2p->tiff_datasize=sbc[0]; + if (sbc[0] != (uint64)(tmsize_t)sbc[0]) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + t2p->tiff_datasize=(tmsize_t)sbc[0]; return; } #endif #ifdef ZIP_SUPPORT if(t2p->pdf_compression == T2P_COMPRESS_ZIP){ TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc); - t2p->tiff_datasize=sbc[0]; + if (sbc[0] != (uint64)(tmsize_t)sbc[0]) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + t2p->tiff_datasize=(tmsize_t)sbc[0]; return; } #endif @@ -1954,7 +2100,7 @@ if(TIFFGetField(input, TIFFTAG_JPEGIFOFFSET, &(t2p->tiff_dataoffset))){ if(t2p->tiff_dataoffset != 0){ if(TIFFGetField(input, TIFFTAG_JPEGIFBYTECOUNT, &(t2p->tiff_datasize))!=0){ - if((uint64)t2p->tiff_datasize < k) { + if((uint64)t2p->tiff_datasize < k) { TIFFWarning(TIFF2PDF_MODULE, "Input file %s has short JPEG interchange file byte count", TIFFFileName(input)); @@ -2012,14 +2158,17 @@ } for(i=0;itiff_datasize = (tsize_t) k; if ((uint64) t2p->tiff_datasize != k) { TIFFError(TIFF2PDF_MODULE, "Integer overflow"); t2p->t2p_error = T2P_ERR_ERROR; } + return; } #endif (void) 0; @@ -2047,9 +2196,10 @@ uncompressed image data from the input TIFF for a tile of a page. */ -static void t2p_read_tiff_size_tile(T2P* t2p, TIFF* input, ttile_t tile){ +static +void t2p_read_tiff_size_tile(T2P* t2p, TIFF* input, ttile_t tile){ - uint32* tbc = NULL; + uint64* tbc = NULL; uint16 edge=0; #ifdef JPEG_SUPPORT unsigned char* jpt; @@ -2085,9 +2235,7 @@ if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt)!=0){ if(count > 4){ k = checkAdd64(k, count, t2p); - k -= 4; /* don't use EOI of header or SOI of tile */ - - + k -= 2; /* don't use EOI of header or SOI of tile */ } } } @@ -2123,7 +2271,8 @@ * and does not have full imaged tile width. */ -static int t2p_tile_is_right_edge(T2P_TILES tiles, ttile_t tile){ +static +int t2p_tile_is_right_edge(T2P_TILES tiles, ttile_t tile){ if( ((tile+1) % tiles.tiles_tilecountx == 0) && (tiles.tiles_edgetilewidth != 0) ){ @@ -2138,7 +2287,8 @@ * and does not have full imaged tile length. */ -static int t2p_tile_is_bottom_edge(T2P_TILES tiles, ttile_t tile){ +static +int t2p_tile_is_bottom_edge(T2P_TILES tiles, ttile_t tile){ if( ((tile+1) > (tiles.tiles_tilecount-tiles.tiles_tilecountx) ) && (tiles.tiles_edgetilelength != 0) ){ @@ -2154,7 +2304,8 @@ or zero on error. */ -static tsize_t t2p_readwrite_pdf_image(T2P* t2p, TIFF* input, TIFF* output){ +static +tsize_t t2p_readwrite_pdf_image(T2P* t2p, TIFF* input, TIFF* output){ tsize_t written=0; unsigned char* buffer=NULL; @@ -2174,15 +2325,15 @@ uint16 v_samp=1; uint16 ri=1; uint32 rows=0; -#endif +#endif /* ifdef OJPEG_SUPPORT */ #ifdef JPEG_SUPPORT unsigned char* jpt; float* xfloatp; - uint32* sbc; + uint64* sbc; unsigned char* stripbuffer; tsize_t striplength=0; uint32 max_striplength=0; -#endif +#endif /* ifdef JPEG_SUPPORT */ /* Fail if prior error (in particular, can't trust tiff_datasize) */ if (t2p->t2p_error != T2P_ERR_OK) @@ -2195,8 +2346,9 @@ _TIFFmalloc(t2p->tiff_datasize); if (buffer == NULL) { TIFFError(TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + "Can't allocate %lu bytes of memory for " + "t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); @@ -2216,20 +2368,20 @@ _TIFFfree(buffer); return(t2p->tiff_datasize); } -#endif +#endif /* ifdef CCITT_SUPPORT */ #ifdef ZIP_SUPPORT if (t2p->pdf_compression == T2P_COMPRESS_ZIP) { buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - memset(buffer, 0, t2p->tiff_datasize); if(buffer == NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); } + memset(buffer, 0, t2p->tiff_datasize); TIFFReadRawStrip(input, 0, (tdata_t) buffer, t2p->tiff_datasize); if (t2p->tiff_fillorder==FILLORDER_LSB2MSB) { @@ -2241,22 +2393,22 @@ _TIFFfree(buffer); return(t2p->tiff_datasize); } -#endif +#endif /* ifdef ZIP_SUPPORT */ #ifdef OJPEG_SUPPORT if(t2p->tiff_compression == COMPRESSION_OJPEG) { if(t2p->tiff_dataoffset != 0) { buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - memset(buffer, 0, t2p->tiff_datasize); if(buffer == NULL) { TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); } + memset(buffer, 0, t2p->tiff_datasize); if(t2p->pdf_ojpegiflength==0){ inputoffset=t2pSeekFile(input, 0, SEEK_CUR); @@ -2324,15 +2476,15 @@ } buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - memset(buffer, 0, t2p->tiff_datasize); if(buffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); } + memset(buffer, 0, t2p->tiff_datasize); _TIFFmemcpy(buffer, t2p->pdf_ojpegdata, t2p->pdf_ojpegdatalength); bufferoffset=t2p->pdf_ojpegdatalength; stripcount=TIFFNumberOfStrips(input); @@ -2353,29 +2505,35 @@ t2pWriteFile(output, (tdata_t) buffer, bufferoffset); _TIFFfree(buffer); return(bufferoffset); +#if 0 + /* + This hunk of code removed code is clearly + mis-placed and we are not sure where it + should be (if anywhere) + */ TIFFError(TIFF2PDF_MODULE, "No support for OJPEG image %s with no JPEG File Interchange offset", TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); +#endif } - return(t2p->tiff_datasize); } -#endif +#endif /* ifdef OJPEG_SUPPORT */ #ifdef JPEG_SUPPORT if(t2p->tiff_compression == COMPRESSION_JPEG) { uint32 count = 0; buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - memset(buffer, 0, t2p->tiff_datasize); if(buffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); } + memset(buffer, 0, t2p->tiff_datasize); if (TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0) { if(count > 4) { _TIFFmemcpy(buffer, jpt, count); @@ -2403,7 +2561,8 @@ if(!t2p_process_jpeg_strip( stripbuffer, &striplength, - buffer, + buffer, + t2p->tiff_datasize, &bufferoffset, i, t2p->tiff_length)){ @@ -2423,21 +2582,21 @@ _TIFFfree(buffer); return(bufferoffset); } -#endif +#endif /* ifdef JPEG_SUPPORT */ (void)0; } if(t2p->pdf_sample==T2P_SAMPLE_NOTHING){ buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - memset(buffer, 0, t2p->tiff_datasize); if(buffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); } + memset(buffer, 0, t2p->tiff_datasize); stripsize=TIFFStripSize(input); stripcount=TIFFNumberOfStrips(input); for(i=0;itiff_datasize - bufferoffset)); if(read==-1){ TIFFError(TIFF2PDF_MODULE, "Error on decoding strip %u of %s", @@ -2467,22 +2626,23 @@ stripcount=sepstripcount/t2p->tiff_samplesperpixel; buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - memset(buffer, 0, t2p->tiff_datasize); if(buffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); } + memset(buffer, 0, t2p->tiff_datasize); samplebuffer = (unsigned char*) _TIFFmalloc(stripsize); if(samplebuffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; + _TIFFfree(buffer); return(0); } for(i=0;itiff_datasize); - memset(buffer, 0, t2p->tiff_datasize); if(buffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); } + memset(buffer, 0, t2p->tiff_datasize); stripsize=TIFFStripSize(input); stripcount=TIFFNumberOfStrips(input); for(i=0;itiff_datasize - bufferoffset)); if(read==-1){ TIFFError(TIFF2PDF_MODULE, "Error on decoding strip %u of %s", @@ -2547,16 +2707,18 @@ } if(t2p->pdf_sample & T2P_SAMPLE_REALIZE_PALETTE){ + // FIXME: overflow? samplebuffer=(unsigned char*)_TIFFrealloc( (tdata_t) buffer, t2p->tiff_datasize * t2p->tiff_samplesperpixel); if(samplebuffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; - _TIFFfree(buffer); + _TIFFfree(buffer); + return(0); } else { buffer=samplebuffer; t2p->tiff_datasize *= t2p->tiff_samplesperpixel; @@ -2583,7 +2745,7 @@ if(samplebuffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; _TIFFfree(buffer); @@ -2637,7 +2799,7 @@ case T2P_COMPRESS_G4: TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); break; -#endif +#endif /* ifdef CCITT_SUPPORT */ #ifdef JPEG_SUPPORT case T2P_COMPRESS_JPEG: if(t2p->tiff_photometric==PHOTOMETRIC_YCBCR) { @@ -2683,7 +2845,7 @@ } break; -#endif +#endif /* ifdef JPEG_SUPPORT */ #ifdef ZIP_SUPPORT case T2P_COMPRESS_ZIP: TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); @@ -2698,7 +2860,7 @@ (t2p->pdf_defaultcompressionquality / 100)); } break; -#endif +#endif /* ifdef ZIP_SUPPORT */ default: break; } @@ -2712,8 +2874,8 @@ buffer, stripsize * stripcount); } else -#endif - { +#endif /* ifdef JPEG_SUPPORT */ + { bufferoffset = TIFFWriteEncodedStrip(output, (tstrip_t)0, buffer, t2p->tiff_datasize); @@ -2741,7 +2903,8 @@ * for the tile. It returns the amount written or zero on error. */ -static tsize_t t2p_readwrite_pdf_image_tile(T2P* t2p, TIFF* input, TIFF* output, ttile_t tile){ +static +tsize_t t2p_readwrite_pdf_image_tile(T2P* t2p, TIFF* input, TIFF* output, ttile_t tile){ uint16 edge=0; tsize_t written=0; @@ -2752,7 +2915,7 @@ tsize_t read=0; uint16 i=0; ttile_t tilecount=0; - tsize_t tilesize=0; + /* tsize_t tilesize=0; */ ttile_t septilecount=0; tsize_t septilesize=0; #ifdef JPEG_SUPPORT @@ -2760,7 +2923,6 @@ float* xfloatp; uint32 xuint32=0; #endif - (void)tilesize; /* Fail if prior error (in particular, can't trust tiff_datasize) */ if (t2p->t2p_error != T2P_ERR_OK) @@ -2782,7 +2944,7 @@ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory " "for t2p_readwrite_pdf_image_tile, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); @@ -2803,7 +2965,7 @@ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory " "for t2p_readwrite_pdf_image_tile, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); @@ -2832,7 +2994,7 @@ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory " "for t2p_readwrite_pdf_image, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); @@ -2871,35 +3033,40 @@ buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); if(buffer==NULL){ TIFFError(TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory " + "Can't allocate " TIFF_SIZE_FORMAT " bytes of memory " "for t2p_readwrite_pdf_image_tile, %s", - (unsigned long)t2p->tiff_datasize, + (TIFF_SIZE_T) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); } if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0) { - if (count > 0) { - _TIFFmemcpy(buffer, jpt, count); + if (count > 4) { + int retTIFFReadRawTile; + /* Ignore EOI marker of JpegTables */ + _TIFFmemcpy(buffer, jpt, count - 2); bufferoffset += count - 2; + /* Store last 2 bytes of the JpegTables */ table_end[0] = buffer[bufferoffset-2]; table_end[1] = buffer[bufferoffset-1]; - } - if (count > 0) { xuint32 = bufferoffset; - bufferoffset += TIFFReadRawTile( - input, - tile, - (tdata_t) &(((unsigned char*)buffer)[bufferoffset-2]), - -1); - buffer[xuint32-2]=table_end[0]; - buffer[xuint32-1]=table_end[1]; - } else { - bufferoffset += TIFFReadRawTile( + bufferoffset -= 2; + retTIFFReadRawTile= TIFFReadRawTile( input, tile, (tdata_t) &(((unsigned char*)buffer)[bufferoffset]), -1); + if( retTIFFReadRawTile < 0 ) + { + _TIFFfree(buffer); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + bufferoffset += retTIFFReadRawTile; + /* Overwrite SOI marker of image scan with previously */ + /* saved end of JpegTables */ + buffer[xuint32-2]=table_end[0]; + buffer[xuint32-1]=table_end[1]; } } t2pWriteFile(output, (tdata_t) buffer, bufferoffset); @@ -2916,7 +3083,7 @@ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory for " "t2p_readwrite_pdf_image_tile, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); @@ -2942,14 +3109,14 @@ if(t2p->pdf_sample == T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG){ septilesize=TIFFTileSize(input); septilecount=TIFFNumberOfTiles(input); - tilesize=septilesize*t2p->tiff_samplesperpixel; + /* tilesize=septilesize*t2p->tiff_samplesperpixel; */ tilecount=septilecount/t2p->tiff_samplesperpixel; buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); if(buffer==NULL){ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory " "for t2p_readwrite_pdf_image_tile, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); @@ -2959,7 +3126,7 @@ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory " "for t2p_readwrite_pdf_image_tile, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); @@ -2998,7 +3165,7 @@ TIFFError(TIFF2PDF_MODULE, "Can't allocate %lu bytes of memory " "for t2p_readwrite_pdf_image_tile, %s", - (unsigned long)t2p->tiff_datasize, + (unsigned long) t2p->tiff_datasize, TIFFFileName(input)); t2p->t2p_error = T2P_ERR_ERROR; return(0); @@ -3183,7 +3350,8 @@ } #ifdef OJPEG_SUPPORT -static int t2p_process_ojpeg_tables(T2P* t2p, TIFF* input){ +static +int t2p_process_ojpeg_tables(T2P* t2p, TIFF* input){ uint16 proc=0; void* q; uint32 q_length=0; @@ -3278,6 +3446,7 @@ "Can't allocate %u bytes of memory for t2p_process_ojpeg_tables, %s", 2048, TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; return(0); } _TIFFmemset(t2p->pdf_ojpegdata, 0x00, 2048); @@ -3427,39 +3596,77 @@ #endif #ifdef JPEG_SUPPORT -static int t2p_process_jpeg_strip( +static +int t2p_process_jpeg_strip( unsigned char* strip, tsize_t* striplength, unsigned char* buffer, + tsize_t buffersize, tsize_t* bufferoffset, tstrip_t no, uint32 height){ tsize_t i=0; - uint16 ri =0; - uint16 v_samp=1; - uint16 h_samp=1; - int j=0; - - i++; - - while(i<(*striplength)){ + + while (i < *striplength) { + tsize_t datalen; + uint16 ri; + uint16 v_samp; + uint16 h_samp; + int j; + int ncomp; + + /* marker header: one or more FFs */ + if (strip[i] != 0xff) + return(0); + i++; + while (i < *striplength && strip[i] == 0xff) + i++; + if (i >= *striplength) + return(0); + /* SOI is the only pre-SOS marker without a length word */ + if (strip[i] == 0xd8) + datalen = 0; + else { + if ((*striplength - i) <= 2) + return(0); + datalen = (strip[i+1] << 8) | strip[i+2]; + if (datalen < 2 || datalen >= (*striplength - i)) + return(0); + } switch( strip[i] ){ - case 0xd8: - i+=2; + case 0xd8: /* SOI - start of image */ + if( *bufferoffset + 2 > buffersize ) + return(0); + if ( *bufferoffset == 0) { /* LB: do not repeat SOI marker */ + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), 2); + *bufferoffset+=2; + } break; - case 0xc0: - case 0xc1: - case 0xc3: - case 0xc9: - case 0xca: + case 0xc0: /* SOF0 */ + case 0xc1: /* SOF1 */ + case 0xc3: /* SOF3 */ + case 0xc9: /* SOF9 */ + case 0xca: /* SOF10 */ if(no==0){ - _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), strip[i+2]+2); - for(j=0;j>4) > h_samp) - h_samp = (buffer[*bufferoffset+11+(2*j)]>>4); - if( (buffer[*bufferoffset+11+(2*j)] & 0x0f) > v_samp) - v_samp = (buffer[*bufferoffset+11+(2*j)] & 0x0f); + if( *bufferoffset + datalen + 2 + 6 > buffersize ) + return(0); + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2); + if( *bufferoffset + 9 >= buffersize ) + return(0); + ncomp = buffer[*bufferoffset+9]; + if (ncomp < 1 || ncomp > 4) + return(0); + v_samp=1; + h_samp=1; + if( *bufferoffset + 11 + 3*(ncomp-1) >= buffersize ) + return(0); + for(j=0;j>4) > h_samp) + h_samp = (samp>>4); + if( (samp & 0x0f) > v_samp) + v_samp = (samp & 0x0f); } v_samp*=8; h_samp*=8; @@ -3473,45 +3680,51 @@ (unsigned char) ((height>>8) & 0xff); buffer[*bufferoffset+6]= (unsigned char) (height & 0xff); - *bufferoffset+=strip[i+2]+2; - i+=strip[i+2]+2; - + *bufferoffset+=datalen+2; + /* insert a DRI marker */ buffer[(*bufferoffset)++]=0xff; buffer[(*bufferoffset)++]=0xdd; buffer[(*bufferoffset)++]=0x00; buffer[(*bufferoffset)++]=0x04; buffer[(*bufferoffset)++]=(ri >> 8) & 0xff; buffer[(*bufferoffset)++]= ri & 0xff; - } else { - i+=strip[i+2]+2; } break; - case 0xc4: - case 0xdb: - _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), strip[i+2]+2); - *bufferoffset+=strip[i+2]+2; - i+=strip[i+2]+2; + case 0xc4: /* DHT */ + case 0xdb: /* DQT */ + if( *bufferoffset + datalen + 2 > buffersize ) + return(0); + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2); + *bufferoffset+=datalen+2; break; - case 0xda: + case 0xda: /* SOS */ if(no==0){ - _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), strip[i+2]+2); - *bufferoffset+=strip[i+2]+2; - i+=strip[i+2]+2; + if( *bufferoffset + datalen + 2 > buffersize ) + return(0); + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2); + *bufferoffset+=datalen+2; } else { + if( *bufferoffset + 2 > buffersize ) + return(0); buffer[(*bufferoffset)++]=0xff; buffer[(*bufferoffset)++]= (unsigned char)(0xd0 | ((no-1)%8)); - i+=strip[i+2]+2; } - _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), (*striplength)-i-1); - *bufferoffset+=(*striplength)-i-1; + i += datalen + 1; + /* copy remainder of strip */ + if( *bufferoffset + *striplength - i > buffersize ) + return(0); + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i]), *striplength - i); + *bufferoffset+= *striplength - i; return(1); default: - i+=strip[i+2]+2; + /* ignore any other marker */ + break; } + i += datalen + 1; } - + /* failed to find SOS marker */ return(0); } #endif @@ -3520,19 +3733,21 @@ This functions converts a tilewidth x tilelength buffer of samples into an edgetilewidth x tilelength buffer of samples. */ -static void t2p_tile_collapse_left( +static +void t2p_tile_collapse_left( tdata_t buffer, tsize_t scanwidth, uint32 tilewidth, uint32 edgetilewidth, uint32 tilelength){ - uint32 i=0; + uint32 i; tsize_t edgescanwidth=0; edgescanwidth = (scanwidth * edgetilewidth + (tilewidth - 1))/ tilewidth; for(i=0;itiff_width*t2p->tiff_length; component_count=t2p->tiff_samplesperpixel; + data_size=TIFFSafeMultiply(size_t,sample_count,component_count); + if( (data_size == 0U) || (t2p->tiff_datasize < 0) || + (data_size > (size_t) t2p->tiff_datasize) ) + { + TIFFError(TIFF2PDF_MODULE, + "Error: sample_count * component_count > t2p->tiff_datasize"); + t2p->t2p_error = T2P_ERR_ERROR; + return 1; + } for(i=sample_count;i>0;i--){ palette_offset=buffer[i-1] * component_count; @@ -3609,7 +3838,8 @@ into RGB interleaved data, discarding A. */ -static tsize_t t2p_sample_abgr_to_rgb(tdata_t data, uint32 samplecount) +static +tsize_t t2p_sample_abgr_to_rgb(tdata_t data, uint32 samplecount) { uint32 i=0; uint32 sample=0; @@ -3629,12 +3859,18 @@ * into RGB interleaved data, discarding A. */ -static tsize_t +static +tsize_t t2p_sample_rgbaa_to_rgb(tdata_t data, uint32 samplecount) { uint32 i; - for(i = 0; i < samplecount; i++) + /* For the 3 first samples, there is overlapping between souce and + destination, so use memmove(). + See http://bugzilla.maptools.org/show_bug.cgi?id=2577 */ + for(i = 0; i < 3 && i < samplecount; i++) + memmove((uint8*)data + i * 3, (uint8*)data + i * 4, 3); + for(; i < samplecount; i++) memcpy((uint8*)data + i * 3, (uint8*)data + i * 4, 3); return(i * 3); @@ -3645,20 +3881,20 @@ * into RGB interleaved data, adding 255-A to each component sample. */ -static tsize_t +static +tsize_t t2p_sample_rgba_to_rgb(tdata_t data, uint32 samplecount) { uint32 i = 0; uint32 sample = 0; uint8 alpha = 0; - + for (i = 0; i < samplecount; i++) { sample=((uint32*)data)[i]; - alpha=(uint8)((255 - (sample & 0xff))); - ((uint8 *)data)[i * 3] = (uint8) ((sample >> 24) & 0xff) + alpha; - ((uint8 *)data)[i * 3 + 1] = (uint8) ((sample >> 16) & 0xff) + alpha; - ((uint8 *)data)[i * 3 + 2] = (uint8) ((sample >> 8) & 0xff) + alpha; - + alpha=(uint8)((255 - ((sample >> 24) & 0xff))); + ((uint8 *)data)[i * 3] = (uint8) ((sample >> 16) & 0xff) + alpha; + ((uint8 *)data)[i * 3 + 1] = (uint8) ((sample >> 8) & 0xff) + alpha; + ((uint8 *)data)[i * 3 + 2] = (uint8) (sample & 0xff) + alpha; } return (i * 3); @@ -3669,7 +3905,8 @@ to unsigned. */ -static tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t buffer, uint32 samplecount){ +static +tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t buffer, uint32 samplecount){ uint32 i=0; @@ -3695,13 +3932,17 @@ This function writes the PDF header to output. */ -static tsize_t t2p_write_pdf_header(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_header(T2P* t2p, TIFF* output){ tsize_t written=0; char buffer[16]; int buflen=0; - buflen=sprintf(buffer, "%%PDF-%u.%u ", t2p->pdf_majorversion&0xff, t2p->pdf_minorversion&0xff); + buflen = snprintf(buffer, sizeof(buffer), "%%PDF-%u.%u ", + t2p->pdf_majorversion&0xff, + t2p->pdf_minorversion&0xff); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t)"\n%\342\343\317\323\n", 7); @@ -3712,13 +3953,15 @@ This function writes the beginning of a PDF object to output. */ -static tsize_t t2p_write_pdf_obj_start(uint32 number, TIFF* output){ +static +tsize_t t2p_write_pdf_obj_start(uint32 number, TIFF* output){ tsize_t written=0; - char buffer[16]; + char buffer[32]; int buflen=0; - buflen=sprintf(buffer, "%lu", (unsigned long)number); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number); + check_snprintf_ret((T2P*)NULL, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen ); written += t2pWriteFile(output, (tdata_t) " 0 obj\n", 7); @@ -3729,7 +3972,8 @@ This function writes the end of a PDF object to output. */ -static tsize_t t2p_write_pdf_obj_end(TIFF* output){ +static +tsize_t t2p_write_pdf_obj_end(TIFF* output){ tsize_t written=0; @@ -3739,23 +3983,23 @@ } /* - This function writes a PDF string object to output. -*/ + * This function writes a PDF string object to output. + */ -static tsize_t t2p_write_pdf_string(unsigned char* pdfstr, TIFF* output){ - +static +tsize_t t2p_write_pdf_string(char* pdfstr, TIFF* output) +{ tsize_t written = 0; uint32 i = 0; char buffer[64]; - uint32 len = 0; + size_t len = 0; - len = strlen((char *)pdfstr); + len = strlen(pdfstr); written += t2pWriteFile(output, (tdata_t) "(", 1); for (i=0; ipdf_pages); - written += t2pWriteFile(output, (tdata_t) buffer, buflen ); + buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_pages); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, + TIFFmin((size_t)buflen, sizeof(buffer) - 1)); written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6); if(t2p->pdf_fitwindow){ written += t2pWriteFile(output, @@ -3927,86 +4183,60 @@ This function writes the PDF Info structure to output. */ -static tsize_t t2p_write_pdf_info(T2P* t2p, TIFF* input, TIFF* output){ - +static +tsize_t t2p_write_pdf_info(T2P* t2p, TIFF* input, TIFF* output) +{ tsize_t written = 0; - unsigned char* info; + char* info; char buffer[512]; - int buflen = 0; - (void) buflen; - - if(t2p->pdf_datetime==NULL){ + if(t2p->pdf_datetime[0] == '\0') t2p_pdf_tifftime(t2p, input); - } - if(strlen((char *)t2p->pdf_datetime) > 0){ + if (strlen(t2p->pdf_datetime) > 0) { written += t2pWriteFile(output, (tdata_t) "<< \n/CreationDate ", 18); written += t2p_write_pdf_string(t2p->pdf_datetime, output); written += t2pWriteFile(output, (tdata_t) "\n/ModDate ", 10); written += t2p_write_pdf_string(t2p->pdf_datetime, output); } written += t2pWriteFile(output, (tdata_t) "\n/Producer ", 11); - _TIFFmemset((tdata_t)buffer, 0x00, sizeof(buffer)); - buflen = sprintf(buffer, "libtiff / tiff2pdf - %d", TIFFLIB_VERSION); - written += t2p_write_pdf_string((unsigned char*)buffer, output); + snprintf(buffer, sizeof(buffer), "libtiff / tiff2pdf - %d", TIFFLIB_VERSION); + written += t2p_write_pdf_string(buffer, output); written += t2pWriteFile(output, (tdata_t) "\n", 1); - if(t2p->pdf_creator != NULL){ - if(strlen((char *)t2p->pdf_creator)>0){ - if(strlen((char *)t2p->pdf_creator) > 511) { - t2p->pdf_creator[512] = '\0'; - } - written += t2pWriteFile(output, (tdata_t) "/Creator ", 9); - written += t2p_write_pdf_string(t2p->pdf_creator, output); - written += t2pWriteFile(output, (tdata_t) "\n", 1); - } - } else{ - if( TIFFGetField(input, TIFFTAG_SOFTWARE, &info) != 0){ - if(strlen((char *)info) > 511) { - info[512] = '\0'; - } + if (t2p->pdf_creator[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Creator ", 9); + written += t2p_write_pdf_string(t2p->pdf_creator, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } else { + if (TIFFGetField(input, TIFFTAG_SOFTWARE, &info) != 0 && info) { + if(strlen(info) >= sizeof(t2p->pdf_creator)) + info[sizeof(t2p->pdf_creator) - 1] = '\0'; written += t2pWriteFile(output, (tdata_t) "/Creator ", 9); written += t2p_write_pdf_string(info, output); written += t2pWriteFile(output, (tdata_t) "\n", 1); } } - if(t2p->pdf_author != NULL) { - if(strlen((char *)t2p->pdf_author) > 0) { - if(strlen((char *)t2p->pdf_author) > 511) { - t2p->pdf_author[512] = '\0'; - } - written += t2pWriteFile(output, (tdata_t) "/Author ", 8); - written += t2p_write_pdf_string(t2p->pdf_author, output); - written += t2pWriteFile(output, (tdata_t) "\n", 1); - } - } else{ - if( TIFFGetField(input, TIFFTAG_ARTIST, &info) != 0){ - if(strlen((char *)info) > 511) { - info[512] = '\0'; - } - written += t2pWriteFile(output, (tdata_t) "/Author ", 8); - written += t2p_write_pdf_string(info, output); - written += t2pWriteFile(output, (tdata_t) "\n", 1); - } else if ( TIFFGetField(input, TIFFTAG_COPYRIGHT, &info) != 0){ - if(strlen((char *)info) > 511) { - info[512] = '\0'; - } + if (t2p->pdf_author[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Author ", 8); + written += t2p_write_pdf_string(t2p->pdf_author, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } else { + if ((TIFFGetField(input, TIFFTAG_ARTIST, &info) != 0 + || TIFFGetField(input, TIFFTAG_COPYRIGHT, &info) != 0) + && info) { + if (strlen(info) >= sizeof(t2p->pdf_author)) + info[sizeof(t2p->pdf_author) - 1] = '\0'; written += t2pWriteFile(output, (tdata_t) "/Author ", 8); written += t2p_write_pdf_string(info, output); written += t2pWriteFile(output, (tdata_t) "\n", 1); - } - } - if(t2p->pdf_title != NULL) { - if(strlen((char *)t2p->pdf_title) > 0) { - if(strlen((char *)t2p->pdf_title) > 511) { - t2p->pdf_title[512] = '\0'; - } - written += t2pWriteFile(output, (tdata_t) "/Title ", 7); - written += t2p_write_pdf_string(t2p->pdf_title, output); - written += t2pWriteFile(output, (tdata_t) "\n", 1); } - } else{ - if( TIFFGetField(input, TIFFTAG_DOCUMENTNAME, &info) != 0){ - if(strlen((char *)info) > 511) { + } + if (t2p->pdf_title[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Title ", 7); + written += t2p_write_pdf_string(t2p->pdf_title, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } else { + if (TIFFGetField(input, TIFFTAG_DOCUMENTNAME, &info) != 0){ + if(strlen(info) > 511) { info[512] = '\0'; } written += t2pWriteFile(output, (tdata_t) "/Title ", 7); @@ -4014,36 +4244,25 @@ written += t2pWriteFile(output, (tdata_t) "\n", 1); } } - if(t2p->pdf_subject != NULL) { - if(strlen((char *)t2p->pdf_subject) > 0) { - if(strlen((char *)t2p->pdf_subject) > 511) { - t2p->pdf_subject[512] = '\0'; - } - written += t2pWriteFile(output, (tdata_t) "/Subject ", 9); - written += t2p_write_pdf_string(t2p->pdf_subject, output); - written += t2pWriteFile(output, (tdata_t) "\n", 1); - } + if (t2p->pdf_subject[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Subject ", 9); + written += t2p_write_pdf_string(t2p->pdf_subject, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); } else { - if(TIFFGetField(input, TIFFTAG_IMAGEDESCRIPTION, &info) != 0) { - if(strlen((char *)info) > 511) { - info[512] = '\0'; - } + if (TIFFGetField(input, TIFFTAG_IMAGEDESCRIPTION, &info) != 0 && info) { + if (strlen(info) >= sizeof(t2p->pdf_subject)) + info[sizeof(t2p->pdf_subject) - 1] = '\0'; written += t2pWriteFile(output, (tdata_t) "/Subject ", 9); written += t2p_write_pdf_string(info, output); written += t2pWriteFile(output, (tdata_t) "\n", 1); } } - if(t2p->pdf_keywords != NULL) { - if(strlen((char *)t2p->pdf_keywords) > 0) { - if(strlen((char *)t2p->pdf_keywords) > 511) { - t2p->pdf_keywords[512] = '\0'; - } - written += t2pWriteFile(output, (tdata_t) "/Keywords ", 10); - written += t2p_write_pdf_string(t2p->pdf_keywords, output); - written += t2pWriteFile(output, (tdata_t) "\n", 1); - } + if (t2p->pdf_keywords[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Keywords ", 10); + written += t2p_write_pdf_string(t2p->pdf_keywords, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); } - written += t2pWriteFile(output, (tdata_t) ">> \n", 4); + written += t2pWriteFile(output, (tdata_t) ">> \n", 4); return(written); } @@ -4053,21 +4272,27 @@ * date string, it is called by t2p_pdf_tifftime. */ -static void t2p_pdf_currenttime(T2P* t2p) +static +void t2p_pdf_currenttime(T2P* t2p) { - struct tm* currenttime; time_t timenow; - timenow=time(0); - currenttime=localtime(&timenow); - sprintf((char *)t2p->pdf_datetime, "D:%.4d%.2d%.2d%.2d%.2d%.2d", - (currenttime->tm_year+1900) % 65536, - (currenttime->tm_mon+1) % 256, - (currenttime->tm_mday) % 256, - (currenttime->tm_hour) % 256, - (currenttime->tm_min) % 256, - (currenttime->tm_sec) % 256); + if (time(&timenow) == (time_t) -1) { + TIFFError(TIFF2PDF_MODULE, + "Can't get the current time: %s", strerror(errno)); + timenow = (time_t) 0; + } + + currenttime = localtime(&timenow); + snprintf(t2p->pdf_datetime, sizeof(t2p->pdf_datetime), + "D:%.4d%.2d%.2d%.2d%.2d%.2d", + TIFFclip( (currenttime->tm_year + 1900) % 65536 , 9999), + TIFFclip( (currenttime->tm_mon + 1) % 256 , 99), + TIFFclip( (currenttime->tm_mday) % 256 , 99), + TIFFclip( (currenttime->tm_hour) % 256 , 99), + TIFFclip( (currenttime->tm_min) % 256 , 99), + TIFFclip( (currenttime->tm_sec) % 256 , 99)); return; } @@ -4077,19 +4302,11 @@ * TIFF file if it exists or the current time as a PDF date string. */ -static void t2p_pdf_tifftime(T2P* t2p, TIFF* input){ - +void t2p_pdf_tifftime(T2P* t2p, TIFF* input) +{ char* datetime; - t2p->pdf_datetime = (unsigned char*) _TIFFmalloc(19); - if(t2p->pdf_datetime == NULL){ - TIFFError(TIFF2PDF_MODULE, - "Can't allocate %u bytes of memory for t2p_pdf_tiff_time", 17); - t2p->t2p_error = T2P_ERR_ERROR; - return; - } - t2p->pdf_datetime[16] = '\0'; - if( TIFFGetField(input, TIFFTAG_DATETIME, &datetime) != 0 + if (TIFFGetField(input, TIFFTAG_DATETIME, &datetime) != 0 && (strlen(datetime) >= 19) ){ t2p->pdf_datetime[0]='D'; t2p->pdf_datetime[1]=':'; @@ -4107,6 +4324,7 @@ t2p->pdf_datetime[13]=datetime[15]; t2p->pdf_datetime[14]=datetime[17]; t2p->pdf_datetime[15]=datetime[18]; + t2p->pdf_datetime[16] = '\0'; } else { t2p_pdf_currenttime(t2p); } @@ -4118,19 +4336,21 @@ * This function writes a PDF Pages Tree structure to output. */ -static tsize_t t2p_write_pdf_pages(T2P* t2p, TIFF* output) +static +tsize_t t2p_write_pdf_pages(T2P* t2p, TIFF* output) { tsize_t written=0; tdir_t i=0; - char buffer[16]; + char buffer[32]; int buflen=0; int page=0; - written += t2pWriteFile(output, + written += t2pWriteFile(output, (tdata_t) "<< \n/Type /Pages \n/Kids [ ", 26); page = t2p->pdf_pages+1; for (i=0;itiff_pagecount;i++){ - buflen=sprintf(buffer, "%d", page); + buflen=snprintf(buffer, sizeof(buffer), "%d", page); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); if ( ((i+1)%8)==0 ) { @@ -4145,8 +4365,8 @@ } } written += t2pWriteFile(output, (tdata_t) "] \n/Count ", 10); - _TIFFmemset(buffer, 0x00, 16); - buflen=sprintf(buffer, "%d", t2p->tiff_pagecount); + buflen=snprintf(buffer, sizeof(buffer), "%d", t2p->tiff_pagecount); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " \n>> \n", 6); @@ -4157,32 +4377,39 @@ This function writes a PDF Page structure to output. */ -static tsize_t t2p_write_pdf_page(uint32 object, T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_page(uint32 object, T2P* t2p, TIFF* output){ unsigned int i=0; tsize_t written=0; - char buffer[16]; + char buffer[256]; int buflen=0; - + written += t2pWriteFile(output, (tdata_t) "<<\n/Type /Page \n/Parent ", 24); - buflen=sprintf(buffer, "%lu", (unsigned long)t2p->pdf_pages); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_pages); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6); written += t2pWriteFile(output, (tdata_t) "/MediaBox [", 11); - buflen=sprintf(buffer, "%.4f",t2p->pdf_mediabox.x1); + buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.x1); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " ", 1); - buflen=sprintf(buffer, "%.4f",t2p->pdf_mediabox.y1); + buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.y1); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " ", 1); - buflen=sprintf(buffer, "%.4f",t2p->pdf_mediabox.x2); + buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.x2); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " ", 1); - buflen=sprintf(buffer, "%.4f",t2p->pdf_mediabox.y2); + buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.y2); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "] \n", 3); written += t2pWriteFile(output, (tdata_t) "/Contents ", 10); - buflen=sprintf(buffer, "%lu", (unsigned long)(object + 1)); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(object + 1)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6); written += t2pWriteFile(output, (tdata_t) "/Resources << \n", 15); @@ -4190,16 +4417,17 @@ written += t2pWriteFile(output, (tdata_t) "/XObject <<\n", 12); for(i=0;itiff_tiles[t2p->pdf_page].tiles_tilecount;i++){ written += t2pWriteFile(output, (tdata_t) "/Im", 3); - buflen = sprintf(buffer, "%u", t2p->pdf_page+1); + buflen = snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_page+1); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "_", 1); - buflen = sprintf(buffer, "%u", i+1); + buflen = snprintf(buffer, sizeof(buffer), "%u", i+1); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " ", 1); - buflen = sprintf( - buffer, - "%lu", + buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(object+3+(2*i)+t2p->tiff_pages[t2p->pdf_page].page_extra)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); if(i%4==3){ @@ -4210,13 +4438,13 @@ } else { written += t2pWriteFile(output, (tdata_t) "/XObject <<\n", 12); written += t2pWriteFile(output, (tdata_t) "/Im", 3); - buflen = sprintf(buffer, "%u", t2p->pdf_page+1); + buflen = snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_page+1); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " ", 1); - buflen = sprintf( - buffer, - "%lu", + buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(object+3+(2*i)+t2p->tiff_pages[t2p->pdf_page].page_extra)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); written += t2pWriteFile(output, (tdata_t) ">>\n", 3); @@ -4224,17 +4452,16 @@ if(t2p->tiff_transferfunctioncount != 0) { written += t2pWriteFile(output, (tdata_t) "/ExtGState <<", 13); t2pWriteFile(output, (tdata_t) "/GS1 ", 5); - buflen = sprintf( - buffer, - "%lu", + buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(object + 3)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); written += t2pWriteFile(output, (tdata_t) ">> \n", 4); } written += t2pWriteFile(output, (tdata_t) "/ProcSet [ ", 11); - if(t2p->pdf_colorspace == T2P_CS_BILEVEL - || t2p->pdf_colorspace == T2P_CS_GRAY + if(t2p->pdf_colorspace & T2P_CS_BILEVEL + || t2p->pdf_colorspace & T2P_CS_GRAY ){ written += t2pWriteFile(output, (tdata_t) "/ImageB ", 8); } else { @@ -4252,7 +4479,8 @@ This function composes the page size and image and tile locations on a page. */ -static void t2p_compose_pdf_page(T2P* t2p){ +static +void t2p_compose_pdf_page(T2P* t2p){ uint32 i=0; uint32 i2=0; @@ -4264,6 +4492,8 @@ uint32 tilelength=0; int istiled=0; float f=0; + float width_ratio=0; + float length_ratio=0; t2p->pdf_xres = t2p->tiff_xres; t2p->pdf_yres = t2p->tiff_yres; @@ -4275,8 +4505,18 @@ t2p->pdf_xres = t2p->pdf_defaultxres; if(t2p->pdf_yres == 0.0) t2p->pdf_yres = t2p->pdf_defaultyres; - if (t2p->tiff_resunit != RESUNIT_CENTIMETER /* RESUNIT_NONE and */ - && t2p->tiff_resunit != RESUNIT_INCH) { /* other cases */ + if (t2p->pdf_image_fillpage) { + width_ratio = t2p->pdf_defaultpagewidth/t2p->tiff_width; + length_ratio = t2p->pdf_defaultpagelength/t2p->tiff_length; + if (width_ratio < length_ratio ) { + t2p->pdf_imagewidth = t2p->pdf_defaultpagewidth; + t2p->pdf_imagelength = t2p->tiff_length * width_ratio; + } else { + t2p->pdf_imagewidth = t2p->tiff_width * length_ratio; + t2p->pdf_imagelength = t2p->pdf_defaultpagelength; + } + } else if (t2p->tiff_resunit != RESUNIT_CENTIMETER /* RESUNIT_NONE and */ + && t2p->tiff_resunit != RESUNIT_INCH) { /* other cases */ t2p->pdf_imagewidth = ((float)(t2p->tiff_width))/t2p->pdf_xres; t2p->pdf_imagelength = ((float)(t2p->tiff_length))/t2p->pdf_yres; } else { @@ -4318,6 +4558,15 @@ } else { tilewidth=(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilewidth; tilelength=(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilelength; + if( tilewidth > INT_MAX || + tilelength > INT_MAX || + t2p->tiff_width > INT_MAX - tilewidth || + t2p->tiff_length > INT_MAX - tilelength ) + { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } tilecountx=(t2p->tiff_width + tilewidth -1)/ tilewidth; @@ -4439,7 +4688,8 @@ return; } -static void t2p_compose_pdf_page_orient(T2P_BOX* boxp, uint16 orientation){ +static +void t2p_compose_pdf_page_orient(T2P_BOX* boxp, uint16 orientation){ float m1[9]; float f=0.0; @@ -4514,7 +4764,8 @@ return; } -static void t2p_compose_pdf_page_orient_flip(T2P_BOX* boxp, uint16 orientation){ +static +void t2p_compose_pdf_page_orient_flip(T2P_BOX* boxp, uint16 orientation){ float m1[9]; float f=0.0; @@ -4576,7 +4827,8 @@ This function writes a PDF Contents stream to output. */ -static tsize_t t2p_write_pdf_page_content_stream(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_page_content_stream(T2P* t2p, TIFF* output){ tsize_t written=0; ttile_t i=0; @@ -4587,7 +4839,7 @@ if(t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount>0){ for(i=0;itiff_tiles[t2p->pdf_page].tiles_tilecount; i++){ box=t2p->tiff_tiles[t2p->pdf_page].tiles_tiles[i].tile_box; - buflen=sprintf(buffer, + buflen=snprintf(buffer, sizeof(buffer), "q %s %.4f %.4f %.4f %.4f %.4f %.4f cm /Im%d_%ld Do Q\n", t2p->tiff_transferfunctioncount?"/GS1 gs ":"", box.mat[0], @@ -4598,11 +4850,12 @@ box.mat[7], t2p->pdf_page + 1, (long)(i + 1)); + check_snprintf_ret(t2p, buflen, buffer); written += t2p_write_pdf_stream(buffer, buflen, output); } } else { box=t2p->pdf_imagebox; - buflen=sprintf(buffer, + buflen=snprintf(buffer, sizeof(buffer), "q %s %.4f %.4f %.4f %.4f %.4f %.4f cm /Im%d Do Q\n", t2p->tiff_transferfunctioncount?"/GS1 gs ":"", box.mat[0], @@ -4612,6 +4865,7 @@ box.mat[6], box.mat[7], t2p->pdf_page+1); + check_snprintf_ret(t2p, buflen, buffer); written += t2p_write_pdf_stream(buffer, buflen, output); } @@ -4622,64 +4876,59 @@ This function writes a PDF Image XObject stream dictionary to output. */ -static tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t tile, - T2P* t2p, - TIFF* output){ +static +tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t tile, + T2P* t2p, + TIFF* output){ tsize_t written=0; - char buffer[16]; + char buffer[32]; int buflen=0; written += t2p_write_pdf_stream_dict(0, t2p->pdf_xrefcount+1, output); written += t2pWriteFile(output, (tdata_t) "/Type /XObject \n/Subtype /Image \n/Name /Im", 42); - buflen=sprintf(buffer, "%u", t2p->pdf_page+1); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_page+1); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); if(tile != 0){ written += t2pWriteFile(output, (tdata_t) "_", 1); - buflen=sprintf(buffer, "%lu", (unsigned long)tile); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)tile); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); } written += t2pWriteFile(output, (tdata_t) "\n/Width ", 8); - _TIFFmemset((tdata_t)buffer, 0x00, 16); if(tile==0){ - buflen=sprintf(buffer, "%lu", (unsigned long)t2p->tiff_width); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_width); } else { if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)!=0){ - buflen=sprintf( - buffer, - "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth); } else { - buflen=sprintf( - buffer, - "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth); } } + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "\n/Height ", 9); - _TIFFmemset((tdata_t)buffer, 0x00, 16); if(tile==0){ - buflen=sprintf(buffer, "%lu", (unsigned long)t2p->tiff_length); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_length); } else { if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)!=0){ - buflen=sprintf( - buffer, - "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength); } else { - buflen=sprintf( - buffer, - "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); } } + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "\n/BitsPerComponent ", 19); - _TIFFmemset((tdata_t)buffer, 0x00, 16); - buflen=sprintf(buffer, "%u", t2p->tiff_bitspersample); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->tiff_bitspersample); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "\n/ColorSpace ", 13); written += t2p_write_pdf_xobject_cs(t2p, output); @@ -4688,7 +4937,7 @@ (tdata_t) "\n/Interpolate true", 18); if( (t2p->pdf_switchdecode != 0) #ifdef CCITT_SUPPORT - && ! (t2p->pdf_colorspace == T2P_CS_BILEVEL + && ! (t2p->pdf_colorspace & T2P_CS_BILEVEL && t2p->pdf_compression == T2P_COMPRESS_G4) #endif ){ @@ -4704,7 +4953,8 @@ */ -static tsize_t t2p_write_pdf_xobject_cs(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_xobject_cs(T2P* t2p, TIFF* output){ tsize_t written=0; char buffer[128]; @@ -4723,11 +4973,12 @@ t2p->pdf_colorspace ^= T2P_CS_PALETTE; written += t2p_write_pdf_xobject_cs(t2p, output); t2p->pdf_colorspace |= T2P_CS_PALETTE; - buflen=sprintf(buffer, "%u", (0x0001 << t2p->tiff_bitspersample)-1 ); + buflen=snprintf(buffer, sizeof(buffer), "%u", (0x0001 << t2p->tiff_bitspersample)-1 ); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " ", 1); - _TIFFmemset(buffer, 0x00, 16); - buflen=sprintf(buffer, "%lu", (unsigned long)t2p->pdf_palettecs ); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_palettecs ); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R ]\n", 7); return(written); @@ -4761,22 +5012,16 @@ X_W /= Y_W; Z_W /= Y_W; Y_W = 1.0F; - buflen=sprintf(buffer, "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); - written += t2pWriteFile(output, (tdata_t) buffer, buflen); - X_W = 0.3457F; /* 0.3127F; */ /* D50, commented D65 */ - Y_W = 0.3585F; /* 0.3290F; */ - Z_W = 1.0F - (X_W + Y_W); - X_W /= Y_W; - Z_W /= Y_W; - Y_W = 1.0F; - buflen=sprintf(buffer, "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); + buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "/Range ", 7); - buflen=sprintf(buffer, "[%d %d %d %d] \n", + buflen=snprintf(buffer, sizeof(buffer), "[%d %d %d %d] \n", t2p->pdf_labrange[0], t2p->pdf_labrange[1], t2p->pdf_labrange[2], t2p->pdf_labrange[3]); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) ">>] \n", 5); @@ -4785,30 +5030,35 @@ return(written); } -static tsize_t t2p_write_pdf_transfer(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_transfer(T2P* t2p, TIFF* output){ tsize_t written=0; - char buffer[16]; + char buffer[32]; int buflen=0; written += t2pWriteFile(output, (tdata_t) "<< /Type /ExtGState \n/TR ", 25); if(t2p->tiff_transferfunctioncount == 1){ - buflen=sprintf(buffer, "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount + 1)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); } else { written += t2pWriteFile(output, (tdata_t) "[ ", 2); - buflen=sprintf(buffer, "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount + 1)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); - buflen=sprintf(buffer, "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount + 2)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); - buflen=sprintf(buffer, "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount + 3)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); written += t2pWriteFile(output, (tdata_t) "/Identity ] ", 12); @@ -4819,31 +5069,34 @@ return(written); } -static tsize_t t2p_write_pdf_transfer_dict(T2P* t2p, TIFF* output, uint16 i){ +static +tsize_t t2p_write_pdf_transfer_dict(T2P* t2p, TIFF* output, uint16 i){ tsize_t written=0; char buffer[32]; int buflen=0; - (void)i; // XXX + (void)i; /* XXX */ written += t2pWriteFile(output, (tdata_t) "/FunctionType 0 \n", 17); written += t2pWriteFile(output, (tdata_t) "/Domain [0.0 1.0] \n", 19); written += t2pWriteFile(output, (tdata_t) "/Range [0.0 1.0] \n", 18); - buflen=sprintf(buffer, "/Size [%u] \n", (1<tiff_bitspersample)); + buflen=snprintf(buffer, sizeof(buffer), "/Size [%u] \n", (1<tiff_bitspersample)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "/BitsPerSample 16 \n", 19); - written += t2p_write_pdf_stream_dict(1<<(t2p->tiff_bitspersample+1), 0, output); + written += t2p_write_pdf_stream_dict(((tsize_t)1)<<(t2p->tiff_bitspersample+1), 0, output); return(written); } -static tsize_t t2p_write_pdf_transfer_stream(T2P* t2p, TIFF* output, uint16 i){ +static +tsize_t t2p_write_pdf_transfer_stream(T2P* t2p, TIFF* output, uint16 i){ tsize_t written=0; written += t2p_write_pdf_stream( t2p->tiff_transferfunction[i], - (1<<(t2p->tiff_bitspersample+1)), + (((tsize_t)1)<<(t2p->tiff_bitspersample+1)), output); return(written); @@ -4853,10 +5106,11 @@ This function writes a PDF Image XObject Colorspace array to output. */ -static tsize_t t2p_write_pdf_xobject_calcs(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_xobject_calcs(T2P* t2p, TIFF* output){ tsize_t written=0; - char buffer[128]; + char buffer[256]; int buflen=0; float X_W=0.0; @@ -4924,19 +5178,22 @@ written += t2pWriteFile(output, (tdata_t) "<< \n", 4); if(t2p->pdf_colorspace & T2P_CS_CALGRAY){ written += t2pWriteFile(output, (tdata_t) "/WhitePoint ", 12); - buflen=sprintf(buffer, "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); + buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "/Gamma 2.2 \n", 12); } if(t2p->pdf_colorspace & T2P_CS_CALRGB){ written += t2pWriteFile(output, (tdata_t) "/WhitePoint ", 12); - buflen=sprintf(buffer, "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); + buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "/Matrix ", 8); - buflen=sprintf(buffer, "[%.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f] \n", + buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f] \n", X_R, Y_R, Z_R, X_G, Y_G, Z_G, X_B, Y_B, Z_B); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "/Gamma [2.2 2.2 2.2] \n", 22); } @@ -4949,28 +5206,32 @@ This function writes a PDF Image XObject Colorspace array to output. */ -static tsize_t t2p_write_pdf_xobject_icccs(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_xobject_icccs(T2P* t2p, TIFF* output){ tsize_t written=0; - char buffer[16]; + char buffer[32]; int buflen=0; written += t2pWriteFile(output, (tdata_t) "[/ICCBased ", 11); - buflen=sprintf(buffer, "%lu", (unsigned long)t2p->pdf_icccs); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_icccs); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " 0 R] \n", 7); return(written); } -static tsize_t t2p_write_pdf_xobject_icccs_dict(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_xobject_icccs_dict(T2P* t2p, TIFF* output){ tsize_t written=0; - char buffer[16]; + char buffer[32]; int buflen=0; written += t2pWriteFile(output, (tdata_t) "/N ", 3); - buflen=sprintf(buffer, "%u \n", t2p->tiff_samplesperpixel); + buflen=snprintf(buffer, sizeof(buffer), "%u \n", t2p->tiff_samplesperpixel); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) "/Alternate ", 11); t2p->pdf_colorspace ^= T2P_CS_ICCBASED; @@ -4981,7 +5242,8 @@ return(written); } -static tsize_t t2p_write_pdf_xobject_icccs_stream(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_xobject_icccs_stream(T2P* t2p, TIFF* output){ tsize_t written=0; @@ -4997,7 +5259,8 @@ This function writes a palette stream for an indexed color space to output. */ -static tsize_t t2p_write_pdf_xobject_palettecs_stream(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_xobject_palettecs_stream(T2P* t2p, TIFF* output){ tsize_t written=0; @@ -5013,7 +5276,8 @@ This function writes a PDF Image XObject Decode array to output. */ -static tsize_t t2p_write_pdf_xobject_decode(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_xobject_decode(T2P* t2p, TIFF* output){ tsize_t written=0; int i=0; @@ -5032,10 +5296,11 @@ output. */ -static tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t tile, T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t tile, T2P* t2p, TIFF* output){ tsize_t written=0; - char buffer[16]; + char buffer[32]; int buflen=0; if(t2p->pdf_compression==T2P_COMPRESS_NONE){ @@ -5050,42 +5315,40 @@ written += t2pWriteFile(output, (tdata_t) "<< /K -1 ", 9); if(tile==0){ written += t2pWriteFile(output, (tdata_t) "/Columns ", 9); - buflen=sprintf(buffer, "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_width); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " /Rows ", 7); - buflen=sprintf(buffer, "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_length); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); } else { if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)==0){ written += t2pWriteFile(output, (tdata_t) "/Columns ", 9); - buflen=sprintf( - buffer, - "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); } else { written += t2pWriteFile(output, (tdata_t) "/Columns ", 9); - buflen=sprintf( - buffer, - "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); } if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)==0){ written += t2pWriteFile(output, (tdata_t) " /Rows ", 7); - buflen=sprintf( - buffer, - "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); } else { written += t2pWriteFile(output, (tdata_t) " /Rows ", 7); - buflen=sprintf( - buffer, - "%lu", + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); } } @@ -5101,7 +5364,7 @@ if(t2p->tiff_photometric != PHOTOMETRIC_YCBCR) { written += t2pWriteFile(output, (tdata_t) "/DecodeParms ", 13); - written += t2pWriteFile(output, (tdata_t) "<< /ColorTransform 0 >>\n", 24); + written += t2pWriteFile(output, (tdata_t) "<< /ColorTransform 1 >>\n", 24); } break; #endif @@ -5111,21 +5374,21 @@ if(t2p->pdf_compressionquality%100){ written += t2pWriteFile(output, (tdata_t) "/DecodeParms ", 13); written += t2pWriteFile(output, (tdata_t) "<< /Predictor ", 14); - _TIFFmemset(buffer, 0x00, 16); - buflen=sprintf(buffer, "%u", t2p->pdf_compressionquality%100); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_compressionquality%100); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " /Columns ", 10); - _TIFFmemset(buffer, 0x00, 16); - buflen = sprintf(buffer, "%lu", + buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_width); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " /Colors ", 9); - _TIFFmemset(buffer, 0x00, 16); - buflen=sprintf(buffer, "%u", t2p->tiff_samplesperpixel); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->tiff_samplesperpixel); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " /BitsPerComponent ", 19); - _TIFFmemset(buffer, 0x00, 16); - buflen=sprintf(buffer, "%u", t2p->tiff_bitspersample); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->tiff_bitspersample); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) ">>\n", 3); } @@ -5142,19 +5405,21 @@ This function writes a PDF xref table to output. */ -static tsize_t t2p_write_pdf_xreftable(T2P* t2p, TIFF* output){ +static +tsize_t t2p_write_pdf_xreftable(T2P* t2p, TIFF* output){ tsize_t written=0; - char buffer[21]; + char buffer[64]; int buflen=0; uint32 i=0; written += t2pWriteFile(output, (tdata_t) "xref\n0 ", 7); - buflen=sprintf(buffer, "%lu", (unsigned long)(t2p->pdf_xrefcount + 1)); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount + 1)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); written += t2pWriteFile(output, (tdata_t) " \n0000000000 65535 f \n", 22); for (i=0;ipdf_xrefcount;i++){ - sprintf(buffer, "%.10lu 00000 n \n", + snprintf(buffer, sizeof(buffer), "%.10lu 00000 n \n", (unsigned long)t2p->pdf_xrefoffsets[i]); written += t2pWriteFile(output, (tdata_t) buffer, 20); } @@ -5166,52 +5431,40 @@ * This function writes a PDF trailer to output. */ -static tsize_t t2p_write_pdf_trailer(T2P* t2p, TIFF* output) +static +tsize_t t2p_write_pdf_trailer(T2P* t2p, TIFF* output) { tsize_t written = 0; char buffer[32]; int buflen = 0; - char fileidbuf[16]; - int i = 0; + size_t i = 0; - for (i=0; i<(int)sizeof(fileidbuf); i++) - fileidbuf[i] = (char) rand(); + for (i = 0; i < sizeof(t2p->pdf_fileid) - 8; i += 8) + snprintf(t2p->pdf_fileid + i, 9, "%.8X", rand()); - t2p->pdf_fileid = (unsigned char*)_TIFFmalloc(33); - if(t2p->pdf_fileid == NULL) { - TIFFError( - TIFF2PDF_MODULE, - "Can't allocate %u bytes of memory for t2p_write_pdf_trailer", - 33 ); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); - } - _TIFFmemset(t2p->pdf_fileid, 0x00, 33); - for (i = 0; i < 16; i++) { - sprintf((char *)t2p->pdf_fileid + 2 * i, - "%.2hhX", fileidbuf[i]); - } written += t2pWriteFile(output, (tdata_t) "trailer\n<<\n/Size ", 17); - buflen = sprintf(buffer, "%lu", (unsigned long)(t2p->pdf_xrefcount+1)); + buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount+1)); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); - _TIFFmemset(buffer, 0x00, 32); written += t2pWriteFile(output, (tdata_t) "\n/Root ", 7); - buflen=sprintf(buffer, "%lu", (unsigned long)t2p->pdf_catalog); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_catalog); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); - _TIFFmemset(buffer, 0x00, 32); written += t2pWriteFile(output, (tdata_t) " 0 R \n/Info ", 12); - buflen=sprintf(buffer, "%lu", (unsigned long)t2p->pdf_info); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_info); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); - _TIFFmemset(buffer, 0x00, 32); written += t2pWriteFile(output, (tdata_t) " 0 R \n/ID[<", 11); - written += t2pWriteFile(output, (tdata_t) t2p->pdf_fileid, 32); + written += t2pWriteFile(output, (tdata_t) t2p->pdf_fileid, + sizeof(t2p->pdf_fileid) - 1); written += t2pWriteFile(output, (tdata_t) "><", 2); - written += t2pWriteFile(output, (tdata_t) t2p->pdf_fileid, 32); + written += t2pWriteFile(output, (tdata_t) t2p->pdf_fileid, + sizeof(t2p->pdf_fileid) - 1); written += t2pWriteFile(output, (tdata_t) ">]\n>>\nstartxref\n", 16); - buflen=sprintf(buffer, "%lu", (unsigned long)t2p->pdf_startxref); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_startxref); + check_snprintf_ret(t2p, buflen, buffer); written += t2pWriteFile(output, (tdata_t) buffer, buflen); - _TIFFmemset(buffer, 0x00, 32); written += t2pWriteFile(output, (tdata_t) "\n%%EOF\n", 7); return(written); @@ -5257,7 +5510,8 @@ and TIFFClose on output. */ -static tsize_t t2p_write_pdf(T2P* t2p, TIFF* input, TIFF* output){ +static +tsize_t t2p_write_pdf(T2P* t2p, TIFF* input, TIFF* output){ tsize_t written=0; ttile_t i2=0; @@ -5266,12 +5520,13 @@ t2p_read_tiff_init(t2p, input); if(t2p->t2p_error!=T2P_ERR_OK){return(0);} - t2p->pdf_xrefoffsets= (uint32*) _TIFFmalloc(t2p->pdf_xrefcount * sizeof(uint32) ); + t2p->pdf_xrefoffsets= (uint32*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->pdf_xrefcount,sizeof(uint32)) ); if(t2p->pdf_xrefoffsets==NULL){ TIFFError( TIFF2PDF_MODULE, - "Can't allocate %lu bytes of memory for t2p_write_pdf", - t2p->pdf_xrefcount * (long)sizeof(uint32) ); + "Can't allocate %u bytes of memory for t2p_write_pdf", + (unsigned int) (t2p->pdf_xrefcount * sizeof(uint32)) ); + t2p->t2p_error = T2P_ERR_ERROR; return(written); } t2p->pdf_xrefcount=0; @@ -5328,9 +5583,9 @@ written += t2p_write_pdf_transfer_dict(t2p, output, i); written += t2p_write_pdf_stream_dict_end(output); written += t2p_write_pdf_stream_start(output); - streamlen=written; + /* streamlen=written; */ /* value not used */ written += t2p_write_pdf_transfer_stream(t2p, output, i); - streamlen=written-streamlen; + /* streamlen=written-streamlen; */ /* value not used */ written += t2p_write_pdf_stream_end(output); written += t2p_write_pdf_obj_end(output); } @@ -5343,9 +5598,9 @@ written += t2p_write_pdf_stream_dict(t2p->pdf_palettesize, 0, output); written += t2p_write_pdf_stream_dict_end(output); written += t2p_write_pdf_stream_start(output); - streamlen=written; + /* streamlen=written; */ /* value not used */ written += t2p_write_pdf_xobject_palettecs_stream(t2p, output); - streamlen=written-streamlen; + /* streamlen=written-streamlen; */ /* value not used */ written += t2p_write_pdf_stream_end(output); written += t2p_write_pdf_obj_end(output); } @@ -5357,9 +5612,9 @@ written += t2p_write_pdf_xobject_icccs_dict(t2p, output); written += t2p_write_pdf_stream_dict_end(output); written += t2p_write_pdf_stream_start(output); - streamlen=written; + /* streamlen=written; */ /* value not used */ written += t2p_write_pdf_xobject_icccs_stream(t2p, output); - streamlen=written-streamlen; + /* streamlen=written-streamlen; */ /* value not used */ written += t2p_write_pdf_stream_end(output); written += t2p_write_pdf_obj_end(output); } @@ -5420,5 +5675,13 @@ } /* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ #endif + diff -Nru djvulibre-3.5.27.1/tools/tiff2pdf.c.diff djvulibre-3.5.28/tools/tiff2pdf.c.diff --- djvulibre-3.5.27.1/tools/tiff2pdf.c.diff 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/tools/tiff2pdf.c.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,1511 +0,0 @@ ---- tiff2pdf.c.orig 2014-07-08 17:16:30.856560449 -0400 -+++ tiff2pdf.c 2014-07-08 17:16:52.260561336 -0400 -@@ -1,3 +1,26 @@ -+/* -*- C -*- -+//C- ------------------------------------------------------------------- -+//C- DjView4 -+//C- Copyright (c) 2006 Leon Bottou -+//C- -+//C- This software is subject to, and may be distributed under, the -+//C- GNU General Public License, either version 2 of the license, -+//C- or (at your option) any later version. The license should have -+//C- accompanied the software or you may obtain a copy of the license -+//C- from the Free Software Foundation at http://www.fsf.org . -+//C- -+//C- This program is distributed in the hope that it will be useful, -+//C- but WITHOUT ANY WARRANTY; without even the implied warranty of -+//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+//C- GNU General Public License for more details. -+//C- ------------------------------------------------------------------ -+// -+// The following code is derived from program "tiff2pdf" -+// whose copyright notice is reproduced below. -+// Changes were made to make it independent from the private -+// include file tiffiop.h. -+*/ -+ - /* $Id: tiff2pdf.c,v 1.37.2.7 2009-01-01 00:10:43 bfriesen Exp $ - * - * tiff2pdf - converts a TIFF image to a PDF document -@@ -24,7 +47,9 @@ - * OF THIS SOFTWARE. - */ - --#include "tif_config.h" -+#include "tiff2pdf.h" -+ -+#ifdef HAVE_TIFF2PDF - - #include - #include -@@ -40,17 +65,137 @@ - # include - #endif - --#ifdef HAVE_IO_H --# include -+#ifdef HAVE_GETOPT_H -+# include -+#endif -+ -+#if defined(__GNUC__) || defined(HAVE_LONG_LONG_INT) -+# define uint64 unsigned long long -+#elif defined(_MSC_VER) -+# define uint64 unsigned __int64 -+#else -+# define uint64 size_t - #endif - --#include "tiffiop.h" --#include "tiffio.h" -+#ifndef HAVE_GETOPT_H -+/* -+ * Copyright (c) 1987, 1993, 1994 -+ * The Regents of the University of California. All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * 3. Neither the name of the University nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -+ * SUCH DAMAGE. -+ */ -+ -+ -+static int opterr = 1, /* if error message should be printed */ -+ optind = 1, /* index into parent argv vector */ -+ optopt, /* character checked for validity */ -+ optreset; /* reset getopt */ -+static char *optarg; /* argument associated with option */ -+ -+#define BADCH (int)'?' -+#define BADARG (int)':' -+#define EMSG "" -+ -+/* -+ * getopt -- -+ * Parse argc/argv argument vector. -+ */ -+static int -+getopt(int argc, char * const argv[], const char *optstring) -+{ -+ static char *place = EMSG; /* option letter processing */ -+ char *oli; /* option letter list index */ -+ -+ if (optreset || *place == 0) { /* update scanning pointer */ -+ optreset = 0; -+ place = argv[optind]; -+ if (optind >= argc || *place++ != '-') { -+ /* Argument is absent or is not an option */ -+ place = EMSG; -+ return (-1); -+ } -+ optopt = *place++; -+ if (optopt == '-' && *place == 0) { -+ /* "--" => end of options */ -+ ++optind; -+ place = EMSG; -+ return (-1); -+ } -+ if (optopt == 0) { -+ /* Solitary '-', treat as a '-' option -+ if the program (eg su) is looking for it. */ -+ place = EMSG; -+ if (strchr(optstring, '-') == NULL) -+ return -1; -+ optopt = '-'; -+ } -+ } else -+ optopt = *place++; - --#ifndef HAVE_GETOPT --extern int getopt(int, char**, char*); -+ /* See if option letter is one the caller wanted... */ -+ if (optopt == ':' || (oli = strchr(optstring, optopt)) == NULL) { -+ if (*place == 0) -+ ++optind; -+ if (opterr && *optstring != ':') -+ (void)fprintf(stderr, -+ "unknown option -- %c\n", optopt); -+ return (BADCH); -+ } -+ -+ /* Does this option need an argument? */ -+ if (oli[1] != ':') { -+ /* don't need argument */ -+ optarg = NULL; -+ if (*place == 0) -+ ++optind; -+ } else { -+ /* Option-argument is either the rest of this argument or the -+ entire next argument. */ -+ if (*place) -+ optarg = place; -+ else if (argc > ++optind) -+ optarg = argv[optind]; -+ else { -+ /* option-argument absent */ -+ place = EMSG; -+ if (*optstring == ':') -+ return (BADARG); -+ if (opterr) -+ (void)fprintf(stderr, -+ "option requires an argument -- %c\n", -+ optopt); -+ return (BADCH); -+ } -+ place = EMSG; -+ ++optind; -+ } -+ return (optopt); /* return option letter */ -+} - #endif - -+ - #define TIFF2PDF_MODULE "tiff2pdf" - - #define PS_UNIT_SIZE 72.0F -@@ -232,8 +377,7 @@ - - /* These functions are called by main. */ - --void tiff2pdf_usage(void); --int tiff2pdf_match_paper_size(float*, float*, char*); -+static int tiff2pdf_match_paper_size(float*, float*, char*); - - /* These functions are used to generate a PDF from a TIFF. */ - -@@ -241,76 +385,76 @@ - extern "C" { - #endif - --T2P* t2p_init(void); --void t2p_validate(T2P*); --tsize_t t2p_write_pdf(T2P*, TIFF*, TIFF*); --void t2p_free(T2P*); -+static T2P* t2p_init(void); -+static void t2p_validate(T2P*); -+static tsize_t t2p_write_pdf(T2P*, TIFF*, TIFF*); -+static void t2p_free(T2P*); - - #ifdef __cplusplus - } - #endif - --void t2p_read_tiff_init(T2P*, TIFF*); --int t2p_cmp_t2p_page(const void*, const void*); --void t2p_read_tiff_data(T2P*, TIFF*); --void t2p_read_tiff_size(T2P*, TIFF*); --void t2p_read_tiff_size_tile(T2P*, TIFF*, ttile_t); --int t2p_tile_is_right_edge(T2P_TILES, ttile_t); --int t2p_tile_is_bottom_edge(T2P_TILES, ttile_t); --int t2p_tile_is_edge(T2P_TILES, ttile_t); --int t2p_tile_is_corner_edge(T2P_TILES, ttile_t); --tsize_t t2p_readwrite_pdf_image(T2P*, TIFF*, TIFF*); --tsize_t t2p_readwrite_pdf_image_tile(T2P*, TIFF*, TIFF*, ttile_t); -+static void t2p_read_tiff_init(T2P*, TIFF*); -+static int t2p_cmp_t2p_page(const void*, const void*); -+static void t2p_read_tiff_data(T2P*, TIFF*); -+static void t2p_read_tiff_size(T2P*, TIFF*); -+static void t2p_read_tiff_size_tile(T2P*, TIFF*, ttile_t); -+static int t2p_tile_is_right_edge(T2P_TILES, ttile_t); -+static int t2p_tile_is_bottom_edge(T2P_TILES, ttile_t); -+/* static int t2p_tile_is_edge(T2P_TILES, ttile_t); */ -+/* static int t2p_tile_is_corner_edge(T2P_TILES, ttile_t); */ -+static tsize_t t2p_readwrite_pdf_image(T2P*, TIFF*, TIFF*); -+static tsize_t t2p_readwrite_pdf_image_tile(T2P*, TIFF*, TIFF*, ttile_t); - #ifdef OJPEG_SUPPORT --int t2p_process_ojpeg_tables(T2P*, TIFF*); -+static int t2p_process_ojpeg_tables(T2P*, TIFF*); - #endif - #ifdef JPEG_SUPPORT --int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t*, tstrip_t, uint32); -+static int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t*, tstrip_t, uint32); - #endif --void t2p_tile_collapse_left(tdata_t, tsize_t, uint32, uint32, uint32); --void t2p_write_advance_directory(T2P*, TIFF*); --tsize_t t2p_sample_planar_separate_to_contig(T2P*, unsigned char*, unsigned char*, tsize_t); --tsize_t t2p_sample_realize_palette(T2P*, unsigned char*); --tsize_t t2p_sample_abgr_to_rgb(tdata_t, uint32); --tsize_t t2p_sample_rgba_to_rgb(tdata_t, uint32); --tsize_t t2p_sample_rgbaa_to_rgb(tdata_t, uint32); --tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t, uint32); --tsize_t t2p_write_pdf_header(T2P*, TIFF*); --tsize_t t2p_write_pdf_obj_start(uint32, TIFF*); --tsize_t t2p_write_pdf_obj_end(TIFF*); --tsize_t t2p_write_pdf_name(unsigned char*, TIFF*); --tsize_t t2p_write_pdf_string(unsigned char*, TIFF*); --tsize_t t2p_write_pdf_stream(tdata_t, tsize_t, TIFF*); --tsize_t t2p_write_pdf_stream_start(TIFF*); --tsize_t t2p_write_pdf_stream_end(TIFF*); --tsize_t t2p_write_pdf_stream_dict(tsize_t, uint32, TIFF*); --tsize_t t2p_write_pdf_stream_dict_start(TIFF*); --tsize_t t2p_write_pdf_stream_dict_end(TIFF*); --tsize_t t2p_write_pdf_stream_length(tsize_t, TIFF*); --tsize_t t2p_write_pdf_catalog(T2P*, TIFF*); --tsize_t t2p_write_pdf_info(T2P*, TIFF*, TIFF*); --void t2p_pdf_currenttime(T2P*); --void t2p_pdf_tifftime(T2P*, TIFF*); --tsize_t t2p_write_pdf_pages(T2P*, TIFF*); --tsize_t t2p_write_pdf_page(uint32, T2P*, TIFF*); --void t2p_compose_pdf_page(T2P*); --void t2p_compose_pdf_page_orient(T2P_BOX*, uint16); --void t2p_compose_pdf_page_orient_flip(T2P_BOX*, uint16); --tsize_t t2p_write_pdf_page_content(T2P*, TIFF*); --tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t, T2P*, TIFF*); --tsize_t t2p_write_pdf_xobject_cs(T2P*, TIFF*); --tsize_t t2p_write_pdf_transfer(T2P*, TIFF*); --tsize_t t2p_write_pdf_transfer_dict(T2P*, TIFF*, uint16); --tsize_t t2p_write_pdf_transfer_stream(T2P*, TIFF*, uint16); --tsize_t t2p_write_pdf_xobject_calcs(T2P*, TIFF*); --tsize_t t2p_write_pdf_xobject_icccs(T2P*, TIFF*); --tsize_t t2p_write_pdf_xobject_icccs_dict(T2P*, TIFF*); --tsize_t t2p_write_pdf_xobject_icccs_stream(T2P*, TIFF*); --tsize_t t2p_write_pdf_xobject_cs_stream(T2P*, TIFF*); --tsize_t t2p_write_pdf_xobject_decode(T2P*, TIFF*); --tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t, T2P*, TIFF*); --tsize_t t2p_write_pdf_xreftable(T2P*, TIFF*); --tsize_t t2p_write_pdf_trailer(T2P*, TIFF*); -+static void t2p_tile_collapse_left(tdata_t, tsize_t, uint32, uint32, uint32); -+static void t2p_write_advance_directory(T2P*, TIFF*); -+static tsize_t t2p_sample_planar_separate_to_contig(T2P*, unsigned char*, unsigned char*, tsize_t); -+static tsize_t t2p_sample_realize_palette(T2P*, unsigned char*); -+static tsize_t t2p_sample_abgr_to_rgb(tdata_t, uint32); -+static tsize_t t2p_sample_rgba_to_rgb(tdata_t, uint32); -+static tsize_t t2p_sample_rgbaa_to_rgb(tdata_t, uint32); -+static tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t, uint32); -+static tsize_t t2p_write_pdf_header(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_obj_start(uint32, TIFF*); -+static tsize_t t2p_write_pdf_obj_end(TIFF*); -+/* static tsize_t t2p_write_pdf_name(unsigned char*, TIFF*); */ -+static tsize_t t2p_write_pdf_string(unsigned char*, TIFF*); -+static tsize_t t2p_write_pdf_stream(tdata_t, tsize_t, TIFF*); -+static tsize_t t2p_write_pdf_stream_start(TIFF*); -+static tsize_t t2p_write_pdf_stream_end(TIFF*); -+static tsize_t t2p_write_pdf_stream_dict(tsize_t, uint32, TIFF*); -+static tsize_t t2p_write_pdf_stream_dict_start(TIFF*); -+static tsize_t t2p_write_pdf_stream_dict_end(TIFF*); -+static tsize_t t2p_write_pdf_stream_length(tsize_t, TIFF*); -+static tsize_t t2p_write_pdf_catalog(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_info(T2P*, TIFF*, TIFF*); -+static void t2p_pdf_currenttime(T2P*); -+static void t2p_pdf_tifftime(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_pages(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_page(uint32, T2P*, TIFF*); -+static void t2p_compose_pdf_page(T2P*); -+static void t2p_compose_pdf_page_orient(T2P_BOX*, uint16); -+static void t2p_compose_pdf_page_orient_flip(T2P_BOX*, uint16); -+/* static tsize_t t2p_write_pdf_page_content(T2P*, TIFF*); */ -+static tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t, T2P*, TIFF*); -+static tsize_t t2p_write_pdf_xobject_cs(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_transfer(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_transfer_dict(T2P*, TIFF*, uint16); -+static tsize_t t2p_write_pdf_transfer_stream(T2P*, TIFF*, uint16); -+static tsize_t t2p_write_pdf_xobject_calcs(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_xobject_icccs(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_xobject_icccs_dict(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_xobject_icccs_stream(T2P*, TIFF*); -+/* static tsize_t t2p_write_pdf_xobject_cs_stream(T2P*, TIFF*); */ -+static tsize_t t2p_write_pdf_xobject_decode(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t, T2P*, TIFF*); -+static tsize_t t2p_write_pdf_xreftable(T2P*, TIFF*); -+static tsize_t t2p_write_pdf_trailer(T2P*, TIFF*); - - static void - t2p_disable(TIFF *tif) -@@ -563,16 +707,17 @@ - See also libtiff.3t, tiffcp. - */ - --int main(int argc, char** argv){ -- -- extern char *optarg; -- extern int optind; -- const char *outfilename = NULL; -+int -+tiff2pdf(TIFF *input, FILE *outputfile, int argc, const char **argv) -+{ -+ char *outfilename = ""; - T2P *t2p = NULL; -- TIFF *input = NULL, *output = NULL; -+ TIFF *output = NULL; - tsize_t written = 0; - int c; - -+ (void)written; -+ - t2p = t2p_init(); - - if (t2p == NULL){ -@@ -581,7 +726,7 @@ - } - - while (argv && -- (c = getopt(argc, argv, -+ (c = getopt(argc, (void*)argv, - "o:q:u:x:y:w:l:r:p:e:c:a:t:s:k:jzndifbh")) != -1){ - switch (c) { - case 'o': -@@ -690,8 +835,8 @@ - _TIFFmalloc(strlen(optarg) + 1); - if(t2p->pdf_creator==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for main", -- strlen(optarg) + 1); -+ "Can't allocate %lu bytes of memory for main", -+ (long)strlen(optarg) + 1); - goto fail; - } - strcpy((char *)t2p->pdf_creator, optarg); -@@ -703,8 +848,8 @@ - if(t2p->pdf_author==NULL){ - TIFFError( - TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for main", -- strlen(optarg) + 1); -+ "Can't allocate %lu bytes of memory for main", -+ (long)strlen(optarg) + 1); - goto fail; - } - strcpy((char *)t2p->pdf_author, optarg); -@@ -716,8 +861,8 @@ - if(t2p->pdf_title==NULL){ - TIFFError( - TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for main", -- strlen(optarg) + 1); -+ "Can't allocate %lu bytes of memory for main", -+ (long)strlen(optarg) + 1); - goto fail; - } - strcpy((char *)t2p->pdf_title, optarg); -@@ -729,8 +874,8 @@ - if(t2p->pdf_subject==NULL){ - TIFFError( - TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for main", -- strlen(optarg)+1); -+ "Can't allocate %lu bytes of memory for main", -+ (long)strlen(optarg)+1); - goto fail; - } - strcpy((char *)t2p->pdf_subject, optarg); -@@ -742,8 +887,8 @@ - if(t2p->pdf_keywords==NULL){ - TIFFError( - TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for main", -- strlen(optarg) + 1); -+ "Can't allocate %lu bytes of memory for main", -+ (long)strlen(optarg) + 1); - goto fail; - } - strcpy((char *)t2p->pdf_keywords, optarg); -@@ -752,54 +897,14 @@ - case 'b': - t2p->pdf_image_interpolate = 1; - break; -- case 'h': -- case '?': -- tiff2pdf_usage(); -- goto success; -- break; -- } -- } -- -- /* -- * Input -- */ -- if(argc > optind) { -- input = TIFFOpen(argv[optind++], "r"); -- if (input==NULL) { -- TIFFError(TIFF2PDF_MODULE, -- "Can't open input file %s for reading", -- argv[optind-1]); -- goto fail; - } -- } else { -- TIFFError(TIFF2PDF_MODULE, "No input file specified"); -- tiff2pdf_usage(); -- goto fail; -- } -- -- if(argc > optind) { -- TIFFError(TIFF2PDF_MODULE, -- "No support for multiple input files"); -- tiff2pdf_usage(); -- goto fail; - } - - /* - * Output - */ - t2p->outputdisable = 0; -- if (outfilename) { -- t2p->outputfile = fopen(outfilename, "wb"); -- if (t2p->outputfile == NULL) { -- TIFFError(TIFF2PDF_MODULE, -- "Can't open output file %s for writing", -- outfilename); -- goto fail; -- } -- } else { -- outfilename = "-"; -- t2p->outputfile = stdout; -- } -+ t2p->outputfile = outputfile; - - output = TIFFClientOpen(outfilename, "w", (thandle_t) t2p, - t2p_readproc, t2p_writeproc, t2p_seekproc, -@@ -827,7 +932,7 @@ - goto fail; - } - --success: -+/* success: */ - if (output != NULL) - TIFFClose(output); - if (t2p != NULL) -@@ -845,50 +950,8 @@ - - } - --void tiff2pdf_usage(){ -- char* lines[]={ -- "usage: tiff2pdf [options] input.tiff", -- "options:", -- " -o: output to file name", --#ifdef JPEG_SUPPORT -- " -j: compress with JPEG", --#endif --#ifdef ZIP_SUPPORT -- " -z: compress with Zip/Deflate", --#endif -- " -q: compression quality", -- " -n: no compressed data passthrough", -- " -d: do not compress (decompress)", -- " -i: invert colors", -- " -u: set distance unit, 'i' for inch, 'm' for centimeter", -- " -x: set x resolution default in dots per unit", -- " -y: set y resolution default in dots per unit", -- " -w: width in units", -- " -l: length in units", -- " -r: 'd' for resolution default, 'o' for resolution override", -- " -p: paper size, eg \"letter\", \"legal\", \"A4\"", -- " -f: set PDF \"Fit Window\" user preference", -- " -e: date, overrides image or current date/time default, YYYYMMDDHHMMSS", -- " -c: sets document creator, overrides image software default", -- " -a: sets document author, overrides image artist default", -- " -t: sets document title, overrides image document name default", -- " -s: sets document subject, overrides image image description default", -- " -k: sets document keywords", -- " -b: set PDF \"Interpolate\" user preference", -- " -h: usage", -- NULL -- }; -- int i=0; - -- fprintf(stderr, "%s\n\n", TIFFGetVersion()); -- for (i=0;lines[i]!=NULL;i++){ -- fprintf(stderr, "%s\n", lines[i]); -- } -- -- return; --} -- --int tiff2pdf_match_paper_size(float* width, float* length, char* papersize){ -+static int tiff2pdf_match_paper_size(float* width, float* length, char* papersize){ - - size_t i, len; - const char* sizes[]={ -@@ -952,14 +1015,14 @@ - This function allocates and initializes a T2P context struct pointer. - */ - --T2P* t2p_init(){ -+static T2P* t2p_init(){ - - T2P* t2p = (T2P*) _TIFFmalloc(sizeof(T2P)); - if(t2p==NULL){ - TIFFError( - TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_init", -- sizeof(T2P)); -+ "Can't allocate %lu bytes of memory for t2p_init", -+ (long)sizeof(T2P)); - return( (T2P*) NULL ); - } - _TIFFmemset(t2p, 0x00, sizeof(T2P)); -@@ -978,7 +1041,7 @@ - This function frees a T2P context struct pointer and any allocated data fields of it. - */ - --void t2p_free(T2P* t2p){ -+static void t2p_free(T2P* t2p){ - - int i=0; - -@@ -1037,7 +1100,7 @@ - before calling t2p_write_pdf with it. - */ - --void t2p_validate(T2P* t2p){ -+static void t2p_validate(T2P* t2p){ - - #ifdef JPEG_SUPPORT - if(t2p->pdf_defaultcompression==T2P_COMPRESS_JPEG){ -@@ -1079,7 +1142,7 @@ - with the output of the PDF document as a whole. - */ - --void t2p_read_tiff_init(T2P* t2p, TIFF* input){ -+static void t2p_read_tiff_init(T2P* t2p, TIFF* input){ - - tdir_t directorycount=0; - tdir_t i=0; -@@ -1092,8 +1155,8 @@ - if(t2p->tiff_pages==NULL){ - TIFFError( - TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for tiff_pages array, %s", -- directorycount * sizeof(T2P_PAGE), -+ "Can't allocate %lu bytes of memory for tiff_pages array, %s", -+ directorycount * (long)sizeof(T2P_PAGE), - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return; -@@ -1103,8 +1166,8 @@ - if(t2p->tiff_tiles==NULL){ - TIFFError( - TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for tiff_tiles array, %s", -- directorycount * sizeof(T2P_TILES), -+ "Can't allocate %lu bytes of memory for tiff_tiles array, %s", -+ directorycount * (long)sizeof(T2P_TILES), - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return; -@@ -1236,8 +1299,8 @@ - if( t2p->tiff_tiles[i].tiles_tiles == NULL){ - TIFFError( - TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_read_tiff_init, %s", -- t2p->tiff_tiles[i].tiles_tilecount * sizeof(T2P_TILE), -+ "Can't allocate %lu bytes of memory for t2p_read_tiff_init, %s", -+ t2p->tiff_tiles[i].tiles_tilecount * (long)sizeof(T2P_TILE), - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return; -@@ -1253,7 +1316,7 @@ - * by page number. - */ - --int t2p_cmp_t2p_page(const void* e1, const void* e2){ -+static int t2p_cmp_t2p_page(const void* e1, const void* e2){ - - return( ((T2P_PAGE*)e1)->page_number - ((T2P_PAGE*)e2)->page_number ); - } -@@ -1270,7 +1333,7 @@ - requiring transcoding of the image data. - */ - --void t2p_read_tiff_data(T2P* t2p, TIFF* input){ -+static void t2p_read_tiff_data(T2P* t2p, TIFF* input){ - - int i=0; - uint16* r; -@@ -1850,7 +1913,7 @@ - uncompressed image data from the input TIFF for a page. - */ - --void t2p_read_tiff_size(T2P* t2p, TIFF* input){ -+static void t2p_read_tiff_size(T2P* t2p, TIFF* input){ - - uint32* sbc=NULL; - #if defined(JPEG_SUPPORT) || defined (OJPEG_SUPPORT) -@@ -1891,7 +1954,7 @@ - if(TIFFGetField(input, TIFFTAG_JPEGIFOFFSET, &(t2p->tiff_dataoffset))){ - if(t2p->tiff_dataoffset != 0){ - if(TIFFGetField(input, TIFFTAG_JPEGIFBYTECOUNT, &(t2p->tiff_datasize))!=0){ -- if(t2p->tiff_datasize < k) { -+ if((uint64)t2p->tiff_datasize < k) { - TIFFWarning(TIFF2PDF_MODULE, - "Input file %s has short JPEG interchange file byte count", - TIFFFileName(input)); -@@ -1984,7 +2047,7 @@ - uncompressed image data from the input TIFF for a tile of a page. - */ - --void t2p_read_tiff_size_tile(T2P* t2p, TIFF* input, ttile_t tile){ -+static void t2p_read_tiff_size_tile(T2P* t2p, TIFF* input, ttile_t tile){ - - uint32* tbc = NULL; - uint16 edge=0; -@@ -2060,7 +2123,7 @@ - * and does not have full imaged tile width. - */ - --int t2p_tile_is_right_edge(T2P_TILES tiles, ttile_t tile){ -+static int t2p_tile_is_right_edge(T2P_TILES tiles, ttile_t tile){ - - if( ((tile+1) % tiles.tiles_tilecountx == 0) - && (tiles.tiles_edgetilewidth != 0) ){ -@@ -2075,7 +2138,7 @@ - * and does not have full imaged tile length. - */ - --int t2p_tile_is_bottom_edge(T2P_TILES tiles, ttile_t tile){ -+static int t2p_tile_is_bottom_edge(T2P_TILES tiles, ttile_t tile){ - - if( ((tile+1) > (tiles.tiles_tilecount-tiles.tiles_tilecountx) ) - && (tiles.tiles_edgetilelength != 0) ){ -@@ -2086,33 +2149,12 @@ - } - - /* -- * This function returns a non-zero value when the tile is a right edge tile -- * or a bottom edge tile. -- */ -- --int t2p_tile_is_edge(T2P_TILES tiles, ttile_t tile){ -- -- return(t2p_tile_is_right_edge(tiles, tile) | t2p_tile_is_bottom_edge(tiles, tile) ); --} -- --/* -- This function returns a non-zero value when the tile is a right edge tile and a bottom -- edge tile. --*/ -- --int t2p_tile_is_corner_edge(T2P_TILES tiles, ttile_t tile){ -- -- return(t2p_tile_is_right_edge(tiles, tile) & t2p_tile_is_bottom_edge(tiles, tile) ); --} -- -- --/* - This function reads the raster image data from the input TIFF for an image and writes - the data to the output PDF XObject image dictionary stream. It returns the amount written - or zero on error. - */ - --tsize_t t2p_readwrite_pdf_image(T2P* t2p, TIFF* input, TIFF* output){ -+static tsize_t t2p_readwrite_pdf_image(T2P* t2p, TIFF* input, TIFF* output){ - - tsize_t written=0; - unsigned char* buffer=NULL; -@@ -2153,8 +2195,8 @@ - _TIFFmalloc(t2p->tiff_datasize); - if (buffer == NULL) { - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2182,8 +2224,8 @@ - memset(buffer, 0, t2p->tiff_datasize); - if(buffer == NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2209,8 +2251,8 @@ - memset(buffer, 0, t2p->tiff_datasize); - if(buffer == NULL) { - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2285,8 +2327,8 @@ - memset(buffer, 0, t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2328,8 +2370,8 @@ - memset(buffer, 0, t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2390,8 +2432,8 @@ - memset(buffer, 0, t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2428,8 +2470,8 @@ - memset(buffer, 0, t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2437,8 +2479,8 @@ - samplebuffer = (unsigned char*) _TIFFmalloc(stripsize); - if(samplebuffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2477,8 +2519,8 @@ - memset(buffer, 0, t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2510,8 +2552,8 @@ - t2p->tiff_datasize * t2p->tiff_samplesperpixel); - if(samplebuffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - _TIFFfree(buffer); -@@ -2540,8 +2582,8 @@ - t2p->tiff_width*t2p->tiff_length*4); - if(samplebuffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - _TIFFfree(buffer); -@@ -2699,7 +2741,7 @@ - * for the tile. It returns the amount written or zero on error. - */ - --tsize_t t2p_readwrite_pdf_image_tile(T2P* t2p, TIFF* input, TIFF* output, ttile_t tile){ -+static tsize_t t2p_readwrite_pdf_image_tile(T2P* t2p, TIFF* input, TIFF* output, ttile_t tile){ - - uint16 edge=0; - tsize_t written=0; -@@ -2718,6 +2760,7 @@ - float* xfloatp; - uint32 xuint32=0; - #endif -+ (void)tilesize; - - /* Fail if prior error (in particular, can't trust tiff_datasize) */ - if (t2p->t2p_error != T2P_ERR_OK) -@@ -2737,9 +2780,9 @@ - buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory " -+ "Can't allocate %lu bytes of memory " - "for t2p_readwrite_pdf_image_tile, %s", -- t2p->tiff_datasize, -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2758,9 +2801,9 @@ - buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory " -+ "Can't allocate %lu bytes of memory " - "for t2p_readwrite_pdf_image_tile, %s", -- t2p->tiff_datasize, -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2787,9 +2830,9 @@ - buffer=(unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory " -+ "Can't allocate %lu bytes of memory " - "for t2p_readwrite_pdf_image, %s", -- t2p->tiff_datasize, -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2828,9 +2871,9 @@ - buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory " -+ "Can't allocate %lu bytes of memory " - "for t2p_readwrite_pdf_image_tile, %s", -- t2p->tiff_datasize, -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2871,9 +2914,9 @@ - buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for " -+ "Can't allocate %lu bytes of memory for " - "t2p_readwrite_pdf_image_tile, %s", -- t2p->tiff_datasize, -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2904,9 +2947,9 @@ - buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory " -+ "Can't allocate %lu bytes of memory " - "for t2p_readwrite_pdf_image_tile, %s", -- t2p->tiff_datasize, -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2914,9 +2957,9 @@ - samplebuffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - if(samplebuffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory " -+ "Can't allocate %lu bytes of memory " - "for t2p_readwrite_pdf_image_tile, %s", -- t2p->tiff_datasize, -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -2953,9 +2996,9 @@ - buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); - if(buffer==NULL){ - TIFFError(TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory " -+ "Can't allocate %lu bytes of memory " - "for t2p_readwrite_pdf_image_tile, %s", -- t2p->tiff_datasize, -+ (unsigned long)t2p->tiff_datasize, - TIFFFileName(input)); - t2p->t2p_error = T2P_ERR_ERROR; - return(0); -@@ -3140,7 +3183,7 @@ - } - - #ifdef OJPEG_SUPPORT --int t2p_process_ojpeg_tables(T2P* t2p, TIFF* input){ -+static int t2p_process_ojpeg_tables(T2P* t2p, TIFF* input){ - uint16 proc=0; - void* q; - uint32 q_length=0; -@@ -3384,7 +3427,7 @@ - #endif - - #ifdef JPEG_SUPPORT --int t2p_process_jpeg_strip( -+static int t2p_process_jpeg_strip( - unsigned char* strip, - tsize_t* striplength, - unsigned char* buffer, -@@ -3477,7 +3520,7 @@ - This functions converts a tilewidth x tilelength buffer of samples into an edgetilewidth x - tilelength buffer of samples. - */ --void t2p_tile_collapse_left( -+static void t2p_tile_collapse_left( - tdata_t buffer, - tsize_t scanwidth, - uint32 tilewidth, -@@ -3488,7 +3531,7 @@ - tsize_t edgescanwidth=0; - - edgescanwidth = (scanwidth * edgetilewidth + (tilewidth - 1))/ tilewidth; -- for(i=i;i126) { -- namelen=126; -- } -- written += t2pWriteFile(output, (tdata_t) "/", 1); -- for (i=0;i 0x7E){ -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- nextchar=1; -- } -- if (nextchar==0){ -- switch (name[i]){ -- case 0x23: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x25: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x28: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x29: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x2F: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x3C: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x3E: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x5B: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x5D: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x7B: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- case 0x7D: -- sprintf(buffer, "#%.2X", name[i]); -- buffer[sizeof(buffer) - 1] = '\0'; -- written += t2pWriteFile(output, (tdata_t) buffer, 3); -- break; -- default: -- written += t2pWriteFile(output, (tdata_t) &name[i], 1); -- } -- } -- nextchar=0; -- } -- written += t2pWriteFile(output, (tdata_t) " ", 1); -- -- return(written); --} -- --/* - This function writes a PDF string object to output. - */ - --tsize_t t2p_write_pdf_string(unsigned char* pdfstr, TIFF* output){ -+static tsize_t t2p_write_pdf_string(unsigned char* pdfstr, TIFF* output){ - - tsize_t written = 0; - uint32 i = 0; -@@ -3853,7 +3797,7 @@ - This function writes a buffer of data to output. - */ - --tsize_t t2p_write_pdf_stream(tdata_t buffer, tsize_t len, TIFF* output){ -+static tsize_t t2p_write_pdf_stream(tdata_t buffer, tsize_t len, TIFF* output){ - - tsize_t written=0; - -@@ -3866,7 +3810,7 @@ - This functions writes the beginning of a PDF stream to output. - */ - --tsize_t t2p_write_pdf_stream_start(TIFF* output){ -+static tsize_t t2p_write_pdf_stream_start(TIFF* output){ - - tsize_t written=0; - -@@ -3879,7 +3823,7 @@ - This function writes the end of a PDF stream to output. - */ - --tsize_t t2p_write_pdf_stream_end(TIFF* output){ -+static tsize_t t2p_write_pdf_stream_end(TIFF* output){ - - tsize_t written=0; - -@@ -3892,7 +3836,7 @@ - This function writes a stream dictionary for a PDF stream to output. - */ - --tsize_t t2p_write_pdf_stream_dict(tsize_t len, uint32 number, TIFF* output){ -+static tsize_t t2p_write_pdf_stream_dict(tsize_t len, uint32 number, TIFF* output){ - - tsize_t written=0; - char buffer[16]; -@@ -3914,7 +3858,7 @@ - This functions writes the beginning of a PDF stream dictionary to output. - */ - --tsize_t t2p_write_pdf_stream_dict_start(TIFF* output){ -+static tsize_t t2p_write_pdf_stream_dict_start(TIFF* output){ - - tsize_t written=0; - -@@ -3927,7 +3871,7 @@ - This function writes the end of a PDF stream dictionary to output. - */ - --tsize_t t2p_write_pdf_stream_dict_end(TIFF* output){ -+static tsize_t t2p_write_pdf_stream_dict_end(TIFF* output){ - - tsize_t written=0; - -@@ -3940,7 +3884,7 @@ - This function writes a number to output. - */ - --tsize_t t2p_write_pdf_stream_length(tsize_t len, TIFF* output){ -+static tsize_t t2p_write_pdf_stream_length(tsize_t len, TIFF* output){ - - tsize_t written=0; - char buffer[16]; -@@ -3957,7 +3901,7 @@ - This function writes the PDF Catalog structure to output. - */ - --tsize_t t2p_write_pdf_catalog(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_catalog(T2P* t2p, TIFF* output){ - - tsize_t written=0; - char buffer[16]; -@@ -3983,13 +3927,15 @@ - This function writes the PDF Info structure to output. - */ - --tsize_t t2p_write_pdf_info(T2P* t2p, TIFF* input, TIFF* output){ -+static tsize_t t2p_write_pdf_info(T2P* t2p, TIFF* input, TIFF* output){ - - tsize_t written = 0; - unsigned char* info; - char buffer[512]; - int buflen = 0; - -+ (void) buflen; -+ - if(t2p->pdf_datetime==NULL){ - t2p_pdf_tifftime(t2p, input); - } -@@ -4107,7 +4053,7 @@ - * date string, it is called by t2p_pdf_tifftime. - */ - --void t2p_pdf_currenttime(T2P* t2p) -+static void t2p_pdf_currenttime(T2P* t2p) - { - - struct tm* currenttime; -@@ -4131,7 +4077,7 @@ - * TIFF file if it exists or the current time as a PDF date string. - */ - --void t2p_pdf_tifftime(T2P* t2p, TIFF* input){ -+static void t2p_pdf_tifftime(T2P* t2p, TIFF* input){ - - char* datetime; - -@@ -4172,7 +4118,7 @@ - * This function writes a PDF Pages Tree structure to output. - */ - --tsize_t t2p_write_pdf_pages(T2P* t2p, TIFF* output) -+static tsize_t t2p_write_pdf_pages(T2P* t2p, TIFF* output) - { - tsize_t written=0; - tdir_t i=0; -@@ -4211,7 +4157,7 @@ - This function writes a PDF Page structure to output. - */ - --tsize_t t2p_write_pdf_page(uint32 object, T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_page(uint32 object, T2P* t2p, TIFF* output){ - - unsigned int i=0; - tsize_t written=0; -@@ -4306,7 +4252,7 @@ - This function composes the page size and image and tile locations on a page. - */ - --void t2p_compose_pdf_page(T2P* t2p){ -+static void t2p_compose_pdf_page(T2P* t2p){ - - uint32 i=0; - uint32 i2=0; -@@ -4493,7 +4439,7 @@ - return; - } - --void t2p_compose_pdf_page_orient(T2P_BOX* boxp, uint16 orientation){ -+static void t2p_compose_pdf_page_orient(T2P_BOX* boxp, uint16 orientation){ - - float m1[9]; - float f=0.0; -@@ -4568,7 +4514,7 @@ - return; - } - --void t2p_compose_pdf_page_orient_flip(T2P_BOX* boxp, uint16 orientation){ -+static void t2p_compose_pdf_page_orient_flip(T2P_BOX* boxp, uint16 orientation){ - - float m1[9]; - float f=0.0; -@@ -4630,7 +4576,7 @@ - This function writes a PDF Contents stream to output. - */ - --tsize_t t2p_write_pdf_page_content_stream(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_page_content_stream(T2P* t2p, TIFF* output){ - - tsize_t written=0; - ttile_t i=0; -@@ -4676,7 +4622,7 @@ - This function writes a PDF Image XObject stream dictionary to output. - */ - --tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t tile, -+static tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t tile, - T2P* t2p, - TIFF* output){ - -@@ -4758,7 +4704,7 @@ - */ - - --tsize_t t2p_write_pdf_xobject_cs(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_xobject_cs(T2P* t2p, TIFF* output){ - - tsize_t written=0; - char buffer[128]; -@@ -4839,7 +4785,7 @@ - return(written); - } - --tsize_t t2p_write_pdf_transfer(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_transfer(T2P* t2p, TIFF* output){ - - tsize_t written=0; - char buffer[16]; -@@ -4873,7 +4819,7 @@ - return(written); - } - --tsize_t t2p_write_pdf_transfer_dict(T2P* t2p, TIFF* output, uint16 i){ -+static tsize_t t2p_write_pdf_transfer_dict(T2P* t2p, TIFF* output, uint16 i){ - - tsize_t written=0; - char buffer[32]; -@@ -4891,7 +4837,7 @@ - return(written); - } - --tsize_t t2p_write_pdf_transfer_stream(T2P* t2p, TIFF* output, uint16 i){ -+static tsize_t t2p_write_pdf_transfer_stream(T2P* t2p, TIFF* output, uint16 i){ - - tsize_t written=0; - -@@ -4907,7 +4853,7 @@ - This function writes a PDF Image XObject Colorspace array to output. - */ - --tsize_t t2p_write_pdf_xobject_calcs(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_xobject_calcs(T2P* t2p, TIFF* output){ - - tsize_t written=0; - char buffer[128]; -@@ -5003,7 +4949,7 @@ - This function writes a PDF Image XObject Colorspace array to output. - */ - --tsize_t t2p_write_pdf_xobject_icccs(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_xobject_icccs(T2P* t2p, TIFF* output){ - - tsize_t written=0; - char buffer[16]; -@@ -5017,7 +4963,7 @@ - return(written); - } - --tsize_t t2p_write_pdf_xobject_icccs_dict(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_xobject_icccs_dict(T2P* t2p, TIFF* output){ - - tsize_t written=0; - char buffer[16]; -@@ -5035,7 +4981,7 @@ - return(written); - } - --tsize_t t2p_write_pdf_xobject_icccs_stream(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_xobject_icccs_stream(T2P* t2p, TIFF* output){ - - tsize_t written=0; - -@@ -5051,7 +4997,7 @@ - This function writes a palette stream for an indexed color space to output. - */ - --tsize_t t2p_write_pdf_xobject_palettecs_stream(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_xobject_palettecs_stream(T2P* t2p, TIFF* output){ - - tsize_t written=0; - -@@ -5067,7 +5013,7 @@ - This function writes a PDF Image XObject Decode array to output. - */ - --tsize_t t2p_write_pdf_xobject_decode(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_xobject_decode(T2P* t2p, TIFF* output){ - - tsize_t written=0; - int i=0; -@@ -5086,7 +5032,7 @@ - output. - */ - --tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t tile, T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t tile, T2P* t2p, TIFF* output){ - - tsize_t written=0; - char buffer[16]; -@@ -5196,7 +5142,7 @@ - This function writes a PDF xref table to output. - */ - --tsize_t t2p_write_pdf_xreftable(T2P* t2p, TIFF* output){ -+static tsize_t t2p_write_pdf_xreftable(T2P* t2p, TIFF* output){ - - tsize_t written=0; - char buffer[21]; -@@ -5220,7 +5166,7 @@ - * This function writes a PDF trailer to output. - */ - --tsize_t t2p_write_pdf_trailer(T2P* t2p, TIFF* output) -+static tsize_t t2p_write_pdf_trailer(T2P* t2p, TIFF* output) - { - - tsize_t written = 0; -@@ -5229,10 +5175,9 @@ - char fileidbuf[16]; - int i = 0; - -- ((int*)fileidbuf)[0] = rand(); -- ((int*)fileidbuf)[1] = rand(); -- ((int*)fileidbuf)[2] = rand(); -- ((int*)fileidbuf)[3] = rand(); -+ for (i=0; i<(int)sizeof(fileidbuf); i++) -+ fileidbuf[i] = (char) rand(); -+ - t2p->pdf_fileid = (unsigned char*)_TIFFmalloc(33); - if(t2p->pdf_fileid == NULL) { - TIFFError( -@@ -5312,7 +5257,7 @@ - and TIFFClose on output. - */ - --tsize_t t2p_write_pdf(T2P* t2p, TIFF* input, TIFF* output){ -+static tsize_t t2p_write_pdf(T2P* t2p, TIFF* input, TIFF* output){ - - tsize_t written=0; - ttile_t i2=0; -@@ -5325,8 +5270,8 @@ - if(t2p->pdf_xrefoffsets==NULL){ - TIFFError( - TIFF2PDF_MODULE, -- "Can't allocate %u bytes of memory for t2p_write_pdf", -- t2p->pdf_xrefcount * sizeof(uint32) ); -+ "Can't allocate %lu bytes of memory for t2p_write_pdf", -+ t2p->pdf_xrefcount * (long)sizeof(uint32) ); - return(written); - } - t2p->pdf_xrefcount=0; -@@ -5475,3 +5420,5 @@ - } - - /* vim: set ts=8 sts=8 sw=8 noet: */ -+ -+#endif diff -Nru djvulibre-3.5.27.1/tools/tiff2pdf.c.LIBTIFF djvulibre-3.5.28/tools/tiff2pdf.c.LIBTIFF --- djvulibre-3.5.27.1/tools/tiff2pdf.c.LIBTIFF 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/tools/tiff2pdf.c.LIBTIFF 2020-11-20 16:57:32.000000000 +0000 @@ -0,0 +1,5594 @@ +/* $Id: tiff2pdf.c,v 1.103 2017-10-29 18:50:41 bfriesen Exp $ + * + * tiff2pdf - converts a TIFF image to a PDF document + * + * Copyright (c) 2003 Ross Finlayson + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the name of + * Ross Finlayson may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Ross Finlayson. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL ROSS FINLAYSON BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "tif_config.h" + +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_UNISTD_H +# include +#endif + +#ifdef HAVE_FCNTL_H +# include +#endif + +#ifdef HAVE_IO_H +# include +#endif + +#ifdef NEED_LIBPORT +# include "libport.h" +#endif + +#include "tiffiop.h" +#include "tiffio.h" + +#ifndef HAVE_GETOPT +extern int getopt(int, char**, char*); +#endif + +#ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +#endif +#ifndef EXIT_FAILURE +# define EXIT_FAILURE 1 +#endif + +#define TIFF2PDF_MODULE "tiff2pdf" + +#define PS_UNIT_SIZE 72.0F + +/* This type is of PDF color spaces. */ +typedef enum { + T2P_CS_BILEVEL = 0x01, /* Bilevel, black and white */ + T2P_CS_GRAY = 0x02, /* Single channel */ + T2P_CS_RGB = 0x04, /* Three channel tristimulus RGB */ + T2P_CS_CMYK = 0x08, /* Four channel CMYK print inkset */ + T2P_CS_LAB = 0x10, /* Three channel L*a*b* color space */ + T2P_CS_PALETTE = 0x1000,/* One of the above with a color map */ + T2P_CS_CALGRAY = 0x20, /* Calibrated single channel */ + T2P_CS_CALRGB = 0x40, /* Calibrated three channel tristimulus RGB */ + T2P_CS_ICCBASED = 0x80 /* ICC profile color specification */ +} t2p_cs_t; + +/* This type is of PDF compression types. */ +typedef enum{ + T2P_COMPRESS_NONE=0x00 +#ifdef CCITT_SUPPORT + , T2P_COMPRESS_G4=0x01 +#endif +#if defined(JPEG_SUPPORT) || defined(OJPEG_SUPPORT) + , T2P_COMPRESS_JPEG=0x02 +#endif +#ifdef ZIP_SUPPORT + , T2P_COMPRESS_ZIP=0x04 +#endif +} t2p_compress_t; + +/* This type is whether TIFF image data can be used in PDF without transcoding. */ +typedef enum{ + T2P_TRANSCODE_RAW=0x01, /* The raw data from the input can be used without recompressing */ + T2P_TRANSCODE_ENCODE=0x02 /* The data from the input is perhaps unencoded and reencoded */ +} t2p_transcode_t; + +/* This type is of information about the data samples of the input image. */ +typedef enum{ + T2P_SAMPLE_NOTHING=0x0000, /* The unencoded samples are normal for the output colorspace */ + T2P_SAMPLE_ABGR_TO_RGB=0x0001, /* The unencoded samples are the result of ReadRGBAImage */ + T2P_SAMPLE_RGBA_TO_RGB=0x0002, /* The unencoded samples are contiguous RGBA */ + T2P_SAMPLE_RGBAA_TO_RGB=0x0004, /* The unencoded samples are RGBA with premultiplied alpha */ + T2P_SAMPLE_YCBCR_TO_RGB=0x0008, + T2P_SAMPLE_YCBCR_TO_LAB=0x0010, + T2P_SAMPLE_REALIZE_PALETTE=0x0020, /* The unencoded samples are indexes into the color map */ + T2P_SAMPLE_SIGNED_TO_UNSIGNED=0x0040, /* The unencoded samples are signed instead of unsignd */ + T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED=0x0040, /* The L*a*b* samples have a* and b* signed */ + T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG=0x0100 /* The unencoded samples are separate instead of contiguous */ +} t2p_sample_t; + +/* This type is of error status of the T2P struct. */ +typedef enum{ + T2P_ERR_OK = 0, /* This is the value of t2p->t2p_error when there is no error */ + T2P_ERR_ERROR = 1 /* This is the value of t2p->t2p_error when there was an error */ +} t2p_err_t; + +/* This struct defines a logical page of a TIFF. */ +typedef struct { + tdir_t page_directory; + uint32 page_number; + ttile_t page_tilecount; + uint32 page_extra; +} T2P_PAGE; + +/* This struct defines a PDF rectangle's coordinates. */ +typedef struct { + float x1; + float y1; + float x2; + float y2; + float mat[9]; +} T2P_BOX; + +/* This struct defines a tile of a PDF. */ +typedef struct { + T2P_BOX tile_box; +} T2P_TILE; + +/* This struct defines information about the tiles on a PDF page. */ +typedef struct { + ttile_t tiles_tilecount; + uint32 tiles_tilewidth; + uint32 tiles_tilelength; + uint32 tiles_tilecountx; + uint32 tiles_tilecounty; + uint32 tiles_edgetilewidth; + uint32 tiles_edgetilelength; + T2P_TILE* tiles_tiles; +} T2P_TILES; + +/* This struct is the context of a function to generate PDF from a TIFF. */ +typedef struct { + t2p_err_t t2p_error; + T2P_PAGE* tiff_pages; + T2P_TILES* tiff_tiles; + tdir_t tiff_pagecount; + uint16 tiff_compression; + uint16 tiff_photometric; + uint16 tiff_fillorder; + uint16 tiff_bitspersample; + uint16 tiff_samplesperpixel; + uint16 tiff_planar; + uint32 tiff_width; + uint32 tiff_length; + float tiff_xres; + float tiff_yres; + uint16 tiff_orientation; + toff_t tiff_dataoffset; + tsize_t tiff_datasize; + uint16 tiff_resunit; + uint16 pdf_centimeters; + uint16 pdf_overrideres; + uint16 pdf_overridepagesize; + float pdf_defaultxres; + float pdf_defaultyres; + float pdf_xres; + float pdf_yres; + float pdf_defaultpagewidth; + float pdf_defaultpagelength; + float pdf_pagewidth; + float pdf_pagelength; + float pdf_imagewidth; + float pdf_imagelength; + int pdf_image_fillpage; /* 0 (default: no scaling, 1:scale imagesize to pagesize */ + T2P_BOX pdf_mediabox; + T2P_BOX pdf_imagebox; + uint16 pdf_majorversion; + uint16 pdf_minorversion; + uint32 pdf_catalog; + uint32 pdf_pages; + uint32 pdf_info; + uint32 pdf_palettecs; + uint16 pdf_fitwindow; + uint32 pdf_startxref; +#define TIFF2PDF_FILEID_SIZE 33 + char pdf_fileid[TIFF2PDF_FILEID_SIZE]; +#define TIFF2PDF_DATETIME_SIZE 17 + char pdf_datetime[TIFF2PDF_DATETIME_SIZE]; +#define TIFF2PDF_CREATOR_SIZE 512 + char pdf_creator[TIFF2PDF_CREATOR_SIZE]; +#define TIFF2PDF_AUTHOR_SIZE 512 + char pdf_author[TIFF2PDF_AUTHOR_SIZE]; +#define TIFF2PDF_TITLE_SIZE 512 + char pdf_title[TIFF2PDF_TITLE_SIZE]; +#define TIFF2PDF_SUBJECT_SIZE 512 + char pdf_subject[TIFF2PDF_SUBJECT_SIZE]; +#define TIFF2PDF_KEYWORDS_SIZE 512 + char pdf_keywords[TIFF2PDF_KEYWORDS_SIZE]; + t2p_cs_t pdf_colorspace; + uint16 pdf_colorspace_invert; + uint16 pdf_switchdecode; + uint16 pdf_palettesize; + unsigned char* pdf_palette; + int pdf_labrange[4]; + t2p_compress_t pdf_defaultcompression; + uint16 pdf_defaultcompressionquality; + t2p_compress_t pdf_compression; + uint16 pdf_compressionquality; + uint16 pdf_nopassthrough; + t2p_transcode_t pdf_transcode; + t2p_sample_t pdf_sample; + uint32* pdf_xrefoffsets; + uint32 pdf_xrefcount; + tdir_t pdf_page; +#ifdef OJPEG_SUPPORT + tdata_t pdf_ojpegdata; + uint32 pdf_ojpegdatalength; + uint32 pdf_ojpegiflength; +#endif + float tiff_whitechromaticities[2]; + float tiff_primarychromaticities[6]; + float tiff_referenceblackwhite[2]; + float* tiff_transferfunction[3]; + int pdf_image_interpolate; /* 0 (default) : do not interpolate, + 1 : interpolate */ + uint16 tiff_transferfunctioncount; + uint32 pdf_icccs; + uint32 tiff_iccprofilelength; + tdata_t tiff_iccprofile; + + /* fields for custom read/write procedures */ + FILE *outputfile; + int outputdisable; + tsize_t outputwritten; +} T2P; + +/* These functions are called by main. */ + +void tiff2pdf_usage(void); +int tiff2pdf_match_paper_size(float*, float*, char*); + +/* These functions are used to generate a PDF from a TIFF. */ + +#ifdef __cplusplus +extern "C" { +#endif + +T2P* t2p_init(void); +void t2p_validate(T2P*); +tsize_t t2p_write_pdf(T2P*, TIFF*, TIFF*); +void t2p_free(T2P*); + +#ifdef __cplusplus +} +#endif + +void t2p_read_tiff_init(T2P*, TIFF*); +int t2p_cmp_t2p_page(const void*, const void*); +void t2p_read_tiff_data(T2P*, TIFF*); +void t2p_read_tiff_size(T2P*, TIFF*); +void t2p_read_tiff_size_tile(T2P*, TIFF*, ttile_t); +int t2p_tile_is_right_edge(T2P_TILES, ttile_t); +int t2p_tile_is_bottom_edge(T2P_TILES, ttile_t); +int t2p_tile_is_edge(T2P_TILES, ttile_t); +int t2p_tile_is_corner_edge(T2P_TILES, ttile_t); +tsize_t t2p_readwrite_pdf_image(T2P*, TIFF*, TIFF*); +tsize_t t2p_readwrite_pdf_image_tile(T2P*, TIFF*, TIFF*, ttile_t); +#ifdef OJPEG_SUPPORT +int t2p_process_ojpeg_tables(T2P*, TIFF*); +#endif +#ifdef JPEG_SUPPORT +int t2p_process_jpeg_strip(unsigned char*, tsize_t*, unsigned char*, tsize_t, tsize_t*, tstrip_t, uint32); +#endif +void t2p_tile_collapse_left(tdata_t, tsize_t, uint32, uint32, uint32); +void t2p_write_advance_directory(T2P*, TIFF*); +tsize_t t2p_sample_planar_separate_to_contig(T2P*, unsigned char*, unsigned char*, tsize_t); +tsize_t t2p_sample_realize_palette(T2P*, unsigned char*); +tsize_t t2p_sample_abgr_to_rgb(tdata_t, uint32); +tsize_t t2p_sample_rgba_to_rgb(tdata_t, uint32); +tsize_t t2p_sample_rgbaa_to_rgb(tdata_t, uint32); +tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t, uint32); +tsize_t t2p_write_pdf_header(T2P*, TIFF*); +tsize_t t2p_write_pdf_obj_start(uint32, TIFF*); +tsize_t t2p_write_pdf_obj_end(TIFF*); +tsize_t t2p_write_pdf_name(unsigned char*, TIFF*); +tsize_t t2p_write_pdf_string(char*, TIFF*); +tsize_t t2p_write_pdf_stream(tdata_t, tsize_t, TIFF*); +tsize_t t2p_write_pdf_stream_start(TIFF*); +tsize_t t2p_write_pdf_stream_end(TIFF*); +tsize_t t2p_write_pdf_stream_dict(tsize_t, uint32, TIFF*); +tsize_t t2p_write_pdf_stream_dict_start(TIFF*); +tsize_t t2p_write_pdf_stream_dict_end(TIFF*); +tsize_t t2p_write_pdf_stream_length(tsize_t, TIFF*); +tsize_t t2p_write_pdf_catalog(T2P*, TIFF*); +tsize_t t2p_write_pdf_info(T2P*, TIFF*, TIFF*); +void t2p_pdf_currenttime(T2P*); +void t2p_pdf_tifftime(T2P*, TIFF*); +tsize_t t2p_write_pdf_pages(T2P*, TIFF*); +tsize_t t2p_write_pdf_page(uint32, T2P*, TIFF*); +void t2p_compose_pdf_page(T2P*); +void t2p_compose_pdf_page_orient(T2P_BOX*, uint16); +void t2p_compose_pdf_page_orient_flip(T2P_BOX*, uint16); +tsize_t t2p_write_pdf_page_content(T2P*, TIFF*); +tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t, T2P*, TIFF*); +tsize_t t2p_write_pdf_xobject_cs(T2P*, TIFF*); +tsize_t t2p_write_pdf_transfer(T2P*, TIFF*); +tsize_t t2p_write_pdf_transfer_dict(T2P*, TIFF*, uint16); +tsize_t t2p_write_pdf_transfer_stream(T2P*, TIFF*, uint16); +tsize_t t2p_write_pdf_xobject_calcs(T2P*, TIFF*); +tsize_t t2p_write_pdf_xobject_icccs(T2P*, TIFF*); +tsize_t t2p_write_pdf_xobject_icccs_dict(T2P*, TIFF*); +tsize_t t2p_write_pdf_xobject_icccs_stream(T2P*, TIFF*); +tsize_t t2p_write_pdf_xobject_cs_stream(T2P*, TIFF*); +tsize_t t2p_write_pdf_xobject_decode(T2P*, TIFF*); +tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t, T2P*, TIFF*); +tsize_t t2p_write_pdf_xreftable(T2P*, TIFF*); +tsize_t t2p_write_pdf_trailer(T2P*, TIFF*); + +#define check_snprintf_ret(t2p, rv, buf) do { \ + if ((rv) < 0) rv = 0; \ + else if((rv) >= (int)sizeof(buf)) (rv) = sizeof(buf) - 1; \ + else break; \ + if ((t2p) != NULL) (t2p)->t2p_error = T2P_ERR_ERROR; \ +} while(0) + +static void +t2p_disable(TIFF *tif) +{ + T2P *t2p = (T2P*) TIFFClientdata(tif); + t2p->outputdisable = 1; +} + +static void +t2p_enable(TIFF *tif) +{ + T2P *t2p = (T2P*) TIFFClientdata(tif); + t2p->outputdisable = 0; +} + +/* + * Procs for TIFFClientOpen + */ + +#ifdef OJPEG_SUPPORT +static tmsize_t +t2pReadFile(TIFF *tif, tdata_t data, tmsize_t size) +{ + thandle_t client = TIFFClientdata(tif); + TIFFReadWriteProc proc = TIFFGetReadProc(tif); + if (proc) + return proc(client, data, size); + return -1; +} +#endif /* OJPEG_SUPPORT */ + +static tmsize_t +t2pWriteFile(TIFF *tif, tdata_t data, tmsize_t size) +{ + thandle_t client = TIFFClientdata(tif); + TIFFReadWriteProc proc = TIFFGetWriteProc(tif); + if (proc) + return proc(client, data, size); + return -1; +} + +static uint64 +t2pSeekFile(TIFF *tif, toff_t offset, int whence) +{ + thandle_t client = TIFFClientdata(tif); + TIFFSeekProc proc = TIFFGetSeekProc(tif); + if (proc) + return proc(client, offset, whence); + return -1; +} + +static tmsize_t +t2p_readproc(thandle_t handle, tdata_t data, tmsize_t size) +{ + (void) handle, (void) data, (void) size; + return -1; +} + +static tmsize_t +t2p_writeproc(thandle_t handle, tdata_t data, tmsize_t size) +{ + T2P *t2p = (T2P*) handle; + if (t2p->outputdisable <= 0 && t2p->outputfile) { + tsize_t written = fwrite(data, 1, size, t2p->outputfile); + t2p->outputwritten += written; + return written; + } + return size; +} + +static uint64 +t2p_seekproc(thandle_t handle, uint64 offset, int whence) +{ + T2P *t2p = (T2P*) handle; + if (t2p->outputdisable <= 0 && t2p->outputfile) + return _TIFF_fseek_f(t2p->outputfile, (_TIFF_off_t) offset, whence); + return offset; +} + +static int +t2p_closeproc(thandle_t handle) +{ + T2P *t2p = (T2P*) handle; + return fclose(t2p->outputfile); +} + +static uint64 +t2p_sizeproc(thandle_t handle) +{ + (void) handle; + return -1; +} + +static int +t2p_mapproc(thandle_t handle, void **data, toff_t *offset) +{ + (void) handle, (void) data, (void) offset; + return -1; +} + +static void +t2p_unmapproc(thandle_t handle, void *data, toff_t offset) +{ + (void) handle, (void) data, (void) offset; +} + +#if defined(OJPEG_SUPPORT) || defined(JPEG_SUPPORT) +static uint64 +checkAdd64(uint64 summand1, uint64 summand2, T2P* t2p) +{ + uint64 bytes = summand1 + summand2; + + if (bytes < summand1) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + bytes = 0; + } + + return bytes; +} +#endif /* defined(OJPEG_SUPPORT) || defined(JPEG_SUPPORT) */ + +static uint64 +checkMultiply64(uint64 first, uint64 second, T2P* t2p) +{ + uint64 bytes = first * second; + + if (second && bytes / second != first) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + bytes = 0; + } + + return bytes; +} + +/* + + This is the main function. + + The program converts one TIFF file to one PDF file, including multiple page + TIFF files, tiled TIFF files, black and white. grayscale, and color TIFF + files that contain data of TIFF photometric interpretations of bilevel, + grayscale, RGB, YCbCr, CMYK separation, and ICC L*a*b* as supported by + libtiff and PDF. + + If you have multiple TIFF files to convert into one PDF file then use tiffcp + or other program to concatenate the files into a multiple page TIFF file. + If the input TIFF file is of huge dimensions (greater than 10000 pixels height + or width) convert the input image to a tiled TIFF if it is not already. + + The standard output is standard output. Set the output file name with the + "-o output.pdf" option. + + All black and white files are compressed into a single strip CCITT G4 Fax + compressed PDF, unless tiled, where tiled black and white images are + compressed into tiled CCITT G4 Fax compressed PDF, libtiff CCITT support + is assumed. + + Color and grayscale data can be compressed using either JPEG compression, + ITU-T T.81, or Zip/Deflate LZ77 compression, per PNG 1.2 and RFC 1951. Set + the compression type using the -j or -z options. JPEG compression support + requires that libtiff be configured with JPEG support, and Zip/Deflate + compression support requires that libtiff is configured with Zip support, + in tiffconf.h. Use only one or the other of -j and -z. The -q option + sets the image compression quality, that is 1-100 with libjpeg JPEG + compression and one of 1, 10, 11, 12, 13, 14, or 15 for PNG group compression + predictor methods, add 100, 200, ..., 900 to set zlib compression quality 1-9. + PNG Group differencing predictor methods are not currently implemented. + + If the input TIFF contains single strip CCITT G4 Fax compressed information, + then that is written to the PDF file without transcoding, unless the options + of no compression and no passthrough are set, -d and -n. + + If the input TIFF contains JPEG or single strip Zip/Deflate compressed + information, and they are configured, then that is written to the PDF file + without transcoding, unless the options of no compression and no passthrough + are set. + + The default page size upon which the TIFF image is placed is determined by + the resolution and extent of the image data. Default values for the TIFF + image resolution can be set using the -x and -y options. The page size can + be set using the -p option for paper size, or -w and -l for paper width and + length, then each page of the TIFF image is centered on its page. The + distance unit for default resolution and page width and length can be set + by the -u option, the default unit is inch. + + Various items of the output document information can be set with the -e, -c, + -a, -t, -s, and -k tags. Setting the argument of the option to "" for these + tags causes the relevant document information field to be not written. Some + of the document information values otherwise get their information from the + input TIFF image, the software, author, document name, and image description. + + The output PDF file conforms to the PDF 1.1 specification or PDF 1.2 if using + Zip/Deflate compression. + + The Portable Document Format (PDF) specification is copyrighted by Adobe + Systems, Incorporated. Todos derechos reservados. + + Here is a listing of the usage example and the options to the tiff2pdf + program that is part of the libtiff distribution. Options followed by + a colon have a required argument. + + usage: tiff2pdf [options] input.tif + + options: + -o: output to file name + + -j: compress with JPEG (requires libjpeg configured with libtiff) + -z: compress with Zip/Deflate (requires zlib configured with libtiff) + -q: compression quality + -n: no compressed data passthrough + -d: do not compress (decompress) + -i: invert colors + -u: set distance unit, 'i' for inch, 'm' for centimeter + -x: set x resolution default + -y: set y resolution default + -w: width in units + -l: length in units + -r: 'd' for resolution default, 'o' for resolution override + -p: paper size, eg "letter", "legal", "a4" + -F: make the tiff fill the PDF page + -f: set pdf "fit window" user preference + -b: set PDF "Interpolate" user preference + -e: date, overrides image or current date/time default, YYYYMMDDHHMMSS + -c: creator, overrides image software default + -a: author, overrides image artist default + -t: title, overrides image document name default + -s: subject, overrides image image description default + -k: keywords + + -h: usage + + examples: + + tiff2pdf -o output.pdf input.tiff + + The above example would generate the file output.pdf from input.tiff. + + tiff2pdf input.tiff + + The above example would generate PDF output from input.tiff and write it + to standard output. + + tiff2pdf -j -p letter -o output.pdf input.tiff + + The above example would generate the file output.pdf from input.tiff, + putting the image pages on a letter sized page, compressing the output + with JPEG. + + Please report bugs through: + + http://bugzilla.remotesensing.org/buglist.cgi?product=libtiff + + See also libtiff.3t, tiffcp. + */ + +int main(int argc, char** argv){ +#if !HAVE_DECL_OPTARG + extern char *optarg; + extern int optind; +#endif + const char *outfilename = NULL; + T2P *t2p = NULL; + TIFF *input = NULL, *output = NULL; + int c, ret = EXIT_SUCCESS; + + t2p = t2p_init(); + + if (t2p == NULL){ + TIFFError(TIFF2PDF_MODULE, "Can't initialize context"); + goto fail; + } + + while (argv && + (c = getopt(argc, argv, + "o:q:u:x:y:w:l:r:p:e:c:a:t:s:k:jzndifbhF")) != -1){ + switch (c) { + case 'o': + outfilename = optarg; + break; +#ifdef JPEG_SUPPORT + case 'j': + t2p->pdf_defaultcompression=T2P_COMPRESS_JPEG; + break; +#endif +#ifndef JPEG_SUPPORT + case 'j': + TIFFWarning( + TIFF2PDF_MODULE, + "JPEG support in libtiff required for JPEG compression, ignoring option"); + break; +#endif +#ifdef ZIP_SUPPORT + case 'z': + t2p->pdf_defaultcompression=T2P_COMPRESS_ZIP; + break; +#endif +#ifndef ZIP_SUPPORT + case 'z': + TIFFWarning( + TIFF2PDF_MODULE, + "Zip support in libtiff required for Zip compression, ignoring option"); + break; +#endif + case 'q': + t2p->pdf_defaultcompressionquality=atoi(optarg); + break; + case 'n': + t2p->pdf_nopassthrough=1; + break; + case 'd': + t2p->pdf_defaultcompression=T2P_COMPRESS_NONE; + break; + case 'u': + if(optarg[0]=='m'){ + t2p->pdf_centimeters=1; + } + break; + case 'x': + t2p->pdf_defaultxres = + (float)atof(optarg) / (t2p->pdf_centimeters?2.54F:1.0F); + break; + case 'y': + t2p->pdf_defaultyres = + (float)atof(optarg) / (t2p->pdf_centimeters?2.54F:1.0F); + break; + case 'w': + t2p->pdf_overridepagesize=1; + t2p->pdf_defaultpagewidth = + ((float)atof(optarg) * PS_UNIT_SIZE) / (t2p->pdf_centimeters?2.54F:1.0F); + break; + case 'l': + t2p->pdf_overridepagesize=1; + t2p->pdf_defaultpagelength = + ((float)atof(optarg) * PS_UNIT_SIZE) / (t2p->pdf_centimeters?2.54F:1.0F); + break; + case 'r': + if(optarg[0]=='o'){ + t2p->pdf_overrideres=1; + } + break; + case 'p': + if(tiff2pdf_match_paper_size( + &(t2p->pdf_defaultpagewidth), + &(t2p->pdf_defaultpagelength), + optarg)){ + t2p->pdf_overridepagesize=1; + } else { + TIFFWarning(TIFF2PDF_MODULE, + "Unknown paper size %s, ignoring option", + optarg); + } + break; + case 'i': + t2p->pdf_colorspace_invert=1; + break; + case 'F': + t2p->pdf_image_fillpage = 1; + break; + case 'f': + t2p->pdf_fitwindow=1; + break; + case 'e': + if (strlen(optarg) == 0) { + t2p->pdf_datetime[0] = '\0'; + } else { + t2p->pdf_datetime[0] = 'D'; + t2p->pdf_datetime[1] = ':'; + strncpy(t2p->pdf_datetime + 2, optarg, + sizeof(t2p->pdf_datetime) - 3); + t2p->pdf_datetime[sizeof(t2p->pdf_datetime) - 1] = '\0'; + } + break; + case 'c': + strncpy(t2p->pdf_creator, optarg, sizeof(t2p->pdf_creator) - 1); + t2p->pdf_creator[sizeof(t2p->pdf_creator) - 1] = '\0'; + break; + case 'a': + strncpy(t2p->pdf_author, optarg, sizeof(t2p->pdf_author) - 1); + t2p->pdf_author[sizeof(t2p->pdf_author) - 1] = '\0'; + break; + case 't': + strncpy(t2p->pdf_title, optarg, sizeof(t2p->pdf_title) - 1); + t2p->pdf_title[sizeof(t2p->pdf_title) - 1] = '\0'; + break; + case 's': + strncpy(t2p->pdf_subject, optarg, sizeof(t2p->pdf_subject) - 1); + t2p->pdf_subject[sizeof(t2p->pdf_subject) - 1] = '\0'; + break; + case 'k': + strncpy(t2p->pdf_keywords, optarg, sizeof(t2p->pdf_keywords) - 1); + t2p->pdf_keywords[sizeof(t2p->pdf_keywords) - 1] = '\0'; + break; + case 'b': + t2p->pdf_image_interpolate = 1; + break; + case 'h': + case '?': + tiff2pdf_usage(); + goto success; + break; + } + } + + /* + * Input + */ + if(argc > optind) { + input = TIFFOpen(argv[optind++], "r"); + if (input==NULL) { + TIFFError(TIFF2PDF_MODULE, + "Can't open input file %s for reading", + argv[optind-1]); + goto fail; + } + } else { + TIFFError(TIFF2PDF_MODULE, "No input file specified"); + tiff2pdf_usage(); + goto fail; + } + + if(argc > optind) { + TIFFError(TIFF2PDF_MODULE, + "No support for multiple input files"); + tiff2pdf_usage(); + goto fail; + } + + /* + * Output + */ + t2p->outputdisable = 1; + if (outfilename) { + t2p->outputfile = fopen(outfilename, "wb"); + if (t2p->outputfile == NULL) { + TIFFError(TIFF2PDF_MODULE, + "Can't open output file %s for writing", + outfilename); + goto fail; + } + } else { + outfilename = "-"; + t2p->outputfile = stdout; + } + + output = TIFFClientOpen(outfilename, "w", (thandle_t) t2p, + t2p_readproc, t2p_writeproc, t2p_seekproc, + t2p_closeproc, t2p_sizeproc, + t2p_mapproc, t2p_unmapproc); + t2p->outputdisable = 0; + if (output == NULL) { + TIFFError(TIFF2PDF_MODULE, + "Can't initialize output descriptor"); + goto fail; + } + + /* + * Validate + */ + t2p_validate(t2p); + t2pSeekFile(output, (toff_t) 0, SEEK_SET); + + /* + * Write + */ + t2p_write_pdf(t2p, input, output); + if (t2p->t2p_error != 0) { + TIFFError(TIFF2PDF_MODULE, + "An error occurred creating output PDF file"); + goto fail; + } + + goto success; +fail: + ret = EXIT_FAILURE; +success: + if(input != NULL) + TIFFClose(input); + if (output != NULL) + TIFFClose(output); + if (t2p != NULL) + t2p_free(t2p); + return ret; + +} + +void tiff2pdf_usage(){ + char* lines[]={ + "usage: tiff2pdf [options] input.tiff", + "options:", + " -o: output to file name", +#ifdef JPEG_SUPPORT + " -j: compress with JPEG", +#endif +#ifdef ZIP_SUPPORT + " -z: compress with Zip/Deflate", +#endif + " -q: compression quality", + " -n: no compressed data passthrough", + " -d: do not compress (decompress)", + " -i: invert colors", + " -u: set distance unit, 'i' for inch, 'm' for centimeter", + " -x: set x resolution default in dots per unit", + " -y: set y resolution default in dots per unit", + " -w: width in units", + " -l: length in units", + " -r: 'd' for resolution default, 'o' for resolution override", + " -p: paper size, eg \"letter\", \"legal\", \"A4\"", + " -F: make the tiff fill the PDF page", + " -f: set PDF \"Fit Window\" user preference", + " -e: date, overrides image or current date/time default, YYYYMMDDHHMMSS", + " -c: sets document creator, overrides image software default", + " -a: sets document author, overrides image artist default", + " -t: sets document title, overrides image document name default", + " -s: sets document subject, overrides image image description default", + " -k: sets document keywords", + " -b: set PDF \"Interpolate\" user preference", + " -h: usage", + NULL + }; + int i=0; + + fprintf(stderr, "%s\n\n", TIFFGetVersion()); + for (i=0;lines[i]!=NULL;i++){ + fprintf(stderr, "%s\n", lines[i]); + } + + return; +} + +int tiff2pdf_match_paper_size(float* width, float* length, char* papersize){ + + size_t i, len; + const char* sizes[]={ + "LETTER", "A4", "LEGAL", + "EXECUTIVE", "LETTER", "LEGAL", "LEDGER", "TABLOID", + "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", + "A10", "A9", "A8", "A7", "A6", "A5", "A4", "A3", "A2", "A1", "A0", + "2A0", "4A0", "2A", "4A", + "B10", "B9", "B8", "B7", "B6", "B5", "B4", "B3", "B2", "B1", "B0", + "JISB10", "JISB9", "JISB8", "JISB7", "JISB6", "JISB5", "JISB4", + "JISB3", "JISB2", "JISB1", "JISB0", + "C10", "C9", "C8", "C7", "C6", "C5", "C4", "C3", "C2", "C1", "C0", + "RA2", "RA1", "RA0", "SRA4", "SRA3", "SRA2", "SRA1", "SRA0", + "A3EXTRA", "A4EXTRA", + "STATEMENT", "FOLIO", "QUARTO", + NULL + } ; + const int widths[]={ + 612, 595, 612, + 522, 612,612,792,792, + 612,792,1224,1584,2448,2016,792,2016,2448,2880, + 74,105,147,210,298,420,595,842,1191,1684,2384,3370,4768,3370,4768, + 88,125,176,249,354,499,709,1001,1417,2004,2835, + 91,128,181,258,363,516,729,1032,1460,2064,2920, + 79,113,162,230,323,459,649,918,1298,1298,2599, + 1219,1729,2438,638,907,1276,1814,2551, + 914,667, + 396, 612, 609, + 0 + }; + const int lengths[]={ + 792,842,1008, + 756,792,1008,1224,1224, + 792,1224,1584,2448,3168,2880,6480,10296,12672,10296, + 105,147,210,298,420,595,842,1191,1684,2384,3370,4768,6741,4768,6741, + 125,176,249,354,499,709,1001,1417,2004,2835,4008, + 128,181,258,363,516,729,1032,1460,2064,2920,4127, + 113,162,230,323,459,649,918,1298,1837,1837,3677, + 1729,2438,3458,907,1276,1814,2551,3628, + 1262,914, + 612, 936, 780, + 0 + }; + + len=strlen(papersize); + for(i=0;ipdf_majorversion=1; + t2p->pdf_minorversion=1; + t2p->pdf_defaultxres=300.0; + t2p->pdf_defaultyres=300.0; + t2p->pdf_defaultpagewidth=612.0; + t2p->pdf_defaultpagelength=792.0; + t2p->pdf_xrefcount=3; /* Catalog, Info, Pages */ + + return(t2p); +} + +/* + * This function frees a T2P context struct pointer and any allocated data fields of it. + */ + +void t2p_free(T2P* t2p) +{ + int i = 0; + + if (t2p != NULL) { + if(t2p->pdf_xrefoffsets != NULL){ + _TIFFfree( (tdata_t) t2p->pdf_xrefoffsets); + } + if(t2p->tiff_pages != NULL){ + _TIFFfree( (tdata_t) t2p->tiff_pages); + } + for(i=0;itiff_pagecount;i++){ + if(t2p->tiff_tiles[i].tiles_tiles != NULL){ + _TIFFfree( (tdata_t) t2p->tiff_tiles[i].tiles_tiles); + } + } + if(t2p->tiff_tiles != NULL){ + _TIFFfree( (tdata_t) t2p->tiff_tiles); + } + if(t2p->pdf_palette != NULL){ + _TIFFfree( (tdata_t) t2p->pdf_palette); + } +#ifdef OJPEG_SUPPORT + if(t2p->pdf_ojpegdata != NULL){ + _TIFFfree( (tdata_t) t2p->pdf_ojpegdata); + } +#endif + _TIFFfree( (tdata_t) t2p ); + } + + return; +} + +/* + This function validates the values of a T2P context struct pointer + before calling t2p_write_pdf with it. +*/ + +void t2p_validate(T2P* t2p){ + +#ifdef JPEG_SUPPORT + if(t2p->pdf_defaultcompression==T2P_COMPRESS_JPEG){ + if(t2p->pdf_defaultcompressionquality>100 || + t2p->pdf_defaultcompressionquality<1){ + t2p->pdf_defaultcompressionquality=0; + } + } +#endif +#ifdef ZIP_SUPPORT + if(t2p->pdf_defaultcompression==T2P_COMPRESS_ZIP){ + uint16 m=t2p->pdf_defaultcompressionquality%100; + if(t2p->pdf_defaultcompressionquality/100 > 9 || + (m>1 && m<10) || m>15){ + t2p->pdf_defaultcompressionquality=0; + } + if(t2p->pdf_defaultcompressionquality%100 !=0){ + t2p->pdf_defaultcompressionquality/=100; + t2p->pdf_defaultcompressionquality*=100; + TIFFError( + TIFF2PDF_MODULE, + "PNG Group predictor differencing not implemented, assuming compression quality %u", + t2p->pdf_defaultcompressionquality); + } + t2p->pdf_defaultcompressionquality%=100; + if(t2p->pdf_minorversion<2){t2p->pdf_minorversion=2;} + } +#endif + (void)0; + + return; +} + + +/* + This function scans the input TIFF file for pages. It attempts + to determine which IFD's of the TIFF file contain image document + pages. For each, it gathers some information that has to do + with the output of the PDF document as a whole. +*/ + +void t2p_read_tiff_init(T2P* t2p, TIFF* input){ + + tdir_t directorycount=0; + tdir_t i=0; + uint16 pagen=0; + uint16 paged=0; + uint16 xuint16=0; + + directorycount=TIFFNumberOfDirectories(input); + t2p->tiff_pages = (T2P_PAGE*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,directorycount,sizeof(T2P_PAGE))); + if(t2p->tiff_pages==NULL){ + TIFFError( + TIFF2PDF_MODULE, + "Can't allocate " TIFF_SIZE_FORMAT " bytes of memory for tiff_pages array, %s", + (TIFF_SIZE_T) directorycount * sizeof(T2P_PAGE), + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + _TIFFmemset( t2p->tiff_pages, 0x00, directorycount * sizeof(T2P_PAGE)); + t2p->tiff_tiles = (T2P_TILES*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,directorycount,sizeof(T2P_TILES))); + if(t2p->tiff_tiles==NULL){ + TIFFError( + TIFF2PDF_MODULE, + "Can't allocate " TIFF_SIZE_FORMAT " bytes of memory for tiff_tiles array, %s", + (TIFF_SIZE_T) directorycount * sizeof(T2P_TILES), + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + _TIFFmemset( t2p->tiff_tiles, 0x00, directorycount * sizeof(T2P_TILES)); + for(i=0;it2p_error = T2P_ERR_ERROR; + return; + } + if(TIFFGetField(input, TIFFTAG_PAGENUMBER, &pagen, &paged)){ + if((pagen>paged) && (paged != 0)){ + t2p->tiff_pages[t2p->tiff_pagecount].page_number = + paged; + } else { + t2p->tiff_pages[t2p->tiff_pagecount].page_number = + pagen; + } + goto ispage2; + } + if(TIFFGetField(input, TIFFTAG_SUBFILETYPE, &subfiletype)){ + if ( ((subfiletype & FILETYPE_PAGE) != 0) + || (subfiletype == 0)){ + goto ispage; + } else { + goto isnotpage; + } + } + if(TIFFGetField(input, TIFFTAG_OSUBFILETYPE, &subfiletype)){ + if ((subfiletype == OFILETYPE_IMAGE) + || (subfiletype == OFILETYPE_PAGE) + || (subfiletype == 0) ){ + goto ispage; + } else { + goto isnotpage; + } + } + ispage: + t2p->tiff_pages[t2p->tiff_pagecount].page_number=t2p->tiff_pagecount; + ispage2: + t2p->tiff_pages[t2p->tiff_pagecount].page_directory=i; + if(TIFFIsTiled(input)){ + t2p->tiff_pages[t2p->tiff_pagecount].page_tilecount = + TIFFNumberOfTiles(input); + } + t2p->tiff_pagecount++; + isnotpage: + (void)0; + } + + qsort((void*) t2p->tiff_pages, t2p->tiff_pagecount, + sizeof(T2P_PAGE), t2p_cmp_t2p_page); + + for(i=0;itiff_pagecount;i++){ + t2p->pdf_xrefcount += 5; + TIFFSetDirectory(input, t2p->tiff_pages[i].page_directory ); + if((TIFFGetField(input, TIFFTAG_PHOTOMETRIC, &xuint16) + && (xuint16==PHOTOMETRIC_PALETTE)) + || TIFFGetField(input, TIFFTAG_INDEXED, &xuint16)) { + t2p->tiff_pages[i].page_extra++; + t2p->pdf_xrefcount++; + } +#ifdef ZIP_SUPPORT + if (TIFFGetField(input, TIFFTAG_COMPRESSION, &xuint16)) { + if( (xuint16== COMPRESSION_DEFLATE || + xuint16== COMPRESSION_ADOBE_DEFLATE) && + ((t2p->tiff_pages[i].page_tilecount != 0) + || TIFFNumberOfStrips(input)==1) && + (t2p->pdf_nopassthrough==0) ){ + if(t2p->pdf_minorversion<2){t2p->pdf_minorversion=2;} + } + } +#endif + if (TIFFGetField(input, TIFFTAG_TRANSFERFUNCTION, + &(t2p->tiff_transferfunction[0]), + &(t2p->tiff_transferfunction[1]), + &(t2p->tiff_transferfunction[2]))) { + if((t2p->tiff_transferfunction[1] != (float*) NULL) && + (t2p->tiff_transferfunction[2] != (float*) NULL) && + (t2p->tiff_transferfunction[1] != + t2p->tiff_transferfunction[0])) { + t2p->tiff_transferfunctioncount = 3; + t2p->tiff_pages[i].page_extra += 4; + t2p->pdf_xrefcount += 4; + } else { + t2p->tiff_transferfunctioncount = 1; + t2p->tiff_pages[i].page_extra += 2; + t2p->pdf_xrefcount += 2; + } + if(t2p->pdf_minorversion < 2) + t2p->pdf_minorversion = 2; + } else { + t2p->tiff_transferfunctioncount=0; + } + if( TIFFGetField( + input, + TIFFTAG_ICCPROFILE, + &(t2p->tiff_iccprofilelength), + &(t2p->tiff_iccprofile)) != 0){ + t2p->tiff_pages[i].page_extra++; + t2p->pdf_xrefcount++; + if(t2p->pdf_minorversion<3){t2p->pdf_minorversion=3;} + } + t2p->tiff_tiles[i].tiles_tilecount= + t2p->tiff_pages[i].page_tilecount; + if( (TIFFGetField(input, TIFFTAG_PLANARCONFIG, &xuint16) != 0) + && (xuint16 == PLANARCONFIG_SEPARATE ) ){ + if( !TIFFGetField(input, TIFFTAG_SAMPLESPERPIXEL, &xuint16) ) + { + TIFFError( + TIFF2PDF_MODULE, + "Missing SamplesPerPixel, %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + if( (t2p->tiff_tiles[i].tiles_tilecount % xuint16) != 0 ) + { + TIFFError( + TIFF2PDF_MODULE, + "Invalid tile count, %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + t2p->tiff_tiles[i].tiles_tilecount/= xuint16; + } + if( t2p->tiff_tiles[i].tiles_tilecount > 0){ + t2p->pdf_xrefcount += + (t2p->tiff_tiles[i].tiles_tilecount -1)*2; + TIFFGetField(input, + TIFFTAG_TILEWIDTH, + &( t2p->tiff_tiles[i].tiles_tilewidth) ); + TIFFGetField(input, + TIFFTAG_TILELENGTH, + &( t2p->tiff_tiles[i].tiles_tilelength) ); + t2p->tiff_tiles[i].tiles_tiles = + (T2P_TILE*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->tiff_tiles[i].tiles_tilecount, + sizeof(T2P_TILE)) ); + if( t2p->tiff_tiles[i].tiles_tiles == NULL){ + TIFFError( + TIFF2PDF_MODULE, + "Can't allocate " TIFF_SIZE_FORMAT " bytes of memory for t2p_read_tiff_init, %s", + (TIFF_SIZE_T) t2p->tiff_tiles[i].tiles_tilecount * sizeof(T2P_TILE), + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + } + } + + return; +} + +/* + * This function is used by qsort to sort a T2P_PAGE* array of page structures + * by page number. If the page numbers are the same, we fall back to comparing + * directory numbers to preserve the order of the input file. + */ + +int t2p_cmp_t2p_page(const void* e1, const void* e2){ + + int d; + d = (int32)(((T2P_PAGE*)e1)->page_number) - (int32)(((T2P_PAGE*)e2)->page_number); + if(d == 0){ + d = (int32)(((T2P_PAGE*)e1)->page_directory) - (int32)(((T2P_PAGE*)e2)->page_directory); + } + return d; +} + +/* + This function sets the input directory to the directory of a given + page and determines information about the image. It checks + the image characteristics to determine if it is possible to convert + the image data into a page of PDF output, setting values of the T2P + struct for this page. It determines what color space is used in + the output PDF to represent the image. + + It determines if the image can be converted as raw data without + requiring transcoding of the image data. +*/ + +void t2p_read_tiff_data(T2P* t2p, TIFF* input){ + + int i=0; + uint16* r; + uint16* g; + uint16* b; + uint16* a; + uint16 xuint16; + uint16* xuint16p; + float* xfloatp; + + t2p->pdf_transcode = T2P_TRANSCODE_ENCODE; + t2p->pdf_sample = T2P_SAMPLE_NOTHING; + t2p->pdf_switchdecode = t2p->pdf_colorspace_invert; + + + TIFFSetDirectory(input, t2p->tiff_pages[t2p->pdf_page].page_directory); + + TIFFGetField(input, TIFFTAG_IMAGEWIDTH, &(t2p->tiff_width)); + if(t2p->tiff_width == 0){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with zero width", + TIFFFileName(input) ); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + + TIFFGetField(input, TIFFTAG_IMAGELENGTH, &(t2p->tiff_length)); + if(t2p->tiff_length == 0){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with zero length", + TIFFFileName(input) ); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + + if(TIFFGetField(input, TIFFTAG_COMPRESSION, &(t2p->tiff_compression)) == 0){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with no compression tag", + TIFFFileName(input) ); + t2p->t2p_error = T2P_ERR_ERROR; + return; + + } + if( TIFFIsCODECConfigured(t2p->tiff_compression) == 0){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with compression type %u: not configured", + TIFFFileName(input), + t2p->tiff_compression + ); + t2p->t2p_error = T2P_ERR_ERROR; + return; + + } + + TIFFGetFieldDefaulted(input, TIFFTAG_BITSPERSAMPLE, &(t2p->tiff_bitspersample)); + switch(t2p->tiff_bitspersample){ + case 1: + case 2: + case 4: + case 8: + break; + case 0: + TIFFWarning( + TIFF2PDF_MODULE, + "Image %s has 0 bits per sample, assuming 1", + TIFFFileName(input)); + t2p->tiff_bitspersample=1; + break; + default: + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with %u bits per sample", + TIFFFileName(input), + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + + TIFFGetFieldDefaulted(input, TIFFTAG_SAMPLESPERPIXEL, &(t2p->tiff_samplesperpixel)); + if(t2p->tiff_samplesperpixel>4){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with %u samples per pixel", + TIFFFileName(input), + t2p->tiff_samplesperpixel); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + if(t2p->tiff_samplesperpixel==0){ + TIFFWarning( + TIFF2PDF_MODULE, + "Image %s has 0 samples per pixel, assuming 1", + TIFFFileName(input)); + t2p->tiff_samplesperpixel=1; + } + + if(TIFFGetField(input, TIFFTAG_SAMPLEFORMAT, &xuint16) != 0 ){ + switch(xuint16){ + case 0: + case 1: + case 4: + break; + default: + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with sample format %u", + TIFFFileName(input), + xuint16); + t2p->t2p_error = T2P_ERR_ERROR; + return; + break; + } + } + + TIFFGetFieldDefaulted(input, TIFFTAG_FILLORDER, &(t2p->tiff_fillorder)); + + if(TIFFGetField(input, TIFFTAG_PHOTOMETRIC, &(t2p->tiff_photometric)) == 0){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with no photometric interpretation tag", + TIFFFileName(input) ); + t2p->t2p_error = T2P_ERR_ERROR; + return; + + } + + switch(t2p->tiff_photometric){ + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + if (t2p->tiff_bitspersample==1){ + t2p->pdf_colorspace=T2P_CS_BILEVEL; + if(t2p->tiff_photometric==PHOTOMETRIC_MINISWHITE){ + t2p->pdf_switchdecode ^= 1; + } + } else { + t2p->pdf_colorspace=T2P_CS_GRAY; + if(t2p->tiff_photometric==PHOTOMETRIC_MINISWHITE){ + t2p->pdf_switchdecode ^= 1; + } + } + break; + case PHOTOMETRIC_RGB: + t2p->pdf_colorspace=T2P_CS_RGB; + if(t2p->tiff_samplesperpixel == 3){ + break; + } + if(TIFFGetField(input, TIFFTAG_INDEXED, &xuint16)){ + if(xuint16==1) + goto photometric_palette; + } + if(t2p->tiff_samplesperpixel > 3) { + if(t2p->tiff_samplesperpixel == 4) { + t2p->pdf_colorspace = T2P_CS_RGB; + if(TIFFGetField(input, + TIFFTAG_EXTRASAMPLES, + &xuint16, &xuint16p) + && xuint16 == 1) { + if(xuint16p[0] == EXTRASAMPLE_ASSOCALPHA){ + if( t2p->tiff_bitspersample != 8 ) + { + TIFFError( + TIFF2PDF_MODULE, + "No support for BitsPerSample=%d for RGBA", + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + t2p->pdf_sample=T2P_SAMPLE_RGBAA_TO_RGB; + break; + } + if(xuint16p[0] == EXTRASAMPLE_UNASSALPHA){ + if( t2p->tiff_bitspersample != 8 ) + { + TIFFError( + TIFF2PDF_MODULE, + "No support for BitsPerSample=%d for RGBA", + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + t2p->pdf_sample=T2P_SAMPLE_RGBA_TO_RGB; + break; + } + TIFFWarning( + TIFF2PDF_MODULE, + "RGB image %s has 4 samples per pixel, assuming RGBA", + TIFFFileName(input)); + break; + } + t2p->pdf_colorspace=T2P_CS_CMYK; + t2p->pdf_switchdecode ^= 1; + TIFFWarning( + TIFF2PDF_MODULE, + "RGB image %s has 4 samples per pixel, assuming inverse CMYK", + TIFFFileName(input)); + break; + } else { + TIFFError( + TIFF2PDF_MODULE, + "No support for RGB image %s with %u samples per pixel", + TIFFFileName(input), + t2p->tiff_samplesperpixel); + t2p->t2p_error = T2P_ERR_ERROR; + break; + } + } else { + TIFFError( + TIFF2PDF_MODULE, + "No support for RGB image %s with %u samples per pixel", + TIFFFileName(input), + t2p->tiff_samplesperpixel); + t2p->t2p_error = T2P_ERR_ERROR; + break; + } + case PHOTOMETRIC_PALETTE: + photometric_palette: + if(t2p->tiff_samplesperpixel!=1){ + TIFFError( + TIFF2PDF_MODULE, + "No support for palettized image %s with not one sample per pixel", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + t2p->pdf_colorspace=T2P_CS_RGB | T2P_CS_PALETTE; + t2p->pdf_palettesize=0x0001<tiff_bitspersample; + if(!TIFFGetField(input, TIFFTAG_COLORMAP, &r, &g, &b)){ + TIFFError( + TIFF2PDF_MODULE, + "Palettized image %s has no color map", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + if(t2p->pdf_palette != NULL){ + _TIFFfree(t2p->pdf_palette); + t2p->pdf_palette=NULL; + } + t2p->pdf_palette = (unsigned char*) + _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->pdf_palettesize,3)); + if(t2p->pdf_palette==NULL){ + TIFFError( + TIFF2PDF_MODULE, + "Can't allocate %u bytes of memory for t2p_read_tiff_image, %s", + t2p->pdf_palettesize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + for(i=0;ipdf_palettesize;i++){ + t2p->pdf_palette[(i*3)] = (unsigned char) (r[i]>>8); + t2p->pdf_palette[(i*3)+1]= (unsigned char) (g[i]>>8); + t2p->pdf_palette[(i*3)+2]= (unsigned char) (b[i]>>8); + } + t2p->pdf_palettesize *= 3; + break; + case PHOTOMETRIC_SEPARATED: + if(TIFFGetField(input, TIFFTAG_INDEXED, &xuint16)){ + if(xuint16==1){ + goto photometric_palette_cmyk; + } + } + if( TIFFGetField(input, TIFFTAG_INKSET, &xuint16) ){ + if(xuint16 != INKSET_CMYK){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s because its inkset is not CMYK", + TIFFFileName(input) ); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + } + if(t2p->tiff_samplesperpixel==4){ + t2p->pdf_colorspace=T2P_CS_CMYK; + } else { + TIFFError( + TIFF2PDF_MODULE, + "No support for %s because it has %u samples per pixel", + TIFFFileName(input), + t2p->tiff_samplesperpixel); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + break; + photometric_palette_cmyk: + if(t2p->tiff_samplesperpixel!=1){ + TIFFError( + TIFF2PDF_MODULE, + "No support for palettized CMYK image %s with not one sample per pixel", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + t2p->pdf_colorspace=T2P_CS_CMYK | T2P_CS_PALETTE; + t2p->pdf_palettesize=0x0001<tiff_bitspersample; + if(!TIFFGetField(input, TIFFTAG_COLORMAP, &r, &g, &b, &a)){ + TIFFError( + TIFF2PDF_MODULE, + "Palettized image %s has no color map", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + if(t2p->pdf_palette != NULL){ + _TIFFfree(t2p->pdf_palette); + t2p->pdf_palette=NULL; + } + t2p->pdf_palette = (unsigned char*) + _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->pdf_palettesize,4)); + if(t2p->pdf_palette==NULL){ + TIFFError( + TIFF2PDF_MODULE, + "Can't allocate %u bytes of memory for t2p_read_tiff_image, %s", + t2p->pdf_palettesize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + for(i=0;ipdf_palettesize;i++){ + t2p->pdf_palette[(i*4)] = (unsigned char) (r[i]>>8); + t2p->pdf_palette[(i*4)+1]= (unsigned char) (g[i]>>8); + t2p->pdf_palette[(i*4)+2]= (unsigned char) (b[i]>>8); + t2p->pdf_palette[(i*4)+3]= (unsigned char) (a[i]>>8); + } + t2p->pdf_palettesize *= 4; + break; + case PHOTOMETRIC_YCBCR: + t2p->pdf_colorspace=T2P_CS_RGB; + if(t2p->tiff_samplesperpixel==1){ + t2p->pdf_colorspace=T2P_CS_GRAY; + t2p->tiff_photometric=PHOTOMETRIC_MINISBLACK; + break; + } + t2p->pdf_sample=T2P_SAMPLE_YCBCR_TO_RGB; +#ifdef JPEG_SUPPORT + if(t2p->pdf_defaultcompression==T2P_COMPRESS_JPEG){ + t2p->pdf_sample=T2P_SAMPLE_NOTHING; + } +#endif + break; + case PHOTOMETRIC_CIELAB: + if( t2p->tiff_samplesperpixel != 3){ + TIFFError( + TIFF2PDF_MODULE, + "Unsupported samplesperpixel = %d for CIELAB", + t2p->tiff_samplesperpixel); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + if( t2p->tiff_bitspersample != 8){ + TIFFError( + TIFF2PDF_MODULE, + "Invalid bitspersample = %d for CIELAB", + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + t2p->pdf_labrange[0]= -127; + t2p->pdf_labrange[1]= 127; + t2p->pdf_labrange[2]= -127; + t2p->pdf_labrange[3]= 127; + t2p->pdf_sample=T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED; + t2p->pdf_colorspace=T2P_CS_LAB; + break; + case PHOTOMETRIC_ICCLAB: + t2p->pdf_labrange[0]= 0; + t2p->pdf_labrange[1]= 255; + t2p->pdf_labrange[2]= 0; + t2p->pdf_labrange[3]= 255; + t2p->pdf_colorspace=T2P_CS_LAB; + break; + case PHOTOMETRIC_ITULAB: + if( t2p->tiff_samplesperpixel != 3){ + TIFFError( + TIFF2PDF_MODULE, + "Unsupported samplesperpixel = %d for ITULAB", + t2p->tiff_samplesperpixel); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + if( t2p->tiff_bitspersample != 8){ + TIFFError( + TIFF2PDF_MODULE, + "Invalid bitspersample = %d for ITULAB", + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + t2p->pdf_labrange[0]=-85; + t2p->pdf_labrange[1]=85; + t2p->pdf_labrange[2]=-75; + t2p->pdf_labrange[3]=124; + t2p->pdf_sample=T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED; + t2p->pdf_colorspace=T2P_CS_LAB; + break; + case PHOTOMETRIC_LOGL: + case PHOTOMETRIC_LOGLUV: + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with photometric interpretation LogL/LogLuv", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + default: + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with photometric interpretation %u", + TIFFFileName(input), + t2p->tiff_photometric); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + + if(TIFFGetField(input, TIFFTAG_PLANARCONFIG, &(t2p->tiff_planar))){ + switch(t2p->tiff_planar){ + case 0: + TIFFWarning( + TIFF2PDF_MODULE, + "Image %s has planar configuration 0, assuming 1", + TIFFFileName(input)); + t2p->tiff_planar=PLANARCONFIG_CONTIG; + case PLANARCONFIG_CONTIG: + break; + case PLANARCONFIG_SEPARATE: + t2p->pdf_sample=T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG; + if(t2p->tiff_bitspersample!=8){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with separated planar configuration and %u bits per sample", + TIFFFileName(input), + t2p->tiff_bitspersample); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + break; + default: + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with planar configuration %u", + TIFFFileName(input), + t2p->tiff_planar); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + } + + TIFFGetFieldDefaulted(input, TIFFTAG_ORIENTATION, + &(t2p->tiff_orientation)); + if(t2p->tiff_orientation>8){ + TIFFWarning(TIFF2PDF_MODULE, + "Image %s has orientation %u, assuming 0", + TIFFFileName(input), t2p->tiff_orientation); + t2p->tiff_orientation=0; + } + + if(TIFFGetField(input, TIFFTAG_XRESOLUTION, &(t2p->tiff_xres) ) == 0){ + t2p->tiff_xres=0.0; + } + if(TIFFGetField(input, TIFFTAG_YRESOLUTION, &(t2p->tiff_yres) ) == 0){ + t2p->tiff_yres=0.0; + } + TIFFGetFieldDefaulted(input, TIFFTAG_RESOLUTIONUNIT, + &(t2p->tiff_resunit)); + if(t2p->tiff_resunit == RESUNIT_CENTIMETER) { + t2p->tiff_xres *= 2.54F; + t2p->tiff_yres *= 2.54F; + } else if (t2p->tiff_resunit != RESUNIT_INCH + && t2p->pdf_centimeters != 0) { + t2p->tiff_xres *= 2.54F; + t2p->tiff_yres *= 2.54F; + } + + t2p_compose_pdf_page(t2p); + if( t2p->t2p_error == T2P_ERR_ERROR ) + return; + + t2p->pdf_transcode = T2P_TRANSCODE_ENCODE; + /* It seems that T2P_TRANSCODE_RAW mode doesn't support separate->contig */ + /* conversion. At least t2p_read_tiff_size and t2p_read_tiff_size_tile */ + /* do not take into account the number of samples, and thus */ + /* that can cause heap buffer overflows such as in */ + /* http://bugzilla.maptools.org/show_bug.cgi?id=2715 */ + if(t2p->pdf_nopassthrough==0 && t2p->tiff_planar!=PLANARCONFIG_SEPARATE){ +#ifdef CCITT_SUPPORT + if(t2p->tiff_compression==COMPRESSION_CCITTFAX4 + ){ + if(TIFFIsTiled(input) || (TIFFNumberOfStrips(input)==1) ){ + t2p->pdf_transcode = T2P_TRANSCODE_RAW; + t2p->pdf_compression=T2P_COMPRESS_G4; + } + } +#endif +#ifdef ZIP_SUPPORT + if(t2p->tiff_compression== COMPRESSION_ADOBE_DEFLATE + || t2p->tiff_compression==COMPRESSION_DEFLATE){ + if(TIFFIsTiled(input) || (TIFFNumberOfStrips(input)==1) ){ + t2p->pdf_transcode = T2P_TRANSCODE_RAW; + t2p->pdf_compression=T2P_COMPRESS_ZIP; + } + } +#endif +#ifdef OJPEG_SUPPORT + if(t2p->tiff_compression==COMPRESSION_OJPEG){ + t2p->pdf_transcode = T2P_TRANSCODE_RAW; + t2p->pdf_compression=T2P_COMPRESS_JPEG; + t2p_process_ojpeg_tables(t2p, input); + } +#endif +#ifdef JPEG_SUPPORT + if(t2p->tiff_compression==COMPRESSION_JPEG){ + t2p->pdf_transcode = T2P_TRANSCODE_RAW; + t2p->pdf_compression=T2P_COMPRESS_JPEG; + } +#endif + (void)0; + } + + if(t2p->pdf_transcode!=T2P_TRANSCODE_RAW){ + t2p->pdf_compression = t2p->pdf_defaultcompression; + } + +#ifdef JPEG_SUPPORT + if(t2p->pdf_defaultcompression==T2P_COMPRESS_JPEG){ + if(t2p->pdf_colorspace & T2P_CS_PALETTE){ + t2p->pdf_sample|=T2P_SAMPLE_REALIZE_PALETTE; + t2p->pdf_colorspace ^= T2P_CS_PALETTE; + t2p->tiff_pages[t2p->pdf_page].page_extra--; + } + } + if(t2p->tiff_compression==COMPRESSION_JPEG){ + if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with JPEG compression and separated planar configuration", + TIFFFileName(input)); + t2p->t2p_error=T2P_ERR_ERROR; + return; + } + } +#endif +#ifdef OJPEG_SUPPORT + if(t2p->tiff_compression==COMPRESSION_OJPEG){ + if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){ + TIFFError( + TIFF2PDF_MODULE, + "No support for %s with OJPEG compression and separated planar configuration", + TIFFFileName(input)); + t2p->t2p_error=T2P_ERR_ERROR; + return; + } + } +#endif + + if(t2p->pdf_sample & T2P_SAMPLE_REALIZE_PALETTE){ + if(t2p->pdf_colorspace & T2P_CS_CMYK){ + t2p->tiff_samplesperpixel=4; + t2p->tiff_photometric=PHOTOMETRIC_SEPARATED; + } else { + t2p->tiff_samplesperpixel=3; + t2p->tiff_photometric=PHOTOMETRIC_RGB; + } + } + + if (TIFFGetField(input, TIFFTAG_TRANSFERFUNCTION, + &(t2p->tiff_transferfunction[0]), + &(t2p->tiff_transferfunction[1]), + &(t2p->tiff_transferfunction[2]))) { + if((t2p->tiff_transferfunction[1] != (float*) NULL) && + (t2p->tiff_transferfunction[2] != (float*) NULL) && + (t2p->tiff_transferfunction[1] != + t2p->tiff_transferfunction[0])) { + t2p->tiff_transferfunctioncount=3; + } else { + t2p->tiff_transferfunctioncount=1; + } + } else { + t2p->tiff_transferfunctioncount=0; + } + if(TIFFGetField(input, TIFFTAG_WHITEPOINT, &xfloatp)!=0){ + t2p->tiff_whitechromaticities[0]=xfloatp[0]; + t2p->tiff_whitechromaticities[1]=xfloatp[1]; + if(t2p->pdf_colorspace & T2P_CS_GRAY){ + t2p->pdf_colorspace |= T2P_CS_CALGRAY; + } + if(t2p->pdf_colorspace & T2P_CS_RGB){ + t2p->pdf_colorspace |= T2P_CS_CALRGB; + } + } + if(TIFFGetField(input, TIFFTAG_PRIMARYCHROMATICITIES, &xfloatp)!=0){ + t2p->tiff_primarychromaticities[0]=xfloatp[0]; + t2p->tiff_primarychromaticities[1]=xfloatp[1]; + t2p->tiff_primarychromaticities[2]=xfloatp[2]; + t2p->tiff_primarychromaticities[3]=xfloatp[3]; + t2p->tiff_primarychromaticities[4]=xfloatp[4]; + t2p->tiff_primarychromaticities[5]=xfloatp[5]; + if(t2p->pdf_colorspace & T2P_CS_RGB){ + t2p->pdf_colorspace |= T2P_CS_CALRGB; + } + } + if(t2p->pdf_colorspace & T2P_CS_LAB){ + if(TIFFGetField(input, TIFFTAG_WHITEPOINT, &xfloatp) != 0){ + t2p->tiff_whitechromaticities[0]=xfloatp[0]; + t2p->tiff_whitechromaticities[1]=xfloatp[1]; + } else { + t2p->tiff_whitechromaticities[0]=0.3457F; /* 0.3127F; */ + t2p->tiff_whitechromaticities[1]=0.3585F; /* 0.3290F; */ + } + } + if(TIFFGetField(input, + TIFFTAG_ICCPROFILE, + &(t2p->tiff_iccprofilelength), + &(t2p->tiff_iccprofile))!=0){ + t2p->pdf_colorspace |= T2P_CS_ICCBASED; + } else { + t2p->tiff_iccprofilelength=0; + t2p->tiff_iccprofile=NULL; + } + +#ifdef CCITT_SUPPORT + if( t2p->tiff_bitspersample==1 && + t2p->tiff_samplesperpixel==1){ + t2p->pdf_compression = T2P_COMPRESS_G4; + } +#endif + + + return; +} + +/* + This function returns the necessary size of a data buffer to contain the raw or + uncompressed image data from the input TIFF for a page. +*/ + +void t2p_read_tiff_size(T2P* t2p, TIFF* input){ + + uint64* sbc=NULL; +#if defined(JPEG_SUPPORT) || defined (OJPEG_SUPPORT) + unsigned char* jpt=NULL; + tstrip_t i=0; + tstrip_t stripcount=0; +#endif + uint64 k = 0; + + if(t2p->pdf_transcode == T2P_TRANSCODE_RAW){ +#ifdef CCITT_SUPPORT + if(t2p->pdf_compression == T2P_COMPRESS_G4 ){ + TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc); + if (sbc[0] != (uint64)(tmsize_t)sbc[0]) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + t2p->tiff_datasize=(tmsize_t)sbc[0]; + return; + } +#endif +#ifdef ZIP_SUPPORT + if(t2p->pdf_compression == T2P_COMPRESS_ZIP){ + TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc); + if (sbc[0] != (uint64)(tmsize_t)sbc[0]) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + t2p->tiff_datasize=(tmsize_t)sbc[0]; + return; + } +#endif +#ifdef OJPEG_SUPPORT + if(t2p->tiff_compression == COMPRESSION_OJPEG){ + if(!TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc)){ + TIFFError(TIFF2PDF_MODULE, + "Input file %s missing field: TIFFTAG_STRIPBYTECOUNTS", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + stripcount=TIFFNumberOfStrips(input); + for(i=0;itiff_dataoffset))){ + if(t2p->tiff_dataoffset != 0){ + if(TIFFGetField(input, TIFFTAG_JPEGIFBYTECOUNT, &(t2p->tiff_datasize))!=0){ + if((uint64)t2p->tiff_datasize < k) { + TIFFWarning(TIFF2PDF_MODULE, + "Input file %s has short JPEG interchange file byte count", + TIFFFileName(input)); + t2p->pdf_ojpegiflength=t2p->tiff_datasize; + k = checkAdd64(k, t2p->tiff_datasize, t2p); + k = checkAdd64(k, 6, t2p); + k = checkAdd64(k, stripcount, t2p); + k = checkAdd64(k, stripcount, t2p); + t2p->tiff_datasize = (tsize_t) k; + if ((uint64) t2p->tiff_datasize != k) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + return; + } + return; + }else { + TIFFError(TIFF2PDF_MODULE, + "Input file %s missing field: TIFFTAG_JPEGIFBYTECOUNT", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + } + } + k = checkAdd64(k, stripcount, t2p); + k = checkAdd64(k, stripcount, t2p); + k = checkAdd64(k, 2048, t2p); + t2p->tiff_datasize = (tsize_t) k; + if ((uint64) t2p->tiff_datasize != k) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + return; + } +#endif +#ifdef JPEG_SUPPORT + if(t2p->tiff_compression == COMPRESSION_JPEG) { + uint32 count = 0; + if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0 ){ + if(count > 4){ + k += count; + k -= 2; /* don't use EOI of header */ + } + } else { + k = 2; /* SOI for first strip */ + } + stripcount=TIFFNumberOfStrips(input); + if(!TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc)){ + TIFFError(TIFF2PDF_MODULE, + "Input file %s missing field: TIFFTAG_STRIPBYTECOUNTS", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + for(i=0;itiff_datasize = (tsize_t) k; + if ((uint64) t2p->tiff_datasize != k) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + return; + } +#endif + (void) 0; + } + k = checkMultiply64(TIFFScanlineSize(input), t2p->tiff_length, t2p); + if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){ + k = checkMultiply64(k, t2p->tiff_samplesperpixel, t2p); + } + if (k == 0) { + /* Assume we had overflow inside TIFFScanlineSize */ + t2p->t2p_error = T2P_ERR_ERROR; + } + + t2p->tiff_datasize = (tsize_t) k; + if ((uint64) t2p->tiff_datasize != k) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + + return; +} + +/* + This function returns the necessary size of a data buffer to contain the raw or + uncompressed image data from the input TIFF for a tile of a page. +*/ + +void t2p_read_tiff_size_tile(T2P* t2p, TIFF* input, ttile_t tile){ + + uint64* tbc = NULL; + uint16 edge=0; +#ifdef JPEG_SUPPORT + unsigned char* jpt; +#endif + uint64 k; + + edge |= t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile); + edge |= t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile); + + if(t2p->pdf_transcode==T2P_TRANSCODE_RAW){ + if(edge +#if defined(JPEG_SUPPORT) || defined(OJPEG_SUPPORT) + && !(t2p->pdf_compression==T2P_COMPRESS_JPEG) +#endif + ){ + t2p->tiff_datasize=TIFFTileSize(input); + if (t2p->tiff_datasize == 0) { + /* Assume we had overflow inside TIFFTileSize */ + t2p->t2p_error = T2P_ERR_ERROR; + } + return; + } else { + TIFFGetField(input, TIFFTAG_TILEBYTECOUNTS, &tbc); + k=tbc[tile]; +#ifdef OJPEG_SUPPORT + if(t2p->tiff_compression==COMPRESSION_OJPEG){ + k = checkAdd64(k, 2048, t2p); + } +#endif +#ifdef JPEG_SUPPORT + if(t2p->tiff_compression==COMPRESSION_JPEG) { + uint32 count = 0; + if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt)!=0){ + if(count > 4){ + k = checkAdd64(k, count, t2p); + k -= 2; /* don't use EOI of header or SOI of tile */ + } + } + } +#endif + t2p->tiff_datasize = (tsize_t) k; + if ((uint64) t2p->tiff_datasize != k) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + return; + } + } + k = TIFFTileSize(input); + if(t2p->tiff_planar==PLANARCONFIG_SEPARATE){ + k = checkMultiply64(k, t2p->tiff_samplesperpixel, t2p); + } + if (k == 0) { + /* Assume we had overflow inside TIFFTileSize */ + t2p->t2p_error = T2P_ERR_ERROR; + } + + t2p->tiff_datasize = (tsize_t) k; + if ((uint64) t2p->tiff_datasize != k) { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + } + + return; +} + +/* + * This functions returns a non-zero value when the tile is on the right edge + * and does not have full imaged tile width. + */ + +int t2p_tile_is_right_edge(T2P_TILES tiles, ttile_t tile){ + + if( ((tile+1) % tiles.tiles_tilecountx == 0) + && (tiles.tiles_edgetilewidth != 0) ){ + return(1); + } else { + return(0); + } +} + +/* + * This functions returns a non-zero value when the tile is on the bottom edge + * and does not have full imaged tile length. + */ + +int t2p_tile_is_bottom_edge(T2P_TILES tiles, ttile_t tile){ + + if( ((tile+1) > (tiles.tiles_tilecount-tiles.tiles_tilecountx) ) + && (tiles.tiles_edgetilelength != 0) ){ + return(1); + } else { + return(0); + } +} + +/* + * This function returns a non-zero value when the tile is a right edge tile + * or a bottom edge tile. + */ + +int t2p_tile_is_edge(T2P_TILES tiles, ttile_t tile){ + + return(t2p_tile_is_right_edge(tiles, tile) | t2p_tile_is_bottom_edge(tiles, tile) ); +} + +/* + This function returns a non-zero value when the tile is a right edge tile and a bottom + edge tile. +*/ + +int t2p_tile_is_corner_edge(T2P_TILES tiles, ttile_t tile){ + + return(t2p_tile_is_right_edge(tiles, tile) & t2p_tile_is_bottom_edge(tiles, tile) ); +} + + +/* + This function reads the raster image data from the input TIFF for an image and writes + the data to the output PDF XObject image dictionary stream. It returns the amount written + or zero on error. +*/ + +tsize_t t2p_readwrite_pdf_image(T2P* t2p, TIFF* input, TIFF* output){ + + tsize_t written=0; + unsigned char* buffer=NULL; + unsigned char* samplebuffer=NULL; + tsize_t bufferoffset=0; + tsize_t samplebufferoffset=0; + tsize_t read=0; + tstrip_t i=0; + tstrip_t j=0; + tstrip_t stripcount=0; + tsize_t stripsize=0; + tsize_t sepstripcount=0; + tsize_t sepstripsize=0; +#ifdef OJPEG_SUPPORT + toff_t inputoffset=0; + uint16 h_samp=1; + uint16 v_samp=1; + uint16 ri=1; + uint32 rows=0; +#endif /* ifdef OJPEG_SUPPORT */ +#ifdef JPEG_SUPPORT + unsigned char* jpt; + float* xfloatp; + uint64* sbc; + unsigned char* stripbuffer; + tsize_t striplength=0; + uint32 max_striplength=0; +#endif /* ifdef JPEG_SUPPORT */ + + /* Fail if prior error (in particular, can't trust tiff_datasize) */ + if (t2p->t2p_error != T2P_ERR_OK) + return(0); + + if(t2p->pdf_transcode == T2P_TRANSCODE_RAW){ +#ifdef CCITT_SUPPORT + if(t2p->pdf_compression == T2P_COMPRESS_G4){ + buffer = (unsigned char*) + _TIFFmalloc(t2p->tiff_datasize); + if (buffer == NULL) { + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for " + "t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + TIFFReadRawStrip(input, 0, (tdata_t) buffer, + t2p->tiff_datasize); + if (t2p->tiff_fillorder==FILLORDER_LSB2MSB){ + /* + * make sure is lsb-to-msb + * bit-endianness fill order + */ + TIFFReverseBits(buffer, + t2p->tiff_datasize); + } + t2pWriteFile(output, (tdata_t) buffer, + t2p->tiff_datasize); + _TIFFfree(buffer); + return(t2p->tiff_datasize); + } +#endif /* ifdef CCITT_SUPPORT */ +#ifdef ZIP_SUPPORT + if (t2p->pdf_compression == T2P_COMPRESS_ZIP) { + buffer = (unsigned char*) + _TIFFmalloc(t2p->tiff_datasize); + if(buffer == NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + memset(buffer, 0, t2p->tiff_datasize); + TIFFReadRawStrip(input, 0, (tdata_t) buffer, + t2p->tiff_datasize); + if (t2p->tiff_fillorder==FILLORDER_LSB2MSB) { + TIFFReverseBits(buffer, + t2p->tiff_datasize); + } + t2pWriteFile(output, (tdata_t) buffer, + t2p->tiff_datasize); + _TIFFfree(buffer); + return(t2p->tiff_datasize); + } +#endif /* ifdef ZIP_SUPPORT */ +#ifdef OJPEG_SUPPORT + if(t2p->tiff_compression == COMPRESSION_OJPEG) { + + if(t2p->tiff_dataoffset != 0) { + buffer = (unsigned char*) + _TIFFmalloc(t2p->tiff_datasize); + if(buffer == NULL) { + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + memset(buffer, 0, t2p->tiff_datasize); + if(t2p->pdf_ojpegiflength==0){ + inputoffset=t2pSeekFile(input, 0, + SEEK_CUR); + t2pSeekFile(input, + t2p->tiff_dataoffset, + SEEK_SET); + t2pReadFile(input, (tdata_t) buffer, + t2p->tiff_datasize); + t2pSeekFile(input, inputoffset, + SEEK_SET); + t2pWriteFile(output, (tdata_t) buffer, + t2p->tiff_datasize); + _TIFFfree(buffer); + return(t2p->tiff_datasize); + } else { + inputoffset=t2pSeekFile(input, 0, + SEEK_CUR); + t2pSeekFile(input, + t2p->tiff_dataoffset, + SEEK_SET); + bufferoffset = t2pReadFile(input, + (tdata_t) buffer, + t2p->pdf_ojpegiflength); + t2p->pdf_ojpegiflength = 0; + t2pSeekFile(input, inputoffset, + SEEK_SET); + TIFFGetField(input, + TIFFTAG_YCBCRSUBSAMPLING, + &h_samp, &v_samp); + buffer[bufferoffset++]= 0xff; + buffer[bufferoffset++]= 0xdd; + buffer[bufferoffset++]= 0x00; + buffer[bufferoffset++]= 0x04; + h_samp*=8; + v_samp*=8; + ri=(t2p->tiff_width+h_samp-1) / h_samp; + TIFFGetField(input, + TIFFTAG_ROWSPERSTRIP, + &rows); + ri*=(rows+v_samp-1)/v_samp; + buffer[bufferoffset++]= (ri>>8) & 0xff; + buffer[bufferoffset++]= ri & 0xff; + stripcount=TIFFNumberOfStrips(input); + for(i=0;ipdf_ojpegdata){ + TIFFError(TIFF2PDF_MODULE, + "No support for OJPEG image %s with bad tables", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + buffer = (unsigned char*) + _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + memset(buffer, 0, t2p->tiff_datasize); + _TIFFmemcpy(buffer, t2p->pdf_ojpegdata, t2p->pdf_ojpegdatalength); + bufferoffset=t2p->pdf_ojpegdatalength; + stripcount=TIFFNumberOfStrips(input); + for(i=0;it2p_error = T2P_ERR_ERROR; + return(0); +#endif + } + } +#endif /* ifdef OJPEG_SUPPORT */ +#ifdef JPEG_SUPPORT + if(t2p->tiff_compression == COMPRESSION_JPEG) { + uint32 count = 0; + buffer = (unsigned char*) + _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + memset(buffer, 0, t2p->tiff_datasize); + if (TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0) { + if(count > 4) { + _TIFFmemcpy(buffer, jpt, count); + bufferoffset += count - 2; + } + } + stripcount=TIFFNumberOfStrips(input); + TIFFGetField(input, TIFFTAG_STRIPBYTECOUNTS, &sbc); + for(i=0;imax_striplength) max_striplength=sbc[i]; + } + stripbuffer = (unsigned char*) + _TIFFmalloc(max_striplength); + if(stripbuffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %u bytes of memory for t2p_readwrite_pdf_image, %s", + max_striplength, + TIFFFileName(input)); + _TIFFfree(buffer); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + for(i=0;itiff_datasize, + &bufferoffset, + i, + t2p->tiff_length)){ + TIFFError(TIFF2PDF_MODULE, + "Can't process JPEG data in input file %s", + TIFFFileName(input)); + _TIFFfree(samplebuffer); + _TIFFfree(buffer); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + } + buffer[bufferoffset++]=0xff; + buffer[bufferoffset++]=0xd9; + t2pWriteFile(output, (tdata_t) buffer, bufferoffset); + _TIFFfree(stripbuffer); + _TIFFfree(buffer); + return(bufferoffset); + } +#endif /* ifdef JPEG_SUPPORT */ + (void)0; + } + + if(t2p->pdf_sample==T2P_SAMPLE_NOTHING){ + buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + memset(buffer, 0, t2p->tiff_datasize); + stripsize=TIFFStripSize(input); + stripcount=TIFFNumberOfStrips(input); + for(i=0;itiff_datasize - bufferoffset)); + if(read==-1){ + TIFFError(TIFF2PDF_MODULE, + "Error on decoding strip %u of %s", + i, + TIFFFileName(input)); + _TIFFfree(buffer); + t2p->t2p_error=T2P_ERR_ERROR; + return(0); + } + bufferoffset+=read; + } + } else { + if(t2p->pdf_sample & T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG){ + + sepstripsize=TIFFStripSize(input); + sepstripcount=TIFFNumberOfStrips(input); + + stripsize=sepstripsize*t2p->tiff_samplesperpixel; + stripcount=sepstripcount/t2p->tiff_samplesperpixel; + + buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + memset(buffer, 0, t2p->tiff_datasize); + samplebuffer = (unsigned char*) _TIFFmalloc(stripsize); + if(samplebuffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + _TIFFfree(buffer); + return(0); + } + for(i=0;itiff_samplesperpixel;j++){ + read = + TIFFReadEncodedStrip(input, + i + j*stripcount, + (tdata_t) &(samplebuffer[samplebufferoffset]), + TIFFmin(sepstripsize, stripsize - samplebufferoffset)); + if(read==-1){ + TIFFError(TIFF2PDF_MODULE, + "Error on decoding strip %u of %s", + i + j*stripcount, + TIFFFileName(input)); + _TIFFfree(buffer); + t2p->t2p_error=T2P_ERR_ERROR; + return(0); + } + samplebufferoffset+=read; + } + t2p_sample_planar_separate_to_contig( + t2p, + &(buffer[bufferoffset]), + samplebuffer, + samplebufferoffset); + bufferoffset+=samplebufferoffset; + } + _TIFFfree(samplebuffer); + goto dataready; + } + + buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + memset(buffer, 0, t2p->tiff_datasize); + stripsize=TIFFStripSize(input); + stripcount=TIFFNumberOfStrips(input); + for(i=0;itiff_datasize - bufferoffset)); + if(read==-1){ + TIFFError(TIFF2PDF_MODULE, + "Error on decoding strip %u of %s", + i, + TIFFFileName(input)); + _TIFFfree(samplebuffer); + _TIFFfree(buffer); + t2p->t2p_error=T2P_ERR_ERROR; + return(0); + } + bufferoffset+=read; + } + + if(t2p->pdf_sample & T2P_SAMPLE_REALIZE_PALETTE){ + // FIXME: overflow? + samplebuffer=(unsigned char*)_TIFFrealloc( + (tdata_t) buffer, + t2p->tiff_datasize * t2p->tiff_samplesperpixel); + if(samplebuffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + _TIFFfree(buffer); + return(0); + } else { + buffer=samplebuffer; + t2p->tiff_datasize *= t2p->tiff_samplesperpixel; + } + t2p_sample_realize_palette(t2p, buffer); + } + + if(t2p->pdf_sample & T2P_SAMPLE_RGBA_TO_RGB){ + t2p->tiff_datasize=t2p_sample_rgba_to_rgb( + (tdata_t)buffer, + t2p->tiff_width*t2p->tiff_length); + } + + if(t2p->pdf_sample & T2P_SAMPLE_RGBAA_TO_RGB){ + t2p->tiff_datasize=t2p_sample_rgbaa_to_rgb( + (tdata_t)buffer, + t2p->tiff_width*t2p->tiff_length); + } + + if(t2p->pdf_sample & T2P_SAMPLE_YCBCR_TO_RGB){ + samplebuffer=(unsigned char*)_TIFFrealloc( + (tdata_t)buffer, + t2p->tiff_width*t2p->tiff_length*4); + if(samplebuffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + _TIFFfree(buffer); + return(0); + } else { + buffer=samplebuffer; + } + if(!TIFFReadRGBAImageOriented( + input, + t2p->tiff_width, + t2p->tiff_length, + (uint32*)buffer, + ORIENTATION_TOPLEFT, + 0)){ + TIFFError(TIFF2PDF_MODULE, + "Can't use TIFFReadRGBAImageOriented to extract RGB image from %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + t2p->tiff_datasize=t2p_sample_abgr_to_rgb( + (tdata_t) buffer, + t2p->tiff_width*t2p->tiff_length); + + } + + if(t2p->pdf_sample & T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED){ + t2p->tiff_datasize=t2p_sample_lab_signed_to_unsigned( + (tdata_t)buffer, + t2p->tiff_width*t2p->tiff_length); + } + } + +dataready: + + t2p_disable(output); + TIFFSetField(output, TIFFTAG_PHOTOMETRIC, t2p->tiff_photometric); + TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, t2p->tiff_bitspersample); + TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, t2p->tiff_samplesperpixel); + TIFFSetField(output, TIFFTAG_IMAGEWIDTH, t2p->tiff_width); + TIFFSetField(output, TIFFTAG_IMAGELENGTH, t2p->tiff_length); + TIFFSetField(output, TIFFTAG_ROWSPERSTRIP, t2p->tiff_length); + TIFFSetField(output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(output, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); + + switch(t2p->pdf_compression){ + case T2P_COMPRESS_NONE: + TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + break; +#ifdef CCITT_SUPPORT + case T2P_COMPRESS_G4: + TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); + break; +#endif /* ifdef CCITT_SUPPORT */ +#ifdef JPEG_SUPPORT + case T2P_COMPRESS_JPEG: + if(t2p->tiff_photometric==PHOTOMETRIC_YCBCR) { + uint16 hor = 0, ver = 0; + if (TIFFGetField(input, TIFFTAG_YCBCRSUBSAMPLING, &hor, &ver) !=0 ) { + if(hor != 0 && ver != 0){ + TIFFSetField(output, TIFFTAG_YCBCRSUBSAMPLING, hor, ver); + } + } + if(TIFFGetField(input, TIFFTAG_REFERENCEBLACKWHITE, &xfloatp)!=0){ + TIFFSetField(output, TIFFTAG_REFERENCEBLACKWHITE, xfloatp); + } + } + if(TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_JPEG)==0){ + TIFFError(TIFF2PDF_MODULE, + "Unable to use JPEG compression for input %s and output %s", + TIFFFileName(input), + TIFFFileName(output)); + _TIFFfree(buffer); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + TIFFSetField(output, TIFFTAG_JPEGTABLESMODE, 0); + + if(t2p->pdf_colorspace & (T2P_CS_RGB | T2P_CS_LAB)){ + TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR); + if(t2p->tiff_photometric != PHOTOMETRIC_YCBCR){ + TIFFSetField(output, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); + } else { + TIFFSetField(output, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW); + } + } + if(t2p->pdf_colorspace & T2P_CS_GRAY){ + (void)0; + } + if(t2p->pdf_colorspace & T2P_CS_CMYK){ + (void)0; + } + if(t2p->pdf_defaultcompressionquality != 0){ + TIFFSetField(output, + TIFFTAG_JPEGQUALITY, + t2p->pdf_defaultcompressionquality); + } + + break; +#endif /* ifdef JPEG_SUPPORT */ +#ifdef ZIP_SUPPORT + case T2P_COMPRESS_ZIP: + TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); + if(t2p->pdf_defaultcompressionquality%100 != 0){ + TIFFSetField(output, + TIFFTAG_PREDICTOR, + t2p->pdf_defaultcompressionquality % 100); + } + if(t2p->pdf_defaultcompressionquality/100 != 0){ + TIFFSetField(output, + TIFFTAG_ZIPQUALITY, + (t2p->pdf_defaultcompressionquality / 100)); + } + break; +#endif /* ifdef ZIP_SUPPORT */ + default: + break; + } + + t2p_enable(output); + t2p->outputwritten = 0; +#ifdef JPEG_SUPPORT + if(t2p->pdf_compression == T2P_COMPRESS_JPEG + && t2p->tiff_photometric == PHOTOMETRIC_YCBCR){ + bufferoffset = TIFFWriteEncodedStrip(output, (tstrip_t)0, + buffer, + stripsize * stripcount); + } else +#endif /* ifdef JPEG_SUPPORT */ + { + bufferoffset = TIFFWriteEncodedStrip(output, (tstrip_t)0, + buffer, + t2p->tiff_datasize); + } + if (buffer != NULL) { + _TIFFfree(buffer); + buffer=NULL; + } + + if (bufferoffset == (tsize_t)-1) { + TIFFError(TIFF2PDF_MODULE, + "Error writing encoded strip to output PDF %s", + TIFFFileName(output)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + + written = t2p->outputwritten; + return(written); +} + +/* + * This function reads the raster image data from the input TIFF for an image + * tile and writes the data to the output PDF XObject image dictionary stream + * for the tile. It returns the amount written or zero on error. + */ + +tsize_t t2p_readwrite_pdf_image_tile(T2P* t2p, TIFF* input, TIFF* output, ttile_t tile){ + + uint16 edge=0; + tsize_t written=0; + unsigned char* buffer=NULL; + tsize_t bufferoffset=0; + unsigned char* samplebuffer=NULL; + tsize_t samplebufferoffset=0; + tsize_t read=0; + uint16 i=0; + ttile_t tilecount=0; + /* tsize_t tilesize=0; */ + ttile_t septilecount=0; + tsize_t septilesize=0; +#ifdef JPEG_SUPPORT + unsigned char* jpt; + float* xfloatp; + uint32 xuint32=0; +#endif + + /* Fail if prior error (in particular, can't trust tiff_datasize) */ + if (t2p->t2p_error != T2P_ERR_OK) + return(0); + + edge |= t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile); + edge |= t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile); + + if( (t2p->pdf_transcode == T2P_TRANSCODE_RAW) && ((edge == 0) +#if defined(JPEG_SUPPORT) || defined(OJPEG_SUPPORT) + || (t2p->pdf_compression == T2P_COMPRESS_JPEG) +#endif + ) + ){ +#ifdef CCITT_SUPPORT + if(t2p->pdf_compression == T2P_COMPRESS_G4){ + buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory " + "for t2p_readwrite_pdf_image_tile, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + TIFFReadRawTile(input, tile, (tdata_t) buffer, t2p->tiff_datasize); + if (t2p->tiff_fillorder==FILLORDER_LSB2MSB){ + TIFFReverseBits(buffer, t2p->tiff_datasize); + } + t2pWriteFile(output, (tdata_t) buffer, t2p->tiff_datasize); + _TIFFfree(buffer); + return(t2p->tiff_datasize); + } +#endif +#ifdef ZIP_SUPPORT + if(t2p->pdf_compression == T2P_COMPRESS_ZIP){ + buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory " + "for t2p_readwrite_pdf_image_tile, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + TIFFReadRawTile(input, tile, (tdata_t) buffer, t2p->tiff_datasize); + if (t2p->tiff_fillorder==FILLORDER_LSB2MSB){ + TIFFReverseBits(buffer, t2p->tiff_datasize); + } + t2pWriteFile(output, (tdata_t) buffer, t2p->tiff_datasize); + _TIFFfree(buffer); + return(t2p->tiff_datasize); + } +#endif +#ifdef OJPEG_SUPPORT + if(t2p->tiff_compression == COMPRESSION_OJPEG){ + if(! t2p->pdf_ojpegdata){ + TIFFError(TIFF2PDF_MODULE, + "No support for OJPEG image %s with " + "bad tables", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + buffer=(unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory " + "for t2p_readwrite_pdf_image, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + _TIFFmemcpy(buffer, t2p->pdf_ojpegdata, t2p->pdf_ojpegdatalength); + if(edge!=0){ + if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile)){ + buffer[7]= + (t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength >> 8) & 0xff; + buffer[8]= + (t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength ) & 0xff; + } + if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile)){ + buffer[9]= + (t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth >> 8) & 0xff; + buffer[10]= + (t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth ) & 0xff; + } + } + bufferoffset=t2p->pdf_ojpegdatalength; + bufferoffset+=TIFFReadRawTile(input, + tile, + (tdata_t) &(((unsigned char*)buffer)[bufferoffset]), + -1); + ((unsigned char*)buffer)[bufferoffset++]=0xff; + ((unsigned char*)buffer)[bufferoffset++]=0xd9; + t2pWriteFile(output, (tdata_t) buffer, bufferoffset); + _TIFFfree(buffer); + return(bufferoffset); + } +#endif +#ifdef JPEG_SUPPORT + if(t2p->tiff_compression == COMPRESSION_JPEG){ + unsigned char table_end[2]; + uint32 count = 0; + buffer= (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate " TIFF_SIZE_FORMAT " bytes of memory " + "for t2p_readwrite_pdf_image_tile, %s", + (TIFF_SIZE_T) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + if(TIFFGetField(input, TIFFTAG_JPEGTABLES, &count, &jpt) != 0) { + if (count > 4) { + int retTIFFReadRawTile; + /* Ignore EOI marker of JpegTables */ + _TIFFmemcpy(buffer, jpt, count - 2); + bufferoffset += count - 2; + /* Store last 2 bytes of the JpegTables */ + table_end[0] = buffer[bufferoffset-2]; + table_end[1] = buffer[bufferoffset-1]; + xuint32 = bufferoffset; + bufferoffset -= 2; + retTIFFReadRawTile= TIFFReadRawTile( + input, + tile, + (tdata_t) &(((unsigned char*)buffer)[bufferoffset]), + -1); + if( retTIFFReadRawTile < 0 ) + { + _TIFFfree(buffer); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + bufferoffset += retTIFFReadRawTile; + /* Overwrite SOI marker of image scan with previously */ + /* saved end of JpegTables */ + buffer[xuint32-2]=table_end[0]; + buffer[xuint32-1]=table_end[1]; + } + } + t2pWriteFile(output, (tdata_t) buffer, bufferoffset); + _TIFFfree(buffer); + return(bufferoffset); + } +#endif + (void)0; + } + + if(t2p->pdf_sample==T2P_SAMPLE_NOTHING){ + buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory for " + "t2p_readwrite_pdf_image_tile, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + + read = TIFFReadEncodedTile( + input, + tile, + (tdata_t) &buffer[bufferoffset], + t2p->tiff_datasize); + if(read==-1){ + TIFFError(TIFF2PDF_MODULE, + "Error on decoding tile %u of %s", + tile, + TIFFFileName(input)); + _TIFFfree(buffer); + t2p->t2p_error=T2P_ERR_ERROR; + return(0); + } + + } else { + + if(t2p->pdf_sample == T2P_SAMPLE_PLANAR_SEPARATE_TO_CONTIG){ + septilesize=TIFFTileSize(input); + septilecount=TIFFNumberOfTiles(input); + /* tilesize=septilesize*t2p->tiff_samplesperpixel; */ + tilecount=septilecount/t2p->tiff_samplesperpixel; + buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory " + "for t2p_readwrite_pdf_image_tile, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + samplebuffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(samplebuffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory " + "for t2p_readwrite_pdf_image_tile, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + samplebufferoffset=0; + for(i=0;itiff_samplesperpixel;i++){ + read = + TIFFReadEncodedTile(input, + tile + i*tilecount, + (tdata_t) &(samplebuffer[samplebufferoffset]), + septilesize); + if(read==-1){ + TIFFError(TIFF2PDF_MODULE, + "Error on decoding tile %u of %s", + tile + i*tilecount, + TIFFFileName(input)); + _TIFFfree(samplebuffer); + _TIFFfree(buffer); + t2p->t2p_error=T2P_ERR_ERROR; + return(0); + } + samplebufferoffset+=read; + } + t2p_sample_planar_separate_to_contig( + t2p, + &(buffer[bufferoffset]), + samplebuffer, + samplebufferoffset); + bufferoffset+=samplebufferoffset; + _TIFFfree(samplebuffer); + } + + if(buffer==NULL){ + buffer = (unsigned char*) _TIFFmalloc(t2p->tiff_datasize); + if(buffer==NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %lu bytes of memory " + "for t2p_readwrite_pdf_image_tile, %s", + (unsigned long) t2p->tiff_datasize, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + read = TIFFReadEncodedTile( + input, + tile, + (tdata_t) &buffer[bufferoffset], + t2p->tiff_datasize); + if(read==-1){ + TIFFError(TIFF2PDF_MODULE, + "Error on decoding tile %u of %s", + tile, + TIFFFileName(input)); + _TIFFfree(buffer); + t2p->t2p_error=T2P_ERR_ERROR; + return(0); + } + } + + if(t2p->pdf_sample & T2P_SAMPLE_RGBA_TO_RGB){ + t2p->tiff_datasize=t2p_sample_rgba_to_rgb( + (tdata_t)buffer, + t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth + *t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); + } + + if(t2p->pdf_sample & T2P_SAMPLE_RGBAA_TO_RGB){ + t2p->tiff_datasize=t2p_sample_rgbaa_to_rgb( + (tdata_t)buffer, + t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth + *t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); + } + + if(t2p->pdf_sample & T2P_SAMPLE_YCBCR_TO_RGB){ + TIFFError(TIFF2PDF_MODULE, + "No support for YCbCr to RGB in tile for %s", + TIFFFileName(input)); + _TIFFfree(buffer); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + + if(t2p->pdf_sample & T2P_SAMPLE_LAB_SIGNED_TO_UNSIGNED){ + t2p->tiff_datasize=t2p_sample_lab_signed_to_unsigned( + (tdata_t)buffer, + t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth + *t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); + } + } + + if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile) != 0){ + t2p_tile_collapse_left( + buffer, + TIFFTileRowSize(input), + t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth, + t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth, + t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); + } + + + t2p_disable(output); + TIFFSetField(output, TIFFTAG_PHOTOMETRIC, t2p->tiff_photometric); + TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, t2p->tiff_bitspersample); + TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, t2p->tiff_samplesperpixel); + if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile) == 0){ + TIFFSetField( + output, + TIFFTAG_IMAGEWIDTH, + t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth); + } else { + TIFFSetField( + output, + TIFFTAG_IMAGEWIDTH, + t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth); + } + if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile) == 0){ + TIFFSetField( + output, + TIFFTAG_IMAGELENGTH, + t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); + TIFFSetField( + output, + TIFFTAG_ROWSPERSTRIP, + t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); + } else { + TIFFSetField( + output, + TIFFTAG_IMAGELENGTH, + t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength); + TIFFSetField( + output, + TIFFTAG_ROWSPERSTRIP, + t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength); + } + TIFFSetField(output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + TIFFSetField(output, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); + + switch(t2p->pdf_compression){ + case T2P_COMPRESS_NONE: + TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_NONE); + break; +#ifdef CCITT_SUPPORT + case T2P_COMPRESS_G4: + TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); + break; +#endif +#ifdef JPEG_SUPPORT + case T2P_COMPRESS_JPEG: + if (t2p->tiff_photometric==PHOTOMETRIC_YCBCR) { + uint16 hor = 0, ver = 0; + if (TIFFGetField(input, TIFFTAG_YCBCRSUBSAMPLING, &hor, &ver)!=0) { + if (hor != 0 && ver != 0) { + TIFFSetField(output, TIFFTAG_YCBCRSUBSAMPLING, hor, ver); + } + } + if(TIFFGetField(input, TIFFTAG_REFERENCEBLACKWHITE, &xfloatp)!=0){ + TIFFSetField(output, TIFFTAG_REFERENCEBLACKWHITE, xfloatp); + } + } + TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_JPEG); + TIFFSetField(output, TIFFTAG_JPEGTABLESMODE, 0); /* JPEGTABLESMODE_NONE */ + if(t2p->pdf_colorspace & (T2P_CS_RGB | T2P_CS_LAB)){ + TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR); + if(t2p->tiff_photometric != PHOTOMETRIC_YCBCR){ + TIFFSetField(output, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB); + } else { + TIFFSetField(output, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RAW); + } + } + if(t2p->pdf_colorspace & T2P_CS_GRAY){ + (void)0; + } + if(t2p->pdf_colorspace & T2P_CS_CMYK){ + (void)0; + } + if(t2p->pdf_defaultcompressionquality != 0){ + TIFFSetField(output, + TIFFTAG_JPEGQUALITY, + t2p->pdf_defaultcompressionquality); + } + break; +#endif +#ifdef ZIP_SUPPORT + case T2P_COMPRESS_ZIP: + TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); + if(t2p->pdf_defaultcompressionquality%100 != 0){ + TIFFSetField(output, + TIFFTAG_PREDICTOR, + t2p->pdf_defaultcompressionquality % 100); + } + if(t2p->pdf_defaultcompressionquality/100 != 0){ + TIFFSetField(output, + TIFFTAG_ZIPQUALITY, + (t2p->pdf_defaultcompressionquality / 100)); + } + break; +#endif + default: + break; + } + + t2p_enable(output); + t2p->outputwritten = 0; + bufferoffset = TIFFWriteEncodedStrip(output, (tstrip_t) 0, buffer, + TIFFStripSize(output)); + if (buffer != NULL) { + _TIFFfree(buffer); + buffer = NULL; + } + if (bufferoffset == -1) { + TIFFError(TIFF2PDF_MODULE, + "Error writing encoded tile to output PDF %s", + TIFFFileName(output)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + + written = t2p->outputwritten; + + return(written); +} + +#ifdef OJPEG_SUPPORT +int t2p_process_ojpeg_tables(T2P* t2p, TIFF* input){ + uint16 proc=0; + void* q; + uint32 q_length=0; + void* dc; + uint32 dc_length=0; + void* ac; + uint32 ac_length=0; + uint16* lp; + uint16* pt; + uint16 h_samp=1; + uint16 v_samp=1; + unsigned char* ojpegdata; + uint16 table_count; + uint32 offset_table; + uint32 offset_ms_l; + uint32 code_count; + uint32 i=0; + uint32 dest=0; + uint16 ri=0; + uint32 rows=0; + + if(!TIFFGetField(input, TIFFTAG_JPEGPROC, &proc)){ + TIFFError(TIFF2PDF_MODULE, + "Missing JPEGProc field in OJPEG image %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + if(proc!=JPEGPROC_BASELINE && proc!=JPEGPROC_LOSSLESS){ + TIFFError(TIFF2PDF_MODULE, + "Bad JPEGProc field in OJPEG image %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + if(!TIFFGetField(input, TIFFTAG_JPEGQTABLES, &q_length, &q)){ + TIFFError(TIFF2PDF_MODULE, + "Missing JPEGQTables field in OJPEG image %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + if(q_length < (64U * t2p->tiff_samplesperpixel)){ + TIFFError(TIFF2PDF_MODULE, + "Bad JPEGQTables field in OJPEG image %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + if(!TIFFGetField(input, TIFFTAG_JPEGDCTABLES, &dc_length, &dc)){ + TIFFError(TIFF2PDF_MODULE, + "Missing JPEGDCTables field in OJPEG image %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + if(proc==JPEGPROC_BASELINE){ + if(!TIFFGetField(input, TIFFTAG_JPEGACTABLES, &ac_length, &ac)){ + TIFFError(TIFF2PDF_MODULE, + "Missing JPEGACTables field in OJPEG image %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + } else { + if(!TIFFGetField(input, TIFFTAG_JPEGLOSSLESSPREDICTORS, &lp)){ + TIFFError(TIFF2PDF_MODULE, + "Missing JPEGLosslessPredictors field in OJPEG image %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + if(!TIFFGetField(input, TIFFTAG_JPEGPOINTTRANSFORM, &pt)){ + TIFFError(TIFF2PDF_MODULE, + "Missing JPEGPointTransform field in OJPEG image %s", + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + } + if(!TIFFGetField(input, TIFFTAG_YCBCRSUBSAMPLING, &h_samp, &v_samp)){ + h_samp=1; + v_samp=1; + } + if(t2p->pdf_ojpegdata != NULL){ + _TIFFfree(t2p->pdf_ojpegdata); + t2p->pdf_ojpegdata=NULL; + } + t2p->pdf_ojpegdata = _TIFFmalloc(2048); + if(t2p->pdf_ojpegdata == NULL){ + TIFFError(TIFF2PDF_MODULE, + "Can't allocate %u bytes of memory for t2p_process_ojpeg_tables, %s", + 2048, + TIFFFileName(input)); + t2p->t2p_error = T2P_ERR_ERROR; + return(0); + } + _TIFFmemset(t2p->pdf_ojpegdata, 0x00, 2048); + t2p->pdf_ojpegdatalength = 0; + table_count=t2p->tiff_samplesperpixel; + if(proc==JPEGPROC_BASELINE){ + if(table_count>2) table_count=2; + } + ojpegdata=(unsigned char*)t2p->pdf_ojpegdata; + ojpegdata[t2p->pdf_ojpegdatalength++]=0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]=0xd8; + ojpegdata[t2p->pdf_ojpegdatalength++]=0xff; + if(proc==JPEGPROC_BASELINE){ + ojpegdata[t2p->pdf_ojpegdatalength++]=0xc0; + } else { + ojpegdata[t2p->pdf_ojpegdatalength++]=0xc3; + } + ojpegdata[t2p->pdf_ojpegdatalength++]=0x00; + ojpegdata[t2p->pdf_ojpegdatalength++]=(8 + 3*t2p->tiff_samplesperpixel); + ojpegdata[t2p->pdf_ojpegdatalength++]=(t2p->tiff_bitspersample & 0xff); + if(TIFFIsTiled(input)){ + ojpegdata[t2p->pdf_ojpegdatalength++]= + (t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength >> 8) & 0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]= + (t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength ) & 0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]= + (t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth >> 8) & 0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]= + (t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth ) & 0xff; + } else { + ojpegdata[t2p->pdf_ojpegdatalength++]= + (t2p->tiff_length >> 8) & 0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]= + (t2p->tiff_length ) & 0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]= + (t2p->tiff_width >> 8) & 0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]= + (t2p->tiff_width ) & 0xff; + } + ojpegdata[t2p->pdf_ojpegdatalength++]=(t2p->tiff_samplesperpixel & 0xff); + for(i=0;itiff_samplesperpixel;i++){ + ojpegdata[t2p->pdf_ojpegdatalength++]=i; + if(i==0){ + ojpegdata[t2p->pdf_ojpegdatalength] |= h_samp<<4 & 0xf0;; + ojpegdata[t2p->pdf_ojpegdatalength++] |= v_samp & 0x0f; + } else { + ojpegdata[t2p->pdf_ojpegdatalength++]= 0x11; + } + ojpegdata[t2p->pdf_ojpegdatalength++]=i; + } + for(dest=0;desttiff_samplesperpixel;dest++){ + ojpegdata[t2p->pdf_ojpegdatalength++]=0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]=0xdb; + ojpegdata[t2p->pdf_ojpegdatalength++]=0x00; + ojpegdata[t2p->pdf_ojpegdatalength++]=0x43; + ojpegdata[t2p->pdf_ojpegdatalength++]=dest; + _TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength++]), + &(((unsigned char*)q)[64*dest]), 64); + t2p->pdf_ojpegdatalength+=64; + } + offset_table=0; + for(dest=0;destpdf_ojpegdatalength++]=0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]=0xc4; + offset_ms_l=t2p->pdf_ojpegdatalength; + t2p->pdf_ojpegdatalength+=2; + ojpegdata[t2p->pdf_ojpegdatalength++]=dest & 0x0f; + _TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength]), + &(((unsigned char*)dc)[offset_table]), 16); + code_count=0; + offset_table+=16; + for(i=0;i<16;i++){ + code_count+=ojpegdata[t2p->pdf_ojpegdatalength++]; + } + ojpegdata[offset_ms_l]=((19+code_count)>>8) & 0xff; + ojpegdata[offset_ms_l+1]=(19+code_count) & 0xff; + _TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength]), + &(((unsigned char*)dc)[offset_table]), code_count); + offset_table+=code_count; + t2p->pdf_ojpegdatalength+=code_count; + } + if(proc==JPEGPROC_BASELINE){ + offset_table=0; + for(dest=0;destpdf_ojpegdatalength++]=0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]=0xc4; + offset_ms_l=t2p->pdf_ojpegdatalength; + t2p->pdf_ojpegdatalength+=2; + ojpegdata[t2p->pdf_ojpegdatalength] |= 0x10; + ojpegdata[t2p->pdf_ojpegdatalength++] |=dest & 0x0f; + _TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength]), + &(((unsigned char*)ac)[offset_table]), 16); + code_count=0; + offset_table+=16; + for(i=0;i<16;i++){ + code_count+=ojpegdata[t2p->pdf_ojpegdatalength++]; + } + ojpegdata[offset_ms_l]=((19+code_count)>>8) & 0xff; + ojpegdata[offset_ms_l+1]=(19+code_count) & 0xff; + _TIFFmemcpy( &(ojpegdata[t2p->pdf_ojpegdatalength]), + &(((unsigned char*)ac)[offset_table]), code_count); + offset_table+=code_count; + t2p->pdf_ojpegdatalength+=code_count; + } + } + if(TIFFNumberOfStrips(input)>1){ + ojpegdata[t2p->pdf_ojpegdatalength++]=0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]=0xdd; + ojpegdata[t2p->pdf_ojpegdatalength++]=0x00; + ojpegdata[t2p->pdf_ojpegdatalength++]=0x04; + h_samp*=8; + v_samp*=8; + ri=(t2p->tiff_width+h_samp-1) / h_samp; + TIFFGetField(input, TIFFTAG_ROWSPERSTRIP, &rows); + ri*=(rows+v_samp-1)/v_samp; + ojpegdata[t2p->pdf_ojpegdatalength++]= (ri>>8) & 0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]= ri & 0xff; + } + ojpegdata[t2p->pdf_ojpegdatalength++]=0xff; + ojpegdata[t2p->pdf_ojpegdatalength++]=0xda; + ojpegdata[t2p->pdf_ojpegdatalength++]=0x00; + ojpegdata[t2p->pdf_ojpegdatalength++]=(6 + 2*t2p->tiff_samplesperpixel); + ojpegdata[t2p->pdf_ojpegdatalength++]=t2p->tiff_samplesperpixel & 0xff; + for(i=0;itiff_samplesperpixel;i++){ + ojpegdata[t2p->pdf_ojpegdatalength++]= i & 0xff; + if(proc==JPEGPROC_BASELINE){ + ojpegdata[t2p->pdf_ojpegdatalength] |= + ( ( (i>(table_count-1U)) ? (table_count-1U) : i) << 4U) & 0xf0; + ojpegdata[t2p->pdf_ojpegdatalength++] |= + ( (i>(table_count-1U)) ? (table_count-1U) : i) & 0x0f; + } else { + ojpegdata[t2p->pdf_ojpegdatalength++] = (i << 4) & 0xf0; + } + } + if(proc==JPEGPROC_BASELINE){ + t2p->pdf_ojpegdatalength++; + ojpegdata[t2p->pdf_ojpegdatalength++]=0x3f; + t2p->pdf_ojpegdatalength++; + } else { + ojpegdata[t2p->pdf_ojpegdatalength++]= (lp[0] & 0xff); + t2p->pdf_ojpegdatalength++; + ojpegdata[t2p->pdf_ojpegdatalength++]= (pt[0] & 0x0f); + } + + return(1); +} +#endif + +#ifdef JPEG_SUPPORT +int t2p_process_jpeg_strip( + unsigned char* strip, + tsize_t* striplength, + unsigned char* buffer, + tsize_t buffersize, + tsize_t* bufferoffset, + tstrip_t no, + uint32 height){ + + tsize_t i=0; + + while (i < *striplength) { + tsize_t datalen; + uint16 ri; + uint16 v_samp; + uint16 h_samp; + int j; + int ncomp; + + /* marker header: one or more FFs */ + if (strip[i] != 0xff) + return(0); + i++; + while (i < *striplength && strip[i] == 0xff) + i++; + if (i >= *striplength) + return(0); + /* SOI is the only pre-SOS marker without a length word */ + if (strip[i] == 0xd8) + datalen = 0; + else { + if ((*striplength - i) <= 2) + return(0); + datalen = (strip[i+1] << 8) | strip[i+2]; + if (datalen < 2 || datalen >= (*striplength - i)) + return(0); + } + switch( strip[i] ){ + case 0xd8: /* SOI - start of image */ + if( *bufferoffset + 2 > buffersize ) + return(0); + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), 2); + *bufferoffset+=2; + break; + case 0xc0: /* SOF0 */ + case 0xc1: /* SOF1 */ + case 0xc3: /* SOF3 */ + case 0xc9: /* SOF9 */ + case 0xca: /* SOF10 */ + if(no==0){ + if( *bufferoffset + datalen + 2 + 6 > buffersize ) + return(0); + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2); + if( *bufferoffset + 9 >= buffersize ) + return(0); + ncomp = buffer[*bufferoffset+9]; + if (ncomp < 1 || ncomp > 4) + return(0); + v_samp=1; + h_samp=1; + if( *bufferoffset + 11 + 3*(ncomp-1) >= buffersize ) + return(0); + for(j=0;j>4) > h_samp) + h_samp = (samp>>4); + if( (samp & 0x0f) > v_samp) + v_samp = (samp & 0x0f); + } + v_samp*=8; + h_samp*=8; + ri=((( ((uint16)(buffer[*bufferoffset+5])<<8) | + (uint16)(buffer[*bufferoffset+6]) )+v_samp-1)/ + v_samp); + ri*=((( ((uint16)(buffer[*bufferoffset+7])<<8) | + (uint16)(buffer[*bufferoffset+8]) )+h_samp-1)/ + h_samp); + buffer[*bufferoffset+5]= + (unsigned char) ((height>>8) & 0xff); + buffer[*bufferoffset+6]= + (unsigned char) (height & 0xff); + *bufferoffset+=datalen+2; + /* insert a DRI marker */ + buffer[(*bufferoffset)++]=0xff; + buffer[(*bufferoffset)++]=0xdd; + buffer[(*bufferoffset)++]=0x00; + buffer[(*bufferoffset)++]=0x04; + buffer[(*bufferoffset)++]=(ri >> 8) & 0xff; + buffer[(*bufferoffset)++]= ri & 0xff; + } + break; + case 0xc4: /* DHT */ + case 0xdb: /* DQT */ + if( *bufferoffset + datalen + 2 > buffersize ) + return(0); + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2); + *bufferoffset+=datalen+2; + break; + case 0xda: /* SOS */ + if(no==0){ + if( *bufferoffset + datalen + 2 > buffersize ) + return(0); + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i-1]), datalen+2); + *bufferoffset+=datalen+2; + } else { + if( *bufferoffset + 2 > buffersize ) + return(0); + buffer[(*bufferoffset)++]=0xff; + buffer[(*bufferoffset)++]= + (unsigned char)(0xd0 | ((no-1)%8)); + } + i += datalen + 1; + /* copy remainder of strip */ + if( *bufferoffset + *striplength - i > buffersize ) + return(0); + _TIFFmemcpy(&(buffer[*bufferoffset]), &(strip[i]), *striplength - i); + *bufferoffset+= *striplength - i; + return(1); + default: + /* ignore any other marker */ + break; + } + i += datalen + 1; + } + + /* failed to find SOS marker */ + return(0); +} +#endif + +/* + This functions converts a tilewidth x tilelength buffer of samples into an edgetilewidth x + tilelength buffer of samples. +*/ +void t2p_tile_collapse_left( + tdata_t buffer, + tsize_t scanwidth, + uint32 tilewidth, + uint32 edgetilewidth, + uint32 tilelength){ + + uint32 i; + tsize_t edgescanwidth=0; + + edgescanwidth = (scanwidth * edgetilewidth + (tilewidth - 1))/ tilewidth; + for(i=0;it2p_error = T2P_ERR_ERROR; + return; + } + t2p_enable(output); + return; +} + +tsize_t t2p_sample_planar_separate_to_contig( + T2P* t2p, + unsigned char* buffer, + unsigned char* samplebuffer, + tsize_t samplebuffersize){ + + tsize_t stride=0; + tsize_t i=0; + tsize_t j=0; + + stride=samplebuffersize/t2p->tiff_samplesperpixel; + for(i=0;itiff_samplesperpixel;j++){ + buffer[i*t2p->tiff_samplesperpixel + j] = samplebuffer[i + j*stride]; + } + } + + return(samplebuffersize); +} + +tsize_t t2p_sample_realize_palette(T2P* t2p, unsigned char* buffer){ + + uint32 sample_count=0; + uint16 component_count=0; + uint32 palette_offset=0; + uint32 sample_offset=0; + uint32 i=0; + uint32 j=0; + size_t data_size; + sample_count=t2p->tiff_width*t2p->tiff_length; + component_count=t2p->tiff_samplesperpixel; + data_size=TIFFSafeMultiply(size_t,sample_count,component_count); + if( (data_size == 0U) || (t2p->tiff_datasize < 0) || + (data_size > (size_t) t2p->tiff_datasize) ) + { + TIFFError(TIFF2PDF_MODULE, + "Error: sample_count * component_count > t2p->tiff_datasize"); + t2p->t2p_error = T2P_ERR_ERROR; + return 1; + } + + for(i=sample_count;i>0;i--){ + palette_offset=buffer[i-1] * component_count; + sample_offset= (i-1) * component_count; + for(j=0;jpdf_palette[palette_offset+j]; + } + } + + return(0); +} + +/* + This functions converts in place a buffer of ABGR interleaved data + into RGB interleaved data, discarding A. +*/ + +tsize_t t2p_sample_abgr_to_rgb(tdata_t data, uint32 samplecount) +{ + uint32 i=0; + uint32 sample=0; + + for(i=0;i>8) & 0xff); + ((char*)data)[i*3+2]= (char) ((sample>>16) & 0xff); + } + + return(i*3); +} + +/* + * This functions converts in place a buffer of RGBA interleaved data + * into RGB interleaved data, discarding A. + */ + +tsize_t +t2p_sample_rgbaa_to_rgb(tdata_t data, uint32 samplecount) +{ + uint32 i; + + /* For the 3 first samples, there is overlapping between souce and + destination, so use memmove(). + See http://bugzilla.maptools.org/show_bug.cgi?id=2577 */ + for(i = 0; i < 3 && i < samplecount; i++) + memmove((uint8*)data + i * 3, (uint8*)data + i * 4, 3); + for(; i < samplecount; i++) + memcpy((uint8*)data + i * 3, (uint8*)data + i * 4, 3); + + return(i * 3); +} + +/* + * This functions converts in place a buffer of RGBA interleaved data + * into RGB interleaved data, adding 255-A to each component sample. + */ + +tsize_t +t2p_sample_rgba_to_rgb(tdata_t data, uint32 samplecount) +{ + uint32 i = 0; + uint32 sample = 0; + uint8 alpha = 0; + + for (i = 0; i < samplecount; i++) { + sample=((uint32*)data)[i]; + alpha=(uint8)((255 - ((sample >> 24) & 0xff))); + ((uint8 *)data)[i * 3] = (uint8) ((sample >> 16) & 0xff) + alpha; + ((uint8 *)data)[i * 3 + 1] = (uint8) ((sample >> 8) & 0xff) + alpha; + ((uint8 *)data)[i * 3 + 2] = (uint8) (sample & 0xff) + alpha; + } + + return (i * 3); +} + +/* + This function converts the a and b samples of Lab data from signed + to unsigned. +*/ + +tsize_t t2p_sample_lab_signed_to_unsigned(tdata_t buffer, uint32 samplecount){ + + uint32 i=0; + + for(i=0;ipdf_majorversion&0xff, + t2p->pdf_minorversion&0xff); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t)"\n%\342\343\317\323\n", 7); + + return(written); +} + +/* + This function writes the beginning of a PDF object to output. +*/ + +tsize_t t2p_write_pdf_obj_start(uint32 number, TIFF* output){ + + tsize_t written=0; + char buffer[32]; + int buflen=0; + + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)number); + check_snprintf_ret((T2P*)NULL, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen ); + written += t2pWriteFile(output, (tdata_t) " 0 obj\n", 7); + + return(written); +} + +/* + This function writes the end of a PDF object to output. +*/ + +tsize_t t2p_write_pdf_obj_end(TIFF* output){ + + tsize_t written=0; + + written += t2pWriteFile(output, (tdata_t) "endobj\n", 7); + + return(written); +} + +/* + This function writes a PDF name object to output. +*/ + +tsize_t t2p_write_pdf_name(unsigned char* name, TIFF* output){ + + tsize_t written=0; + uint32 i=0; + char buffer[64]; + uint16 nextchar=0; + size_t namelen=0; + + namelen = strlen((char *)name); + if (namelen>126) { + namelen=126; + } + written += t2pWriteFile(output, (tdata_t) "/", 1); + for (i=0;i 0x7E){ + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + nextchar=1; + } + if (nextchar==0){ + switch (name[i]){ + case 0x23: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x25: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x28: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x29: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x2F: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x3C: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x3E: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x5B: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x5D: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x7B: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + case 0x7D: + snprintf(buffer, sizeof(buffer), "#%.2X", name[i]); + buffer[sizeof(buffer) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) buffer, 3); + break; + default: + written += t2pWriteFile(output, (tdata_t) &name[i], 1); + } + } + nextchar=0; + } + written += t2pWriteFile(output, (tdata_t) " ", 1); + + return(written); +} + +/* + * This function writes a PDF string object to output. + */ + +tsize_t t2p_write_pdf_string(char* pdfstr, TIFF* output) +{ + tsize_t written = 0; + uint32 i = 0; + char buffer[64]; + size_t len = 0; + + len = strlen(pdfstr); + written += t2pWriteFile(output, (tdata_t) "(", 1); + for (i=0; i>\n", 4); + + return(written); +} + +/* + This function writes a number to output. +*/ + +tsize_t t2p_write_pdf_stream_length(tsize_t len, TIFF* output){ + + tsize_t written=0; + char buffer[32]; + int buflen=0; + + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)len); + check_snprintf_ret((T2P*)NULL, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + + return(written); +} + +/* + * This function writes the PDF Catalog structure to output. + */ + +tsize_t t2p_write_pdf_catalog(T2P* t2p, TIFF* output) +{ + tsize_t written = 0; + char buffer[32]; + int buflen = 0; + + written += t2pWriteFile(output, + (tdata_t)"<< \n/Type /Catalog \n/Pages ", + 27); + buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_pages); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, + TIFFmin((size_t)buflen, sizeof(buffer) - 1)); + written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6); + if(t2p->pdf_fitwindow){ + written += t2pWriteFile(output, + (tdata_t) "/ViewerPreferences <>\n", + 39); + } + written += t2pWriteFile(output, (tdata_t)">>\n", 3); + + return(written); +} + +/* + This function writes the PDF Info structure to output. +*/ + +tsize_t t2p_write_pdf_info(T2P* t2p, TIFF* input, TIFF* output) +{ + tsize_t written = 0; + char* info; + char buffer[512]; + + if(t2p->pdf_datetime[0] == '\0') + t2p_pdf_tifftime(t2p, input); + if (strlen(t2p->pdf_datetime) > 0) { + written += t2pWriteFile(output, (tdata_t) "<< \n/CreationDate ", 18); + written += t2p_write_pdf_string(t2p->pdf_datetime, output); + written += t2pWriteFile(output, (tdata_t) "\n/ModDate ", 10); + written += t2p_write_pdf_string(t2p->pdf_datetime, output); + } + written += t2pWriteFile(output, (tdata_t) "\n/Producer ", 11); + snprintf(buffer, sizeof(buffer), "libtiff / tiff2pdf - %d", TIFFLIB_VERSION); + written += t2p_write_pdf_string(buffer, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + if (t2p->pdf_creator[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Creator ", 9); + written += t2p_write_pdf_string(t2p->pdf_creator, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } else { + if (TIFFGetField(input, TIFFTAG_SOFTWARE, &info) != 0 && info) { + if(strlen(info) >= sizeof(t2p->pdf_creator)) + info[sizeof(t2p->pdf_creator) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) "/Creator ", 9); + written += t2p_write_pdf_string(info, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } + } + if (t2p->pdf_author[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Author ", 8); + written += t2p_write_pdf_string(t2p->pdf_author, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } else { + if ((TIFFGetField(input, TIFFTAG_ARTIST, &info) != 0 + || TIFFGetField(input, TIFFTAG_COPYRIGHT, &info) != 0) + && info) { + if (strlen(info) >= sizeof(t2p->pdf_author)) + info[sizeof(t2p->pdf_author) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) "/Author ", 8); + written += t2p_write_pdf_string(info, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } + } + if (t2p->pdf_title[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Title ", 7); + written += t2p_write_pdf_string(t2p->pdf_title, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } else { + if (TIFFGetField(input, TIFFTAG_DOCUMENTNAME, &info) != 0){ + if(strlen(info) > 511) { + info[512] = '\0'; + } + written += t2pWriteFile(output, (tdata_t) "/Title ", 7); + written += t2p_write_pdf_string(info, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } + } + if (t2p->pdf_subject[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Subject ", 9); + written += t2p_write_pdf_string(t2p->pdf_subject, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } else { + if (TIFFGetField(input, TIFFTAG_IMAGEDESCRIPTION, &info) != 0 && info) { + if (strlen(info) >= sizeof(t2p->pdf_subject)) + info[sizeof(t2p->pdf_subject) - 1] = '\0'; + written += t2pWriteFile(output, (tdata_t) "/Subject ", 9); + written += t2p_write_pdf_string(info, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } + } + if (t2p->pdf_keywords[0] != '\0') { + written += t2pWriteFile(output, (tdata_t) "/Keywords ", 10); + written += t2p_write_pdf_string(t2p->pdf_keywords, output); + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } + written += t2pWriteFile(output, (tdata_t) ">> \n", 4); + + return(written); +} + +/* + * This function fills a string of a T2P struct with the current time as a PDF + * date string, it is called by t2p_pdf_tifftime. + */ + +void t2p_pdf_currenttime(T2P* t2p) +{ + struct tm* currenttime; + time_t timenow; + + if (time(&timenow) == (time_t) -1) { + TIFFError(TIFF2PDF_MODULE, + "Can't get the current time: %s", strerror(errno)); + timenow = (time_t) 0; + } + + currenttime = localtime(&timenow); + snprintf(t2p->pdf_datetime, sizeof(t2p->pdf_datetime), + "D:%.4d%.2d%.2d%.2d%.2d%.2d", + (currenttime->tm_year + 1900) % 65536, + (currenttime->tm_mon + 1) % 256, + (currenttime->tm_mday) % 256, + (currenttime->tm_hour) % 256, + (currenttime->tm_min) % 256, + (currenttime->tm_sec) % 256); + + return; +} + +/* + * This function fills a string of a T2P struct with the date and time of a + * TIFF file if it exists or the current time as a PDF date string. + */ + +void t2p_pdf_tifftime(T2P* t2p, TIFF* input) +{ + char* datetime; + + if (TIFFGetField(input, TIFFTAG_DATETIME, &datetime) != 0 + && (strlen(datetime) >= 19) ){ + t2p->pdf_datetime[0]='D'; + t2p->pdf_datetime[1]=':'; + t2p->pdf_datetime[2]=datetime[0]; + t2p->pdf_datetime[3]=datetime[1]; + t2p->pdf_datetime[4]=datetime[2]; + t2p->pdf_datetime[5]=datetime[3]; + t2p->pdf_datetime[6]=datetime[5]; + t2p->pdf_datetime[7]=datetime[6]; + t2p->pdf_datetime[8]=datetime[8]; + t2p->pdf_datetime[9]=datetime[9]; + t2p->pdf_datetime[10]=datetime[11]; + t2p->pdf_datetime[11]=datetime[12]; + t2p->pdf_datetime[12]=datetime[14]; + t2p->pdf_datetime[13]=datetime[15]; + t2p->pdf_datetime[14]=datetime[17]; + t2p->pdf_datetime[15]=datetime[18]; + t2p->pdf_datetime[16] = '\0'; + } else { + t2p_pdf_currenttime(t2p); + } + + return; +} + +/* + * This function writes a PDF Pages Tree structure to output. + */ + +tsize_t t2p_write_pdf_pages(T2P* t2p, TIFF* output) +{ + tsize_t written=0; + tdir_t i=0; + char buffer[32]; + int buflen=0; + + int page=0; + written += t2pWriteFile(output, + (tdata_t) "<< \n/Type /Pages \n/Kids [ ", 26); + page = t2p->pdf_pages+1; + for (i=0;itiff_pagecount;i++){ + buflen=snprintf(buffer, sizeof(buffer), "%d", page); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); + if ( ((i+1)%8)==0 ) { + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } + page +=3; + page += t2p->tiff_pages[i].page_extra; + if(t2p->tiff_pages[i].page_tilecount>0){ + page += (2 * t2p->tiff_pages[i].page_tilecount); + } else { + page +=2; + } + } + written += t2pWriteFile(output, (tdata_t) "] \n/Count ", 10); + buflen=snprintf(buffer, sizeof(buffer), "%d", t2p->tiff_pagecount); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " \n>> \n", 6); + + return(written); +} + +/* + This function writes a PDF Page structure to output. +*/ + +tsize_t t2p_write_pdf_page(uint32 object, T2P* t2p, TIFF* output){ + + unsigned int i=0; + tsize_t written=0; + char buffer[256]; + int buflen=0; + + written += t2pWriteFile(output, (tdata_t) "<<\n/Type /Page \n/Parent ", 24); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_pages); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6); + written += t2pWriteFile(output, (tdata_t) "/MediaBox [", 11); + buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.x1); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " ", 1); + buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.y1); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " ", 1); + buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.x2); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " ", 1); + buflen=snprintf(buffer, sizeof(buffer), "%.4f",t2p->pdf_mediabox.y2); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "] \n", 3); + written += t2pWriteFile(output, (tdata_t) "/Contents ", 10); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(object + 1)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R \n", 6); + written += t2pWriteFile(output, (tdata_t) "/Resources << \n", 15); + if( t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount != 0 ){ + written += t2pWriteFile(output, (tdata_t) "/XObject <<\n", 12); + for(i=0;itiff_tiles[t2p->pdf_page].tiles_tilecount;i++){ + written += t2pWriteFile(output, (tdata_t) "/Im", 3); + buflen = snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_page+1); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "_", 1); + buflen = snprintf(buffer, sizeof(buffer), "%u", i+1); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " ", 1); + buflen = snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)(object+3+(2*i)+t2p->tiff_pages[t2p->pdf_page].page_extra)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); + if(i%4==3){ + written += t2pWriteFile(output, (tdata_t) "\n", 1); + } + } + written += t2pWriteFile(output, (tdata_t) ">>\n", 3); + } else { + written += t2pWriteFile(output, (tdata_t) "/XObject <<\n", 12); + written += t2pWriteFile(output, (tdata_t) "/Im", 3); + buflen = snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_page+1); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " ", 1); + buflen = snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)(object+3+(2*i)+t2p->tiff_pages[t2p->pdf_page].page_extra)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); + written += t2pWriteFile(output, (tdata_t) ">>\n", 3); + } + if(t2p->tiff_transferfunctioncount != 0) { + written += t2pWriteFile(output, (tdata_t) "/ExtGState <<", 13); + t2pWriteFile(output, (tdata_t) "/GS1 ", 5); + buflen = snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)(object + 3)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); + written += t2pWriteFile(output, (tdata_t) ">> \n", 4); + } + written += t2pWriteFile(output, (tdata_t) "/ProcSet [ ", 11); + if(t2p->pdf_colorspace & T2P_CS_BILEVEL + || t2p->pdf_colorspace & T2P_CS_GRAY + ){ + written += t2pWriteFile(output, (tdata_t) "/ImageB ", 8); + } else { + written += t2pWriteFile(output, (tdata_t) "/ImageC ", 8); + if(t2p->pdf_colorspace & T2P_CS_PALETTE){ + written += t2pWriteFile(output, (tdata_t) "/ImageI ", 8); + } + } + written += t2pWriteFile(output, (tdata_t) "]\n>>\n>>\n", 8); + + return(written); +} + +/* + This function composes the page size and image and tile locations on a page. +*/ + +void t2p_compose_pdf_page(T2P* t2p){ + + uint32 i=0; + uint32 i2=0; + T2P_TILE* tiles=NULL; + T2P_BOX* boxp=NULL; + uint32 tilecountx=0; + uint32 tilecounty=0; + uint32 tilewidth=0; + uint32 tilelength=0; + int istiled=0; + float f=0; + float width_ratio=0; + float length_ratio=0; + + t2p->pdf_xres = t2p->tiff_xres; + t2p->pdf_yres = t2p->tiff_yres; + if(t2p->pdf_overrideres) { + t2p->pdf_xres = t2p->pdf_defaultxres; + t2p->pdf_yres = t2p->pdf_defaultyres; + } + if(t2p->pdf_xres == 0.0) + t2p->pdf_xres = t2p->pdf_defaultxres; + if(t2p->pdf_yres == 0.0) + t2p->pdf_yres = t2p->pdf_defaultyres; + if (t2p->pdf_image_fillpage) { + width_ratio = t2p->pdf_defaultpagewidth/t2p->tiff_width; + length_ratio = t2p->pdf_defaultpagelength/t2p->tiff_length; + if (width_ratio < length_ratio ) { + t2p->pdf_imagewidth = t2p->pdf_defaultpagewidth; + t2p->pdf_imagelength = t2p->tiff_length * width_ratio; + } else { + t2p->pdf_imagewidth = t2p->tiff_width * length_ratio; + t2p->pdf_imagelength = t2p->pdf_defaultpagelength; + } + } else if (t2p->tiff_resunit != RESUNIT_CENTIMETER /* RESUNIT_NONE and */ + && t2p->tiff_resunit != RESUNIT_INCH) { /* other cases */ + t2p->pdf_imagewidth = ((float)(t2p->tiff_width))/t2p->pdf_xres; + t2p->pdf_imagelength = ((float)(t2p->tiff_length))/t2p->pdf_yres; + } else { + t2p->pdf_imagewidth = + ((float)(t2p->tiff_width))*PS_UNIT_SIZE/t2p->pdf_xres; + t2p->pdf_imagelength = + ((float)(t2p->tiff_length))*PS_UNIT_SIZE/t2p->pdf_yres; + } + if(t2p->pdf_overridepagesize != 0) { + t2p->pdf_pagewidth = t2p->pdf_defaultpagewidth; + t2p->pdf_pagelength = t2p->pdf_defaultpagelength; + } else { + t2p->pdf_pagewidth = t2p->pdf_imagewidth; + t2p->pdf_pagelength = t2p->pdf_imagelength; + } + t2p->pdf_mediabox.x1=0.0; + t2p->pdf_mediabox.y1=0.0; + t2p->pdf_mediabox.x2=t2p->pdf_pagewidth; + t2p->pdf_mediabox.y2=t2p->pdf_pagelength; + t2p->pdf_imagebox.x1=0.0; + t2p->pdf_imagebox.y1=0.0; + t2p->pdf_imagebox.x2=t2p->pdf_imagewidth; + t2p->pdf_imagebox.y2=t2p->pdf_imagelength; + if(t2p->pdf_overridepagesize!=0){ + t2p->pdf_imagebox.x1+=((t2p->pdf_pagewidth-t2p->pdf_imagewidth)/2.0F); + t2p->pdf_imagebox.y1+=((t2p->pdf_pagelength-t2p->pdf_imagelength)/2.0F); + t2p->pdf_imagebox.x2+=((t2p->pdf_pagewidth-t2p->pdf_imagewidth)/2.0F); + t2p->pdf_imagebox.y2+=((t2p->pdf_pagelength-t2p->pdf_imagelength)/2.0F); + } + if(t2p->tiff_orientation > 4){ + f=t2p->pdf_mediabox.x2; + t2p->pdf_mediabox.x2=t2p->pdf_mediabox.y2; + t2p->pdf_mediabox.y2=f; + } + istiled=((t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecount==0) ? 0 : 1; + if(istiled==0){ + t2p_compose_pdf_page_orient(&(t2p->pdf_imagebox), t2p->tiff_orientation); + return; + } else { + tilewidth=(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilewidth; + tilelength=(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilelength; + if( tilewidth > INT_MAX || + tilelength > INT_MAX || + t2p->tiff_width > INT_MAX - tilewidth || + t2p->tiff_length > INT_MAX - tilelength ) + { + TIFFError(TIFF2PDF_MODULE, "Integer overflow"); + t2p->t2p_error = T2P_ERR_ERROR; + return; + } + tilecountx=(t2p->tiff_width + + tilewidth -1)/ + tilewidth; + (t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecountx=tilecountx; + tilecounty=(t2p->tiff_length + + tilelength -1)/ + tilelength; + (t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecounty=tilecounty; + (t2p->tiff_tiles[t2p->pdf_page]).tiles_edgetilewidth= + t2p->tiff_width % tilewidth; + (t2p->tiff_tiles[t2p->pdf_page]).tiles_edgetilelength= + t2p->tiff_length % tilelength; + tiles=(t2p->tiff_tiles[t2p->pdf_page]).tiles_tiles; + for(i2=0;i2x1 = + t2p->pdf_imagebox.x1 + + ((float)(t2p->pdf_imagewidth * i * tilewidth) + / (float)t2p->tiff_width); + boxp->x2 = + t2p->pdf_imagebox.x1 + + ((float)(t2p->pdf_imagewidth * (i+1) * tilewidth) + / (float)t2p->tiff_width); + boxp->y1 = + t2p->pdf_imagebox.y2 + - ((float)(t2p->pdf_imagelength * (i2+1) * tilelength) + / (float)t2p->tiff_length); + boxp->y2 = + t2p->pdf_imagebox.y2 + - ((float)(t2p->pdf_imagelength * i2 * tilelength) + / (float)t2p->tiff_length); + } + boxp=&(tiles[i2*tilecountx+i].tile_box); + boxp->x1 = + t2p->pdf_imagebox.x1 + + ((float)(t2p->pdf_imagewidth * i * tilewidth) + / (float)t2p->tiff_width); + boxp->x2 = t2p->pdf_imagebox.x2; + boxp->y1 = + t2p->pdf_imagebox.y2 + - ((float)(t2p->pdf_imagelength * (i2+1) * tilelength) + / (float)t2p->tiff_length); + boxp->y2 = + t2p->pdf_imagebox.y2 + - ((float)(t2p->pdf_imagelength * i2 * tilelength) + / (float)t2p->tiff_length); + } + for(i=0;ix1 = + t2p->pdf_imagebox.x1 + + ((float)(t2p->pdf_imagewidth * i * tilewidth) + / (float)t2p->tiff_width); + boxp->x2 = + t2p->pdf_imagebox.x1 + + ((float)(t2p->pdf_imagewidth * (i+1) * tilewidth) + / (float)t2p->tiff_width); + boxp->y1 = t2p->pdf_imagebox.y1; + boxp->y2 = + t2p->pdf_imagebox.y2 + - ((float)(t2p->pdf_imagelength * i2 * tilelength) + / (float)t2p->tiff_length); + } + boxp=&(tiles[i2*tilecountx+i].tile_box); + boxp->x1 = + t2p->pdf_imagebox.x1 + + ((float)(t2p->pdf_imagewidth * i * tilewidth) + / (float)t2p->tiff_width); + boxp->x2 = t2p->pdf_imagebox.x2; + boxp->y1 = t2p->pdf_imagebox.y1; + boxp->y2 = + t2p->pdf_imagebox.y2 + - ((float)(t2p->pdf_imagelength * i2 * tilelength) + / (float)t2p->tiff_length); + } + if(t2p->tiff_orientation==0 || t2p->tiff_orientation==1){ + for(i=0;i<(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecount;i++){ + t2p_compose_pdf_page_orient( &(tiles[i].tile_box) , 0); + } + return; + } + for(i=0;i<(t2p->tiff_tiles[t2p->pdf_page]).tiles_tilecount;i++){ + boxp=&(tiles[i].tile_box); + boxp->x1 -= t2p->pdf_imagebox.x1; + boxp->x2 -= t2p->pdf_imagebox.x1; + boxp->y1 -= t2p->pdf_imagebox.y1; + boxp->y2 -= t2p->pdf_imagebox.y1; + if(t2p->tiff_orientation==2 || t2p->tiff_orientation==3){ + boxp->x1 = t2p->pdf_imagebox.x2 - t2p->pdf_imagebox.x1 - boxp->x1; + boxp->x2 = t2p->pdf_imagebox.x2 - t2p->pdf_imagebox.x1 - boxp->x2; + } + if(t2p->tiff_orientation==3 || t2p->tiff_orientation==4){ + boxp->y1 = t2p->pdf_imagebox.y2 - t2p->pdf_imagebox.y1 - boxp->y1; + boxp->y2 = t2p->pdf_imagebox.y2 - t2p->pdf_imagebox.y1 - boxp->y2; + } + if(t2p->tiff_orientation==8 || t2p->tiff_orientation==5){ + boxp->y1 = t2p->pdf_imagebox.y2 - t2p->pdf_imagebox.y1 - boxp->y1; + boxp->y2 = t2p->pdf_imagebox.y2 - t2p->pdf_imagebox.y1 - boxp->y2; + } + if(t2p->tiff_orientation==5 || t2p->tiff_orientation==6){ + boxp->x1 = t2p->pdf_imagebox.x2 - t2p->pdf_imagebox.x1 - boxp->x1; + boxp->x2 = t2p->pdf_imagebox.x2 - t2p->pdf_imagebox.x1 - boxp->x2; + } + if(t2p->tiff_orientation > 4){ + f=boxp->x1; + boxp->x1 = boxp->y1; + boxp->y1 = f; + f=boxp->x2; + boxp->x2 = boxp->y2; + boxp->y2 = f; + t2p_compose_pdf_page_orient_flip(boxp, t2p->tiff_orientation); + } else { + t2p_compose_pdf_page_orient(boxp, t2p->tiff_orientation); + } + + } + + return; +} + +void t2p_compose_pdf_page_orient(T2P_BOX* boxp, uint16 orientation){ + + float m1[9]; + float f=0.0; + + if( boxp->x1 > boxp->x2){ + f=boxp->x1; + boxp->x1=boxp->x2; + boxp->x2 = f; + } + if( boxp->y1 > boxp->y2){ + f=boxp->y1; + boxp->y1=boxp->y2; + boxp->y2 = f; + } + boxp->mat[0]=m1[0]=boxp->x2-boxp->x1; + boxp->mat[1]=m1[1]=0.0; + boxp->mat[2]=m1[2]=0.0; + boxp->mat[3]=m1[3]=0.0; + boxp->mat[4]=m1[4]=boxp->y2-boxp->y1; + boxp->mat[5]=m1[5]=0.0; + boxp->mat[6]=m1[6]=boxp->x1; + boxp->mat[7]=m1[7]=boxp->y1; + boxp->mat[8]=m1[8]=1.0; + switch(orientation){ + case 0: + case 1: + break; + case 2: + boxp->mat[0]=0.0F-m1[0]; + boxp->mat[6]+=m1[0]; + break; + case 3: + boxp->mat[0]=0.0F-m1[0]; + boxp->mat[4]=0.0F-m1[4]; + boxp->mat[6]+=m1[0]; + boxp->mat[7]+=m1[4]; + break; + case 4: + boxp->mat[4]=0.0F-m1[4]; + boxp->mat[7]+=m1[4]; + break; + case 5: + boxp->mat[0]=0.0F; + boxp->mat[1]=0.0F-m1[0]; + boxp->mat[3]=0.0F-m1[4]; + boxp->mat[4]=0.0F; + boxp->mat[6]+=m1[4]; + boxp->mat[7]+=m1[0]; + break; + case 6: + boxp->mat[0]=0.0F; + boxp->mat[1]=0.0F-m1[0]; + boxp->mat[3]=m1[4]; + boxp->mat[4]=0.0F; + boxp->mat[7]+=m1[0]; + break; + case 7: + boxp->mat[0]=0.0F; + boxp->mat[1]=m1[0]; + boxp->mat[3]=m1[4]; + boxp->mat[4]=0.0F; + break; + case 8: + boxp->mat[0]=0.0F; + boxp->mat[1]=m1[0]; + boxp->mat[3]=0.0F-m1[4]; + boxp->mat[4]=0.0F; + boxp->mat[6]+=m1[4]; + break; + } + + return; +} + +void t2p_compose_pdf_page_orient_flip(T2P_BOX* boxp, uint16 orientation){ + + float m1[9]; + float f=0.0; + + if( boxp->x1 > boxp->x2){ + f=boxp->x1; + boxp->x1=boxp->x2; + boxp->x2 = f; + } + if( boxp->y1 > boxp->y2){ + f=boxp->y1; + boxp->y1=boxp->y2; + boxp->y2 = f; + } + boxp->mat[0]=m1[0]=boxp->x2-boxp->x1; + boxp->mat[1]=m1[1]=0.0F; + boxp->mat[2]=m1[2]=0.0F; + boxp->mat[3]=m1[3]=0.0F; + boxp->mat[4]=m1[4]=boxp->y2-boxp->y1; + boxp->mat[5]=m1[5]=0.0F; + boxp->mat[6]=m1[6]=boxp->x1; + boxp->mat[7]=m1[7]=boxp->y1; + boxp->mat[8]=m1[8]=1.0F; + switch(orientation){ + case 5: + boxp->mat[0]=0.0F; + boxp->mat[1]=0.0F-m1[4]; + boxp->mat[3]=0.0F-m1[0]; + boxp->mat[4]=0.0F; + boxp->mat[6]+=m1[0]; + boxp->mat[7]+=m1[4]; + break; + case 6: + boxp->mat[0]=0.0F; + boxp->mat[1]=0.0F-m1[4]; + boxp->mat[3]=m1[0]; + boxp->mat[4]=0.0F; + boxp->mat[7]+=m1[4]; + break; + case 7: + boxp->mat[0]=0.0F; + boxp->mat[1]=m1[4]; + boxp->mat[3]=m1[0]; + boxp->mat[4]=0.0F; + break; + case 8: + boxp->mat[0]=0.0F; + boxp->mat[1]=m1[4]; + boxp->mat[3]=0.0F-m1[0]; + boxp->mat[4]=0.0F; + boxp->mat[6]+=m1[0]; + break; + } + + return; +} + +/* + This function writes a PDF Contents stream to output. +*/ + +tsize_t t2p_write_pdf_page_content_stream(T2P* t2p, TIFF* output){ + + tsize_t written=0; + ttile_t i=0; + char buffer[512]; + int buflen=0; + T2P_BOX box; + + if(t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount>0){ + for(i=0;itiff_tiles[t2p->pdf_page].tiles_tilecount; i++){ + box=t2p->tiff_tiles[t2p->pdf_page].tiles_tiles[i].tile_box; + buflen=snprintf(buffer, sizeof(buffer), + "q %s %.4f %.4f %.4f %.4f %.4f %.4f cm /Im%d_%ld Do Q\n", + t2p->tiff_transferfunctioncount?"/GS1 gs ":"", + box.mat[0], + box.mat[1], + box.mat[3], + box.mat[4], + box.mat[6], + box.mat[7], + t2p->pdf_page + 1, + (long)(i + 1)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2p_write_pdf_stream(buffer, buflen, output); + } + } else { + box=t2p->pdf_imagebox; + buflen=snprintf(buffer, sizeof(buffer), + "q %s %.4f %.4f %.4f %.4f %.4f %.4f cm /Im%d Do Q\n", + t2p->tiff_transferfunctioncount?"/GS1 gs ":"", + box.mat[0], + box.mat[1], + box.mat[3], + box.mat[4], + box.mat[6], + box.mat[7], + t2p->pdf_page+1); + check_snprintf_ret(t2p, buflen, buffer); + written += t2p_write_pdf_stream(buffer, buflen, output); + } + + return(written); +} + +/* + This function writes a PDF Image XObject stream dictionary to output. +*/ + +tsize_t t2p_write_pdf_xobject_stream_dict(ttile_t tile, + T2P* t2p, + TIFF* output){ + + tsize_t written=0; + char buffer[32]; + int buflen=0; + + written += t2p_write_pdf_stream_dict(0, t2p->pdf_xrefcount+1, output); + written += t2pWriteFile(output, + (tdata_t) "/Type /XObject \n/Subtype /Image \n/Name /Im", + 42); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_page+1); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + if(tile != 0){ + written += t2pWriteFile(output, (tdata_t) "_", 1); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)tile); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + } + written += t2pWriteFile(output, (tdata_t) "\n/Width ", 8); + if(tile==0){ + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_width); + } else { + if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)!=0){ + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth); + } else { + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth); + } + } + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "\n/Height ", 9); + if(tile==0){ + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->tiff_length); + } else { + if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)!=0){ + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength); + } else { + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); + } + } + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "\n/BitsPerComponent ", 19); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->tiff_bitspersample); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "\n/ColorSpace ", 13); + written += t2p_write_pdf_xobject_cs(t2p, output); + if (t2p->pdf_image_interpolate) + written += t2pWriteFile(output, + (tdata_t) "\n/Interpolate true", 18); + if( (t2p->pdf_switchdecode != 0) +#ifdef CCITT_SUPPORT + && ! (t2p->pdf_colorspace & T2P_CS_BILEVEL + && t2p->pdf_compression == T2P_COMPRESS_G4) +#endif + ){ + written += t2p_write_pdf_xobject_decode(t2p, output); + } + written += t2p_write_pdf_xobject_stream_filter(tile, t2p, output); + + return(written); +} + +/* + * This function writes a PDF Image XObject Colorspace name to output. + */ + + +tsize_t t2p_write_pdf_xobject_cs(T2P* t2p, TIFF* output){ + + tsize_t written=0; + char buffer[128]; + int buflen=0; + + float X_W=1.0; + float Y_W=1.0; + float Z_W=1.0; + + if( (t2p->pdf_colorspace & T2P_CS_ICCBASED) != 0){ + written += t2p_write_pdf_xobject_icccs(t2p, output); + return(written); + } + if( (t2p->pdf_colorspace & T2P_CS_PALETTE) != 0){ + written += t2pWriteFile(output, (tdata_t) "[ /Indexed ", 11); + t2p->pdf_colorspace ^= T2P_CS_PALETTE; + written += t2p_write_pdf_xobject_cs(t2p, output); + t2p->pdf_colorspace |= T2P_CS_PALETTE; + buflen=snprintf(buffer, sizeof(buffer), "%u", (0x0001 << t2p->tiff_bitspersample)-1 ); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " ", 1); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_palettecs ); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R ]\n", 7); + return(written); + } + if(t2p->pdf_colorspace & T2P_CS_BILEVEL){ + written += t2pWriteFile(output, (tdata_t) "/DeviceGray \n", 13); + } + if(t2p->pdf_colorspace & T2P_CS_GRAY){ + if(t2p->pdf_colorspace & T2P_CS_CALGRAY){ + written += t2p_write_pdf_xobject_calcs(t2p, output); + } else { + written += t2pWriteFile(output, (tdata_t) "/DeviceGray \n", 13); + } + } + if(t2p->pdf_colorspace & T2P_CS_RGB){ + if(t2p->pdf_colorspace & T2P_CS_CALRGB){ + written += t2p_write_pdf_xobject_calcs(t2p, output); + } else { + written += t2pWriteFile(output, (tdata_t) "/DeviceRGB \n", 12); + } + } + if(t2p->pdf_colorspace & T2P_CS_CMYK){ + written += t2pWriteFile(output, (tdata_t) "/DeviceCMYK \n", 13); + } + if(t2p->pdf_colorspace & T2P_CS_LAB){ + written += t2pWriteFile(output, (tdata_t) "[/Lab << \n", 10); + written += t2pWriteFile(output, (tdata_t) "/WhitePoint ", 12); + X_W = t2p->tiff_whitechromaticities[0]; + Y_W = t2p->tiff_whitechromaticities[1]; + Z_W = 1.0F - (X_W + Y_W); + X_W /= Y_W; + Z_W /= Y_W; + Y_W = 1.0F; + buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "/Range ", 7); + buflen=snprintf(buffer, sizeof(buffer), "[%d %d %d %d] \n", + t2p->pdf_labrange[0], + t2p->pdf_labrange[1], + t2p->pdf_labrange[2], + t2p->pdf_labrange[3]); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) ">>] \n", 5); + + } + + return(written); +} + +tsize_t t2p_write_pdf_transfer(T2P* t2p, TIFF* output){ + + tsize_t written=0; + char buffer[32]; + int buflen=0; + + written += t2pWriteFile(output, (tdata_t) "<< /Type /ExtGState \n/TR ", 25); + if(t2p->tiff_transferfunctioncount == 1){ + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)(t2p->pdf_xrefcount + 1)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); + } else { + written += t2pWriteFile(output, (tdata_t) "[ ", 2); + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)(t2p->pdf_xrefcount + 1)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)(t2p->pdf_xrefcount + 2)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)(t2p->pdf_xrefcount + 3)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R ", 5); + written += t2pWriteFile(output, (tdata_t) "/Identity ] ", 12); + } + + written += t2pWriteFile(output, (tdata_t) " >> \n", 5); + + return(written); +} + +tsize_t t2p_write_pdf_transfer_dict(T2P* t2p, TIFF* output, uint16 i){ + + tsize_t written=0; + char buffer[32]; + int buflen=0; + (void)i; /* XXX */ + + written += t2pWriteFile(output, (tdata_t) "/FunctionType 0 \n", 17); + written += t2pWriteFile(output, (tdata_t) "/Domain [0.0 1.0] \n", 19); + written += t2pWriteFile(output, (tdata_t) "/Range [0.0 1.0] \n", 18); + buflen=snprintf(buffer, sizeof(buffer), "/Size [%u] \n", (1<tiff_bitspersample)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "/BitsPerSample 16 \n", 19); + written += t2p_write_pdf_stream_dict(((tsize_t)1)<<(t2p->tiff_bitspersample+1), 0, output); + + return(written); +} + +tsize_t t2p_write_pdf_transfer_stream(T2P* t2p, TIFF* output, uint16 i){ + + tsize_t written=0; + + written += t2p_write_pdf_stream( + t2p->tiff_transferfunction[i], + (((tsize_t)1)<<(t2p->tiff_bitspersample+1)), + output); + + return(written); +} + +/* + This function writes a PDF Image XObject Colorspace array to output. +*/ + +tsize_t t2p_write_pdf_xobject_calcs(T2P* t2p, TIFF* output){ + + tsize_t written=0; + char buffer[256]; + int buflen=0; + + float X_W=0.0; + float Y_W=0.0; + float Z_W=0.0; + float X_R=0.0; + float Y_R=0.0; + float Z_R=0.0; + float X_G=0.0; + float Y_G=0.0; + float Z_G=0.0; + float X_B=0.0; + float Y_B=0.0; + float Z_B=0.0; + float x_w=0.0; + float y_w=0.0; + float z_w=0.0; + float x_r=0.0; + float y_r=0.0; + float x_g=0.0; + float y_g=0.0; + float x_b=0.0; + float y_b=0.0; + float R=1.0; + float G=1.0; + float B=1.0; + + written += t2pWriteFile(output, (tdata_t) "[", 1); + if(t2p->pdf_colorspace & T2P_CS_CALGRAY){ + written += t2pWriteFile(output, (tdata_t) "/CalGray ", 9); + X_W = t2p->tiff_whitechromaticities[0]; + Y_W = t2p->tiff_whitechromaticities[1]; + Z_W = 1.0F - (X_W + Y_W); + X_W /= Y_W; + Z_W /= Y_W; + Y_W = 1.0F; + } + if(t2p->pdf_colorspace & T2P_CS_CALRGB){ + written += t2pWriteFile(output, (tdata_t) "/CalRGB ", 8); + x_w = t2p->tiff_whitechromaticities[0]; + y_w = t2p->tiff_whitechromaticities[1]; + x_r = t2p->tiff_primarychromaticities[0]; + y_r = t2p->tiff_primarychromaticities[1]; + x_g = t2p->tiff_primarychromaticities[2]; + y_g = t2p->tiff_primarychromaticities[3]; + x_b = t2p->tiff_primarychromaticities[4]; + y_b = t2p->tiff_primarychromaticities[5]; + z_w = y_w * ((x_g - x_b)*y_r - (x_r-x_b)*y_g + (x_r-x_g)*y_b); + Y_R = (y_r/R) * ((x_g-x_b)*y_w - (x_w-x_b)*y_g + (x_w-x_g)*y_b) / z_w; + X_R = Y_R * x_r / y_r; + Z_R = Y_R * (((1-x_r)/y_r)-1); + Y_G = ((0.0F-(y_g))/G) * ((x_r-x_b)*y_w - (x_w-x_b)*y_r + (x_w-x_r)*y_b) / z_w; + X_G = Y_G * x_g / y_g; + Z_G = Y_G * (((1-x_g)/y_g)-1); + Y_B = (y_b/B) * ((x_r-x_g)*y_w - (x_w-x_g)*y_r + (x_w-x_r)*y_g) / z_w; + X_B = Y_B * x_b / y_b; + Z_B = Y_B * (((1-x_b)/y_b)-1); + X_W = (X_R * R) + (X_G * G) + (X_B * B); + Y_W = (Y_R * R) + (Y_G * G) + (Y_B * B); + Z_W = (Z_R * R) + (Z_G * G) + (Z_B * B); + X_W /= Y_W; + Z_W /= Y_W; + Y_W = 1.0; + } + written += t2pWriteFile(output, (tdata_t) "<< \n", 4); + if(t2p->pdf_colorspace & T2P_CS_CALGRAY){ + written += t2pWriteFile(output, (tdata_t) "/WhitePoint ", 12); + buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "/Gamma 2.2 \n", 12); + } + if(t2p->pdf_colorspace & T2P_CS_CALRGB){ + written += t2pWriteFile(output, (tdata_t) "/WhitePoint ", 12); + buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f] \n", X_W, Y_W, Z_W); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "/Matrix ", 8); + buflen=snprintf(buffer, sizeof(buffer), "[%.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f] \n", + X_R, Y_R, Z_R, + X_G, Y_G, Z_G, + X_B, Y_B, Z_B); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "/Gamma [2.2 2.2 2.2] \n", 22); + } + written += t2pWriteFile(output, (tdata_t) ">>] \n", 5); + + return(written); +} + +/* + This function writes a PDF Image XObject Colorspace array to output. +*/ + +tsize_t t2p_write_pdf_xobject_icccs(T2P* t2p, TIFF* output){ + + tsize_t written=0; + char buffer[32]; + int buflen=0; + + written += t2pWriteFile(output, (tdata_t) "[/ICCBased ", 11); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_icccs); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R] \n", 7); + + return(written); +} + +tsize_t t2p_write_pdf_xobject_icccs_dict(T2P* t2p, TIFF* output){ + + tsize_t written=0; + char buffer[32]; + int buflen=0; + + written += t2pWriteFile(output, (tdata_t) "/N ", 3); + buflen=snprintf(buffer, sizeof(buffer), "%u \n", t2p->tiff_samplesperpixel); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "/Alternate ", 11); + t2p->pdf_colorspace ^= T2P_CS_ICCBASED; + written += t2p_write_pdf_xobject_cs(t2p, output); + t2p->pdf_colorspace |= T2P_CS_ICCBASED; + written += t2p_write_pdf_stream_dict(t2p->tiff_iccprofilelength, 0, output); + + return(written); +} + +tsize_t t2p_write_pdf_xobject_icccs_stream(T2P* t2p, TIFF* output){ + + tsize_t written=0; + + written += t2p_write_pdf_stream( + (tdata_t) t2p->tiff_iccprofile, + (tsize_t) t2p->tiff_iccprofilelength, + output); + + return(written); +} + +/* + This function writes a palette stream for an indexed color space to output. +*/ + +tsize_t t2p_write_pdf_xobject_palettecs_stream(T2P* t2p, TIFF* output){ + + tsize_t written=0; + + written += t2p_write_pdf_stream( + (tdata_t) t2p->pdf_palette, + (tsize_t) t2p->pdf_palettesize, + output); + + return(written); +} + +/* + This function writes a PDF Image XObject Decode array to output. +*/ + +tsize_t t2p_write_pdf_xobject_decode(T2P* t2p, TIFF* output){ + + tsize_t written=0; + int i=0; + + written += t2pWriteFile(output, (tdata_t) "/Decode [ ", 10); + for (i=0;itiff_samplesperpixel;i++){ + written += t2pWriteFile(output, (tdata_t) "1 0 ", 4); + } + written += t2pWriteFile(output, (tdata_t) "]\n", 2); + + return(written); +} + +/* + This function writes a PDF Image XObject stream filter name and parameters to + output. +*/ + +tsize_t t2p_write_pdf_xobject_stream_filter(ttile_t tile, T2P* t2p, TIFF* output){ + + tsize_t written=0; + char buffer[32]; + int buflen=0; + + if(t2p->pdf_compression==T2P_COMPRESS_NONE){ + return(written); + } + written += t2pWriteFile(output, (tdata_t) "/Filter ", 8); + switch(t2p->pdf_compression){ +#ifdef CCITT_SUPPORT + case T2P_COMPRESS_G4: + written += t2pWriteFile(output, (tdata_t) "/CCITTFaxDecode ", 16); + written += t2pWriteFile(output, (tdata_t) "/DecodeParms ", 13); + written += t2pWriteFile(output, (tdata_t) "<< /K -1 ", 9); + if(tile==0){ + written += t2pWriteFile(output, (tdata_t) "/Columns ", 9); + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_width); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " /Rows ", 7); + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_length); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + } else { + if(t2p_tile_is_right_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)==0){ + written += t2pWriteFile(output, (tdata_t) "/Columns ", 9); + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilewidth); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + } else { + written += t2pWriteFile(output, (tdata_t) "/Columns ", 9); + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilewidth); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + } + if(t2p_tile_is_bottom_edge(t2p->tiff_tiles[t2p->pdf_page], tile-1)==0){ + written += t2pWriteFile(output, (tdata_t) " /Rows ", 7); + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_tilelength); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + } else { + written += t2pWriteFile(output, (tdata_t) " /Rows ", 7); + buflen=snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_tiles[t2p->pdf_page].tiles_edgetilelength); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + } + } + if(t2p->pdf_switchdecode == 0){ + written += t2pWriteFile(output, (tdata_t) " /BlackIs1 true ", 16); + } + written += t2pWriteFile(output, (tdata_t) ">>\n", 3); + break; +#endif +#ifdef JPEG_SUPPORT + case T2P_COMPRESS_JPEG: + written += t2pWriteFile(output, (tdata_t) "/DCTDecode ", 11); + + if(t2p->tiff_photometric != PHOTOMETRIC_YCBCR) { + written += t2pWriteFile(output, (tdata_t) "/DecodeParms ", 13); + written += t2pWriteFile(output, (tdata_t) "<< /ColorTransform 1 >>\n", 24); + } + break; +#endif +#ifdef ZIP_SUPPORT + case T2P_COMPRESS_ZIP: + written += t2pWriteFile(output, (tdata_t) "/FlateDecode ", 13); + if(t2p->pdf_compressionquality%100){ + written += t2pWriteFile(output, (tdata_t) "/DecodeParms ", 13); + written += t2pWriteFile(output, (tdata_t) "<< /Predictor ", 14); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->pdf_compressionquality%100); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " /Columns ", 10); + buflen = snprintf(buffer, sizeof(buffer), "%lu", + (unsigned long)t2p->tiff_width); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " /Colors ", 9); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->tiff_samplesperpixel); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " /BitsPerComponent ", 19); + buflen=snprintf(buffer, sizeof(buffer), "%u", t2p->tiff_bitspersample); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) ">>\n", 3); + } + break; +#endif + default: + break; + } + + return(written); +} + +/* + This function writes a PDF xref table to output. +*/ + +tsize_t t2p_write_pdf_xreftable(T2P* t2p, TIFF* output){ + + tsize_t written=0; + char buffer[64]; + int buflen=0; + uint32 i=0; + + written += t2pWriteFile(output, (tdata_t) "xref\n0 ", 7); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount + 1)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " \n0000000000 65535 f \n", 22); + for (i=0;ipdf_xrefcount;i++){ + snprintf(buffer, sizeof(buffer), "%.10lu 00000 n \n", + (unsigned long)t2p->pdf_xrefoffsets[i]); + written += t2pWriteFile(output, (tdata_t) buffer, 20); + } + + return(written); +} + +/* + * This function writes a PDF trailer to output. + */ + +tsize_t t2p_write_pdf_trailer(T2P* t2p, TIFF* output) +{ + + tsize_t written = 0; + char buffer[32]; + int buflen = 0; + size_t i = 0; + + for (i = 0; i < sizeof(t2p->pdf_fileid) - 8; i += 8) + snprintf(t2p->pdf_fileid + i, 9, "%.8X", rand()); + + written += t2pWriteFile(output, (tdata_t) "trailer\n<<\n/Size ", 17); + buflen = snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)(t2p->pdf_xrefcount+1)); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "\n/Root ", 7); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_catalog); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R \n/Info ", 12); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_info); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) " 0 R \n/ID[<", 11); + written += t2pWriteFile(output, (tdata_t) t2p->pdf_fileid, + sizeof(t2p->pdf_fileid) - 1); + written += t2pWriteFile(output, (tdata_t) "><", 2); + written += t2pWriteFile(output, (tdata_t) t2p->pdf_fileid, + sizeof(t2p->pdf_fileid) - 1); + written += t2pWriteFile(output, (tdata_t) ">]\n>>\nstartxref\n", 16); + buflen=snprintf(buffer, sizeof(buffer), "%lu", (unsigned long)t2p->pdf_startxref); + check_snprintf_ret(t2p, buflen, buffer); + written += t2pWriteFile(output, (tdata_t) buffer, buflen); + written += t2pWriteFile(output, (tdata_t) "\n%%EOF\n", 7); + + return(written); +} + +/* + + This function writes a PDF to a file given a pointer to a TIFF. + + The idea with using a TIFF* as output for a PDF file is that the file + can be created with TIFFClientOpen for memory-mapped use within the TIFF + library, and TIFFWriteEncodedStrip can be used to write compressed data to + the output. The output is not actually a TIFF file, it is a PDF file. + + This function uses only t2pWriteFile and TIFFWriteEncodedStrip to write to + the output TIFF file. When libtiff would otherwise be writing data to the + output file, the write procedure of the TIFF structure is replaced with an + empty implementation. + + The first argument to the function is an initialized and validated T2P + context struct pointer. + + The second argument to the function is the TIFF* that is the input that has + been opened for reading and no other functions have been called upon it. + + The third argument to the function is the TIFF* that is the output that has + been opened for writing. It has to be opened so that it hasn't written any + data to the output. If the output is seekable then it's OK to seek to the + beginning of the file. The function only writes to the output PDF and does + not seek. See the example usage in the main() function. + + TIFF* output = TIFFOpen("output.pdf", "w"); + assert(output != NULL); + + if(output->tif_seekproc != NULL){ + t2pSeekFile(output, (toff_t) 0, SEEK_SET); + } + + This function returns the file size of the output PDF file. On error it + returns zero and the t2p->t2p_error variable is set to T2P_ERR_ERROR. + + After this function completes, call t2p_free on t2p, TIFFClose on input, + and TIFFClose on output. +*/ + +tsize_t t2p_write_pdf(T2P* t2p, TIFF* input, TIFF* output){ + + tsize_t written=0; + ttile_t i2=0; + tsize_t streamlen=0; + uint16 i=0; + + t2p_read_tiff_init(t2p, input); + if(t2p->t2p_error!=T2P_ERR_OK){return(0);} + t2p->pdf_xrefoffsets= (uint32*) _TIFFmalloc(TIFFSafeMultiply(tmsize_t,t2p->pdf_xrefcount,sizeof(uint32)) ); + if(t2p->pdf_xrefoffsets==NULL){ + TIFFError( + TIFF2PDF_MODULE, + "Can't allocate %u bytes of memory for t2p_write_pdf", + (unsigned int) (t2p->pdf_xrefcount * sizeof(uint32)) ); + t2p->t2p_error = T2P_ERR_ERROR; + return(written); + } + t2p->pdf_xrefcount=0; + t2p->pdf_catalog=1; + t2p->pdf_info=2; + t2p->pdf_pages=3; + written += t2p_write_pdf_header(t2p, output); + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + t2p->pdf_catalog=t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_catalog(t2p, output); + written += t2p_write_pdf_obj_end(output); + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + t2p->pdf_info=t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_info(t2p, input, output); + written += t2p_write_pdf_obj_end(output); + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + t2p->pdf_pages=t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_pages(t2p, output); + written += t2p_write_pdf_obj_end(output); + for(t2p->pdf_page=0;t2p->pdf_pagetiff_pagecount;t2p->pdf_page++){ + t2p_read_tiff_data(t2p, input); + if(t2p->t2p_error!=T2P_ERR_OK){return(0);} + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_page(t2p->pdf_xrefcount, t2p, output); + written += t2p_write_pdf_obj_end(output); + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += t2p_write_pdf_stream_dict(0, t2p->pdf_xrefcount+1, output); + written += t2p_write_pdf_stream_dict_end(output); + written += t2p_write_pdf_stream_start(output); + streamlen=written; + written += t2p_write_pdf_page_content_stream(t2p, output); + streamlen=written-streamlen; + written += t2p_write_pdf_stream_end(output); + written += t2p_write_pdf_obj_end(output); + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_length(streamlen, output); + written += t2p_write_pdf_obj_end(output); + if(t2p->tiff_transferfunctioncount != 0){ + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_transfer(t2p, output); + written += t2p_write_pdf_obj_end(output); + for(i=0; i < t2p->tiff_transferfunctioncount; i++){ + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += t2p_write_pdf_transfer_dict(t2p, output, i); + written += t2p_write_pdf_stream_dict_end(output); + written += t2p_write_pdf_stream_start(output); + /* streamlen=written; */ /* value not used */ + written += t2p_write_pdf_transfer_stream(t2p, output, i); + /* streamlen=written-streamlen; */ /* value not used */ + written += t2p_write_pdf_stream_end(output); + written += t2p_write_pdf_obj_end(output); + } + } + if( (t2p->pdf_colorspace & T2P_CS_PALETTE) != 0){ + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + t2p->pdf_palettecs=t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += t2p_write_pdf_stream_dict(t2p->pdf_palettesize, 0, output); + written += t2p_write_pdf_stream_dict_end(output); + written += t2p_write_pdf_stream_start(output); + /* streamlen=written; */ /* value not used */ + written += t2p_write_pdf_xobject_palettecs_stream(t2p, output); + /* streamlen=written-streamlen; */ /* value not used */ + written += t2p_write_pdf_stream_end(output); + written += t2p_write_pdf_obj_end(output); + } + if( (t2p->pdf_colorspace & T2P_CS_ICCBASED) != 0){ + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + t2p->pdf_icccs=t2p->pdf_xrefcount; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += t2p_write_pdf_xobject_icccs_dict(t2p, output); + written += t2p_write_pdf_stream_dict_end(output); + written += t2p_write_pdf_stream_start(output); + /* streamlen=written; */ /* value not used */ + written += t2p_write_pdf_xobject_icccs_stream(t2p, output); + /* streamlen=written-streamlen; */ /* value not used */ + written += t2p_write_pdf_stream_end(output); + written += t2p_write_pdf_obj_end(output); + } + if(t2p->tiff_tiles[t2p->pdf_page].tiles_tilecount !=0){ + for(i2=0;i2tiff_tiles[t2p->pdf_page].tiles_tilecount;i2++){ + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += t2p_write_pdf_xobject_stream_dict( + i2+1, + t2p, + output); + written += t2p_write_pdf_stream_dict_end(output); + written += t2p_write_pdf_stream_start(output); + streamlen=written; + t2p_read_tiff_size_tile(t2p, input, i2); + written += t2p_readwrite_pdf_image_tile(t2p, input, output, i2); + t2p_write_advance_directory(t2p, output); + if(t2p->t2p_error!=T2P_ERR_OK){return(0);} + streamlen=written-streamlen; + written += t2p_write_pdf_stream_end(output); + written += t2p_write_pdf_obj_end(output); + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_length(streamlen, output); + written += t2p_write_pdf_obj_end(output); + } + } else { + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_dict_start(output); + written += t2p_write_pdf_xobject_stream_dict( + 0, + t2p, + output); + written += t2p_write_pdf_stream_dict_end(output); + written += t2p_write_pdf_stream_start(output); + streamlen=written; + t2p_read_tiff_size(t2p, input); + written += t2p_readwrite_pdf_image(t2p, input, output); + t2p_write_advance_directory(t2p, output); + if(t2p->t2p_error!=T2P_ERR_OK){return(0);} + streamlen=written-streamlen; + written += t2p_write_pdf_stream_end(output); + written += t2p_write_pdf_obj_end(output); + t2p->pdf_xrefoffsets[t2p->pdf_xrefcount++]=written; + written += t2p_write_pdf_obj_start(t2p->pdf_xrefcount, output); + written += t2p_write_pdf_stream_length(streamlen, output); + written += t2p_write_pdf_obj_end(output); + } + } + t2p->pdf_startxref = written; + written += t2p_write_pdf_xreftable(t2p, output); + written += t2p_write_pdf_trailer(t2p, output); + t2p_disable(output); + + return(written); +} + +/* vim: set ts=8 sts=8 sw=8 noet: */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff -Nru djvulibre-3.5.27.1/win32/djvulibre/bzz/bzz.vcxproj djvulibre-3.5.28/win32/djvulibre/bzz/bzz.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/bzz/bzz.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/bzz/bzz.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/c44/c44.vcxproj djvulibre-3.5.28/win32/djvulibre/c44/c44.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/c44/c44.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/c44/c44.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,11 +20,13 @@ Application MultiByte true + v142 Application MultiByte false + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/cjb2/cjb2.vcxproj djvulibre-3.5.28/win32/djvulibre/cjb2/cjb2.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/cjb2/cjb2.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/cjb2/cjb2.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/cpaldjvu/cpaldjvu.vcxproj djvulibre-3.5.28/win32/djvulibre/cpaldjvu/cpaldjvu.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/cpaldjvu/cpaldjvu.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/cpaldjvu/cpaldjvu.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/csepdjvu/csepdjvu.vcxproj djvulibre-3.5.28/win32/djvulibre/csepdjvu/csepdjvu.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/csepdjvu/csepdjvu.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/csepdjvu/csepdjvu.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/ddjvu/ddjvu.vcxproj djvulibre-3.5.28/win32/djvulibre/ddjvu/ddjvu.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/ddjvu/ddjvu.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/ddjvu/ddjvu.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 @@ -33,12 +35,14 @@ + + diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvm/djvm.vcxproj djvulibre-3.5.28/win32/djvulibre/djvm/djvm.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvm/djvm.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvm/djvm.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvmcvt/djvmcvt.vcxproj djvulibre-3.5.28/win32/djvulibre/djvmcvt/djvmcvt.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvmcvt/djvmcvt.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvmcvt/djvmcvt.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvudump/djvudump.vcxproj djvulibre-3.5.28/win32/djvulibre/djvudump/djvudump.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvudump/djvudump.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvudump/djvudump.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvuextract/djvuextract.vcxproj djvulibre-3.5.28/win32/djvulibre/djvuextract/djvuextract.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvuextract/djvuextract.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvuextract/djvuextract.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvulibre-install.sh djvulibre-3.5.28/win32/djvulibre/djvulibre-install.sh --- djvulibre-3.5.27.1/win32/djvulibre/djvulibre-install.sh 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvulibre-install.sh 2020-11-20 16:57:32.000000000 +0000 @@ -1,14 +1,19 @@ #!/bin/sh -c=/cygdrive/c -qtdir=$c/QtSDK/Desktop/Qt/4.8.1/msvc2010 -djdir=$HOME/djvulibre-3.5 +c=/c +qtdir=$c/Qt/5.15.1/msvc2019 +djdir=$HOME/djvu/djvulibre-3.5 dwdir=$djdir/win32/djvulibre/Release -djsrc=$HOME/djvulibre-djview/src -msvc="$c/Program Files/Microsoft Visual Studio 10.0/VC" -msredist="$msvc/redist/x86/Microsoft.VC100.CRT" +djsrc=$HOME/djvu/djvulibre-djview/src +msvc="$c/Program Files/Microsoft Visual Studio/2019/Community/VC" +msredist="$msvc/Redist/MSVC/14.23.27820/vcredist_x86.exe" +ssl="$c/Qt/Tools/OpenSSL/win_x86_pre/lib*-1_1.dll" -target=$HOME/DjVuLibre +target=$HOME/djvu/DjVuLibre + +if [ ! -d $target ] ; then + mkdir $target +fi function run() { echo "$@" @@ -23,7 +28,7 @@ djexe="bzz.exe c44.exe cjb2.exe cpaldjvu.exe csepdjvu.exe ddjvu.exe djvm.exe djvmcvt.exe djvudump.exe djvuextract.exe - djvumake.exe djvups.exe djvused.exe djvuserve.exe djvutoxml.exe + djvumake.exe djvups.exe djvused.exe djvutoxml.exe djvutxt.exe djvuxmlparser.exe" djdll="libdjvulibre.dll libjpeg.dll libtiff.dll libz.dll" for n in $djdll $djexe ; do @@ -32,20 +37,21 @@ ## Qt libs echo ---- Qt libs -qtdll="QtCore4.dll QtGui4.dll QtNetwork4.dll QtOpenGL4.dll" -qtssl="ssleay32.dll libeay32.dll libssl32.dll" -qtplug="accessible codecs imageformats" +qtdll="Qt5Core.dll Qt5Gui.dll Qt5Widgets.dll Qt5Network.dll Qt5OpenGL.dll Qt5PrintSupport.dll" +qtplug="platforms styles imageformats" for n in $qtdll ; do - run cp $qtdir/lib/$n $target ; done -for n in $qtssl ; do - test -r $qtdir/bin/$n && run cp $qtdir/bin/$n $target ; done + run cp $qtdir/bin/$n $target ; done test -d $target/plugins || run mkdir $target/plugins for n in $qtplug ; do test -d $target/plugins/$n || run mkdir $target/plugins/$n for m in $qtdir/plugins/$n/*.dll ; do run cp $m $target/plugins/$n ; done - run chmod 0755 $target/plugins/$n/* ; done - run rm $target/plugins/*/*d4.dll + run chmod 0755 $target/plugins/$n/*.dll + for m in $target/plugins/$n/*.dll; do + md="`dirname $m`/`basename $m .dll`d.dll" + test -r $md && run rm $md + done +done run rm $target/plugins/imageformats/qsvg* run find $target -name '*.dll' -exec chmod 0755 {} \; @@ -54,7 +60,7 @@ ## MS libs echo ---- MS libs -for n in "$msredist"/* ; do +for n in "$msredist" ; do run cp "$n" $target; done ## DjVuLibre shared files @@ -88,6 +94,11 @@ run chmod 0644 $target/share/djvu/djview4/qt*.qm run rm -f $target/share/djvu/djview4/qt_help_*.qm +## OpenSSL + +for n in $ssl ; do + run cp "$n" "$target" +done ## Doc echo ---- Doc @@ -95,7 +106,6 @@ run cp $djdir/win32/djvulibre/djvulibre.nsi $target run cp $djdir/win32/djvulibre/djvulibre*.nsh $target -test -d $target/man || run mkdir $target/man test -d $target/doc || run mkdir $target/doc run cp $djdir/doc/*.djvu $target/doc run cp $djdir/doc/*.txt $target/doc diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvulibrelang-es.nsh djvulibre-3.5.28/win32/djvulibre/djvulibrelang-es.nsh --- djvulibre-3.5.27.1/win32/djvulibre/djvulibrelang-es.nsh 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvulibrelang-es.nsh 2020-11-20 16:57:32.000000000 +0000 @@ -0,0 +1,23 @@ +; Language strings: Spanish +; Encoding: UTF-8 with BOM +; Reviewed by: Mike Molina + +LangString DESC_Assoc ${LANG_SPANISH} "Establecer DjView como el visor DjVu predeterminado" +LangString DESC_Quick ${LANG_SPANISH} "Crear acceso directo de DjView en la barra de inicio rápido para el usuario actual" +LangString DESC_Desk ${LANG_SPANISH} "Crear acceso directo de DjView en el Escritorio" +LangString secAssoc ${LANG_SPANISH} "Establecer DjView como visor predeterminado para archivos DjVu" +LangString secQuick ${LANG_SPANISH} "Crear acceso directo en la barra de inicio rápido" +LangString secDesk ${LANG_SPANISH} "Crear acceso directo en el escritorio" +LangString Uninst_DIR ${LANG_SPANISH} "Desinstalar" +LangString Uninst_LNK ${LANG_SPANISH} "Eliminar completamente ${PRODUCT_NAME}" +LangString Doc_DIR ${LANG_SPANISH} "Ayuda" +LangString WEB_LNK ${LANG_SPANISH} "Visite" +LangString WebDL_LNK ${LANG_SPANISH} "página de descarga" +LangString Doc_LNK ${LANG_SPANISH} "Documentación" +LangString Lic_TXT ${LANG_SPANISH} "Licencia" +LangString Uninst_MSG ${LANG_SPANISH} "Está seguro de que desea eliminar por completo $(^Name) y todos sus componentes?" +LangString UninstSux_MSG ${LANG_SPANISH} "$(^Name) fue eliminado exitosamente de su computadora." +LangString Launch_LAB ${LANG_SPANISH} "Abrir DjView" +LangString Message_AlreadyInstalled ${LANG_SPANISH} "${PRODUCT_NAME} ${PRODUCT_VERSION} ya está instalado. Desinstalar?" +LangString Message_OldFound ${LANG_SPANISH} "${PRODUCT_NAME} versión anterior $COUNT está instalado. Desinstalar?" +LangString Message_NewFound ${LANG_SPANISH} "${PRODUCT_NAME} versión nueva $COUNT está instalado. Desinstalar?" diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvulibrelang-ru.nsh djvulibre-3.5.28/win32/djvulibre/djvulibrelang-ru.nsh --- djvulibre-3.5.27.1/win32/djvulibre/djvulibrelang-ru.nsh 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvulibrelang-ru.nsh 2020-11-20 16:57:32.000000000 +0000 @@ -1,23 +1,22 @@ -;WARNING! This is ANSI Win 1251 codepage file -;! ANSI Win 1251 +;WARNING! This is a UTF-8 file with BOM ;Lang strings RU -LangString DESC_Assoc ${LANG_RUSSIAN} " ${PRODUCT_NAME} djv djvu" -LangString DESC_Quick ${LANG_RUSSIAN} " DjView " -LangString DESC_Desk ${LANG_RUSSIAN} " DjView " -LangString secAssoc ${LANG_RUSSIAN} " DjView DjVu" -LangString secQuick ${LANG_RUSSIAN} ' " "' -LangString secDesk ${LANG_RUSSIAN} " " -LangString Uninst_DIR ${LANG_RUSSIAN} "" -LangString Uninst_LNK ${LANG_RUSSIAN} " ${PRODUCT_NAME}" -LangString Doc_DIR ${LANG_RUSSIAN} "" -LangString WEB_LNK ${LANG_RUSSIAN} "-" -LangString WebDL_LNK ${LANG_RUSSIAN} "- " -LangString Doc_LNK ${LANG_RUSSIAN} " " -LangString Lic_TXT ${LANG_RUSSIAN} "" -LangString Uninst_MSG ${LANG_RUSSIAN} " $(^Name)?" -LangString UninstSux_MSG ${LANG_RUSSIAN} " $(^Name) ." -LangString Launch_LAB ${LANG_RUSSIAN} " DjView" -LangString Message_AlreadyInstalled ${LANG_RUSSIAN} "${PRODUCT_NAME} ${PRODUCT_VERSION} . ?" -LangString Message_OldFound ${LANG_RUSSIAN} " ${PRODUCT_NAME} $COUNT. ?" -LangString Message_NewFound ${LANG_RUSSIAN} " ${PRODUCT_NAME} $COUNT. ?" \ No newline at end of file +LangString DESC_Assoc ${LANG_RUSSIAN} "Установка ${PRODUCT_NAME} программой по умолчанию для djv и djvu" +LangString DESC_Quick ${LANG_RUSSIAN} "Создать ярлык DjView на Панели быстрого запуска текущего пользователя" +LangString DESC_Desk ${LANG_RUSSIAN} "Создать ярлык DjView на Рабочем столе" +LangString secAssoc ${LANG_RUSSIAN} "Ассоциировать DjView с файлами DjVu" +LangString secQuick ${LANG_RUSSIAN} 'Создать ярлык на панели "Быстрый запуск"' +LangString secDesk ${LANG_RUSSIAN} "Создать ярлык на Рабочем столе" +LangString Uninst_DIR ${LANG_RUSSIAN} "Удаление" +LangString Uninst_LNK ${LANG_RUSSIAN} "Удалить полностью ${PRODUCT_NAME}" +LangString Doc_DIR ${LANG_RUSSIAN} "Справочник" +LangString WEB_LNK ${LANG_RUSSIAN} "Веб-сайт" +LangString WebDL_LNK ${LANG_RUSSIAN} "- страница загрузки" +LangString Doc_LNK ${LANG_RUSSIAN} "Справка " +LangString Lic_TXT ${LANG_RUSSIAN} "Лицензия" +LangString Uninst_MSG ${LANG_RUSSIAN} "Вы точно хотите полностью удалить с компьютера $(^Name)?" +LangString UninstSux_MSG ${LANG_RUSSIAN} "Программа $(^Name) благополучно удалена." +LangString Launch_LAB ${LANG_RUSSIAN} "Запустить DjView" +LangString Message_AlreadyInstalled ${LANG_RUSSIAN} "${PRODUCT_NAME} ${PRODUCT_VERSION} уже установлен. Удалить?" +LangString Message_OldFound ${LANG_RUSSIAN} "У Вас установлена старая версия ${PRODUCT_NAME} $COUNT. Удалить?" +LangString Message_NewFound ${LANG_RUSSIAN} "У Вас установлена более новая версия ${PRODUCT_NAME} $COUNT. Удалить?" \ No newline at end of file diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvulibre.nsi djvulibre-3.5.28/win32/djvulibre/djvulibre.nsi --- djvulibre-3.5.27.1/win32/djvulibre/djvulibre.nsi 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvulibre.nsi 2020-11-20 16:57:32.000000000 +0000 @@ -7,11 +7,10 @@ ;Used software: ;-------------- -;NSIS 2.46 (http://sourceforge.net/projects/nsis/files/NSIS%202/2.46/nsis-2.46-setup.exe/download) -;add-on NSIS 2.46+log (http://sourceforge.net/projects/nsis/files/NSIS%202/2.46/nsis-2.46-log.zip/download) -;HM NIS Edit 2.0.3 -- it's good IDE for NSI building (http://prdownloads.sourceforge.net/hmne/nisedit2.0.3.exe?download) -;with 2.46 NSIS update (http://nsis.sourceforge.net/mediawiki/images/6/64/HMnsiSyntaxConfig.zip) -;Notepad ++ 6.3 (http://download.tuxfamily.org/notepadplus/6.3/npp.6.3.Installer.exe) +;NSIS 3.05 (http://sourceforge.net/projects/nsis/files/) +;add-on NSIS 3.05+log (http://sourceforge.net/projects/nsis/files/NSIS%203/3.05/nsis-3.05-log.zip) +;HM NIS Edit 2.0.3 -- it's good IDE for NSI building +; ;Used docs ;--------- ;NSIS docs and manuals at http://forum.oszone.net/thread-248731.html @@ -26,14 +25,15 @@ ;prepare names RequestExecutionLevel admin +Unicode true !define NSI_VER "9.2" !define DJVULIBRE_NAME "DjVuLibre" -!define DJVULIBRE_VERSION "3.5.27" +!define DJVULIBRE_VERSION "3.5.28" !define CLASSES "Software\Classes\" !define DJVIEW_NAME "DjView" -!define DJVIEW_VERSION "4.10" -!define VI_PRODUCT_VERSION "4.10.0.0" +!define DJVIEW_VERSION "4.12" +!define VI_PRODUCT_VERSION "4.12.0.0" !define PRODUCT_NAME "${DJVULIBRE_NAME} ${DJVIEW_NAME}" !define UNINST_NAME "${DJVULIBRE_NAME}+${DJVIEW_NAME}" ; for uninstaller @@ -160,6 +160,7 @@ ;language files !insertmacro MUI_LANGUAGE "English" !insertmacro MUI_LANGUAGE "Russian" +!insertmacro MUI_LANGUAGE "Spanish" ; end MUI 1.67 compatible ------ @@ -234,6 +235,8 @@ File "djvulibre*.ns?" File "COPYING.txt" Logset off + ;; call vcredist + ExecWait '"$INSTDIR/vcredist_x86.exe" /passive /norestart' SectionEnd ;--- registry @@ -566,6 +569,7 @@ !include "djvulibrelang-ru.nsh" !include "djvulibrelang-en.nsh" +!include "djvulibrelang-es.nsh" ; Section descriptions set diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvumake/djvumake.vcxproj djvulibre-3.5.28/win32/djvulibre/djvumake/djvumake.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvumake/djvumake.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvumake/djvumake.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvups/djvups.vcxproj djvulibre-3.5.28/win32/djvulibre/djvups/djvups.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvups/djvups.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvups/djvups.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvused/djvused.vcxproj djvulibre-3.5.28/win32/djvulibre/djvused/djvused.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvused/djvused.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvused/djvused.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvuserve/djvuserve.vcxproj djvulibre-3.5.28/win32/djvulibre/djvuserve/djvuserve.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvuserve/djvuserve.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvuserve/djvuserve.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvutoxml/djvutoxml.vcxproj djvulibre-3.5.28/win32/djvulibre/djvutoxml/djvutoxml.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvutoxml/djvutoxml.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvutoxml/djvutoxml.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvutxt/djvutxt.vcxproj djvulibre-3.5.28/win32/djvulibre/djvutxt/djvutxt.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvutxt/djvutxt.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvutxt/djvutxt.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/djvuxmlparser/djvuxmlparser.vcxproj djvulibre-3.5.28/win32/djvulibre/djvuxmlparser/djvuxmlparser.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/djvuxmlparser/djvuxmlparser.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/djvuxmlparser/djvuxmlparser.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ Application MultiByte true + v142 Application MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/libdjvulibre/libdjvulibre.vcxproj djvulibre-3.5.28/win32/djvulibre/libdjvulibre/libdjvulibre.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/libdjvulibre/libdjvulibre.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/libdjvulibre/libdjvulibre.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ DynamicLibrary MultiByte true + v142 DynamicLibrary MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/libdjvulibre.props djvulibre-3.5.28/win32/djvulibre/libdjvulibre.props --- djvulibre-3.5.27.1/win32/djvulibre/libdjvulibre.props 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/libdjvulibre.props 2020-11-20 16:57:32.000000000 +0000 @@ -5,7 +5,7 @@ - $(JpegRoot);$(JpegDir);%(AdditionalIncludeDirectories) + $(DjVuLibreRoot);$(JpegRoot);$(JpegDir);%(AdditionalIncludeDirectories) HAVE_NAMESPACES;NEED_JPEG_DECODER;%(PreprocessorDefinitions) diff -Nru djvulibre-3.5.27.1/win32/djvulibre/libjpeg/libjpeg.vcxproj djvulibre-3.5.28/win32/djvulibre/libjpeg/libjpeg.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/libjpeg/libjpeg.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/libjpeg/libjpeg.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ DynamicLibrary MultiByte true + v142 DynamicLibrary MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/djvulibre/libtiff/libtiff.vcxproj djvulibre-3.5.28/win32/djvulibre/libtiff/libtiff.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/libtiff/libtiff.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/libtiff/libtiff.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ DynamicLibrary MultiByte true + v142 DynamicLibrary MultiByte + v142 @@ -130,6 +132,7 @@ + diff -Nru djvulibre-3.5.27.1/win32/djvulibre/libtiff/libtiff.vcxproj.filters djvulibre-3.5.28/win32/djvulibre/libtiff/libtiff.vcxproj.filters --- djvulibre-3.5.27.1/win32/djvulibre/libtiff/libtiff.vcxproj.filters 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/libtiff/libtiff.vcxproj.filters 2020-11-20 16:57:32.000000000 +0000 @@ -128,6 +128,9 @@ Source Files + + Source Files + diff -Nru djvulibre-3.5.27.1/win32/djvulibre/libz/libz.vcxproj djvulibre-3.5.28/win32/djvulibre/libz/libz.vcxproj --- djvulibre-3.5.27.1/win32/djvulibre/libz/libz.vcxproj 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/djvulibre/libz/libz.vcxproj 2020-11-20 16:57:32.000000000 +0000 @@ -20,10 +20,12 @@ DynamicLibrary MultiByte true + v142 DynamicLibrary MultiByte + v142 diff -Nru djvulibre-3.5.27.1/win32/jpeg/README djvulibre-3.5.28/win32/jpeg/README --- djvulibre-3.5.27.1/win32/jpeg/README 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/jpeg/README 2020-11-20 16:57:32.000000000 +0000 @@ -1,5 +1,5 @@ UNPACK THE SOURCE CODE OF LIBJPEG HERE. -ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz - + jpegsrc.v6b.tar.gz +All the source code should go under subdirectory jpeg-6b diff -Nru djvulibre-3.5.27.1/win32/tiff/README djvulibre-3.5.28/win32/tiff/README --- djvulibre-3.5.27.1/win32/tiff/README 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/tiff/README 2020-11-20 16:57:32.000000000 +0000 @@ -1,4 +1,4 @@ UNPACK THE SOURCE CODE OF LIBTIFF HERE. -ftp://ftp.remotesensing.org/pub/libtiff/tiff-3.8.2.tar.gz - -Then rename directory "tiff-3.8.2" AS "tiff" +Previously at +ftp://ftp.remotesensing.org/pub/libtiff/tiff-4.0.X.tar.gz +Then rename directory "tiff-4.0.X" AS "tiff" diff -Nru djvulibre-3.5.27.1/win32/tiff/tif_config.h djvulibre-3.5.28/win32/tiff/tif_config.h --- djvulibre-3.5.27.1/win32/tiff/tif_config.h 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/tiff/tif_config.h 2020-11-20 16:57:32.000000000 +0000 @@ -1,3 +1,6 @@ +#ifndef _TIF_CONFIG_H_ +#define _TIF_CONFIG_H_ + /* Define to 1 if you have the header file. */ #define HAVE_ASSERT_H 1 @@ -8,6 +11,9 @@ machine */ #define HAVE_IEEEFP 1 +/* Define to 1 if you have the `jbg_newlen' function. */ +#define HAVE_JBG_NEWLEN 1 + /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 @@ -20,15 +26,91 @@ /* Define to 1 if you have the header file. */ #define HAVE_SEARCH_H 1 +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* Define to 1 if you have the declaration of `optarg', and to 0 if you don't. */ +#define HAVE_DECL_OPTARG 0 + /* The size of a `int', as computed by sizeof. */ #define SIZEOF_INT 4 /* The size of a `long', as computed by sizeof. */ #define SIZEOF_LONG 4 +/* Signed 64-bit type formatter */ +#define TIFF_INT64_FORMAT "%I64d" + +/* Signed 64-bit type */ +#define TIFF_INT64_T signed __int64 + +/* Unsigned 64-bit type formatter */ +#define TIFF_UINT64_FORMAT "%I64u" + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned __int64 + +#if _WIN64 +/* + Windows 64-bit build +*/ + +/* Pointer difference type */ +# define TIFF_PTRDIFF_T TIFF_INT64_T + +/* The size of `size_t', as computed by sizeof. */ +# define SIZEOF_SIZE_T 8 + +/* Size type formatter */ +# define TIFF_SIZE_FORMAT TIFF_INT64_FORMAT + +/* Unsigned size type */ +# define TIFF_SIZE_T TIFF_UINT64_T + +/* Signed size type formatter */ +# define TIFF_SSIZE_FORMAT TIFF_INT64_FORMAT + +/* Signed size type */ +# define TIFF_SSIZE_T TIFF_INT64_T + +#else +/* + Windows 32-bit build +*/ + +/* Pointer difference type */ +# define TIFF_PTRDIFF_T signed int + +/* The size of `size_t', as computed by sizeof. */ +# define SIZEOF_SIZE_T 4 + +/* Size type formatter */ +# define TIFF_SIZE_FORMAT "%u" + +/* Size type formatter */ +# define TIFF_SIZE_FORMAT "%u" + +/* Unsigned size type */ +# define TIFF_SIZE_T unsigned int + +/* Signed size type formatter */ +# define TIFF_SSIZE_FORMAT "%d" + +/* Signed size type */ +# define TIFF_SSIZE_T signed int + +#endif + /* Set the native cpu bit order */ #define HOST_FILLORDER FILLORDER_LSB2MSB +/* Visual Studio 2015 / VC 14 / MSVC 19.00 finally has snprintf() */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define snprintf _snprintf +#else +#define HAVE_SNPRINTF 1 +#endif + /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ /* #undef WORDS_BIGENDIAN */ @@ -42,3 +124,14 @@ #endif #define lfind _lfind + +#pragma warning(disable : 4996) /* function deprecation warnings */ + +#endif /* _TIF_CONFIG_H_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff -Nru djvulibre-3.5.27.1/win32/tiff/tiffconf.h djvulibre-3.5.28/win32/tiff/tiffconf.h --- djvulibre-3.5.27.1/win32/tiff/tiffconf.h 1970-01-01 00:00:00.000000000 +0000 +++ djvulibre-3.5.28/win32/tiff/tiffconf.h 2020-11-20 16:57:32.000000000 +0000 @@ -0,0 +1,161 @@ +/* + Configuration defines for installed libtiff. + This file maintained for backward compatibility. Do not use definitions + from this file in your programs. +*/ + +#ifndef _TIFFCONF_ +#define _TIFFCONF_ + +/* Define to 1 if the system has the type `int16'. */ +/* #undef HAVE_INT16 */ + +/* Define to 1 if the system has the type `int32'. */ +/* #undef HAVE_INT32 */ + +/* Define to 1 if the system has the type `int8'. */ +/* #undef HAVE_INT8 */ + +/* The size of a `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* Signed 8-bit type */ +#define TIFF_INT8_T signed char + +/* Unsigned 8-bit type */ +#define TIFF_UINT8_T unsigned char + +/* Signed 16-bit type */ +#define TIFF_INT16_T signed short + +/* Unsigned 16-bit type */ +#define TIFF_UINT16_T unsigned short + +/* Signed 32-bit type formatter */ +#define TIFF_INT32_FORMAT "%d" + +/* Signed 32-bit type */ +#define TIFF_INT32_T signed int + +/* Unsigned 32-bit type formatter */ +#define TIFF_UINT32_FORMAT "%u" + +/* Unsigned 32-bit type */ +#define TIFF_UINT32_T unsigned int + +/* Signed 64-bit type formatter */ +#define TIFF_INT64_FORMAT "%I64d" + +/* Signed 64-bit type */ +#define TIFF_INT64_T signed __int64 + +/* Unsigned 64-bit type formatter */ +#define TIFF_UINT64_FORMAT "%I64u" + +/* Unsigned 64-bit type */ +#define TIFF_UINT64_T unsigned __int64 + +#if _WIN64 +/* + Windows 64-bit build +*/ + +/* Signed size type */ +# define TIFF_SSIZE_T TIFF_INT64_T + +#else +/* + Windows 32-bit build +*/ + +/* Signed size type */ +# define TIFF_SSIZE_T signed int + +#endif + +/* Compatibility stuff. */ + +/* Define as 0 or 1 according to the floating point format suported by the + machine */ +#define HAVE_IEEEFP 1 + +/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */ +#define HOST_FILLORDER FILLORDER_LSB2MSB + +/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian + (Intel) */ +#define HOST_BIGENDIAN 0 + +/* Support CCITT Group 3 & 4 algorithms */ +#define CCITT_SUPPORT 1 + +/* Support JPEG compression (requires IJG JPEG library) */ +/* #undef JPEG_SUPPORT */ + +/* Support JBIG compression (requires JBIG-KIT library) */ +/* #undef JBIG_SUPPORT */ + +/* Support LogLuv high dynamic range encoding */ +#define LOGLUV_SUPPORT 1 + +/* Support LZW algorithm */ +#define LZW_SUPPORT 1 + +/* Support NeXT 2-bit RLE algorithm */ +#define NEXT_SUPPORT 1 + +/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation + fails with unpatched IJG JPEG library) */ +/* #undef OJPEG_SUPPORT */ + +/* Support Macintosh PackBits algorithm */ +#define PACKBITS_SUPPORT 1 + +/* Support Pixar log-format algorithm (requires Zlib) */ +/* #undef PIXARLOG_SUPPORT */ + +/* Support ThunderScan 4-bit RLE algorithm */ +#define THUNDER_SUPPORT 1 + +/* Support Deflate compression */ +/* #undef ZIP_SUPPORT */ + +/* Support strip chopping (whether or not to convert single-strip uncompressed + images to mutiple strips of ~8Kb to reduce memory usage) */ +#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP + +/* Enable SubIFD tag (330) support */ +#define SUBIFD_SUPPORT 1 + +/* Treat extra sample as alpha (default enabled). The RGBA interface will + treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many + packages produce RGBA files but don't mark the alpha properly. */ +#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1 + +/* Pick up YCbCr subsampling info from the JPEG data stream to support files + lacking the tag (default enabled). */ +#define CHECK_JPEG_YCBCR_SUBSAMPLING 1 + +/* Support MS MDI magic number files as TIFF */ +/* #undef MDI_SUPPORT */ + +/* + * Feature support definitions. + * XXX: These macros are obsoleted. Don't use them in your apps! + * Macros stays here for backward compatibility and should be always defined. + */ +#define COLORIMETRY_SUPPORT +#define YCBCR_SUPPORT +#define CMYK_SUPPORT +#define ICC_SUPPORT +#define PHOTOSHOP_SUPPORT +#define IPTC_SUPPORT + +#endif /* _TIFFCONF_ */ +/* + * Local Variables: + * mode: c + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ diff -Nru djvulibre-3.5.27.1/win32/zlib/README djvulibre-3.5.28/win32/zlib/README --- djvulibre-3.5.27.1/win32/zlib/README 2015-04-02 19:51:53.000000000 +0000 +++ djvulibre-3.5.28/win32/zlib/README 2020-11-20 16:57:32.000000000 +0000 @@ -1,5 +1,5 @@ UNPACK THE SOURCE CODE OF ZLIB HERE. - + -Then rename directory "zlib-1.2.5" AS "zlib" +Then rename directory "zlib-1.2.x" AS "zlib"