From 0f3092ceb81694e94e3e4abec4e6e6427d4e1e6d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 21 Aug 2026 20:10:30 +0200 Subject: [PATCH] added support to view JPEG2000 images commonly used with epassports. The lib use a BSD-2 license compatible with our GPL3+ --- .gitignore | 8 + CHANGELOG.md | 1 + client/CMakeLists.txt | 4 + client/Makefile | 20 + client/deps/CMakeLists.txt | 6 + client/deps/openjpeg/LICENSE | 39 + client/deps/openjpeg/Makefile | 32 + client/deps/openjpeg/README.pm3 | 59 + client/deps/openjpeg/bio.c | 211 + client/deps/openjpeg/bio.h | 142 + client/deps/openjpeg/cio.c | 683 + client/deps/openjpeg/cio.h | 412 + client/deps/openjpeg/dwt.c | 3979 ++++++ client/deps/openjpeg/dwt.h | 120 + client/deps/openjpeg/event.c | 151 + client/deps/openjpeg/event.h | 108 + client/deps/openjpeg/function_list.c | 117 + client/deps/openjpeg/function_list.h | 134 + client/deps/openjpeg/ht_dec.c | 2689 ++++ client/deps/openjpeg/image.c | 263 + client/deps/openjpeg/image.h | 70 + client/deps/openjpeg/invert.c | 295 + client/deps/openjpeg/invert.h | 64 + client/deps/openjpeg/j2k.c | 13595 ++++++++++++++++++++ client/deps/openjpeg/j2k.h | 954 ++ client/deps/openjpeg/jp2.c | 3424 +++++ client/deps/openjpeg/jp2.h | 521 + client/deps/openjpeg/mct.c | 464 + client/deps/openjpeg/mct.h | 160 + client/deps/openjpeg/mqc.c | 524 + client/deps/openjpeg/mqc.h | 268 + client/deps/openjpeg/mqc_inl.h | 282 + client/deps/openjpeg/openjpeg.a | Bin 0 -> 717158 bytes client/deps/openjpeg/openjpeg.c | 1144 ++ client/deps/openjpeg/openjpeg.h | 1786 +++ client/deps/openjpeg/opj_clock.c | 67 + client/deps/openjpeg/opj_clock.h | 59 + client/deps/openjpeg/opj_codec.h | 179 + client/deps/openjpeg/opj_common.h | 47 + client/deps/openjpeg/opj_config.h | 13 + client/deps/openjpeg/opj_config_private.h | 44 + client/deps/openjpeg/opj_includes.h | 266 + client/deps/openjpeg/opj_intmath.h | 333 + client/deps/openjpeg/opj_malloc.c | 249 + client/deps/openjpeg/opj_malloc.h | 106 + client/deps/openjpeg/pi.c | 2149 ++++ client/deps/openjpeg/pi.h | 207 + client/deps/openjpeg/sparse_array.c | 346 + client/deps/openjpeg/sparse_array.h | 141 + client/deps/openjpeg/t1.c | 2741 ++++ client/deps/openjpeg/t1.h | 268 + client/deps/openjpeg/t1_ht_luts.h | 261 + client/deps/openjpeg/t1_luts.h | 175 + client/deps/openjpeg/t2.c | 1705 +++ client/deps/openjpeg/t2.h | 142 + client/deps/openjpeg/tcd.c | 2930 +++++ client/deps/openjpeg/tcd.h | 512 + client/deps/openjpeg/tgt.c | 344 + client/deps/openjpeg/tgt.h | 148 + client/deps/openjpeg/thread.c | 954 ++ client/deps/openjpeg/thread.h | 256 + client/deps/openjpeg/tls_keys.h | 37 + client/src/cmdhfemrtd.c | 17 +- client/src/proxgui.cpp | 29 +- 64 files changed, 47449 insertions(+), 5 deletions(-) create mode 100644 client/deps/openjpeg/LICENSE create mode 100644 client/deps/openjpeg/Makefile create mode 100644 client/deps/openjpeg/README.pm3 create mode 100644 client/deps/openjpeg/bio.c create mode 100644 client/deps/openjpeg/bio.h create mode 100644 client/deps/openjpeg/cio.c create mode 100644 client/deps/openjpeg/cio.h create mode 100644 client/deps/openjpeg/dwt.c create mode 100644 client/deps/openjpeg/dwt.h create mode 100644 client/deps/openjpeg/event.c create mode 100644 client/deps/openjpeg/event.h create mode 100644 client/deps/openjpeg/function_list.c create mode 100644 client/deps/openjpeg/function_list.h create mode 100644 client/deps/openjpeg/ht_dec.c create mode 100644 client/deps/openjpeg/image.c create mode 100644 client/deps/openjpeg/image.h create mode 100644 client/deps/openjpeg/invert.c create mode 100644 client/deps/openjpeg/invert.h create mode 100644 client/deps/openjpeg/j2k.c create mode 100644 client/deps/openjpeg/j2k.h create mode 100644 client/deps/openjpeg/jp2.c create mode 100644 client/deps/openjpeg/jp2.h create mode 100644 client/deps/openjpeg/mct.c create mode 100644 client/deps/openjpeg/mct.h create mode 100644 client/deps/openjpeg/mqc.c create mode 100644 client/deps/openjpeg/mqc.h create mode 100644 client/deps/openjpeg/mqc_inl.h create mode 100644 client/deps/openjpeg/openjpeg.a create mode 100644 client/deps/openjpeg/openjpeg.c create mode 100644 client/deps/openjpeg/openjpeg.h create mode 100644 client/deps/openjpeg/opj_clock.c create mode 100644 client/deps/openjpeg/opj_clock.h create mode 100644 client/deps/openjpeg/opj_codec.h create mode 100644 client/deps/openjpeg/opj_common.h create mode 100644 client/deps/openjpeg/opj_config.h create mode 100644 client/deps/openjpeg/opj_config_private.h create mode 100644 client/deps/openjpeg/opj_includes.h create mode 100644 client/deps/openjpeg/opj_intmath.h create mode 100644 client/deps/openjpeg/opj_malloc.c create mode 100644 client/deps/openjpeg/opj_malloc.h create mode 100644 client/deps/openjpeg/pi.c create mode 100644 client/deps/openjpeg/pi.h create mode 100644 client/deps/openjpeg/sparse_array.c create mode 100644 client/deps/openjpeg/sparse_array.h create mode 100644 client/deps/openjpeg/t1.c create mode 100644 client/deps/openjpeg/t1.h create mode 100644 client/deps/openjpeg/t1_ht_luts.h create mode 100644 client/deps/openjpeg/t1_luts.h create mode 100644 client/deps/openjpeg/t2.c create mode 100644 client/deps/openjpeg/t2.h create mode 100644 client/deps/openjpeg/tcd.c create mode 100644 client/deps/openjpeg/tcd.h create mode 100644 client/deps/openjpeg/tgt.c create mode 100644 client/deps/openjpeg/tgt.h create mode 100644 client/deps/openjpeg/thread.c create mode 100644 client/deps/openjpeg/thread.h create mode 100644 client/deps/openjpeg/tls_keys.h diff --git a/.gitignore b/.gitignore index f81d51807..e667db8a6 100644 --- a/.gitignore +++ b/.gitignore @@ -49,10 +49,18 @@ client/CMakeFiles/ client/deps/** !client/deps/id48/ !client/deps/id48/** +# vendored openjpeg, sources only. openjpeg.a and obj/ stay ignored +!client/deps/openjpeg/ +!client/deps/openjpeg/*.c +!client/deps/openjpeg/*.h +!client/deps/openjpeg/Makefile +!client/deps/openjpeg/LICENSE +!client/deps/openjpeg/README.pm3 client/build/ client/android/build/ CMakeCache.txt *.cmake +!client/deps/openjpeg.cmake .cache # Coverity diff --git a/CHANGELOG.md b/CHANGELOG.md index ed70d8494..0dee60f20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] +- Changed `hf emrtd info` - now shows EF_DG2 portraits for JPREG2000 via new dependecy lib (@iceman1001) - Changed `hf emrtd info`- now shows portrait, signature and other biometrics at the same time (@iceman1001) - Fixed `pm3_grabbed_output_get` - heap overflow (@jonyen) - Fixed `hf iclass sam` - removed the old implementation (@iceman1001) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 5097e27a5..585edfd8a 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -579,8 +579,12 @@ if ((NOT SKIPQT EQUAL 1) AND (Qt5_FOUND OR Qt6_FOUND)) set (TARGET_SOURCES ${PM3_ROOT}/client/src/proxgui.cpp ${PM3_ROOT}/client/src/proxguiqt.cpp + ${PM3_ROOT}/client/src/imgjp2.c ${TARGET_SOURCES}) + # Qt has no JPEG2000 image handler, so we decode EF_DG2 & friends ourselves + set(ADDITIONAL_LNK pm3rrg_rdv4_openjpeg ${ADDITIONAL_LNK}) + add_definitions("-DHAVE_GUI") if (Qt6_FOUND) set(ADDITIONAL_DIRS ${Qt6_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) diff --git a/client/Makefile b/client/Makefile index cc3feb156..31b3d5b4c 100644 --- a/client/Makefile +++ b/client/Makefile @@ -123,6 +123,12 @@ REVENGLIBINC = -I$(REVENGLIBPATH) REVENGLIB = $(REVENGLIBPATH)/libreveng.a REVENGLIBLD = +## OpenJPEG (JPEG2000 decoding for the picture viewer) +OPENJPEGLIBPATH = ./deps/openjpeg +OPENJPEGLIBINC = -I$(OPENJPEGLIBPATH) +OPENJPEGLIB = $(OPENJPEGLIBPATH)/openjpeg.a +OPENJPEGLIBLD = + ## Tinycbor TINYCBORLIBPATH = ./deps/tinycbor TINYCBORLIBINC = -I$(TINYCBORLIBPATH) @@ -234,6 +240,11 @@ STATICLIBS += $(REVENGLIB) LDLIBS += $(REVENGLIBLD) PM3INCLUDES += $(REVENGLIBINC) +## OpenJPEG +# vendored, Qt has no JPEG2000 image handler. +# Only linked in when the Qt GUI is built, see the "gui" section below +PM3INCLUDES += $(OPENJPEGLIBINC) + ## Tinycbor # not distributed as system library STATICLIBS += $(TINYCBORLIB) @@ -946,6 +957,10 @@ endif # gui ifeq ($(QT_FOUND),1) CXXSRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp + # Qt has no JPEG2000 image handler, so we decode EF_DG2 & friends ourselves + SRCS += imgjp2.c + STATICLIBS += $(OPENJPEGLIB) + LDLIBS += $(OPENJPEGLIBLD) else CXXSRCS = guidummy.cpp endif @@ -1026,6 +1041,7 @@ ifeq ($(LINENOISE_LOCAL_FOUND), 1) endif $(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) clean + $(Q)$(MAKE) --no-print-directory -C $(OPENJPEGLIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) clean $(Q)$(MAKE) --no-print-directory -C $(MQTTLIBPATH) clean @@ -1116,6 +1132,10 @@ $(REVENGLIB): .FORCE $(info [*] MAKE $@) $(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) all +$(OPENJPEGLIB): .FORCE + $(info [*] MAKE $@) + $(Q)$(MAKE) --no-print-directory -C $(OPENJPEGLIBPATH) all + $(TINYCBORLIB): .FORCE $(info [*] MAKE $@) $(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) all diff --git a/client/deps/CMakeLists.txt b/client/deps/CMakeLists.txt index b531aed04..e9f95f106 100644 --- a/client/deps/CMakeLists.txt +++ b/client/deps/CMakeLists.txt @@ -25,6 +25,12 @@ endif() if (NOT TARGET pm3rrg_rdv4_mqtt) include(mqtt.cmake) endif() +# JPEG2000 is only decoded by the Qt picture viewer, so don't build it for +# targets without a GUI (experimental_lib links guidummy.cpp instead). +# Condition must match the one guarding proxgui.cpp in client/CMakeLists.txt +if ((NOT TARGET pm3rrg_rdv4_openjpeg) AND (NOT SKIPQT EQUAL 1) AND (Qt5_FOUND OR Qt6_FOUND)) + include(openjpeg.cmake) +endif() if (NOT TARGET pm3rrg_rdv4_reveng) include(reveng.cmake) endif() diff --git a/client/deps/openjpeg/LICENSE b/client/deps/openjpeg/LICENSE new file mode 100644 index 000000000..e8fa41040 --- /dev/null +++ b/client/deps/openjpeg/LICENSE @@ -0,0 +1,39 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2003-2009, Francois-Olivier Devaux + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France + * Copyright (c) 2012, CS Systemes d'Information, France + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ diff --git a/client/deps/openjpeg/Makefile b/client/deps/openjpeg/Makefile new file mode 100644 index 000000000..8fd3ed6b1 --- /dev/null +++ b/client/deps/openjpeg/Makefile @@ -0,0 +1,32 @@ +MYSRCPATHS = +MYINCLUDES = +# Third party code, don't fail the build on upstream's warnings +MYCFLAGS = -w -O3 +MYDEFS = +MYSRCS = \ + bio.c \ + cio.c \ + dwt.c \ + event.c \ + function_list.c \ + ht_dec.c \ + image.c \ + invert.c \ + j2k.c \ + jp2.c \ + mct.c \ + mqc.c \ + openjpeg.c \ + opj_clock.c \ + opj_malloc.c \ + pi.c \ + sparse_array.c \ + t1.c \ + t2.c \ + tcd.c \ + tgt.c \ + thread.c \ + +LIB_A = openjpeg.a + +include ../../../Makefile.host diff --git a/client/deps/openjpeg/README.pm3 b/client/deps/openjpeg/README.pm3 new file mode 100644 index 000000000..0608a08a2 --- /dev/null +++ b/client/deps/openjpeg/README.pm3 @@ -0,0 +1,59 @@ +openjpeg (openjp2) - vendored for Proxmark3 +=========================================== + +Why +--- +Qt has no JPEG2000 image handler. The old JasPer based `jp2` plugin was +dropped from qtimageformats and neither Debian/Ubuntu nor Fedora ship a +replacement -- `qt5-image-formats-plugins` and `qt6-image-formats-plugins` +contain only ICNS, MNG, TGA, TIFF, WBMP and WEBP. + +Most eMRTD passports store EF_DG2 (the portrait) as JPEG2000, and EF_DG4 +(iris) uses it as well, so without a decoder of our own `hf emrtd info` +could not show the very images people run it for. + +Origin +------ + https://github.com/uclouvain/openjpeg + tag v2.5.4 + license: 2-clause BSD, see LICENSE in this directory + +2-clause BSD is GPL compatible, so it mixes with the Proxmark3 GPLv3 +codebase. Keep the per file BSD headers intact, they are not ours to +relicense. + +Upstream's own notice applies and is repeated here: + + "This software may be subject to other third party and contributor + rights, including patent rights, and no such rights are granted under + this license." + +What was taken +-------------- +Only the sources listed in upstream's `OPENJPEG_SRCS` +(src/lib/openjp2/CMakeLists.txt), which is the openjp2 core library. + +Left out on purpose: + - the JPIP index box code (cidx_manager.c, indexbox_manager.h, + phix/ppix/thix/tpix_manager.c). It is `#ifdef USE_JPIP` only and we + never define that. + - the bin/ codec applications, tests, benchmarks and the LUT generators + (t1_generate_luts.c, t1_ht_generate_luts.c, bench_dwt.c, + test_sparse_array.c). The pre-generated LUT headers are kept. + +Local changes +------------- + - opj_config.h and opj_config_private.h are hand written replacements + for the CMake generated ones. They decide everything from compiler + predefines instead of configure time probes, so no CMake config step + is needed. On Windows/MinGW no aligned-alloc macro is defined, which + makes openjpeg use its own portable fallback. + - Makefile added, for the non-CMake build. The CMake side lives in + ../openjpeg.cmake + +No openjpeg .c or .h file was otherwise modified. + +Updating +-------- +Copy the OPENJPEG_SRCS files from a new upstream tag over this directory, +then keep opj_config.h, opj_config_private.h, Makefile and this README. diff --git a/client/deps/openjpeg/bio.c b/client/deps/openjpeg/bio.c new file mode 100644 index 000000000..8106df754 --- /dev/null +++ b/client/deps/openjpeg/bio.c @@ -0,0 +1,211 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +/** @defgroup BIO BIO - Individual bit input-output stream */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Read a bit +@param bio BIO handle +@return Returns the read bit +*/ +static OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio); +/** +Write a byte +@param bio BIO handle +@return Returns OPJ_TRUE if successful, returns OPJ_FALSE otherwise +*/ +static OPJ_BOOL opj_bio_byteout(opj_bio_t *bio); +/** +Read a byte +@param bio BIO handle +@return Returns OPJ_TRUE if successful, returns OPJ_FALSE otherwise +*/ +static OPJ_BOOL opj_bio_bytein(opj_bio_t *bio); + +/*@}*/ + +/*@}*/ + +/* +========================================================== + local functions +========================================================== +*/ + +static OPJ_BOOL opj_bio_byteout(opj_bio_t *bio) +{ + bio->buf = (bio->buf << 8) & 0xffff; + bio->ct = bio->buf == 0xff00 ? 7 : 8; + if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) { + return OPJ_FALSE; + } + *bio->bp++ = (OPJ_BYTE)(bio->buf >> 8); + return OPJ_TRUE; +} + +static OPJ_BOOL opj_bio_bytein(opj_bio_t *bio) +{ + bio->buf = (bio->buf << 8) & 0xffff; + bio->ct = bio->buf == 0xff00 ? 7 : 8; + if ((OPJ_SIZE_T)bio->bp >= (OPJ_SIZE_T)bio->end) { + return OPJ_FALSE; + } + bio->buf |= *bio->bp++; + return OPJ_TRUE; +} + +static OPJ_UINT32 opj_bio_getbit(opj_bio_t *bio) +{ + if (bio->ct == 0) { + opj_bio_bytein( + bio); /* MSD: why not check the return value of this function ? */ + } + bio->ct--; + return (bio->buf >> bio->ct) & 1; +} + +/* +========================================================== + Bit Input/Output interface +========================================================== +*/ + +opj_bio_t* opj_bio_create(void) +{ + opj_bio_t *bio = (opj_bio_t*)opj_malloc(sizeof(opj_bio_t)); + return bio; +} + +void opj_bio_destroy(opj_bio_t *bio) +{ + if (bio) { + opj_free(bio); + } +} + +ptrdiff_t opj_bio_numbytes(opj_bio_t *bio) +{ + return (bio->bp - bio->start); +} + +void opj_bio_init_enc(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len) +{ + bio->start = bp; + bio->end = bp + len; + bio->bp = bp; + bio->buf = 0; + bio->ct = 8; +} + +void opj_bio_init_dec(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len) +{ + bio->start = bp; + bio->end = bp + len; + bio->bp = bp; + bio->buf = 0; + bio->ct = 0; +} + +void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) +{ + if (bio->ct == 0) { + opj_bio_byteout( + bio); /* MSD: why not check the return value of this function ? */ + } + bio->ct--; + bio->buf |= b << bio->ct; +} + +void opj_bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n) +{ + OPJ_INT32 i; + + assert((n > 0U) && (n <= 32U)); + for (i = (OPJ_INT32)n - 1; i >= 0; i--) { + opj_bio_putbit(bio, (v >> i) & 1); + } +} + +OPJ_UINT32 opj_bio_read(opj_bio_t *bio, OPJ_UINT32 n) +{ + OPJ_INT32 i; + OPJ_UINT32 v; + + assert((n > 0U) /* && (n <= 32U)*/); +#ifdef OPJ_UBSAN_BUILD + /* This assert fails for some corrupted images which are gracefully rejected */ + /* Add this assert only for ubsan build. */ + /* This is the condition for overflow not to occur below which is needed because of OPJ_NOSANITIZE */ + assert(n <= 32U); +#endif + v = 0U; + for (i = (OPJ_INT32)n - 1; i >= 0; i--) { + v |= opj_bio_getbit(bio) << + i; /* can't overflow, opj_bio_getbit returns 0 or 1 */ + } + return v; +} + +OPJ_BOOL opj_bio_flush(opj_bio_t *bio) +{ + if (! opj_bio_byteout(bio)) { + return OPJ_FALSE; + } + if (bio->ct == 7) { + if (! opj_bio_byteout(bio)) { + return OPJ_FALSE; + } + } + return OPJ_TRUE; +} + +OPJ_BOOL opj_bio_inalign(opj_bio_t *bio) +{ + if ((bio->buf & 0xff) == 0xff) { + if (! opj_bio_bytein(bio)) { + return OPJ_FALSE; + } + } + bio->ct = 0; + return OPJ_TRUE; +} diff --git a/client/deps/openjpeg/bio.h b/client/deps/openjpeg/bio.h new file mode 100644 index 000000000..d482f9ead --- /dev/null +++ b/client/deps/openjpeg/bio.h @@ -0,0 +1,142 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_BIO_H +#define OPJ_BIO_H + +#include /* ptrdiff_t */ + +/** +@file bio.h +@brief Implementation of an individual bit input-output (BIO) + +The functions in BIO.C have for goal to realize an individual bit input - output. +*/ + +/** @defgroup BIO BIO - Individual bit input-output stream */ +/*@{*/ + +/** +Individual bit input-output stream (BIO) +*/ +typedef struct opj_bio { + /** pointer to the start of the buffer */ + OPJ_BYTE *start; + /** pointer to the end of the buffer */ + OPJ_BYTE *end; + /** pointer to the present position in the buffer */ + OPJ_BYTE *bp; + /** temporary place where each byte is read or written */ + OPJ_UINT32 buf; + /** coder : number of bits free to write. decoder : number of bits read */ + OPJ_UINT32 ct; +} opj_bio_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new BIO handle +@return Returns a new BIO handle if successful, returns NULL otherwise +*/ +opj_bio_t* opj_bio_create(void); +/** +Destroy a previously created BIO handle +@param bio BIO handle to destroy +*/ +void opj_bio_destroy(opj_bio_t *bio); +/** +Number of bytes written. +@param bio BIO handle +@return Returns the number of bytes written +*/ +ptrdiff_t opj_bio_numbytes(opj_bio_t *bio); +/** +Init encoder +@param bio BIO handle +@param bp Output buffer +@param len Output buffer length +*/ +void opj_bio_init_enc(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len); +/** +Init decoder +@param bio BIO handle +@param bp Input buffer +@param len Input buffer length +*/ +void opj_bio_init_dec(opj_bio_t *bio, OPJ_BYTE *bp, OPJ_UINT32 len); +/** +Write bits +@param bio BIO handle +@param v Value of bits +@param n Number of bits to write +*/ +void opj_bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n); + +/** +Write a bit +@param bio BIO handle +@param b Bit to write (0 or 1) +*/ +void opj_bio_putbit(opj_bio_t *bio, OPJ_UINT32 b); + +/** +Read bits +@param bio BIO handle +@param n Number of bits to read +@return Returns the corresponding read number +*/ +OPJ_UINT32 opj_bio_read(opj_bio_t *bio, OPJ_UINT32 n); +/** +Flush bits +@param bio BIO handle +@return Returns OPJ_TRUE if successful, returns OPJ_FALSE otherwise +*/ +OPJ_BOOL opj_bio_flush(opj_bio_t *bio); +/** +Passes the ending bits (coming from flushing) +@param bio BIO handle +@return Returns OPJ_TRUE if successful, returns OPJ_FALSE otherwise +*/ +OPJ_BOOL opj_bio_inalign(opj_bio_t *bio); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_BIO_H */ + diff --git a/client/deps/openjpeg/cio.c b/client/deps/openjpeg/cio.c new file mode 100644 index 000000000..4fde9fe23 --- /dev/null +++ b/client/deps/openjpeg/cio.c @@ -0,0 +1,683 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ + +void opj_write_bytes_BE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, + OPJ_UINT32 p_nb_bytes) +{ + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof( + OPJ_UINT32) - p_nb_bytes; + + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + + memcpy(p_buffer, l_data_ptr, p_nb_bytes); +} + +void opj_write_bytes_LE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, + OPJ_UINT32 p_nb_bytes) +{ + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes - 1; + OPJ_UINT32 i; + + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + + for (i = 0; i < p_nb_bytes; ++i) { + *(p_buffer++) = *(l_data_ptr--); + } +} + +void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, + OPJ_UINT32 p_nb_bytes) +{ + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value); + + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + + *p_value = 0; + memcpy(l_data_ptr + sizeof(OPJ_UINT32) - p_nb_bytes, p_buffer, p_nb_bytes); +} + +void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, + OPJ_UINT32 p_nb_bytes) +{ + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + p_nb_bytes - 1; + OPJ_UINT32 i; + + assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); + + *p_value = 0; + for (i = 0; i < p_nb_bytes; ++i) { + *(l_data_ptr--) = *(p_buffer++); + } +} + +void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value) +{ + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value); + memcpy(p_buffer, l_data_ptr, sizeof(OPJ_FLOAT64)); +} + +void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value) +{ + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof( + OPJ_FLOAT64) - 1; + OPJ_UINT32 i; + for (i = 0; i < sizeof(OPJ_FLOAT64); ++i) { + *(p_buffer++) = *(l_data_ptr--); + } +} + +void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value) +{ + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value); + memcpy(l_data_ptr, p_buffer, sizeof(OPJ_FLOAT64)); +} + +void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value) +{ + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT64) - 1; + OPJ_UINT32 i; + for (i = 0; i < sizeof(OPJ_FLOAT64); ++i) { + *(l_data_ptr--) = *(p_buffer++); + } +} + +void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value) +{ + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value); + memcpy(p_buffer, l_data_ptr, sizeof(OPJ_FLOAT32)); +} + +void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value) +{ + const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + sizeof( + OPJ_FLOAT32) - 1; + OPJ_UINT32 i; + for (i = 0; i < sizeof(OPJ_FLOAT32); ++i) { + *(p_buffer++) = *(l_data_ptr--); + } +} + +void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value) +{ + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value); + memcpy(l_data_ptr, p_buffer, sizeof(OPJ_FLOAT32)); +} + +void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value) +{ + OPJ_BYTE * l_data_ptr = ((OPJ_BYTE *) p_value) + sizeof(OPJ_FLOAT32) - 1; + OPJ_UINT32 i; + for (i = 0; i < sizeof(OPJ_FLOAT32); ++i) { + *(l_data_ptr--) = *(p_buffer++); + } +} + +opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size, + OPJ_BOOL l_is_input) +{ + opj_stream_private_t * l_stream = 00; + l_stream = (opj_stream_private_t*) opj_calloc(1, sizeof(opj_stream_private_t)); + if (! l_stream) { + return 00; + } + + l_stream->m_buffer_size = p_buffer_size; + l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_buffer_size); + if (! l_stream->m_stored_data) { + opj_free(l_stream); + return 00; + } + + l_stream->m_current_data = l_stream->m_stored_data; + + if (l_is_input) { + l_stream->m_status |= OPJ_STREAM_STATUS_INPUT; + l_stream->m_opj_skip = opj_stream_read_skip; + l_stream->m_opj_seek = opj_stream_read_seek; + } else { + l_stream->m_status |= OPJ_STREAM_STATUS_OUTPUT; + l_stream->m_opj_skip = opj_stream_write_skip; + l_stream->m_opj_seek = opj_stream_write_seek; + } + + l_stream->m_read_fn = opj_stream_default_read; + l_stream->m_write_fn = opj_stream_default_write; + l_stream->m_skip_fn = opj_stream_default_skip; + l_stream->m_seek_fn = opj_stream_default_seek; + + return (opj_stream_t *) l_stream; +} + +opj_stream_t* OPJ_CALLCONV opj_stream_default_create(OPJ_BOOL l_is_input) +{ + return opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE, l_is_input); +} + +void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if (l_stream) { + if (l_stream->m_free_user_data_fn) { + l_stream->m_free_user_data_fn(l_stream->m_user_data); + } + opj_free(l_stream->m_stored_data); + l_stream->m_stored_data = 00; + opj_free(l_stream); + } +} + +void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, + opj_stream_read_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if ((!l_stream) || (!(l_stream->m_status & OPJ_STREAM_STATUS_INPUT))) { + return; + } + + l_stream->m_read_fn = p_function; +} + +void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, + opj_stream_seek_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if (!l_stream) { + return; + } + l_stream->m_seek_fn = p_function; +} + +void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, + opj_stream_write_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if ((!l_stream) || (!(l_stream->m_status & OPJ_STREAM_STATUS_OUTPUT))) { + return; + } + + l_stream->m_write_fn = p_function; +} + +void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, + opj_stream_skip_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if (! l_stream) { + return; + } + + l_stream->m_skip_fn = p_function; +} + +void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, + void * p_data, opj_stream_free_user_data_fn p_function) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + if (!l_stream) { + return; + } + l_stream->m_user_data = p_data; + l_stream->m_free_user_data_fn = p_function; +} + +void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, + OPJ_UINT64 data_length) +{ + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + if (!l_stream) { + return; + } + l_stream->m_user_data_length = data_length; +} + +OPJ_SIZE_T opj_stream_read_data(opj_stream_private_t * p_stream, + OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) +{ + OPJ_SIZE_T l_read_nb_bytes = 0; + if (p_stream->m_bytes_in_buffer >= p_size) { + memcpy(p_buffer, p_stream->m_current_data, p_size); + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer -= p_size; + l_read_nb_bytes += p_size; + p_stream->m_byte_offset += (OPJ_OFF_T)p_size; + return l_read_nb_bytes; + } + + /* we are now in the case when the remaining data if not sufficient */ + if (p_stream->m_status & OPJ_STREAM_STATUS_END) { + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + memcpy(p_buffer, p_stream->m_current_data, p_stream->m_bytes_in_buffer); + p_stream->m_current_data += p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T) - 1; + } + + /* the flag is not set, we copy data and then do an actual read on the stream */ + if (p_stream->m_bytes_in_buffer) { + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + memcpy(p_buffer, p_stream->m_current_data, p_stream->m_bytes_in_buffer); + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += p_stream->m_bytes_in_buffer; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } else { + /* case where we are already at the end of the buffer + so reset the m_current_data to point to the start of the + stored buffer to get ready to read from disk*/ + p_stream->m_current_data = p_stream->m_stored_data; + } + + for (;;) { + /* we should read less than a chunk -> read a chunk */ + if (p_size < p_stream->m_buffer_size) { + /* we should do an actual read on the media */ + p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_stream->m_stored_data, + p_stream->m_buffer_size, p_stream->m_user_data); + + if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T) - 1) { + /* end of stream */ + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + + p_stream->m_bytes_in_buffer = 0; + p_stream->m_status |= OPJ_STREAM_STATUS_END; + /* end of stream */ + return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T) - 1; + } else if (p_stream->m_bytes_in_buffer < p_size) { + /* not enough data */ + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + memcpy(p_buffer, p_stream->m_current_data, p_stream->m_bytes_in_buffer); + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += p_stream->m_bytes_in_buffer; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } else { + l_read_nb_bytes += p_size; + memcpy(p_buffer, p_stream->m_current_data, p_size); + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer -= p_size; + p_stream->m_byte_offset += (OPJ_OFF_T)p_size; + return l_read_nb_bytes; + } + } else { + /* direct read on the dest buffer */ + p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer, p_size, + p_stream->m_user_data); + + if (p_stream->m_bytes_in_buffer == (OPJ_SIZE_T) - 1) { + /* end of stream */ + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + + p_stream->m_bytes_in_buffer = 0; + p_stream->m_status |= OPJ_STREAM_STATUS_END; + /* end of stream */ + return l_read_nb_bytes ? l_read_nb_bytes : (OPJ_SIZE_T) - 1; + } else if (p_stream->m_bytes_in_buffer < p_size) { + /* not enough data */ + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + p_stream->m_current_data = p_stream->m_stored_data; + p_buffer += p_stream->m_bytes_in_buffer; + p_size -= p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } else { + /* we have read the exact size */ + l_read_nb_bytes += p_stream->m_bytes_in_buffer; + p_stream->m_byte_offset += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_current_data = p_stream->m_stored_data; + p_stream->m_bytes_in_buffer = 0; + return l_read_nb_bytes; + } + } + } +} + +OPJ_SIZE_T opj_stream_write_data(opj_stream_private_t * p_stream, + const OPJ_BYTE * p_buffer, + OPJ_SIZE_T p_size, + opj_event_mgr_t * p_event_mgr) +{ + OPJ_SIZE_T l_remaining_bytes = 0; + OPJ_SIZE_T l_write_nb_bytes = 0; + + if (p_stream->m_status & OPJ_STREAM_STATUS_ERROR) { + return (OPJ_SIZE_T) - 1; + } + + for (;;) { + l_remaining_bytes = p_stream->m_buffer_size - p_stream->m_bytes_in_buffer; + + /* we have more memory than required */ + if (l_remaining_bytes >= p_size) { + memcpy(p_stream->m_current_data, p_buffer, p_size); + + p_stream->m_current_data += p_size; + p_stream->m_bytes_in_buffer += p_size; + l_write_nb_bytes += p_size; + p_stream->m_byte_offset += (OPJ_OFF_T)p_size; + + return l_write_nb_bytes; + } + + /* we copy data and then do an actual read on the stream */ + if (l_remaining_bytes) { + l_write_nb_bytes += l_remaining_bytes; + + memcpy(p_stream->m_current_data, p_buffer, l_remaining_bytes); + + p_stream->m_current_data = p_stream->m_stored_data; + + p_buffer += l_remaining_bytes; + p_size -= l_remaining_bytes; + p_stream->m_bytes_in_buffer += l_remaining_bytes; + p_stream->m_byte_offset += (OPJ_OFF_T)l_remaining_bytes; + } + + if (! opj_stream_flush(p_stream, p_event_mgr)) { + return (OPJ_SIZE_T) - 1; + } + } + +} + +OPJ_BOOL opj_stream_flush(opj_stream_private_t * p_stream, + opj_event_mgr_t * p_event_mgr) +{ + /* the number of bytes written on the media. */ + OPJ_SIZE_T l_current_write_nb_bytes = 0; + + p_stream->m_current_data = p_stream->m_stored_data; + + while (p_stream->m_bytes_in_buffer) { + /* we should do an actual write on the media */ + l_current_write_nb_bytes = p_stream->m_write_fn(p_stream->m_current_data, + p_stream->m_bytes_in_buffer, + p_stream->m_user_data); + + if (l_current_write_nb_bytes == (OPJ_SIZE_T) - 1) { + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + opj_event_msg(p_event_mgr, EVT_INFO, "Error on writing stream!\n"); + + return OPJ_FALSE; + } + + p_stream->m_current_data += l_current_write_nb_bytes; + p_stream->m_bytes_in_buffer -= l_current_write_nb_bytes; + } + + p_stream->m_current_data = p_stream->m_stored_data; + + return OPJ_TRUE; +} + +OPJ_OFF_T opj_stream_read_skip(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) +{ + OPJ_OFF_T l_skip_nb_bytes = 0; + OPJ_OFF_T l_current_skip_nb_bytes = 0; + + assert(p_size >= 0); + + if (p_stream->m_bytes_in_buffer >= (OPJ_SIZE_T)p_size) { + p_stream->m_current_data += p_size; + /* it is safe to cast p_size to OPJ_SIZE_T since it is <= m_bytes_in_buffer + which is of type OPJ_SIZE_T */ + p_stream->m_bytes_in_buffer -= (OPJ_SIZE_T)p_size; + l_skip_nb_bytes += p_size; + p_stream->m_byte_offset += l_skip_nb_bytes; + return l_skip_nb_bytes; + } + + /* we are now in the case when the remaining data if not sufficient */ + if (p_stream->m_status & OPJ_STREAM_STATUS_END) { + l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_current_data += p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + p_stream->m_byte_offset += l_skip_nb_bytes; + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1; + } + + /* the flag is not set, we copy data and then do an actual skip on the stream */ + if (p_stream->m_bytes_in_buffer) { + l_skip_nb_bytes += (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_current_data = p_stream->m_stored_data; + p_size -= (OPJ_OFF_T)p_stream->m_bytes_in_buffer; + p_stream->m_bytes_in_buffer = 0; + } + + while (p_size > 0) { + /* Check if we are going beyond the end of file. Most skip_fn do not */ + /* check that, but we must be careful not to advance m_byte_offset */ + /* beyond m_user_data_length, otherwise */ + /* opj_stream_get_number_byte_left() will assert. */ + if ((OPJ_UINT64)(p_stream->m_byte_offset + l_skip_nb_bytes + p_size) > + p_stream->m_user_data_length) { + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + + p_stream->m_byte_offset += l_skip_nb_bytes; + l_skip_nb_bytes = (OPJ_OFF_T)(p_stream->m_user_data_length - + (OPJ_UINT64)p_stream->m_byte_offset); + + opj_stream_read_seek(p_stream, (OPJ_OFF_T)p_stream->m_user_data_length, + p_event_mgr); + p_stream->m_status |= OPJ_STREAM_STATUS_END; + + /* end if stream */ + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1; + } + + /* we should do an actual skip on the media */ + l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data); + if (l_current_skip_nb_bytes == (OPJ_OFF_T) - 1) { + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + + p_stream->m_status |= OPJ_STREAM_STATUS_END; + p_stream->m_byte_offset += l_skip_nb_bytes; + /* end if stream */ + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1; + } + p_size -= l_current_skip_nb_bytes; + l_skip_nb_bytes += l_current_skip_nb_bytes; + } + + p_stream->m_byte_offset += l_skip_nb_bytes; + + return l_skip_nb_bytes; +} + +OPJ_OFF_T opj_stream_write_skip(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) +{ + OPJ_BOOL l_is_written = 0; + OPJ_OFF_T l_current_skip_nb_bytes = 0; + OPJ_OFF_T l_skip_nb_bytes = 0; + + if (p_stream->m_status & OPJ_STREAM_STATUS_ERROR) { + return (OPJ_OFF_T) - 1; + } + + /* we should flush data */ + l_is_written = opj_stream_flush(p_stream, p_event_mgr); + if (! l_is_written) { + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + p_stream->m_bytes_in_buffer = 0; + return (OPJ_OFF_T) - 1; + } + /* then skip */ + + while (p_size > 0) { + /* we should do an actual skip on the media */ + l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data); + + if (l_current_skip_nb_bytes == (OPJ_OFF_T) - 1) { + opj_event_msg(p_event_mgr, EVT_INFO, "Stream error!\n"); + + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + p_stream->m_byte_offset += l_skip_nb_bytes; + /* end if stream */ + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1; + } + p_size -= l_current_skip_nb_bytes; + l_skip_nb_bytes += l_current_skip_nb_bytes; + } + + p_stream->m_byte_offset += l_skip_nb_bytes; + + return l_skip_nb_bytes; +} + +OPJ_OFF_T opj_stream_tell(const opj_stream_private_t * p_stream) +{ + return p_stream->m_byte_offset; +} + +OPJ_OFF_T opj_stream_get_number_byte_left(const opj_stream_private_t * p_stream) +{ + assert(p_stream->m_byte_offset >= 0); + assert(p_stream->m_user_data_length >= (OPJ_UINT64)p_stream->m_byte_offset); + return p_stream->m_user_data_length ? + (OPJ_OFF_T)(p_stream->m_user_data_length) - p_stream->m_byte_offset : + 0; +} + +OPJ_OFF_T opj_stream_skip(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + opj_event_mgr_t * p_event_mgr) +{ + assert(p_size >= 0); + return p_stream->m_opj_skip(p_stream, p_size, p_event_mgr); +} + +OPJ_BOOL opj_stream_read_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + opj_event_mgr_t * p_event_mgr) +{ + OPJ_ARG_NOT_USED(p_event_mgr); + p_stream->m_current_data = p_stream->m_stored_data; + p_stream->m_bytes_in_buffer = 0; + + if (!(p_stream->m_seek_fn(p_size, p_stream->m_user_data))) { + p_stream->m_status |= OPJ_STREAM_STATUS_END; + return OPJ_FALSE; + } else { + /* reset stream status */ + p_stream->m_status &= (~OPJ_STREAM_STATUS_END); + p_stream->m_byte_offset = p_size; + + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_stream_write_seek(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, opj_event_mgr_t * p_event_mgr) +{ + if (! opj_stream_flush(p_stream, p_event_mgr)) { + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + return OPJ_FALSE; + } + + p_stream->m_current_data = p_stream->m_stored_data; + p_stream->m_bytes_in_buffer = 0; + + if (! p_stream->m_seek_fn(p_size, p_stream->m_user_data)) { + p_stream->m_status |= OPJ_STREAM_STATUS_ERROR; + return OPJ_FALSE; + } else { + p_stream->m_byte_offset = p_size; + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_stream_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + struct opj_event_mgr * p_event_mgr) +{ + assert(p_size >= 0); + return p_stream->m_opj_seek(p_stream, p_size, p_event_mgr); +} + +OPJ_BOOL opj_stream_has_seek(const opj_stream_private_t * p_stream) +{ + return p_stream->m_seek_fn != opj_stream_default_seek; +} + +OPJ_SIZE_T opj_stream_default_read(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data) +{ + OPJ_ARG_NOT_USED(p_buffer); + OPJ_ARG_NOT_USED(p_nb_bytes); + OPJ_ARG_NOT_USED(p_user_data); + return (OPJ_SIZE_T) - 1; +} + +OPJ_SIZE_T opj_stream_default_write(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data) +{ + OPJ_ARG_NOT_USED(p_buffer); + OPJ_ARG_NOT_USED(p_nb_bytes); + OPJ_ARG_NOT_USED(p_user_data); + return (OPJ_SIZE_T) - 1; +} + +OPJ_OFF_T opj_stream_default_skip(OPJ_OFF_T p_nb_bytes, void * p_user_data) +{ + OPJ_ARG_NOT_USED(p_nb_bytes); + OPJ_ARG_NOT_USED(p_user_data); + return (OPJ_OFF_T) - 1; +} + +OPJ_BOOL opj_stream_default_seek(OPJ_OFF_T p_nb_bytes, void * p_user_data) +{ + OPJ_ARG_NOT_USED(p_nb_bytes); + OPJ_ARG_NOT_USED(p_user_data); + return OPJ_FALSE; +} diff --git a/client/deps/openjpeg/cio.h b/client/deps/openjpeg/cio.h new file mode 100644 index 000000000..7caee30af --- /dev/null +++ b/client/deps/openjpeg/cio.h @@ -0,0 +1,412 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_CIO_H +#define OPJ_CIO_H +/** +@file cio.h +@brief Implementation of a byte input-output process (CIO) + +The functions in CIO.C have for goal to realize a byte input / output process. +*/ + +/** @defgroup CIO CIO - byte input-output stream */ +/*@{*/ + +#include "opj_config_private.h" + +/* ----------------------------------------------------------------------- */ + +#if defined(OPJ_BIG_ENDIAN) +#define opj_write_bytes opj_write_bytes_BE +#define opj_read_bytes opj_read_bytes_BE +#define opj_write_double opj_write_double_BE +#define opj_read_double opj_read_double_BE +#define opj_write_float opj_write_float_BE +#define opj_read_float opj_read_float_BE +#else +#define opj_write_bytes opj_write_bytes_LE +#define opj_read_bytes opj_read_bytes_LE +#define opj_write_double opj_write_double_LE +#define opj_read_double opj_read_double_LE +#define opj_write_float opj_write_float_LE +#define opj_read_float opj_read_float_LE +#endif + + +#define OPJ_STREAM_STATUS_OUTPUT 0x1U +#define OPJ_STREAM_STATUS_INPUT 0x2U +#define OPJ_STREAM_STATUS_END 0x4U +#define OPJ_STREAM_STATUS_ERROR 0x8U + +/** +Byte input-output stream. +*/ +typedef struct opj_stream_private { + /** + * User data, be it files, ... The actual data depends on the type of the stream. + */ + void * m_user_data; + + /** + * Pointer to function to free m_user_data (NULL at initialization) + * when destroying the stream. If pointer is NULL the function is not + * called and the m_user_data is not freed (even if non-NULL). + */ + opj_stream_free_user_data_fn m_free_user_data_fn; + + /** + * User data length + */ + OPJ_UINT64 m_user_data_length; + + /** + * Pointer to actual read function (NULL at the initialization of the cio. + */ + opj_stream_read_fn m_read_fn; + + /** + * Pointer to actual write function (NULL at the initialization of the cio. + */ + opj_stream_write_fn m_write_fn; + + /** + * Pointer to actual skip function (NULL at the initialization of the cio. + * There is no seek function to prevent from back and forth slow procedures. + */ + opj_stream_skip_fn m_skip_fn; + + /** + * Pointer to actual seek function (if available). + */ + opj_stream_seek_fn m_seek_fn; + + /** + * Actual data stored into the stream if read from. Data is read by chunk of fixed size. + * you should never access this data directly. + */ + OPJ_BYTE * m_stored_data; + + /** + * Pointer to the current read data. + */ + OPJ_BYTE * m_current_data; + + /** + * FIXME DOC. + */ + OPJ_OFF_T(* m_opj_skip)(struct opj_stream_private *, OPJ_OFF_T, + struct opj_event_mgr *); + + /** + * FIXME DOC. + */ + OPJ_BOOL(* m_opj_seek)(struct opj_stream_private *, OPJ_OFF_T, + struct opj_event_mgr *); + + /** + * number of bytes containing in the buffer. + */ + OPJ_SIZE_T m_bytes_in_buffer; + + /** + * The number of bytes read/written from the beginning of the stream + */ + OPJ_OFF_T m_byte_offset; + + /** + * The size of the buffer. + */ + OPJ_SIZE_T m_buffer_size; + + /** + * Flags to tell the status of the stream. + * Used with OPJ_STREAM_STATUS_* defines. + */ + OPJ_UINT32 m_status; + +} +opj_stream_private_t; + +/** @name Exported functions (see also openjpeg.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** + * Write some bytes to the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + * @param p_nb_bytes the number of bytes to write +*/ +void opj_write_bytes_BE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, + OPJ_UINT32 p_nb_bytes); + +/** + * Reads some bytes from the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + * @param p_nb_bytes the nb bytes to read. + * @return the number of bytes read or -1 if an error occurred. + */ +void opj_read_bytes_BE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, + OPJ_UINT32 p_nb_bytes); + +/** + * Write some bytes to the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + * @param p_nb_bytes the number of bytes to write + * @return the number of bytes written or -1 if an error occurred +*/ +void opj_write_bytes_LE(OPJ_BYTE * p_buffer, OPJ_UINT32 p_value, + OPJ_UINT32 p_nb_bytes); + +/** + * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + * @param p_nb_bytes the nb bytes to read. + * @return the number of bytes read or -1 if an error occurred. + */ +void opj_read_bytes_LE(const OPJ_BYTE * p_buffer, OPJ_UINT32 * p_value, + OPJ_UINT32 p_nb_bytes); + + +/** + * Write some bytes to the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + */ +void opj_write_double_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value); + +/*** + * Write some bytes to the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + */ +void opj_write_double_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT64 p_value); + +/** + * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + */ +void opj_read_double_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value); + +/** + * Reads some bytes from the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + */ +void opj_read_double_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT64 * p_value); + +/** + * Reads some bytes from the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + */ +void opj_read_float_LE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value); + +/** + * Reads some bytes from the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to read data from. + * @param p_value pointer to the value that will store the data. + */ +void opj_read_float_BE(const OPJ_BYTE * p_buffer, OPJ_FLOAT32 * p_value); + +/** + * Write some bytes to the given data buffer, this function is used in Little Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + */ +void opj_write_float_LE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value); + +/*** + * Write some bytes to the given data buffer, this function is used in Big Endian cpus. + * @param p_buffer pointer the data buffer to write data to. + * @param p_value the value to write + */ +void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value); + +/** + * Reads some bytes from the stream. + * @param p_stream the stream to read data from. + * @param p_buffer pointer to the data buffer that will receive the data. + * @param p_size number of bytes to read. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes read, or -1 if an error occurred or if the stream is at the end. + */ +OPJ_SIZE_T opj_stream_read_data(opj_stream_private_t * p_stream, + OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Writes some bytes to the stream. + * @param p_stream the stream to write data to. + * @param p_buffer pointer to the data buffer holds the data to be writtent. + * @param p_size number of bytes to write. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes writtent, or -1 if an error occurred. + */ +OPJ_SIZE_T opj_stream_write_data(opj_stream_private_t * p_stream, + const OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, + struct opj_event_mgr * p_event_mgr); + +/** + * Writes the content of the stream buffer to the stream. + * @param p_stream the stream to write data to. + * @param p_event_mgr the user event manager to be notified of special events. + * @return true if the data could be flushed, false else. + */ +OPJ_BOOL opj_stream_flush(opj_stream_private_t * p_stream, + struct opj_event_mgr * p_event_mgr); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occurred. + */ +OPJ_OFF_T opj_stream_skip(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + struct opj_event_mgr * p_event_mgr); + +/** + * Tells the byte offset on the stream (similar to ftell). + * + * @param p_stream the stream to get the information from. + * + * @return the current position o fthe stream. + */ +OPJ_OFF_T opj_stream_tell(const opj_stream_private_t * p_stream); + + +/** + * Get the number of bytes left before the end of the stream (similar to cio_numbytesleft). + * + * @param p_stream the stream to get the information from. + * + * @return Number of bytes left before the end of the stream. + */ +OPJ_OFF_T opj_stream_get_number_byte_left(const opj_stream_private_t * + p_stream); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occurred. + */ +OPJ_OFF_T opj_stream_write_skip(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occurred. + */ +OPJ_OFF_T opj_stream_read_skip(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return OPJ_TRUE if success, or OPJ_FALSE if an error occurred. + */ +OPJ_BOOL opj_stream_read_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + struct opj_event_mgr * p_event_mgr); + +/** + * Skips a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return the number of bytes skipped, or -1 if an error occurred. + */ +OPJ_BOOL opj_stream_write_seek(opj_stream_private_t * p_stream, + OPJ_OFF_T p_size, struct opj_event_mgr * p_event_mgr); + +/** + * Seeks a number of bytes from the stream. + * @param p_stream the stream to skip data from. + * @param p_size the number of bytes to skip. + * @param p_event_mgr the user event manager to be notified of special events. + * @return true if the stream is seekable. + */ +OPJ_BOOL opj_stream_seek(opj_stream_private_t * p_stream, OPJ_OFF_T p_size, + struct opj_event_mgr * p_event_mgr); + +/** + * Tells if the given stream is seekable. + */ +OPJ_BOOL opj_stream_has_seek(const opj_stream_private_t * p_stream); + +/** + * FIXME DOC. + */ +OPJ_SIZE_T opj_stream_default_read(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data); + +/** + * FIXME DOC. + */ +OPJ_SIZE_T opj_stream_default_write(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data); + +/** + * FIXME DOC. + */ +OPJ_OFF_T opj_stream_default_skip(OPJ_OFF_T p_nb_bytes, void * p_user_data); + +/** + * FIXME DOC. + */ +OPJ_BOOL opj_stream_default_seek(OPJ_OFF_T p_nb_bytes, void * p_user_data); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + + +#endif /* OPJ_CIO_H */ + diff --git a/client/deps/openjpeg/dwt.c b/client/deps/openjpeg/dwt.c new file mode 100644 index 000000000..11aae472d --- /dev/null +++ b/client/deps/openjpeg/dwt.c @@ -0,0 +1,3979 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2007, Jonathan Ballard + * Copyright (c) 2007, Callum Lerwick + * Copyright (c) 2017, IntoPIX SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include + +#define OPJ_SKIP_POISON +#include "opj_includes.h" + +#ifdef __SSE__ +#include +#endif +#ifdef __SSE2__ +#include +#endif +#ifdef __SSSE3__ +#include +#endif +#if (defined(__AVX2__) || defined(__AVX512F__)) +#include +#endif + +#if defined(__GNUC__) +#pragma GCC poison malloc calloc realloc free +#endif + +/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ +/*@{*/ + +#define OPJ_WS(i) v->mem[(i)*2] +#define OPJ_WD(i) v->mem[(1+(i)*2)] + +#if defined(__AVX512F__) +/** Number of int32 values in a AVX512 register */ +#define VREG_INT_COUNT 16 +#elif defined(__AVX2__) +/** Number of int32 values in a AVX2 register */ +#define VREG_INT_COUNT 8 +#else +/** Number of int32 values in a SSE2 register */ +#define VREG_INT_COUNT 4 +#endif + +/** Number of columns that we can process in parallel in the vertical pass */ +#define PARALLEL_COLS_53 (2*VREG_INT_COUNT) + +/** @name Local data structures */ +/*@{*/ + +typedef struct dwt_local { + OPJ_INT32* mem; + OPJ_INT32 dn; /* number of elements in high pass band */ + OPJ_INT32 sn; /* number of elements in low pass band */ + OPJ_INT32 cas; /* 0 = start on even coord, 1 = start on odd coord */ +} opj_dwt_t; + +#define NB_ELTS_V8 8 + +typedef union { + OPJ_FLOAT32 f[NB_ELTS_V8]; +} opj_v8_t; + +typedef struct v8dwt_local { + opj_v8_t* wavelet ; + OPJ_INT32 dn ; /* number of elements in high pass band */ + OPJ_INT32 sn ; /* number of elements in low pass band */ + OPJ_INT32 cas ; /* 0 = start on even coord, 1 = start on odd coord */ + OPJ_UINT32 win_l_x0; /* start coord in low pass band */ + OPJ_UINT32 win_l_x1; /* end coord in low pass band */ + OPJ_UINT32 win_h_x0; /* start coord in high pass band */ + OPJ_UINT32 win_h_x1; /* end coord in high pass band */ +} opj_v8dwt_t ; + +/* From table F.4 from the standard */ +static const OPJ_FLOAT32 opj_dwt_alpha = -1.586134342f; +static const OPJ_FLOAT32 opj_dwt_beta = -0.052980118f; +static const OPJ_FLOAT32 opj_dwt_gamma = 0.882911075f; +static const OPJ_FLOAT32 opj_dwt_delta = 0.443506852f; + +static const OPJ_FLOAT32 opj_K = 1.230174105f; +static const OPJ_FLOAT32 opj_invK = (OPJ_FLOAT32)(1.0 / 1.230174105); + +/*@}*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Forward lazy transform (horizontal) +*/ +static void opj_dwt_deinterleave_h(const OPJ_INT32 * OPJ_RESTRICT a, + OPJ_INT32 * OPJ_RESTRICT b, + OPJ_INT32 dn, + OPJ_INT32 sn, OPJ_INT32 cas); + +/** +Forward 9-7 wavelet transform in 1-D +*/ +static void opj_dwt_encode_1_real(void *a, OPJ_INT32 dn, OPJ_INT32 sn, + OPJ_INT32 cas); +/** +Explicit calculation of the Quantization Stepsizes +*/ +static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, + opj_stepsize_t *bandno_stepsize); +/** +Inverse wavelet transform in 2-D. +*/ +static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, + opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i); + +static OPJ_BOOL opj_dwt_decode_partial_tile( + opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres); + +/* Forward transform, for the vertical pass, processing cols columns */ +/* where cols <= NB_ELTS_V8 */ +/* Where void* is a OPJ_INT32* for 5x3 and OPJ_FLOAT32* for 9x7 */ +typedef void (*opj_encode_and_deinterleave_v_fnptr_type)( + void *array, + void *tmp, + OPJ_UINT32 height, + OPJ_BOOL even, + OPJ_UINT32 stride_width, + OPJ_UINT32 cols); + +/* Where void* is a OPJ_INT32* for 5x3 and OPJ_FLOAT32* for 9x7 */ +typedef void (*opj_encode_and_deinterleave_h_one_row_fnptr_type)( + void *row, + void *tmp, + OPJ_UINT32 width, + OPJ_BOOL even); + +static OPJ_BOOL opj_dwt_encode_procedure(opj_thread_pool_t* tp, + opj_tcd_tilecomp_t * tilec, + opj_encode_and_deinterleave_v_fnptr_type p_encode_and_deinterleave_v, + opj_encode_and_deinterleave_h_one_row_fnptr_type + p_encode_and_deinterleave_h_one_row); + +static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r, + OPJ_UINT32 i); + +/* */ +/* Inverse 9-7 wavelet transform in 1-D. */ +/* */ + +/*@}*/ + +/*@}*/ + +#define OPJ_S(i) a[(i)*2] +#define OPJ_D(i) a[(1+(i)*2)] +#define OPJ_S_(i) ((i)<0?OPJ_S(0):((i)>=sn?OPJ_S(sn-1):OPJ_S(i))) +#define OPJ_D_(i) ((i)<0?OPJ_D(0):((i)>=dn?OPJ_D(dn-1):OPJ_D(i))) +/* new */ +#define OPJ_SS_(i) ((i)<0?OPJ_S(0):((i)>=dn?OPJ_S(dn-1):OPJ_S(i))) +#define OPJ_DD_(i) ((i)<0?OPJ_D(0):((i)>=sn?OPJ_D(sn-1):OPJ_D(i))) + +/* */ +/* This table contains the norms of the 5-3 wavelets for different bands. */ +/* */ +/* FIXME! the array should really be extended up to 33 resolution levels */ +/* See https://github.com/uclouvain/openjpeg/issues/493 */ +static const OPJ_FLOAT64 opj_dwt_norms[4][10] = { + {1.000, 1.500, 2.750, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3}, + {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {.7186, .9218, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93} +}; + +/* */ +/* This table contains the norms of the 9-7 wavelets for different bands. */ +/* */ +/* FIXME! the array should really be extended up to 33 resolution levels */ +/* See https://github.com/uclouvain/openjpeg/issues/493 */ +static const OPJ_FLOAT64 opj_dwt_norms_real[4][10] = { + {1.000, 1.965, 4.177, 8.403, 16.90, 33.84, 67.69, 135.3, 270.6, 540.9}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0}, + {2.080, 3.865, 8.307, 17.18, 34.71, 69.59, 139.3, 278.6, 557.2} +}; + +/* +========================================================== + local functions +========================================================== +*/ + +/* */ +/* Forward lazy transform (horizontal). */ +/* */ +static void opj_dwt_deinterleave_h(const OPJ_INT32 * OPJ_RESTRICT a, + OPJ_INT32 * OPJ_RESTRICT b, + OPJ_INT32 dn, + OPJ_INT32 sn, OPJ_INT32 cas) +{ + OPJ_INT32 i; + OPJ_INT32 * OPJ_RESTRICT l_dest = b; + const OPJ_INT32 * OPJ_RESTRICT l_src = a + cas; + + for (i = 0; i < sn; ++i) { + *l_dest++ = *l_src; + l_src += 2; + } + + l_dest = b + sn; + l_src = a + 1 - cas; + + for (i = 0; i < dn; ++i) { + *l_dest++ = *l_src; + l_src += 2; + } +} + +#ifdef STANDARD_SLOW_VERSION +/* */ +/* Inverse lazy transform (horizontal). */ +/* */ +static void opj_dwt_interleave_h(const opj_dwt_t* h, OPJ_INT32 *a) +{ + const OPJ_INT32 *ai = a; + OPJ_INT32 *bi = h->mem + h->cas; + OPJ_INT32 i = h->sn; + while (i--) { + *bi = *(ai++); + bi += 2; + } + ai = a + h->sn; + bi = h->mem + 1 - h->cas; + i = h->dn ; + while (i--) { + *bi = *(ai++); + bi += 2; + } +} + +/* */ +/* Inverse lazy transform (vertical). */ +/* */ +static void opj_dwt_interleave_v(const opj_dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) +{ + const OPJ_INT32 *ai = a; + OPJ_INT32 *bi = v->mem + v->cas; + OPJ_INT32 i = v->sn; + while (i--) { + *bi = *ai; + bi += 2; + ai += x; + } + ai = a + (v->sn * (OPJ_SIZE_T)x); + bi = v->mem + 1 - v->cas; + i = v->dn ; + while (i--) { + *bi = *ai; + bi += 2; + ai += x; + } +} + +#endif /* STANDARD_SLOW_VERSION */ + +#ifdef STANDARD_SLOW_VERSION +/* */ +/* Inverse 5-3 wavelet transform in 1-D. */ +/* */ +static void opj_dwt_decode_1_(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, + OPJ_INT32 cas) +{ + OPJ_INT32 i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < sn; i++) { + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + } + for (i = 0; i < dn; i++) { + OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; + } + } + } else { + if (!sn && dn == 1) { /* NEW : CASE ONE ELEMENT */ + OPJ_S(0) /= 2; + } else { + for (i = 0; i < sn; i++) { + OPJ_D(i) -= (OPJ_SS_(i) + OPJ_SS_(i + 1) + 2) >> 2; + } + for (i = 0; i < dn; i++) { + OPJ_S(i) += (OPJ_DD_(i) + OPJ_DD_(i - 1)) >> 1; + } + } + } +} + +static void opj_dwt_decode_1(const opj_dwt_t *v) +{ + opj_dwt_decode_1_(v->mem, v->dn, v->sn, v->cas); +} + +#endif /* STANDARD_SLOW_VERSION */ + +#if defined(__AVX512F__) +static int32_t loop_short_sse(int32_t len, const int32_t** lf_ptr, + const int32_t** hf_ptr, int32_t** out_ptr, + int32_t* prev_even) +{ + int32_t next_even; + __m128i odd, even_m1, unpack1, unpack2; + const int32_t batch = (len - 2) / 8; + const __m128i two = _mm_set1_epi32(2); + + for (int32_t i = 0; i < batch; i++) { + const __m128i lf_ = _mm_loadu_si128((__m128i*)(*lf_ptr + 1)); + const __m128i hf1_ = _mm_loadu_si128((__m128i*)(*hf_ptr)); + const __m128i hf2_ = _mm_loadu_si128((__m128i*)(*hf_ptr + 1)); + + __m128i even = _mm_add_epi32(hf1_, hf2_); + even = _mm_add_epi32(even, two); + even = _mm_srai_epi32(even, 2); + even = _mm_sub_epi32(lf_, even); + + next_even = _mm_extract_epi32(even, 3); + even_m1 = _mm_bslli_si128(even, 4); + even_m1 = _mm_insert_epi32(even_m1, *prev_even, 0); + + //out[0] + out[2] + odd = _mm_add_epi32(even_m1, even); + odd = _mm_srai_epi32(odd, 1); + odd = _mm_add_epi32(odd, hf1_); + + unpack1 = _mm_unpacklo_epi32(even_m1, odd); + unpack2 = _mm_unpackhi_epi32(even_m1, odd); + + _mm_storeu_si128((__m128i*)(*out_ptr + 0), unpack1); + _mm_storeu_si128((__m128i*)(*out_ptr + 4), unpack2); + + *prev_even = next_even; + + *out_ptr += 8; + *lf_ptr += 4; + *hf_ptr += 4; + } + return batch; +} +#endif + +#if !defined(STANDARD_SLOW_VERSION) +static void opj_idwt53_h_cas0(OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp) +{ + OPJ_INT32 i, j; + const OPJ_INT32* in_even = &tiledp[0]; + const OPJ_INT32* in_odd = &tiledp[sn]; + +#ifdef TWO_PASS_VERSION + /* For documentation purpose: performs lifting in two iterations, */ + /* but without explicit interleaving */ + + assert(len > 1); + + /* Even */ + tmp[0] = in_even[0] - ((in_odd[0] + 1) >> 1); + for (i = 2, j = 0; i <= len - 2; i += 2, j++) { + tmp[i] = in_even[j + 1] - ((in_odd[j] + in_odd[j + 1] + 2) >> 2); + } + if (len & 1) { /* if len is odd */ + tmp[len - 1] = in_even[(len - 1) / 2] - ((in_odd[(len - 2) / 2] + 1) >> 1); + } + + /* Odd */ + for (i = 1, j = 0; i < len - 1; i += 2, j++) { + tmp[i] = in_odd[j] + ((tmp[i - 1] + tmp[i + 1]) >> 1); + } + if (!(len & 1)) { /* if len is even */ + tmp[len - 1] = in_odd[(len - 1) / 2] + tmp[len - 2]; + } +#else +#if defined(__AVX512F__) + OPJ_INT32* out_ptr = tmp; + int32_t prev_even = in_even[0] - ((in_odd[0] + 1) >> 1); + + const __m512i permutevar_mask = _mm512_setr_epi32( + 0x10, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e); + const __m512i store1_perm = _mm512_setr_epi64(0x00, 0x01, 0x08, 0x09, 0x02, + 0x03, 0x0a, 0x0b); + const __m512i store2_perm = _mm512_setr_epi64(0x04, 0x05, 0x0c, 0x0d, 0x06, + 0x07, 0x0e, 0x0f); + + const __m512i two = _mm512_set1_epi32(2); + + int32_t simd_batch_512 = (len - 2) / 32; + int32_t leftover; + + for (i = 0; i < simd_batch_512; i++) { + const __m512i lf_avx2 = _mm512_loadu_si512((__m512i*)(in_even + 1)); + const __m512i hf1_avx2 = _mm512_loadu_si512((__m512i*)(in_odd)); + const __m512i hf2_avx2 = _mm512_loadu_si512((__m512i*)(in_odd + 1)); + int32_t next_even; + __m512i duplicate, even_m1, odd, unpack1, unpack2, store1, store2; + + __m512i even = _mm512_add_epi32(hf1_avx2, hf2_avx2); + even = _mm512_add_epi32(even, two); + even = _mm512_srai_epi32(even, 2); + even = _mm512_sub_epi32(lf_avx2, even); + + next_even = _mm_extract_epi32(_mm512_extracti32x4_epi32(even, 3), 3); + + duplicate = _mm512_set1_epi32(prev_even); + even_m1 = _mm512_permutex2var_epi32(even, permutevar_mask, duplicate); + + //out[0] + out[2] + odd = _mm512_add_epi32(even_m1, even); + odd = _mm512_srai_epi32(odd, 1); + odd = _mm512_add_epi32(odd, hf1_avx2); + + unpack1 = _mm512_unpacklo_epi32(even_m1, odd); + unpack2 = _mm512_unpackhi_epi32(even_m1, odd); + + store1 = _mm512_permutex2var_epi64(unpack1, store1_perm, unpack2); + store2 = _mm512_permutex2var_epi64(unpack1, store2_perm, unpack2); + + _mm512_storeu_si512(out_ptr, store1); + _mm512_storeu_si512(out_ptr + 16, store2); + + prev_even = next_even; + + out_ptr += 32; + in_even += 16; + in_odd += 16; + } + + leftover = len - simd_batch_512 * 32; + if (leftover > 8) { + leftover -= 8 * loop_short_sse(leftover, &in_even, &in_odd, &out_ptr, + &prev_even); + } + out_ptr[0] = prev_even; + + for (j = 1; j < (leftover - 2); j += 2) { + out_ptr[2] = in_even[1] - ((in_odd[0] + (in_odd[1]) + 2) >> 2); + out_ptr[1] = in_odd[0] + ((out_ptr[0] + out_ptr[2]) >> 1); + in_even++; + in_odd++; + out_ptr += 2; + } + + if (len & 1) { + out_ptr[2] = in_even[1] - ((in_odd[0] + 1) >> 1); + out_ptr[1] = in_odd[0] + ((out_ptr[0] + out_ptr[2]) >> 1); + } else { //!(len & 1) + out_ptr[1] = in_odd[0] + out_ptr[0]; + } +#elif defined(__AVX2__) + OPJ_INT32* out_ptr = tmp; + int32_t prev_even = in_even[0] - ((in_odd[0] + 1) >> 1); + + const __m256i reg_permutevar_mask_move_right = _mm256_setr_epi32(0x00, 0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06); + const __m256i two = _mm256_set1_epi32(2); + + int32_t simd_batch = (len - 2) / 16; + int32_t next_even; + __m256i even_m1, odd, unpack1_avx2, unpack2_avx2; + + for (i = 0; i < simd_batch; i++) { + const __m256i lf_avx2 = _mm256_loadu_si256((__m256i*)(in_even + 1)); + const __m256i hf1_avx2 = _mm256_loadu_si256((__m256i*)(in_odd)); + const __m256i hf2_avx2 = _mm256_loadu_si256((__m256i*)(in_odd + 1)); + + __m256i even = _mm256_add_epi32(hf1_avx2, hf2_avx2); + even = _mm256_add_epi32(even, two); + even = _mm256_srai_epi32(even, 2); + even = _mm256_sub_epi32(lf_avx2, even); + + next_even = _mm_extract_epi32(_mm256_extracti128_si256(even, 1), 3); + even_m1 = _mm256_permutevar8x32_epi32(even, reg_permutevar_mask_move_right); + even_m1 = _mm256_blend_epi32(even_m1, _mm256_set1_epi32(prev_even), (1 << 0)); + + //out[0] + out[2] + odd = _mm256_add_epi32(even_m1, even); + odd = _mm256_srai_epi32(odd, 1); + odd = _mm256_add_epi32(odd, hf1_avx2); + + unpack1_avx2 = _mm256_unpacklo_epi32(even_m1, odd); + unpack2_avx2 = _mm256_unpackhi_epi32(even_m1, odd); + + _mm_storeu_si128((__m128i*)(out_ptr + 0), _mm256_castsi256_si128(unpack1_avx2)); + _mm_storeu_si128((__m128i*)(out_ptr + 4), _mm256_castsi256_si128(unpack2_avx2)); + _mm_storeu_si128((__m128i*)(out_ptr + 8), _mm256_extracti128_si256(unpack1_avx2, + 0x1)); + _mm_storeu_si128((__m128i*)(out_ptr + 12), + _mm256_extracti128_si256(unpack2_avx2, 0x1)); + + prev_even = next_even; + + out_ptr += 16; + in_even += 8; + in_odd += 8; + } + out_ptr[0] = prev_even; + for (j = simd_batch * 16 + 1; j < (len - 2); j += 2) { + out_ptr[2] = in_even[1] - ((in_odd[0] + in_odd[1] + 2) >> 2); + out_ptr[1] = in_odd[0] + ((out_ptr[0] + out_ptr[2]) >> 1); + in_even++; + in_odd++; + out_ptr += 2; + } + + if (len & 1) { + out_ptr[2] = in_even[1] - ((in_odd[0] + 1) >> 1); + out_ptr[1] = in_odd[0] + ((out_ptr[0] + out_ptr[2]) >> 1); + } else { //!(len & 1) + out_ptr[1] = in_odd[0] + out_ptr[0]; + } +#else + OPJ_INT32 d1c, d1n, s1n, s0c, s0n; + + assert(len > 1); + + /* Improved version of the TWO_PASS_VERSION: */ + /* Performs lifting in one single iteration. Saves memory */ + /* accesses and explicit interleaving. */ + s1n = in_even[0]; + d1n = in_odd[0]; + s0n = s1n - ((d1n + 1) >> 1); + + for (i = 0, j = 1; i < (len - 3); i += 2, j++) { + d1c = d1n; + s0c = s0n; + + s1n = in_even[j]; + d1n = in_odd[j]; + + s0n = s1n - ((d1c + d1n + 2) >> 2); + + tmp[i ] = s0c; + tmp[i + 1] = opj_int_add_no_overflow(d1c, opj_int_add_no_overflow(s0c, + s0n) >> 1); + } + + tmp[i] = s0n; + + if (len & 1) { + tmp[len - 1] = in_even[(len - 1) / 2] - ((d1n + 1) >> 1); + tmp[len - 2] = d1n + ((s0n + tmp[len - 1]) >> 1); + } else { + tmp[len - 1] = d1n + s0n; + } +#endif /*(__AVX512F__ || __AVX2__)*/ +#endif /*TWO_PASS_VERSION*/ + memcpy(tiledp, tmp, (OPJ_UINT32)len * sizeof(OPJ_INT32)); +} + +static void opj_idwt53_h_cas1(OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp) +{ + OPJ_INT32 i, j; + const OPJ_INT32* in_even = &tiledp[sn]; + const OPJ_INT32* in_odd = &tiledp[0]; + +#ifdef TWO_PASS_VERSION + /* For documentation purpose: performs lifting in two iterations, */ + /* but without explicit interleaving */ + + assert(len > 2); + + /* Odd */ + for (i = 1, j = 0; i < len - 1; i += 2, j++) { + tmp[i] = in_odd[j] - ((in_even[j] + in_even[j + 1] + 2) >> 2); + } + if (!(len & 1)) { + tmp[len - 1] = in_odd[len / 2 - 1] - ((in_even[len / 2 - 1] + 1) >> 1); + } + + /* Even */ + tmp[0] = in_even[0] + tmp[1]; + for (i = 2, j = 1; i < len - 1; i += 2, j++) { + tmp[i] = in_even[j] + ((tmp[i + 1] + tmp[i - 1]) >> 1); + } + if (len & 1) { + tmp[len - 1] = in_even[len / 2] + tmp[len - 2]; + } +#else + OPJ_INT32 s1, s2, dc, dn; + + assert(len > 2); + + /* Improved version of the TWO_PASS_VERSION: */ + /* Performs lifting in one single iteration. Saves memory */ + /* accesses and explicit interleaving. */ + + s1 = in_even[1]; + dc = in_odd[0] - ((in_even[0] + s1 + 2) >> 2); + tmp[0] = in_even[0] + dc; + + for (i = 1, j = 1; i < (len - 2 - !(len & 1)); i += 2, j++) { + + s2 = in_even[j + 1]; + + dn = in_odd[j] - ((s1 + s2 + 2) >> 2); + tmp[i ] = dc; + tmp[i + 1] = opj_int_add_no_overflow(s1, opj_int_add_no_overflow(dn, dc) >> 1); + + dc = dn; + s1 = s2; + } + + tmp[i] = dc; + + if (!(len & 1)) { + dn = in_odd[len / 2 - 1] - ((s1 + 1) >> 1); + tmp[len - 2] = s1 + ((dn + dc) >> 1); + tmp[len - 1] = dn; + } else { + tmp[len - 1] = s1 + dc; + } +#endif + memcpy(tiledp, tmp, (OPJ_UINT32)len * sizeof(OPJ_INT32)); +} + + +#endif /* !defined(STANDARD_SLOW_VERSION) */ + +/* */ +/* Inverse 5-3 wavelet transform in 1-D for one row. */ +/* */ +/* Performs interleave, inverse wavelet transform and copy back to buffer */ +static void opj_idwt53_h(const opj_dwt_t *dwt, + OPJ_INT32* tiledp) +{ +#ifdef STANDARD_SLOW_VERSION + /* For documentation purpose */ + opj_dwt_interleave_h(dwt, tiledp); + opj_dwt_decode_1(dwt); + memcpy(tiledp, dwt->mem, (OPJ_UINT32)(dwt->sn + dwt->dn) * sizeof(OPJ_INT32)); +#else + const OPJ_INT32 sn = dwt->sn; + const OPJ_INT32 len = sn + dwt->dn; + if (dwt->cas == 0) { /* Left-most sample is on even coordinate */ + if (len > 1) { + opj_idwt53_h_cas0(dwt->mem, sn, len, tiledp); + } else { + /* Unmodified value */ + } + } else { /* Left-most sample is on odd coordinate */ + if (len == 1) { + tiledp[0] /= 2; + } else if (len == 2) { + OPJ_INT32* out = dwt->mem; + const OPJ_INT32* in_even = &tiledp[sn]; + const OPJ_INT32* in_odd = &tiledp[0]; + out[1] = in_odd[0] - ((in_even[0] + 1) >> 1); + out[0] = in_even[0] + out[1]; + memcpy(tiledp, dwt->mem, (OPJ_UINT32)len * sizeof(OPJ_INT32)); + } else if (len > 2) { + opj_idwt53_h_cas1(dwt->mem, sn, len, tiledp); + } + } +#endif +} + +#if (defined(__SSE2__) || defined(__AVX2__) || defined(__AVX512F__)) && !defined(STANDARD_SLOW_VERSION) + +/* Conveniency macros to improve the readability of the formulas */ +#if defined(__AVX512F__) +#define VREG __m512i +#define LOAD_CST(x) _mm512_set1_epi32(x) +#define LOAD(x) _mm512_loadu_si512((const VREG*)(x)) +#define LOADU(x) _mm512_loadu_si512((const VREG*)(x)) +#define STORE(x,y) _mm512_storeu_si512((VREG*)(x),(y)) +#define STOREU(x,y) _mm512_storeu_si512((VREG*)(x),(y)) +#define ADD(x,y) _mm512_add_epi32((x),(y)) +#define SUB(x,y) _mm512_sub_epi32((x),(y)) +#define SAR(x,y) _mm512_srai_epi32((x),(y)) +#elif defined(__AVX2__) +#define VREG __m256i +#define LOAD_CST(x) _mm256_set1_epi32(x) +#define LOAD(x) _mm256_load_si256((const VREG*)(x)) +#define LOADU(x) _mm256_loadu_si256((const VREG*)(x)) +#define STORE(x,y) _mm256_store_si256((VREG*)(x),(y)) +#define STOREU(x,y) _mm256_storeu_si256((VREG*)(x),(y)) +#define ADD(x,y) _mm256_add_epi32((x),(y)) +#define SUB(x,y) _mm256_sub_epi32((x),(y)) +#define SAR(x,y) _mm256_srai_epi32((x),(y)) +#else +#define VREG __m128i +#define LOAD_CST(x) _mm_set1_epi32(x) +#define LOAD(x) _mm_load_si128((const VREG*)(x)) +#define LOADU(x) _mm_loadu_si128((const VREG*)(x)) +#define STORE(x,y) _mm_store_si128((VREG*)(x),(y)) +#define STOREU(x,y) _mm_storeu_si128((VREG*)(x),(y)) +#define ADD(x,y) _mm_add_epi32((x),(y)) +#define SUB(x,y) _mm_sub_epi32((x),(y)) +#define SAR(x,y) _mm_srai_epi32((x),(y)) +#endif +#define ADD3(x,y,z) ADD(ADD(x,y),z) + +static +void opj_idwt53_v_final_memcpy(OPJ_INT32* tiledp_col, + const OPJ_INT32* tmp, + OPJ_INT32 len, + OPJ_SIZE_T stride) +{ + OPJ_INT32 i; + for (i = 0; i < len; ++i) { + /* A memcpy(&tiledp_col[i * stride + 0], + &tmp[PARALLEL_COLS_53 * i + 0], + PARALLEL_COLS_53 * sizeof(OPJ_INT32)) + would do but would be a tiny bit slower. + We can take here advantage of our knowledge of alignment */ + STOREU(&tiledp_col[(OPJ_SIZE_T)i * stride + 0], + LOAD(&tmp[PARALLEL_COLS_53 * i + 0])); + STOREU(&tiledp_col[(OPJ_SIZE_T)i * stride + VREG_INT_COUNT], + LOAD(&tmp[PARALLEL_COLS_53 * i + VREG_INT_COUNT])); + } +} + +/** Vertical inverse 5x3 wavelet transform for 8 columns in SSE2, or + * 16 in AVX2, when top-most pixel is on even coordinate */ +static void opj_idwt53_v_cas0_mcols_SSE2_OR_AVX2( + OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp_col, + const OPJ_SIZE_T stride) +{ + const OPJ_INT32* in_even = &tiledp_col[0]; + const OPJ_INT32* in_odd = &tiledp_col[(OPJ_SIZE_T)sn * stride]; + + OPJ_INT32 i; + OPJ_SIZE_T j; + VREG d1c_0, d1n_0, s1n_0, s0c_0, s0n_0; + VREG d1c_1, d1n_1, s1n_1, s0c_1, s0n_1; + const VREG two = LOAD_CST(2); + + assert(len > 1); +#if defined(__AVX512F__) + assert(PARALLEL_COLS_53 == 32); + assert(VREG_INT_COUNT == 16); +#elif defined(__AVX2__) + assert(PARALLEL_COLS_53 == 16); + assert(VREG_INT_COUNT == 8); +#else + assert(PARALLEL_COLS_53 == 8); + assert(VREG_INT_COUNT == 4); +#endif + +//For AVX512 code aligned load/store is set to it's unaligned equivalents +#if !defined(__AVX512F__) + /* Note: loads of input even/odd values must be done in a unaligned */ + /* fashion. But stores in tmp can be done with aligned store, since */ + /* the temporary buffer is properly aligned */ + assert((OPJ_SIZE_T)tmp % (sizeof(OPJ_INT32) * VREG_INT_COUNT) == 0); +#endif + + s1n_0 = LOADU(in_even + 0); + s1n_1 = LOADU(in_even + VREG_INT_COUNT); + d1n_0 = LOADU(in_odd); + d1n_1 = LOADU(in_odd + VREG_INT_COUNT); + + /* s0n = s1n - ((d1n + 1) >> 1); <==> */ + /* s0n = s1n - ((d1n + d1n + 2) >> 2); */ + s0n_0 = SUB(s1n_0, SAR(ADD3(d1n_0, d1n_0, two), 2)); + s0n_1 = SUB(s1n_1, SAR(ADD3(d1n_1, d1n_1, two), 2)); + + for (i = 0, j = 1; i < (len - 3); i += 2, j++) { + d1c_0 = d1n_0; + s0c_0 = s0n_0; + d1c_1 = d1n_1; + s0c_1 = s0n_1; + + s1n_0 = LOADU(in_even + j * stride); + s1n_1 = LOADU(in_even + j * stride + VREG_INT_COUNT); + d1n_0 = LOADU(in_odd + j * stride); + d1n_1 = LOADU(in_odd + j * stride + VREG_INT_COUNT); + + /*s0n = s1n - ((d1c + d1n + 2) >> 2);*/ + s0n_0 = SUB(s1n_0, SAR(ADD3(d1c_0, d1n_0, two), 2)); + s0n_1 = SUB(s1n_1, SAR(ADD3(d1c_1, d1n_1, two), 2)); + + STORE(tmp + PARALLEL_COLS_53 * (i + 0), s0c_0); + STORE(tmp + PARALLEL_COLS_53 * (i + 0) + VREG_INT_COUNT, s0c_1); + + /* d1c + ((s0c + s0n) >> 1) */ + STORE(tmp + PARALLEL_COLS_53 * (i + 1) + 0, + ADD(d1c_0, SAR(ADD(s0c_0, s0n_0), 1))); + STORE(tmp + PARALLEL_COLS_53 * (i + 1) + VREG_INT_COUNT, + ADD(d1c_1, SAR(ADD(s0c_1, s0n_1), 1))); + } + + STORE(tmp + PARALLEL_COLS_53 * (i + 0) + 0, s0n_0); + STORE(tmp + PARALLEL_COLS_53 * (i + 0) + VREG_INT_COUNT, s0n_1); + + if (len & 1) { + VREG tmp_len_minus_1; + s1n_0 = LOADU(in_even + (OPJ_SIZE_T)((len - 1) / 2) * stride); + /* tmp_len_minus_1 = s1n - ((d1n + 1) >> 1); */ + tmp_len_minus_1 = SUB(s1n_0, SAR(ADD3(d1n_0, d1n_0, two), 2)); + STORE(tmp + PARALLEL_COLS_53 * (len - 1), tmp_len_minus_1); + /* d1n + ((s0n + tmp_len_minus_1) >> 1) */ + STORE(tmp + PARALLEL_COLS_53 * (len - 2), + ADD(d1n_0, SAR(ADD(s0n_0, tmp_len_minus_1), 1))); + + s1n_1 = LOADU(in_even + (OPJ_SIZE_T)((len - 1) / 2) * stride + VREG_INT_COUNT); + /* tmp_len_minus_1 = s1n - ((d1n + 1) >> 1); */ + tmp_len_minus_1 = SUB(s1n_1, SAR(ADD3(d1n_1, d1n_1, two), 2)); + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + VREG_INT_COUNT, + tmp_len_minus_1); + /* d1n + ((s0n + tmp_len_minus_1) >> 1) */ + STORE(tmp + PARALLEL_COLS_53 * (len - 2) + VREG_INT_COUNT, + ADD(d1n_1, SAR(ADD(s0n_1, tmp_len_minus_1), 1))); + + + } else { + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + 0, + ADD(d1n_0, s0n_0)); + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + VREG_INT_COUNT, + ADD(d1n_1, s0n_1)); + } + + opj_idwt53_v_final_memcpy(tiledp_col, tmp, len, stride); +} + + +/** Vertical inverse 5x3 wavelet transform for 8 columns in SSE2, or + * 16 in AVX2, when top-most pixel is on odd coordinate */ +static void opj_idwt53_v_cas1_mcols_SSE2_OR_AVX2( + OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp_col, + const OPJ_SIZE_T stride) +{ + OPJ_INT32 i; + OPJ_SIZE_T j; + + VREG s1_0, s2_0, dc_0, dn_0; + VREG s1_1, s2_1, dc_1, dn_1; + const VREG two = LOAD_CST(2); + + const OPJ_INT32* in_even = &tiledp_col[(OPJ_SIZE_T)sn * stride]; + const OPJ_INT32* in_odd = &tiledp_col[0]; + + assert(len > 2); +#if defined(__AVX512F__) + assert(PARALLEL_COLS_53 == 32); + assert(VREG_INT_COUNT == 16); +#elif defined(__AVX2__) + assert(PARALLEL_COLS_53 == 16); + assert(VREG_INT_COUNT == 8); +#else + assert(PARALLEL_COLS_53 == 8); + assert(VREG_INT_COUNT == 4); +#endif + +//For AVX512 code aligned load/store is set to it's unaligned equivalents +#if !defined(__AVX512F__) + /* Note: loads of input even/odd values must be done in a unaligned */ + /* fashion. But stores in tmp can be done with aligned store, since */ + /* the temporary buffer is properly aligned */ + assert((OPJ_SIZE_T)tmp % (sizeof(OPJ_INT32) * VREG_INT_COUNT) == 0); +#endif + + s1_0 = LOADU(in_even + stride); + /* in_odd[0] - ((in_even[0] + s1 + 2) >> 2); */ + dc_0 = SUB(LOADU(in_odd + 0), + SAR(ADD3(LOADU(in_even + 0), s1_0, two), 2)); + STORE(tmp + PARALLEL_COLS_53 * 0, ADD(LOADU(in_even + 0), dc_0)); + + s1_1 = LOADU(in_even + stride + VREG_INT_COUNT); + /* in_odd[0] - ((in_even[0] + s1 + 2) >> 2); */ + dc_1 = SUB(LOADU(in_odd + VREG_INT_COUNT), + SAR(ADD3(LOADU(in_even + VREG_INT_COUNT), s1_1, two), 2)); + STORE(tmp + PARALLEL_COLS_53 * 0 + VREG_INT_COUNT, + ADD(LOADU(in_even + VREG_INT_COUNT), dc_1)); + + for (i = 1, j = 1; i < (len - 2 - !(len & 1)); i += 2, j++) { + + s2_0 = LOADU(in_even + (j + 1) * stride); + s2_1 = LOADU(in_even + (j + 1) * stride + VREG_INT_COUNT); + + /* dn = in_odd[j * stride] - ((s1 + s2 + 2) >> 2); */ + dn_0 = SUB(LOADU(in_odd + j * stride), + SAR(ADD3(s1_0, s2_0, two), 2)); + dn_1 = SUB(LOADU(in_odd + j * stride + VREG_INT_COUNT), + SAR(ADD3(s1_1, s2_1, two), 2)); + + STORE(tmp + PARALLEL_COLS_53 * i, dc_0); + STORE(tmp + PARALLEL_COLS_53 * i + VREG_INT_COUNT, dc_1); + + /* tmp[i + 1] = s1 + ((dn + dc) >> 1); */ + STORE(tmp + PARALLEL_COLS_53 * (i + 1) + 0, + ADD(s1_0, SAR(ADD(dn_0, dc_0), 1))); + STORE(tmp + PARALLEL_COLS_53 * (i + 1) + VREG_INT_COUNT, + ADD(s1_1, SAR(ADD(dn_1, dc_1), 1))); + + dc_0 = dn_0; + s1_0 = s2_0; + dc_1 = dn_1; + s1_1 = s2_1; + } + STORE(tmp + PARALLEL_COLS_53 * i, dc_0); + STORE(tmp + PARALLEL_COLS_53 * i + VREG_INT_COUNT, dc_1); + + if (!(len & 1)) { + /*dn = in_odd[(len / 2 - 1) * stride] - ((s1 + 1) >> 1); */ + dn_0 = SUB(LOADU(in_odd + (OPJ_SIZE_T)(len / 2 - 1) * stride), + SAR(ADD3(s1_0, s1_0, two), 2)); + dn_1 = SUB(LOADU(in_odd + (OPJ_SIZE_T)(len / 2 - 1) * stride + VREG_INT_COUNT), + SAR(ADD3(s1_1, s1_1, two), 2)); + + /* tmp[len - 2] = s1 + ((dn + dc) >> 1); */ + STORE(tmp + PARALLEL_COLS_53 * (len - 2) + 0, + ADD(s1_0, SAR(ADD(dn_0, dc_0), 1))); + STORE(tmp + PARALLEL_COLS_53 * (len - 2) + VREG_INT_COUNT, + ADD(s1_1, SAR(ADD(dn_1, dc_1), 1))); + + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + 0, dn_0); + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + VREG_INT_COUNT, dn_1); + } else { + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + 0, ADD(s1_0, dc_0)); + STORE(tmp + PARALLEL_COLS_53 * (len - 1) + VREG_INT_COUNT, + ADD(s1_1, dc_1)); + } + + opj_idwt53_v_final_memcpy(tiledp_col, tmp, len, stride); +} + +#undef VREG +#undef LOAD_CST +#undef LOADU +#undef LOAD +#undef STORE +#undef STOREU +#undef ADD +#undef ADD3 +#undef SUB +#undef SAR + +#endif /* (defined(__SSE2__) || defined(__AVX2__)) && !defined(STANDARD_SLOW_VERSION) */ + +#if !defined(STANDARD_SLOW_VERSION) +/** Vertical inverse 5x3 wavelet transform for one column, when top-most + * pixel is on even coordinate */ +static void opj_idwt3_v_cas0(OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp_col, + const OPJ_SIZE_T stride) +{ + OPJ_INT32 i, j; + OPJ_INT32 d1c, d1n, s1n, s0c, s0n; + + assert(len > 1); + + /* Performs lifting in one single iteration. Saves memory */ + /* accesses and explicit interleaving. */ + + s1n = tiledp_col[0]; + d1n = tiledp_col[(OPJ_SIZE_T)sn * stride]; + s0n = s1n - ((d1n + 1) >> 1); + + for (i = 0, j = 0; i < (len - 3); i += 2, j++) { + d1c = d1n; + s0c = s0n; + + s1n = tiledp_col[(OPJ_SIZE_T)(j + 1) * stride]; + d1n = tiledp_col[(OPJ_SIZE_T)(sn + j + 1) * stride]; + + s0n = opj_int_sub_no_overflow(s1n, + opj_int_add_no_overflow(opj_int_add_no_overflow(d1c, d1n), 2) >> 2); + + tmp[i ] = s0c; + tmp[i + 1] = opj_int_add_no_overflow(d1c, opj_int_add_no_overflow(s0c, + s0n) >> 1); + } + + tmp[i] = s0n; + + if (len & 1) { + tmp[len - 1] = + tiledp_col[(OPJ_SIZE_T)((len - 1) / 2) * stride] - + ((d1n + 1) >> 1); + tmp[len - 2] = d1n + ((s0n + tmp[len - 1]) >> 1); + } else { + tmp[len - 1] = d1n + s0n; + } + + for (i = 0; i < len; ++i) { + tiledp_col[(OPJ_SIZE_T)i * stride] = tmp[i]; + } +} + + +/** Vertical inverse 5x3 wavelet transform for one column, when top-most + * pixel is on odd coordinate */ +static void opj_idwt3_v_cas1(OPJ_INT32* tmp, + const OPJ_INT32 sn, + const OPJ_INT32 len, + OPJ_INT32* tiledp_col, + const OPJ_SIZE_T stride) +{ + OPJ_INT32 i, j; + OPJ_INT32 s1, s2, dc, dn; + const OPJ_INT32* in_even = &tiledp_col[(OPJ_SIZE_T)sn * stride]; + const OPJ_INT32* in_odd = &tiledp_col[0]; + + assert(len > 2); + + /* Performs lifting in one single iteration. Saves memory */ + /* accesses and explicit interleaving. */ + + s1 = in_even[stride]; + dc = in_odd[0] - ((in_even[0] + s1 + 2) >> 2); + tmp[0] = in_even[0] + dc; + for (i = 1, j = 1; i < (len - 2 - !(len & 1)); i += 2, j++) { + + s2 = in_even[(OPJ_SIZE_T)(j + 1) * stride]; + + dn = in_odd[(OPJ_SIZE_T)j * stride] - ((s1 + s2 + 2) >> 2); + tmp[i ] = dc; + tmp[i + 1] = s1 + ((dn + dc) >> 1); + + dc = dn; + s1 = s2; + } + tmp[i] = dc; + if (!(len & 1)) { + dn = in_odd[(OPJ_SIZE_T)(len / 2 - 1) * stride] - ((s1 + 1) >> 1); + tmp[len - 2] = s1 + ((dn + dc) >> 1); + tmp[len - 1] = dn; + } else { + tmp[len - 1] = s1 + dc; + } + + for (i = 0; i < len; ++i) { + tiledp_col[(OPJ_SIZE_T)i * stride] = tmp[i]; + } +} +#endif /* !defined(STANDARD_SLOW_VERSION) */ + +/* */ +/* Inverse vertical 5-3 wavelet transform in 1-D for several columns. */ +/* */ +/* Performs interleave, inverse wavelet transform and copy back to buffer */ +static void opj_idwt53_v(const opj_dwt_t *dwt, + OPJ_INT32* tiledp_col, + OPJ_SIZE_T stride, + OPJ_INT32 nb_cols) +{ +#ifdef STANDARD_SLOW_VERSION + /* For documentation purpose */ + OPJ_INT32 k, c; + for (c = 0; c < nb_cols; c ++) { + opj_dwt_interleave_v(dwt, tiledp_col + c, stride); + opj_dwt_decode_1(dwt); + for (k = 0; k < dwt->sn + dwt->dn; ++k) { + tiledp_col[c + k * stride] = dwt->mem[k]; + } + } +#else + const OPJ_INT32 sn = dwt->sn; + const OPJ_INT32 len = sn + dwt->dn; + if (dwt->cas == 0) { + /* If len == 1, unmodified value */ + +#if (defined(__SSE2__) || defined(__AVX2__)) + if (len > 1 && nb_cols == PARALLEL_COLS_53) { + /* Same as below general case, except that thanks to SSE2/AVX2 */ + /* we can efficiently process 8/16 columns in parallel */ + opj_idwt53_v_cas0_mcols_SSE2_OR_AVX2(dwt->mem, sn, len, tiledp_col, stride); + return; + } +#endif + if (len > 1) { + OPJ_INT32 c; + for (c = 0; c < nb_cols; c++, tiledp_col++) { + opj_idwt3_v_cas0(dwt->mem, sn, len, tiledp_col, stride); + } + return; + } + } else { + if (len == 1) { + OPJ_INT32 c; + for (c = 0; c < nb_cols; c++, tiledp_col++) { + tiledp_col[0] /= 2; + } + return; + } + + if (len == 2) { + OPJ_INT32 c; + OPJ_INT32* out = dwt->mem; + for (c = 0; c < nb_cols; c++, tiledp_col++) { + OPJ_INT32 i; + const OPJ_INT32* in_even = &tiledp_col[(OPJ_SIZE_T)sn * stride]; + const OPJ_INT32* in_odd = &tiledp_col[0]; + + out[1] = in_odd[0] - ((in_even[0] + 1) >> 1); + out[0] = in_even[0] + out[1]; + + for (i = 0; i < len; ++i) { + tiledp_col[(OPJ_SIZE_T)i * stride] = out[i]; + } + } + + return; + } + +#if (defined(__SSE2__) || defined(__AVX2__)) + if (len > 2 && nb_cols == PARALLEL_COLS_53) { + /* Same as below general case, except that thanks to SSE2/AVX2 */ + /* we can efficiently process 8/16 columns in parallel */ + opj_idwt53_v_cas1_mcols_SSE2_OR_AVX2(dwt->mem, sn, len, tiledp_col, stride); + return; + } +#endif + if (len > 2) { + OPJ_INT32 c; + for (c = 0; c < nb_cols; c++, tiledp_col++) { + opj_idwt3_v_cas1(dwt->mem, sn, len, tiledp_col, stride); + } + return; + } + } +#endif +} + +#if 0 +static void opj_dwt_encode_step1(OPJ_FLOAT32* fw, + OPJ_UINT32 end, + const OPJ_FLOAT32 c) +{ + OPJ_UINT32 i = 0; + for (; i < end; ++i) { + fw[0] *= c; + fw += 2; + } +} +#else +static void opj_dwt_encode_step1_combined(OPJ_FLOAT32* fw, + OPJ_UINT32 iters_c1, + OPJ_UINT32 iters_c2, + const OPJ_FLOAT32 c1, + const OPJ_FLOAT32 c2) +{ + OPJ_UINT32 i = 0; + const OPJ_UINT32 iters_common = opj_uint_min(iters_c1, iters_c2); + assert((((OPJ_SIZE_T)fw) & 0xf) == 0); + assert(opj_int_abs((OPJ_INT32)iters_c1 - (OPJ_INT32)iters_c2) <= 1); + for (; i + 3 < iters_common; i += 4) { +#ifdef __SSE__ + const __m128 vcst = _mm_set_ps(c2, c1, c2, c1); + *(__m128*)fw = _mm_mul_ps(*(__m128*)fw, vcst); + *(__m128*)(fw + 4) = _mm_mul_ps(*(__m128*)(fw + 4), vcst); +#else + fw[0] *= c1; + fw[1] *= c2; + fw[2] *= c1; + fw[3] *= c2; + fw[4] *= c1; + fw[5] *= c2; + fw[6] *= c1; + fw[7] *= c2; +#endif + fw += 8; + } + for (; i < iters_common; i++) { + fw[0] *= c1; + fw[1] *= c2; + fw += 2; + } + if (i < iters_c1) { + fw[0] *= c1; + } else if (i < iters_c2) { + fw[1] *= c2; + } +} + +#endif + +static void opj_dwt_encode_step2(OPJ_FLOAT32* fl, OPJ_FLOAT32* fw, + OPJ_UINT32 end, + OPJ_UINT32 m, + OPJ_FLOAT32 c) +{ + OPJ_UINT32 i; + OPJ_UINT32 imax = opj_uint_min(end, m); + if (imax > 0) { + fw[-1] += (fl[0] + fw[0]) * c; + fw += 2; + i = 1; + for (; i + 3 < imax; i += 4) { + fw[-1] += (fw[-2] + fw[0]) * c; + fw[1] += (fw[0] + fw[2]) * c; + fw[3] += (fw[2] + fw[4]) * c; + fw[5] += (fw[4] + fw[6]) * c; + fw += 8; + } + for (; i < imax; ++i) { + fw[-1] += (fw[-2] + fw[0]) * c; + fw += 2; + } + } + if (m < end) { + assert(m + 1 == end); + fw[-1] += (2 * fw[-2]) * c; + } +} + +static void opj_dwt_encode_1_real(void *aIn, OPJ_INT32 dn, OPJ_INT32 sn, + OPJ_INT32 cas) +{ + OPJ_FLOAT32* w = (OPJ_FLOAT32*)aIn; + OPJ_INT32 a, b; + assert(dn + sn > 1); + if (cas == 0) { + a = 0; + b = 1; + } else { + a = 1; + b = 0; + } + opj_dwt_encode_step2(w + a, w + b + 1, + (OPJ_UINT32)dn, + (OPJ_UINT32)opj_int_min(dn, sn - b), + opj_dwt_alpha); + opj_dwt_encode_step2(w + b, w + a + 1, + (OPJ_UINT32)sn, + (OPJ_UINT32)opj_int_min(sn, dn - a), + opj_dwt_beta); + opj_dwt_encode_step2(w + a, w + b + 1, + (OPJ_UINT32)dn, + (OPJ_UINT32)opj_int_min(dn, sn - b), + opj_dwt_gamma); + opj_dwt_encode_step2(w + b, w + a + 1, + (OPJ_UINT32)sn, + (OPJ_UINT32)opj_int_min(sn, dn - a), + opj_dwt_delta); +#if 0 + opj_dwt_encode_step1(w + b, (OPJ_UINT32)dn, + opj_K); + opj_dwt_encode_step1(w + a, (OPJ_UINT32)sn, + opj_invK); +#else + if (a == 0) { + opj_dwt_encode_step1_combined(w, + (OPJ_UINT32)sn, + (OPJ_UINT32)dn, + opj_invK, + opj_K); + } else { + opj_dwt_encode_step1_combined(w, + (OPJ_UINT32)dn, + (OPJ_UINT32)sn, + opj_K, + opj_invK); + } +#endif +} + +static void opj_dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, + opj_stepsize_t *bandno_stepsize) +{ + OPJ_INT32 p, n; + p = opj_int_floorlog2(stepsize) - 13; + n = 11 - opj_int_floorlog2(stepsize); + bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff; + bandno_stepsize->expn = numbps - p; +} + +/* +========================================================== + DWT interface +========================================================== +*/ + +/** Process one line for the horizontal pass of the 5x3 forward transform */ +static +void opj_dwt_encode_and_deinterleave_h_one_row(void* rowIn, + void* tmpIn, + OPJ_UINT32 width, + OPJ_BOOL even) +{ + OPJ_INT32* OPJ_RESTRICT row = (OPJ_INT32*)rowIn; + OPJ_INT32* OPJ_RESTRICT tmp = (OPJ_INT32*)tmpIn; + const OPJ_INT32 sn = (OPJ_INT32)((width + (even ? 1 : 0)) >> 1); + const OPJ_INT32 dn = (OPJ_INT32)(width - (OPJ_UINT32)sn); + + if (even) { + if (width > 1) { + OPJ_INT32 i; + for (i = 0; i < sn - 1; i++) { + tmp[sn + i] = row[2 * i + 1] - ((row[(i) * 2] + row[(i + 1) * 2]) >> 1); + } + if ((width % 2) == 0) { + tmp[sn + i] = row[2 * i + 1] - row[(i) * 2]; + } + row[0] += (tmp[sn] + tmp[sn] + 2) >> 2; + for (i = 1; i < dn; i++) { + row[i] = row[2 * i] + ((tmp[sn + (i - 1)] + tmp[sn + i] + 2) >> 2); + } + if ((width % 2) == 1) { + row[i] = row[2 * i] + ((tmp[sn + (i - 1)] + tmp[sn + (i - 1)] + 2) >> 2); + } + memcpy(row + sn, tmp + sn, (OPJ_SIZE_T)dn * sizeof(OPJ_INT32)); + } + } else { + if (width == 1) { + row[0] *= 2; + } else { + OPJ_INT32 i; + tmp[sn + 0] = row[0] - row[1]; + for (i = 1; i < sn; i++) { + tmp[sn + i] = row[2 * i] - ((row[2 * i + 1] + row[2 * (i - 1) + 1]) >> 1); + } + if ((width % 2) == 1) { + tmp[sn + i] = row[2 * i] - row[2 * (i - 1) + 1]; + } + + for (i = 0; i < dn - 1; i++) { + row[i] = row[2 * i + 1] + ((tmp[sn + i] + tmp[sn + i + 1] + 2) >> 2); + } + if ((width % 2) == 0) { + row[i] = row[2 * i + 1] + ((tmp[sn + i] + tmp[sn + i] + 2) >> 2); + } + memcpy(row + sn, tmp + sn, (OPJ_SIZE_T)dn * sizeof(OPJ_INT32)); + } + } +} + +/** Process one line for the horizontal pass of the 9x7 forward transform */ +static +void opj_dwt_encode_and_deinterleave_h_one_row_real(void* rowIn, + void* tmpIn, + OPJ_UINT32 width, + OPJ_BOOL even) +{ + OPJ_FLOAT32* OPJ_RESTRICT row = (OPJ_FLOAT32*)rowIn; + OPJ_FLOAT32* OPJ_RESTRICT tmp = (OPJ_FLOAT32*)tmpIn; + const OPJ_INT32 sn = (OPJ_INT32)((width + (even ? 1 : 0)) >> 1); + const OPJ_INT32 dn = (OPJ_INT32)(width - (OPJ_UINT32)sn); + if (width == 1) { + return; + } + memcpy(tmp, row, width * sizeof(OPJ_FLOAT32)); + opj_dwt_encode_1_real(tmp, dn, sn, even ? 0 : 1); + opj_dwt_deinterleave_h((OPJ_INT32 * OPJ_RESTRICT)tmp, + (OPJ_INT32 * OPJ_RESTRICT)row, + dn, sn, even ? 0 : 1); +} + +typedef struct { + opj_dwt_t h; + OPJ_UINT32 rw; /* Width of the resolution to process */ + OPJ_UINT32 w; /* Width of tiledp */ + OPJ_INT32 * OPJ_RESTRICT tiledp; + OPJ_UINT32 min_j; + OPJ_UINT32 max_j; + opj_encode_and_deinterleave_h_one_row_fnptr_type p_function; +} opj_dwt_encode_h_job_t; + +static void opj_dwt_encode_h_func(void* user_data, opj_tls_t* tls) +{ + OPJ_UINT32 j; + opj_dwt_encode_h_job_t* job; + (void)tls; + + job = (opj_dwt_encode_h_job_t*)user_data; + for (j = job->min_j; j < job->max_j; j++) { + OPJ_INT32* OPJ_RESTRICT aj = job->tiledp + j * job->w; + (*job->p_function)(aj, job->h.mem, job->rw, + job->h.cas == 0 ? OPJ_TRUE : OPJ_FALSE); + } + + opj_aligned_free(job->h.mem); + opj_free(job); +} + +typedef struct { + opj_dwt_t v; + OPJ_UINT32 rh; + OPJ_UINT32 w; + OPJ_INT32 * OPJ_RESTRICT tiledp; + OPJ_UINT32 min_j; + OPJ_UINT32 max_j; + opj_encode_and_deinterleave_v_fnptr_type p_encode_and_deinterleave_v; +} opj_dwt_encode_v_job_t; + +static void opj_dwt_encode_v_func(void* user_data, opj_tls_t* tls) +{ + OPJ_UINT32 j; + opj_dwt_encode_v_job_t* job; + (void)tls; + + job = (opj_dwt_encode_v_job_t*)user_data; + for (j = job->min_j; j + NB_ELTS_V8 - 1 < job->max_j; j += NB_ELTS_V8) { + (*job->p_encode_and_deinterleave_v)(job->tiledp + j, + job->v.mem, + job->rh, + job->v.cas == 0, + job->w, + NB_ELTS_V8); + } + if (j < job->max_j) { + (*job->p_encode_and_deinterleave_v)(job->tiledp + j, + job->v.mem, + job->rh, + job->v.cas == 0, + job->w, + job->max_j - j); + } + + opj_aligned_free(job->v.mem); + opj_free(job); +} + +/** Fetch up to cols <= NB_ELTS_V8 for each line, and put them in tmpOut */ +/* that has a NB_ELTS_V8 interleave factor. */ +static void opj_dwt_fetch_cols_vertical_pass(const void *arrayIn, + void *tmpOut, + OPJ_UINT32 height, + OPJ_UINT32 stride_width, + OPJ_UINT32 cols) +{ + const OPJ_INT32* OPJ_RESTRICT array = (const OPJ_INT32 * OPJ_RESTRICT)arrayIn; + OPJ_INT32* OPJ_RESTRICT tmp = (OPJ_INT32 * OPJ_RESTRICT)tmpOut; + if (cols == NB_ELTS_V8) { + OPJ_UINT32 k; + for (k = 0; k < height; ++k) { + memcpy(tmp + NB_ELTS_V8 * k, + array + k * stride_width, + NB_ELTS_V8 * sizeof(OPJ_INT32)); + } + } else { + OPJ_UINT32 k; + for (k = 0; k < height; ++k) { + OPJ_UINT32 c; + for (c = 0; c < cols; c++) { + tmp[NB_ELTS_V8 * k + c] = array[c + k * stride_width]; + } + for (; c < NB_ELTS_V8; c++) { + tmp[NB_ELTS_V8 * k + c] = 0; + } + } + } +} + +/* Deinterleave result of forward transform, where cols <= NB_ELTS_V8 */ +/* and src contains NB_ELTS_V8 consecutive values for up to NB_ELTS_V8 */ +/* columns. */ +static INLINE void opj_dwt_deinterleave_v_cols( + const OPJ_INT32 * OPJ_RESTRICT src, + OPJ_INT32 * OPJ_RESTRICT dst, + OPJ_INT32 dn, + OPJ_INT32 sn, + OPJ_UINT32 stride_width, + OPJ_INT32 cas, + OPJ_UINT32 cols) +{ + OPJ_INT32 k; + OPJ_INT32 i = sn; + OPJ_INT32 * OPJ_RESTRICT l_dest = dst; + const OPJ_INT32 * OPJ_RESTRICT l_src = src + cas * NB_ELTS_V8; + OPJ_UINT32 c; + + for (k = 0; k < 2; k++) { + while (i--) { + if (cols == NB_ELTS_V8) { + memcpy(l_dest, l_src, NB_ELTS_V8 * sizeof(OPJ_INT32)); + } else { + c = 0; + switch (cols) { + case 7: + l_dest[c] = l_src[c]; + c++; /* fallthru */ + case 6: + l_dest[c] = l_src[c]; + c++; /* fallthru */ + case 5: + l_dest[c] = l_src[c]; + c++; /* fallthru */ + case 4: + l_dest[c] = l_src[c]; + c++; /* fallthru */ + case 3: + l_dest[c] = l_src[c]; + c++; /* fallthru */ + case 2: + l_dest[c] = l_src[c]; + c++; /* fallthru */ + default: + l_dest[c] = l_src[c]; + break; + } + } + l_dest += stride_width; + l_src += 2 * NB_ELTS_V8; + } + + l_dest = dst + (OPJ_SIZE_T)sn * (OPJ_SIZE_T)stride_width; + l_src = src + (1 - cas) * NB_ELTS_V8; + i = dn; + } +} + + +/* Forward 5-3 transform, for the vertical pass, processing cols columns */ +/* where cols <= NB_ELTS_V8 */ +static void opj_dwt_encode_and_deinterleave_v( + void *arrayIn, + void *tmpIn, + OPJ_UINT32 height, + OPJ_BOOL even, + OPJ_UINT32 stride_width, + OPJ_UINT32 cols) +{ + OPJ_INT32* OPJ_RESTRICT array = (OPJ_INT32 * OPJ_RESTRICT)arrayIn; + OPJ_INT32* OPJ_RESTRICT tmp = (OPJ_INT32 * OPJ_RESTRICT)tmpIn; + const OPJ_UINT32 sn = (height + (even ? 1 : 0)) >> 1; + const OPJ_UINT32 dn = height - sn; + + opj_dwt_fetch_cols_vertical_pass(arrayIn, tmpIn, height, stride_width, cols); + +#define OPJ_Sc(i) tmp[(i)*2* NB_ELTS_V8 + c] +#define OPJ_Dc(i) tmp[((1+(i)*2))* NB_ELTS_V8 + c] + +#ifdef __SSE2__ + if (height == 1) { + if (!even) { + OPJ_UINT32 c; + for (c = 0; c < NB_ELTS_V8; c++) { + tmp[c] *= 2; + } + } + } else if (even) { + OPJ_UINT32 c; + OPJ_UINT32 i; + i = 0; + if (i + 1 < sn) { + __m128i xmm_Si_0 = *(const __m128i*)(tmp + 4 * 0); + __m128i xmm_Si_1 = *(const __m128i*)(tmp + 4 * 1); + for (; i + 1 < sn; i++) { + __m128i xmm_Sip1_0 = *(const __m128i*)(tmp + + (i + 1) * 2 * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Sip1_1 = *(const __m128i*)(tmp + + (i + 1) * 2 * NB_ELTS_V8 + 4 * 1); + __m128i xmm_Di_0 = *(const __m128i*)(tmp + + (1 + i * 2) * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Di_1 = *(const __m128i*)(tmp + + (1 + i * 2) * NB_ELTS_V8 + 4 * 1); + xmm_Di_0 = _mm_sub_epi32(xmm_Di_0, + _mm_srai_epi32(_mm_add_epi32(xmm_Si_0, xmm_Sip1_0), 1)); + xmm_Di_1 = _mm_sub_epi32(xmm_Di_1, + _mm_srai_epi32(_mm_add_epi32(xmm_Si_1, xmm_Sip1_1), 1)); + *(__m128i*)(tmp + (1 + i * 2) * NB_ELTS_V8 + 4 * 0) = xmm_Di_0; + *(__m128i*)(tmp + (1 + i * 2) * NB_ELTS_V8 + 4 * 1) = xmm_Di_1; + xmm_Si_0 = xmm_Sip1_0; + xmm_Si_1 = xmm_Sip1_1; + } + } + if (((height) % 2) == 0) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Dc(i) -= OPJ_Sc(i); + } + } + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(0) += (OPJ_Dc(0) + OPJ_Dc(0) + 2) >> 2; + } + i = 1; + if (i < dn) { + __m128i xmm_Dim1_0 = *(const __m128i*)(tmp + (1 + + (i - 1) * 2) * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Dim1_1 = *(const __m128i*)(tmp + (1 + + (i - 1) * 2) * NB_ELTS_V8 + 4 * 1); + const __m128i xmm_two = _mm_set1_epi32(2); + for (; i < dn; i++) { + __m128i xmm_Di_0 = *(const __m128i*)(tmp + + (1 + i * 2) * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Di_1 = *(const __m128i*)(tmp + + (1 + i * 2) * NB_ELTS_V8 + 4 * 1); + __m128i xmm_Si_0 = *(const __m128i*)(tmp + + (i * 2) * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Si_1 = *(const __m128i*)(tmp + + (i * 2) * NB_ELTS_V8 + 4 * 1); + xmm_Si_0 = _mm_add_epi32(xmm_Si_0, + _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(xmm_Dim1_0, xmm_Di_0), xmm_two), 2)); + xmm_Si_1 = _mm_add_epi32(xmm_Si_1, + _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(xmm_Dim1_1, xmm_Di_1), xmm_two), 2)); + *(__m128i*)(tmp + (i * 2) * NB_ELTS_V8 + 4 * 0) = xmm_Si_0; + *(__m128i*)(tmp + (i * 2) * NB_ELTS_V8 + 4 * 1) = xmm_Si_1; + xmm_Dim1_0 = xmm_Di_0; + xmm_Dim1_1 = xmm_Di_1; + } + } + if (((height) % 2) == 1) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(i) += (OPJ_Dc(i - 1) + OPJ_Dc(i - 1) + 2) >> 2; + } + } + } else { + OPJ_UINT32 c; + OPJ_UINT32 i; + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(0) -= OPJ_Dc(0); + } + i = 1; + if (i < sn) { + __m128i xmm_Dim1_0 = *(const __m128i*)(tmp + (1 + + (i - 1) * 2) * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Dim1_1 = *(const __m128i*)(tmp + (1 + + (i - 1) * 2) * NB_ELTS_V8 + 4 * 1); + for (; i < sn; i++) { + __m128i xmm_Di_0 = *(const __m128i*)(tmp + + (1 + i * 2) * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Di_1 = *(const __m128i*)(tmp + + (1 + i * 2) * NB_ELTS_V8 + 4 * 1); + __m128i xmm_Si_0 = *(const __m128i*)(tmp + + (i * 2) * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Si_1 = *(const __m128i*)(tmp + + (i * 2) * NB_ELTS_V8 + 4 * 1); + xmm_Si_0 = _mm_sub_epi32(xmm_Si_0, + _mm_srai_epi32(_mm_add_epi32(xmm_Di_0, xmm_Dim1_0), 1)); + xmm_Si_1 = _mm_sub_epi32(xmm_Si_1, + _mm_srai_epi32(_mm_add_epi32(xmm_Di_1, xmm_Dim1_1), 1)); + *(__m128i*)(tmp + (i * 2) * NB_ELTS_V8 + 4 * 0) = xmm_Si_0; + *(__m128i*)(tmp + (i * 2) * NB_ELTS_V8 + 4 * 1) = xmm_Si_1; + xmm_Dim1_0 = xmm_Di_0; + xmm_Dim1_1 = xmm_Di_1; + } + } + if (((height) % 2) == 1) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(i) -= OPJ_Dc(i - 1); + } + } + i = 0; + if (i + 1 < dn) { + __m128i xmm_Si_0 = *((const __m128i*)(tmp + 4 * 0)); + __m128i xmm_Si_1 = *((const __m128i*)(tmp + 4 * 1)); + const __m128i xmm_two = _mm_set1_epi32(2); + for (; i + 1 < dn; i++) { + __m128i xmm_Sip1_0 = *(const __m128i*)(tmp + + (i + 1) * 2 * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Sip1_1 = *(const __m128i*)(tmp + + (i + 1) * 2 * NB_ELTS_V8 + 4 * 1); + __m128i xmm_Di_0 = *(const __m128i*)(tmp + + (1 + i * 2) * NB_ELTS_V8 + 4 * 0); + __m128i xmm_Di_1 = *(const __m128i*)(tmp + + (1 + i * 2) * NB_ELTS_V8 + 4 * 1); + xmm_Di_0 = _mm_add_epi32(xmm_Di_0, + _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(xmm_Si_0, xmm_Sip1_0), xmm_two), 2)); + xmm_Di_1 = _mm_add_epi32(xmm_Di_1, + _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(xmm_Si_1, xmm_Sip1_1), xmm_two), 2)); + *(__m128i*)(tmp + (1 + i * 2) * NB_ELTS_V8 + 4 * 0) = xmm_Di_0; + *(__m128i*)(tmp + (1 + i * 2) * NB_ELTS_V8 + 4 * 1) = xmm_Di_1; + xmm_Si_0 = xmm_Sip1_0; + xmm_Si_1 = xmm_Sip1_1; + } + } + if (((height) % 2) == 0) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Dc(i) += (OPJ_Sc(i) + OPJ_Sc(i) + 2) >> 2; + } + } + } +#else + if (even) { + OPJ_UINT32 c; + if (height > 1) { + OPJ_UINT32 i; + for (i = 0; i + 1 < sn; i++) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Dc(i) -= (OPJ_Sc(i) + OPJ_Sc(i + 1)) >> 1; + } + } + if (((height) % 2) == 0) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Dc(i) -= OPJ_Sc(i); + } + } + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(0) += (OPJ_Dc(0) + OPJ_Dc(0) + 2) >> 2; + } + for (i = 1; i < dn; i++) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(i) += (OPJ_Dc(i - 1) + OPJ_Dc(i) + 2) >> 2; + } + } + if (((height) % 2) == 1) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(i) += (OPJ_Dc(i - 1) + OPJ_Dc(i - 1) + 2) >> 2; + } + } + } + } else { + OPJ_UINT32 c; + if (height == 1) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(0) *= 2; + } + } else { + OPJ_UINT32 i; + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(0) -= OPJ_Dc(0); + } + for (i = 1; i < sn; i++) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(i) -= (OPJ_Dc(i) + OPJ_Dc(i - 1)) >> 1; + } + } + if (((height) % 2) == 1) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Sc(i) -= OPJ_Dc(i - 1); + } + } + for (i = 0; i + 1 < dn; i++) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Dc(i) += (OPJ_Sc(i) + OPJ_Sc(i + 1) + 2) >> 2; + } + } + if (((height) % 2) == 0) { + for (c = 0; c < NB_ELTS_V8; c++) { + OPJ_Dc(i) += (OPJ_Sc(i) + OPJ_Sc(i) + 2) >> 2; + } + } + } + } +#endif + + if (cols == NB_ELTS_V8) { + opj_dwt_deinterleave_v_cols(tmp, array, (OPJ_INT32)dn, (OPJ_INT32)sn, + stride_width, even ? 0 : 1, NB_ELTS_V8); + } else { + opj_dwt_deinterleave_v_cols(tmp, array, (OPJ_INT32)dn, (OPJ_INT32)sn, + stride_width, even ? 0 : 1, cols); + } +} + +static void opj_v8dwt_encode_step1(OPJ_FLOAT32* fw, + OPJ_UINT32 end, + const OPJ_FLOAT32 cst) +{ + OPJ_UINT32 i; +#ifdef __SSE__ + __m128* vw = (__m128*) fw; + const __m128 vcst = _mm_set1_ps(cst); + for (i = 0; i < end; ++i) { + vw[0] = _mm_mul_ps(vw[0], vcst); + vw[1] = _mm_mul_ps(vw[1], vcst); + vw += 2 * (NB_ELTS_V8 * sizeof(OPJ_FLOAT32) / sizeof(__m128)); + } +#else + OPJ_UINT32 c; + for (i = 0; i < end; ++i) { + for (c = 0; c < NB_ELTS_V8; c++) { + fw[i * 2 * NB_ELTS_V8 + c] *= cst; + } + } +#endif +} + +static void opj_v8dwt_encode_step2(OPJ_FLOAT32* fl, OPJ_FLOAT32* fw, + OPJ_UINT32 end, + OPJ_UINT32 m, + OPJ_FLOAT32 cst) +{ + OPJ_UINT32 i; + OPJ_UINT32 imax = opj_uint_min(end, m); +#ifdef __SSE__ + __m128* vw = (__m128*) fw; + __m128 vcst = _mm_set1_ps(cst); + if (imax > 0) { + __m128* vl = (__m128*) fl; + vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(_mm_add_ps(vl[0], vw[0]), vcst)); + vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(_mm_add_ps(vl[1], vw[1]), vcst)); + vw += 2 * (NB_ELTS_V8 * sizeof(OPJ_FLOAT32) / sizeof(__m128)); + i = 1; + + for (; i < imax; ++i) { + vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(_mm_add_ps(vw[-4], vw[0]), vcst)); + vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(_mm_add_ps(vw[-3], vw[1]), vcst)); + vw += 2 * (NB_ELTS_V8 * sizeof(OPJ_FLOAT32) / sizeof(__m128)); + } + } + if (m < end) { + assert(m + 1 == end); + vcst = _mm_add_ps(vcst, vcst); + vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(vw[-4], vcst)); + vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(vw[-3], vcst)); + } +#else + OPJ_INT32 c; + if (imax > 0) { + for (c = 0; c < NB_ELTS_V8; c++) { + fw[-1 * NB_ELTS_V8 + c] += (fl[0 * NB_ELTS_V8 + c] + fw[0 * NB_ELTS_V8 + c]) * + cst; + } + fw += 2 * NB_ELTS_V8; + i = 1; + for (; i < imax; ++i) { + for (c = 0; c < NB_ELTS_V8; c++) { + fw[-1 * NB_ELTS_V8 + c] += (fw[-2 * NB_ELTS_V8 + c] + fw[0 * NB_ELTS_V8 + c]) * + cst; + } + fw += 2 * NB_ELTS_V8; + } + } + if (m < end) { + assert(m + 1 == end); + for (c = 0; c < NB_ELTS_V8; c++) { + fw[-1 * NB_ELTS_V8 + c] += (2 * fw[-2 * NB_ELTS_V8 + c]) * cst; + } + } +#endif +} + +/* Forward 9-7 transform, for the vertical pass, processing cols columns */ +/* where cols <= NB_ELTS_V8 */ +static void opj_dwt_encode_and_deinterleave_v_real( + void *arrayIn, + void *tmpIn, + OPJ_UINT32 height, + OPJ_BOOL even, + OPJ_UINT32 stride_width, + OPJ_UINT32 cols) +{ + OPJ_FLOAT32* OPJ_RESTRICT array = (OPJ_FLOAT32 * OPJ_RESTRICT)arrayIn; + OPJ_FLOAT32* OPJ_RESTRICT tmp = (OPJ_FLOAT32 * OPJ_RESTRICT)tmpIn; + const OPJ_INT32 sn = (OPJ_INT32)((height + (even ? 1 : 0)) >> 1); + const OPJ_INT32 dn = (OPJ_INT32)(height - (OPJ_UINT32)sn); + OPJ_INT32 a, b; + + if (height == 1) { + return; + } + + opj_dwt_fetch_cols_vertical_pass(arrayIn, tmpIn, height, stride_width, cols); + + if (even) { + a = 0; + b = 1; + } else { + a = 1; + b = 0; + } + opj_v8dwt_encode_step2(tmp + a * NB_ELTS_V8, + tmp + (b + 1) * NB_ELTS_V8, + (OPJ_UINT32)dn, + (OPJ_UINT32)opj_int_min(dn, sn - b), + opj_dwt_alpha); + opj_v8dwt_encode_step2(tmp + b * NB_ELTS_V8, + tmp + (a + 1) * NB_ELTS_V8, + (OPJ_UINT32)sn, + (OPJ_UINT32)opj_int_min(sn, dn - a), + opj_dwt_beta); + opj_v8dwt_encode_step2(tmp + a * NB_ELTS_V8, + tmp + (b + 1) * NB_ELTS_V8, + (OPJ_UINT32)dn, + (OPJ_UINT32)opj_int_min(dn, sn - b), + opj_dwt_gamma); + opj_v8dwt_encode_step2(tmp + b * NB_ELTS_V8, + tmp + (a + 1) * NB_ELTS_V8, + (OPJ_UINT32)sn, + (OPJ_UINT32)opj_int_min(sn, dn - a), + opj_dwt_delta); + opj_v8dwt_encode_step1(tmp + b * NB_ELTS_V8, (OPJ_UINT32)dn, + opj_K); + opj_v8dwt_encode_step1(tmp + a * NB_ELTS_V8, (OPJ_UINT32)sn, + opj_invK); + + + if (cols == NB_ELTS_V8) { + opj_dwt_deinterleave_v_cols((OPJ_INT32*)tmp, + (OPJ_INT32*)array, + (OPJ_INT32)dn, (OPJ_INT32)sn, + stride_width, even ? 0 : 1, NB_ELTS_V8); + } else { + opj_dwt_deinterleave_v_cols((OPJ_INT32*)tmp, + (OPJ_INT32*)array, + (OPJ_INT32)dn, (OPJ_INT32)sn, + stride_width, even ? 0 : 1, cols); + } +} + + +/* */ +/* Forward 5-3 wavelet transform in 2-D. */ +/* */ +static INLINE OPJ_BOOL opj_dwt_encode_procedure(opj_thread_pool_t* tp, + opj_tcd_tilecomp_t * tilec, + opj_encode_and_deinterleave_v_fnptr_type p_encode_and_deinterleave_v, + opj_encode_and_deinterleave_h_one_row_fnptr_type + p_encode_and_deinterleave_h_one_row) +{ + OPJ_INT32 i; + OPJ_INT32 *bj = 00; + OPJ_UINT32 w; + OPJ_INT32 l; + + OPJ_SIZE_T l_data_size; + + opj_tcd_resolution_t * l_cur_res = 0; + opj_tcd_resolution_t * l_last_res = 0; + const int num_threads = opj_thread_pool_get_thread_count(tp); + OPJ_INT32 * OPJ_RESTRICT tiledp = tilec->data; + + w = (OPJ_UINT32)(tilec->x1 - tilec->x0); + l = (OPJ_INT32)tilec->numresolutions - 1; + + l_cur_res = tilec->resolutions + l; + l_last_res = l_cur_res - 1; + + l_data_size = opj_dwt_max_resolution(tilec->resolutions, tilec->numresolutions); + /* overflow check */ + if (l_data_size > (SIZE_MAX / (NB_ELTS_V8 * sizeof(OPJ_INT32)))) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + l_data_size *= NB_ELTS_V8 * sizeof(OPJ_INT32); + bj = (OPJ_INT32*)opj_aligned_32_malloc(l_data_size); + /* l_data_size is equal to 0 when numresolutions == 1 but bj is not used */ + /* in that case, so do not error out */ + if (l_data_size != 0 && ! bj) { + return OPJ_FALSE; + } + i = l; + + while (i--) { + OPJ_UINT32 j; + OPJ_UINT32 rw; /* width of the resolution level computed */ + OPJ_UINT32 rh; /* height of the resolution level computed */ + OPJ_UINT32 + rw1; /* width of the resolution level once lower than computed one */ + OPJ_UINT32 + rh1; /* height of the resolution level once lower than computed one */ + OPJ_INT32 cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ + OPJ_INT32 cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ + OPJ_INT32 dn, sn; + + rw = (OPJ_UINT32)(l_cur_res->x1 - l_cur_res->x0); + rh = (OPJ_UINT32)(l_cur_res->y1 - l_cur_res->y0); + rw1 = (OPJ_UINT32)(l_last_res->x1 - l_last_res->x0); + rh1 = (OPJ_UINT32)(l_last_res->y1 - l_last_res->y0); + + cas_row = l_cur_res->x0 & 1; + cas_col = l_cur_res->y0 & 1; + + sn = (OPJ_INT32)rh1; + dn = (OPJ_INT32)(rh - rh1); + + /* Perform vertical pass */ + if (num_threads <= 1 || rw < 2 * NB_ELTS_V8) { + for (j = 0; j + NB_ELTS_V8 - 1 < rw; j += NB_ELTS_V8) { + p_encode_and_deinterleave_v(tiledp + j, + bj, + rh, + cas_col == 0, + w, + NB_ELTS_V8); + } + if (j < rw) { + p_encode_and_deinterleave_v(tiledp + j, + bj, + rh, + cas_col == 0, + w, + rw - j); + } + } else { + OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads; + OPJ_UINT32 step_j; + + if (rw < num_jobs) { + num_jobs = rw; + } + step_j = ((rw / num_jobs) / NB_ELTS_V8) * NB_ELTS_V8; + + for (j = 0; j < num_jobs; j++) { + opj_dwt_encode_v_job_t* job; + + job = (opj_dwt_encode_v_job_t*) opj_malloc(sizeof(opj_dwt_encode_v_job_t)); + if (!job) { + opj_thread_pool_wait_completion(tp, 0); + opj_aligned_free(bj); + return OPJ_FALSE; + } + job->v.mem = (OPJ_INT32*)opj_aligned_32_malloc(l_data_size); + if (!job->v.mem) { + opj_thread_pool_wait_completion(tp, 0); + opj_free(job); + opj_aligned_free(bj); + return OPJ_FALSE; + } + job->v.dn = dn; + job->v.sn = sn; + job->v.cas = cas_col; + job->rh = rh; + job->w = w; + job->tiledp = tiledp; + job->min_j = j * step_j; + job->max_j = (j + 1 == num_jobs) ? rw : (j + 1) * step_j; + job->p_encode_and_deinterleave_v = p_encode_and_deinterleave_v; + opj_thread_pool_submit_job(tp, opj_dwt_encode_v_func, job); + } + opj_thread_pool_wait_completion(tp, 0); + } + + sn = (OPJ_INT32)rw1; + dn = (OPJ_INT32)(rw - rw1); + + /* Perform horizontal pass */ + if (num_threads <= 1 || rh <= 1) { + for (j = 0; j < rh; j++) { + OPJ_INT32* OPJ_RESTRICT aj = tiledp + j * w; + (*p_encode_and_deinterleave_h_one_row)(aj, bj, rw, + cas_row == 0 ? OPJ_TRUE : OPJ_FALSE); + } + } else { + OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads; + OPJ_UINT32 step_j; + + if (rh < num_jobs) { + num_jobs = rh; + } + step_j = (rh / num_jobs); + + for (j = 0; j < num_jobs; j++) { + opj_dwt_encode_h_job_t* job; + + job = (opj_dwt_encode_h_job_t*) opj_malloc(sizeof(opj_dwt_encode_h_job_t)); + if (!job) { + opj_thread_pool_wait_completion(tp, 0); + opj_aligned_free(bj); + return OPJ_FALSE; + } + job->h.mem = (OPJ_INT32*)opj_aligned_32_malloc(l_data_size); + if (!job->h.mem) { + opj_thread_pool_wait_completion(tp, 0); + opj_free(job); + opj_aligned_free(bj); + return OPJ_FALSE; + } + job->h.dn = dn; + job->h.sn = sn; + job->h.cas = cas_row; + job->rw = rw; + job->w = w; + job->tiledp = tiledp; + job->min_j = j * step_j; + job->max_j = (j + 1U) * step_j; /* this can overflow */ + if (j == (num_jobs - 1U)) { /* this will take care of the overflow */ + job->max_j = rh; + } + job->p_function = p_encode_and_deinterleave_h_one_row; + opj_thread_pool_submit_job(tp, opj_dwt_encode_h_func, job); + } + opj_thread_pool_wait_completion(tp, 0); + } + + l_cur_res = l_last_res; + + --l_last_res; + } + + opj_aligned_free(bj); + return OPJ_TRUE; +} + +/* Forward 5-3 wavelet transform in 2-D. */ +/* */ +OPJ_BOOL opj_dwt_encode(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t * tilec) +{ + return opj_dwt_encode_procedure(p_tcd->thread_pool, tilec, + opj_dwt_encode_and_deinterleave_v, + opj_dwt_encode_and_deinterleave_h_one_row); +} + +/* */ +/* Inverse 5-3 wavelet transform in 2-D. */ +/* */ +OPJ_BOOL opj_dwt_decode(opj_tcd_t *p_tcd, opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres) +{ + if (p_tcd->whole_tile_decoding) { + return opj_dwt_decode_tile(p_tcd->thread_pool, tilec, numres); + } else { + return opj_dwt_decode_partial_tile(tilec, numres); + } +} + +/* */ +/* Get norm of 5-3 wavelet. */ +/* */ +OPJ_FLOAT64 opj_dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient) +{ + /* FIXME ! This is just a band-aid to avoid a buffer overflow */ + /* but the array should really be extended up to 33 resolution levels */ + /* See https://github.com/uclouvain/openjpeg/issues/493 */ + if (orient == 0 && level >= 10) { + level = 9; + } else if (orient > 0 && level >= 9) { + level = 8; + } + return opj_dwt_norms[orient][level]; +} + +/* */ +/* Forward 9-7 wavelet transform in 2-D. */ +/* */ +OPJ_BOOL opj_dwt_encode_real(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t * tilec) +{ + return opj_dwt_encode_procedure(p_tcd->thread_pool, tilec, + opj_dwt_encode_and_deinterleave_v_real, + opj_dwt_encode_and_deinterleave_h_one_row_real); +} + +/* */ +/* Get norm of 9-7 wavelet. */ +/* */ +OPJ_FLOAT64 opj_dwt_getnorm_real(OPJ_UINT32 level, OPJ_UINT32 orient) +{ + /* FIXME ! This is just a band-aid to avoid a buffer overflow */ + /* but the array should really be extended up to 33 resolution levels */ + /* See https://github.com/uclouvain/openjpeg/issues/493 */ + if (orient == 0 && level >= 10) { + level = 9; + } else if (orient > 0 && level >= 9) { + level = 8; + } + return opj_dwt_norms_real[orient][level]; +} + +void opj_dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, OPJ_UINT32 prec) +{ + OPJ_UINT32 numbands, bandno; + numbands = 3 * tccp->numresolutions - 2; + for (bandno = 0; bandno < numbands; bandno++) { + OPJ_FLOAT64 stepsize; + OPJ_UINT32 resno, level, orient, gain; + + resno = (bandno == 0) ? 0 : ((bandno - 1) / 3 + 1); + orient = (bandno == 0) ? 0 : ((bandno - 1) % 3 + 1); + level = tccp->numresolutions - 1 - resno; + gain = (tccp->qmfbid == 0) ? 0 : ((orient == 0) ? 0 : (((orient == 1) || + (orient == 2)) ? 1 : 2)); + if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + stepsize = 1.0; + } else { + OPJ_FLOAT64 norm = opj_dwt_getnorm_real(level, orient); + stepsize = (1 << (gain)) / norm; + } + opj_dwt_encode_stepsize((OPJ_INT32) floor(stepsize * 8192.0), + (OPJ_INT32)(prec + gain), &tccp->stepsizes[bandno]); + } +} + +/* */ +/* Determine maximum computed resolution level for inverse wavelet transform */ +/* */ +static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* OPJ_RESTRICT r, + OPJ_UINT32 i) +{ + OPJ_UINT32 mr = 0; + OPJ_UINT32 w; + while (--i) { + ++r; + if (mr < (w = (OPJ_UINT32)(r->x1 - r->x0))) { + mr = w ; + } + if (mr < (w = (OPJ_UINT32)(r->y1 - r->y0))) { + mr = w ; + } + } + return mr ; +} + +typedef struct { + opj_dwt_t h; + OPJ_UINT32 rw; + OPJ_UINT32 w; + OPJ_INT32 * OPJ_RESTRICT tiledp; + OPJ_UINT32 min_j; + OPJ_UINT32 max_j; +} opj_dwt_decode_h_job_t; + +static void opj_dwt_decode_h_func(void* user_data, opj_tls_t* tls) +{ + OPJ_UINT32 j; + opj_dwt_decode_h_job_t* job; + (void)tls; + + job = (opj_dwt_decode_h_job_t*)user_data; + for (j = job->min_j; j < job->max_j; j++) { + opj_idwt53_h(&job->h, &job->tiledp[j * job->w]); + } + + opj_aligned_free(job->h.mem); + opj_free(job); +} + +typedef struct { + opj_dwt_t v; + OPJ_UINT32 rh; + OPJ_UINT32 w; + OPJ_INT32 * OPJ_RESTRICT tiledp; + OPJ_UINT32 min_j; + OPJ_UINT32 max_j; +} opj_dwt_decode_v_job_t; + +static void opj_dwt_decode_v_func(void* user_data, opj_tls_t* tls) +{ + OPJ_UINT32 j; + opj_dwt_decode_v_job_t* job; + (void)tls; + + job = (opj_dwt_decode_v_job_t*)user_data; + for (j = job->min_j; j + PARALLEL_COLS_53 <= job->max_j; + j += PARALLEL_COLS_53) { + opj_idwt53_v(&job->v, &job->tiledp[j], (OPJ_SIZE_T)job->w, + PARALLEL_COLS_53); + } + if (j < job->max_j) + opj_idwt53_v(&job->v, &job->tiledp[j], (OPJ_SIZE_T)job->w, + (OPJ_INT32)(job->max_j - j)); + + opj_aligned_free(job->v.mem); + opj_free(job); +} + + +/* */ +/* Inverse wavelet transform in 2-D. */ +/* */ +static OPJ_BOOL opj_dwt_decode_tile(opj_thread_pool_t* tp, + opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) +{ + opj_dwt_t h; + opj_dwt_t v; + + opj_tcd_resolution_t* tr = tilec->resolutions; + + OPJ_UINT32 rw = (OPJ_UINT32)(tr->x1 - + tr->x0); /* width of the resolution level computed */ + OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - + tr->y0); /* height of the resolution level computed */ + + OPJ_UINT32 w = (OPJ_UINT32)(tilec->resolutions[tilec->minimum_num_resolutions - + 1].x1 - + tilec->resolutions[tilec->minimum_num_resolutions - 1].x0); + OPJ_SIZE_T h_mem_size; + int num_threads; + + /* Not entirely sure for the return code of w == 0 which is triggered per */ + /* https://github.com/uclouvain/openjpeg/issues/1505 */ + if (numres == 1U || w == 0) { + return OPJ_TRUE; + } + num_threads = opj_thread_pool_get_thread_count(tp); + h_mem_size = opj_dwt_max_resolution(tr, numres); + /* overflow check */ + if (h_mem_size > (SIZE_MAX / PARALLEL_COLS_53 / sizeof(OPJ_INT32))) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + /* We need PARALLEL_COLS_53 times the height of the array, */ + /* since for the vertical pass */ + /* we process PARALLEL_COLS_53 columns at a time */ + h_mem_size *= PARALLEL_COLS_53 * sizeof(OPJ_INT32); + h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (! h.mem) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + + v.mem = h.mem; + + while (--numres) { + OPJ_INT32 * OPJ_RESTRICT tiledp = tilec->data; + OPJ_UINT32 j; + + ++tr; + h.sn = (OPJ_INT32)rw; + v.sn = (OPJ_INT32)rh; + + rw = (OPJ_UINT32)(tr->x1 - tr->x0); + rh = (OPJ_UINT32)(tr->y1 - tr->y0); + + h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); + h.cas = tr->x0 % 2; + + if (num_threads <= 1 || rh <= 1) { + for (j = 0; j < rh; ++j) { + opj_idwt53_h(&h, &tiledp[(OPJ_SIZE_T)j * w]); + } + } else { + OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads; + OPJ_UINT32 step_j; + + if (rh < num_jobs) { + num_jobs = rh; + } + step_j = (rh / num_jobs); + + for (j = 0; j < num_jobs; j++) { + opj_dwt_decode_h_job_t* job; + + job = (opj_dwt_decode_h_job_t*) opj_malloc(sizeof(opj_dwt_decode_h_job_t)); + if (!job) { + /* It would be nice to fallback to single thread case, but */ + /* unfortunately some jobs may be launched and have modified */ + /* tiledp, so it is not practical to recover from that error */ + /* FIXME event manager error callback */ + opj_thread_pool_wait_completion(tp, 0); + opj_aligned_free(h.mem); + return OPJ_FALSE; + } + job->h = h; + job->rw = rw; + job->w = w; + job->tiledp = tiledp; + job->min_j = j * step_j; + job->max_j = (j + 1U) * step_j; /* this can overflow */ + if (j == (num_jobs - 1U)) { /* this will take care of the overflow */ + job->max_j = rh; + } + job->h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (!job->h.mem) { + /* FIXME event manager error callback */ + opj_thread_pool_wait_completion(tp, 0); + opj_free(job); + opj_aligned_free(h.mem); + return OPJ_FALSE; + } + opj_thread_pool_submit_job(tp, opj_dwt_decode_h_func, job); + } + opj_thread_pool_wait_completion(tp, 0); + } + + v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); + v.cas = tr->y0 % 2; + + if (num_threads <= 1 || rw <= 1) { + for (j = 0; j + PARALLEL_COLS_53 <= rw; + j += PARALLEL_COLS_53) { + opj_idwt53_v(&v, &tiledp[j], (OPJ_SIZE_T)w, PARALLEL_COLS_53); + } + if (j < rw) { + opj_idwt53_v(&v, &tiledp[j], (OPJ_SIZE_T)w, (OPJ_INT32)(rw - j)); + } + } else { + OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads; + OPJ_UINT32 step_j; + + if (rw < num_jobs) { + num_jobs = rw; + } + step_j = (rw / num_jobs); + + for (j = 0; j < num_jobs; j++) { + opj_dwt_decode_v_job_t* job; + + job = (opj_dwt_decode_v_job_t*) opj_malloc(sizeof(opj_dwt_decode_v_job_t)); + if (!job) { + /* It would be nice to fallback to single thread case, but */ + /* unfortunately some jobs may be launched and have modified */ + /* tiledp, so it is not practical to recover from that error */ + /* FIXME event manager error callback */ + opj_thread_pool_wait_completion(tp, 0); + opj_aligned_free(v.mem); + return OPJ_FALSE; + } + job->v = v; + job->rh = rh; + job->w = w; + job->tiledp = tiledp; + job->min_j = j * step_j; + job->max_j = (j + 1U) * step_j; /* this can overflow */ + if (j == (num_jobs - 1U)) { /* this will take care of the overflow */ + job->max_j = rw; + } + job->v.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (!job->v.mem) { + /* FIXME event manager error callback */ + opj_thread_pool_wait_completion(tp, 0); + opj_free(job); + opj_aligned_free(v.mem); + return OPJ_FALSE; + } + opj_thread_pool_submit_job(tp, opj_dwt_decode_v_func, job); + } + opj_thread_pool_wait_completion(tp, 0); + } + } + opj_aligned_free(h.mem); + return OPJ_TRUE; +} + +static void opj_dwt_interleave_partial_h(OPJ_INT32 *dest, + OPJ_INT32 cas, + opj_sparse_array_int32_t* sa, + OPJ_UINT32 sa_line, + OPJ_UINT32 sn, + OPJ_UINT32 win_l_x0, + OPJ_UINT32 win_l_x1, + OPJ_UINT32 win_h_x0, + OPJ_UINT32 win_h_x1) +{ + OPJ_BOOL ret; + ret = opj_sparse_array_int32_read(sa, + win_l_x0, sa_line, + win_l_x1, sa_line + 1, + dest + cas + 2 * win_l_x0, + 2, 0, OPJ_TRUE); + assert(ret); + ret = opj_sparse_array_int32_read(sa, + sn + win_h_x0, sa_line, + sn + win_h_x1, sa_line + 1, + dest + 1 - cas + 2 * win_h_x0, + 2, 0, OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); +} + + +static void opj_dwt_interleave_partial_v(OPJ_INT32 *dest, + OPJ_INT32 cas, + opj_sparse_array_int32_t* sa, + OPJ_UINT32 sa_col, + OPJ_UINT32 nb_cols, + OPJ_UINT32 sn, + OPJ_UINT32 win_l_y0, + OPJ_UINT32 win_l_y1, + OPJ_UINT32 win_h_y0, + OPJ_UINT32 win_h_y1) +{ + OPJ_BOOL ret; + ret = opj_sparse_array_int32_read(sa, + sa_col, win_l_y0, + sa_col + nb_cols, win_l_y1, + dest + cas * 4 + 2 * 4 * win_l_y0, + 1, 2 * 4, OPJ_TRUE); + assert(ret); + ret = opj_sparse_array_int32_read(sa, + sa_col, sn + win_h_y0, + sa_col + nb_cols, sn + win_h_y1, + dest + (1 - cas) * 4 + 2 * 4 * win_h_y0, + 1, 2 * 4, OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); +} + +static void opj_dwt_decode_partial_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, + OPJ_INT32 cas, + OPJ_INT32 win_l_x0, + OPJ_INT32 win_l_x1, + OPJ_INT32 win_h_x0, + OPJ_INT32 win_h_x1) +{ + OPJ_INT32 i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + + /* Naive version is : + for (i = win_l_x0; i < i_max; i++) { + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + } + for (i = win_h_x0; i < win_h_x1; i++) { + OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; + } + but the compiler doesn't manage to unroll it to avoid bound + checking in OPJ_S_ and OPJ_D_ macros + */ + + i = win_l_x0; + if (i < win_l_x1) { + OPJ_INT32 i_max; + + /* Left-most case */ + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + i ++; + + i_max = win_l_x1; + if (i_max > dn) { + i_max = dn; + } + for (; i < i_max; i++) { + /* No bound checking */ + OPJ_S(i) -= (OPJ_D(i - 1) + OPJ_D(i) + 2) >> 2; + } + for (; i < win_l_x1; i++) { + /* Right-most case */ + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + } + } + + i = win_h_x0; + if (i < win_h_x1) { + OPJ_INT32 i_max = win_h_x1; + if (i_max >= sn) { + i_max = sn - 1; + } + for (; i < i_max; i++) { + /* No bound checking */ + OPJ_D(i) += (OPJ_S(i) + OPJ_S(i + 1)) >> 1; + } + for (; i < win_h_x1; i++) { + /* Right-most case */ + OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; + } + } + } + } else { + if (!sn && dn == 1) { /* NEW : CASE ONE ELEMENT */ + OPJ_S(0) /= 2; + } else { + for (i = win_l_x0; i < win_l_x1; i++) { + OPJ_D(i) = opj_int_sub_no_overflow(OPJ_D(i), + opj_int_add_no_overflow(opj_int_add_no_overflow(OPJ_SS_(i), OPJ_SS_(i + 1)), + 2) >> 2); + } + for (i = win_h_x0; i < win_h_x1; i++) { + OPJ_S(i) = opj_int_add_no_overflow(OPJ_S(i), + opj_int_add_no_overflow(OPJ_DD_(i), OPJ_DD_(i - 1)) >> 1); + } + } + } +} + +#define OPJ_S_off(i,off) a[(OPJ_UINT32)(i)*2*4+off] +#define OPJ_D_off(i,off) a[(1+(OPJ_UINT32)(i)*2)*4+off] +#define OPJ_S__off(i,off) ((i)<0?OPJ_S_off(0,off):((i)>=sn?OPJ_S_off(sn-1,off):OPJ_S_off(i,off))) +#define OPJ_D__off(i,off) ((i)<0?OPJ_D_off(0,off):((i)>=dn?OPJ_D_off(dn-1,off):OPJ_D_off(i,off))) +#define OPJ_SS__off(i,off) ((i)<0?OPJ_S_off(0,off):((i)>=dn?OPJ_S_off(dn-1,off):OPJ_S_off(i,off))) +#define OPJ_DD__off(i,off) ((i)<0?OPJ_D_off(0,off):((i)>=sn?OPJ_D_off(sn-1,off):OPJ_D_off(i,off))) + +static void opj_dwt_decode_partial_1_parallel(OPJ_INT32 *a, + OPJ_UINT32 nb_cols, + OPJ_INT32 dn, OPJ_INT32 sn, + OPJ_INT32 cas, + OPJ_INT32 win_l_x0, + OPJ_INT32 win_l_x1, + OPJ_INT32 win_h_x0, + OPJ_INT32 win_h_x1) +{ + OPJ_INT32 i; + OPJ_UINT32 off; + + (void)nb_cols; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + + /* Naive version is : + for (i = win_l_x0; i < i_max; i++) { + OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2; + } + for (i = win_h_x0; i < win_h_x1; i++) { + OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1; + } + but the compiler doesn't manage to unroll it to avoid bound + checking in OPJ_S_ and OPJ_D_ macros + */ + + i = win_l_x0; + if (i < win_l_x1) { + OPJ_INT32 i_max; + + /* Left-most case */ + for (off = 0; off < 4; off++) { + OPJ_S_off(i, off) -= (OPJ_D__off(i - 1, off) + OPJ_D__off(i, off) + 2) >> 2; + } + i ++; + + i_max = win_l_x1; + if (i_max > dn) { + i_max = dn; + } + +#ifdef __SSE2__ + if (i + 1 < i_max) { + const __m128i two = _mm_set1_epi32(2); + __m128i Dm1 = _mm_load_si128((__m128i * const)(a + 4 + (i - 1) * 8)); + for (; i + 1 < i_max; i += 2) { + /* No bound checking */ + __m128i S = _mm_load_si128((__m128i * const)(a + i * 8)); + __m128i D = _mm_load_si128((__m128i * const)(a + 4 + i * 8)); + __m128i S1 = _mm_load_si128((__m128i * const)(a + (i + 1) * 8)); + __m128i D1 = _mm_load_si128((__m128i * const)(a + 4 + (i + 1) * 8)); + S = _mm_sub_epi32(S, + _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(Dm1, D), two), 2)); + S1 = _mm_sub_epi32(S1, + _mm_srai_epi32(_mm_add_epi32(_mm_add_epi32(D, D1), two), 2)); + _mm_store_si128((__m128i*)(a + i * 8), S); + _mm_store_si128((__m128i*)(a + (i + 1) * 8), S1); + Dm1 = D1; + } + } +#endif + + for (; i < i_max; i++) { + /* No bound checking */ + for (off = 0; off < 4; off++) { + OPJ_S_off(i, off) -= (OPJ_D_off(i - 1, off) + OPJ_D_off(i, off) + 2) >> 2; + } + } + for (; i < win_l_x1; i++) { + /* Right-most case */ + for (off = 0; off < 4; off++) { + OPJ_S_off(i, off) -= (OPJ_D__off(i - 1, off) + OPJ_D__off(i, off) + 2) >> 2; + } + } + } + + i = win_h_x0; + if (i < win_h_x1) { + OPJ_INT32 i_max = win_h_x1; + if (i_max >= sn) { + i_max = sn - 1; + } + +#ifdef __SSE2__ + if (i + 1 < i_max) { + __m128i S = _mm_load_si128((__m128i * const)(a + i * 8)); + for (; i + 1 < i_max; i += 2) { + /* No bound checking */ + __m128i D = _mm_load_si128((__m128i * const)(a + 4 + i * 8)); + __m128i S1 = _mm_load_si128((__m128i * const)(a + (i + 1) * 8)); + __m128i D1 = _mm_load_si128((__m128i * const)(a + 4 + (i + 1) * 8)); + __m128i S2 = _mm_load_si128((__m128i * const)(a + (i + 2) * 8)); + D = _mm_add_epi32(D, _mm_srai_epi32(_mm_add_epi32(S, S1), 1)); + D1 = _mm_add_epi32(D1, _mm_srai_epi32(_mm_add_epi32(S1, S2), 1)); + _mm_store_si128((__m128i*)(a + 4 + i * 8), D); + _mm_store_si128((__m128i*)(a + 4 + (i + 1) * 8), D1); + S = S2; + } + } +#endif + + for (; i < i_max; i++) { + /* No bound checking */ + for (off = 0; off < 4; off++) { + OPJ_D_off(i, off) += (OPJ_S_off(i, off) + OPJ_S_off(i + 1, off)) >> 1; + } + } + for (; i < win_h_x1; i++) { + /* Right-most case */ + for (off = 0; off < 4; off++) { + OPJ_D_off(i, off) += (OPJ_S__off(i, off) + OPJ_S__off(i + 1, off)) >> 1; + } + } + } + } + } else { + if (!sn && dn == 1) { /* NEW : CASE ONE ELEMENT */ + for (off = 0; off < 4; off++) { + OPJ_S_off(0, off) /= 2; + } + } else { + for (i = win_l_x0; i < win_l_x1; i++) { + for (off = 0; off < 4; off++) { + OPJ_D_off(i, off) = opj_int_sub_no_overflow( + OPJ_D_off(i, off), + opj_int_add_no_overflow( + opj_int_add_no_overflow(OPJ_SS__off(i, off), OPJ_SS__off(i + 1, off)), 2) >> 2); + } + } + for (i = win_h_x0; i < win_h_x1; i++) { + for (off = 0; off < 4; off++) { + OPJ_S_off(i, off) = opj_int_add_no_overflow( + OPJ_S_off(i, off), + opj_int_add_no_overflow(OPJ_DD__off(i, off), OPJ_DD__off(i - 1, off)) >> 1); + } + } + } + } +} + +static void opj_dwt_get_band_coordinates(opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 resno, + OPJ_UINT32 bandno, + OPJ_UINT32 tcx0, + OPJ_UINT32 tcy0, + OPJ_UINT32 tcx1, + OPJ_UINT32 tcy1, + OPJ_UINT32* tbx0, + OPJ_UINT32* tby0, + OPJ_UINT32* tbx1, + OPJ_UINT32* tby1) +{ + /* Compute number of decomposition for this band. See table F-1 */ + OPJ_UINT32 nb = (resno == 0) ? + tilec->numresolutions - 1 : + tilec->numresolutions - resno; + /* Map above tile-based coordinates to sub-band-based coordinates per */ + /* equation B-15 of the standard */ + OPJ_UINT32 x0b = bandno & 1; + OPJ_UINT32 y0b = bandno >> 1; + if (tbx0) { + *tbx0 = (nb == 0) ? tcx0 : + (tcx0 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx0 - (1U << (nb - 1)) * x0b, nb); + } + if (tby0) { + *tby0 = (nb == 0) ? tcy0 : + (tcy0 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy0 - (1U << (nb - 1)) * y0b, nb); + } + if (tbx1) { + *tbx1 = (nb == 0) ? tcx1 : + (tcx1 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx1 - (1U << (nb - 1)) * x0b, nb); + } + if (tby1) { + *tby1 = (nb == 0) ? tcy1 : + (tcy1 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy1 - (1U << (nb - 1)) * y0b, nb); + } +} + +static void opj_dwt_segment_grow(OPJ_UINT32 filter_width, + OPJ_UINT32 max_size, + OPJ_UINT32* start, + OPJ_UINT32* end) +{ + *start = opj_uint_subs(*start, filter_width); + *end = opj_uint_adds(*end, filter_width); + *end = opj_uint_min(*end, max_size); +} + + +static opj_sparse_array_int32_t* opj_dwt_init_sparse_array( + opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres) +{ + opj_tcd_resolution_t* tr_max = &(tilec->resolutions[numres - 1]); + OPJ_UINT32 w = (OPJ_UINT32)(tr_max->x1 - tr_max->x0); + OPJ_UINT32 h = (OPJ_UINT32)(tr_max->y1 - tr_max->y0); + OPJ_UINT32 resno, bandno, precno, cblkno; + opj_sparse_array_int32_t* sa = opj_sparse_array_int32_create( + w, h, opj_uint_min(w, 64), opj_uint_min(h, 64)); + if (sa == NULL) { + return NULL; + } + + for (resno = 0; resno < numres; ++resno) { + opj_tcd_resolution_t* res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t* precinct = &band->precincts[precno]; + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; + if (cblk->decoded_data != NULL) { + OPJ_UINT32 x = (OPJ_UINT32)(cblk->x0 - band->x0); + OPJ_UINT32 y = (OPJ_UINT32)(cblk->y0 - band->y0); + OPJ_UINT32 cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0); + OPJ_UINT32 cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0); + + if (band->bandno & 1) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + x += (OPJ_UINT32)(pres->x1 - pres->x0); + } + if (band->bandno & 2) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + y += (OPJ_UINT32)(pres->y1 - pres->y0); + } + + if (!opj_sparse_array_int32_write(sa, x, y, + x + cblk_w, y + cblk_h, + cblk->decoded_data, + 1, cblk_w, OPJ_TRUE)) { + opj_sparse_array_int32_free(sa); + return NULL; + } + } + } + } + } + } + + return sa; +} + + +static OPJ_BOOL opj_dwt_decode_partial_tile( + opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres) +{ + opj_sparse_array_int32_t* sa; + opj_dwt_t h; + opj_dwt_t v; + OPJ_UINT32 resno; + /* This value matches the maximum left/right extension given in tables */ + /* F.2 and F.3 of the standard. */ + const OPJ_UINT32 filter_width = 2U; + + opj_tcd_resolution_t* tr = tilec->resolutions; + opj_tcd_resolution_t* tr_max = &(tilec->resolutions[numres - 1]); + + OPJ_UINT32 rw = (OPJ_UINT32)(tr->x1 - + tr->x0); /* width of the resolution level computed */ + OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - + tr->y0); /* height of the resolution level computed */ + + OPJ_SIZE_T h_mem_size; + + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 win_tcx0 = tilec->win_x0; + OPJ_UINT32 win_tcy0 = tilec->win_y0; + OPJ_UINT32 win_tcx1 = tilec->win_x1; + OPJ_UINT32 win_tcy1 = tilec->win_y1; + + if (tr_max->x0 == tr_max->x1 || tr_max->y0 == tr_max->y1) { + return OPJ_TRUE; + } + + sa = opj_dwt_init_sparse_array(tilec, numres); + if (sa == NULL) { + return OPJ_FALSE; + } + + if (numres == 1U) { + OPJ_BOOL ret = opj_sparse_array_int32_read(sa, + tr_max->win_x0 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y0 - (OPJ_UINT32)tr_max->y0, + tr_max->win_x1 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y1 - (OPJ_UINT32)tr_max->y0, + tilec->data_win, + 1, tr_max->win_x1 - tr_max->win_x0, + OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + opj_sparse_array_int32_free(sa); + return OPJ_TRUE; + } + h_mem_size = opj_dwt_max_resolution(tr, numres); + /* overflow check */ + /* in vertical pass, we process 4 columns at a time */ + if (h_mem_size > (SIZE_MAX / (4 * sizeof(OPJ_INT32)))) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + return OPJ_FALSE; + } + + h_mem_size *= 4 * sizeof(OPJ_INT32); + h.mem = (OPJ_INT32*)opj_aligned_32_malloc(h_mem_size); + if (! h.mem) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + return OPJ_FALSE; + } + + v.mem = h.mem; + + for (resno = 1; resno < numres; resno ++) { + OPJ_UINT32 i, j; + /* Window of interest subband-based coordinates */ + OPJ_UINT32 win_ll_x0, win_ll_y0, win_ll_x1, win_ll_y1; + OPJ_UINT32 win_hl_x0, win_hl_x1; + OPJ_UINT32 win_lh_y0, win_lh_y1; + /* Window of interest tile-resolution-based coordinates */ + OPJ_UINT32 win_tr_x0, win_tr_x1, win_tr_y0, win_tr_y1; + /* Tile-resolution subband-based coordinates */ + OPJ_UINT32 tr_ll_x0, tr_ll_y0, tr_hl_x0, tr_lh_y0; + + ++tr; + + h.sn = (OPJ_INT32)rw; + v.sn = (OPJ_INT32)rh; + + rw = (OPJ_UINT32)(tr->x1 - tr->x0); + rh = (OPJ_UINT32)(tr->y1 - tr->y0); + + h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); + h.cas = tr->x0 % 2; + + v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); + v.cas = tr->y0 % 2; + + /* Get the subband coordinates for the window of interest */ + /* LL band */ + opj_dwt_get_band_coordinates(tilec, resno, 0, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + &win_ll_x0, &win_ll_y0, + &win_ll_x1, &win_ll_y1); + + /* HL band */ + opj_dwt_get_band_coordinates(tilec, resno, 1, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + &win_hl_x0, NULL, &win_hl_x1, NULL); + + /* LH band */ + opj_dwt_get_band_coordinates(tilec, resno, 2, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + NULL, &win_lh_y0, NULL, &win_lh_y1); + + /* Beware: band index for non-LL0 resolution are 0=HL, 1=LH and 2=HH */ + tr_ll_x0 = (OPJ_UINT32)tr->bands[1].x0; + tr_ll_y0 = (OPJ_UINT32)tr->bands[0].y0; + tr_hl_x0 = (OPJ_UINT32)tr->bands[0].x0; + tr_lh_y0 = (OPJ_UINT32)tr->bands[1].y0; + + /* Subtract the origin of the bands for this tile, to the subwindow */ + /* of interest band coordinates, so as to get them relative to the */ + /* tile */ + win_ll_x0 = opj_uint_subs(win_ll_x0, tr_ll_x0); + win_ll_y0 = opj_uint_subs(win_ll_y0, tr_ll_y0); + win_ll_x1 = opj_uint_subs(win_ll_x1, tr_ll_x0); + win_ll_y1 = opj_uint_subs(win_ll_y1, tr_ll_y0); + win_hl_x0 = opj_uint_subs(win_hl_x0, tr_hl_x0); + win_hl_x1 = opj_uint_subs(win_hl_x1, tr_hl_x0); + win_lh_y0 = opj_uint_subs(win_lh_y0, tr_lh_y0); + win_lh_y1 = opj_uint_subs(win_lh_y1, tr_lh_y0); + + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)h.sn, &win_ll_x0, &win_ll_x1); + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)h.dn, &win_hl_x0, &win_hl_x1); + + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)v.sn, &win_ll_y0, &win_ll_y1); + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)v.dn, &win_lh_y0, &win_lh_y1); + + /* Compute the tile-resolution-based coordinates for the window of interest */ + if (h.cas == 0) { + win_tr_x0 = opj_uint_min(2 * win_ll_x0, 2 * win_hl_x0 + 1); + win_tr_x1 = opj_uint_min(opj_uint_max(2 * win_ll_x1, 2 * win_hl_x1 + 1), rw); + } else { + win_tr_x0 = opj_uint_min(2 * win_hl_x0, 2 * win_ll_x0 + 1); + win_tr_x1 = opj_uint_min(opj_uint_max(2 * win_hl_x1, 2 * win_ll_x1 + 1), rw); + } + + if (v.cas == 0) { + win_tr_y0 = opj_uint_min(2 * win_ll_y0, 2 * win_lh_y0 + 1); + win_tr_y1 = opj_uint_min(opj_uint_max(2 * win_ll_y1, 2 * win_lh_y1 + 1), rh); + } else { + win_tr_y0 = opj_uint_min(2 * win_lh_y0, 2 * win_ll_y0 + 1); + win_tr_y1 = opj_uint_min(opj_uint_max(2 * win_lh_y1, 2 * win_ll_y1 + 1), rh); + } + + for (j = 0; j < rh; ++j) { + if ((j >= win_ll_y0 && j < win_ll_y1) || + (j >= win_lh_y0 + (OPJ_UINT32)v.sn && j < win_lh_y1 + (OPJ_UINT32)v.sn)) { + + /* Avoids dwt.c:1584:44 (in opj_dwt_decode_partial_1): runtime error: */ + /* signed integer overflow: -1094795586 + -1094795586 cannot be represented in type 'int' */ + /* on opj_decompress -i ../../openjpeg/MAPA.jp2 -o out.tif -d 0,0,256,256 */ + /* This is less extreme than memsetting the whole buffer to 0 */ + /* although we could potentially do better with better handling of edge conditions */ + if (win_tr_x1 >= 1 && win_tr_x1 < rw) { + h.mem[win_tr_x1 - 1] = 0; + } + if (win_tr_x1 < rw) { + h.mem[win_tr_x1] = 0; + } + + opj_dwt_interleave_partial_h(h.mem, + h.cas, + sa, + j, + (OPJ_UINT32)h.sn, + win_ll_x0, + win_ll_x1, + win_hl_x0, + win_hl_x1); + opj_dwt_decode_partial_1(h.mem, h.dn, h.sn, h.cas, + (OPJ_INT32)win_ll_x0, + (OPJ_INT32)win_ll_x1, + (OPJ_INT32)win_hl_x0, + (OPJ_INT32)win_hl_x1); + if (!opj_sparse_array_int32_write(sa, + win_tr_x0, j, + win_tr_x1, j + 1, + h.mem + win_tr_x0, + 1, 0, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.mem); + return OPJ_FALSE; + } + } + } + + for (i = win_tr_x0; i < win_tr_x1;) { + OPJ_UINT32 nb_cols = opj_uint_min(4U, win_tr_x1 - i); + opj_dwt_interleave_partial_v(v.mem, + v.cas, + sa, + i, + nb_cols, + (OPJ_UINT32)v.sn, + win_ll_y0, + win_ll_y1, + win_lh_y0, + win_lh_y1); + opj_dwt_decode_partial_1_parallel(v.mem, nb_cols, v.dn, v.sn, v.cas, + (OPJ_INT32)win_ll_y0, + (OPJ_INT32)win_ll_y1, + (OPJ_INT32)win_lh_y0, + (OPJ_INT32)win_lh_y1); + if (!opj_sparse_array_int32_write(sa, + i, win_tr_y0, + i + nb_cols, win_tr_y1, + v.mem + 4 * win_tr_y0, + 1, 4, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.mem); + return OPJ_FALSE; + } + + i += nb_cols; + } + } + opj_aligned_free(h.mem); + + { + OPJ_BOOL ret = opj_sparse_array_int32_read(sa, + tr_max->win_x0 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y0 - (OPJ_UINT32)tr_max->y0, + tr_max->win_x1 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y1 - (OPJ_UINT32)tr_max->y0, + tilec->data_win, + 1, tr_max->win_x1 - tr_max->win_x0, + OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + } + opj_sparse_array_int32_free(sa); + return OPJ_TRUE; +} + +static void opj_v8dwt_interleave_h(opj_v8dwt_t* OPJ_RESTRICT dwt, + OPJ_FLOAT32* OPJ_RESTRICT a, + OPJ_UINT32 width, + OPJ_UINT32 remaining_height) +{ + OPJ_FLOAT32* OPJ_RESTRICT bi = (OPJ_FLOAT32*)(dwt->wavelet + dwt->cas); + OPJ_UINT32 i, k; + OPJ_UINT32 x0 = dwt->win_l_x0; + OPJ_UINT32 x1 = dwt->win_l_x1; + + for (k = 0; k < 2; ++k) { + if (remaining_height >= NB_ELTS_V8 && ((OPJ_SIZE_T) a & 0x0f) == 0 && + ((OPJ_SIZE_T) bi & 0x0f) == 0) { + /* Fast code path */ + for (i = x0; i < x1; ++i) { + OPJ_UINT32 j = i; + OPJ_FLOAT32* OPJ_RESTRICT dst = bi + i * 2 * NB_ELTS_V8; + dst[0] = a[j]; + j += width; + dst[1] = a[j]; + j += width; + dst[2] = a[j]; + j += width; + dst[3] = a[j]; + j += width; + dst[4] = a[j]; + j += width; + dst[5] = a[j]; + j += width; + dst[6] = a[j]; + j += width; + dst[7] = a[j]; + } + } else { + /* Slow code path */ + for (i = x0; i < x1; ++i) { + OPJ_UINT32 j = i; + OPJ_FLOAT32* OPJ_RESTRICT dst = bi + i * 2 * NB_ELTS_V8; + dst[0] = a[j]; + j += width; + if (remaining_height == 1) { + continue; + } + dst[1] = a[j]; + j += width; + if (remaining_height == 2) { + continue; + } + dst[2] = a[j]; + j += width; + if (remaining_height == 3) { + continue; + } + dst[3] = a[j]; + j += width; + if (remaining_height == 4) { + continue; + } + dst[4] = a[j]; + j += width; + if (remaining_height == 5) { + continue; + } + dst[5] = a[j]; + j += width; + if (remaining_height == 6) { + continue; + } + dst[6] = a[j]; + j += width; + if (remaining_height == 7) { + continue; + } + dst[7] = a[j]; + } + } + + bi = (OPJ_FLOAT32*)(dwt->wavelet + 1 - dwt->cas); + a += dwt->sn; + x0 = dwt->win_h_x0; + x1 = dwt->win_h_x1; + } +} + +static void opj_v8dwt_interleave_partial_h(opj_v8dwt_t* dwt, + opj_sparse_array_int32_t* sa, + OPJ_UINT32 sa_line, + OPJ_UINT32 remaining_height) +{ + OPJ_UINT32 i; + for (i = 0; i < remaining_height; i++) { + OPJ_BOOL ret; + ret = opj_sparse_array_int32_read(sa, + dwt->win_l_x0, sa_line + i, + dwt->win_l_x1, sa_line + i + 1, + /* Nasty cast from float* to int32* */ + (OPJ_INT32*)(dwt->wavelet + dwt->cas + 2 * dwt->win_l_x0) + i, + 2 * NB_ELTS_V8, 0, OPJ_TRUE); + assert(ret); + ret = opj_sparse_array_int32_read(sa, + (OPJ_UINT32)dwt->sn + dwt->win_h_x0, sa_line + i, + (OPJ_UINT32)dwt->sn + dwt->win_h_x1, sa_line + i + 1, + /* Nasty cast from float* to int32* */ + (OPJ_INT32*)(dwt->wavelet + 1 - dwt->cas + 2 * dwt->win_h_x0) + i, + 2 * NB_ELTS_V8, 0, OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + } +} + +static INLINE void opj_v8dwt_interleave_v(opj_v8dwt_t* OPJ_RESTRICT dwt, + OPJ_FLOAT32* OPJ_RESTRICT a, + OPJ_UINT32 width, + OPJ_UINT32 nb_elts_read) +{ + opj_v8_t* OPJ_RESTRICT bi = dwt->wavelet + dwt->cas; + OPJ_UINT32 i; + + for (i = dwt->win_l_x0; i < dwt->win_l_x1; ++i) { + memcpy(&bi[i * 2], &a[i * (OPJ_SIZE_T)width], + (OPJ_SIZE_T)nb_elts_read * sizeof(OPJ_FLOAT32)); + } + + a += (OPJ_UINT32)dwt->sn * (OPJ_SIZE_T)width; + bi = dwt->wavelet + 1 - dwt->cas; + + for (i = dwt->win_h_x0; i < dwt->win_h_x1; ++i) { + memcpy(&bi[i * 2], &a[i * (OPJ_SIZE_T)width], + (OPJ_SIZE_T)nb_elts_read * sizeof(OPJ_FLOAT32)); + } +} + +static void opj_v8dwt_interleave_partial_v(opj_v8dwt_t* OPJ_RESTRICT dwt, + opj_sparse_array_int32_t* sa, + OPJ_UINT32 sa_col, + OPJ_UINT32 nb_elts_read) +{ + OPJ_BOOL ret; + ret = opj_sparse_array_int32_read(sa, + sa_col, dwt->win_l_x0, + sa_col + nb_elts_read, dwt->win_l_x1, + (OPJ_INT32*)(dwt->wavelet + dwt->cas + 2 * dwt->win_l_x0), + 1, 2 * NB_ELTS_V8, OPJ_TRUE); + assert(ret); + ret = opj_sparse_array_int32_read(sa, + sa_col, (OPJ_UINT32)dwt->sn + dwt->win_h_x0, + sa_col + nb_elts_read, (OPJ_UINT32)dwt->sn + dwt->win_h_x1, + (OPJ_INT32*)(dwt->wavelet + 1 - dwt->cas + 2 * dwt->win_h_x0), + 1, 2 * NB_ELTS_V8, OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); +} + +#ifdef __SSE__ + +static void opj_v8dwt_decode_step1_sse(opj_v8_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + const __m128 c) +{ + __m128* OPJ_RESTRICT vw = (__m128*) w; + OPJ_UINT32 i = start; + /* To be adapted if NB_ELTS_V8 changes */ + vw += 4 * start; + /* Note: attempt at loop unrolling x2 doesn't help */ + for (; i < end; ++i, vw += 4) { + vw[0] = _mm_mul_ps(vw[0], c); + vw[1] = _mm_mul_ps(vw[1], c); + } +} + +static void opj_v8dwt_decode_step2_sse(opj_v8_t* l, opj_v8_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + OPJ_UINT32 m, + __m128 c) +{ + __m128* OPJ_RESTRICT vl = (__m128*) l; + __m128* OPJ_RESTRICT vw = (__m128*) w; + /* To be adapted if NB_ELTS_V8 changes */ + OPJ_UINT32 i; + OPJ_UINT32 imax = opj_uint_min(end, m); + if (start == 0) { + if (imax >= 1) { + vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(_mm_add_ps(vl[0], vw[0]), c)); + vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(_mm_add_ps(vl[1], vw[1]), c)); + vw += 4; + start = 1; + } + } else { + vw += start * 4; + } + + i = start; + /* Note: attempt at loop unrolling x2 doesn't help */ + for (; i < imax; ++i) { + vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(_mm_add_ps(vw[-4], vw[0]), c)); + vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(_mm_add_ps(vw[-3], vw[1]), c)); + vw += 4; + } + if (m < end) { + assert(m + 1 == end); + c = _mm_add_ps(c, c); + vw[-2] = _mm_add_ps(vw[-2], _mm_mul_ps(c, vw[-4])); + vw[-1] = _mm_add_ps(vw[-1], _mm_mul_ps(c, vw[-3])); + } +} + +#else + +static void opj_v8dwt_decode_step1(opj_v8_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + const OPJ_FLOAT32 c) +{ + OPJ_FLOAT32* OPJ_RESTRICT fw = (OPJ_FLOAT32*) w; + OPJ_UINT32 i; + /* To be adapted if NB_ELTS_V8 changes */ + for (i = start; i < end; ++i) { + fw[i * 2 * 8 ] = fw[i * 2 * 8 ] * c; + fw[i * 2 * 8 + 1] = fw[i * 2 * 8 + 1] * c; + fw[i * 2 * 8 + 2] = fw[i * 2 * 8 + 2] * c; + fw[i * 2 * 8 + 3] = fw[i * 2 * 8 + 3] * c; + fw[i * 2 * 8 + 4] = fw[i * 2 * 8 + 4] * c; + fw[i * 2 * 8 + 5] = fw[i * 2 * 8 + 5] * c; + fw[i * 2 * 8 + 6] = fw[i * 2 * 8 + 6] * c; + fw[i * 2 * 8 + 7] = fw[i * 2 * 8 + 7] * c; + } +} + +static void opj_v8dwt_decode_step2(opj_v8_t* l, opj_v8_t* w, + OPJ_UINT32 start, + OPJ_UINT32 end, + OPJ_UINT32 m, + OPJ_FLOAT32 c) +{ + OPJ_FLOAT32* fl = (OPJ_FLOAT32*) l; + OPJ_FLOAT32* fw = (OPJ_FLOAT32*) w; + OPJ_UINT32 i; + OPJ_UINT32 imax = opj_uint_min(end, m); + if (start > 0) { + fw += 2 * NB_ELTS_V8 * start; + fl = fw - 2 * NB_ELTS_V8; + } + /* To be adapted if NB_ELTS_V8 changes */ + for (i = start; i < imax; ++i) { + fw[-8] = fw[-8] + ((fl[0] + fw[0]) * c); + fw[-7] = fw[-7] + ((fl[1] + fw[1]) * c); + fw[-6] = fw[-6] + ((fl[2] + fw[2]) * c); + fw[-5] = fw[-5] + ((fl[3] + fw[3]) * c); + fw[-4] = fw[-4] + ((fl[4] + fw[4]) * c); + fw[-3] = fw[-3] + ((fl[5] + fw[5]) * c); + fw[-2] = fw[-2] + ((fl[6] + fw[6]) * c); + fw[-1] = fw[-1] + ((fl[7] + fw[7]) * c); + fl = fw; + fw += 2 * NB_ELTS_V8; + } + if (m < end) { + assert(m + 1 == end); + c += c; + fw[-8] = fw[-8] + fl[0] * c; + fw[-7] = fw[-7] + fl[1] * c; + fw[-6] = fw[-6] + fl[2] * c; + fw[-5] = fw[-5] + fl[3] * c; + fw[-4] = fw[-4] + fl[4] * c; + fw[-3] = fw[-3] + fl[5] * c; + fw[-2] = fw[-2] + fl[6] * c; + fw[-1] = fw[-1] + fl[7] * c; + } +} + +#endif + +/* */ +/* Inverse 9-7 wavelet transform in 1-D. */ +/* */ +static void opj_v8dwt_decode(opj_v8dwt_t* OPJ_RESTRICT dwt) +{ + OPJ_INT32 a, b; + /* BUG_WEIRD_TWO_INVK (look for this identifier in tcd.c) */ + /* Historic value for 2 / opj_invK */ + /* Normally, we should use invK, but if we do so, we have failures in the */ + /* conformance test, due to MSE and peak errors significantly higher than */ + /* accepted value */ + /* Due to using two_invK instead of invK, we have to compensate in tcd.c */ + /* the computation of the stepsize for the non LL subbands */ + const float two_invK = 1.625732422f; + if (dwt->cas == 0) { + if (!((dwt->dn > 0) || (dwt->sn > 1))) { + return; + } + a = 0; + b = 1; + } else { + if (!((dwt->sn > 0) || (dwt->dn > 1))) { + return; + } + a = 1; + b = 0; + } +#ifdef __SSE__ + opj_v8dwt_decode_step1_sse(dwt->wavelet + a, dwt->win_l_x0, dwt->win_l_x1, + _mm_set1_ps(opj_K)); + opj_v8dwt_decode_step1_sse(dwt->wavelet + b, dwt->win_h_x0, dwt->win_h_x1, + _mm_set1_ps(two_invK)); + opj_v8dwt_decode_step2_sse(dwt->wavelet + b, dwt->wavelet + a + 1, + dwt->win_l_x0, dwt->win_l_x1, + (OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a), + _mm_set1_ps(-opj_dwt_delta)); + opj_v8dwt_decode_step2_sse(dwt->wavelet + a, dwt->wavelet + b + 1, + dwt->win_h_x0, dwt->win_h_x1, + (OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b), + _mm_set1_ps(-opj_dwt_gamma)); + opj_v8dwt_decode_step2_sse(dwt->wavelet + b, dwt->wavelet + a + 1, + dwt->win_l_x0, dwt->win_l_x1, + (OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a), + _mm_set1_ps(-opj_dwt_beta)); + opj_v8dwt_decode_step2_sse(dwt->wavelet + a, dwt->wavelet + b + 1, + dwt->win_h_x0, dwt->win_h_x1, + (OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b), + _mm_set1_ps(-opj_dwt_alpha)); +#else + opj_v8dwt_decode_step1(dwt->wavelet + a, dwt->win_l_x0, dwt->win_l_x1, + opj_K); + opj_v8dwt_decode_step1(dwt->wavelet + b, dwt->win_h_x0, dwt->win_h_x1, + two_invK); + opj_v8dwt_decode_step2(dwt->wavelet + b, dwt->wavelet + a + 1, + dwt->win_l_x0, dwt->win_l_x1, + (OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a), + -opj_dwt_delta); + opj_v8dwt_decode_step2(dwt->wavelet + a, dwt->wavelet + b + 1, + dwt->win_h_x0, dwt->win_h_x1, + (OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b), + -opj_dwt_gamma); + opj_v8dwt_decode_step2(dwt->wavelet + b, dwt->wavelet + a + 1, + dwt->win_l_x0, dwt->win_l_x1, + (OPJ_UINT32)opj_int_min(dwt->sn, dwt->dn - a), + -opj_dwt_beta); + opj_v8dwt_decode_step2(dwt->wavelet + a, dwt->wavelet + b + 1, + dwt->win_h_x0, dwt->win_h_x1, + (OPJ_UINT32)opj_int_min(dwt->dn, dwt->sn - b), + -opj_dwt_alpha); +#endif +} + +typedef struct { + opj_v8dwt_t h; + OPJ_UINT32 rw; + OPJ_UINT32 w; + OPJ_FLOAT32 * OPJ_RESTRICT aj; + OPJ_UINT32 nb_rows; +} opj_dwt97_decode_h_job_t; + +static void opj_dwt97_decode_h_func(void* user_data, opj_tls_t* tls) +{ + OPJ_UINT32 j; + opj_dwt97_decode_h_job_t* job; + OPJ_FLOAT32 * OPJ_RESTRICT aj; + OPJ_UINT32 w; + (void)tls; + + job = (opj_dwt97_decode_h_job_t*)user_data; + w = job->w; + + assert((job->nb_rows % NB_ELTS_V8) == 0); + + aj = job->aj; + for (j = 0; j + NB_ELTS_V8 <= job->nb_rows; j += NB_ELTS_V8) { + OPJ_UINT32 k; + opj_v8dwt_interleave_h(&job->h, aj, job->w, NB_ELTS_V8); + opj_v8dwt_decode(&job->h); + + /* To be adapted if NB_ELTS_V8 changes */ + for (k = 0; k < job->rw; k++) { + aj[k ] = job->h.wavelet[k].f[0]; + aj[k + (OPJ_SIZE_T)w ] = job->h.wavelet[k].f[1]; + aj[k + (OPJ_SIZE_T)w * 2] = job->h.wavelet[k].f[2]; + aj[k + (OPJ_SIZE_T)w * 3] = job->h.wavelet[k].f[3]; + } + for (k = 0; k < job->rw; k++) { + aj[k + (OPJ_SIZE_T)w * 4] = job->h.wavelet[k].f[4]; + aj[k + (OPJ_SIZE_T)w * 5] = job->h.wavelet[k].f[5]; + aj[k + (OPJ_SIZE_T)w * 6] = job->h.wavelet[k].f[6]; + aj[k + (OPJ_SIZE_T)w * 7] = job->h.wavelet[k].f[7]; + } + + aj += w * NB_ELTS_V8; + } + + opj_aligned_free(job->h.wavelet); + opj_free(job); +} + + +typedef struct { + opj_v8dwt_t v; + OPJ_UINT32 rh; + OPJ_UINT32 w; + OPJ_FLOAT32 * OPJ_RESTRICT aj; + OPJ_UINT32 nb_columns; +} opj_dwt97_decode_v_job_t; + +static void opj_dwt97_decode_v_func(void* user_data, opj_tls_t* tls) +{ + OPJ_UINT32 j; + opj_dwt97_decode_v_job_t* job; + OPJ_FLOAT32 * OPJ_RESTRICT aj; + (void)tls; + + job = (opj_dwt97_decode_v_job_t*)user_data; + + assert((job->nb_columns % NB_ELTS_V8) == 0); + + aj = job->aj; + for (j = 0; j + NB_ELTS_V8 <= job->nb_columns; j += NB_ELTS_V8) { + OPJ_UINT32 k; + + opj_v8dwt_interleave_v(&job->v, aj, job->w, NB_ELTS_V8); + opj_v8dwt_decode(&job->v); + + for (k = 0; k < job->rh; ++k) { + memcpy(&aj[k * (OPJ_SIZE_T)job->w], &job->v.wavelet[k], + NB_ELTS_V8 * sizeof(OPJ_FLOAT32)); + } + aj += NB_ELTS_V8; + } + + opj_aligned_free(job->v.wavelet); + opj_free(job); +} + + +/* */ +/* Inverse 9-7 wavelet transform in 2-D. */ +/* */ +static +OPJ_BOOL opj_dwt_decode_tile_97(opj_thread_pool_t* tp, + opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, + OPJ_UINT32 numres) +{ + opj_v8dwt_t h; + opj_v8dwt_t v; + + opj_tcd_resolution_t* res = tilec->resolutions; + + OPJ_UINT32 rw = (OPJ_UINT32)(res->x1 - + res->x0); /* width of the resolution level computed */ + OPJ_UINT32 rh = (OPJ_UINT32)(res->y1 - + res->y0); /* height of the resolution level computed */ + + OPJ_UINT32 w = (OPJ_UINT32)(tilec->resolutions[tilec->minimum_num_resolutions - + 1].x1 - + tilec->resolutions[tilec->minimum_num_resolutions - 1].x0); + + OPJ_SIZE_T l_data_size; + const int num_threads = opj_thread_pool_get_thread_count(tp); + + if (numres == 1) { + return OPJ_TRUE; + } + + l_data_size = opj_dwt_max_resolution(res, numres); + /* overflow check */ + if (l_data_size > (SIZE_MAX / sizeof(opj_v8_t))) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + h.wavelet = (opj_v8_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v8_t)); + if (!h.wavelet) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + v.wavelet = h.wavelet; + + while (--numres) { + OPJ_FLOAT32 * OPJ_RESTRICT aj = (OPJ_FLOAT32*) tilec->data; + OPJ_UINT32 j; + + h.sn = (OPJ_INT32)rw; + v.sn = (OPJ_INT32)rh; + + ++res; + + rw = (OPJ_UINT32)(res->x1 - + res->x0); /* width of the resolution level computed */ + rh = (OPJ_UINT32)(res->y1 - + res->y0); /* height of the resolution level computed */ + + h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); + h.cas = res->x0 % 2; + + h.win_l_x0 = 0; + h.win_l_x1 = (OPJ_UINT32)h.sn; + h.win_h_x0 = 0; + h.win_h_x1 = (OPJ_UINT32)h.dn; + + if (num_threads <= 1 || rh < 2 * NB_ELTS_V8) { + for (j = 0; j + (NB_ELTS_V8 - 1) < rh; j += NB_ELTS_V8) { + OPJ_UINT32 k; + opj_v8dwt_interleave_h(&h, aj, w, NB_ELTS_V8); + opj_v8dwt_decode(&h); + + /* To be adapted if NB_ELTS_V8 changes */ + for (k = 0; k < rw; k++) { + aj[k ] = h.wavelet[k].f[0]; + aj[k + (OPJ_SIZE_T)w ] = h.wavelet[k].f[1]; + aj[k + (OPJ_SIZE_T)w * 2] = h.wavelet[k].f[2]; + aj[k + (OPJ_SIZE_T)w * 3] = h.wavelet[k].f[3]; + } + for (k = 0; k < rw; k++) { + aj[k + (OPJ_SIZE_T)w * 4] = h.wavelet[k].f[4]; + aj[k + (OPJ_SIZE_T)w * 5] = h.wavelet[k].f[5]; + aj[k + (OPJ_SIZE_T)w * 6] = h.wavelet[k].f[6]; + aj[k + (OPJ_SIZE_T)w * 7] = h.wavelet[k].f[7]; + } + + aj += w * NB_ELTS_V8; + } + } else { + OPJ_UINT32 num_jobs = (OPJ_UINT32)num_threads; + OPJ_UINT32 step_j; + + if ((rh / NB_ELTS_V8) < num_jobs) { + num_jobs = rh / NB_ELTS_V8; + } + step_j = ((rh / num_jobs) / NB_ELTS_V8) * NB_ELTS_V8; + for (j = 0; j < num_jobs; j++) { + opj_dwt97_decode_h_job_t* job; + + job = (opj_dwt97_decode_h_job_t*) opj_malloc(sizeof(opj_dwt97_decode_h_job_t)); + if (!job) { + opj_thread_pool_wait_completion(tp, 0); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + job->h.wavelet = (opj_v8_t*)opj_aligned_malloc(l_data_size * sizeof(opj_v8_t)); + if (!job->h.wavelet) { + opj_thread_pool_wait_completion(tp, 0); + opj_free(job); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + job->h.dn = h.dn; + job->h.sn = h.sn; + job->h.cas = h.cas; + job->h.win_l_x0 = h.win_l_x0; + job->h.win_l_x1 = h.win_l_x1; + job->h.win_h_x0 = h.win_h_x0; + job->h.win_h_x1 = h.win_h_x1; + job->rw = rw; + job->w = w; + job->aj = aj; + job->nb_rows = (j + 1 == num_jobs) ? (rh & (OPJ_UINT32)~ + (NB_ELTS_V8 - 1)) - j * step_j : step_j; + aj += w * job->nb_rows; + opj_thread_pool_submit_job(tp, opj_dwt97_decode_h_func, job); + } + opj_thread_pool_wait_completion(tp, 0); + j = rh & (OPJ_UINT32)~(NB_ELTS_V8 - 1); + } + + if (j < rh) { + OPJ_UINT32 k; + opj_v8dwt_interleave_h(&h, aj, w, rh - j); + opj_v8dwt_decode(&h); + for (k = 0; k < rw; k++) { + OPJ_UINT32 l; + for (l = 0; l < rh - j; l++) { + aj[k + (OPJ_SIZE_T)w * l ] = h.wavelet[k].f[l]; + } + } + } + + v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); + v.cas = res->y0 % 2; + v.win_l_x0 = 0; + v.win_l_x1 = (OPJ_UINT32)v.sn; + v.win_h_x0 = 0; + v.win_h_x1 = (OPJ_UINT32)v.dn; + + aj = (OPJ_FLOAT32*) tilec->data; + if (num_threads <= 1 || rw < 2 * NB_ELTS_V8) { + for (j = rw; j > (NB_ELTS_V8 - 1); j -= NB_ELTS_V8) { + OPJ_UINT32 k; + + opj_v8dwt_interleave_v(&v, aj, w, NB_ELTS_V8); + opj_v8dwt_decode(&v); + + for (k = 0; k < rh; ++k) { + memcpy(&aj[k * (OPJ_SIZE_T)w], &v.wavelet[k], NB_ELTS_V8 * sizeof(OPJ_FLOAT32)); + } + aj += NB_ELTS_V8; + } + } else { + /* "bench_dwt -I" shows that scaling is poor, likely due to RAM + transfer being the limiting factor. So limit the number of + threads. + */ + OPJ_UINT32 num_jobs = opj_uint_max((OPJ_UINT32)num_threads / 2, 2U); + OPJ_UINT32 step_j; + + if ((rw / NB_ELTS_V8) < num_jobs) { + num_jobs = rw / NB_ELTS_V8; + } + step_j = ((rw / num_jobs) / NB_ELTS_V8) * NB_ELTS_V8; + for (j = 0; j < num_jobs; j++) { + opj_dwt97_decode_v_job_t* job; + + job = (opj_dwt97_decode_v_job_t*) opj_malloc(sizeof(opj_dwt97_decode_v_job_t)); + if (!job) { + opj_thread_pool_wait_completion(tp, 0); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + job->v.wavelet = (opj_v8_t*)opj_aligned_malloc(l_data_size * sizeof(opj_v8_t)); + if (!job->v.wavelet) { + opj_thread_pool_wait_completion(tp, 0); + opj_free(job); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + job->v.dn = v.dn; + job->v.sn = v.sn; + job->v.cas = v.cas; + job->v.win_l_x0 = v.win_l_x0; + job->v.win_l_x1 = v.win_l_x1; + job->v.win_h_x0 = v.win_h_x0; + job->v.win_h_x1 = v.win_h_x1; + job->rh = rh; + job->w = w; + job->aj = aj; + job->nb_columns = (j + 1 == num_jobs) ? (rw & (OPJ_UINT32)~ + (NB_ELTS_V8 - 1)) - j * step_j : step_j; + aj += job->nb_columns; + opj_thread_pool_submit_job(tp, opj_dwt97_decode_v_func, job); + } + opj_thread_pool_wait_completion(tp, 0); + } + + if (rw & (NB_ELTS_V8 - 1)) { + OPJ_UINT32 k; + + j = rw & (NB_ELTS_V8 - 1); + + opj_v8dwt_interleave_v(&v, aj, w, j); + opj_v8dwt_decode(&v); + + for (k = 0; k < rh; ++k) { + memcpy(&aj[k * (OPJ_SIZE_T)w], &v.wavelet[k], + (OPJ_SIZE_T)j * sizeof(OPJ_FLOAT32)); + } + } + } + + opj_aligned_free(h.wavelet); + return OPJ_TRUE; +} + +static +OPJ_BOOL opj_dwt_decode_partial_97(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, + OPJ_UINT32 numres) +{ + opj_sparse_array_int32_t* sa; + opj_v8dwt_t h; + opj_v8dwt_t v; + OPJ_UINT32 resno; + /* This value matches the maximum left/right extension given in tables */ + /* F.2 and F.3 of the standard. Note: in opj_tcd_is_subband_area_of_interest() */ + /* we currently use 3. */ + const OPJ_UINT32 filter_width = 4U; + + opj_tcd_resolution_t* tr = tilec->resolutions; + opj_tcd_resolution_t* tr_max = &(tilec->resolutions[numres - 1]); + + OPJ_UINT32 rw = (OPJ_UINT32)(tr->x1 - + tr->x0); /* width of the resolution level computed */ + OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - + tr->y0); /* height of the resolution level computed */ + + OPJ_SIZE_T l_data_size; + + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 win_tcx0 = tilec->win_x0; + OPJ_UINT32 win_tcy0 = tilec->win_y0; + OPJ_UINT32 win_tcx1 = tilec->win_x1; + OPJ_UINT32 win_tcy1 = tilec->win_y1; + + if (tr_max->x0 == tr_max->x1 || tr_max->y0 == tr_max->y1) { + return OPJ_TRUE; + } + + sa = opj_dwt_init_sparse_array(tilec, numres); + if (sa == NULL) { + return OPJ_FALSE; + } + + if (numres == 1U) { + OPJ_BOOL ret = opj_sparse_array_int32_read(sa, + tr_max->win_x0 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y0 - (OPJ_UINT32)tr_max->y0, + tr_max->win_x1 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y1 - (OPJ_UINT32)tr_max->y0, + tilec->data_win, + 1, tr_max->win_x1 - tr_max->win_x0, + OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + opj_sparse_array_int32_free(sa); + return OPJ_TRUE; + } + + l_data_size = opj_dwt_max_resolution(tr, numres); + /* overflow check */ + if (l_data_size > (SIZE_MAX / sizeof(opj_v8_t))) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + return OPJ_FALSE; + } + h.wavelet = (opj_v8_t*) opj_aligned_malloc(l_data_size * sizeof(opj_v8_t)); + if (!h.wavelet) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + return OPJ_FALSE; + } + v.wavelet = h.wavelet; + + for (resno = 1; resno < numres; resno ++) { + OPJ_UINT32 j; + /* Window of interest subband-based coordinates */ + OPJ_UINT32 win_ll_x0, win_ll_y0, win_ll_x1, win_ll_y1; + OPJ_UINT32 win_hl_x0, win_hl_x1; + OPJ_UINT32 win_lh_y0, win_lh_y1; + /* Window of interest tile-resolution-based coordinates */ + OPJ_UINT32 win_tr_x0, win_tr_x1, win_tr_y0, win_tr_y1; + /* Tile-resolution subband-based coordinates */ + OPJ_UINT32 tr_ll_x0, tr_ll_y0, tr_hl_x0, tr_lh_y0; + + ++tr; + + h.sn = (OPJ_INT32)rw; + v.sn = (OPJ_INT32)rh; + + rw = (OPJ_UINT32)(tr->x1 - tr->x0); + rh = (OPJ_UINT32)(tr->y1 - tr->y0); + + h.dn = (OPJ_INT32)(rw - (OPJ_UINT32)h.sn); + h.cas = tr->x0 % 2; + + v.dn = (OPJ_INT32)(rh - (OPJ_UINT32)v.sn); + v.cas = tr->y0 % 2; + + /* Get the subband coordinates for the window of interest */ + /* LL band */ + opj_dwt_get_band_coordinates(tilec, resno, 0, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + &win_ll_x0, &win_ll_y0, + &win_ll_x1, &win_ll_y1); + + /* HL band */ + opj_dwt_get_band_coordinates(tilec, resno, 1, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + &win_hl_x0, NULL, &win_hl_x1, NULL); + + /* LH band */ + opj_dwt_get_band_coordinates(tilec, resno, 2, + win_tcx0, win_tcy0, win_tcx1, win_tcy1, + NULL, &win_lh_y0, NULL, &win_lh_y1); + + /* Beware: band index for non-LL0 resolution are 0=HL, 1=LH and 2=HH */ + tr_ll_x0 = (OPJ_UINT32)tr->bands[1].x0; + tr_ll_y0 = (OPJ_UINT32)tr->bands[0].y0; + tr_hl_x0 = (OPJ_UINT32)tr->bands[0].x0; + tr_lh_y0 = (OPJ_UINT32)tr->bands[1].y0; + + /* Subtract the origin of the bands for this tile, to the subwindow */ + /* of interest band coordinates, so as to get them relative to the */ + /* tile */ + win_ll_x0 = opj_uint_subs(win_ll_x0, tr_ll_x0); + win_ll_y0 = opj_uint_subs(win_ll_y0, tr_ll_y0); + win_ll_x1 = opj_uint_subs(win_ll_x1, tr_ll_x0); + win_ll_y1 = opj_uint_subs(win_ll_y1, tr_ll_y0); + win_hl_x0 = opj_uint_subs(win_hl_x0, tr_hl_x0); + win_hl_x1 = opj_uint_subs(win_hl_x1, tr_hl_x0); + win_lh_y0 = opj_uint_subs(win_lh_y0, tr_lh_y0); + win_lh_y1 = opj_uint_subs(win_lh_y1, tr_lh_y0); + + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)h.sn, &win_ll_x0, &win_ll_x1); + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)h.dn, &win_hl_x0, &win_hl_x1); + + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)v.sn, &win_ll_y0, &win_ll_y1); + opj_dwt_segment_grow(filter_width, (OPJ_UINT32)v.dn, &win_lh_y0, &win_lh_y1); + + /* Compute the tile-resolution-based coordinates for the window of interest */ + if (h.cas == 0) { + win_tr_x0 = opj_uint_min(2 * win_ll_x0, 2 * win_hl_x0 + 1); + win_tr_x1 = opj_uint_min(opj_uint_max(2 * win_ll_x1, 2 * win_hl_x1 + 1), rw); + } else { + win_tr_x0 = opj_uint_min(2 * win_hl_x0, 2 * win_ll_x0 + 1); + win_tr_x1 = opj_uint_min(opj_uint_max(2 * win_hl_x1, 2 * win_ll_x1 + 1), rw); + } + + if (v.cas == 0) { + win_tr_y0 = opj_uint_min(2 * win_ll_y0, 2 * win_lh_y0 + 1); + win_tr_y1 = opj_uint_min(opj_uint_max(2 * win_ll_y1, 2 * win_lh_y1 + 1), rh); + } else { + win_tr_y0 = opj_uint_min(2 * win_lh_y0, 2 * win_ll_y0 + 1); + win_tr_y1 = opj_uint_min(opj_uint_max(2 * win_lh_y1, 2 * win_ll_y1 + 1), rh); + } + + h.win_l_x0 = win_ll_x0; + h.win_l_x1 = win_ll_x1; + h.win_h_x0 = win_hl_x0; + h.win_h_x1 = win_hl_x1; + for (j = 0; j + (NB_ELTS_V8 - 1) < rh; j += NB_ELTS_V8) { + if ((j + (NB_ELTS_V8 - 1) >= win_ll_y0 && j < win_ll_y1) || + (j + (NB_ELTS_V8 - 1) >= win_lh_y0 + (OPJ_UINT32)v.sn && + j < win_lh_y1 + (OPJ_UINT32)v.sn)) { + opj_v8dwt_interleave_partial_h(&h, sa, j, opj_uint_min(NB_ELTS_V8, rh - j)); + opj_v8dwt_decode(&h); + if (!opj_sparse_array_int32_write(sa, + win_tr_x0, j, + win_tr_x1, j + NB_ELTS_V8, + (OPJ_INT32*)&h.wavelet[win_tr_x0].f[0], + NB_ELTS_V8, 1, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + } + } + + if (j < rh && + ((j + (NB_ELTS_V8 - 1) >= win_ll_y0 && j < win_ll_y1) || + (j + (NB_ELTS_V8 - 1) >= win_lh_y0 + (OPJ_UINT32)v.sn && + j < win_lh_y1 + (OPJ_UINT32)v.sn))) { + opj_v8dwt_interleave_partial_h(&h, sa, j, rh - j); + opj_v8dwt_decode(&h); + if (!opj_sparse_array_int32_write(sa, + win_tr_x0, j, + win_tr_x1, rh, + (OPJ_INT32*)&h.wavelet[win_tr_x0].f[0], + NB_ELTS_V8, 1, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + } + + v.win_l_x0 = win_ll_y0; + v.win_l_x1 = win_ll_y1; + v.win_h_x0 = win_lh_y0; + v.win_h_x1 = win_lh_y1; + for (j = win_tr_x0; j < win_tr_x1; j += NB_ELTS_V8) { + OPJ_UINT32 nb_elts = opj_uint_min(NB_ELTS_V8, win_tr_x1 - j); + + opj_v8dwt_interleave_partial_v(&v, sa, j, nb_elts); + opj_v8dwt_decode(&v); + + if (!opj_sparse_array_int32_write(sa, + j, win_tr_y0, + j + nb_elts, win_tr_y1, + (OPJ_INT32*)&h.wavelet[win_tr_y0].f[0], + 1, NB_ELTS_V8, OPJ_TRUE)) { + /* FIXME event manager error callback */ + opj_sparse_array_int32_free(sa); + opj_aligned_free(h.wavelet); + return OPJ_FALSE; + } + } + } + + { + OPJ_BOOL ret = opj_sparse_array_int32_read(sa, + tr_max->win_x0 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y0 - (OPJ_UINT32)tr_max->y0, + tr_max->win_x1 - (OPJ_UINT32)tr_max->x0, + tr_max->win_y1 - (OPJ_UINT32)tr_max->y0, + tilec->data_win, + 1, tr_max->win_x1 - tr_max->win_x0, + OPJ_TRUE); + assert(ret); + OPJ_UNUSED(ret); + } + opj_sparse_array_int32_free(sa); + + opj_aligned_free(h.wavelet); + return OPJ_TRUE; +} + + +OPJ_BOOL opj_dwt_decode_real(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, + OPJ_UINT32 numres) +{ + if (p_tcd->whole_tile_decoding) { + return opj_dwt_decode_tile_97(p_tcd->thread_pool, tilec, numres); + } else { + return opj_dwt_decode_partial_97(tilec, numres); + } +} diff --git a/client/deps/openjpeg/dwt.h b/client/deps/openjpeg/dwt.h new file mode 100644 index 000000000..215061e6b --- /dev/null +++ b/client/deps/openjpeg/dwt.h @@ -0,0 +1,120 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_DWT_H +#define OPJ_DWT_H +/** +@file dwt.h +@brief Implementation of a discrete wavelet transform (DWT) + +The functions in DWT.C have for goal to realize forward and inverse discret wavelet +transform with filter 5-3 (reversible) and filter 9-7 (irreversible). The functions in +DWT.C are used by some function in TCD.C. +*/ + +/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ +/*@{*/ + + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Forward 5-3 wavelet transform in 2-D. +Apply a reversible DWT transform to a component of an image. +@param p_tcd TCD handle +@param tilec Tile component information (current tile) +*/ +OPJ_BOOL opj_dwt_encode(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t * tilec); + +/** +Inverse 5-3 wavelet transform in 2-D. +Apply a reversible inverse DWT transform to a component of an image. +@param p_tcd TCD handle +@param tilec Tile component information (current tile) +@param numres Number of resolution levels to decode +*/ +OPJ_BOOL opj_dwt_decode(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t* tilec, + OPJ_UINT32 numres); + +/** +Get the norm of a wavelet function of a subband at a specified level for the reversible 5-3 DWT. +@param level Level of the wavelet function +@param orient Band of the wavelet function +@return Returns the norm of the wavelet function +*/ +OPJ_FLOAT64 opj_dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient); +/** +Forward 9-7 wavelet transform in 2-D. +Apply an irreversible DWT transform to a component of an image. +@param p_tcd TCD handle +@param tilec Tile component information (current tile) +*/ +OPJ_BOOL opj_dwt_encode_real(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t * tilec); +/** +Inverse 9-7 wavelet transform in 2-D. +Apply an irreversible inverse DWT transform to a component of an image. +@param p_tcd TCD handle +@param tilec Tile component information (current tile) +@param numres Number of resolution levels to decode +*/ +OPJ_BOOL opj_dwt_decode_real(opj_tcd_t *p_tcd, + opj_tcd_tilecomp_t* OPJ_RESTRICT tilec, + OPJ_UINT32 numres); + +/** +Get the norm of a wavelet function of a subband at a specified level for the irreversible 9-7 DWT +@param level Level of the wavelet function +@param orient Band of the wavelet function +@return Returns the norm of the 9-7 wavelet +*/ +OPJ_FLOAT64 opj_dwt_getnorm_real(OPJ_UINT32 level, OPJ_UINT32 orient); +/** +Explicit calculation of the Quantization Stepsizes +@param tccp Tile-component coding parameters +@param prec Precint analyzed +*/ +void opj_dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, OPJ_UINT32 prec); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_DWT_H */ diff --git a/client/deps/openjpeg/event.c b/client/deps/openjpeg/event.c new file mode 100644 index 000000000..aad9d76c9 --- /dev/null +++ b/client/deps/openjpeg/event.c @@ -0,0 +1,151 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +/* ========================================================== + Utility functions + ==========================================================*/ + +#ifdef OPJ_CODE_NOT_USED +#ifndef _WIN32 +static char* +i2a(unsigned i, char *a, unsigned r) +{ + if (i / r > 0) { + a = i2a(i / r, a, r); + } + *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % r]; + return a + 1; +} + +/** + Transforms integer i into an ascii string and stores the result in a; + string is encoded in the base indicated by r. + @param i Number to be converted + @param a String result + @param r Base of value; must be in the range 2 - 36 + @return Returns a +*/ +static char * +_itoa(int i, char *a, int r) +{ + r = ((r < 2) || (r > 36)) ? 10 : r; + if (i < 0) { + *a = '-'; + *i2a(-i, a + 1, r) = 0; + } else { + *i2a(i, a, r) = 0; + } + return a; +} + +#endif /* !_WIN32 */ +#endif + +/* ----------------------------------------------------------------------- */ +/** + * Default callback function. + * Do nothing. + */ +static void opj_default_callback(const char *msg, void *client_data) +{ + OPJ_ARG_NOT_USED(msg); + OPJ_ARG_NOT_USED(client_data); +} + +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ +OPJ_BOOL opj_event_msg(opj_event_mgr_t* p_event_mgr, OPJ_INT32 event_type, + const char *fmt, ...) +{ +#define OPJ_MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */ + opj_msg_callback msg_handler = 00; + void * l_data = 00; + + if (p_event_mgr != 00) { + switch (event_type) { + case EVT_ERROR: + msg_handler = p_event_mgr->error_handler; + l_data = p_event_mgr->m_error_data; + break; + case EVT_WARNING: + msg_handler = p_event_mgr->warning_handler; + l_data = p_event_mgr->m_warning_data; + break; + case EVT_INFO: + msg_handler = p_event_mgr->info_handler; + l_data = p_event_mgr->m_info_data; + break; + default: + break; + } + if (msg_handler == 00) { + return OPJ_FALSE; + } + } else { + return OPJ_FALSE; + } + + if ((fmt != 00) && (p_event_mgr != 00)) { + va_list arg; + char message[OPJ_MSG_SIZE]; + memset(message, 0, OPJ_MSG_SIZE); + /* initialize the optional parameter list */ + va_start(arg, fmt); + /* parse the format string and put the result in 'message' */ + vsnprintf(message, OPJ_MSG_SIZE, fmt, arg); + /* force zero termination for Windows _vsnprintf() of old MSVC */ + message[OPJ_MSG_SIZE - 1] = '\0'; + /* deinitialize the optional parameter list */ + va_end(arg); + + /* output the message to the user program */ + msg_handler(message, l_data); + } + + return OPJ_TRUE; +} + +void opj_set_default_event_handler(opj_event_mgr_t * p_manager) +{ + p_manager->m_error_data = 00; + p_manager->m_warning_data = 00; + p_manager->m_info_data = 00; + p_manager->error_handler = opj_default_callback; + p_manager->info_handler = opj_default_callback; + p_manager->warning_handler = opj_default_callback; +} + diff --git a/client/deps/openjpeg/event.h b/client/deps/openjpeg/event.h new file mode 100644 index 000000000..d880388d0 --- /dev/null +++ b/client/deps/openjpeg/event.h @@ -0,0 +1,108 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_EVENT_H +#define OPJ_EVENT_H +/** +@file event.h +@brief Implementation of a event callback system + +The functions in EVENT.C have for goal to send output messages (errors, warnings, debug) to the user. +*/ +/** +Message handler object +used for +
    +
  • Error messages +
  • Warning messages +
  • Debugging messages +
+*/ +typedef struct opj_event_mgr { + /** Data to call the event manager upon */ + void * m_error_data; + /** Data to call the event manager upon */ + void * m_warning_data; + /** Data to call the event manager upon */ + void * m_info_data; + /** Error message callback if available, NULL otherwise */ + opj_msg_callback error_handler; + /** Warning message callback if available, NULL otherwise */ + opj_msg_callback warning_handler; + /** Debug message callback if available, NULL otherwise */ + opj_msg_callback info_handler; +} opj_event_mgr_t; + + +#define EVT_ERROR 1 /**< Error event type */ +#define EVT_WARNING 2 /**< Warning event type */ +#define EVT_INFO 4 /**< Debug event type */ + +/** @defgroup EVENT EVENT - Implementation of a event callback system */ +/*@{*/ + +/** @name Exported functions (see also openjpeg.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + + +/* ----------------------------------------------------------------------- */ + +/** + * Write formatted data to a string and send the string to a user callback. + * + * @param event_mgr Event handler + * @param event_type Event type or callback to use to send the message + * @param fmt Format-control string (plus optional arguments) + * + * @return Returns true if successful, returns false otherwise + */ +OPJ_BOOL opj_event_msg(opj_event_mgr_t* event_mgr, OPJ_INT32 event_type, + const char *fmt, ...); +/* ----------------------------------------------------------------------- */ + +/** + * Set the event manager with the default callback function for the 3 levels. + */ +void opj_set_default_event_handler(opj_event_mgr_t * p_manager); + +/* +#ifdef __GNUC__ +#pragma GCC poison printf fprintf +#endif +*/ + +/*@}*/ + +/*@}*/ + +#endif /* OPJ_EVENT_H */ diff --git a/client/deps/openjpeg/function_list.c b/client/deps/openjpeg/function_list.c new file mode 100644 index 000000000..e1c1af389 --- /dev/null +++ b/client/deps/openjpeg/function_list.c @@ -0,0 +1,117 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +/** + * Default size of the validation list, if not sufficient, data will be reallocated with a double size. + */ +#define OPJ_VALIDATION_SIZE 10 + +opj_procedure_list_t * opj_procedure_list_create() +{ + /* memory allocation */ + opj_procedure_list_t * l_validation = (opj_procedure_list_t *) opj_calloc(1, + sizeof(opj_procedure_list_t)); + if (! l_validation) { + return 00; + } + /* initialization */ + l_validation->m_nb_max_procedures = OPJ_VALIDATION_SIZE; + l_validation->m_procedures = (opj_procedure*)opj_calloc(OPJ_VALIDATION_SIZE, + sizeof(opj_procedure)); + if (! l_validation->m_procedures) { + opj_free(l_validation); + return 00; + } + return l_validation; +} + +void opj_procedure_list_destroy(opj_procedure_list_t * p_list) +{ + if (! p_list) { + return; + } + /* initialization */ + if (p_list->m_procedures) { + opj_free(p_list->m_procedures); + } + opj_free(p_list); +} + +OPJ_BOOL opj_procedure_list_add_procedure(opj_procedure_list_t * + p_validation_list, opj_procedure p_procedure, opj_event_mgr_t* p_manager) +{ + + assert(p_manager != NULL); + + if (p_validation_list->m_nb_max_procedures == + p_validation_list->m_nb_procedures) { + opj_procedure * new_procedures; + + p_validation_list->m_nb_max_procedures += OPJ_VALIDATION_SIZE; + new_procedures = (opj_procedure*)opj_realloc( + p_validation_list->m_procedures, + p_validation_list->m_nb_max_procedures * sizeof(opj_procedure)); + if (! new_procedures) { + opj_free(p_validation_list->m_procedures); + p_validation_list->m_nb_max_procedures = 0; + p_validation_list->m_nb_procedures = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to add a new validation procedure\n"); + return OPJ_FALSE; + } else { + p_validation_list->m_procedures = new_procedures; + } + } + p_validation_list->m_procedures[p_validation_list->m_nb_procedures] = + p_procedure; + ++p_validation_list->m_nb_procedures; + + return OPJ_TRUE; +} + +OPJ_UINT32 opj_procedure_list_get_nb_procedures(opj_procedure_list_t * + p_validation_list) +{ + return p_validation_list->m_nb_procedures; +} + +opj_procedure* opj_procedure_list_get_first_procedure(opj_procedure_list_t * + p_validation_list) +{ + return p_validation_list->m_procedures; +} + +void opj_procedure_list_clear(opj_procedure_list_t * p_validation_list) +{ + p_validation_list->m_nb_procedures = 0; +} diff --git a/client/deps/openjpeg/function_list.h b/client/deps/openjpeg/function_list.h new file mode 100644 index 000000000..81a3954a1 --- /dev/null +++ b/client/deps/openjpeg/function_list.h @@ -0,0 +1,134 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_FUNCTION_LIST_H +#define OPJ_FUNCTION_LIST_H + +/** + * @file function_list.h + * @brief Implementation of a list of procedures. + + * The functions in validation.c aims to have access to a list of procedures. +*/ + +/** @defgroup VAL VAL - validation procedure*/ +/*@{*/ + +/************************************************************************************************** + ***************************************** FORWARD DECLARATION ************************************ + **************************************************************************************************/ + +/** + * declare a function pointer + */ +typedef void (*opj_procedure)(void); + +/** + * A list of procedures. +*/ +typedef struct opj_procedure_list { + /** + * The number of validation procedures. + */ + OPJ_UINT32 m_nb_procedures; + /** + * The number of the array of validation procedures. + */ + OPJ_UINT32 m_nb_max_procedures; + /** + * The array of procedures. + */ + opj_procedure * m_procedures; + +} opj_procedure_list_t; + +/* ----------------------------------------------------------------------- */ + +/** + * Creates a validation list. + * + * @return the newly created validation list. + */ +opj_procedure_list_t * opj_procedure_list_create(void); + +/** + * Destroys a validation list. + * + * @param p_list the list to destroy. + */ +void opj_procedure_list_destroy(opj_procedure_list_t * p_list); + +/** + * Adds a new validation procedure. + * + * @param p_validation_list the list of procedure to modify. + * @param p_procedure the procedure to add. + * @param p_manager the user event manager. + * + * @return OPJ_TRUE if the procedure could be added. + */ +OPJ_BOOL opj_procedure_list_add_procedure(opj_procedure_list_t * + p_validation_list, opj_procedure p_procedure, opj_event_mgr_t* p_manager); + +/** + * Gets the number of validation procedures. + * + * @param p_validation_list the list of procedure to modify. + * + * @return the number of validation procedures. + */ +OPJ_UINT32 opj_procedure_list_get_nb_procedures(opj_procedure_list_t * + p_validation_list); + +/** + * Gets the pointer on the first validation procedure. This function is similar to the C++ + * iterator class to iterate through all the procedures inside the validation list. + * the caller does not take ownership of the pointer. + * + * @param p_validation_list the list of procedure to get the first procedure from. + * + * @return a pointer to the first procedure. + */ +opj_procedure* opj_procedure_list_get_first_procedure(opj_procedure_list_t * + p_validation_list); + + +/** + * Clears the list of validation procedures. + * + * @param p_validation_list the list of procedure to clear. + * + */ +void opj_procedure_list_clear(opj_procedure_list_t * p_validation_list); +/*@}*/ + +#endif /* OPJ_FUNCTION_LIST_H */ + diff --git a/client/deps/openjpeg/ht_dec.c b/client/deps/openjpeg/ht_dec.c new file mode 100644 index 000000000..2984f5609 --- /dev/null +++ b/client/deps/openjpeg/ht_dec.c @@ -0,0 +1,2689 @@ +//***************************************************************************/ +// This software is released under the 2-Clause BSD license, included +// below. +// +// Copyright (c) 2021, Aous Naman +// Copyright (c) 2021, Kakadu Software Pty Ltd, Australia +// Copyright (c) 2021, The University of New South Wales, Australia +// +// 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. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT +// HOLDER 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. +//***************************************************************************/ +// This file is part of the OpenJpeg software implementation. +// File: ht_dec.c +// Author: Aous Naman +// Date: 01 September 2021 +//***************************************************************************/ + +//***************************************************************************/ +/** @file ht_dec.c + * @brief implements HTJ2K block decoder + */ + +#include +#include +#include "opj_includes.h" + +#include "t1_ht_luts.h" + +///////////////////////////////////////////////////////////////////////////// +// compiler detection +///////////////////////////////////////////////////////////////////////////// +#ifdef _MSC_VER +#define OPJ_COMPILER_MSVC +#elif (defined __GNUC__) +#define OPJ_COMPILER_GNUC +#endif + +#if defined(OPJ_COMPILER_MSVC) && defined(_M_ARM64) \ + && !defined(_M_ARM64EC) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \ + && !defined(__INTEL_COMPILER) && !defined(__clang__) +#define MSVC_NEON_INTRINSICS +#endif + +#ifdef MSVC_NEON_INTRINSICS +#include +#endif + +//************************************************************************/ +/** @brief Displays the error message for disabling the decoding of SPP and + * MRP passes + */ +static OPJ_BOOL only_cleanup_pass_is_decoded = OPJ_FALSE; + +//************************************************************************/ +/** @brief Generates population count (i.e., the number of set bits) + * + * @param [in] val is the value for which population count is sought + */ +static INLINE +OPJ_UINT32 population_count(OPJ_UINT32 val) +{ +#if defined(OPJ_COMPILER_MSVC) && (defined(_M_IX86) || defined(_M_AMD64)) + return (OPJ_UINT32)__popcnt(val); +#elif defined(OPJ_COMPILER_MSVC) && defined(MSVC_NEON_INTRINSICS) + const __n64 temp = neon_cnt(__uint64ToN64_v(val)); + return neon_addv8(temp).n8_i8[0]; +#elif (defined OPJ_COMPILER_GNUC) + return (OPJ_UINT32)__builtin_popcount(val); +#else + val -= ((val >> 1) & 0x55555555); + val = (((val >> 2) & 0x33333333) + (val & 0x33333333)); + val = (((val >> 4) + val) & 0x0f0f0f0f); + val += (val >> 8); + val += (val >> 16); + return (OPJ_UINT32)(val & 0x0000003f); +#endif +} + +//************************************************************************/ +/** @brief Counts the number of leading zeros + * + * @param [in] val is the value for which leading zero count is sought + */ +#ifdef OPJ_COMPILER_MSVC +#pragma intrinsic(_BitScanReverse) +#endif +static INLINE +OPJ_UINT32 count_leading_zeros(OPJ_UINT32 val) +{ +#ifdef OPJ_COMPILER_MSVC + unsigned long result = 0; + _BitScanReverse(&result, val); + return 31U ^ (OPJ_UINT32)result; +#elif (defined OPJ_COMPILER_GNUC) + return (OPJ_UINT32)__builtin_clz(val); +#else + val |= (val >> 1); + val |= (val >> 2); + val |= (val >> 4); + val |= (val >> 8); + val |= (val >> 16); + return 32U - population_count(val); +#endif +} + +//************************************************************************/ +/** @brief Read a little-endian serialized UINT32. + * + * @param [in] dataIn pointer to byte stream to read from + */ +static INLINE OPJ_UINT32 read_le_uint32(const void* dataIn) +{ +#if defined(OPJ_BIG_ENDIAN) + const OPJ_UINT8* data = (const OPJ_UINT8*)dataIn; + return ((OPJ_UINT32)data[0]) | (OPJ_UINT32)(data[1] << 8) | (OPJ_UINT32)( + data[2] << 16) | ((( + OPJ_UINT32)data[3]) << + 24U); +#else + return *(OPJ_UINT32*)dataIn; +#endif +} + +//************************************************************************/ +/** @brief MEL state structure for reading and decoding the MEL bitstream + * + * A number of events is decoded from the MEL bitstream ahead of time + * and stored in run/num_runs. + * Each run represents the number of zero events before a one event. + */ +typedef struct dec_mel { + // data decoding machinery + OPJ_UINT8* data; //!bits > 32) { //there are enough bits in the tmp variable + return; // return without reading new data + } + + val = 0xFFFFFFFF; // feed in 0xFF if buffer is exhausted + if (melp->size > 4) { // if there is more than 4 bytes the MEL segment + val = read_le_uint32(melp->data); // read 32 bits from MEL data + melp->data += 4; // advance pointer + melp->size -= 4; // reduce counter + } else if (melp->size > 0) { // 4 or less + OPJ_UINT32 m, v; + int i = 0; + while (melp->size > 1) { + OPJ_UINT32 v = *melp->data++; // read one byte at a time + OPJ_UINT32 m = ~(0xFFu << i); // mask of location + val = (val & m) | (v << i); // put byte in its correct location + --melp->size; + i += 8; + } + // size equal to 1 + v = *melp->data++; // the one before the last is different + v |= 0xF; // MEL and VLC segments can overlap + m = ~(0xFFu << i); + val = (val & m) | (v << i); + --melp->size; + } + + // next we unstuff them before adding them to the buffer + bits = 32 - melp->unstuff; // number of bits in val, subtract 1 if + // the previously read byte requires + // unstuffing + + // data is unstuffed and accumulated in t + // bits has the number of bits in t + t = val & 0xFF; + unstuff = ((val & 0xFF) == 0xFF); // true if the byte needs unstuffing + bits -= unstuff; // there is one less bit in t if unstuffing is needed + t = t << (8 - unstuff); // move up to make room for the next byte + + //this is a repeat of the above + t |= (val >> 8) & 0xFF; + unstuff = (((val >> 8) & 0xFF) == 0xFF); + bits -= unstuff; + t = t << (8 - unstuff); + + t |= (val >> 16) & 0xFF; + unstuff = (((val >> 16) & 0xFF) == 0xFF); + bits -= unstuff; + t = t << (8 - unstuff); + + t |= (val >> 24) & 0xFF; + melp->unstuff = (((val >> 24) & 0xFF) == 0xFF); + + // move t to tmp, and push the result all the way up, so we read from + // the MSB + melp->tmp |= ((OPJ_UINT64)t) << (64 - bits - melp->bits); + melp->bits += bits; //increment the number of bits in tmp +} + +//************************************************************************/ +/** @brief Decodes unstuffed MEL segment bits stored in tmp to runs + * + * Runs are stored in "runs" and the number of runs in "num_runs". + * Each run represents a number of zero events that may or may not + * terminate in a 1 event. + * Each run is stored in 7 bits. The LSB is 1 if the run terminates in + * a 1 event, 0 otherwise. The next 6 bits, for the case terminating + * with 1, contain the number of consecutive 0 zero events * 2; for the + * case terminating with 0, they store (number of consecutive 0 zero + * events - 1) * 2. + * A total of 6 bits (made up of 1 + 5) should have been enough. + * + * @param [in] melp is a pointer to dec_mel_t structure + */ +static INLINE +void mel_decode(dec_mel_t *melp) +{ + static const int mel_exp[13] = { //MEL exponents + 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5 + }; + + if (melp->bits < 6) { // if there are less than 6 bits in tmp + mel_read(melp); // then read from the MEL bitstream + } + // 6 bits is the largest decodable MEL cwd + + //repeat so long that there is enough decodable bits in tmp, + // and the runs store is not full (num_runs < 8) + while (melp->bits >= 6 && melp->num_runs < 8) { + int eval = mel_exp[melp->k]; // number of bits associated with state + int run = 0; + if (melp->tmp & (1ull << 63)) { //The next bit to decode (stored in MSB) + //one is found + run = 1 << eval; + run--; // consecutive runs of 0 events - 1 + melp->k = melp->k + 1 < 12 ? melp->k + 1 : 12;//increment, max is 12 + melp->tmp <<= 1; // consume one bit from tmp + melp->bits -= 1; + run = run << 1; // a stretch of zeros not terminating in one + } else { + //0 is found + run = (int)(melp->tmp >> (63 - eval)) & ((1 << eval) - 1); + melp->k = melp->k - 1 > 0 ? melp->k - 1 : 0; //decrement, min is 0 + melp->tmp <<= eval + 1; //consume eval + 1 bits (max is 6) + melp->bits -= eval + 1; + run = (run << 1) + 1; // a stretch of zeros terminating with one + } + eval = melp->num_runs * 7; // 7 bits per run + melp->runs &= ~((OPJ_UINT64)0x3F << eval); // 6 bits are sufficient + melp->runs |= ((OPJ_UINT64)run) << eval; // store the value in runs + melp->num_runs++; // increment count + } +} + +//************************************************************************/ +/** @brief Initiates a dec_mel_t structure for MEL decoding and reads + * some bytes in order to get the read address to a multiple + * of 4 + * + * @param [in] melp is a pointer to dec_mel_t structure + * @param [in] bbuf is a pointer to byte buffer + * @param [in] lcup is the length of MagSgn+MEL+VLC segments + * @param [in] scup is the length of MEL+VLC segments + */ +static INLINE +OPJ_BOOL mel_init(dec_mel_t *melp, OPJ_UINT8* bbuf, int lcup, int scup) +{ + int num; + int i; + + melp->data = bbuf + lcup - scup; // move the pointer to the start of MEL + melp->bits = 0; // 0 bits in tmp + melp->tmp = 0; // + melp->unstuff = OPJ_FALSE; // no unstuffing + melp->size = scup - 1; // size is the length of MEL+VLC-1 + melp->k = 0; // 0 for state + melp->num_runs = 0; // num_runs is 0 + melp->runs = 0; // + + //This code is borrowed; original is for a different architecture + //These few lines take care of the case where data is not at a multiple + // of 4 boundary. It reads 1,2,3 up to 4 bytes from the MEL segment + num = 4 - (int)((intptr_t)(melp->data) & 0x3); + for (i = 0; i < num; ++i) { // this code is similar to mel_read + OPJ_UINT64 d; + int d_bits; + + if (melp->unstuff == OPJ_TRUE && melp->data[0] > 0x8F) { + return OPJ_FALSE; + } + d = (melp->size > 0) ? *melp->data : 0xFF; // if buffer is consumed + // set data to 0xFF + if (melp->size == 1) { + d |= 0xF; //if this is MEL+VLC-1, set LSBs to 0xF + } + // see the standard + melp->data += melp->size-- > 0; //increment if the end is not reached + d_bits = 8 - melp->unstuff; //if unstuffing is needed, reduce by 1 + melp->tmp = (melp->tmp << d_bits) | d; //store bits in tmp + melp->bits += d_bits; //increment tmp by number of bits + melp->unstuff = ((d & 0xFF) == 0xFF); //true of next byte needs + //unstuffing + } + melp->tmp <<= (64 - melp->bits); //push all the way up so the first bit + // is the MSB + return OPJ_TRUE; +} + +//************************************************************************/ +/** @brief Retrieves one run from dec_mel_t; if there are no runs stored + * MEL segment is decoded + * + * @param [in] melp is a pointer to dec_mel_t structure + */ +static INLINE +int mel_get_run(dec_mel_t *melp) +{ + int t; + if (melp->num_runs == 0) { //if no runs, decode more bit from MEL segment + mel_decode(melp); + } + + t = melp->runs & 0x7F; //retrieve one run + melp->runs >>= 7; // remove the retrieved run + melp->num_runs--; + return t; // return run +} + +//************************************************************************/ +/** @brief A structure for reading and unstuffing a segment that grows + * backward, such as VLC and MRP + */ +typedef struct rev_struct { + //storage + OPJ_UINT8* data; //!bits > 32) { // if there are more than 32 bits in tmp, then + return; // reading 32 bits can overflow vlcp->tmp + } + val = 0; + //the next line (the if statement) needs to be tested first + if (vlcp->size > 3) { // if there are more than 3 bytes left in VLC + // (vlcp->data - 3) move pointer back to read 32 bits at once + val = read_le_uint32(vlcp->data - 3); // then read 32 bits + vlcp->data -= 4; // move data pointer back by 4 + vlcp->size -= 4; // reduce available byte by 4 + } else if (vlcp->size > 0) { // 4 or less + int i = 24; + while (vlcp->size > 0) { + OPJ_UINT32 v = *vlcp->data--; // read one byte at a time + val |= (v << i); // put byte in its correct location + --vlcp->size; + i -= 8; + } + } + + //accumulate in tmp, number of bits in tmp are stored in bits + tmp = val >> 24; //start with the MSB byte + + // test unstuff (previous byte is >0x8F), and this byte is 0x7F + bits = 8u - ((vlcp->unstuff && (((val >> 24) & 0x7F) == 0x7F)) ? 1u : 0u); + unstuff = (val >> 24) > 0x8F; //this is for the next byte + + tmp |= ((val >> 16) & 0xFF) << bits; //process the next byte + bits += 8u - ((unstuff && (((val >> 16) & 0x7F) == 0x7F)) ? 1u : 0u); + unstuff = ((val >> 16) & 0xFF) > 0x8F; + + tmp |= ((val >> 8) & 0xFF) << bits; + bits += 8u - ((unstuff && (((val >> 8) & 0x7F) == 0x7F)) ? 1u : 0u); + unstuff = ((val >> 8) & 0xFF) > 0x8F; + + tmp |= (val & 0xFF) << bits; + bits += 8u - ((unstuff && ((val & 0x7F) == 0x7F)) ? 1u : 0u); + unstuff = (val & 0xFF) > 0x8F; + + // now move the read and unstuffed bits into vlcp->tmp + vlcp->tmp |= (OPJ_UINT64)tmp << vlcp->bits; + vlcp->bits += bits; + vlcp->unstuff = unstuff; // this for the next read +} + +//************************************************************************/ +/** @brief Initiates the rev_struct_t structure and reads a few bytes to + * move the read address to multiple of 4 + * + * There is another similar rev_init_mrp subroutine. The difference is + * that this one, rev_init, discards the first 12 bits (they have the + * sum of the lengths of VLC and MEL segments), and first unstuff depends + * on first 4 bits. + * + * @param [in] vlcp is a pointer to rev_struct_t structure + * @param [in] data is a pointer to byte at the start of the cleanup pass + * @param [in] lcup is the length of MagSgn+MEL+VLC segments + * @param [in] scup is the length of MEL+VLC segments + */ +static INLINE +void rev_init(rev_struct_t *vlcp, OPJ_UINT8* data, int lcup, int scup) +{ + OPJ_UINT32 d; + int num, tnum, i; + + //first byte has only the upper 4 bits + vlcp->data = data + lcup - 2; + + //size can not be larger than this, in fact it should be smaller + vlcp->size = scup - 2; + + d = *vlcp->data--; // read one byte (this is a half byte) + vlcp->tmp = d >> 4; // both initialize and set + vlcp->bits = 4 - ((vlcp->tmp & 7) == 7); //check standard + vlcp->unstuff = (d | 0xF) > 0x8F; //this is useful for the next byte + + //This code is designed for an architecture that read address should + // align to the read size (address multiple of 4 if read size is 4) + //These few lines take care of the case where data is not at a multiple + // of 4 boundary. It reads 1,2,3 up to 4 bytes from the VLC bitstream. + // To read 32 bits, read from (vlcp->data - 3) + num = 1 + (int)((intptr_t)(vlcp->data) & 0x3); + tnum = num < vlcp->size ? num : vlcp->size; + for (i = 0; i < tnum; ++i) { + OPJ_UINT64 d; + OPJ_UINT32 d_bits; + d = *vlcp->data--; // read one byte and move read pointer + //check if the last byte was >0x8F (unstuff == true) and this is 0x7F + d_bits = 8u - ((vlcp->unstuff && ((d & 0x7F) == 0x7F)) ? 1u : 0u); + vlcp->tmp |= d << vlcp->bits; // move data to vlcp->tmp + vlcp->bits += d_bits; + vlcp->unstuff = d > 0x8F; // for next byte + } + vlcp->size -= tnum; + rev_read(vlcp); // read another 32 buts +} + +//************************************************************************/ +/** @brief Retrieves 32 bits from the head of a rev_struct structure + * + * By the end of this call, vlcp->tmp must have no less than 33 bits + * + * @param [in] vlcp is a pointer to rev_struct structure + */ +static INLINE +OPJ_UINT32 rev_fetch(rev_struct_t *vlcp) +{ + if (vlcp->bits < 32) { // if there are less then 32 bits, read more + rev_read(vlcp); // read 32 bits, but unstuffing might reduce this + if (vlcp->bits < 32) { // if there is still space in vlcp->tmp for 32 bits + rev_read(vlcp); // read another 32 + } + } + return (OPJ_UINT32)vlcp->tmp; // return the head (bottom-most) of vlcp->tmp +} + +//************************************************************************/ +/** @brief Consumes num_bits from a rev_struct structure + * + * @param [in] vlcp is a pointer to rev_struct structure + * @param [in] num_bits is the number of bits to be removed + */ +static INLINE +OPJ_UINT32 rev_advance(rev_struct_t *vlcp, OPJ_UINT32 num_bits) +{ + assert(num_bits <= vlcp->bits); // vlcp->tmp must have more than num_bits + vlcp->tmp >>= num_bits; // remove bits + vlcp->bits -= num_bits; // decrement the number of bits + return (OPJ_UINT32)vlcp->tmp; +} + +//************************************************************************/ +/** @brief Reads and unstuffs from rev_struct + * + * This is different than rev_read in that this fills in zeros when the + * the available data is consumed. The other does not care about the + * values when all data is consumed. + * + * See rev_read for more information about unstuffing + * + * @param [in] mrp is a pointer to rev_struct structure + */ +static INLINE +void rev_read_mrp(rev_struct_t *mrp) +{ + OPJ_UINT32 val; + OPJ_UINT32 tmp; + OPJ_UINT32 bits; + OPJ_BOOL unstuff; + + //process 4 bytes at a time + if (mrp->bits > 32) { + return; + } + val = 0; + if (mrp->size > 3) { // If there are 3 byte or more + // (mrp->data - 3) move pointer back to read 32 bits at once + val = read_le_uint32(mrp->data - 3); // read 32 bits + mrp->data -= 4; // move back pointer + mrp->size -= 4; // reduce count + } else if (mrp->size > 0) { + int i = 24; + while (mrp->size > 0) { + OPJ_UINT32 v = *mrp->data--; // read one byte at a time + val |= (v << i); // put byte in its correct location + --mrp->size; + i -= 8; + } + } + + + //accumulate in tmp, and keep count in bits + tmp = val >> 24; + + //test if the last byte > 0x8F (unstuff must be true) and this is 0x7F + bits = 8u - ((mrp->unstuff && (((val >> 24) & 0x7F) == 0x7F)) ? 1u : 0u); + unstuff = (val >> 24) > 0x8F; + + //process the next byte + tmp |= ((val >> 16) & 0xFF) << bits; + bits += 8u - ((unstuff && (((val >> 16) & 0x7F) == 0x7F)) ? 1u : 0u); + unstuff = ((val >> 16) & 0xFF) > 0x8F; + + tmp |= ((val >> 8) & 0xFF) << bits; + bits += 8u - ((unstuff && (((val >> 8) & 0x7F) == 0x7F)) ? 1u : 0u); + unstuff = ((val >> 8) & 0xFF) > 0x8F; + + tmp |= (val & 0xFF) << bits; + bits += 8u - ((unstuff && ((val & 0x7F) == 0x7F)) ? 1u : 0u); + unstuff = (val & 0xFF) > 0x8F; + + mrp->tmp |= (OPJ_UINT64)tmp << mrp->bits; // move data to mrp pointer + mrp->bits += bits; + mrp->unstuff = unstuff; // next byte +} + +//************************************************************************/ +/** @brief Initialized rev_struct structure for MRP segment, and reads + * a number of bytes such that the next 32 bits read are from + * an address that is a multiple of 4. Note this is designed for + * an architecture that read size must be compatible with the + * alignment of the read address + * + * There is another similar subroutine rev_init. This subroutine does + * NOT skip the first 12 bits, and starts with unstuff set to true. + * + * @param [in] mrp is a pointer to rev_struct structure + * @param [in] data is a pointer to byte at the start of the cleanup pass + * @param [in] lcup is the length of MagSgn+MEL+VLC segments + * @param [in] len2 is the length of SPP+MRP segments + */ +static INLINE +void rev_init_mrp(rev_struct_t *mrp, OPJ_UINT8* data, int lcup, int len2) +{ + int num, i; + + mrp->data = data + lcup + len2 - 1; + mrp->size = len2; + mrp->unstuff = OPJ_TRUE; + mrp->bits = 0; + mrp->tmp = 0; + + //This code is designed for an architecture that read address should + // align to the read size (address multiple of 4 if read size is 4) + //These few lines take care of the case where data is not at a multiple + // of 4 boundary. It reads 1,2,3 up to 4 bytes from the MRP stream + num = 1 + (int)((intptr_t)(mrp->data) & 0x3); + for (i = 0; i < num; ++i) { + OPJ_UINT64 d; + OPJ_UINT32 d_bits; + + //read a byte, 0 if no more data + d = (mrp->size-- > 0) ? *mrp->data-- : 0; + //check if unstuffing is needed + d_bits = 8u - ((mrp->unstuff && ((d & 0x7F) == 0x7F)) ? 1u : 0u); + mrp->tmp |= d << mrp->bits; // move data to vlcp->tmp + mrp->bits += d_bits; + mrp->unstuff = d > 0x8F; // for next byte + } + rev_read_mrp(mrp); +} + +//************************************************************************/ +/** @brief Retrieves 32 bits from the head of a rev_struct structure + * + * By the end of this call, mrp->tmp must have no less than 33 bits + * + * @param [in] mrp is a pointer to rev_struct structure + */ +static INLINE +OPJ_UINT32 rev_fetch_mrp(rev_struct_t *mrp) +{ + if (mrp->bits < 32) { // if there are less than 32 bits in mrp->tmp + rev_read_mrp(mrp); // read 30-32 bits from mrp + if (mrp->bits < 32) { // if there is a space of 32 bits + rev_read_mrp(mrp); // read more + } + } + return (OPJ_UINT32)mrp->tmp; // return the head of mrp->tmp +} + +//************************************************************************/ +/** @brief Consumes num_bits from a rev_struct structure + * + * @param [in] mrp is a pointer to rev_struct structure + * @param [in] num_bits is the number of bits to be removed + */ +static INLINE +OPJ_UINT32 rev_advance_mrp(rev_struct_t *mrp, OPJ_UINT32 num_bits) +{ + assert(num_bits <= mrp->bits); // we must not consume more than mrp->bits + mrp->tmp >>= num_bits; // discard the lowest num_bits bits + mrp->bits -= num_bits; + return (OPJ_UINT32)mrp->tmp; // return data after consumption +} + +//************************************************************************/ +/** @brief Decode initial UVLC to get the u value (or u_q) + * + * @param [in] vlc is the head of the VLC bitstream + * @param [in] mode is 0, 1, 2, 3, or 4. Values in 0 to 3 are composed of + * u_off of 1st quad and 2nd quad of a quad pair. The value + * 4 occurs when both bits are 1, and the event decoded + * from MEL bitstream is also 1. + * @param [out] u is the u value (or u_q) + 1. Note: we produce u + 1; + * this value is a partial calculation of u + kappa. + */ +static INLINE +OPJ_UINT32 decode_init_uvlc(OPJ_UINT32 vlc, OPJ_UINT32 mode, OPJ_UINT32 *u) +{ + //table stores possible decoding three bits from vlc + // there are 8 entries for xx1, x10, 100, 000, where x means do not care + // table value is made up of + // 2 bits in the LSB for prefix length + // 3 bits for suffix length + // 3 bits in the MSB for prefix value (u_pfx in Table 3 of ITU T.814) + static const OPJ_UINT8 dec[8] = { // the index is the prefix codeword + 3 | (5 << 2) | (5 << 5), //000 == 000, prefix codeword "000" + 1 | (0 << 2) | (1 << 5), //001 == xx1, prefix codeword "1" + 2 | (0 << 2) | (2 << 5), //010 == x10, prefix codeword "01" + 1 | (0 << 2) | (1 << 5), //011 == xx1, prefix codeword "1" + 3 | (1 << 2) | (3 << 5), //100 == 100, prefix codeword "001" + 1 | (0 << 2) | (1 << 5), //101 == xx1, prefix codeword "1" + 2 | (0 << 2) | (2 << 5), //110 == x10, prefix codeword "01" + 1 | (0 << 2) | (1 << 5) //111 == xx1, prefix codeword "1" + }; + + OPJ_UINT32 consumed_bits = 0; + if (mode == 0) { // both u_off are 0 + u[0] = u[1] = 1; //Kappa is 1 for initial line + } else if (mode <= 2) { // u_off are either 01 or 10 + OPJ_UINT32 d; + OPJ_UINT32 suffix_len; + + d = dec[vlc & 0x7]; //look at the least significant 3 bits + vlc >>= d & 0x3; //prefix length + consumed_bits += d & 0x3; + + suffix_len = ((d >> 2) & 0x7); + consumed_bits += suffix_len; + + d = (d >> 5) + (vlc & ((1U << suffix_len) - 1)); // u value + u[0] = (mode == 1) ? d + 1 : 1; // kappa is 1 for initial line + u[1] = (mode == 1) ? 1 : d + 1; // kappa is 1 for initial line + } else if (mode == 3) { // both u_off are 1, and MEL event is 0 + OPJ_UINT32 d1 = dec[vlc & 0x7]; // LSBs of VLC are prefix codeword + vlc >>= d1 & 0x3; // Consume bits + consumed_bits += d1 & 0x3; + + if ((d1 & 0x3) > 2) { + OPJ_UINT32 suffix_len; + + //u_{q_2} prefix + u[1] = (vlc & 1) + 1 + 1; //Kappa is 1 for initial line + ++consumed_bits; + vlc >>= 1; + + suffix_len = ((d1 >> 2) & 0x7); + consumed_bits += suffix_len; + d1 = (d1 >> 5) + (vlc & ((1U << suffix_len) - 1)); // u value + u[0] = d1 + 1; //Kappa is 1 for initial line + } else { + OPJ_UINT32 d2; + OPJ_UINT32 suffix_len; + + d2 = dec[vlc & 0x7]; // LSBs of VLC are prefix codeword + vlc >>= d2 & 0x3; // Consume bits + consumed_bits += d2 & 0x3; + + suffix_len = ((d1 >> 2) & 0x7); + consumed_bits += suffix_len; + + d1 = (d1 >> 5) + (vlc & ((1U << suffix_len) - 1)); // u value + u[0] = d1 + 1; //Kappa is 1 for initial line + vlc >>= suffix_len; + + suffix_len = ((d2 >> 2) & 0x7); + consumed_bits += suffix_len; + + d2 = (d2 >> 5) + (vlc & ((1U << suffix_len) - 1)); // u value + u[1] = d2 + 1; //Kappa is 1 for initial line + } + } else if (mode == 4) { // both u_off are 1, and MEL event is 1 + OPJ_UINT32 d1; + OPJ_UINT32 d2; + OPJ_UINT32 suffix_len; + + d1 = dec[vlc & 0x7]; // LSBs of VLC are prefix codeword + vlc >>= d1 & 0x3; // Consume bits + consumed_bits += d1 & 0x3; + + d2 = dec[vlc & 0x7]; // LSBs of VLC are prefix codeword + vlc >>= d2 & 0x3; // Consume bits + consumed_bits += d2 & 0x3; + + suffix_len = ((d1 >> 2) & 0x7); + consumed_bits += suffix_len; + + d1 = (d1 >> 5) + (vlc & ((1U << suffix_len) - 1)); // u value + u[0] = d1 + 3; // add 2+kappa + vlc >>= suffix_len; + + suffix_len = ((d2 >> 2) & 0x7); + consumed_bits += suffix_len; + + d2 = (d2 >> 5) + (vlc & ((1U << suffix_len) - 1)); // u value + u[1] = d2 + 3; // add 2+kappa + } + return consumed_bits; +} + +//************************************************************************/ +/** @brief Decode non-initial UVLC to get the u value (or u_q) + * + * @param [in] vlc is the head of the VLC bitstream + * @param [in] mode is 0, 1, 2, or 3. The 1st bit is u_off of 1st quad + * and 2nd for 2nd quad of a quad pair + * @param [out] u is the u value (or u_q) + 1. Note: we produce u + 1; + * this value is a partial calculation of u + kappa. + */ +static INLINE +OPJ_UINT32 decode_noninit_uvlc(OPJ_UINT32 vlc, OPJ_UINT32 mode, OPJ_UINT32 *u) +{ + //table stores possible decoding three bits from vlc + // there are 8 entries for xx1, x10, 100, 000, where x means do not care + // table value is made up of + // 2 bits in the LSB for prefix length + // 3 bits for suffix length + // 3 bits in the MSB for prefix value (u_pfx in Table 3 of ITU T.814) + static const OPJ_UINT8 dec[8] = { + 3 | (5 << 2) | (5 << 5), //000 == 000, prefix codeword "000" + 1 | (0 << 2) | (1 << 5), //001 == xx1, prefix codeword "1" + 2 | (0 << 2) | (2 << 5), //010 == x10, prefix codeword "01" + 1 | (0 << 2) | (1 << 5), //011 == xx1, prefix codeword "1" + 3 | (1 << 2) | (3 << 5), //100 == 100, prefix codeword "001" + 1 | (0 << 2) | (1 << 5), //101 == xx1, prefix codeword "1" + 2 | (0 << 2) | (2 << 5), //110 == x10, prefix codeword "01" + 1 | (0 << 2) | (1 << 5) //111 == xx1, prefix codeword "1" + }; + + OPJ_UINT32 consumed_bits = 0; + if (mode == 0) { + u[0] = u[1] = 1; //for kappa + } else if (mode <= 2) { //u_off are either 01 or 10 + OPJ_UINT32 d; + OPJ_UINT32 suffix_len; + + d = dec[vlc & 0x7]; //look at the least significant 3 bits + vlc >>= d & 0x3; //prefix length + consumed_bits += d & 0x3; + + suffix_len = ((d >> 2) & 0x7); + consumed_bits += suffix_len; + + d = (d >> 5) + (vlc & ((1U << suffix_len) - 1)); // u value + u[0] = (mode == 1) ? d + 1 : 1; //for kappa + u[1] = (mode == 1) ? 1 : d + 1; //for kappa + } else if (mode == 3) { // both u_off are 1 + OPJ_UINT32 d1; + OPJ_UINT32 d2; + OPJ_UINT32 suffix_len; + + d1 = dec[vlc & 0x7]; // LSBs of VLC are prefix codeword + vlc >>= d1 & 0x3; // Consume bits + consumed_bits += d1 & 0x3; + + d2 = dec[vlc & 0x7]; // LSBs of VLC are prefix codeword + vlc >>= d2 & 0x3; // Consume bits + consumed_bits += d2 & 0x3; + + suffix_len = ((d1 >> 2) & 0x7); + consumed_bits += suffix_len; + + d1 = (d1 >> 5) + (vlc & ((1U << suffix_len) - 1)); // u value + u[0] = d1 + 1; //1 for kappa + vlc >>= suffix_len; + + suffix_len = ((d2 >> 2) & 0x7); + consumed_bits += suffix_len; + + d2 = (d2 >> 5) + (vlc & ((1U << suffix_len) - 1)); // u value + u[1] = d2 + 1; //1 for kappa + } + return consumed_bits; +} + +//************************************************************************/ +/** @brief State structure for reading and unstuffing of forward-growing + * bitstreams; these are: MagSgn and SPP bitstreams + */ +typedef struct frwd_struct { + const OPJ_UINT8* data; //!bits <= 32); // assert that there is a space for 32 bits + + val = 0u; + if (msp->size > 3) { + val = read_le_uint32(msp->data); // read 32 bits + msp->data += 4; // increment pointer + msp->size -= 4; // reduce size + } else if (msp->size > 0) { + int i = 0; + val = msp->X != 0 ? 0xFFFFFFFFu : 0; + while (msp->size > 0) { + OPJ_UINT32 v = *msp->data++; // read one byte at a time + OPJ_UINT32 m = ~(0xFFu << i); // mask of location + val = (val & m) | (v << i); // put one byte in its correct location + --msp->size; + i += 8; + } + } else { + val = msp->X != 0 ? 0xFFFFFFFFu : 0; + } + + // we accumulate in t and keep a count of the number of bits in bits + bits = 8u - (msp->unstuff ? 1u : 0u); + t = val & 0xFF; + unstuff = ((val & 0xFF) == 0xFF); // Do we need unstuffing next? + + t |= ((val >> 8) & 0xFF) << bits; + bits += 8u - (unstuff ? 1u : 0u); + unstuff = (((val >> 8) & 0xFF) == 0xFF); + + t |= ((val >> 16) & 0xFF) << bits; + bits += 8u - (unstuff ? 1u : 0u); + unstuff = (((val >> 16) & 0xFF) == 0xFF); + + t |= ((val >> 24) & 0xFF) << bits; + bits += 8u - (unstuff ? 1u : 0u); + msp->unstuff = (((val >> 24) & 0xFF) == 0xFF); // for next byte + + msp->tmp |= ((OPJ_UINT64)t) << msp->bits; // move data to msp->tmp + msp->bits += bits; +} + +//************************************************************************/ +/** @brief Initialize frwd_struct_t struct and reads some bytes + * + * @param [in] msp is a pointer to frwd_struct_t + * @param [in] data is a pointer to the start of data + * @param [in] size is the number of byte in the bitstream + * @param [in] X is the value fed in when the bitstream is exhausted. + * See frwd_read. + */ +static INLINE +void frwd_init(frwd_struct_t *msp, const OPJ_UINT8* data, int size, + OPJ_UINT32 X) +{ + int num, i; + + msp->data = data; + msp->tmp = 0; + msp->bits = 0; + msp->unstuff = OPJ_FALSE; + msp->size = size; + msp->X = X; + assert(msp->X == 0 || msp->X == 0xFF); + + //This code is designed for an architecture that read address should + // align to the read size (address multiple of 4 if read size is 4) + //These few lines take care of the case where data is not at a multiple + // of 4 boundary. It reads 1,2,3 up to 4 bytes from the bitstream + num = 4 - (int)((intptr_t)(msp->data) & 0x3); + for (i = 0; i < num; ++i) { + OPJ_UINT64 d; + //read a byte if the buffer is not exhausted, otherwise set it to X + d = msp->size-- > 0 ? *msp->data++ : msp->X; + msp->tmp |= (d << msp->bits); // store data in msp->tmp + msp->bits += 8u - (msp->unstuff ? 1u : 0u); // number of bits added to msp->tmp + msp->unstuff = ((d & 0xFF) == 0xFF); // unstuffing for next byte + } + frwd_read(msp); // read 32 bits more +} + +//************************************************************************/ +/** @brief Consume num_bits bits from the bitstream of frwd_struct_t + * + * @param [in] msp is a pointer to frwd_struct_t + * @param [in] num_bits is the number of bit to consume + */ +static INLINE +void frwd_advance(frwd_struct_t *msp, OPJ_UINT32 num_bits) +{ + assert(num_bits <= msp->bits); + msp->tmp >>= num_bits; // consume num_bits + msp->bits -= num_bits; +} + +//************************************************************************/ +/** @brief Fetches 32 bits from the frwd_struct_t bitstream + * + * @param [in] msp is a pointer to frwd_struct_t + */ +static INLINE +OPJ_UINT32 frwd_fetch(frwd_struct_t *msp) +{ + if (msp->bits < 32) { + frwd_read(msp); + if (msp->bits < 32) { //need to test + frwd_read(msp); + } + } + return (OPJ_UINT32)msp->tmp; +} + +//************************************************************************/ +/** @brief Allocates T1 buffers + * + * @param [in, out] t1 is codeblock coefficients storage + * @param [in] w is codeblock width + * @param [in] h is codeblock height + */ +static OPJ_BOOL opj_t1_allocate_buffers( + opj_t1_t *t1, + OPJ_UINT32 w, + OPJ_UINT32 h) +{ + OPJ_UINT32 flagssize; + + /* No risk of overflow. Prior checks ensure those assert are met */ + /* They are per the specification */ + assert(w <= 1024); + assert(h <= 1024); + assert(w * h <= 4096); + + /* encoder uses tile buffer, so no need to allocate */ + { + OPJ_UINT32 datasize = w * h; + + if (datasize > t1->datasize) { + opj_aligned_free(t1->data); + t1->data = (OPJ_INT32*) + opj_aligned_malloc(datasize * sizeof(OPJ_INT32)); + if (!t1->data) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + t1->datasize = datasize; + } + /* memset first arg is declared to never be null by gcc */ + if (t1->data != NULL) { + memset(t1->data, 0, datasize * sizeof(OPJ_INT32)); + } + } + + // We expand these buffers to multiples of 16 bytes. + // We need 4 buffers of 129 integers each, expanded to 132 integers each + // We also need 514 bytes of buffer, expanded to 528 bytes + flagssize = 132U * sizeof(OPJ_UINT32) * 4U; // expanded to multiple of 16 + flagssize += 528U; // 514 expanded to multiples of 16 + + { + if (flagssize > t1->flagssize) { + + opj_aligned_free(t1->flags); + t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize * sizeof(opj_flag_t)); + if (!t1->flags) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + } + t1->flagssize = flagssize; + + memset(t1->flags, 0, flagssize * sizeof(opj_flag_t)); + } + + t1->w = w; + t1->h = h; + + return OPJ_TRUE; +} + +/** +Decode 1 HT code-block +@param t1 T1 handle +@param cblk Code-block coding parameters +@param orient +@param roishift Region of interest shifting value +@param cblksty Code-block style +@param p_manager the event manager +@param p_manager_mutex mutex for the event manager +@param check_pterm whether PTERM correct termination should be checked +*/ +OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm); + +//************************************************************************/ +/** @brief Decodes one codeblock, processing the cleanup, siginificance + * propagation, and magnitude refinement pass + * + * @param [in, out] t1 is codeblock coefficients storage + * @param [in] cblk is codeblock properties + * @param [in] orient is the subband to which the codeblock belongs (not needed) + * @param [in] roishift is region of interest shift + * @param [in] cblksty is codeblock style + * @param [in] p_manager is events print manager + * @param [in] p_manager_mutex a mutex to control access to p_manager + * @param [in] check_pterm: check termination (not used) + */ +OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm) +{ + OPJ_BYTE* cblkdata = NULL; + OPJ_UINT8* coded_data; + OPJ_UINT32* decoded_data; + OPJ_UINT32 zero_bplanes; + OPJ_UINT32 num_passes; + OPJ_UINT32 lengths1; + OPJ_UINT32 lengths2; + OPJ_INT32 width; + OPJ_INT32 height; + OPJ_INT32 stride; + OPJ_UINT32 *pflags, *sigma1, *sigma2, *mbr1, *mbr2, *sip, sip_shift; + OPJ_UINT32 p; + OPJ_UINT32 zero_bplanes_p1; + int lcup, scup; + dec_mel_t mel; + rev_struct_t vlc; + frwd_struct_t magsgn; + frwd_struct_t sigprop; + rev_struct_t magref; + OPJ_UINT8 *lsp, *line_state; + int run; + OPJ_UINT32 vlc_val; // fetched data from VLC bitstream + OPJ_UINT32 qinf[2]; + OPJ_UINT32 c_q; + OPJ_UINT32* sp; + OPJ_INT32 x, y; // loop indices + OPJ_BOOL stripe_causal = (cblksty & J2K_CCP_CBLKSTY_VSC) != 0; + OPJ_UINT32 cblk_len = 0; + + (void)(orient); // stops unused parameter message + (void)(check_pterm); // stops unused parameter message + + // We ignor orient, because the same decoder is used for all subbands + // We also ignore check_pterm, because I am not sure how it applies + if (roishift != 0) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "We do not support ROI in decoding " + "HT codeblocks\n"); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + + if (!opj_t1_allocate_buffers( + t1, + (OPJ_UINT32)(cblk->x1 - cblk->x0), + (OPJ_UINT32)(cblk->y1 - cblk->y0))) { + return OPJ_FALSE; + } + + if (cblk->Mb == 0) { + return OPJ_TRUE; + } + + /* numbps = Mb + 1 - zero_bplanes, Mb = Kmax, zero_bplanes = missing_msbs */ + zero_bplanes = (cblk->Mb + 1) - cblk->numbps; + + /* Compute whole codeblock length from chunk lengths */ + cblk_len = 0; + { + OPJ_UINT32 i; + for (i = 0; i < cblk->numchunks; i++) { + cblk_len += cblk->chunks[i].len; + } + } + + if (cblk->numchunks > 1 || t1->mustuse_cblkdatabuffer) { + OPJ_UINT32 i; + + /* Allocate temporary memory if needed */ + if (cblk_len > t1->cblkdatabuffersize) { + cblkdata = (OPJ_BYTE*)opj_realloc( + t1->cblkdatabuffer, cblk_len); + if (cblkdata == NULL) { + return OPJ_FALSE; + } + t1->cblkdatabuffer = cblkdata; + t1->cblkdatabuffersize = cblk_len; + } + + /* Concatenate all chunks */ + cblkdata = t1->cblkdatabuffer; + if (cblkdata == NULL) { + return OPJ_FALSE; + } + cblk_len = 0; + for (i = 0; i < cblk->numchunks; i++) { + memcpy(cblkdata + cblk_len, cblk->chunks[i].data, cblk->chunks[i].len); + cblk_len += cblk->chunks[i].len; + } + } else if (cblk->numchunks == 1) { + cblkdata = cblk->chunks[0].data; + } else { + /* Not sure if that can happen in practice, but avoid Coverity to */ + /* think we will dereference a null cblkdta pointer */ + return OPJ_TRUE; + } + + // OPJ_BYTE* coded_data is a pointer to bitstream + coded_data = cblkdata; + // OPJ_UINT32* decoded_data is a pointer to decoded codeblock data buf. + decoded_data = (OPJ_UINT32*)t1->data; + // OPJ_UINT32 num_passes is the number of passes: 1 if CUP only, 2 for + // CUP+SPP, and 3 for CUP+SPP+MRP + num_passes = cblk->numsegs > 0 ? cblk->segs[0].real_num_passes : 0; + num_passes += cblk->numsegs > 1 ? cblk->segs[1].real_num_passes : 0; + // OPJ_UINT32 lengths1 is the length of cleanup pass + lengths1 = num_passes > 0 ? cblk->segs[0].len : 0; + // OPJ_UINT32 lengths2 is the length of refinement passes (either SPP only or SPP+MRP) + lengths2 = num_passes > 1 ? cblk->segs[1].len : 0; + // OPJ_INT32 width is the decoded codeblock width + width = cblk->x1 - cblk->x0; + // OPJ_INT32 height is the decoded codeblock height + height = cblk->y1 - cblk->y0; + // OPJ_INT32 stride is the decoded codeblock buffer stride + stride = width; + + /* sigma1 and sigma2 contains significant (i.e., non-zero) pixel + * locations. The buffers are used interchangeably, because we need + * more than 4 rows of significance information at a given time. + * Each 32 bits contain significance information for 4 rows of 8 + * columns each. If we denote 32 bits by 0xaaaaaaaa, the each "a" is + * called a nibble and has significance information for 4 rows. + * The least significant nibble has information for the first column, + * and so on. The nibble's LSB is for the first row, and so on. + * Since, at most, we can have 1024 columns in a quad, we need 128 + * entries; we added 1 for convenience when propagation of signifcance + * goes outside the structure + * To work in OpenJPEG these buffers has been expanded to 132. + */ + // OPJ_UINT32 *pflags, *sigma1, *sigma2, *mbr1, *mbr2, *sip, sip_shift; + pflags = (OPJ_UINT32 *)t1->flags; + sigma1 = pflags; + sigma2 = sigma1 + 132; + // mbr arrangement is similar to sigma; mbr contains locations + // that become significant during significance propagation pass + mbr1 = sigma2 + 132; + mbr2 = mbr1 + 132; + //a pointer to sigma + sip = sigma1; //pointers to arrays to be used interchangeably + sip_shift = 0; //the amount of shift needed for sigma + + if (num_passes > 1 && lengths2 == 0) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, "A malformed codeblock that has " + "more than one coding pass, but zero length for " + "2nd and potentially the 3rd pass in an HT codeblock.\n"); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + num_passes = 1; + } + if (num_passes > 3) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "We do not support more than 3 " + "coding passes in an HT codeblock; This codeblocks has " + "%d passes.\n", num_passes); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + + if (cblk->Mb > 30) { + /* This check is better moved to opj_t2_read_packet_header() in t2.c + We do not have enough precision to decode any passes + The design of openjpeg assumes that the bits of a 32-bit integer are + assigned as follows: + bit 31 is for sign + bits 30-1 are for magnitude + bit 0 is for the center of the quantization bin + Therefore we can only do values of cblk->Mb <= 30 + */ + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "32 bits are not enough to " + "decode this codeblock, since the number of " + "bitplane, %d, is larger than 30.\n", cblk->Mb); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + if (zero_bplanes > cblk->Mb) { + /* This check is better moved to opj_t2_read_packet_header() in t2.c, + in the line "l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i;" + where i is the zero bitplanes, and should be no larger than cblk->Mb + We cannot have more zero bitplanes than there are planes. */ + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. " + "Decoding this codeblock is stopped. There are " + "%d zero bitplanes in %d bitplanes.\n", + zero_bplanes, cblk->Mb); + + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } else if (zero_bplanes == cblk->Mb && num_passes > 1) { + /* When the number of zero bitplanes is equal to the number of bitplanes, + only the cleanup pass makes sense*/ + if (only_cleanup_pass_is_decoded == OPJ_FALSE) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + /* We have a second check to prevent the possibility of an overrun condition, + in the very unlikely event of a second thread discovering that + only_cleanup_pass_is_decoded is false before the first thread changing + the condition. */ + if (only_cleanup_pass_is_decoded == OPJ_FALSE) { + only_cleanup_pass_is_decoded = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, "Malformed HT codeblock. " + "When the number of zero planes bitplanes is " + "equal to the number of bitplanes, only the cleanup " + "pass makes sense, but we have %d passes in this " + "codeblock. Therefore, only the cleanup pass will be " + "decoded. This message will not be displayed again.\n", + num_passes); + } + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + } + num_passes = 1; + } + + /* OPJ_UINT32 */ + p = cblk->numbps; + + // OPJ_UINT32 zero planes plus 1 + zero_bplanes_p1 = zero_bplanes + 1; + + if (lengths1 < 2 || (OPJ_UINT32)lengths1 > cblk_len || + (OPJ_UINT32)(lengths1 + lengths2) > cblk_len) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. " + "Invalid codeblock length values.\n"); + + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + // read scup and fix the bytes there + lcup = (int)lengths1; // length of CUP + //scup is the length of MEL + VLC + scup = (((int)coded_data[lcup - 1]) << 4) + (coded_data[lcup - 2] & 0xF); + if (scup < 2 || scup > lcup || scup > 4079) { //something is wrong + /* The standard stipulates 2 <= Scup <= min(Lcup, 4079) */ + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. " + "One of the following condition is not met: " + "2 <= Scup <= min(Lcup, 4079)\n"); + + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + + // init structures + if (mel_init(&mel, coded_data, lcup, scup) == OPJ_FALSE) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. " + "Incorrect MEL segment sequence.\n"); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + rev_init(&vlc, coded_data, lcup, scup); + frwd_init(&magsgn, coded_data, lcup - scup, 0xFF); + if (num_passes > 1) { // needs to be tested + frwd_init(&sigprop, coded_data + lengths1, (int)lengths2, 0); + } + if (num_passes > 2) { + rev_init_mrp(&magref, coded_data, (int)lengths1, (int)lengths2); + } + + /** State storage + * One byte per quad; for 1024 columns, or 512 quads, we need + * 512 bytes. We are using 2 extra bytes one on the left and one on + * the right for convenience. + * + * The MSB bit in each byte is (\sigma^nw | \sigma^n), and the 7 LSBs + * contain max(E^nw | E^n) + */ + + // 514 is enough for a block width of 1024, +2 extra + // here expanded to 528 + line_state = (OPJ_UINT8 *)(mbr2 + 132); + + //initial 2 lines + ///////////////// + lsp = line_state; // point to line state + lsp[0] = 0; // for initial row of quad, we set to 0 + run = mel_get_run(&mel); // decode runs of events from MEL bitstrm + // data represented as runs of 0 events + // See mel_decode description + qinf[0] = qinf[1] = 0; // quad info decoded from VLC bitstream + c_q = 0; // context for quad q + sp = decoded_data; // decoded codeblock samples + // vlc_val; // fetched data from VLC bitstream + + for (x = 0; x < width; x += 4) { // one iteration per quad pair + OPJ_UINT32 U_q[2]; // u values for the quad pair + OPJ_UINT32 uvlc_mode; + OPJ_UINT32 consumed_bits; + OPJ_UINT32 m_n, v_n; + OPJ_UINT32 ms_val; + OPJ_UINT32 locs; + + // decode VLC + ///////////// + + //first quad + // Get the head of the VLC bitstream. One fetch is enough for two + // quads, since the largest VLC code is 7 bits, and maximum number of + // bits used for u is 8. Therefore for two quads we need 30 bits + // (if we include unstuffing, then 32 bits are enough, since we have + // a maximum of one stuffing per two bytes) + vlc_val = rev_fetch(&vlc); + + //decode VLC using the context c_q and the head of the VLC bitstream + qinf[0] = vlc_tbl0[(c_q << 7) | (vlc_val & 0x7F) ]; + + if (c_q == 0) { // if zero context, we need to use one MEL event + run -= 2; //the number of 0 events is multiplied by 2, so subtract 2 + + // Is the run terminated in 1? if so, use decoded VLC code, + // otherwise, discard decoded data, since we will decoded again + // using a different context + qinf[0] = (run == -1) ? qinf[0] : 0; + + // is run -1 or -2? this means a run has been consumed + if (run < 0) { + run = mel_get_run(&mel); // get another run + } + } + + // prepare context for the next quad; eqn. 1 in ITU T.814 + c_q = ((qinf[0] & 0x10) >> 4) | ((qinf[0] & 0xE0) >> 5); + + //remove data from vlc stream (0 bits are removed if qinf is not used) + vlc_val = rev_advance(&vlc, qinf[0] & 0x7); + + //update sigma + // The update depends on the value of x; consider one OPJ_UINT32 + // if x is 0, 8, 16 and so on, then this line update c locations + // nibble (4 bits) number 0 1 2 3 4 5 6 7 + // LSB c c 0 0 0 0 0 0 + // c c 0 0 0 0 0 0 + // 0 0 0 0 0 0 0 0 + // 0 0 0 0 0 0 0 0 + // if x is 4, 12, 20, then this line update locations c + // nibble (4 bits) number 0 1 2 3 4 5 6 7 + // LSB 0 0 0 0 c c 0 0 + // 0 0 0 0 c c 0 0 + // 0 0 0 0 0 0 0 0 + // 0 0 0 0 0 0 0 0 + *sip |= (((qinf[0] & 0x30) >> 4) | ((qinf[0] & 0xC0) >> 2)) << sip_shift; + + //second quad + qinf[1] = 0; + if (x + 2 < width) { // do not run if codeblock is narrower + //decode VLC using the context c_q and the head of the VLC bitstream + qinf[1] = vlc_tbl0[(c_q << 7) | (vlc_val & 0x7F)]; + + // if context is zero, use one MEL event + if (c_q == 0) { //zero context + run -= 2; //subtract 2, since events number if multiplied by 2 + + // if event is 0, discard decoded qinf + qinf[1] = (run == -1) ? qinf[1] : 0; + + if (run < 0) { // have we consumed all events in a run + run = mel_get_run(&mel); // if yes, then get another run + } + } + + //prepare context for the next quad, eqn. 1 in ITU T.814 + c_q = ((qinf[1] & 0x10) >> 4) | ((qinf[1] & 0xE0) >> 5); + + //remove data from vlc stream, if qinf is not used, cwdlen is 0 + vlc_val = rev_advance(&vlc, qinf[1] & 0x7); + } + + //update sigma + // The update depends on the value of x; consider one OPJ_UINT32 + // if x is 0, 8, 16 and so on, then this line update c locations + // nibble (4 bits) number 0 1 2 3 4 5 6 7 + // LSB 0 0 c c 0 0 0 0 + // 0 0 c c 0 0 0 0 + // 0 0 0 0 0 0 0 0 + // 0 0 0 0 0 0 0 0 + // if x is 4, 12, 20, then this line update locations c + // nibble (4 bits) number 0 1 2 3 4 5 6 7 + // LSB 0 0 0 0 0 0 c c + // 0 0 0 0 0 0 c c + // 0 0 0 0 0 0 0 0 + // 0 0 0 0 0 0 0 0 + *sip |= (((qinf[1] & 0x30) | ((qinf[1] & 0xC0) << 2))) << (4 + sip_shift); + + sip += x & 0x7 ? 1 : 0; // move sigma pointer to next entry + sip_shift ^= 0x10; // increment/decrement sip_shift by 16 + + // retrieve u + ///////////// + + // uvlc_mode is made up of u_offset bits from the quad pair + uvlc_mode = ((qinf[0] & 0x8) >> 3) | ((qinf[1] & 0x8) >> 2); + if (uvlc_mode == 3) { // if both u_offset are set, get an event from + // the MEL run of events + run -= 2; //subtract 2, since events number if multiplied by 2 + uvlc_mode += (run == -1) ? 1 : 0; //increment uvlc_mode if event is 1 + if (run < 0) { // if run is consumed (run is -1 or -2), get another run + run = mel_get_run(&mel); + } + } + //decode uvlc_mode to get u for both quads + consumed_bits = decode_init_uvlc(vlc_val, uvlc_mode, U_q); + if (U_q[0] > zero_bplanes_p1 || U_q[1] > zero_bplanes_p1) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. Decoding " + "this codeblock is stopped. U_q is larger than zero " + "bitplanes + 1 \n"); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + + //consume u bits in the VLC code + vlc_val = rev_advance(&vlc, consumed_bits); + + //decode magsgn and update line_state + ///////////////////////////////////// + + //We obtain a mask for the samples locations that needs evaluation + locs = 0xFF; + if (x + 4 > width) { + locs >>= (x + 4 - width) << 1; // limits width + } + locs = height > 1 ? locs : (locs & 0x55); // limits height + + if ((((qinf[0] & 0xF0) >> 4) | (qinf[1] & 0xF0)) & ~locs) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. " + "VLC code produces significant samples outside " + "the codeblock area.\n"); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + + //first quad, starting at first sample in quad and moving on + if (qinf[0] & 0x10) { //is it significant? (sigma_n) + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); //get 32 bits of magsgn data + m_n = U_q[0] - ((qinf[0] >> 12) & 1); //evaluate m_n (number of bits + // to read from bitstream), using EMB e_k + frwd_advance(&magsgn, m_n); //consume m_n + val = ms_val << 31; //get sign bit + v_n = ms_val & ((1U << m_n) - 1); //keep only m_n bits + v_n |= ((qinf[0] & 0x100) >> 8) << m_n; //add EMB e_1 as MSB + v_n |= 1; //add center of bin + //v_n now has 2 * (\mu - 1) + 0.5 with correct sign bit + //add 2 to make it 2*\mu+0.5, shift it up to missing MSBs + sp[0] = val | ((v_n + 2) << (p - 1)); + } else if (locs & 0x1) { // if this is inside the codeblock, set the + sp[0] = 0; // sample to zero + } + + if (qinf[0] & 0x20) { //sigma_n + OPJ_UINT32 val, t; + + ms_val = frwd_fetch(&magsgn); //get 32 bits + m_n = U_q[0] - ((qinf[0] >> 13) & 1); //m_n, uses EMB e_k + frwd_advance(&magsgn, m_n); //consume m_n + val = ms_val << 31; //get sign bit + v_n = ms_val & ((1U << m_n) - 1); //keep only m_n bits + v_n |= ((qinf[0] & 0x200) >> 9) << m_n; //add EMB e_1 + v_n |= 1; //bin center + //v_n now has 2 * (\mu - 1) + 0.5 with correct sign bit + //add 2 to make it 2*\mu+0.5, shift it up to missing MSBs + sp[stride] = val | ((v_n + 2) << (p - 1)); + + //update line_state: bit 7 (\sigma^N), and E^N + t = lsp[0] & 0x7F; // keep E^NW + v_n = 32 - count_leading_zeros(v_n); + lsp[0] = (OPJ_UINT8)(0x80 | (t > v_n ? t : v_n)); //max(E^NW, E^N) | s + } else if (locs & 0x2) { // if this is inside the codeblock, set the + sp[stride] = 0; // sample to zero + } + + ++lsp; // move to next quad information + ++sp; // move to next column of samples + + //this is similar to the above two samples + if (qinf[0] & 0x40) { + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[0] - ((qinf[0] >> 14) & 1); + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[0] & 0x400) >> 10) << m_n); + v_n |= 1; + sp[0] = val | ((v_n + 2) << (p - 1)); + } else if (locs & 0x4) { + sp[0] = 0; + } + + lsp[0] = 0; + if (qinf[0] & 0x80) { + OPJ_UINT32 val; + ms_val = frwd_fetch(&magsgn); + m_n = U_q[0] - ((qinf[0] >> 15) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= ((qinf[0] & 0x800) >> 11) << m_n; + v_n |= 1; //center of bin + sp[stride] = val | ((v_n + 2) << (p - 1)); + + //line_state: bit 7 (\sigma^NW), and E^NW for next quad + lsp[0] = (OPJ_UINT8)(0x80 | (32 - count_leading_zeros(v_n))); + } else if (locs & 0x8) { //if outside set to 0 + sp[stride] = 0; + } + + ++sp; //move to next column + + //second quad + if (qinf[1] & 0x10) { + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[1] - ((qinf[1] >> 12) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[1] & 0x100) >> 8) << m_n); + v_n |= 1; + sp[0] = val | ((v_n + 2) << (p - 1)); + } else if (locs & 0x10) { + sp[0] = 0; + } + + if (qinf[1] & 0x20) { + OPJ_UINT32 val, t; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[1] - ((qinf[1] >> 13) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[1] & 0x200) >> 9) << m_n); + v_n |= 1; + sp[stride] = val | ((v_n + 2) << (p - 1)); + + //update line_state: bit 7 (\sigma^N), and E^N + t = lsp[0] & 0x7F; //E^NW + v_n = 32 - count_leading_zeros(v_n); //E^N + lsp[0] = (OPJ_UINT8)(0x80 | (t > v_n ? t : v_n)); //max(E^NW, E^N) | s + } else if (locs & 0x20) { + sp[stride] = 0; //no need to update line_state + } + + ++lsp; //move line state to next quad + ++sp; //move to next sample + + if (qinf[1] & 0x40) { + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[1] - ((qinf[1] >> 14) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[1] & 0x400) >> 10) << m_n); + v_n |= 1; + sp[0] = val | ((v_n + 2) << (p - 1)); + } else if (locs & 0x40) { + sp[0] = 0; + } + + lsp[0] = 0; + if (qinf[1] & 0x80) { + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[1] - ((qinf[1] >> 15) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[1] & 0x800) >> 11) << m_n); + v_n |= 1; //center of bin + sp[stride] = val | ((v_n + 2) << (p - 1)); + + //line_state: bit 7 (\sigma^NW), and E^NW for next quad + lsp[0] = (OPJ_UINT8)(0x80 | (32 - count_leading_zeros(v_n))); + } else if (locs & 0x80) { + sp[stride] = 0; + } + + ++sp; + } + + //non-initial lines + ////////////////////////// + for (y = 2; y < height; /*done at the end of loop*/) { + OPJ_UINT32 *sip; + OPJ_UINT8 ls0; + OPJ_INT32 x; + + sip_shift ^= 0x2; // shift sigma to the upper half od the nibble + sip_shift &= 0xFFFFFFEFU; //move back to 0 (it might have been at 0x10) + sip = y & 0x4 ? sigma2 : sigma1; //choose sigma array + + lsp = line_state; + ls0 = lsp[0]; // read the line state value + lsp[0] = 0; // and set it to zero + sp = decoded_data + y * stride; // generated samples + c_q = 0; // context + for (x = 0; x < width; x += 4) { + OPJ_UINT32 U_q[2]; + OPJ_UINT32 uvlc_mode, consumed_bits; + OPJ_UINT32 m_n, v_n; + OPJ_UINT32 ms_val; + OPJ_UINT32 locs; + + // decode vlc + ///////////// + + //first quad + // get context, eqn. 2 ITU T.814 + // c_q has \sigma^W | \sigma^SW + c_q |= (ls0 >> 7); //\sigma^NW | \sigma^N + c_q |= (lsp[1] >> 5) & 0x4; //\sigma^NE | \sigma^NF + + //the following is very similar to previous code, so please refer to + // that + vlc_val = rev_fetch(&vlc); + qinf[0] = vlc_tbl1[(c_q << 7) | (vlc_val & 0x7F)]; + if (c_q == 0) { //zero context + run -= 2; + qinf[0] = (run == -1) ? qinf[0] : 0; + if (run < 0) { + run = mel_get_run(&mel); + } + } + //prepare context for the next quad, \sigma^W | \sigma^SW + c_q = ((qinf[0] & 0x40) >> 5) | ((qinf[0] & 0x80) >> 6); + + //remove data from vlc stream + vlc_val = rev_advance(&vlc, qinf[0] & 0x7); + + //update sigma + // The update depends on the value of x and y; consider one OPJ_UINT32 + // if x is 0, 8, 16 and so on, and y is 2, 6, etc., then this + // line update c locations + // nibble (4 bits) number 0 1 2 3 4 5 6 7 + // LSB 0 0 0 0 0 0 0 0 + // 0 0 0 0 0 0 0 0 + // c c 0 0 0 0 0 0 + // c c 0 0 0 0 0 0 + *sip |= (((qinf[0] & 0x30) >> 4) | ((qinf[0] & 0xC0) >> 2)) << sip_shift; + + //second quad + qinf[1] = 0; + if (x + 2 < width) { + c_q |= (lsp[1] >> 7); + c_q |= (lsp[2] >> 5) & 0x4; + qinf[1] = vlc_tbl1[(c_q << 7) | (vlc_val & 0x7F)]; + if (c_q == 0) { //zero context + run -= 2; + qinf[1] = (run == -1) ? qinf[1] : 0; + if (run < 0) { + run = mel_get_run(&mel); + } + } + //prepare context for the next quad + c_q = ((qinf[1] & 0x40) >> 5) | ((qinf[1] & 0x80) >> 6); + //remove data from vlc stream + vlc_val = rev_advance(&vlc, qinf[1] & 0x7); + } + + //update sigma + *sip |= (((qinf[1] & 0x30) | ((qinf[1] & 0xC0) << 2))) << (4 + sip_shift); + + sip += x & 0x7 ? 1 : 0; + sip_shift ^= 0x10; + + //retrieve u + //////////// + uvlc_mode = ((qinf[0] & 0x8) >> 3) | ((qinf[1] & 0x8) >> 2); + consumed_bits = decode_noninit_uvlc(vlc_val, uvlc_mode, U_q); + vlc_val = rev_advance(&vlc, consumed_bits); + + //calculate E^max and add it to U_q, eqns 5 and 6 in ITU T.814 + if ((qinf[0] & 0xF0) & ((qinf[0] & 0xF0) - 1)) { // is \gamma_q 1? + OPJ_UINT32 E = (ls0 & 0x7Fu); + E = E > (lsp[1] & 0x7Fu) ? E : (lsp[1] & 0x7Fu); //max(E, E^NE, E^NF) + //since U_q already has u_q + 1, we subtract 2 instead of 1 + U_q[0] += E > 2 ? E - 2 : 0; + } + + if ((qinf[1] & 0xF0) & ((qinf[1] & 0xF0) - 1)) { //is \gamma_q 1? + OPJ_UINT32 E = (lsp[1] & 0x7Fu); + E = E > (lsp[2] & 0x7Fu) ? E : (lsp[2] & 0x7Fu); //max(E, E^NE, E^NF) + //since U_q already has u_q + 1, we subtract 2 instead of 1 + U_q[1] += E > 2 ? E - 2 : 0; + } + + if (U_q[0] > zero_bplanes_p1 || U_q[1] > zero_bplanes_p1) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. " + "Decoding this codeblock is stopped. U_q is" + "larger than bitplanes + 1 \n"); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + + ls0 = lsp[2]; //for next double quad + lsp[1] = lsp[2] = 0; + + //decode magsgn and update line_state + ///////////////////////////////////// + + //locations where samples need update + locs = 0xFF; + if (x + 4 > width) { + locs >>= (x + 4 - width) << 1; + } + locs = y + 2 <= height ? locs : (locs & 0x55); + + if ((((qinf[0] & 0xF0) >> 4) | (qinf[1] & 0xF0)) & ~locs) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_ERROR, "Malformed HT codeblock. " + "VLC code produces significant samples outside " + "the codeblock area.\n"); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + + + + if (qinf[0] & 0x10) { //sigma_n + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[0] - ((qinf[0] >> 12) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= ((qinf[0] & 0x100) >> 8) << m_n; + v_n |= 1; //center of bin + sp[0] = val | ((v_n + 2) << (p - 1)); + } else if (locs & 0x1) { + sp[0] = 0; + } + + if (qinf[0] & 0x20) { //sigma_n + OPJ_UINT32 val, t; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[0] - ((qinf[0] >> 13) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= ((qinf[0] & 0x200) >> 9) << m_n; + v_n |= 1; //center of bin + sp[stride] = val | ((v_n + 2) << (p - 1)); + + //update line_state: bit 7 (\sigma^N), and E^N + t = lsp[0] & 0x7F; //E^NW + v_n = 32 - count_leading_zeros(v_n); + lsp[0] = (OPJ_UINT8)(0x80 | (t > v_n ? t : v_n)); + } else if (locs & 0x2) { + sp[stride] = 0; //no need to update line_state + } + + ++lsp; + ++sp; + + if (qinf[0] & 0x40) { //sigma_n + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[0] - ((qinf[0] >> 14) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[0] & 0x400) >> 10) << m_n); + v_n |= 1; //center of bin + sp[0] = val | ((v_n + 2) << (p - 1)); + } else if (locs & 0x4) { + sp[0] = 0; + } + + if (qinf[0] & 0x80) { //sigma_n + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[0] - ((qinf[0] >> 15) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= ((qinf[0] & 0x800) >> 11) << m_n; + v_n |= 1; //center of bin + sp[stride] = val | ((v_n + 2) << (p - 1)); + + //update line_state: bit 7 (\sigma^NW), and E^NW for next quad + lsp[0] = (OPJ_UINT8)(0x80 | (32 - count_leading_zeros(v_n))); + } else if (locs & 0x8) { + sp[stride] = 0; + } + + ++sp; + + if (qinf[1] & 0x10) { //sigma_n + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[1] - ((qinf[1] >> 12) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[1] & 0x100) >> 8) << m_n); + v_n |= 1; //center of bin + sp[0] = val | ((v_n + 2) << (p - 1)); + } else if (locs & 0x10) { + sp[0] = 0; + } + + if (qinf[1] & 0x20) { //sigma_n + OPJ_UINT32 val, t; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[1] - ((qinf[1] >> 13) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[1] & 0x200) >> 9) << m_n); + v_n |= 1; //center of bin + sp[stride] = val | ((v_n + 2) << (p - 1)); + + //update line_state: bit 7 (\sigma^N), and E^N + t = lsp[0] & 0x7F; //E^NW + v_n = 32 - count_leading_zeros(v_n); + lsp[0] = (OPJ_UINT8)(0x80 | (t > v_n ? t : v_n)); + } else if (locs & 0x20) { + sp[stride] = 0; //no need to update line_state + } + + ++lsp; + ++sp; + + if (qinf[1] & 0x40) { //sigma_n + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[1] - ((qinf[1] >> 14) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[1] & 0x400) >> 10) << m_n); + v_n |= 1; //center of bin + sp[0] = val | ((v_n + 2) << (p - 1)); + } else if (locs & 0x40) { + sp[0] = 0; + } + + if (qinf[1] & 0x80) { //sigma_n + OPJ_UINT32 val; + + ms_val = frwd_fetch(&magsgn); + m_n = U_q[1] - ((qinf[1] >> 15) & 1); //m_n + frwd_advance(&magsgn, m_n); + val = ms_val << 31; + v_n = ms_val & ((1U << m_n) - 1); + v_n |= (((qinf[1] & 0x800) >> 11) << m_n); + v_n |= 1; //center of bin + sp[stride] = val | ((v_n + 2) << (p - 1)); + + //update line_state: bit 7 (\sigma^NW), and E^NW for next quad + lsp[0] = (OPJ_UINT8)(0x80 | (32 - count_leading_zeros(v_n))); + } else if (locs & 0x80) { + sp[stride] = 0; + } + + ++sp; + } + + y += 2; + if (num_passes > 1 && (y & 3) == 0) { //executed at multiples of 4 + // This is for SPP and potentially MRP + + if (num_passes > 2) { //do MRP + // select the current stripe + OPJ_UINT32 *cur_sig = y & 0x4 ? sigma1 : sigma2; + // the address of the data that needs updating + OPJ_UINT32 *dpp = decoded_data + (y - 4) * stride; + OPJ_UINT32 half = 1u << (p - 2); // half the center of the bin + OPJ_INT32 i; + for (i = 0; i < width; i += 8) { + //Process one entry from sigma array at a time + // Each nibble (4 bits) in the sigma array represents 4 rows, + // and the 32 bits contain 8 columns + OPJ_UINT32 cwd = rev_fetch_mrp(&magref); // get 32 bit data + OPJ_UINT32 sig = *cur_sig++; // 32 bit that will be processed now + OPJ_UINT32 col_mask = 0xFu; // a mask for a column in sig + OPJ_UINT32 *dp = dpp + i; // next column in decode samples + if (sig) { // if any of the 32 bits are set + int j; + for (j = 0; j < 8; ++j, dp++) { //one column at a time + if (sig & col_mask) { // lowest nibble + OPJ_UINT32 sample_mask = 0x11111111u & col_mask; //LSB + + if (sig & sample_mask) { //if LSB is set + OPJ_UINT32 sym; + + assert(dp[0] != 0); // decoded value cannot be zero + sym = cwd & 1; // get it value + // remove center of bin if sym is 0 + dp[0] ^= (1 - sym) << (p - 1); + dp[0] |= half; // put half the center of bin + cwd >>= 1; //consume word + } + sample_mask += sample_mask; //next row + + if (sig & sample_mask) { + OPJ_UINT32 sym; + + assert(dp[stride] != 0); + sym = cwd & 1; + dp[stride] ^= (1 - sym) << (p - 1); + dp[stride] |= half; + cwd >>= 1; + } + sample_mask += sample_mask; + + if (sig & sample_mask) { + OPJ_UINT32 sym; + + assert(dp[2 * stride] != 0); + sym = cwd & 1; + dp[2 * stride] ^= (1 - sym) << (p - 1); + dp[2 * stride] |= half; + cwd >>= 1; + } + sample_mask += sample_mask; + + if (sig & sample_mask) { + OPJ_UINT32 sym; + + assert(dp[3 * stride] != 0); + sym = cwd & 1; + dp[3 * stride] ^= (1 - sym) << (p - 1); + dp[3 * stride] |= half; + cwd >>= 1; + } + sample_mask += sample_mask; + } + col_mask <<= 4; //next column + } + } + // consume data according to the number of bits set + rev_advance_mrp(&magref, population_count(sig)); + } + } + + if (y >= 4) { // update mbr array at the end of each stripe + //generate mbr corresponding to a stripe + OPJ_UINT32 *sig = y & 0x4 ? sigma1 : sigma2; + OPJ_UINT32 *mbr = y & 0x4 ? mbr1 : mbr2; + + //data is processed in patches of 8 columns, each + // each 32 bits in sigma1 or mbr1 represent 4 rows + + //integrate horizontally + OPJ_UINT32 prev = 0; // previous columns + OPJ_INT32 i; + for (i = 0; i < width; i += 8, mbr++, sig++) { + OPJ_UINT32 t, z; + + mbr[0] = sig[0]; //start with significant samples + mbr[0] |= prev >> 28; //for first column, left neighbors + mbr[0] |= sig[0] << 4; //left neighbors + mbr[0] |= sig[0] >> 4; //right neighbors + mbr[0] |= sig[1] << 28; //for last column, right neighbors + prev = sig[0]; // for next group of columns + + //integrate vertically + t = mbr[0], z = mbr[0]; + z |= (t & 0x77777777) << 1; //above neighbors + z |= (t & 0xEEEEEEEE) >> 1; //below neighbors + mbr[0] = z & ~sig[0]; //remove already significance samples + } + } + + if (y >= 8) { //wait until 8 rows has been processed + OPJ_UINT32 *cur_sig, *cur_mbr, *nxt_sig, *nxt_mbr; + OPJ_UINT32 prev; + OPJ_UINT32 val; + OPJ_INT32 i; + + // add membership from the next stripe, obtained above + cur_sig = y & 0x4 ? sigma2 : sigma1; + cur_mbr = y & 0x4 ? mbr2 : mbr1; + nxt_sig = y & 0x4 ? sigma1 : sigma2; //future samples + prev = 0; // the columns before these group of 8 columns + for (i = 0; i < width; i += 8, cur_mbr++, cur_sig++, nxt_sig++) { + OPJ_UINT32 t = nxt_sig[0]; + t |= prev >> 28; //for first column, left neighbors + t |= nxt_sig[0] << 4; //left neighbors + t |= nxt_sig[0] >> 4; //right neighbors + t |= nxt_sig[1] << 28; //for last column, right neighbors + prev = nxt_sig[0]; // for next group of columns + + if (!stripe_causal) { + cur_mbr[0] |= (t & 0x11111111u) << 3; //propagate up to cur_mbr + } + cur_mbr[0] &= ~cur_sig[0]; //remove already significance samples + } + + //find new locations and get signs + cur_sig = y & 0x4 ? sigma2 : sigma1; + cur_mbr = y & 0x4 ? mbr2 : mbr1; + nxt_sig = y & 0x4 ? sigma1 : sigma2; //future samples + nxt_mbr = y & 0x4 ? mbr1 : mbr2; //future samples + val = 3u << (p - 2); // sample values for newly discovered + // significant samples including the bin center + for (i = 0; i < width; + i += 8, cur_sig++, cur_mbr++, nxt_sig++, nxt_mbr++) { + OPJ_UINT32 ux, tx; + OPJ_UINT32 mbr = *cur_mbr; + OPJ_UINT32 new_sig = 0; + if (mbr) { //are there any samples that might be significant + OPJ_INT32 n; + for (n = 0; n < 8; n += 4) { + OPJ_UINT32 col_mask; + OPJ_UINT32 inv_sig; + OPJ_INT32 end; + OPJ_INT32 j; + + OPJ_UINT32 cwd = frwd_fetch(&sigprop); //get 32 bits + OPJ_UINT32 cnt = 0; + + OPJ_UINT32 *dp = decoded_data + (y - 8) * stride; + dp += i + n; //address for decoded samples + + col_mask = 0xFu << (4 * n); //a mask to select a column + + inv_sig = ~cur_sig[0]; // insignificant samples + + //find the last sample we operate on + end = n + 4 + i < width ? n + 4 : width - i; + + for (j = n; j < end; ++j, ++dp, col_mask <<= 4) { + OPJ_UINT32 sample_mask; + + if ((col_mask & mbr) == 0) { //no samples need checking + continue; + } + + //scan mbr to find a new significant sample + sample_mask = 0x11111111u & col_mask; // LSB + if (mbr & sample_mask) { + assert(dp[0] == 0); // the sample must have been 0 + if (cwd & 1) { //if this sample has become significant + // must propagate it to nearby samples + OPJ_UINT32 t; + new_sig |= sample_mask; // new significant samples + t = 0x32u << (j * 4);// propagation to neighbors + mbr |= t & inv_sig; //remove already significant samples + } + cwd >>= 1; + ++cnt; //consume bit and increment number of + //consumed bits + } + + sample_mask += sample_mask; // next row + if (mbr & sample_mask) { + assert(dp[stride] == 0); + if (cwd & 1) { + OPJ_UINT32 t; + new_sig |= sample_mask; + t = 0x74u << (j * 4); + mbr |= t & inv_sig; + } + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (mbr & sample_mask) { + assert(dp[2 * stride] == 0); + if (cwd & 1) { + OPJ_UINT32 t; + new_sig |= sample_mask; + t = 0xE8u << (j * 4); + mbr |= t & inv_sig; + } + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (mbr & sample_mask) { + assert(dp[3 * stride] == 0); + if (cwd & 1) { + OPJ_UINT32 t; + new_sig |= sample_mask; + t = 0xC0u << (j * 4); + mbr |= t & inv_sig; + } + cwd >>= 1; + ++cnt; + } + } + + //obtain signs here + if (new_sig & (0xFFFFu << (4 * n))) { //if any + OPJ_UINT32 col_mask; + OPJ_INT32 j; + OPJ_UINT32 *dp = decoded_data + (y - 8) * stride; + dp += i + n; // decoded samples address + col_mask = 0xFu << (4 * n); //mask to select a column + + for (j = n; j < end; ++j, ++dp, col_mask <<= 4) { + OPJ_UINT32 sample_mask; + + if ((col_mask & new_sig) == 0) { //if non is significant + continue; + } + + //scan 4 signs + sample_mask = 0x11111111u & col_mask; + if (new_sig & sample_mask) { + assert(dp[0] == 0); + dp[0] |= ((cwd & 1) << 31) | val; //put value and sign + cwd >>= 1; + ++cnt; //consume bit and increment number + //of consumed bits + } + + sample_mask += sample_mask; + if (new_sig & sample_mask) { + assert(dp[stride] == 0); + dp[stride] |= ((cwd & 1) << 31) | val; + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (new_sig & sample_mask) { + assert(dp[2 * stride] == 0); + dp[2 * stride] |= ((cwd & 1) << 31) | val; + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (new_sig & sample_mask) { + assert(dp[3 * stride] == 0); + dp[3 * stride] |= ((cwd & 1) << 31) | val; + cwd >>= 1; + ++cnt; + } + } + + } + frwd_advance(&sigprop, cnt); //consume the bits from bitstrm + cnt = 0; + + //update the next 8 columns + if (n == 4) { + //horizontally + OPJ_UINT32 t = new_sig >> 28; + t |= ((t & 0xE) >> 1) | ((t & 7) << 1); + cur_mbr[1] |= t & ~cur_sig[1]; + } + } + } + //update the next stripe (vertically propagation) + new_sig |= cur_sig[0]; + ux = (new_sig & 0x88888888) >> 3; + tx = ux | (ux << 4) | (ux >> 4); //left and right neighbors + if (i > 0) { + nxt_mbr[-1] |= (ux << 28) & ~nxt_sig[-1]; + } + nxt_mbr[0] |= tx & ~nxt_sig[0]; + nxt_mbr[1] |= (ux >> 28) & ~nxt_sig[1]; + } + + //clear current sigma + //mbr need not be cleared because it is overwritten + cur_sig = y & 0x4 ? sigma2 : sigma1; + memset(cur_sig, 0, ((((OPJ_UINT32)width + 7u) >> 3) + 1u) << 2); + } + } + } + + //terminating + if (num_passes > 1) { + OPJ_INT32 st, y; + + if (num_passes > 2 && ((height & 3) == 1 || (height & 3) == 2)) { + //do magref + OPJ_UINT32 *cur_sig = height & 0x4 ? sigma2 : sigma1; //reversed + OPJ_UINT32 *dpp = decoded_data + (height & 0xFFFFFC) * stride; + OPJ_UINT32 half = 1u << (p - 2); + OPJ_INT32 i; + for (i = 0; i < width; i += 8) { + OPJ_UINT32 cwd = rev_fetch_mrp(&magref); + OPJ_UINT32 sig = *cur_sig++; + OPJ_UINT32 col_mask = 0xF; + OPJ_UINT32 *dp = dpp + i; + if (sig) { + int j; + for (j = 0; j < 8; ++j, dp++) { + if (sig & col_mask) { + OPJ_UINT32 sample_mask = 0x11111111 & col_mask; + + if (sig & sample_mask) { + OPJ_UINT32 sym; + assert(dp[0] != 0); + sym = cwd & 1; + dp[0] ^= (1 - sym) << (p - 1); + dp[0] |= half; + cwd >>= 1; + } + sample_mask += sample_mask; + + if (sig & sample_mask) { + OPJ_UINT32 sym; + assert(dp[stride] != 0); + sym = cwd & 1; + dp[stride] ^= (1 - sym) << (p - 1); + dp[stride] |= half; + cwd >>= 1; + } + sample_mask += sample_mask; + + if (sig & sample_mask) { + OPJ_UINT32 sym; + assert(dp[2 * stride] != 0); + sym = cwd & 1; + dp[2 * stride] ^= (1 - sym) << (p - 1); + dp[2 * stride] |= half; + cwd >>= 1; + } + sample_mask += sample_mask; + + if (sig & sample_mask) { + OPJ_UINT32 sym; + assert(dp[3 * stride] != 0); + sym = cwd & 1; + dp[3 * stride] ^= (1 - sym) << (p - 1); + dp[3 * stride] |= half; + cwd >>= 1; + } + sample_mask += sample_mask; + } + col_mask <<= 4; + } + } + rev_advance_mrp(&magref, population_count(sig)); + } + } + + //do the last incomplete stripe + // for cases of (height & 3) == 0 and 3 + // the should have been processed previously + if ((height & 3) == 1 || (height & 3) == 2) { + //generate mbr of first stripe + OPJ_UINT32 *sig = height & 0x4 ? sigma2 : sigma1; + OPJ_UINT32 *mbr = height & 0x4 ? mbr2 : mbr1; + //integrate horizontally + OPJ_UINT32 prev = 0; + OPJ_INT32 i; + for (i = 0; i < width; i += 8, mbr++, sig++) { + OPJ_UINT32 t, z; + + mbr[0] = sig[0]; + mbr[0] |= prev >> 28; //for first column, left neighbors + mbr[0] |= sig[0] << 4; //left neighbors + mbr[0] |= sig[0] >> 4; //left neighbors + mbr[0] |= sig[1] << 28; //for last column, right neighbors + prev = sig[0]; + + //integrate vertically + t = mbr[0], z = mbr[0]; + z |= (t & 0x77777777) << 1; //above neighbors + z |= (t & 0xEEEEEEEE) >> 1; //below neighbors + mbr[0] = z & ~sig[0]; //remove already significance samples + } + } + + st = height; + st -= height > 6 ? (((height + 1) & 3) + 3) : height; + for (y = st; y < height; y += 4) { + OPJ_UINT32 *cur_sig, *cur_mbr, *nxt_sig, *nxt_mbr; + OPJ_UINT32 val; + OPJ_INT32 i; + + OPJ_UINT32 pattern = 0xFFFFFFFFu; // a pattern needed samples + if (height - y == 3) { + pattern = 0x77777777u; + } else if (height - y == 2) { + pattern = 0x33333333u; + } else if (height - y == 1) { + pattern = 0x11111111u; + } + + //add membership from the next stripe, obtained above + if (height - y > 4) { + OPJ_UINT32 prev = 0; + OPJ_INT32 i; + cur_sig = y & 0x4 ? sigma2 : sigma1; + cur_mbr = y & 0x4 ? mbr2 : mbr1; + nxt_sig = y & 0x4 ? sigma1 : sigma2; + for (i = 0; i < width; i += 8, cur_mbr++, cur_sig++, nxt_sig++) { + OPJ_UINT32 t = nxt_sig[0]; + t |= prev >> 28; //for first column, left neighbors + t |= nxt_sig[0] << 4; //left neighbors + t |= nxt_sig[0] >> 4; //left neighbors + t |= nxt_sig[1] << 28; //for last column, right neighbors + prev = nxt_sig[0]; + + if (!stripe_causal) { + cur_mbr[0] |= (t & 0x11111111u) << 3; + } + //remove already significance samples + cur_mbr[0] &= ~cur_sig[0]; + } + } + + //find new locations and get signs + cur_sig = y & 0x4 ? sigma2 : sigma1; + cur_mbr = y & 0x4 ? mbr2 : mbr1; + nxt_sig = y & 0x4 ? sigma1 : sigma2; + nxt_mbr = y & 0x4 ? mbr1 : mbr2; + val = 3u << (p - 2); + for (i = 0; i < width; i += 8, + cur_sig++, cur_mbr++, nxt_sig++, nxt_mbr++) { + OPJ_UINT32 mbr = *cur_mbr & pattern; //skip unneeded samples + OPJ_UINT32 new_sig = 0; + OPJ_UINT32 ux, tx; + if (mbr) { + OPJ_INT32 n; + for (n = 0; n < 8; n += 4) { + OPJ_UINT32 col_mask; + OPJ_UINT32 inv_sig; + OPJ_INT32 end; + OPJ_INT32 j; + + OPJ_UINT32 cwd = frwd_fetch(&sigprop); + OPJ_UINT32 cnt = 0; + + OPJ_UINT32 *dp = decoded_data + y * stride; + dp += i + n; + + col_mask = 0xFu << (4 * n); + + inv_sig = ~cur_sig[0] & pattern; + + end = n + 4 + i < width ? n + 4 : width - i; + for (j = n; j < end; ++j, ++dp, col_mask <<= 4) { + OPJ_UINT32 sample_mask; + + if ((col_mask & mbr) == 0) { + continue; + } + + //scan 4 mbr + sample_mask = 0x11111111u & col_mask; + if (mbr & sample_mask) { + assert(dp[0] == 0); + if (cwd & 1) { + OPJ_UINT32 t; + new_sig |= sample_mask; + t = 0x32u << (j * 4); + mbr |= t & inv_sig; + } + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (mbr & sample_mask) { + assert(dp[stride] == 0); + if (cwd & 1) { + OPJ_UINT32 t; + new_sig |= sample_mask; + t = 0x74u << (j * 4); + mbr |= t & inv_sig; + } + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (mbr & sample_mask) { + assert(dp[2 * stride] == 0); + if (cwd & 1) { + OPJ_UINT32 t; + new_sig |= sample_mask; + t = 0xE8u << (j * 4); + mbr |= t & inv_sig; + } + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (mbr & sample_mask) { + assert(dp[3 * stride] == 0); + if (cwd & 1) { + OPJ_UINT32 t; + new_sig |= sample_mask; + t = 0xC0u << (j * 4); + mbr |= t & inv_sig; + } + cwd >>= 1; + ++cnt; + } + } + + //signs here + if (new_sig & (0xFFFFu << (4 * n))) { + OPJ_UINT32 col_mask; + OPJ_INT32 j; + OPJ_UINT32 *dp = decoded_data + y * stride; + dp += i + n; + col_mask = 0xFu << (4 * n); + + for (j = n; j < end; ++j, ++dp, col_mask <<= 4) { + OPJ_UINT32 sample_mask; + if ((col_mask & new_sig) == 0) { + continue; + } + + //scan 4 signs + sample_mask = 0x11111111u & col_mask; + if (new_sig & sample_mask) { + assert(dp[0] == 0); + dp[0] |= ((cwd & 1) << 31) | val; + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (new_sig & sample_mask) { + assert(dp[stride] == 0); + dp[stride] |= ((cwd & 1) << 31) | val; + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (new_sig & sample_mask) { + assert(dp[2 * stride] == 0); + dp[2 * stride] |= ((cwd & 1) << 31) | val; + cwd >>= 1; + ++cnt; + } + + sample_mask += sample_mask; + if (new_sig & sample_mask) { + assert(dp[3 * stride] == 0); + dp[3 * stride] |= ((cwd & 1) << 31) | val; + cwd >>= 1; + ++cnt; + } + } + + } + frwd_advance(&sigprop, cnt); + cnt = 0; + + //update next columns + if (n == 4) { + //horizontally + OPJ_UINT32 t = new_sig >> 28; + t |= ((t & 0xE) >> 1) | ((t & 7) << 1); + cur_mbr[1] |= t & ~cur_sig[1]; + } + } + } + //propagate down (vertically propagation) + new_sig |= cur_sig[0]; + ux = (new_sig & 0x88888888) >> 3; + tx = ux | (ux << 4) | (ux >> 4); + if (i > 0) { + nxt_mbr[-1] |= (ux << 28) & ~nxt_sig[-1]; + } + nxt_mbr[0] |= tx & ~nxt_sig[0]; + nxt_mbr[1] |= (ux >> 28) & ~nxt_sig[1]; + } + } + } + + { + OPJ_INT32 x, y; + for (y = 0; y < height; ++y) { + OPJ_INT32* sp = (OPJ_INT32*)decoded_data + y * stride; + for (x = 0; x < width; ++x, ++sp) { + OPJ_INT32 val = (*sp & 0x7FFFFFFF); + *sp = ((OPJ_UINT32) * sp & 0x80000000) ? -val : val; + } + } + } + + return OPJ_TRUE; +} diff --git a/client/deps/openjpeg/image.c b/client/deps/openjpeg/image.c new file mode 100644 index 000000000..017201a00 --- /dev/null +++ b/client/deps/openjpeg/image.c @@ -0,0 +1,263 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +opj_image_t* opj_image_create0(void) +{ + opj_image_t *image = (opj_image_t*)opj_calloc(1, sizeof(opj_image_t)); + return image; +} + +opj_image_t* OPJ_CALLCONV opj_image_create(OPJ_UINT32 numcmpts, + opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) +{ + OPJ_UINT32 compno; + opj_image_t *image = NULL; + + image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t)); + if (image) { + image->color_space = clrspc; + image->numcomps = numcmpts; + /* allocate memory for the per-component information */ + image->comps = (opj_image_comp_t*)opj_calloc(image->numcomps, + sizeof(opj_image_comp_t)); + if (!image->comps) { + /* TODO replace with event manager, breaks API */ + /* fprintf(stderr,"Unable to allocate memory for image.\n"); */ + opj_image_destroy(image); + return NULL; + } + /* create the individual image components */ + for (compno = 0; compno < numcmpts; compno++) { + opj_image_comp_t *comp = &image->comps[compno]; + comp->dx = cmptparms[compno].dx; + comp->dy = cmptparms[compno].dy; + comp->w = cmptparms[compno].w; + comp->h = cmptparms[compno].h; + comp->x0 = cmptparms[compno].x0; + comp->y0 = cmptparms[compno].y0; + comp->prec = cmptparms[compno].prec; + comp->sgnd = cmptparms[compno].sgnd; + if (comp->h != 0 && + (OPJ_SIZE_T)comp->w > SIZE_MAX / comp->h / sizeof(OPJ_INT32)) { + /* TODO event manager */ + opj_image_destroy(image); + return NULL; + } + comp->data = (OPJ_INT32*) opj_image_data_alloc( + (size_t)comp->w * comp->h * sizeof(OPJ_INT32)); + if (!comp->data) { + /* TODO replace with event manager, breaks API */ + /* fprintf(stderr,"Unable to allocate memory for image.\n"); */ + opj_image_destroy(image); + return NULL; + } + memset(comp->data, 0, (size_t)comp->w * comp->h * sizeof(OPJ_INT32)); + } + } + + return image; +} + +void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) +{ + if (image) { + if (image->comps) { + OPJ_UINT32 compno; + + /* image components */ + for (compno = 0; compno < image->numcomps; compno++) { + opj_image_comp_t *image_comp = &(image->comps[compno]); + if (image_comp->data) { + opj_image_data_free(image_comp->data); + } + } + opj_free(image->comps); + } + + if (image->icc_profile_buf) { + opj_free(image->icc_profile_buf); + } + + opj_free(image); + } +} + +/** + * Updates the components characteristics of the image from the coding parameters. + * + * @param p_image_header the image header to update. + * @param p_cp the coding parameters from which to update the image. + */ +void opj_image_comp_header_update(opj_image_t * p_image_header, + const struct opj_cp * p_cp) +{ + OPJ_UINT32 i, l_width, l_height; + OPJ_UINT32 l_x0, l_y0, l_x1, l_y1; + OPJ_UINT32 l_comp_x0, l_comp_y0, l_comp_x1, l_comp_y1; + opj_image_comp_t* l_img_comp = NULL; + + l_x0 = opj_uint_max(p_cp->tx0, p_image_header->x0); + l_y0 = opj_uint_max(p_cp->ty0, p_image_header->y0); + l_x1 = p_cp->tx0 + (p_cp->tw - 1U) * + p_cp->tdx; /* validity of p_cp members used here checked in opj_j2k_read_siz. Can't overflow. */ + l_y1 = p_cp->ty0 + (p_cp->th - 1U) * p_cp->tdy; /* can't overflow */ + l_x1 = opj_uint_min(opj_uint_adds(l_x1, p_cp->tdx), + p_image_header->x1); /* use add saturated to prevent overflow */ + l_y1 = opj_uint_min(opj_uint_adds(l_y1, p_cp->tdy), + p_image_header->y1); /* use add saturated to prevent overflow */ + + l_img_comp = p_image_header->comps; + for (i = 0; i < p_image_header->numcomps; ++i) { + l_comp_x0 = opj_uint_ceildiv(l_x0, l_img_comp->dx); + l_comp_y0 = opj_uint_ceildiv(l_y0, l_img_comp->dy); + l_comp_x1 = opj_uint_ceildiv(l_x1, l_img_comp->dx); + l_comp_y1 = opj_uint_ceildiv(l_y1, l_img_comp->dy); + l_width = opj_uint_ceildivpow2(l_comp_x1 - l_comp_x0, l_img_comp->factor); + l_height = opj_uint_ceildivpow2(l_comp_y1 - l_comp_y0, l_img_comp->factor); + l_img_comp->w = l_width; + l_img_comp->h = l_height; + l_img_comp->x0 = l_comp_x0; + l_img_comp->y0 = l_comp_y0; + ++l_img_comp; + } +} + + +/** + * Copy only header of image and its component header (no data are copied) + * if dest image have data, they will be freed + * + * @param p_image_src the src image + * @param p_image_dest the dest image + * + */ +void opj_copy_image_header(const opj_image_t* p_image_src, + opj_image_t* p_image_dest) +{ + OPJ_UINT32 compno; + + /* preconditions */ + assert(p_image_src != 00); + assert(p_image_dest != 00); + + p_image_dest->x0 = p_image_src->x0; + p_image_dest->y0 = p_image_src->y0; + p_image_dest->x1 = p_image_src->x1; + p_image_dest->y1 = p_image_src->y1; + + if (p_image_dest->comps) { + for (compno = 0; compno < p_image_dest->numcomps; compno++) { + opj_image_comp_t *image_comp = &(p_image_dest->comps[compno]); + if (image_comp->data) { + opj_image_data_free(image_comp->data); + } + } + opj_free(p_image_dest->comps); + p_image_dest->comps = NULL; + } + + p_image_dest->numcomps = p_image_src->numcomps; + + p_image_dest->comps = (opj_image_comp_t*) opj_malloc(p_image_dest->numcomps * + sizeof(opj_image_comp_t)); + if (!p_image_dest->comps) { + p_image_dest->comps = NULL; + p_image_dest->numcomps = 0; + return; + } + + for (compno = 0; compno < p_image_dest->numcomps; compno++) { + memcpy(&(p_image_dest->comps[compno]), + &(p_image_src->comps[compno]), + sizeof(opj_image_comp_t)); + p_image_dest->comps[compno].data = NULL; + } + + p_image_dest->color_space = p_image_src->color_space; + p_image_dest->icc_profile_len = p_image_src->icc_profile_len; + + if (p_image_dest->icc_profile_len) { + p_image_dest->icc_profile_buf = (OPJ_BYTE*)opj_malloc( + p_image_dest->icc_profile_len); + if (!p_image_dest->icc_profile_buf) { + p_image_dest->icc_profile_buf = NULL; + p_image_dest->icc_profile_len = 0; + return; + } + memcpy(p_image_dest->icc_profile_buf, + p_image_src->icc_profile_buf, + p_image_src->icc_profile_len); + } else { + p_image_dest->icc_profile_buf = NULL; + } + + return; +} + +opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts, + opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) +{ + OPJ_UINT32 compno; + opj_image_t *image = 00; + + image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t)); + if (image) { + + image->color_space = clrspc; + image->numcomps = numcmpts; + + /* allocate memory for the per-component information */ + image->comps = (opj_image_comp_t*)opj_calloc(image->numcomps, + sizeof(opj_image_comp_t)); + if (!image->comps) { + opj_image_destroy(image); + return 00; + } + + /* create the individual image components */ + for (compno = 0; compno < numcmpts; compno++) { + opj_image_comp_t *comp = &image->comps[compno]; + comp->dx = cmptparms[compno].dx; + comp->dy = cmptparms[compno].dy; + comp->w = cmptparms[compno].w; + comp->h = cmptparms[compno].h; + comp->x0 = cmptparms[compno].x0; + comp->y0 = cmptparms[compno].y0; + comp->prec = cmptparms[compno].prec; + comp->sgnd = cmptparms[compno].sgnd; + comp->data = 0; + } + } + + return image; +} diff --git a/client/deps/openjpeg/image.h b/client/deps/openjpeg/image.h new file mode 100644 index 000000000..bad83c613 --- /dev/null +++ b/client/deps/openjpeg/image.h @@ -0,0 +1,70 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_IMAGE_H +#define OPJ_IMAGE_H +/** +@file image.h +@brief Implementation of operations on images (IMAGE) + +The functions in IMAGE.C have for goal to realize operations on images. +*/ + +struct opj_image; +struct opj_cp; + +/** @defgroup IMAGE IMAGE - Implementation of operations on images */ +/*@{*/ + +/** + * Create an empty image + * + * @return returns an empty image if successful, returns NULL otherwise + */ +opj_image_t* opj_image_create0(void); + + + +/** + * Updates the components characteristics of the image from the coding parameters. + * + * @param p_image_header the image header to update. + * @param p_cp the coding parameters from which to update the image. + */ +void opj_image_comp_header_update(opj_image_t * p_image, + const struct opj_cp* p_cp); + +void opj_copy_image_header(const opj_image_t* p_image_src, + opj_image_t* p_image_dest); + +/*@}*/ + +#endif /* OPJ_IMAGE_H */ + diff --git a/client/deps/openjpeg/invert.c b/client/deps/openjpeg/invert.c new file mode 100644 index 000000000..89f607155 --- /dev/null +++ b/client/deps/openjpeg/invert.c @@ -0,0 +1,295 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +/** + * LUP decomposition + */ +static OPJ_BOOL opj_lupDecompose(OPJ_FLOAT32 * matrix, + OPJ_UINT32 * permutations, + OPJ_FLOAT32 * p_swap_area, + OPJ_UINT32 nb_compo); +/** + * LUP solving + */ +static void opj_lupSolve(OPJ_FLOAT32 * pResult, + OPJ_FLOAT32* pMatrix, + OPJ_FLOAT32* pVector, + OPJ_UINT32* pPermutations, + OPJ_UINT32 nb_compo, + OPJ_FLOAT32 * p_intermediate_data); + +/** + *LUP inversion (call with the result of lupDecompose) + */ +static void opj_lupInvert(OPJ_FLOAT32 * pSrcMatrix, + OPJ_FLOAT32 * pDestMatrix, + OPJ_UINT32 nb_compo, + OPJ_UINT32 * pPermutations, + OPJ_FLOAT32 * p_src_temp, + OPJ_FLOAT32 * p_dest_temp, + OPJ_FLOAT32 * p_swap_area); + +/* +========================================================== + Matric inversion interface +========================================================== +*/ +/** + * Matrix inversion. + */ +OPJ_BOOL opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix, + OPJ_FLOAT32 * pDestMatrix, + OPJ_UINT32 nb_compo) +{ + OPJ_BYTE * l_data = 00; + OPJ_UINT32 l_permutation_size = nb_compo * (OPJ_UINT32)sizeof(OPJ_UINT32); + OPJ_UINT32 l_swap_size = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + OPJ_UINT32 l_total_size = l_permutation_size + 3 * l_swap_size; + OPJ_UINT32 * lPermutations = 00; + OPJ_FLOAT32 * l_double_data = 00; + + l_data = (OPJ_BYTE *) opj_malloc(l_total_size); + if (l_data == 0) { + return OPJ_FALSE; + } + lPermutations = (OPJ_UINT32 *) l_data; + l_double_data = (OPJ_FLOAT32 *)(l_data + l_permutation_size); + memset(lPermutations, 0, l_permutation_size); + + if (! opj_lupDecompose(pSrcMatrix, lPermutations, l_double_data, nb_compo)) { + opj_free(l_data); + return OPJ_FALSE; + } + + opj_lupInvert(pSrcMatrix, pDestMatrix, nb_compo, lPermutations, l_double_data, + l_double_data + nb_compo, l_double_data + 2 * nb_compo); + opj_free(l_data); + + return OPJ_TRUE; +} + + +/* +========================================================== + Local functions +========================================================== +*/ +static OPJ_BOOL opj_lupDecompose(OPJ_FLOAT32 * matrix, + OPJ_UINT32 * permutations, + OPJ_FLOAT32 * p_swap_area, + OPJ_UINT32 nb_compo) +{ + OPJ_UINT32 * tmpPermutations = permutations; + OPJ_UINT32 * dstPermutations; + OPJ_UINT32 k2 = 0, t; + OPJ_FLOAT32 temp; + OPJ_UINT32 i, j, k; + OPJ_FLOAT32 p; + OPJ_UINT32 lLastColum = nb_compo - 1; + OPJ_UINT32 lSwapSize = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + OPJ_FLOAT32 * lTmpMatrix = matrix; + OPJ_FLOAT32 * lColumnMatrix, * lDestMatrix; + OPJ_UINT32 offset = 1; + OPJ_UINT32 lStride = nb_compo - 1; + + /*initialize permutations */ + for (i = 0; i < nb_compo; ++i) { + *tmpPermutations++ = i; + } + /* now make a pivot with column switch */ + tmpPermutations = permutations; + for (k = 0; k < lLastColum; ++k) { + p = 0.0; + + /* take the middle element */ + lColumnMatrix = lTmpMatrix + k; + + /* make permutation with the biggest value in the column */ + for (i = k; i < nb_compo; ++i) { + temp = ((*lColumnMatrix > 0) ? *lColumnMatrix : -(*lColumnMatrix)); + if (temp > p) { + p = temp; + k2 = i; + } + /* next line */ + lColumnMatrix += nb_compo; + } + + /* a whole rest of 0 -> non singular */ + if (p == 0.0) { + return OPJ_FALSE; + } + + /* should we permute ? */ + if (k2 != k) { + /*exchange of line */ + /* k2 > k */ + dstPermutations = tmpPermutations + k2 - k; + /* swap indices */ + t = *tmpPermutations; + *tmpPermutations = *dstPermutations; + *dstPermutations = t; + + /* and swap entire line. */ + lColumnMatrix = lTmpMatrix + (k2 - k) * nb_compo; + memcpy(p_swap_area, lColumnMatrix, lSwapSize); + memcpy(lColumnMatrix, lTmpMatrix, lSwapSize); + memcpy(lTmpMatrix, p_swap_area, lSwapSize); + } + + /* now update data in the rest of the line and line after */ + lDestMatrix = lTmpMatrix + k; + lColumnMatrix = lDestMatrix + nb_compo; + /* take the middle element */ + temp = *(lDestMatrix++); + + /* now compute up data (i.e. coeff up of the diagonal). */ + for (i = offset; i < nb_compo; ++i) { + /*lColumnMatrix; */ + /* divide the lower column elements by the diagonal value */ + + /* matrix[i][k] /= matrix[k][k]; */ + /* p = matrix[i][k] */ + p = *lColumnMatrix / temp; + *(lColumnMatrix++) = p; + + for (j = /* k + 1 */ offset; j < nb_compo; ++j) { + /* matrix[i][j] -= matrix[i][k] * matrix[k][j]; */ + *(lColumnMatrix++) -= p * (*(lDestMatrix++)); + } + /* come back to the k+1th element */ + lDestMatrix -= lStride; + /* go to kth element of the next line */ + lColumnMatrix += k; + } + + /* offset is now k+2 */ + ++offset; + /* 1 element less for stride */ + --lStride; + /* next line */ + lTmpMatrix += nb_compo; + /* next permutation element */ + ++tmpPermutations; + } + return OPJ_TRUE; +} + +static void opj_lupSolve(OPJ_FLOAT32 * pResult, + OPJ_FLOAT32 * pMatrix, + OPJ_FLOAT32 * pVector, + OPJ_UINT32* pPermutations, + OPJ_UINT32 nb_compo, OPJ_FLOAT32 * p_intermediate_data) +{ + OPJ_INT32 k; + OPJ_UINT32 i, j; + OPJ_FLOAT32 sum; + OPJ_FLOAT32 u; + OPJ_UINT32 lStride = nb_compo + 1; + OPJ_FLOAT32 * lCurrentPtr; + OPJ_FLOAT32 * lIntermediatePtr; + OPJ_FLOAT32 * lDestPtr; + OPJ_FLOAT32 * lTmpMatrix; + OPJ_FLOAT32 * lLineMatrix = pMatrix; + OPJ_FLOAT32 * lBeginPtr = pResult + nb_compo - 1; + OPJ_FLOAT32 * lGeneratedData; + OPJ_UINT32 * lCurrentPermutationPtr = pPermutations; + + + lIntermediatePtr = p_intermediate_data; + lGeneratedData = p_intermediate_data + nb_compo - 1; + + for (i = 0; i < nb_compo; ++i) { + sum = 0.0; + lCurrentPtr = p_intermediate_data; + lTmpMatrix = lLineMatrix; + for (j = 1; j <= i; ++j) { + /* sum += matrix[i][j-1] * y[j-1]; */ + sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++)); + } + /*y[i] = pVector[pPermutations[i]] - sum; */ + *(lIntermediatePtr++) = pVector[*(lCurrentPermutationPtr++)] - sum; + lLineMatrix += nb_compo; + } + + /* we take the last point of the matrix */ + lLineMatrix = pMatrix + nb_compo * nb_compo - 1; + + /* and we take after the last point of the destination vector */ + lDestPtr = pResult + nb_compo; + + + assert(nb_compo != 0); + for (k = (OPJ_INT32)nb_compo - 1; k != -1 ; --k) { + sum = 0.0; + lTmpMatrix = lLineMatrix; + u = *(lTmpMatrix++); + lCurrentPtr = lDestPtr--; + for (j = (OPJ_UINT32)(k + 1); j < nb_compo; ++j) { + /* sum += matrix[k][j] * x[j] */ + sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++)); + } + /*x[k] = (y[k] - sum) / u; */ + *(lBeginPtr--) = (*(lGeneratedData--) - sum) / u; + lLineMatrix -= lStride; + } +} + + +static void opj_lupInvert(OPJ_FLOAT32 * pSrcMatrix, + OPJ_FLOAT32 * pDestMatrix, + OPJ_UINT32 nb_compo, + OPJ_UINT32 * pPermutations, + OPJ_FLOAT32 * p_src_temp, + OPJ_FLOAT32 * p_dest_temp, + OPJ_FLOAT32 * p_swap_area) +{ + OPJ_UINT32 j, i; + OPJ_FLOAT32 * lCurrentPtr; + OPJ_FLOAT32 * lLineMatrix = pDestMatrix; + OPJ_UINT32 lSwapSize = nb_compo * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + + for (j = 0; j < nb_compo; ++j) { + lCurrentPtr = lLineMatrix++; + memset(p_src_temp, 0, lSwapSize); + p_src_temp[j] = 1.0; + opj_lupSolve(p_dest_temp, pSrcMatrix, p_src_temp, pPermutations, nb_compo, + p_swap_area); + + for (i = 0; i < nb_compo; ++i) { + *(lCurrentPtr) = p_dest_temp[i]; + lCurrentPtr += nb_compo; + } + } +} + diff --git a/client/deps/openjpeg/invert.h b/client/deps/openjpeg/invert.h new file mode 100644 index 000000000..704021355 --- /dev/null +++ b/client/deps/openjpeg/invert.h @@ -0,0 +1,64 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_INVERT_H +#define OPJ_INVERT_H +/** +@file invert.h +@brief Implementation of the matrix inversion + +The function in INVERT.H compute a matrix inversion with a LUP method +*/ + +/** @defgroup INVERT INVERT - Implementation of a matrix inversion */ +/*@{*/ +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** + * Calculates a n x n double matrix inversion with a LUP method. Data is aligned, rows after rows (or columns after columns). + * The function does not take ownership of any memory block, data must be fred by the user. + * + * @param pSrcMatrix the matrix to invert. + * @param pDestMatrix data to store the inverted matrix. + * @param nb_compo size of the matrix + * @return OPJ_TRUE if the inversion is successful, OPJ_FALSE if the matrix is singular. + */ +OPJ_BOOL opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix, + OPJ_FLOAT32 * pDestMatrix, + OPJ_UINT32 nb_compo); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_INVERT_H */ diff --git a/client/deps/openjpeg/j2k.c b/client/deps/openjpeg/j2k.c new file mode 100644 index 000000000..a2014c89b --- /dev/null +++ b/client/deps/openjpeg/j2k.c @@ -0,0 +1,13595 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2010-2011, Kaori Hagihara + * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France + * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** + * Sets up the procedures to do on reading header. Developers wanting to extend the library can add their own reading procedures. + */ +static OPJ_BOOL opj_j2k_setup_header_reading(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); + +/** + * The read header procedure. + */ +static OPJ_BOOL opj_j2k_read_header_procedure(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * The default encoding validation procedure without any extension. + * + * @param p_j2k the jpeg2000 codec to validate. + * @param p_stream the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +static OPJ_BOOL opj_j2k_encoding_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * The default decoding validation procedure without any extension. + * + * @param p_j2k the jpeg2000 codec to validate. + * @param p_stream the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +static OPJ_BOOL opj_j2k_decoding_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters + * are valid. Developers wanting to extend the library can add their own validation procedures. + */ +static OPJ_BOOL opj_j2k_setup_encoding_validation(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); + +/** + * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters + * are valid. Developers wanting to extend the library can add their own validation procedures. + */ +static OPJ_BOOL opj_j2k_setup_decoding_validation(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); + +/** + * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters + * are valid. Developers wanting to extend the library can add their own validation procedures. + */ +static OPJ_BOOL opj_j2k_setup_end_compress(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); + +/** + * The mct encoding validation procedure. + * + * @param p_j2k the jpeg2000 codec to validate. + * @param p_stream the input stream to validate. + * @param p_manager the user event manager. + * + * @return true if the parameters are correct. + */ +static OPJ_BOOL opj_j2k_mct_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Builds the tcd decoder to use to decode tile. + */ +static OPJ_BOOL opj_j2k_build_decoder(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); +/** + * Builds the tcd encoder to use to encode tile. + */ +static OPJ_BOOL opj_j2k_build_encoder(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Creates a tile-coder encoder. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_create_tcd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Executes the given procedures on the given codec. + * + * @param p_procedure_list the list of procedures to execute + * @param p_j2k the jpeg2000 codec to execute the procedures on. + * @param p_stream the stream to execute the procedures on. + * @param p_manager the user manager. + * + * @return true if all the procedures were successfully executed. + */ +static OPJ_BOOL opj_j2k_exec(opj_j2k_t * p_j2k, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Updates the rates of the tcp. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Copies the decoding tile parameters onto all the tile parameters. + * Creates also the tile decoder. + */ +static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Destroys the memory associated with the decoding of headers. + */ +static OPJ_BOOL opj_j2k_destroy_header_memory(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads the lookup table containing all the marker, status and action, and returns the handler associated + * with the marker value. + * @param p_id Marker value to look up + * + * @return the handler associated with the id. +*/ +static const struct opj_dec_memory_marker_handler * opj_j2k_get_marker_handler( + OPJ_UINT32 p_id); + +/** + * Destroys a tile coding parameter structure. + * + * @param p_tcp the tile coding parameter to destroy. + */ +static void opj_j2k_tcp_destroy(opj_tcp_t *p_tcp); + +/** + * Destroys the data inside a tile coding parameter structure. + * + * @param p_tcp the tile coding parameter which contain data to destroy. + */ +static void opj_j2k_tcp_data_destroy(opj_tcp_t *p_tcp); + +/** + * Destroys a coding parameter structure. + * + * @param p_cp the coding parameter to destroy. + */ +static void opj_j2k_cp_destroy(opj_cp_t *p_cp); + +/** + * Compare 2 a SPCod/ SPCoc elements, i.e. the coding style of a given component of a tile. + * + * @param p_j2k J2K codec. + * @param p_tile_no Tile number + * @param p_first_comp_no The 1st component number to compare. + * @param p_second_comp_no The 1st component number to compare. + * + * @return OPJ_TRUE if SPCdod are equals. + */ +static OPJ_BOOL opj_j2k_compare_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no); + +/** + * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. + * + * @param p_j2k J2K codec. + * @param p_tile_no FIXME DOC + * @param p_comp_no the component number to output. + * @param p_data FIXME DOC + * @param p_header_size FIXME DOC + * @param p_manager the user event manager. + * + * @return FIXME DOC +*/ +static OPJ_BOOL opj_j2k_write_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Gets the size taken by writing a SPCod or SPCoc for the given tile and component. + * + * @param p_j2k the J2K codec. + * @param p_tile_no the tile index. + * @param p_comp_no the component being outputted. + * + * @return the number of bytes taken by the SPCod element. + */ +static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no); + +/** + * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. + * @param p_j2k the jpeg2000 codec. + * @param compno FIXME DOC + * @param p_header_data the data contained in the COM box. + * @param p_header_size the size of the data contained in the COM marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Gets the size taken by writing SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. + * + * @param p_tile_no the tile index. + * @param p_comp_no the component being outputted. + * @param p_j2k the J2K codec. + * + * @return the number of bytes taken by the SPCod element. + */ +static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no); + +/** + * Compares 2 SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. + * + * @param p_j2k J2K codec. + * @param p_tile_no the tile to output. + * @param p_first_comp_no the first component number to compare. + * @param p_second_comp_no the second component number to compare. + * + * @return OPJ_TRUE if equals. + */ +static OPJ_BOOL opj_j2k_compare_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no); + + +/** + * Writes a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. + * + * @param p_tile_no the tile to output. + * @param p_comp_no the component number to output. + * @param p_data the data buffer. + * @param p_header_size pointer to the size of the data buffer, it is changed by the function. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. + * +*/ +static OPJ_BOOL opj_j2k_write_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Updates the Tile Length Marker. + */ +static void opj_j2k_update_tlm(opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size); + +/** + * Reads a SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. + * + * @param p_j2k J2K codec. + * @param compno the component number to output. + * @param p_header_data the data buffer. + * @param p_header_size pointer to the size of the data buffer, it is changed by the function. + * @param p_manager the user event manager. + * +*/ +static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Copies the tile component parameters of all the component from the first tile component. + * + * @param p_j2k the J2k codec. + */ +static void opj_j2k_copy_tile_component_parameters(opj_j2k_t *p_j2k); + +/** + * Copies the tile quantization parameters of all the component from the first tile component. + * + * @param p_j2k the J2k codec. + */ +static void opj_j2k_copy_tile_quantization_parameters(opj_j2k_t *p_j2k); + +/** + * Reads the tiles. + */ +static OPJ_BOOL opj_j2k_decode_tiles(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +static OPJ_BOOL opj_j2k_pre_write_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, + opj_image_t* p_output_image); + +static void opj_get_tile_dimensions(opj_image_t * l_image, + opj_tcd_tilecomp_t * l_tilec, + opj_image_comp_t * l_img_comp, + OPJ_UINT32* l_size_comp, + OPJ_UINT32* l_width, + OPJ_UINT32* l_height, + OPJ_UINT32* l_offset_x, + OPJ_UINT32* l_offset_y, + OPJ_UINT32* l_image_width, + OPJ_UINT32* l_stride, + OPJ_UINT32* l_tile_offset); + +static void opj_j2k_get_tile_data(opj_tcd_t * p_tcd, OPJ_BYTE * p_data); + +static OPJ_BOOL opj_j2k_post_write_tile(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Sets up the procedures to do on writing header. + * Developers wanting to extend the library can add their own writing procedures. + */ +static OPJ_BOOL opj_j2k_setup_header_writing(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager); + +static OPJ_BOOL opj_j2k_write_first_tile_part(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager); + +static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager); + +/** + * Gets the offset of the header. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_get_end_header(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +static OPJ_BOOL opj_j2k_allocate_tile_element_cstr_index(opj_j2k_t *p_j2k); + +/* + * ----------------------------------------------------------------------- + * ----------------------------------------------------------------------- + * ----------------------------------------------------------------------- + */ + +/** + * Writes the SOC marker (Start Of Codestream) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_soc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a SOC marker (Start of Codestream) + * @param p_j2k the jpeg2000 file codec. + * @param p_stream XXX needs data + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_soc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Writes the SIZ marker (image and tile size) + * + * @param p_j2k J2K codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_siz(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a SIZ marker (image and tile size) + * @param p_j2k the jpeg2000 file codec. + * @param p_header_data the data contained in the SIZ box. + * @param p_header_size the size of the data contained in the SIZ marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Writes the COM marker (comment) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_com(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a COM marker (comments) + * @param p_j2k the jpeg2000 file codec. + * @param p_header_data the data contained in the COM box. + * @param p_header_size the size of the data contained in the COM marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_com(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); +/** + * Writes the COD marker (Coding style default) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_cod(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a COD marker (Coding style defaults) + * @param p_header_data the data contained in the COD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COD marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_cod(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Compares 2 COC markers (Coding style component) + * + * @param p_j2k J2K codec. + * @param p_first_comp_no the index of the first component to compare. + * @param p_second_comp_no the index of the second component to compare. + * + * @return OPJ_TRUE if equals + */ +static OPJ_BOOL opj_j2k_compare_coc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no); + +/** + * Writes the COC marker (Coding style component) + * + * @param p_j2k J2K codec. + * @param p_comp_no the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_coc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Writes the COC marker (Coding style component) + * + * @param p_j2k J2K codec. + * @param p_comp_no the index of the component to output. + * @param p_data FIXME DOC + * @param p_data_written FIXME DOC + * @param p_manager the user event manager. +*/ +static void opj_j2k_write_coc_in_memory(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager); + +/** + * Gets the maximum size taken by a coc. + * + * @param p_j2k the jpeg2000 codec to use. + */ +static OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_t *p_j2k); + +/** + * Reads a COC marker (Coding Style Component) + * @param p_header_data the data contained in the COC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COC marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_coc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Writes the QCD marker (quantization default) + * + * @param p_j2k J2K codec. + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_qcd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a QCD marker (Quantization defaults) + * @param p_header_data the data contained in the QCD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the QCD marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_qcd(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Compare QCC markers (quantization component) + * + * @param p_j2k J2K codec. + * @param p_first_comp_no the index of the first component to compare. + * @param p_second_comp_no the index of the second component to compare. + * + * @return OPJ_TRUE if equals. + */ +static OPJ_BOOL opj_j2k_compare_qcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no); + +/** + * Writes the QCC marker (quantization component) + * + * @param p_comp_no the index of the component to output. + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_qcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Writes the QCC marker (quantization component) + * + * @param p_j2k J2K codec. + * @param p_comp_no the index of the component to output. + * @param p_data FIXME DOC + * @param p_data_written the stream to write data to. + * @param p_manager the user event manager. +*/ +static void opj_j2k_write_qcc_in_memory(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager); + +/** + * Gets the maximum size taken by a qcc. + */ +static OPJ_UINT32 opj_j2k_get_max_qcc_size(opj_j2k_t *p_j2k); + +/** + * Reads a QCC marker (Quantization component) + * @param p_header_data the data contained in the QCC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the QCC marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_qcc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); +/** + * Writes the POC marker (Progression Order Change) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_poc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); +/** + * Writes the POC marker (Progression Order Change) + * + * @param p_j2k J2K codec. + * @param p_data FIXME DOC + * @param p_data_written the stream to write data to. + * @param p_manager the user event manager. + */ +static void opj_j2k_write_poc_in_memory(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager); +/** + * Gets the maximum size taken by the writing of a POC. + */ +static OPJ_UINT32 opj_j2k_get_max_poc_size(opj_j2k_t *p_j2k); + +/** + * Reads a POC marker (Progression Order Change) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_poc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Gets the maximum size taken by the toc headers of all the tile parts of any given tile. + */ +static OPJ_UINT32 opj_j2k_get_max_toc_size(opj_j2k_t *p_j2k); + +/** + * Gets the maximum size taken by the headers of the SOT. + * + * @param p_j2k the jpeg2000 codec to use. + */ +static OPJ_UINT32 opj_j2k_get_specific_header_sizes(opj_j2k_t *p_j2k); + +/** + * Reads a CRG marker (Component registration) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_crg(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); +/** + * Reads a TLM marker (Tile Length Marker) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_tlm(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Writes the updated tlm. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_updated_tlm(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a PLM marker (Packet length, main header marker) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_plm(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); +/** + * Reads a PLT marker (Packet length, tile-part header) + * + * @param p_header_data the data contained in the PLT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PLT marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_plt(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Reads a PPM marker (Packed headers, main header) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. + */ + +static OPJ_BOOL opj_j2k_read_ppm( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Merges all PPM markers read (Packed headers, main header) + * + * @param p_cp main coding parameters. + * @param p_manager the user event manager. + */ +static OPJ_BOOL opj_j2k_merge_ppm(opj_cp_t *p_cp, opj_event_mgr_t * p_manager); + +/** + * Reads a PPT marker (Packed packet headers, tile-part header) + * + * @param p_header_data the data contained in the PPT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PPT marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_ppt(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Merges all PPT markers read (Packed headers, tile-part header) + * + * @param p_tcp the tile. + * @param p_manager the user event manager. + */ +static OPJ_BOOL opj_j2k_merge_ppt(opj_tcp_t *p_tcp, + opj_event_mgr_t * p_manager); + + +/** + * Writes the TLM marker (Tile Length Marker) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Writes the SOT marker (Start of tile-part) + * + * @param p_j2k J2K codec. + * @param p_data Output buffer + * @param total_data_size Output buffer size + * @param p_data_written Number of bytes written into stream + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_sot(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 total_data_size, + OPJ_UINT32 * p_data_written, + const opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads values from a SOT marker (Start of tile-part) + * + * the j2k decoder state is not affected. No side effects, no checks except for p_header_size. + * + * @param p_header_data the data contained in the SOT marker. + * @param p_header_size the size of the data contained in the SOT marker. + * @param p_tile_no Isot. + * @param p_tot_len Psot. + * @param p_current_part TPsot. + * @param p_num_parts TNsot. + * @param p_manager the user event manager. + */ +static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + OPJ_UINT32* p_tile_no, + OPJ_UINT32* p_tot_len, + OPJ_UINT32* p_current_part, + OPJ_UINT32* p_num_parts, + opj_event_mgr_t * p_manager); +/** + * Reads a SOT marker (Start of tile-part) + * + * @param p_header_data the data contained in the SOT marker. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PPT marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_sot(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); +/** + * Writes the SOD marker (Start of data) + * + * This also writes optional PLT markers (before SOD) + * + * @param p_j2k J2K codec. + * @param p_tile_coder FIXME DOC + * @param p_data FIXME DOC + * @param p_data_written FIXME DOC + * @param total_data_size FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_sod(opj_j2k_t *p_j2k, + opj_tcd_t * p_tile_coder, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 total_data_size, + const opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a SOD marker (Start Of Data) + * + * @param p_j2k the jpeg2000 codec. + * @param p_stream FIXME DOC + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +static void opj_j2k_update_tlm(opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size) +{ + if (p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte) { + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current, + p_j2k->m_current_tile_number, 1); + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 1; + } else { + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current, + p_j2k->m_current_tile_number, 2); + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 2; + } + + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current, + p_tile_part_size, 4); /* PSOT */ + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 4; +} + +/** + * Writes the RGN marker (Region Of Interest) + * + * @param p_tile_no the tile to output + * @param p_comp_no the component to output + * @param nb_comps the number of components + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_rgn(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_UINT32 nb_comps, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a RGN marker (Region Of Interest) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_rgn(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Writes the EOC marker (End of Codestream) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_eoc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +#if 0 +/** + * Reads a EOC marker (End Of Codestream) + * + * @param p_j2k the jpeg2000 codec. + * @param p_stream FIXME DOC + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_eoc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); +#endif + +/** + * Writes the CBD-MCT-MCC-MCO markers (Multi components transform) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_mct_data_group(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Inits the Info + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_init_info(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** +Add main header marker information +@param cstr_index Codestream information structure +@param type marker type +@param pos byte offset of marker segment +@param len length of marker segment + */ +static OPJ_BOOL opj_j2k_add_mhmarker(opj_codestream_index_t *cstr_index, + OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len) ; +/** +Add tile header marker information +@param tileno tile index number +@param cstr_index Codestream information structure +@param type marker type +@param pos byte offset of marker segment +@param len length of marker segment + */ +static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, + opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, + OPJ_UINT32 len); + +/** + * Reads an unknown marker + * + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream object to read from. + * @param output_marker FIXME DOC + * @param p_manager the user event manager. + * + * @return true if the marker could be deduced. +*/ +static OPJ_BOOL opj_j2k_read_unk(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + OPJ_UINT32 *output_marker, + opj_event_mgr_t * p_manager); + +/** + * Writes the MCT marker (Multiple Component Transform) + * + * @param p_j2k J2K codec. + * @param p_mct_record FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_mct_record(opj_j2k_t *p_j2k, + opj_mct_data_t * p_mct_record, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a MCT marker (Multiple Component Transform) + * + * @param p_header_data the data contained in the MCT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCT marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Writes the MCC marker (Multiple Component Collection) + * + * @param p_j2k J2K codec. + * @param p_mcc_record FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_mcc_record(opj_j2k_t *p_j2k, + opj_simple_mcc_decorrelation_data_t * p_mcc_record, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a MCC marker (Multiple Component Collection) + * + * @param p_header_data the data contained in the MCC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCC marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_mcc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Writes the MCO marker (Multiple component transformation ordering) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_mco(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a MCO marker (Multiple Component Transform Ordering) + * + * @param p_header_data the data contained in the MCO box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCO marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_mco(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, + OPJ_UINT32 p_index); + +static void opj_j2k_read_int16_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_int32_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_float32_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_float64_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); + +static void opj_j2k_read_int16_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_int32_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_float32_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_read_float64_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); + +static void opj_j2k_write_float_to_int16(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_write_float_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_write_float_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); +static void opj_j2k_write_float_to_float64(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); + +/** + * Ends the encoding, i.e. frees memory. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_end_encoding(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Writes the CBD marker (Component bit depth definition) + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_cbd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a CBD marker (Component bit depth definition) + * @param p_header_data the data contained in the CBD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the CBD marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_cbd(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Reads a CAP marker (extended capabilities definition). Empty implementation. + * Found in HTJ2K files + * + * @param p_header_data the data contained in the CAP box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the CAP marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_cap(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Reads a CPF marker (corresponding profile). Empty implementation. Found in HTJ2K files + * @param p_header_data the data contained in the CPF box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the CPF marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_cpf(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + + +/** + * Writes COC marker for each component. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_all_coc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Writes QCC marker for each component. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_all_qcc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Writes regions of interests. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_regions(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Writes EPC ???? + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_write_epc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Checks the progression order changes values. Tells of the poc given as input are valid. + * A nice message is outputted at errors. + * + * @param p_pocs the progression order changes. + * @param tileno the tile number of interest + * @param p_nb_pocs the number of progression order changes. + * @param p_nb_resolutions the number of resolutions. + * @param numcomps the number of components + * @param numlayers the number of layers. + * @param p_manager the user event manager. + * + * @return true if the pocs are valid. + */ +static OPJ_BOOL opj_j2k_check_poc_val(const opj_poc_t *p_pocs, + OPJ_UINT32 tileno, + OPJ_UINT32 p_nb_pocs, + OPJ_UINT32 p_nb_resolutions, + OPJ_UINT32 numcomps, + OPJ_UINT32 numlayers, + opj_event_mgr_t * p_manager); + +/** + * Gets the number of tile parts used for the given change of progression (if any) and the given tile. + * + * @param cp the coding parameters. + * @param pino the offset of the given poc (i.e. its position in the coding parameter). + * @param tileno the given tile. + * + * @return the number of tile parts. + */ +static OPJ_UINT32 opj_j2k_get_num_tp(opj_cp_t *cp, OPJ_UINT32 pino, + OPJ_UINT32 tileno); + +/** + * Calculates the total number of tile parts needed by the encoder to + * encode such an image. If not enough memory is available, then the function return false. + * + * @param p_nb_tiles pointer that will hold the number of tile parts. + * @param cp the coding parameters for the image. + * @param image the image to encode. + * @param p_j2k the p_j2k encoder. + * @param p_manager the user event manager. + * + * @return true if the function was successful, false else. + */ +static OPJ_BOOL opj_j2k_calculate_tp(opj_j2k_t *p_j2k, + opj_cp_t *cp, + OPJ_UINT32 * p_nb_tiles, + opj_image_t *image, + opj_event_mgr_t * p_manager); + +static void opj_j2k_dump_MH_info(opj_j2k_t* p_j2k, FILE* out_stream); + +static void opj_j2k_dump_MH_index(opj_j2k_t* p_j2k, FILE* out_stream); + +static opj_codestream_index_t* opj_j2k_create_cstr_index(void); + +static OPJ_FLOAT32 opj_j2k_get_tp_stride(opj_tcp_t * p_tcp); + +static OPJ_FLOAT32 opj_j2k_get_default_stride(opj_tcp_t * p_tcp); + +static int opj_j2k_initialise_4K_poc(opj_poc_t *POC, int numres); + +static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, + opj_image_t *image, opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, + opj_event_mgr_t *p_manager); + +static void opj_j2k_set_imf_parameters(opj_cparameters_t *parameters, + opj_image_t *image, opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_j2k_is_imf_compliant(opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t *p_manager); + +/** + * Checks for invalid number of tile-parts in SOT marker (TPsot==TNsot). See issue 254. + * + * @param p_stream the stream to read data from. + * @param tile_no tile number we're looking for. + * @param p_correction_needed output value. if true, non conformant codestream needs TNsot correction. + * @param p_manager the user event manager. + * + * @return true if the function was successful, false else. + */ +static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t + *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, + opj_event_mgr_t * p_manager); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ +typedef struct j2k_prog_order { + OPJ_PROG_ORDER enum_prog; + char str_prog[5]; +} j2k_prog_order_t; + +static const j2k_prog_order_t j2k_prog_order_list[] = { + {OPJ_CPRL, "CPRL"}, + {OPJ_LRCP, "LRCP"}, + {OPJ_PCRL, "PCRL"}, + {OPJ_RLCP, "RLCP"}, + {OPJ_RPCL, "RPCL"}, + {(OPJ_PROG_ORDER) - 1, ""} +}; + +/** + * FIXME DOC + */ +static const OPJ_UINT32 MCT_ELEMENT_SIZE [] = { + 2, + 4, + 4, + 8 +}; + +typedef void (* opj_j2k_mct_function)(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem); + +static const opj_j2k_mct_function j2k_mct_read_functions_to_float [] = { + opj_j2k_read_int16_to_float, + opj_j2k_read_int32_to_float, + opj_j2k_read_float32_to_float, + opj_j2k_read_float64_to_float +}; + +static const opj_j2k_mct_function j2k_mct_read_functions_to_int32 [] = { + opj_j2k_read_int16_to_int32, + opj_j2k_read_int32_to_int32, + opj_j2k_read_float32_to_int32, + opj_j2k_read_float64_to_int32 +}; + +static const opj_j2k_mct_function j2k_mct_write_functions_from_float [] = { + opj_j2k_write_float_to_int16, + opj_j2k_write_float_to_int32, + opj_j2k_write_float_to_float, + opj_j2k_write_float_to_float64 +}; + +typedef struct opj_dec_memory_marker_handler { + /** marker value */ + OPJ_UINT32 id; + /** value of the state when the marker can appear */ + OPJ_UINT32 states; + /** action linked to the marker */ + OPJ_BOOL(*handler)(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); +} +opj_dec_memory_marker_handler_t; + +static const opj_dec_memory_marker_handler_t j2k_memory_marker_handler_tab [] = +{ + {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, opj_j2k_read_sot}, + {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_cod}, + {J2K_MS_COC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_coc}, + {J2K_MS_RGN, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_rgn}, + {J2K_MS_QCD, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_qcd}, + {J2K_MS_QCC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_qcc}, + {J2K_MS_POC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_poc}, + {J2K_MS_SIZ, J2K_STATE_MHSIZ, opj_j2k_read_siz}, + {J2K_MS_TLM, J2K_STATE_MH, opj_j2k_read_tlm}, + {J2K_MS_PLM, J2K_STATE_MH, opj_j2k_read_plm}, + {J2K_MS_PLT, J2K_STATE_TPH, opj_j2k_read_plt}, + {J2K_MS_PPM, J2K_STATE_MH, opj_j2k_read_ppm}, + {J2K_MS_PPT, J2K_STATE_TPH, opj_j2k_read_ppt}, + {J2K_MS_SOP, 0, 0}, + {J2K_MS_CRG, J2K_STATE_MH, opj_j2k_read_crg}, + {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_com}, + {J2K_MS_MCT, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mct}, + {J2K_MS_CBD, J2K_STATE_MH, opj_j2k_read_cbd}, + {J2K_MS_CAP, J2K_STATE_MH, opj_j2k_read_cap}, + {J2K_MS_CPF, J2K_STATE_MH, opj_j2k_read_cpf}, + {J2K_MS_MCC, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mcc}, + {J2K_MS_MCO, J2K_STATE_MH | J2K_STATE_TPH, opj_j2k_read_mco}, +#ifdef USE_JPWL +#ifdef TODO_MS /* remove these functions which are not compatible with the v2 API */ + {J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc}, + {J2K_MS_EPB, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epb}, + {J2K_MS_ESD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_esd}, + {J2K_MS_RED, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_red}, +#endif +#endif /* USE_JPWL */ +#ifdef USE_JPSEC + {J2K_MS_SEC, J2K_DEC_STATE_MH, j2k_read_sec}, + {J2K_MS_INSEC, 0, j2k_read_insec} +#endif /* USE_JPSEC */ + {J2K_MS_UNK, J2K_STATE_MH | J2K_STATE_TPH, 0}/*opj_j2k_read_unk is directly used*/ +}; + +static void opj_j2k_read_int16_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + opj_read_bytes(l_src_data, &l_temp, 2); + + l_src_data += sizeof(OPJ_INT16); + + *(l_dest_data++) = (OPJ_FLOAT32) l_temp; + } +} + +static void opj_j2k_read_int32_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + opj_read_bytes(l_src_data, &l_temp, 4); + + l_src_data += sizeof(OPJ_INT32); + + *(l_dest_data++) = (OPJ_FLOAT32) l_temp; + } +} + +static void opj_j2k_read_float32_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_FLOAT32 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + opj_read_float(l_src_data, &l_temp); + + l_src_data += sizeof(OPJ_FLOAT32); + + *(l_dest_data++) = l_temp; + } +} + +static void opj_j2k_read_float64_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_FLOAT64 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + opj_read_double(l_src_data, &l_temp); + + l_src_data += sizeof(OPJ_FLOAT64); + + *(l_dest_data++) = (OPJ_FLOAT32) l_temp; + } +} + +static void opj_j2k_read_int16_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + opj_read_bytes(l_src_data, &l_temp, 2); + + l_src_data += sizeof(OPJ_INT16); + + *(l_dest_data++) = (OPJ_INT32) l_temp; + } +} + +static void opj_j2k_read_int32_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + opj_read_bytes(l_src_data, &l_temp, 4); + + l_src_data += sizeof(OPJ_INT32); + + *(l_dest_data++) = (OPJ_INT32) l_temp; + } +} + +static void opj_j2k_read_float32_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_FLOAT32 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + opj_read_float(l_src_data, &l_temp); + + l_src_data += sizeof(OPJ_FLOAT32); + + *(l_dest_data++) = (OPJ_INT32) l_temp; + } +} + +static void opj_j2k_read_float64_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data; + OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data; + OPJ_UINT32 i; + OPJ_FLOAT64 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + opj_read_double(l_src_data, &l_temp); + + l_src_data += sizeof(OPJ_FLOAT64); + + *(l_dest_data++) = (OPJ_INT32) l_temp; + } +} + +static void opj_j2k_write_float_to_int16(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; + OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + l_temp = (OPJ_UINT32) * (l_src_data++); + + opj_write_bytes(l_dest_data, l_temp, sizeof(OPJ_INT16)); + + l_dest_data += sizeof(OPJ_INT16); + } +} + +static void opj_j2k_write_float_to_int32(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; + OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; + OPJ_UINT32 i; + OPJ_UINT32 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + l_temp = (OPJ_UINT32) * (l_src_data++); + + opj_write_bytes(l_dest_data, l_temp, sizeof(OPJ_INT32)); + + l_dest_data += sizeof(OPJ_INT32); + } +} + +static void opj_j2k_write_float_to_float(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; + OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; + OPJ_UINT32 i; + OPJ_FLOAT32 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + l_temp = (OPJ_FLOAT32) * (l_src_data++); + + opj_write_float(l_dest_data, l_temp); + + l_dest_data += sizeof(OPJ_FLOAT32); + } +} + +static void opj_j2k_write_float_to_float64(const void * p_src_data, + void * p_dest_data, OPJ_UINT32 p_nb_elem) +{ + OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data; + OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data; + OPJ_UINT32 i; + OPJ_FLOAT64 l_temp; + + for (i = 0; i < p_nb_elem; ++i) { + l_temp = (OPJ_FLOAT64) * (l_src_data++); + + opj_write_double(l_dest_data, l_temp); + + l_dest_data += sizeof(OPJ_FLOAT64); + } +} + +const char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order) +{ + const j2k_prog_order_t *po; + for (po = j2k_prog_order_list; po->enum_prog != -1; po++) { + if (po->enum_prog == prg_order) { + return po->str_prog; + } + } + return po->str_prog; +} + +static OPJ_BOOL opj_j2k_check_poc_val(const opj_poc_t *p_pocs, + OPJ_UINT32 tileno, + OPJ_UINT32 p_nb_pocs, + OPJ_UINT32 p_nb_resolutions, + OPJ_UINT32 p_num_comps, + OPJ_UINT32 p_num_layers, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32* packet_array; + OPJ_UINT32 index, resno, compno, layno; + OPJ_UINT32 i; + OPJ_UINT32 step_c = 1; + OPJ_UINT32 step_r = p_num_comps * step_c; + OPJ_UINT32 step_l = p_nb_resolutions * step_r; + OPJ_BOOL loss = OPJ_FALSE; + + assert(p_nb_pocs > 0); + + packet_array = (OPJ_UINT32*) opj_calloc((size_t)step_l * p_num_layers, + sizeof(OPJ_UINT32)); + if (packet_array == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory for checking the poc values.\n"); + return OPJ_FALSE; + } + + /* iterate through all the pocs that match our tile of interest. */ + for (i = 0; i < p_nb_pocs; ++i) { + const opj_poc_t *poc = &p_pocs[i]; + if (tileno + 1 == poc->tile) { + index = step_r * poc->resno0; + + /* take each resolution for each poc */ + for (resno = poc->resno0 ; + resno < opj_uint_min(poc->resno1, p_nb_resolutions); ++resno) { + OPJ_UINT32 res_index = index + poc->compno0 * step_c; + + /* take each comp of each resolution for each poc */ + for (compno = poc->compno0 ; + compno < opj_uint_min(poc->compno1, p_num_comps); ++compno) { + /* The layer index always starts at zero for every progression. */ + const OPJ_UINT32 layno0 = 0; + OPJ_UINT32 comp_index = res_index + layno0 * step_l; + + /* and finally take each layer of each res of ... */ + for (layno = layno0; layno < opj_uint_min(poc->layno1, p_num_layers); + ++layno) { + packet_array[comp_index] = 1; + comp_index += step_l; + } + + res_index += step_c; + } + + index += step_r; + } + } + } + + index = 0; + for (layno = 0; layno < p_num_layers ; ++layno) { + for (resno = 0; resno < p_nb_resolutions; ++resno) { + for (compno = 0; compno < p_num_comps; ++compno) { + loss |= (packet_array[index] != 1); +#ifdef DEBUG_VERBOSE + if (packet_array[index] != 1) { + fprintf(stderr, + "Missing packet in POC: layno=%d resno=%d compno=%d\n", + layno, resno, compno); + } +#endif + index += step_c; + } + } + } + + if (loss) { + opj_event_msg(p_manager, EVT_ERROR, "Missing packets possible loss of data\n"); + } + + opj_free(packet_array); + + return !loss; +} + +/* ----------------------------------------------------------------------- */ + +static OPJ_UINT32 opj_j2k_get_num_tp(opj_cp_t *cp, OPJ_UINT32 pino, + OPJ_UINT32 tileno) +{ + const OPJ_CHAR *prog = 00; + OPJ_INT32 i; + OPJ_UINT32 tpnum = 1; + opj_tcp_t *tcp = 00; + opj_poc_t * l_current_poc = 00; + + /* preconditions */ + assert(tileno < (cp->tw * cp->th)); + assert(pino < (cp->tcps[tileno].numpocs + 1)); + + /* get the given tile coding parameter */ + tcp = &cp->tcps[tileno]; + assert(tcp != 00); + + l_current_poc = &(tcp->pocs[pino]); + assert(l_current_poc != 0); + + /* get the progression order as a character string */ + prog = opj_j2k_convert_progression_order(tcp->prg); + assert(strlen(prog) > 0); + + if (cp->m_specific_param.m_enc.m_tp_on == 1) { + for (i = 0; i < 4; ++i) { + switch (prog[i]) { + /* component wise */ + case 'C': + tpnum *= l_current_poc->compE; + break; + /* resolution wise */ + case 'R': + tpnum *= l_current_poc->resE; + break; + /* precinct wise */ + case 'P': + tpnum *= l_current_poc->prcE; + break; + /* layer wise */ + case 'L': + tpnum *= l_current_poc->layE; + break; + } + /* would we split here ? */ + if (cp->m_specific_param.m_enc.m_tp_flag == prog[i]) { + cp->m_specific_param.m_enc.m_tp_pos = i; + break; + } + } + } else { + tpnum = 1; + } + + return tpnum; +} + +static OPJ_BOOL opj_j2k_calculate_tp(opj_j2k_t *p_j2k, + opj_cp_t *cp, + OPJ_UINT32 * p_nb_tiles, + opj_image_t *image, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 pino, tileno; + OPJ_UINT32 l_nb_tiles; + opj_tcp_t *tcp; + + /* preconditions */ + assert(p_nb_tiles != 00); + assert(cp != 00); + assert(image != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_j2k); + OPJ_UNUSED(p_manager); + + l_nb_tiles = cp->tw * cp->th; + * p_nb_tiles = 0; + tcp = cp->tcps; + + /* INDEX >> */ + /* TODO mergeV2: check this part which use cstr_info */ + /*if (p_j2k->cstr_info) { + opj_tile_info_t * l_info_tile_ptr = p_j2k->cstr_info->tile; + + for (tileno = 0; tileno < l_nb_tiles; ++tileno) { + OPJ_UINT32 cur_totnum_tp = 0; + + opj_pi_update_encoding_parameters(image,cp,tileno); + + for (pino = 0; pino <= tcp->numpocs; ++pino) + { + OPJ_UINT32 tp_num = opj_j2k_get_num_tp(cp,pino,tileno); + + *p_nb_tiles = *p_nb_tiles + tp_num; + + cur_totnum_tp += tp_num; + } + + tcp->m_nb_tile_parts = cur_totnum_tp; + + l_info_tile_ptr->tp = (opj_tp_info_t *) opj_malloc(cur_totnum_tp * sizeof(opj_tp_info_t)); + if (l_info_tile_ptr->tp == 00) { + return OPJ_FALSE; + } + + memset(l_info_tile_ptr->tp,0,cur_totnum_tp * sizeof(opj_tp_info_t)); + + l_info_tile_ptr->num_tps = cur_totnum_tp; + + ++l_info_tile_ptr; + ++tcp; + } + } + else */{ + for (tileno = 0; tileno < l_nb_tiles; ++tileno) { + OPJ_UINT32 cur_totnum_tp = 0; + + opj_pi_update_encoding_parameters(image, cp, tileno); + + for (pino = 0; pino <= tcp->numpocs; ++pino) { + OPJ_UINT32 tp_num = opj_j2k_get_num_tp(cp, pino, tileno); + + *p_nb_tiles = *p_nb_tiles + tp_num; + + cur_totnum_tp += tp_num; + } + tcp->m_nb_tile_parts = cur_totnum_tp; + + ++tcp; + } + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_soc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + /* 2 bytes will be written */ + OPJ_BYTE * l_start_stream = 00; + + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_start_stream = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + /* write SOC identifier */ + opj_write_bytes(l_start_stream, J2K_MS_SOC, 2); + + if (opj_stream_write_data(p_stream, l_start_stream, 2, p_manager) != 2) { + return OPJ_FALSE; + } + + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + /* + OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOC, p_stream_tell(p_stream) - 2, 2); + */ + assert(0 && "TODO"); +#endif /* USE_JPWL */ + /* <m_specific_param.m_decoder.m_state = J2K_STATE_MHSIZ; + + /* FIXME move it in a index structure included in p_j2k*/ + p_j2k->cstr_index->main_head_start = opj_stream_tell(p_stream) - 2; + + opj_event_msg(p_manager, EVT_INFO, + "Start to read j2k main header (%" PRId64 ").\n", + p_j2k->cstr_index->main_head_start); + + /* Add the marker to the codestream index*/ + if (OPJ_FALSE == opj_j2k_add_mhmarker(p_j2k->cstr_index, J2K_MS_SOC, + p_j2k->cstr_index->main_head_start, 2)) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); + return OPJ_FALSE; + } + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_siz(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_size_len; + OPJ_BYTE * l_current_ptr; + opj_image_t * l_image = 00; + opj_cp_t *cp = 00; + opj_image_comp_t * l_img_comp = 00; + + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_private_image; + cp = &(p_j2k->m_cp); + l_size_len = 40 + 3 * l_image->numcomps; + l_img_comp = l_image->comps; + + if (l_size_len > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_size_len); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for the SIZ marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_size_len; + } + + l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + /* write SOC identifier */ + opj_write_bytes(l_current_ptr, J2K_MS_SIZ, 2); /* SIZ */ + l_current_ptr += 2; + + opj_write_bytes(l_current_ptr, l_size_len - 2, 2); /* L_SIZ */ + l_current_ptr += 2; + + opj_write_bytes(l_current_ptr, cp->rsiz, 2); /* Rsiz (capabilities) */ + l_current_ptr += 2; + + opj_write_bytes(l_current_ptr, l_image->x1, 4); /* Xsiz */ + l_current_ptr += 4; + + opj_write_bytes(l_current_ptr, l_image->y1, 4); /* Ysiz */ + l_current_ptr += 4; + + opj_write_bytes(l_current_ptr, l_image->x0, 4); /* X0siz */ + l_current_ptr += 4; + + opj_write_bytes(l_current_ptr, l_image->y0, 4); /* Y0siz */ + l_current_ptr += 4; + + opj_write_bytes(l_current_ptr, cp->tdx, 4); /* XTsiz */ + l_current_ptr += 4; + + opj_write_bytes(l_current_ptr, cp->tdy, 4); /* YTsiz */ + l_current_ptr += 4; + + opj_write_bytes(l_current_ptr, cp->tx0, 4); /* XT0siz */ + l_current_ptr += 4; + + opj_write_bytes(l_current_ptr, cp->ty0, 4); /* YT0siz */ + l_current_ptr += 4; + + opj_write_bytes(l_current_ptr, l_image->numcomps, 2); /* Csiz */ + l_current_ptr += 2; + + for (i = 0; i < l_image->numcomps; ++i) { + /* TODO here with MCT ? */ + opj_write_bytes(l_current_ptr, l_img_comp->prec - 1 + (l_img_comp->sgnd << 7), + 1); /* Ssiz_i */ + ++l_current_ptr; + + opj_write_bytes(l_current_ptr, l_img_comp->dx, 1); /* XRsiz_i */ + ++l_current_ptr; + + opj_write_bytes(l_current_ptr, l_img_comp->dy, 1); /* YRsiz_i */ + ++l_current_ptr; + + ++l_img_comp; + } + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_size_len, + p_manager) != l_size_len) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads a SIZ marker (image and tile size) + * @param p_j2k the jpeg2000 file codec. + * @param p_header_data the data contained in the SIZ box. + * @param p_header_size the size of the data contained in the SIZ marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_comp_remain; + OPJ_UINT32 l_remaining_size; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 l_tmp, l_tx1, l_ty1; + OPJ_UINT32 l_prec0, l_sgnd0; + opj_image_t *l_image = 00; + opj_cp_t *l_cp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_tcp_t * l_current_tile_param = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + + l_image = p_j2k->m_private_image; + l_cp = &(p_j2k->m_cp); + + /* minimum size == 39 - 3 (= minimum component parameter) */ + if (p_header_size < 36) { + opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); + return OPJ_FALSE; + } + + l_remaining_size = p_header_size - 36; + l_nb_comp = l_remaining_size / 3; + l_nb_comp_remain = l_remaining_size % 3; + if (l_nb_comp_remain != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &l_tmp, + 2); /* Rsiz (capabilities) */ + p_header_data += 2; + l_cp->rsiz = (OPJ_UINT16) l_tmp; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->x1, 4); /* Xsiz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->y1, 4); /* Ysiz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->x0, 4); /* X0siz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_image->y0, 4); /* Y0siz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->tdx, + 4); /* XTsiz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->tdy, + 4); /* YTsiz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->tx0, + 4); /* XT0siz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_cp->ty0, + 4); /* YT0siz */ + p_header_data += 4; + opj_read_bytes(p_header_data, (OPJ_UINT32*) &l_tmp, + 2); /* Csiz */ + p_header_data += 2; + if (l_tmp < 16385) { + l_image->numcomps = (OPJ_UINT16) l_tmp; + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: number of component is illegal -> %d\n", l_tmp); + return OPJ_FALSE; + } + + if (l_image->numcomps != l_nb_comp) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: number of component is not compatible with the remaining number of parameters ( %d vs %d)\n", + l_image->numcomps, l_nb_comp); + return OPJ_FALSE; + } + + /* testcase 4035.pdf.SIGSEGV.d8b.3375 */ + /* testcase issue427-null-image-size.jp2 */ + if ((l_image->x0 >= l_image->x1) || (l_image->y0 >= l_image->y1)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: negative or zero image size (%" PRId64 " x %" PRId64 + ")\n", (OPJ_INT64)l_image->x1 - l_image->x0, + (OPJ_INT64)l_image->y1 - l_image->y0); + return OPJ_FALSE; + } + /* testcase 2539.pdf.SIGFPE.706.1712 (also 3622.pdf.SIGFPE.706.2916 and 4008.pdf.SIGFPE.706.3345 and maybe more) */ + if ((l_cp->tdx == 0U) || (l_cp->tdy == 0U)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: invalid tile size (tdx: %d, tdy: %d)\n", l_cp->tdx, + l_cp->tdy); + return OPJ_FALSE; + } + + /* testcase issue427-illegal-tile-offset.jp2 */ + l_tx1 = opj_uint_adds(l_cp->tx0, l_cp->tdx); /* manage overflow */ + l_ty1 = opj_uint_adds(l_cp->ty0, l_cp->tdy); /* manage overflow */ + if ((l_cp->tx0 > l_image->x0) || (l_cp->ty0 > l_image->y0) || + (l_tx1 <= l_image->x0) || (l_ty1 <= l_image->y0)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: illegal tile offset\n"); + return OPJ_FALSE; + } + if (!p_j2k->dump_state) { + OPJ_UINT32 siz_w, siz_h; + + siz_w = l_image->x1 - l_image->x0; + siz_h = l_image->y1 - l_image->y0; + + if (p_j2k->ihdr_w > 0 && p_j2k->ihdr_h > 0 + && (p_j2k->ihdr_w != siz_w || p_j2k->ihdr_h != siz_h)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with SIZ marker: IHDR w(%u) h(%u) vs. SIZ w(%u) h(%u)\n", p_j2k->ihdr_w, + p_j2k->ihdr_h, siz_w, siz_h); + return OPJ_FALSE; + } + } +#ifdef USE_JPWL + if (l_cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters */ + if (!(l_image->x1 * l_image->y1)) { + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad image size (%d x %d)\n", + l_image->x1, l_image->y1); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + } + + /* FIXME check previously in the function so why keep this piece of code ? Need by the norm ? + if (l_image->numcomps != ((len - 38) / 3)) { + opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: Csiz is %d => space in SIZ only for %d comps.!!!\n", + l_image->numcomps, ((len - 38) / 3)); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + */ /* we try to correct */ + /* opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n"); + if (l_image->numcomps < ((len - 38) / 3)) { + len = 38 + 3 * l_image->numcomps; + opj_event_msg(p_manager, EVT_WARNING, "- setting Lsiz to %d => HYPOTHESIS!!!\n", + len); + } else { + l_image->numcomps = ((len - 38) / 3); + opj_event_msg(p_manager, EVT_WARNING, "- setting Csiz to %d => HYPOTHESIS!!!\n", + l_image->numcomps); + } + } + */ + + /* update components number in the jpwl_exp_comps filed */ + l_cp->exp_comps = l_image->numcomps; + } +#endif /* USE_JPWL */ + + /* Allocate the resulting image components */ + l_image->comps = (opj_image_comp_t*) opj_calloc(l_image->numcomps, + sizeof(opj_image_comp_t)); + if (l_image->comps == 00) { + l_image->numcomps = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } + + l_img_comp = l_image->comps; + + l_prec0 = 0; + l_sgnd0 = 0; + /* Read the component information */ + for (i = 0; i < l_image->numcomps; ++i) { + OPJ_UINT32 tmp; + opj_read_bytes(p_header_data, &tmp, 1); /* Ssiz_i */ + ++p_header_data; + l_img_comp->prec = (tmp & 0x7f) + 1; + l_img_comp->sgnd = tmp >> 7; + + if (p_j2k->dump_state == 0) { + if (i == 0) { + l_prec0 = l_img_comp->prec; + l_sgnd0 = l_img_comp->sgnd; + } else if (!l_cp->allow_different_bit_depth_sign + && (l_img_comp->prec != l_prec0 || l_img_comp->sgnd != l_sgnd0)) { + opj_event_msg(p_manager, EVT_WARNING, + "Despite JP2 BPC!=255, precision and/or sgnd values for comp[%d] is different than comp[0]:\n" + " [0] prec(%d) sgnd(%d) [%d] prec(%d) sgnd(%d)\n", i, l_prec0, l_sgnd0, + i, l_img_comp->prec, l_img_comp->sgnd); + } + /* TODO: we should perhaps also check against JP2 BPCC values */ + } + opj_read_bytes(p_header_data, &tmp, 1); /* XRsiz_i */ + ++p_header_data; + l_img_comp->dx = (OPJ_UINT32)tmp; /* should be between 1 and 255 */ + opj_read_bytes(p_header_data, &tmp, 1); /* YRsiz_i */ + ++p_header_data; + l_img_comp->dy = (OPJ_UINT32)tmp; /* should be between 1 and 255 */ + if (l_img_comp->dx < 1 || l_img_comp->dx > 255 || + l_img_comp->dy < 1 || l_img_comp->dy > 255) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid values for comp = %d : dx=%u dy=%u (should be between 1 and 255 according to the JPEG2000 norm)\n", + i, l_img_comp->dx, l_img_comp->dy); + return OPJ_FALSE; + } + /* Avoids later undefined shift in computation of */ + /* p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[i].m_dc_level_shift = 1 + << (l_image->comps[i].prec - 1); */ + if (l_img_comp->prec > 31) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid values for comp = %d : prec=%u (should be between 1 and 38 according to the JPEG2000 norm. OpenJpeg only supports up to 31)\n", + i, l_img_comp->prec); + return OPJ_FALSE; + } +#ifdef USE_JPWL + if (l_cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters, again */ + if (!(l_image->comps[i].dx * l_image->comps[i].dy)) { + opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad XRsiz_%d/YRsiz_%d (%d x %d)\n", + i, i, l_image->comps[i].dx, l_image->comps[i].dy); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust them\n"); + if (!l_image->comps[i].dx) { + l_image->comps[i].dx = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- setting XRsiz_%d to %d => HYPOTHESIS!!!\n", + i, l_image->comps[i].dx); + } + if (!l_image->comps[i].dy) { + l_image->comps[i].dy = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- setting YRsiz_%d to %d => HYPOTHESIS!!!\n", + i, l_image->comps[i].dy); + } + } + } +#endif /* USE_JPWL */ + l_img_comp->resno_decoded = + 0; /* number of resolution decoded */ + l_img_comp->factor = + l_cp->m_specific_param.m_dec.m_reduce; /* reducing factor per component */ + ++l_img_comp; + } + + if (l_cp->tdx == 0 || l_cp->tdy == 0) { + return OPJ_FALSE; + } + + /* Compute the number of tiles */ + l_cp->tw = opj_uint_ceildiv(l_image->x1 - l_cp->tx0, l_cp->tdx); + l_cp->th = opj_uint_ceildiv(l_image->y1 - l_cp->ty0, l_cp->tdy); + + /* Check that the number of tiles is valid */ + if (l_cp->tw == 0 || l_cp->th == 0 || l_cp->tw > 65535 / l_cp->th) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid number of tiles : %u x %u (maximum fixed by jpeg2000 norm is 65535 tiles)\n", + l_cp->tw, l_cp->th); + return OPJ_FALSE; + } + l_nb_tiles = l_cp->tw * l_cp->th; + + /* Define the tiles which will be decoded */ + if (p_j2k->m_specific_param.m_decoder.m_discard_tiles) { + p_j2k->m_specific_param.m_decoder.m_start_tile_x = + (p_j2k->m_specific_param.m_decoder.m_start_tile_x - l_cp->tx0) / l_cp->tdx; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = + (p_j2k->m_specific_param.m_decoder.m_start_tile_y - l_cp->ty0) / l_cp->tdy; + p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv( + p_j2k->m_specific_param.m_decoder.m_end_tile_x - l_cp->tx0, + l_cp->tdx); + p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv( + p_j2k->m_specific_param.m_decoder.m_end_tile_y - l_cp->ty0, + l_cp->tdy); + } else { + p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; + p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; + p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; + } + +#ifdef USE_JPWL + if (l_cp->correct) { + /* if JPWL is on, we check whether TX errors have damaged + too much the SIZ parameters */ + if ((l_cp->tw < 1) || (l_cp->th < 1) || (l_cp->tw > l_cp->max_tiles) || + (l_cp->th > l_cp->max_tiles)) { + opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad number of tiles (%d x %d)\n", + l_cp->tw, l_cp->th); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust them\n"); + if (l_cp->tw < 1) { + l_cp->tw = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- setting %d tiles in x => HYPOTHESIS!!!\n", + l_cp->tw); + } + if (l_cp->tw > l_cp->max_tiles) { + l_cp->tw = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- too large x, increase expectance of %d\n" + "- setting %d tiles in x => HYPOTHESIS!!!\n", + l_cp->max_tiles, l_cp->tw); + } + if (l_cp->th < 1) { + l_cp->th = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- setting %d tiles in y => HYPOTHESIS!!!\n", + l_cp->th); + } + if (l_cp->th > l_cp->max_tiles) { + l_cp->th = 1; + opj_event_msg(p_manager, EVT_WARNING, + "- too large y, increase expectance of %d to continue\n", + "- setting %d tiles in y => HYPOTHESIS!!!\n", + l_cp->max_tiles, l_cp->th); + } + } + } +#endif /* USE_JPWL */ + + /* memory allocations */ + l_cp->tcps = (opj_tcp_t*) opj_calloc(l_nb_tiles, sizeof(opj_tcp_t)); + if (l_cp->tcps == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } + +#ifdef USE_JPWL + if (l_cp->correct) { + if (!l_cp->tcps) { + opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: could not alloc tcps field of cp\n"); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + } + } +#endif /* USE_JPWL */ + + p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps = + (opj_tccp_t*) opj_calloc(l_image->numcomps, sizeof(opj_tccp_t)); + if (p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } + + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records = + (opj_mct_data_t*)opj_calloc(OPJ_J2K_MCT_DEFAULT_NB_RECORDS, + sizeof(opj_mct_data_t)); + + if (! p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mct_records = + OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records = + (opj_simple_mcc_decorrelation_data_t*) + opj_calloc(OPJ_J2K_MCC_DEFAULT_NB_RECORDS, + sizeof(opj_simple_mcc_decorrelation_data_t)); + + if (! p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mcc_records = + OPJ_J2K_MCC_DEFAULT_NB_RECORDS; + + /* set up default dc level shift */ + for (i = 0; i < l_image->numcomps; ++i) { + if (! l_image->comps[i].sgnd) { + p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[i].m_dc_level_shift = 1 + << (l_image->comps[i].prec - 1); + } + } + + l_current_tile_param = l_cp->tcps; + for (i = 0; i < l_nb_tiles; ++i) { + l_current_tile_param->tccps = (opj_tccp_t*) opj_calloc(l_image->numcomps, + sizeof(opj_tccp_t)); + if (l_current_tile_param->tccps == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to take in charge SIZ marker\n"); + return OPJ_FALSE; + } + + ++l_current_tile_param; + } + + /*Allocate and initialize some elements of codestrem index*/ + if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)) { + return OPJ_FALSE; + } + + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MH; + opj_image_comp_header_update(l_image, l_cp); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_com(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_comment_size; + OPJ_UINT32 l_total_com_size; + const OPJ_CHAR *l_comment; + OPJ_BYTE * l_current_ptr = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + l_comment = p_j2k->m_cp.comment; + l_comment_size = (OPJ_UINT32)strlen(l_comment); + l_total_com_size = l_comment_size + 6; + + if (l_total_com_size > + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_total_com_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to write the COM marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_total_com_size; + } + + l_current_ptr = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_ptr, J2K_MS_COM, 2); /* COM */ + l_current_ptr += 2; + + opj_write_bytes(l_current_ptr, l_total_com_size - 2, 2); /* L_COM */ + l_current_ptr += 2; + + opj_write_bytes(l_current_ptr, 1, + 2); /* General use (IS 8859-15:1999 (Latin) values) */ + l_current_ptr += 2; + + memcpy(l_current_ptr, l_comment, l_comment_size); + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_total_com_size, + p_manager) != l_total_com_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads a COM marker (comments) + * @param p_j2k the jpeg2000 file codec. + * @param p_header_data the data contained in the COM box. + * @param p_header_size the size of the data contained in the COM marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_com(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + + OPJ_UNUSED(p_j2k); + OPJ_UNUSED(p_header_data); + OPJ_UNUSED(p_header_size); + OPJ_UNUSED(p_manager); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_cod(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_code_size, l_remaining_size; + OPJ_BYTE * l_current_data = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_code_size = 9 + opj_j2k_get_SPCod_SPCoc_size(p_j2k, + p_j2k->m_current_tile_number, 0); + l_remaining_size = l_code_size; + + if (l_code_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_code_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write COD marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_code_size; + } + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data, J2K_MS_COD, 2); /* COD */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_code_size - 2, 2); /* L_COD */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_tcp->csty, 1); /* Scod */ + ++l_current_data; + + opj_write_bytes(l_current_data, (OPJ_UINT32)l_tcp->prg, 1); /* SGcod (A) */ + ++l_current_data; + + opj_write_bytes(l_current_data, l_tcp->numlayers, 2); /* SGcod (B) */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_tcp->mct, 1); /* SGcod (C) */ + ++l_current_data; + + l_remaining_size -= 9; + + if (! opj_j2k_write_SPCod_SPCoc(p_j2k, p_j2k->m_current_tile_number, 0, + l_current_data, &l_remaining_size, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing COD marker\n"); + return OPJ_FALSE; + } + + if (l_remaining_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing COD marker\n"); + return OPJ_FALSE; + } + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_code_size, + p_manager) != l_code_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads a COD marker (Coding style defaults) + * @param p_header_data the data contained in the COD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COD marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_cod(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + /* loop */ + OPJ_UINT32 i; + OPJ_UINT32 l_tmp; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_image_t *l_image = 00; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_private_image; + l_cp = &(p_j2k->m_cp); + + /* If we are in the first tile-part header of the current tile */ + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + +#if 0 + /* This check was added per https://github.com/uclouvain/openjpeg/commit/daed8cc9195555e101ab708a501af2dfe6d5e001 */ + /* but this is no longer necessary to handle issue476.jp2 */ + /* and this actually cause issues on legit files. See https://github.com/uclouvain/openjpeg/issues/1043 */ + /* Only one COD per tile */ + if (l_tcp->cod) { + opj_event_msg(p_manager, EVT_ERROR, + "COD marker already read. No more than one COD marker per tile.\n"); + return OPJ_FALSE; + } +#endif + l_tcp->cod = 1; + + /* Make sure room is sufficient */ + if (p_header_size < 5) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &l_tcp->csty, 1); /* Scod */ + ++p_header_data; + /* Make sure we know how to decode this */ + if ((l_tcp->csty & ~(OPJ_UINT32)(J2K_CP_CSTY_PRT | J2K_CP_CSTY_SOP | + J2K_CP_CSTY_EPH)) != 0U) { + opj_event_msg(p_manager, EVT_ERROR, "Unknown Scod value in COD marker\n"); + return OPJ_FALSE; + } + opj_read_bytes(p_header_data, &l_tmp, 1); /* SGcod (A) */ + ++p_header_data; + l_tcp->prg = (OPJ_PROG_ORDER) l_tmp; + /* Make sure progression order is valid */ + if (l_tcp->prg > OPJ_CPRL) { + opj_event_msg(p_manager, EVT_ERROR, + "Unknown progression order in COD marker\n"); + l_tcp->prg = OPJ_PROG_UNKNOWN; + } + opj_read_bytes(p_header_data, &l_tcp->numlayers, 2); /* SGcod (B) */ + p_header_data += 2; + + if ((l_tcp->numlayers < 1U) || (l_tcp->numlayers > 65535U)) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid number of layers in COD marker : %d not in range [1-65535]\n", + l_tcp->numlayers); + return OPJ_FALSE; + } + + /* If user didn't set a number layer to decode take the max specify in the codestream. */ + if (l_cp->m_specific_param.m_dec.m_layer) { + l_tcp->num_layers_to_decode = l_cp->m_specific_param.m_dec.m_layer; + } else { + l_tcp->num_layers_to_decode = l_tcp->numlayers; + } + + opj_read_bytes(p_header_data, &l_tcp->mct, 1); /* SGcod (C) */ + ++p_header_data; + + if (l_tcp->mct > 1) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid multiple component transformation\n"); + return OPJ_FALSE; + } + + p_header_size -= 5; + for (i = 0; i < l_image->numcomps; ++i) { + l_tcp->tccps[i].csty = l_tcp->csty & J2K_CCP_CSTY_PRT; + } + + if (! opj_j2k_read_SPCod_SPCoc(p_j2k, 0, p_header_data, &p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); + return OPJ_FALSE; + } + + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); + return OPJ_FALSE; + } + + /* Apply the coding style to other components of the current tile or the m_default_tcp*/ + opj_j2k_copy_tile_component_parameters(p_j2k); + + /* Index */ +#ifdef WIP_REMOVE_MSD + if (p_j2k->cstr_info) { + /*opj_codestream_info_t *l_cstr_info = p_j2k->cstr_info;*/ + p_j2k->cstr_info->prog = l_tcp->prg; + p_j2k->cstr_info->numlayers = l_tcp->numlayers; + p_j2k->cstr_info->numdecompos = (OPJ_INT32*) opj_malloc( + l_image->numcomps * sizeof(OPJ_UINT32)); + if (!p_j2k->cstr_info->numdecompos) { + return OPJ_FALSE; + } + for (i = 0; i < l_image->numcomps; ++i) { + p_j2k->cstr_info->numdecompos[i] = l_tcp->tccps[i].numresolutions - 1; + } + } +#endif + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_coc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 l_coc_size, l_remaining_size; + OPJ_UINT32 l_comp_room; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_comp_room = (p_j2k->m_private_image->numcomps <= 256) ? 1 : 2; + + l_coc_size = 5 + l_comp_room + opj_j2k_get_SPCod_SPCoc_size(p_j2k, + p_j2k->m_current_tile_number, p_comp_no); + + if (l_coc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data; + /*p_j2k->m_specific_param.m_encoder.m_header_tile_data + = (OPJ_BYTE*)opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, + l_coc_size);*/ + + new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_coc_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write COC marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_coc_size; + } + + opj_j2k_write_coc_in_memory(p_j2k, p_comp_no, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, &l_remaining_size, + p_manager); + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_coc_size, + p_manager) != l_coc_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_compare_coc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no) +{ + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + + /* preconditions */ + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + + if (l_tcp->tccps[p_first_comp_no].csty != l_tcp->tccps[p_second_comp_no].csty) { + return OPJ_FALSE; + } + + + return opj_j2k_compare_SPCod_SPCoc(p_j2k, p_j2k->m_current_tile_number, + p_first_comp_no, p_second_comp_no); +} + +static void opj_j2k_write_coc_in_memory(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager + ) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_coc_size, l_remaining_size; + OPJ_BYTE * l_current_data = 00; + opj_image_t *l_image = 00; + OPJ_UINT32 l_comp_room; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_image = p_j2k->m_private_image; + l_comp_room = (l_image->numcomps <= 256) ? 1 : 2; + + l_coc_size = 5 + l_comp_room + opj_j2k_get_SPCod_SPCoc_size(p_j2k, + p_j2k->m_current_tile_number, p_comp_no); + l_remaining_size = l_coc_size; + + l_current_data = p_data; + + opj_write_bytes(l_current_data, J2K_MS_COC, + 2); /* COC */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_coc_size - 2, + 2); /* L_COC */ + l_current_data += 2; + + opj_write_bytes(l_current_data, p_comp_no, l_comp_room); /* Ccoc */ + l_current_data += l_comp_room; + + opj_write_bytes(l_current_data, l_tcp->tccps[p_comp_no].csty, + 1); /* Scoc */ + ++l_current_data; + + l_remaining_size -= (5 + l_comp_room); + opj_j2k_write_SPCod_SPCoc(p_j2k, p_j2k->m_current_tile_number, 0, + l_current_data, &l_remaining_size, p_manager); + * p_data_written = l_coc_size; +} + +static OPJ_UINT32 opj_j2k_get_max_coc_size(opj_j2k_t *p_j2k) +{ + OPJ_UINT32 i, j; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 l_max = 0; + + /* preconditions */ + + l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ; + l_nb_comp = p_j2k->m_private_image->numcomps; + + for (i = 0; i < l_nb_tiles; ++i) { + for (j = 0; j < l_nb_comp; ++j) { + l_max = opj_uint_max(l_max, opj_j2k_get_SPCod_SPCoc_size(p_j2k, i, j)); + } + } + + return 6 + l_max; +} + +/** + * Reads a COC marker (Coding Style Component) + * @param p_header_data the data contained in the COC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the COC marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_coc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_image_t *l_image = NULL; + OPJ_UINT32 l_comp_room; + OPJ_UINT32 l_comp_no; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) + ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_image = p_j2k->m_private_image; + + l_comp_room = l_image->numcomps <= 256 ? 1 : 2; + + /* make sure room is sufficient*/ + if (p_header_size < l_comp_room + 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); + return OPJ_FALSE; + } + p_header_size -= l_comp_room + 1; + + opj_read_bytes(p_header_data, &l_comp_no, + l_comp_room); /* Ccoc */ + p_header_data += l_comp_room; + if (l_comp_no >= l_image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, + "Error reading COC marker (bad number of components)\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &l_tcp->tccps[l_comp_no].csty, + 1); /* Scoc */ + ++p_header_data ; + + if (! opj_j2k_read_SPCod_SPCoc(p_j2k, l_comp_no, p_header_data, &p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); + return OPJ_FALSE; + } + + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); + return OPJ_FALSE; + } + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_qcd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_qcd_size, l_remaining_size; + OPJ_BYTE * l_current_data = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_qcd_size = 4 + opj_j2k_get_SQcd_SQcc_size(p_j2k, p_j2k->m_current_tile_number, + 0); + l_remaining_size = l_qcd_size; + + if (l_qcd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcd_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write QCD marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcd_size; + } + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data, J2K_MS_QCD, 2); /* QCD */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_qcd_size - 2, 2); /* L_QCD */ + l_current_data += 2; + + l_remaining_size -= 4; + + if (! opj_j2k_write_SQcd_SQcc(p_j2k, p_j2k->m_current_tile_number, 0, + l_current_data, &l_remaining_size, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing QCD marker\n"); + return OPJ_FALSE; + } + + if (l_remaining_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing QCD marker\n"); + return OPJ_FALSE; + } + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcd_size, + p_manager) != l_qcd_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads a QCD marker (Quantization defaults) + * @param p_header_data the data contained in the QCD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the QCD marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_qcd(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if (! opj_j2k_read_SQcd_SQcc(p_j2k, 0, p_header_data, &p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCD marker\n"); + return OPJ_FALSE; + } + + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCD marker\n"); + return OPJ_FALSE; + } + + /* Apply the quantization parameters to other components of the current tile or the m_default_tcp */ + opj_j2k_copy_tile_quantization_parameters(p_j2k); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_qcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_qcc_size, l_remaining_size; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_qcc_size = 5 + opj_j2k_get_SQcd_SQcc_size(p_j2k, p_j2k->m_current_tile_number, + p_comp_no); + l_qcc_size += p_j2k->m_private_image->numcomps <= 256 ? 0 : 1; + l_remaining_size = l_qcc_size; + + if (l_qcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcc_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write QCC marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcc_size; + } + + opj_j2k_write_qcc_in_memory(p_j2k, p_comp_no, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, &l_remaining_size, + p_manager); + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_qcc_size, + p_manager) != l_qcc_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_compare_qcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no) +{ + return opj_j2k_compare_SQcd_SQcc(p_j2k, p_j2k->m_current_tile_number, + p_first_comp_no, p_second_comp_no); +} + +static void opj_j2k_write_qcc_in_memory(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_qcc_size, l_remaining_size; + OPJ_BYTE * l_current_data = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + + l_qcc_size = 6 + opj_j2k_get_SQcd_SQcc_size(p_j2k, p_j2k->m_current_tile_number, + p_comp_no); + l_remaining_size = l_qcc_size; + + l_current_data = p_data; + + opj_write_bytes(l_current_data, J2K_MS_QCC, 2); /* QCC */ + l_current_data += 2; + + if (p_j2k->m_private_image->numcomps <= 256) { + --l_qcc_size; + + opj_write_bytes(l_current_data, l_qcc_size - 2, 2); /* L_QCC */ + l_current_data += 2; + + opj_write_bytes(l_current_data, p_comp_no, 1); /* Cqcc */ + ++l_current_data; + + /* in the case only one byte is sufficient the last byte allocated is useless -> still do -6 for available */ + l_remaining_size -= 6; + } else { + opj_write_bytes(l_current_data, l_qcc_size - 2, 2); /* L_QCC */ + l_current_data += 2; + + opj_write_bytes(l_current_data, p_comp_no, 2); /* Cqcc */ + l_current_data += 2; + + l_remaining_size -= 6; + } + + opj_j2k_write_SQcd_SQcc(p_j2k, p_j2k->m_current_tile_number, p_comp_no, + l_current_data, &l_remaining_size, p_manager); + + *p_data_written = l_qcc_size; +} + +static OPJ_UINT32 opj_j2k_get_max_qcc_size(opj_j2k_t *p_j2k) +{ + return opj_j2k_get_max_coc_size(p_j2k); +} + +/** + * Reads a QCC marker (Quantization component) + * @param p_header_data the data contained in the QCC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the QCC marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_qcc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_num_comp, l_comp_no; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_num_comp = p_j2k->m_private_image->numcomps; + + if (l_num_comp <= 256) { + if (p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return OPJ_FALSE; + } + opj_read_bytes(p_header_data, &l_comp_no, 1); + ++p_header_data; + --p_header_size; + } else { + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return OPJ_FALSE; + } + opj_read_bytes(p_header_data, &l_comp_no, 2); + p_header_data += 2; + p_header_size -= 2; + } + +#ifdef USE_JPWL + if (p_j2k->m_cp.correct) { + + static OPJ_UINT32 backup_compno = 0; + + /* compno is negative or larger than the number of components!!! */ + if (/*(l_comp_no < 0) ||*/ (l_comp_no >= l_num_comp)) { + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad component number in QCC (%d out of a maximum of %d)\n", + l_comp_no, l_num_comp); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + l_comp_no = backup_compno % l_num_comp; + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n" + "- setting component number to %d\n", + l_comp_no); + } + + /* keep your private count of tiles */ + backup_compno++; + }; +#endif /* USE_JPWL */ + + if (l_comp_no >= p_j2k->m_private_image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid component number: %d, regarding the number of components %d\n", + l_comp_no, p_j2k->m_private_image->numcomps); + return OPJ_FALSE; + } + + if (! opj_j2k_read_SQcd_SQcc(p_j2k, l_comp_no, p_header_data, &p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return OPJ_FALSE; + } + + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_poc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_poc; + OPJ_UINT32 l_poc_size; + OPJ_UINT32 l_written_size = 0; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_poc_room; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; + l_nb_comp = p_j2k->m_private_image->numcomps; + l_nb_poc = 1 + l_tcp->numpocs; + + if (l_nb_comp <= 256) { + l_poc_room = 1; + } else { + l_poc_room = 2; + } + l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc; + + if (l_poc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_poc_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write POC marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_poc_size; + } + + opj_j2k_write_poc_in_memory(p_j2k, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, &l_written_size, + p_manager); + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_poc_size, + p_manager) != l_poc_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static void opj_j2k_write_poc_in_memory(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 i; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_nb_comp; + OPJ_UINT32 l_nb_poc; + OPJ_UINT32 l_poc_size; + opj_image_t *l_image = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + opj_poc_t *l_current_poc = 00; + OPJ_UINT32 l_poc_room; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_manager); + + l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; + l_tccp = &l_tcp->tccps[0]; + l_image = p_j2k->m_private_image; + l_nb_comp = l_image->numcomps; + l_nb_poc = 1 + l_tcp->numpocs; + + if (l_nb_comp <= 256) { + l_poc_room = 1; + } else { + l_poc_room = 2; + } + + l_poc_size = 4 + (5 + 2 * l_poc_room) * l_nb_poc; + + l_current_data = p_data; + + opj_write_bytes(l_current_data, J2K_MS_POC, + 2); /* POC */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_poc_size - 2, + 2); /* Lpoc */ + l_current_data += 2; + + l_current_poc = l_tcp->pocs; + for (i = 0; i < l_nb_poc; ++i) { + opj_write_bytes(l_current_data, l_current_poc->resno0, + 1); /* RSpoc_i */ + ++l_current_data; + + opj_write_bytes(l_current_data, l_current_poc->compno0, + l_poc_room); /* CSpoc_i */ + l_current_data += l_poc_room; + + opj_write_bytes(l_current_data, l_current_poc->layno1, + 2); /* LYEpoc_i */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_current_poc->resno1, + 1); /* REpoc_i */ + ++l_current_data; + + opj_write_bytes(l_current_data, l_current_poc->compno1, + l_poc_room); /* CEpoc_i */ + l_current_data += l_poc_room; + + opj_write_bytes(l_current_data, (OPJ_UINT32)l_current_poc->prg, + 1); /* Ppoc_i */ + ++l_current_data; + + /* change the value of the max layer according to the actual number of layers in the file, components and resolutions*/ + l_current_poc->layno1 = (OPJ_UINT32)opj_int_min((OPJ_INT32) + l_current_poc->layno1, (OPJ_INT32)l_tcp->numlayers); + l_current_poc->resno1 = (OPJ_UINT32)opj_int_min((OPJ_INT32) + l_current_poc->resno1, (OPJ_INT32)l_tccp->numresolutions); + l_current_poc->compno1 = (OPJ_UINT32)opj_int_min((OPJ_INT32) + l_current_poc->compno1, (OPJ_INT32)l_nb_comp); + + ++l_current_poc; + } + + *p_data_written = l_poc_size; +} + +static OPJ_UINT32 opj_j2k_get_max_poc_size(opj_j2k_t *p_j2k) +{ + opj_tcp_t * l_tcp = 00; + OPJ_UINT32 l_nb_tiles = 0; + OPJ_UINT32 l_max_poc = 0; + OPJ_UINT32 i; + + l_tcp = p_j2k->m_cp.tcps; + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + + for (i = 0; i < l_nb_tiles; ++i) { + l_max_poc = opj_uint_max(l_max_poc, l_tcp->numpocs); + ++l_tcp; + } + + ++l_max_poc; + + return 4 + 9 * l_max_poc; +} + +static OPJ_UINT32 opj_j2k_get_max_toc_size(opj_j2k_t *p_j2k) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 l_max = 0; + opj_tcp_t * l_tcp = 00; + + l_tcp = p_j2k->m_cp.tcps; + l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ; + + for (i = 0; i < l_nb_tiles; ++i) { + l_max = opj_uint_max(l_max, l_tcp->m_nb_tile_parts); + + ++l_tcp; + } + + return 12 * l_max; +} + +static OPJ_UINT32 opj_j2k_get_specific_header_sizes(opj_j2k_t *p_j2k) +{ + OPJ_UINT32 l_nb_bytes = 0; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 l_coc_bytes, l_qcc_bytes; + + l_nb_comps = p_j2k->m_private_image->numcomps - 1; + l_nb_bytes += opj_j2k_get_max_toc_size(p_j2k); + + if (!(OPJ_IS_CINEMA(p_j2k->m_cp.rsiz))) { + l_coc_bytes = opj_j2k_get_max_coc_size(p_j2k); + l_nb_bytes += l_nb_comps * l_coc_bytes; + + l_qcc_bytes = opj_j2k_get_max_qcc_size(p_j2k); + l_nb_bytes += l_nb_comps * l_qcc_bytes; + } + + l_nb_bytes += opj_j2k_get_max_poc_size(p_j2k); + + if (p_j2k->m_specific_param.m_encoder.m_PLT) { + /* Reserve space for PLT markers */ + + OPJ_UINT32 i; + const opj_cp_t * l_cp = &(p_j2k->m_cp); + OPJ_UINT32 l_max_packet_count = 0; + for (i = 0; i < l_cp->th * l_cp->tw; ++i) { + l_max_packet_count = opj_uint_max(l_max_packet_count, + opj_get_encoding_packet_count(p_j2k->m_private_image, l_cp, i)); + } + /* Minimum 6 bytes per PLT marker, and at a minimum (taking a pessimistic */ + /* estimate of 4 bytes for a packet size), one can write */ + /* (65536-6) / 4 = 16382 paquet sizes per PLT marker */ + p_j2k->m_specific_param.m_encoder.m_reserved_bytes_for_PLT = + 6 * opj_uint_ceildiv(l_max_packet_count, 16382); + /* Maximum 5 bytes per packet to encode a full UINT32 */ + p_j2k->m_specific_param.m_encoder.m_reserved_bytes_for_PLT += + l_nb_bytes += 5 * l_max_packet_count; + p_j2k->m_specific_param.m_encoder.m_reserved_bytes_for_PLT += 1; + l_nb_bytes += p_j2k->m_specific_param.m_encoder.m_reserved_bytes_for_PLT; + } + + /*** DEVELOPER CORNER, Add room for your headers ***/ + + return l_nb_bytes; +} + +/** + * Reads a POC marker (Progression Order Change) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_poc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 i, l_nb_comp, l_tmp; + opj_image_t * l_image = 00; + OPJ_UINT32 l_old_poc_nb, l_current_poc_nb, l_current_poc_remaining; + OPJ_UINT32 l_chunk_size, l_comp_room; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_poc_t *l_current_poc = 00; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_private_image; + l_nb_comp = l_image->numcomps; + if (l_nb_comp <= 256) { + l_comp_room = 1; + } else { + l_comp_room = 2; + } + l_chunk_size = 5 + 2 * l_comp_room; + l_current_poc_nb = p_header_size / l_chunk_size; + l_current_poc_remaining = p_header_size % l_chunk_size; + + if ((l_current_poc_nb <= 0) || (l_current_poc_remaining != 0)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading POC marker\n"); + return OPJ_FALSE; + } + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_old_poc_nb = l_tcp->POC ? l_tcp->numpocs + 1 : 0; + l_current_poc_nb += l_old_poc_nb; + + if (l_current_poc_nb >= J2K_MAX_POCS) { + opj_event_msg(p_manager, EVT_ERROR, "Too many POCs %d\n", l_current_poc_nb); + return OPJ_FALSE; + } + + /* now poc is in use.*/ + l_tcp->POC = 1; + + l_current_poc = &l_tcp->pocs[l_old_poc_nb]; + for (i = l_old_poc_nb; i < l_current_poc_nb; ++i) { + opj_read_bytes(p_header_data, &(l_current_poc->resno0), + 1); /* RSpoc_i */ + ++p_header_data; + opj_read_bytes(p_header_data, &(l_current_poc->compno0), + l_comp_room); /* CSpoc_i */ + p_header_data += l_comp_room; + opj_read_bytes(p_header_data, &(l_current_poc->layno1), + 2); /* LYEpoc_i */ + /* make sure layer end is in acceptable bounds */ + l_current_poc->layno1 = opj_uint_min(l_current_poc->layno1, l_tcp->numlayers); + p_header_data += 2; + opj_read_bytes(p_header_data, &(l_current_poc->resno1), + 1); /* REpoc_i */ + ++p_header_data; + opj_read_bytes(p_header_data, &(l_current_poc->compno1), + l_comp_room); /* CEpoc_i */ + p_header_data += l_comp_room; + opj_read_bytes(p_header_data, &l_tmp, + 1); /* Ppoc_i */ + ++p_header_data; + l_current_poc->prg = (OPJ_PROG_ORDER) l_tmp; + /* make sure comp is in acceptable bounds */ + l_current_poc->compno1 = opj_uint_min(l_current_poc->compno1, l_nb_comp); + ++l_current_poc; + } + + l_tcp->numpocs = l_current_poc_nb - 1; + return OPJ_TRUE; +} + +/** + * Reads a CRG marker (Component registration) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_crg(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_nb_comp; + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_header_data); + + l_nb_comp = p_j2k->m_private_image->numcomps; + + if (p_header_size != l_nb_comp * 4) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading CRG marker\n"); + return OPJ_FALSE; + } + /* Do not care of this at the moment since only local variables are set here */ + /* + for + (i = 0; i < l_nb_comp; ++i) + { + opj_read_bytes(p_header_data,&l_Xcrg_i,2); // Xcrg_i + p_header_data+=2; + opj_read_bytes(p_header_data,&l_Ycrg_i,2); // Xcrg_i + p_header_data+=2; + } + */ + return OPJ_TRUE; +} + +/** + * Reads a TLM marker (Tile Length Marker) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_tlm(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_Ztlm, l_Stlm, l_ST, l_SP, + l_Ptlm_size, l_entry_size, l_num_tileparts; + OPJ_UINT32 i; + opj_j2k_tlm_tile_part_info_t* l_tile_part_infos; + opj_j2k_tlm_info_t* l_tlm; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_tlm = &(p_j2k->m_specific_param.m_decoder.m_tlm); + + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker.\n"); + return OPJ_FALSE; + } + p_header_size -= 2; + + if (l_tlm->m_is_invalid) { + return OPJ_TRUE; + } + + opj_read_bytes(p_header_data, &l_Ztlm, + 1); /* Ztlm */ + ++p_header_data; + opj_read_bytes(p_header_data, &l_Stlm, + 1); /* Stlm */ + ++p_header_data; + + l_ST = ((l_Stlm >> 4) & 0x3); + if (l_ST == 3) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): ST = 3 is invalid.\n"); + return OPJ_TRUE; + } + l_SP = (l_Stlm >> 6) & 0x1; + + l_Ptlm_size = (l_SP + 1) * 2; + l_entry_size = l_Ptlm_size + l_ST; + + if ((p_header_size % l_entry_size) != 0) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): TLM marker not of expected size.\n"); + return OPJ_TRUE; + } + + l_num_tileparts = p_header_size / l_entry_size; + if (l_num_tileparts == 0) { + /* not totally sure if this is valid... */ + return OPJ_TRUE; + } + + /* Highly unlikely, unless there are gazillions of TLM markers */ + if (l_tlm->m_entries_count > UINT32_MAX - l_num_tileparts || + l_tlm->m_entries_count + l_num_tileparts > UINT32_MAX / sizeof( + opj_j2k_tlm_tile_part_info_t)) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): too many TLM markers.\n"); + return OPJ_TRUE; + } + + l_tile_part_infos = (opj_j2k_tlm_tile_part_info_t*)opj_realloc( + l_tlm->m_tile_part_infos, + (l_tlm->m_entries_count + l_num_tileparts) * sizeof( + opj_j2k_tlm_tile_part_info_t)); + if (!l_tile_part_infos) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): cannot allocate m_tile_part_infos.\n"); + return OPJ_TRUE; + } + + l_tlm->m_tile_part_infos = l_tile_part_infos; + + for (i = 0; i < l_num_tileparts; ++ i) { + OPJ_UINT32 l_tile_index; + OPJ_UINT32 l_length; + + /* Read Ttlm_i */ + if (l_ST == 0) { + l_tile_index = l_tlm->m_entries_count; + } else { + opj_read_bytes(p_header_data, &l_tile_index, l_ST); + p_header_data += l_ST; + } + + if (l_tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th) { + l_tlm->m_is_invalid = OPJ_TRUE; + opj_event_msg(p_manager, EVT_WARNING, + "opj_j2k_read_tlm(): invalid tile number %d\n", + l_tile_index); + return OPJ_TRUE; + } + + /* Read Ptlm_i */ + opj_read_bytes(p_header_data, &l_length, l_Ptlm_size); + p_header_data += l_Ptlm_size; + + l_tile_part_infos[l_tlm->m_entries_count].m_tile_index = + (OPJ_UINT16)l_tile_index; + l_tile_part_infos[l_tlm->m_entries_count].m_length = l_length; + ++l_tlm->m_entries_count; + } + + return OPJ_TRUE; +} + +/** + * Reads a PLM marker (Packet length, main header marker) + * + * @param p_header_data the data contained in the TLM box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the TLM marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_plm(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_j2k); + OPJ_UNUSED(p_header_data); + + if (p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return OPJ_FALSE; + } + /* Do not care of this at the moment since only local variables are set here */ + /* + opj_read_bytes(p_header_data,&l_Zplm,1); // Zplm + ++p_header_data; + --p_header_size; + + while + (p_header_size > 0) + { + opj_read_bytes(p_header_data,&l_Nplm,1); // Nplm + ++p_header_data; + p_header_size -= (1+l_Nplm); + if + (p_header_size < 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return false; + } + for + (i = 0; i < l_Nplm; ++i) + { + opj_read_bytes(p_header_data,&l_tmp,1); // Iplm_ij + ++p_header_data; + // take only the last seven bytes + l_packet_len |= (l_tmp & 0x7f); + if + (l_tmp & 0x80) + { + l_packet_len <<= 7; + } + else + { + // store packet length and proceed to next packet + l_packet_len = 0; + } + } + if + (l_packet_len != 0) + { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); + return false; + } + } + */ + return OPJ_TRUE; +} + +/** + * Reads a PLT marker (Packet length, tile-part header) + * + * @param p_header_data the data contained in the PLT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PLT marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_plt(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_Zplt, l_tmp, l_packet_len = 0, i; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_j2k); + + if (p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLT marker\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &l_Zplt, 1); /* Zplt */ + ++p_header_data; + --p_header_size; + + for (i = 0; i < p_header_size; ++i) { + opj_read_bytes(p_header_data, &l_tmp, 1); /* Iplt_ij */ + ++p_header_data; + /* take only the last seven bytes */ + l_packet_len |= (l_tmp & 0x7f); + if (l_tmp & 0x80) { + l_packet_len <<= 7; + } else { + /* store packet length and proceed to next packet */ + l_packet_len = 0; + } + } + + if (l_packet_len != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PLT marker\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads a PPM marker (Packed packet headers, main header) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. + */ + +static OPJ_BOOL opj_j2k_read_ppm( + opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager) +{ + opj_cp_t *l_cp = 00; + OPJ_UINT32 l_Z_ppm; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + /* We need to have the Z_ppm element + 1 byte of Nppm/Ippm at minimum */ + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n"); + return OPJ_FALSE; + } + + l_cp = &(p_j2k->m_cp); + l_cp->ppm = 1; + + opj_read_bytes(p_header_data, &l_Z_ppm, 1); /* Z_ppm */ + ++p_header_data; + --p_header_size; + + /* check allocation needed */ + if (l_cp->ppm_markers == NULL) { /* first PPM marker */ + OPJ_UINT32 l_newCount = l_Z_ppm + 1U; /* can't overflow, l_Z_ppm is UINT8 */ + assert(l_cp->ppm_markers_count == 0U); + + l_cp->ppm_markers = (opj_ppx *) opj_calloc(l_newCount, sizeof(opj_ppx)); + if (l_cp->ppm_markers == NULL) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); + return OPJ_FALSE; + } + l_cp->ppm_markers_count = l_newCount; + } else if (l_cp->ppm_markers_count <= l_Z_ppm) { + OPJ_UINT32 l_newCount = l_Z_ppm + 1U; /* can't overflow, l_Z_ppm is UINT8 */ + opj_ppx *new_ppm_markers; + new_ppm_markers = (opj_ppx *) opj_realloc(l_cp->ppm_markers, + l_newCount * sizeof(opj_ppx)); + if (new_ppm_markers == NULL) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); + return OPJ_FALSE; + } + l_cp->ppm_markers = new_ppm_markers; + memset(l_cp->ppm_markers + l_cp->ppm_markers_count, 0, + (l_newCount - l_cp->ppm_markers_count) * sizeof(opj_ppx)); + l_cp->ppm_markers_count = l_newCount; + } + + if (l_cp->ppm_markers[l_Z_ppm].m_data != NULL) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Zppm %u already read\n", l_Z_ppm); + return OPJ_FALSE; + } + + l_cp->ppm_markers[l_Z_ppm].m_data = (OPJ_BYTE *) opj_malloc(p_header_size); + if (l_cp->ppm_markers[l_Z_ppm].m_data == NULL) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); + return OPJ_FALSE; + } + l_cp->ppm_markers[l_Z_ppm].m_data_size = p_header_size; + memcpy(l_cp->ppm_markers[l_Z_ppm].m_data, p_header_data, p_header_size); + + return OPJ_TRUE; +} + +/** + * Merges all PPM markers read (Packed headers, main header) + * + * @param p_cp main coding parameters. + * @param p_manager the user event manager. + */ +static OPJ_BOOL opj_j2k_merge_ppm(opj_cp_t *p_cp, opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, l_ppm_data_size, l_N_ppm_remaining; + + /* preconditions */ + assert(p_cp != 00); + assert(p_manager != 00); + assert(p_cp->ppm_buffer == NULL); + + if (p_cp->ppm == 0U) { + return OPJ_TRUE; + } + + l_ppm_data_size = 0U; + l_N_ppm_remaining = 0U; + for (i = 0U; i < p_cp->ppm_markers_count; ++i) { + if (p_cp->ppm_markers[i].m_data != + NULL) { /* standard doesn't seem to require contiguous Zppm */ + OPJ_UINT32 l_N_ppm; + OPJ_UINT32 l_data_size = p_cp->ppm_markers[i].m_data_size; + const OPJ_BYTE* l_data = p_cp->ppm_markers[i].m_data; + + if (l_N_ppm_remaining >= l_data_size) { + l_N_ppm_remaining -= l_data_size; + l_data_size = 0U; + } else { + l_data += l_N_ppm_remaining; + l_data_size -= l_N_ppm_remaining; + l_N_ppm_remaining = 0U; + } + + if (l_data_size > 0U) { + do { + /* read Nppm */ + if (l_data_size < 4U) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes to read Nppm\n"); + return OPJ_FALSE; + } + opj_read_bytes(l_data, &l_N_ppm, 4); + l_data += 4; + l_data_size -= 4; + + if (l_ppm_data_size > UINT_MAX - l_N_ppm) { + opj_event_msg(p_manager, EVT_ERROR, "Too large value for Nppm\n"); + return OPJ_FALSE; + } + l_ppm_data_size += l_N_ppm; + if (l_data_size >= l_N_ppm) { + l_data_size -= l_N_ppm; + l_data += l_N_ppm; + } else { + l_N_ppm_remaining = l_N_ppm - l_data_size; + l_data_size = 0U; + } + } while (l_data_size > 0U); + } + } + } + + if (l_N_ppm_remaining != 0U) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Corrupted PPM markers\n"); + return OPJ_FALSE; + } + + p_cp->ppm_buffer = (OPJ_BYTE *) opj_malloc(l_ppm_data_size); + if (p_cp->ppm_buffer == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPM marker\n"); + return OPJ_FALSE; + } + p_cp->ppm_len = l_ppm_data_size; + l_ppm_data_size = 0U; + l_N_ppm_remaining = 0U; + for (i = 0U; i < p_cp->ppm_markers_count; ++i) { + if (p_cp->ppm_markers[i].m_data != + NULL) { /* standard doesn't seem to require contiguous Zppm */ + OPJ_UINT32 l_N_ppm; + OPJ_UINT32 l_data_size = p_cp->ppm_markers[i].m_data_size; + const OPJ_BYTE* l_data = p_cp->ppm_markers[i].m_data; + + if (l_N_ppm_remaining >= l_data_size) { + memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_data_size); + l_ppm_data_size += l_data_size; + l_N_ppm_remaining -= l_data_size; + l_data_size = 0U; + } else { + memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_N_ppm_remaining); + l_ppm_data_size += l_N_ppm_remaining; + l_data += l_N_ppm_remaining; + l_data_size -= l_N_ppm_remaining; + l_N_ppm_remaining = 0U; + } + + if (l_data_size > 0U) { + do { + /* read Nppm */ + if (l_data_size < 4U) { + /* clean up to be done on l_cp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes to read Nppm\n"); + return OPJ_FALSE; + } + opj_read_bytes(l_data, &l_N_ppm, 4); + l_data += 4; + l_data_size -= 4; + + if (l_data_size >= l_N_ppm) { + memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_N_ppm); + l_ppm_data_size += l_N_ppm; + l_data_size -= l_N_ppm; + l_data += l_N_ppm; + } else { + memcpy(p_cp->ppm_buffer + l_ppm_data_size, l_data, l_data_size); + l_ppm_data_size += l_data_size; + l_N_ppm_remaining = l_N_ppm - l_data_size; + l_data_size = 0U; + } + } while (l_data_size > 0U); + } + opj_free(p_cp->ppm_markers[i].m_data); + p_cp->ppm_markers[i].m_data = NULL; + p_cp->ppm_markers[i].m_data_size = 0U; + } + } + + p_cp->ppm_data = p_cp->ppm_buffer; + p_cp->ppm_data_size = p_cp->ppm_len; + + p_cp->ppm_markers_count = 0U; + opj_free(p_cp->ppm_markers); + p_cp->ppm_markers = NULL; + + return OPJ_TRUE; +} + +/** + * Reads a PPT marker (Packed packet headers, tile-part header) + * + * @param p_header_data the data contained in the PPT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the PPT marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_ppt(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_Z_ppt; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + /* We need to have the Z_ppt element + 1 byte of Ippt at minimum */ + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker\n"); + return OPJ_FALSE; + } + + l_cp = &(p_j2k->m_cp); + if (l_cp->ppm) { + opj_event_msg(p_manager, EVT_ERROR, + "Error reading PPT marker: packet header have been previously found in the main header (PPM marker).\n"); + return OPJ_FALSE; + } + + l_tcp = &(l_cp->tcps[p_j2k->m_current_tile_number]); + l_tcp->ppt = 1; + + opj_read_bytes(p_header_data, &l_Z_ppt, 1); /* Z_ppt */ + ++p_header_data; + --p_header_size; + + /* check allocation needed */ + if (l_tcp->ppt_markers == NULL) { /* first PPT marker */ + OPJ_UINT32 l_newCount = l_Z_ppt + 1U; /* can't overflow, l_Z_ppt is UINT8 */ + assert(l_tcp->ppt_markers_count == 0U); + + l_tcp->ppt_markers = (opj_ppx *) opj_calloc(l_newCount, sizeof(opj_ppx)); + if (l_tcp->ppt_markers == NULL) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); + return OPJ_FALSE; + } + l_tcp->ppt_markers_count = l_newCount; + } else if (l_tcp->ppt_markers_count <= l_Z_ppt) { + OPJ_UINT32 l_newCount = l_Z_ppt + 1U; /* can't overflow, l_Z_ppt is UINT8 */ + opj_ppx *new_ppt_markers; + new_ppt_markers = (opj_ppx *) opj_realloc(l_tcp->ppt_markers, + l_newCount * sizeof(opj_ppx)); + if (new_ppt_markers == NULL) { + /* clean up to be done on l_tcp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); + return OPJ_FALSE; + } + l_tcp->ppt_markers = new_ppt_markers; + memset(l_tcp->ppt_markers + l_tcp->ppt_markers_count, 0, + (l_newCount - l_tcp->ppt_markers_count) * sizeof(opj_ppx)); + l_tcp->ppt_markers_count = l_newCount; + } + + if (l_tcp->ppt_markers[l_Z_ppt].m_data != NULL) { + /* clean up to be done on l_tcp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Zppt %u already read\n", l_Z_ppt); + return OPJ_FALSE; + } + + l_tcp->ppt_markers[l_Z_ppt].m_data = (OPJ_BYTE *) opj_malloc(p_header_size); + if (l_tcp->ppt_markers[l_Z_ppt].m_data == NULL) { + /* clean up to be done on l_tcp destruction */ + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); + return OPJ_FALSE; + } + l_tcp->ppt_markers[l_Z_ppt].m_data_size = p_header_size; + memcpy(l_tcp->ppt_markers[l_Z_ppt].m_data, p_header_data, p_header_size); + return OPJ_TRUE; +} + +/** + * Merges all PPT markers read (Packed packet headers, tile-part header) + * + * @param p_tcp the tile. + * @param p_manager the user event manager. + */ +static OPJ_BOOL opj_j2k_merge_ppt(opj_tcp_t *p_tcp, opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, l_ppt_data_size; + /* preconditions */ + assert(p_tcp != 00); + assert(p_manager != 00); + + if (p_tcp->ppt_buffer != NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_j2k_merge_ppt() has already been called\n"); + return OPJ_FALSE; + } + + if (p_tcp->ppt == 0U) { + return OPJ_TRUE; + } + + l_ppt_data_size = 0U; + for (i = 0U; i < p_tcp->ppt_markers_count; ++i) { + l_ppt_data_size += + p_tcp->ppt_markers[i].m_data_size; /* can't overflow, max 256 markers of max 65536 bytes */ + } + + p_tcp->ppt_buffer = (OPJ_BYTE *) opj_malloc(l_ppt_data_size); + if (p_tcp->ppt_buffer == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n"); + return OPJ_FALSE; + } + p_tcp->ppt_len = l_ppt_data_size; + l_ppt_data_size = 0U; + for (i = 0U; i < p_tcp->ppt_markers_count; ++i) { + if (p_tcp->ppt_markers[i].m_data != + NULL) { /* standard doesn't seem to require contiguous Zppt */ + memcpy(p_tcp->ppt_buffer + l_ppt_data_size, p_tcp->ppt_markers[i].m_data, + p_tcp->ppt_markers[i].m_data_size); + l_ppt_data_size += + p_tcp->ppt_markers[i].m_data_size; /* can't overflow, max 256 markers of max 65536 bytes */ + + opj_free(p_tcp->ppt_markers[i].m_data); + p_tcp->ppt_markers[i].m_data = NULL; + p_tcp->ppt_markers[i].m_data_size = 0U; + } + } + + p_tcp->ppt_markers_count = 0U; + opj_free(p_tcp->ppt_markers); + p_tcp->ppt_markers = NULL; + + p_tcp->ppt_data = p_tcp->ppt_buffer; + p_tcp->ppt_data_size = p_tcp->ppt_len; + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tlm_size; + OPJ_UINT32 size_per_tile_part; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + /* 10921 = (65535 - header_size) / size_per_tile_part where */ + /* header_size = 4 and size_per_tile_part = 6 */ + if (p_j2k->m_specific_param.m_encoder.m_total_tile_parts > 10921) { + /* We could do more but it would require writing several TLM markers */ + opj_event_msg(p_manager, EVT_ERROR, + "A maximum of 10921 tile-parts are supported currently " + "when writing TLM marker\n"); + return OPJ_FALSE; + } + + if (p_j2k->m_specific_param.m_encoder.m_total_tile_parts <= 255) { + size_per_tile_part = 5; + p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte = OPJ_TRUE; + } else { + size_per_tile_part = 6; + p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte = OPJ_FALSE; + } + + l_tlm_size = 2 + 4 + (size_per_tile_part * + p_j2k->m_specific_param.m_encoder.m_total_tile_parts); + + if (l_tlm_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_tlm_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write TLM marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_tlm_size; + } + memset(p_j2k->m_specific_param.m_encoder.m_header_tile_data, 0, l_tlm_size); + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + /* change the way data is written to avoid seeking if possible */ + /* TODO */ + p_j2k->m_specific_param.m_encoder.m_tlm_start = opj_stream_tell(p_stream); + + opj_write_bytes(l_current_data, J2K_MS_TLM, + 2); /* TLM */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_tlm_size - 2, + 2); /* Lpoc */ + l_current_data += 2; + + opj_write_bytes(l_current_data, 0, + 1); /* Ztlm=0*/ + ++l_current_data; + + /* Stlm 0x50= ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */ + /* Stlm 0x60= ST=2(16bits-65535 tiles max),SP=1(Ptlm=32bits) */ + opj_write_bytes(l_current_data, + size_per_tile_part == 5 ? 0x50 : 0x60, + 1); + ++l_current_data; + + /* do nothing on the size_per_tile_part * l_j2k->m_specific_param.m_encoder.m_total_tile_parts remaining data */ + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_tlm_size, + p_manager) != l_tlm_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_sot(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 total_data_size, + OPJ_UINT32 * p_data_written, + const opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + OPJ_UNUSED(p_stream); + + if (total_data_size < 12) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough bytes in output buffer to write SOT marker\n"); + return OPJ_FALSE; + } + + opj_write_bytes(p_data, J2K_MS_SOT, + 2); /* SOT */ + p_data += 2; + + opj_write_bytes(p_data, 10, + 2); /* Lsot */ + p_data += 2; + + opj_write_bytes(p_data, p_j2k->m_current_tile_number, + 2); /* Isot */ + p_data += 2; + + /* Psot */ + p_data += 4; + + opj_write_bytes(p_data, + p_j2k->m_specific_param.m_encoder.m_current_tile_part_number, + 1); /* TPsot */ + ++p_data; + + opj_write_bytes(p_data, + p_j2k->m_cp.tcps[p_j2k->m_current_tile_number].m_nb_tile_parts, + 1); /* TNsot */ + ++p_data; + + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + /* + OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOT, p_j2k->sot_start, len + 2); + */ + assert(0 && "TODO"); +#endif /* USE_JPWL */ + + * p_data_written = 12; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + OPJ_UINT32* p_tile_no, + OPJ_UINT32* p_tot_len, + OPJ_UINT32* p_current_part, + OPJ_UINT32* p_num_parts, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(p_header_data != 00); + assert(p_manager != 00); + + /* Size of this marker is fixed = 12 (we have already read marker and its size)*/ + if (p_header_size != 8) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, p_tile_no, 2); /* Isot */ + p_header_data += 2; + opj_read_bytes(p_header_data, p_tot_len, 4); /* Psot */ + p_header_data += 4; + opj_read_bytes(p_header_data, p_current_part, 1); /* TPsot */ + ++p_header_data; + opj_read_bytes(p_header_data, p_num_parts, 1); /* TNsot */ + ++p_header_data; + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_read_sot(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_tot_len, l_num_parts = 0; + OPJ_UINT32 l_current_part; + OPJ_UINT32 l_tile_x, l_tile_y; + + /* preconditions */ + + assert(p_j2k != 00); + assert(p_manager != 00); + + if (! opj_j2k_get_sot_values(p_header_data, p_header_size, + &(p_j2k->m_current_tile_number), &l_tot_len, &l_current_part, &l_num_parts, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n"); + return OPJ_FALSE; + } +#ifdef DEBUG_VERBOSE + fprintf(stderr, "SOT %d %d %d %d\n", + p_j2k->m_current_tile_number, l_tot_len, l_current_part, l_num_parts); +#endif + + l_cp = &(p_j2k->m_cp); + + /* testcase 2.pdf.SIGFPE.706.1112 */ + if (p_j2k->m_current_tile_number >= l_cp->tw * l_cp->th) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid tile number %d\n", + p_j2k->m_current_tile_number); + return OPJ_FALSE; + } + + l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; + l_tile_x = p_j2k->m_current_tile_number % l_cp->tw; + l_tile_y = p_j2k->m_current_tile_number / l_cp->tw; + + if (p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec < 0 || + p_j2k->m_current_tile_number == (OPJ_UINT32) + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec) { + /* Do only this check if we decode all tile part headers, or if */ + /* we decode one precise tile. Otherwise the m_current_tile_part_number */ + /* might not be valid */ + /* Fixes issue with id_000020,sig_06,src_001958,op_flip4,pos_149 */ + /* of https://github.com/uclouvain/openjpeg/issues/939 */ + /* We must avoid reading twice the same tile part number for a given tile */ + /* so as to avoid various issues, like opj_j2k_merge_ppt being called */ + /* several times. */ + /* ISO 15444-1 A.4.2 Start of tile-part (SOT) mandates that tile parts */ + /* should appear in increasing order. */ + if (l_tcp->m_current_tile_part_number + 1 != (OPJ_INT32)l_current_part) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid tile part index for tile number %d. " + "Got %d, expected %d\n", + p_j2k->m_current_tile_number, + l_current_part, + l_tcp->m_current_tile_part_number + 1); + return OPJ_FALSE; + } + } + + l_tcp->m_current_tile_part_number = (OPJ_INT32) l_current_part; + +#ifdef USE_JPWL + if (l_cp->correct) { + + OPJ_UINT32 tileno = p_j2k->m_current_tile_number; + static OPJ_UINT32 backup_tileno = 0; + + /* tileno is negative or larger than the number of tiles!!! */ + if (tileno > (l_cp->tw * l_cp->th)) { + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad tile number (%d out of a maximum of %d)\n", + tileno, (l_cp->tw * l_cp->th)); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + tileno = backup_tileno; + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n" + "- setting tile number to %d\n", + tileno); + } + + /* keep your private count of tiles */ + backup_tileno++; + }; +#endif /* USE_JPWL */ + + /* look for the tile in the list of already processed tile (in parts). */ + /* Optimization possible here with a more complex data structure and with the removing of tiles */ + /* since the time taken by this function can only grow at the time */ + + /* PSot should be equal to zero or >=14 or <= 2^32-1 */ + if ((l_tot_len != 0) && (l_tot_len < 14)) { + if (l_tot_len == + 12) { /* MSD: Special case for the PHR data which are read by kakadu*/ + opj_event_msg(p_manager, EVT_WARNING, "Empty SOT marker detected: Psot=%d.\n", + l_tot_len); + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Psot value is not correct regards to the JPEG2000 norm: %d.\n", l_tot_len); + return OPJ_FALSE; + } + } + +#ifdef USE_JPWL + if (l_cp->correct) { + + /* totlen is negative or larger than the bytes left!!! */ + if (/*(l_tot_len < 0) ||*/ (l_tot_len > + p_header_size)) { /* FIXME it seems correct; for info in V1 -> (p_stream_numbytesleft(p_stream) + 8))) { */ + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad tile byte size (%d bytes against %d bytes left)\n", + l_tot_len, + p_header_size); /* FIXME it seems correct; for info in V1 -> p_stream_numbytesleft(p_stream) + 8); */ + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + l_tot_len = 0; + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust this\n" + "- setting Psot to %d => assuming it is the last tile\n", + l_tot_len); + } + }; +#endif /* USE_JPWL */ + + /* Ref A.4.2: Psot could be equal zero if it is the last tile-part of the codestream.*/ + if (!l_tot_len) { + opj_event_msg(p_manager, EVT_INFO, + "Psot value of the current tile-part is equal to zero, " + "we assuming it is the last tile-part of the codestream.\n"); + p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; + } + + if (l_tcp->m_nb_tile_parts != 0 && l_current_part >= l_tcp->m_nb_tile_parts) { + /* Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2851 */ + opj_event_msg(p_manager, EVT_ERROR, + "In SOT marker, TPSot (%d) is not valid regards to the previous " + "number of tile-part (%d), giving up\n", l_current_part, + l_tcp->m_nb_tile_parts); + p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; + return OPJ_FALSE; + } + + if (l_num_parts != + 0) { /* Number of tile-part header is provided by this tile-part header */ + l_num_parts += p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction; + /* Useful to manage the case of textGBR.jp2 file because two values of TNSot are allowed: the correct numbers of + * tile-parts for that tile and zero (A.4.2 of 15444-1 : 2002). */ + if (l_tcp->m_nb_tile_parts) { + if (l_current_part >= l_tcp->m_nb_tile_parts) { + opj_event_msg(p_manager, EVT_ERROR, + "In SOT marker, TPSot (%d) is not valid regards to the current " + "number of tile-part (%d), giving up\n", l_current_part, + l_tcp->m_nb_tile_parts); + p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; + return OPJ_FALSE; + } + } + if (l_current_part >= l_num_parts) { + /* testcase 451.pdf.SIGSEGV.ce9.3723 */ + opj_event_msg(p_manager, EVT_ERROR, + "In SOT marker, TPSot (%d) is not valid regards to the current " + "number of tile-part (header) (%d), giving up\n", l_current_part, l_num_parts); + p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1; + return OPJ_FALSE; + } + l_tcp->m_nb_tile_parts = l_num_parts; + } + + /* If know the number of tile part header we will check if we didn't read the last*/ + if (l_tcp->m_nb_tile_parts) { + if (l_tcp->m_nb_tile_parts == (l_current_part + 1)) { + p_j2k->m_specific_param.m_decoder.m_can_decode = + 1; /* Process the last tile-part header*/ + } + } + + if (!p_j2k->m_specific_param.m_decoder.m_last_tile_part) { + /* Keep the size of data to skip after this marker */ + p_j2k->m_specific_param.m_decoder.m_sot_length = l_tot_len - + 12; /* SOT_marker_size = 12 */ + } else { + /* FIXME: need to be computed from the number of bytes remaining in the codestream */ + p_j2k->m_specific_param.m_decoder.m_sot_length = 0; + } + + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPH; + + /* Check if the current tile is outside the area we want decode or not corresponding to the tile index*/ + if (p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec == -1) { + p_j2k->m_specific_param.m_decoder.m_skip_data = + (l_tile_x < p_j2k->m_specific_param.m_decoder.m_start_tile_x) + || (l_tile_x >= p_j2k->m_specific_param.m_decoder.m_end_tile_x) + || (l_tile_y < p_j2k->m_specific_param.m_decoder.m_start_tile_y) + || (l_tile_y >= p_j2k->m_specific_param.m_decoder.m_end_tile_y); + } else { + assert(p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec >= 0); + p_j2k->m_specific_param.m_decoder.m_skip_data = + (p_j2k->m_current_tile_number != (OPJ_UINT32) + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec); + } + + /* Index */ + { + assert(p_j2k->cstr_index->tile_index != 00); + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tileno = + p_j2k->m_current_tile_number; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno = + l_current_part; + + if (!p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid && + l_num_parts > + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps) { + opj_event_msg(p_manager, EVT_WARNING, + "SOT marker for tile %u declares more tile-parts than found in TLM marker.", + p_j2k->m_current_tile_number); + p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid = OPJ_TRUE; + } + + if (!p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid) { + /* do nothing */ + } else if (l_num_parts != 0) { + + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps = + l_num_parts; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = + l_num_parts; + + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + (opj_tp_index_t*)opj_calloc(l_num_parts, sizeof(opj_tp_index_t)); + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to read SOT marker. Tile index allocation failed\n"); + return OPJ_FALSE; + } + } else { + opj_tp_index_t *new_tp_index = (opj_tp_index_t *) opj_realloc( + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index, + l_num_parts * sizeof(opj_tp_index_t)); + if (! new_tp_index) { + opj_free(p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index); + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to read SOT marker. Tile index allocation failed\n"); + return OPJ_FALSE; + } + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + new_tp_index; + } + } else { + /*if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index)*/ { + + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 10; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + (opj_tp_index_t*)opj_calloc( + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps, + sizeof(opj_tp_index_t)); + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to read SOT marker. Tile index allocation failed\n"); + return OPJ_FALSE; + } + } + + if (l_current_part >= + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps) { + opj_tp_index_t *new_tp_index; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = + l_current_part + 1; + new_tp_index = (opj_tp_index_t *) opj_realloc( + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index, + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps * + sizeof(opj_tp_index_t)); + if (! new_tp_index) { + opj_free(p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index); + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = NULL; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 0; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to read SOT marker. Tile index allocation failed\n"); + return OPJ_FALSE; + } + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + new_tp_index; + } + } + + } + + } + + return OPJ_TRUE; +} + +/** + * Write one or more PLT markers in the provided buffer + */ +static OPJ_BOOL opj_j2k_write_plt_in_memory(opj_j2k_t *p_j2k, + opj_tcd_marker_info_t* marker_info, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE Zplt = 0; + OPJ_UINT16 Lplt; + OPJ_BYTE* p_data_start = p_data; + OPJ_BYTE* p_data_Lplt = p_data + 2; + OPJ_UINT32 i; + + OPJ_UNUSED(p_j2k); + + opj_write_bytes(p_data, J2K_MS_PLT, 2); + p_data += 2; + + /* Reserve space for Lplt */ + p_data += 2; + + opj_write_bytes(p_data, Zplt, 1); + p_data += 1; + + Lplt = 3; + + for (i = 0; i < marker_info->packet_count; i++) { + OPJ_BYTE var_bytes[5]; + OPJ_UINT8 var_bytes_size = 0; + OPJ_UINT32 packet_size = marker_info->p_packet_size[i]; + + /* Packet size written in variable-length way, starting with LSB */ + var_bytes[var_bytes_size] = (OPJ_BYTE)(packet_size & 0x7f); + var_bytes_size ++; + packet_size >>= 7; + while (packet_size > 0) { + var_bytes[var_bytes_size] = (OPJ_BYTE)((packet_size & 0x7f) | 0x80); + var_bytes_size ++; + packet_size >>= 7; + } + + /* Check if that can fit in the current PLT marker. If not, finish */ + /* current one, and start a new one */ + if (Lplt + var_bytes_size > 65535) { + if (Zplt == 255) { + opj_event_msg(p_manager, EVT_ERROR, + "More than 255 PLT markers would be needed for current tile-part !\n"); + return OPJ_FALSE; + } + + /* Patch Lplt */ + opj_write_bytes(p_data_Lplt, Lplt, 2); + + /* Start new segment */ + opj_write_bytes(p_data, J2K_MS_PLT, 2); + p_data += 2; + + /* Reserve space for Lplt */ + p_data_Lplt = p_data; + p_data += 2; + + Zplt ++; + opj_write_bytes(p_data, Zplt, 1); + p_data += 1; + + Lplt = 3; + } + + Lplt = (OPJ_UINT16)(Lplt + var_bytes_size); + + /* Serialize variable-length packet size, starting with MSB */ + for (; var_bytes_size > 0; --var_bytes_size) { + opj_write_bytes(p_data, var_bytes[var_bytes_size - 1], 1); + p_data += 1; + } + } + + *p_data_written = (OPJ_UINT32)(p_data - p_data_start); + + /* Patch Lplt */ + opj_write_bytes(p_data_Lplt, Lplt, 2); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_sod(opj_j2k_t *p_j2k, + opj_tcd_t * p_tile_coder, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 total_data_size, + const opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + opj_codestream_info_t *l_cstr_info = 00; + OPJ_UINT32 l_remaining_data; + opj_tcd_marker_info_t* marker_info = NULL; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + OPJ_UNUSED(p_stream); + + if (total_data_size < 4) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough bytes in output buffer to write SOD marker\n"); + return OPJ_FALSE; + } + + opj_write_bytes(p_data, J2K_MS_SOD, + 2); /* SOD */ + + /* make room for the EOF marker */ + l_remaining_data = total_data_size - 4; + + /* update tile coder */ + p_tile_coder->tp_num = + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number ; + p_tile_coder->cur_tp_num = + p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + + /* INDEX >> */ + /* TODO mergeV2: check this part which use cstr_info */ + /*l_cstr_info = p_j2k->cstr_info; + if (l_cstr_info) { + if (!p_j2k->m_specific_param.m_encoder.m_current_tile_part_number ) { + //TODO cstr_info->tile[p_j2k->m_current_tile_number].end_header = p_stream_tell(p_stream) + p_j2k->pos_correction - 1; + l_cstr_info->tile[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number; + } + else {*/ + /* + TODO + if + (cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno - 1].end_pos < p_stream_tell(p_stream)) + { + cstr_info->tile[p_j2k->m_current_tile_number].packet[cstr_info->packno].start_pos = p_stream_tell(p_stream); + }*/ + /*}*/ + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + /*OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOD, p_j2k->sod_start, 2); + */ + assert(0 && "TODO"); +#endif /* USE_JPWL */ + /* <m_specific_param.m_encoder.m_current_tile_part_number == 0) { + p_tile_coder->tcd_image->tiles->packno = 0; +#ifdef deadcode + if (l_cstr_info) { + l_cstr_info->packno = 0; + } +#endif + } + + *p_data_written = 0; + + if (p_j2k->m_specific_param.m_encoder.m_PLT) { + marker_info = opj_tcd_marker_info_create( + p_j2k->m_specific_param.m_encoder.m_PLT); + if (marker_info == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "Cannot encode tile: opj_tcd_marker_info_create() failed\n"); + return OPJ_FALSE; + } + } + + if (l_remaining_data < + p_j2k->m_specific_param.m_encoder.m_reserved_bytes_for_PLT) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough bytes in output buffer to write SOD marker\n"); + opj_tcd_marker_info_destroy(marker_info); + return OPJ_FALSE; + } + l_remaining_data -= p_j2k->m_specific_param.m_encoder.m_reserved_bytes_for_PLT; + + if (! opj_tcd_encode_tile(p_tile_coder, p_j2k->m_current_tile_number, + p_data + 2, + p_data_written, l_remaining_data, l_cstr_info, + marker_info, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot encode tile\n"); + opj_tcd_marker_info_destroy(marker_info); + return OPJ_FALSE; + } + + /* For SOD */ + *p_data_written += 2; + + if (p_j2k->m_specific_param.m_encoder.m_PLT) { + OPJ_UINT32 l_data_written_PLT = 0; + OPJ_BYTE* p_PLT_buffer = (OPJ_BYTE*)opj_malloc( + p_j2k->m_specific_param.m_encoder.m_reserved_bytes_for_PLT); + if (!p_PLT_buffer) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot allocate memory\n"); + opj_tcd_marker_info_destroy(marker_info); + return OPJ_FALSE; + } + if (!opj_j2k_write_plt_in_memory(p_j2k, + marker_info, + p_PLT_buffer, + &l_data_written_PLT, + p_manager)) { + opj_tcd_marker_info_destroy(marker_info); + opj_free(p_PLT_buffer); + return OPJ_FALSE; + } + + assert(l_data_written_PLT <= + p_j2k->m_specific_param.m_encoder.m_reserved_bytes_for_PLT); + + /* Move PLT marker(s) before SOD */ + memmove(p_data + l_data_written_PLT, p_data, *p_data_written); + memcpy(p_data, p_PLT_buffer, l_data_written_PLT); + opj_free(p_PLT_buffer); + *p_data_written += l_data_written_PLT; + } + + opj_tcd_marker_info_destroy(marker_info); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_SIZE_T l_current_read_size; + opj_codestream_index_t * l_cstr_index = 00; + OPJ_BYTE ** l_current_data = 00; + opj_tcp_t * l_tcp = 00; + OPJ_UINT32 * l_tile_len = 00; + OPJ_BOOL l_sot_length_pb_detected = OPJ_FALSE; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); + + if (p_j2k->m_specific_param.m_decoder.m_last_tile_part) { + /* opj_stream_get_number_byte_left returns OPJ_OFF_T + // but we are in the last tile part, + // so its result will fit on OPJ_UINT32 unless we find + // a file with a single tile part of more than 4 GB...*/ + p_j2k->m_specific_param.m_decoder.m_sot_length = (OPJ_UINT32)( + opj_stream_get_number_byte_left(p_stream) - 2); + } else { + /* Check to avoid pass the limit of OPJ_UINT32 */ + if (p_j2k->m_specific_param.m_decoder.m_sot_length >= 2) { + p_j2k->m_specific_param.m_decoder.m_sot_length -= 2; + } else { + /* MSD: case commented to support empty SOT marker (PHR data) */ + } + } + + l_current_data = &(l_tcp->m_data); + l_tile_len = &l_tcp->m_data_size; + + /* Patch to support new PHR data */ + if (p_j2k->m_specific_param.m_decoder.m_sot_length) { + /* If we are here, we'll try to read the data after allocation */ + /* Check enough bytes left in stream before allocation */ + if ((OPJ_OFF_T)p_j2k->m_specific_param.m_decoder.m_sot_length > + opj_stream_get_number_byte_left(p_stream)) { + if (p_j2k->m_cp.strict) { + opj_event_msg(p_manager, EVT_ERROR, + "Tile part length size inconsistent with stream length\n"); + return OPJ_FALSE; + } else { + opj_event_msg(p_manager, EVT_WARNING, + "Tile part length size inconsistent with stream length\n"); + } + } + if (p_j2k->m_specific_param.m_decoder.m_sot_length > + UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA) { + opj_event_msg(p_manager, EVT_ERROR, + "p_j2k->m_specific_param.m_decoder.m_sot_length > " + "UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA"); + return OPJ_FALSE; + } + /* Add a margin of OPJ_COMMON_CBLK_DATA_EXTRA to the allocation we */ + /* do so that opj_mqc_init_dec_common() can safely add a synthetic */ + /* 0xFFFF marker. */ + if (! *l_current_data) { + /* LH: oddly enough, in this path, l_tile_len!=0. + * TODO: If this was consistent, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...). + */ + *l_current_data = (OPJ_BYTE*) opj_malloc( + p_j2k->m_specific_param.m_decoder.m_sot_length + OPJ_COMMON_CBLK_DATA_EXTRA); + } else { + OPJ_BYTE *l_new_current_data; + if (*l_tile_len > UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA - + p_j2k->m_specific_param.m_decoder.m_sot_length) { + opj_event_msg(p_manager, EVT_ERROR, + "*l_tile_len > UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA - " + "p_j2k->m_specific_param.m_decoder.m_sot_length"); + return OPJ_FALSE; + } + + l_new_current_data = (OPJ_BYTE *) opj_realloc(*l_current_data, + *l_tile_len + p_j2k->m_specific_param.m_decoder.m_sot_length + + OPJ_COMMON_CBLK_DATA_EXTRA); + if (! l_new_current_data) { + opj_free(*l_current_data); + /*nothing more is done as l_current_data will be set to null, and just + afterward we enter in the error path + and the actual tile_len is updated (committed) at the end of the + function. */ + } + *l_current_data = l_new_current_data; + } + + if (*l_current_data == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tile\n"); + return OPJ_FALSE; + } + } else { + l_sot_length_pb_detected = OPJ_TRUE; + } + + /* Index */ + l_cstr_index = p_j2k->cstr_index; + { + OPJ_OFF_T l_current_pos = opj_stream_tell(p_stream) - 2; + + OPJ_UINT32 l_current_tile_part = + l_cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno; + l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_header + = + l_current_pos; + l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_pos + = + l_current_pos + p_j2k->m_specific_param.m_decoder.m_sot_length + 2; + + if (OPJ_FALSE == opj_j2k_add_tlmarker(p_j2k->m_current_tile_number, + l_cstr_index, + J2K_MS_SOD, + l_current_pos, + p_j2k->m_specific_param.m_decoder.m_sot_length + 2)) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); + return OPJ_FALSE; + } + + /*l_cstr_index->packno = 0;*/ + } + + /* Patch to support new PHR data */ + if (!l_sot_length_pb_detected) { + l_current_read_size = opj_stream_read_data( + p_stream, + *l_current_data + *l_tile_len, + p_j2k->m_specific_param.m_decoder.m_sot_length, + p_manager); + } else { + l_current_read_size = 0; + } + + if (l_current_read_size != p_j2k->m_specific_param.m_decoder.m_sot_length) { + if (l_current_read_size == (OPJ_SIZE_T)(-1)) { + /* Avoid issue of https://github.com/uclouvain/openjpeg/issues/1533 */ + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; + } else { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + } + + *l_tile_len += (OPJ_UINT32)l_current_read_size; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_rgn(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_UINT32 nb_comps, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_rgn_size; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + OPJ_UINT32 l_comp_room; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + if (nb_comps <= 256) { + l_comp_room = 1; + } else { + l_comp_room = 2; + } + + l_rgn_size = 6 + l_comp_room; + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data, J2K_MS_RGN, + 2); /* RGN */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_rgn_size - 2, + 2); /* Lrgn */ + l_current_data += 2; + + opj_write_bytes(l_current_data, p_comp_no, + l_comp_room); /* Crgn */ + l_current_data += l_comp_room; + + opj_write_bytes(l_current_data, 0, + 1); /* Srgn */ + ++l_current_data; + + opj_write_bytes(l_current_data, (OPJ_UINT32)l_tccp->roishift, + 1); /* SPrgn */ + ++l_current_data; + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_rgn_size, + p_manager) != l_rgn_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_eoc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_header_tile_data, + J2K_MS_EOC, 2); /* EOC */ + + /* UniPG>> */ +#ifdef USE_JPWL + /* update markers struct */ + /* + OPJ_BOOL res = j2k_add_marker(p_j2k->cstr_info, J2K_MS_EOC, p_stream_tell(p_stream) - 2, 2); + */ +#endif /* USE_JPWL */ + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, 2, p_manager) != 2) { + return OPJ_FALSE; + } + + if (! opj_stream_flush(p_stream, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads a RGN marker (Region Of Interest) + * + * @param p_header_data the data contained in the POC box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the POC marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_rgn(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_nb_comp; + opj_image_t * l_image = 00; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_comp_room, l_comp_no, l_roi_sty; + + /* preconditions*/ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_private_image; + l_nb_comp = l_image->numcomps; + + if (l_nb_comp <= 256) { + l_comp_room = 1; + } else { + l_comp_room = 2; + } + + if (p_header_size != 2 + l_comp_room) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading RGN marker\n"); + return OPJ_FALSE; + } + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + opj_read_bytes(p_header_data, &l_comp_no, l_comp_room); /* Crgn */ + p_header_data += l_comp_room; + opj_read_bytes(p_header_data, &l_roi_sty, + 1); /* Srgn */ + ++p_header_data; + +#ifdef USE_JPWL + if (l_cp->correct) { + /* totlen is negative or larger than the bytes left!!! */ + if (l_comp_room >= l_nb_comp) { + opj_event_msg(p_manager, EVT_ERROR, + "JPWL: bad component number in RGN (%d when there are only %d)\n", + l_comp_room, l_nb_comp); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + } + }; +#endif /* USE_JPWL */ + + /* testcase 3635.pdf.asan.77.2930 */ + if (l_comp_no >= l_nb_comp) { + opj_event_msg(p_manager, EVT_ERROR, + "bad component number in RGN (%d when there are only %d)\n", + l_comp_no, l_nb_comp); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, + (OPJ_UINT32 *)(&(l_tcp->tccps[l_comp_no].roishift)), 1); /* SPrgn */ + ++p_header_data; + + return OPJ_TRUE; + +} + +static OPJ_FLOAT32 opj_j2k_get_tp_stride(opj_tcp_t * p_tcp) +{ + return (OPJ_FLOAT32)((p_tcp->m_nb_tile_parts - 1) * 14); +} + +static OPJ_FLOAT32 opj_j2k_get_default_stride(opj_tcp_t * p_tcp) +{ + (void)p_tcp; + return 0; +} + +static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + opj_cp_t * l_cp = 00; + opj_image_t * l_image = 00; + opj_tcp_t * l_tcp = 00; + opj_image_comp_t * l_img_comp = 00; + + OPJ_UINT32 i, j, k; + OPJ_INT32 l_x0, l_y0, l_x1, l_y1; + OPJ_FLOAT32 * l_rates = 0; + OPJ_FLOAT32 l_sot_remove; + OPJ_UINT32 l_bits_empty, l_size_pixel; + OPJ_UINT64 l_tile_size = 0; + OPJ_UINT32 l_last_res; + OPJ_FLOAT32(* l_tp_stride_func)(opj_tcp_t *) = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + OPJ_UNUSED(p_manager); + + l_cp = &(p_j2k->m_cp); + l_image = p_j2k->m_private_image; + l_tcp = l_cp->tcps; + + l_bits_empty = 8 * l_image->comps->dx * l_image->comps->dy; + l_size_pixel = l_image->numcomps * l_image->comps->prec; + l_sot_remove = (OPJ_FLOAT32) opj_stream_tell(p_stream) / (OPJ_FLOAT32)( + l_cp->th * l_cp->tw); + + if (l_cp->m_specific_param.m_enc.m_tp_on) { + l_tp_stride_func = opj_j2k_get_tp_stride; + } else { + l_tp_stride_func = opj_j2k_get_default_stride; + } + + for (i = 0; i < l_cp->th; ++i) { + for (j = 0; j < l_cp->tw; ++j) { + OPJ_FLOAT32 l_offset = (OPJ_FLOAT32)(*l_tp_stride_func)(l_tcp) / + (OPJ_FLOAT32)l_tcp->numlayers; + + /* 4 borders of the tile rescale on the image if necessary */ + l_x0 = opj_int_max((OPJ_INT32)(l_cp->tx0 + j * l_cp->tdx), + (OPJ_INT32)l_image->x0); + l_y0 = opj_int_max((OPJ_INT32)(l_cp->ty0 + i * l_cp->tdy), + (OPJ_INT32)l_image->y0); + l_x1 = opj_int_min((OPJ_INT32)(l_cp->tx0 + (j + 1) * l_cp->tdx), + (OPJ_INT32)l_image->x1); + l_y1 = opj_int_min((OPJ_INT32)(l_cp->ty0 + (i + 1) * l_cp->tdy), + (OPJ_INT32)l_image->y1); + + l_rates = l_tcp->rates; + + /* Modification of the RATE >> */ + for (k = 0; k < l_tcp->numlayers; ++k) { + if (*l_rates > 0.0f) { + *l_rates = (OPJ_FLOAT32)(((OPJ_FLOAT64)l_size_pixel * (OPJ_UINT32)( + l_x1 - l_x0) * + (OPJ_UINT32)(l_y1 - l_y0)) + / ((*l_rates) * (OPJ_FLOAT32)l_bits_empty)) + - + l_offset; + } + + ++l_rates; + } + + ++l_tcp; + + } + } + + l_tcp = l_cp->tcps; + + for (i = 0; i < l_cp->th; ++i) { + for (j = 0; j < l_cp->tw; ++j) { + l_rates = l_tcp->rates; + + if (*l_rates > 0.0f) { + *l_rates -= l_sot_remove; + + if (*l_rates < 30.0f) { + *l_rates = 30.0f; + } + } + + ++l_rates; + + l_last_res = l_tcp->numlayers - 1; + + for (k = 1; k < l_last_res; ++k) { + + if (*l_rates > 0.0f) { + *l_rates -= l_sot_remove; + + if (*l_rates < * (l_rates - 1) + 10.0f) { + *l_rates = (*(l_rates - 1)) + 20.0f; + } + } + + ++l_rates; + } + + if (*l_rates > 0.0f) { + *l_rates -= (l_sot_remove + 2.f); + + if (*l_rates < * (l_rates - 1) + 10.0f) { + *l_rates = (*(l_rates - 1)) + 20.0f; + } + } + + ++l_tcp; + } + } + + l_img_comp = l_image->comps; + l_tile_size = 0; + + for (i = 0; i < l_image->numcomps; ++i) { + l_tile_size += (OPJ_UINT64)opj_uint_ceildiv(l_cp->tdx, l_img_comp->dx) + * + opj_uint_ceildiv(l_cp->tdy, l_img_comp->dy) + * + l_img_comp->prec; + + ++l_img_comp; + } + + /* TODO: where does this magic value come from ? */ + /* This used to be 1.3 / 8, but with random data and very small code */ + /* block sizes, this is not enough. For example with */ + /* bin/test_tile_encoder 1 256 256 32 32 8 0 reversible_with_precinct.j2k 4 4 3 0 0 1 16 16 */ + /* TODO revise this to take into account the overhead linked to the */ + /* number of packets and number of code blocks in packets */ + l_tile_size = (OPJ_UINT64)((double)l_tile_size * 1.4 / 8); + + /* Arbitrary amount to make the following work: */ + /* bin/test_tile_encoder 1 256 256 17 16 8 0 reversible_no_precinct.j2k 4 4 3 0 0 1 */ + l_tile_size += 500; + + l_tile_size += opj_j2k_get_specific_header_sizes(p_j2k); + + if (l_tile_size > UINT_MAX) { + l_tile_size = UINT_MAX; + } + + p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = (OPJ_UINT32)l_tile_size; + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = + (OPJ_BYTE *) opj_malloc(p_j2k->m_specific_param.m_encoder.m_encoded_tile_size); + if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate m_encoded_tile_data. %u MB required\n", + (OPJ_UINT32)(l_tile_size / 1024 / 1024)); + return OPJ_FALSE; + } + + if (p_j2k->m_specific_param.m_encoder.m_TLM) { + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = + (OPJ_BYTE *) opj_malloc(6 * + p_j2k->m_specific_param.m_encoder.m_total_tile_parts); + if (! p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) { + return OPJ_FALSE; + } + + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer; + } + + return OPJ_TRUE; +} + +#if 0 +static OPJ_BOOL opj_j2k_read_eoc(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i; + opj_tcd_t * l_tcd = 00; + OPJ_UINT32 l_nb_tiles; + opj_tcp_t * l_tcp = 00; + OPJ_BOOL l_success; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + l_tcp = p_j2k->m_cp.tcps; + + l_tcd = opj_tcd_create(OPJ_TRUE); + if (l_tcd == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return OPJ_FALSE; + } + + for (i = 0; i < l_nb_tiles; ++i) { + if (l_tcp->m_data) { + if (! opj_tcd_init_decode_tile(l_tcd, i)) { + opj_tcd_destroy(l_tcd); + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return OPJ_FALSE; + } + + l_success = opj_tcd_decode_tile(l_tcd, l_tcp->m_data, l_tcp->m_data_size, i, + p_j2k->cstr_index); + /* cleanup */ + + if (! l_success) { + p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_ERR; + break; + } + } + + opj_j2k_tcp_destroy(l_tcp); + ++l_tcp; + } + + opj_tcd_destroy(l_tcd); + return OPJ_TRUE; +} +#endif + +static OPJ_BOOL opj_j2k_get_end_header(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + OPJ_UNUSED(p_manager); + + p_j2k->cstr_index->main_head_end = opj_stream_tell(p_stream); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_mct_data_group(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 i; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + opj_mct_data_t * l_mct_record; + opj_tcp_t * l_tcp; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + if (! opj_j2k_write_cbd(p_j2k, p_stream, p_manager)) { + return OPJ_FALSE; + } + + l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); + l_mct_record = l_tcp->m_mct_records; + + for (i = 0; i < l_tcp->m_nb_mct_records; ++i) { + + if (! opj_j2k_write_mct_record(p_j2k, l_mct_record, p_stream, p_manager)) { + return OPJ_FALSE; + } + + ++l_mct_record; + } + + l_mcc_record = l_tcp->m_mcc_records; + + for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) { + + if (! opj_j2k_write_mcc_record(p_j2k, l_mcc_record, p_stream, p_manager)) { + return OPJ_FALSE; + } + + ++l_mcc_record; + } + + if (! opj_j2k_write_mco(p_j2k, p_stream, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_all_coc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 compno; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + for (compno = 1; compno < p_j2k->m_private_image->numcomps; ++compno) { + /* cod is first component of first tile */ + if (! opj_j2k_compare_coc(p_j2k, 0, compno)) { + if (! opj_j2k_write_coc(p_j2k, compno, p_stream, p_manager)) { + return OPJ_FALSE; + } + } + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_all_qcc( + opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 compno; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + for (compno = 1; compno < p_j2k->m_private_image->numcomps; ++compno) { + /* qcd is first component of first tile */ + if (! opj_j2k_compare_qcc(p_j2k, 0, compno)) { + if (! opj_j2k_write_qcc(p_j2k, compno, p_stream, p_manager)) { + return OPJ_FALSE; + } + } + } + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_regions(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 compno; + const opj_tccp_t *l_tccp = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tccp = p_j2k->m_cp.tcps->tccps; + + for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno) { + if (l_tccp->roishift) { + + if (! opj_j2k_write_rgn(p_j2k, 0, compno, p_j2k->m_private_image->numcomps, + p_stream, p_manager)) { + return OPJ_FALSE; + } + } + + ++l_tccp; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_epc(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + opj_codestream_index_t * l_cstr_index = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + OPJ_UNUSED(p_manager); + + l_cstr_index = p_j2k->cstr_index; + if (l_cstr_index) { + l_cstr_index->codestream_size = (OPJ_UINT64)opj_stream_tell(p_stream); + /* UniPG>> */ + /* The following adjustment is done to adjust the codestream size */ + /* if SOD is not at 0 in the buffer. Useful in case of JP2, where */ + /* the first bunch of bytes is not in the codestream */ + l_cstr_index->codestream_size -= (OPJ_UINT64)l_cstr_index->main_head_start; + /* <epc_on) { + + /* encode according to JPWL */ + jpwl_encode(p_j2k, p_stream, image); + + } +#endif + assert(0 && "TODO"); +#endif /* USE_JPWL */ + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_read_unk(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + OPJ_UINT32 *output_marker, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_unknown_marker; + const opj_dec_memory_marker_handler_t * l_marker_handler; + OPJ_UINT32 l_size_unk = 2; + + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + opj_event_msg(p_manager, EVT_WARNING, "Unknown marker\n"); + + for (;;) { + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer*/ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* read 2 bytes as the new marker ID*/ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_unknown_marker, 2); + + if (!(l_unknown_marker < 0xff00)) { + + /* Get the marker handler from the marker ID*/ + l_marker_handler = opj_j2k_get_marker_handler(l_unknown_marker); + + if (!(p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker is not compliant with its position\n"); + return OPJ_FALSE; + } else { + if (l_marker_handler->id != J2K_MS_UNK) { + /* Add the marker to the codestream index*/ + if (l_marker_handler->id != J2K_MS_SOT) { + OPJ_BOOL res = opj_j2k_add_mhmarker(p_j2k->cstr_index, J2K_MS_UNK, + (OPJ_UINT32) opj_stream_tell(p_stream) - l_size_unk, + l_size_unk); + if (res == OPJ_FALSE) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); + return OPJ_FALSE; + } + } + break; /* next marker is known and well located */ + } else { + l_size_unk += 2; + } + } + } + } + + *output_marker = l_marker_handler->id ; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_mct_record(opj_j2k_t *p_j2k, + opj_mct_data_t * p_mct_record, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 l_mct_size; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tmp; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_mct_size = 10 + p_mct_record->m_data_size; + + if (l_mct_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mct_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write MCT marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mct_size; + } + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data, J2K_MS_MCT, + 2); /* MCT */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_mct_size - 2, + 2); /* Lmct */ + l_current_data += 2; + + opj_write_bytes(l_current_data, 0, + 2); /* Zmct */ + l_current_data += 2; + + /* only one marker atm */ + l_tmp = (p_mct_record->m_index & 0xff) | (p_mct_record->m_array_type << 8) | + (p_mct_record->m_element_type << 10); + + opj_write_bytes(l_current_data, l_tmp, 2); + l_current_data += 2; + + opj_write_bytes(l_current_data, 0, + 2); /* Ymct */ + l_current_data += 2; + + memcpy(l_current_data, p_mct_record->m_data, p_mct_record->m_data_size); + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mct_size, + p_manager) != l_mct_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads a MCT marker (Multiple Component Transform) + * + * @param p_header_data the data contained in the MCT box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCT marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 i; + opj_tcp_t *l_tcp = 00; + OPJ_UINT32 l_tmp; + OPJ_UINT32 l_indix; + opj_mct_data_t * l_mct_data; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? + &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return OPJ_FALSE; + } + + /* first marker */ + opj_read_bytes(p_header_data, &l_tmp, 2); /* Zmct */ + p_header_data += 2; + if (l_tmp != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge mct data within multiple MCT records\n"); + return OPJ_TRUE; + } + + if (p_header_size <= 6) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return OPJ_FALSE; + } + + /* Imct -> no need for other values, take the first, type is double with decorrelation x0000 1101 0000 0000*/ + opj_read_bytes(p_header_data, &l_tmp, 2); /* Imct */ + p_header_data += 2; + + l_indix = l_tmp & 0xff; + l_mct_data = l_tcp->m_mct_records; + + for (i = 0; i < l_tcp->m_nb_mct_records; ++i) { + if (l_mct_data->m_index == l_indix) { + break; + } + ++l_mct_data; + } + + /* NOT FOUND */ + if (i == l_tcp->m_nb_mct_records) { + if (l_tcp->m_nb_mct_records == l_tcp->m_nb_max_mct_records) { + opj_mct_data_t *new_mct_records; + l_tcp->m_nb_max_mct_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + + new_mct_records = (opj_mct_data_t *) opj_realloc(l_tcp->m_mct_records, + l_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if (! new_mct_records) { + opj_free(l_tcp->m_mct_records); + l_tcp->m_mct_records = NULL; + l_tcp->m_nb_max_mct_records = 0; + l_tcp->m_nb_mct_records = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read MCT marker\n"); + return OPJ_FALSE; + } + + /* Update m_mcc_records[].m_offset_array and m_decorrelation_array + * to point to the new addresses */ + if (new_mct_records != l_tcp->m_mct_records) { + for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) { + opj_simple_mcc_decorrelation_data_t* l_mcc_record = + &(l_tcp->m_mcc_records[i]); + if (l_mcc_record->m_decorrelation_array) { + l_mcc_record->m_decorrelation_array = + new_mct_records + + (l_mcc_record->m_decorrelation_array - + l_tcp->m_mct_records); + } + if (l_mcc_record->m_offset_array) { + l_mcc_record->m_offset_array = + new_mct_records + + (l_mcc_record->m_offset_array - + l_tcp->m_mct_records); + } + } + } + + l_tcp->m_mct_records = new_mct_records; + l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; + memset(l_mct_data, 0, (l_tcp->m_nb_max_mct_records - l_tcp->m_nb_mct_records) * + sizeof(opj_mct_data_t)); + } + + l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records; + ++l_tcp->m_nb_mct_records; + } + + if (l_mct_data->m_data) { + opj_free(l_mct_data->m_data); + l_mct_data->m_data = 00; + l_mct_data->m_data_size = 0; + } + + l_mct_data->m_index = l_indix; + l_mct_data->m_array_type = (J2K_MCT_ARRAY_TYPE)((l_tmp >> 8) & 3); + l_mct_data->m_element_type = (J2K_MCT_ELEMENT_TYPE)((l_tmp >> 10) & 3); + + opj_read_bytes(p_header_data, &l_tmp, 2); /* Ymct */ + p_header_data += 2; + if (l_tmp != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple MCT markers\n"); + return OPJ_TRUE; + } + + p_header_size -= 6; + + l_mct_data->m_data = (OPJ_BYTE*)opj_malloc(p_header_size); + if (! l_mct_data->m_data) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); + return OPJ_FALSE; + } + memcpy(l_mct_data->m_data, p_header_data, p_header_size); + + l_mct_data->m_data_size = p_header_size; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_mcc_record(opj_j2k_t *p_j2k, + struct opj_simple_mcc_decorrelation_data * p_mcc_record, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_mcc_size; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_nb_bytes_for_comp; + OPJ_UINT32 l_mask; + OPJ_UINT32 l_tmcc; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + if (p_mcc_record->m_nb_comps > 255) { + l_nb_bytes_for_comp = 2; + l_mask = 0x8000; + } else { + l_nb_bytes_for_comp = 1; + l_mask = 0; + } + + l_mcc_size = p_mcc_record->m_nb_comps * 2 * l_nb_bytes_for_comp + 19; + if (l_mcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mcc_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write MCC marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mcc_size; + } + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data, J2K_MS_MCC, + 2); /* MCC */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_mcc_size - 2, + 2); /* Lmcc */ + l_current_data += 2; + + /* first marker */ + opj_write_bytes(l_current_data, 0, + 2); /* Zmcc */ + l_current_data += 2; + + opj_write_bytes(l_current_data, p_mcc_record->m_index, + 1); /* Imcc -> no need for other values, take the first */ + ++l_current_data; + + /* only one marker atm */ + opj_write_bytes(l_current_data, 0, + 2); /* Ymcc */ + l_current_data += 2; + + opj_write_bytes(l_current_data, 1, + 2); /* Qmcc -> number of collections -> 1 */ + l_current_data += 2; + + opj_write_bytes(l_current_data, 0x1, + 1); /* Xmcci type of component transformation -> array based decorrelation */ + ++l_current_data; + + opj_write_bytes(l_current_data, p_mcc_record->m_nb_comps | l_mask, + 2); /* Nmcci number of input components involved and size for each component offset = 8 bits */ + l_current_data += 2; + + for (i = 0; i < p_mcc_record->m_nb_comps; ++i) { + opj_write_bytes(l_current_data, i, + l_nb_bytes_for_comp); /* Cmccij Component offset*/ + l_current_data += l_nb_bytes_for_comp; + } + + opj_write_bytes(l_current_data, p_mcc_record->m_nb_comps | l_mask, + 2); /* Mmcci number of output components involved and size for each component offset = 8 bits */ + l_current_data += 2; + + for (i = 0; i < p_mcc_record->m_nb_comps; ++i) { + opj_write_bytes(l_current_data, i, + l_nb_bytes_for_comp); /* Wmccij Component offset*/ + l_current_data += l_nb_bytes_for_comp; + } + + l_tmcc = ((!p_mcc_record->m_is_irreversible) & 1U) << 16; + + if (p_mcc_record->m_decorrelation_array) { + l_tmcc |= p_mcc_record->m_decorrelation_array->m_index; + } + + if (p_mcc_record->m_offset_array) { + l_tmcc |= ((p_mcc_record->m_offset_array->m_index) << 8); + } + + opj_write_bytes(l_current_data, l_tmcc, + 3); /* Tmcci : use MCT defined as number 1 and irreversible array based. */ + l_current_data += 3; + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mcc_size, + p_manager) != l_mcc_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_read_mcc(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, j; + OPJ_UINT32 l_tmp; + OPJ_UINT32 l_indix; + opj_tcp_t * l_tcp; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + opj_mct_data_t * l_mct_data; + OPJ_UINT32 l_nb_collections; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 l_nb_bytes_by_comp; + OPJ_BOOL l_new_mcc = OPJ_FALSE; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? + &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } + + /* first marker */ + opj_read_bytes(p_header_data, &l_tmp, 2); /* Zmcc */ + p_header_data += 2; + if (l_tmp != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple data spanning\n"); + return OPJ_TRUE; + } + + if (p_header_size < 7) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &l_indix, + 1); /* Imcc -> no need for other values, take the first */ + ++p_header_data; + + l_mcc_record = l_tcp->m_mcc_records; + + for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) { + if (l_mcc_record->m_index == l_indix) { + break; + } + ++l_mcc_record; + } + + /** NOT FOUND */ + if (i == l_tcp->m_nb_mcc_records) { + if (l_tcp->m_nb_mcc_records == l_tcp->m_nb_max_mcc_records) { + opj_simple_mcc_decorrelation_data_t *new_mcc_records; + l_tcp->m_nb_max_mcc_records += OPJ_J2K_MCC_DEFAULT_NB_RECORDS; + + new_mcc_records = (opj_simple_mcc_decorrelation_data_t *) opj_realloc( + l_tcp->m_mcc_records, l_tcp->m_nb_max_mcc_records * sizeof( + opj_simple_mcc_decorrelation_data_t)); + if (! new_mcc_records) { + opj_free(l_tcp->m_mcc_records); + l_tcp->m_mcc_records = NULL; + l_tcp->m_nb_max_mcc_records = 0; + l_tcp->m_nb_mcc_records = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read MCC marker\n"); + return OPJ_FALSE; + } + l_tcp->m_mcc_records = new_mcc_records; + l_mcc_record = l_tcp->m_mcc_records + l_tcp->m_nb_mcc_records; + memset(l_mcc_record, 0, (l_tcp->m_nb_max_mcc_records - l_tcp->m_nb_mcc_records) + * sizeof(opj_simple_mcc_decorrelation_data_t)); + } + l_mcc_record = l_tcp->m_mcc_records + l_tcp->m_nb_mcc_records; + l_new_mcc = OPJ_TRUE; + } + l_mcc_record->m_index = l_indix; + + /* only one marker atm */ + opj_read_bytes(p_header_data, &l_tmp, 2); /* Ymcc */ + p_header_data += 2; + if (l_tmp != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple data spanning\n"); + return OPJ_TRUE; + } + + opj_read_bytes(p_header_data, &l_nb_collections, + 2); /* Qmcc -> number of collections -> 1 */ + p_header_data += 2; + + if (l_nb_collections > 1) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple collections\n"); + return OPJ_TRUE; + } + + p_header_size -= 7; + + for (i = 0; i < l_nb_collections; ++i) { + if (p_header_size < 3) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &l_tmp, + 1); /* Xmcci type of component transformation -> array based decorrelation */ + ++p_header_data; + + if (l_tmp != 1) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge collections other than array decorrelation\n"); + return OPJ_TRUE; + } + + opj_read_bytes(p_header_data, &l_nb_comps, 2); + + p_header_data += 2; + p_header_size -= 3; + + l_nb_bytes_by_comp = 1 + (l_nb_comps >> 15); + l_mcc_record->m_nb_comps = l_nb_comps & 0x7fff; + + if (p_header_size < (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } + + p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2); + + for (j = 0; j < l_mcc_record->m_nb_comps; ++j) { + opj_read_bytes(p_header_data, &l_tmp, + l_nb_bytes_by_comp); /* Cmccij Component offset*/ + p_header_data += l_nb_bytes_by_comp; + + if (l_tmp != j) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge collections with indix shuffle\n"); + return OPJ_TRUE; + } + } + + opj_read_bytes(p_header_data, &l_nb_comps, 2); + p_header_data += 2; + + l_nb_bytes_by_comp = 1 + (l_nb_comps >> 15); + l_nb_comps &= 0x7fff; + + if (l_nb_comps != l_mcc_record->m_nb_comps) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge collections without same number of indixes\n"); + return OPJ_TRUE; + } + + if (p_header_size < (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3)) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } + + p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3); + + for (j = 0; j < l_mcc_record->m_nb_comps; ++j) { + opj_read_bytes(p_header_data, &l_tmp, + l_nb_bytes_by_comp); /* Wmccij Component offset*/ + p_header_data += l_nb_bytes_by_comp; + + if (l_tmp != j) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge collections with indix shuffle\n"); + return OPJ_TRUE; + } + } + + opj_read_bytes(p_header_data, &l_tmp, 3); /* Wmccij Component offset*/ + p_header_data += 3; + + l_mcc_record->m_is_irreversible = !((l_tmp >> 16) & 1); + l_mcc_record->m_decorrelation_array = 00; + l_mcc_record->m_offset_array = 00; + + l_indix = l_tmp & 0xff; + if (l_indix != 0) { + l_mct_data = l_tcp->m_mct_records; + for (j = 0; j < l_tcp->m_nb_mct_records; ++j) { + if (l_mct_data->m_index == l_indix) { + l_mcc_record->m_decorrelation_array = l_mct_data; + break; + } + ++l_mct_data; + } + + if (l_mcc_record->m_decorrelation_array == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } + } + + l_indix = (l_tmp >> 8) & 0xff; + if (l_indix != 0) { + l_mct_data = l_tcp->m_mct_records; + for (j = 0; j < l_tcp->m_nb_mct_records; ++j) { + if (l_mct_data->m_index == l_indix) { + l_mcc_record->m_offset_array = l_mct_data; + break; + } + ++l_mct_data; + } + + if (l_mcc_record->m_offset_array == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } + } + } + + if (p_header_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); + return OPJ_FALSE; + } + + if (l_new_mcc) { + ++l_tcp->m_nb_mcc_records; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_mco(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_mco_size; + opj_tcp_t * l_tcp = 00; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + OPJ_UINT32 i; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_tcp = &(p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]); + + l_mco_size = 5 + l_tcp->m_nb_mcc_records; + if (l_mco_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mco_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write MCO marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mco_size; + } + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + + opj_write_bytes(l_current_data, J2K_MS_MCO, 2); /* MCO */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_mco_size - 2, 2); /* Lmco */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_tcp->m_nb_mcc_records, + 1); /* Nmco : only one transform stage*/ + ++l_current_data; + + l_mcc_record = l_tcp->m_mcc_records; + for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) { + opj_write_bytes(l_current_data, l_mcc_record->m_index, + 1); /* Imco -> use the mcc indicated by 1*/ + ++l_current_data; + ++l_mcc_record; + } + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_mco_size, + p_manager) != l_mco_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads a MCO marker (Multiple Component Transform Ordering) + * + * @param p_header_data the data contained in the MCO box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the MCO marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_mco(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_tmp, i; + OPJ_UINT32 l_nb_stages; + opj_tcp_t * l_tcp; + opj_tccp_t * l_tccp; + opj_image_t * l_image; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_image = p_j2k->m_private_image; + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? + &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + if (p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading MCO marker\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &l_nb_stages, + 1); /* Nmco : only one transform stage*/ + ++p_header_data; + + if (l_nb_stages > 1) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot take in charge multiple transformation stages.\n"); + return OPJ_TRUE; + } + + if (p_header_size != l_nb_stages + 1) { + opj_event_msg(p_manager, EVT_WARNING, "Error reading MCO marker\n"); + return OPJ_FALSE; + } + + l_tccp = l_tcp->tccps; + + for (i = 0; i < l_image->numcomps; ++i) { + l_tccp->m_dc_level_shift = 0; + ++l_tccp; + } + + if (l_tcp->m_mct_decoding_matrix) { + opj_free(l_tcp->m_mct_decoding_matrix); + l_tcp->m_mct_decoding_matrix = 00; + } + + for (i = 0; i < l_nb_stages; ++i) { + opj_read_bytes(p_header_data, &l_tmp, 1); + ++p_header_data; + + if (! opj_j2k_add_mct(l_tcp, p_j2k->m_private_image, l_tmp)) { + return OPJ_FALSE; + } + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_add_mct(opj_tcp_t * p_tcp, opj_image_t * p_image, + OPJ_UINT32 p_index) +{ + OPJ_UINT32 i; + opj_simple_mcc_decorrelation_data_t * l_mcc_record; + opj_mct_data_t * l_deco_array, * l_offset_array; + OPJ_UINT32 l_data_size, l_mct_size, l_offset_size; + OPJ_UINT32 l_nb_elem; + OPJ_UINT32 * l_offset_data, * l_current_offset_data; + opj_tccp_t * l_tccp; + + /* preconditions */ + assert(p_tcp != 00); + + l_mcc_record = p_tcp->m_mcc_records; + + for (i = 0; i < p_tcp->m_nb_mcc_records; ++i) { + if (l_mcc_record->m_index == p_index) { + break; + } + } + + if (i == p_tcp->m_nb_mcc_records) { + /** element discarded **/ + return OPJ_TRUE; + } + + if (l_mcc_record->m_nb_comps != p_image->numcomps) { + /** do not support number of comps != image */ + return OPJ_TRUE; + } + + l_deco_array = l_mcc_record->m_decorrelation_array; + + if (l_deco_array) { + l_data_size = MCT_ELEMENT_SIZE[l_deco_array->m_element_type] * p_image->numcomps + * p_image->numcomps; + if (l_deco_array->m_data_size != l_data_size) { + return OPJ_FALSE; + } + + l_nb_elem = p_image->numcomps * p_image->numcomps; + l_mct_size = l_nb_elem * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + p_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size); + + if (! p_tcp->m_mct_decoding_matrix) { + return OPJ_FALSE; + } + + j2k_mct_read_functions_to_float[l_deco_array->m_element_type]( + l_deco_array->m_data, p_tcp->m_mct_decoding_matrix, l_nb_elem); + } + + l_offset_array = l_mcc_record->m_offset_array; + + if (l_offset_array) { + l_data_size = MCT_ELEMENT_SIZE[l_offset_array->m_element_type] * + p_image->numcomps; + if (l_offset_array->m_data_size != l_data_size) { + return OPJ_FALSE; + } + + l_nb_elem = p_image->numcomps; + l_offset_size = l_nb_elem * (OPJ_UINT32)sizeof(OPJ_UINT32); + l_offset_data = (OPJ_UINT32*)opj_malloc(l_offset_size); + + if (! l_offset_data) { + return OPJ_FALSE; + } + + j2k_mct_read_functions_to_int32[l_offset_array->m_element_type]( + l_offset_array->m_data, l_offset_data, l_nb_elem); + + l_tccp = p_tcp->tccps; + l_current_offset_data = l_offset_data; + + for (i = 0; i < p_image->numcomps; ++i) { + l_tccp->m_dc_level_shift = (OPJ_INT32) * (l_current_offset_data++); + ++l_tccp; + } + + opj_free(l_offset_data); + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_cbd(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_cbd_size; + OPJ_BYTE * l_current_data = 00; + opj_image_t *l_image = 00; + opj_image_comp_t * l_comp = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + l_image = p_j2k->m_private_image; + l_cbd_size = 6 + p_j2k->m_private_image->numcomps; + + if (l_cbd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) { + OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_cbd_size); + if (! new_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = NULL; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to write CBD marker\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_cbd_size; + } + + l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; + + opj_write_bytes(l_current_data, J2K_MS_CBD, 2); /* CBD */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_cbd_size - 2, 2); /* L_CBD */ + l_current_data += 2; + + opj_write_bytes(l_current_data, l_image->numcomps, 2); /* Ncbd */ + l_current_data += 2; + + l_comp = l_image->comps; + + for (i = 0; i < l_image->numcomps; ++i) { + opj_write_bytes(l_current_data, (l_comp->sgnd << 7) | (l_comp->prec - 1), + 1); /* Component bit depth */ + ++l_current_data; + + ++l_comp; + } + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_cbd_size, + p_manager) != l_cbd_size) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads a CBD marker (Component bit depth definition) + * @param p_header_data the data contained in the CBD box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the CBD marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_cbd(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_nb_comp, l_num_comp; + OPJ_UINT32 l_comp_def; + OPJ_UINT32 i; + opj_image_comp_t * l_comp = 00; + + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + l_num_comp = p_j2k->m_private_image->numcomps; + + if (p_header_size != (p_j2k->m_private_image->numcomps + 2)) { + opj_event_msg(p_manager, EVT_ERROR, "Crror reading CBD marker\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &l_nb_comp, + 2); /* Ncbd */ + p_header_data += 2; + + if (l_nb_comp != l_num_comp) { + opj_event_msg(p_manager, EVT_ERROR, "Crror reading CBD marker\n"); + return OPJ_FALSE; + } + + l_comp = p_j2k->m_private_image->comps; + for (i = 0; i < l_num_comp; ++i) { + opj_read_bytes(p_header_data, &l_comp_def, + 1); /* Component bit depth */ + ++p_header_data; + l_comp->sgnd = (l_comp_def >> 7) & 1; + l_comp->prec = (l_comp_def & 0x7f) + 1; + + if (l_comp->prec > 31) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid values for comp = %d : prec=%u (should be between 1 and 38 according to the JPEG2000 norm. OpenJpeg only supports up to 31)\n", + i, l_comp->prec); + return OPJ_FALSE; + } + ++l_comp; + } + + return OPJ_TRUE; +} + +/** + * Reads a CAP marker (extended capabilities definition). Empty implementation. + * Found in HTJ2K files. + * + * @param p_header_data the data contained in the CAP box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the CAP marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_cap(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + (void)p_j2k; + (void)p_header_data; + (void)p_header_size; + (void)p_manager; + + return OPJ_TRUE; +} + +/** + * Reads a CPF marker (corresponding profile). Empty implementation. Found in HTJ2K files + * @param p_header_data the data contained in the CPF box. + * @param p_j2k the jpeg2000 codec. + * @param p_header_size the size of the data contained in the CPF marker. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_read_cpf(opj_j2k_t *p_j2k, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + (void)p_j2k; + (void)p_header_data; + (void)p_header_size; + (void)p_manager; + + return OPJ_TRUE; +} + +/* ----------------------------------------------------------------------- */ +/* J2K / JPT decoder interface */ +/* ----------------------------------------------------------------------- */ + +void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters) +{ + if (j2k && parameters) { + j2k->m_cp.m_specific_param.m_dec.m_layer = parameters->cp_layer; + j2k->m_cp.m_specific_param.m_dec.m_reduce = parameters->cp_reduce; + + j2k->dump_state = (parameters->flags & OPJ_DPARAMETERS_DUMP_FLAG); +#ifdef USE_JPWL + j2k->m_cp.correct = parameters->jpwl_correct; + j2k->m_cp.exp_comps = parameters->jpwl_exp_comps; + j2k->m_cp.max_tiles = parameters->jpwl_max_tiles; +#endif /* USE_JPWL */ + } +} + +void opj_j2k_decoder_set_strict_mode(opj_j2k_t *j2k, OPJ_BOOL strict) +{ + if (j2k) { + j2k->m_cp.strict = strict; + if (strict) { + j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; + } + } +} + +OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads) +{ + /* Currently we pass the thread-pool to the tcd, so we cannot re-set it */ + /* afterwards */ + if (opj_has_thread_support() && j2k->m_tcd == NULL) { + opj_thread_pool_destroy(j2k->m_tp); + j2k->m_tp = NULL; + if (num_threads <= (OPJ_UINT32)INT_MAX) { + j2k->m_tp = opj_thread_pool_create((int)num_threads); + } + if (j2k->m_tp == NULL) { + j2k->m_tp = opj_thread_pool_create(0); + return OPJ_FALSE; + } + return OPJ_TRUE; + } + return OPJ_FALSE; +} + +static int opj_j2k_get_default_thread_count(void) +{ + const char* num_threads_str = getenv("OPJ_NUM_THREADS"); + int num_cpus; + int num_threads; + + if (num_threads_str == NULL || !opj_has_thread_support()) { + return 0; + } + num_cpus = opj_get_num_cpus(); + if (strcmp(num_threads_str, "ALL_CPUS") == 0) { + return num_cpus; + } + if (num_cpus == 0) { + num_cpus = 32; + } + num_threads = atoi(num_threads_str); + if (num_threads < 0) { + num_threads = 0; + } else if (num_threads > 2 * num_cpus) { + num_threads = 2 * num_cpus; + } + return num_threads; +} + +/* ----------------------------------------------------------------------- */ +/* J2K encoder interface */ +/* ----------------------------------------------------------------------- */ + +opj_j2k_t* opj_j2k_create_compress(void) +{ + opj_j2k_t *l_j2k = (opj_j2k_t*) opj_calloc(1, sizeof(opj_j2k_t)); + if (!l_j2k) { + return NULL; + } + + + l_j2k->m_is_decoder = 0; + l_j2k->m_cp.m_is_decoder = 0; + + l_j2k->m_specific_param.m_encoder.m_header_tile_data = (OPJ_BYTE *) opj_malloc( + OPJ_J2K_DEFAULT_HEADER_SIZE); + if (! l_j2k->m_specific_param.m_encoder.m_header_tile_data) { + opj_j2k_destroy(l_j2k); + return NULL; + } + + l_j2k->m_specific_param.m_encoder.m_header_tile_data_size = + OPJ_J2K_DEFAULT_HEADER_SIZE; + + /* validation list creation*/ + l_j2k->m_validation_list = opj_procedure_list_create(); + if (! l_j2k->m_validation_list) { + opj_j2k_destroy(l_j2k); + return NULL; + } + + /* execution list creation*/ + l_j2k->m_procedure_list = opj_procedure_list_create(); + if (! l_j2k->m_procedure_list) { + opj_j2k_destroy(l_j2k); + return NULL; + } + + l_j2k->m_tp = opj_thread_pool_create(opj_j2k_get_default_thread_count()); + if (!l_j2k->m_tp) { + l_j2k->m_tp = opj_thread_pool_create(0); + } + if (!l_j2k->m_tp) { + opj_j2k_destroy(l_j2k); + return NULL; + } + + return l_j2k; +} + +static int opj_j2k_initialise_4K_poc(opj_poc_t *POC, int numres) +{ + POC[0].tile = 1; + POC[0].resno0 = 0; + POC[0].compno0 = 0; + POC[0].layno1 = 1; + POC[0].resno1 = (OPJ_UINT32)(numres - 1); + POC[0].compno1 = 3; + POC[0].prg1 = OPJ_CPRL; + POC[1].tile = 1; + POC[1].resno0 = (OPJ_UINT32)(numres - 1); + POC[1].compno0 = 0; + POC[1].layno1 = 1; + POC[1].resno1 = (OPJ_UINT32)numres; + POC[1].compno1 = 3; + POC[1].prg1 = OPJ_CPRL; + return 2; +} + +static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, + opj_image_t *image, opj_event_mgr_t *p_manager) +{ + /* Configure cinema parameters */ + int i; + + /* No tiling */ + parameters->tile_size_on = OPJ_FALSE; + parameters->cp_tdx = 1; + parameters->cp_tdy = 1; + + /* One tile part for each component */ + parameters->tp_flag = 'C'; + parameters->tp_on = 1; + + /* Tile and Image shall be at (0,0) */ + parameters->cp_tx0 = 0; + parameters->cp_ty0 = 0; + parameters->image_offset_x0 = 0; + parameters->image_offset_y0 = 0; + + /* Codeblock size= 32*32 */ + parameters->cblockw_init = 32; + parameters->cblockh_init = 32; + + /* Codeblock style: no mode switch enabled */ + parameters->mode = 0; + + /* No ROI */ + parameters->roi_compno = -1; + + /* No subsampling */ + parameters->subsampling_dx = 1; + parameters->subsampling_dy = 1; + + /* 9-7 transform */ + parameters->irreversible = 1; + + /* Number of layers */ + if (parameters->tcp_numlayers > 1) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n" + "1 single quality layer" + "-> Number of layers forced to 1 (rather than %d)\n" + "-> Rate of the last layer (%3.1f) will be used", + parameters->tcp_numlayers, + parameters->tcp_rates[parameters->tcp_numlayers - 1]); + parameters->tcp_rates[0] = parameters->tcp_rates[parameters->tcp_numlayers - 1]; + parameters->tcp_numlayers = 1; + } + + /* Resolution levels */ + switch (parameters->rsiz) { + case OPJ_PROFILE_CINEMA_2K: + if (parameters->numresolution > 6) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-3 (2k dc profile) requires:\n" + "Number of decomposition levels <= 5\n" + "-> Number of decomposition levels forced to 5 (rather than %d)\n", + parameters->numresolution + 1); + parameters->numresolution = 6; + } + break; + case OPJ_PROFILE_CINEMA_4K: + if (parameters->numresolution < 2) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-4 (4k dc profile) requires:\n" + "Number of decomposition levels >= 1 && <= 6\n" + "-> Number of decomposition levels forced to 1 (rather than %d)\n", + parameters->numresolution + 1); + parameters->numresolution = 1; + } else if (parameters->numresolution > 7) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-4 (4k dc profile) requires:\n" + "Number of decomposition levels >= 1 && <= 6\n" + "-> Number of decomposition levels forced to 6 (rather than %d)\n", + parameters->numresolution + 1); + parameters->numresolution = 7; + } + break; + default : + break; + } + + /* Precincts */ + parameters->csty |= J2K_CP_CSTY_PRT; + if (parameters->numresolution == 1) { + parameters->res_spec = 1; + parameters->prcw_init[0] = 128; + parameters->prch_init[0] = 128; + } else { + parameters->res_spec = parameters->numresolution - 1; + for (i = 0; i < parameters->res_spec; i++) { + parameters->prcw_init[i] = 256; + parameters->prch_init[i] = 256; + } + } + + /* The progression order shall be CPRL */ + parameters->prog_order = OPJ_CPRL; + + /* Progression order changes for 4K, disallowed for 2K */ + if (parameters->rsiz == OPJ_PROFILE_CINEMA_4K) { + parameters->numpocs = (OPJ_UINT32)opj_j2k_initialise_4K_poc(parameters->POC, + parameters->numresolution); + } else { + parameters->numpocs = 0; + } + + /* Limited bit-rate */ + parameters->cp_disto_alloc = 1; + if (parameters->max_cs_size <= 0) { + /* No rate has been introduced, 24 fps is assumed */ + parameters->max_cs_size = OPJ_CINEMA_24_CS; + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n" + "Maximum 1302083 compressed bytes @ 24fps\n" + "As no rate has been given, this limit will be used.\n"); + } else if (parameters->max_cs_size > OPJ_CINEMA_24_CS) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n" + "Maximum 1302083 compressed bytes @ 24fps\n" + "-> Specified rate exceeds this limit. Rate will be forced to 1302083 bytes.\n"); + parameters->max_cs_size = OPJ_CINEMA_24_CS; + } + + if (parameters->max_comp_size <= 0) { + /* No rate has been introduced, 24 fps is assumed */ + parameters->max_comp_size = OPJ_CINEMA_24_COMP; + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n" + "Maximum 1041666 compressed bytes @ 24fps\n" + "As no rate has been given, this limit will be used.\n"); + } else if (parameters->max_comp_size > OPJ_CINEMA_24_COMP) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-3 and 4 (2k/4k dc profile) requires:\n" + "Maximum 1041666 compressed bytes @ 24fps\n" + "-> Specified rate exceeds this limit. Rate will be forced to 1041666 bytes.\n"); + parameters->max_comp_size = OPJ_CINEMA_24_COMP; + } + + parameters->tcp_rates[0] = (OPJ_FLOAT32)(image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec) / + (OPJ_FLOAT32)(((OPJ_UINT32)parameters->max_cs_size) * 8 * image->comps[0].dx * + image->comps[0].dy); + +} + +static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, + opj_event_mgr_t *p_manager) +{ + OPJ_UINT32 i; + + /* Number of components */ + if (image->numcomps != 3) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-3 (2k dc profile) requires:\n" + "3 components" + "-> Number of components of input image (%d) is not compliant\n" + "-> Non-profile-3 codestream will be generated\n", + image->numcomps); + return OPJ_FALSE; + } + + /* Bitdepth */ + for (i = 0; i < image->numcomps; i++) { + if ((image->comps[i].prec != 12) | (image->comps[i].sgnd)) { + char signed_str[] = "signed"; + char unsigned_str[] = "unsigned"; + char *tmp_str = image->comps[i].sgnd ? signed_str : unsigned_str; + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-3 (2k dc profile) requires:\n" + "Precision of each component shall be 12 bits unsigned" + "-> At least component %d of input image (%d bits, %s) is not compliant\n" + "-> Non-profile-3 codestream will be generated\n", + i, image->comps[i].prec, tmp_str); + return OPJ_FALSE; + } + } + + /* Image size */ + switch (rsiz) { + case OPJ_PROFILE_CINEMA_2K: + if (((image->comps[0].w > 2048) | (image->comps[0].h > 1080))) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-3 (2k dc profile) requires:\n" + "width <= 2048 and height <= 1080\n" + "-> Input image size %d x %d is not compliant\n" + "-> Non-profile-3 codestream will be generated\n", + image->comps[0].w, image->comps[0].h); + return OPJ_FALSE; + } + break; + case OPJ_PROFILE_CINEMA_4K: + if (((image->comps[0].w > 4096) | (image->comps[0].h > 2160))) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Profile-4 (4k dc profile) requires:\n" + "width <= 4096 and height <= 2160\n" + "-> Image size %d x %d is not compliant\n" + "-> Non-profile-4 codestream will be generated\n", + image->comps[0].w, image->comps[0].h); + return OPJ_FALSE; + } + break; + default : + break; + } + + return OPJ_TRUE; +} + +static int opj_j2k_get_imf_max_NL(opj_cparameters_t *parameters, + opj_image_t *image) +{ + /* Decomposition levels */ + const OPJ_UINT16 rsiz = parameters->rsiz; + const OPJ_UINT16 profile = OPJ_GET_IMF_PROFILE(rsiz); + const OPJ_UINT32 XTsiz = parameters->tile_size_on ? (OPJ_UINT32) + parameters->cp_tdx : image->x1; + switch (profile) { + case OPJ_PROFILE_IMF_2K: + return 5; + case OPJ_PROFILE_IMF_4K: + return 6; + case OPJ_PROFILE_IMF_8K: + return 7; + case OPJ_PROFILE_IMF_2K_R: { + if (XTsiz >= 2048) { + return 5; + } else if (XTsiz >= 1024) { + return 4; + } + break; + } + case OPJ_PROFILE_IMF_4K_R: { + if (XTsiz >= 4096) { + return 6; + } else if (XTsiz >= 2048) { + return 5; + } else if (XTsiz >= 1024) { + return 4; + } + break; + } + case OPJ_PROFILE_IMF_8K_R: { + if (XTsiz >= 8192) { + return 7; + } else if (XTsiz >= 4096) { + return 6; + } else if (XTsiz >= 2048) { + return 5; + } else if (XTsiz >= 1024) { + return 4; + } + break; + } + default: + break; + } + return -1; +} + +static void opj_j2k_set_imf_parameters(opj_cparameters_t *parameters, + opj_image_t *image, opj_event_mgr_t *p_manager) +{ + const OPJ_UINT16 rsiz = parameters->rsiz; + const OPJ_UINT16 profile = OPJ_GET_IMF_PROFILE(rsiz); + + OPJ_UNUSED(p_manager); + + /* Override defaults set by opj_set_default_encoder_parameters */ + if (parameters->cblockw_init == OPJ_COMP_PARAM_DEFAULT_CBLOCKW && + parameters->cblockh_init == OPJ_COMP_PARAM_DEFAULT_CBLOCKH) { + parameters->cblockw_init = 32; + parameters->cblockh_init = 32; + } + + /* One tile part for each component */ + parameters->tp_flag = 'C'; + parameters->tp_on = 1; + + if (parameters->prog_order == OPJ_COMP_PARAM_DEFAULT_PROG_ORDER) { + parameters->prog_order = OPJ_CPRL; + } + + if (profile == OPJ_PROFILE_IMF_2K || + profile == OPJ_PROFILE_IMF_4K || + profile == OPJ_PROFILE_IMF_8K) { + /* 9-7 transform */ + parameters->irreversible = 1; + } + + /* Adjust the number of resolutions if set to its defaults */ + if (parameters->numresolution == OPJ_COMP_PARAM_DEFAULT_NUMRESOLUTION && + image->x0 == 0 && + image->y0 == 0) { + const int max_NL = opj_j2k_get_imf_max_NL(parameters, image); + if (max_NL >= 0 && parameters->numresolution > max_NL) { + parameters->numresolution = max_NL + 1; + } + + /* Note: below is generic logic */ + if (!parameters->tile_size_on) { + while (parameters->numresolution > 0) { + if (image->x1 < (1U << ((OPJ_UINT32)parameters->numresolution - 1U))) { + parameters->numresolution --; + continue; + } + if (image->y1 < (1U << ((OPJ_UINT32)parameters->numresolution - 1U))) { + parameters->numresolution --; + continue; + } + break; + } + } + } + + /* Set defaults precincts */ + if (parameters->csty == 0) { + parameters->csty |= J2K_CP_CSTY_PRT; + if (parameters->numresolution == 1) { + parameters->res_spec = 1; + parameters->prcw_init[0] = 128; + parameters->prch_init[0] = 128; + } else { + int i; + parameters->res_spec = parameters->numresolution - 1; + for (i = 0; i < parameters->res_spec; i++) { + parameters->prcw_init[i] = 256; + parameters->prch_init[i] = 256; + } + } + } +} + +/* Table A.53 from JPEG2000 standard */ +static const OPJ_UINT16 tabMaxSubLevelFromMainLevel[] = { + 15, /* unspecified */ + 1, + 1, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 +}; + +static OPJ_BOOL opj_j2k_is_imf_compliant(opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t *p_manager) +{ + OPJ_UINT32 i; + const OPJ_UINT16 rsiz = parameters->rsiz; + const OPJ_UINT16 profile = OPJ_GET_IMF_PROFILE(rsiz); + const OPJ_UINT16 mainlevel = OPJ_GET_IMF_MAINLEVEL(rsiz); + const OPJ_UINT16 sublevel = OPJ_GET_IMF_SUBLEVEL(rsiz); + const int NL = parameters->numresolution - 1; + const OPJ_UINT32 XTsiz = parameters->tile_size_on ? (OPJ_UINT32) + parameters->cp_tdx : image->x1; + OPJ_BOOL ret = OPJ_TRUE; + + /* Validate mainlevel */ + if (mainlevel > OPJ_IMF_MAINLEVEL_MAX) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profile require mainlevel <= 11.\n" + "-> %d is thus not compliant\n" + "-> Non-IMF codestream will be generated\n", + mainlevel); + ret = OPJ_FALSE; + } else { + /* Validate sublevel */ + assert(sizeof(tabMaxSubLevelFromMainLevel) == + (OPJ_IMF_MAINLEVEL_MAX + 1) * sizeof(tabMaxSubLevelFromMainLevel[0])); + if (sublevel > tabMaxSubLevelFromMainLevel[mainlevel]) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profile require sublevel <= %d for mainlevel = %d.\n" + "-> %d is thus not compliant\n" + "-> Non-IMF codestream will be generated\n", + tabMaxSubLevelFromMainLevel[mainlevel], + mainlevel, + sublevel); + ret = OPJ_FALSE; + } + } + + /* Number of components */ + if (image->numcomps > 3) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require at most 3 components.\n" + "-> Number of components of input image (%d) is not compliant\n" + "-> Non-IMF codestream will be generated\n", + image->numcomps); + ret = OPJ_FALSE; + } + + if (image->x0 != 0 || image->y0 != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require image origin to be at 0,0.\n" + "-> %d,%d is not compliant\n" + "-> Non-IMF codestream will be generated\n", + image->x0, image->y0 != 0); + ret = OPJ_FALSE; + } + + if (parameters->cp_tx0 != 0 || parameters->cp_ty0 != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require tile origin to be at 0,0.\n" + "-> %d,%d is not compliant\n" + "-> Non-IMF codestream will be generated\n", + parameters->cp_tx0, parameters->cp_ty0); + ret = OPJ_FALSE; + } + + if (parameters->tile_size_on) { + if (profile == OPJ_PROFILE_IMF_2K || + profile == OPJ_PROFILE_IMF_4K || + profile == OPJ_PROFILE_IMF_8K) { + if ((OPJ_UINT32)parameters->cp_tdx < image->x1 || + (OPJ_UINT32)parameters->cp_tdy < image->y1) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 2K/4K/8K single tile profiles require tile to be greater or equal to image size.\n" + "-> %d,%d is lesser than %d,%d\n" + "-> Non-IMF codestream will be generated\n", + parameters->cp_tdx, + parameters->cp_tdy, + image->x1, + image->y1); + ret = OPJ_FALSE; + } + } else { + if ((OPJ_UINT32)parameters->cp_tdx >= image->x1 && + (OPJ_UINT32)parameters->cp_tdy >= image->y1) { + /* ok */ + } else if (parameters->cp_tdx == 1024 && + parameters->cp_tdy == 1024) { + /* ok */ + } else if (parameters->cp_tdx == 2048 && + parameters->cp_tdy == 2048 && + (profile == OPJ_PROFILE_IMF_4K || + profile == OPJ_PROFILE_IMF_8K)) { + /* ok */ + } else if (parameters->cp_tdx == 4096 && + parameters->cp_tdy == 4096 && + profile == OPJ_PROFILE_IMF_8K) { + /* ok */ + } else { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 2K_R/4K_R/8K_R single/multiple tile profiles " + "require tile to be greater or equal to image size,\n" + "or to be (1024,1024), or (2048,2048) for 4K_R/8K_R " + "or (4096,4096) for 8K_R.\n" + "-> %d,%d is non conformant\n" + "-> Non-IMF codestream will be generated\n", + parameters->cp_tdx, + parameters->cp_tdy); + ret = OPJ_FALSE; + } + } + } + + /* Bitdepth */ + for (i = 0; i < image->numcomps; i++) { + if (!(image->comps[i].prec >= 8 && image->comps[i].prec <= 16) || + (image->comps[i].sgnd)) { + char signed_str[] = "signed"; + char unsigned_str[] = "unsigned"; + char *tmp_str = image->comps[i].sgnd ? signed_str : unsigned_str; + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require precision of each component to b in [8-16] bits unsigned" + "-> At least component %d of input image (%d bits, %s) is not compliant\n" + "-> Non-IMF codestream will be generated\n", + i, image->comps[i].prec, tmp_str); + ret = OPJ_FALSE; + } + } + + /* Sub-sampling */ + for (i = 0; i < image->numcomps; i++) { + if (i == 0 && image->comps[i].dx != 1) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require XRSiz1 == 1. Here it is set to %d.\n" + "-> Non-IMF codestream will be generated\n", + image->comps[i].dx); + ret = OPJ_FALSE; + } + if (i == 1 && image->comps[i].dx != 1 && image->comps[i].dx != 2) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require XRSiz2 == 1 or 2. Here it is set to %d.\n" + "-> Non-IMF codestream will be generated\n", + image->comps[i].dx); + ret = OPJ_FALSE; + } + if (i > 1 && image->comps[i].dx != image->comps[i - 1].dx) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require XRSiz%d to be the same as XRSiz2. " + "Here it is set to %d instead of %d.\n" + "-> Non-IMF codestream will be generated\n", + i + 1, image->comps[i].dx, image->comps[i - 1].dx); + ret = OPJ_FALSE; + } + if (image->comps[i].dy != 1) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require YRsiz == 1. " + "Here it is set to %d for component %d.\n" + "-> Non-IMF codestream will be generated\n", + image->comps[i].dy, i); + ret = OPJ_FALSE; + } + } + + /* Image size */ + switch (profile) { + case OPJ_PROFILE_IMF_2K: + case OPJ_PROFILE_IMF_2K_R: + if (((image->comps[0].w > 2048) | (image->comps[0].h > 1556))) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 2K/2K_R profile require:\n" + "width <= 2048 and height <= 1556\n" + "-> Input image size %d x %d is not compliant\n" + "-> Non-IMF codestream will be generated\n", + image->comps[0].w, image->comps[0].h); + ret = OPJ_FALSE; + } + break; + case OPJ_PROFILE_IMF_4K: + case OPJ_PROFILE_IMF_4K_R: + if (((image->comps[0].w > 4096) | (image->comps[0].h > 3112))) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 4K/4K_R profile require:\n" + "width <= 4096 and height <= 3112\n" + "-> Input image size %d x %d is not compliant\n" + "-> Non-IMF codestream will be generated\n", + image->comps[0].w, image->comps[0].h); + ret = OPJ_FALSE; + } + break; + case OPJ_PROFILE_IMF_8K: + case OPJ_PROFILE_IMF_8K_R: + if (((image->comps[0].w > 8192) | (image->comps[0].h > 6224))) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 8K/8K_R profile require:\n" + "width <= 8192 and height <= 6224\n" + "-> Input image size %d x %d is not compliant\n" + "-> Non-IMF codestream will be generated\n", + image->comps[0].w, image->comps[0].h); + ret = OPJ_FALSE; + } + break; + default : + assert(0); + return OPJ_FALSE; + } + + if (parameters->roi_compno != -1) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profile forbid RGN / region of interest marker.\n" + "-> Compression parameters specify a ROI\n" + "-> Non-IMF codestream will be generated\n"); + ret = OPJ_FALSE; + } + + if (parameters->cblockw_init != 32 || parameters->cblockh_init != 32) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profile require code block size to be 32x32.\n" + "-> Compression parameters set it to %dx%d.\n" + "-> Non-IMF codestream will be generated\n", + parameters->cblockw_init, + parameters->cblockh_init); + ret = OPJ_FALSE; + } + + if (parameters->prog_order != OPJ_CPRL) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profile require progression order to be CPRL.\n" + "-> Compression parameters set it to %d.\n" + "-> Non-IMF codestream will be generated\n", + parameters->prog_order); + ret = OPJ_FALSE; + } + + if (parameters->numpocs != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profile forbid POC markers.\n" + "-> Compression parameters set %d POC.\n" + "-> Non-IMF codestream will be generated\n", + parameters->numpocs); + ret = OPJ_FALSE; + } + + /* Codeblock style: no mode switch enabled */ + if (parameters->mode != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profile forbid mode switch in code block style.\n" + "-> Compression parameters set code block style to %d.\n" + "-> Non-IMF codestream will be generated\n", + parameters->mode); + ret = OPJ_FALSE; + } + + if (profile == OPJ_PROFILE_IMF_2K || + profile == OPJ_PROFILE_IMF_4K || + profile == OPJ_PROFILE_IMF_8K) { + /* Expect 9-7 transform */ + if (parameters->irreversible != 1) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 2K/4K/8K profiles require 9-7 Irreversible Transform.\n" + "-> Compression parameters set it to reversible.\n" + "-> Non-IMF codestream will be generated\n"); + ret = OPJ_FALSE; + } + } else { + /* Expect 5-3 transform */ + if (parameters->irreversible != 0) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 2K/4K/8K profiles require 5-3 reversible Transform.\n" + "-> Compression parameters set it to irreversible.\n" + "-> Non-IMF codestream will be generated\n"); + ret = OPJ_FALSE; + } + } + + /* Number of layers */ + if (parameters->tcp_numlayers != 1) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 2K/4K/8K profiles require 1 single quality layer.\n" + "-> Number of layers is %d.\n" + "-> Non-IMF codestream will be generated\n", + parameters->tcp_numlayers); + ret = OPJ_FALSE; + } + + /* Decomposition levels */ + switch (profile) { + case OPJ_PROFILE_IMF_2K: + if (!(NL >= 1 && NL <= 5)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 2K profile requires 1 <= NL <= 5:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + break; + case OPJ_PROFILE_IMF_4K: + if (!(NL >= 1 && NL <= 6)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 4K profile requires 1 <= NL <= 6:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + break; + case OPJ_PROFILE_IMF_8K: + if (!(NL >= 1 && NL <= 7)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 8K profile requires 1 <= NL <= 7:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + break; + case OPJ_PROFILE_IMF_2K_R: { + if (XTsiz >= 2048) { + if (!(NL >= 1 && NL <= 5)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 2K_R profile requires 1 <= NL <= 5 for XTsiz >= 2048:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + } else if (XTsiz >= 1024) { + if (!(NL >= 1 && NL <= 4)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 2K_R profile requires 1 <= NL <= 4 for XTsiz in [1024,2048[:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + } + break; + } + case OPJ_PROFILE_IMF_4K_R: { + if (XTsiz >= 4096) { + if (!(NL >= 1 && NL <= 6)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 4K_R profile requires 1 <= NL <= 6 for XTsiz >= 4096:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + } else if (XTsiz >= 2048) { + if (!(NL >= 1 && NL <= 5)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 4K_R profile requires 1 <= NL <= 5 for XTsiz in [2048,4096[:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + } else if (XTsiz >= 1024) { + if (!(NL >= 1 && NL <= 4)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 4K_R profile requires 1 <= NL <= 4 for XTsiz in [1024,2048[:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + } + break; + } + case OPJ_PROFILE_IMF_8K_R: { + if (XTsiz >= 8192) { + if (!(NL >= 1 && NL <= 7)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 4K_R profile requires 1 <= NL <= 7 for XTsiz >= 8192:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + } else if (XTsiz >= 4096) { + if (!(NL >= 1 && NL <= 6)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 4K_R profile requires 1 <= NL <= 6 for XTsiz in [4096,8192[:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + } else if (XTsiz >= 2048) { + if (!(NL >= 1 && NL <= 5)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 4K_R profile requires 1 <= NL <= 5 for XTsiz in [2048,4096[:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + } else if (XTsiz >= 1024) { + if (!(NL >= 1 && NL <= 4)) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF 4K_R profile requires 1 <= NL <= 4 for XTsiz in [1024,2048[:\n" + "-> Number of decomposition levels is %d.\n" + "-> Non-IMF codestream will be generated\n", + NL); + ret = OPJ_FALSE; + } + } + break; + } + default: + break; + } + + if (parameters->numresolution == 1) { + if (parameters->res_spec != 1 || + parameters->prcw_init[0] != 128 || + parameters->prch_init[0] != 128) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require PPx = PPy = 7 for NLLL band, else 8.\n" + "-> Supplied values are different from that.\n" + "-> Non-IMF codestream will be generated\n"); + ret = OPJ_FALSE; + } + } else { + int i; + for (i = 0; i < parameters->res_spec; i++) { + if (parameters->prcw_init[i] != 256 || + parameters->prch_init[i] != 256) { + opj_event_msg(p_manager, EVT_WARNING, + "IMF profiles require PPx = PPy = 7 for NLLL band, else 8.\n" + "-> Supplied values are different from that.\n" + "-> Non-IMF codestream will be generated\n"); + ret = OPJ_FALSE; + } + } + } + + return ret; +} + + +OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, + opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, j, tileno, numpocs_tile; + opj_cp_t *cp = 00; + OPJ_UINT32 cblkw, cblkh; + + if (!p_j2k || !parameters || ! image) { + return OPJ_FALSE; + } + + if ((parameters->numresolution <= 0) || + (parameters->numresolution > OPJ_J2K_MAXRLVLS)) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid number of resolutions : %d not in range [1,%d]\n", + parameters->numresolution, OPJ_J2K_MAXRLVLS); + return OPJ_FALSE; + } + + if (parameters->cblockw_init < 4 || parameters->cblockw_init > 1024) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockw_init: %d not a power of 2 in range [4,1024]\n", + parameters->cblockw_init); + return OPJ_FALSE; + } + if (parameters->cblockh_init < 4 || parameters->cblockh_init > 1024) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockh_init: %d not a power of 2 not in range [4,1024]\n", + parameters->cblockh_init); + return OPJ_FALSE; + } + if (parameters->cblockw_init * parameters->cblockh_init > 4096) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockw_init * cblockh_init: should be <= 4096\n"); + return OPJ_FALSE; + } + cblkw = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockw_init); + cblkh = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockh_init); + if (parameters->cblockw_init != (1 << cblkw)) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockw_init: %d not a power of 2 in range [4,1024]\n", + parameters->cblockw_init); + return OPJ_FALSE; + } + if (parameters->cblockh_init != (1 << cblkh)) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cblockw_init: %d not a power of 2 in range [4,1024]\n", + parameters->cblockh_init); + return OPJ_FALSE; + } + + if (parameters->cp_fixed_alloc) { + if (parameters->cp_matrice == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "cp_fixed_alloc set, but cp_matrice missing\n"); + return OPJ_FALSE; + } + + if (parameters->tcp_numlayers > J2K_TCD_MATRIX_MAX_LAYER_COUNT) { + opj_event_msg(p_manager, EVT_ERROR, + "tcp_numlayers when cp_fixed_alloc set should not exceed %d\n", + J2K_TCD_MATRIX_MAX_LAYER_COUNT); + return OPJ_FALSE; + } + if (parameters->numresolution > J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT) { + opj_event_msg(p_manager, EVT_ERROR, + "numresolution when cp_fixed_alloc set should not exceed %d\n", + J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT); + return OPJ_FALSE; + } + } + + p_j2k->m_specific_param.m_encoder.m_nb_comps = image->numcomps; + + /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */ + cp = &(p_j2k->m_cp); + + /* set default values for cp */ + cp->tw = 1; + cp->th = 1; + + /* FIXME ADE: to be removed once deprecated cp_cinema and cp_rsiz have been removed */ + if (parameters->rsiz == + OPJ_PROFILE_NONE) { /* consider deprecated fields only if RSIZ has not been set */ + OPJ_BOOL deprecated_used = OPJ_FALSE; + switch (parameters->cp_cinema) { + case OPJ_CINEMA2K_24: + parameters->rsiz = OPJ_PROFILE_CINEMA_2K; + parameters->max_cs_size = OPJ_CINEMA_24_CS; + parameters->max_comp_size = OPJ_CINEMA_24_COMP; + deprecated_used = OPJ_TRUE; + break; + case OPJ_CINEMA2K_48: + parameters->rsiz = OPJ_PROFILE_CINEMA_2K; + parameters->max_cs_size = OPJ_CINEMA_48_CS; + parameters->max_comp_size = OPJ_CINEMA_48_COMP; + deprecated_used = OPJ_TRUE; + break; + case OPJ_CINEMA4K_24: + parameters->rsiz = OPJ_PROFILE_CINEMA_4K; + parameters->max_cs_size = OPJ_CINEMA_24_CS; + parameters->max_comp_size = OPJ_CINEMA_24_COMP; + deprecated_used = OPJ_TRUE; + break; + case OPJ_OFF: + default: + break; + } + switch (parameters->cp_rsiz) { + case OPJ_CINEMA2K: + parameters->rsiz = OPJ_PROFILE_CINEMA_2K; + deprecated_used = OPJ_TRUE; + break; + case OPJ_CINEMA4K: + parameters->rsiz = OPJ_PROFILE_CINEMA_4K; + deprecated_used = OPJ_TRUE; + break; + case OPJ_MCT: + parameters->rsiz = OPJ_PROFILE_PART2 | OPJ_EXTENSION_MCT; + deprecated_used = OPJ_TRUE; + case OPJ_STD_RSIZ: + default: + break; + } + if (deprecated_used) { + opj_event_msg(p_manager, EVT_WARNING, + "Deprecated fields cp_cinema or cp_rsiz are used\n" + "Please consider using only the rsiz field\n" + "See openjpeg.h documentation for more details\n"); + } + } + + /* If no explicit layers are provided, use lossless settings */ + if (parameters->tcp_numlayers == 0) { + parameters->tcp_numlayers = 1; + parameters->cp_disto_alloc = 1; + parameters->tcp_rates[0] = 0; + } + + if (parameters->cp_disto_alloc) { + /* Emit warnings if tcp_rates are not decreasing */ + for (i = 1; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) { + OPJ_FLOAT32 rate_i_corr = parameters->tcp_rates[i]; + OPJ_FLOAT32 rate_i_m_1_corr = parameters->tcp_rates[i - 1]; + if (rate_i_corr <= 1.0) { + rate_i_corr = 1.0; + } + if (rate_i_m_1_corr <= 1.0) { + rate_i_m_1_corr = 1.0; + } + if (rate_i_corr >= rate_i_m_1_corr) { + if (rate_i_corr != parameters->tcp_rates[i] && + rate_i_m_1_corr != parameters->tcp_rates[i - 1]) { + opj_event_msg(p_manager, EVT_WARNING, + "tcp_rates[%d]=%f (corrected as %f) should be strictly lesser " + "than tcp_rates[%d]=%f (corrected as %f)\n", + i, parameters->tcp_rates[i], rate_i_corr, + i - 1, parameters->tcp_rates[i - 1], rate_i_m_1_corr); + } else if (rate_i_corr != parameters->tcp_rates[i]) { + opj_event_msg(p_manager, EVT_WARNING, + "tcp_rates[%d]=%f (corrected as %f) should be strictly lesser " + "than tcp_rates[%d]=%f\n", + i, parameters->tcp_rates[i], rate_i_corr, + i - 1, parameters->tcp_rates[i - 1]); + } else if (rate_i_m_1_corr != parameters->tcp_rates[i - 1]) { + opj_event_msg(p_manager, EVT_WARNING, + "tcp_rates[%d]=%f should be strictly lesser " + "than tcp_rates[%d]=%f (corrected as %f)\n", + i, parameters->tcp_rates[i], + i - 1, parameters->tcp_rates[i - 1], rate_i_m_1_corr); + } else { + opj_event_msg(p_manager, EVT_WARNING, + "tcp_rates[%d]=%f should be strictly lesser " + "than tcp_rates[%d]=%f\n", + i, parameters->tcp_rates[i], + i - 1, parameters->tcp_rates[i - 1]); + } + } + } + } else if (parameters->cp_fixed_quality) { + /* Emit warnings if tcp_distoratio are not increasing */ + for (i = 1; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) { + if (parameters->tcp_distoratio[i] < parameters->tcp_distoratio[i - 1] && + !(i == (OPJ_UINT32)parameters->tcp_numlayers - 1 && + parameters->tcp_distoratio[i] == 0)) { + opj_event_msg(p_manager, EVT_WARNING, + "tcp_distoratio[%d]=%f should be strictly greater " + "than tcp_distoratio[%d]=%f\n", + i, parameters->tcp_distoratio[i], i - 1, + parameters->tcp_distoratio[i - 1]); + } + } + } + + /* see if max_codestream_size does limit input rate */ + if (parameters->max_cs_size <= 0) { + if (parameters->tcp_rates[parameters->tcp_numlayers - 1] > 0) { + OPJ_FLOAT32 temp_size; + temp_size = (OPJ_FLOAT32)(((double)image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec) / + ((double)parameters->tcp_rates[parameters->tcp_numlayers - 1] * 8 * + image->comps[0].dx * image->comps[0].dy)); + if (temp_size > (OPJ_FLOAT32)INT_MAX) { + parameters->max_cs_size = INT_MAX; + } else { + parameters->max_cs_size = (int) floor(temp_size); + } + } else { + parameters->max_cs_size = 0; + } + } else { + OPJ_FLOAT32 temp_rate; + OPJ_BOOL cap = OPJ_FALSE; + + if (OPJ_IS_IMF(parameters->rsiz) && parameters->max_cs_size > 0 && + parameters->tcp_numlayers == 1 && parameters->tcp_rates[0] == 0) { + parameters->tcp_rates[0] = (OPJ_FLOAT32)(image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec) / + (OPJ_FLOAT32)(((OPJ_UINT32)parameters->max_cs_size) * 8 * image->comps[0].dx * + image->comps[0].dy); + } + + temp_rate = (OPJ_FLOAT32)(((double)image->numcomps * image->comps[0].w * + image->comps[0].h * image->comps[0].prec) / + (((double)parameters->max_cs_size) * 8 * image->comps[0].dx * + image->comps[0].dy)); + for (i = 0; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) { + if (parameters->tcp_rates[i] < temp_rate) { + parameters->tcp_rates[i] = temp_rate; + cap = OPJ_TRUE; + } + } + if (cap) { + opj_event_msg(p_manager, EVT_WARNING, + "The desired maximum codestream size has limited\n" + "at least one of the desired quality layers\n"); + } + } + + if (OPJ_IS_CINEMA(parameters->rsiz) || OPJ_IS_IMF(parameters->rsiz)) { + p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE; + } + + /* Manage profiles and applications and set RSIZ */ + /* set cinema parameters if required */ + if (OPJ_IS_CINEMA(parameters->rsiz)) { + if ((parameters->rsiz == OPJ_PROFILE_CINEMA_S2K) + || (parameters->rsiz == OPJ_PROFILE_CINEMA_S4K)) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Scalable Digital Cinema profiles not yet supported\n"); + parameters->rsiz = OPJ_PROFILE_NONE; + } else { + opj_j2k_set_cinema_parameters(parameters, image, p_manager); + if (!opj_j2k_is_cinema_compliant(image, parameters->rsiz, p_manager)) { + parameters->rsiz = OPJ_PROFILE_NONE; + } + } + } else if (OPJ_IS_STORAGE(parameters->rsiz)) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Long Term Storage profile not yet supported\n"); + parameters->rsiz = OPJ_PROFILE_NONE; + } else if (OPJ_IS_BROADCAST(parameters->rsiz)) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Broadcast profiles not yet supported\n"); + parameters->rsiz = OPJ_PROFILE_NONE; + } else if (OPJ_IS_IMF(parameters->rsiz)) { + opj_j2k_set_imf_parameters(parameters, image, p_manager); + if (!opj_j2k_is_imf_compliant(parameters, image, p_manager)) { + parameters->rsiz = OPJ_PROFILE_NONE; + } + } else if (OPJ_IS_PART2(parameters->rsiz)) { + if (parameters->rsiz == ((OPJ_PROFILE_PART2) | (OPJ_EXTENSION_NONE))) { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG 2000 Part-2 profile defined\n" + "but no Part-2 extension enabled.\n" + "Profile set to NONE.\n"); + parameters->rsiz = OPJ_PROFILE_NONE; + } else if (parameters->rsiz != ((OPJ_PROFILE_PART2) | (OPJ_EXTENSION_MCT))) { + opj_event_msg(p_manager, EVT_WARNING, + "Unsupported Part-2 extension enabled\n" + "Profile set to NONE.\n"); + parameters->rsiz = OPJ_PROFILE_NONE; + } + } + + /* + copy user encoding parameters + */ + cp->m_specific_param.m_enc.m_max_comp_size = (OPJ_UINT32) + parameters->max_comp_size; + cp->rsiz = parameters->rsiz; + if (parameters->cp_fixed_alloc) { + cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy = FIXED_LAYER; + } else if (parameters->cp_fixed_quality) { + cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy = + FIXED_DISTORTION_RATIO; + } else { + cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy = + RATE_DISTORTION_RATIO; + } + + if (parameters->cp_fixed_alloc) { + size_t array_size = (size_t)parameters->tcp_numlayers * + (size_t)parameters->numresolution * 3 * sizeof(OPJ_INT32); + cp->m_specific_param.m_enc.m_matrice = (OPJ_INT32 *) opj_malloc(array_size); + if (!cp->m_specific_param.m_enc.m_matrice) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate copy of user encoding parameters matrix \n"); + return OPJ_FALSE; + } + memcpy(cp->m_specific_param.m_enc.m_matrice, parameters->cp_matrice, + array_size); + } + + /* tiles */ + cp->tdx = (OPJ_UINT32)parameters->cp_tdx; + cp->tdy = (OPJ_UINT32)parameters->cp_tdy; + + /* tile offset */ + cp->tx0 = (OPJ_UINT32)parameters->cp_tx0; + cp->ty0 = (OPJ_UINT32)parameters->cp_ty0; + + /* comment string */ + if (parameters->cp_comment) { + cp->comment = (char*)opj_malloc(strlen(parameters->cp_comment) + 1U); + if (!cp->comment) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate copy of comment string\n"); + return OPJ_FALSE; + } + strcpy(cp->comment, parameters->cp_comment); + } else { + /* Create default comment for codestream */ + const char comment[] = "Created by OpenJPEG version "; + const size_t clen = strlen(comment); + const char *version = opj_version(); + + /* UniPG>> */ +#ifdef USE_JPWL + const size_t cp_comment_buf_size = clen + strlen(version) + 11; + cp->comment = (char*)opj_malloc(cp_comment_buf_size); + if (!cp->comment) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate comment string\n"); + return OPJ_FALSE; + } + snprintf(cp->comment, cp_comment_buf_size, "%s%s with JPWL", + comment, version); +#else + const size_t cp_comment_buf_size = clen + strlen(version) + 1; + cp->comment = (char*)opj_malloc(cp_comment_buf_size); + if (!cp->comment) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate comment string\n"); + return OPJ_FALSE; + } + snprintf(cp->comment, cp_comment_buf_size, "%s%s", comment, version); +#endif + /* <tile_size_on) { + if (cp->tdx == 0) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid tile width\n"); + return OPJ_FALSE; + } + if (cp->tdy == 0) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid tile height\n"); + return OPJ_FALSE; + } + cp->tw = opj_uint_ceildiv(image->x1 - cp->tx0, cp->tdx); + cp->th = opj_uint_ceildiv(image->y1 - cp->ty0, cp->tdy); + /* Check that the number of tiles is valid */ + if (cp->tw > 65535 / cp->th) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid number of tiles : %u x %u (maximum fixed by jpeg2000 norm is 65535 tiles)\n", + cp->tw, cp->th); + return OPJ_FALSE; + } + } else { + cp->tdx = image->x1 - cp->tx0; + cp->tdy = image->y1 - cp->ty0; + } + + if (parameters->tp_on) { + cp->m_specific_param.m_enc.m_tp_flag = (OPJ_BYTE)parameters->tp_flag; + cp->m_specific_param.m_enc.m_tp_on = 1; + } + +#ifdef USE_JPWL + /* + calculate JPWL encoding parameters + */ + + if (parameters->jpwl_epc_on) { + OPJ_INT32 i; + + /* set JPWL on */ + cp->epc_on = OPJ_TRUE; + cp->info_on = OPJ_FALSE; /* no informative technique */ + + /* set EPB on */ + if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) { + cp->epb_on = OPJ_TRUE; + + cp->hprot_MH = parameters->jpwl_hprot_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->hprot_TPH_tileno[i] = parameters->jpwl_hprot_TPH_tileno[i]; + cp->hprot_TPH[i] = parameters->jpwl_hprot_TPH[i]; + } + /* if tile specs are not specified, copy MH specs */ + if (cp->hprot_TPH[0] == -1) { + cp->hprot_TPH_tileno[0] = 0; + cp->hprot_TPH[0] = parameters->jpwl_hprot_MH; + } + for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { + cp->pprot_tileno[i] = parameters->jpwl_pprot_tileno[i]; + cp->pprot_packno[i] = parameters->jpwl_pprot_packno[i]; + cp->pprot[i] = parameters->jpwl_pprot[i]; + } + } + + /* set ESD writing */ + if ((parameters->jpwl_sens_size == 1) || (parameters->jpwl_sens_size == 2)) { + cp->esd_on = OPJ_TRUE; + + cp->sens_size = parameters->jpwl_sens_size; + cp->sens_addr = parameters->jpwl_sens_addr; + cp->sens_range = parameters->jpwl_sens_range; + + cp->sens_MH = parameters->jpwl_sens_MH; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + cp->sens_TPH_tileno[i] = parameters->jpwl_sens_TPH_tileno[i]; + cp->sens_TPH[i] = parameters->jpwl_sens_TPH[i]; + } + } + + /* always set RED writing to false: we are at the encoder */ + cp->red_on = OPJ_FALSE; + + } else { + cp->epc_on = OPJ_FALSE; + } +#endif /* USE_JPWL */ + + /* initialize the multiple tiles */ + /* ---------------------------- */ + cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); + if (!cp->tcps) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate tile coding parameters\n"); + return OPJ_FALSE; + } + + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + opj_tcp_t *tcp = &cp->tcps[tileno]; + const OPJ_BOOL fixed_distoratio = + cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + FIXED_DISTORTION_RATIO; + tcp->numlayers = (OPJ_UINT32)parameters->tcp_numlayers; + + for (j = 0; j < tcp->numlayers; j++) { + if (OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)) { + if (fixed_distoratio) { + tcp->distoratio[j] = parameters->tcp_distoratio[j]; + } + tcp->rates[j] = parameters->tcp_rates[j]; + } else { + if (fixed_distoratio) { + tcp->distoratio[j] = parameters->tcp_distoratio[j]; + } else { + tcp->rates[j] = parameters->tcp_rates[j]; + } + } + if (!fixed_distoratio && + tcp->rates[j] <= 1.0) { + tcp->rates[j] = 0.0; /* force lossless */ + } + } + + tcp->csty = (OPJ_UINT32)parameters->csty; + tcp->prg = parameters->prog_order; + tcp->mct = (OPJ_UINT32)parameters->tcp_mct; + + numpocs_tile = 0; + tcp->POC = 0; + + if (parameters->numpocs) { + /* initialisation of POC */ + for (i = 0; i < parameters->numpocs; i++) { + if (tileno + 1 == parameters->POC[i].tile) { + opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile]; + + if (parameters->POC[numpocs_tile].compno0 >= image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid compno0 for POC %d\n", i); + return OPJ_FALSE; + } + + tcp_poc->resno0 = parameters->POC[numpocs_tile].resno0; + tcp_poc->compno0 = parameters->POC[numpocs_tile].compno0; + tcp_poc->layno1 = parameters->POC[numpocs_tile].layno1; + tcp_poc->resno1 = parameters->POC[numpocs_tile].resno1; + tcp_poc->compno1 = opj_uint_min(parameters->POC[numpocs_tile].compno1, + image->numcomps); + tcp_poc->prg1 = parameters->POC[numpocs_tile].prg1; + tcp_poc->tile = parameters->POC[numpocs_tile].tile; + + numpocs_tile++; + } + } + + if (numpocs_tile) { + + /* TODO MSD use the return value*/ + opj_j2k_check_poc_val(parameters->POC, tileno, parameters->numpocs, + (OPJ_UINT32)parameters->numresolution, image->numcomps, + (OPJ_UINT32)parameters->tcp_numlayers, p_manager); + + tcp->POC = 1; + tcp->numpocs = numpocs_tile - 1 ; + } + } else { + tcp->numpocs = 0; + } + + tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t)); + if (!tcp->tccps) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate tile component coding parameters\n"); + return OPJ_FALSE; + } + if (parameters->mct_data) { + + OPJ_UINT32 lMctSize = image->numcomps * image->numcomps * (OPJ_UINT32)sizeof( + OPJ_FLOAT32); + OPJ_FLOAT32 * lTmpBuf = (OPJ_FLOAT32*)opj_malloc(lMctSize); + OPJ_INT32 * l_dc_shift = (OPJ_INT32 *)((OPJ_BYTE *) parameters->mct_data + + lMctSize); + + if (!lTmpBuf) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate temp buffer\n"); + return OPJ_FALSE; + } + + tcp->mct = 2; + tcp->m_mct_coding_matrix = (OPJ_FLOAT32*)opj_malloc(lMctSize); + if (! tcp->m_mct_coding_matrix) { + opj_free(lTmpBuf); + lTmpBuf = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate encoder MCT coding matrix \n"); + return OPJ_FALSE; + } + memcpy(tcp->m_mct_coding_matrix, parameters->mct_data, lMctSize); + memcpy(lTmpBuf, parameters->mct_data, lMctSize); + + tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(lMctSize); + if (! tcp->m_mct_decoding_matrix) { + opj_free(lTmpBuf); + lTmpBuf = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate encoder MCT decoding matrix \n"); + return OPJ_FALSE; + } + if (opj_matrix_inversion_f(lTmpBuf, (tcp->m_mct_decoding_matrix), + image->numcomps) == OPJ_FALSE) { + opj_free(lTmpBuf); + lTmpBuf = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Failed to inverse encoder MCT decoding matrix \n"); + return OPJ_FALSE; + } + + tcp->mct_norms = (OPJ_FLOAT64*) + opj_malloc(image->numcomps * sizeof(OPJ_FLOAT64)); + if (! tcp->mct_norms) { + opj_free(lTmpBuf); + lTmpBuf = NULL; + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to allocate encoder MCT norms \n"); + return OPJ_FALSE; + } + opj_calculate_norms(tcp->mct_norms, image->numcomps, + tcp->m_mct_decoding_matrix); + opj_free(lTmpBuf); + + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + tccp->m_dc_level_shift = l_dc_shift[i]; + } + + if (opj_j2k_setup_mct_encoding(tcp, image) == OPJ_FALSE) { + /* free will be handled by opj_j2k_destroy */ + opj_event_msg(p_manager, EVT_ERROR, "Failed to setup j2k mct encoding\n"); + return OPJ_FALSE; + } + } else { + if (tcp->mct == 1 && image->numcomps >= 3) { /* RGB->YCC MCT is enabled */ + if ((image->comps[0].dx != image->comps[1].dx) || + (image->comps[0].dx != image->comps[2].dx) || + (image->comps[0].dy != image->comps[1].dy) || + (image->comps[0].dy != image->comps[2].dy)) { + opj_event_msg(p_manager, EVT_WARNING, + "Cannot perform MCT on components with different sizes. Disabling MCT.\n"); + tcp->mct = 0; + } + } + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + opj_image_comp_t * l_comp = &(image->comps[i]); + + if (! l_comp->sgnd) { + tccp->m_dc_level_shift = 1 << (l_comp->prec - 1); + } + } + } + + for (i = 0; i < image->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + + tccp->csty = parameters->csty & + 0x01; /* 0 => one precinct || 1 => custom precinct */ + tccp->numresolutions = (OPJ_UINT32)parameters->numresolution; + tccp->cblkw = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockw_init); + tccp->cblkh = (OPJ_UINT32)opj_int_floorlog2(parameters->cblockh_init); + tccp->cblksty = (OPJ_UINT32)parameters->mode; + tccp->qmfbid = parameters->irreversible ? 0 : 1; + tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : + J2K_CCP_QNTSTY_NOQNT; + + if (OPJ_IS_CINEMA(parameters->rsiz) && + parameters->rsiz == OPJ_PROFILE_CINEMA_2K) { + /* From https://github.com/uclouvain/openjpeg/issues/1340 */ + tccp->numgbits = 1; + } else { + tccp->numgbits = 2; + } + + if ((OPJ_INT32)i == parameters->roi_compno) { + tccp->roishift = parameters->roi_shift; + } else { + tccp->roishift = 0; + } + + if (parameters->csty & J2K_CCP_CSTY_PRT) { + OPJ_INT32 p = 0, it_res; + assert(tccp->numresolutions > 0); + for (it_res = (OPJ_INT32)tccp->numresolutions - 1; it_res >= 0; it_res--) { + if (p < parameters->res_spec) { + + if (parameters->prcw_init[p] < 1) { + tccp->prcw[it_res] = 1; + } else { + tccp->prcw[it_res] = (OPJ_UINT32)opj_int_floorlog2(parameters->prcw_init[p]); + } + + if (parameters->prch_init[p] < 1) { + tccp->prch[it_res] = 1; + } else { + tccp->prch[it_res] = (OPJ_UINT32)opj_int_floorlog2(parameters->prch_init[p]); + } + + } else { + OPJ_INT32 res_spec = parameters->res_spec; + OPJ_INT32 size_prcw = 0; + OPJ_INT32 size_prch = 0; + + assert(res_spec > 0); /* issue 189 */ + size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1)); + size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1)); + + + if (size_prcw < 1) { + tccp->prcw[it_res] = 1; + } else { + tccp->prcw[it_res] = (OPJ_UINT32)opj_int_floorlog2(size_prcw); + } + + if (size_prch < 1) { + tccp->prch[it_res] = 1; + } else { + tccp->prch[it_res] = (OPJ_UINT32)opj_int_floorlog2(size_prch); + } + } + p++; + /*printf("\nsize precinct for level %d : %d,%d\n", it_res,tccp->prcw[it_res], tccp->prch[it_res]); */ + } /*end for*/ + } else { + for (j = 0; j < tccp->numresolutions; j++) { + tccp->prcw[j] = 15; + tccp->prch[j] = 15; + } + } + + opj_dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec); + } + } + + if (parameters->mct_data) { + opj_free(parameters->mct_data); + parameters->mct_data = 00; + } + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_add_mhmarker(opj_codestream_index_t *cstr_index, + OPJ_UINT32 type, OPJ_OFF_T pos, OPJ_UINT32 len) +{ + assert(cstr_index != 00); + + /* expand the list? */ + if ((cstr_index->marknum + 1) > cstr_index->maxmarknum) { + opj_marker_info_t *new_marker; + cstr_index->maxmarknum = (OPJ_UINT32)(100 + (OPJ_FLOAT32) + cstr_index->maxmarknum); + new_marker = (opj_marker_info_t *) opj_realloc(cstr_index->marker, + cstr_index->maxmarknum * sizeof(opj_marker_info_t)); + if (! new_marker) { + opj_free(cstr_index->marker); + cstr_index->marker = NULL; + cstr_index->maxmarknum = 0; + cstr_index->marknum = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); */ + return OPJ_FALSE; + } + cstr_index->marker = new_marker; + } + + /* add the marker */ + cstr_index->marker[cstr_index->marknum].type = (OPJ_UINT16)type; + cstr_index->marker[cstr_index->marknum].pos = (OPJ_INT32)pos; + cstr_index->marker[cstr_index->marknum].len = (OPJ_INT32)len; + cstr_index->marknum++; + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_add_tlmarker(OPJ_UINT32 tileno, + opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_OFF_T pos, + OPJ_UINT32 len) +{ + assert(cstr_index != 00); + assert(cstr_index->tile_index != 00); + + /* expand the list? */ + if ((cstr_index->tile_index[tileno].marknum + 1) > + cstr_index->tile_index[tileno].maxmarknum) { + opj_marker_info_t *new_marker; + cstr_index->tile_index[tileno].maxmarknum = (OPJ_UINT32)(100 + + (OPJ_FLOAT32) cstr_index->tile_index[tileno].maxmarknum); + new_marker = (opj_marker_info_t *) opj_realloc( + cstr_index->tile_index[tileno].marker, + cstr_index->tile_index[tileno].maxmarknum * sizeof(opj_marker_info_t)); + if (! new_marker) { + opj_free(cstr_index->tile_index[tileno].marker); + cstr_index->tile_index[tileno].marker = NULL; + cstr_index->tile_index[tileno].maxmarknum = 0; + cstr_index->tile_index[tileno].marknum = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); */ + return OPJ_FALSE; + } + cstr_index->tile_index[tileno].marker = new_marker; + } + + /* add the marker */ + cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].type + = (OPJ_UINT16)type; + cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].pos + = (OPJ_INT32)pos; + cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].len + = (OPJ_INT32)len; + cstr_index->tile_index[tileno].marknum++; + + if (type == J2K_MS_SOT) { + OPJ_UINT32 l_current_tile_part = cstr_index->tile_index[tileno].current_tpsno; + + if (cstr_index->tile_index[tileno].tp_index && + l_current_tile_part < cstr_index->tile_index[tileno].nb_tps) { + cstr_index->tile_index[tileno].tp_index[l_current_tile_part].start_pos = pos; + } + + } + return OPJ_TRUE; +} + +/* + * ----------------------------------------------------------------------- + * ----------------------------------------------------------------------- + * ----------------------------------------------------------------------- + */ + +OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + (void)p_j2k; + (void)p_stream; + (void)p_manager; + return OPJ_TRUE; +} + +OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream, + opj_j2k_t* p_j2k, + opj_image_t** p_image, + opj_event_mgr_t* p_manager) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + /* create an empty image header */ + p_j2k->m_private_image = opj_image_create0(); + if (! p_j2k->m_private_image) { + return OPJ_FALSE; + } + + /* customization of the validation */ + if (! opj_j2k_setup_decoding_validation(p_j2k, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } + + /* validation of the parameters codec */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_validation_list, p_stream, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } + + /* customization of the encoding */ + if (! opj_j2k_setup_header_reading(p_j2k, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } + + /* read header */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } + + *p_image = opj_image_create0(); + if (!(*p_image)) { + return OPJ_FALSE; + } + + /* Copy codestream image information to the output image */ + opj_copy_image_header(p_j2k->m_private_image, *p_image); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_setup_header_reading(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) +{ + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_read_header_procedure, p_manager)) { + return OPJ_FALSE; + } + + /* DEVELOPER CORNER, add your custom procedures */ + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_copy_default_tcp_and_create_tcd, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_setup_decoding_validation(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) +{ + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_build_decoder, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_decoding_validation, p_manager)) { + return OPJ_FALSE; + } + + /* DEVELOPER CORNER, add your custom validation procedure */ + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_mct_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_BOOL l_is_valid = OPJ_TRUE; + OPJ_UINT32 i, j; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_stream); + OPJ_UNUSED(p_manager); + + if ((p_j2k->m_cp.rsiz & 0x8200) == 0x8200) { + OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + opj_tcp_t * l_tcp = p_j2k->m_cp.tcps; + + for (i = 0; i < l_nb_tiles; ++i) { + if (l_tcp->mct == 2) { + opj_tccp_t * l_tccp = l_tcp->tccps; + l_is_valid &= (l_tcp->m_mct_coding_matrix != 00); + + for (j = 0; j < p_j2k->m_private_image->numcomps; ++j) { + l_is_valid &= !(l_tccp->qmfbid & 1); + ++l_tccp; + } + } + ++l_tcp; + } + } + + return l_is_valid; +} + +OPJ_BOOL opj_j2k_setup_mct_encoding(opj_tcp_t * p_tcp, opj_image_t * p_image) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_indix = 1; + opj_mct_data_t * l_mct_deco_data = 00, * l_mct_offset_data = 00; + opj_simple_mcc_decorrelation_data_t * l_mcc_data; + OPJ_UINT32 l_mct_size, l_nb_elem; + OPJ_FLOAT32 * l_data, * l_current_data; + opj_tccp_t * l_tccp; + + /* preconditions */ + assert(p_tcp != 00); + + if (p_tcp->mct != 2) { + return OPJ_TRUE; + } + + if (p_tcp->m_mct_decoding_matrix) { + if (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) { + opj_mct_data_t *new_mct_records; + p_tcp->m_nb_max_mct_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + + new_mct_records = (opj_mct_data_t *) opj_realloc(p_tcp->m_mct_records, + p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if (! new_mct_records) { + opj_free(p_tcp->m_mct_records); + p_tcp->m_mct_records = NULL; + p_tcp->m_nb_max_mct_records = 0; + p_tcp->m_nb_mct_records = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */ + return OPJ_FALSE; + } + p_tcp->m_mct_records = new_mct_records; + l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + + memset(l_mct_deco_data, 0, + (p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof( + opj_mct_data_t)); + } + l_mct_deco_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + + if (l_mct_deco_data->m_data) { + opj_free(l_mct_deco_data->m_data); + l_mct_deco_data->m_data = 00; + } + + l_mct_deco_data->m_index = l_indix++; + l_mct_deco_data->m_array_type = MCT_TYPE_DECORRELATION; + l_mct_deco_data->m_element_type = MCT_TYPE_FLOAT; + l_nb_elem = p_image->numcomps * p_image->numcomps; + l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_deco_data->m_element_type]; + l_mct_deco_data->m_data = (OPJ_BYTE*)opj_malloc(l_mct_size); + + if (! l_mct_deco_data->m_data) { + return OPJ_FALSE; + } + + j2k_mct_write_functions_from_float[l_mct_deco_data->m_element_type]( + p_tcp->m_mct_decoding_matrix, l_mct_deco_data->m_data, l_nb_elem); + + l_mct_deco_data->m_data_size = l_mct_size; + ++p_tcp->m_nb_mct_records; + } + + if (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) { + opj_mct_data_t *new_mct_records; + p_tcp->m_nb_max_mct_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + new_mct_records = (opj_mct_data_t *) opj_realloc(p_tcp->m_mct_records, + p_tcp->m_nb_max_mct_records * sizeof(opj_mct_data_t)); + if (! new_mct_records) { + opj_free(p_tcp->m_mct_records); + p_tcp->m_mct_records = NULL; + p_tcp->m_nb_max_mct_records = 0; + p_tcp->m_nb_mct_records = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */ + return OPJ_FALSE; + } + p_tcp->m_mct_records = new_mct_records; + l_mct_offset_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + + memset(l_mct_offset_data, 0, + (p_tcp->m_nb_max_mct_records - p_tcp->m_nb_mct_records) * sizeof( + opj_mct_data_t)); + + if (l_mct_deco_data) { + l_mct_deco_data = l_mct_offset_data - 1; + } + } + + l_mct_offset_data = p_tcp->m_mct_records + p_tcp->m_nb_mct_records; + + if (l_mct_offset_data->m_data) { + opj_free(l_mct_offset_data->m_data); + l_mct_offset_data->m_data = 00; + } + + l_mct_offset_data->m_index = l_indix++; + l_mct_offset_data->m_array_type = MCT_TYPE_OFFSET; + l_mct_offset_data->m_element_type = MCT_TYPE_FLOAT; + l_nb_elem = p_image->numcomps; + l_mct_size = l_nb_elem * MCT_ELEMENT_SIZE[l_mct_offset_data->m_element_type]; + l_mct_offset_data->m_data = (OPJ_BYTE*)opj_malloc(l_mct_size); + + if (! l_mct_offset_data->m_data) { + return OPJ_FALSE; + } + + l_data = (OPJ_FLOAT32*)opj_malloc(l_nb_elem * sizeof(OPJ_FLOAT32)); + if (! l_data) { + opj_free(l_mct_offset_data->m_data); + l_mct_offset_data->m_data = 00; + return OPJ_FALSE; + } + + l_tccp = p_tcp->tccps; + l_current_data = l_data; + + for (i = 0; i < l_nb_elem; ++i) { + *(l_current_data++) = (OPJ_FLOAT32)(l_tccp->m_dc_level_shift); + ++l_tccp; + } + + j2k_mct_write_functions_from_float[l_mct_offset_data->m_element_type](l_data, + l_mct_offset_data->m_data, l_nb_elem); + + opj_free(l_data); + + l_mct_offset_data->m_data_size = l_mct_size; + + ++p_tcp->m_nb_mct_records; + + if (p_tcp->m_nb_mcc_records == p_tcp->m_nb_max_mcc_records) { + opj_simple_mcc_decorrelation_data_t *new_mcc_records; + p_tcp->m_nb_max_mcc_records += OPJ_J2K_MCT_DEFAULT_NB_RECORDS; + new_mcc_records = (opj_simple_mcc_decorrelation_data_t *) opj_realloc( + p_tcp->m_mcc_records, p_tcp->m_nb_max_mcc_records * sizeof( + opj_simple_mcc_decorrelation_data_t)); + if (! new_mcc_records) { + opj_free(p_tcp->m_mcc_records); + p_tcp->m_mcc_records = NULL; + p_tcp->m_nb_max_mcc_records = 0; + p_tcp->m_nb_mcc_records = 0; + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup mct encoding\n"); */ + return OPJ_FALSE; + } + p_tcp->m_mcc_records = new_mcc_records; + l_mcc_data = p_tcp->m_mcc_records + p_tcp->m_nb_mcc_records; + memset(l_mcc_data, 0, (p_tcp->m_nb_max_mcc_records - p_tcp->m_nb_mcc_records) * + sizeof(opj_simple_mcc_decorrelation_data_t)); + + } + + l_mcc_data = p_tcp->m_mcc_records + p_tcp->m_nb_mcc_records; + l_mcc_data->m_decorrelation_array = l_mct_deco_data; + l_mcc_data->m_is_irreversible = 1; + l_mcc_data->m_nb_comps = p_image->numcomps; + l_mcc_data->m_index = l_indix++; + l_mcc_data->m_offset_array = l_mct_offset_data; + ++p_tcp->m_nb_mcc_records; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_build_decoder(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + /* add here initialization of cp + copy paste of setup_decoder */ + (void)p_j2k; + (void)p_stream; + (void)p_manager; + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_build_encoder(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + /* add here initialization of cp + copy paste of setup_encoder */ + (void)p_j2k; + (void)p_stream; + (void)p_manager; + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_encoding_validation(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_BOOL l_is_valid = OPJ_TRUE; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_stream); + + /* STATE checking */ + /* make sure the state is at 0 */ + l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NONE); + + /* POINTER validation */ + /* make sure a p_j2k codec is present */ + l_is_valid &= (p_j2k->m_procedure_list != 00); + /* make sure a validation list is present */ + l_is_valid &= (p_j2k->m_validation_list != 00); + + /* ISO 15444-1:2004 states between 1 & 33 (0 -> 32) */ + /* 33 (32) would always fail the check below (if a cast to 64bits was done) */ + /* FIXME Shall we change OPJ_J2K_MAXRLVLS to 32 ? */ + if ((p_j2k->m_cp.tcps->tccps->numresolutions <= 0) || + (p_j2k->m_cp.tcps->tccps->numresolutions > 32)) { + opj_event_msg(p_manager, EVT_ERROR, + "Number of resolutions is too high in comparison to the size of tiles\n"); + return OPJ_FALSE; + } + + if ((p_j2k->m_cp.tdx) < (OPJ_UINT32)(1 << + (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) { + opj_event_msg(p_manager, EVT_ERROR, + "Number of resolutions is too high in comparison to the size of tiles\n"); + return OPJ_FALSE; + } + + if ((p_j2k->m_cp.tdy) < (OPJ_UINT32)(1 << + (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) { + opj_event_msg(p_manager, EVT_ERROR, + "Number of resolutions is too high in comparison to the size of tiles\n"); + return OPJ_FALSE; + } + + /* PARAMETER VALIDATION */ + return l_is_valid; +} + +static OPJ_BOOL opj_j2k_decoding_validation(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + OPJ_BOOL l_is_valid = OPJ_TRUE; + + /* preconditions*/ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_stream); + OPJ_UNUSED(p_manager); + + /* STATE checking */ + /* make sure the state is at 0 */ +#ifdef TODO_MSD + l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_NONE); +#endif + l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == 0x0000); + + /* POINTER validation */ + /* make sure a p_j2k codec is present */ + /* make sure a procedure list is present */ + l_is_valid &= (p_j2k->m_procedure_list != 00); + /* make sure a validation list is present */ + l_is_valid &= (p_j2k->m_validation_list != 00); + + /* PARAMETER VALIDATION */ + return l_is_valid; +} + +/** Fill p_j2k->cstr_index->tp_index[].start_pos/end_pos fields from TLM marker segments */ +static void opj_j2k_build_tp_index_from_tlm(opj_j2k_t* p_j2k, + opj_event_mgr_t * p_manager) +{ + opj_j2k_tlm_info_t* l_tlm; + OPJ_UINT32 i; + OPJ_OFF_T l_cur_offset; + + assert(p_j2k->cstr_index->main_head_end > 0); + assert(p_j2k->cstr_index->nb_of_tiles > 0); + assert(p_j2k->cstr_index->tile_index != NULL); + + l_tlm = &(p_j2k->m_specific_param.m_decoder.m_tlm); + + if (l_tlm->m_entries_count == 0) { + l_tlm->m_is_invalid = OPJ_TRUE; + return; + } + + if (l_tlm->m_is_invalid) { + return; + } + + /* Initial pass to count the number of tile-parts per tile */ + for (i = 0; i < l_tlm->m_entries_count; ++i) { + OPJ_UINT32 l_tile_index_no = l_tlm->m_tile_part_infos[i].m_tile_index; + assert(l_tile_index_no < p_j2k->cstr_index->nb_of_tiles); + p_j2k->cstr_index->tile_index[l_tile_index_no].tileno = l_tile_index_no; + ++p_j2k->cstr_index->tile_index[l_tile_index_no].current_nb_tps; + } + + /* Now check that all tiles have at least one tile-part */ + for (i = 0; i < p_j2k->cstr_index->nb_of_tiles; ++i) { + if (p_j2k->cstr_index->tile_index[i].current_nb_tps == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_j2k_build_tp_index_from_tlm(): tile %d has no " + "registered tile-part in TLM marker segments.\n", i); + goto error; + } + } + + /* Final pass to fill p_j2k->cstr_index */ + l_cur_offset = p_j2k->cstr_index->main_head_end; + for (i = 0; i < l_tlm->m_entries_count; ++i) { + OPJ_UINT32 l_tile_index_no = l_tlm->m_tile_part_infos[i].m_tile_index; + opj_tile_index_t* l_tile_index = & + (p_j2k->cstr_index->tile_index[l_tile_index_no]); + if (!l_tile_index->tp_index) { + l_tile_index->tp_index = (opj_tp_index_t *) opj_calloc( + l_tile_index->current_nb_tps, sizeof(opj_tp_index_t)); + if (! l_tile_index->tp_index) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_j2k_build_tp_index_from_tlm(): tile index allocation failed\n"); + goto error; + } + } + + assert(l_tile_index->nb_tps < l_tile_index->current_nb_tps); + l_tile_index->tp_index[l_tile_index->nb_tps].start_pos = l_cur_offset; + /* We don't know how to set the tp_index[].end_header field, but this is not really needed */ + /* If there would be no markers between SOT and SOD, that would be : */ + /* l_tile_index->tp_index[l_tile_index->nb_tps].end_header = l_cur_offset + 12; */ + l_tile_index->tp_index[l_tile_index->nb_tps].end_pos = l_cur_offset + + l_tlm->m_tile_part_infos[i].m_length; + ++l_tile_index->nb_tps; + + l_cur_offset += l_tlm->m_tile_part_infos[i].m_length; + } + + return; + +error: + l_tlm->m_is_invalid = OPJ_TRUE; + for (i = 0; i < l_tlm->m_entries_count; ++i) { + OPJ_UINT32 l_tile_index = l_tlm->m_tile_part_infos[i].m_tile_index; + p_j2k->cstr_index->tile_index[l_tile_index].current_nb_tps = 0; + opj_free(p_j2k->cstr_index->tile_index[l_tile_index].tp_index); + p_j2k->cstr_index->tile_index[l_tile_index].tp_index = NULL; + } +} + +static OPJ_BOOL opj_j2k_read_header_procedure(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 l_current_marker; + OPJ_UINT32 l_marker_size; + const opj_dec_memory_marker_handler_t * l_marker_handler = 00; + OPJ_BOOL l_has_siz = 0; + OPJ_BOOL l_has_cod = 0; + OPJ_BOOL l_has_qcd = 0; + + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + /* We enter in the main header */ + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MHSOC; + + /* Try to read the SOC marker, the codestream must begin with SOC marker */ + if (! opj_j2k_read_soc(p_j2k, p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Expected a SOC marker \n"); + return OPJ_FALSE; + } + + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes as the new marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, 2); + + /* Try to read until the SOT is detected */ + while (l_current_marker != J2K_MS_SOT) { + + /* Check if the current marker ID is valid */ + if (l_current_marker < 0xff00) { + opj_event_msg(p_manager, EVT_ERROR, + "A marker ID was expected (0xff--) instead of %.8x\n", l_current_marker); + return OPJ_FALSE; + } + + /* Get the marker handler from the marker ID */ + l_marker_handler = opj_j2k_get_marker_handler(l_current_marker); + + /* Manage case where marker is unknown */ + if (l_marker_handler->id == J2K_MS_UNK) { + if (! opj_j2k_read_unk(p_j2k, p_stream, &l_current_marker, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Unknown marker has been detected and generated error.\n"); + return OPJ_FALSE; + } + + if (l_current_marker == J2K_MS_SOT) { + break; /* SOT marker is detected main header is completely read */ + } else { /* Get the marker handler from the marker ID */ + l_marker_handler = opj_j2k_get_marker_handler(l_current_marker); + } + } + + if (l_marker_handler->id == J2K_MS_SIZ) { + /* Mark required SIZ marker as found */ + l_has_siz = 1; + } + if (l_marker_handler->id == J2K_MS_COD) { + /* Mark required COD marker as found */ + l_has_cod = 1; + } + if (l_marker_handler->id == J2K_MS_QCD) { + /* Mark required QCD marker as found */ + l_has_qcd = 1; + } + + /* Check if the marker is known and if it is the right place to find it */ + if (!(p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker is not compliant with its position\n"); + return OPJ_FALSE; + } + + /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* read 2 bytes as the marker size */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, &l_marker_size, + 2); + if (l_marker_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid marker size\n"); + return OPJ_FALSE; + } + l_marker_size -= 2; /* Subtract the size of the marker ID already read */ + + /* Check if the marker size is compatible with the header data size */ + if (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) { + OPJ_BYTE *new_header_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size); + if (! new_header_data) { + opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); + p_j2k->m_specific_param.m_decoder.m_header_data = NULL; + p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read header\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_header_data = new_header_data; + p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; + } + + /* Try to read the rest of the marker segment from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size, + p_manager) != l_marker_size) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read the marker segment with the correct marker handler */ + if (!(*(l_marker_handler->handler))(p_j2k, + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker handler function failed to read the marker segment\n"); + return OPJ_FALSE; + } + + /* Add the marker to the codestream index*/ + if (OPJ_FALSE == opj_j2k_add_mhmarker( + p_j2k->cstr_index, + l_marker_handler->id, + (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4, + l_marker_size + 4)) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add mh marker\n"); + return OPJ_FALSE; + } + + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* read 2 bytes as the new marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, 2); + } + + if (l_has_siz == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "required SIZ marker not found in main header\n"); + return OPJ_FALSE; + } + if (l_has_cod == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "required COD marker not found in main header\n"); + return OPJ_FALSE; + } + if (l_has_qcd == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "required QCD marker not found in main header\n"); + return OPJ_FALSE; + } + + if (! opj_j2k_merge_ppm(&(p_j2k->m_cp), p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to merge PPM data\n"); + return OPJ_FALSE; + } + + opj_event_msg(p_manager, EVT_INFO, "Main header has been correctly decoded.\n"); + + /* Position of the last element if the main header */ + p_j2k->cstr_index->main_head_end = (OPJ_UINT32) opj_stream_tell(p_stream) - 2; + + /* Build tile-part index from TLM information */ + opj_j2k_build_tp_index_from_tlm(p_j2k, p_manager); + + /* Next step: read a tile-part header */ + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_exec(opj_j2k_t * p_j2k, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_BOOL(** l_procedure)(opj_j2k_t *, opj_stream_private_t *, + opj_event_mgr_t *) = 00; + OPJ_BOOL l_result = OPJ_TRUE; + OPJ_UINT32 l_nb_proc, i; + + /* preconditions*/ + assert(p_procedure_list != 00); + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list); + l_procedure = (OPJ_BOOL(**)(opj_j2k_t *, opj_stream_private_t *, + opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list); + + for (i = 0; i < l_nb_proc; ++i) { + l_result = l_result && ((*l_procedure)(p_j2k, p_stream, p_manager)); + ++l_procedure; + } + + /* and clear the procedure list at the end.*/ + opj_procedure_list_clear(p_procedure_list); + return l_result; +} + +/* FIXME DOC*/ +static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + opj_tcp_t * l_tcp = 00; + opj_tcp_t * l_default_tcp = 00; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 i, j; + opj_tccp_t *l_current_tccp = 00; + OPJ_UINT32 l_tccp_size; + OPJ_UINT32 l_mct_size; + opj_image_t * l_image; + OPJ_UINT32 l_mcc_records_size, l_mct_records_size; + opj_mct_data_t * l_src_mct_rec, *l_dest_mct_rec; + opj_simple_mcc_decorrelation_data_t * l_src_mcc_rec, *l_dest_mcc_rec; + OPJ_UINT32 l_offset; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_stream); + + l_image = p_j2k->m_private_image; + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + l_tcp = p_j2k->m_cp.tcps; + l_tccp_size = l_image->numcomps * (OPJ_UINT32)sizeof(opj_tccp_t); + l_default_tcp = p_j2k->m_specific_param.m_decoder.m_default_tcp; + l_mct_size = l_image->numcomps * l_image->numcomps * (OPJ_UINT32)sizeof( + OPJ_FLOAT32); + + /* For each tile */ + for (i = 0; i < l_nb_tiles; ++i) { + /* keep the tile-compo coding parameters pointer of the current tile coding parameters*/ + l_current_tccp = l_tcp->tccps; + /*Copy default coding parameters into the current tile coding parameters*/ + memcpy(l_tcp, l_default_tcp, sizeof(opj_tcp_t)); + /* Initialize some values of the current tile coding parameters*/ + l_tcp->cod = 0; + l_tcp->ppt = 0; + l_tcp->ppt_data = 00; + l_tcp->m_current_tile_part_number = -1; + /* Remove memory not owned by this tile in case of early error return. */ + l_tcp->m_mct_decoding_matrix = 00; + l_tcp->m_nb_max_mct_records = 0; + l_tcp->m_mct_records = 00; + l_tcp->m_nb_max_mcc_records = 0; + l_tcp->m_mcc_records = 00; + /* Reconnect the tile-compo coding parameters pointer to the current tile coding parameters*/ + l_tcp->tccps = l_current_tccp; + + /* Get the mct_decoding_matrix of the dflt_tile_cp and copy them into the current tile cp*/ + if (l_default_tcp->m_mct_decoding_matrix) { + l_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size); + if (! l_tcp->m_mct_decoding_matrix) { + return OPJ_FALSE; + } + memcpy(l_tcp->m_mct_decoding_matrix, l_default_tcp->m_mct_decoding_matrix, + l_mct_size); + } + + /* Get the mct_record of the dflt_tile_cp and copy them into the current tile cp*/ + l_mct_records_size = l_default_tcp->m_nb_max_mct_records * (OPJ_UINT32)sizeof( + opj_mct_data_t); + l_tcp->m_mct_records = (opj_mct_data_t*)opj_malloc(l_mct_records_size); + if (! l_tcp->m_mct_records) { + return OPJ_FALSE; + } + memcpy(l_tcp->m_mct_records, l_default_tcp->m_mct_records, l_mct_records_size); + + /* Copy the mct record data from dflt_tile_cp to the current tile*/ + l_src_mct_rec = l_default_tcp->m_mct_records; + l_dest_mct_rec = l_tcp->m_mct_records; + + for (j = 0; j < l_default_tcp->m_nb_mct_records; ++j) { + + if (l_src_mct_rec->m_data) { + + l_dest_mct_rec->m_data = (OPJ_BYTE*) opj_malloc(l_src_mct_rec->m_data_size); + if (! l_dest_mct_rec->m_data) { + return OPJ_FALSE; + } + memcpy(l_dest_mct_rec->m_data, l_src_mct_rec->m_data, + l_src_mct_rec->m_data_size); + } + + ++l_src_mct_rec; + ++l_dest_mct_rec; + /* Update with each pass to free exactly what has been allocated on early return. */ + l_tcp->m_nb_max_mct_records += 1; + } + + /* Get the mcc_record of the dflt_tile_cp and copy them into the current tile cp*/ + l_mcc_records_size = l_default_tcp->m_nb_max_mcc_records * (OPJ_UINT32)sizeof( + opj_simple_mcc_decorrelation_data_t); + l_tcp->m_mcc_records = (opj_simple_mcc_decorrelation_data_t*) opj_malloc( + l_mcc_records_size); + if (! l_tcp->m_mcc_records) { + return OPJ_FALSE; + } + memcpy(l_tcp->m_mcc_records, l_default_tcp->m_mcc_records, l_mcc_records_size); + l_tcp->m_nb_max_mcc_records = l_default_tcp->m_nb_max_mcc_records; + + /* Copy the mcc record data from dflt_tile_cp to the current tile*/ + l_src_mcc_rec = l_default_tcp->m_mcc_records; + l_dest_mcc_rec = l_tcp->m_mcc_records; + + for (j = 0; j < l_default_tcp->m_nb_max_mcc_records; ++j) { + + if (l_src_mcc_rec->m_decorrelation_array) { + l_offset = (OPJ_UINT32)(l_src_mcc_rec->m_decorrelation_array - + l_default_tcp->m_mct_records); + l_dest_mcc_rec->m_decorrelation_array = l_tcp->m_mct_records + l_offset; + } + + if (l_src_mcc_rec->m_offset_array) { + l_offset = (OPJ_UINT32)(l_src_mcc_rec->m_offset_array - + l_default_tcp->m_mct_records); + l_dest_mcc_rec->m_offset_array = l_tcp->m_mct_records + l_offset; + } + + ++l_src_mcc_rec; + ++l_dest_mcc_rec; + } + + /* Copy all the dflt_tile_compo_cp to the current tile cp */ + memcpy(l_current_tccp, l_default_tcp->tccps, l_tccp_size); + + /* Move to next tile cp*/ + ++l_tcp; + } + + /* Create the current tile decoder*/ + p_j2k->m_tcd = opj_tcd_create(OPJ_TRUE); + if (! p_j2k->m_tcd) { + return OPJ_FALSE; + } + + if (!opj_tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp), p_j2k->m_tp)) { + opj_tcd_destroy(p_j2k->m_tcd); + p_j2k->m_tcd = 00; + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static const opj_dec_memory_marker_handler_t * opj_j2k_get_marker_handler( + OPJ_UINT32 p_id) +{ + const opj_dec_memory_marker_handler_t *e; + for (e = j2k_memory_marker_handler_tab; e->id != 0; ++e) { + if (e->id == p_id) { + break; /* we find a handler corresponding to the marker ID*/ + } + } + return e; +} + +void opj_j2k_destroy(opj_j2k_t *p_j2k) +{ + if (p_j2k == 00) { + return; + } + + if (p_j2k->m_is_decoder) { + + if (p_j2k->m_specific_param.m_decoder.m_default_tcp != 00) { + opj_j2k_tcp_destroy(p_j2k->m_specific_param.m_decoder.m_default_tcp); + opj_free(p_j2k->m_specific_param.m_decoder.m_default_tcp); + p_j2k->m_specific_param.m_decoder.m_default_tcp = 00; + } + + if (p_j2k->m_specific_param.m_decoder.m_header_data != 00) { + opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); + p_j2k->m_specific_param.m_decoder.m_header_data = 00; + p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; + } + + opj_free(p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode); + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode = 00; + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode = 0; + + opj_free(p_j2k->m_specific_param.m_decoder.m_tlm.m_tile_part_infos); + p_j2k->m_specific_param.m_decoder.m_tlm.m_tile_part_infos = NULL; + + opj_free(p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset); + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset = NULL; + + } else { + + if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 00; + } + + if (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) { + opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer); + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 00; + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 00; + } + + if (p_j2k->m_specific_param.m_encoder.m_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = 00; + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + } + } + + opj_tcd_destroy(p_j2k->m_tcd); + + opj_j2k_cp_destroy(&(p_j2k->m_cp)); + memset(&(p_j2k->m_cp), 0, sizeof(opj_cp_t)); + + opj_procedure_list_destroy(p_j2k->m_procedure_list); + p_j2k->m_procedure_list = 00; + + opj_procedure_list_destroy(p_j2k->m_validation_list); + p_j2k->m_procedure_list = 00; + + j2k_destroy_cstr_index(p_j2k->cstr_index); + p_j2k->cstr_index = NULL; + + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + + opj_image_destroy(p_j2k->m_output_image); + p_j2k->m_output_image = NULL; + + opj_thread_pool_destroy(p_j2k->m_tp); + p_j2k->m_tp = NULL; + + opj_free(p_j2k); +} + +void j2k_destroy_cstr_index(opj_codestream_index_t *p_cstr_ind) +{ + if (p_cstr_ind) { + + if (p_cstr_ind->marker) { + opj_free(p_cstr_ind->marker); + p_cstr_ind->marker = NULL; + } + + if (p_cstr_ind->tile_index) { + OPJ_UINT32 it_tile = 0; + + for (it_tile = 0; it_tile < p_cstr_ind->nb_of_tiles; it_tile++) { + + if (p_cstr_ind->tile_index[it_tile].packet_index) { + opj_free(p_cstr_ind->tile_index[it_tile].packet_index); + p_cstr_ind->tile_index[it_tile].packet_index = NULL; + } + + if (p_cstr_ind->tile_index[it_tile].tp_index) { + opj_free(p_cstr_ind->tile_index[it_tile].tp_index); + p_cstr_ind->tile_index[it_tile].tp_index = NULL; + } + + if (p_cstr_ind->tile_index[it_tile].marker) { + opj_free(p_cstr_ind->tile_index[it_tile].marker); + p_cstr_ind->tile_index[it_tile].marker = NULL; + + } + } + + opj_free(p_cstr_ind->tile_index); + p_cstr_ind->tile_index = NULL; + } + + opj_free(p_cstr_ind); + } +} + +static void opj_j2k_tcp_destroy(opj_tcp_t *p_tcp) +{ + if (p_tcp == 00) { + return; + } + + if (p_tcp->ppt_markers != 00) { + OPJ_UINT32 i; + for (i = 0U; i < p_tcp->ppt_markers_count; ++i) { + if (p_tcp->ppt_markers[i].m_data != NULL) { + opj_free(p_tcp->ppt_markers[i].m_data); + } + } + p_tcp->ppt_markers_count = 0U; + opj_free(p_tcp->ppt_markers); + p_tcp->ppt_markers = NULL; + } + + if (p_tcp->ppt_buffer != 00) { + opj_free(p_tcp->ppt_buffer); + p_tcp->ppt_buffer = 00; + } + + if (p_tcp->tccps != 00) { + opj_free(p_tcp->tccps); + p_tcp->tccps = 00; + } + + if (p_tcp->m_mct_coding_matrix != 00) { + opj_free(p_tcp->m_mct_coding_matrix); + p_tcp->m_mct_coding_matrix = 00; + } + + if (p_tcp->m_mct_decoding_matrix != 00) { + opj_free(p_tcp->m_mct_decoding_matrix); + p_tcp->m_mct_decoding_matrix = 00; + } + + if (p_tcp->m_mcc_records) { + opj_free(p_tcp->m_mcc_records); + p_tcp->m_mcc_records = 00; + p_tcp->m_nb_max_mcc_records = 0; + p_tcp->m_nb_mcc_records = 0; + } + + if (p_tcp->m_mct_records) { + opj_mct_data_t * l_mct_data = p_tcp->m_mct_records; + OPJ_UINT32 i; + + for (i = 0; i < p_tcp->m_nb_mct_records; ++i) { + if (l_mct_data->m_data) { + opj_free(l_mct_data->m_data); + l_mct_data->m_data = 00; + } + + ++l_mct_data; + } + + opj_free(p_tcp->m_mct_records); + p_tcp->m_mct_records = 00; + } + + if (p_tcp->mct_norms != 00) { + opj_free(p_tcp->mct_norms); + p_tcp->mct_norms = 00; + } + + opj_j2k_tcp_data_destroy(p_tcp); + +} + +static void opj_j2k_tcp_data_destroy(opj_tcp_t *p_tcp) +{ + if (p_tcp->m_data) { + opj_free(p_tcp->m_data); + p_tcp->m_data = NULL; + p_tcp->m_data_size = 0; + } +} + +static void opj_j2k_cp_destroy(opj_cp_t *p_cp) +{ + OPJ_UINT32 l_nb_tiles; + opj_tcp_t * l_current_tile = 00; + + if (p_cp == 00) { + return; + } + if (p_cp->tcps != 00) { + OPJ_UINT32 i; + l_current_tile = p_cp->tcps; + l_nb_tiles = p_cp->th * p_cp->tw; + + for (i = 0U; i < l_nb_tiles; ++i) { + opj_j2k_tcp_destroy(l_current_tile); + ++l_current_tile; + } + opj_free(p_cp->tcps); + p_cp->tcps = 00; + } + if (p_cp->ppm_markers != 00) { + OPJ_UINT32 i; + for (i = 0U; i < p_cp->ppm_markers_count; ++i) { + if (p_cp->ppm_markers[i].m_data != NULL) { + opj_free(p_cp->ppm_markers[i].m_data); + } + } + p_cp->ppm_markers_count = 0U; + opj_free(p_cp->ppm_markers); + p_cp->ppm_markers = NULL; + } + opj_free(p_cp->ppm_buffer); + p_cp->ppm_buffer = 00; + p_cp->ppm_data = + NULL; /* ppm_data belongs to the allocated buffer pointed by ppm_buffer */ + opj_free(p_cp->comment); + p_cp->comment = 00; + if (! p_cp->m_is_decoder) { + opj_free(p_cp->m_specific_param.m_enc.m_matrice); + p_cp->m_specific_param.m_enc.m_matrice = 00; + } +} + +static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t + *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_header_data[10]; + OPJ_OFF_T l_stream_pos_backup; + OPJ_UINT32 l_current_marker; + OPJ_UINT32 l_marker_size; + OPJ_UINT32 l_tile_no, l_tot_len, l_current_part, l_num_parts; + + /* initialize to no correction needed */ + *p_correction_needed = OPJ_FALSE; + + if (!opj_stream_has_seek(p_stream)) { + /* We can't do much in this case, seek is needed */ + return OPJ_TRUE; + } + + l_stream_pos_backup = opj_stream_tell(p_stream); + if (l_stream_pos_backup == -1) { + /* let's do nothing */ + return OPJ_TRUE; + } + + for (;;) { + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, l_header_data, 2, p_manager) != 2) { + /* assume all is OK */ + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; + } + + /* Read 2 bytes from buffer as the new marker ID */ + opj_read_bytes(l_header_data, &l_current_marker, 2); + + if (l_current_marker != J2K_MS_SOT) { + /* assume all is OK */ + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; + } + + /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, l_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from the buffer as the marker size */ + opj_read_bytes(l_header_data, &l_marker_size, 2); + + /* Check marker size for SOT Marker */ + if (l_marker_size != 10) { + opj_event_msg(p_manager, EVT_ERROR, "Inconsistent marker size\n"); + return OPJ_FALSE; + } + l_marker_size -= 2; + + if (opj_stream_read_data(p_stream, l_header_data, l_marker_size, + p_manager) != l_marker_size) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + if (! opj_j2k_get_sot_values(l_header_data, l_marker_size, &l_tile_no, + &l_tot_len, &l_current_part, &l_num_parts, p_manager)) { + return OPJ_FALSE; + } + + if (l_tile_no == tile_no) { + /* we found what we were looking for */ + break; + } + + if (l_tot_len < 14U) { + /* last SOT until EOC or invalid Psot value */ + /* assume all is OK */ + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; + } + l_tot_len -= 12U; + /* look for next SOT marker */ + if (opj_stream_skip(p_stream, (OPJ_OFF_T)(l_tot_len), + p_manager) != (OPJ_OFF_T)(l_tot_len)) { + /* assume all is OK */ + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; + } + } + + /* check for correction */ + if (l_current_part == l_num_parts) { + *p_correction_needed = OPJ_TRUE; + } + + if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; +} + +OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 l_current_marker = J2K_MS_SOT; + OPJ_UINT32 l_marker_size; + const opj_dec_memory_marker_handler_t * l_marker_handler = 00; + opj_tcp_t * l_tcp = NULL; + const OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th; + + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + /* Reach the End Of Codestream ?*/ + if (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC) { + l_current_marker = J2K_MS_EOC; + } + /* We need to encounter a SOT marker (a new tile-part header) */ + else if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) { + return OPJ_FALSE; + } + + /* Read into the codestream until reach the EOC or ! can_decode ??? FIXME */ + while ((!p_j2k->m_specific_param.m_decoder.m_can_decode) && + (l_current_marker != J2K_MS_EOC)) { + + if (p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts > 0 && + p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts < + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts) { + OPJ_OFF_T next_tp_sot_pos; + + next_tp_sot_pos = + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset[p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts]; + ++p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts; + if (!(opj_stream_read_seek(p_stream, + next_tp_sot_pos, + p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; + } + + /* Try to read 2 bytes (the marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from the buffer as the marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, + 2); + + if (l_current_marker != J2K_MS_SOT) { + opj_event_msg(p_manager, EVT_ERROR, "Did not get expected SOT marker\n"); + return OPJ_FALSE; + } + } + + /* Try to read until the Start Of Data is detected */ + while (l_current_marker != J2K_MS_SOD) { + + if (opj_stream_get_number_byte_left(p_stream) == 0) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; + break; + } + + /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from the buffer as the marker size */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, &l_marker_size, + 2); + + /* Check marker size (does not include marker ID but includes marker size) */ + if (l_marker_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Inconsistent marker size\n"); + return OPJ_FALSE; + } + + /* cf. https://code.google.com/p/openjpeg/issues/detail?id=226 */ + if (l_current_marker == 0x8080 && + opj_stream_get_number_byte_left(p_stream) == 0) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; + break; + } + + /* Why this condition? FIXME */ + if ((p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_TPH) && + p_j2k->m_specific_param.m_decoder.m_sot_length != 0) { + if (p_j2k->m_specific_param.m_decoder.m_sot_length < l_marker_size + 2) { + opj_event_msg(p_manager, EVT_ERROR, + "Sot length is less than marker size + marker ID\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_sot_length -= (l_marker_size + 2); + } + l_marker_size -= 2; /* Subtract the size of the marker ID already read */ + + /* Get the marker handler from the marker ID */ + l_marker_handler = opj_j2k_get_marker_handler(l_current_marker); + + /* Check if the marker is known and if it is the right place to find it */ + if (!(p_j2k->m_specific_param.m_decoder.m_state & l_marker_handler->states)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker is not compliant with its position\n"); + return OPJ_FALSE; + } + /* FIXME manage case of unknown marker as in the main header ? */ + + /* Check if the marker size is compatible with the header data size */ + if (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) { + OPJ_BYTE *new_header_data = NULL; + /* If we are here, this means we consider this marker as known & we will read it */ + /* Check enough bytes left in stream before allocation */ + if ((OPJ_OFF_T)l_marker_size > opj_stream_get_number_byte_left(p_stream)) { + opj_event_msg(p_manager, EVT_ERROR, + "Marker size inconsistent with stream length\n"); + return OPJ_FALSE; + } + new_header_data = (OPJ_BYTE *) opj_realloc( + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size); + if (! new_header_data) { + opj_free(p_j2k->m_specific_param.m_decoder.m_header_data); + p_j2k->m_specific_param.m_decoder.m_header_data = NULL; + p_j2k->m_specific_param.m_decoder.m_header_data_size = 0; + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read header\n"); + return OPJ_FALSE; + } + p_j2k->m_specific_param.m_decoder.m_header_data = new_header_data; + p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; + } + + /* Try to read the rest of the marker segment from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size, + p_manager) != l_marker_size) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + if (!l_marker_handler->handler) { + /* See issue #175 */ + opj_event_msg(p_manager, EVT_ERROR, "Not sure how that happened.\n"); + return OPJ_FALSE; + } + /* Read the marker segment with the correct marker handler */ + if (!(*(l_marker_handler->handler))(p_j2k, + p_j2k->m_specific_param.m_decoder.m_header_data, l_marker_size, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Fail to read the current marker segment (%#x)\n", l_current_marker); + return OPJ_FALSE; + } + + /* Add the marker to the codestream index*/ + if (OPJ_FALSE == opj_j2k_add_tlmarker(p_j2k->m_current_tile_number, + p_j2k->cstr_index, + l_marker_handler->id, + (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4, + l_marker_size + 4)) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to add tl marker\n"); + return OPJ_FALSE; + } + + /* Keep the position of the last SOT marker read */ + if (l_marker_handler->id == J2K_MS_SOT) { + OPJ_UINT32 sot_pos = (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4 + ; + if (sot_pos > p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos) { + p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = sot_pos; + } + } + + if (p_j2k->m_specific_param.m_decoder.m_skip_data) { + /* Skip the rest of the tile part header*/ + if (opj_stream_skip(p_stream, p_j2k->m_specific_param.m_decoder.m_sot_length, + p_manager) != p_j2k->m_specific_param.m_decoder.m_sot_length) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + l_current_marker = J2K_MS_SOD; /* Normally we reached a SOD */ + } else { + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer*/ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + /* Read 2 bytes from the buffer as the new marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, 2); + } + } + if (opj_stream_get_number_byte_left(p_stream) == 0 + && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) { + break; + } + + /* If we didn't skip data before, we need to read the SOD marker*/ + if (! p_j2k->m_specific_param.m_decoder.m_skip_data) { + /* Try to read the SOD marker and skip data ? FIXME */ + if (! opj_j2k_read_sod(p_j2k, p_stream, p_manager)) { + return OPJ_FALSE; + } + + /* Check if we can use the TLM index to access the next tile-part */ + if (!p_j2k->m_specific_param.m_decoder.m_can_decode && + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec >= 0 && + p_j2k->m_current_tile_number == (OPJ_UINT32) + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec && + !p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid && + opj_stream_has_seek(p_stream)) { + l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number; + if (l_tcp->m_nb_tile_parts == + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps && + (OPJ_UINT32)l_tcp->m_current_tile_part_number + 1 < l_tcp->m_nb_tile_parts) { + const OPJ_OFF_T next_tp_sot_pos = p_j2k->cstr_index->tile_index[ + p_j2k->m_current_tile_number].tp_index[l_tcp->m_current_tile_part_number + + 1].start_pos; + + if (next_tp_sot_pos != opj_stream_tell(p_stream)) { +#if 0 + opj_event_msg(p_manager, EVT_INFO, + "opj_j2k_read_tile_header(tile=%u): seek to tile part %u at %" PRId64 "\n", + p_j2k->m_current_tile_number, + l_tcp->m_current_tile_part_number + 1, + next_tp_sot_pos); +#endif + + if (!(opj_stream_read_seek(p_stream, + next_tp_sot_pos, + p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; + } + } + + /* Try to read 2 bytes (the marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from the buffer as the marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, + 2); + + if (l_current_marker != J2K_MS_SOT) { + opj_event_msg(p_manager, EVT_ERROR, "Did not get expected SOT marker\n"); + return OPJ_FALSE; + } + + continue; + } + } + + if (p_j2k->m_specific_param.m_decoder.m_can_decode && + !p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked) { + /* Issue 254 */ + OPJ_BOOL l_correction_needed = OPJ_FALSE; + + p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; + if (p_j2k->m_cp.tcps[p_j2k->m_current_tile_number].m_nb_tile_parts == 1) { + /* Skip opj_j2k_need_nb_tile_parts_correction() if there is + * only a single tile part declared. The + * opj_j2k_need_nb_tile_parts_correction() hack was needed + * for files with 5 declared tileparts (where they were + * actually 6). + * Doing it systematically hurts performance when reading + * Sentinel2 L1C JPEG2000 files as explained in + * https://lists.osgeo.org/pipermail/gdal-dev/2024-November/059805.html + */ + } else if (!opj_j2k_need_nb_tile_parts_correction(p_stream, + p_j2k->m_current_tile_number, &l_correction_needed, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_j2k_apply_nb_tile_parts_correction error\n"); + return OPJ_FALSE; + } + if (l_correction_needed) { + OPJ_UINT32 l_tile_no; + + p_j2k->m_specific_param.m_decoder.m_can_decode = 0; + p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction = 1; + /* correct tiles */ + for (l_tile_no = 0U; l_tile_no < l_nb_tiles; ++l_tile_no) { + if (p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts != 0U) { + p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts += 1; + } + } + opj_event_msg(p_manager, EVT_WARNING, + "Non conformant codestream TPsot==TNsot.\n"); + } + } + } else { + /* Indicate we will try to read a new tile-part header*/ + p_j2k->m_specific_param.m_decoder.m_skip_data = 0; + p_j2k->m_specific_param.m_decoder.m_can_decode = 0; + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + } + + if (! p_j2k->m_specific_param.m_decoder.m_can_decode) { + /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + + /* Deal with likely non conformant SPOT6 files, where the last */ + /* row of tiles have TPsot == 0 and TNsot == 0, and missing EOC, */ + /* but no other tile-parts were found. */ + if (p_j2k->m_current_tile_number + 1 == l_nb_tiles) { + OPJ_UINT32 l_tile_no; + for (l_tile_no = 0U; l_tile_no < l_nb_tiles; ++l_tile_no) { + if (p_j2k->m_cp.tcps[l_tile_no].m_current_tile_part_number == 0 && + p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts == 0) { + break; + } + } + if (l_tile_no < l_nb_tiles) { + opj_event_msg(p_manager, EVT_INFO, + "Tile %u has TPsot == 0 and TNsot == 0, " + "but no other tile-parts were found. " + "EOC is also missing.\n", + l_tile_no); + p_j2k->m_current_tile_number = l_tile_no; + l_current_marker = J2K_MS_EOC; + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC; + break; + } + } + + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from buffer as the new marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, + &l_current_marker, 2); + } + } + + /* Current marker is the EOC marker ?*/ + if (l_current_marker == J2K_MS_EOC) { + if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC) { + p_j2k->m_current_tile_number = 0; + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC; + } + } + + /* Deal with tiles that have a single tile-part with TPsot == 0 and TNsot == 0 */ + if (! p_j2k->m_specific_param.m_decoder.m_can_decode) { + l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number; + + while ((p_j2k->m_current_tile_number < l_nb_tiles) && (l_tcp->m_data == 00)) { + ++p_j2k->m_current_tile_number; + ++l_tcp; + } + + if (p_j2k->m_current_tile_number == l_nb_tiles) { + *p_go_on = OPJ_FALSE; + return OPJ_TRUE; + } + } + + if (! opj_j2k_merge_ppt(p_j2k->m_cp.tcps + p_j2k->m_current_tile_number, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to merge PPT data\n"); + return OPJ_FALSE; + } + /*FIXME ???*/ + if (! opj_tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); + return OPJ_FALSE; + } + + opj_event_msg(p_manager, EVT_INFO, "Header of tile %d / %d has been read.\n", + p_j2k->m_current_tile_number + 1, (p_j2k->m_cp.th * p_j2k->m_cp.tw)); + + *p_tile_index = p_j2k->m_current_tile_number; + *p_go_on = OPJ_TRUE; + if (p_data_size) { + /* For internal use in j2k.c, we don't need this */ + /* This is just needed for folks using the opj_read_tile_header() / opj_decode_tile_data() combo */ + *p_data_size = opj_tcd_get_decoded_tile_size(p_j2k->m_tcd, OPJ_FALSE); + if (*p_data_size == UINT_MAX) { + return OPJ_FALSE; + } + } + *p_tile_x0 = p_j2k->m_tcd->tcd_image->tiles->x0; + *p_tile_y0 = p_j2k->m_tcd->tcd_image->tiles->y0; + *p_tile_x1 = p_j2k->m_tcd->tcd_image->tiles->x1; + *p_tile_y1 = p_j2k->m_tcd->tcd_image->tiles->y1; + *p_nb_comps = p_j2k->m_tcd->tcd_image->tiles->numcomps; + + p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_DATA; + + return OPJ_TRUE; +} + +OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 l_current_marker; + OPJ_BYTE l_data [2]; + opj_tcp_t * l_tcp; + opj_image_t* l_image_for_bounds; + + /* preconditions */ + assert(p_stream != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + if (!(p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_DATA) + || (p_tile_index != p_j2k->m_current_tile_number)) { + return OPJ_FALSE; + } + + l_tcp = &(p_j2k->m_cp.tcps[p_tile_index]); + if (! l_tcp->m_data) { + opj_j2k_tcp_destroy(l_tcp); + return OPJ_FALSE; + } + + /* When using the opj_read_tile_header / opj_decode_tile_data API */ + /* such as in test_tile_decoder, m_output_image is NULL, so fall back */ + /* to the full image dimension. This is a bit surprising that */ + /* opj_set_decode_area() is only used to determine intersecting tiles, */ + /* but full tile decoding is done */ + l_image_for_bounds = p_j2k->m_output_image ? p_j2k->m_output_image : + p_j2k->m_private_image; + if (! opj_tcd_decode_tile(p_j2k->m_tcd, + l_image_for_bounds->x0, + l_image_for_bounds->y0, + l_image_for_bounds->x1, + l_image_for_bounds->y1, + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode, + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode, + l_tcp->m_data, + l_tcp->m_data_size, + p_tile_index, + p_j2k->cstr_index, p_manager)) { + opj_j2k_tcp_destroy(l_tcp); + p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_ERR; + opj_event_msg(p_manager, EVT_ERROR, "Failed to decode.\n"); + return OPJ_FALSE; + } + + /* p_data can be set to NULL when the call will take care of using */ + /* itself the TCD data. This is typically the case for whole single */ + /* tile decoding optimization. */ + if (p_data != NULL) { + if (! opj_tcd_update_tile_data(p_j2k->m_tcd, p_data, p_data_size)) { + return OPJ_FALSE; + } + + /* To avoid to destroy the tcp which can be useful when we try to decode a tile decoded before (cf j2k_random_tile_access) + * we destroy just the data which will be re-read in read_tile_header*/ + /*opj_j2k_tcp_destroy(l_tcp); + p_j2k->m_tcd->tcp = 0;*/ + opj_j2k_tcp_data_destroy(l_tcp); + } + + p_j2k->m_specific_param.m_decoder.m_can_decode = 0; + p_j2k->m_specific_param.m_decoder.m_state &= (~(OPJ_UINT32)J2K_STATE_DATA); + + if (opj_stream_get_number_byte_left(p_stream) == 0 + && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) { + return OPJ_TRUE; + } + + if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC) { + if (opj_stream_read_data(p_stream, l_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, p_j2k->m_cp.strict ? EVT_ERROR : EVT_WARNING, + "Stream too short\n"); + return p_j2k->m_cp.strict ? OPJ_FALSE : OPJ_TRUE; + } + opj_read_bytes(l_data, &l_current_marker, 2); + + if (l_current_marker == J2K_MS_EOC) { + p_j2k->m_current_tile_number = 0; + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC; + } else if (l_current_marker != J2K_MS_SOT) { + if (opj_stream_get_number_byte_left(p_stream) == 0) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC; + opj_event_msg(p_manager, EVT_WARNING, "Stream does not end with EOC\n"); + return OPJ_TRUE; + } + opj_event_msg(p_manager, EVT_ERROR, "Stream too short, expected SOT\n"); + return OPJ_FALSE; + } + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, + opj_image_t* p_output_image) +{ + OPJ_UINT32 i, j; + OPJ_UINT32 l_width_src, l_height_src; + OPJ_UINT32 l_width_dest, l_height_dest; + OPJ_INT32 l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src; + OPJ_SIZE_T l_start_offset_src; + OPJ_UINT32 l_start_x_dest, l_start_y_dest; + OPJ_UINT32 l_x0_dest, l_y0_dest, l_x1_dest, l_y1_dest; + OPJ_SIZE_T l_start_offset_dest; + + opj_image_comp_t * l_img_comp_src = 00; + opj_image_comp_t * l_img_comp_dest = 00; + + opj_tcd_tilecomp_t * l_tilec = 00; + opj_image_t * l_image_src = 00; + OPJ_INT32 * l_dest_ptr; + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_image_src = p_tcd->image; + l_img_comp_src = l_image_src->comps; + + l_img_comp_dest = p_output_image->comps; + + for (i = 0; i < l_image_src->numcomps; + i++, ++l_img_comp_dest, ++l_img_comp_src, ++l_tilec) { + OPJ_INT32 res_x0, res_x1, res_y0, res_y1; + OPJ_UINT32 src_data_stride; + const OPJ_INT32* p_src_data; + + /* Copy info from decoded comp image to output image */ + l_img_comp_dest->resno_decoded = l_img_comp_src->resno_decoded; + + if (p_tcd->whole_tile_decoding) { + opj_tcd_resolution_t* l_res = l_tilec->resolutions + + l_img_comp_src->resno_decoded; + res_x0 = l_res->x0; + res_y0 = l_res->y0; + res_x1 = l_res->x1; + res_y1 = l_res->y1; + src_data_stride = (OPJ_UINT32)( + l_tilec->resolutions[l_tilec->minimum_num_resolutions - 1].x1 - + l_tilec->resolutions[l_tilec->minimum_num_resolutions - 1].x0); + p_src_data = l_tilec->data; + } else { + opj_tcd_resolution_t* l_res = l_tilec->resolutions + + l_img_comp_src->resno_decoded; + res_x0 = (OPJ_INT32)l_res->win_x0; + res_y0 = (OPJ_INT32)l_res->win_y0; + res_x1 = (OPJ_INT32)l_res->win_x1; + res_y1 = (OPJ_INT32)l_res->win_y1; + src_data_stride = l_res->win_x1 - l_res->win_x0; + p_src_data = l_tilec->data_win; + } + + if (p_src_data == NULL) { + /* Happens for partial component decoding */ + continue; + } + + l_width_src = (OPJ_UINT32)(res_x1 - res_x0); + l_height_src = (OPJ_UINT32)(res_y1 - res_y0); + + + /* Current tile component size*/ + /*if (i == 0) { + fprintf(stdout, "SRC: l_res_x0=%d, l_res_x1=%d, l_res_y0=%d, l_res_y1=%d\n", + res_x0, res_x1, res_y0, res_y1); + }*/ + + + /* Border of the current output component*/ + l_x0_dest = opj_uint_ceildivpow2(l_img_comp_dest->x0, l_img_comp_dest->factor); + l_y0_dest = opj_uint_ceildivpow2(l_img_comp_dest->y0, l_img_comp_dest->factor); + l_x1_dest = l_x0_dest + + l_img_comp_dest->w; /* can't overflow given that image->x1 is uint32 */ + l_y1_dest = l_y0_dest + l_img_comp_dest->h; + + /*if (i == 0) { + fprintf(stdout, "DEST: l_x0_dest=%d, l_x1_dest=%d, l_y0_dest=%d, l_y1_dest=%d (%d)\n", + l_x0_dest, l_x1_dest, l_y0_dest, l_y1_dest, l_img_comp_dest->factor ); + }*/ + + /*-----*/ + /* Compute the area (l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src) + * of the input buffer (decoded tile component) which will be move + * in the output buffer. Compute the area of the output buffer (l_start_x_dest, + * l_start_y_dest, l_width_dest, l_height_dest) which will be modified + * by this input area. + * */ + assert(res_x0 >= 0); + assert(res_x1 >= 0); + if (l_x0_dest < (OPJ_UINT32)res_x0) { + l_start_x_dest = (OPJ_UINT32)res_x0 - l_x0_dest; + l_offset_x0_src = 0; + + if (l_x1_dest >= (OPJ_UINT32)res_x1) { + l_width_dest = l_width_src; + l_offset_x1_src = 0; + } else { + l_width_dest = l_x1_dest - (OPJ_UINT32)res_x0 ; + l_offset_x1_src = (OPJ_INT32)(l_width_src - l_width_dest); + } + } else { + l_start_x_dest = 0U; + l_offset_x0_src = (OPJ_INT32)l_x0_dest - res_x0; + + if (l_x1_dest >= (OPJ_UINT32)res_x1) { + l_width_dest = l_width_src - (OPJ_UINT32)l_offset_x0_src; + l_offset_x1_src = 0; + } else { + l_width_dest = l_img_comp_dest->w ; + l_offset_x1_src = res_x1 - (OPJ_INT32)l_x1_dest; + } + } + + if (l_y0_dest < (OPJ_UINT32)res_y0) { + l_start_y_dest = (OPJ_UINT32)res_y0 - l_y0_dest; + l_offset_y0_src = 0; + + if (l_y1_dest >= (OPJ_UINT32)res_y1) { + l_height_dest = l_height_src; + l_offset_y1_src = 0; + } else { + l_height_dest = l_y1_dest - (OPJ_UINT32)res_y0 ; + l_offset_y1_src = (OPJ_INT32)(l_height_src - l_height_dest); + } + } else { + l_start_y_dest = 0U; + l_offset_y0_src = (OPJ_INT32)l_y0_dest - res_y0; + + if (l_y1_dest >= (OPJ_UINT32)res_y1) { + l_height_dest = l_height_src - (OPJ_UINT32)l_offset_y0_src; + l_offset_y1_src = 0; + } else { + l_height_dest = l_img_comp_dest->h ; + l_offset_y1_src = res_y1 - (OPJ_INT32)l_y1_dest; + } + } + + if ((l_offset_x0_src < 0) || (l_offset_y0_src < 0) || (l_offset_x1_src < 0) || + (l_offset_y1_src < 0)) { + return OPJ_FALSE; + } + /* testcase 2977.pdf.asan.67.2198 */ + if ((OPJ_INT32)l_width_dest < 0 || (OPJ_INT32)l_height_dest < 0) { + return OPJ_FALSE; + } + /*-----*/ + + /* Compute the input buffer offset */ + l_start_offset_src = (OPJ_SIZE_T)l_offset_x0_src + (OPJ_SIZE_T)l_offset_y0_src + * (OPJ_SIZE_T)src_data_stride; + + /* Compute the output buffer offset */ + l_start_offset_dest = (OPJ_SIZE_T)l_start_x_dest + (OPJ_SIZE_T)l_start_y_dest + * (OPJ_SIZE_T)l_img_comp_dest->w; + + /* Allocate output component buffer if necessary */ + if (l_img_comp_dest->data == NULL && + l_start_offset_src == 0 && l_start_offset_dest == 0 && + src_data_stride == l_img_comp_dest->w && + l_width_dest == l_img_comp_dest->w && + l_height_dest == l_img_comp_dest->h) { + /* If the final image matches the tile buffer, then borrow it */ + /* directly to save a copy */ + if (p_tcd->whole_tile_decoding) { + l_img_comp_dest->data = l_tilec->data; + l_tilec->data = NULL; + } else { + l_img_comp_dest->data = l_tilec->data_win; + l_tilec->data_win = NULL; + } + continue; + } else if (l_img_comp_dest->data == NULL) { + OPJ_SIZE_T l_width = l_img_comp_dest->w; + OPJ_SIZE_T l_height = l_img_comp_dest->h; + + if ((l_height == 0U) || (l_width > (SIZE_MAX / l_height)) || + l_width * l_height > SIZE_MAX / sizeof(OPJ_INT32)) { + /* would overflow */ + return OPJ_FALSE; + } + l_img_comp_dest->data = (OPJ_INT32*) opj_image_data_alloc(l_width * l_height * + sizeof(OPJ_INT32)); + if (! l_img_comp_dest->data) { + return OPJ_FALSE; + } + + if (l_img_comp_dest->w != l_width_dest || + l_img_comp_dest->h != l_height_dest) { + memset(l_img_comp_dest->data, 0, + (OPJ_SIZE_T)l_img_comp_dest->w * l_img_comp_dest->h * sizeof(OPJ_INT32)); + } + } + + /* Move the output buffer to the first place where we will write*/ + l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest; + + { + const OPJ_INT32 * l_src_ptr = p_src_data; + l_src_ptr += l_start_offset_src; + + for (j = 0; j < l_height_dest; ++j) { + memcpy(l_dest_ptr, l_src_ptr, l_width_dest * sizeof(OPJ_INT32)); + l_dest_ptr += l_img_comp_dest->w; + l_src_ptr += src_data_stride; + } + } + + + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 it_comp; + OPJ_INT32 l_comp_x1, l_comp_y1; + opj_image_comp_t* l_img_comp = NULL; + + l_img_comp = p_image->comps; + for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) { + OPJ_INT32 l_h, l_w; + if (p_image->x0 > (OPJ_UINT32)INT_MAX || + p_image->y0 > (OPJ_UINT32)INT_MAX || + p_image->x1 > (OPJ_UINT32)INT_MAX || + p_image->y1 > (OPJ_UINT32)INT_MAX) { + opj_event_msg(p_manager, EVT_ERROR, + "Image coordinates above INT_MAX are not supported\n"); + return OPJ_FALSE; + } + + l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); + l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); + l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); + l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); + + l_w = opj_int_ceildivpow2(l_comp_x1, (OPJ_INT32)l_img_comp->factor) + - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, (OPJ_INT32)l_img_comp->factor); + if (l_w < 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Size x of the decoded component image is incorrect (comp[%d].w=%d).\n", + it_comp, l_w); + return OPJ_FALSE; + } + l_img_comp->w = (OPJ_UINT32)l_w; + + l_h = opj_int_ceildivpow2(l_comp_y1, (OPJ_INT32)l_img_comp->factor) + - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, (OPJ_INT32)l_img_comp->factor); + if (l_h < 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Size y of the decoded component image is incorrect (comp[%d].h=%d).\n", + it_comp, l_h); + return OPJ_FALSE; + } + l_img_comp->h = (OPJ_UINT32)l_h; + + l_img_comp++; + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i; + OPJ_BOOL* already_mapped; + + if (p_j2k->m_private_image == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_read_header() should be called before " + "opj_set_decoded_components().\n"); + return OPJ_FALSE; + } + + already_mapped = (OPJ_BOOL*) opj_calloc(sizeof(OPJ_BOOL), + p_j2k->m_private_image->numcomps); + if (already_mapped == NULL) { + return OPJ_FALSE; + } + + for (i = 0; i < numcomps; i++) { + if (comps_indices[i] >= p_j2k->m_private_image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid component index: %u\n", + comps_indices[i]); + opj_free(already_mapped); + return OPJ_FALSE; + } + if (already_mapped[comps_indices[i]]) { + opj_event_msg(p_manager, EVT_ERROR, + "Component index %u used several times\n", + comps_indices[i]); + opj_free(already_mapped); + return OPJ_FALSE; + } + already_mapped[comps_indices[i]] = OPJ_TRUE; + } + opj_free(already_mapped); + + opj_free(p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode); + if (numcomps) { + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode = + (OPJ_UINT32*) opj_malloc(numcomps * sizeof(OPJ_UINT32)); + if (p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode == NULL) { + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode = 0; + return OPJ_FALSE; + } + memcpy(p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode, + comps_indices, + numcomps * sizeof(OPJ_UINT32)); + } else { + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode = NULL; + } + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode = numcomps; + + return OPJ_TRUE; +} + + +OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + opj_event_mgr_t * p_manager) +{ + opj_cp_t * l_cp = &(p_j2k->m_cp); + opj_image_t * l_image = p_j2k->m_private_image; + OPJ_BOOL ret; + OPJ_UINT32 it_comp; + + if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 && + p_j2k->m_cp.tcps[0].m_data != NULL) { + /* In the case of a single-tiled image whose codestream we have already */ + /* ingested, go on */ + } + /* Check if we are read the main header */ + else if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) { + opj_event_msg(p_manager, EVT_ERROR, + "Need to decode the main header before begin to decode the remaining codestream.\n"); + return OPJ_FALSE; + } + + /* Update the comps[].factor member of the output image with the one */ + /* of m_reduce */ + for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) { + p_image->comps[it_comp].factor = p_j2k->m_cp.m_specific_param.m_dec.m_reduce; + } + + if (!p_start_x && !p_start_y && !p_end_x && !p_end_y) { + opj_event_msg(p_manager, EVT_INFO, + "No decoded area parameters, set the decoded area to the whole image\n"); + + p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; + p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; + p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; + p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; + + p_image->x0 = l_image->x0; + p_image->y0 = l_image->y0; + p_image->x1 = l_image->x1; + p_image->y1 = l_image->y1; + + return opj_j2k_update_image_dimensions(p_image, p_manager); + } + + /* ----- */ + /* Check if the positions provided by the user are correct */ + + /* Left */ + if (p_start_x < 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Left position of the decoded area (region_x0=%d) should be >= 0.\n", + p_start_x); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_start_x > l_image->x1) { + opj_event_msg(p_manager, EVT_ERROR, + "Left position of the decoded area (region_x0=%d) is outside the image area (Xsiz=%d).\n", + p_start_x, l_image->x1); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_start_x < l_image->x0) { + opj_event_msg(p_manager, EVT_WARNING, + "Left position of the decoded area (region_x0=%d) is outside the image area (XOsiz=%d).\n", + p_start_x, l_image->x0); + p_j2k->m_specific_param.m_decoder.m_start_tile_x = 0; + p_image->x0 = l_image->x0; + } else { + p_j2k->m_specific_param.m_decoder.m_start_tile_x = ((OPJ_UINT32)p_start_x - + l_cp->tx0) / l_cp->tdx; + p_image->x0 = (OPJ_UINT32)p_start_x; + } + + /* Up */ + if (p_start_y < 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Up position of the decoded area (region_y0=%d) should be >= 0.\n", + p_start_y); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_start_y > l_image->y1) { + opj_event_msg(p_manager, EVT_ERROR, + "Up position of the decoded area (region_y0=%d) is outside the image area (Ysiz=%d).\n", + p_start_y, l_image->y1); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_start_y < l_image->y0) { + opj_event_msg(p_manager, EVT_WARNING, + "Up position of the decoded area (region_y0=%d) is outside the image area (YOsiz=%d).\n", + p_start_y, l_image->y0); + p_j2k->m_specific_param.m_decoder.m_start_tile_y = 0; + p_image->y0 = l_image->y0; + } else { + p_j2k->m_specific_param.m_decoder.m_start_tile_y = ((OPJ_UINT32)p_start_y - + l_cp->ty0) / l_cp->tdy; + p_image->y0 = (OPJ_UINT32)p_start_y; + } + + /* Right */ + if (p_end_x <= 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Right position of the decoded area (region_x1=%d) should be > 0.\n", + p_end_x); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_end_x < l_image->x0) { + opj_event_msg(p_manager, EVT_ERROR, + "Right position of the decoded area (region_x1=%d) is outside the image area (XOsiz=%d).\n", + p_end_x, l_image->x0); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_end_x > l_image->x1) { + opj_event_msg(p_manager, EVT_WARNING, + "Right position of the decoded area (region_x1=%d) is outside the image area (Xsiz=%d).\n", + p_end_x, l_image->x1); + p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw; + p_image->x1 = l_image->x1; + } else { + p_j2k->m_specific_param.m_decoder.m_end_tile_x = opj_uint_ceildiv(( + OPJ_UINT32)p_end_x - l_cp->tx0, l_cp->tdx); + p_image->x1 = (OPJ_UINT32)p_end_x; + } + + /* Bottom */ + if (p_end_y <= 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Bottom position of the decoded area (region_y1=%d) should be > 0.\n", + p_end_y); + return OPJ_FALSE; + } else if ((OPJ_UINT32)p_end_y < l_image->y0) { + opj_event_msg(p_manager, EVT_ERROR, + "Bottom position of the decoded area (region_y1=%d) is outside the image area (YOsiz=%d).\n", + p_end_y, l_image->y0); + return OPJ_FALSE; + } + if ((OPJ_UINT32)p_end_y > l_image->y1) { + opj_event_msg(p_manager, EVT_WARNING, + "Bottom position of the decoded area (region_y1=%d) is outside the image area (Ysiz=%d).\n", + p_end_y, l_image->y1); + p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th; + p_image->y1 = l_image->y1; + } else { + p_j2k->m_specific_param.m_decoder.m_end_tile_y = opj_uint_ceildiv(( + OPJ_UINT32)p_end_y - l_cp->ty0, l_cp->tdy); + p_image->y1 = (OPJ_UINT32)p_end_y; + } + /* ----- */ + + p_j2k->m_specific_param.m_decoder.m_discard_tiles = 1; + + ret = opj_j2k_update_image_dimensions(p_image, p_manager); + + if (ret) { + opj_event_msg(p_manager, EVT_INFO, "Setting decoding area to %d,%d,%d,%d\n", + p_image->x0, p_image->y0, p_image->x1, p_image->y1); + } + + return ret; +} + +opj_j2k_t* opj_j2k_create_decompress(void) +{ + opj_j2k_t *l_j2k = (opj_j2k_t*) opj_calloc(1, sizeof(opj_j2k_t)); + if (!l_j2k) { + return 00; + } + + l_j2k->m_is_decoder = 1; + l_j2k->m_cp.m_is_decoder = 1; + /* in the absence of JP2 boxes, consider different bit depth / sign */ + /* per component is allowed */ + l_j2k->m_cp.allow_different_bit_depth_sign = 1; + + /* Default to using strict mode. */ + l_j2k->m_cp.strict = OPJ_TRUE; + +#ifdef OPJ_DISABLE_TPSOT_FIX + l_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; +#endif + + l_j2k->m_specific_param.m_decoder.m_default_tcp = (opj_tcp_t*) opj_calloc(1, + sizeof(opj_tcp_t)); + if (!l_j2k->m_specific_param.m_decoder.m_default_tcp) { + opj_j2k_destroy(l_j2k); + return 00; + } + + l_j2k->m_specific_param.m_decoder.m_header_data = (OPJ_BYTE *) opj_calloc(1, + OPJ_J2K_DEFAULT_HEADER_SIZE); + if (! l_j2k->m_specific_param.m_decoder.m_header_data) { + opj_j2k_destroy(l_j2k); + return 00; + } + + l_j2k->m_specific_param.m_decoder.m_header_data_size = + OPJ_J2K_DEFAULT_HEADER_SIZE; + + l_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = -1 ; + + l_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = 0 ; + + /* codestream index creation */ + l_j2k->cstr_index = opj_j2k_create_cstr_index(); + if (!l_j2k->cstr_index) { + opj_j2k_destroy(l_j2k); + return 00; + } + + /* validation list creation */ + l_j2k->m_validation_list = opj_procedure_list_create(); + if (! l_j2k->m_validation_list) { + opj_j2k_destroy(l_j2k); + return 00; + } + + /* execution list creation */ + l_j2k->m_procedure_list = opj_procedure_list_create(); + if (! l_j2k->m_procedure_list) { + opj_j2k_destroy(l_j2k); + return 00; + } + + l_j2k->m_tp = opj_thread_pool_create(opj_j2k_get_default_thread_count()); + if (!l_j2k->m_tp) { + l_j2k->m_tp = opj_thread_pool_create(0); + } + if (!l_j2k->m_tp) { + opj_j2k_destroy(l_j2k); + return NULL; + } + + return l_j2k; +} + +static opj_codestream_index_t* opj_j2k_create_cstr_index(void) +{ + opj_codestream_index_t* cstr_index = (opj_codestream_index_t*) + opj_calloc(1, sizeof(opj_codestream_index_t)); + if (!cstr_index) { + return NULL; + } + + cstr_index->maxmarknum = 100; + cstr_index->marknum = 0; + cstr_index->marker = (opj_marker_info_t*) + opj_calloc(cstr_index->maxmarknum, sizeof(opj_marker_info_t)); + if (!cstr_index-> marker) { + opj_free(cstr_index); + return NULL; + } + + cstr_index->tile_index = NULL; + + return cstr_index; +} + +static OPJ_UINT32 opj_j2k_get_SPCod_SPCoc_size(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no) +{ + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + /* preconditions */ + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + /* preconditions again */ + assert(p_tile_no < (l_cp->tw * l_cp->th)); + assert(p_comp_no < p_j2k->m_private_image->numcomps); + + if (l_tccp->csty & J2K_CCP_CSTY_PRT) { + return 5 + l_tccp->numresolutions; + } else { + return 5; + } +} + +static OPJ_BOOL opj_j2k_compare_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no) +{ + OPJ_UINT32 i; + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_tccp0 = NULL; + opj_tccp_t *l_tccp1 = NULL; + + /* preconditions */ + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp0 = &l_tcp->tccps[p_first_comp_no]; + l_tccp1 = &l_tcp->tccps[p_second_comp_no]; + + if (l_tccp0->numresolutions != l_tccp1->numresolutions) { + return OPJ_FALSE; + } + if (l_tccp0->cblkw != l_tccp1->cblkw) { + return OPJ_FALSE; + } + if (l_tccp0->cblkh != l_tccp1->cblkh) { + return OPJ_FALSE; + } + if (l_tccp0->cblksty != l_tccp1->cblksty) { + return OPJ_FALSE; + } + if (l_tccp0->qmfbid != l_tccp1->qmfbid) { + return OPJ_FALSE; + } + if ((l_tccp0->csty & J2K_CCP_CSTY_PRT) != (l_tccp1->csty & J2K_CCP_CSTY_PRT)) { + return OPJ_FALSE; + } + + for (i = 0U; i < l_tccp0->numresolutions; ++i) { + if (l_tccp0->prcw[i] != l_tccp1->prcw[i]) { + return OPJ_FALSE; + } + if (l_tccp0->prch[i] != l_tccp1->prch[i]) { + return OPJ_FALSE; + } + } + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 i; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_header_size != 00); + assert(p_manager != 00); + assert(p_data != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + /* preconditions again */ + assert(p_tile_no < (l_cp->tw * l_cp->th)); + assert(p_comp_no < (p_j2k->m_private_image->numcomps)); + + if (*p_header_size < 5) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing SPCod SPCoc element\n"); + return OPJ_FALSE; + } + + opj_write_bytes(p_data, l_tccp->numresolutions - 1, 1); /* SPcoc (D) */ + ++p_data; + + opj_write_bytes(p_data, l_tccp->cblkw - 2, 1); /* SPcoc (E) */ + ++p_data; + + opj_write_bytes(p_data, l_tccp->cblkh - 2, 1); /* SPcoc (F) */ + ++p_data; + + opj_write_bytes(p_data, l_tccp->cblksty, + 1); /* SPcoc (G) */ + ++p_data; + + opj_write_bytes(p_data, l_tccp->qmfbid, + 1); /* SPcoc (H) */ + ++p_data; + + *p_header_size = *p_header_size - 5; + + if (l_tccp->csty & J2K_CCP_CSTY_PRT) { + + if (*p_header_size < l_tccp->numresolutions) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing SPCod SPCoc element\n"); + return OPJ_FALSE; + } + + for (i = 0; i < l_tccp->numresolutions; ++i) { + opj_write_bytes(p_data, l_tccp->prcw[i] + (l_tccp->prch[i] << 4), + 1); /* SPcoc (I_i) */ + ++p_data; + } + + *p_header_size = *p_header_size - l_tccp->numresolutions; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_read_SPCod_SPCoc(opj_j2k_t *p_j2k, + OPJ_UINT32 compno, + OPJ_BYTE * p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, l_tmp; + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_tccp = NULL; + OPJ_BYTE * l_current_ptr = NULL; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + /* precondition again */ + assert(compno < p_j2k->m_private_image->numcomps); + + l_tccp = &l_tcp->tccps[compno]; + l_current_ptr = p_header_data; + + /* make sure room is sufficient */ + if (*p_header_size < 5) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); + return OPJ_FALSE; + } + + /* SPcod (D) / SPcoc (A) */ + opj_read_bytes(l_current_ptr, &l_tccp->numresolutions, 1); + ++l_tccp->numresolutions; /* tccp->numresolutions = read() + 1 */ + if (l_tccp->numresolutions > OPJ_J2K_MAXRLVLS) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for numresolutions : %d, max value is set in openjpeg.h at %d\n", + l_tccp->numresolutions, OPJ_J2K_MAXRLVLS); + return OPJ_FALSE; + } + ++l_current_ptr; + + /* If user wants to remove more resolutions than the codestream contains, return error */ + if (l_cp->m_specific_param.m_dec.m_reduce >= l_tccp->numresolutions) { + opj_event_msg(p_manager, EVT_ERROR, + "Error decoding component %d.\nThe number of resolutions " + "to remove (%d) is greater or equal than the number " + "of resolutions of this component (%d)\nModify the cp_reduce parameter.\n\n", + compno, l_cp->m_specific_param.m_dec.m_reduce, l_tccp->numresolutions); + p_j2k->m_specific_param.m_decoder.m_state |= + 0x8000;/* FIXME J2K_DEC_STATE_ERR;*/ + return OPJ_FALSE; + } + + /* SPcod (E) / SPcoc (B) */ + opj_read_bytes(l_current_ptr, &l_tccp->cblkw, 1); + ++l_current_ptr; + l_tccp->cblkw += 2; + + /* SPcod (F) / SPcoc (C) */ + opj_read_bytes(l_current_ptr, &l_tccp->cblkh, 1); + ++l_current_ptr; + l_tccp->cblkh += 2; + + if ((l_tccp->cblkw > 10) || (l_tccp->cblkh > 10) || + ((l_tccp->cblkw + l_tccp->cblkh) > 12)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error reading SPCod SPCoc element, Invalid cblkw/cblkh combination\n"); + return OPJ_FALSE; + } + + /* SPcod (G) / SPcoc (D) */ + opj_read_bytes(l_current_ptr, &l_tccp->cblksty, 1); + ++l_current_ptr; + if ((l_tccp->cblksty & J2K_CCP_CBLKSTY_HTMIXED) != 0) { + /* We do not support HT mixed mode yet. For conformance, it should be supported.*/ + opj_event_msg(p_manager, EVT_ERROR, + "Error reading SPCod SPCoc element. Unsupported Mixed HT code-block style found\n"); + return OPJ_FALSE; + } + + /* SPcod (H) / SPcoc (E) */ + opj_read_bytes(l_current_ptr, &l_tccp->qmfbid, 1); + ++l_current_ptr; + + if (l_tccp->qmfbid > 1) { + opj_event_msg(p_manager, EVT_ERROR, + "Error reading SPCod SPCoc element, Invalid transformation found\n"); + return OPJ_FALSE; + } + + *p_header_size = *p_header_size - 5; + + /* use custom precinct size ? */ + if (l_tccp->csty & J2K_CCP_CSTY_PRT) { + if (*p_header_size < l_tccp->numresolutions) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element\n"); + return OPJ_FALSE; + } + + /* SPcod (I_i) / SPcoc (F_i) */ + for (i = 0; i < l_tccp->numresolutions; ++i) { + opj_read_bytes(l_current_ptr, &l_tmp, 1); + ++l_current_ptr; + /* Precinct exponent 0 is only allowed for lowest resolution level (Table A.21) */ + if ((i != 0) && (((l_tmp & 0xf) == 0) || ((l_tmp >> 4) == 0))) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid precinct size\n"); + return OPJ_FALSE; + } + l_tccp->prcw[i] = l_tmp & 0xf; + l_tccp->prch[i] = l_tmp >> 4; + } + + *p_header_size = *p_header_size - l_tccp->numresolutions; + } else { + /* set default size for the precinct width and height */ + for (i = 0; i < l_tccp->numresolutions; ++i) { + l_tccp->prcw[i] = 15; + l_tccp->prch[i] = 15; + } + } + +#ifdef WIP_REMOVE_MSD + /* INDEX >> */ + if (p_j2k->cstr_info && compno == 0) { + OPJ_UINT32 l_data_size = l_tccp->numresolutions * sizeof(OPJ_UINT32); + + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkh = + l_tccp->cblkh; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblkw = + l_tccp->cblkw; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].numresolutions + = l_tccp->numresolutions; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].cblksty = + l_tccp->cblksty; + p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].tccp_info[compno].qmfbid = + l_tccp->qmfbid; + + memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdx, l_tccp->prcw, + l_data_size); + memcpy(p_j2k->cstr_info->tile[p_j2k->m_current_tile_number].pdy, l_tccp->prch, + l_data_size); + } + /* << INDEX */ +#endif + + return OPJ_TRUE; +} + +static void opj_j2k_copy_tile_component_parameters(opj_j2k_t *p_j2k) +{ + /* loop */ + OPJ_UINT32 i; + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_ref_tccp = NULL, *l_copied_tccp = NULL; + OPJ_UINT32 l_prc_size; + + /* preconditions */ + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) + ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + l_ref_tccp = &l_tcp->tccps[0]; + l_copied_tccp = l_ref_tccp + 1; + l_prc_size = l_ref_tccp->numresolutions * (OPJ_UINT32)sizeof(OPJ_UINT32); + + for (i = 1; i < p_j2k->m_private_image->numcomps; ++i) { + l_copied_tccp->numresolutions = l_ref_tccp->numresolutions; + l_copied_tccp->cblkw = l_ref_tccp->cblkw; + l_copied_tccp->cblkh = l_ref_tccp->cblkh; + l_copied_tccp->cblksty = l_ref_tccp->cblksty; + l_copied_tccp->qmfbid = l_ref_tccp->qmfbid; + memcpy(l_copied_tccp->prcw, l_ref_tccp->prcw, l_prc_size); + memcpy(l_copied_tccp->prch, l_ref_tccp->prch, l_prc_size); + ++l_copied_tccp; + } +} + +static OPJ_UINT32 opj_j2k_get_SQcd_SQcc_size(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no) +{ + OPJ_UINT32 l_num_bands; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + /* preconditions */ + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + /* preconditions again */ + assert(p_tile_no < l_cp->tw * l_cp->th); + assert(p_comp_no < p_j2k->m_private_image->numcomps); + + l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : + (l_tccp->numresolutions * 3 - 2); + + if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + return 1 + l_num_bands; + } else { + return 1 + 2 * l_num_bands; + } +} + +static OPJ_BOOL opj_j2k_compare_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, OPJ_UINT32 p_first_comp_no, OPJ_UINT32 p_second_comp_no) +{ + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_tccp0 = NULL; + opj_tccp_t *l_tccp1 = NULL; + OPJ_UINT32 l_band_no, l_num_bands; + + /* preconditions */ + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp0 = &l_tcp->tccps[p_first_comp_no]; + l_tccp1 = &l_tcp->tccps[p_second_comp_no]; + + if (l_tccp0->qntsty != l_tccp1->qntsty) { + return OPJ_FALSE; + } + if (l_tccp0->numgbits != l_tccp1->numgbits) { + return OPJ_FALSE; + } + if (l_tccp0->qntsty == J2K_CCP_QNTSTY_SIQNT) { + l_num_bands = 1U; + } else { + l_num_bands = l_tccp0->numresolutions * 3U - 2U; + if (l_num_bands != (l_tccp1->numresolutions * 3U - 2U)) { + return OPJ_FALSE; + } + } + + for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { + if (l_tccp0->stepsizes[l_band_no].expn != l_tccp1->stepsizes[l_band_no].expn) { + return OPJ_FALSE; + } + } + if (l_tccp0->qntsty != J2K_CCP_QNTSTY_NOQNT) { + for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { + if (l_tccp0->stepsizes[l_band_no].mant != l_tccp1->stepsizes[l_band_no].mant) { + return OPJ_FALSE; + } + } + } + return OPJ_TRUE; +} + + +static OPJ_BOOL opj_j2k_write_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_tile_no, + OPJ_UINT32 p_comp_no, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_header_size, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 l_header_size; + OPJ_UINT32 l_band_no, l_num_bands; + OPJ_UINT32 l_expn, l_mant; + + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_header_size != 00); + assert(p_manager != 00); + assert(p_data != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = &l_cp->tcps[p_tile_no]; + l_tccp = &l_tcp->tccps[p_comp_no]; + + /* preconditions again */ + assert(p_tile_no < l_cp->tw * l_cp->th); + assert(p_comp_no < p_j2k->m_private_image->numcomps); + + l_num_bands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : + (l_tccp->numresolutions * 3 - 2); + + if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + l_header_size = 1 + l_num_bands; + + if (*p_header_size < l_header_size) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n"); + return OPJ_FALSE; + } + + opj_write_bytes(p_data, l_tccp->qntsty + (l_tccp->numgbits << 5), + 1); /* Sqcx */ + ++p_data; + + for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { + l_expn = (OPJ_UINT32)l_tccp->stepsizes[l_band_no].expn; + opj_write_bytes(p_data, l_expn << 3, 1); /* SPqcx_i */ + ++p_data; + } + } else { + l_header_size = 1 + 2 * l_num_bands; + + if (*p_header_size < l_header_size) { + opj_event_msg(p_manager, EVT_ERROR, "Error writing SQcd SQcc element\n"); + return OPJ_FALSE; + } + + opj_write_bytes(p_data, l_tccp->qntsty + (l_tccp->numgbits << 5), + 1); /* Sqcx */ + ++p_data; + + for (l_band_no = 0; l_band_no < l_num_bands; ++l_band_no) { + l_expn = (OPJ_UINT32)l_tccp->stepsizes[l_band_no].expn; + l_mant = (OPJ_UINT32)l_tccp->stepsizes[l_band_no].mant; + + opj_write_bytes(p_data, (l_expn << 11) + l_mant, 2); /* SPqcx_i */ + p_data += 2; + } + } + + *p_header_size = *p_header_size - l_header_size; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k, + OPJ_UINT32 p_comp_no, + OPJ_BYTE* p_header_data, + OPJ_UINT32 * p_header_size, + opj_event_mgr_t * p_manager + ) +{ + /* loop*/ + OPJ_UINT32 l_band_no; + opj_cp_t *l_cp = 00; + opj_tcp_t *l_tcp = 00; + opj_tccp_t *l_tccp = 00; + OPJ_BYTE * l_current_ptr = 00; + OPJ_UINT32 l_tmp, l_num_band; + + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_header_data != 00); + + l_cp = &(p_j2k->m_cp); + /* come from tile part header or main header ?*/ + l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) + ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + /* precondition again*/ + assert(p_comp_no < p_j2k->m_private_image->numcomps); + + l_tccp = &l_tcp->tccps[p_comp_no]; + l_current_ptr = p_header_data; + + if (*p_header_size < 1) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading SQcd or SQcc element\n"); + return OPJ_FALSE; + } + *p_header_size -= 1; + + opj_read_bytes(l_current_ptr, &l_tmp, 1); /* Sqcx */ + ++l_current_ptr; + + l_tccp->qntsty = l_tmp & 0x1f; + l_tccp->numgbits = l_tmp >> 5; + if (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) { + l_num_band = 1; + } else { + l_num_band = (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) ? + (*p_header_size) : + (*p_header_size) / 2; + + if (l_num_band > OPJ_J2K_MAXBANDS) { + opj_event_msg(p_manager, EVT_WARNING, + "While reading CCP_QNTSTY element inside QCD or QCC marker segment, " + "number of subbands (%d) is greater to OPJ_J2K_MAXBANDS (%d). So we limit the number of elements stored to " + "OPJ_J2K_MAXBANDS (%d) and skip the rest. \n", l_num_band, OPJ_J2K_MAXBANDS, + OPJ_J2K_MAXBANDS); + /*return OPJ_FALSE;*/ + } + } + +#ifdef USE_JPWL + if (l_cp->correct) { + + /* if JPWL is on, we check whether there are too many subbands */ + if (/*(l_num_band < 0) ||*/ (l_num_band >= OPJ_J2K_MAXBANDS)) { + opj_event_msg(p_manager, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, + "JPWL: bad number of subbands in Sqcx (%d)\n", + l_num_band); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + /* we try to correct */ + l_num_band = 1; + opj_event_msg(p_manager, EVT_WARNING, "- trying to adjust them\n" + "- setting number of bands to %d => HYPOTHESIS!!!\n", + l_num_band); + }; + + }; +#endif /* USE_JPWL */ + + if (l_tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) { + for (l_band_no = 0; l_band_no < l_num_band; l_band_no++) { + opj_read_bytes(l_current_ptr, &l_tmp, 1); /* SPqcx_i */ + ++l_current_ptr; + if (l_band_no < OPJ_J2K_MAXBANDS) { + l_tccp->stepsizes[l_band_no].expn = (OPJ_INT32)(l_tmp >> 3); + l_tccp->stepsizes[l_band_no].mant = 0; + } + } + + if (*p_header_size < l_num_band) { + return OPJ_FALSE; + } + *p_header_size = *p_header_size - l_num_band; + } else { + for (l_band_no = 0; l_band_no < l_num_band; l_band_no++) { + opj_read_bytes(l_current_ptr, &l_tmp, 2); /* SPqcx_i */ + l_current_ptr += 2; + if (l_band_no < OPJ_J2K_MAXBANDS) { + l_tccp->stepsizes[l_band_no].expn = (OPJ_INT32)(l_tmp >> 11); + l_tccp->stepsizes[l_band_no].mant = l_tmp & 0x7ff; + } + } + + if (*p_header_size < 2 * l_num_band) { + return OPJ_FALSE; + } + *p_header_size = *p_header_size - 2 * l_num_band; + } + + /* Add Antonin : if scalar_derived -> compute other stepsizes */ + if (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) { + for (l_band_no = 1; l_band_no < OPJ_J2K_MAXBANDS; l_band_no++) { + l_tccp->stepsizes[l_band_no].expn = + ((OPJ_INT32)(l_tccp->stepsizes[0].expn) - (OPJ_INT32)((l_band_no - 1) / 3) > 0) + ? + (OPJ_INT32)(l_tccp->stepsizes[0].expn) - (OPJ_INT32)((l_band_no - 1) / 3) : 0; + l_tccp->stepsizes[l_band_no].mant = l_tccp->stepsizes[0].mant; + } + } + + return OPJ_TRUE; +} + +static void opj_j2k_copy_tile_quantization_parameters(opj_j2k_t *p_j2k) +{ + OPJ_UINT32 i; + opj_cp_t *l_cp = NULL; + opj_tcp_t *l_tcp = NULL; + opj_tccp_t *l_ref_tccp = NULL; + opj_tccp_t *l_copied_tccp = NULL; + OPJ_UINT32 l_size; + + /* preconditions */ + assert(p_j2k != 00); + + l_cp = &(p_j2k->m_cp); + l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ? + &l_cp->tcps[p_j2k->m_current_tile_number] : + p_j2k->m_specific_param.m_decoder.m_default_tcp; + + l_ref_tccp = &l_tcp->tccps[0]; + l_copied_tccp = l_ref_tccp + 1; + l_size = OPJ_J2K_MAXBANDS * sizeof(opj_stepsize_t); + + for (i = 1; i < p_j2k->m_private_image->numcomps; ++i) { + l_copied_tccp->qntsty = l_ref_tccp->qntsty; + l_copied_tccp->numgbits = l_ref_tccp->numgbits; + memcpy(l_copied_tccp->stepsizes, l_ref_tccp->stepsizes, l_size); + ++l_copied_tccp; + } +} + +static void opj_j2k_dump_tile_info(opj_tcp_t * l_default_tile, + OPJ_INT32 numcomps, FILE* out_stream) +{ + if (l_default_tile) { + OPJ_INT32 compno; + + fprintf(out_stream, "\t default tile {\n"); + fprintf(out_stream, "\t\t csty=%#x\n", l_default_tile->csty); + fprintf(out_stream, "\t\t prg=%#x\n", l_default_tile->prg); + fprintf(out_stream, "\t\t numlayers=%d\n", l_default_tile->numlayers); + fprintf(out_stream, "\t\t mct=%x\n", l_default_tile->mct); + + for (compno = 0; compno < numcomps; compno++) { + opj_tccp_t *l_tccp = &(l_default_tile->tccps[compno]); + OPJ_UINT32 resno; + OPJ_INT32 bandno, numbands; + + /* coding style*/ + fprintf(out_stream, "\t\t comp %d {\n", compno); + fprintf(out_stream, "\t\t\t csty=%#x\n", l_tccp->csty); + fprintf(out_stream, "\t\t\t numresolutions=%d\n", l_tccp->numresolutions); + fprintf(out_stream, "\t\t\t cblkw=2^%d\n", l_tccp->cblkw); + fprintf(out_stream, "\t\t\t cblkh=2^%d\n", l_tccp->cblkh); + fprintf(out_stream, "\t\t\t cblksty=%#x\n", l_tccp->cblksty); + fprintf(out_stream, "\t\t\t qmfbid=%d\n", l_tccp->qmfbid); + + fprintf(out_stream, "\t\t\t preccintsize (w,h)="); + for (resno = 0; resno < l_tccp->numresolutions; resno++) { + fprintf(out_stream, "(%d,%d) ", l_tccp->prcw[resno], l_tccp->prch[resno]); + } + fprintf(out_stream, "\n"); + + /* quantization style*/ + fprintf(out_stream, "\t\t\t qntsty=%d\n", l_tccp->qntsty); + fprintf(out_stream, "\t\t\t numgbits=%d\n", l_tccp->numgbits); + fprintf(out_stream, "\t\t\t stepsizes (m,e)="); + numbands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : + (OPJ_INT32)l_tccp->numresolutions * 3 - 2; + for (bandno = 0; bandno < numbands; bandno++) { + fprintf(out_stream, "(%d,%d) ", l_tccp->stepsizes[bandno].mant, + l_tccp->stepsizes[bandno].expn); + } + fprintf(out_stream, "\n"); + + /* RGN value*/ + fprintf(out_stream, "\t\t\t roishift=%d\n", l_tccp->roishift); + + fprintf(out_stream, "\t\t }\n"); + } /*end of component of default tile*/ + fprintf(out_stream, "\t }\n"); /*end of default tile*/ + } +} + +void j2k_dump(opj_j2k_t* p_j2k, OPJ_INT32 flag, FILE* out_stream) +{ + /* Check if the flag is compatible with j2k file*/ + if ((flag & OPJ_JP2_INFO) || (flag & OPJ_JP2_IND)) { + fprintf(out_stream, "Wrong flag\n"); + return; + } + + /* Dump the image_header */ + if (flag & OPJ_IMG_INFO) { + if (p_j2k->m_private_image) { + j2k_dump_image_header(p_j2k->m_private_image, 0, out_stream); + } + } + + /* Dump the codestream info from main header */ + if (flag & OPJ_J2K_MH_INFO) { + if (p_j2k->m_private_image) { + opj_j2k_dump_MH_info(p_j2k, out_stream); + } + } + /* Dump all tile/codestream info */ + if (flag & OPJ_J2K_TCH_INFO) { + OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + OPJ_UINT32 i; + opj_tcp_t * l_tcp = p_j2k->m_cp.tcps; + if (p_j2k->m_private_image) { + for (i = 0; i < l_nb_tiles; ++i) { + opj_j2k_dump_tile_info(l_tcp, (OPJ_INT32)p_j2k->m_private_image->numcomps, + out_stream); + ++l_tcp; + } + } + } + + /* Dump the codestream info of the current tile */ + if (flag & OPJ_J2K_TH_INFO) { + + } + + /* Dump the codestream index from main header */ + if (flag & OPJ_J2K_MH_IND) { + opj_j2k_dump_MH_index(p_j2k, out_stream); + } + + /* Dump the codestream index of the current tile */ + if (flag & OPJ_J2K_TH_IND) { + + } + +} + +static void opj_j2k_dump_MH_index(opj_j2k_t* p_j2k, FILE* out_stream) +{ + opj_codestream_index_t* cstr_index = p_j2k->cstr_index; + OPJ_UINT32 it_marker, it_tile, it_tile_part; + + fprintf(out_stream, "Codestream index from main header: {\n"); + + fprintf(out_stream, "\t Main header start position=%" PRIi64 "\n" + "\t Main header end position=%" PRIi64 "\n", + cstr_index->main_head_start, cstr_index->main_head_end); + + fprintf(out_stream, "\t Marker list: {\n"); + + if (cstr_index->marker) { + for (it_marker = 0; it_marker < cstr_index->marknum ; it_marker++) { + fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n", + cstr_index->marker[it_marker].type, + cstr_index->marker[it_marker].pos, + cstr_index->marker[it_marker].len); + } + } + + fprintf(out_stream, "\t }\n"); + + if (cstr_index->tile_index) { + + /* Simple test to avoid to write empty information*/ + OPJ_UINT32 l_acc_nb_of_tile_part = 0; + for (it_tile = 0; it_tile < cstr_index->nb_of_tiles ; it_tile++) { + l_acc_nb_of_tile_part += cstr_index->tile_index[it_tile].nb_tps; + + /* To avoid regenerating expected opj_dump results from the test */ + /* suite when there is a TLM marker present */ + if (cstr_index->tile_index[it_tile].nb_tps && + cstr_index->tile_index[it_tile].tp_index && + cstr_index->tile_index[it_tile].tp_index[0].start_pos > 0 && + cstr_index->tile_index[it_tile].tp_index[0].end_header == 0 && + getenv("OJP_DO_NOT_DISPLAY_TILE_INDEX_IF_TLM") != NULL) { + l_acc_nb_of_tile_part = 0; + break; + } + } + + if (l_acc_nb_of_tile_part) { + fprintf(out_stream, "\t Tile index: {\n"); + + for (it_tile = 0; it_tile < cstr_index->nb_of_tiles ; it_tile++) { + OPJ_UINT32 nb_of_tile_part = cstr_index->tile_index[it_tile].nb_tps; + + fprintf(out_stream, "\t\t nb of tile-part in tile [%d]=%d\n", it_tile, + nb_of_tile_part); + + if (cstr_index->tile_index[it_tile].tp_index) { + for (it_tile_part = 0; it_tile_part < nb_of_tile_part; it_tile_part++) { + fprintf(out_stream, "\t\t\t tile-part[%d]: star_pos=%" PRIi64 ", end_header=%" + PRIi64 ", end_pos=%" PRIi64 ".\n", + it_tile_part, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].start_pos, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_header, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_pos); + } + } + + if (cstr_index->tile_index[it_tile].marker) { + for (it_marker = 0; it_marker < cstr_index->tile_index[it_tile].marknum ; + it_marker++) { + fprintf(out_stream, "\t\t type=%#x, pos=%" PRIi64 ", len=%d\n", + cstr_index->tile_index[it_tile].marker[it_marker].type, + cstr_index->tile_index[it_tile].marker[it_marker].pos, + cstr_index->tile_index[it_tile].marker[it_marker].len); + } + } + } + fprintf(out_stream, "\t }\n"); + } + } + + fprintf(out_stream, "}\n"); + +} + + +static void opj_j2k_dump_MH_info(opj_j2k_t* p_j2k, FILE* out_stream) +{ + + fprintf(out_stream, "Codestream info from main header: {\n"); + + fprintf(out_stream, "\t tx0=%" PRIu32 ", ty0=%" PRIu32 "\n", p_j2k->m_cp.tx0, + p_j2k->m_cp.ty0); + fprintf(out_stream, "\t tdx=%" PRIu32 ", tdy=%" PRIu32 "\n", p_j2k->m_cp.tdx, + p_j2k->m_cp.tdy); + fprintf(out_stream, "\t tw=%" PRIu32 ", th=%" PRIu32 "\n", p_j2k->m_cp.tw, + p_j2k->m_cp.th); + opj_j2k_dump_tile_info(p_j2k->m_specific_param.m_decoder.m_default_tcp, + (OPJ_INT32)p_j2k->m_private_image->numcomps, out_stream); + fprintf(out_stream, "}\n"); +} + +void j2k_dump_image_header(opj_image_t* img_header, OPJ_BOOL dev_dump_flag, + FILE* out_stream) +{ + char tab[2]; + + if (dev_dump_flag) { + fprintf(stdout, "[DEV] Dump an image_header struct {\n"); + tab[0] = '\0'; + } else { + fprintf(out_stream, "Image info {\n"); + tab[0] = '\t'; + tab[1] = '\0'; + } + + fprintf(out_stream, "%s x0=%d, y0=%d\n", tab, img_header->x0, img_header->y0); + fprintf(out_stream, "%s x1=%d, y1=%d\n", tab, img_header->x1, + img_header->y1); + fprintf(out_stream, "%s numcomps=%d\n", tab, img_header->numcomps); + + if (img_header->comps) { + OPJ_UINT32 compno; + for (compno = 0; compno < img_header->numcomps; compno++) { + fprintf(out_stream, "%s\t component %d {\n", tab, compno); + j2k_dump_image_comp_header(&(img_header->comps[compno]), dev_dump_flag, + out_stream); + fprintf(out_stream, "%s}\n", tab); + } + } + + fprintf(out_stream, "}\n"); +} + +void j2k_dump_image_comp_header(opj_image_comp_t* comp_header, + OPJ_BOOL dev_dump_flag, FILE* out_stream) +{ + char tab[3]; + + if (dev_dump_flag) { + fprintf(stdout, "[DEV] Dump an image_comp_header struct {\n"); + tab[0] = '\0'; + } else { + tab[0] = '\t'; + tab[1] = '\t'; + tab[2] = '\0'; + } + + fprintf(out_stream, "%s dx=%d, dy=%d\n", tab, comp_header->dx, comp_header->dy); + fprintf(out_stream, "%s prec=%d\n", tab, comp_header->prec); + fprintf(out_stream, "%s sgnd=%d\n", tab, comp_header->sgnd); + + if (dev_dump_flag) { + fprintf(out_stream, "}\n"); + } +} + +opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k) +{ + OPJ_UINT32 compno; + OPJ_UINT32 numcomps = p_j2k->m_private_image->numcomps; + opj_tcp_t *l_default_tile; + opj_codestream_info_v2_t* cstr_info = (opj_codestream_info_v2_t*) opj_calloc(1, + sizeof(opj_codestream_info_v2_t)); + if (!cstr_info) { + return NULL; + } + + cstr_info->nbcomps = p_j2k->m_private_image->numcomps; + + cstr_info->tx0 = p_j2k->m_cp.tx0; + cstr_info->ty0 = p_j2k->m_cp.ty0; + cstr_info->tdx = p_j2k->m_cp.tdx; + cstr_info->tdy = p_j2k->m_cp.tdy; + cstr_info->tw = p_j2k->m_cp.tw; + cstr_info->th = p_j2k->m_cp.th; + + cstr_info->tile_info = NULL; /* Not fill from the main header*/ + + l_default_tile = p_j2k->m_specific_param.m_decoder.m_default_tcp; + + cstr_info->m_default_tile_info.csty = l_default_tile->csty; + cstr_info->m_default_tile_info.prg = l_default_tile->prg; + cstr_info->m_default_tile_info.numlayers = l_default_tile->numlayers; + cstr_info->m_default_tile_info.mct = l_default_tile->mct; + + cstr_info->m_default_tile_info.tccp_info = (opj_tccp_info_t*) opj_calloc( + cstr_info->nbcomps, sizeof(opj_tccp_info_t)); + if (!cstr_info->m_default_tile_info.tccp_info) { + opj_destroy_cstr_info(&cstr_info); + return NULL; + } + + for (compno = 0; compno < numcomps; compno++) { + opj_tccp_t *l_tccp = &(l_default_tile->tccps[compno]); + opj_tccp_info_t *l_tccp_info = & + (cstr_info->m_default_tile_info.tccp_info[compno]); + OPJ_INT32 bandno, numbands; + + /* coding style*/ + l_tccp_info->csty = l_tccp->csty; + l_tccp_info->numresolutions = l_tccp->numresolutions; + l_tccp_info->cblkw = l_tccp->cblkw; + l_tccp_info->cblkh = l_tccp->cblkh; + l_tccp_info->cblksty = l_tccp->cblksty; + l_tccp_info->qmfbid = l_tccp->qmfbid; + if (l_tccp->numresolutions < OPJ_J2K_MAXRLVLS) { + memcpy(l_tccp_info->prch, l_tccp->prch, l_tccp->numresolutions); + memcpy(l_tccp_info->prcw, l_tccp->prcw, l_tccp->numresolutions); + } + + /* quantization style*/ + l_tccp_info->qntsty = l_tccp->qntsty; + l_tccp_info->numgbits = l_tccp->numgbits; + + numbands = (l_tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ? 1 : + (OPJ_INT32)l_tccp->numresolutions * 3 - 2; + if (numbands < OPJ_J2K_MAXBANDS) { + for (bandno = 0; bandno < numbands; bandno++) { + l_tccp_info->stepsizes_mant[bandno] = (OPJ_UINT32) + l_tccp->stepsizes[bandno].mant; + l_tccp_info->stepsizes_expn[bandno] = (OPJ_UINT32) + l_tccp->stepsizes[bandno].expn; + } + } + + /* RGN value*/ + l_tccp_info->roishift = l_tccp->roishift; + } + + return cstr_info; +} + +opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k) +{ + opj_codestream_index_t* l_cstr_index = (opj_codestream_index_t*) + opj_calloc(1, sizeof(opj_codestream_index_t)); + if (!l_cstr_index) { + return NULL; + } + + l_cstr_index->main_head_start = p_j2k->cstr_index->main_head_start; + l_cstr_index->main_head_end = p_j2k->cstr_index->main_head_end; + l_cstr_index->codestream_size = p_j2k->cstr_index->codestream_size; + + l_cstr_index->marknum = p_j2k->cstr_index->marknum; + l_cstr_index->marker = (opj_marker_info_t*)opj_malloc(l_cstr_index->marknum * + sizeof(opj_marker_info_t)); + if (!l_cstr_index->marker) { + opj_free(l_cstr_index); + return NULL; + } + + if (p_j2k->cstr_index->marker) { + memcpy(l_cstr_index->marker, p_j2k->cstr_index->marker, + l_cstr_index->marknum * sizeof(opj_marker_info_t)); + } else { + opj_free(l_cstr_index->marker); + l_cstr_index->marker = NULL; + } + + l_cstr_index->nb_of_tiles = p_j2k->cstr_index->nb_of_tiles; + l_cstr_index->tile_index = (opj_tile_index_t*)opj_calloc( + l_cstr_index->nb_of_tiles, sizeof(opj_tile_index_t)); + if (!l_cstr_index->tile_index) { + opj_free(l_cstr_index->marker); + opj_free(l_cstr_index); + return NULL; + } + + if (!p_j2k->cstr_index->tile_index) { + opj_free(l_cstr_index->tile_index); + l_cstr_index->tile_index = NULL; + } else { + OPJ_UINT32 it_tile = 0; + for (it_tile = 0; it_tile < l_cstr_index->nb_of_tiles; it_tile++) { + + /* Tile Marker*/ + l_cstr_index->tile_index[it_tile].marknum = + p_j2k->cstr_index->tile_index[it_tile].marknum; + + l_cstr_index->tile_index[it_tile].marker = + (opj_marker_info_t*)opj_malloc(l_cstr_index->tile_index[it_tile].marknum * + sizeof(opj_marker_info_t)); + + if (!l_cstr_index->tile_index[it_tile].marker) { + OPJ_UINT32 it_tile_free; + + for (it_tile_free = 0; it_tile_free < it_tile; it_tile_free++) { + opj_free(l_cstr_index->tile_index[it_tile_free].marker); + } + + opj_free(l_cstr_index->tile_index); + opj_free(l_cstr_index->marker); + opj_free(l_cstr_index); + return NULL; + } + + if (p_j2k->cstr_index->tile_index[it_tile].marker) + memcpy(l_cstr_index->tile_index[it_tile].marker, + p_j2k->cstr_index->tile_index[it_tile].marker, + l_cstr_index->tile_index[it_tile].marknum * sizeof(opj_marker_info_t)); + else { + opj_free(l_cstr_index->tile_index[it_tile].marker); + l_cstr_index->tile_index[it_tile].marker = NULL; + } + + /* Tile part index*/ + l_cstr_index->tile_index[it_tile].nb_tps = + p_j2k->cstr_index->tile_index[it_tile].nb_tps; + + l_cstr_index->tile_index[it_tile].tp_index = + (opj_tp_index_t*)opj_malloc(l_cstr_index->tile_index[it_tile].nb_tps * sizeof( + opj_tp_index_t)); + + if (!l_cstr_index->tile_index[it_tile].tp_index) { + OPJ_UINT32 it_tile_free; + + for (it_tile_free = 0; it_tile_free < it_tile; it_tile_free++) { + opj_free(l_cstr_index->tile_index[it_tile_free].marker); + opj_free(l_cstr_index->tile_index[it_tile_free].tp_index); + } + + opj_free(l_cstr_index->tile_index); + opj_free(l_cstr_index->marker); + opj_free(l_cstr_index); + return NULL; + } + + if (p_j2k->cstr_index->tile_index[it_tile].tp_index) { + memcpy(l_cstr_index->tile_index[it_tile].tp_index, + p_j2k->cstr_index->tile_index[it_tile].tp_index, + l_cstr_index->tile_index[it_tile].nb_tps * sizeof(opj_tp_index_t)); + } else { + opj_free(l_cstr_index->tile_index[it_tile].tp_index); + l_cstr_index->tile_index[it_tile].tp_index = NULL; + } + + /* Packet index (NOT USED)*/ + l_cstr_index->tile_index[it_tile].nb_packet = 0; + l_cstr_index->tile_index[it_tile].packet_index = NULL; + + } + } + + return l_cstr_index; +} + +static OPJ_BOOL opj_j2k_allocate_tile_element_cstr_index(opj_j2k_t *p_j2k) +{ + OPJ_UINT32 it_tile = 0; + + p_j2k->cstr_index->nb_of_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th; + p_j2k->cstr_index->tile_index = (opj_tile_index_t*)opj_calloc( + p_j2k->cstr_index->nb_of_tiles, sizeof(opj_tile_index_t)); + if (!p_j2k->cstr_index->tile_index) { + return OPJ_FALSE; + } + + for (it_tile = 0; it_tile < p_j2k->cstr_index->nb_of_tiles; it_tile++) { + p_j2k->cstr_index->tile_index[it_tile].maxmarknum = 100; + p_j2k->cstr_index->tile_index[it_tile].marknum = 0; + p_j2k->cstr_index->tile_index[it_tile].marker = (opj_marker_info_t*) + opj_calloc(p_j2k->cstr_index->tile_index[it_tile].maxmarknum, + sizeof(opj_marker_info_t)); + if (!p_j2k->cstr_index->tile_index[it_tile].marker) { + return OPJ_FALSE; + } + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_are_all_used_components_decoded(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 compno; + OPJ_BOOL decoded_all_used_components = OPJ_TRUE; + + if (p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode) { + for (compno = 0; + compno < p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode; compno++) { + OPJ_UINT32 dec_compno = + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode[compno]; + if (p_j2k->m_output_image->comps[dec_compno].data == NULL) { + opj_event_msg(p_manager, EVT_WARNING, "Failed to decode component %d\n", + dec_compno); + decoded_all_used_components = OPJ_FALSE; + } + } + } else { + for (compno = 0; compno < p_j2k->m_output_image->numcomps; compno++) { + if (p_j2k->m_output_image->comps[compno].data == NULL) { + opj_event_msg(p_manager, EVT_WARNING, "Failed to decode component %d\n", + compno); + decoded_all_used_components = OPJ_FALSE; + } + } + } + + if (decoded_all_used_components == OPJ_FALSE) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to decode all used components\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static int CompareOffT(const void* a, const void* b) +{ + const OPJ_OFF_T offA = *(const OPJ_OFF_T*)a; + const OPJ_OFF_T offB = *(const OPJ_OFF_T*)b; + if (offA < offB) { + return -1; + } + if (offA == offB) { + return 0; + } + return 1; +} + +static OPJ_BOOL opj_j2k_decode_tiles(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_BOOL l_go_on = OPJ_TRUE; + OPJ_UINT32 l_current_tile_no; + OPJ_INT32 l_tile_x0, l_tile_y0, l_tile_x1, l_tile_y1; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 nr_tiles = 0; + OPJ_OFF_T end_pos = 0; + + /* Particular case for whole single tile decoding */ + /* We can avoid allocating intermediate tile buffers */ + if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 && + p_j2k->m_cp.tx0 == 0 && p_j2k->m_cp.ty0 == 0 && + p_j2k->m_output_image->x0 == 0 && + p_j2k->m_output_image->y0 == 0 && + p_j2k->m_output_image->x1 == p_j2k->m_cp.tdx && + p_j2k->m_output_image->y1 == p_j2k->m_cp.tdy) { + OPJ_UINT32 i; + if (! opj_j2k_read_tile_header(p_j2k, + &l_current_tile_no, + NULL, + &l_tile_x0, &l_tile_y0, + &l_tile_x1, &l_tile_y1, + &l_nb_comps, + &l_go_on, + p_stream, + p_manager)) { + return OPJ_FALSE; + } + + if (!l_go_on || + ! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0, + p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to decode tile 1/1\n"); + return OPJ_FALSE; + } + + /* Transfer TCD data to output image data */ + for (i = 0; i < p_j2k->m_output_image->numcomps; i++) { + opj_image_data_free(p_j2k->m_output_image->comps[i].data); + p_j2k->m_output_image->comps[i].data = + p_j2k->m_tcd->tcd_image->tiles->comps[i].data; + p_j2k->m_output_image->comps[i].resno_decoded = + p_j2k->m_tcd->image->comps[i].resno_decoded; + p_j2k->m_tcd->tcd_image->tiles->comps[i].data = NULL; + } + + return OPJ_TRUE; + } + + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts = 0; + p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts = 0; + opj_free(p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset); + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset = NULL; + + /* If the area to decode only intersects a subset of tiles, and we have + * valid TLM information, then use it to plan the tilepart offsets to + * seek to. + */ + if (!(p_j2k->m_specific_param.m_decoder.m_start_tile_x == 0 && + p_j2k->m_specific_param.m_decoder.m_start_tile_y == 0 && + p_j2k->m_specific_param.m_decoder.m_end_tile_x == p_j2k->m_cp.tw && + p_j2k->m_specific_param.m_decoder.m_end_tile_y == p_j2k->m_cp.th) && + !p_j2k->m_specific_param.m_decoder.m_tlm.m_is_invalid && + opj_stream_has_seek(p_stream)) { + OPJ_UINT32 m_num_intersecting_tile_parts = 0; + + OPJ_UINT32 j; + for (j = 0; j < p_j2k->m_cp.tw * p_j2k->m_cp.th; ++j) { + if (p_j2k->cstr_index->tile_index[j].nb_tps > 0 && + p_j2k->cstr_index->tile_index[j].tp_index[ + p_j2k->cstr_index->tile_index[j].nb_tps - 1].end_pos > end_pos) { + end_pos = p_j2k->cstr_index->tile_index[j].tp_index[ + p_j2k->cstr_index->tile_index[j].nb_tps - 1].end_pos; + } + } + + for (j = p_j2k->m_specific_param.m_decoder.m_start_tile_y; + j < p_j2k->m_specific_param.m_decoder.m_end_tile_y; ++j) { + OPJ_UINT32 i; + for (i = p_j2k->m_specific_param.m_decoder.m_start_tile_x; + i < p_j2k->m_specific_param.m_decoder.m_end_tile_x; ++i) { + const OPJ_UINT32 tile_number = j * p_j2k->m_cp.tw + i; + m_num_intersecting_tile_parts += + p_j2k->cstr_index->tile_index[tile_number].nb_tps; + } + } + + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset = + (OPJ_OFF_T*) + opj_malloc(m_num_intersecting_tile_parts * sizeof(OPJ_OFF_T)); + if (m_num_intersecting_tile_parts > 0 && + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset) { + OPJ_UINT32 idx = 0; + for (j = p_j2k->m_specific_param.m_decoder.m_start_tile_y; + j < p_j2k->m_specific_param.m_decoder.m_end_tile_y; ++j) { + OPJ_UINT32 i; + for (i = p_j2k->m_specific_param.m_decoder.m_start_tile_x; + i < p_j2k->m_specific_param.m_decoder.m_end_tile_x; ++i) { + const OPJ_UINT32 tile_number = j * p_j2k->m_cp.tw + i; + OPJ_UINT32 k; + for (k = 0; k < p_j2k->cstr_index->tile_index[tile_number].nb_tps; ++k) { + const OPJ_OFF_T next_tp_sot_pos = + p_j2k->cstr_index->tile_index[tile_number].tp_index[k].start_pos; + p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset[idx] = + next_tp_sot_pos; + ++idx; + } + } + } + + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts = idx; + + /* Sort by increasing offset */ + qsort(p_j2k->m_specific_param.m_decoder.m_intersecting_tile_parts_offset, + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts, + sizeof(OPJ_OFF_T), + CompareOffT); + } + } + + for (;;) { + if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 && + p_j2k->m_cp.tcps[0].m_data != NULL) { + l_current_tile_no = 0; + p_j2k->m_current_tile_number = 0; + p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_DATA; + } else { + if (! opj_j2k_read_tile_header(p_j2k, + &l_current_tile_no, + NULL, + &l_tile_x0, &l_tile_y0, + &l_tile_x1, &l_tile_y1, + &l_nb_comps, + &l_go_on, + p_stream, + p_manager)) { + return OPJ_FALSE; + } + + if (! l_go_on) { + break; + } + } + + if (! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0, + p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to decode tile %d/%d\n", + l_current_tile_no + 1, p_j2k->m_cp.th * p_j2k->m_cp.tw); + return OPJ_FALSE; + } + + opj_event_msg(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", + l_current_tile_no + 1, p_j2k->m_cp.th * p_j2k->m_cp.tw); + + if (! opj_j2k_update_image_data(p_j2k->m_tcd, + p_j2k->m_output_image)) { + return OPJ_FALSE; + } + + if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 && + !(p_j2k->m_output_image->x0 == p_j2k->m_private_image->x0 && + p_j2k->m_output_image->y0 == p_j2k->m_private_image->y0 && + p_j2k->m_output_image->x1 == p_j2k->m_private_image->x1 && + p_j2k->m_output_image->y1 == p_j2k->m_private_image->y1)) { + /* Keep current tcp data */ + } else { + opj_j2k_tcp_data_destroy(&p_j2k->m_cp.tcps[l_current_tile_no]); + } + + opj_event_msg(p_manager, EVT_INFO, + "Image data has been updated with tile %d.\n\n", l_current_tile_no + 1); + + if (opj_stream_get_number_byte_left(p_stream) == 0 + && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) { + break; + } + if (++nr_tiles == p_j2k->m_cp.th * p_j2k->m_cp.tw) { + break; + } + if (p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts > 0 && + p_j2k->m_specific_param.m_decoder.m_idx_intersecting_tile_parts == + p_j2k->m_specific_param.m_decoder.m_num_intersecting_tile_parts) { + opj_stream_seek(p_stream, end_pos + 2, p_manager); + break; + } + } + + if (! opj_j2k_are_all_used_components_decoded(p_j2k, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Sets up the procedures to do on decoding data. Developers wanting to extend the library can add their own reading procedures. + */ +static OPJ_BOOL opj_j2k_setup_decoding(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) +{ + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_decode_tiles, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom procedures */ + + return OPJ_TRUE; +} + +/* + * Read and decode one tile. + */ +static OPJ_BOOL opj_j2k_decode_one_tile(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_BOOL l_go_on = OPJ_TRUE; + OPJ_UINT32 l_current_tile_no; + OPJ_UINT32 l_tile_no_to_dec; + OPJ_INT32 l_tile_x0, l_tile_y0, l_tile_x1, l_tile_y1; + OPJ_UINT32 l_nb_comps; + OPJ_UINT32 l_nb_tiles; + OPJ_UINT32 i; + + /* Move into the codestream to the first SOT used to decode the desired tile */ + l_tile_no_to_dec = (OPJ_UINT32) + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec; + if (p_j2k->cstr_index->tile_index) + if (p_j2k->cstr_index->tile_index->tp_index) { + if (! p_j2k->cstr_index->tile_index[l_tile_no_to_dec].nb_tps) { + /* the index for this tile has not been built, + * so move to the last SOT read */ + if (!(opj_stream_read_seek(p_stream, + p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos + 2, p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; + } + } else { + OPJ_OFF_T sot_pos = + p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos; + OPJ_UINT32 l_marker; + +#if 0 + opj_event_msg(p_manager, EVT_INFO, + "opj_j2k_decode_one_tile(%u): seek to %" PRId64 "\n", + l_tile_no_to_dec, + sot_pos); +#endif + if (!(opj_stream_read_seek(p_stream, + sot_pos, + p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; + } + + /* Try to read 2 bytes (the marker ID) from stream and copy them into the buffer */ + if (opj_stream_read_data(p_stream, + p_j2k->m_specific_param.m_decoder.m_header_data, 2, p_manager) != 2) { + opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); + return OPJ_FALSE; + } + + /* Read 2 bytes from the buffer as the marker ID */ + opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data, &l_marker, + 2); + + if (l_marker != J2K_MS_SOT) { + opj_event_msg(p_manager, EVT_ERROR, "Did not get expected SOT marker\n"); + return OPJ_FALSE; + } + } + /* Special case if we have previously read the EOC marker (if the previous tile getted is the last ) */ + if (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC) { + p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT; + } + } + + /* Reset current tile part number for all tiles, and not only the one */ + /* of interest. */ + /* Not completely sure this is always correct but required for */ + /* ./build/bin/j2k_random_tile_access ./build/tests/tte1.j2k */ + l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th; + for (i = 0; i < l_nb_tiles; ++i) { + p_j2k->m_cp.tcps[i].m_current_tile_part_number = -1; + } + + for (;;) { + if (! opj_j2k_read_tile_header(p_j2k, + &l_current_tile_no, + NULL, + &l_tile_x0, &l_tile_y0, + &l_tile_x1, &l_tile_y1, + &l_nb_comps, + &l_go_on, + p_stream, + p_manager)) { + return OPJ_FALSE; + } + + if (! l_go_on) { + break; + } + + if (! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0, + p_stream, p_manager)) { + return OPJ_FALSE; + } + opj_event_msg(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", + l_current_tile_no + 1, p_j2k->m_cp.th * p_j2k->m_cp.tw); + + if (! opj_j2k_update_image_data(p_j2k->m_tcd, + p_j2k->m_output_image)) { + return OPJ_FALSE; + } + opj_j2k_tcp_data_destroy(&p_j2k->m_cp.tcps[l_current_tile_no]); + + opj_event_msg(p_manager, EVT_INFO, + "Image data has been updated with tile %d.\n\n", l_current_tile_no + 1); + + if (l_current_tile_no == l_tile_no_to_dec) { + /* move into the codestream to the first SOT (FIXME or not move?)*/ + if (!(opj_stream_read_seek(p_stream, p_j2k->cstr_index->main_head_end + 2, + p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\n"); + return OPJ_FALSE; + } + break; + } else { + opj_event_msg(p_manager, EVT_WARNING, + "Tile read, decoded and updated is not the desired one (%d vs %d).\n", + l_current_tile_no + 1, l_tile_no_to_dec + 1); + } + + } + + if (! opj_j2k_are_all_used_components_decoded(p_j2k, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Sets up the procedures to do on decoding one tile. Developers wanting to extend the library can add their own reading procedures. + */ +static OPJ_BOOL opj_j2k_setup_decoding_tile(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) +{ + /* preconditions*/ + assert(p_j2k != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_decode_one_tile, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom procedures */ + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_move_data_from_codec_to_output_image(opj_j2k_t * p_j2k, + opj_image_t * p_image) +{ + OPJ_UINT32 compno; + + /* Move data and copy one information from codec to output image*/ + if (p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode > 0) { + opj_image_comp_t* newcomps = + (opj_image_comp_t*) opj_malloc( + p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode * + sizeof(opj_image_comp_t)); + if (newcomps == NULL) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } + for (compno = 0; compno < p_image->numcomps; compno++) { + opj_image_data_free(p_image->comps[compno].data); + p_image->comps[compno].data = NULL; + } + for (compno = 0; + compno < p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode; compno++) { + OPJ_UINT32 src_compno = + p_j2k->m_specific_param.m_decoder.m_comps_indices_to_decode[compno]; + memcpy(&(newcomps[compno]), + &(p_j2k->m_output_image->comps[src_compno]), + sizeof(opj_image_comp_t)); + newcomps[compno].resno_decoded = + p_j2k->m_output_image->comps[src_compno].resno_decoded; + newcomps[compno].data = p_j2k->m_output_image->comps[src_compno].data; + p_j2k->m_output_image->comps[src_compno].data = NULL; + } + for (compno = 0; compno < p_image->numcomps; compno++) { + assert(p_j2k->m_output_image->comps[compno].data == NULL); + opj_image_data_free(p_j2k->m_output_image->comps[compno].data); + p_j2k->m_output_image->comps[compno].data = NULL; + } + p_image->numcomps = p_j2k->m_specific_param.m_decoder.m_numcomps_to_decode; + opj_free(p_image->comps); + p_image->comps = newcomps; + } else { + for (compno = 0; compno < p_image->numcomps; compno++) { + p_image->comps[compno].resno_decoded = + p_j2k->m_output_image->comps[compno].resno_decoded; + opj_image_data_free(p_image->comps[compno].data); + p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data; +#if 0 + char fn[256]; + snprintf(fn, sizeof fn, "/tmp/%d.raw", compno); + FILE *debug = fopen(fn, "wb"); + fwrite(p_image->comps[compno].data, sizeof(OPJ_INT32), + p_image->comps[compno].w * p_image->comps[compno].h, debug); + fclose(debug); +#endif + p_j2k->m_output_image->comps[compno].data = NULL; + } + } + return OPJ_TRUE; +} + +OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k, + opj_stream_private_t * p_stream, + opj_image_t * p_image, + opj_event_mgr_t * p_manager) +{ + if (!p_image) { + return OPJ_FALSE; + } + + /* Heuristics to detect sequence opj_read_header(), opj_set_decoded_resolution_factor() */ + /* and finally opj_decode_image() without manual setting of comps[].factor */ + /* We could potentially always execute it, if we don't allow people to do */ + /* opj_read_header(), modify x0,y0,x1,y1 of returned image an call opj_decode_image() */ + if (p_j2k->m_cp.m_specific_param.m_dec.m_reduce > 0 && + p_j2k->m_private_image != NULL && + p_j2k->m_private_image->numcomps > 0 && + p_j2k->m_private_image->comps[0].factor == + p_j2k->m_cp.m_specific_param.m_dec.m_reduce && + p_image->numcomps > 0 && + p_image->comps[0].factor == 0 && + /* Don't mess with image dimension if the user has allocated it */ + p_image->comps[0].data == NULL) { + OPJ_UINT32 it_comp; + + /* Update the comps[].factor member of the output image with the one */ + /* of m_reduce */ + for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) { + p_image->comps[it_comp].factor = p_j2k->m_cp.m_specific_param.m_dec.m_reduce; + } + if (!opj_j2k_update_image_dimensions(p_image, p_manager)) { + return OPJ_FALSE; + } + } + + if (p_j2k->m_output_image == NULL) { + p_j2k->m_output_image = opj_image_create0(); + if (!(p_j2k->m_output_image)) { + return OPJ_FALSE; + } + } + opj_copy_image_header(p_image, p_j2k->m_output_image); + + /* customization of the decoding */ + if (!opj_j2k_setup_decoding(p_j2k, p_manager)) { + return OPJ_FALSE; + } + + /* Decode the codestream */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } + + /* Move data and copy one information from codec to output image*/ + return opj_j2k_move_data_from_codec_to_output_image(p_j2k, p_image); +} + +OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager, + OPJ_UINT32 tile_index) +{ + OPJ_UINT32 compno; + OPJ_UINT32 l_tile_x, l_tile_y; + opj_image_comp_t* l_img_comp; + + if (!p_image) { + opj_event_msg(p_manager, EVT_ERROR, "We need an image previously created.\n"); + return OPJ_FALSE; + } + + if (p_image->numcomps < p_j2k->m_private_image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, + "Image has less components than codestream.\n"); + return OPJ_FALSE; + } + + if (/*(tile_index < 0) &&*/ (tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th)) { + opj_event_msg(p_manager, EVT_ERROR, + "Tile index provided by the user is incorrect %d (max = %d) \n", tile_index, + (p_j2k->m_cp.tw * p_j2k->m_cp.th) - 1); + return OPJ_FALSE; + } + + /* Compute the dimension of the desired tile*/ + l_tile_x = tile_index % p_j2k->m_cp.tw; + l_tile_y = tile_index / p_j2k->m_cp.tw; + + p_image->x0 = l_tile_x * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0; + if (p_image->x0 < p_j2k->m_private_image->x0) { + p_image->x0 = p_j2k->m_private_image->x0; + } + p_image->x1 = (l_tile_x + 1) * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0; + if (p_image->x1 > p_j2k->m_private_image->x1) { + p_image->x1 = p_j2k->m_private_image->x1; + } + + p_image->y0 = l_tile_y * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0; + if (p_image->y0 < p_j2k->m_private_image->y0) { + p_image->y0 = p_j2k->m_private_image->y0; + } + p_image->y1 = (l_tile_y + 1) * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0; + if (p_image->y1 > p_j2k->m_private_image->y1) { + p_image->y1 = p_j2k->m_private_image->y1; + } + + l_img_comp = p_image->comps; + for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno) { + OPJ_INT32 l_comp_x1, l_comp_y1; + + l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor; + + l_img_comp->x0 = opj_uint_ceildiv(p_image->x0, l_img_comp->dx); + l_img_comp->y0 = opj_uint_ceildiv(p_image->y0, l_img_comp->dy); + l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx); + l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy); + + l_img_comp->w = (OPJ_UINT32)(opj_int_ceildivpow2(l_comp_x1, + (OPJ_INT32)l_img_comp->factor) - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, + (OPJ_INT32)l_img_comp->factor)); + l_img_comp->h = (OPJ_UINT32)(opj_int_ceildivpow2(l_comp_y1, + (OPJ_INT32)l_img_comp->factor) - opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, + (OPJ_INT32)l_img_comp->factor)); + + l_img_comp++; + } + + if (p_image->numcomps > p_j2k->m_private_image->numcomps) { + /* Can happen when calling repeatdly opj_get_decoded_tile() on an + * image with a color palette, where color palette expansion is done + * later in jp2.c */ + for (compno = p_j2k->m_private_image->numcomps; compno < p_image->numcomps; + ++compno) { + opj_image_data_free(p_image->comps[compno].data); + p_image->comps[compno].data = NULL; + } + p_image->numcomps = p_j2k->m_private_image->numcomps; + } + + /* Destroy the previous output image*/ + if (p_j2k->m_output_image) { + opj_image_destroy(p_j2k->m_output_image); + } + + /* Create the output image from the information previously computed*/ + p_j2k->m_output_image = opj_image_create0(); + if (!(p_j2k->m_output_image)) { + return OPJ_FALSE; + } + opj_copy_image_header(p_image, p_j2k->m_output_image); + + p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = (OPJ_INT32)tile_index; + + /* customization of the decoding */ + if (!opj_j2k_setup_decoding_tile(p_j2k, p_manager)) { + return OPJ_FALSE; + } + + /* Decode the codestream */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + opj_image_destroy(p_j2k->m_private_image); + p_j2k->m_private_image = NULL; + return OPJ_FALSE; + } + + /* Move data and copy one information from codec to output image*/ + return opj_j2k_move_data_from_codec_to_output_image(p_j2k, p_image); +} + +OPJ_BOOL opj_j2k_set_decoded_resolution_factor(opj_j2k_t *p_j2k, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 it_comp; + + p_j2k->m_cp.m_specific_param.m_dec.m_reduce = res_factor; + + if (p_j2k->m_private_image) { + if (p_j2k->m_private_image->comps) { + if (p_j2k->m_specific_param.m_decoder.m_default_tcp) { + if (p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps) { + for (it_comp = 0 ; it_comp < p_j2k->m_private_image->numcomps; it_comp++) { + OPJ_UINT32 max_res = + p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps[it_comp].numresolutions; + if (res_factor >= max_res) { + opj_event_msg(p_manager, EVT_ERROR, + "Resolution factor is greater than the maximum resolution in the component.\n"); + return OPJ_FALSE; + } + p_j2k->m_private_image->comps[it_comp].factor = res_factor; + } + return OPJ_TRUE; + } + } + } + } + + return OPJ_FALSE; +} + +/* ----------------------------------------------------------------------- */ + +OPJ_BOOL opj_j2k_encoder_set_extra_options( + opj_j2k_t *p_j2k, + const char* const* p_options, + opj_event_mgr_t * p_manager) +{ + const char* const* p_option_iter; + + if (p_options == NULL) { + return OPJ_TRUE; + } + + for (p_option_iter = p_options; *p_option_iter != NULL; ++p_option_iter) { + if (strncmp(*p_option_iter, "PLT=", 4) == 0) { + if (strcmp(*p_option_iter, "PLT=YES") == 0) { + p_j2k->m_specific_param.m_encoder.m_PLT = OPJ_TRUE; + } else if (strcmp(*p_option_iter, "PLT=NO") == 0) { + p_j2k->m_specific_param.m_encoder.m_PLT = OPJ_FALSE; + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for option: %s.\n", *p_option_iter); + return OPJ_FALSE; + } + } else if (strncmp(*p_option_iter, "TLM=", 4) == 0) { + if (strcmp(*p_option_iter, "TLM=YES") == 0) { + p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE; + } else if (strcmp(*p_option_iter, "TLM=NO") == 0) { + p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_FALSE; + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for option: %s.\n", *p_option_iter); + return OPJ_FALSE; + } + } else if (strncmp(*p_option_iter, "GUARD_BITS=", strlen("GUARD_BITS=")) == 0) { + OPJ_UINT32 tileno; + opj_cp_t *cp = cp = &(p_j2k->m_cp); + + int numgbits = atoi(*p_option_iter + strlen("GUARD_BITS=")); + if (numgbits < 0 || numgbits > 7) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for option: %s. Should be in [0,7]\n", *p_option_iter); + return OPJ_FALSE; + } + + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + OPJ_UINT32 i; + opj_tcp_t *tcp = &cp->tcps[tileno]; + for (i = 0; i < p_j2k->m_specific_param.m_encoder.m_nb_comps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + tccp->numgbits = (OPJ_UINT32)numgbits; + } + } + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid option: %s.\n", *p_option_iter); + return OPJ_FALSE; + } + } + + return OPJ_TRUE; +} + +/* ----------------------------------------------------------------------- */ + +OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i, j; + OPJ_UINT32 l_nb_tiles; + OPJ_SIZE_T l_max_tile_size = 0, l_current_tile_size; + OPJ_BYTE * l_current_data = 00; + OPJ_BOOL l_reuse_data = OPJ_FALSE; + opj_tcd_t* p_tcd = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + p_tcd = p_j2k->m_tcd; + + l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; + if (l_nb_tiles == 1) { + l_reuse_data = OPJ_TRUE; +#ifdef __SSE__ + for (j = 0; j < p_j2k->m_tcd->image->numcomps; ++j) { + opj_image_comp_t * l_img_comp = p_tcd->image->comps + j; + if (((size_t)l_img_comp->data & 0xFU) != + 0U) { /* tile data shall be aligned on 16 bytes */ + l_reuse_data = OPJ_FALSE; + } + } +#endif + } + for (i = 0; i < l_nb_tiles; ++i) { + if (! opj_j2k_pre_write_tile(p_j2k, i, p_stream, p_manager)) { + if (l_current_data) { + opj_free(l_current_data); + } + return OPJ_FALSE; + } + + /* if we only have one tile, then simply set tile component data equal to image component data */ + /* otherwise, allocate the data */ + for (j = 0; j < p_j2k->m_tcd->image->numcomps; ++j) { + opj_tcd_tilecomp_t* l_tilec = p_tcd->tcd_image->tiles->comps + j; + if (l_reuse_data) { + opj_image_comp_t * l_img_comp = p_tcd->image->comps + j; + l_tilec->data = l_img_comp->data; + l_tilec->ownsData = OPJ_FALSE; + } else { + if (! opj_alloc_tile_component_data(l_tilec)) { + opj_event_msg(p_manager, EVT_ERROR, "Error allocating tile component data."); + if (l_current_data) { + opj_free(l_current_data); + } + return OPJ_FALSE; + } + } + } + l_current_tile_size = opj_tcd_get_encoder_input_buffer_size(p_j2k->m_tcd); + if (!l_reuse_data) { + if (l_current_tile_size > l_max_tile_size) { + OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(l_current_data, + l_current_tile_size); + if (! l_new_current_data) { + if (l_current_data) { + opj_free(l_current_data); + } + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to encode all tiles\n"); + return OPJ_FALSE; + } + l_current_data = l_new_current_data; + l_max_tile_size = l_current_tile_size; + } + if (l_current_data == NULL) { + /* Should not happen in practice, but will avoid Coverity to */ + /* complain about a null pointer dereference */ + assert(0); + return OPJ_FALSE; + } + + /* copy image data (32 bit) to l_current_data as contiguous, all-component, zero offset buffer */ + /* 32 bit components @ 8 bit precision get converted to 8 bit */ + /* 32 bit components @ 16 bit precision get converted to 16 bit */ + opj_j2k_get_tile_data(p_j2k->m_tcd, l_current_data); + + /* now copy this data into the tile component */ + if (! opj_tcd_copy_tile_data(p_j2k->m_tcd, l_current_data, + l_current_tile_size)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size mismatch between tile data and sent data."); + opj_free(l_current_data); + return OPJ_FALSE; + } + } + + if (! opj_j2k_post_write_tile(p_j2k, p_stream, p_manager)) { + if (l_current_data) { + opj_free(l_current_data); + } + return OPJ_FALSE; + } + } + + if (l_current_data) { + opj_free(l_current_data); + } + return OPJ_TRUE; +} + +OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + /* customization of the encoding */ + if (! opj_j2k_setup_end_compress(p_j2k, p_manager)) { + return OPJ_FALSE; + } + + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_image_t * p_image, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + p_j2k->m_private_image = opj_image_create0(); + if (! p_j2k->m_private_image) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to allocate image header."); + return OPJ_FALSE; + } + opj_copy_image_header(p_image, p_j2k->m_private_image); + + /* TODO_MSD: Find a better way */ + if (p_image->comps) { + OPJ_UINT32 it_comp; + for (it_comp = 0 ; it_comp < p_image->numcomps; it_comp++) { + if (p_image->comps[it_comp].data) { + p_j2k->m_private_image->comps[it_comp].data = p_image->comps[it_comp].data; + p_image->comps[it_comp].data = NULL; + + } + } + } + + /* customization of the validation */ + if (! opj_j2k_setup_encoding_validation(p_j2k, p_manager)) { + return OPJ_FALSE; + } + + /* validation of the parameters codec */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_validation_list, p_stream, p_manager)) { + return OPJ_FALSE; + } + + /* customization of the encoding */ + if (! opj_j2k_setup_header_writing(p_j2k, p_manager)) { + return OPJ_FALSE; + } + + /* write header */ + if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_pre_write_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + (void)p_stream; + if (p_tile_index != p_j2k->m_current_tile_number) { + opj_event_msg(p_manager, EVT_ERROR, "The given tile index does not match."); + return OPJ_FALSE; + } + + opj_event_msg(p_manager, EVT_INFO, "tile number %d / %d\n", + p_j2k->m_current_tile_number + 1, p_j2k->m_cp.tw * p_j2k->m_cp.th); + + p_j2k->m_specific_param.m_encoder.m_current_tile_part_number = 0; + p_j2k->m_tcd->cur_totnum_tp = p_j2k->m_cp.tcps[p_tile_index].m_nb_tile_parts; + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0; + + /* initialisation before tile encoding */ + if (! opj_tcd_init_encode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number, + p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static void opj_get_tile_dimensions(opj_image_t * l_image, + opj_tcd_tilecomp_t * l_tilec, + opj_image_comp_t * l_img_comp, + OPJ_UINT32* l_size_comp, + OPJ_UINT32* l_width, + OPJ_UINT32* l_height, + OPJ_UINT32* l_offset_x, + OPJ_UINT32* l_offset_y, + OPJ_UINT32* l_image_width, + OPJ_UINT32* l_stride, + OPJ_UINT32* l_tile_offset) +{ + OPJ_UINT32 l_remaining; + *l_size_comp = l_img_comp->prec >> 3; /* (/8) */ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + if (l_remaining) { + *l_size_comp += 1; + } + + if (*l_size_comp == 3) { + *l_size_comp = 4; + } + + *l_width = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0); + *l_height = (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0); + *l_offset_x = opj_uint_ceildiv(l_image->x0, l_img_comp->dx); + *l_offset_y = opj_uint_ceildiv(l_image->y0, l_img_comp->dy); + *l_image_width = opj_uint_ceildiv(l_image->x1 - l_image->x0, l_img_comp->dx); + *l_stride = *l_image_width - *l_width; + *l_tile_offset = ((OPJ_UINT32)l_tilec->x0 - *l_offset_x) + (( + OPJ_UINT32)l_tilec->y0 - *l_offset_y) * *l_image_width; +} + +static void opj_j2k_get_tile_data(opj_tcd_t * p_tcd, OPJ_BYTE * p_data) +{ + OPJ_UINT32 i, j, k = 0; + + for (i = 0; i < p_tcd->image->numcomps; ++i) { + opj_image_t * l_image = p_tcd->image; + OPJ_INT32 * l_src_ptr; + opj_tcd_tilecomp_t * l_tilec = p_tcd->tcd_image->tiles->comps + i; + opj_image_comp_t * l_img_comp = l_image->comps + i; + OPJ_UINT32 l_size_comp, l_width, l_height, l_offset_x, l_offset_y, + l_image_width, l_stride, l_tile_offset; + + opj_get_tile_dimensions(l_image, + l_tilec, + l_img_comp, + &l_size_comp, + &l_width, + &l_height, + &l_offset_x, + &l_offset_y, + &l_image_width, + &l_stride, + &l_tile_offset); + + l_src_ptr = l_img_comp->data + l_tile_offset; + + switch (l_size_comp) { + case 1: { + OPJ_CHAR * l_dest_ptr = (OPJ_CHAR*) p_data; + if (l_img_comp->sgnd) { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr) = (OPJ_CHAR)(*l_src_ptr); + ++l_dest_ptr; + ++l_src_ptr; + } + l_src_ptr += l_stride; + } + } else { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr) = (OPJ_CHAR)((*l_src_ptr) & 0xff); + ++l_dest_ptr; + ++l_src_ptr; + } + l_src_ptr += l_stride; + } + } + + p_data = (OPJ_BYTE*) l_dest_ptr; + } + break; + case 2: { + OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_data; + if (l_img_comp->sgnd) { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = (OPJ_INT16)(*(l_src_ptr++)); + } + l_src_ptr += l_stride; + } + } else { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = (OPJ_INT16)((*(l_src_ptr++)) & 0xffff); + } + l_src_ptr += l_stride; + } + } + + p_data = (OPJ_BYTE*) l_dest_ptr; + } + break; + case 4: { + OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_data; + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = *(l_src_ptr++); + } + l_src_ptr += l_stride; + } + + p_data = (OPJ_BYTE*) l_dest_ptr; + } + break; + } + } +} + +static OPJ_BOOL opj_j2k_post_write_tile(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 l_nb_bytes_written; + OPJ_BYTE * l_current_data = 00; + OPJ_UINT32 l_tile_size = 0; + OPJ_UINT32 l_available_data; + + /* preconditions */ + assert(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); + + l_tile_size = p_j2k->m_specific_param.m_encoder.m_encoded_tile_size; + l_available_data = l_tile_size; + l_current_data = p_j2k->m_specific_param.m_encoder.m_encoded_tile_data; + + l_nb_bytes_written = 0; + if (! opj_j2k_write_first_tile_part(p_j2k, l_current_data, &l_nb_bytes_written, + l_available_data, p_stream, p_manager)) { + return OPJ_FALSE; + } + l_current_data += l_nb_bytes_written; + l_available_data -= l_nb_bytes_written; + + l_nb_bytes_written = 0; + if (! opj_j2k_write_all_tile_parts(p_j2k, l_current_data, &l_nb_bytes_written, + l_available_data, p_stream, p_manager)) { + return OPJ_FALSE; + } + + l_available_data -= l_nb_bytes_written; + l_nb_bytes_written = l_tile_size - l_available_data; + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data, + l_nb_bytes_written, p_manager) != l_nb_bytes_written) { + return OPJ_FALSE; + } + + ++p_j2k->m_current_tile_number; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_setup_end_compress(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + + /* DEVELOPER CORNER, insert your custom procedures */ + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_eoc, p_manager)) { + return OPJ_FALSE; + } + + if (p_j2k->m_specific_param.m_encoder.m_TLM) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_updated_tlm, p_manager)) { + return OPJ_FALSE; + } + } + + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_epc, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_end_encoding, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_destroy_header_memory, p_manager)) { + return OPJ_FALSE; + } + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_setup_encoding_validation(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_build_encoder, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_encoding_validation, p_manager)) { + return OPJ_FALSE; + } + + /* DEVELOPER CORNER, add your custom validation procedure */ + if (! opj_procedure_list_add_procedure(p_j2k->m_validation_list, + (opj_procedure)opj_j2k_mct_validation, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_setup_header_writing(opj_j2k_t *p_j2k, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_init_info, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_soc, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_siz, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_cod, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_qcd, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_all_coc, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_all_qcc, p_manager)) { + return OPJ_FALSE; + } + + if (p_j2k->m_specific_param.m_encoder.m_TLM) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_tlm, p_manager)) { + return OPJ_FALSE; + } + + if (p_j2k->m_cp.rsiz == OPJ_PROFILE_CINEMA_4K) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_poc, p_manager)) { + return OPJ_FALSE; + } + } + } + + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_regions, p_manager)) { + return OPJ_FALSE; + } + + if (p_j2k->m_cp.comment != 00) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_com, p_manager)) { + return OPJ_FALSE; + } + } + + /* DEVELOPER CORNER, insert your custom procedures */ + if ((p_j2k->m_cp.rsiz & (OPJ_PROFILE_PART2 | OPJ_EXTENSION_MCT)) == + (OPJ_PROFILE_PART2 | OPJ_EXTENSION_MCT)) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_write_mct_data_group, p_manager)) { + return OPJ_FALSE; + } + } + /* End of Developer Corner */ + + if (p_j2k->cstr_index) { + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_get_end_header, p_manager)) { + return OPJ_FALSE; + } + } + + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_create_tcd, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list, + (opj_procedure)opj_j2k_update_rates, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_first_tile_part(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 l_nb_bytes_written = 0; + OPJ_UINT32 l_current_nb_bytes_written; + OPJ_BYTE * l_begin_data = 00; + + opj_tcd_t * l_tcd = 00; + opj_cp_t * l_cp = 00; + + l_tcd = p_j2k->m_tcd; + l_cp = &(p_j2k->m_cp); + + l_tcd->cur_pino = 0; + + /*Get number of tile parts*/ + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = 0; + + /* INDEX >> */ + /* << INDEX */ + + l_current_nb_bytes_written = 0; + l_begin_data = p_data; + if (! opj_j2k_write_sot(p_j2k, p_data, total_data_size, + &l_current_nb_bytes_written, p_stream, + p_manager)) { + return OPJ_FALSE; + } + + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + total_data_size -= l_current_nb_bytes_written; + + if (!OPJ_IS_CINEMA(l_cp->rsiz)) { +#if 0 + for (compno = 1; compno < p_j2k->m_private_image->numcomps; compno++) { + l_current_nb_bytes_written = 0; + opj_j2k_write_coc_in_memory(p_j2k, compno, p_data, &l_current_nb_bytes_written, + p_manager); + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + total_data_size -= l_current_nb_bytes_written; + + l_current_nb_bytes_written = 0; + opj_j2k_write_qcc_in_memory(p_j2k, compno, p_data, &l_current_nb_bytes_written, + p_manager); + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + total_data_size -= l_current_nb_bytes_written; + } +#endif + if (l_cp->tcps[p_j2k->m_current_tile_number].POC) { + l_current_nb_bytes_written = 0; + opj_j2k_write_poc_in_memory(p_j2k, p_data, &l_current_nb_bytes_written, + p_manager); + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + total_data_size -= l_current_nb_bytes_written; + } + } + + l_current_nb_bytes_written = 0; + if (! opj_j2k_write_sod(p_j2k, l_tcd, p_data, &l_current_nb_bytes_written, + total_data_size, p_stream, p_manager)) { + return OPJ_FALSE; + } + + l_nb_bytes_written += l_current_nb_bytes_written; + * p_data_written = l_nb_bytes_written; + + /* Writing Psot in SOT marker */ + opj_write_bytes(l_begin_data + 6, l_nb_bytes_written, + 4); /* PSOT */ + + if (p_j2k->m_specific_param.m_encoder.m_TLM) { + opj_j2k_update_tlm(p_j2k, l_nb_bytes_written); + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 total_data_size, + opj_stream_private_t *p_stream, + struct opj_event_mgr * p_manager + ) +{ + OPJ_UINT32 tilepartno = 0; + OPJ_UINT32 l_nb_bytes_written = 0; + OPJ_UINT32 l_current_nb_bytes_written; + OPJ_UINT32 l_part_tile_size; + OPJ_UINT32 tot_num_tp; + OPJ_UINT32 pino; + + OPJ_BYTE * l_begin_data; + opj_tcp_t *l_tcp = 00; + opj_tcd_t * l_tcd = 00; + opj_cp_t * l_cp = 00; + + l_tcd = p_j2k->m_tcd; + l_cp = &(p_j2k->m_cp); + l_tcp = l_cp->tcps + p_j2k->m_current_tile_number; + + /*Get number of tile parts*/ + tot_num_tp = opj_j2k_get_num_tp(l_cp, 0, p_j2k->m_current_tile_number); + + /* start writing remaining tile parts */ + ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + for (tilepartno = 1; tilepartno < tot_num_tp ; ++tilepartno) { + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno; + l_current_nb_bytes_written = 0; + l_part_tile_size = 0; + l_begin_data = p_data; + + if (! opj_j2k_write_sot(p_j2k, p_data, + total_data_size, + &l_current_nb_bytes_written, + p_stream, + p_manager)) { + return OPJ_FALSE; + } + + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; + + l_current_nb_bytes_written = 0; + if (! opj_j2k_write_sod(p_j2k, l_tcd, p_data, &l_current_nb_bytes_written, + total_data_size, p_stream, p_manager)) { + return OPJ_FALSE; + } + + p_data += l_current_nb_bytes_written; + l_nb_bytes_written += l_current_nb_bytes_written; + total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; + + /* Writing Psot in SOT marker */ + opj_write_bytes(l_begin_data + 6, l_part_tile_size, + 4); /* PSOT */ + + if (p_j2k->m_specific_param.m_encoder.m_TLM) { + opj_j2k_update_tlm(p_j2k, l_part_tile_size); + } + + ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + } + + for (pino = 1; pino <= l_tcp->numpocs; ++pino) { + l_tcd->cur_pino = pino; + + /*Get number of tile parts*/ + tot_num_tp = opj_j2k_get_num_tp(l_cp, pino, p_j2k->m_current_tile_number); + for (tilepartno = 0; tilepartno < tot_num_tp ; ++tilepartno) { + p_j2k->m_specific_param.m_encoder.m_current_poc_tile_part_number = tilepartno; + l_current_nb_bytes_written = 0; + l_part_tile_size = 0; + l_begin_data = p_data; + + if (! opj_j2k_write_sot(p_j2k, p_data, + total_data_size, + &l_current_nb_bytes_written, p_stream, + p_manager)) { + return OPJ_FALSE; + } + + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; + + l_current_nb_bytes_written = 0; + + if (! opj_j2k_write_sod(p_j2k, l_tcd, p_data, &l_current_nb_bytes_written, + total_data_size, p_stream, p_manager)) { + return OPJ_FALSE; + } + + l_nb_bytes_written += l_current_nb_bytes_written; + p_data += l_current_nb_bytes_written; + total_data_size -= l_current_nb_bytes_written; + l_part_tile_size += l_current_nb_bytes_written; + + /* Writing Psot in SOT marker */ + opj_write_bytes(l_begin_data + 6, l_part_tile_size, + 4); /* PSOT */ + + if (p_j2k->m_specific_param.m_encoder.m_TLM) { + opj_j2k_update_tlm(p_j2k, l_part_tile_size); + } + + ++p_j2k->m_specific_param.m_encoder.m_current_tile_part_number; + } + } + + *p_data_written = l_nb_bytes_written; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_write_updated_tlm(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + OPJ_UINT32 l_tlm_size; + OPJ_OFF_T l_tlm_position, l_current_position; + OPJ_UINT32 size_per_tile_part; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + size_per_tile_part = p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte ? 5 : 6; + l_tlm_size = size_per_tile_part * + p_j2k->m_specific_param.m_encoder.m_total_tile_parts; + l_tlm_position = 6 + p_j2k->m_specific_param.m_encoder.m_tlm_start; + l_current_position = opj_stream_tell(p_stream); + + if (! opj_stream_seek(p_stream, l_tlm_position, p_manager)) { + return OPJ_FALSE; + } + + if (opj_stream_write_data(p_stream, + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer, l_tlm_size, + p_manager) != l_tlm_size) { + return OPJ_FALSE; + } + + if (! opj_stream_seek(p_stream, l_current_position, p_manager)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_end_encoding(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + OPJ_UNUSED(p_stream); + OPJ_UNUSED(p_manager); + + opj_tcd_destroy(p_j2k->m_tcd); + p_j2k->m_tcd = 00; + + if (p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) { + opj_free(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer); + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = 0; + p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current = 0; + } + + if (p_j2k->m_specific_param.m_encoder.m_encoded_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); + p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = 0; + } + + p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = 0; + + return OPJ_TRUE; +} + +/** + * Destroys the memory associated with the decoding of headers. + */ +static OPJ_BOOL opj_j2k_destroy_header_memory(opj_j2k_t * p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_stream); + OPJ_UNUSED(p_manager); + + if (p_j2k->m_specific_param.m_encoder.m_header_tile_data) { + opj_free(p_j2k->m_specific_param.m_encoder.m_header_tile_data); + p_j2k->m_specific_param.m_encoder.m_header_tile_data = 0; + } + + p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_j2k_init_info(opj_j2k_t *p_j2k, + struct opj_stream_private *p_stream, + struct opj_event_mgr * p_manager) +{ + opj_codestream_info_t * l_cstr_info = 00; + + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + (void)l_cstr_info; + + OPJ_UNUSED(p_stream); + + /* TODO mergeV2: check this part which use cstr_info */ + /*l_cstr_info = p_j2k->cstr_info; + + if (l_cstr_info) { + OPJ_UINT32 compno; + l_cstr_info->tile = (opj_tile_info_t *) opj_malloc(p_j2k->m_cp.tw * p_j2k->m_cp.th * sizeof(opj_tile_info_t)); + + l_cstr_info->image_w = p_j2k->m_image->x1 - p_j2k->m_image->x0; + l_cstr_info->image_h = p_j2k->m_image->y1 - p_j2k->m_image->y0; + + l_cstr_info->prog = (&p_j2k->m_cp.tcps[0])->prg; + + l_cstr_info->tw = p_j2k->m_cp.tw; + l_cstr_info->th = p_j2k->m_cp.th; + + l_cstr_info->tile_x = p_j2k->m_cp.tdx;*/ /* new version parser */ + /*l_cstr_info->tile_y = p_j2k->m_cp.tdy;*/ /* new version parser */ + /*l_cstr_info->tile_Ox = p_j2k->m_cp.tx0;*/ /* new version parser */ + /*l_cstr_info->tile_Oy = p_j2k->m_cp.ty0;*/ /* new version parser */ + + /*l_cstr_info->numcomps = p_j2k->m_image->numcomps; + + l_cstr_info->numlayers = (&p_j2k->m_cp.tcps[0])->numlayers; + + l_cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(p_j2k->m_image->numcomps * sizeof(OPJ_INT32)); + + for (compno=0; compno < p_j2k->m_image->numcomps; compno++) { + l_cstr_info->numdecompos[compno] = (&p_j2k->m_cp.tcps[0])->tccps->numresolutions - 1; + } + + l_cstr_info->D_max = 0.0; */ /* ADD Marcela */ + + /*l_cstr_info->main_head_start = opj_stream_tell(p_stream);*/ /* position of SOC */ + + /*l_cstr_info->maxmarknum = 100; + l_cstr_info->marker = (opj_marker_info_t *) opj_malloc(l_cstr_info->maxmarknum * sizeof(opj_marker_info_t)); + l_cstr_info->marknum = 0; + }*/ + + return opj_j2k_calculate_tp(p_j2k, &(p_j2k->m_cp), + &p_j2k->m_specific_param.m_encoder.m_total_tile_parts, p_j2k->m_private_image, + p_manager); +} + +/** + * Creates a tile-coder encoder. + * + * @param p_stream the stream to write data to. + * @param p_j2k J2K codec. + * @param p_manager the user event manager. +*/ +static OPJ_BOOL opj_j2k_create_tcd(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(p_j2k != 00); + assert(p_manager != 00); + assert(p_stream != 00); + + OPJ_UNUSED(p_stream); + + p_j2k->m_tcd = opj_tcd_create(OPJ_FALSE); + + if (! p_j2k->m_tcd) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to create Tile Coder\n"); + return OPJ_FALSE; + } + + if (!opj_tcd_init(p_j2k->m_tcd, p_j2k->m_private_image, &p_j2k->m_cp, + p_j2k->m_tp)) { + opj_tcd_destroy(p_j2k->m_tcd); + p_j2k->m_tcd = 00; + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager) +{ + if (! opj_j2k_pre_write_tile(p_j2k, p_tile_index, p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error while opj_j2k_pre_write_tile with tile index = %d\n", p_tile_index); + return OPJ_FALSE; + } else { + OPJ_UINT32 j; + /* Allocate data */ + for (j = 0; j < p_j2k->m_tcd->image->numcomps; ++j) { + opj_tcd_tilecomp_t* l_tilec = p_j2k->m_tcd->tcd_image->tiles->comps + j; + + if (! opj_alloc_tile_component_data(l_tilec)) { + opj_event_msg(p_manager, EVT_ERROR, "Error allocating tile component data."); + return OPJ_FALSE; + } + } + + /* now copy data into the tile component */ + if (! opj_tcd_copy_tile_data(p_j2k->m_tcd, p_data, p_data_size)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size mismatch between tile data and sent data."); + return OPJ_FALSE; + } + if (! opj_j2k_post_write_tile(p_j2k, p_stream, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Error while opj_j2k_post_write_tile with tile index = %d\n", p_tile_index); + return OPJ_FALSE; + } + } + + return OPJ_TRUE; +} diff --git a/client/deps/openjpeg/j2k.h b/client/deps/openjpeg/j2k.h new file mode 100644 index 000000000..bcf70a419 --- /dev/null +++ b/client/deps/openjpeg/j2k.h @@ -0,0 +1,954 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France + * Copyright (c) 2012, CS Systemes d'Information, France + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_J2K_H +#define OPJ_J2K_H +/** +@file j2k.h +@brief The JPEG-2000 Codestream Reader/Writer (J2K) + +The functions in J2K.C have for goal to read/write the several parts of the codestream: markers and data. +*/ + +/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ +/*@{*/ + +#define J2K_CP_CSTY_PRT 0x01 +#define J2K_CP_CSTY_SOP 0x02 +#define J2K_CP_CSTY_EPH 0x04 +#define J2K_CCP_CSTY_PRT 0x01 +#define J2K_CCP_CBLKSTY_LAZY 0x01 /**< Selective arithmetic coding bypass */ +#define J2K_CCP_CBLKSTY_RESET 0x02 /**< Reset context probabilities on coding pass boundaries */ +#define J2K_CCP_CBLKSTY_TERMALL 0x04 /**< Termination on each coding pass */ +#define J2K_CCP_CBLKSTY_VSC 0x08 /**< Vertically stripe causal context */ +#define J2K_CCP_CBLKSTY_PTERM 0x10 /**< Predictable termination */ +#define J2K_CCP_CBLKSTY_SEGSYM 0x20 /**< Segmentation symbols are used */ +#define J2K_CCP_CBLKSTY_HT 0x40 /**< (high throughput) HT codeblocks */ +#define J2K_CCP_CBLKSTY_HTMIXED 0x80 /**< MIXED mode HT codeblocks */ +#define J2K_CCP_QNTSTY_NOQNT 0 +#define J2K_CCP_QNTSTY_SIQNT 1 +#define J2K_CCP_QNTSTY_SEQNT 2 + +/* ----------------------------------------------------------------------- */ + +#define J2K_MS_SOC 0xff4f /**< SOC marker value */ +#define J2K_MS_SOT 0xff90 /**< SOT marker value */ +#define J2K_MS_SOD 0xff93 /**< SOD marker value */ +#define J2K_MS_EOC 0xffd9 /**< EOC marker value */ +#define J2K_MS_CAP 0xff50 /**< CAP marker value */ +#define J2K_MS_SIZ 0xff51 /**< SIZ marker value */ +#define J2K_MS_COD 0xff52 /**< COD marker value */ +#define J2K_MS_COC 0xff53 /**< COC marker value */ +#define J2K_MS_CPF 0xff59 /**< CPF marker value */ +#define J2K_MS_RGN 0xff5e /**< RGN marker value */ +#define J2K_MS_QCD 0xff5c /**< QCD marker value */ +#define J2K_MS_QCC 0xff5d /**< QCC marker value */ +#define J2K_MS_POC 0xff5f /**< POC marker value */ +#define J2K_MS_TLM 0xff55 /**< TLM marker value */ +#define J2K_MS_PLM 0xff57 /**< PLM marker value */ +#define J2K_MS_PLT 0xff58 /**< PLT marker value */ +#define J2K_MS_PPM 0xff60 /**< PPM marker value */ +#define J2K_MS_PPT 0xff61 /**< PPT marker value */ +#define J2K_MS_SOP 0xff91 /**< SOP marker value */ +#define J2K_MS_EPH 0xff92 /**< EPH marker value */ +#define J2K_MS_CRG 0xff63 /**< CRG marker value */ +#define J2K_MS_COM 0xff64 /**< COM marker value */ +#define J2K_MS_CBD 0xff78 /**< CBD marker value */ +#define J2K_MS_MCC 0xff75 /**< MCC marker value */ +#define J2K_MS_MCT 0xff74 /**< MCT marker value */ +#define J2K_MS_MCO 0xff77 /**< MCO marker value */ + +#define J2K_MS_UNK 0 /**< UNKNOWN marker value */ + +/* UniPG>> */ +#ifdef USE_JPWL +#define J2K_MS_EPC 0xff68 /**< EPC marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_EPB 0xff66 /**< EPB marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_ESD 0xff67 /**< ESD marker value (Part 11: JPEG 2000 for Wireless) */ +#define J2K_MS_RED 0xff69 /**< RED marker value (Part 11: JPEG 2000 for Wireless) */ +#endif /* USE_JPWL */ +#ifdef USE_JPSEC +#define J2K_MS_SEC 0xff65 /**< SEC marker value (Part 8: Secure JPEG 2000) */ +#define J2K_MS_INSEC 0xff94 /**< INSEC marker value (Part 8: Secure JPEG 2000) */ +#endif /* USE_JPSEC */ +/* < Zppx not read yet */ + OPJ_UINT32 m_data_size; +} opj_ppx; + +/** +Tile coding parameters : +this structure is used to store coding/decoding parameters common to all +tiles (information like COD, COC in main header) +*/ +typedef struct opj_tcp { + /** coding style */ + OPJ_UINT32 csty; + /** progression order */ + OPJ_PROG_ORDER prg; + /** number of layers */ + OPJ_UINT32 numlayers; + OPJ_UINT32 num_layers_to_decode; + /** multi-component transform identifier */ + OPJ_UINT32 mct; + /** rates of layers */ + OPJ_FLOAT32 rates[100]; + /** number of progression order changes */ + OPJ_UINT32 numpocs; + /** progression order changes */ + opj_poc_t pocs[J2K_MAX_POCS]; + + /** number of ppt markers (reserved size) */ + OPJ_UINT32 ppt_markers_count; + /** ppt markers data (table indexed by Zppt) */ + opj_ppx* ppt_markers; + + /** packet header store there for future use in t2_decode_packet */ + OPJ_BYTE *ppt_data; + /** used to keep a track of the allocated memory */ + OPJ_BYTE *ppt_buffer; + /** Number of bytes stored inside ppt_data*/ + OPJ_UINT32 ppt_data_size; + /** size of ppt_data*/ + OPJ_UINT32 ppt_len; + /** PSNR values */ + OPJ_FLOAT32 distoratio[100]; + /** tile-component coding parameters */ + opj_tccp_t *tccps; + /** current tile part number or -1 if first time into this tile */ + OPJ_INT32 m_current_tile_part_number; + /** number of tile parts for the tile. */ + OPJ_UINT32 m_nb_tile_parts; + /** data for the tile */ + OPJ_BYTE * m_data; + /** size of data */ + OPJ_UINT32 m_data_size; + /** encoding norms */ + OPJ_FLOAT64 * mct_norms; + /** the mct decoding matrix */ + OPJ_FLOAT32 * m_mct_decoding_matrix; + /** the mct coding matrix */ + OPJ_FLOAT32 * m_mct_coding_matrix; + /** mct records */ + opj_mct_data_t * m_mct_records; + /** the number of mct records. */ + OPJ_UINT32 m_nb_mct_records; + /** the max number of mct records. */ + OPJ_UINT32 m_nb_max_mct_records; + /** mcc records */ + opj_simple_mcc_decorrelation_data_t * m_mcc_records; + /** the number of mct records. */ + OPJ_UINT32 m_nb_mcc_records; + /** the max number of mct records. */ + OPJ_UINT32 m_nb_max_mcc_records; + + + /***** FLAGS *******/ + /** If cod == 1 --> there was a COD marker for the present tile */ + OPJ_BITFIELD cod : 1; + /** If ppt == 1 --> there was a PPT marker for the present tile */ + OPJ_BITFIELD ppt : 1; + /** indicates if a POC marker has been used O:NO, 1:YES */ + OPJ_BITFIELD POC : 1; +} opj_tcp_t; + + +/** +Rate allocation strategy +*/ +typedef enum { + RATE_DISTORTION_RATIO = 0, /** allocation by rate/distortion */ + FIXED_DISTORTION_RATIO = 1, /** allocation by fixed distortion ratio (PSNR) (fixed quality) */ + FIXED_LAYER = 2, /** allocation by fixed layer (number of passes per layer / resolution / subband) */ +} J2K_QUALITY_LAYER_ALLOCATION_STRATEGY; + + +typedef struct opj_encoding_param { + /** Maximum rate for each component. If == 0, component size limitation is not considered */ + OPJ_UINT32 m_max_comp_size; + /** Position of tile part flag in progression order*/ + OPJ_INT32 m_tp_pos; + /** fixed layer */ + OPJ_INT32 *m_matrice; + /** Flag determining tile part generation*/ + OPJ_BYTE m_tp_flag; + /** Quality layer allocation strategy */ + J2K_QUALITY_LAYER_ALLOCATION_STRATEGY m_quality_layer_alloc_strategy; + /** Enabling Tile part generation*/ + OPJ_BITFIELD m_tp_on : 1; +} +opj_encoding_param_t; + +typedef struct opj_decoding_param { + /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */ + OPJ_UINT32 m_reduce; + /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */ + OPJ_UINT32 m_layer; +} +opj_decoding_param_t; + + +/** + * Coding parameters + */ +typedef struct opj_cp { + /** Size of the image in bits*/ + /*int img_size;*/ + /** Rsiz*/ + OPJ_UINT16 rsiz; + /** XTOsiz */ + OPJ_UINT32 tx0; /* MSD see norm */ + /** YTOsiz */ + OPJ_UINT32 ty0; /* MSD see norm */ + /** XTsiz */ + OPJ_UINT32 tdx; + /** YTsiz */ + OPJ_UINT32 tdy; + /** comment */ + OPJ_CHAR *comment; + /** number of tiles in width */ + OPJ_UINT32 tw; + /** number of tiles in height */ + OPJ_UINT32 th; + + /** number of ppm markers (reserved size) */ + OPJ_UINT32 ppm_markers_count; + /** ppm markers data (table indexed by Zppm) */ + opj_ppx* ppm_markers; + + /** packet header store there for future use in t2_decode_packet */ + OPJ_BYTE *ppm_data; + /** size of the ppm_data*/ + OPJ_UINT32 ppm_len; + /** size of the ppm_data*/ + OPJ_UINT32 ppm_data_read; + + OPJ_BYTE *ppm_data_current; + + /** packet header storage original buffer */ + OPJ_BYTE *ppm_buffer; + /** pointer remaining on the first byte of the first header if ppm is used */ + OPJ_BYTE *ppm_data_first; + /** Number of bytes actually stored inside the ppm_data */ + OPJ_UINT32 ppm_data_size; + /** use in case of multiple marker PPM (number of info already store) */ + OPJ_INT32 ppm_store; + /** use in case of multiple marker PPM (case on non-finished previous info) */ + OPJ_INT32 ppm_previous; + + /** tile coding parameters */ + opj_tcp_t *tcps; + + union { + opj_decoding_param_t m_dec; + opj_encoding_param_t m_enc; + } + m_specific_param; + + /** OPJ_TRUE if entire bit stream must be decoded, OPJ_FALSE if partial bitstream decoding allowed */ + OPJ_BOOL strict; + + /* UniPG>> */ +#ifdef USE_JPWL + /** enables writing of EPC in MH, thus activating JPWL */ + OPJ_BOOL epc_on; + /** enables writing of EPB, in case of activated JPWL */ + OPJ_BOOL epb_on; + /** enables writing of ESD, in case of activated JPWL */ + OPJ_BOOL esd_on; + /** enables writing of informative techniques of ESD, in case of activated JPWL */ + OPJ_BOOL info_on; + /** enables writing of RED, in case of activated JPWL */ + OPJ_BOOL red_on; + /** error protection method for MH (0,1,16,32,37-128) */ + int hprot_MH; + /** tile number of header protection specification (>=0) */ + int hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** error protection methods for TPHs (0,1,16,32,37-128) */ + int hprot_TPH[JPWL_MAX_NO_TILESPECS]; + /** tile number of packet protection specification (>=0) */ + int pprot_tileno[JPWL_MAX_NO_PACKSPECS]; + /** packet number of packet protection specification (>=0) */ + int pprot_packno[JPWL_MAX_NO_PACKSPECS]; + /** error protection methods for packets (0,1,16,32,37-128) */ + int pprot[JPWL_MAX_NO_PACKSPECS]; + /** enables writing of ESD, (0/2/4 bytes) */ + int sens_size; + /** sensitivity addressing size (0=auto/2/4 bytes) */ + int sens_addr; + /** sensitivity range (0-3) */ + int sens_range; + /** sensitivity method for MH (-1,0-7) */ + int sens_MH; + /** tile number of sensitivity specification (>=0) */ + int sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** sensitivity methods for TPHs (-1,0-7) */ + int sens_TPH[JPWL_MAX_NO_TILESPECS]; + /** enables JPWL correction at the decoder */ + OPJ_BOOL correct; + /** expected number of components at the decoder */ + int exp_comps; + /** maximum number of tiles at the decoder */ + OPJ_UINT32 max_tiles; +#endif /* USE_JPWL */ + + /******** FLAGS *********/ + /** if ppm == 1 --> there was a PPM marker*/ + OPJ_BITFIELD ppm : 1; + /** tells if the parameter is a coding or decoding one */ + OPJ_BITFIELD m_is_decoder : 1; + /** whether different bit depth or sign per component is allowed. Decoder only for ow */ + OPJ_BITFIELD allow_different_bit_depth_sign : 1; + /* <cp. +@param j2k J2K decompressor handle +@param parameters decompression parameters +*/ +void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters); + +void opj_j2k_decoder_set_strict_mode(opj_j2k_t *j2k, OPJ_BOOL strict); + +OPJ_BOOL opj_j2k_set_threads(opj_j2k_t *j2k, OPJ_UINT32 num_threads); + +/** + * Creates a J2K compression structure + * + * @return Returns a handle to a J2K compressor if successful, returns NULL otherwise +*/ +opj_j2k_t* opj_j2k_create_compress(void); + + +OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k, + opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t * p_manager); + +/** +Converts an enum type progression order to string type +*/ +const char *opj_j2k_convert_progression_order(OPJ_PROG_ORDER prg_order); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +/** + * Ends the decompression procedures and possibiliy add data to be read after the + * codestream. + */ +OPJ_BOOL opj_j2k_end_decompress(opj_j2k_t *j2k, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a jpeg2000 codestream header structure. + * + * @param p_stream the stream to read data from. + * @param p_j2k the jpeg2000 codec. + * @param p_image FIXME DOC + * @param p_manager the user event manager. + * + * @return true if the box is valid. + */ +OPJ_BOOL opj_j2k_read_header(opj_stream_private_t *p_stream, + opj_j2k_t* p_j2k, + opj_image_t** p_image, + opj_event_mgr_t* p_manager); + + +/** + * Destroys a jpeg2000 codec. + * + * @param p_j2k the jpeg20000 structure to destroy. + */ +void opj_j2k_destroy(opj_j2k_t *p_j2k); + +/** + * Destroys a codestream index structure. + * + * @param p_cstr_ind the codestream index parameter to destroy. + */ +void j2k_destroy_cstr_index(opj_codestream_index_t *p_cstr_ind); + +/** + * Decode tile data. + * @param p_j2k the jpeg2000 codec. + * @param p_tile_index + * @param p_data FIXME DOC + * @param p_data_size FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a tile header. + * @param p_j2k the jpeg2000 codec. + * @param p_tile_index FIXME DOC + * @param p_data_size FIXME DOC + * @param p_tile_x0 FIXME DOC + * @param p_tile_y0 FIXME DOC + * @param p_tile_x1 FIXME DOC + * @param p_tile_y1 FIXME DOC + * @param p_nb_comps FIXME DOC + * @param p_go_on FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + + +/** Sets the indices of the components to decode. + * + * @param p_j2k the jpeg2000 codec. + * @param numcomps Number of components to decode. + * @param comps_indices Array of num_compts indices (numbering starting at 0) + * corresponding to the components to decode. + * @param p_manager Event manager + * + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_j2k_set_decoded_components(opj_j2k_t *p_j2k, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager); + +/** + * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. + * + * @param p_j2k the jpeg2000 codec. + * @param p_image FIXME DOC + * @param p_start_x the left position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * @param p_manager the user event manager + * + * @return true if the area could be set. + */ +OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + opj_event_mgr_t * p_manager); + +/** + * Creates a J2K decompression structure. + * + * @return a handle to a J2K decompressor if successful, NULL otherwise. + */ +opj_j2k_t* opj_j2k_create_decompress(void); + + +/** + * Dump some elements from the J2K decompression structure . + * + *@param p_j2k the jpeg2000 codec. + *@param flag flag to describe what elements are dump. + *@param out_stream output stream where dump the elements. + * +*/ +void j2k_dump(opj_j2k_t* p_j2k, OPJ_INT32 flag, FILE* out_stream); + + + +/** + * Dump an image header structure. + * + *@param image the image header to dump. + *@param dev_dump_flag flag to describe if we are in the case of this function is use outside j2k_dump function + *@param out_stream output stream where dump the elements. + */ +void j2k_dump_image_header(opj_image_t* image, OPJ_BOOL dev_dump_flag, + FILE* out_stream); + +/** + * Dump a component image header structure. + * + *@param comp the component image header to dump. + *@param dev_dump_flag flag to describe if we are in the case of this function is use outside j2k_dump function + *@param out_stream output stream where dump the elements. + */ +void j2k_dump_image_comp_header(opj_image_comp_t* comp, OPJ_BOOL dev_dump_flag, + FILE* out_stream); + +/** + * Get the codestream info from a JPEG2000 codec. + * + *@param p_j2k the component image header to dump. + * + *@return the codestream information extract from the jpg2000 codec + */ +opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k); + +/** + * Get the codestream index from a JPEG2000 codec. + * + *@param p_j2k the component image header to dump. + * + *@return the codestream index extract from the jpg2000 codec + */ +opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_t* p_j2k); + +/** + * Decode an image from a JPEG-2000 codestream + * @param j2k J2K decompressor handle + * @param p_stream FIXME DOC + * @param p_image FIXME DOC + * @param p_manager FIXME DOC + * @return FIXME DOC +*/ +OPJ_BOOL opj_j2k_decode(opj_j2k_t *j2k, + opj_stream_private_t *p_stream, + opj_image_t *p_image, + opj_event_mgr_t *p_manager); + + +OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager, + OPJ_UINT32 tile_index); + +OPJ_BOOL opj_j2k_set_decoded_resolution_factor(opj_j2k_t *p_j2k, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager); + +/** + * Specify extra options for the encoder. + * + * @param p_j2k the jpeg2000 codec. + * @param p_options options + * @param p_manager the user event manager + * + * @see opj_encoder_set_extra_options() for more details. + */ +OPJ_BOOL opj_j2k_encoder_set_extra_options( + opj_j2k_t *p_j2k, + const char* const* p_options, + opj_event_mgr_t * p_manager); + +/** + * Writes a tile. + * @param p_j2k the jpeg2000 codec. + * @param p_tile_index FIXME DOC + * @param p_data FIXME DOC + * @param p_data_size FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +OPJ_BOOL opj_j2k_write_tile(opj_j2k_t * p_j2k, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Encodes an image into a JPEG-2000 codestream + */ +OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/** + * Starts a compression scheme, i.e. validates the codec parameters, writes the header. + * + * @param p_j2k the jpeg2000 codec. + * @param p_stream the stream object. + * @param p_image FIXME DOC + * @param p_manager the user event manager. + * + * @return true if the codec is valid. + */ +OPJ_BOOL opj_j2k_start_compress(opj_j2k_t *p_j2k, + opj_stream_private_t *p_stream, + opj_image_t * p_image, + opj_event_mgr_t * p_manager); + +/** + * Ends the compression procedures and possibiliy add data to be read after the + * codestream. + */ +OPJ_BOOL opj_j2k_end_compress(opj_j2k_t *p_j2k, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +OPJ_BOOL opj_j2k_setup_mct_encoding(opj_tcp_t * p_tcp, opj_image_t * p_image); + + +#endif /* OPJ_J2K_H */ diff --git a/client/deps/openjpeg/jp2.c b/client/deps/openjpeg/jp2.c new file mode 100644 index 000000000..3d16d1075 --- /dev/null +++ b/client/deps/openjpeg/jp2.c @@ -0,0 +1,3424 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2010-2011, Kaori Hagihara + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#include "opj_includes.h" + +/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ +/*@{*/ + +#define OPJ_BOX_SIZE 1024 + +#define OPJ_UNUSED(x) (void)x + +/** @name Local static functions */ +/*@{*/ + +/*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/ + +/** + * Reads a IHDR box - Image Header box + * + * @param p_image_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_image_header_size the size of the image header + * @param p_manager the user event manager. + * + * @return true if the image header is valid, false else. + */ +static OPJ_BOOL opj_jp2_read_ihdr(opj_jp2_t *jp2, + OPJ_BYTE *p_image_header_data, + OPJ_UINT32 p_image_header_size, + opj_event_mgr_t * p_manager); + +/** + * Writes the Image Header box - Image Header box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. +*/ +static OPJ_BYTE * opj_jp2_write_ihdr(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written); + +/** + * Writes the Bit per Component box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. +*/ +static OPJ_BYTE * opj_jp2_write_bpcc(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written); + +/** + * Reads a Bit per Component box. + * + * @param p_bpc_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_bpc_header_size the size of the bpc header + * @param p_manager the user event manager. + * + * @return true if the bpc header is valid, false else. + */ +static OPJ_BOOL opj_jp2_read_bpcc(opj_jp2_t *jp2, + OPJ_BYTE * p_bpc_header_data, + OPJ_UINT32 p_bpc_header_size, + opj_event_mgr_t * p_manager); + +static OPJ_BOOL opj_jp2_read_cdef(opj_jp2_t * jp2, + OPJ_BYTE * p_cdef_header_data, + OPJ_UINT32 p_cdef_header_size, + opj_event_mgr_t * p_manager); + +static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color, + opj_event_mgr_t *); + +/** + * Writes the Channel Definition box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. + */ +static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written); + +/** + * Writes the Colour Specification box. + * + * @param jp2 jpeg2000 file codec. + * @param p_nb_bytes_written pointer to store the nb of bytes written by the function. + * + * @return the data being copied. +*/ +static OPJ_BYTE * opj_jp2_write_colr(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written); + +/** + * Writes a FTYP box - File type box + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager the user event manager. + * + * @return true if writing was successful. + */ +static OPJ_BOOL opj_jp2_write_ftyp(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/** + * Reads a a FTYP box - File type box + * + * @param p_header_data the data contained in the FTYP box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the FTYP box. + * @param p_manager the user event manager. + * + * @return true if the FTYP box is valid. + */ +static OPJ_BOOL opj_jp2_read_ftyp(opj_jp2_t *jp2, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +static OPJ_BOOL opj_jp2_skip_jp2c(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); + +/** + * Reads the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). + * + * @param p_header_data the data contained in the file header box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the file header box. + * @param p_manager the user event manager. + * + * @return true if the JP2 Header box was successfully recognized. +*/ +static OPJ_BOOL opj_jp2_read_jp2h(opj_jp2_t *jp2, + OPJ_BYTE *p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Writes the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). + * + * @param jp2 the jpeg2000 file codec. + * @param stream the stream to write data to. + * @param p_manager user event manager. + * + * @return true if writing was successful. + */ +static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); + +/** + * Writes the Jpeg2000 codestream Header box - JP2C Header box. This function must be called AFTER the coding has been done. + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. + * + * @return true if writing was successful. +*/ +static OPJ_BOOL opj_jp2_write_jp2c(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +#ifdef USE_JPIP +/** + * Write index Finder box + * @param cio the stream to write to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. +*/ +static OPJ_BOOL opj_jpip_write_iptr(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/** + * Write index Finder box + * @param cio the stream to write to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. + */ +static OPJ_BOOL opj_jpip_write_cidx(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/** + * Write file Index (superbox) + * @param cio the stream to write to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager user event manager. + */ +static OPJ_BOOL opj_jpip_write_fidx(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); +#endif /* USE_JPIP */ + +/** + * Reads a jpeg2000 file signature box. + * + * @param p_header_data the data contained in the signature box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the signature box. + * @param p_manager the user event manager. + * + * @return true if the file signature box is valid. + */ +static OPJ_BOOL opj_jp2_read_jp(opj_jp2_t *jp2, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); + +/** + * Writes a jpeg2000 file signature box. + * + * @param cio the stream to write data to. + * @param jp2 the jpeg2000 file codec. + * @param p_manager the user event manager. + * + * @return true if writing was successful. + */ +static OPJ_BOOL opj_jp2_write_jp(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/** +Apply collected palette data +@param image Image. +@param color Collector for profile, cdef and pclr data. +@param p_manager the user event manager. +@return true in case of success +*/ +static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, + opj_jp2_color_t *color, + opj_event_mgr_t * p_manager); + +static void opj_jp2_free_pclr(opj_jp2_color_t *color); + +/** + * Collect palette data + * + * @param jp2 JP2 handle + * @param p_pclr_header_data FIXME DOC + * @param p_pclr_header_size FIXME DOC + * @param p_manager + * + * @return Returns true if successful, returns false otherwise +*/ +static OPJ_BOOL opj_jp2_read_pclr(opj_jp2_t *jp2, + OPJ_BYTE * p_pclr_header_data, + OPJ_UINT32 p_pclr_header_size, + opj_event_mgr_t * p_manager); + +/** + * Collect component mapping data + * + * @param jp2 JP2 handle + * @param p_cmap_header_data FIXME DOC + * @param p_cmap_header_size FIXME DOC + * @param p_manager FIXME DOC + * + * @return Returns true if successful, returns false otherwise +*/ + +static OPJ_BOOL opj_jp2_read_cmap(opj_jp2_t * jp2, + OPJ_BYTE * p_cmap_header_data, + OPJ_UINT32 p_cmap_header_size, + opj_event_mgr_t * p_manager); + +/** + * Reads the Color Specification box. + * + * @param p_colr_header_data pointer to actual data (already read from file) + * @param jp2 the jpeg2000 file codec. + * @param p_colr_header_size the size of the color header + * @param p_manager the user event manager. + * + * @return true if the bpc header is valid, false else. +*/ +static OPJ_BOOL opj_jp2_read_colr(opj_jp2_t *jp2, + OPJ_BYTE * p_colr_header_data, + OPJ_UINT32 p_colr_header_size, + opj_event_mgr_t * p_manager); + +/*@}*/ + +/*@}*/ + +/** + * Sets up the procedures to do on writing header after the codestream. + * Developers wanting to extend the library can add their own writing procedures. + */ +static OPJ_BOOL opj_jp2_setup_end_header_writing(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); + +/** + * Sets up the procedures to do on reading header after the codestream. + * Developers wanting to extend the library can add their own writing procedures. + */ +static OPJ_BOOL opj_jp2_setup_end_header_reading(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); + +/** + * Reads a jpeg2000 file header structure. + * + * @param jp2 the jpeg2000 file header structure. + * @param stream the stream to read data from. + * @param p_manager the user event manager. + * + * @return true if the box is valid. + */ +static OPJ_BOOL opj_jp2_read_header_procedure(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); + +/** + * Executes the given procedures on the given codec. + * + * @param p_procedure_list the list of procedures to execute + * @param jp2 the jpeg2000 file codec to execute the procedures on. + * @param stream the stream to execute the procedures on. + * @param p_manager the user manager. + * + * @return true if all the procedures were successfully executed. + */ +static OPJ_BOOL opj_jp2_exec(opj_jp2_t * jp2, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); + +/** + * Reads a box header. The box is the way data is packed inside a jpeg2000 file structure. + * + * @param cio the input stream to read data from. + * @param box the box structure to fill. + * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (shoul usually be 2). + * @param p_manager user event manager. + * + * @return true if the box is recognized, false otherwise +*/ +static OPJ_BOOL opj_jp2_read_boxhdr(opj_jp2_box_t *box, + OPJ_UINT32 * p_number_bytes_read, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/** + * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters + * are valid. Developers wanting to extend the library can add their own validation procedures. + */ +static OPJ_BOOL opj_jp2_setup_encoding_validation(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); + +/** + * Sets up the procedures to do on writing header. Developers wanting to extend the library can add their own writing procedures. + */ +static OPJ_BOOL opj_jp2_setup_header_writing(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); + +static OPJ_BOOL opj_jp2_default_validation(opj_jp2_t * jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/** + * Finds the image execution function related to the given box id. + * + * @param p_id the id of the handler to fetch. + * + * @return the given handler or NULL if it could not be found. + */ +static const opj_jp2_header_handler_t * opj_jp2_img_find_handler( + OPJ_UINT32 p_id); + +/** + * Finds the execution function related to the given box id. + * + * @param p_id the id of the handler to fetch. + * + * @return the given handler or NULL if it could not be found. + */ +static const opj_jp2_header_handler_t * opj_jp2_find_handler(OPJ_UINT32 p_id); + +static const opj_jp2_header_handler_t jp2_header [] = { + {JP2_JP, opj_jp2_read_jp}, + {JP2_FTYP, opj_jp2_read_ftyp}, + {JP2_JP2H, opj_jp2_read_jp2h} +}; + +static const opj_jp2_header_handler_t jp2_img_header [] = { + {JP2_IHDR, opj_jp2_read_ihdr}, + {JP2_COLR, opj_jp2_read_colr}, + {JP2_BPCC, opj_jp2_read_bpcc}, + {JP2_PCLR, opj_jp2_read_pclr}, + {JP2_CMAP, opj_jp2_read_cmap}, + {JP2_CDEF, opj_jp2_read_cdef} + +}; + +/** + * Reads a box header. The box is the way data is packed inside a jpeg2000 file structure. Data is read from a character string + * + * @param box the box structure to fill. + * @param p_data the character string to read data from. + * @param p_number_bytes_read pointer to an int that will store the number of bytes read from the stream (shoul usually be 2). + * @param p_box_max_size the maximum number of bytes in the box. + * @param p_manager FIXME DOC + * + * @return true if the box is recognized, false otherwise +*/ +static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_number_bytes_read, + OPJ_UINT32 p_box_max_size, + opj_event_mgr_t * p_manager); + +/** + * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters + * are valid. Developers wanting to extend the library can add their own validation procedures. + */ +static OPJ_BOOL opj_jp2_setup_decoding_validation(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); + +/** + * Sets up the procedures to do on reading header. + * Developers wanting to extend the library can add their own writing procedures. + */ +static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager); + +/* ----------------------------------------------------------------------- */ +static OPJ_BOOL opj_jp2_read_boxhdr(opj_jp2_box_t *box, + OPJ_UINT32 * p_number_bytes_read, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + /* read header from file */ + OPJ_BYTE l_data_header [8]; + + /* preconditions */ + assert(cio != 00); + assert(box != 00); + assert(p_number_bytes_read != 00); + assert(p_manager != 00); + + *p_number_bytes_read = (OPJ_UINT32)opj_stream_read_data(cio, l_data_header, 8, + p_manager); + if (*p_number_bytes_read != 8) { + return OPJ_FALSE; + } + + /* process read data */ + opj_read_bytes(l_data_header, &(box->length), 4); + opj_read_bytes(l_data_header + 4, &(box->type), 4); + + if (box->length == 0) { /* last box */ + const OPJ_OFF_T bleft = opj_stream_get_number_byte_left(cio); + if (bleft > (OPJ_OFF_T)(0xFFFFFFFFU - 8U)) { + opj_event_msg(p_manager, EVT_ERROR, + "Cannot handle box sizes higher than 2^32\n"); + return OPJ_FALSE; + } + box->length = (OPJ_UINT32)bleft + 8U; + assert((OPJ_OFF_T)box->length == bleft + 8); + return OPJ_TRUE; + } + + /* do we have a "special very large box ?" */ + /* read then the XLBox */ + if (box->length == 1) { + OPJ_UINT32 l_xl_part_size; + + OPJ_UINT32 l_nb_bytes_read = (OPJ_UINT32)opj_stream_read_data(cio, + l_data_header, 8, p_manager); + if (l_nb_bytes_read != 8) { + if (l_nb_bytes_read > 0) { + *p_number_bytes_read += l_nb_bytes_read; + } + + return OPJ_FALSE; + } + + *p_number_bytes_read = 16; + opj_read_bytes(l_data_header, &l_xl_part_size, 4); + if (l_xl_part_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Cannot handle box sizes higher than 2^32\n"); + return OPJ_FALSE; + } + opj_read_bytes(l_data_header + 4, &(box->length), 4); + } + return OPJ_TRUE; +} + +#if 0 +static void jp2_write_url(opj_cio_t *cio, char *Idx_file) +{ + OPJ_UINT32 i; + opj_jp2_box_t box; + + box.init_pos = cio_tell(cio); + cio_skip(cio, 4); + cio_write(cio, JP2_URL, 4); /* DBTL */ + cio_write(cio, 0, 1); /* VERS */ + cio_write(cio, 0, 3); /* FLAG */ + + if (Idx_file) { + for (i = 0; i < strlen(Idx_file); i++) { + cio_write(cio, Idx_file[i], 1); + } + } + + box.length = cio_tell(cio) - box.init_pos; + cio_seek(cio, box.init_pos); + cio_write(cio, box.length, 4); /* L */ + cio_seek(cio, box.init_pos + box.length); +} +#endif + +static OPJ_BOOL opj_jp2_read_ihdr(opj_jp2_t *jp2, + OPJ_BYTE *p_image_header_data, + OPJ_UINT32 p_image_header_size, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(p_image_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + if (jp2->comps != NULL) { + opj_event_msg(p_manager, EVT_WARNING, + "Ignoring ihdr box. First ihdr box already read\n"); + return OPJ_TRUE; + } + + if (p_image_header_size != 14) { + opj_event_msg(p_manager, EVT_ERROR, "Bad image header box (bad size)\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_image_header_data, &(jp2->h), 4); /* HEIGHT */ + p_image_header_data += 4; + opj_read_bytes(p_image_header_data, &(jp2->w), 4); /* WIDTH */ + p_image_header_data += 4; + opj_read_bytes(p_image_header_data, &(jp2->numcomps), 2); /* NC */ + p_image_header_data += 2; + + if (jp2->h < 1 || jp2->w < 1 || jp2->numcomps < 1) { + opj_event_msg(p_manager, EVT_ERROR, + "Wrong values for: w(%d) h(%d) numcomps(%d) (ihdr)\n", + jp2->w, jp2->h, jp2->numcomps); + return OPJ_FALSE; + } + if ((jp2->numcomps - 1U) >= + 16384U) { /* unsigned underflow is well defined: 1U <= jp2->numcomps <= 16384U */ + opj_event_msg(p_manager, EVT_ERROR, "Invalid number of components (ihdr)\n"); + return OPJ_FALSE; + } + + /* allocate memory for components */ + jp2->comps = (opj_jp2_comps_t*) opj_calloc(jp2->numcomps, + sizeof(opj_jp2_comps_t)); + if (jp2->comps == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to handle image header (ihdr)\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_image_header_data, &(jp2->bpc), 1); /* BPC */ + ++ p_image_header_data; + + opj_read_bytes(p_image_header_data, &(jp2->C), 1); /* C */ + ++ p_image_header_data; + + /* Should be equal to 7 cf. chapter about image header box of the norm */ + if (jp2->C != 7) { + opj_event_msg(p_manager, EVT_INFO, + "JP2 IHDR box: compression type indicate that the file is not a conforming JP2 file (%d) \n", + jp2->C); + } + + opj_read_bytes(p_image_header_data, &(jp2->UnkC), 1); /* UnkC */ + ++ p_image_header_data; + opj_read_bytes(p_image_header_data, &(jp2->IPR), 1); /* IPR */ + ++ p_image_header_data; + + jp2->j2k->m_cp.allow_different_bit_depth_sign = (jp2->bpc == 255); + jp2->j2k->ihdr_w = jp2->w; + jp2->j2k->ihdr_h = jp2->h; + jp2->has_ihdr = 1; + + return OPJ_TRUE; +} + +static OPJ_BYTE * opj_jp2_write_ihdr(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written + ) +{ + OPJ_BYTE * l_ihdr_data, * l_current_ihdr_ptr; + + /* preconditions */ + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + + /* default image header is 22 bytes wide */ + l_ihdr_data = (OPJ_BYTE *) opj_calloc(1, 22); + if (l_ihdr_data == 00) { + return 00; + } + + l_current_ihdr_ptr = l_ihdr_data; + + opj_write_bytes(l_current_ihdr_ptr, 22, 4); /* write box size */ + l_current_ihdr_ptr += 4; + + opj_write_bytes(l_current_ihdr_ptr, JP2_IHDR, 4); /* IHDR */ + l_current_ihdr_ptr += 4; + + opj_write_bytes(l_current_ihdr_ptr, jp2->h, 4); /* HEIGHT */ + l_current_ihdr_ptr += 4; + + opj_write_bytes(l_current_ihdr_ptr, jp2->w, 4); /* WIDTH */ + l_current_ihdr_ptr += 4; + + opj_write_bytes(l_current_ihdr_ptr, jp2->numcomps, 2); /* NC */ + l_current_ihdr_ptr += 2; + + opj_write_bytes(l_current_ihdr_ptr, jp2->bpc, 1); /* BPC */ + ++l_current_ihdr_ptr; + + opj_write_bytes(l_current_ihdr_ptr, jp2->C, 1); /* C : Always 7 */ + ++l_current_ihdr_ptr; + + opj_write_bytes(l_current_ihdr_ptr, jp2->UnkC, + 1); /* UnkC, colorspace unknown */ + ++l_current_ihdr_ptr; + + opj_write_bytes(l_current_ihdr_ptr, jp2->IPR, + 1); /* IPR, no intellectual property */ + ++l_current_ihdr_ptr; + + *p_nb_bytes_written = 22; + + return l_ihdr_data; +} + +static OPJ_BYTE * opj_jp2_write_bpcc(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written + ) +{ + OPJ_UINT32 i; + /* room for 8 bytes for box and 1 byte for each component */ + OPJ_UINT32 l_bpcc_size; + OPJ_BYTE * l_bpcc_data, * l_current_bpcc_ptr; + + /* preconditions */ + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + l_bpcc_size = 8 + jp2->numcomps; + + l_bpcc_data = (OPJ_BYTE *) opj_calloc(1, l_bpcc_size); + if (l_bpcc_data == 00) { + return 00; + } + + l_current_bpcc_ptr = l_bpcc_data; + + opj_write_bytes(l_current_bpcc_ptr, l_bpcc_size, + 4); /* write box size */ + l_current_bpcc_ptr += 4; + + opj_write_bytes(l_current_bpcc_ptr, JP2_BPCC, 4); /* BPCC */ + l_current_bpcc_ptr += 4; + + for (i = 0; i < jp2->numcomps; ++i) { + opj_write_bytes(l_current_bpcc_ptr, jp2->comps[i].bpcc, + 1); /* write each component information */ + ++l_current_bpcc_ptr; + } + + *p_nb_bytes_written = l_bpcc_size; + + return l_bpcc_data; +} + +static OPJ_BOOL opj_jp2_read_bpcc(opj_jp2_t *jp2, + OPJ_BYTE * p_bpc_header_data, + OPJ_UINT32 p_bpc_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 i; + + /* preconditions */ + assert(p_bpc_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + + if (jp2->bpc != 255) { + opj_event_msg(p_manager, EVT_WARNING, + "A BPCC header box is available although BPC given by the IHDR box (%d) indicate components bit depth is constant\n", + jp2->bpc); + } + + /* and length is relevant */ + if (p_bpc_header_size != jp2->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, "Bad BPCC header box (bad size)\n"); + return OPJ_FALSE; + } + + /* read info for each component */ + for (i = 0; i < jp2->numcomps; ++i) { + opj_read_bytes(p_bpc_header_data, &jp2->comps[i].bpcc, + 1); /* read each BPCC component */ + ++p_bpc_header_data; + } + + return OPJ_TRUE; +} +static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written) +{ + /* room for 8 bytes for box, 2 for n */ + OPJ_UINT32 l_cdef_size = 10; + OPJ_BYTE * l_cdef_data, * l_current_cdef_ptr; + OPJ_UINT32 l_value; + OPJ_UINT16 i; + + /* preconditions */ + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + assert(jp2->color.jp2_cdef != 00); + assert(jp2->color.jp2_cdef->info != 00); + assert(jp2->color.jp2_cdef->n > 0U); + + l_cdef_size += 6U * jp2->color.jp2_cdef->n; + + l_cdef_data = (OPJ_BYTE *) opj_malloc(l_cdef_size); + if (l_cdef_data == 00) { + return 00; + } + + l_current_cdef_ptr = l_cdef_data; + + opj_write_bytes(l_current_cdef_ptr, l_cdef_size, 4); /* write box size */ + l_current_cdef_ptr += 4; + + opj_write_bytes(l_current_cdef_ptr, JP2_CDEF, 4); /* BPCC */ + l_current_cdef_ptr += 4; + + l_value = jp2->color.jp2_cdef->n; + opj_write_bytes(l_current_cdef_ptr, l_value, 2); /* N */ + l_current_cdef_ptr += 2; + + for (i = 0U; i < jp2->color.jp2_cdef->n; ++i) { + l_value = jp2->color.jp2_cdef->info[i].cn; + opj_write_bytes(l_current_cdef_ptr, l_value, 2); /* Cni */ + l_current_cdef_ptr += 2; + l_value = jp2->color.jp2_cdef->info[i].typ; + opj_write_bytes(l_current_cdef_ptr, l_value, 2); /* Typi */ + l_current_cdef_ptr += 2; + l_value = jp2->color.jp2_cdef->info[i].asoc; + opj_write_bytes(l_current_cdef_ptr, l_value, 2); /* Asoci */ + l_current_cdef_ptr += 2; + } + *p_nb_bytes_written = l_cdef_size; + + return l_cdef_data; +} + +static OPJ_BYTE * opj_jp2_write_colr(opj_jp2_t *jp2, + OPJ_UINT32 * p_nb_bytes_written + ) +{ + /* room for 8 bytes for box 3 for common data and variable upon profile*/ + OPJ_UINT32 l_colr_size = 11; + OPJ_BYTE * l_colr_data, * l_current_colr_ptr; + + /* preconditions */ + assert(jp2 != 00); + assert(p_nb_bytes_written != 00); + assert(jp2->meth == 1 || jp2->meth == 2); + + switch (jp2->meth) { + case 1 : + l_colr_size += 4; /* EnumCS */ + break; + case 2 : + assert(jp2->color.icc_profile_len); /* ICC profile */ + l_colr_size += jp2->color.icc_profile_len; + break; + default : + return 00; + } + + l_colr_data = (OPJ_BYTE *) opj_calloc(1, l_colr_size); + if (l_colr_data == 00) { + return 00; + } + + l_current_colr_ptr = l_colr_data; + + opj_write_bytes(l_current_colr_ptr, l_colr_size, + 4); /* write box size */ + l_current_colr_ptr += 4; + + opj_write_bytes(l_current_colr_ptr, JP2_COLR, 4); /* BPCC */ + l_current_colr_ptr += 4; + + opj_write_bytes(l_current_colr_ptr, jp2->meth, 1); /* METH */ + ++l_current_colr_ptr; + + opj_write_bytes(l_current_colr_ptr, jp2->precedence, 1); /* PRECEDENCE */ + ++l_current_colr_ptr; + + opj_write_bytes(l_current_colr_ptr, jp2->approx, 1); /* APPROX */ + ++l_current_colr_ptr; + + if (jp2->meth == + 1) { /* Meth value is restricted to 1 or 2 (Table I.9 of part 1) */ + opj_write_bytes(l_current_colr_ptr, jp2->enumcs, 4); + } /* EnumCS */ + else { + if (jp2->meth == 2) { /* ICC profile */ + OPJ_UINT32 i; + for (i = 0; i < jp2->color.icc_profile_len; ++i) { + opj_write_bytes(l_current_colr_ptr, jp2->color.icc_profile_buf[i], 1); + ++l_current_colr_ptr; + } + } + } + + *p_nb_bytes_written = l_colr_size; + + return l_colr_data; +} + +static void opj_jp2_free_pclr(opj_jp2_color_t *color) +{ + opj_free(color->jp2_pclr->channel_sign); + opj_free(color->jp2_pclr->channel_size); + opj_free(color->jp2_pclr->entries); + + if (color->jp2_pclr->cmap) { + opj_free(color->jp2_pclr->cmap); + } + + opj_free(color->jp2_pclr); + color->jp2_pclr = NULL; +} + +static OPJ_BOOL opj_jp2_check_color(opj_image_t *image, opj_jp2_color_t *color, + opj_event_mgr_t *p_manager) +{ + OPJ_UINT16 i; + + /* testcase 4149.pdf.SIGSEGV.cf7.3501 */ + if (color->jp2_cdef) { + opj_jp2_cdef_info_t *info = color->jp2_cdef->info; + OPJ_UINT16 n = color->jp2_cdef->n; + OPJ_UINT32 nr_channels = + image->numcomps; /* FIXME image->numcomps == jp2->numcomps before color is applied ??? */ + + /* cdef applies to cmap channels if any */ + if (color->jp2_pclr && color->jp2_pclr->cmap) { + nr_channels = (OPJ_UINT32)color->jp2_pclr->nr_channels; + } + + for (i = 0; i < n; i++) { + if (info[i].cn >= nr_channels) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", + info[i].cn, nr_channels); + return OPJ_FALSE; + } + if (info[i].asoc == 65535U) { + continue; + } + + if (info[i].asoc > 0 && (OPJ_UINT32)(info[i].asoc - 1) >= nr_channels) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", + info[i].asoc - 1, nr_channels); + return OPJ_FALSE; + } + } + + /* issue 397 */ + /* ISO 15444-1 states that if cdef is present, it shall contain a complete list of channel definitions. */ + while (nr_channels > 0) { + for (i = 0; i < n; ++i) { + if ((OPJ_UINT32)info[i].cn == (nr_channels - 1U)) { + break; + } + } + if (i == n) { + opj_event_msg(p_manager, EVT_ERROR, "Incomplete channel definitions.\n"); + return OPJ_FALSE; + } + --nr_channels; + } + } + + /* testcases 451.pdf.SIGSEGV.f4c.3723, 451.pdf.SIGSEGV.5b5.3723 and + 66ea31acbb0f23a2bbc91f64d69a03f5_signal_sigsegv_13937c0_7030_5725.pdf */ + if (color->jp2_pclr && color->jp2_pclr->cmap) { + OPJ_UINT16 nr_channels = color->jp2_pclr->nr_channels; + opj_jp2_cmap_comp_t *cmap = color->jp2_pclr->cmap; + OPJ_BOOL *pcol_usage, is_sane = OPJ_TRUE; + + /* verify that all original components match an existing one */ + for (i = 0; i < nr_channels; i++) { + if (cmap[i].cmp >= image->numcomps) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", + cmap[i].cmp, image->numcomps); + is_sane = OPJ_FALSE; + } + } + + pcol_usage = (OPJ_BOOL *) opj_calloc(nr_channels, sizeof(OPJ_BOOL)); + if (!pcol_usage) { + opj_event_msg(p_manager, EVT_ERROR, "Unexpected OOM.\n"); + return OPJ_FALSE; + } + /* verify that no component is targeted more than once */ + for (i = 0; i < nr_channels; i++) { + OPJ_BYTE mtyp = cmap[i].mtyp; + OPJ_BYTE pcol = cmap[i].pcol; + /* See ISO 15444-1 Table I.14 – MTYPi field values */ + if (mtyp != 0 && mtyp != 1) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid value for cmap[%d].mtyp = %d.\n", i, + mtyp); + is_sane = OPJ_FALSE; + } else if (pcol >= nr_channels) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid component/palette index for direct mapping %d.\n", pcol); + is_sane = OPJ_FALSE; + } else if (pcol_usage[pcol] && mtyp == 1) { + opj_event_msg(p_manager, EVT_ERROR, "Component %d is mapped twice.\n", pcol); + is_sane = OPJ_FALSE; + } else if (mtyp == 0 && pcol != 0) { + /* I.5.3.5 PCOL: If the value of the MTYP field for this channel is 0, then + * the value of this field shall be 0. */ + opj_event_msg(p_manager, EVT_ERROR, "Direct use at #%d however pcol=%d.\n", i, + pcol); + is_sane = OPJ_FALSE; + } else if (mtyp == 1 && pcol != i) { + /* OpenJPEG implementation limitation. See assert(i == pcol); */ + /* in opj_jp2_apply_pclr() */ + opj_event_msg(p_manager, EVT_ERROR, + "Implementation limitation: for palette mapping, " + "pcol[%d] should be equal to %d, but is equal " + "to %d.\n", i, i, pcol); + is_sane = OPJ_FALSE; + } else { + pcol_usage[pcol] = OPJ_TRUE; + } + } + /* verify that all components are targeted at least once */ + for (i = 0; i < nr_channels; i++) { + if (!pcol_usage[i] && cmap[i].mtyp != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Component %d doesn't have a mapping.\n", + i); + is_sane = OPJ_FALSE; + } + } + /* Issue 235/447 weird cmap */ + if (1 && is_sane && (image->numcomps == 1U)) { + for (i = 0; i < nr_channels; i++) { + if (!pcol_usage[i]) { + is_sane = 0U; + opj_event_msg(p_manager, EVT_WARNING, + "Component mapping seems wrong. Trying to correct.\n"); + break; + } + } + if (!is_sane) { + is_sane = OPJ_TRUE; + for (i = 0; i < nr_channels; i++) { + cmap[i].mtyp = 1U; + cmap[i].pcol = (OPJ_BYTE) i; + } + } + } + opj_free(pcol_usage); + if (!is_sane) { + return OPJ_FALSE; + } + } + + return OPJ_TRUE; +} + +/* file9.jp2 */ +static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image, + opj_jp2_color_t *color, + opj_event_mgr_t * p_manager) +{ + opj_image_comp_t *old_comps, *new_comps; + OPJ_BYTE *channel_size, *channel_sign; + OPJ_UINT32 *entries; + opj_jp2_cmap_comp_t *cmap; + OPJ_INT32 *src, *dst; + OPJ_UINT32 j, max; + OPJ_UINT16 i, nr_channels, cmp, pcol; + OPJ_INT32 k, top_k; + + channel_size = color->jp2_pclr->channel_size; + channel_sign = color->jp2_pclr->channel_sign; + entries = color->jp2_pclr->entries; + cmap = color->jp2_pclr->cmap; + nr_channels = color->jp2_pclr->nr_channels; + + for (i = 0; i < nr_channels; ++i) { + /* Palette mapping: */ + cmp = cmap[i].cmp; + if (image->comps[cmp].data == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "image->comps[%d].data == NULL in opj_jp2_apply_pclr().\n", i); + return OPJ_FALSE; + } + } + + old_comps = image->comps; + new_comps = (opj_image_comp_t*) + opj_malloc(nr_channels * sizeof(opj_image_comp_t)); + if (!new_comps) { + opj_event_msg(p_manager, EVT_ERROR, + "Memory allocation failure in opj_jp2_apply_pclr().\n"); + return OPJ_FALSE; + } + for (i = 0; i < nr_channels; ++i) { + pcol = cmap[i].pcol; + cmp = cmap[i].cmp; + + /* Direct use */ + if (cmap[i].mtyp == 0) { + assert(pcol == 0); + new_comps[i] = old_comps[cmp]; + } else { + assert(i == pcol); + new_comps[pcol] = old_comps[cmp]; + } + + /* Palette mapping: */ + new_comps[i].data = (OPJ_INT32*) + opj_image_data_alloc(sizeof(OPJ_INT32) * old_comps[cmp].w * old_comps[cmp].h); + if (!new_comps[i].data) { + while (i > 0) { + -- i; + opj_image_data_free(new_comps[i].data); + } + opj_free(new_comps); + opj_event_msg(p_manager, EVT_ERROR, + "Memory allocation failure in opj_jp2_apply_pclr().\n"); + return OPJ_FALSE; + } + new_comps[i].prec = channel_size[i]; + new_comps[i].sgnd = channel_sign[i]; + } + + top_k = color->jp2_pclr->nr_entries - 1; + + for (i = 0; i < nr_channels; ++i) { + /* Palette mapping: */ + cmp = cmap[i].cmp; + pcol = cmap[i].pcol; + src = old_comps[cmp].data; + assert(src); /* verified above */ + max = new_comps[i].w * new_comps[i].h; + + /* Direct use: */ + if (cmap[i].mtyp == 0) { + dst = new_comps[i].data; + assert(dst); + for (j = 0; j < max; ++j) { + dst[j] = src[j]; + } + } else { + assert(i == pcol); + dst = new_comps[pcol].data; + assert(dst); + for (j = 0; j < max; ++j) { + /* The index */ + if ((k = src[j]) < 0) { + k = 0; + } else if (k > top_k) { + k = top_k; + } + + /* The colour */ + dst[j] = (OPJ_INT32)entries[k * nr_channels + pcol]; + } + } + } + + max = image->numcomps; + for (j = 0; j < max; ++j) { + if (old_comps[j].data) { + opj_image_data_free(old_comps[j].data); + } + } + + opj_free(old_comps); + image->comps = new_comps; + image->numcomps = nr_channels; + + return OPJ_TRUE; +}/* apply_pclr() */ + +static OPJ_BOOL opj_jp2_read_pclr(opj_jp2_t *jp2, + OPJ_BYTE * p_pclr_header_data, + OPJ_UINT32 p_pclr_header_size, + opj_event_mgr_t * p_manager + ) +{ + opj_jp2_pclr_t *jp2_pclr; + OPJ_BYTE *channel_size, *channel_sign; + OPJ_UINT32 *entries; + OPJ_UINT16 nr_entries, nr_channels; + OPJ_UINT16 i, j; + OPJ_UINT32 l_value; + OPJ_BYTE *orig_header_data = p_pclr_header_data; + + /* preconditions */ + assert(p_pclr_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + (void)p_pclr_header_size; + + if (jp2->color.jp2_pclr) { + return OPJ_FALSE; + } + + if (p_pclr_header_size < 3) { + return OPJ_FALSE; + } + + opj_read_bytes(p_pclr_header_data, &l_value, 2); /* NE */ + p_pclr_header_data += 2; + nr_entries = (OPJ_UINT16) l_value; + if ((nr_entries == 0U) || (nr_entries > 1024U)) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid PCLR box. Reports %d entries\n", + (int)nr_entries); + return OPJ_FALSE; + } + + opj_read_bytes(p_pclr_header_data, &l_value, 1); /* NPC */ + ++p_pclr_header_data; + nr_channels = (OPJ_UINT16) l_value; + if (nr_channels == 0U) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid PCLR box. Reports 0 palette columns\n"); + return OPJ_FALSE; + } + + if (p_pclr_header_size < 3 + (OPJ_UINT32)nr_channels) { + return OPJ_FALSE; + } + + entries = (OPJ_UINT32*) opj_malloc(sizeof(OPJ_UINT32) * nr_channels * + nr_entries); + if (!entries) { + return OPJ_FALSE; + } + channel_size = (OPJ_BYTE*) opj_malloc(nr_channels); + if (!channel_size) { + opj_free(entries); + return OPJ_FALSE; + } + channel_sign = (OPJ_BYTE*) opj_malloc(nr_channels); + if (!channel_sign) { + opj_free(entries); + opj_free(channel_size); + return OPJ_FALSE; + } + + jp2_pclr = (opj_jp2_pclr_t*)opj_malloc(sizeof(opj_jp2_pclr_t)); + if (!jp2_pclr) { + opj_free(entries); + opj_free(channel_size); + opj_free(channel_sign); + return OPJ_FALSE; + } + + jp2_pclr->channel_sign = channel_sign; + jp2_pclr->channel_size = channel_size; + jp2_pclr->entries = entries; + jp2_pclr->nr_entries = nr_entries; + jp2_pclr->nr_channels = (OPJ_BYTE) l_value; + jp2_pclr->cmap = NULL; + + jp2->color.jp2_pclr = jp2_pclr; + + for (i = 0; i < nr_channels; ++i) { + opj_read_bytes(p_pclr_header_data, &l_value, 1); /* Bi */ + ++p_pclr_header_data; + + channel_size[i] = (OPJ_BYTE)((l_value & 0x7f) + 1); + channel_sign[i] = (l_value & 0x80) ? 1 : 0; + } + + for (j = 0; j < nr_entries; ++j) { + for (i = 0; i < nr_channels; ++i) { + OPJ_UINT32 bytes_to_read = (OPJ_UINT32)((channel_size[i] + 7) >> 3); + + if (bytes_to_read > sizeof(OPJ_UINT32)) { + bytes_to_read = sizeof(OPJ_UINT32); + } + if ((ptrdiff_t)p_pclr_header_size < (ptrdiff_t)(p_pclr_header_data - + orig_header_data) + (ptrdiff_t)bytes_to_read) { + return OPJ_FALSE; + } + + opj_read_bytes(p_pclr_header_data, &l_value, bytes_to_read); /* Cji */ + p_pclr_header_data += bytes_to_read; + *entries = (OPJ_UINT32) l_value; + entries++; + } + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_read_cmap(opj_jp2_t * jp2, + OPJ_BYTE * p_cmap_header_data, + OPJ_UINT32 p_cmap_header_size, + opj_event_mgr_t * p_manager + ) +{ + opj_jp2_cmap_comp_t *cmap; + OPJ_BYTE i, nr_channels; + OPJ_UINT32 l_value; + + /* preconditions */ + assert(jp2 != 00); + assert(p_cmap_header_data != 00); + assert(p_manager != 00); + (void)p_cmap_header_size; + + /* Need nr_channels: */ + if (jp2->color.jp2_pclr == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "Need to read a PCLR box before the CMAP box.\n"); + return OPJ_FALSE; + } + + /* Part 1, I.5.3.5: 'There shall be at most one Component Mapping box + * inside a JP2 Header box' : + */ + if (jp2->color.jp2_pclr->cmap) { + opj_event_msg(p_manager, EVT_ERROR, "Only one CMAP box is allowed.\n"); + return OPJ_FALSE; + } + + nr_channels = jp2->color.jp2_pclr->nr_channels; + if (p_cmap_header_size < (OPJ_UINT32)nr_channels * 4) { + opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CMAP box.\n"); + return OPJ_FALSE; + } + + cmap = (opj_jp2_cmap_comp_t*) opj_malloc(nr_channels * sizeof( + opj_jp2_cmap_comp_t)); + if (!cmap) { + return OPJ_FALSE; + } + + + for (i = 0; i < nr_channels; ++i) { + opj_read_bytes(p_cmap_header_data, &l_value, 2); /* CMP^i */ + p_cmap_header_data += 2; + cmap[i].cmp = (OPJ_UINT16) l_value; + + opj_read_bytes(p_cmap_header_data, &l_value, 1); /* MTYP^i */ + ++p_cmap_header_data; + cmap[i].mtyp = (OPJ_BYTE) l_value; + + opj_read_bytes(p_cmap_header_data, &l_value, 1); /* PCOL^i */ + ++p_cmap_header_data; + cmap[i].pcol = (OPJ_BYTE) l_value; + } + + jp2->color.jp2_pclr->cmap = cmap; + + return OPJ_TRUE; +} + +static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color, + opj_event_mgr_t *manager) +{ + opj_jp2_cdef_info_t *info; + OPJ_UINT16 i, n, cn, asoc, acn; + + info = color->jp2_cdef->info; + n = color->jp2_cdef->n; + + for (i = 0; i < n; ++i) { + /* WATCH: acn = asoc - 1 ! */ + asoc = info[i].asoc; + cn = info[i].cn; + + if (cn >= image->numcomps) { + opj_event_msg(manager, EVT_WARNING, "opj_jp2_apply_cdef: cn=%d, numcomps=%d\n", + cn, image->numcomps); + continue; + } + if (asoc == 0 || asoc == 65535) { + image->comps[cn].alpha = info[i].typ; + continue; + } + + acn = (OPJ_UINT16)(asoc - 1); + if (acn >= image->numcomps) { + opj_event_msg(manager, EVT_WARNING, "opj_jp2_apply_cdef: acn=%d, numcomps=%d\n", + acn, image->numcomps); + continue; + } + + /* Swap only if color channel */ + if ((cn != acn) && (info[i].typ == 0)) { + opj_image_comp_t saved; + OPJ_UINT16 j; + + memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t)); + memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t)); + + /* Swap channels in following channel definitions, don't bother with j <= i that are already processed */ + for (j = (OPJ_UINT16)(i + 1U); j < n ; ++j) { + if (info[j].cn == cn) { + info[j].cn = acn; + } else if (info[j].cn == acn) { + info[j].cn = cn; + } + /* asoc is related to color index. Do not update. */ + } + } + + image->comps[cn].alpha = info[i].typ; + } + + if (color->jp2_cdef->info) { + opj_free(color->jp2_cdef->info); + } + + opj_free(color->jp2_cdef); + color->jp2_cdef = NULL; + +}/* jp2_apply_cdef() */ + +static OPJ_BOOL opj_jp2_read_cdef(opj_jp2_t * jp2, + OPJ_BYTE * p_cdef_header_data, + OPJ_UINT32 p_cdef_header_size, + opj_event_mgr_t * p_manager + ) +{ + opj_jp2_cdef_info_t *cdef_info; + OPJ_UINT16 i; + OPJ_UINT32 l_value; + + /* preconditions */ + assert(jp2 != 00); + assert(p_cdef_header_data != 00); + assert(p_manager != 00); + (void)p_cdef_header_size; + + /* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box + * inside a JP2 Header box.'*/ + if (jp2->color.jp2_cdef) { + return OPJ_FALSE; + } + + if (p_cdef_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_cdef_header_data, &l_value, 2); /* N */ + p_cdef_header_data += 2; + + if ((OPJ_UINT16)l_value == 0) { /* szukw000: FIXME */ + opj_event_msg(p_manager, EVT_ERROR, + "Number of channel description is equal to zero in CDEF box.\n"); + return OPJ_FALSE; + } + + if (p_cdef_header_size < 2 + (OPJ_UINT32)(OPJ_UINT16)l_value * 6) { + opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n"); + return OPJ_FALSE; + } + + cdef_info = (opj_jp2_cdef_info_t*) opj_malloc(l_value * sizeof( + opj_jp2_cdef_info_t)); + if (!cdef_info) { + return OPJ_FALSE; + } + + jp2->color.jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); + if (!jp2->color.jp2_cdef) { + opj_free(cdef_info); + return OPJ_FALSE; + } + jp2->color.jp2_cdef->info = cdef_info; + jp2->color.jp2_cdef->n = (OPJ_UINT16) l_value; + + for (i = 0; i < jp2->color.jp2_cdef->n; ++i) { + opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Cn^i */ + p_cdef_header_data += 2; + cdef_info[i].cn = (OPJ_UINT16) l_value; + + opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Typ^i */ + p_cdef_header_data += 2; + cdef_info[i].typ = (OPJ_UINT16) l_value; + + opj_read_bytes(p_cdef_header_data, &l_value, 2); /* Asoc^i */ + p_cdef_header_data += 2; + cdef_info[i].asoc = (OPJ_UINT16) l_value; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_read_colr(opj_jp2_t *jp2, + OPJ_BYTE * p_colr_header_data, + OPJ_UINT32 p_colr_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_value; + + /* preconditions */ + assert(jp2 != 00); + assert(p_colr_header_data != 00); + assert(p_manager != 00); + + if (p_colr_header_size < 3) { + opj_event_msg(p_manager, EVT_ERROR, "Bad COLR header box (bad size)\n"); + return OPJ_FALSE; + } + + /* Part 1, I.5.3.3 : 'A conforming JP2 reader shall ignore all Colour + * Specification boxes after the first.' + */ + if (jp2->color.jp2_has_colr) { + opj_event_msg(p_manager, EVT_INFO, + "A conforming JP2 reader shall ignore all Colour Specification boxes after the first, so we ignore this one.\n"); + p_colr_header_data += p_colr_header_size; + return OPJ_TRUE; + } + + opj_read_bytes(p_colr_header_data, &jp2->meth, 1); /* METH */ + ++p_colr_header_data; + + opj_read_bytes(p_colr_header_data, &jp2->precedence, 1); /* PRECEDENCE */ + ++p_colr_header_data; + + opj_read_bytes(p_colr_header_data, &jp2->approx, 1); /* APPROX */ + ++p_colr_header_data; + + if (jp2->meth == 1) { + if (p_colr_header_size < 7) { + opj_event_msg(p_manager, EVT_ERROR, "Bad COLR header box (bad size: %d)\n", + p_colr_header_size); + return OPJ_FALSE; + } + if ((p_colr_header_size > 7) && + (jp2->enumcs != 14)) { /* handled below for CIELab) */ + /* testcase Altona_Technical_v20_x4.pdf */ + opj_event_msg(p_manager, EVT_WARNING, "Bad COLR header box (bad size: %d)\n", + p_colr_header_size); + } + + opj_read_bytes(p_colr_header_data, &jp2->enumcs, 4); /* EnumCS */ + + p_colr_header_data += 4; + + if (jp2->enumcs == 14) { /* CIELab */ + OPJ_UINT32 *cielab; + OPJ_UINT32 rl, ol, ra, oa, rb, ob, il; + + cielab = (OPJ_UINT32*)opj_malloc(9 * sizeof(OPJ_UINT32)); + if (cielab == NULL) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for cielab\n"); + return OPJ_FALSE; + } + cielab[0] = 14; /* enumcs */ + + /* default values */ + rl = ra = rb = ol = oa = ob = 0; + il = 0x00443530; /* D50 */ + cielab[1] = 0x44454600;/* DEF */ + + if (p_colr_header_size == 35) { + opj_read_bytes(p_colr_header_data, &rl, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &ol, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &ra, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &oa, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &rb, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &ob, 4); + p_colr_header_data += 4; + opj_read_bytes(p_colr_header_data, &il, 4); + p_colr_header_data += 4; + + cielab[1] = 0; + } else if (p_colr_header_size != 7) { + opj_event_msg(p_manager, EVT_WARNING, + "Bad COLR header box (CIELab, bad size: %d)\n", p_colr_header_size); + } + cielab[2] = rl; + cielab[4] = ra; + cielab[6] = rb; + cielab[3] = ol; + cielab[5] = oa; + cielab[7] = ob; + cielab[8] = il; + + jp2->color.icc_profile_buf = (OPJ_BYTE*)cielab; + jp2->color.icc_profile_len = 0; + } + jp2->color.jp2_has_colr = 1; + } else if (jp2->meth == 2) { + /* ICC profile */ + OPJ_INT32 it_icc_value = 0; + OPJ_INT32 icc_len = (OPJ_INT32)p_colr_header_size - 3; + + jp2->color.icc_profile_len = (OPJ_UINT32)icc_len; + jp2->color.icc_profile_buf = (OPJ_BYTE*) opj_calloc(1, (size_t)icc_len); + if (!jp2->color.icc_profile_buf) { + jp2->color.icc_profile_len = 0; + return OPJ_FALSE; + } + + for (it_icc_value = 0; it_icc_value < icc_len; ++it_icc_value) { + opj_read_bytes(p_colr_header_data, &l_value, 1); /* icc values */ + ++p_colr_header_data; + jp2->color.icc_profile_buf[it_icc_value] = (OPJ_BYTE) l_value; + } + + jp2->color.jp2_has_colr = 1; + } else if (jp2->meth > 2) { + /* ISO/IEC 15444-1:2004 (E), Table I.9 Legal METH values: + conforming JP2 reader shall ignore the entire Colour Specification box.*/ + opj_event_msg(p_manager, EVT_INFO, + "COLR BOX meth value is not a regular value (%d), " + "so we will ignore the entire Colour Specification box. \n", jp2->meth); + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_apply_color_postprocessing(opj_jp2_t *jp2, + opj_image_t* p_image, + opj_event_mgr_t * p_manager) +{ + if (jp2->j2k->m_specific_param.m_decoder.m_numcomps_to_decode) { + /* Bypass all JP2 component transforms */ + return OPJ_TRUE; + } + + if (!jp2->ignore_pclr_cmap_cdef) { + if (!opj_jp2_check_color(p_image, &(jp2->color), p_manager)) { + return OPJ_FALSE; + } + + if (jp2->color.jp2_pclr) { + /* Part 1, I.5.3.4: Either both or none : */ + if (!jp2->color.jp2_pclr->cmap) { + opj_jp2_free_pclr(&(jp2->color)); + } else { + if (!opj_jp2_apply_pclr(p_image, &(jp2->color), p_manager)) { + return OPJ_FALSE; + } + } + } + + /* Apply the color space if needed */ + if (jp2->color.jp2_cdef) { + opj_jp2_apply_cdef(p_image, &(jp2->color), p_manager); + } + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager) +{ + if (!p_image) { + return OPJ_FALSE; + } + + /* J2K decoding */ + if (! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Failed to decode the codestream in the JP2 file\n"); + return OPJ_FALSE; + } + + return opj_jp2_apply_color_postprocessing(jp2, p_image, p_manager); +} + +static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager + ) +{ + opj_jp2_img_header_writer_handler_t l_writers [4]; + opj_jp2_img_header_writer_handler_t * l_current_writer; + + OPJ_INT32 i, l_nb_pass; + /* size of data for super box*/ + OPJ_UINT32 l_jp2h_size = 8; + OPJ_BOOL l_result = OPJ_TRUE; + + /* to store the data of the super box */ + OPJ_BYTE l_jp2h_data [8]; + + /* preconditions */ + assert(stream != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + memset(l_writers, 0, sizeof(l_writers)); + + if (jp2->bpc == 255) { + l_nb_pass = 3; + l_writers[0].handler = opj_jp2_write_ihdr; + l_writers[1].handler = opj_jp2_write_bpcc; + l_writers[2].handler = opj_jp2_write_colr; + } else { + l_nb_pass = 2; + l_writers[0].handler = opj_jp2_write_ihdr; + l_writers[1].handler = opj_jp2_write_colr; + } + + if (jp2->color.jp2_cdef != NULL) { + l_writers[l_nb_pass].handler = opj_jp2_write_cdef; + l_nb_pass++; + } + + /* write box header */ + /* write JP2H type */ + opj_write_bytes(l_jp2h_data + 4, JP2_JP2H, 4); + + l_current_writer = l_writers; + for (i = 0; i < l_nb_pass; ++i) { + l_current_writer->m_data = l_current_writer->handler(jp2, + &(l_current_writer->m_size)); + if (l_current_writer->m_data == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to hold JP2 Header data\n"); + l_result = OPJ_FALSE; + break; + } + + l_jp2h_size += l_current_writer->m_size; + ++l_current_writer; + } + + if (! l_result) { + l_current_writer = l_writers; + for (i = 0; i < l_nb_pass; ++i) { + if (l_current_writer->m_data != 00) { + opj_free(l_current_writer->m_data); + } + ++l_current_writer; + } + + return OPJ_FALSE; + } + + /* write super box size */ + opj_write_bytes(l_jp2h_data, l_jp2h_size, 4); + + /* write super box data on stream */ + if (opj_stream_write_data(stream, l_jp2h_data, 8, p_manager) != 8) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while writing JP2 Header box\n"); + l_result = OPJ_FALSE; + } + + if (l_result) { + l_current_writer = l_writers; + for (i = 0; i < l_nb_pass; ++i) { + if (opj_stream_write_data(stream, l_current_writer->m_data, + l_current_writer->m_size, p_manager) != l_current_writer->m_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while writing JP2 Header box\n"); + l_result = OPJ_FALSE; + break; + } + ++l_current_writer; + } + } + + l_current_writer = l_writers; + + /* cleanup */ + for (i = 0; i < l_nb_pass; ++i) { + if (l_current_writer->m_data != 00) { + opj_free(l_current_writer->m_data); + } + ++l_current_writer; + } + + return l_result; +} + +static OPJ_BOOL opj_jp2_write_ftyp(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_ftyp_size; + OPJ_BYTE * l_ftyp_data, * l_current_data_ptr; + OPJ_BOOL l_result; + + /* preconditions */ + assert(cio != 00); + assert(jp2 != 00); + assert(p_manager != 00); + l_ftyp_size = 16 + 4 * jp2->numcl; + + l_ftyp_data = (OPJ_BYTE *) opj_calloc(1, l_ftyp_size); + + if (l_ftyp_data == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle ftyp data\n"); + return OPJ_FALSE; + } + + l_current_data_ptr = l_ftyp_data; + + opj_write_bytes(l_current_data_ptr, l_ftyp_size, 4); /* box size */ + l_current_data_ptr += 4; + + opj_write_bytes(l_current_data_ptr, JP2_FTYP, 4); /* FTYP */ + l_current_data_ptr += 4; + + opj_write_bytes(l_current_data_ptr, jp2->brand, 4); /* BR */ + l_current_data_ptr += 4; + + opj_write_bytes(l_current_data_ptr, jp2->minversion, 4); /* MinV */ + l_current_data_ptr += 4; + + for (i = 0; i < jp2->numcl; i++) { + opj_write_bytes(l_current_data_ptr, jp2->cl[i], 4); /* CL */ + } + + l_result = (opj_stream_write_data(cio, l_ftyp_data, l_ftyp_size, + p_manager) == l_ftyp_size); + if (! l_result) { + opj_event_msg(p_manager, EVT_ERROR, + "Error while writing ftyp data to stream\n"); + } + + opj_free(l_ftyp_data); + + return l_result; +} + +static OPJ_BOOL opj_jp2_write_jp2c(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_OFF_T j2k_codestream_exit; + OPJ_BYTE l_data_header [8]; + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + assert(opj_stream_has_seek(cio)); + + j2k_codestream_exit = opj_stream_tell(cio); + opj_write_bytes(l_data_header, + (OPJ_UINT32)(j2k_codestream_exit - jp2->j2k_codestream_offset), + 4); /* size of codestream */ + opj_write_bytes(l_data_header + 4, JP2_JP2C, + 4); /* JP2C */ + + if (! opj_stream_seek(cio, jp2->j2k_codestream_offset, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + if (opj_stream_write_data(cio, l_data_header, 8, p_manager) != 8) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_write_jp(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + /* 12 bytes will be read */ + OPJ_BYTE l_signature_data [12]; + + /* preconditions */ + assert(cio != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + OPJ_UNUSED(jp2); + + /* write box length */ + opj_write_bytes(l_signature_data, 12, 4); + /* writes box type */ + opj_write_bytes(l_signature_data + 4, JP2_JP, 4); + /* writes magic number*/ + opj_write_bytes(l_signature_data + 8, 0x0d0a870a, 4); + + if (opj_stream_write_data(cio, l_signature_data, 12, p_manager) != 12) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/* ----------------------------------------------------------------------- */ +/* JP2 decoder interface */ +/* ----------------------------------------------------------------------- */ + +void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) +{ + /* setup the J2K codec */ + opj_j2k_setup_decoder(jp2->j2k, parameters); + + /* further JP2 initializations go here */ + jp2->color.jp2_has_colr = 0; + jp2->ignore_pclr_cmap_cdef = parameters->flags & + OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG; +} + +void opj_jp2_decoder_set_strict_mode(opj_jp2_t *jp2, OPJ_BOOL strict) +{ + opj_j2k_decoder_set_strict_mode(jp2->j2k, strict); +} + +OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads) +{ + return opj_j2k_set_threads(jp2->j2k, num_threads); +} + +/* ----------------------------------------------------------------------- */ +/* JP2 encoder interface */ +/* ----------------------------------------------------------------------- */ + +OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2, + opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 i; + OPJ_UINT32 depth_0; + OPJ_UINT32 sign; + OPJ_UINT32 alpha_count; + OPJ_UINT32 color_channels = 0U; + OPJ_UINT32 alpha_channel = 0U; + + + if (!jp2 || !parameters || !image) { + return OPJ_FALSE; + } + + /* setup the J2K codec */ + /* ------------------- */ + + /* Check if number of components respects standard */ + if (image->numcomps < 1 || image->numcomps > 16384) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid number of components specified while setting up JP2 encoder\n"); + return OPJ_FALSE; + } + + if (opj_j2k_setup_encoder(jp2->j2k, parameters, image, + p_manager) == OPJ_FALSE) { + return OPJ_FALSE; + } + + /* setup the JP2 codec */ + /* ------------------- */ + + /* Profile box */ + + jp2->brand = JP2_JP2; /* BR */ + jp2->minversion = 0; /* MinV */ + jp2->numcl = 1; + jp2->cl = (OPJ_UINT32*) opj_malloc(jp2->numcl * sizeof(OPJ_UINT32)); + if (!jp2->cl) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory when setup the JP2 encoder\n"); + return OPJ_FALSE; + } + jp2->cl[0] = JP2_JP2; /* CL0 : JP2 */ + + /* Image Header box */ + + jp2->numcomps = image->numcomps; /* NC */ + jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof( + opj_jp2_comps_t)); + if (!jp2->comps) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory when setup the JP2 encoder\n"); + /* Memory of jp2->cl will be freed by opj_jp2_destroy */ + return OPJ_FALSE; + } + + jp2->h = image->y1 - image->y0; /* HEIGHT */ + jp2->w = image->x1 - image->x0; /* WIDTH */ + /* BPC */ + depth_0 = image->comps[0].prec - 1; + sign = image->comps[0].sgnd; + jp2->bpc = depth_0 + (sign << 7); + for (i = 1; i < image->numcomps; i++) { + OPJ_UINT32 depth = image->comps[i].prec - 1; + sign = image->comps[i].sgnd; + if (depth_0 != depth) { + jp2->bpc = 255; + } + } + jp2->C = 7; /* C : Always 7 */ + jp2->UnkC = 0; /* UnkC, colorspace specified in colr box */ + jp2->IPR = 0; /* IPR, no intellectual property */ + + /* BitsPerComponent box */ + for (i = 0; i < image->numcomps; i++) { + jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7); + } + + /* Colour Specification box */ + if (image->icc_profile_len) { + jp2->meth = 2; + jp2->enumcs = 0; + jp2->color.icc_profile_buf = (OPJ_BYTE *)opj_malloc(image->icc_profile_len); + if (jp2->color.icc_profile_buf) { + jp2->color.icc_profile_len = image->icc_profile_len; + memcpy(jp2->color.icc_profile_buf, image->icc_profile_buf, + image->icc_profile_len); + } + } else { + jp2->meth = 1; + if (image->color_space == OPJ_CLRSPC_SRGB) { + jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2-1 */ + } else if (image->color_space == OPJ_CLRSPC_GRAY) { + jp2->enumcs = 17; + } else if (image->color_space == OPJ_CLRSPC_SYCC) { + jp2->enumcs = 18; /* YUV */ + } else if (image->color_space == OPJ_CLRSPC_EYCC) { + jp2->enumcs = 24; + } else if (image->color_space == OPJ_CLRSPC_CMYK) { + jp2->enumcs = 12; + } + } + + /* Channel Definition box */ + /* FIXME not provided by parameters */ + /* We try to do what we can... */ + alpha_count = 0U; + for (i = 0; i < image->numcomps; i++) { + if (image->comps[i].alpha != 0) { + alpha_count++; + alpha_channel = i; + } + } + if (alpha_count == 1U) { /* no way to deal with more than 1 alpha channel */ + switch (jp2->enumcs) { + case 16: + case 18: + color_channels = 3; + break; + case 17: + color_channels = 1; + break; + default: + alpha_count = 0U; + break; + } + if (alpha_count == 0U) { + opj_event_msg(p_manager, EVT_WARNING, + "Alpha channel specified but unknown enumcs. No cdef box will be created.\n"); + } else if (image->numcomps < (color_channels + 1)) { + opj_event_msg(p_manager, EVT_WARNING, + "Alpha channel specified but not enough image components for an automatic cdef box creation.\n"); + alpha_count = 0U; + } else if ((OPJ_UINT32)alpha_channel < color_channels) { + opj_event_msg(p_manager, EVT_WARNING, + "Alpha channel position conflicts with color channel. No cdef box will be created.\n"); + alpha_count = 0U; + } + } else if (alpha_count > 1) { + opj_event_msg(p_manager, EVT_WARNING, + "Multiple alpha channels specified. No cdef box will be created.\n"); + } + if (alpha_count == 1U) { /* if here, we know what we can do */ + jp2->color.jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t)); + if (!jp2->color.jp2_cdef) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to setup the JP2 encoder\n"); + return OPJ_FALSE; + } + /* no memset needed, all values will be overwritten except if jp2->color.jp2_cdef->info allocation fails, */ + /* in which case jp2->color.jp2_cdef->info will be NULL => valid for destruction */ + jp2->color.jp2_cdef->info = (opj_jp2_cdef_info_t*) opj_malloc( + image->numcomps * sizeof(opj_jp2_cdef_info_t)); + if (!jp2->color.jp2_cdef->info) { + /* memory will be freed by opj_jp2_destroy */ + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to setup the JP2 encoder\n"); + return OPJ_FALSE; + } + jp2->color.jp2_cdef->n = (OPJ_UINT16) + image->numcomps; /* cast is valid : image->numcomps [1,16384] */ + for (i = 0U; i < color_channels; i++) { + jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16) + i; /* cast is valid : image->numcomps [1,16384] */ + jp2->color.jp2_cdef->info[i].typ = 0U; + jp2->color.jp2_cdef->info[i].asoc = (OPJ_UINT16)(i + + 1U); /* No overflow + cast is valid : image->numcomps [1,16384] */ + } + for (; i < image->numcomps; i++) { + if (image->comps[i].alpha != 0) { /* we'll be here exactly once */ + jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16) + i; /* cast is valid : image->numcomps [1,16384] */ + jp2->color.jp2_cdef->info[i].typ = 1U; /* Opacity channel */ + jp2->color.jp2_cdef->info[i].asoc = + 0U; /* Apply alpha channel to the whole image */ + } else { + /* Unknown channel */ + jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16) + i; /* cast is valid : image->numcomps [1,16384] */ + jp2->color.jp2_cdef->info[i].typ = 65535U; + jp2->color.jp2_cdef->info[i].asoc = 65535U; + } + } + } + + jp2->precedence = 0; /* PRECEDENCE */ + jp2->approx = 0; /* APPROX */ + + jp2->jpip_on = parameters->jpip_on; + + return OPJ_TRUE; +} + +OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager) +{ + return opj_j2k_encode(jp2->j2k, stream, p_manager); +} + +OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + /* customization of the end encoding */ + if (! opj_jp2_setup_end_header_reading(jp2, p_manager)) { + return OPJ_FALSE; + } + + /* write header */ + if (! opj_jp2_exec(jp2, jp2->m_procedure_list, cio, p_manager)) { + return OPJ_FALSE; + } + + return opj_j2k_end_decompress(jp2->j2k, cio, p_manager); +} + +OPJ_BOOL opj_jp2_end_compress(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + /* customization of the end encoding */ + if (! opj_jp2_setup_end_header_writing(jp2, p_manager)) { + return OPJ_FALSE; + } + + if (! opj_j2k_end_compress(jp2->j2k, cio, p_manager)) { + return OPJ_FALSE; + } + + /* write header */ + return opj_jp2_exec(jp2, jp2->m_procedure_list, cio, p_manager); +} + +static OPJ_BOOL opj_jp2_setup_end_header_writing(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + +#ifdef USE_JPIP + if (jp2->jpip_on) { + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jpip_write_iptr, p_manager)) { + return OPJ_FALSE; + } + } +#endif + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_write_jp2c, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom procedures */ +#ifdef USE_JPIP + if (jp2->jpip_on) { + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jpip_write_cidx, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jpip_write_fidx, p_manager)) { + return OPJ_FALSE; + } + } +#endif + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_setup_end_header_reading(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_read_header_procedure, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom procedures */ + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_default_validation(opj_jp2_t * jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager + ) +{ + OPJ_BOOL l_is_valid = OPJ_TRUE; + OPJ_UINT32 i; + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_manager); + + /* JPEG2000 codec validation */ + + /* STATE checking */ + /* make sure the state is at 0 */ + l_is_valid &= (jp2->jp2_state == JP2_STATE_NONE); + + /* make sure not reading a jp2h ???? WEIRD */ + l_is_valid &= (jp2->jp2_img_state == JP2_IMG_STATE_NONE); + + /* POINTER validation */ + /* make sure a j2k codec is present */ + l_is_valid &= (jp2->j2k != 00); + + /* make sure a procedure list is present */ + l_is_valid &= (jp2->m_procedure_list != 00); + + /* make sure a validation list is present */ + l_is_valid &= (jp2->m_validation_list != 00); + + /* PARAMETER VALIDATION */ + /* number of components */ + l_is_valid &= (jp2->numcl > 0); + /* width */ + l_is_valid &= (jp2->h > 0); + /* height */ + l_is_valid &= (jp2->w > 0); + /* precision */ + for (i = 0; i < jp2->numcomps; ++i) { + l_is_valid &= ((jp2->comps[i].bpcc & 0x7FU) < + 38U); /* 0 is valid, ignore sign for check */ + } + + /* METH */ + l_is_valid &= ((jp2->meth > 0) && (jp2->meth < 3)); + + /* stream validation */ + /* back and forth is needed */ + l_is_valid &= opj_stream_has_seek(cio); + + return l_is_valid; +} + +static OPJ_BOOL opj_jp2_read_header_procedure(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager + ) +{ + opj_jp2_box_t box; + OPJ_UINT32 l_nb_bytes_read; + const opj_jp2_header_handler_t * l_current_handler; + const opj_jp2_header_handler_t * l_current_handler_misplaced; + OPJ_UINT32 l_last_data_size = OPJ_BOX_SIZE; + OPJ_UINT32 l_current_data_size; + OPJ_BYTE * l_current_data = 00; + + /* preconditions */ + assert(stream != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + l_current_data = (OPJ_BYTE*)opj_calloc(1, l_last_data_size); + + if (l_current_data == 00) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to handle jpeg2000 file header\n"); + return OPJ_FALSE; + } + + while (opj_jp2_read_boxhdr(&box, &l_nb_bytes_read, stream, p_manager)) { + /* is it the codestream box ? */ + if (box.type == JP2_JP2C) { + if (jp2->jp2_state & JP2_STATE_HEADER) { + jp2->jp2_state |= JP2_STATE_CODESTREAM; + opj_free(l_current_data); + return OPJ_TRUE; + } else { + opj_event_msg(p_manager, EVT_ERROR, "bad placed jpeg codestream\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + } else if (box.length == 0) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + /* testcase 1851.pdf.SIGSEGV.ce9.948 */ + else if (box.length < l_nb_bytes_read) { + opj_event_msg(p_manager, EVT_ERROR, "invalid box size %d (%x)\n", box.length, + box.type); + opj_free(l_current_data); + return OPJ_FALSE; + } + + l_current_handler = opj_jp2_find_handler(box.type); + l_current_handler_misplaced = opj_jp2_img_find_handler(box.type); + l_current_data_size = box.length - l_nb_bytes_read; + + if ((l_current_handler != 00) || (l_current_handler_misplaced != 00)) { + if (l_current_handler == 00) { + opj_event_msg(p_manager, EVT_WARNING, + "Found a misplaced '%c%c%c%c' box outside jp2h box\n", + (OPJ_BYTE)(box.type >> 24), (OPJ_BYTE)(box.type >> 16), + (OPJ_BYTE)(box.type >> 8), (OPJ_BYTE)(box.type >> 0)); + if (jp2->jp2_state & JP2_STATE_HEADER) { + /* read anyway, we already have jp2h */ + l_current_handler = l_current_handler_misplaced; + } else { + opj_event_msg(p_manager, EVT_WARNING, + "JPEG2000 Header box not read yet, '%c%c%c%c' box will be ignored\n", + (OPJ_BYTE)(box.type >> 24), (OPJ_BYTE)(box.type >> 16), + (OPJ_BYTE)(box.type >> 8), (OPJ_BYTE)(box.type >> 0)); + jp2->jp2_state |= JP2_STATE_UNKNOWN; + if (opj_stream_skip(stream, l_current_data_size, + p_manager) != l_current_data_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Problem with skipping JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + continue; + } + } + if ((OPJ_OFF_T)l_current_data_size > opj_stream_get_number_byte_left(stream)) { + /* do not even try to malloc if we can't read */ + opj_event_msg(p_manager, EVT_ERROR, + "Invalid box size %d for box '%c%c%c%c'. Need %d bytes, %d bytes remaining \n", + box.length, (OPJ_BYTE)(box.type >> 24), (OPJ_BYTE)(box.type >> 16), + (OPJ_BYTE)(box.type >> 8), (OPJ_BYTE)(box.type >> 0), l_current_data_size, + (OPJ_UINT32)opj_stream_get_number_byte_left(stream)); + opj_free(l_current_data); + return OPJ_FALSE; + } + if (l_current_data_size > l_last_data_size) { + OPJ_BYTE* new_current_data = (OPJ_BYTE*)opj_realloc(l_current_data, + l_current_data_size); + if (!new_current_data) { + opj_free(l_current_data); + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to handle jpeg2000 box\n"); + return OPJ_FALSE; + } + l_current_data = new_current_data; + l_last_data_size = l_current_data_size; + } + + l_nb_bytes_read = (OPJ_UINT32)opj_stream_read_data(stream, l_current_data, + l_current_data_size, p_manager); + if (l_nb_bytes_read != l_current_data_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Problem with reading JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + + if (! l_current_handler->handler(jp2, l_current_data, l_current_data_size, + p_manager)) { + opj_free(l_current_data); + return OPJ_FALSE; + } + } else { + if (!(jp2->jp2_state & JP2_STATE_SIGNATURE)) { + opj_event_msg(p_manager, EVT_ERROR, + "Malformed JP2 file format: first box must be JPEG 2000 signature box\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + if (!(jp2->jp2_state & JP2_STATE_FILE_TYPE)) { + opj_event_msg(p_manager, EVT_ERROR, + "Malformed JP2 file format: second box must be file type box\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + jp2->jp2_state |= JP2_STATE_UNKNOWN; + if (opj_stream_skip(stream, l_current_data_size, + p_manager) != l_current_data_size) { + if (jp2->jp2_state & JP2_STATE_CODESTREAM) { + /* If we already read the codestream, do not error out */ + /* Needed for data/input/nonregression/issue254.jp2 */ + opj_event_msg(p_manager, EVT_WARNING, + "Problem with skipping JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_TRUE; + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Problem with skipping JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } + } + } + } + + opj_free(l_current_data); + + return OPJ_TRUE; +} + +/** + * Executes the given procedures on the given codec. + * + * @param p_procedure_list the list of procedures to execute + * @param jp2 the jpeg2000 file codec to execute the procedures on. + * @param stream the stream to execute the procedures on. + * @param p_manager the user manager. + * + * @return true if all the procedures were successfully executed. + */ +static OPJ_BOOL opj_jp2_exec(opj_jp2_t * jp2, + opj_procedure_list_t * p_procedure_list, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager + ) + +{ + OPJ_BOOL(** l_procedure)(opj_jp2_t * jp2, opj_stream_private_t *, + opj_event_mgr_t *) = 00; + OPJ_BOOL l_result = OPJ_TRUE; + OPJ_UINT32 l_nb_proc, i; + + /* preconditions */ + assert(p_procedure_list != 00); + assert(jp2 != 00); + assert(stream != 00); + assert(p_manager != 00); + + l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list); + l_procedure = (OPJ_BOOL(**)(opj_jp2_t * jp2, opj_stream_private_t *, + opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list); + + for (i = 0; i < l_nb_proc; ++i) { + l_result = l_result && (*l_procedure)(jp2, stream, p_manager); + ++l_procedure; + } + + /* and clear the procedure list at the end. */ + opj_procedure_list_clear(p_procedure_list); + return l_result; +} + +OPJ_BOOL opj_jp2_start_compress(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_image_t * p_image, + opj_event_mgr_t * p_manager + ) +{ + /* preconditions */ + assert(jp2 != 00); + assert(stream != 00); + assert(p_manager != 00); + + /* customization of the validation */ + if (! opj_jp2_setup_encoding_validation(jp2, p_manager)) { + return OPJ_FALSE; + } + + /* validation of the parameters codec */ + if (! opj_jp2_exec(jp2, jp2->m_validation_list, stream, p_manager)) { + return OPJ_FALSE; + } + + /* customization of the encoding */ + if (! opj_jp2_setup_header_writing(jp2, p_manager)) { + return OPJ_FALSE; + } + + /* write header */ + if (! opj_jp2_exec(jp2, jp2->m_procedure_list, stream, p_manager)) { + return OPJ_FALSE; + } + + return opj_j2k_start_compress(jp2->j2k, stream, p_image, p_manager); +} + +static const opj_jp2_header_handler_t * opj_jp2_find_handler(OPJ_UINT32 p_id) +{ + OPJ_UINT32 i, l_handler_size = sizeof(jp2_header) / sizeof( + opj_jp2_header_handler_t); + + for (i = 0; i < l_handler_size; ++i) { + if (jp2_header[i].id == p_id) { + return &jp2_header[i]; + } + } + return NULL; +} + +/** + * Finds the image execution function related to the given box id. + * + * @param p_id the id of the handler to fetch. + * + * @return the given handler or 00 if it could not be found. + */ +static const opj_jp2_header_handler_t * opj_jp2_img_find_handler( + OPJ_UINT32 p_id) +{ + OPJ_UINT32 i, l_handler_size = sizeof(jp2_img_header) / sizeof( + opj_jp2_header_handler_t); + for (i = 0; i < l_handler_size; ++i) { + if (jp2_img_header[i].id == p_id) { + return &jp2_img_header[i]; + } + } + + return NULL; +} + +/** + * Reads a jpeg2000 file signature box. + * + * @param p_header_data the data contained in the signature box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the signature box. + * @param p_manager the user event manager. + * + * @return true if the file signature box is valid. + */ +static OPJ_BOOL opj_jp2_read_jp(opj_jp2_t *jp2, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) + +{ + OPJ_UINT32 l_magic_number; + + /* preconditions */ + assert(p_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + if (jp2->jp2_state != JP2_STATE_NONE) { + opj_event_msg(p_manager, EVT_ERROR, + "The signature box must be the first box in the file.\n"); + return OPJ_FALSE; + } + + /* assure length of data is correct (4 -> magic number) */ + if (p_header_size != 4) { + opj_event_msg(p_manager, EVT_ERROR, "Error with JP signature Box size\n"); + return OPJ_FALSE; + } + + /* rearrange data */ + opj_read_bytes(p_header_data, &l_magic_number, 4); + if (l_magic_number != 0x0d0a870a) { + opj_event_msg(p_manager, EVT_ERROR, + "Error with JP Signature : bad magic number\n"); + return OPJ_FALSE; + } + + jp2->jp2_state |= JP2_STATE_SIGNATURE; + + return OPJ_TRUE; +} + +/** + * Reads a a FTYP box - File type box + * + * @param p_header_data the data contained in the FTYP box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the FTYP box. + * @param p_manager the user event manager. + * + * @return true if the FTYP box is valid. + */ +static OPJ_BOOL opj_jp2_read_ftyp(opj_jp2_t *jp2, + OPJ_BYTE * p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 i, l_remaining_bytes; + + /* preconditions */ + assert(p_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + if (jp2->jp2_state != JP2_STATE_SIGNATURE) { + opj_event_msg(p_manager, EVT_ERROR, + "The ftyp box must be the second box in the file.\n"); + return OPJ_FALSE; + } + + /* assure length of data is correct */ + if (p_header_size < 8) { + opj_event_msg(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_header_data, &jp2->brand, 4); /* BR */ + p_header_data += 4; + + opj_read_bytes(p_header_data, &jp2->minversion, 4); /* MinV */ + p_header_data += 4; + + l_remaining_bytes = p_header_size - 8; + + /* the number of remaining bytes should be a multiple of 4 */ + if ((l_remaining_bytes & 0x3) != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error with FTYP signature Box size\n"); + return OPJ_FALSE; + } + + /* div by 4 */ + jp2->numcl = l_remaining_bytes >> 2; + if (jp2->numcl) { + jp2->cl = (OPJ_UINT32 *) opj_calloc(jp2->numcl, sizeof(OPJ_UINT32)); + if (jp2->cl == 00) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory with FTYP Box\n"); + return OPJ_FALSE; + } + } + + for (i = 0; i < jp2->numcl; ++i) { + opj_read_bytes(p_header_data, &jp2->cl[i], 4); /* CLi */ + p_header_data += 4; + } + + jp2->jp2_state |= JP2_STATE_FILE_TYPE; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_skip_jp2c(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(stream != 00); + assert(p_manager != 00); + + jp2->j2k_codestream_offset = opj_stream_tell(stream); + + if (opj_stream_skip(stream, 8, p_manager) != 8) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jpip_skip_iptr(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(stream != 00); + assert(p_manager != 00); + + jp2->jpip_iptr_offset = opj_stream_tell(stream); + + if (opj_stream_skip(stream, 24, p_manager) != 24) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +/** + * Reads the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). + * + * @param p_header_data the data contained in the file header box. + * @param jp2 the jpeg2000 file codec. + * @param p_header_size the size of the data contained in the file header box. + * @param p_manager the user event manager. + * + * @return true if the JP2 Header box was successfully recognized. +*/ +static OPJ_BOOL opj_jp2_read_jp2h(opj_jp2_t *jp2, + OPJ_BYTE *p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_box_size = 0, l_current_data_size = 0; + opj_jp2_box_t box; + const opj_jp2_header_handler_t * l_current_handler; + OPJ_BOOL l_has_ihdr = 0; + + /* preconditions */ + assert(p_header_data != 00); + assert(jp2 != 00); + assert(p_manager != 00); + + /* make sure the box is well placed */ + if ((jp2->jp2_state & JP2_STATE_FILE_TYPE) != JP2_STATE_FILE_TYPE) { + opj_event_msg(p_manager, EVT_ERROR, + "The box must be the first box in the file.\n"); + return OPJ_FALSE; + } + + jp2->jp2_img_state = JP2_IMG_STATE_NONE; + + /* iterate while remaining data */ + while (p_header_size > 0) { + + if (! opj_jp2_read_boxhdr_char(&box, p_header_data, &l_box_size, p_header_size, + p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while reading JP2 Header box\n"); + return OPJ_FALSE; + } + + if (box.length > p_header_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while reading JP2 Header box: box length is inconsistent.\n"); + return OPJ_FALSE; + } + + l_current_handler = opj_jp2_img_find_handler(box.type); + l_current_data_size = box.length - l_box_size; + p_header_data += l_box_size; + + if (l_current_handler != 00) { + if (! l_current_handler->handler(jp2, p_header_data, l_current_data_size, + p_manager)) { + return OPJ_FALSE; + } + } else { + jp2->jp2_img_state |= JP2_IMG_STATE_UNKNOWN; + } + + if (box.type == JP2_IHDR) { + l_has_ihdr = 1; + } + + p_header_data += l_current_data_size; + p_header_size -= box.length; + } + + if (l_has_ihdr == 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Stream error while reading JP2 Header box: no 'ihdr' box.\n"); + return OPJ_FALSE; + } + + jp2->jp2_state |= JP2_STATE_HEADER; + jp2->has_jp2h = 1; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_read_boxhdr_char(opj_jp2_box_t *box, + OPJ_BYTE * p_data, + OPJ_UINT32 * p_number_bytes_read, + OPJ_UINT32 p_box_max_size, + opj_event_mgr_t * p_manager + ) +{ + OPJ_UINT32 l_value; + + /* preconditions */ + assert(p_data != 00); + assert(box != 00); + assert(p_number_bytes_read != 00); + assert(p_manager != 00); + + if (p_box_max_size < 8) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of less than 8 bytes\n"); + return OPJ_FALSE; + } + + /* process read data */ + opj_read_bytes(p_data, &l_value, 4); + p_data += 4; + box->length = (OPJ_UINT32)(l_value); + + opj_read_bytes(p_data, &l_value, 4); + p_data += 4; + box->type = (OPJ_UINT32)(l_value); + + *p_number_bytes_read = 8; + + /* do we have a "special very large box ?" */ + /* read then the XLBox */ + if (box->length == 1) { + OPJ_UINT32 l_xl_part_size; + + if (p_box_max_size < 16) { + opj_event_msg(p_manager, EVT_ERROR, + "Cannot handle XL box of less than 16 bytes\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_data, &l_xl_part_size, 4); + p_data += 4; + *p_number_bytes_read += 4; + + if (l_xl_part_size != 0) { + opj_event_msg(p_manager, EVT_ERROR, + "Cannot handle box sizes higher than 2^32\n"); + return OPJ_FALSE; + } + + opj_read_bytes(p_data, &l_value, 4); + *p_number_bytes_read += 4; + box->length = (OPJ_UINT32)(l_value); + + if (box->length == 0) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); + return OPJ_FALSE; + } + } else if (box->length == 0) { + opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); + return OPJ_FALSE; + } + if (box->length < *p_number_bytes_read) { + opj_event_msg(p_manager, EVT_ERROR, "Box length is inconsistent.\n"); + return OPJ_FALSE; + } + return OPJ_TRUE; +} + +OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream, + opj_jp2_t *jp2, + opj_image_t ** p_image, + opj_event_mgr_t * p_manager + ) +{ + int ret; + + /* preconditions */ + assert(jp2 != 00); + assert(p_stream != 00); + assert(p_manager != 00); + + /* customization of the validation */ + if (! opj_jp2_setup_decoding_validation(jp2, p_manager)) { + return OPJ_FALSE; + } + + /* customization of the encoding */ + if (! opj_jp2_setup_header_reading(jp2, p_manager)) { + return OPJ_FALSE; + } + + /* validation of the parameters codec */ + if (! opj_jp2_exec(jp2, jp2->m_validation_list, p_stream, p_manager)) { + return OPJ_FALSE; + } + + /* read header */ + if (! opj_jp2_exec(jp2, jp2->m_procedure_list, p_stream, p_manager)) { + return OPJ_FALSE; + } + if (jp2->has_jp2h == 0) { + opj_event_msg(p_manager, EVT_ERROR, "JP2H box missing. Required.\n"); + return OPJ_FALSE; + } + if (jp2->has_ihdr == 0) { + opj_event_msg(p_manager, EVT_ERROR, "IHDR box_missing. Required.\n"); + return OPJ_FALSE; + } + + ret = opj_j2k_read_header(p_stream, + jp2->j2k, + p_image, + p_manager); + + if (ret && p_image && *p_image) { + /* Set Image Color Space */ + if (jp2->enumcs == 16) { + (*p_image)->color_space = OPJ_CLRSPC_SRGB; + } else if (jp2->enumcs == 17) { + (*p_image)->color_space = OPJ_CLRSPC_GRAY; + } else if (jp2->enumcs == 18) { + (*p_image)->color_space = OPJ_CLRSPC_SYCC; + } else if (jp2->enumcs == 24) { + (*p_image)->color_space = OPJ_CLRSPC_EYCC; + } else if (jp2->enumcs == 12) { + (*p_image)->color_space = OPJ_CLRSPC_CMYK; + } else { + (*p_image)->color_space = OPJ_CLRSPC_UNKNOWN; + } + + if (jp2->color.icc_profile_buf) { + (*p_image)->icc_profile_buf = jp2->color.icc_profile_buf; + (*p_image)->icc_profile_len = jp2->color.icc_profile_len; + jp2->color.icc_profile_buf = NULL; + } + } + return ret; +} + +static OPJ_BOOL opj_jp2_setup_encoding_validation(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(jp2->m_validation_list, + (opj_procedure)opj_jp2_default_validation, p_manager)) { + return OPJ_FALSE; + } + /* DEVELOPER CORNER, add your custom validation procedure */ + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_setup_decoding_validation(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + + OPJ_UNUSED(jp2); + OPJ_UNUSED(p_manager); + + /* DEVELOPER CORNER, add your custom validation procedure */ + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_setup_header_writing(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_write_jp, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_write_ftyp, p_manager)) { + return OPJ_FALSE; + } + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_write_jp2h, p_manager)) { + return OPJ_FALSE; + } + if (jp2->jpip_on) { + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jpip_skip_iptr, p_manager)) { + return OPJ_FALSE; + } + } + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_skip_jp2c, p_manager)) { + return OPJ_FALSE; + } + + /* DEVELOPER CORNER, insert your custom procedures */ + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2, + opj_event_mgr_t * p_manager) +{ + /* preconditions */ + assert(jp2 != 00); + assert(p_manager != 00); + + if (! opj_procedure_list_add_procedure(jp2->m_procedure_list, + (opj_procedure)opj_jp2_read_header_procedure, p_manager)) { + return OPJ_FALSE; + } + + /* DEVELOPER CORNER, add your custom procedures */ + + return OPJ_TRUE; +} + +OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + return opj_j2k_read_tile_header(p_jp2->j2k, + p_tile_index, + p_data_size, + p_tile_x0, p_tile_y0, + p_tile_x1, p_tile_y1, + p_nb_comps, + p_go_on, + p_stream, + p_manager); +} + +OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) + +{ + return opj_j2k_write_tile(p_jp2->j2k, p_tile_index, p_data, p_data_size, + p_stream, p_manager); +} + +OPJ_BOOL opj_jp2_decode_tile(opj_jp2_t * p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager + ) +{ + return opj_j2k_decode_tile(p_jp2->j2k, p_tile_index, p_data, p_data_size, + p_stream, p_manager); +} + +void opj_jp2_destroy(opj_jp2_t *jp2) +{ + if (jp2) { + /* destroy the J2K codec */ + opj_j2k_destroy(jp2->j2k); + jp2->j2k = 00; + + if (jp2->comps) { + opj_free(jp2->comps); + jp2->comps = 00; + } + + if (jp2->cl) { + opj_free(jp2->cl); + jp2->cl = 00; + } + + if (jp2->color.icc_profile_buf) { + opj_free(jp2->color.icc_profile_buf); + jp2->color.icc_profile_buf = 00; + } + + if (jp2->color.jp2_cdef) { + if (jp2->color.jp2_cdef->info) { + opj_free(jp2->color.jp2_cdef->info); + jp2->color.jp2_cdef->info = NULL; + } + + opj_free(jp2->color.jp2_cdef); + jp2->color.jp2_cdef = 00; + } + + if (jp2->color.jp2_pclr) { + if (jp2->color.jp2_pclr->cmap) { + opj_free(jp2->color.jp2_pclr->cmap); + jp2->color.jp2_pclr->cmap = NULL; + } + if (jp2->color.jp2_pclr->channel_sign) { + opj_free(jp2->color.jp2_pclr->channel_sign); + jp2->color.jp2_pclr->channel_sign = NULL; + } + if (jp2->color.jp2_pclr->channel_size) { + opj_free(jp2->color.jp2_pclr->channel_size); + jp2->color.jp2_pclr->channel_size = NULL; + } + if (jp2->color.jp2_pclr->entries) { + opj_free(jp2->color.jp2_pclr->entries); + jp2->color.jp2_pclr->entries = NULL; + } + + opj_free(jp2->color.jp2_pclr); + jp2->color.jp2_pclr = 00; + } + + if (jp2->m_validation_list) { + opj_procedure_list_destroy(jp2->m_validation_list); + jp2->m_validation_list = 00; + } + + if (jp2->m_procedure_list) { + opj_procedure_list_destroy(jp2->m_procedure_list); + jp2->m_procedure_list = 00; + } + + opj_free(jp2); + } +} + +OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *p_jp2, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager) +{ + return opj_j2k_set_decoded_components(p_jp2->j2k, + numcomps, comps_indices, + p_manager); +} + +OPJ_BOOL opj_jp2_set_decode_area(opj_jp2_t *p_jp2, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + opj_event_mgr_t * p_manager + ) +{ + return opj_j2k_set_decode_area(p_jp2->j2k, p_image, p_start_x, p_start_y, + p_end_x, p_end_y, p_manager); +} + +OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager, + OPJ_UINT32 tile_index + ) +{ + if (!p_image) { + return OPJ_FALSE; + } + + opj_event_msg(p_manager, EVT_WARNING, + "JP2 box which are after the codestream will not be read by this function.\n"); + + if (! opj_j2k_get_tile(p_jp2->j2k, p_stream, p_image, p_manager, tile_index)) { + opj_event_msg(p_manager, EVT_ERROR, + "Failed to decode the codestream in the JP2 file\n"); + return OPJ_FALSE; + } + + return opj_jp2_apply_color_postprocessing(p_jp2, p_image, p_manager); +} + +/* ----------------------------------------------------------------------- */ +/* JP2 encoder interface */ +/* ----------------------------------------------------------------------- */ + +opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder) +{ + opj_jp2_t *jp2 = (opj_jp2_t*)opj_calloc(1, sizeof(opj_jp2_t)); + if (jp2) { + + /* create the J2K codec */ + if (! p_is_decoder) { + jp2->j2k = opj_j2k_create_compress(); + } else { + jp2->j2k = opj_j2k_create_decompress(); + } + + if (jp2->j2k == 00) { + opj_jp2_destroy(jp2); + return 00; + } + + /* Color structure */ + jp2->color.icc_profile_buf = NULL; + jp2->color.icc_profile_len = 0; + jp2->color.jp2_cdef = NULL; + jp2->color.jp2_pclr = NULL; + jp2->color.jp2_has_colr = 0; + + /* validation list creation */ + jp2->m_validation_list = opj_procedure_list_create(); + if (! jp2->m_validation_list) { + opj_jp2_destroy(jp2); + return 00; + } + + /* execution list creation */ + jp2->m_procedure_list = opj_procedure_list_create(); + if (! jp2->m_procedure_list) { + opj_jp2_destroy(jp2); + return 00; + } + } + + return jp2; +} + +void jp2_dump(opj_jp2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream) +{ + /* preconditions */ + assert(p_jp2 != 00); + + j2k_dump(p_jp2->j2k, + flag, + out_stream); +} + +opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_t* p_jp2) +{ + return j2k_get_cstr_index(p_jp2->j2k); +} + +opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_t* p_jp2) +{ + return j2k_get_cstr_info(p_jp2->j2k); +} + +OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager) +{ + return opj_j2k_set_decoded_resolution_factor(p_jp2->j2k, res_factor, p_manager); +} + +/* ----------------------------------------------------------------------- */ + +OPJ_BOOL opj_jp2_encoder_set_extra_options( + opj_jp2_t *p_jp2, + const char* const* p_options, + opj_event_mgr_t * p_manager) +{ + return opj_j2k_encoder_set_extra_options(p_jp2->j2k, p_options, p_manager); +} + +/* ----------------------------------------------------------------------- */ + +/* JPIP specific */ + +#ifdef USE_JPIP +static OPJ_BOOL opj_jpip_write_iptr(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_OFF_T j2k_codestream_exit; + OPJ_BYTE l_data_header [24]; + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + assert(opj_stream_has_seek(cio)); + + j2k_codestream_exit = opj_stream_tell(cio); + opj_write_bytes(l_data_header, 24, 4); /* size of iptr */ + opj_write_bytes(l_data_header + 4, JPIP_IPTR, + 4); /* IPTR */ +#if 0 + opj_write_bytes(l_data_header + 4 + 4, 0, 8); /* offset */ + opj_write_bytes(l_data_header + 8 + 8, 0, 8); /* length */ +#else + opj_write_double(l_data_header + 4 + 4, 0); /* offset */ + opj_write_double(l_data_header + 8 + 8, 0); /* length */ +#endif + + if (! opj_stream_seek(cio, jp2->jpip_iptr_offset, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + if (opj_stream_write_data(cio, l_data_header, 24, p_manager) != 24) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jpip_write_fidx(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_OFF_T j2k_codestream_exit; + OPJ_BYTE l_data_header [24]; + + OPJ_UNUSED(jp2); + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + assert(opj_stream_has_seek(cio)); + + opj_write_bytes(l_data_header, 24, 4); /* size of iptr */ + opj_write_bytes(l_data_header + 4, JPIP_FIDX, + 4); /* IPTR */ + opj_write_double(l_data_header + 4 + 4, 0); /* offset */ + opj_write_double(l_data_header + 8 + 8, 0); /* length */ + + if (opj_stream_write_data(cio, l_data_header, 24, p_manager) != 24) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + j2k_codestream_exit = opj_stream_tell(cio); + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_jpip_write_cidx(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_OFF_T j2k_codestream_exit; + OPJ_BYTE l_data_header [24]; + + OPJ_UNUSED(jp2); + + /* preconditions */ + assert(jp2 != 00); + assert(cio != 00); + assert(p_manager != 00); + assert(opj_stream_has_seek(cio)); + + j2k_codestream_exit = opj_stream_tell(cio); + opj_write_bytes(l_data_header, 24, 4); /* size of iptr */ + opj_write_bytes(l_data_header + 4, JPIP_CIDX, + 4); /* IPTR */ +#if 0 + opj_write_bytes(l_data_header + 4 + 4, 0, 8); /* offset */ + opj_write_bytes(l_data_header + 8 + 8, 0, 8); /* length */ +#else + opj_write_double(l_data_header + 4 + 4, 0); /* offset */ + opj_write_double(l_data_header + 8 + 8, 0); /* length */ +#endif + + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + if (opj_stream_write_data(cio, l_data_header, 24, p_manager) != 24) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + j2k_codestream_exit = opj_stream_tell(cio); + if (! opj_stream_seek(cio, j2k_codestream_exit, p_manager)) { + opj_event_msg(p_manager, EVT_ERROR, "Failed to seek in the stream.\n"); + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +#if 0 +static void write_prxy(int offset_jp2c, int length_jp2c, int offset_idx, + int length_idx, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [8]; + OPJ_OFF_T len, lenp; + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_PRXY, 4); /* IPTR */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + opj_write_bytes(l_data_header, offset_jp2c, 8); /* OOFF */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + opj_write_bytes(l_data_header, length_jp2c, 4); /* OBH part 1 */ + opj_write_bytes(l_data_header + 4, JP2_JP2C, 4); /* OBH part 2 */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + + opj_write_bytes(l_data_header, 1, 1); /* NI */ + opj_stream_write_data(cio, l_data_header, 1, p_manager); + + opj_write_bytes(l_data_header, offset_idx, 8); /* IOFF */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + opj_write_bytes(l_data_header, length_idx, 4); /* IBH part 1 */ + opj_write_bytes(l_data_header + 4, JPIP_CIDX, 4); /* IBH part 2 */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + + len = opj_stream_tell(cio) - lenp; + opj_stream_skip(cio, lenp, p_manager); + opj_write_bytes(l_data_header, len, 4); /* L */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + opj_stream_seek(cio, lenp + len, p_manager); +} +#endif + + +#if 0 +static int write_fidx(int offset_jp2c, int length_jp2c, int offset_idx, + int length_idx, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [4]; + OPJ_OFF_T len, lenp; + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); + opj_write_bytes(l_data_header, JPIP_FIDX, 4); /* FIDX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + write_prxy(offset_jp2c, length_jp2c, offset_idx, length_idx, cio, p_manager); + + len = opj_stream_tell(cio) - lenp; + opj_stream_skip(cio, lenp, p_manager); + opj_write_bytes(l_data_header, len, 4); /* L */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + opj_stream_seek(cio, lenp + len, p_manager); + + return len; +} +#endif +#endif /* USE_JPIP */ diff --git a/client/deps/openjpeg/jp2.h b/client/deps/openjpeg/jp2.h new file mode 100644 index 000000000..173f25119 --- /dev/null +++ b/client/deps/openjpeg/jp2.h @@ -0,0 +1,521 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_JP2_H +#define OPJ_JP2_H +/** +@file jp2.h +@brief The JPEG-2000 file format Reader/Writer (JP2) + +*/ + +/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ +/*@{*/ + +/*#define JPIP_JPIP 0x6a706970*/ + +#define JP2_JP 0x6a502020 /**< JPEG 2000 signature box */ +#define JP2_FTYP 0x66747970 /**< File type box */ +#define JP2_JP2H 0x6a703268 /**< JP2 header box (super-box) */ +#define JP2_IHDR 0x69686472 /**< Image header box */ +#define JP2_COLR 0x636f6c72 /**< Colour specification box */ +#define JP2_JP2C 0x6a703263 /**< Contiguous codestream box */ +#define JP2_URL 0x75726c20 /**< Data entry URL box */ +#define JP2_PCLR 0x70636c72 /**< Palette box */ +#define JP2_CMAP 0x636d6170 /**< Component Mapping box */ +#define JP2_CDEF 0x63646566 /**< Channel Definition box */ +#define JP2_DTBL 0x6474626c /**< Data Reference box */ +#define JP2_BPCC 0x62706363 /**< Bits per component box */ +#define JP2_JP2 0x6a703220 /**< File type fields */ + +/* For the future */ +/* #define JP2_RES 0x72657320 */ /**< Resolution box (super-box) */ +/* #define JP2_JP2I 0x6a703269 */ /**< Intellectual property box */ +/* #define JP2_XML 0x786d6c20 */ /**< XML box */ +/* #define JP2_UUID 0x75756994 */ /**< UUID box */ +/* #define JP2_UINF 0x75696e66 */ /**< UUID info box (super-box) */ +/* #define JP2_ULST 0x756c7374 */ /**< UUID list box */ + +/* ----------------------------------------------------------------------- */ + +typedef enum { + JP2_STATE_NONE = 0x0, + JP2_STATE_SIGNATURE = 0x1, + JP2_STATE_FILE_TYPE = 0x2, + JP2_STATE_HEADER = 0x4, + JP2_STATE_CODESTREAM = 0x8, + JP2_STATE_END_CODESTREAM = 0x10, + JP2_STATE_UNKNOWN = 0x7fffffff /* ISO C restricts enumerator values to range of 'int' */ +} +JP2_STATE; + +typedef enum { + JP2_IMG_STATE_NONE = 0x0, + JP2_IMG_STATE_UNKNOWN = 0x7fffffff +} +JP2_IMG_STATE; + +/** +Channel description: channel index, type, association +*/ +typedef struct opj_jp2_cdef_info { + OPJ_UINT16 cn, typ, asoc; +} opj_jp2_cdef_info_t; + +/** +Channel descriptions and number of descriptions +*/ +typedef struct opj_jp2_cdef { + opj_jp2_cdef_info_t *info; + OPJ_UINT16 n; +} opj_jp2_cdef_t; + +/** +Component mappings: channel index, mapping type, palette index +*/ +typedef struct opj_jp2_cmap_comp { + OPJ_UINT16 cmp; + OPJ_BYTE mtyp, pcol; +} opj_jp2_cmap_comp_t; + +/** +Palette data: table entries, palette columns +*/ +typedef struct opj_jp2_pclr { + OPJ_UINT32 *entries; + OPJ_BYTE *channel_sign; + OPJ_BYTE *channel_size; + opj_jp2_cmap_comp_t *cmap; + OPJ_UINT16 nr_entries; + OPJ_BYTE nr_channels; +} opj_jp2_pclr_t; + +/** +Collector for ICC profile, palette, component mapping, channel description +*/ +typedef struct opj_jp2_color { + OPJ_BYTE *icc_profile_buf; + OPJ_UINT32 icc_profile_len; + + opj_jp2_cdef_t *jp2_cdef; + opj_jp2_pclr_t *jp2_pclr; + OPJ_BYTE jp2_has_colr; +} opj_jp2_color_t; + +/** +JP2 component +*/ +typedef struct opj_jp2_comps { + OPJ_UINT32 depth; + OPJ_UINT32 sgnd; + OPJ_UINT32 bpcc; +} opj_jp2_comps_t; + +/** +JPEG-2000 file format reader/writer +*/ +typedef struct opj_jp2 { + /** handle to the J2K codec */ + opj_j2k_t *j2k; + /** list of validation procedures */ + struct opj_procedure_list * m_validation_list; + /** list of execution procedures */ + struct opj_procedure_list * m_procedure_list; + + /* width of image */ + OPJ_UINT32 w; + /* height of image */ + OPJ_UINT32 h; + /* number of components in the image */ + OPJ_UINT32 numcomps; + OPJ_UINT32 bpc; + OPJ_UINT32 C; + OPJ_UINT32 UnkC; + OPJ_UINT32 IPR; + OPJ_UINT32 meth; + OPJ_UINT32 approx; + OPJ_UINT32 enumcs; + OPJ_UINT32 precedence; + OPJ_UINT32 brand; + OPJ_UINT32 minversion; + OPJ_UINT32 numcl; + OPJ_UINT32 *cl; + opj_jp2_comps_t *comps; + /* FIXME: The following two variables are used to save offset + as we write out a JP2 file to disk. This mechanism is not flexible + as codec writers will need to extand those fields as new part + of the standard are implemented. + */ + OPJ_OFF_T j2k_codestream_offset; + OPJ_OFF_T jpip_iptr_offset; + OPJ_BOOL jpip_on; + OPJ_UINT32 jp2_state; + OPJ_UINT32 jp2_img_state; + + opj_jp2_color_t color; + + OPJ_BOOL ignore_pclr_cmap_cdef; + OPJ_BYTE has_jp2h; + OPJ_BYTE has_ihdr; +} +opj_jp2_t; + +/** +JP2 Box +*/ +typedef struct opj_jp2_box { + OPJ_UINT32 length; + OPJ_UINT32 type; + OPJ_INT32 init_pos; +} opj_jp2_box_t; + +typedef struct opj_jp2_header_handler { + /* marker value */ + OPJ_UINT32 id; + /* action linked to the marker */ + OPJ_BOOL(*handler)(opj_jp2_t *jp2, + OPJ_BYTE *p_header_data, + OPJ_UINT32 p_header_size, + opj_event_mgr_t * p_manager); +} +opj_jp2_header_handler_t; + + +typedef struct opj_jp2_img_header_writer_handler { + /* action to perform */ + OPJ_BYTE* (*handler)(opj_jp2_t *jp2, OPJ_UINT32 * p_data_size); + /* result of the action : data */ + OPJ_BYTE* m_data; + /* size of data */ + OPJ_UINT32 m_size; +} +opj_jp2_img_header_writer_handler_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Setup the decoder decoding parameters using user parameters. +Decoding parameters are returned in jp2->j2k->cp. +@param jp2 JP2 decompressor handle +@param parameters decompression parameters +*/ +void opj_jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters); + +/** +Set the strict mode parameter. When strict mode is enabled, the entire +bitstream must be decoded or an error is returned. When it is disabled, +the decoder will decode partial bitstreams. +@param jp2 JP2 decompressor handle +@param strict OPJ_TRUE for strict mode +*/ +void opj_jp2_decoder_set_strict_mode(opj_jp2_t *jp2, OPJ_BOOL strict); + +/** Allocates worker threads for the compressor/decompressor. + * + * @param jp2 JP2 decompressor handle + * @param num_threads Number of threads. + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads); + +/** + * Decode an image from a JPEG-2000 file stream + * @param jp2 JP2 decompressor handle + * @param p_stream FIXME DOC + * @param p_image FIXME DOC + * @param p_manager FIXME DOC + * + * @return Returns a decoded image if successful, returns NULL otherwise +*/ +OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager); + +/** + * Setup the encoder parameters using the current image and using user parameters. + * Coding parameters are returned in jp2->j2k->cp. + * + * @param jp2 JP2 compressor handle + * @param parameters compression parameters + * @param image input filled image + * @param p_manager FIXME DOC + * @return OPJ_TRUE if successful, OPJ_FALSE otherwise +*/ +OPJ_BOOL opj_jp2_setup_encoder(opj_jp2_t *jp2, + opj_cparameters_t *parameters, + opj_image_t *image, + opj_event_mgr_t * p_manager); + +/** +Encode an image into a JPEG-2000 file stream +@param jp2 JP2 compressor handle +@param stream Output buffer stream +@param p_manager event manager +@return Returns true if successful, returns false otherwise +*/ +OPJ_BOOL opj_jp2_encode(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_event_mgr_t * p_manager); + + +/** + * Starts a compression scheme, i.e. validates the codec parameters, writes the header. + * + * @param jp2 the jpeg2000 file codec. + * @param stream the stream object. + * @param p_image FIXME DOC + * @param p_manager FIXME DOC + * + * @return true if the codec is valid. + */ +OPJ_BOOL opj_jp2_start_compress(opj_jp2_t *jp2, + opj_stream_private_t *stream, + opj_image_t * p_image, + opj_event_mgr_t * p_manager); + + +/** + * Ends the compression procedures and possibiliy add data to be read after the + * codestream. + */ +OPJ_BOOL opj_jp2_end_compress(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/* ----------------------------------------------------------------------- */ + +/** + * Ends the decompression procedures and possibiliy add data to be read after the + * codestream. + */ +OPJ_BOOL opj_jp2_end_decompress(opj_jp2_t *jp2, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/** + * Reads a jpeg2000 file header structure. + * + * @param p_stream the stream to read data from. + * @param jp2 the jpeg2000 file header structure. + * @param p_image FIXME DOC + * @param p_manager the user event manager. + * + * @return true if the box is valid. + */ +OPJ_BOOL opj_jp2_read_header(opj_stream_private_t *p_stream, + opj_jp2_t *jp2, + opj_image_t ** p_image, + opj_event_mgr_t * p_manager); + +/** Sets the indices of the components to decode. + * + * @param jp2 JP2 decompressor handle + * @param numcomps Number of components to decode. + * @param comps_indices Array of num_compts indices (numbering starting at 0) + * corresponding to the components to decode. + * @param p_manager Event manager; + * + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *jp2, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager); + +/** + * Reads a tile header. + * @param p_jp2 the jpeg2000 codec. + * @param p_tile_index FIXME DOC + * @param p_data_size FIXME DOC + * @param p_tile_x0 FIXME DOC + * @param p_tile_y0 FIXME DOC + * @param p_tile_x1 FIXME DOC + * @param p_tile_y1 FIXME DOC + * @param p_nb_comps FIXME DOC + * @param p_go_on FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +OPJ_BOOL opj_jp2_read_tile_header(opj_jp2_t * p_jp2, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_go_on, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Writes a tile. + * + * @param p_jp2 the jpeg2000 codec. + * @param p_tile_index FIXME DOC + * @param p_data FIXME DOC + * @param p_data_size FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + */ +OPJ_BOOL opj_jp2_write_tile(opj_jp2_t *p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Decode tile data. + * @param p_jp2 the jpeg2000 codec. + * @param p_tile_index FIXME DOC + * @param p_data FIXME DOC + * @param p_data_size FIXME DOC + * @param p_stream the stream to write data to. + * @param p_manager the user event manager. + * + * @return FIXME DOC + */ +OPJ_BOOL opj_jp2_decode_tile(opj_jp2_t * p_jp2, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_private_t *p_stream, + opj_event_mgr_t * p_manager); + +/** + * Creates a jpeg2000 file decompressor. + * + * @return an empty jpeg2000 file codec. + */ +opj_jp2_t* opj_jp2_create(OPJ_BOOL p_is_decoder); + +/** +Destroy a JP2 decompressor handle +@param jp2 JP2 decompressor handle to destroy +*/ +void opj_jp2_destroy(opj_jp2_t *jp2); + + +/** + * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. + * + * @param p_jp2 the jpeg2000 codec. + * @param p_image FIXME DOC + * @param p_start_x the left position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * @param p_manager the user event manager + * + * @return true if the area could be set. + */ +OPJ_BOOL opj_jp2_set_decode_area(opj_jp2_t *p_jp2, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, + opj_event_mgr_t * p_manager); + +/** +* +*/ +OPJ_BOOL opj_jp2_get_tile(opj_jp2_t *p_jp2, + opj_stream_private_t *p_stream, + opj_image_t* p_image, + opj_event_mgr_t * p_manager, + OPJ_UINT32 tile_index); + + +/** + * + */ +OPJ_BOOL opj_jp2_set_decoded_resolution_factor(opj_jp2_t *p_jp2, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager); + +/** + * Specify extra options for the encoder. + * + * @param p_jp2 the jpeg2000 codec. + * @param p_options options + * @param p_manager the user event manager + * + * @see opj_encoder_set_extra_options() for more details. + */ +OPJ_BOOL opj_jp2_encoder_set_extra_options( + opj_jp2_t *p_jp2, + const char* const* p_options, + opj_event_mgr_t * p_manager); + + +/* TODO MSD: clean these 3 functions */ +/** + * Dump some elements from the JP2 decompression structure . + * + *@param p_jp2 the jp2 codec. + *@param flag flag to describe what elements are dump. + *@param out_stream output stream where dump the elements. + * +*/ +void jp2_dump(opj_jp2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream); + +/** + * Get the codestream info from a JPEG2000 codec. + * + *@param p_jp2 jp2 codec. + * + *@return the codestream information extract from the jpg2000 codec + */ +opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_t* p_jp2); + +/** + * Get the codestream index from a JPEG2000 codec. + * + *@param p_jp2 jp2 codec. + * + *@return the codestream index extract from the jpg2000 codec + */ +opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_t* p_jp2); + + +/*@}*/ + +/*@}*/ + +#endif /* OPJ_JP2_H */ + diff --git a/client/deps/openjpeg/mct.c b/client/deps/openjpeg/mct.c new file mode 100644 index 000000000..780581280 --- /dev/null +++ b/client/deps/openjpeg/mct.c @@ -0,0 +1,464 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifdef __SSE__ +#include +#endif +#ifdef __SSE2__ +#include +#endif +#ifdef __SSE4_1__ +#include +#endif + +#include "opj_includes.h" + +/* */ +/* This table contains the norms of the basis function of the reversible MCT. */ +/* */ +static const OPJ_FLOAT64 opj_mct_norms[3] = { 1.732, .8292, .8292 }; + +/* */ +/* This table contains the norms of the basis function of the irreversible MCT. */ +/* */ +static const OPJ_FLOAT64 opj_mct_norms_real[3] = { 1.732, 1.805, 1.573 }; + +const OPJ_FLOAT64 * opj_mct_get_mct_norms() +{ + return opj_mct_norms; +} + +const OPJ_FLOAT64 * opj_mct_get_mct_norms_real() +{ + return opj_mct_norms_real; +} + +/* */ +/* Forward reversible MCT. */ +/* */ +#ifdef __SSE2__ +void opj_mct_encode( + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) +{ + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + /* buffer are aligned on 16 bytes */ + assert(((size_t)c0 & 0xf) == 0); + assert(((size_t)c1 & 0xf) == 0); + assert(((size_t)c2 & 0xf) == 0); + + for (i = 0; i < (len & ~3U); i += 4) { + __m128i y, u, v; + __m128i r = _mm_load_si128((const __m128i *) & (c0[i])); + __m128i g = _mm_load_si128((const __m128i *) & (c1[i])); + __m128i b = _mm_load_si128((const __m128i *) & (c2[i])); + y = _mm_add_epi32(g, g); + y = _mm_add_epi32(y, b); + y = _mm_add_epi32(y, r); + y = _mm_srai_epi32(y, 2); + u = _mm_sub_epi32(b, g); + v = _mm_sub_epi32(r, g); + _mm_store_si128((__m128i *) & (c0[i]), y); + _mm_store_si128((__m128i *) & (c1[i]), u); + _mm_store_si128((__m128i *) & (c2[i]), v); + } + + for (; i < len; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = (r + (g * 2) + b) >> 2; + OPJ_INT32 u = b - g; + OPJ_INT32 v = r - g; + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} +#else +void opj_mct_encode( + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) +{ + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + + for (i = 0; i < len; ++i) { + OPJ_INT32 r = c0[i]; + OPJ_INT32 g = c1[i]; + OPJ_INT32 b = c2[i]; + OPJ_INT32 y = (r + (g * 2) + b) >> 2; + OPJ_INT32 u = b - g; + OPJ_INT32 v = r - g; + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} +#endif + +/* */ +/* Inverse reversible MCT. */ +/* */ +#ifdef __SSE2__ +void opj_mct_decode( + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) +{ + OPJ_SIZE_T i; + const OPJ_SIZE_T len = n; + + for (i = 0; i < (len & ~3U); i += 4) { + __m128i r, g, b; + __m128i y = _mm_load_si128((const __m128i *) & (c0[i])); + __m128i u = _mm_load_si128((const __m128i *) & (c1[i])); + __m128i v = _mm_load_si128((const __m128i *) & (c2[i])); + g = y; + g = _mm_sub_epi32(g, _mm_srai_epi32(_mm_add_epi32(u, v), 2)); + r = _mm_add_epi32(v, g); + b = _mm_add_epi32(u, g); + _mm_store_si128((__m128i *) & (c0[i]), r); + _mm_store_si128((__m128i *) & (c1[i]), g); + _mm_store_si128((__m128i *) & (c2[i]), b); + } + for (; i < len; ++i) { + OPJ_INT32 y = c0[i]; + OPJ_INT32 u = c1[i]; + OPJ_INT32 v = c2[i]; + OPJ_INT32 g = y - ((u + v) >> 2); + OPJ_INT32 r = v + g; + OPJ_INT32 b = u + g; + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} +#else +void opj_mct_decode( + OPJ_INT32* OPJ_RESTRICT c0, + OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) +{ + OPJ_SIZE_T i; + for (i = 0; i < n; ++i) { + OPJ_INT32 y = c0[i]; + OPJ_INT32 u = c1[i]; + OPJ_INT32 v = c2[i]; + OPJ_INT32 g = y - ((u + v) >> 2); + OPJ_INT32 r = v + g; + OPJ_INT32 b = u + g; + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} +#endif + +/* */ +/* Get norm of basis function of reversible MCT. */ +/* */ +OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno) +{ + return opj_mct_norms[compno]; +} + +/* */ +/* Forward irreversible MCT. */ +/* */ +void opj_mct_encode_real( + OPJ_FLOAT32* OPJ_RESTRICT c0, + OPJ_FLOAT32* OPJ_RESTRICT c1, + OPJ_FLOAT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) +{ + OPJ_SIZE_T i; +#ifdef __SSE__ + const __m128 YR = _mm_set1_ps(0.299f); + const __m128 YG = _mm_set1_ps(0.587f); + const __m128 YB = _mm_set1_ps(0.114f); + const __m128 UR = _mm_set1_ps(-0.16875f); + const __m128 UG = _mm_set1_ps(-0.331260f); + const __m128 UB = _mm_set1_ps(0.5f); + const __m128 VR = _mm_set1_ps(0.5f); + const __m128 VG = _mm_set1_ps(-0.41869f); + const __m128 VB = _mm_set1_ps(-0.08131f); + for (i = 0; i < (n >> 3); i ++) { + __m128 r, g, b, y, u, v; + + r = _mm_load_ps(c0); + g = _mm_load_ps(c1); + b = _mm_load_ps(c2); + y = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, YR), _mm_mul_ps(g, YG)), + _mm_mul_ps(b, YB)); + u = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, UR), _mm_mul_ps(g, UG)), + _mm_mul_ps(b, UB)); + v = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, VR), _mm_mul_ps(g, VG)), + _mm_mul_ps(b, VB)); + _mm_store_ps(c0, y); + _mm_store_ps(c1, u); + _mm_store_ps(c2, v); + c0 += 4; + c1 += 4; + c2 += 4; + + r = _mm_load_ps(c0); + g = _mm_load_ps(c1); + b = _mm_load_ps(c2); + y = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, YR), _mm_mul_ps(g, YG)), + _mm_mul_ps(b, YB)); + u = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, UR), _mm_mul_ps(g, UG)), + _mm_mul_ps(b, UB)); + v = _mm_add_ps(_mm_add_ps(_mm_mul_ps(r, VR), _mm_mul_ps(g, VG)), + _mm_mul_ps(b, VB)); + _mm_store_ps(c0, y); + _mm_store_ps(c1, u); + _mm_store_ps(c2, v); + c0 += 4; + c1 += 4; + c2 += 4; + } + n &= 7; +#endif + for (i = 0; i < n; ++i) { + OPJ_FLOAT32 r = c0[i]; + OPJ_FLOAT32 g = c1[i]; + OPJ_FLOAT32 b = c2[i]; + OPJ_FLOAT32 y = 0.299f * r + 0.587f * g + 0.114f * b; + OPJ_FLOAT32 u = -0.16875f * r - 0.331260f * g + 0.5f * b; + OPJ_FLOAT32 v = 0.5f * r - 0.41869f * g - 0.08131f * b; + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} + +/* */ +/* Inverse irreversible MCT. */ +/* */ +void opj_mct_decode_real( + OPJ_FLOAT32* OPJ_RESTRICT c0, + OPJ_FLOAT32* OPJ_RESTRICT c1, + OPJ_FLOAT32* OPJ_RESTRICT c2, + OPJ_SIZE_T n) +{ + OPJ_SIZE_T i; +#ifdef __SSE__ + __m128 vrv, vgu, vgv, vbu; + vrv = _mm_set1_ps(1.402f); + vgu = _mm_set1_ps(0.34413f); + vgv = _mm_set1_ps(0.71414f); + vbu = _mm_set1_ps(1.772f); + for (i = 0; i < (n >> 3); ++i) { + __m128 vy, vu, vv; + __m128 vr, vg, vb; + + vy = _mm_load_ps(c0); + vu = _mm_load_ps(c1); + vv = _mm_load_ps(c2); + vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv)); + vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv)); + vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu)); + _mm_store_ps(c0, vr); + _mm_store_ps(c1, vg); + _mm_store_ps(c2, vb); + c0 += 4; + c1 += 4; + c2 += 4; + + vy = _mm_load_ps(c0); + vu = _mm_load_ps(c1); + vv = _mm_load_ps(c2); + vr = _mm_add_ps(vy, _mm_mul_ps(vv, vrv)); + vg = _mm_sub_ps(_mm_sub_ps(vy, _mm_mul_ps(vu, vgu)), _mm_mul_ps(vv, vgv)); + vb = _mm_add_ps(vy, _mm_mul_ps(vu, vbu)); + _mm_store_ps(c0, vr); + _mm_store_ps(c1, vg); + _mm_store_ps(c2, vb); + c0 += 4; + c1 += 4; + c2 += 4; + } + n &= 7; +#endif + for (i = 0; i < n; ++i) { + OPJ_FLOAT32 y = c0[i]; + OPJ_FLOAT32 u = c1[i]; + OPJ_FLOAT32 v = c2[i]; + OPJ_FLOAT32 r = y + (v * 1.402f); + OPJ_FLOAT32 g = y - (u * 0.34413f) - (v * (0.71414f)); + OPJ_FLOAT32 b = y + (u * 1.772f); + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} + +/* */ +/* Get norm of basis function of irreversible MCT. */ +/* */ +OPJ_FLOAT64 opj_mct_getnorm_real(OPJ_UINT32 compno) +{ + return opj_mct_norms_real[compno]; +} + + +OPJ_BOOL opj_mct_encode_custom( + OPJ_BYTE * pCodingdata, + OPJ_SIZE_T n, + OPJ_BYTE ** pData, + OPJ_UINT32 pNbComp, + OPJ_UINT32 isSigned) +{ + OPJ_FLOAT32 * lMct = (OPJ_FLOAT32 *) pCodingdata; + OPJ_SIZE_T i; + OPJ_UINT32 j; + OPJ_UINT32 k; + OPJ_UINT32 lNbMatCoeff = pNbComp * pNbComp; + OPJ_INT32 * lCurrentData = 00; + OPJ_INT32 * lCurrentMatrix = 00; + OPJ_INT32 ** lData = (OPJ_INT32 **) pData; + OPJ_UINT32 lMultiplicator = 1 << 13; + OPJ_INT32 * lMctPtr; + + OPJ_ARG_NOT_USED(isSigned); + + lCurrentData = (OPJ_INT32 *) opj_malloc((pNbComp + lNbMatCoeff) * sizeof( + OPJ_INT32)); + if (! lCurrentData) { + return OPJ_FALSE; + } + + lCurrentMatrix = lCurrentData + pNbComp; + + for (i = 0; i < lNbMatCoeff; ++i) { + lCurrentMatrix[i] = (OPJ_INT32)(*(lMct++) * (OPJ_FLOAT32)lMultiplicator); + } + + for (i = 0; i < n; ++i) { + lMctPtr = lCurrentMatrix; + for (j = 0; j < pNbComp; ++j) { + lCurrentData[j] = (*(lData[j])); + } + + for (j = 0; j < pNbComp; ++j) { + *(lData[j]) = 0; + for (k = 0; k < pNbComp; ++k) { + *(lData[j]) += opj_int_fix_mul(*lMctPtr, lCurrentData[k]); + ++lMctPtr; + } + + ++lData[j]; + } + } + + opj_free(lCurrentData); + + return OPJ_TRUE; +} + +OPJ_BOOL opj_mct_decode_custom( + OPJ_BYTE * pDecodingData, + OPJ_SIZE_T n, + OPJ_BYTE ** pData, + OPJ_UINT32 pNbComp, + OPJ_UINT32 isSigned) +{ + OPJ_FLOAT32 * lMct; + OPJ_SIZE_T i; + OPJ_UINT32 j; + OPJ_UINT32 k; + + OPJ_FLOAT32 * lCurrentData = 00; + OPJ_FLOAT32 * lCurrentResult = 00; + OPJ_FLOAT32 ** lData = (OPJ_FLOAT32 **) pData; + + OPJ_ARG_NOT_USED(isSigned); + + lCurrentData = (OPJ_FLOAT32 *) opj_malloc(2 * pNbComp * sizeof(OPJ_FLOAT32)); + if (! lCurrentData) { + return OPJ_FALSE; + } + lCurrentResult = lCurrentData + pNbComp; + + for (i = 0; i < n; ++i) { + lMct = (OPJ_FLOAT32 *) pDecodingData; + for (j = 0; j < pNbComp; ++j) { + lCurrentData[j] = (OPJ_FLOAT32)(*(lData[j])); + } + for (j = 0; j < pNbComp; ++j) { + lCurrentResult[j] = 0; + for (k = 0; k < pNbComp; ++k) { + lCurrentResult[j] += *(lMct++) * lCurrentData[k]; + } + *(lData[j]++) = (OPJ_FLOAT32)(lCurrentResult[j]); + } + } + opj_free(lCurrentData); + return OPJ_TRUE; +} + +void opj_calculate_norms(OPJ_FLOAT64 * pNorms, + OPJ_UINT32 pNbComps, + OPJ_FLOAT32 * pMatrix) +{ + OPJ_UINT32 i, j, lIndex; + OPJ_FLOAT32 lCurrentValue; + OPJ_FLOAT64 * lNorms = (OPJ_FLOAT64 *) pNorms; + OPJ_FLOAT32 * lMatrix = (OPJ_FLOAT32 *) pMatrix; + + for (i = 0; i < pNbComps; ++i) { + lNorms[i] = 0; + lIndex = i; + + for (j = 0; j < pNbComps; ++j) { + lCurrentValue = lMatrix[lIndex]; + lIndex += pNbComps; + lNorms[i] += (OPJ_FLOAT64) lCurrentValue * lCurrentValue; + } + lNorms[i] = sqrt(lNorms[i]); + } +} diff --git a/client/deps/openjpeg/mct.h b/client/deps/openjpeg/mct.h new file mode 100644 index 000000000..3e1f5e494 --- /dev/null +++ b/client/deps/openjpeg/mct.h @@ -0,0 +1,160 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_MCT_H +#define OPJ_MCT_H +/** +@file mct.h +@brief Implementation of a multi-component transforms (MCT) + +The functions in MCT.C have for goal to realize reversible and irreversible multicomponent +transform. The functions in MCT.C are used by some function in TCD.C. +*/ + +/** @defgroup MCT MCT - Implementation of a multi-component transform */ +/*@{*/ + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Apply a reversible multi-component transform to an image +@param c0 Samples for red component +@param c1 Samples for green component +@param c2 Samples blue component +@param n Number of samples for each component +*/ +void opj_mct_encode(OPJ_INT32* OPJ_RESTRICT c0, OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, OPJ_SIZE_T n); +/** +Apply a reversible multi-component inverse transform to an image +@param c0 Samples for luminance component +@param c1 Samples for red chrominance component +@param c2 Samples for blue chrominance component +@param n Number of samples for each component +*/ +void opj_mct_decode(OPJ_INT32* OPJ_RESTRICT c0, OPJ_INT32* OPJ_RESTRICT c1, + OPJ_INT32* OPJ_RESTRICT c2, OPJ_SIZE_T n); +/** +Get norm of the basis function used for the reversible multi-component transform +@param compno Number of the component (0->Y, 1->U, 2->V) +@return +*/ +OPJ_FLOAT64 opj_mct_getnorm(OPJ_UINT32 compno); + +/** +Apply an irreversible multi-component transform to an image +@param c0 Samples for red component +@param c1 Samples for green component +@param c2 Samples blue component +@param n Number of samples for each component +*/ +void opj_mct_encode_real(OPJ_FLOAT32* OPJ_RESTRICT c0, + OPJ_FLOAT32* OPJ_RESTRICT c1, + OPJ_FLOAT32* OPJ_RESTRICT c2, OPJ_SIZE_T n); +/** +Apply an irreversible multi-component inverse transform to an image +@param c0 Samples for luminance component +@param c1 Samples for red chrominance component +@param c2 Samples for blue chrominance component +@param n Number of samples for each component +*/ +void opj_mct_decode_real(OPJ_FLOAT32* OPJ_RESTRICT c0, + OPJ_FLOAT32* OPJ_RESTRICT c1, OPJ_FLOAT32* OPJ_RESTRICT c2, OPJ_SIZE_T n); +/** +Get norm of the basis function used for the irreversible multi-component transform +@param compno Number of the component (0->Y, 1->U, 2->V) +@return +*/ +OPJ_FLOAT64 opj_mct_getnorm_real(OPJ_UINT32 compno); + +/** +FIXME DOC +@param p_coding_data MCT data +@param n size of components +@param p_data components +@param p_nb_comp nb of components (i.e. size of p_data) +@param is_signed tells if the data is signed +@return OPJ_FALSE if function encounter a problem, OPJ_TRUE otherwise +*/ +OPJ_BOOL opj_mct_encode_custom( + OPJ_BYTE * p_coding_data, + OPJ_SIZE_T n, + OPJ_BYTE ** p_data, + OPJ_UINT32 p_nb_comp, + OPJ_UINT32 is_signed); +/** +FIXME DOC +@param pDecodingData MCT data +@param n size of components +@param pData components +@param pNbComp nb of components (i.e. size of p_data) +@param isSigned tells if the data is signed +@return OPJ_FALSE if function encounter a problem, OPJ_TRUE otherwise +*/ +OPJ_BOOL opj_mct_decode_custom( + OPJ_BYTE * pDecodingData, + OPJ_SIZE_T n, + OPJ_BYTE ** pData, + OPJ_UINT32 pNbComp, + OPJ_UINT32 isSigned); +/** +FIXME DOC +@param pNorms MCT data +@param p_nb_comps size of components +@param pMatrix components +@return +*/ +void opj_calculate_norms(OPJ_FLOAT64 * pNorms, + OPJ_UINT32 p_nb_comps, + OPJ_FLOAT32 * pMatrix); +/** +FIXME DOC +*/ +const OPJ_FLOAT64 * opj_mct_get_mct_norms(void); +/** +FIXME DOC +*/ +const OPJ_FLOAT64 * opj_mct_get_mct_norms_real(void); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_MCT_H */ diff --git a/client/deps/openjpeg/mqc.c b/client/deps/openjpeg/mqc.c new file mode 100644 index 000000000..4cbfabd03 --- /dev/null +++ b/client/deps/openjpeg/mqc.c @@ -0,0 +1,524 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +#include + +/** @defgroup MQC MQC - Implementation of an MQ-Coder */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Fill mqc->c with 1's for flushing +@param mqc MQC handle +*/ +static void opj_mqc_setbits(opj_mqc_t *mqc); +/*@}*/ + +/*@}*/ + +/* */ +/* This array defines all the possible states for a context. */ +/* */ +static const opj_mqc_state_t mqc_states[47 * 2] = { + {0x5601, 0, &mqc_states[2], &mqc_states[3]}, + {0x5601, 1, &mqc_states[3], &mqc_states[2]}, + {0x3401, 0, &mqc_states[4], &mqc_states[12]}, + {0x3401, 1, &mqc_states[5], &mqc_states[13]}, + {0x1801, 0, &mqc_states[6], &mqc_states[18]}, + {0x1801, 1, &mqc_states[7], &mqc_states[19]}, + {0x0ac1, 0, &mqc_states[8], &mqc_states[24]}, + {0x0ac1, 1, &mqc_states[9], &mqc_states[25]}, + {0x0521, 0, &mqc_states[10], &mqc_states[58]}, + {0x0521, 1, &mqc_states[11], &mqc_states[59]}, + {0x0221, 0, &mqc_states[76], &mqc_states[66]}, + {0x0221, 1, &mqc_states[77], &mqc_states[67]}, + {0x5601, 0, &mqc_states[14], &mqc_states[13]}, + {0x5601, 1, &mqc_states[15], &mqc_states[12]}, + {0x5401, 0, &mqc_states[16], &mqc_states[28]}, + {0x5401, 1, &mqc_states[17], &mqc_states[29]}, + {0x4801, 0, &mqc_states[18], &mqc_states[28]}, + {0x4801, 1, &mqc_states[19], &mqc_states[29]}, + {0x3801, 0, &mqc_states[20], &mqc_states[28]}, + {0x3801, 1, &mqc_states[21], &mqc_states[29]}, + {0x3001, 0, &mqc_states[22], &mqc_states[34]}, + {0x3001, 1, &mqc_states[23], &mqc_states[35]}, + {0x2401, 0, &mqc_states[24], &mqc_states[36]}, + {0x2401, 1, &mqc_states[25], &mqc_states[37]}, + {0x1c01, 0, &mqc_states[26], &mqc_states[40]}, + {0x1c01, 1, &mqc_states[27], &mqc_states[41]}, + {0x1601, 0, &mqc_states[58], &mqc_states[42]}, + {0x1601, 1, &mqc_states[59], &mqc_states[43]}, + {0x5601, 0, &mqc_states[30], &mqc_states[29]}, + {0x5601, 1, &mqc_states[31], &mqc_states[28]}, + {0x5401, 0, &mqc_states[32], &mqc_states[28]}, + {0x5401, 1, &mqc_states[33], &mqc_states[29]}, + {0x5101, 0, &mqc_states[34], &mqc_states[30]}, + {0x5101, 1, &mqc_states[35], &mqc_states[31]}, + {0x4801, 0, &mqc_states[36], &mqc_states[32]}, + {0x4801, 1, &mqc_states[37], &mqc_states[33]}, + {0x3801, 0, &mqc_states[38], &mqc_states[34]}, + {0x3801, 1, &mqc_states[39], &mqc_states[35]}, + {0x3401, 0, &mqc_states[40], &mqc_states[36]}, + {0x3401, 1, &mqc_states[41], &mqc_states[37]}, + {0x3001, 0, &mqc_states[42], &mqc_states[38]}, + {0x3001, 1, &mqc_states[43], &mqc_states[39]}, + {0x2801, 0, &mqc_states[44], &mqc_states[38]}, + {0x2801, 1, &mqc_states[45], &mqc_states[39]}, + {0x2401, 0, &mqc_states[46], &mqc_states[40]}, + {0x2401, 1, &mqc_states[47], &mqc_states[41]}, + {0x2201, 0, &mqc_states[48], &mqc_states[42]}, + {0x2201, 1, &mqc_states[49], &mqc_states[43]}, + {0x1c01, 0, &mqc_states[50], &mqc_states[44]}, + {0x1c01, 1, &mqc_states[51], &mqc_states[45]}, + {0x1801, 0, &mqc_states[52], &mqc_states[46]}, + {0x1801, 1, &mqc_states[53], &mqc_states[47]}, + {0x1601, 0, &mqc_states[54], &mqc_states[48]}, + {0x1601, 1, &mqc_states[55], &mqc_states[49]}, + {0x1401, 0, &mqc_states[56], &mqc_states[50]}, + {0x1401, 1, &mqc_states[57], &mqc_states[51]}, + {0x1201, 0, &mqc_states[58], &mqc_states[52]}, + {0x1201, 1, &mqc_states[59], &mqc_states[53]}, + {0x1101, 0, &mqc_states[60], &mqc_states[54]}, + {0x1101, 1, &mqc_states[61], &mqc_states[55]}, + {0x0ac1, 0, &mqc_states[62], &mqc_states[56]}, + {0x0ac1, 1, &mqc_states[63], &mqc_states[57]}, + {0x09c1, 0, &mqc_states[64], &mqc_states[58]}, + {0x09c1, 1, &mqc_states[65], &mqc_states[59]}, + {0x08a1, 0, &mqc_states[66], &mqc_states[60]}, + {0x08a1, 1, &mqc_states[67], &mqc_states[61]}, + {0x0521, 0, &mqc_states[68], &mqc_states[62]}, + {0x0521, 1, &mqc_states[69], &mqc_states[63]}, + {0x0441, 0, &mqc_states[70], &mqc_states[64]}, + {0x0441, 1, &mqc_states[71], &mqc_states[65]}, + {0x02a1, 0, &mqc_states[72], &mqc_states[66]}, + {0x02a1, 1, &mqc_states[73], &mqc_states[67]}, + {0x0221, 0, &mqc_states[74], &mqc_states[68]}, + {0x0221, 1, &mqc_states[75], &mqc_states[69]}, + {0x0141, 0, &mqc_states[76], &mqc_states[70]}, + {0x0141, 1, &mqc_states[77], &mqc_states[71]}, + {0x0111, 0, &mqc_states[78], &mqc_states[72]}, + {0x0111, 1, &mqc_states[79], &mqc_states[73]}, + {0x0085, 0, &mqc_states[80], &mqc_states[74]}, + {0x0085, 1, &mqc_states[81], &mqc_states[75]}, + {0x0049, 0, &mqc_states[82], &mqc_states[76]}, + {0x0049, 1, &mqc_states[83], &mqc_states[77]}, + {0x0025, 0, &mqc_states[84], &mqc_states[78]}, + {0x0025, 1, &mqc_states[85], &mqc_states[79]}, + {0x0015, 0, &mqc_states[86], &mqc_states[80]}, + {0x0015, 1, &mqc_states[87], &mqc_states[81]}, + {0x0009, 0, &mqc_states[88], &mqc_states[82]}, + {0x0009, 1, &mqc_states[89], &mqc_states[83]}, + {0x0005, 0, &mqc_states[90], &mqc_states[84]}, + {0x0005, 1, &mqc_states[91], &mqc_states[85]}, + {0x0001, 0, &mqc_states[90], &mqc_states[86]}, + {0x0001, 1, &mqc_states[91], &mqc_states[87]}, + {0x5601, 0, &mqc_states[92], &mqc_states[92]}, + {0x5601, 1, &mqc_states[93], &mqc_states[93]}, +}; + +/* +========================================================== + local functions +========================================================== +*/ + +static void opj_mqc_setbits(opj_mqc_t *mqc) +{ + OPJ_UINT32 tempc = mqc->c + mqc->a; + mqc->c |= 0xffff; + if (mqc->c >= tempc) { + mqc->c -= 0x8000; + } +} + +/* +========================================================== + MQ-Coder interface +========================================================== +*/ + +OPJ_UINT32 opj_mqc_numbytes(opj_mqc_t *mqc) +{ + const ptrdiff_t diff = mqc->bp - mqc->start; +#if 0 + assert(diff <= 0xffffffff && diff >= 0); /* UINT32_MAX */ +#endif + return (OPJ_UINT32)diff; +} + +void opj_mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp) +{ + /* To avoid the curctx pointer to be dangling, but not strictly */ + /* required as the current context is always set before encoding */ + opj_mqc_setcurctx(mqc, 0); + + /* As specified in Figure C.10 - Initialization of the encoder */ + /* (C.2.8 Initialization of the encoder (INITENC)) */ + mqc->a = 0x8000; + mqc->c = 0; + /* Yes, we point before the start of the buffer, but this is safe */ + /* given opj_tcd_code_block_enc_allocate_data() */ + mqc->bp = bp - 1; + mqc->ct = 12; + /* At this point we should test *(mqc->bp) against 0xFF, but this is not */ + /* necessary, as this is only used at the beginning of the code block */ + /* and our initial fake byte is set at 0 */ + assert(*(mqc->bp) != 0xff); + + mqc->start = bp; + mqc->end_of_byte_stream_counter = 0; +} + + +void opj_mqc_flush(opj_mqc_t *mqc) +{ + /* C.2.9 Termination of coding (FLUSH) */ + /* Figure C.11 – FLUSH procedure */ + opj_mqc_setbits(mqc); + mqc->c <<= mqc->ct; + opj_mqc_byteout(mqc); + mqc->c <<= mqc->ct; + opj_mqc_byteout(mqc); + + /* It is forbidden that a coding pass ends with 0xff */ + if (*mqc->bp != 0xff) { + /* Advance pointer so that opj_mqc_numbytes() returns a valid value */ + mqc->bp++; + } +} + +void opj_mqc_bypass_init_enc(opj_mqc_t *mqc) +{ + /* This function is normally called after at least one opj_mqc_flush() */ + /* which will have advance mqc->bp by at least 2 bytes beyond its */ + /* initial position */ + assert(mqc->bp >= mqc->start); + mqc->c = 0; + /* in theory we should initialize to 8, but use this special value */ + /* as a hint that opj_mqc_bypass_enc() has never been called, so */ + /* as to avoid the 0xff 0x7f elimination trick in opj_mqc_bypass_flush_enc() */ + /* to trigger when we don't have output any bit during this bypass sequence */ + /* Any value > 8 will do */ + mqc->ct = BYPASS_CT_INIT; + /* Given that we are called after opj_mqc_flush(), the previous byte */ + /* cannot be 0xff. */ + assert(mqc->bp[-1] != 0xff); +} + +void opj_mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d) +{ + if (mqc->ct == BYPASS_CT_INIT) { + mqc->ct = 8; + } + mqc->ct--; + mqc->c = mqc->c + (d << mqc->ct); + if (mqc->ct == 0) { + *mqc->bp = (OPJ_BYTE)mqc->c; + mqc->ct = 8; + /* If the previous byte was 0xff, make sure that the next msb is 0 */ + if (*mqc->bp == 0xff) { + mqc->ct = 7; + } + mqc->bp++; + mqc->c = 0; + } +} + +OPJ_UINT32 opj_mqc_bypass_get_extra_bytes(opj_mqc_t *mqc, OPJ_BOOL erterm) +{ + return (mqc->ct < 7 || + (mqc->ct == 7 && (erterm || mqc->bp[-1] != 0xff))) ? 1 : 0; +} + +void opj_mqc_bypass_flush_enc(opj_mqc_t *mqc, OPJ_BOOL erterm) +{ + /* Is there any bit remaining to be flushed ? */ + /* If the last output byte is 0xff, we can discard it, unless */ + /* erterm is required (I'm not completely sure why in erterm */ + /* we must output 0xff 0x2a if the last byte was 0xff instead of */ + /* discarding it, but Kakadu requires it when decoding */ + /* in -fussy mode) */ + if (mqc->ct < 7 || (mqc->ct == 7 && (erterm || mqc->bp[-1] != 0xff))) { + OPJ_BYTE bit_value = 0; + /* If so, fill the remaining lsbs with an alternating sequence of */ + /* 0,1,... */ + /* Note: it seems the standard only requires that for a ERTERM flush */ + /* and doesn't specify what to do for a regular BYPASS flush */ + while (mqc->ct > 0) { + mqc->ct--; + mqc->c += (OPJ_UINT32)(bit_value << mqc->ct); + bit_value = (OPJ_BYTE)(1U - bit_value); + } + *mqc->bp = (OPJ_BYTE)mqc->c; + /* Advance pointer so that opj_mqc_numbytes() returns a valid value */ + mqc->bp++; + } else if (mqc->ct == 7 && mqc->bp[-1] == 0xff) { + /* Discard last 0xff */ + assert(!erterm); + mqc->bp --; + } else if (mqc->ct == 8 && !erterm && + mqc->bp[-1] == 0x7f && mqc->bp[-2] == 0xff) { + /* Tiny optimization: discard terminating 0xff 0x7f since it is */ + /* interpreted as 0xff 0x7f [0xff 0xff] by the decoder, and given */ + /* the bit stuffing, in fact as 0xff 0xff [0xff ..] */ + /* Happens once on opj_compress -i ../MAPA.tif -o MAPA.j2k -M 1 */ + mqc->bp -= 2; + } + + assert(mqc->bp[-1] != 0xff); +} + +void opj_mqc_reset_enc(opj_mqc_t *mqc) +{ + opj_mqc_resetstates(mqc); + opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); +} + +#ifdef notdef +OPJ_UINT32 opj_mqc_restart_enc(opj_mqc_t *mqc) +{ + OPJ_UINT32 correction = 1; + + /* */ + OPJ_INT32 n = (OPJ_INT32)(27 - 15 - mqc->ct); + mqc->c <<= mqc->ct; + while (n > 0) { + opj_mqc_byteout(mqc); + n -= (OPJ_INT32)mqc->ct; + mqc->c <<= mqc->ct; + } + opj_mqc_byteout(mqc); + + return correction; +} +#endif + +void opj_mqc_restart_init_enc(opj_mqc_t *mqc) +{ + /* */ + + /* As specified in Figure C.10 - Initialization of the encoder */ + /* (C.2.8 Initialization of the encoder (INITENC)) */ + mqc->a = 0x8000; + mqc->c = 0; + mqc->ct = 12; + /* This function is normally called after at least one opj_mqc_flush() */ + /* which will have advance mqc->bp by at least 2 bytes beyond its */ + /* initial position */ + mqc->bp --; + assert(mqc->bp >= mqc->start - 1); + assert(*mqc->bp != 0xff); + if (*mqc->bp == 0xff) { + mqc->ct = 13; + } +} + +void opj_mqc_erterm_enc(opj_mqc_t *mqc) +{ + OPJ_INT32 k = (OPJ_INT32)(11 - mqc->ct + 1); + + while (k > 0) { + mqc->c <<= mqc->ct; + mqc->ct = 0; + opj_mqc_byteout(mqc); + k -= (OPJ_INT32)mqc->ct; + } + + if (*mqc->bp != 0xff) { + opj_mqc_byteout(mqc); + } +} + +static INLINE void opj_mqc_renorme(opj_mqc_t *mqc) +{ + opj_mqc_renorme_macro(mqc, mqc->a, mqc->c, mqc->ct); +} + +/** +Encode the most probable symbol +@param mqc MQC handle +*/ +static INLINE void opj_mqc_codemps(opj_mqc_t *mqc) +{ + opj_mqc_codemps_macro(mqc, mqc->curctx, mqc->a, mqc->c, mqc->ct); +} + +/** +Encode the most least symbol +@param mqc MQC handle +*/ +static INLINE void opj_mqc_codelps(opj_mqc_t *mqc) +{ + opj_mqc_codelps_macro(mqc, mqc->curctx, mqc->a, mqc->c, mqc->ct); +} + +/** +Encode a symbol using the MQ-coder +@param mqc MQC handle +@param d The symbol to be encoded (0 or 1) +*/ +static INLINE void opj_mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d) +{ + if ((*mqc->curctx)->mps == d) { + opj_mqc_codemps(mqc); + } else { + opj_mqc_codelps(mqc); + } +} + +void opj_mqc_segmark_enc(opj_mqc_t *mqc) +{ + OPJ_UINT32 i; + opj_mqc_setcurctx(mqc, 18); + + for (i = 1; i < 5; i++) { + opj_mqc_encode(mqc, i % 2); + } +} + +static void opj_mqc_init_dec_common(opj_mqc_t *mqc, + OPJ_BYTE *bp, + OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes) +{ + (void)extra_writable_bytes; + + assert(extra_writable_bytes >= OPJ_COMMON_CBLK_DATA_EXTRA); + mqc->start = bp; + mqc->end = bp + len; + /* Insert an artificial 0xFF 0xFF marker at end of the code block */ + /* data so that the bytein routines stop on it. This saves us comparing */ + /* the bp and end pointers */ + /* But before inserting it, backup th bytes we will overwrite */ + memcpy(mqc->backup, mqc->end, OPJ_COMMON_CBLK_DATA_EXTRA); + mqc->end[0] = 0xFF; + mqc->end[1] = 0xFF; + mqc->bp = bp; +} +void opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes) +{ + /* Implements ISO 15444-1 C.3.5 Initialization of the decoder (INITDEC) */ + /* Note: alternate "J.1 - Initialization of the software-conventions */ + /* decoder" has been tried, but does */ + /* not bring any improvement. */ + /* See https://github.com/uclouvain/openjpeg/issues/921 */ + opj_mqc_init_dec_common(mqc, bp, len, extra_writable_bytes); + opj_mqc_setcurctx(mqc, 0); + mqc->end_of_byte_stream_counter = 0; + if (len == 0) { + mqc->c = 0xff << 16; + } else { + mqc->c = (OPJ_UINT32)(*mqc->bp << 16); + } + + opj_mqc_bytein(mqc); + mqc->c <<= 7; + mqc->ct -= 7; + mqc->a = 0x8000; +} + + +void opj_mqc_raw_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes) +{ + opj_mqc_init_dec_common(mqc, bp, len, extra_writable_bytes); + mqc->c = 0; + mqc->ct = 0; +} + + +void opq_mqc_finish_dec(opj_mqc_t *mqc) +{ + /* Restore the bytes overwritten by opj_mqc_init_dec_common() */ + memcpy(mqc->end, mqc->backup, OPJ_COMMON_CBLK_DATA_EXTRA); +} + +void opj_mqc_resetstates(opj_mqc_t *mqc) +{ + OPJ_UINT32 i; + for (i = 0; i < MQC_NUMCTXS; i++) { + mqc->ctxs[i] = mqc_states; + } +} + +void opj_mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb, + OPJ_INT32 prob) +{ + mqc->ctxs[ctxno] = &mqc_states[msb + (OPJ_UINT32)(prob << 1)]; +} + +void opj_mqc_byteout(opj_mqc_t *mqc) +{ + /* bp is initialized to start - 1 in opj_mqc_init_enc() */ + /* but this is safe, see opj_tcd_code_block_enc_allocate_data() */ + assert(mqc->bp >= mqc->start - 1); + if (*mqc->bp == 0xff) { + mqc->bp++; + *mqc->bp = (OPJ_BYTE)(mqc->c >> 20); + mqc->c &= 0xfffff; + mqc->ct = 7; + } else { + if ((mqc->c & 0x8000000) == 0) { + mqc->bp++; + *mqc->bp = (OPJ_BYTE)(mqc->c >> 19); + mqc->c &= 0x7ffff; + mqc->ct = 8; + } else { + (*mqc->bp)++; + if (*mqc->bp == 0xff) { + mqc->c &= 0x7ffffff; + mqc->bp++; + *mqc->bp = (OPJ_BYTE)(mqc->c >> 20); + mqc->c &= 0xfffff; + mqc->ct = 7; + } else { + mqc->bp++; + *mqc->bp = (OPJ_BYTE)(mqc->c >> 19); + mqc->c &= 0x7ffff; + mqc->ct = 8; + } + } + } +} \ No newline at end of file diff --git a/client/deps/openjpeg/mqc.h b/client/deps/openjpeg/mqc.h new file mode 100644 index 000000000..9850fed03 --- /dev/null +++ b/client/deps/openjpeg/mqc.h @@ -0,0 +1,268 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_MQC_H +#define OPJ_MQC_H + +#include "opj_common.h" + +/** +@file mqc.h +@brief Implementation of an MQ-Coder (MQC) + +The functions in MQC.C have for goal to realize the MQ-coder operations. The functions +in MQC.C are used by some function in T1.C. +*/ + +/** @defgroup MQC MQC - Implementation of an MQ-Coder */ +/*@{*/ + +/** +This struct defines the state of a context. +*/ +typedef struct opj_mqc_state { + /** the probability of the Least Probable Symbol (0.75->0x8000, 1.5->0xffff) */ + OPJ_UINT32 qeval; + /** the Most Probable Symbol (0 or 1) */ + OPJ_UINT32 mps; + /** next state if the next encoded symbol is the MPS */ + const struct opj_mqc_state *nmps; + /** next state if the next encoded symbol is the LPS */ + const struct opj_mqc_state *nlps; +} opj_mqc_state_t; + +#define MQC_NUMCTXS 19 + +/** +MQ coder +*/ +typedef struct opj_mqc { + /** temporary buffer where bits are coded or decoded */ + OPJ_UINT32 c; + /** only used by MQ decoder */ + OPJ_UINT32 a; + /** number of bits already read or free to write */ + OPJ_UINT32 ct; + /* only used by decoder, to count the number of times a terminating 0xFF >0x8F marker is read */ + OPJ_UINT32 end_of_byte_stream_counter; + /** pointer to the current position in the buffer */ + OPJ_BYTE *bp; + /** pointer to the start of the buffer */ + OPJ_BYTE *start; + /** pointer to the end of the buffer */ + OPJ_BYTE *end; + /** Array of contexts */ + const opj_mqc_state_t *ctxs[MQC_NUMCTXS]; + /** Active context */ + const opj_mqc_state_t **curctx; + /* lut_ctxno_zc shifted by (1 << 9) * bandno */ + const OPJ_BYTE* lut_ctxno_zc_orient; + /** Original value of the 2 bytes at end[0] and end[1] */ + OPJ_BYTE backup[OPJ_COMMON_CBLK_DATA_EXTRA]; +} opj_mqc_t; + +#define BYPASS_CT_INIT 0xDEADBEEF + +#include "mqc_inl.h" + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Return the number of bytes written/read since initialisation +@param mqc MQC handle +@return Returns the number of bytes already encoded +*/ +OPJ_UINT32 opj_mqc_numbytes(opj_mqc_t *mqc); +/** +Reset the states of all the context of the coder/decoder +(each context is set to a state where 0 and 1 are more or less equiprobable) +@param mqc MQC handle +*/ +void opj_mqc_resetstates(opj_mqc_t *mqc); +/** +Set the state of a particular context +@param mqc MQC handle +@param ctxno Number that identifies the context +@param msb The MSB of the new state of the context +@param prob Number that identifies the probability of the symbols for the new state of the context +*/ +void opj_mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb, + OPJ_INT32 prob); +/** +Initialize the encoder +@param mqc MQC handle +@param bp Pointer to the start of the buffer where the bytes will be written +*/ +void opj_mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp); +/** +Set the current context used for coding/decoding +@param mqc MQC handle +@param ctxno Number that identifies the context +*/ +#define opj_mqc_setcurctx(mqc, ctxno) (mqc)->curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)] + +/** +Flush the encoder, so that all remaining data is written +@param mqc MQC handle +*/ +void opj_mqc_flush(opj_mqc_t *mqc); +/** +BYPASS mode switch, initialization operation. +JPEG 2000 p 505. +@param mqc MQC handle +*/ +void opj_mqc_bypass_init_enc(opj_mqc_t *mqc); + +/** Return number of extra bytes to add to opj_mqc_numbytes() for the² + size of a non-terminating BYPASS pass +@param mqc MQC handle +@param erterm 1 if ERTERM is enabled, 0 otherwise +*/ +OPJ_UINT32 opj_mqc_bypass_get_extra_bytes(opj_mqc_t *mqc, OPJ_BOOL erterm); + +/** +BYPASS mode switch, coding operation. +JPEG 2000 p 505. +@param mqc MQC handle +@param d The symbol to be encoded (0 or 1) +*/ +void opj_mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d); +/** +BYPASS mode switch, flush operation +@param mqc MQC handle +@param erterm 1 if ERTERM is enabled, 0 otherwise +*/ +void opj_mqc_bypass_flush_enc(opj_mqc_t *mqc, OPJ_BOOL erterm); +/** +RESET mode switch +@param mqc MQC handle +*/ +void opj_mqc_reset_enc(opj_mqc_t *mqc); + +#ifdef notdef +/** +RESTART mode switch (TERMALL) +@param mqc MQC handle +@return Returns 1 (always) +*/ +OPJ_UINT32 opj_mqc_restart_enc(opj_mqc_t *mqc); +#endif + +/** +RESTART mode switch (TERMALL) reinitialisation +@param mqc MQC handle +*/ +void opj_mqc_restart_init_enc(opj_mqc_t *mqc); +/** +ERTERM mode switch (PTERM) +@param mqc MQC handle +*/ +void opj_mqc_erterm_enc(opj_mqc_t *mqc); +/** +SEGMARK mode switch (SEGSYM) +@param mqc MQC handle +*/ +void opj_mqc_segmark_enc(opj_mqc_t *mqc); + +/** +Initialize the decoder for MQ decoding. + +opj_mqc_finish_dec() must be absolutely called after finishing the decoding +passes, so as to restore the bytes temporarily overwritten. + +@param mqc MQC handle +@param bp Pointer to the start of the buffer from which the bytes will be read + Note that OPJ_COMMON_CBLK_DATA_EXTRA bytes at the end of the buffer + will be temporarily overwritten with an artificial 0xFF 0xFF marker. + (they will be backuped in the mqc structure to be restored later) + So bp must be at least len + OPJ_COMMON_CBLK_DATA_EXTRA large, and + writable. +@param len Length of the input buffer +@param extra_writable_bytes Indicate how many bytes after len are writable. + This is to indicate your consent that bp must be + large enough. +*/ +void opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes); + +/** +Initialize the decoder for RAW decoding. + +opj_mqc_finish_dec() must be absolutely called after finishing the decoding +passes, so as to restore the bytes temporarily overwritten. + +@param mqc MQC handle +@param bp Pointer to the start of the buffer from which the bytes will be read + Note that OPJ_COMMON_CBLK_DATA_EXTRA bytes at the end of the buffer + will be temporarily overwritten with an artificial 0xFF 0xFF marker. + (they will be backuped in the mqc structure to be restored later) + So bp must be at least len + OPJ_COMMON_CBLK_DATA_EXTRA large, and + writable. +@param len Length of the input buffer +@param extra_writable_bytes Indicate how many bytes after len are writable. + This is to indicate your consent that bp must be + large enough. +*/ +void opj_mqc_raw_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len, + OPJ_UINT32 extra_writable_bytes); + + +/** +Terminate RAW/MQC decoding + +This restores the bytes temporarily overwritten by opj_mqc_init_dec()/ +opj_mqc_raw_init_dec() + +@param mqc MQC handle +*/ +void opq_mqc_finish_dec(opj_mqc_t *mqc); + +/** +Decode a symbol +@param mqc MQC handle +@return Returns the decoded symbol (0 or 1) +*/ +/*static INLINE OPJ_UINT32 opj_mqc_decode(opj_mqc_t * const mqc);*/ +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_MQC_H */ diff --git a/client/deps/openjpeg/mqc_inl.h b/client/deps/openjpeg/mqc_inl.h new file mode 100644 index 000000000..0031b94be --- /dev/null +++ b/client/deps/openjpeg/mqc_inl.h @@ -0,0 +1,282 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_MQC_INL_H +#define OPJ_MQC_INL_H + +/* For internal use of opj_mqc_decode_macro() */ +#define opj_mqc_mpsexchange_macro(d, curctx, a) \ +{ \ + if (a < (*curctx)->qeval) { \ + d = !((*curctx)->mps); \ + *curctx = (*curctx)->nlps; \ + } else { \ + d = (*curctx)->mps; \ + *curctx = (*curctx)->nmps; \ + } \ +} + +/* For internal use of opj_mqc_decode_macro() */ +#define opj_mqc_lpsexchange_macro(d, curctx, a) \ +{ \ + if (a < (*curctx)->qeval) { \ + a = (*curctx)->qeval; \ + d = (*curctx)->mps; \ + *curctx = (*curctx)->nmps; \ + } else { \ + a = (*curctx)->qeval; \ + d = !((*curctx)->mps); \ + *curctx = (*curctx)->nlps; \ + } \ +} + + +/** +Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN +@param mqc MQC handle +@return Returns the decoded symbol (0 or 1) +*/ +static INLINE OPJ_UINT32 opj_mqc_raw_decode(opj_mqc_t *mqc) +{ + OPJ_UINT32 d; + if (mqc->ct == 0) { + /* Given opj_mqc_raw_init_dec() we know that at some point we will */ + /* have a 0xFF 0xFF artificial marker */ + if (mqc->c == 0xff) { + if (*mqc->bp > 0x8f) { + mqc->c = 0xff; + mqc->ct = 8; + } else { + mqc->c = *mqc->bp; + mqc->bp ++; + mqc->ct = 7; + } + } else { + mqc->c = *mqc->bp; + mqc->bp ++; + mqc->ct = 8; + } + } + mqc->ct--; + d = ((OPJ_UINT32)mqc->c >> mqc->ct) & 0x01U; + + return d; +} + + +#define opj_mqc_bytein_macro(mqc, c, ct) \ +{ \ + OPJ_UINT32 l_c; \ + /* Given opj_mqc_init_dec() we know that at some point we will */ \ + /* have a 0xFF 0xFF artificial marker */ \ + l_c = *(mqc->bp + 1); \ + if (*mqc->bp == 0xff) { \ + if (l_c > 0x8f) { \ + c += 0xff00; \ + ct = 8; \ + mqc->end_of_byte_stream_counter ++; \ + } else { \ + mqc->bp++; \ + c += l_c << 9; \ + ct = 7; \ + } \ + } else { \ + mqc->bp++; \ + c += l_c << 8; \ + ct = 8; \ + } \ +} + +/* For internal use of opj_mqc_decode_macro() */ +#define opj_mqc_renormd_macro(mqc, a, c, ct) \ +{ \ + do { \ + if (ct == 0) { \ + opj_mqc_bytein_macro(mqc, c, ct); \ + } \ + a <<= 1; \ + c <<= 1; \ + ct--; \ + } while (a < 0x8000); \ +} + +#define opj_mqc_decode_macro(d, mqc, curctx, a, c, ct) \ +{ \ + /* Implements ISO 15444-1 C.3.2 Decoding a decision (DECODE) */ \ + /* Note: alternate "J.2 - Decoding an MPS or an LPS in the */ \ + /* software-conventions decoder" has been tried, but does not bring any */ \ + /* improvement. See https://github.com/uclouvain/openjpeg/issues/921 */ \ + a -= (*curctx)->qeval; \ + if ((c >> 16) < (*curctx)->qeval) { \ + opj_mqc_lpsexchange_macro(d, curctx, a); \ + opj_mqc_renormd_macro(mqc, a, c, ct); \ + } else { \ + c -= (*curctx)->qeval << 16; \ + if ((a & 0x8000) == 0) { \ + opj_mqc_mpsexchange_macro(d, curctx, a); \ + opj_mqc_renormd_macro(mqc, a, c, ct); \ + } else { \ + d = (*curctx)->mps; \ + } \ + } \ +} + +#define DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct) \ + register const opj_mqc_state_t **curctx = mqc->curctx; \ + register OPJ_UINT32 c = mqc->c; \ + register OPJ_UINT32 a = mqc->a; \ + register OPJ_UINT32 ct = mqc->ct + +#define UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct) \ + mqc->curctx = curctx; \ + mqc->c = c; \ + mqc->a = a; \ + mqc->ct = ct; + +/** +Input a byte +@param mqc MQC handle +*/ +static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc) +{ + opj_mqc_bytein_macro(mqc, mqc->c, mqc->ct); +} + +/** +Renormalize mqc->a and mqc->c while decoding +@param mqc MQC handle +*/ +#define opj_mqc_renormd(mqc) \ + opj_mqc_renormd_macro(mqc, mqc->a, mqc->c, mqc->ct) + +/** +Decode a symbol +@param d OPJ_UINT32 value where to store the decoded symbol +@param mqc MQC handle +@return Returns the decoded symbol (0 or 1) in d +*/ +#define opj_mqc_decode(d, mqc) \ + opj_mqc_decode_macro(d, mqc, mqc->curctx, mqc->a, mqc->c, mqc->ct) + +/** +Output a byte, doing bit-stuffing if necessary. +After a 0xff byte, the next byte must be smaller than 0x90. +@param mqc MQC handle +*/ +void opj_mqc_byteout(opj_mqc_t *mqc); + +/** +Renormalize mqc->a and mqc->c while encoding, so that mqc->a stays between 0x8000 and 0x10000 +@param mqc MQC handle +@param a_ value of mqc->a +@param c_ value of mqc->c_ +@param ct_ value of mqc->ct_ +*/ +#define opj_mqc_renorme_macro(mqc, a_, c_, ct_) \ +{ \ + do { \ + a_ <<= 1; \ + c_ <<= 1; \ + ct_--; \ + if (ct_ == 0) { \ + mqc->c = c_; \ + opj_mqc_byteout(mqc); \ + c_ = mqc->c; \ + ct_ = mqc->ct; \ + } \ + } while( (a_ & 0x8000) == 0); \ +} + +#define opj_mqc_codemps_macro(mqc, curctx, a, c, ct) \ +{ \ + a -= (*curctx)->qeval; \ + if ((a & 0x8000) == 0) { \ + if (a < (*curctx)->qeval) { \ + a = (*curctx)->qeval; \ + } else { \ + c += (*curctx)->qeval; \ + } \ + *curctx = (*curctx)->nmps; \ + opj_mqc_renorme_macro(mqc, a, c, ct); \ + } else { \ + c += (*curctx)->qeval; \ + } \ +} + +#define opj_mqc_codelps_macro(mqc, curctx, a, c, ct) \ +{ \ + a -= (*curctx)->qeval; \ + if (a < (*curctx)->qeval) { \ + c += (*curctx)->qeval; \ + } else { \ + a = (*curctx)->qeval; \ + } \ + *curctx = (*curctx)->nlps; \ + opj_mqc_renorme_macro(mqc, a, c, ct); \ +} + +#define opj_mqc_encode_macro(mqc, curctx, a, c, ct, d) \ +{ \ + if ((*curctx)->mps == (d)) { \ + opj_mqc_codemps_macro(mqc, curctx, a, c, ct); \ + } else { \ + opj_mqc_codelps_macro(mqc, curctx, a, c, ct); \ + } \ +} + + +#define opj_mqc_bypass_enc_macro(mqc, c, ct, d) \ +{\ + if (ct == BYPASS_CT_INIT) {\ + ct = 8;\ + }\ + ct--;\ + c = c + ((d) << ct);\ + if (ct == 0) {\ + *mqc->bp = (OPJ_BYTE)c;\ + ct = 8;\ + /* If the previous byte was 0xff, make sure that the next msb is 0 */ \ + if (*mqc->bp == 0xff) {\ + ct = 7;\ + }\ + mqc->bp++;\ + c = 0;\ + }\ +} + +#endif /* OPJ_MQC_INL_H */ diff --git a/client/deps/openjpeg/openjpeg.a b/client/deps/openjpeg/openjpeg.a new file mode 100644 index 0000000000000000000000000000000000000000..a30067f91dca8352daf5986c1307a16fd975bc54 GIT binary patch literal 717158 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

e_2-&?!7+so|O8V zZ$@bGOrNy(Pr|5nOQ*5mtY( zmy-cG*KZ_}p{OF11T|nJ34=`=C#jbZ5IMVSx6nz6m~voov)iv0LF4|;#Zs-Np~FsS2|_z7ewMk3`? zXVR-SqRtF?qnO}=JL88*TG>A3gQK9k6~Z&gyOt`kGphauUAcA$-FX35+QPNe|I7cC}Riy->gRBc zQ4b6%{ez>rGR*Y*+?Y4>wBVm^e@3&aPJH$YX{jZ;TT07YTy8aE- zS9WV`t{`&JQ46GXxr#$MWa;gVAP@cq+4C!-R8Xe3`~9~1S`9F-?QozEx32XN6mWG4H`98Kh3QL zdp1lnb=9LWeHxDPI?wD7W!5*8!Bc}DVzx5W-#n|CMKc2jGeB?&@k$1)mDtUU@T7$ylr;@JbX&m^L`Pz?!EXcD!uLZTkFtmUHNzeT(z)voKn zQ*2mBS28CV_k)?m=$8@}V$wYwm7kwiX}J$V0T|DwiCC-e^hT_C(`n$vmV#UW!H1*?X7f+{gu?qc+uy%9Q_*pxG z?jOg?ST{@tk}WU|0`Ll?FIq{gn_tJvVJ>+KN%Hn*q-kp!t-lK(dx~lu0)X&SuS33~ z=F#ax6y{R)&XM$I&;(h1=aDkB+M_=Fr1v-^Zr9`zw`D7AP0$S39#gTcO;|?T;`RiT z^zvG(5cZIHe$9jqzw{yu#1AnL_hG58^lI<#WmjOuuV_~Lm>zg3F^0ubfY^~Mb3))T z$TNqKnEW+6{-3Qf>z5X2ELCah*W|(C@)ONk{dak(GkJkwO-YeTtE8)0^e1F?$kT%_ z-M%aFR$k)uu|#jak$OFkxvz*cy`x)&5T36?4llg|vauUW?VqAi!t6YU6s8HJa{(8@ zOJE_RvsO6u2N8TZ7r}e7BG{o%LjF3%?^`+>;NrJCKQ@!us>SIqS~bCdklgL}SR zY}Q{v@|V?@L;QAc@R<4)9;TOPq%S{h2R%5<2CW+vR1#}h+$sq36!>Nr7D>~f^64b~ zlmVt+F=|&tO5riP{c!9W@|P)wvfl`fW#ylZpS_0z_U}fmMt7|>`y+!`hRyp(;+PV( z)*mk{KL&naf6~nQ&$?i+Fx_)Bb{QHOGWcM%75x-np6P*prFU>lS6 zT(cv%{xHhkht0!1eE<8%vzC5R(751$q6p(n zD*h6CF7f(lHUhbt2)?6sj-u(=KwtzaRBX0k75x_YcfbsX$;OczmbbhIF@|;`HKa2# z-(k*V1F7Lll!3ufrlkKj@BR>MXn(Ge)}FBIXP9c&9(Bt%kqr#~8X60uW>d@7O4I!> z7&B)6;Hkg>)36kE{|i%CzNtYO`(M<3M({*@e_BIEbVK>c^p_{dzu-=d^{b^gRz0Ft z?_|%B?fk1~yA!IHzADJE1*E4B1)@fc`PlTn8-jg{r z`Vv;?lPLZUKBm!*-GU&F29N4$b+6FD-b2H%x7qW7LALY#1FA7dw$ty90b0I??4h?T z)-2;Rx;?^hG3XApXi&poQ7_sPvA&`}hn|81^NN+{K*Nw)+AtzsF*XL` zhZ3)xj-+0hVtvJZm8DPj>A~)fwK_`$24R7Xtpa}4>jQGN^niNN0ri>})tSX7Q%dab z*iP8C(b6RY_}Qagvsb;aXu$dkT>vsb4b@((1xGue?OkKI(Jls-4>-w7dMiNq&g5nV z0HCuE9NmqA%J-n0qrbFQO#eE0!`ab4pFA4)#D0=Jx1)87S)rd>o=a)r#NK6l>6+Uy zvQtOc8QgWltsG{dA0y`;w?FYAX7qj}?b=am#r&8x*86cC$i3Uudv*U*+zWC{IXHMM za1^P#$iE|aP-6$c3{%iIE_OgyuYMLM&>?wsHmI|Df8p@gA?v>Fud!q;(3PWA{~rNh3o(jWD~tV{1Fl1;Rv!3ARH0w2zv>b0H)nZR9{ds{4>~y zaHGpSzZL%QDy!&sUxZ}|M%;rS*@} zfmvD1v_ho+70d?@ul7#`eZQoOi8i4E*0;tJ+`Mv1y!Q1=c5`2V(vJK-emgp;@)n>etm^N2sn(XHBX>X|V#wieuPw=;Th zm+Zm9;Wo4}=LgKb-~&6&1b*-gFF-20pD~6+e-R&+iwNG&6BwWv5$phaYqEZR0>=6D zg?uvFNDL5V>GEVc1^^z@F;&<@W_a=;L-WTD2uqAZh@YKdnm_0qm0GH*rH~f|xFskA z5$nPPpkDKo+Hmy)Y5?ETs|VE5C0?~*P`&0)YQxtaQUhOmNTZFL&euQ&-q4A3P)oCJ zJB`VS&q0Yd#u9z`PBz;L`J|TCd0|~J62lwSh90$Hr+UpcUev~ApkHm++(wUp2$hDC zYCu3rjRCb`AE)3&PDH~4YC|0e!81_zQ1JQq|5Qu8Dsm+H6txuhC^vKy>W0t|%v-2i z2>DY2GC~F~Y@K#|0w_Y5BI^hv)wj-vP#F;VumCL6upvbTJlytdm}W8f7L4+9926lHhvLA|Tfp zrj@tV>iyWUL8o->iAOM8x|XAL!@+$WxKVVX2$dR1^e2b#PS~$D4AAUCoRrgv z@3jB3-HEBcsuP3z+drn`I-1n$u(C$WL+Sk(3l4f^_d1hI-qq;`kP-Y@pf*g!W#9Q!kICpF|$fMCq_&@a={t(j;9>^PjE%OPhT$4C-FptSK}X zdN3H{|9}CxWh&;QKZK~a{^+CMC+QcLhiHF5-?)y>2A(kPUfM#;g+uck-Ows~-B2bmo-lPkj5(N`IC2amt zOFftkLh3dBWFNsOLr2o} zr!>z0e;)q=%Y8*u8OIp0(LnH~*xLr{rAf7rXdix*=Fh4^)EZj~9`h=n9vFu5{kf>} zhPkLj4<;RXF?^BZE}p{!mk8YP#Pm#RtN6T_P%3QGn-dN0@wYPyB0(Yy~QDih#!PG@+ z=W$dC+dfft+$y?U!#Yoap|WV3Vdmec+~~T|i(SR7aPYAAfqc00<#w~9#Av!oA{aIo z6ZP1gs?q%)d zL&l!Y$QOE&5e55>RXzS_2rcp${g7>aoO>1V>mPyL9pdsk@n(gQU*j{|3TL&s&2^qx z6~WzV_3q&FYW4GiSh~!t7XvE7dU1nb=a2FF2(%^+5TouAcSa`<)3 zz6DqCMBum(QJ#*Niz`4atpsp+;|MHM-7r-6y&Al3ir9eqn?5SCn_@|Qr2Ecde(zRf z`5}~@s)(ukixKFLnubw}|7=)i8bvz(S^)oCV1`QAGde6Dv%c-uX2pF082@X_^guW1 z_A_eD8ec>i*7Dmt+N`p~D|xZ=MK#m;w-wI14XXT`9;@&o-EvR8QTZx61zq<>@ed2= zO0bC9xtSW?K`U0V3h2dl(w(%#7k4tjhypqH6@00AV2A33t?xIfV6S?of<(HBHqpQ+ z`jyLz)jRuWM8K26NAObPj-DiyLD9h#{@H3*hZr#xQI@fQa{~wTq4#-rhRaVLeTmCk zSiQya0H&YCi{Ldz7O>9WqbsOOYN?w&KpwW%VOM^If24do(67Vm>~Ppxsf3}>GHlFh zR%nW5)#Zm-3c+Cn3(AjSgBO8!v1NV`2)Ib@Bo&AaJ4T@6mBueih0Xcju?j0NhwE%U z+_C!OM?un5^)3Zjt1P##&rOOkSz16RZ3$Od`lnqP=op~Saj5%J38ZZm&Ki)rpGtsq zkBm?|e~FY}jl;S!got4eOJ<_JC!&T$)VtZJ*f){mU4S!*G26tOH47^uIGiZTK~32& z(IDlUN}nEF>K{?N-a)T8EMQb$oejy9lwFbUsHT(lE*%^o)~|#wQ-(ww`(Jhwr+2Rlh@Nt>L1HVoeN4k1-XAbyyB0;87JA{7bv~|kovP!XGopdrwDCpj^VI88 z$Y}`1=CWFAzSn5Fwa{ErR0|JAjOJljDgT3ricCwIx0aZN@wy+>6f9M@b5)ZaQ;W!i?=5K`H@OHP&ogBoSny9u{5(g?Mj_sY z;rhVOR6vG|==gaT?SiJDMo_zEl5_~}>3AH~L}QDZ>VM}_o+kdvsbB1i*ny@Bo^Vuf z#phkhu1pPIkTtxY*Rbc$*6{wns)p-8VfrKZfxJ1(9?^iyhs`DUzZ%#T9-OLn{g||W zbQ9*yYs+ZdbB|Z{tmS@|H~>u%;@j@lykiu`lArA7*vS@sU+R%h!W2j|s~s^epe#y^VW~)G7O}-*U|J}SA_pY-fd$t3k3)bj zg}}#pC#(5mBqdoAx!6O--whu;z zrT%LDQ%n6d;ZNee<54)6_C>MqMJj#T%TYe9e6mmGr%cfx+yZ{kLwP&<)Xo7~I-?aZ z)#GBs`HyE%?54z;XH@O{6_Sv;SY)t1_$QGy4u&;%%U0Ff>QlY9mKllT8&z)&z6+B& zUJ!9RR@|jetG#a>RK1NuI=QNm#jW&hP3;|krKLA{Q0;vmuEx(CM8Y1m^b{V?sl6{E z*t?Aqe6Tqzlb+g)xIuWQ&d*m%M-erMyk`LH-3tWU4+3(Ea*Q0LGzgcFI=wFt{N~4RR-okh$~!M2x(;~a8dCVz;@^U0bZ(Mk3W(LV8QNc(cuaH1zgfBZKJ3_9uaTir4luPQBDR>lWYJr z5dmVkQepw9RCQiMd7p+J45xwvi6xYj5j+J)>Cd}}yCOl{s6FquV2_kO?U~T0*88iC z;5&%vjRc<((A}RLTVTykAeYEMyu=fCj=_Y2=>s|#*cu6BzGo00^1KaoACaJ^sC>uS z#xbx}JNWJE;I|{-wMu-yO8i!dh;I_V?N)nFfZuK;euEo(DfSKyfG_%OetQ{w@jUU{ zcD3{aJoc)+Z=Q?apvTT!f4)mF+zv3@7%|+lz|fmvxP5q=IUfr#@|k~@0);cAA<>P^ zi4^RJyVb60$#A@hGhC;f%Jz0O+@K`q71{hnY*_3Jl-L2A^9Cg6{Z}v%_o)d|!H9>I zQxll*ZzGGiFhpFad>|PSg7r8ioV5l2yVu%3hCITc+%h3NJL!m3( zabsvi>5bq@SCX^AwhHymQm7*d%o`rF4)aW3dL`_Kw!WjI4v?5&X35dG0k|8Rbh4$L zxQV^v0>h@bOl@iGHSS06lox2tF5o3bTGuzIxX$ z_%spqm*T$9)GK+D7jh1$V}IJK56}^fnNR^xm_ATM0XJF^@5THbZgqGs;qP$QAy1i| z@!s@rp*!L(TR!z>d>wIVE_@yBm%(Gxv^}`2QO%>n-Uxf2fNk8gNT8u z%I_--2L>X055r-`Js#OREK5{7|B-NHknUC!&x<_VZ8scvJF<5Oc|0OdKK-Xa=W+~S z_5uF#4*OBqWlj8n=inL0(zbU9lCo^v*!x!c^GJzy;>7&~sk-n71zx~-MY43>*#MZ< z7e)%I3Cx{00)VpOKS{rfjVgZ2#yCQtG5xBD=e52G?-aM3 z;uenc>Zea5kR3YM*2C4z?=Lc%>ae4aA!*X=o9 ziFhavPUUbugEP#$>5yl6@b#Pt-;<;g_i2NpWIv{JM5C2v?5@*+Ughn<53nAc33M~D z*?U=(?Uqi(q_-PZ32InOHC%Z{H_wBio%=kZ72rin<71+WW0wA%(7VWi5%j|k&;0|? zKhsG+NYsBI=zsS10j$)e`(ng$Cr|_Sd@>}n0ZWFSA%lnjFg(|s2LdLYRP zl>R7ti5w!)-1>#18R9n*1DO|Py#ork)0DK=DcIhdfs8Ua)PjFB(31tU=|5F&`sWwG zfyKlh8%|A+z_Lf}5oP<*-vB@If1ODGfOtyETio?+8}>}$-yLvtEIXq9W)c2~vC0QQ z#$CGSZ5_T9NXe=D&^er^v+TN+uU9hvO@g%wtx-C_Ot?}W3ym|{AILbuy`A`C<%@`N z6c2e?3!m0nuerF${PyfC7Z-QbvH_e8BZ1(8du1Qo)jAy+EcXRiWfx$nNnX9FAt-nK z*d7L~8oqhG*uwV$N&7wk*ITD-WlJPC`#<Ts#{E!)#i355G7+ zDYoD97gH7T_@vm1tx4Drt_+v955n|`wfuIE9$ZtQCZ0jJ8s@jf-;Rl9)dSXMvwu zr{Sx?Ip;WBR$C9i&1OHo@asH9et+D@n!Bbe>da}>PADk75S%ago$!_p@Z!@!K;f@C z0t++Nf!si1mSa&nQ!|6u;u{-drR$|^3gq)@mY5+_(|rfE?Fk5j?10Dr0r>F8wJ_wDz=VJc^Wl{= ze8YZBgr5O(vhC@Qk?6^$Kg*tB=rBRxPjImD>%~;6(SmU#%%0X5&JFH?Gf9}-(dzwv zI8op~2Xwy|SO3%htLWDJi)ihRy&7%scsTGun2ph+K%l8Er`uYa)+P-=WFWKgV6k7SO9yHorIeb*dXHI zdyF%PQGW#y?;n1Dhzi6Ta9{{#GC^xA4hQ?f>eV?@>N+5+= zqV*2{D^elBWC(|u#Ng$cJXLf)cKTxV$eclj{Wh#+Xm`lb_Rd#({!>eFjx(`cY{1oG z1FlwVz|{^I!Dr*Igh@RqL%&4XDJOCWN{)OhHgyaAkV=Grd~N+nK%#y^!h_hyI}|^F zsuT(>oeVhlbi;+sUcp3^mxX2e5TpRwz?XVGA1=1wBe(;QM`1I13vci|y&Ogo=>AX` z9w!A=?fMBGVfvS4`j3(bc5HF(cT2S@UU!nl03AvN9YK@_86z)2~NcyX-bskm!bUf zG;M52`IXpaIP~_d25h#)nzdv+%=#m2TRI}=ds#P*n;#(29^<&5Alw@F8a?_W%vUlU zkK_9k+GAAv^fZ)6?Pk(yEJPHuDy+7Spyh~`%z8;9?Xa^2FyXRnuy>;D!!X;OrY)3~ ztvUIhRl5!Yezf1_H)jvee~6zG(BWK3E)mKA`ZD$z2bY3gngxj>b!I+ZD+kCjY$&@7 zoRU9G-qW2g06n*#V`(HPIr?kl!{Gp&J;2mDDsXoj%7+GsWBKSGWcwMiiS6%94XE@( z8j!}G3tQD=Ve1$i?}Qaj>5OVS1C z8@`SFB(W=JR8n^`jJg(df*SDY>(oh{PwB2<=qM;vdz7NBmSF-_Rhns7bB8(is2)e-8;v>-D~Q-eV8f=b@n#?B5WM9hbL^! zzIgcGUlp^IM;knbxdR>o$M_8gok{^#wb%wNhu9@|O&l)%HZ-40@%@IEGX>{&(e8{6 zx8U$Y>n^CEIOfpmzlVO8-s82tGD_w#zBrj*gky3=(4kr{5a%UugvCD62j%G$4k@;( zc*65SRRb4j!S~`n*Q|S~OK_kH7ZE7&R%?L={}5%)`<)h;cek}*n$@mkL({ExoJhCh z&a>L{v!Oz(-JK1cZ?#X!hGtmp1=)~_|B}b?se80Q(cQd`FuCCWy!eUxdViT%kE&~X z2|U|Rzt{w(y5r;sW;%5Y?%Vv--P@!Qj?fS6Lh=mB(}?RO`=OtVJ$^5>>jpkD|497K z576SA(i`%$pY(5H?+E;@-HBc=wQLD*-}-yJ)be9b(Rni*2%-xU(9(DXE%M+WFBm(5 zcH57kg~#%E3+Dx&j{hq=LX%+^$=@u4gG+S$M-l8!kuhh0$*Zp zb`xnzsW)&h$M{04@CmWhuZJGNm%E))>6#LL`xc2awd+2_gvpvS20;Y>07$cv(xWjk zPmV(V{2Xv(#XL!OY8mW6gl*@X_M~H+@<}9&YX@{T3wK7)Of{E+B>w=y4FTRH?gqF3 z8c7AVQNE7t@1if5>pe*}e>$B7?c69z!F*YOH4&HY zXF<+ce%|Et3JsH3QI2zd`qZY6#yfb7_>qtI3_oJLgTJ1V9~I_HI3mIaM`Op*FGJ2}^ew07 z?$!zTqU0p01K-g{YIr=#G7^A;y1irb*Uw}p&!RprLU>>OUrUwzd6}`lsvlfhMX5rmhpzwFr z0>x_oAS+VytoBpcP`=gvVK(Hp+D~UgQ>^wg*-!xvsAWS_;b>7Qa71MX<>uX>($5v@U#0j?K9RDkf(940ljR zLN7eS^}@x_3!8;r*iBxIxFyN!)C(QT0k^M2%?n6n2|^z=teQ|HxLxhMA2>-C$G$3L@-5#Xc^qHOE;Qi8gwnLf zX@;ah^#?ADpWsTNLl~Q1W>2^4p+&x;PsaZCl?yz1IFh!e(sdI@Ut}WVav4C z(M9<0JvqSHg=SqpTO{kP9dgy!JZieb=; z$*Q?1Y<}BAcl*?uaUU!JM#K!mAc{RV5=m<34{46JR{L>4;GOc5S6S=Vz(oE=K~#C) zSzcC<+4jRb`+?v5&Qtg`?&wb9F)MG@0(TI9GFu66IQ-(M&Z#(99vj~{&l=RC$;8OIc!I({bl7Zkkw`-Jek>h@4pX^mWssCC~$|4mhtfkY$4h;hAHL{Hs`K; ze0*Gim**7!yXbl3oE<^pGTvHGR)AdohJ`m8Ozr#$DND4gFQINf2R{ff@Ro%^Kp|az zLyk1C`TIS9mWI&-B^2WJ8+g&eKZOeM1y{p8ri+d=l1*m?i1-PP|Is!d5y$DEjlY#3 z^Wn#+aqIoqo_(3>S4J&S%Bd(n2^fDPS4W*tl~T4cx_C|F$L5Mj`$8+~!BMmruFg|y z#>@AhbwFL3HvD+MpMopVrKm~Rx^a~6a`G}5ytszZ++~UPln8qkW6B9{{PSej89`>&vU3t@Ph#xu{rj z(PZ@}d)L2-_+@0$t3%)Ef{E(jp~+su-2&h+a_C$ZX3t||hs=5*e9NqwaXcyJ^sO;7kku?R#CsaJq70_M|PS~d*Pn*Mi$gx;lN z7%cI$_P>@mE~7N= zcypBZ_&0ncd+XRe{*5RD;ts=SR=&o1akgMq6=bV9`_rXVI{T%cP6nE-4I0}{t2XYi z15Xw6_7HYKl15*rKZykNq4y#Aj(taR*@M;69a00G{)ebo2yA*Epm$}TS?8JMWkr52 z2Ri9KZ1Nu1jHj&K0eGkD{-qjtnb1&nY`#r6a+U3TZZG^R=AS5xb$tGb0yp-k_#`A6 zn9IvexD=Iq_B@zZmMSDlU5mm%el=3aB#XlY+QC--4AW7gmlJp3h4W6)B zhmjE~3(u-^hXb$Dlv51*UtolagTpXRU2DoVE(!v8K%v<5*=d+lp73u3223lLAOzI7 zc2M`P46~Pr?aLs1G!l;k=(SK-&L}JVM)?bvOt`SDpz&P>47~9&lLBtVr^;|H;iEZ< z9;MD;oql2%L}Ex|8b+AhC=fQVpc5Si81=1TiYH7J_?KdkL~5)t-jH3S*X=j|sJ_6Mv>>+_8;@5*v1?C>T7!Dt8Rq zjO+b%W=#XyZy(T@HB0gKB7a+kw;}$v0&j=$Hhj@;(j0jU#l8^nZNWW0oKs4{S=Ke7)VV_NgvJpk)KpD z&3wX7IvF97QIR{gB?W|7mp*}EoEZiu;}w0b2Sx%fBlr-47F?*n0gypudf+(y4>Kw< zf(XQK#lryOG_WW9qj*OV`y@iMp=kVf{x*c^;O%fwv8-e)>2z zYxW*NvLPgc6Rt=lOw4=Vpj7bBgm2J(_&OmKF;}>J&t$3UMJmEY>{dR0b|PGdONorV z$2H8Kbx27)s9{w3!}#%qp$ygI_~e~8eF9BB!cu%46HKX9DYPc_F|LBcXs=L`_-#Xe z;t1F$?))fa*q4*R$Yk*F3`>!LdY>+9a^bxFg;WIH$%XTmMk?)lfB&=;+I0X)M8Pj1 z$xAq{-HRkhmKyfGzi%2&ydF^R{NBgqg-?3m0DQM9pR>L`hS@k|&HI>G*ar8tUmOnX z)8X62i@;gk)DhqN2lQ#(VO;8PXBiNL1GbSq*d11@y2(*VM@^%k0LZ*JjPNnBPR1$Q z_KWqvGa6js`toq*FE0XY+WQBzY1qKsO>zlWLE|hIn2*|&-7SPKu6N!Aj(LzOJV>%k zt^Pm@Zb!=Pn3JjXz_{=W_%hnF3?)w5m|62jF=JDlk2*BdO@ayaB>dUYm8b zf~#3;cEJk;Hwwc`u5y6d7dhF}2-OTAc`=y33|DVrsF4^@lDGv36_~>6c4wERfOw(P7O_^6Y`oE0!fi+0XdkfC77Ocd$?We)5yum>S@v zbl2v4{CA;9)VYmB$^g-Yd-HJn+G+uzv1~MT`Zv=Po-l!4Y?WY7>Ar}i|K5%LS_5rK zBN)U}`w^D=@ua=Ld#IeMaX>22U|_CJzYi~T%^xqhU#6##s^M%M;!Ev>#dtxbyIwHv zSAPQL7=s4szKgJvh){o$EPr8IH*NnPl*p1284-$xFmz=Ei6217o<9J^lIq1^4>h;? zgKpTJzn{bzqt5QQ4?UKFfF9ge}=z-Rtpo+}|vwEbc>FD)dFO=2YQT=07@DIv&g!RSRLDqzIfl8=9|!FA!VIy7~|o9Hf6LHaGff&dIY z!8=X8yY26h{0S~Rtk{=vU)@Pq_QWQ;; zYL@uvj7>4=N+Fzz)4{|zO(8TKC|g{2!X4V!YQ=gMIxc&UZ_B<9O&9tS$mN<*1rB;> z@RPB1qp0#KdXnZCOj)EA>Fjr06B<7C99DHf%qj7njOJl*WkoaV+`xww^`GFz8Q7Le zUt+nZlMd1^b&yTp#ufNkJ+BoZWLT;P_i@#3AJn=JvBk!J+z?W7pO~}J9Tmvy4Rp&x=&4upalyrpxDo*wH9~pFo!}VB4ahGDDq0nU9MUR= z)=v%PLpG8yf$yCyddd(1*HaPH{p+kscy|h^M8njo%(sI{1YxEik+xo7>w3Xzb7R}( z_f{K>ZBOua5y1iq-j56-IF*7A$RNExi1(2C6R6H-6g+#Uy&u{v#1S%l7lv?3MDh|H zUIrgXfKbBkxHcz(1;GzBvbX(?3r~XKEc*%Us1k@227vA(U;W>4t%*YLA*D5Gn|RN| z6)U1@zvI0_P?E*enlx%CCy8!cEC>kDQKNuQaieEOZdV{4Vcudif(MY0aD)V$v}_Xq&oa9t1OFFBtp(A?{t^qpGg`@tI^G6NoucBgU5MXk(jEqzRxV z7G+MDkO@p63Mg9IfFTGiLJZ-dMF>nHoDK)LRjY07E%(>Q_1}71+FE>3NrFPa2d^sl z4*1F#AAl7?z~uk^?!C{<&XCl4@BMv#=ku94`>eh8+V8d3eyt@ciO15{wVjXlf67=J zqL{D+OQz(|pMQuBh`p2tP?28vt~=|S@O@N_-S$LJ2u@NkQ?u7YwBh;eJ=Q?dWzj~n zK(}E;9$XEQp6A(*1U=7chu&V&+al>r8epb+)}vg!5WJc@Q~WIsB@3&MvRXhBIshz& ziqrf!iDsTob0BHz^jNu)o~TPs6UDkhj71mE_a}m8Mm*n-O5ZG&%1zw%f54t{c1j2V z1eHfc{$&2s0Ax#o_)v7hSoaGys;c`$7P(tG{ei56;$Vz@57^nC0Yz#d1@FMN<$Kt+ zd_eB(_g=pMW9HdXv88%TmbD%GlTabL;2bDNL>BSIBL&+a7Gvyg0UMVGC%CWas25#e zHetWF8Ol+hl;nn{q7y5APsy3dmD-Gpq#UvQZnkG?az<~q4nXd~Zq|CJ{$35(=TiMQ zcJQ{MV>=%9T`(C?+^zfJw1f;~-<1Nt9^DUx==h~ZTD%D_XcAm4TIsqpakOOJ?1Ayr z#hQ@PM48y*vGbO(-e?$bDF#Ap;v<2-l$89?$(wIRM_?3L_hv2#jOTvbdPrF7eucV3 zY6dVj3FHxGw1CLV;A@Y^KAl7kO5}mPkqe?%6Zb-aiw+`jdqgUV(@JrUzSs`C!K2*B z8g?1|FG75AVRK$0j#Uajp9;=y6VSVEJx4 z17;0&LhxKKLOp~~sO%jb=x0i-D+YX_~9`&q*c^<=_cBvh7Llb9bN{QbiaMrR~i=H#qiNUNECUGRZVI{-X zc99l#zt0S}Nrhv9VZS;aE+E34lHq!i!!4V~xZV+Acn(UYGZkUbV@{VwGgjjwx@p%H zIBmN-WvqV``s?$?x^9HRsS^-be=gc2jG#bagvjTc5boIXz6x+`F#h88u_VK^j&}TB zeV0T_y$GX@#{^JNrMMc_9Ah}PPmVW_BbHz^6X(|i={po@UU!PI-$=YVOnVbZQx(#F zZ1csaT_e8U4zXR*3#x{ZqfpNyJ+GpNA=PVj7VLu}&31QDw^80=hX-Q%`#f?AYG@1% zpn|3c`4)}VXRLb_GNjdQb#i3gjP|5z83;Z$%nd-cZ%mD`>e1fi0R-@|A79LZ9`6RX zS-%)3mLWT_&ae_(M2$Ke>pdKp0^JCl)N(!TC9>`SPO5#PQN#f2^g9cvo> z<+lpI(ePvSJ%~7>I7kPBEIO94p0{F4qLXr;ZO8K zgv$mPW!2chDt=j1v1~6JMTCeg<^j6He;yS)0vE6V_r>9uUDjs`0fDlp8tXo`8bpq(d+RRE60L-z-TK4;Hd35boRn>*vWjuZ zD9ssDMKTCh$VkZ`6RI|(7&AiNtHV`H@GRyJ<}AAWEk&Kiq`h`93(fo)WBoGlTb!4U zx9_f#;J;|hCgyJIzIGPsRIYxpf1qXT$NZi`PYuYS^N6!)5Sb=ogq!jJBpB6SFr|U` z!b4&=;0||7AoL(5B+qJGP+Oga4&Lm@G%Y-uB`?lEsu>R%rW-p&;~~QgEb3hLIHRyS z{YUH@-B@UZ3frOs>XF7O&G?7X7#g^9EyG6G{>dbEV(d3{#1ePdeeJtQ+B-&iM*kdo-ot)e@=55LHEq!h~_urX%e^?A_!CS#riadB@q z&L?f1glP`0^gu>la|{c0X3-1Ay3zsc#XMK_m>{zi9*~ug?oq$o+wDe2#KB04)oW-v z4`;5hAPHQwMj7oEtU~}F`5}JL{W1hA@OB2+!etzBEK8F9?pKL=gQpboF%V_XV3_R` zf0~VT+n}5|&M{sv)|0VQSg1ihgVBqazV#P4u;|sXY`B@6C0-^cauOr=9RRtHI|(U? z-h_)?X}IX!u@3iJqekp9l&{misK>IPDQE}N-AXDzSArHxn2c)Hrfy&8bm*bO>_B2X zsK168206s1#dh6=-~pJh;1cOE)5_jKF#?&r8%H`?F=Vs`i*_25FkradsEzgi2X+zT z?H@T0V7v$!>&h_UfIJg2p%Q9+38fgh@@Tc7)dUQC?m6sGaN?#BP83jkxYRoNQ`8y8 zLhOB}n$7LxA!+D6X(+F7ng@3Q20&F%{5}NE=Vd_Y@q#I7JP_&O8NIrJoKU=CY~KZy z2HT;w;MFypLvYG~{zf}(HLX);8_PZTS{`kMzGs>gJHT4Ei)bRekyHVGNc7uK~isUz7X9-k!1U(W{I0+5>fSto*r#@&(K~?ikqO9RS8!9r?o?OA9BLD|Fd55J5e74Z)EP-{qw$tt-kR4qq zSjDBd3ciUIS_-Yyi2LH* z2~M>c6B@E2cQ+%WfG&7xPV{QiItKn{9oXAVz6Ca&;F*6sPx9sU+Yp)rkAPq>3QK@5 z$65hmJ3{Br0yUT-+{*SuiIHNjX@pL5Ewc%3>ln1|s}){X(Wk~b2Czc|N}^bb=>nh3 z7T=#^^jL3)+@z!n{KIuNCtHgd<@)G%y}cT%Qef%Wx?O_Z2-H<_8G#j0lq! z53@~tLwsXgsUi$I36!xrF>)c~F;rLy7HXSu791$&=wuDM2>Apvhq%8#7KU4tH@Q0i z9lwju4{pNzV81p$$SJX2Wp*1YMEFW?jOu(Geof_jm&|`v{@H~8M;snR1C0AY&tl#8B|hLiarjWcgMj1uDM(?si8OnqXHn#@l^T5NYS=boYjKacVY;j8vtGCm!0bRNcjybW(xZXtm!0piq?&w2u`QfNh`l1s6 zd!xk0jwu4<#9n7IH*n3P4G|;b2k{Ex{W?Flh@JGsGLsbXt@EEsU z!)A2cm~=#IGG=sz2iNVvW8Jt8l>)UAZV${AU@hY1yWb|WvyPx%JJFj^ujGRqnAT@v z8W!`ukMmsE2wk2I*#^VY>W(cK+BzQ7s8c>lBhLoEHvPc^yyodH+Pfkadr0ve9EHI- z%FkZM-ppZlbXYFdNswZBs`)gI9l?b=t~|?atp6J2AA54=%C0{G$GB&j_#W$ybaoo6 zC-5V33T()PtNDY}r+h%d&;nT$)!c-LF_1k+dvi5AY5GFWr%>3y*+aPlnjw!0+bfa7 zsW8UI>Ngs`k2Kg7SaR84n;mI_qQY%BG2D_E@32*7ta<>rJiIXj(umP87xET&`SOC+ zo3XjC%JwL7w4UoSdJc|5HsJPv$U%%BA_s55^)KXr?K~;{ikAp}&PER&!L1j}k*pJx z^IpXfP|;i2Q`dfv-SaU168VX!Gcw$bswV;YjWybOQ67IrP4Gl&UJ#_o&|^)gyF_@a zCANbLXAVC!qflbrkPpocyC|YcpC3WyxE_(!FXWevHJWILfz0Y>C8yT#Vdesr|jNBcLe8EgY`IIhsduAEYl7@f^TZ`XS+lAowiT!5WWa=ZmvU65)_3=hYkF zvOe#aDBFR1-`*~8HW(T+!L4x)0k+A`htq3eUu`s2%n2BR=rcIf?uGRXSpJn<5H`%t z4|0*D36a^?!_E#YYjTzSdYmr6Cerm7*)AXv$QWn_J&W!wDSCFrIG)?BNj*1&uHTM; ziRf?gNazs(b)PR&fU5_oH-YE6heWT&;zLIC+}INEx?+2%kaV#h@=J$=eLWUxCV5Iy zGaj&Z!SqkiZ7_Pkyx_G2lK~T+DQOA*>IXHfKkK|BAMid=F7x^Xfk}bDyOn+8%2tISv zZqE6vd#<9Y6@%#cvF9*TNwlXW9_s|Q_QB}vDOaZe`C(8N4GI=ciaxR2NIRpT@drDE zt?`|Py@K?La4PyaYlrcR2C+_R`nLh}IDBw~d$K!dg!iELK~>@tfS5%m4I!^kg?6ZF zue>FJtLn{%v3@YWjVcH^^;vfQX$aEiL+N%GXFlL9u!NZC4ZQ!lAe-}_>0+-T&fP-4S~3O7fdU>fwwfE$lVf0LiT`7Ef1%7lSSlkikJhX#OFW{;N~3WKYPK7 z?NRBRn_*=FwVnpq5(}{pL~nv`i&MrNWQ+DLzX1z^O7=AEWzcri11`NR&1>J8f&y4R z(q2A*+So8ZiH_cCPdT5+=7qT->?JVoMu*= z`?25PBt>J-@{IDTgP1t}GIlSLRTBM5EQ+_&{y47UR2wFAumuFoe-roU)t#t$2OsLB zG1J5JWxE?|33ZrEH%qHqo$V2yIS11v`;BD8rlBjO?nBwuQax-``>a>X~Y@ z==h4kumg{4)}p_`F4#cV#tTFcm;kGy9$C&qMU%jl-N_o$Rjn_ zf?C2GeQYPjTU=mi$2AP>y*5x;`(tY`bvzi^ z2C?GJg*g8Y8oZ5x3o%%q=tANOW533-727R6aheAQK}v7|$7#ek)I$jaE7$N4nGh&E z^&_;q=EZJT;VFwE$IOX|39-o?>4KoQi625t`Yl}6w&sphdUc);F_Hjr4JHQ+ z^9nQq2!Nk7NlQF9=Wzr!&Yt!O==|e|>$q#fr?6j{LpzjhG_b+13IPjkq&u()bUp`X z{&;qYF&hT57R+eE-?TmWt7yX?mMTh&uGg_*Qu{WBkh7=Nlh#3Eze=C|^f^qQ3So+P z4}JF1XBT}A(I>Q#VOr_KKVdf)OJVRq^zfkt;@Qsty$j1FwePr%vu89RS@@X!HpYtA z0el<4X%J!&Gb3iaj25v1i_$IPWR#2%5#q)hw9vXa;2SmkTi$uRCDmy779=-oFBZ~l z&kN`bE_>Ju_;>ktVS}w<9T|l8MtQp z@ON__{;to*Us<7+L4iO12Y7^x0-W6*c+aleGaufIpe_o3cldJAgDK5F2+Pa8VmxVX*yl3KJGn9B(;um;$125xDyex^Aq44kqUe=j- z*%A-w67*#Hvd_fBeLu#Vt?=*$y__@ga1)StISLPN;0^7KCsDAsB%&M&d#}%evvwGf zKXPa87EF04WUm1ab9VjXBS%ylPSgMrA3ZpzU^Kz_!C}O|ON}6MI1xh#7;Ew<()c8{ zsT?C3-H<|X@{n~NvajV!@M`jP@;0I42sZ>HxD(JUl?_EsWf`j;#+VO3JQ{&d_c$Av~zSLaE%24bS0{- zqsltLqP#!=yV5L1Qd1yi=PjIyFZ^4qK~Tk@730~-f}J9*IG%Y6RwkU{|0U+`eH6dr z{nvl){nS7A{%POdqJqO{ZendVb)>UvgdL;UQcRMPGe99O+y7SIKbcul&T%A(5 zuJ1O=sd;QCke!q;6+eH60&z<0cC4#%*E!~UO(L`+sU^{`#&+O4S?I&k-Pl(I{?OPk zI2`|s&nZJfZ18@;c{!XFtQ&%pfc74y{b7tzTq20A#TWOtW6!~nAPNxxv&-HG@F-#G z2l`kTSkN580{JG1=1QX3v9}K>>X(qH-2aZsS(dwVVr~8__+V*i zXq3N2L*RyI4%U{v*kPQCr3=>gMv!BDzxAg4eo%e?9N&=eW0yhd=S)9#8iFP#@3E() z!xOt(IMQO*;>{>IUoMHJ#!fl~-3A9eI1x5e2Pfv@;uzWT*O2qIKfuydY?BO;6I-Q1 zaGu^Pggm9T{8a|=G0646jIZzTet+ZfMR}2)^u=G_iaz18j$6DNxf!D!>>RKAy@{s6-I96WwRU9l| zGz8iMRzAb5Xt(pQK57SZagiRjD<72ytsgY~DTqRYKl8{wcNPh>~0Gp#1L9|BtBBoq#`qETU%&(z>t9FLrfXiBU%xW=6m z4P{&&@|gY?(9J;eMQk527reKc3!I{6Tyz+B6c%N0gW$w*oUhKK%7KR5dLVUN>6E+t z7Sjr;df@O~O7*}ikD$|G;`2{c4;%q=VPIJoWtK;(9{36-qDU6f0qtnG4Zw@!5JkWb z0L9MEvbgF2G$F(h*F1nj`g2j{%o2rQr4C^t(!_iT60mkW;98^&`UMhK$#r!DzZON$ zDO8TUcaQ5qtLGr0xH?YjM)F$uYjtD7;0|k08oW-A3nCr3;Nz?(grc5YVSV}#%w9qa zDsg`vvPW;g#Lw40<43fQx#;!K%6Yjnnh>5xE;oudT8fbQKg1nuhk9%tqDEqTVhR2Z zk&dRIbut`Bbdc8R4nk|gr_kEK z``WqSG!2({kXtNkBBhKAnlB1I3UXZ&0Q8D_yiEVItl%K7aH2KvG8QJ<8he0zuInoh z7e*TH0bRYN$;&6NGByw~as8#lnh!C19GjT0#F`CJnwQl*XoSm$;&O`*@LZv$AP@Gz zG2=iOM@zvmv{5vxd$3>tNoK_oYAF~e)omazOfwdq8*f9)j1?m!x)(G^UPFyDU!ex@<$C0-wV7;aQ$E_MvPaDvhNm{p4#JG-Db?MF10gj>w9 z66>Q9904hU#fnM0dGxFe$Et??7^e=(n%@~HL(Svb!7v+CAZEwNj7TZRYAVCb3GK5G z^O{vbYi({lFvz=V%6UJm)3kP%x&K~fy@U(wCD!ZZ)HsD%pE|Ea$#G8DdM)IC4tvu^ z!|m8WxfV?k7iyG~(bis~#1+b>3UbC4JgN=A;M!!cU62Pi!O0*Usf zC!%P7$NGZ6+kk)@S1dVRjf8ar#4A>VIDM?3Zii`gH)$E}+Zj(_qy=VXn_R}t#W=!N zj8zP&R#(CH00vdGyB6)H63CF_8-}`b1nQf#!SgIe-XI>M6GkaKdMxw@01%2o*?Vtq->i??4b^xwrDg|J#1+DIm%_82i$To16 z>A6dd##g}8xGl=I43S4PZ&(Sk-j3aa$$%P9$aT>^2aIk+PvTk?E`_lxp;!6qP}1mf z?FcVw&e4Yv`%9OsKv88dAowpdiVXBrr}RXlDA?DlO?-%{R=lAVU@1XX1E+C&;pKey z74%OG+D}V}{TK|;VeBG*ah)A<6)tu+R_gutV`m8 z_QiI_4Op*-B7R)8*n#zZ-T?h8sL|e5!wYagG|k!J$>rGq(_VmUyhZ~TueIFH-XO{i z^6`1_pqzXu-?L#ih%0QzjLST^$BgeaA2V(qknos-nep&Li$@*{8N-@@w-e#6kls`G z0C*V!=e=^wXgLVgcvIduW=zMl`bGrG1EFD^=vFK8pTM-w^)zOlJsse+I4|L$251+K zngp%Sq3!`mr^$}*0%5Dm2R_uk@dtZ2v?Wp0T{+WxRh-K`qHJS9vzo)IjnwhoW@mP zHkKKvbC^DL^x9BWvX=^NxXr=`yZRwWtN~6J41a^zSHsSqP-w#~xR4u0lN)j?n4CG@ zXb!_tD&s?s8E}jCM-}j1B;)V!kT%Az#2E$?df%be99=?9N5pm_CIXxy>Xn}8y&BY! z_8T#M@+Gs6AKCy*uan%KFh5)IbC`m zp4{pZm9P?5Rht9=g9fJM8{tNIi~=n_aE?~aaCBOJbfFgkTj7EH4ueN@LdNA2Jopf6 z2@TN016Zn(W~>(fc3jUz)p`Bh?mb8a=iQt^Ju0UE*mHYS)EW{``4cbJkC;q-9od2$ z%d}!LbsoMjhKY)>c3Z9G)*EK?C(t2=V~{*?LAqwqTS2Qw+{{K#!FDFDXD<_zDC3U@ zQ4G*&%-iJ{??7oI$aaiK)DSu!ZZ@LPU{Zy~j^Xdgb(~INTw%w|hhjxh`db4CC|r)- zo*Ob)nm9PEplU`n6qh(rRLmA9Rk&+ky{_5i_eCf`<~! zU_SZ{D@RR2uMje0G)_h@q|&P_WTGBeNNE;Q8it@%2&oYh3geH@LYi%ZpP$+ca(Oy! zIGgJR~&En9%Wp+02&QY4D=f7dY9|)HQ9c1Q^I5)n>5MIgK(Los)0e zW8z4Aq6Lh^7b==9KpZ;21Q03pvIT_pevC6b#Ye1zSTu&K6fQBtQB!ChEQ?n@F6ejU zVtv6HhY}I>eaz}$-eC3k%Edp$M52$HmNS~CF&ODJEoU@;1{A@uNx9r>{{U0A*__mH z2bslU?ii=)c$}zWcw_D}ZWuyj!B186a$mVMKOgGVP{FsNf{j0JLwzE1pNU!vVI2hD zp~!oks6GF7Yf)jjJ@2oq`)3~P=}D?VZka+kvbV4qanfg#uQ)nl0l_v{)(SuMy|30At zDDr^^Hm*>_^#CFQHZK_YHdZ~0W1vBQ>k~xAcX4y1-GjE2EA%@pMLDryN>W98YqNv? zy}bT~hSCHT=0bf_E0EY=Orcl-2g#^cX(x_A0}XnWaMwlYRoaE)v8!T;PekTFQMB7A zK50)njl((VLPvMeXHXCIne|EJSdZ5Os2Mv#<1IRRBy^k_u5d@2{|9vZtp3QH=apnE+&Br%Xx6f-X`ZNeq zECOTPr|u><^w7WSM#}Py#=k;9R3o#Av(D&g4gPxuXWAOx_)Uu8Q+A%W|ic6nqp$jyED%A@^sZ7{s_TFSjCSz2xvm z=qJIQ;SY-r(s-;{^pWx7X4(%6G`zSd2eh+rbnWV**4lY!=lMZ*CvGM#oB?S$PwZnb zb}uz%BfgxV{}Aq*mA1C;yjxC?bJ|z@kX`UY9Nhu8p-LmD)Zpq(4Sv%QR;bg+Yex!k zmPsB$Dn!AQ6#c_!titeEV!e-a;~Y2g$2|g7&Cm;EAU%29b&9Mldr z2>d=%&4t-|#)O2!BG^D!p~ja;wa|M=79*teT10@RgaqL{$Na-^hJ_S}LltaO^Jj_H zh1NE&nKetUiDnuZ1i6>#U1~~RB&(HHJgcO32pC{3^KVE0W`8KdFaA>JXqTanK10kD(n4;z@^rbzL0B3Sy5jvWx|1 zeJ;1DXzI%U21>cKoh5^U$a23Sl@H9p+9l{!V09`OFA83)c#XmnkjL6nu5?*3>rLQW z?|(l_2Ajq}`Mm-}8Nl8mW;N~QcdAN=2SluFGI7;cfSXt@U#@i0l}iMhrt@Z*WO`#FXrotR^?acEAC3cyH8KlnoGd172ZkUl}y=_&*@g4U7rB%1J^wO>jRXWHv0mYceLOW|0XN4weIw&yEQhlRBxVA00) zz0K*Z7w_R}G3;9IDl2*!;lf345x%QokI}FVqbm=mvmQbW%#gr%4dK1;{}uev&kDo5 z@FGtPdcYTqtT{d-s|KatUTIzL#qD<)>ln{GZ#Ghb8ZGzreh_36tRG zxg7iQFfV^T&C5dz?hq`)!`SyOqp=Ka5sFl@#4%r1EORkB4{|SLq z5P*64|85G%kD6HTsNkFl_UMbz$Sw&(xh_4}Aj0mpP*HP;ycvz64C)8&ZA!-pXbiHK z$lfBn!}LaLqpA4xR#MBCO)d{jE`+O5IS8#9qiA%0!`d&KWS)q*4AM`pXtt@g_YtIBcrS zwZFy&;|SPEy8~M2v{_1753x7npbbfpvEqc!#FwW@EnGUR*R)?rz2ngcjAw=CDzx` zjyR}0hn%qRg<}X!m^35{JYc z84KG5kONY}ID~)!y8?@)P!tFqoQE*VehsV57!NU`BHmU}yxS4qGbPsPa_aGDxV=O(Y02Ta`F)V%Ha57ysyLu$wLdeT zYprm>fJ_*tGnD+rAsp&;U#t6ieE&n(Z}N%ewIFbWC!R4zz;4c>cbKRUtm61W5b+z2 zp;F7O?lS8QOlx9eP;->d83ptnaPsmjcBAl_&reKjHsdo^h(E}8OHtmulAFtSEP%70 zSTCvP2cCj`F%KZ1wv=;8IjfY@NnX8mrjx}ju}5%pRb>QdoUo!X1dE=-QIS_7!0j}O z6LZ#BDXCyoAJ_#j#4FS47nE7ie+d#^uX4ykMo$i%}db12r@ae#`)5w~ctkj-oupJTZ0z zMMf&2*l!fQ5aS3G9Pb^yb2}p*{Wze5Y8%L*EOVtc=`i-~p;d=bajA)Y!oQ71Qqh#k z?a>3p3Qowcn${6^kSxyGHUbf?u@Nuysb^qr9mdVWJQ?)@Zs7?ro{M1Qq3K3+@A8bAZ)|Qp=xX^cp;VK*BPgeFC{CPGQ*)7J9W{6ZNky9R8^Jpe`O))087`V`q zBc}$`jTEr4c1E6nWk*g8th>m84fhz{K}ZFjSnDZgRu8uRJ%#NiwE6$PR`) zRtJ_tK7dst&VPBf$%Qx724}@+uQhTi#c1q-WQ^PnA=wSgOGZ6z!U@XFZ5|`Ld8~1+ zXLYy;+VdqXF6Iat4nagkW^f2cAqw{4OxB|R6tpxdpN_@&DQLXg@uVnx&I7~PhC#7= zuCg;^SzGUkvM;eS@-d~r_6sk8%ll~K>|FOadssSF#jFFO#2*%E-DnTZEU|OXMvU1H zn)c8vsQ1S@5sRPIvLR?^4}qA!m0v?y5dsmlAwwHy<6urU%}Zx&V3v*S=Zqn{jI)h! z(XmBQ+FOB0g;M0~k!2f_Mescc@ySIHdl0*~V9;gOsgNz#T*dM%3{bVdi8Fm@>t62k zpM~;9=YsZT%tmlJ1nUC@2-jRjyK~QmtY*v(Wpl>;7fb{_p%ZVETYoQizk<;SD^IDD z?9u0zop@d2?%@B(K?>W1=P4eF6KWR#D)tE2R#tR_jUp$^D`0uJgIaetzcWPb;B=m+ z?sk4>(H}a+2h@F!pVj9Kbzup{2m&%UKGn1g3QH{Q(m0ANo)kh`FECQ z6$Aua;5i${v|h#{BgBCn*imosm5FuECQq1lFh*il5o^N%aH<>-Lt_;;>sVqmjo5G> za#2=wnudS!aqI^hZO!keuq72vROJRU=$+ySm31m|2r9FLRVu|(aKcoM<7jp4A!499 zf;p@axdiNh3f&tw!hxgU=LL<;gMw?k+@iox1kG$CQ^Cl$V}RUO^x~qYxr~JCcZitd zS4c1@C&~WykhM+dv0f*V`wtkz7In&m<`?XQ5wH{-@4(TxS-2~Q+aE`vZzl~){c-=Y1=4%3L3X!Tj=OYO8hYzM1?>?v+&PD z!5q^QdDnx@F=+gRd=fe7U0489IgKGC4p&REjLj+Lni9cp8{Yv;RJZ#La1*29FQ{Y$ zsND^F&}H@_*x>=!c@K*!C9d(&;GoV4R`4uTWP8Yeq|D#sZpGA$V zT{x#RY=^vMkwcwfe`}e42h>}LbQ-Jnf*&O4zlJlDCYFgNM6tisI*q^a~2usl@5|qekY+j#rI`%kH6O0ZDT5Ou!dIQpYKAWst<9}CB;$&G^#hIrsYc_8PLQ>8uY$og zdzc&zz`+HZeAomVg0bXmvdBr$H-%BbG|qJi7W**yLBPuaVtedWoU$?=3l8d@&9rvM zGMHB5vGDobvzgBB*cJ%;#$(Hdbk9b@x?{JnjL?1h*a$~osz(A*FlX+A`(MTC+I?~t z{Nsz@szKXg&AP?L8b|!t6zDMtL1NP3=6^k#QVO!y?c>Zifx@fNX%MNH@wPqyYF&ef$!RDebw`4x$^Sz zCRL2DoLqKGN#zv(>?MBRH+=a^XZz`&@0v9qxC`g|uJaYRYOCv*JeQ7NcYBTRQeWP} zxp!4Bm@PcYCQcbS!tcAxcjFBurIq-q96M?1#3_m%!!M}$e&yWxb(J%3T`1$0LFU#~ z*DkEAD)3$5(+DXjD2~1sY2cIh{ROvPaozk|D{B`lS%}yt7FU*pr%bNAu~3Ud$E#W} zZ_(}Z{~4;FoBYRgE-ploF}2mT^QvbquCA<^Sz9-E=DfY4L21SfporI!fbhd)X$;h$7~b#v#* z0wVpn$iS5&D;HN*&0JVec{^%)Vddn>B_k>)-B4-XIIUNDwWJAWa`^l&8D7#mGUkqJ z2OaoTP0yG)|Mtsvm{`>-PLv!CLL z%~0=}z(_vt*9RCZ^9omB^QWKxeQC@H9M40Dzxo2Ce(j)wz_!l-xWo*Q+Vy$Y%kci0 z>U~E*q$h8seBowW0)AG&!`}$Vd|V~t z**Gq65efeLjgrnovn3pf`roGaUtQC0f42L*F*n}*ht0RH_-M?I30GU@jFV%I?JK`E zYnnIEwfy^A>dwuP`5Ta@(orbO;dH4i_ft2;(+6ozDF4C>Pg6j=T=`?=`^cDu1E1Ua z2lvf?TRiaAF;mZd`?_h1e=%m;1r>BZ4H*5d1}9#+Nts)r-U+d)}}}gPD2bGJPePImMY-#hKo+!Kn>>f=hvGX6AuVv4b1JdE{I~ z2l})X4~$ z2O{zGj~kqFLlUTTaLOG?pwQqvkgZd3bTf`H^B80vLz%wRoD`WNc6l(64j|!X51}@rcUuhR@HketFT8Q%QBk{q(>=#2-C;6F3#}7q1*e6CQ z_#1?y`9xAurXmgFnT8qo@eUWC(f_pkL>fwwh7VaBvH;P0;ssSQxI7NmdrH~hrJ((| zio;+U#r-6Q5#1;<5IkRt=Wi0*hlo4D7ew5XGHX)5?ao|U zmRavMGuOCFGdH-)GHX&+AZtirQky|7P6OTh6#a2=`d}$~`xAMSeCO6a+I-32lr3k_ z2HhZjN6tulI8J+9oTrJlo$Bv{wuwp(gH9nCDxSlftbI{C+u%<9Wm=y(E@7Kty4EOq z1LJuHPtfx$c&#YYlu2iHUD5VL`&V?vlMecb;w|4DBsk~z!6_e0SJ~i{zerbj@I(hR zUOJelTm&DAE1`U*@UIt-z1v~2u0nVP72faJ7Eu;9+u~aC*n7w`BW#PQH7LxyV5Sf3 zT#gPUf*01Su+>a&uQ*axgB41K55~kYe?;MK$rrwv9*_xX2 zhs-^xWtj&d0=41S4l&_K>fB6tM^fR9QiDKt5Wlw6?*N)|4}d84)UXcx06>(wzzhQO zW?+T^n*dmeLYxfP&48iK90Yl3Hep@PGclOudGPC=@MsE9k$TB>xqdk2g zq`K(a`(f8e(cnTh1&pf_gjc9C7V;xtr3$`D!G*jC*moU#D8A?8$QG;McDvGCZ7S+Z zg|Ev+rS~FUu{xyWL%@Eg;5At5;Ui=^ym#YAIvbPdyazbx)Zh#oA0gM_eF8s0|2#sK z?1eWszX=bVFTgG#6Tx`_;G~Z~@u*;~Zz+5iZba}AvXXj>d`Z#SXo`)5F{nzBTkd5Hv4PDZ2l31aBMN_p!pFq| z@o@YT<#4h57BUo^=PNjE3Goqf58jkf8Ly8(JSrMjSm9T&ui+803f{97yyhDM>=H5t zoU0YQDNn*3{NE{f+hr0i#(Owh0B5}Q5-jFxbRJard(^6j7|#Je?a&z|1Bme%&UDCe z%y0hH5-!GCI4@H04GJ#CR=}?Yobhgy=<#^V6@GwY1|Bh<;$5ZSo4zf;E-`k(`6C6d zFP3mI2EzG>qF;~t;X`?s&o%|0q2Q|eU9T#5APIid!N;4AS5I0x;`ZMRx!v2A_#y+QV!Tf6Oog`zb?S-W9YE$7~ zS}d=uthk|M%9NWc$4#9$c1qc#iItVZ3$7CJaG_qU)91$l|8(WPPhz9uVVy<)IDo{& zN7A0g2v=W}3j0FUwmxVGh4e+FND%2`U#2f)S#}cnj7_4x0*utC%K#cc zYXr_V)|@^Iry!oux%21NRW1bf!s^PIwY4+vjQh;4uB)1Z?ILWrEUw0$SQR$KYGy86 z*mrz$hF2|^zp$>Rc0tW>S^ub|Gj_K6%8{&b*6D54b(OcW$g37CsGT);{>-}Sg~R7A ztevSSs=c5&@g%Ae>)oysk*b#6SEN@a)6jZ>*1XQB|HZQ2le*BEXnmJ@-z~MEpl|GW zF;>oBP;$I>EiuhL`u?2d8KrIlV zuBPV*5e&Vah$74gfj&Z@j1crj2;UI`f28moDc~bT*pY(d$g5npSKnS$BU{|ed2?^W zu4Lux+UjaiH^Na_i3W$pS2=s;+<5}5H&t%ijvT>~nAM+O6+G)C!9GGRsm1Pde?j9Z zNwf!nS~rIgR@N+7Fi*5t^P&`9Y$1=#Os1CKAV2D`*q z!>cN*m)6XiTScaT&1!D@CmNpWZgE0RMpgPC(p0CmQRD*L4@6hj5aMBNJ@Eg>;*`fcCqW?V& zuG6p9;5z;9D|j;fSCoL~(C4}hpLaF5PX9v8O-x8%PtRK#Tu)D`n$RYvXQ&3((=$?o z>+ybDgX`&>rNLP*yj0DnMuY41vP6S_8+cBBmnnF1y?3hx9j9Gw5!79-L25ySaGn0y z8eDI;Lliuj{vn?v=+K`oKV2VbaGm}?G`LRxq=F~Yf8b(Cko5KP9B@ejJ{nG^9Kss> zS`EHNgI}k?w`%Y)8vLjR4`}e;d>tQnn9g$ioOs*&foJCuTk=m)zw*=N)8Kmfd{cv) zz;);kQ*aMpI^T2V9Vvk8^v7s)bo%2oxK4jUKlJa{;1jj1 z@Cv*gxW&rGLwtR__^pCF>0c(WT&_QBa6SD`Xz*g-I`p5`=Pib(S&OK_OIk`Nu zS-5xz*YOKAxL)tGHMpMNKkx%jGM%4IPr!A)dY~WpC*Mop>*+bCG6C1qbEyW`+li^c z^>mKc;Cgv((BL}X``WFEc=hy8?Fatx>;%3}C;PSpoK4uNub~=TPfzNd5}*A#sNp}` z4}8c9iO=%a^LwEN*W2MYHMkz{MJp3@^!$#};ClMs(cpT#i&rJ+= z-!-@%?`Z{3K{R^#oU=L+uTH00gX{TPs^FwE9KU658NNY-=L6)_S5$+W8hnFBUmq9V z(cpS|POOpfIPp$b@upe{xE}8y4X(#)C^+j~k9UZM&wPzm^e@riI(@$e*Xa-MhyIls zzE0oN;5z+~2G{AA_d|b*hEMuV`OMJZI{n);xK4jwKlJa=;L||gso$YL!UrCwUYz!j zr@{4jzoo(TctvZnX;ClbP@!t}3bo%o&xK96N4X)F_?p{fU<$NW6PWe}9@T)ZVIt{MNMH@A^ zE*E+3OVHQlqM`l3uhHPTyfo~7Nr&aHr@v5x>*X_9!ISf~RDT{zk@$TgX?q#|3Z)v@#=KW)8IF1bT0h&zVY)kxE}9y z8eEU}1r4spdq9Kh@s8Y>h*zic>)#~cx?FV2Z~KN<|7QZOkJmrx2mZ1K*XbYC;1wY0 zl=CSKuD7=v)J8MwSC4nL2G{BQS%d54utkIG^zZ*mB40ZGFEqH`kN#7G>vXao?VHX} z4X)Gqh6dN^ta&OyN6*)9HMoxd$(97ZUOqh`t@ju=DJve=L6={ zSDpsf$Jr}1`nvoxO2eo8;Lr(ZaGids2G{9_`=LKs!`JCoYH*$YYz?l{|3N?WYc#kn zpDfYnFkYwJA{tze_eUCBk9WOBUoW>dC6BQEmuclzpN0=S$?)H&C*XQ}8#}0P_%BEF z4R>9Yfa~%8tsnS@{lM$5PSDZQlfywB57V#1U+o9(BQhSgPc`I-@B74m0`8nYRLwt* z@0>q;CmCOr3(x)XiPJwzep8Je9|!K7GyHWj{2YmwqY~%fyUvsF2b18=dBROeaOd3M z-;?0Z`9Pm)4-S3j9AIG*+&S+zEeY(3Vch2wqBMI)D z-y4l{Bsv}E{NCCmxN}aA=Tv&(kCNZMfxY3*IlWL4+&QP$kOX(m<84ZUJLmCSsvkM| zb2(T-v>Wz~NDA&D;uR0zM-1+`09BjhL@QODjM&SkWorM?U zQPmkg_xTM4SKUb><9~lrypD%r8_uU|7+j?J-wj`Yu%xNjI9&2^;x`?DdOPtu?*QO^ zh0l3f26$eDb6!sVo$!?H=w>_a^=y@28x?y>G&s;T8Lg`)=GOoxV6kI-K~O z_bh<>3g4u{vwZc(NsjZr1D<__KhjV9YzKUtH<#@go@2cJWIZFlC==)parrp!HJV#^ zsK4t}cpXN!6V8D@2nShGa`^{Tc%Or)-cGqW;7xFlW^(u$D*PNZK05fx;eQVg4}Jj$ zLA}?Ukd7SHuvuQ2_&MQo6kcC()2sDGiO{YBoQ+S)A<5y%7F857fcoEbKstVz#2Avx zk97MAzp+b(e^SwNUdiFB7lZo^U+^uTdh#6y-qJ1quNpN<_>9Oex=NzV7__1!JTAqZ zpy+m8cSij(Ugypn-2wjL|14JqlonmswN2B9BW&SFlbvm-&k!`Ph42nTM_GkzdH6(-1@ABHd7`)Giz_!0?!Gz#d^E9HD4sPB{9_5UuNw!Gs$3)%_r3&&%}{ zG(8ajfVyt1Po8#xV%Ubd$|vD)eH!{bfK(pEs(ON+QqLJ6`S^flI4|21-WlwN^n~>{ zJlh*`FCqn~;0A@B{Zd;RG^jAi(2krf@~~(EG$XeGLcPe_5-OUI+PrY|wk#&M@p>H6 z(aM@Sbqbm~{vvhjRQiDDjpYJI#4B|vu|8n(Y$|lUND~*O>;*34?6lb-V?Gov&4XsE zQfOE&&DrMqlK09~c}uV%hQe5t}6LN3G@EZ*^C@G_!tS z>ImGf;sru^Wn0`ACapOPgeRHTN@(JrWWUT^Blc}^7e$e9(t07jdFGgL^AYLAoAEm^ z!kve6vcBM)FO$wj)dl0}mz`RjBCei2bJ08;GQ%;oTXB|592pY`mA5av4W|+pFPvXf zi&J*9dCCmmeVjO3h(nvR6df6K4vs_4tFDzPyimo@`eYuRx$#dlIN6v3_rcAFEt@~* zQ6h63?&Nu%LU8b%{C;`a@&B!~=R-bNBuOmY6#$IS^Qye$*O_(RpRDI)!Q;u7FWgp; z@p#p@GgkE{>t*Pbpu+H#l$?HLy?-^lBkMWobfR*?f03+lO&@6@jcfkJ^p6K_pR$Gu z?;|noamvpD-3kZGBssbn3b52cRPW^Q-vzucS;LvLhEzD#AHzD~o%-u5ZU#B1;&0*y zp27Grp5*ZT$r=wT0pbS?tUbx~-=C~euiBr}PaP7;;i>qDr(7%N&0R>D!p5Uc`zYe&Gt@_w4(w$cR+f6~_)>m>%X z`yTubRF=Laparjq&kbU1gf_v8CWoLGGP(k&J#_5j`b)OENL zfT$6&UW(oXdjhA*tbdR~(XP4+XhH_|9&&exk=`0CMs(7Nv<$K)dqT<>t%_#{(|1+~ z35^c!ct+`W{-M+cEA3!dpFptLA?i0|i=`Zyi>8j>IC{+3EBeqfmLw}M{n4~-alODI z|It#fp1&PpZDCvQYOZqC;E446nYUHf`YyiKH*sn>%<`DHpbnbL7A(4Ljt?iq7u4SA zt6SikIct`0rf+`r65nE+JH|90jm3xgcUASQMYYweoPHl3dX8g?2384b2@oWVFQxc~ zO`5Ic%gQE{OB~sRb4%(Zh@{*F^&aNniJ4w8@8)>U$Irj<^q;y7UamZRP9qG@pZJ#~ z!_>sJ&6J4y<_*Nbqn30;dLNV^7yCM&Z2TS(F3A^^v)>o{?3a;o$P;*<)Ojv;9C-J2 zzw(>HKY0XnWG_cTN)X|g!CGKl=nt1`Df>8&C~JIF;FpX`obU7lp9MJSFdQFICwOyS zOn5!sd_;ZVy%E2@=(CLbf^+`W7rYg4(hsOCI3@Uzf>$VbydLpQ{22;P9xtBc-qzPm z7} z5+Pm{f`Y&}R9;euf67iyq}g+87uF^4`pg{^{|RZ;sSEaRmaQX`IXSpbE;|oWaN={_!J%`WhEG2Sez6AEW$io-&Nk-Y zU!l=AGHA!%%{XdihciR7^B)HT5zr5_PFBJE` zZv6jthTwAfkY83!GKUNR#^(pB-sIPryrsW6g0tUHsKT>t(urY5JdTXn-yFfwAE40V zucYMkJ4g6e!;{~WX7YNl6aJET%+le+@4N#5_Z5DRLbx(1ypw+?JjW5bl}H`O_9?){ zafo#IlD?hw;QS=Gslq#a#_@LIb>1`J;kX?fz854XNO>mXvj4K5C!^OWfKP>UUQYg< zZ}v~pOb)+60h$~{^-c~S0i3)ep!}Uzy&B*)C;;0Z$1o?n)BgI3n?Wkn9Hmudm^_hT zlf#pzD^$1=PmU5T9KPrHB$prMnZCkjsfd2;1XSl7y~Kj*7tL|59ChW0Lb0Iw zug`H@dlQKW2xkB?hT$@A3|U>~R2r%eMoY8INap}!-CID2-sLl&VoLuu27e*@YYb#Q z$q$&A{9JtbPj>u3%~cwYKSAVj>s@2wQ4=;X%J#o&`deYK&VMxWF}^+wUfgB}UGAW@ z)2fA@_?JTu!un@ue;X9Phb>t9JMnVp>$R{QSd2t8r-jnDTX*?FR&Ab4QW~g7deV&b z-H0Vr1x@qOTcPuMR0Ouwf))%^9tEX#cX{JGhE;aGQhvSN69Vn|C*NWTlIe*vrr7 z==Pu7-X-Rr~ro=_%y3FJJJo0HbfD!m%x4d4vts?I&IiUi@OnE_FM_7qU_iD*^(+6=^k$%}vazvH6JAY;BW;)2k?(`z*>1 zQIx0jqI}QT{CsnJR{D!p3`Ai&6~<#@=|@CS9*k{5$(%*irKZ)4e8ncg`8a+TnWABe z8N4a%(8^{VTY&(~EkhiQ`GEQ~gTuti6?i$egrZBbBHcb?HP8N4ry$m4UF!w%2gd4G z=-7YQOz+w%2&_CwufI+&2D}>hua?+C@pw(M?OH?g72L@Rz-I6`&sFyB3;-5`3S`vvakO2_NMQT?S-G}kItF^GA24#dKY`v3Ye!qAM{~}G-%PLh|G5^6)?HqfU+ytx0NG- z%xi48s63Q2xxM)mOZy3qBe8oC+3XD!)0{O7u3+_E!=MSxcA)B}t`qpw&h%yQ|L`U8 zkNr#OL3<2g2_@2f(P9tE%muD}6HHZinW9Ou^MVtY_W0A$i)i&1JSAjZ6CIxoKGD$5 z_V<)1mnY)oVr+&|{>}T*-qH`Cm9fK>7{TXEtJ8X``4gBe-5CJN{`Xlc!So%bb@0S~ za6q=5=Jp&k))H&mI6Iu4226AR+i11m1S{VrS40CNzcg2Ns&3qpz8j`}_P-BfH<>}} zhU`#!r)k#>P77JZUaJ-z?IPozC=&3U#F|lb#ZWXd&|yOygA9bDDa~(R)O_lqGJB~z zA1iCun8xP9^iw7qCeS>iIy1zSB~D2W6~zVx_zQ-uQBZjy~(RVXiZ!8?A94qnb~q`J2C-2J zV=>rg74|rKZR&F8xS$DJs(GO63c=xX93lsXzacjZIDGrmJ72vwp=}c0q~4r7@ViaD zkEl1LWLQI4!foJNLe_zhwO{ZYwbV+(5nizlThJuo&LVOXbHEhF_i&BIrC5H)J}&d; zNCjpksy_fuC01?)rLeVIkm`79Hp*xD#2oyMgORmQXB%CuvyJ8W)f{?vw(&A-LE`h> zYblKztIwYAa;^Max^v++{@9LBG$>>B;M=)veL57~dJqL<7Cj>D0~)LT0OrCy@y2)I zFjsEL{Rg}!VeO&}wg%haUh;L3lC1%(nF&{!C5@fHG7=W1jfV4Bxv=xWfE5V%Bryw) z%c6jBkU|FFS1>xkM@u{nmm#WPbnNKpWEcekg}ac#P;@M;P46i92nK;@eK+LZp*0fC zxgi)`4ude;vrP9VFu@!u>R$8_BrV8GlffaGF)!be22gdWl?)GSfHx!ljn9GnOZ*l6pJg@of z>A9n8_lB*vX=4axgg`K8b(O*L4vQGPAQ+vT@88RP{-r_tPPZ_Cv<_3EP&73dod)@^ z%U$OQrcU#fA)Rdq6S9Ajk0pT+Y*7c;)++$;p=RmEDEJe$WV%Dq$wRG|FJG7q#G2^B z9P7m8Kg@zjr9$upqv7Ysc`yo@oTj8kA--UA2AIJ+M&nErG))N!)7Eu3c)^60!{SfF zdQ?dm=DqQaU)>zQ=G~$#M@AyZ@`e;n64n~<6KGJ!ivATm*3d?w_Zo||n2;1VT z)*vqC(70zgT+y+)Qiwxg)Y)bVn#Ah}TUPZ!nO!%$8|*wdoTJ)6n5qd{Eim;4V_^0V zyI1yngxnabCzBe?4y_#zN2qFl$Z8il+h9{J4Ex*&km}!SY|cWS)-X*pjpn%wj$K9= zqYfy4AcXA)YRE6@yC4OvgttBUb1@qDn_-29nSo6zNL2N^VAAWQClQs)-xAp(NTvXz z9spzAuDg(y`Z4Q`)h}Euj&saF6LYE3pmaarQXqgAi=k`9w}en#u+xHhViEIw%}C`2 z1Yx_GA>uE?l**obI_Te7ZpGYdbL-(-w*OFBdb5h%Q*OOrG!9<^T3bX|RPFP*;7b@| z-^5!)N8#<8GCHf7k)79w&Eveo3IoQ}ne0l}J zJ&VsivFG6xiv}wwWm4KS+}{>Tm)S>GC%PL#d8fx{JT#kWS_})@N6M_DVy`hIX90@` z3rYi?CXFx*eD7~_A9bh{G?mE-0cH)foXW~D?TVfdX5k_K%OOjGLe?=_`{tpr1JSFjl+)hRUEJnf-58#c@CcN;~1YdlqSU!|rA~FoVKzST2%;nz`wD$R7IP9mx z(6;UGxoJ6k6FktwE)@Lx)XnIdJ3}kQ6cP>B#5O6K^tuKFaO{4U*~>9mEeJsPm@}5QC7Bc%+zezSKgCq3?i9kShJp3n-q%yk<`IMN}UT_&{8`Hkt zjc(kE%tK231dFkv23T%|T*+Vwvt;bzQ>-<(R3eSW5h#nN4M4;U$?6Okn-3V9pTSB> zb6WZyITMF z7gh2s(HX;FGpsFtD|_L?0&$Dz)$S%1=~6-N5mAW<*9HWHXvGV;-+&jN*k4kS>kZZ` z*1^cTY0WWDbNc|Ky$N2CHss5l-f9+oXspVpLud)N-ZK3kHh+>5Ig}cCKR=K~Nwu+4xoq!A)##!y@*vRa@IypZb(qt5*9UzLEe!fL30jyoiN>3b`Nz z1PO0Re&6rR+|BGJ0d4#L{h$7x`}yqNd(X_AGjrz5nVBaILkr)Y$P~sZeF4&ZLT>`o_4=S_i@yIQ7DuaSJj; z+V$}u3C@tb>sWZG3nd{kfJn*LXPwK@aY%%0As68Ua|tt4x0|(1el%?Y7UZSRG1OvB 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�ivTuwCw+j4 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 dur!pgPkw({^WB&)em@%)+<&*X?0 +#endif /* _WIN32 */ + +#include "opj_includes.h" + + +/* ---------------------------------------------------------------------- */ +/* Functions to set the message handlers */ + +OPJ_BOOL OPJ_CALLCONV opj_set_info_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if (! l_codec) { + return OPJ_FALSE; + } + + l_codec->m_event_mgr.info_handler = p_callback; + l_codec->m_event_mgr.m_info_data = p_user_data; + + return OPJ_TRUE; +} + +OPJ_BOOL OPJ_CALLCONV opj_set_warning_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if (! l_codec) { + return OPJ_FALSE; + } + + l_codec->m_event_mgr.warning_handler = p_callback; + l_codec->m_event_mgr.m_warning_data = p_user_data; + + return OPJ_TRUE; +} + +OPJ_BOOL OPJ_CALLCONV opj_set_error_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + if (! l_codec) { + return OPJ_FALSE; + } + + l_codec->m_event_mgr.error_handler = p_callback; + l_codec->m_event_mgr.m_error_data = p_user_data; + + return OPJ_TRUE; +} + +/* ---------------------------------------------------------------------- */ + +static OPJ_SIZE_T opj_read_from_file(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data) +{ + FILE* p_file = (FILE*)p_user_data; + OPJ_SIZE_T l_nb_read = fread(p_buffer, 1, p_nb_bytes, (FILE*)p_file); + return l_nb_read ? l_nb_read : (OPJ_SIZE_T) - 1; +} + +static OPJ_UINT64 opj_get_data_length_from_file(void * p_user_data) +{ + FILE* p_file = (FILE*)p_user_data; + OPJ_OFF_T file_length = 0; + + OPJ_FSEEK(p_file, 0, SEEK_END); + file_length = (OPJ_OFF_T)OPJ_FTELL(p_file); + OPJ_FSEEK(p_file, 0, SEEK_SET); + + return (OPJ_UINT64)file_length; +} + +static OPJ_SIZE_T opj_write_from_file(void * p_buffer, OPJ_SIZE_T p_nb_bytes, + void * p_user_data) +{ + FILE* p_file = (FILE*)p_user_data; + return fwrite(p_buffer, 1, p_nb_bytes, p_file); +} + +static OPJ_OFF_T opj_skip_from_file(OPJ_OFF_T p_nb_bytes, void * p_user_data) +{ + FILE* p_file = (FILE*)p_user_data; + if (OPJ_FSEEK(p_file, p_nb_bytes, SEEK_CUR)) { + return -1; + } + + return p_nb_bytes; +} + +static OPJ_BOOL opj_seek_from_file(OPJ_OFF_T p_nb_bytes, void * p_user_data) +{ + FILE* p_file = (FILE*)p_user_data; + if (OPJ_FSEEK(p_file, p_nb_bytes, SEEK_SET)) { + return OPJ_FALSE; + } + + return OPJ_TRUE; +} + +static void opj_close_from_file(void* p_user_data) +{ + FILE* p_file = (FILE*)p_user_data; + fclose(p_file); +} + +/* ---------------------------------------------------------------------- */ +#ifdef _WIN32 +#ifndef OPJ_STATIC + +/* declaration to avoid warning: no previous prototype for 'DllMain' */ +BOOL APIENTRY +DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved); + +BOOL APIENTRY +DllMain(HINSTANCE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + + OPJ_ARG_NOT_USED(lpReserved); + OPJ_ARG_NOT_USED(hModule); + + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH : + break; + case DLL_PROCESS_DETACH : + break; + case DLL_THREAD_ATTACH : + case DLL_THREAD_DETACH : + break; + } + + return TRUE; +} +#endif /* OPJ_STATIC */ +#endif /* _WIN32 */ + +/* ---------------------------------------------------------------------- */ + +const char* OPJ_CALLCONV opj_version(void) +{ + return OPJ_PACKAGE_VERSION; +} + +/* ---------------------------------------------------------------------- */ +/* DECOMPRESSION FUNCTIONS*/ + +opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format) +{ + opj_codec_private_t *l_codec = 00; + + l_codec = (opj_codec_private_t*) opj_calloc(1, sizeof(opj_codec_private_t)); + if (!l_codec) { + return 00; + } + + l_codec->is_decompressor = 1; + + switch (p_format) { + case OPJ_CODEC_J2K: + l_codec->opj_dump_codec = (void (*)(void*, OPJ_INT32, FILE*)) j2k_dump; + + l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*)( + void*)) j2k_get_cstr_info; + + l_codec->opj_get_codec_index = (opj_codestream_index_t* (*)( + void*)) j2k_get_cstr_index; + + l_codec->m_codec_data.m_decompression.opj_decode = + (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + opj_image_t*, struct opj_event_mgr *)) opj_j2k_decode; + + l_codec->m_codec_data.m_decompression.opj_end_decompress = + (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_end_decompress; + + l_codec->m_codec_data.m_decompression.opj_read_header = + (OPJ_BOOL(*)(struct opj_stream_private *, + void *, + opj_image_t **, + struct opj_event_mgr *)) opj_j2k_read_header; + + l_codec->m_codec_data.m_decompression.opj_destroy = + (void (*)(void *))opj_j2k_destroy; + + l_codec->m_codec_data.m_decompression.opj_setup_decoder = + (void (*)(void *, opj_dparameters_t *)) opj_j2k_setup_decoder; + + l_codec->m_codec_data.m_decompression.opj_decoder_set_strict_mode = + (void (*)(void *, OPJ_BOOL)) opj_j2k_decoder_set_strict_mode; + + + l_codec->m_codec_data.m_decompression.opj_read_tile_header = + (OPJ_BOOL(*)(void *, + OPJ_UINT32*, + OPJ_UINT32*, + OPJ_INT32*, OPJ_INT32*, + OPJ_INT32*, OPJ_INT32*, + OPJ_UINT32*, + OPJ_BOOL*, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_read_tile_header; + + l_codec->m_codec_data.m_decompression.opj_decode_tile_data = + (OPJ_BOOL(*)(void *, + OPJ_UINT32, + OPJ_BYTE*, + OPJ_UINT32, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_decode_tile; + + l_codec->m_codec_data.m_decompression.opj_set_decode_area = + (OPJ_BOOL(*)(void *, + opj_image_t*, + OPJ_INT32, OPJ_INT32, OPJ_INT32, OPJ_INT32, + struct opj_event_mgr *)) opj_j2k_set_decode_area; + + l_codec->m_codec_data.m_decompression.opj_get_decoded_tile = + (OPJ_BOOL(*)(void *p_codec, + opj_stream_private_t *p_cio, + opj_image_t *p_image, + struct opj_event_mgr * p_manager, + OPJ_UINT32 tile_index)) opj_j2k_get_tile; + + l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor = + (OPJ_BOOL(*)(void * p_codec, + OPJ_UINT32 res_factor, + struct opj_event_mgr * p_manager)) opj_j2k_set_decoded_resolution_factor; + + l_codec->m_codec_data.m_decompression.opj_set_decoded_components = + (OPJ_BOOL(*)(void * p_codec, + OPJ_UINT32 numcomps, + const OPJ_UINT32 * comps_indices, + struct opj_event_mgr * p_manager)) opj_j2k_set_decoded_components; + + l_codec->opj_set_threads = + (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_j2k_set_threads; + + l_codec->m_codec = opj_j2k_create_decompress(); + + if (! l_codec->m_codec) { + opj_free(l_codec); + return NULL; + } + + break; + + case OPJ_CODEC_JP2: + /* get a JP2 decoder handle */ + l_codec->opj_dump_codec = (void (*)(void*, OPJ_INT32, FILE*)) jp2_dump; + + l_codec->opj_get_codec_info = (opj_codestream_info_v2_t* (*)( + void*)) jp2_get_cstr_info; + + l_codec->opj_get_codec_index = (opj_codestream_index_t* (*)( + void*)) jp2_get_cstr_index; + + l_codec->m_codec_data.m_decompression.opj_decode = + (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + opj_image_t*, + struct opj_event_mgr *)) opj_jp2_decode; + + l_codec->m_codec_data.m_decompression.opj_end_decompress = + (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_end_decompress; + + l_codec->m_codec_data.m_decompression.opj_read_header = + (OPJ_BOOL(*)(struct opj_stream_private *, + void *, + opj_image_t **, + struct opj_event_mgr *)) opj_jp2_read_header; + + l_codec->m_codec_data.m_decompression.opj_read_tile_header = + (OPJ_BOOL(*)(void *, + OPJ_UINT32*, + OPJ_UINT32*, + OPJ_INT32*, + OPJ_INT32*, + OPJ_INT32 *, + OPJ_INT32 *, + OPJ_UINT32 *, + OPJ_BOOL *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_read_tile_header; + + l_codec->m_codec_data.m_decompression.opj_decode_tile_data = + (OPJ_BOOL(*)(void *, + OPJ_UINT32, OPJ_BYTE*, OPJ_UINT32, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_decode_tile; + + l_codec->m_codec_data.m_decompression.opj_destroy = (void (*)( + void *))opj_jp2_destroy; + + l_codec->m_codec_data.m_decompression.opj_setup_decoder = + (void (*)(void *, opj_dparameters_t *)) opj_jp2_setup_decoder; + + l_codec->m_codec_data.m_decompression.opj_decoder_set_strict_mode = + (void (*)(void *, OPJ_BOOL)) opj_jp2_decoder_set_strict_mode; + + l_codec->m_codec_data.m_decompression.opj_set_decode_area = + (OPJ_BOOL(*)(void *, + opj_image_t*, + OPJ_INT32, OPJ_INT32, OPJ_INT32, OPJ_INT32, + struct opj_event_mgr *)) opj_jp2_set_decode_area; + + l_codec->m_codec_data.m_decompression.opj_get_decoded_tile = + (OPJ_BOOL(*)(void *p_codec, + opj_stream_private_t *p_cio, + opj_image_t *p_image, + struct opj_event_mgr * p_manager, + OPJ_UINT32 tile_index)) opj_jp2_get_tile; + + l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor = + (OPJ_BOOL(*)(void * p_codec, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager)) opj_jp2_set_decoded_resolution_factor; + + l_codec->m_codec_data.m_decompression.opj_set_decoded_components = + (OPJ_BOOL(*)(void * p_codec, + OPJ_UINT32 numcomps, + const OPJ_UINT32 * comps_indices, + struct opj_event_mgr * p_manager)) opj_jp2_set_decoded_components; + + l_codec->opj_set_threads = + (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_jp2_set_threads; + + l_codec->m_codec = opj_jp2_create(OPJ_TRUE); + + if (! l_codec->m_codec) { + opj_free(l_codec); + return 00; + } + + break; + case OPJ_CODEC_UNKNOWN: + case OPJ_CODEC_JPT: + default: + opj_free(l_codec); + return 00; + } + + opj_set_default_event_handler(&(l_codec->m_event_mgr)); + return (opj_codec_t*) l_codec; +} + +void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t + *parameters) +{ + if (parameters) { + memset(parameters, 0, sizeof(opj_dparameters_t)); + /* default decoding parameters */ + parameters->cp_layer = 0; + parameters->cp_reduce = 0; + + parameters->decod_format = -1; + parameters->cod_format = -1; + parameters->flags = 0; + /* UniPG>> */ +#ifdef USE_JPWL + parameters->jpwl_correct = OPJ_FALSE; + parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS; + parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES; +#endif /* USE_JPWL */ + /* <= 0)) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + return l_codec->opj_set_threads(l_codec->m_codec, (OPJ_UINT32)num_threads); + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec, + opj_dparameters_t *parameters + ) +{ + if (p_codec && parameters) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (! l_codec->is_decompressor) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "Codec provided to the opj_setup_decoder function is not a decompressor handler.\n"); + return OPJ_FALSE; + } + + l_codec->m_codec_data.m_decompression.opj_setup_decoder(l_codec->m_codec, + parameters); + return OPJ_TRUE; + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_decoder_set_strict_mode(opj_codec_t *p_codec, + OPJ_BOOL strict) +{ + if (p_codec) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (! l_codec->is_decompressor) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "Codec provided to the opj_decoder_set_strict_mode function is not a decompressor handler.\n"); + return OPJ_FALSE; + } + + l_codec->m_codec_data.m_decompression.opj_decoder_set_strict_mode( + l_codec->m_codec, + strict); + return OPJ_TRUE; + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_read_header(opj_stream_t *p_stream, + opj_codec_t *p_codec, + opj_image_t **p_image) +{ + if (p_codec && p_stream) { + opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; + opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; + + if (! l_codec->is_decompressor) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "Codec provided to the opj_read_header function is not a decompressor handler.\n"); + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_read_header(l_stream, + l_codec->m_codec, + p_image, + &(l_codec->m_event_mgr)); + } + + return OPJ_FALSE; +} + + +OPJ_BOOL OPJ_CALLCONV opj_set_decoded_components(opj_codec_t *p_codec, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + OPJ_BOOL apply_color_transforms) +{ + if (p_codec) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (! l_codec->is_decompressor) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "Codec provided to the opj_set_decoded_components function is not a decompressor handler.\n"); + return OPJ_FALSE; + } + + if (apply_color_transforms) { + opj_event_msg(&(l_codec->m_event_mgr), EVT_ERROR, + "apply_color_transforms = OPJ_TRUE is not supported.\n"); + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_set_decoded_components( + l_codec->m_codec, + numcomps, + comps_indices, + &(l_codec->m_event_mgr)); + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_decode(opj_codec_t *p_codec, + opj_stream_t *p_stream, + opj_image_t* p_image) +{ + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_decode(l_codec->m_codec, + l_stream, + p_image, + &(l_codec->m_event_mgr)); + } + + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_set_decode_area(opj_codec_t *p_codec, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y + ) +{ + if (p_codec) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_set_decode_area( + l_codec->m_codec, + p_image, + p_start_x, p_start_y, + p_end_x, p_end_y, + &(l_codec->m_event_mgr)); + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_read_tile_header(opj_codec_t *p_codec, + opj_stream_t * p_stream, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_should_go_on) +{ + if (p_codec && p_stream && p_data_size && p_tile_index) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_read_tile_header( + l_codec->m_codec, + p_tile_index, + p_data_size, + p_tile_x0, p_tile_y0, + p_tile_x1, p_tile_y1, + p_nb_comps, + p_should_go_on, + l_stream, + &(l_codec->m_event_mgr)); + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_decode_tile_data(opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream + ) +{ + if (p_codec && p_data && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_decode_tile_data( + l_codec->m_codec, + p_tile_index, + p_data, + p_data_size, + l_stream, + &(l_codec->m_event_mgr)); + } + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_get_decoded_tile(opj_codec_t *p_codec, + opj_stream_t *p_stream, + opj_image_t *p_image, + OPJ_UINT32 tile_index) +{ + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_get_decoded_tile( + l_codec->m_codec, + l_stream, + p_image, + &(l_codec->m_event_mgr), + tile_index); + } + + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_set_decoded_resolution_factor(opj_codec_t *p_codec, + OPJ_UINT32 res_factor) +{ + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (!l_codec) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_set_decoded_resolution_factor( + l_codec->m_codec, + res_factor, + &(l_codec->m_event_mgr)); +} + +/* ---------------------------------------------------------------------- */ +/* COMPRESSION FUNCTIONS*/ + +opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format) +{ + opj_codec_private_t *l_codec = 00; + + l_codec = (opj_codec_private_t*)opj_calloc(1, sizeof(opj_codec_private_t)); + if (!l_codec) { + return 00; + } + + l_codec->is_decompressor = 0; + + switch (p_format) { + case OPJ_CODEC_J2K: + l_codec->m_codec_data.m_compression.opj_encode = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_encode; + + l_codec->m_codec_data.m_compression.opj_end_compress = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_end_compress; + + l_codec->m_codec_data.m_compression.opj_start_compress = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_image *, + struct opj_event_mgr *)) opj_j2k_start_compress; + + l_codec->m_codec_data.m_compression.opj_write_tile = (OPJ_BOOL(*)(void *, + OPJ_UINT32, + OPJ_BYTE*, + OPJ_UINT32, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_j2k_write_tile; + + l_codec->m_codec_data.m_compression.opj_destroy = (void (*)( + void *)) opj_j2k_destroy; + + l_codec->m_codec_data.m_compression.opj_setup_encoder = (OPJ_BOOL(*)(void *, + opj_cparameters_t *, + struct opj_image *, + struct opj_event_mgr *)) opj_j2k_setup_encoder; + + l_codec->m_codec_data.m_compression.opj_encoder_set_extra_options = (OPJ_BOOL( + *)(void *, + const char* const*, + struct opj_event_mgr *)) opj_j2k_encoder_set_extra_options; + + l_codec->opj_set_threads = + (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_j2k_set_threads; + + l_codec->m_codec = opj_j2k_create_compress(); + if (! l_codec->m_codec) { + opj_free(l_codec); + return 00; + } + + break; + + case OPJ_CODEC_JP2: + /* get a JP2 decoder handle */ + l_codec->m_codec_data.m_compression.opj_encode = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_encode; + + l_codec->m_codec_data.m_compression.opj_end_compress = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_end_compress; + + l_codec->m_codec_data.m_compression.opj_start_compress = (OPJ_BOOL(*)(void *, + struct opj_stream_private *, + struct opj_image *, + struct opj_event_mgr *)) opj_jp2_start_compress; + + l_codec->m_codec_data.m_compression.opj_write_tile = (OPJ_BOOL(*)(void *, + OPJ_UINT32, + OPJ_BYTE*, + OPJ_UINT32, + struct opj_stream_private *, + struct opj_event_mgr *)) opj_jp2_write_tile; + + l_codec->m_codec_data.m_compression.opj_destroy = (void (*)( + void *)) opj_jp2_destroy; + + l_codec->m_codec_data.m_compression.opj_setup_encoder = (OPJ_BOOL(*)(void *, + opj_cparameters_t *, + struct opj_image *, + struct opj_event_mgr *)) opj_jp2_setup_encoder; + + l_codec->m_codec_data.m_compression.opj_encoder_set_extra_options = (OPJ_BOOL( + *)(void *, + const char* const*, + struct opj_event_mgr *)) opj_jp2_encoder_set_extra_options; + + l_codec->opj_set_threads = + (OPJ_BOOL(*)(void * p_codec, OPJ_UINT32 num_threads)) opj_jp2_set_threads; + + l_codec->m_codec = opj_jp2_create(OPJ_FALSE); + if (! l_codec->m_codec) { + opj_free(l_codec); + return 00; + } + + break; + + case OPJ_CODEC_UNKNOWN: + case OPJ_CODEC_JPT: + default: + opj_free(l_codec); + return 00; + } + + opj_set_default_event_handler(&(l_codec->m_event_mgr)); + return (opj_codec_t*) l_codec; +} + +void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t + *parameters) +{ + if (parameters) { + memset(parameters, 0, sizeof(opj_cparameters_t)); + /* default coding parameters */ + parameters->cp_cinema = OPJ_OFF; /* DEPRECATED */ + parameters->rsiz = OPJ_PROFILE_NONE; + parameters->max_comp_size = 0; + parameters->numresolution = OPJ_COMP_PARAM_DEFAULT_NUMRESOLUTION; + parameters->cp_rsiz = OPJ_STD_RSIZ; /* DEPRECATED */ + parameters->cblockw_init = OPJ_COMP_PARAM_DEFAULT_CBLOCKW; + parameters->cblockh_init = OPJ_COMP_PARAM_DEFAULT_CBLOCKH; + parameters->prog_order = OPJ_COMP_PARAM_DEFAULT_PROG_ORDER; + parameters->roi_compno = -1; /* no ROI */ + parameters->subsampling_dx = 1; + parameters->subsampling_dy = 1; + parameters->tp_on = 0; + parameters->decod_format = -1; + parameters->cod_format = -1; + parameters->tcp_rates[0] = 0; + parameters->tcp_numlayers = 0; + parameters->cp_disto_alloc = 0; + parameters->cp_fixed_alloc = 0; + parameters->cp_fixed_quality = 0; + parameters->jpip_on = OPJ_FALSE; + /* UniPG>> */ +#ifdef USE_JPWL + parameters->jpwl_epc_on = OPJ_FALSE; + parameters->jpwl_hprot_MH = -1; /* -1 means unassigned */ + { + int i; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + parameters->jpwl_hprot_TPH_tileno[i] = -1; /* unassigned */ + parameters->jpwl_hprot_TPH[i] = 0; /* absent */ + } + }; + { + int i; + for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) { + parameters->jpwl_pprot_tileno[i] = -1; /* unassigned */ + parameters->jpwl_pprot_packno[i] = -1; /* unassigned */ + parameters->jpwl_pprot[i] = 0; /* absent */ + } + }; + parameters->jpwl_sens_size = 0; /* 0 means no ESD */ + parameters->jpwl_sens_addr = 0; /* 0 means auto */ + parameters->jpwl_sens_range = 0; /* 0 means packet */ + parameters->jpwl_sens_MH = -1; /* -1 means unassigned */ + { + int i; + for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) { + parameters->jpwl_sens_TPH_tileno[i] = -1; /* unassigned */ + parameters->jpwl_sens_TPH[i] = -1; /* absent */ + } + }; +#endif /* USE_JPWL */ + /* <is_decompressor) { + return l_codec->m_codec_data.m_compression.opj_setup_encoder(l_codec->m_codec, + parameters, + p_image, + &(l_codec->m_event_mgr)); + } + } + + return OPJ_FALSE; +} + +/* ----------------------------------------------------------------------- */ + +OPJ_BOOL OPJ_CALLCONV opj_encoder_set_extra_options(opj_codec_t *p_codec, + const char* const* options) +{ + if (p_codec) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (! l_codec->is_decompressor) { + return l_codec->m_codec_data.m_compression.opj_encoder_set_extra_options( + l_codec->m_codec, + options, + &(l_codec->m_event_mgr)); + } + } + + return OPJ_FALSE; +} + +/* ----------------------------------------------------------------------- */ + +OPJ_BOOL OPJ_CALLCONV opj_start_compress(opj_codec_t *p_codec, + opj_image_t * p_image, + opj_stream_t *p_stream) +{ + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return l_codec->m_codec_data.m_compression.opj_start_compress(l_codec->m_codec, + l_stream, + p_image, + &(l_codec->m_event_mgr)); + } + } + + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_encode(opj_codec_t *p_info, opj_stream_t *p_stream) +{ + if (p_info && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_info; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return l_codec->m_codec_data.m_compression.opj_encode(l_codec->m_codec, + l_stream, + &(l_codec->m_event_mgr)); + } + } + + return OPJ_FALSE; + +} + +OPJ_BOOL OPJ_CALLCONV opj_end_compress(opj_codec_t *p_codec, + opj_stream_t *p_stream) +{ + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return l_codec->m_codec_data.m_compression.opj_end_compress(l_codec->m_codec, + l_stream, + &(l_codec->m_event_mgr)); + } + } + return OPJ_FALSE; + +} + +OPJ_BOOL OPJ_CALLCONV opj_end_decompress(opj_codec_t *p_codec, + opj_stream_t *p_stream) +{ + if (p_codec && p_stream) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (! l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_decompression.opj_end_decompress( + l_codec->m_codec, + l_stream, + &(l_codec->m_event_mgr)); + } + + return OPJ_FALSE; +} + +OPJ_BOOL OPJ_CALLCONV opj_set_MCT(opj_cparameters_t *parameters, + OPJ_FLOAT32 * pEncodingMatrix, + OPJ_INT32 * p_dc_shift, OPJ_UINT32 pNbComp) +{ + OPJ_UINT32 l_matrix_size = pNbComp * pNbComp * (OPJ_UINT32)sizeof(OPJ_FLOAT32); + OPJ_UINT32 l_dc_shift_size = pNbComp * (OPJ_UINT32)sizeof(OPJ_INT32); + OPJ_UINT32 l_mct_total_size = l_matrix_size + l_dc_shift_size; + + /* add MCT capability */ + if (OPJ_IS_PART2(parameters->rsiz)) { + parameters->rsiz |= OPJ_EXTENSION_MCT; + } else { + parameters->rsiz = ((OPJ_PROFILE_PART2) | (OPJ_EXTENSION_MCT)); + } + parameters->irreversible = 1; + + /* use array based MCT */ + parameters->tcp_mct = 2; + parameters->mct_data = opj_malloc(l_mct_total_size); + if (! parameters->mct_data) { + return OPJ_FALSE; + } + + memcpy(parameters->mct_data, pEncodingMatrix, l_matrix_size); + memcpy(((OPJ_BYTE *) parameters->mct_data) + l_matrix_size, p_dc_shift, + l_dc_shift_size); + + return OPJ_TRUE; +} + +OPJ_BOOL OPJ_CALLCONV opj_write_tile(opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream) +{ + if (p_codec && p_stream && p_data) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + opj_stream_private_t * l_stream = (opj_stream_private_t *) p_stream; + + if (l_codec->is_decompressor) { + return OPJ_FALSE; + } + + return l_codec->m_codec_data.m_compression.opj_write_tile(l_codec->m_codec, + p_tile_index, + p_data, + p_data_size, + l_stream, + &(l_codec->m_event_mgr)); + } + + return OPJ_FALSE; +} + +/* ---------------------------------------------------------------------- */ + +void OPJ_CALLCONV opj_destroy_codec(opj_codec_t *p_codec) +{ + if (p_codec) { + opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; + + if (l_codec->is_decompressor) { + l_codec->m_codec_data.m_decompression.opj_destroy(l_codec->m_codec); + } else { + l_codec->m_codec_data.m_compression.opj_destroy(l_codec->m_codec); + } + + l_codec->m_codec = 00; + opj_free(l_codec); + } +} + +/* ---------------------------------------------------------------------- */ + +void OPJ_CALLCONV opj_dump_codec(opj_codec_t *p_codec, + OPJ_INT32 info_flag, + FILE* output_stream) +{ + if (p_codec) { + opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; + + l_codec->opj_dump_codec(l_codec->m_codec, info_flag, output_stream); + return; + } + + /* TODO return error */ + /* fprintf(stderr, "[ERROR] Input parameter of the dump_codec function are incorrect.\n"); */ + return; +} + +opj_codestream_info_v2_t* OPJ_CALLCONV opj_get_cstr_info(opj_codec_t *p_codec) +{ + if (p_codec) { + opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; + + return l_codec->opj_get_codec_info(l_codec->m_codec); + } + + return NULL; +} + +void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_v2_t **cstr_info) +{ + if (cstr_info) { + + if ((*cstr_info)->m_default_tile_info.tccp_info) { + opj_free((*cstr_info)->m_default_tile_info.tccp_info); + } + + if ((*cstr_info)->tile_info) { + /* FIXME not used for the moment*/ + } + + opj_free((*cstr_info)); + (*cstr_info) = NULL; + } +} + +opj_codestream_index_t * OPJ_CALLCONV opj_get_cstr_index(opj_codec_t *p_codec) +{ + if (p_codec) { + opj_codec_private_t* l_codec = (opj_codec_private_t*) p_codec; + + return l_codec->opj_get_codec_index(l_codec->m_codec); + } + + return NULL; +} + +void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t **p_cstr_index) +{ + if (*p_cstr_index) { + j2k_destroy_cstr_index(*p_cstr_index); + (*p_cstr_index) = NULL; + } +} + +opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream( + const char *fname, OPJ_BOOL p_is_read_stream) +{ + return opj_stream_create_file_stream(fname, OPJ_J2K_STREAM_CHUNK_SIZE, + p_is_read_stream); +} + +opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream( + const char *fname, + OPJ_SIZE_T p_size, + OPJ_BOOL p_is_read_stream) +{ + opj_stream_t* l_stream = 00; + FILE *p_file; + const char *mode; + + if (! fname) { + return NULL; + } + + if (p_is_read_stream) { + mode = "rb"; + } else { + mode = "wb"; + } + + p_file = fopen(fname, mode); + + if (! p_file) { + return NULL; + } + + l_stream = opj_stream_create(p_size, p_is_read_stream); + if (! l_stream) { + fclose(p_file); + return NULL; + } + + opj_stream_set_user_data(l_stream, p_file, opj_close_from_file); + opj_stream_set_user_data_length(l_stream, + opj_get_data_length_from_file(p_file)); + opj_stream_set_read_function(l_stream, opj_read_from_file); + opj_stream_set_write_function(l_stream, + (opj_stream_write_fn) opj_write_from_file); + opj_stream_set_skip_function(l_stream, opj_skip_from_file); + opj_stream_set_seek_function(l_stream, opj_seek_from_file); + + return l_stream; +} + + +void* OPJ_CALLCONV opj_image_data_alloc(OPJ_SIZE_T size) +{ + void* ret = opj_aligned_malloc(size); + /* printf("opj_image_data_alloc %p\n", ret); */ + return ret; +} + +void OPJ_CALLCONV opj_image_data_free(void* ptr) +{ + /* printf("opj_image_data_free %p\n", ptr); */ + opj_aligned_free(ptr); +} diff --git a/client/deps/openjpeg/openjpeg.h b/client/deps/openjpeg/openjpeg.h new file mode 100644 index 000000000..fe2f1ee0c --- /dev/null +++ b/client/deps/openjpeg/openjpeg.h @@ -0,0 +1,1786 @@ +/* +* The copyright in this software is being made available under the 2-clauses +* BSD License, included below. This software may be subject to other third +* party and contributor rights, including patent rights, and no such rights +* are granted under this license. +* +* Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium +* Copyright (c) 2002-2014, Professor Benoit Macq +* Copyright (c) 2001-2003, David Janssens +* Copyright (c) 2002-2003, Yannick Verschueren +* Copyright (c) 2003-2007, Francois-Olivier Devaux +* Copyright (c) 2003-2014, Antonin Descampe +* Copyright (c) 2005, Herve Drolon, FreeImage Team +* Copyright (c) 2006-2007, Parvatha Elangovan +* Copyright (c) 2008, Jerome Fimes, Communications & Systemes +* Copyright (c) 2010-2011, Kaori Hagihara +* Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France +* Copyright (c) 2012, CS Systemes d'Information, France +* 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. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. +*/ +#ifndef OPENJPEG_H +#define OPENJPEG_H + + +/* +========================================================== + Compiler directives +========================================================== +*/ + +/* +The inline keyword is supported by C99 but not by C90. +Most compilers implement their own version of this keyword ... +*/ +#ifndef INLINE +#if defined(_MSC_VER) +#define INLINE __forceinline +#elif defined(__GNUC__) +#define INLINE __inline__ +#elif defined(__MWERKS__) +#define INLINE inline +#else +/* add other compilers here ... */ +#define INLINE +#endif /* defined() */ +#endif /* INLINE */ + +/* deprecated attribute */ +#ifdef __GNUC__ +#define OPJ_DEPRECATED(func) func __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define OPJ_DEPRECATED(func) __declspec(deprecated) func +#else +#pragma message("WARNING: You need to implement DEPRECATED for this compiler") +#define OPJ_DEPRECATED(func) func +#endif + +#if defined(__GNUC__) && __GNUC__ >= 6 +#define OPJ_DEPRECATED_STRUCT_MEMBER(memb, msg) __attribute__ ((deprecated(msg))) memb +#else +#define OPJ_DEPRECATED_STRUCT_MEMBER(memb, msg) memb +#endif + +#if defined(OPJ_STATIC) || !defined(_WIN32) +/* http://gcc.gnu.org/wiki/Visibility */ +# if !defined(_WIN32) && __GNUC__ >= 4 +# if defined(OPJ_STATIC) /* static library uses "hidden" */ +# define OPJ_API __attribute__ ((visibility ("hidden"))) +# else +# define OPJ_API __attribute__ ((visibility ("default"))) +# endif +# define OPJ_LOCAL __attribute__ ((visibility ("hidden"))) +# else +# define OPJ_API +# define OPJ_LOCAL +# endif +# define OPJ_CALLCONV +#else +# define OPJ_CALLCONV __stdcall +/* +The following ifdef block is the standard way of creating macros which make exporting +from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS +symbol defined on the command line. this symbol should not be defined on any project +that uses this DLL. This way any other project whose source files include this file see +OPJ_API functions as being imported from a DLL, whereas this DLL sees symbols +defined with this macro as being exported. +*/ +# if defined(OPJ_EXPORTS) || defined(DLL_EXPORT) +# define OPJ_API __declspec(dllexport) +# else +# define OPJ_API __declspec(dllimport) +# endif /* OPJ_EXPORTS */ +#endif /* !OPJ_STATIC || !_WIN32 */ + +typedef int OPJ_BOOL; +#define OPJ_TRUE 1 +#define OPJ_FALSE 0 + +typedef char OPJ_CHAR; +typedef float OPJ_FLOAT32; +typedef double OPJ_FLOAT64; +typedef unsigned char OPJ_BYTE; + +#include + +typedef int8_t OPJ_INT8; +typedef uint8_t OPJ_UINT8; +typedef int16_t OPJ_INT16; +typedef uint16_t OPJ_UINT16; +typedef int32_t OPJ_INT32; +typedef uint32_t OPJ_UINT32; +typedef int64_t OPJ_INT64; +typedef uint64_t OPJ_UINT64; + +typedef int64_t OPJ_OFF_T; /* 64-bit file offset type */ + +#include +typedef size_t OPJ_SIZE_T; + +#include "opj_config.h" + +/* Avoid compile-time warning because parameter is not used */ +#define OPJ_ARG_NOT_USED(x) (void)(x) + +/* +========================================================== + Useful constant definitions +========================================================== +*/ + +#define OPJ_PATH_LEN 4096 /**< Maximum allowed size for filenames */ + +#define OPJ_J2K_MAXRLVLS 33 /**< Number of maximum resolution level authorized */ +#define OPJ_J2K_MAXBANDS (3*OPJ_J2K_MAXRLVLS-2) /**< Number of maximum sub-band linked to number of resolution level */ + +#define OPJ_J2K_DEFAULT_NB_SEGS 10 +#define OPJ_J2K_STREAM_CHUNK_SIZE 0x100000 /** 1 mega by default */ +#define OPJ_J2K_DEFAULT_HEADER_SIZE 1000 +#define OPJ_J2K_MCC_DEFAULT_NB_RECORDS 10 +#define OPJ_J2K_MCT_DEFAULT_NB_RECORDS 10 + +/* UniPG>> */ /* NOT YET USED IN THE V2 VERSION OF OPENJPEG */ +#define JPWL_MAX_NO_TILESPECS 16 /**< Maximum number of tile parts expected by JPWL: increase at your will */ +#define JPWL_MAX_NO_PACKSPECS 16 /**< Maximum number of packet parts expected by JPWL: increase at your will */ +#define JPWL_MAX_NO_MARKERS 512 /**< Maximum number of JPWL markers: increase at your will */ +#define JPWL_PRIVATEINDEX_NAME "jpwl_index_privatefilename" /**< index file name used when JPWL is on */ +#define JPWL_EXPECTED_COMPONENTS 3 /**< Expect this number of components, so you'll find better the first EPB */ +#define JPWL_MAXIMUM_TILES 8192 /**< Expect this maximum number of tiles, to avoid some crashes */ +#define JPWL_MAXIMUM_HAMMING 2 /**< Expect this maximum number of bit errors in marker id's */ +#define JPWL_MAXIMUM_EPB_ROOM 65450 /**< Expect this maximum number of bytes for composition of EPBs */ +/* <= OPJ_PROFILE_CINEMA_2K)&&((v) <= OPJ_PROFILE_CINEMA_S4K)) +#define OPJ_IS_STORAGE(v) ((v) == OPJ_PROFILE_CINEMA_LTS) +#define OPJ_IS_BROADCAST(v) (((v) >= OPJ_PROFILE_BC_SINGLE)&&((v) <= ((OPJ_PROFILE_BC_MULTI_R) | (0x000b)))) +#define OPJ_IS_IMF(v) (((v) >= OPJ_PROFILE_IMF_2K)&&((v) <= ((OPJ_PROFILE_IMF_8K_R) | (0x009b)))) +#define OPJ_IS_PART2(v) ((v) & OPJ_PROFILE_PART2) + +#define OPJ_GET_IMF_PROFILE(v) ((v) & 0xff00) /** Extract IMF profile without mainlevel/sublevel */ +#define OPJ_GET_IMF_MAINLEVEL(v) ((v) & 0xf) /** Extract IMF main level */ +#define OPJ_GET_IMF_SUBLEVEL(v) (((v) >> 4) & 0xf) /** Extract IMF sub level */ + +#define OPJ_IMF_MAINLEVEL_MAX 11 /** Maximum main level */ + +/** Max. Components Sampling Rate (MSamples/sec) per IMF main level */ +#define OPJ_IMF_MAINLEVEL_1_MSAMPLESEC 65 /** MSamples/sec for IMF main level 1 */ +#define OPJ_IMF_MAINLEVEL_2_MSAMPLESEC 130 /** MSamples/sec for IMF main level 2 */ +#define OPJ_IMF_MAINLEVEL_3_MSAMPLESEC 195 /** MSamples/sec for IMF main level 3 */ +#define OPJ_IMF_MAINLEVEL_4_MSAMPLESEC 260 /** MSamples/sec for IMF main level 4 */ +#define OPJ_IMF_MAINLEVEL_5_MSAMPLESEC 520 /** MSamples/sec for IMF main level 5 */ +#define OPJ_IMF_MAINLEVEL_6_MSAMPLESEC 1200 /** MSamples/sec for IMF main level 6 */ +#define OPJ_IMF_MAINLEVEL_7_MSAMPLESEC 2400 /** MSamples/sec for IMF main level 7 */ +#define OPJ_IMF_MAINLEVEL_8_MSAMPLESEC 4800 /** MSamples/sec for IMF main level 8 */ +#define OPJ_IMF_MAINLEVEL_9_MSAMPLESEC 9600 /** MSamples/sec for IMF main level 9 */ +#define OPJ_IMF_MAINLEVEL_10_MSAMPLESEC 19200 /** MSamples/sec for IMF main level 10 */ +#define OPJ_IMF_MAINLEVEL_11_MSAMPLESEC 38400 /** MSamples/sec for IMF main level 11 */ + +/** Max. compressed Bit Rate (Mbits/s) per IMF sub level */ +#define OPJ_IMF_SUBLEVEL_1_MBITSSEC 200 /** Mbits/s for IMF sub level 1 */ +#define OPJ_IMF_SUBLEVEL_2_MBITSSEC 400 /** Mbits/s for IMF sub level 2 */ +#define OPJ_IMF_SUBLEVEL_3_MBITSSEC 800 /** Mbits/s for IMF sub level 3 */ +#define OPJ_IMF_SUBLEVEL_4_MBITSSEC 1600 /** Mbits/s for IMF sub level 4 */ +#define OPJ_IMF_SUBLEVEL_5_MBITSSEC 3200 /** Mbits/s for IMF sub level 5 */ +#define OPJ_IMF_SUBLEVEL_6_MBITSSEC 6400 /** Mbits/s for IMF sub level 6 */ +#define OPJ_IMF_SUBLEVEL_7_MBITSSEC 12800 /** Mbits/s for IMF sub level 7 */ +#define OPJ_IMF_SUBLEVEL_8_MBITSSEC 25600 /** Mbits/s for IMF sub level 8 */ +#define OPJ_IMF_SUBLEVEL_9_MBITSSEC 51200 /** Mbits/s for IMF sub level 9 */ + +/** + * JPEG 2000 codestream and component size limits in cinema profiles + * */ +#define OPJ_CINEMA_24_CS 1302083 /** Maximum codestream length for 24fps */ +#define OPJ_CINEMA_48_CS 651041 /** Maximum codestream length for 48fps */ +#define OPJ_CINEMA_24_COMP 1041666 /** Maximum size per color component for 2K & 4K @ 24fps */ +#define OPJ_CINEMA_48_COMP 520833 /** Maximum size per color component for 2K @ 48fps */ + +/* +========================================================== + enum definitions +========================================================== +*/ + +/** + * DEPRECATED: use RSIZ, OPJ_PROFILE_* and OPJ_EXTENSION_* instead + * Rsiz Capabilities + * */ +typedef enum RSIZ_CAPABILITIES { + OPJ_STD_RSIZ = 0, /** Standard JPEG2000 profile*/ + OPJ_CINEMA2K = 3, /** Profile name for a 2K image*/ + OPJ_CINEMA4K = 4, /** Profile name for a 4K image*/ + OPJ_MCT = 0x8100 +} OPJ_RSIZ_CAPABILITIES; + +/** + * DEPRECATED: use RSIZ, OPJ_PROFILE_* and OPJ_EXTENSION_* instead + * Digital cinema operation mode + * */ +typedef enum CINEMA_MODE { + OPJ_OFF = 0, /** Not Digital Cinema*/ + OPJ_CINEMA2K_24 = 1, /** 2K Digital Cinema at 24 fps*/ + OPJ_CINEMA2K_48 = 2, /** 2K Digital Cinema at 48 fps*/ + OPJ_CINEMA4K_24 = 3 /** 4K Digital Cinema at 24 fps*/ +} OPJ_CINEMA_MODE; + +/** + * Progression order + * */ +typedef enum PROG_ORDER { + OPJ_PROG_UNKNOWN = -1, /**< place-holder */ + OPJ_LRCP = 0, /**< layer-resolution-component-precinct order */ + OPJ_RLCP = 1, /**< resolution-layer-component-precinct order */ + OPJ_RPCL = 2, /**< resolution-precinct-component-layer order */ + OPJ_PCRL = 3, /**< precinct-component-resolution-layer order */ + OPJ_CPRL = 4 /**< component-precinct-resolution-layer order */ +} OPJ_PROG_ORDER; + +/** + * Supported image color spaces +*/ +typedef enum COLOR_SPACE { + OPJ_CLRSPC_UNKNOWN = -1, /**< not supported by the library */ + OPJ_CLRSPC_UNSPECIFIED = 0, /**< not specified in the codestream */ + OPJ_CLRSPC_SRGB = 1, /**< sRGB */ + OPJ_CLRSPC_GRAY = 2, /**< grayscale */ + OPJ_CLRSPC_SYCC = 3, /**< YUV */ + OPJ_CLRSPC_EYCC = 4, /**< e-YCC */ + OPJ_CLRSPC_CMYK = 5 /**< CMYK */ +} OPJ_COLOR_SPACE; + +/** + * Supported codec +*/ +typedef enum CODEC_FORMAT { + OPJ_CODEC_UNKNOWN = -1, /**< place-holder */ + OPJ_CODEC_J2K = 0, /**< JPEG-2000 codestream : read/write */ + OPJ_CODEC_JPT = 1, /**< JPT-stream (JPEG 2000, JPIP) : read only */ + OPJ_CODEC_JP2 = 2, /**< JP2 file format : read/write */ + OPJ_CODEC_JPP = 3, /**< JPP-stream (JPEG 2000, JPIP) : to be coded */ + OPJ_CODEC_JPX = 4 /**< JPX file format (JPEG 2000 Part-2) : to be coded */ +} OPJ_CODEC_FORMAT; + + +/* +========================================================== + event manager typedef definitions +========================================================== +*/ + +/** + * Callback function prototype for events + * @param msg Event message + * @param client_data Client object where will be return the event message + * */ +typedef void (*opj_msg_callback)(const char *msg, void *client_data); + +/* +========================================================== + codec typedef definitions +========================================================== +*/ + +#ifndef OPJ_UINT32_SEMANTICALLY_BUT_INT32 +#define OPJ_UINT32_SEMANTICALLY_BUT_INT32 OPJ_INT32 +#endif + +/** + * Progression order changes + * + */ +typedef struct opj_poc { + /** Resolution num start, Component num start, given by POC */ + OPJ_UINT32 resno0, compno0; + /** Layer num end,Resolution num end, Component num end, given by POC */ + OPJ_UINT32 layno1, resno1, compno1; + /** Layer num start,Precinct num start, Precinct num end */ + OPJ_UINT32 layno0, precno0, precno1; + /** Progression order enum*/ + OPJ_PROG_ORDER prg1, prg; + /** Progression order string*/ + OPJ_CHAR progorder[5]; + /** Tile number (starting at 1) */ + OPJ_UINT32 tile; + /** Start and end values for Tile width and height*/ + OPJ_UINT32_SEMANTICALLY_BUT_INT32 tx0, tx1, ty0, ty1; + /** Start value, initialised in pi_initialise_encode*/ + OPJ_UINT32 layS, resS, compS, prcS; + /** End value, initialised in pi_initialise_encode */ + OPJ_UINT32 layE, resE, compE, prcE; + /** Start and end values of Tile width and height, initialised in pi_initialise_encode*/ + OPJ_UINT32 txS, txE, tyS, tyE, dx, dy; + /** Temporary values for Tile parts, initialised in pi_create_encode */ + OPJ_UINT32 lay_t, res_t, comp_t, prc_t, tx0_t, ty0_t; +} opj_poc_t; + +/** + * Compression parameters + * */ +typedef struct opj_cparameters { + /** size of tile: tile_size_on = false (not in argument) or = true (in argument) */ + OPJ_BOOL tile_size_on; + /** XTOsiz */ + int cp_tx0; + /** YTOsiz */ + int cp_ty0; + /** XTsiz */ + int cp_tdx; + /** YTsiz */ + int cp_tdy; + /** allocation by rate/distortion */ + int cp_disto_alloc; + /** allocation by fixed layer */ + int cp_fixed_alloc; + /** allocation by fixed quality (PSNR) */ + int cp_fixed_quality; + /** fixed layer */ + int *cp_matrice; + /** comment for coding */ + char *cp_comment; + /** csty : coding style */ + int csty; + /** progression order (default OPJ_LRCP) */ + OPJ_PROG_ORDER prog_order; + /** progression order changes */ + opj_poc_t POC[32]; + /** number of progression order changes (POC), default to 0 */ + OPJ_UINT32 numpocs; + /** number of layers */ + int tcp_numlayers; + /** rates of layers - might be subsequently limited by the max_cs_size field. + * Should be decreasing. 1 can be + * used as last value to indicate the last layer is lossless. */ + float tcp_rates[100]; + /** different psnr for successive layers. Should be increasing. 0 can be + * used as last value to indicate the last layer is lossless. */ + float tcp_distoratio[100]; + /** number of resolutions */ + int numresolution; + /** initial code block width, default to 64 */ + int cblockw_init; + /** initial code block height, default to 64 */ + int cblockh_init; + /** mode switch (cblk_style) */ + int mode; + /** 1 : use the irreversible DWT 9-7, 0 : use lossless compression (default) */ + int irreversible; + /** region of interest: affected component in [0..3], -1 means no ROI */ + int roi_compno; + /** region of interest: upshift value */ + int roi_shift; + /* number of precinct size specifications */ + int res_spec; + /** initial precinct width */ + int prcw_init[OPJ_J2K_MAXRLVLS]; + /** initial precinct height */ + int prch_init[OPJ_J2K_MAXRLVLS]; + + /**@name command line encoder parameters (not used inside the library) */ + /*@{*/ + /** input file name */ + char infile[OPJ_PATH_LEN]; + /** output file name */ + char outfile[OPJ_PATH_LEN]; + /** DEPRECATED. Index generation is now handled with the opj_encode_with_info() function. Set to NULL */ + int index_on; + /** DEPRECATED. Index generation is now handled with the opj_encode_with_info() function. Set to NULL */ + char index[OPJ_PATH_LEN]; + /** subimage encoding: origin image offset in x direction */ + int image_offset_x0; + /** subimage encoding: origin image offset in y direction */ + int image_offset_y0; + /** subsampling value for dx */ + int subsampling_dx; + /** subsampling value for dy */ + int subsampling_dy; + /** input file format 0: PGX, 1: PxM, 2: BMP 3:TIF*/ + int decod_format; + /** output file format 0: J2K, 1: JP2, 2: JPT */ + int cod_format; + /*@}*/ + + /* UniPG>> */ /* NOT YET USED IN THE V2 VERSION OF OPENJPEG */ + /**@name JPWL encoding parameters */ + /*@{*/ + /** enables writing of EPC in MH, thus activating JPWL */ + OPJ_BOOL jpwl_epc_on; + /** error protection method for MH (0,1,16,32,37-128) */ + int jpwl_hprot_MH; + /** tile number of header protection specification (>=0) */ + int jpwl_hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** error protection methods for TPHs (0,1,16,32,37-128) */ + int jpwl_hprot_TPH[JPWL_MAX_NO_TILESPECS]; + /** tile number of packet protection specification (>=0) */ + int jpwl_pprot_tileno[JPWL_MAX_NO_PACKSPECS]; + /** packet number of packet protection specification (>=0) */ + int jpwl_pprot_packno[JPWL_MAX_NO_PACKSPECS]; + /** error protection methods for packets (0,1,16,32,37-128) */ + int jpwl_pprot[JPWL_MAX_NO_PACKSPECS]; + /** enables writing of ESD, (0=no/1/2 bytes) */ + int jpwl_sens_size; + /** sensitivity addressing size (0=auto/2/4 bytes) */ + int jpwl_sens_addr; + /** sensitivity range (0-3) */ + int jpwl_sens_range; + /** sensitivity method for MH (-1=no,0-7) */ + int jpwl_sens_MH; + /** tile number of sensitivity specification (>=0) */ + int jpwl_sens_TPH_tileno[JPWL_MAX_NO_TILESPECS]; + /** sensitivity methods for TPHs (-1=no,0-7) */ + int jpwl_sens_TPH[JPWL_MAX_NO_TILESPECS]; + /*@}*/ + /* <> */ /* NOT YET USED IN THE V2 VERSION OF OPENJPEG */ + /**@name JPWL decoding parameters */ + /*@{*/ + /** activates the JPWL correction capabilities */ + OPJ_BOOL jpwl_correct; + /** expected number of components */ + int jpwl_exp_comps; + /** maximum number of tiles */ + int jpwl_max_tiles; + /*@}*/ + /* <> */ +/** + * Marker structure + * */ +typedef struct opj_marker_info { + /** marker type */ + unsigned short int type; + /** position in codestream */ + OPJ_OFF_T pos; + /** length, marker val included */ + int len; +} opj_marker_info_t; +/* <> */ + /** number of markers */ + int marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + int maxmarknum; + /* <> */ /* NOT USED FOR THE MOMENT IN THE V2 VERSION */ + /** number of markers */ + OPJ_UINT32 marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + OPJ_UINT32 maxmarknum; + /* <> */ /* NOT USED FOR THE MOMENT IN THE V2 VERSION */ + /** number of markers */ + OPJ_UINT32 marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + OPJ_UINT32 maxmarknum; + /* < */ + +/* +========================================================== + Metadata from the JP2file +========================================================== +*/ + +/** + * Info structure of the JP2 file + * EXPERIMENTAL FOR THE MOMENT + */ +typedef struct opj_jp2_metadata { + /** */ + OPJ_INT32 not_used; + +} opj_jp2_metadata_t; + +/** + * Index structure of the JP2 file + * EXPERIMENTAL FOR THE MOMENT + */ +typedef struct opj_jp2_index { + /** */ + OPJ_INT32 not_used; + +} opj_jp2_index_t; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +========================================================== + openjpeg version +========================================================== +*/ + +/* Get the version of the openjpeg library*/ +OPJ_API const char * OPJ_CALLCONV opj_version(void); + +/* +========================================================== + image functions definitions +========================================================== +*/ + +/** + * Create an image + * + * @param numcmpts number of components + * @param cmptparms components parameters + * @param clrspc image color space + * @return returns a new image structure if successful, returns NULL otherwise + * */ +OPJ_API opj_image_t* OPJ_CALLCONV opj_image_create(OPJ_UINT32 numcmpts, + opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc); + +/** + * Deallocate any resources associated with an image + * + * @param image image to be destroyed + */ +OPJ_API void OPJ_CALLCONV opj_image_destroy(opj_image_t *image); + +/** + * Creates an image without allocating memory for the image (used in the new version of the library). + * + * @param numcmpts the number of components + * @param cmptparms the components parameters + * @param clrspc the image color space + * + * @return a new image structure if successful, NULL otherwise. +*/ +OPJ_API opj_image_t* OPJ_CALLCONV opj_image_tile_create(OPJ_UINT32 numcmpts, + opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc); + +/** + * Allocator for opj_image_t->comps[].data + * To be paired with opj_image_data_free. + * + * @param size number of bytes to allocate + * + * @return a new pointer if successful, NULL otherwise. + * @since 2.2.0 +*/ +OPJ_API void* OPJ_CALLCONV opj_image_data_alloc(OPJ_SIZE_T size); + +/** + * Destructor for opj_image_t->comps[].data + * To be paired with opj_image_data_alloc. + * + * @param ptr Pointer to free + * + * @since 2.2.0 +*/ +OPJ_API void OPJ_CALLCONV opj_image_data_free(void* ptr); + +/* +========================================================== + stream functions definitions +========================================================== +*/ + +/** + * Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream. + * + * @param p_is_input if set to true then the stream will be an input stream, an output stream else. + * + * @return a stream object. +*/ +OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_default_create( + OPJ_BOOL p_is_input); + +/** + * Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream. + * + * @param p_buffer_size FIXME DOC + * @param p_is_input if set to true then the stream will be an input stream, an output stream else. + * + * @return a stream object. +*/ +OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size, + OPJ_BOOL p_is_input); + +/** + * Destroys a stream created by opj_create_stream. This function does NOT close the abstract stream. If needed the user must + * close its own implementation of the stream. + * + * @param p_stream the stream to destroy. + */ +OPJ_API void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream); + +/** + * Sets the given function to be used as a read function. + * @param p_stream the stream to modify + * @param p_function the function to use a read function. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, + opj_stream_read_fn p_function); + +/** + * Sets the given function to be used as a write function. + * @param p_stream the stream to modify + * @param p_function the function to use a write function. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_write_function(opj_stream_t* p_stream, + opj_stream_write_fn p_function); + +/** + * Sets the given function to be used as a skip function. + * @param p_stream the stream to modify + * @param p_function the function to use a skip function. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_skip_function(opj_stream_t* p_stream, + opj_stream_skip_fn p_function); + +/** + * Sets the given function to be used as a seek function, the stream is then seekable, + * using SEEK_SET behavior. + * @param p_stream the stream to modify + * @param p_function the function to use a skip function. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, + opj_stream_seek_fn p_function); + +/** + * Sets the given data to be used as a user data for the stream. + * @param p_stream the stream to modify + * @param p_data the data to set. + * @param p_function the function to free p_data when opj_stream_destroy() is called. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, + void * p_data, opj_stream_free_user_data_fn p_function); + +/** + * Sets the length of the user data for the stream. + * @param p_stream the stream to modify + * @param data_length length of the user_data. +*/ +OPJ_API void OPJ_CALLCONV opj_stream_set_user_data_length( + opj_stream_t* p_stream, OPJ_UINT64 data_length); + +/** + * Create a stream from a file identified with its filename with default parameters (helper function) + * @param fname the filename of the file to stream + * @param p_is_read_stream whether the stream is a read stream (true) or not (false) +*/ +OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream( + const char *fname, OPJ_BOOL p_is_read_stream); + +/** Create a stream from a file identified with its filename with a specific buffer size + * @param fname the filename of the file to stream + * @param p_buffer_size size of the chunk used to stream + * @param p_is_read_stream whether the stream is a read stream (true) or not (false) +*/ +OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream( + const char *fname, + OPJ_SIZE_T p_buffer_size, + OPJ_BOOL p_is_read_stream); + +/* +========================================================== + event manager functions definitions +========================================================== +*/ +/** + * Set the info handler use by openjpeg. + * @param p_codec the codec previously initialise + * @param p_callback the callback function which will be used + * @param p_user_data client object where will be returned the message +*/ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_info_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data); +/** + * Set the warning handler use by openjpeg. + * @param p_codec the codec previously initialise + * @param p_callback the callback function which will be used + * @param p_user_data client object where will be returned the message +*/ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_warning_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data); +/** + * Set the error handler use by openjpeg. + * @param p_codec the codec previously initialise + * @param p_callback the callback function which will be used + * @param p_user_data client object where will be returned the message +*/ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_error_handler(opj_codec_t * p_codec, + opj_msg_callback p_callback, + void * p_user_data); + +/* +========================================================== + codec functions definitions +========================================================== +*/ + +/** + * Creates a J2K/JP2 decompression structure + * @param format Decoder to select + * + * @return Returns a handle to a decompressor if successful, returns NULL otherwise + * */ +OPJ_API opj_codec_t* OPJ_CALLCONV opj_create_decompress( + OPJ_CODEC_FORMAT format); + +/** + * Destroy a decompressor handle + * + * @param p_codec decompressor handle to destroy + */ +OPJ_API void OPJ_CALLCONV opj_destroy_codec(opj_codec_t * p_codec); + +/** + * Read after the codestream if necessary + * @param p_codec the JPEG2000 codec to read. + * @param p_stream the JPEG2000 stream. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_end_decompress(opj_codec_t *p_codec, + opj_stream_t *p_stream); + + +/** + * Set decoding parameters to default values + * @param parameters Decompression parameters + */ +OPJ_API void OPJ_CALLCONV opj_set_default_decoder_parameters( + opj_dparameters_t *parameters); + +/** + * Setup the decoder with decompression parameters provided by the user and with the message handler + * provided by the user. + * + * @param p_codec decompressor handler + * @param parameters decompression parameters + * + * @return true if the decoder is correctly set + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec, + opj_dparameters_t *parameters); + +/** + * Set strict decoding parameter for this decoder. + * If strict decoding is enabled, partial bit streams will fail to decode, and + * the check for invalid TPSOT values added in https://github.com/uclouvain/openjpeg/pull/514 + * will be disabled. + * If strict decoding is disabled, the decoder will decode partial + * bitstreams as much as possible without erroring, and the TPSOT fixing logic + * will be enabled. + * + * @param p_codec decompressor handler + * @param strict OPJ_TRUE to enable strict decoding, OPJ_FALSE to disable + * + * @return true if the decoder is correctly set + */ + +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decoder_set_strict_mode(opj_codec_t *p_codec, + OPJ_BOOL strict); + +/** + * Allocates worker threads for the compressor/decompressor. + * + * By default, only the main thread is used. If this function is not used, + * but the OPJ_NUM_THREADS environment variable is set, its value will be + * used to initialize the number of threads. The value can be either an integer + * number, or "ALL_CPUS". If OPJ_NUM_THREADS is set and this function is called, + * this function will override the behaviour of the environment variable. + * + * This function must be called after opj_setup_decoder() and + * before opj_read_header() for the decoding side, or after opj_setup_encoder() + * and before opj_start_compress() for the encoding side. + * + * @param p_codec decompressor or compressor handler + * @param num_threads number of threads. + * + * @return OPJ_TRUE if the function is successful. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_codec_set_threads(opj_codec_t *p_codec, + int num_threads); + +/** + * Decodes an image header. + * + * @param p_stream the jpeg2000 stream. + * @param p_codec the jpeg2000 codec to read. + * @param p_image the image structure initialized with the characteristics of encoded image. + * + * @return true if the main header of the codestream and the JP2 header is correctly read. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_read_header(opj_stream_t *p_stream, + opj_codec_t *p_codec, + opj_image_t **p_image); + + +/** Restrict the number of components to decode. + * + * This function should be called after opj_read_header(). + * + * This function enables to restrict the set of decoded components to the + * specified indices. + * Note that the current implementation (apply_color_transforms == OPJ_FALSE) + * is such that neither the multi-component transform at codestream level, + * nor JP2 channel transformations will be applied. + * Consequently the indices are relative to the codestream. + * + * Note: opj_decode_tile_data() should not be used together with opj_set_decoded_components(). + * + * @param p_codec the jpeg2000 codec to read. + * @param numcomps Size of the comps_indices array. + * @param comps_indices Array of numcomps values representing the indices + * of the components to decode (relative to the + * codestream, starting at 0) + * @param apply_color_transforms Whether multi-component transform at codestream level + * or JP2 channel transformations should be applied. + * Currently this parameter should be set to OPJ_FALSE. + * Setting it to OPJ_TRUE will result in an error. + * + * @return OPJ_TRUE in case of success. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_decoded_components(opj_codec_t *p_codec, + OPJ_UINT32 numcomps, + const OPJ_UINT32* comps_indices, + OPJ_BOOL apply_color_transforms); + +/** + * Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading. + * + * The coordinates passed to this function should be expressed in the reference grid, + * that is to say at the highest resolution level, even if requesting the image at lower + * resolution levels. + * + * Note: If p_start_x, p_start_y, p_end_x, p_end_y are all 0, then the whole image is decoded. + * + * Generally opj_set_decode_area() should be followed by opj_decode(), and the + * codec cannot be re-used. + * In the particular case of an image made of a single tile, several sequences of + * calls to opoj_set_decode_area() and opj_decode() are allowed, and will bring + * performance improvements when reading an image by chunks. + * + * @param p_codec the jpeg2000 codec. + * @param p_image the decoded image previously set by opj_read_header + * @param p_start_x the left position of the rectangle to decode (in image coordinates). + * @param p_end_x the right position of the rectangle to decode (in image coordinates). + * @param p_start_y the up position of the rectangle to decode (in image coordinates). + * @param p_end_y the bottom position of the rectangle to decode (in image coordinates). + * + * @return true if the area could be set. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_decode_area(opj_codec_t *p_codec, + opj_image_t* p_image, + OPJ_INT32 p_start_x, OPJ_INT32 p_start_y, + OPJ_INT32 p_end_x, OPJ_INT32 p_end_y); + +/** + * Decode an image from a JPEG-2000 codestream + * + * @param p_decompressor decompressor handle + * @param p_stream Input buffer stream + * @param p_image the decoded image + * @return true if success, otherwise false + * */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decode(opj_codec_t *p_decompressor, + opj_stream_t *p_stream, + opj_image_t *p_image); + +/** + * Get the decoded tile from the codec + * + * @param p_codec the jpeg2000 codec. + * @param p_stream input stream + * @param p_image output image + * @param tile_index index of the tile which will be decode + * + * @return true if success, otherwise false + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_get_decoded_tile(opj_codec_t *p_codec, + opj_stream_t *p_stream, + opj_image_t *p_image, + OPJ_UINT32 tile_index); + +/** + * Set the resolution factor of the decoded image + * @param p_codec the jpeg2000 codec. + * @param res_factor resolution factor to set + * + * @return true if success, otherwise false + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_decoded_resolution_factor( + opj_codec_t *p_codec, OPJ_UINT32 res_factor); + +/** + * Writes a tile with the given data. + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index the index of the tile to write. At the moment, the tiles must be written from 0 to n-1 in sequence. + * @param p_data pointer to the data to write. Data is arranged in sequence, data_comp0, then data_comp1, then ... NO INTERLEAVING should be set. + * @param p_data_size this value os used to make sure the data being written is correct. The size must be equal to the sum for each component of + * tile_width * tile_height * component_size. component_size can be 1,2 or 4 bytes, depending on the precision of the given component. + * @param p_stream the stream to write data to. + * + * @return true if the data could be written. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_write_tile(opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream); + +/** + * Reads a tile header. This function is compulsory and allows one to know the size of the tile that will be decoded. + * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index pointer to a value that will hold the index of the tile being decoded, in case of success. + * @param p_data_size pointer to a value that will hold the maximum size of the decoded data, in case of success. In case + * of truncated codestreams, the actual number of bytes decoded may be lower. The computation of the size is the same + * as depicted in opj_write_tile. + * @param p_tile_x0 pointer to a value that will hold the x0 pos of the tile (in the image). + * @param p_tile_y0 pointer to a value that will hold the y0 pos of the tile (in the image). + * @param p_tile_x1 pointer to a value that will hold the x1 pos of the tile (in the image). + * @param p_tile_y1 pointer to a value that will hold the y1 pos of the tile (in the image). + * @param p_nb_comps pointer to a value that will hold the number of components in the tile. + * @param p_should_go_on pointer to a boolean that will hold the fact that the decoding should go on. In case the + * codestream is over at the time of the call, the value will be set to false. The user should then stop + * the decoding. + * @param p_stream the stream to decode. + * @return true if the tile header could be decoded. In case the decoding should end, the returned value is still true. + * returning false may be the result of a shortage of memory or an internal error. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_read_tile_header(opj_codec_t *p_codec, + opj_stream_t * p_stream, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_should_go_on); + +/** + * Reads a tile data. This function is compulsory and allows one to decode tile data. opj_read_tile_header should be called before. + * The user may need to refer to the image got by opj_read_header to understand the size being taken by the tile. + * + * Note: opj_decode_tile_data() should not be used together with opj_set_decoded_components(). + * + * @param p_codec the jpeg2000 codec. + * @param p_tile_index the index of the tile being decoded, this should be the value set by opj_read_tile_header. + * @param p_data pointer to a memory block that will hold the decoded data. + * @param p_data_size size of p_data. p_data_size should be bigger or equal to the value set by opj_read_tile_header. + * @param p_stream the stream to decode. + * + * @return true if the data could be decoded. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decode_tile_data(opj_codec_t *p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + opj_stream_t *p_stream); + +/* COMPRESSION FUNCTIONS*/ + +/** + * Creates a J2K/JP2 compression structure + * @param format Coder to select + * @return Returns a handle to a compressor if successful, returns NULL otherwise + */ +OPJ_API opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format); + +/** +Set encoding parameters to default values, that means : +

    +
  • Lossless +
  • 1 tile +
  • Size of precinct : 2^15 x 2^15 (means 1 precinct) +
  • Size of code-block : 64 x 64 +
  • Number of resolutions: 6 +
  • No SOP marker in the codestream +
  • No EPH marker in the codestream +
  • No sub-sampling in x or y direction +
  • No mode switch activated +
  • Progression order: LRCP +
  • No index file +
  • No ROI upshifted +
  • No offset of the origin of the image +
  • No offset of the origin of the tiles +
  • Reversible DWT 5-3 +
+@param parameters Compression parameters +*/ +OPJ_API void OPJ_CALLCONV opj_set_default_encoder_parameters( + opj_cparameters_t *parameters); + +/** + * Setup the encoder parameters using the current image and using user parameters. + * @param p_codec Compressor handle + * @param parameters Compression parameters + * @param image Input filled image + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec, + opj_cparameters_t *parameters, + opj_image_t *image); + + +/** + * Specify extra options for the encoder. + * + * This may be called after opj_setup_encoder() and before opj_start_compress() + * + * This is the way to add new options in a fully ABI compatible way, without + * extending the opj_cparameters_t structure. + * + * Currently supported options are: + *
    + *
  • PLT=YES/NO. Defaults to NO. If set to YES, PLT marker segments, + * indicating the length of each packet in the tile-part header, will be + * written. Since 2.4.0
  • + *
  • TLM=YES/NO. Defaults to NO (except for Cinema and IMF profiles). + * If set to YES, TLM marker segments, indicating the length of each + * tile-part part will be written. Since 2.4.0
  • + *
  • GUARD_BITS=value. Number of guard bits in [0,7] range. Default value is 2. + * 1 may be used sometimes (like in SMPTE DCP Bv2.1 Application Profile for 2K images). + * Since 2.5.0
  • + *
+ * + * @param p_codec Compressor handle + * @param p_options Compression options. This should be a NULL terminated + * array of strings. Each string is of the form KEY=VALUE. + * + * @return OPJ_TRUE in case of success. + * @since 2.4.0 + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_encoder_set_extra_options( + opj_codec_t *p_codec, + const char* const* p_options); + +/** + * Start to compress the current image. + * @param p_codec Compressor handle + * @param p_image Input filled image + * @param p_stream Input stgream + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_start_compress(opj_codec_t *p_codec, + opj_image_t * p_image, + opj_stream_t *p_stream); + +/** + * End to compress the current image. + * @param p_codec Compressor handle + * @param p_stream Input stgream + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_end_compress(opj_codec_t *p_codec, + opj_stream_t *p_stream); + +/** + * Encode an image into a JPEG-2000 codestream + * @param p_codec compressor handle + * @param p_stream Output buffer stream + * + * @return Returns true if successful, returns false otherwise + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_encode(opj_codec_t *p_codec, + opj_stream_t *p_stream); +/* +========================================================== + codec output functions definitions +========================================================== +*/ +/* EXPERIMENTAL FUNCTIONS FOR NOW, USED ONLY IN J2K_DUMP*/ + +/** +Destroy Codestream information after compression or decompression +@param cstr_info Codestream information structure +*/ +OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_v2_t + **cstr_info); + + +/** + * Dump the codec information into the output stream + * + * @param p_codec the jpeg2000 codec. + * @param info_flag type of information dump. + * @param output_stream output stream where dump the information gotten from the codec. + * + */ +OPJ_API void OPJ_CALLCONV opj_dump_codec(opj_codec_t *p_codec, + OPJ_INT32 info_flag, + FILE* output_stream); + +/** + * Get the codestream information from the codec + * + * @param p_codec the jpeg2000 codec. + * + * @return a pointer to a codestream information structure. + * + */ +OPJ_API opj_codestream_info_v2_t* OPJ_CALLCONV opj_get_cstr_info( + opj_codec_t *p_codec); + +/** + * Get the codestream index from the codec + * + * @param p_codec the jpeg2000 codec. + * + * @return a pointer to a codestream index structure. + * + */ +OPJ_API opj_codestream_index_t * OPJ_CALLCONV opj_get_cstr_index( + opj_codec_t *p_codec); + +OPJ_API void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t + **p_cstr_index); + + +/** + * Get the JP2 file information from the codec FIXME + * + * @param p_codec the jpeg2000 codec. + * + * @return a pointer to a JP2 metadata structure. + * + */ +OPJ_API opj_jp2_metadata_t* OPJ_CALLCONV opj_get_jp2_metadata( + opj_codec_t *p_codec); + +/** + * Get the JP2 file index from the codec FIXME + * + * @param p_codec the jpeg2000 codec. + * + * @return a pointer to a JP2 index structure. + * + */ +OPJ_API opj_jp2_index_t* OPJ_CALLCONV opj_get_jp2_index(opj_codec_t *p_codec); + + +/* +========================================================== + MCT functions +========================================================== +*/ + +/** + * Sets the MCT matrix to use. + * + * @param parameters the parameters to change. + * @param pEncodingMatrix the encoding matrix. + * @param p_dc_shift the dc shift coefficients to use. + * @param pNbComp the number of components of the image. + * + * @return true if the parameters could be set. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_set_MCT(opj_cparameters_t *parameters, + OPJ_FLOAT32 * pEncodingMatrix, + OPJ_INT32 * p_dc_shift, + OPJ_UINT32 pNbComp); + +/* +========================================================== + Thread functions +========================================================== +*/ + +/** Returns if the library is built with thread support. + * OPJ_TRUE if mutex, condition, thread, thread pool are available. + */ +OPJ_API OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void); + +/** Return the number of virtual CPUs */ +OPJ_API int OPJ_CALLCONV opj_get_num_cpus(void); + + +#ifdef __cplusplus +} +#endif + +#endif /* OPENJPEG_H */ diff --git a/client/deps/openjpeg/opj_clock.c b/client/deps/openjpeg/opj_clock.c new file mode 100644 index 000000000..24f79a9ae --- /dev/null +++ b/client/deps/openjpeg/opj_clock.c @@ -0,0 +1,67 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif /* _WIN32 */ + +OPJ_FLOAT64 opj_clock(void) +{ +#ifdef _WIN32 + /* _WIN32: use QueryPerformance (very accurate) */ + LARGE_INTEGER freq, t ; + /* freq is the clock speed of the CPU */ + QueryPerformanceFrequency(&freq) ; + /* cout << "freq = " << ((double) freq.QuadPart) << endl; */ + /* t is the high resolution performance counter (see MSDN) */ + QueryPerformanceCounter(& t) ; + return ((OPJ_FLOAT64) t.QuadPart / (OPJ_FLOAT64) freq.QuadPart) ; +#else + /* Unix or Linux: use resource usage */ + struct rusage t; + OPJ_FLOAT64 procTime; + /* (1) Get the rusage data structure at this moment (man getrusage) */ + getrusage(0, &t); + /* (2) What is the elapsed time ? - CPU time = User time + System time */ + /* (2a) Get the seconds */ + procTime = (OPJ_FLOAT64)(t.ru_utime.tv_sec + t.ru_stime.tv_sec); + /* (2b) More precisely! Get the microseconds part ! */ + return (procTime + (OPJ_FLOAT64)(t.ru_utime.tv_usec + t.ru_stime.tv_usec) * + 1e-6) ; +#endif +} + diff --git a/client/deps/openjpeg/opj_clock.h b/client/deps/openjpeg/opj_clock.h new file mode 100644 index 000000000..76366f53b --- /dev/null +++ b/client/deps/openjpeg/opj_clock.h @@ -0,0 +1,59 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_CLOCK_H +#define OPJ_CLOCK_H +/** +@file opj_clock.h +@brief Internal function for timing + +The functions in OPJ_CLOCK.C are internal utilities mainly used for timing. +*/ + +/** @defgroup MISC MISC - Miscellaneous internal functions */ +/*@{*/ + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Difference in successive opj_clock() calls tells you the elapsed time +@return Returns time in seconds +*/ +OPJ_FLOAT64 opj_clock(void); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_CLOCK_H */ + diff --git a/client/deps/openjpeg/opj_codec.h b/client/deps/openjpeg/opj_codec.h new file mode 100644 index 000000000..7cff67082 --- /dev/null +++ b/client/deps/openjpeg/opj_codec.h @@ -0,0 +1,179 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_CODEC_H +#define OPJ_CODEC_H +/** +@file opj_codec.h +*/ + + +/** + * Main codec handler used for compression or decompression. + */ +typedef struct opj_codec_private { + /** FIXME DOC */ + union { + /** + * Decompression handler. + */ + struct opj_decompression { + /** Main header reading function handler */ + OPJ_BOOL(*opj_read_header)(struct opj_stream_private * cio, + void * p_codec, + opj_image_t **p_image, + struct opj_event_mgr * p_manager); + + /** Decoding function */ + OPJ_BOOL(*opj_decode)(void * p_codec, + struct opj_stream_private * p_cio, + opj_image_t * p_image, + struct opj_event_mgr * p_manager); + + /** FIXME DOC */ + OPJ_BOOL(*opj_read_tile_header)(void * p_codec, + OPJ_UINT32 * p_tile_index, + OPJ_UINT32 * p_data_size, + OPJ_INT32 * p_tile_x0, + OPJ_INT32 * p_tile_y0, + OPJ_INT32 * p_tile_x1, + OPJ_INT32 * p_tile_y1, + OPJ_UINT32 * p_nb_comps, + OPJ_BOOL * p_should_go_on, + struct opj_stream_private * p_cio, + struct opj_event_mgr * p_manager); + + /** FIXME DOC */ + OPJ_BOOL(*opj_decode_tile_data)(void * p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private * p_cio, + struct opj_event_mgr * p_manager); + + /** Reading function used after codestream if necessary */ + OPJ_BOOL(* opj_end_decompress)(void *p_codec, + struct opj_stream_private * cio, + struct opj_event_mgr * p_manager); + + /** Codec destroy function handler */ + void (*opj_destroy)(void * p_codec); + + /** Setup decoder function handler */ + void (*opj_setup_decoder)(void * p_codec, opj_dparameters_t * p_param); + + /** Strict mode function handler */ + void (*opj_decoder_set_strict_mode)(void * p_codec, OPJ_BOOL strict); + + /** Set decode area function handler */ + OPJ_BOOL(*opj_set_decode_area)(void * p_codec, + opj_image_t * p_image, + OPJ_INT32 p_start_x, + OPJ_INT32 p_end_x, + OPJ_INT32 p_start_y, + OPJ_INT32 p_end_y, + struct opj_event_mgr * p_manager); + + /** Get tile function */ + OPJ_BOOL(*opj_get_decoded_tile)(void *p_codec, + opj_stream_private_t * p_cio, + opj_image_t *p_image, + struct opj_event_mgr * p_manager, + OPJ_UINT32 tile_index); + + /** Set the decoded resolution factor */ + OPJ_BOOL(*opj_set_decoded_resolution_factor)(void * p_codec, + OPJ_UINT32 res_factor, + opj_event_mgr_t * p_manager); + + /** Set the decoded components */ + OPJ_BOOL(*opj_set_decoded_components)(void * p_codec, + OPJ_UINT32 num_comps, + const OPJ_UINT32* comps_indices, + opj_event_mgr_t * p_manager); + } m_decompression; + + /** + * Compression handler. FIXME DOC + */ + struct opj_compression { + OPJ_BOOL(* opj_start_compress)(void *p_codec, + struct opj_stream_private * cio, + struct opj_image * p_image, + struct opj_event_mgr * p_manager); + + OPJ_BOOL(* opj_encode)(void * p_codec, + struct opj_stream_private *p_cio, + struct opj_event_mgr * p_manager); + + OPJ_BOOL(* opj_write_tile)(void * p_codec, + OPJ_UINT32 p_tile_index, + OPJ_BYTE * p_data, + OPJ_UINT32 p_data_size, + struct opj_stream_private * p_cio, + struct opj_event_mgr * p_manager); + + OPJ_BOOL(* opj_end_compress)(void * p_codec, + struct opj_stream_private * p_cio, + struct opj_event_mgr * p_manager); + + void (* opj_destroy)(void * p_codec); + + OPJ_BOOL(* opj_setup_encoder)(void * p_codec, + opj_cparameters_t * p_param, + struct opj_image * p_image, + struct opj_event_mgr * p_manager); + + OPJ_BOOL(* opj_encoder_set_extra_options)(void * p_codec, + const char* const* p_options, + struct opj_event_mgr * p_manager); + + } m_compression; + } m_codec_data; + /** FIXME DOC*/ + void * m_codec; + /** Event handler */ + opj_event_mgr_t m_event_mgr; + /** Flag to indicate if the codec is used to decode or encode*/ + OPJ_BOOL is_decompressor; + void (*opj_dump_codec)(void * p_codec, OPJ_INT32 info_flag, + FILE* output_stream); + opj_codestream_info_v2_t* (*opj_get_codec_info)(void* p_codec); + opj_codestream_index_t* (*opj_get_codec_index)(void* p_codec); + + /** Set number of threads */ + OPJ_BOOL(*opj_set_threads)(void * p_codec, OPJ_UINT32 num_threads); +} +opj_codec_private_t; + + +#endif /* OPJ_CODEC_H */ + diff --git a/client/deps/openjpeg/opj_common.h b/client/deps/openjpeg/opj_common.h new file mode 100644 index 000000000..2923a35b7 --- /dev/null +++ b/client/deps/openjpeg/opj_common.h @@ -0,0 +1,47 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2017, IntoPIX SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_COMMON_H +#define OPJ_COMMON_H + +/* + ========================================================== + Common constants shared among several modules + ========================================================== +*/ +#define OPJ_COMMON_CBLK_DATA_EXTRA 2 /**< Margin for a fake FFFF marker */ + + +#define OPJ_COMP_PARAM_DEFAULT_CBLOCKW 64 +#define OPJ_COMP_PARAM_DEFAULT_CBLOCKH 64 +#define OPJ_COMP_PARAM_DEFAULT_PROG_ORDER OPJ_LRCP +#define OPJ_COMP_PARAM_DEFAULT_NUMRESOLUTION 6 + +#endif /* OPJ_COMMON_H */ diff --git a/client/deps/openjpeg/opj_config.h b/client/deps/openjpeg/opj_config.h new file mode 100644 index 000000000..1ae8e1410 --- /dev/null +++ b/client/deps/openjpeg/opj_config.h @@ -0,0 +1,13 @@ +#ifndef OPJ_CONFIG_H_INCLUDED +#define OPJ_CONFIG_H_INCLUDED + +/* + * Hand written replacement for the CMake generated opj_config.h + * Proxmark3 vendors only the openjp2 decoder, see README.pm3 + */ + +#define OPJ_VERSION_MAJOR 2 +#define OPJ_VERSION_MINOR 5 +#define OPJ_VERSION_BUILD 4 + +#endif diff --git a/client/deps/openjpeg/opj_config_private.h b/client/deps/openjpeg/opj_config_private.h new file mode 100644 index 000000000..b90c05f32 --- /dev/null +++ b/client/deps/openjpeg/opj_config_private.h @@ -0,0 +1,44 @@ +#ifndef OPJ_CONFIG_PRIVATE_H_INCLUDED +#define OPJ_CONFIG_PRIVATE_H_INCLUDED + +/* + * Hand written replacement for the CMake generated opj_config_private.h + * + * Upstream probes the host with CMake try_compile checks. We vendor the + * sources instead, so everything is decided from compiler predefines here. + * This file is included before any system header, see opj_includes.h + */ + +#define OPJ_PACKAGE_VERSION "2.5.4" + +/* + * Aligned allocation. + * + * On POSIX we take posix_memalign, it is declared by and openjpeg + * prefers it over memalign anyway. + * + * On Windows / MinGW we deliberately define nothing. openjpeg then falls back + * to its own portable aligned malloc, which avoids having to reason about + * whether _aligned_malloc is visible in a given mingw-w64 / msvcrt combination. + * We decode a handful of passport images, the alloc path is not hot. + */ +#if !defined(_WIN32) +# define OPJ_HAVE_POSIX_MEMALIGN +# define OPJ_HAVE_FSEEKO +#endif + +#if !defined(_POSIX_C_SOURCE) +# if defined(OPJ_HAVE_FSEEKO) || defined(OPJ_HAVE_POSIX_MEMALIGN) +/* Get declarations of fseeko, ftello, posix_memalign. */ +# define _POSIX_C_SOURCE 200112L +# endif +#endif + +/* Byte order, taken from the compiler rather than from a TRY_RUN */ +#if defined(__BIG_ENDIAN__) +# define OPJ_BIG_ENDIAN +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define OPJ_BIG_ENDIAN +#endif + +#endif diff --git a/client/deps/openjpeg/opj_includes.h b/client/deps/openjpeg/opj_includes.h new file mode 100644 index 000000000..13613ce52 --- /dev/null +++ b/client/deps/openjpeg/opj_includes.h @@ -0,0 +1,266 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_INCLUDES_H +#define OPJ_INCLUDES_H + +/* + * This must be included before any system headers, + * since they can react to macro defined there + */ +#include "opj_config_private.h" + +/* + ========================================================== + Standard includes used by the library + ========================================================== +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + Use fseeko() and ftello() if they are available since they use + 'off_t' rather than 'long'. It is wrong to use fseeko() and + ftello() only on systems with special LFS support since some systems + (e.g. FreeBSD) support a 64-bit off_t by default. +*/ +#if defined(OPJ_HAVE_FSEEKO) && !defined(fseek) +# define fseek fseeko +# define ftell ftello +#endif + + +#if defined(WIN32) && !defined(Windows95) && !defined(__BORLANDC__) && \ + !(defined(_MSC_VER) && _MSC_VER < 1400) && \ + !(defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x800) +/* + Windows '95 and Borland C do not support _lseeki64 + Visual Studio does not support _fseeki64 and _ftelli64 until the 2005 release. + Without these interfaces, files over 2GB in size are not supported for Windows. +*/ +# define OPJ_FSEEK(stream,offset,whence) _fseeki64(stream,/* __int64 */ offset,whence) +# define OPJ_FSTAT(fildes,stat_buff) _fstati64(fildes,/* struct _stati64 */ stat_buff) +# define OPJ_FTELL(stream) /* __int64 */ _ftelli64(stream) +# define OPJ_STAT_STRUCT_T struct _stati64 +# define OPJ_STAT(path,stat_buff) _stati64(path,/* struct _stati64 */ stat_buff) +#else +# define OPJ_FSEEK(stream,offset,whence) fseek(stream,offset,whence) +# define OPJ_FSTAT(fildes,stat_buff) fstat(fildes,stat_buff) +# define OPJ_FTELL(stream) ftell(stream) +# define OPJ_STAT_STRUCT_T struct stat +# define OPJ_STAT(path,stat_buff) stat(path,stat_buff) +#endif + + +/* + ========================================================== + OpenJPEG interface + ========================================================== + */ +#include "openjpeg.h" + +/* + ========================================================== + OpenJPEG modules + ========================================================== +*/ + +/* Are restricted pointers available? (C99) */ +#if (__STDC_VERSION__ >= 199901L) +#define OPJ_RESTRICT restrict +#else +/* Not a C99 compiler */ +#if defined(__GNUC__) +#define OPJ_RESTRICT __restrict__ + +/* + vc14 (2015) outputs wrong results. + Need to check OPJ_RESTRICT usage (or a bug in vc14) + #elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define OPJ_RESTRICT __restrict +*/ +#else +#define OPJ_RESTRICT /* restrict */ +#endif +#endif + +#ifdef __has_attribute +#if __has_attribute(no_sanitize) +#define OPJ_NOSANITIZE(kind) __attribute__((no_sanitize(kind))) +#endif +#endif +#ifndef OPJ_NOSANITIZE +#define OPJ_NOSANITIZE(kind) +#endif + + +/* MSVC before 2013 and Borland C do not have lrintf */ +#if defined(_MSC_VER) +#include +static INLINE long opj_lrintf(float f) +{ +#ifdef _M_X64 + return _mm_cvt_ss2si(_mm_load_ss(&f)); + + /* commented out line breaks many tests */ + /* return (long)((f>0.0f) ? (f + 0.5f):(f -0.5f)); */ +#elif defined(_M_IX86) + int i; + _asm{ + fld f + fistp i + }; + + return i; +#else + return (long)((f>0.0f) ? (f + 0.5f) : (f - 0.5f)); +#endif +} +#elif defined(__BORLANDC__) +static INLINE long opj_lrintf(float f) +{ +#ifdef _M_X64 + return (long)((f > 0.0f) ? (f + 0.5f) : (f - 0.5f)); +#else + int i; + + _asm { + fld f + fistp i + }; + + return i; +#endif +} +#else +static INLINE long opj_lrintf(float f) +{ + return lrintf(f); +} +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1400) +#define vsnprintf _vsnprintf +#endif + +/* MSVC x86 is really bad at doing int64 = int32 * int32 on its own. Use intrinsic. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86) +# include +# pragma intrinsic(__emul) +#endif + +/* Apparently Visual Studio doesn't define __SSE__ / __SSE2__ macros */ +#if defined(_M_X64) +/* Intel 64bit support SSE and SSE2 */ +# ifndef __SSE__ +# define __SSE__ 1 +# endif +# ifndef __SSE2__ +# define __SSE2__ 1 +# endif +#endif + +/* For x86, test the value of the _M_IX86_FP macro. */ +/* See https://msdn.microsoft.com/en-us/library/b0084kay.aspx */ +#if defined(_M_IX86_FP) +# if _M_IX86_FP >= 1 +# ifndef __SSE__ +# define __SSE__ 1 +# endif +# endif +# if _M_IX86_FP >= 2 +# ifndef __SSE2__ +# define __SSE2__ 1 +# endif +# endif +#endif + +/* Type to use for bit-fields in internal headers */ +typedef unsigned int OPJ_BITFIELD; + +#define OPJ_UNUSED(x) (void)x + +#include "opj_clock.h" +#include "opj_malloc.h" +#include "event.h" +#include "function_list.h" +#include "bio.h" +#include "cio.h" + +#include "thread.h" +#include "tls_keys.h" + +#include "image.h" +#include "invert.h" +#include "j2k.h" +#include "jp2.h" + +#include "mqc.h" +#include "bio.h" + +#include "pi.h" +#include "tgt.h" +#include "tcd.h" +#include "t1.h" +#include "dwt.h" +#include "t2.h" +#include "mct.h" +#include "opj_intmath.h" +#include "sparse_array.h" + +#ifdef USE_JPIP +#include "cidx_manager.h" +#include "indexbox_manager.h" +#endif + +/* JPWL>> */ +#ifdef USE_JPWL +#include "openjpwl/jpwl.h" +#endif /* USE_JPWL */ +/* < b else b +*/ +static INLINE OPJ_INT32 opj_int_max(OPJ_INT32 a, OPJ_INT32 b) +{ + return (a > b) ? a : b; +} + +/** +Get the maximum of two integers +@return Returns a if a > b else b +*/ +static INLINE OPJ_UINT32 opj_uint_max(OPJ_UINT32 a, OPJ_UINT32 b) +{ + return (a > b) ? a : b; +} + +/** + Get the saturated sum of two unsigned integers + @return Returns saturated sum of a+b + */ +static INLINE OPJ_UINT32 opj_uint_adds(OPJ_UINT32 a, OPJ_UINT32 b) +{ + OPJ_UINT64 sum = (OPJ_UINT64)a + (OPJ_UINT64)b; + return (OPJ_UINT32)(-(OPJ_INT32)(sum >> 32)) | (OPJ_UINT32)sum; +} + +/** + Get the saturated difference of two unsigned integers + @return Returns saturated sum of a-b + */ +static INLINE OPJ_UINT32 opj_uint_subs(OPJ_UINT32 a, OPJ_UINT32 b) +{ + return (a >= b) ? a - b : 0; +} + +/** +Clamp an integer inside an interval +@return +
    +
  • Returns a if (min < a < max) +
  • Returns max if (a > max) +
  • Returns min if (a < min) +
+*/ +static INLINE OPJ_INT32 opj_int_clamp(OPJ_INT32 a, OPJ_INT32 min, + OPJ_INT32 max) +{ + if (a < min) { + return min; + } + if (a > max) { + return max; + } + return a; +} + +/** +Clamp an integer inside an interval +@return +
    +
  • Returns a if (min < a < max) +
  • Returns max if (a > max) +
  • Returns min if (a < min) +
+*/ +static INLINE OPJ_INT64 opj_int64_clamp(OPJ_INT64 a, OPJ_INT64 min, + OPJ_INT64 max) +{ + if (a < min) { + return min; + } + if (a > max) { + return max; + } + return a; +} + +/** +@return Get absolute value of integer +*/ +static INLINE OPJ_INT32 opj_int_abs(OPJ_INT32 a) +{ + return a < 0 ? -a : a; +} +/** +Divide an integer and round upwards +@return Returns a divided by b +*/ +static INLINE OPJ_INT32 opj_int_ceildiv(OPJ_INT32 a, OPJ_INT32 b) +{ + assert(b); + return (OPJ_INT32)(((OPJ_INT64)a + b - 1) / b); +} + +/** +Divide an integer and round upwards +@return Returns a divided by b +*/ +static INLINE OPJ_UINT32 opj_uint_ceildiv(OPJ_UINT32 a, OPJ_UINT32 b) +{ + assert(b); + return (OPJ_UINT32)(((OPJ_UINT64)a + b - 1) / b); +} + +/** +Divide an integer and round upwards +@return Returns a divided by b +*/ +static INLINE OPJ_UINT32 opj_uint64_ceildiv_res_uint32(OPJ_UINT64 a, + OPJ_UINT64 b) +{ + assert(b); + return (OPJ_UINT32)((a + b - 1) / b); +} + +/** +Divide an integer by a power of 2 and round upwards +@return Returns a divided by 2^b +*/ +static INLINE OPJ_INT32 opj_int_ceildivpow2(OPJ_INT32 a, OPJ_INT32 b) +{ + return (OPJ_INT32)((a + ((OPJ_INT64)1 << b) - 1) >> b); +} + +/** + Divide a 64bits integer by a power of 2 and round upwards + @return Returns a divided by 2^b + */ +static INLINE OPJ_INT32 opj_int64_ceildivpow2(OPJ_INT64 a, OPJ_INT32 b) +{ + return (OPJ_INT32)((a + ((OPJ_INT64)1 << b) - 1) >> b); +} + +/** + Divide an integer by a power of 2 and round upwards + @return Returns a divided by 2^b + */ +static INLINE OPJ_UINT32 opj_uint_ceildivpow2(OPJ_UINT32 a, OPJ_UINT32 b) +{ + return (OPJ_UINT32)((a + ((OPJ_UINT64)1U << b) - 1U) >> b); +} + +/** +Divide an integer by a power of 2 and round downwards +@return Returns a divided by 2^b +*/ +static INLINE OPJ_INT32 opj_int_floordivpow2(OPJ_INT32 a, OPJ_INT32 b) +{ + return a >> b; +} + +/** +Divide an integer by a power of 2 and round downwards +@return Returns a divided by 2^b +*/ +static INLINE OPJ_UINT32 opj_uint_floordivpow2(OPJ_UINT32 a, OPJ_UINT32 b) +{ + return a >> b; +} + +/** +Get logarithm of an integer and round downwards +@return Returns log2(a) +*/ +static INLINE OPJ_INT32 opj_int_floorlog2(OPJ_INT32 a) +{ + OPJ_INT32 l; + for (l = 0; a > 1; l++) { + a >>= 1; + } + return l; +} +/** +Get logarithm of an integer and round downwards +@return Returns log2(a) +*/ +static INLINE OPJ_UINT32 opj_uint_floorlog2(OPJ_UINT32 a) +{ + OPJ_UINT32 l; + for (l = 0; a > 1; ++l) { + a >>= 1; + } + return l; +} + +/** +Multiply two fixed-precision rational numbers. +@param a +@param b +@return Returns a * b +*/ +static INLINE OPJ_INT32 opj_int_fix_mul(OPJ_INT32 a, OPJ_INT32 b) +{ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86) + OPJ_INT64 temp = __emul(a, b); +#else + OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; +#endif + temp += 4096; + assert((temp >> 13) <= (OPJ_INT64)0x7FFFFFFF); + assert((temp >> 13) >= (-(OPJ_INT64)0x7FFFFFFF - (OPJ_INT64)1)); + return (OPJ_INT32)(temp >> 13); +} + +static INLINE OPJ_INT32 opj_int_fix_mul_t1(OPJ_INT32 a, OPJ_INT32 b) +{ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) && defined(_M_IX86) + OPJ_INT64 temp = __emul(a, b); +#else + OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; +#endif + temp += 4096; + assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) <= (OPJ_INT64)0x7FFFFFFF); + assert((temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) >= (-(OPJ_INT64)0x7FFFFFFF - + (OPJ_INT64)1)); + return (OPJ_INT32)(temp >> (13 + 11 - T1_NMSEDEC_FRACBITS)) ; +} + +/** +Addition two signed integers with a wrap-around behaviour. +Assumes complement-to-two signed integers. +@param a +@param b +@return Returns a + b +*/ +static INLINE OPJ_INT32 opj_int_add_no_overflow(OPJ_INT32 a, OPJ_INT32 b) +{ + void* pa = &a; + void* pb = &b; + OPJ_UINT32* upa = (OPJ_UINT32*)pa; + OPJ_UINT32* upb = (OPJ_UINT32*)pb; + OPJ_UINT32 ures = *upa + *upb; + void* pures = &ures; + OPJ_INT32* ipres = (OPJ_INT32*)pures; + return *ipres; +} + +/** +Subtract two signed integers with a wrap-around behaviour. +Assumes complement-to-two signed integers. +@param a +@param b +@return Returns a - b +*/ +static INLINE OPJ_INT32 opj_int_sub_no_overflow(OPJ_INT32 a, OPJ_INT32 b) +{ + void* pa = &a; + void* pb = &b; + OPJ_UINT32* upa = (OPJ_UINT32*)pa; + OPJ_UINT32* upb = (OPJ_UINT32*)pb; + OPJ_UINT32 ures = *upa - *upb; + void* pures = &ures; + OPJ_INT32* ipres = (OPJ_INT32*)pures; + return *ipres; +} + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_INTMATH_H */ diff --git a/client/deps/openjpeg/opj_malloc.c b/client/deps/openjpeg/opj_malloc.c new file mode 100644 index 000000000..dca91bfcb --- /dev/null +++ b/client/deps/openjpeg/opj_malloc.c @@ -0,0 +1,249 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2015, Mathieu Malaterre + * Copyright (c) 2015, Matthieu Darbois + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#define OPJ_SKIP_POISON +#include "opj_includes.h" + +#if defined(OPJ_HAVE_MALLOC_H) && defined(OPJ_HAVE_MEMALIGN) +# include +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t) -1) +#endif + +static INLINE void *opj_aligned_alloc_n(size_t alignment, size_t size) +{ + void* ptr; + + /* alignment shall be power of 2 */ + assert((alignment != 0U) && ((alignment & (alignment - 1U)) == 0U)); + /* alignment shall be at least sizeof(void*) */ + assert(alignment >= sizeof(void*)); + + if (size == 0U) { /* prevent implementation defined behavior of realloc */ + return NULL; + } + +#if defined(OPJ_HAVE_POSIX_MEMALIGN) + /* aligned_alloc requires c11, restrict to posix_memalign for now. Quote: + * This function was introduced in POSIX 1003.1d. Although this function is + * superseded by aligned_alloc, it is more portable to older POSIX systems + * that do not support ISO C11. */ + if (posix_memalign(&ptr, alignment, size)) { + ptr = NULL; + } + /* older linux */ +#elif defined(OPJ_HAVE_MEMALIGN) + ptr = memalign(alignment, size); + /* _MSC_VER */ +#elif defined(OPJ_HAVE__ALIGNED_MALLOC) + ptr = _aligned_malloc(size, alignment); +#else + /* + * Generic aligned malloc implementation. + * Uses size_t offset for the integer manipulation of the pointer, + * as uintptr_t is not available in C89 to do + * bitwise operations on the pointer itself. + */ + alignment--; + { + size_t offset; + OPJ_UINT8 *mem; + + /* Room for padding and extra pointer stored in front of allocated area */ + size_t overhead = alignment + sizeof(void *); + + /* let's be extra careful */ + assert(alignment <= (SIZE_MAX - sizeof(void *))); + + /* Avoid integer overflow */ + if (size > (SIZE_MAX - overhead)) { + return NULL; + } + + mem = (OPJ_UINT8*)malloc(size + overhead); + if (mem == NULL) { + return mem; + } + /* offset = ((alignment + 1U) - ((size_t)(mem + sizeof(void*)) & alignment)) & alignment; */ + /* Use the fact that alignment + 1U is a power of 2 */ + offset = ((alignment ^ ((size_t)(mem + sizeof(void*)) & alignment)) + 1U) & + alignment; + ptr = (void *)(mem + sizeof(void*) + offset); + ((void**) ptr)[-1] = mem; + } +#endif + return ptr; +} +static INLINE void *opj_aligned_realloc_n(void *ptr, size_t alignment, + size_t new_size) +{ + void *r_ptr; + + /* alignment shall be power of 2 */ + assert((alignment != 0U) && ((alignment & (alignment - 1U)) == 0U)); + /* alignment shall be at least sizeof(void*) */ + assert(alignment >= sizeof(void*)); + + if (new_size == 0U) { /* prevent implementation defined behavior of realloc */ + return NULL; + } + + /* no portable aligned realloc */ +#if defined(OPJ_HAVE_POSIX_MEMALIGN) || defined(OPJ_HAVE_MEMALIGN) + /* glibc doc states one can mix aligned malloc with realloc */ + r_ptr = realloc(ptr, new_size); /* fast path */ + /* we simply use `size_t` to cast, since we are only interest in binary AND + * operator */ + if (((size_t)r_ptr & (alignment - 1U)) != 0U) { + /* this is non-trivial to implement a portable aligned realloc, so use a + * simple approach where we do not need a function that return the size of an + * allocated array (eg. _msize on Windows, malloc_size on MacOS, + * malloc_usable_size on systems with glibc) */ + void *a_ptr = opj_aligned_alloc_n(alignment, new_size); + if (a_ptr != NULL) { + memcpy(a_ptr, r_ptr, new_size); + } + free(r_ptr); + r_ptr = a_ptr; + } + /* _MSC_VER */ +#elif defined(OPJ_HAVE__ALIGNED_MALLOC) + r_ptr = _aligned_realloc(ptr, new_size, alignment); +#else + if (ptr == NULL) { + return opj_aligned_alloc_n(alignment, new_size); + } + alignment--; + { + void *oldmem; + OPJ_UINT8 *newmem; + size_t overhead = alignment + sizeof(void *); + + /* let's be extra careful */ + assert(alignment <= (SIZE_MAX - sizeof(void *))); + + /* Avoid integer overflow */ + if (new_size > SIZE_MAX - overhead) { + return NULL; + } + + oldmem = ((void**) ptr)[-1]; + newmem = (OPJ_UINT8*)realloc(oldmem, new_size + overhead); + if (newmem == NULL) { + return newmem; + } + + if (newmem == oldmem) { + r_ptr = ptr; + } else { + size_t old_offset; + size_t new_offset; + + /* realloc created a new copy, realign the copied memory block */ + old_offset = (size_t)((OPJ_UINT8*)ptr - (OPJ_UINT8*)oldmem); + + /* offset = ((alignment + 1U) - ((size_t)(mem + sizeof(void*)) & alignment)) & alignment; */ + /* Use the fact that alignment + 1U is a power of 2 */ + new_offset = ((alignment ^ ((size_t)(newmem + sizeof(void*)) & alignment)) + + 1U) & alignment; + new_offset += sizeof(void*); + r_ptr = (void *)(newmem + new_offset); + + if (new_offset != old_offset) { + memmove(newmem + new_offset, newmem + old_offset, new_size); + } + ((void**) r_ptr)[-1] = newmem; + } + } +#endif + return r_ptr; +} +void * opj_malloc(size_t size) +{ + if (size == 0U) { /* prevent implementation defined behavior of realloc */ + return NULL; + } + return malloc(size); +} +void * opj_calloc(size_t num, size_t size) +{ + if (num == 0 || size == 0) { + /* prevent implementation defined behavior of realloc */ + return NULL; + } + return calloc(num, size); +} + +void *opj_aligned_malloc(size_t size) +{ + return opj_aligned_alloc_n(16U, size); +} +void * opj_aligned_realloc(void *ptr, size_t size) +{ + return opj_aligned_realloc_n(ptr, 16U, size); +} + +void *opj_aligned_32_malloc(size_t size) +{ + return opj_aligned_alloc_n(32U, size); +} +void * opj_aligned_32_realloc(void *ptr, size_t size) +{ + return opj_aligned_realloc_n(ptr, 32U, size); +} + +void opj_aligned_free(void* ptr) +{ +#if defined(OPJ_HAVE_POSIX_MEMALIGN) || defined(OPJ_HAVE_MEMALIGN) + free(ptr); +#elif defined(OPJ_HAVE__ALIGNED_MALLOC) + _aligned_free(ptr); +#else + /* Generic implementation has malloced pointer stored in front of used area */ + if (ptr != NULL) { + free(((void**) ptr)[-1]); + } +#endif +} + +void * opj_realloc(void *ptr, size_t new_size) +{ + if (new_size == 0U) { /* prevent implementation defined behavior of realloc */ + return NULL; + } + return realloc(ptr, new_size); +} +void opj_free(void *ptr) +{ + free(ptr); +} diff --git a/client/deps/openjpeg/opj_malloc.h b/client/deps/openjpeg/opj_malloc.h new file mode 100644 index 000000000..cbc4106c7 --- /dev/null +++ b/client/deps/openjpeg/opj_malloc.h @@ -0,0 +1,106 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2007, Callum Lerwick + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_MALLOC_H +#define OPJ_MALLOC_H + +#include +/** +@file opj_malloc.h +@brief Internal functions + +The functions in opj_malloc.h are internal utilities used for memory management. +*/ + +/** @defgroup MISC MISC - Miscellaneous internal functions */ +/*@{*/ + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Allocate an uninitialized memory block +@param size Bytes to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +void * opj_malloc(size_t size); + +/** +Allocate a memory block with elements initialized to 0 +@param numOfElements Blocks to allocate +@param sizeOfElements Bytes per block to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +void * opj_calloc(size_t numOfElements, size_t sizeOfElements); + +/** +Allocate memory aligned to a 16 byte boundary +@param size Bytes to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +void * opj_aligned_malloc(size_t size); +void * opj_aligned_realloc(void *ptr, size_t size); +void opj_aligned_free(void* ptr); + +/** +Allocate memory aligned to a 32 byte boundary +@param size Bytes to allocate +@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available +*/ +void * opj_aligned_32_malloc(size_t size); +void * opj_aligned_32_realloc(void *ptr, size_t size); + +/** +Reallocate memory blocks. +@param m Pointer to previously allocated memory block +@param s New size in bytes +@return Returns a void pointer to the reallocated (and possibly moved) memory block +*/ +void * opj_realloc(void * m, size_t s); + +/** +Deallocates or frees a memory block. +@param m Previously allocated memory block to be freed +*/ +void opj_free(void * m); + +#if defined(__GNUC__) && !defined(OPJ_SKIP_POISON) +#pragma GCC poison malloc calloc realloc free +#endif + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_MALLOC_H */ + diff --git a/client/deps/openjpeg/pi.c b/client/deps/openjpeg/pi.c new file mode 100644 index 000000000..15ac33142 --- /dev/null +++ b/client/deps/openjpeg/pi.c @@ -0,0 +1,2149 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#define OPJ_UINT32_SEMANTICALLY_BUT_INT32 OPJ_UINT32 + +#include "opj_includes.h" + +/** @defgroup PI PI - Implementation of a packet iterator */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +/** +Get next packet in layer-resolution-component-precinct order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static OPJ_BOOL opj_pi_next_lrcp(opj_pi_iterator_t * pi); +/** +Get next packet in resolution-layer-component-precinct order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static OPJ_BOOL opj_pi_next_rlcp(opj_pi_iterator_t * pi); +/** +Get next packet in resolution-precinct-component-layer order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static OPJ_BOOL opj_pi_next_rpcl(opj_pi_iterator_t * pi); +/** +Get next packet in precinct-component-resolution-layer order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi); +/** +Get next packet in component-precinct-resolution-layer order. +@param pi packet iterator to modify +@return returns false if pi pointed to the last packet or else returns true +*/ +static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi); + +/** + * Updates the coding parameters if the encoding is used with Progression order changes and final (or cinema parameters are used). + * + * @param p_cp the coding parameters to modify + * @param p_tileno the tile index being concerned. + * @param p_tx0 X0 parameter for the tile + * @param p_tx1 X1 parameter for the tile + * @param p_ty0 Y0 parameter for the tile + * @param p_ty1 Y1 parameter for the tile + * @param p_max_prec the maximum precision for all the bands of the tile + * @param p_max_res the maximum number of resolutions for all the poc inside the tile. + * @param p_dx_min the minimum dx of all the components of all the resolutions for the tile. + * @param p_dy_min the minimum dy of all the components of all the resolutions for the tile. + */ +static void opj_pi_update_encode_poc_and_final(opj_cp_t *p_cp, + OPJ_UINT32 p_tileno, + OPJ_UINT32 p_tx0, + OPJ_UINT32 p_tx1, + OPJ_UINT32 p_ty0, + OPJ_UINT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min); + +/** + * Updates the coding parameters if the encoding is not used with Progression order changes and final (and cinema parameters are used). + * + * @param p_cp the coding parameters to modify + * @param p_num_comps the number of components + * @param p_tileno the tile index being concerned. + * @param p_tx0 X0 parameter for the tile + * @param p_tx1 X1 parameter for the tile + * @param p_ty0 Y0 parameter for the tile + * @param p_ty1 Y1 parameter for the tile + * @param p_max_prec the maximum precision for all the bands of the tile + * @param p_max_res the maximum number of resolutions for all the poc inside the tile. + * @param p_dx_min the minimum dx of all the components of all the resolutions for the tile. + * @param p_dy_min the minimum dy of all the components of all the resolutions for the tile. + */ +static void opj_pi_update_encode_not_poc(opj_cp_t *p_cp, + OPJ_UINT32 p_num_comps, + OPJ_UINT32 p_tileno, + OPJ_UINT32 p_tx0, + OPJ_UINT32 p_tx1, + OPJ_UINT32 p_ty0, + OPJ_UINT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min); +/** + * Gets the encoding parameters needed to update the coding parameters and all the pocs. + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param tileno the tile index of the tile being encoded. + * @param p_tx0 pointer that will hold the X0 parameter for the tile + * @param p_tx1 pointer that will hold the X1 parameter for the tile + * @param p_ty0 pointer that will hold the Y0 parameter for the tile + * @param p_ty1 pointer that will hold the Y1 parameter for the tile + * @param p_max_prec pointer that will hold the maximum precision for all the bands of the tile + * @param p_max_res pointer that will hold the maximum number of resolutions for all the poc inside the tile. + * @param p_dx_min pointer that will hold the minimum dx of all the components of all the resolutions for the tile. + * @param p_dy_min pointer that will hold the minimum dy of all the components of all the resolutions for the tile. + */ +static void opj_get_encoding_parameters(const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 tileno, + OPJ_UINT32 * p_tx0, + OPJ_UINT32 * p_tx1, + OPJ_UINT32 * p_ty0, + OPJ_UINT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res); + +/** + * Gets the encoding parameters needed to update the coding parameters and all the pocs. + * The precinct widths, heights, dx and dy for each component at each resolution will be stored as well. + * the last parameter of the function should be an array of pointers of size nb components, each pointer leading + * to an area of size 4 * max_res. The data is stored inside this area with the following pattern : + * dx_compi_res0 , dy_compi_res0 , w_compi_res0, h_compi_res0 , dx_compi_res1 , dy_compi_res1 , w_compi_res1, h_compi_res1 , ... + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param tileno the tile index of the tile being encoded. + * @param p_tx0 pointer that will hold the X0 parameter for the tile + * @param p_tx1 pointer that will hold the X1 parameter for the tile + * @param p_ty0 pointer that will hold the Y0 parameter for the tile + * @param p_ty1 pointer that will hold the Y1 parameter for the tile + * @param p_max_prec pointer that will hold the maximum precision for all the bands of the tile + * @param p_max_res pointer that will hold the maximum number of resolutions for all the poc inside the tile. + * @param p_dx_min pointer that will hold the minimum dx of all the components of all the resolutions for the tile. + * @param p_dy_min pointer that will hold the minimum dy of all the components of all the resolutions for the tile. + * @param p_resolutions pointer to an area corresponding to the one described above. + */ +static void opj_get_all_encoding_parameters(const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 tileno, + OPJ_UINT32 * p_tx0, + OPJ_UINT32 * p_tx1, + OPJ_UINT32 * p_ty0, + OPJ_UINT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res, + OPJ_UINT32 ** p_resolutions); +/** + * Allocates memory for a packet iterator. Data and data sizes are set by this operation. + * No other data is set. The include section of the packet iterator is not allocated. + * + * @param p_image the image used to initialize the packet iterator (in fact only the number of components is relevant. + * @param p_cp the coding parameters. + * @param tileno the index of the tile from which creating the packet iterator. + * @param manager Event manager + */ +static opj_pi_iterator_t * opj_pi_create(const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 tileno, + opj_event_mgr_t* manager); +/** + * FIXME DOC + */ +static void opj_pi_update_decode_not_poc(opj_pi_iterator_t * p_pi, + opj_tcp_t * p_tcp, + OPJ_UINT32 p_max_precision, + OPJ_UINT32 p_max_res); +/** + * FIXME DOC + */ +static void opj_pi_update_decode_poc(opj_pi_iterator_t * p_pi, + opj_tcp_t * p_tcp, + OPJ_UINT32 p_max_precision, + OPJ_UINT32 p_max_res); + +/** + * FIXME DOC + */ +static OPJ_BOOL opj_pi_check_next_level(OPJ_INT32 pos, + opj_cp_t *cp, + OPJ_UINT32 tileno, + OPJ_UINT32 pino, + const OPJ_CHAR *prog); + +/*@}*/ + +/*@}*/ + +/* +========================================================== + local functions +========================================================== +*/ + +static OPJ_BOOL opj_pi_next_lrcp(opj_pi_iterator_t * pi) +{ + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (pi->poc.compno0 >= pi->numcomps || + pi->poc.compno1 >= pi->numcomps + 1) { + opj_event_msg(pi->manager, EVT_ERROR, + "opj_pi_next_lrcp(): invalid compno0/compno1\n"); + return OPJ_FALSE; + } + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + res = &comp->resolutions[pi->resno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; + pi->resno++) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + if (!pi->tp_on) { + pi->poc.precno1 = res->pw * res->ph; + } + for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + /* Avoids index out of bounds access with */ + /* id_000098,sig_11,src_005411,op_havoc,rep_2 of */ + /* https://github.com/uclouvain/openjpeg/issues/938 */ + /* Not sure if this is the most clever fix. Perhaps */ + /* include should be resized when a POC arises, or */ + /* the POC should be rejected */ + if (index >= pi->include_size) { + opj_event_msg(pi->manager, EVT_ERROR, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + + return OPJ_FALSE; +} + +static OPJ_BOOL opj_pi_next_rlcp(opj_pi_iterator_t * pi) +{ + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (pi->poc.compno0 >= pi->numcomps || + pi->poc.compno1 >= pi->numcomps + 1) { + opj_event_msg(pi->manager, EVT_ERROR, + "opj_pi_next_rlcp(): invalid compno0/compno1\n"); + return OPJ_FALSE; + } + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + res = &comp->resolutions[pi->resno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + if (!pi->tp_on) { + pi->poc.precno1 = res->pw * res->ph; + } + for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + if (index >= pi->include_size) { + opj_event_msg(pi->manager, EVT_ERROR, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + + return OPJ_FALSE; +} + +static OPJ_BOOL opj_pi_next_rpcl(opj_pi_iterator_t * pi) +{ + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (pi->poc.compno0 >= pi->numcomps || + pi->poc.compno1 >= pi->numcomps + 1) { + opj_event_msg(pi->manager, EVT_ERROR, + "opj_pi_next_rpcl(): invalid compno0/compno1\n"); + return OPJ_FALSE; + } + + if (!pi->first) { + goto LABEL_SKIP; + } else { + OPJ_UINT32 compno, resno; + pi->first = 0; + pi->dx = 0; + pi->dy = 0; + for (compno = 0; compno < pi->numcomps; compno++) { + comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolutions; resno++) { + OPJ_UINT32 dx, dy; + res = &comp->resolutions[resno]; + if (res->pdx + comp->numresolutions - 1 - resno < 32 && + comp->dx <= UINT_MAX / (1u << (res->pdx + comp->numresolutions - 1 - resno))) { + dx = comp->dx * (1u << (res->pdx + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : opj_uint_min(pi->dx, dx); + } + if (res->pdy + comp->numresolutions - 1 - resno < 32 && + comp->dy <= UINT_MAX / (1u << (res->pdy + comp->numresolutions - 1 - resno))) { + dy = comp->dy * (1u << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dy = !pi->dy ? dy : opj_uint_min(pi->dy, dy); + } + } + } + if (pi->dx == 0 || pi->dy == 0) { + return OPJ_FALSE; + } + } + if (!pi->tp_on) { + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { + for (pi->y = (OPJ_UINT32)pi->poc.ty0; pi->y < (OPJ_UINT32)pi->poc.ty1; + pi->y += (pi->dy - (pi->y % pi->dy))) { + for (pi->x = (OPJ_UINT32)pi->poc.tx0; pi->x < (OPJ_UINT32)pi->poc.tx1; + pi->x += (pi->dx - (pi->x % pi->dx))) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + OPJ_UINT32 levelno; + OPJ_UINT32 trx0, try0; + OPJ_UINT32 trx1, try1; + OPJ_UINT32 rpx, rpy; + OPJ_UINT32 prci, prcj; + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolutions) { + continue; + } + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << levelno) >> levelno) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << levelno) >> levelno) != comp->dy) { + continue; + } + + trx0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx0, + ((OPJ_UINT64)comp->dx << levelno)); + try0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty0, + ((OPJ_UINT64)comp->dy << levelno)); + trx1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx1, + ((OPJ_UINT64)comp->dx << levelno)); + try1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty1, + ((OPJ_UINT64)comp->dy << levelno)); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << rpx) >> rpx) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << rpy) >> rpy) != comp->dy) { + continue; + } + + /* See ISO-15441. B.12.1.3 Resolution level-position-component-layer progression */ + if (!(((OPJ_UINT64)pi->y % ((OPJ_UINT64)comp->dy << rpy) == 0) || + ((pi->y == pi->ty0) && + (((OPJ_UINT64)try0 << levelno) % ((OPJ_UINT64)1U << rpy))))) { + continue; + } + if (!(((OPJ_UINT64)pi->x % ((OPJ_UINT64)comp->dx << rpx) == 0) || + ((pi->x == pi->tx0) && + (((OPJ_UINT64)trx0 << levelno) % ((OPJ_UINT64)1U << rpx))))) { + continue; + } + + if ((res->pw == 0) || (res->ph == 0)) { + continue; + } + + if ((trx0 == trx1) || (try0 == try1)) { + continue; + } + + prci = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->x, + ((OPJ_UINT64)comp->dx << levelno)), res->pdx) + - opj_uint_floordivpow2(trx0, res->pdx); + prcj = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->y, + ((OPJ_UINT64)comp->dy << levelno)), res->pdy) + - opj_uint_floordivpow2(try0, res->pdy); + pi->precno = prci + prcj * res->pw; + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + if (index >= pi->include_size) { + opj_event_msg(pi->manager, EVT_ERROR, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + } + + return OPJ_FALSE; +} + +static OPJ_BOOL opj_pi_next_pcrl(opj_pi_iterator_t * pi) +{ + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (pi->poc.compno0 >= pi->numcomps || + pi->poc.compno1 >= pi->numcomps + 1) { + opj_event_msg(pi->manager, EVT_ERROR, + "opj_pi_next_pcrl(): invalid compno0/compno1\n"); + return OPJ_FALSE; + } + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + goto LABEL_SKIP; + } else { + OPJ_UINT32 compno, resno; + pi->first = 0; + pi->dx = 0; + pi->dy = 0; + for (compno = 0; compno < pi->numcomps; compno++) { + comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolutions; resno++) { + OPJ_UINT32 dx, dy; + res = &comp->resolutions[resno]; + if (res->pdx + comp->numresolutions - 1 - resno < 32 && + comp->dx <= UINT_MAX / (1u << (res->pdx + comp->numresolutions - 1 - resno))) { + dx = comp->dx * (1u << (res->pdx + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : opj_uint_min(pi->dx, dx); + } + if (res->pdy + comp->numresolutions - 1 - resno < 32 && + comp->dy <= UINT_MAX / (1u << (res->pdy + comp->numresolutions - 1 - resno))) { + dy = comp->dy * (1u << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dy = !pi->dy ? dy : opj_uint_min(pi->dy, dy); + } + } + } + if (pi->dx == 0 || pi->dy == 0) { + return OPJ_FALSE; + } + } + if (!pi->tp_on) { + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->y = (OPJ_UINT32)pi->poc.ty0; pi->y < (OPJ_UINT32)pi->poc.ty1; + pi->y += (pi->dy - (pi->y % pi->dy))) { + for (pi->x = (OPJ_UINT32)pi->poc.tx0; pi->x < (OPJ_UINT32)pi->poc.tx1; + pi->x += (pi->dx - (pi->x % pi->dx))) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + comp = &pi->comps[pi->compno]; + for (pi->resno = pi->poc.resno0; + pi->resno < opj_uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + OPJ_UINT32 levelno; + OPJ_UINT32 trx0, try0; + OPJ_UINT32 trx1, try1; + OPJ_UINT32 rpx, rpy; + OPJ_UINT32 prci, prcj; + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << levelno) >> levelno) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << levelno) >> levelno) != comp->dy) { + continue; + } + + trx0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx0, + ((OPJ_UINT64)comp->dx << levelno)); + try0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty0, + ((OPJ_UINT64)comp->dy << levelno)); + trx1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx1, + ((OPJ_UINT64)comp->dx << levelno)); + try1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty1, + ((OPJ_UINT64)comp->dy << levelno)); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << rpx) >> rpx) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << rpy) >> rpy) != comp->dy) { + continue; + } + + /* See ISO-15441. B.12.1.4 Position-component-resolution level-layer progression */ + if (!(((OPJ_UINT64)pi->y % ((OPJ_UINT64)comp->dy << rpy) == 0) || + ((pi->y == pi->ty0) && + (((OPJ_UINT64)try0 << levelno) % ((OPJ_UINT64)1U << rpy))))) { + continue; + } + if (!(((OPJ_UINT64)pi->x % ((OPJ_UINT64)comp->dx << rpx) == 0) || + ((pi->x == pi->tx0) && + (((OPJ_UINT64)trx0 << levelno) % ((OPJ_UINT64)1U << rpx))))) { + continue; + } + + if ((res->pw == 0) || (res->ph == 0)) { + continue; + } + + if ((trx0 == trx1) || (try0 == try1)) { + continue; + } + + prci = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->x, + ((OPJ_UINT64)comp->dx << levelno)), res->pdx) + - opj_uint_floordivpow2(trx0, res->pdx); + prcj = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->y, + ((OPJ_UINT64)comp->dy << levelno)), res->pdy) + - opj_uint_floordivpow2(try0, res->pdy); + pi->precno = prci + prcj * res->pw; + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + if (index >= pi->include_size) { + opj_event_msg(pi->manager, EVT_ERROR, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + } + + return OPJ_FALSE; +} + +static OPJ_BOOL opj_pi_next_cprl(opj_pi_iterator_t * pi) +{ + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + OPJ_UINT32 index = 0; + + if (pi->poc.compno0 >= pi->numcomps || + pi->poc.compno1 >= pi->numcomps + 1) { + opj_event_msg(pi->manager, EVT_ERROR, + "opj_pi_next_cprl(): invalid compno0/compno1\n"); + return OPJ_FALSE; + } + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + OPJ_UINT32 resno; + comp = &pi->comps[pi->compno]; + pi->dx = 0; + pi->dy = 0; + for (resno = 0; resno < comp->numresolutions; resno++) { + OPJ_UINT32 dx, dy; + res = &comp->resolutions[resno]; + if (res->pdx + comp->numresolutions - 1 - resno < 32 && + comp->dx <= UINT_MAX / (1u << (res->pdx + comp->numresolutions - 1 - resno))) { + dx = comp->dx * (1u << (res->pdx + comp->numresolutions - 1 - resno)); + pi->dx = !pi->dx ? dx : opj_uint_min(pi->dx, dx); + } + if (res->pdy + comp->numresolutions - 1 - resno < 32 && + comp->dy <= UINT_MAX / (1u << (res->pdy + comp->numresolutions - 1 - resno))) { + dy = comp->dy * (1u << (res->pdy + comp->numresolutions - 1 - resno)); + pi->dy = !pi->dy ? dy : opj_uint_min(pi->dy, dy); + } + } + if (pi->dx == 0 || pi->dy == 0) { + return OPJ_FALSE; + } + if (!pi->tp_on) { + pi->poc.ty0 = pi->ty0; + pi->poc.tx0 = pi->tx0; + pi->poc.ty1 = pi->ty1; + pi->poc.tx1 = pi->tx1; + } + for (pi->y = (OPJ_UINT32)pi->poc.ty0; pi->y < (OPJ_UINT32)pi->poc.ty1; + pi->y += (pi->dy - (pi->y % pi->dy))) { + for (pi->x = (OPJ_UINT32)pi->poc.tx0; pi->x < (OPJ_UINT32)pi->poc.tx1; + pi->x += (pi->dx - (pi->x % pi->dx))) { + for (pi->resno = pi->poc.resno0; + pi->resno < opj_uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { + OPJ_UINT32 levelno; + OPJ_UINT32 trx0, try0; + OPJ_UINT32 trx1, try1; + OPJ_UINT32 rpx, rpy; + OPJ_UINT32 prci, prcj; + res = &comp->resolutions[pi->resno]; + levelno = comp->numresolutions - 1 - pi->resno; + + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << levelno) >> levelno) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << levelno) >> levelno) != comp->dy) { + continue; + } + + trx0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx0, + ((OPJ_UINT64)comp->dx << levelno)); + try0 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty0, + ((OPJ_UINT64)comp->dy << levelno)); + trx1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->tx1, + ((OPJ_UINT64)comp->dx << levelno)); + try1 = opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->ty1, + ((OPJ_UINT64)comp->dy << levelno)); + rpx = res->pdx + levelno; + rpy = res->pdy + levelno; + + if ((OPJ_UINT32)(((OPJ_UINT64)comp->dx << rpx) >> rpx) != comp->dx || + (OPJ_UINT32)(((OPJ_UINT64)comp->dy << rpy) >> rpy) != comp->dy) { + continue; + } + + /* See ISO-15441. B.12.1.5 Component-position-resolution level-layer progression */ + if (!(((OPJ_UINT64)pi->y % ((OPJ_UINT64)comp->dy << rpy) == 0) || + ((pi->y == pi->ty0) && + (((OPJ_UINT64)try0 << levelno) % ((OPJ_UINT64)1U << rpy))))) { + continue; + } + if (!(((OPJ_UINT64)pi->x % ((OPJ_UINT64)comp->dx << rpx) == 0) || + ((pi->x == pi->tx0) && + (((OPJ_UINT64)trx0 << levelno) % ((OPJ_UINT64)1U << rpx))))) { + continue; + } + + if ((res->pw == 0) || (res->ph == 0)) { + continue; + } + + if ((trx0 == trx1) || (try0 == try1)) { + continue; + } + + prci = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->x, + ((OPJ_UINT64)comp->dx << levelno)), res->pdx) + - opj_uint_floordivpow2(trx0, res->pdx); + prcj = opj_uint_floordivpow2(opj_uint64_ceildiv_res_uint32((OPJ_UINT64)pi->y, + ((OPJ_UINT64)comp->dy << levelno)), res->pdy) + - opj_uint_floordivpow2(try0, res->pdy); + pi->precno = (OPJ_UINT32)(prci + prcj * res->pw); + for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * + pi->step_c + pi->precno * pi->step_p; + if (index >= pi->include_size) { + opj_event_msg(pi->manager, EVT_ERROR, "Invalid access to pi->include"); + return OPJ_FALSE; + } + if (!pi->include[index]) { + pi->include[index] = 1; + return OPJ_TRUE; + } +LABEL_SKIP: + ; + } + } + } + } + } + + return OPJ_FALSE; +} + +static void opj_get_encoding_parameters(const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 p_tileno, + OPJ_UINT32 * p_tx0, + OPJ_UINT32 * p_tx1, + OPJ_UINT32 * p_ty0, + OPJ_UINT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res) +{ + /* loop */ + OPJ_UINT32 compno, resno; + /* pointers */ + const opj_tcp_t *l_tcp = 00; + const opj_tccp_t * l_tccp = 00; + const opj_image_comp_t * l_img_comp = 00; + + /* position in x and y of tile */ + OPJ_UINT32 p, q; + + /* non-corrected (in regard to image offset) tile offset */ + OPJ_UINT32 l_tx0, l_ty0; + + /* preconditions */ + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tileno < p_cp->tw * p_cp->th); + + /* initializations */ + l_tcp = &p_cp->tcps [p_tileno]; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + /* here calculation of tx0, tx1, ty0, ty1, maxprec, dx and dy */ + p = p_tileno % p_cp->tw; + q = p_tileno / p_cp->tw; + + /* find extent of tile */ + l_tx0 = p_cp->tx0 + p * + p_cp->tdx; /* can't be greater than p_image->x1 so won't overflow */ + *p_tx0 = opj_uint_max(l_tx0, p_image->x0); + *p_tx1 = opj_uint_min(opj_uint_adds(l_tx0, p_cp->tdx), p_image->x1); + l_ty0 = p_cp->ty0 + q * + p_cp->tdy; /* can't be greater than p_image->y1 so won't overflow */ + *p_ty0 = opj_uint_max(l_ty0, p_image->y0); + *p_ty1 = opj_uint_min(opj_uint_adds(l_ty0, p_cp->tdy), p_image->y1); + + /* max precision is 0 (can only grow) */ + *p_max_prec = 0; + *p_max_res = 0; + + /* take the largest value for dx_min and dy_min */ + *p_dx_min = 0x7fffffff; + *p_dy_min = 0x7fffffff; + + for (compno = 0; compno < p_image->numcomps; ++compno) { + /* arithmetic variables to calculate */ + OPJ_UINT32 l_level_no; + OPJ_UINT32 l_rx0, l_ry0, l_rx1, l_ry1; + OPJ_UINT32 l_px0, l_py0, l_px1, py1; + OPJ_UINT32 l_pdx, l_pdy; + OPJ_UINT32 l_pw, l_ph; + OPJ_UINT32 l_product; + OPJ_UINT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; + + l_tcx0 = opj_uint_ceildiv(*p_tx0, l_img_comp->dx); + l_tcy0 = opj_uint_ceildiv(*p_ty0, l_img_comp->dy); + l_tcx1 = opj_uint_ceildiv(*p_tx1, l_img_comp->dx); + l_tcy1 = opj_uint_ceildiv(*p_ty1, l_img_comp->dy); + + if (l_tccp->numresolutions > *p_max_res) { + *p_max_res = l_tccp->numresolutions; + } + + /* use custom size for precincts */ + for (resno = 0; resno < l_tccp->numresolutions; ++resno) { + OPJ_UINT64 l_dx, l_dy; + + /* precinct width and height */ + l_pdx = l_tccp->prcw[resno]; + l_pdy = l_tccp->prch[resno]; + + l_dx = l_img_comp->dx * ((OPJ_UINT64)1u << (l_pdx + l_tccp->numresolutions - 1 - + resno)); + l_dy = l_img_comp->dy * ((OPJ_UINT64)1u << (l_pdy + l_tccp->numresolutions - 1 - + resno)); + + /* take the minimum size for dx for each comp and resolution */ + if (l_dx <= UINT_MAX) { + *p_dx_min = opj_uint_min(*p_dx_min, (OPJ_UINT32)l_dx); + } + if (l_dy <= UINT_MAX) { + *p_dy_min = opj_uint_min(*p_dy_min, (OPJ_UINT32)l_dy); + } + + /* various calculations of extents */ + l_level_no = l_tccp->numresolutions - 1 - resno; + + l_rx0 = opj_uint_ceildivpow2(l_tcx0, l_level_no); + l_ry0 = opj_uint_ceildivpow2(l_tcy0, l_level_no); + l_rx1 = opj_uint_ceildivpow2(l_tcx1, l_level_no); + l_ry1 = opj_uint_ceildivpow2(l_tcy1, l_level_no); + + l_px0 = opj_uint_floordivpow2(l_rx0, l_pdx) << l_pdx; + l_py0 = opj_uint_floordivpow2(l_ry0, l_pdy) << l_pdy; + l_px1 = opj_uint_ceildivpow2(l_rx1, l_pdx) << l_pdx; + + py1 = opj_uint_ceildivpow2(l_ry1, l_pdy) << l_pdy; + + l_pw = (l_rx0 == l_rx1) ? 0 : ((l_px1 - l_px0) >> l_pdx); + l_ph = (l_ry0 == l_ry1) ? 0 : ((py1 - l_py0) >> l_pdy); + + l_product = l_pw * l_ph; + + /* update precision */ + if (l_product > *p_max_prec) { + *p_max_prec = l_product; + } + } + ++l_img_comp; + ++l_tccp; + } +} + + +static void opj_get_all_encoding_parameters(const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 tileno, + OPJ_UINT32 * p_tx0, + OPJ_UINT32 * p_tx1, + OPJ_UINT32 * p_ty0, + OPJ_UINT32 * p_ty1, + OPJ_UINT32 * p_dx_min, + OPJ_UINT32 * p_dy_min, + OPJ_UINT32 * p_max_prec, + OPJ_UINT32 * p_max_res, + OPJ_UINT32 ** p_resolutions) +{ + /* loop*/ + OPJ_UINT32 compno, resno; + + /* pointers*/ + const opj_tcp_t *tcp = 00; + const opj_tccp_t * l_tccp = 00; + const opj_image_comp_t * l_img_comp = 00; + + /* to store l_dx, l_dy, w and h for each resolution and component.*/ + OPJ_UINT32 * lResolutionPtr; + + /* position in x and y of tile*/ + OPJ_UINT32 p, q; + + /* non-corrected (in regard to image offset) tile offset */ + OPJ_UINT32 l_tx0, l_ty0; + + /* preconditions in debug*/ + assert(p_cp != 00); + assert(p_image != 00); + assert(tileno < p_cp->tw * p_cp->th); + + /* initializations*/ + tcp = &p_cp->tcps [tileno]; + l_tccp = tcp->tccps; + l_img_comp = p_image->comps; + + /* position in x and y of tile*/ + p = tileno % p_cp->tw; + q = tileno / p_cp->tw; + + /* here calculation of tx0, tx1, ty0, ty1, maxprec, l_dx and l_dy */ + l_tx0 = p_cp->tx0 + p * + p_cp->tdx; /* can't be greater than p_image->x1 so won't overflow */ + *p_tx0 = opj_uint_max(l_tx0, p_image->x0); + *p_tx1 = opj_uint_min(opj_uint_adds(l_tx0, p_cp->tdx), p_image->x1); + l_ty0 = p_cp->ty0 + q * + p_cp->tdy; /* can't be greater than p_image->y1 so won't overflow */ + *p_ty0 = opj_uint_max(l_ty0, p_image->y0); + *p_ty1 = opj_uint_min(opj_uint_adds(l_ty0, p_cp->tdy), p_image->y1); + + /* max precision and resolution is 0 (can only grow)*/ + *p_max_prec = 0; + *p_max_res = 0; + + /* take the largest value for dx_min and dy_min*/ + *p_dx_min = 0x7fffffff; + *p_dy_min = 0x7fffffff; + + for (compno = 0; compno < p_image->numcomps; ++compno) { + /* arithmetic variables to calculate*/ + OPJ_UINT32 l_level_no; + OPJ_UINT32 l_rx0, l_ry0, l_rx1, l_ry1; + OPJ_UINT32 l_px0, l_py0, l_px1, py1; + OPJ_UINT32 l_product; + OPJ_UINT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; + OPJ_UINT32 l_pdx, l_pdy, l_pw, l_ph; + + lResolutionPtr = p_resolutions ? p_resolutions[compno] : NULL; + + l_tcx0 = opj_uint_ceildiv(*p_tx0, l_img_comp->dx); + l_tcy0 = opj_uint_ceildiv(*p_ty0, l_img_comp->dy); + l_tcx1 = opj_uint_ceildiv(*p_tx1, l_img_comp->dx); + l_tcy1 = opj_uint_ceildiv(*p_ty1, l_img_comp->dy); + + if (l_tccp->numresolutions > *p_max_res) { + *p_max_res = l_tccp->numresolutions; + } + + /* use custom size for precincts*/ + l_level_no = l_tccp->numresolutions; + for (resno = 0; resno < l_tccp->numresolutions; ++resno) { + OPJ_UINT32 l_dx, l_dy; + + --l_level_no; + + /* precinct width and height*/ + l_pdx = l_tccp->prcw[resno]; + l_pdy = l_tccp->prch[resno]; + if (lResolutionPtr) { + *lResolutionPtr++ = l_pdx; + *lResolutionPtr++ = l_pdy; + } + if (l_pdx + l_level_no < 32 && + l_img_comp->dx <= UINT_MAX / (1u << (l_pdx + l_level_no))) { + l_dx = l_img_comp->dx * (1u << (l_pdx + l_level_no)); + /* take the minimum size for l_dx for each comp and resolution*/ + *p_dx_min = opj_uint_min(*p_dx_min, l_dx); + } + if (l_pdy + l_level_no < 32 && + l_img_comp->dy <= UINT_MAX / (1u << (l_pdy + l_level_no))) { + l_dy = l_img_comp->dy * (1u << (l_pdy + l_level_no)); + *p_dy_min = opj_uint_min(*p_dy_min, l_dy); + } + + /* various calculations of extents*/ + l_rx0 = opj_uint_ceildivpow2(l_tcx0, l_level_no); + l_ry0 = opj_uint_ceildivpow2(l_tcy0, l_level_no); + l_rx1 = opj_uint_ceildivpow2(l_tcx1, l_level_no); + l_ry1 = opj_uint_ceildivpow2(l_tcy1, l_level_no); + l_px0 = opj_uint_floordivpow2(l_rx0, l_pdx) << l_pdx; + l_py0 = opj_uint_floordivpow2(l_ry0, l_pdy) << l_pdy; + l_px1 = opj_uint_ceildivpow2(l_rx1, l_pdx) << l_pdx; + py1 = opj_uint_ceildivpow2(l_ry1, l_pdy) << l_pdy; + l_pw = (l_rx0 == l_rx1) ? 0 : ((l_px1 - l_px0) >> l_pdx); + l_ph = (l_ry0 == l_ry1) ? 0 : ((py1 - l_py0) >> l_pdy); + if (lResolutionPtr) { + *lResolutionPtr++ = l_pw; + *lResolutionPtr++ = l_ph; + } + l_product = l_pw * l_ph; + + /* update precision*/ + if (l_product > *p_max_prec) { + *p_max_prec = l_product; + } + + } + ++l_tccp; + ++l_img_comp; + } +} + +static opj_pi_iterator_t * opj_pi_create(const opj_image_t *image, + const opj_cp_t *cp, + OPJ_UINT32 tileno, + opj_event_mgr_t* manager) +{ + /* loop*/ + OPJ_UINT32 pino, compno; + /* number of poc in the p_pi*/ + OPJ_UINT32 l_poc_bound; + + /* pointers to tile coding parameters and components.*/ + opj_pi_iterator_t *l_pi = 00; + opj_tcp_t *tcp = 00; + const opj_tccp_t *tccp = 00; + + /* current packet iterator being allocated*/ + opj_pi_iterator_t *l_current_pi = 00; + + /* preconditions in debug*/ + assert(cp != 00); + assert(image != 00); + assert(tileno < cp->tw * cp->th); + + /* initializations*/ + tcp = &cp->tcps[tileno]; + l_poc_bound = tcp->numpocs + 1; + + /* memory allocations*/ + l_pi = (opj_pi_iterator_t*) opj_calloc((l_poc_bound), + sizeof(opj_pi_iterator_t)); + if (!l_pi) { + return NULL; + } + + l_current_pi = l_pi; + for (pino = 0; pino < l_poc_bound ; ++pino) { + + l_current_pi->manager = manager; + + l_current_pi->comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, + sizeof(opj_pi_comp_t)); + if (! l_current_pi->comps) { + opj_pi_destroy(l_pi, l_poc_bound); + return NULL; + } + + l_current_pi->numcomps = image->numcomps; + + for (compno = 0; compno < image->numcomps; ++compno) { + opj_pi_comp_t *comp = &l_current_pi->comps[compno]; + + tccp = &tcp->tccps[compno]; + + comp->resolutions = (opj_pi_resolution_t*) opj_calloc(tccp->numresolutions, + sizeof(opj_pi_resolution_t)); + if (!comp->resolutions) { + opj_pi_destroy(l_pi, l_poc_bound); + return 00; + } + + comp->numresolutions = tccp->numresolutions; + } + ++l_current_pi; + } + return l_pi; +} + +static void opj_pi_update_encode_poc_and_final(opj_cp_t *p_cp, + OPJ_UINT32 p_tileno, + OPJ_UINT32 p_tx0, + OPJ_UINT32 p_tx1, + OPJ_UINT32 p_ty0, + OPJ_UINT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min) +{ + /* loop*/ + OPJ_UINT32 pino; + /* tile coding parameter*/ + opj_tcp_t *l_tcp = 00; + /* current poc being updated*/ + opj_poc_t * l_current_poc = 00; + + /* number of pocs*/ + OPJ_UINT32 l_poc_bound; + + OPJ_ARG_NOT_USED(p_max_res); + + /* preconditions in debug*/ + assert(p_cp != 00); + assert(p_tileno < p_cp->tw * p_cp->th); + + /* initializations*/ + l_tcp = &p_cp->tcps [p_tileno]; + /* number of iterations in the loop */ + l_poc_bound = l_tcp->numpocs + 1; + + /* start at first element, and to make sure the compiler will not make a calculation each time in the loop + store a pointer to the current element to modify rather than l_tcp->pocs[i]*/ + l_current_poc = l_tcp->pocs; + + l_current_poc->compS = l_current_poc->compno0; + l_current_poc->compE = l_current_poc->compno1; + l_current_poc->resS = l_current_poc->resno0; + l_current_poc->resE = l_current_poc->resno1; + l_current_poc->layE = l_current_poc->layno1; + + /* special treatment for the first element*/ + l_current_poc->layS = 0; + l_current_poc->prg = l_current_poc->prg1; + l_current_poc->prcS = 0; + + l_current_poc->prcE = p_max_prec; + l_current_poc->txS = (OPJ_UINT32)p_tx0; + l_current_poc->txE = (OPJ_UINT32)p_tx1; + l_current_poc->tyS = (OPJ_UINT32)p_ty0; + l_current_poc->tyE = (OPJ_UINT32)p_ty1; + l_current_poc->dx = p_dx_min; + l_current_poc->dy = p_dy_min; + + ++ l_current_poc; + for (pino = 1; pino < l_poc_bound ; ++pino) { + l_current_poc->compS = l_current_poc->compno0; + l_current_poc->compE = l_current_poc->compno1; + l_current_poc->resS = l_current_poc->resno0; + l_current_poc->resE = l_current_poc->resno1; + l_current_poc->layE = l_current_poc->layno1; + l_current_poc->prg = l_current_poc->prg1; + l_current_poc->prcS = 0; + /* special treatment here different from the first element*/ + l_current_poc->layS = (l_current_poc->layE > (l_current_poc - 1)->layE) ? + l_current_poc->layE : 0; + + l_current_poc->prcE = p_max_prec; + l_current_poc->txS = (OPJ_UINT32)p_tx0; + l_current_poc->txE = (OPJ_UINT32)p_tx1; + l_current_poc->tyS = (OPJ_UINT32)p_ty0; + l_current_poc->tyE = (OPJ_UINT32)p_ty1; + l_current_poc->dx = p_dx_min; + l_current_poc->dy = p_dy_min; + ++ l_current_poc; + } +} + +static void opj_pi_update_encode_not_poc(opj_cp_t *p_cp, + OPJ_UINT32 p_num_comps, + OPJ_UINT32 p_tileno, + OPJ_UINT32 p_tx0, + OPJ_UINT32 p_tx1, + OPJ_UINT32 p_ty0, + OPJ_UINT32 p_ty1, + OPJ_UINT32 p_max_prec, + OPJ_UINT32 p_max_res, + OPJ_UINT32 p_dx_min, + OPJ_UINT32 p_dy_min) +{ + /* loop*/ + OPJ_UINT32 pino; + /* tile coding parameter*/ + opj_tcp_t *l_tcp = 00; + /* current poc being updated*/ + opj_poc_t * l_current_poc = 00; + /* number of pocs*/ + OPJ_UINT32 l_poc_bound; + + /* preconditions in debug*/ + assert(p_cp != 00); + assert(p_tileno < p_cp->tw * p_cp->th); + + /* initializations*/ + l_tcp = &p_cp->tcps [p_tileno]; + + /* number of iterations in the loop */ + l_poc_bound = l_tcp->numpocs + 1; + + /* start at first element, and to make sure the compiler will not make a calculation each time in the loop + store a pointer to the current element to modify rather than l_tcp->pocs[i]*/ + l_current_poc = l_tcp->pocs; + + for (pino = 0; pino < l_poc_bound ; ++pino) { + l_current_poc->compS = 0; + l_current_poc->compE = p_num_comps;/*p_image->numcomps;*/ + l_current_poc->resS = 0; + l_current_poc->resE = p_max_res; + l_current_poc->layS = 0; + l_current_poc->layE = l_tcp->numlayers; + l_current_poc->prg = l_tcp->prg; + l_current_poc->prcS = 0; + l_current_poc->prcE = p_max_prec; + l_current_poc->txS = p_tx0; + l_current_poc->txE = p_tx1; + l_current_poc->tyS = p_ty0; + l_current_poc->tyE = p_ty1; + l_current_poc->dx = p_dx_min; + l_current_poc->dy = p_dy_min; + ++ l_current_poc; + } +} + +static void opj_pi_update_decode_poc(opj_pi_iterator_t * p_pi, + opj_tcp_t * p_tcp, + OPJ_UINT32 p_max_precision, + OPJ_UINT32 p_max_res) +{ + /* loop*/ + OPJ_UINT32 pino; + + /* encoding parameters to set*/ + OPJ_UINT32 l_bound; + + opj_pi_iterator_t * l_current_pi = 00; + opj_poc_t* l_current_poc = 0; + + OPJ_ARG_NOT_USED(p_max_res); + + /* preconditions in debug*/ + assert(p_pi != 00); + assert(p_tcp != 00); + + /* initializations*/ + l_bound = p_tcp->numpocs + 1; + l_current_pi = p_pi; + l_current_poc = p_tcp->pocs; + + for (pino = 0; pino < l_bound; ++pino) { + l_current_pi->poc.prg = l_current_poc->prg; /* Progression Order #0 */ + l_current_pi->first = 1; + + l_current_pi->poc.resno0 = + l_current_poc->resno0; /* Resolution Level Index #0 (Start) */ + l_current_pi->poc.compno0 = + l_current_poc->compno0; /* Component Index #0 (Start) */ + l_current_pi->poc.layno0 = 0; + l_current_pi->poc.precno0 = 0; + l_current_pi->poc.resno1 = + l_current_poc->resno1; /* Resolution Level Index #0 (End) */ + l_current_pi->poc.compno1 = + l_current_poc->compno1; /* Component Index #0 (End) */ + l_current_pi->poc.layno1 = opj_uint_min(l_current_poc->layno1, + p_tcp->numlayers); /* Layer Index #0 (End) */ + l_current_pi->poc.precno1 = p_max_precision; + ++l_current_pi; + ++l_current_poc; + } +} + +static void opj_pi_update_decode_not_poc(opj_pi_iterator_t * p_pi, + opj_tcp_t * p_tcp, + OPJ_UINT32 p_max_precision, + OPJ_UINT32 p_max_res) +{ + /* loop*/ + OPJ_UINT32 pino; + + /* encoding parameters to set*/ + OPJ_UINT32 l_bound; + + opj_pi_iterator_t * l_current_pi = 00; + /* preconditions in debug*/ + assert(p_tcp != 00); + assert(p_pi != 00); + + /* initializations*/ + l_bound = p_tcp->numpocs + 1; + l_current_pi = p_pi; + + for (pino = 0; pino < l_bound; ++pino) { + l_current_pi->poc.prg = p_tcp->prg; + l_current_pi->first = 1; + l_current_pi->poc.resno0 = 0; + l_current_pi->poc.compno0 = 0; + l_current_pi->poc.layno0 = 0; + l_current_pi->poc.precno0 = 0; + l_current_pi->poc.resno1 = p_max_res; + l_current_pi->poc.compno1 = l_current_pi->numcomps; + l_current_pi->poc.layno1 = p_tcp->numlayers; + l_current_pi->poc.precno1 = p_max_precision; + ++l_current_pi; + } +} + + + +static OPJ_BOOL opj_pi_check_next_level(OPJ_INT32 pos, + opj_cp_t *cp, + OPJ_UINT32 tileno, + OPJ_UINT32 pino, + const OPJ_CHAR *prog) +{ + OPJ_INT32 i; + opj_tcp_t *tcps = &cp->tcps[tileno]; + opj_poc_t *tcp = &tcps->pocs[pino]; + + if (pos >= 0) { + for (i = pos; i >= 0; i--) { + switch (prog[i]) { + case 'R': + if (tcp->res_t == tcp->resE) { + if (opj_pi_check_next_level(pos - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + } + break; + case 'C': + if (tcp->comp_t == tcp->compE) { + if (opj_pi_check_next_level(pos - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + } + break; + case 'L': + if (tcp->lay_t == tcp->layE) { + if (opj_pi_check_next_level(pos - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + } + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: /* fall through */ + case OPJ_RLCP: + if (tcp->prc_t == tcp->prcE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + } + break; + default: + if (tcp->tx0_t == tcp->txE) { + /*TY*/ + if (tcp->ty0_t == tcp->tyE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + return OPJ_TRUE; + } else { + return OPJ_FALSE; + } + } else { + return OPJ_TRUE; + }/*TY*/ + } else { + return OPJ_TRUE; + } + break; + }/*end case P*/ + }/*end switch*/ + }/*end for*/ + }/*end if*/ + return OPJ_FALSE; +} + + +/* +========================================================== + Packet iterator interface +========================================================== +*/ +opj_pi_iterator_t *opj_pi_create_decode(opj_image_t *p_image, + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no, + opj_event_mgr_t* manager) +{ + OPJ_UINT32 numcomps = p_image->numcomps; + + /* loop */ + OPJ_UINT32 pino; + OPJ_UINT32 compno, resno; + + /* to store w, h, dx and dy for all components and resolutions */ + OPJ_UINT32 * l_tmp_data; + OPJ_UINT32 ** l_tmp_ptr; + + /* encoding parameters to set */ + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_UINT32 l_tx0, l_tx1, l_ty0, l_ty1; + OPJ_UINT32 l_dx_min, l_dy_min; + OPJ_UINT32 l_bound; + OPJ_UINT32 l_step_p, l_step_c, l_step_r, l_step_l ; + OPJ_UINT32 l_data_stride; + + /* pointers */ + opj_pi_iterator_t *l_pi = 00; + opj_tcp_t *l_tcp = 00; + const opj_tccp_t *l_tccp = 00; + opj_pi_comp_t *l_current_comp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_pi_iterator_t * l_current_pi = 00; + OPJ_UINT32 * l_encoding_value_ptr = 00; + + /* preconditions in debug */ + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + /* initializations */ + l_tcp = &p_cp->tcps[p_tile_no]; + l_bound = l_tcp->numpocs + 1; + + l_data_stride = 4 * OPJ_J2K_MAXRLVLS; + l_tmp_data = (OPJ_UINT32*)opj_malloc( + l_data_stride * numcomps * sizeof(OPJ_UINT32)); + if + (! l_tmp_data) { + return 00; + } + l_tmp_ptr = (OPJ_UINT32**)opj_malloc( + numcomps * sizeof(OPJ_UINT32 *)); + if + (! l_tmp_ptr) { + opj_free(l_tmp_data); + return 00; + } + + /* memory allocation for pi */ + l_pi = opj_pi_create(p_image, p_cp, p_tile_no, manager); + if (!l_pi) { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + return 00; + } + + l_encoding_value_ptr = l_tmp_data; + /* update pointer array */ + for + (compno = 0; compno < numcomps; ++compno) { + l_tmp_ptr[compno] = l_encoding_value_ptr; + l_encoding_value_ptr += l_data_stride; + } + /* get encoding parameters */ + opj_get_all_encoding_parameters(p_image, p_cp, p_tile_no, &l_tx0, &l_tx1, + &l_ty0, &l_ty1, &l_dx_min, &l_dy_min, &l_max_prec, &l_max_res, l_tmp_ptr); + + /* step calculations */ + l_step_p = 1; + l_step_c = l_max_prec * l_step_p; + l_step_r = numcomps * l_step_c; + l_step_l = l_max_res * l_step_r; + + /* set values for first packet iterator */ + l_current_pi = l_pi; + + /* memory allocation for include */ + /* prevent an integer overflow issue */ + /* 0 < l_tcp->numlayers < 65536 c.f. opj_j2k_read_cod in j2k.c */ + l_current_pi->include = 00; + if (l_step_l <= (UINT_MAX / (l_tcp->numlayers + 1U))) { + l_current_pi->include_size = (l_tcp->numlayers + 1U) * l_step_l; + l_current_pi->include = (OPJ_INT16*) opj_calloc( + l_current_pi->include_size, sizeof(OPJ_INT16)); + } + + if (!l_current_pi->include) { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + opj_pi_destroy(l_pi, l_bound); + return 00; + } + + /* special treatment for the first packet iterator */ + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + + /*l_current_pi->dx = l_img_comp->dx;*/ + /*l_current_pi->dy = l_img_comp->dy;*/ + + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by opj_pi_create */ + for + (compno = 0; compno < numcomps; ++compno) { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for + (resno = 0; resno < l_current_comp->numresolutions; resno++) { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + ++l_current_pi; + + for (pino = 1 ; pino < l_bound ; ++pino) { + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + /*l_current_pi->dx = l_dx_min;*/ + /*l_current_pi->dy = l_dy_min;*/ + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by opj_pi_create */ + for + (compno = 0; compno < numcomps; ++compno) { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for + (resno = 0; resno < l_current_comp->numresolutions; resno++) { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + /* special treatment*/ + l_current_pi->include = (l_current_pi - 1)->include; + l_current_pi->include_size = (l_current_pi - 1)->include_size; + ++l_current_pi; + } + opj_free(l_tmp_data); + l_tmp_data = 00; + opj_free(l_tmp_ptr); + l_tmp_ptr = 00; + if + (l_tcp->POC) { + opj_pi_update_decode_poc(l_pi, l_tcp, l_max_prec, l_max_res); + } else { + opj_pi_update_decode_not_poc(l_pi, l_tcp, l_max_prec, l_max_res); + } + return l_pi; +} + + +OPJ_UINT32 opj_get_encoding_packet_count(const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no) +{ + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_UINT32 l_tx0, l_tx1, l_ty0, l_ty1; + OPJ_UINT32 l_dx_min, l_dy_min; + + /* preconditions in debug*/ + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + /* get encoding parameters*/ + opj_get_all_encoding_parameters(p_image, p_cp, p_tile_no, &l_tx0, &l_tx1, + &l_ty0, &l_ty1, &l_dx_min, &l_dy_min, &l_max_prec, &l_max_res, NULL); + + return p_cp->tcps[p_tile_no].numlayers * l_max_prec * p_image->numcomps * + l_max_res; +} + + +opj_pi_iterator_t *opj_pi_initialise_encode(const opj_image_t *p_image, + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no, + J2K_T2_MODE p_t2_mode, + opj_event_mgr_t* manager) +{ + OPJ_UINT32 numcomps = p_image->numcomps; + + /* loop*/ + OPJ_UINT32 pino; + OPJ_UINT32 compno, resno; + + /* to store w, h, dx and dy for all components and resolutions*/ + OPJ_UINT32 * l_tmp_data; + OPJ_UINT32 ** l_tmp_ptr; + + /* encoding parameters to set*/ + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_UINT32 l_tx0, l_tx1, l_ty0, l_ty1; + OPJ_UINT32 l_dx_min, l_dy_min; + OPJ_UINT32 l_bound; + OPJ_UINT32 l_step_p, l_step_c, l_step_r, l_step_l ; + OPJ_UINT32 l_data_stride; + + /* pointers*/ + opj_pi_iterator_t *l_pi = 00; + opj_tcp_t *l_tcp = 00; + const opj_tccp_t *l_tccp = 00; + opj_pi_comp_t *l_current_comp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_pi_iterator_t * l_current_pi = 00; + OPJ_UINT32 * l_encoding_value_ptr = 00; + + /* preconditions in debug*/ + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + /* initializations*/ + l_tcp = &p_cp->tcps[p_tile_no]; + l_bound = l_tcp->numpocs + 1; + + l_data_stride = 4 * OPJ_J2K_MAXRLVLS; + l_tmp_data = (OPJ_UINT32*)opj_malloc( + l_data_stride * numcomps * sizeof(OPJ_UINT32)); + if (! l_tmp_data) { + return 00; + } + + l_tmp_ptr = (OPJ_UINT32**)opj_malloc( + numcomps * sizeof(OPJ_UINT32 *)); + if (! l_tmp_ptr) { + opj_free(l_tmp_data); + return 00; + } + + /* memory allocation for pi*/ + l_pi = opj_pi_create(p_image, p_cp, p_tile_no, manager); + if (!l_pi) { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + return 00; + } + + l_encoding_value_ptr = l_tmp_data; + /* update pointer array*/ + for (compno = 0; compno < numcomps; ++compno) { + l_tmp_ptr[compno] = l_encoding_value_ptr; + l_encoding_value_ptr += l_data_stride; + } + + /* get encoding parameters*/ + opj_get_all_encoding_parameters(p_image, p_cp, p_tile_no, &l_tx0, &l_tx1, + &l_ty0, &l_ty1, &l_dx_min, &l_dy_min, &l_max_prec, &l_max_res, l_tmp_ptr); + + /* step calculations*/ + l_step_p = 1; + l_step_c = l_max_prec * l_step_p; + l_step_r = numcomps * l_step_c; + l_step_l = l_max_res * l_step_r; + + /* set values for first packet iterator*/ + l_pi->tp_on = (OPJ_BYTE)p_cp->m_specific_param.m_enc.m_tp_on; + l_current_pi = l_pi; + + /* memory allocation for include*/ + l_current_pi->include_size = l_tcp->numlayers * l_step_l; + l_current_pi->include = (OPJ_INT16*) opj_calloc(l_current_pi->include_size, + sizeof(OPJ_INT16)); + if (!l_current_pi->include) { + opj_free(l_tmp_data); + opj_free(l_tmp_ptr); + opj_pi_destroy(l_pi, l_bound); + return 00; + } + + /* special treatment for the first packet iterator*/ + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + l_current_pi->dx = l_dx_min; + l_current_pi->dy = l_dy_min; + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by opj_pi_create */ + for (compno = 0; compno < numcomps; ++compno) { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + + /* resolutions have already been initialized */ + for (resno = 0; resno < l_current_comp->numresolutions; resno++) { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + ++l_current_pi; + + for (pino = 1 ; pino < l_bound ; ++pino) { + l_current_comp = l_current_pi->comps; + l_img_comp = p_image->comps; + l_tccp = l_tcp->tccps; + + l_current_pi->tx0 = l_tx0; + l_current_pi->ty0 = l_ty0; + l_current_pi->tx1 = l_tx1; + l_current_pi->ty1 = l_ty1; + l_current_pi->dx = l_dx_min; + l_current_pi->dy = l_dy_min; + l_current_pi->step_p = l_step_p; + l_current_pi->step_c = l_step_c; + l_current_pi->step_r = l_step_r; + l_current_pi->step_l = l_step_l; + + /* allocation for components and number of components has already been calculated by opj_pi_create */ + for (compno = 0; compno < numcomps; ++compno) { + opj_pi_resolution_t *l_res = l_current_comp->resolutions; + l_encoding_value_ptr = l_tmp_ptr[compno]; + + l_current_comp->dx = l_img_comp->dx; + l_current_comp->dy = l_img_comp->dy; + /* resolutions have already been initialized */ + for (resno = 0; resno < l_current_comp->numresolutions; resno++) { + l_res->pdx = *(l_encoding_value_ptr++); + l_res->pdy = *(l_encoding_value_ptr++); + l_res->pw = *(l_encoding_value_ptr++); + l_res->ph = *(l_encoding_value_ptr++); + ++l_res; + } + ++l_current_comp; + ++l_img_comp; + ++l_tccp; + } + + /* special treatment*/ + l_current_pi->include = (l_current_pi - 1)->include; + l_current_pi->include_size = (l_current_pi - 1)->include_size; + ++l_current_pi; + } + + opj_free(l_tmp_data); + l_tmp_data = 00; + opj_free(l_tmp_ptr); + l_tmp_ptr = 00; + + if (l_tcp->POC && (OPJ_IS_CINEMA(p_cp->rsiz) || p_t2_mode == FINAL_PASS)) { + opj_pi_update_encode_poc_and_final(p_cp, p_tile_no, l_tx0, l_tx1, l_ty0, l_ty1, + l_max_prec, l_max_res, l_dx_min, l_dy_min); + } else { + opj_pi_update_encode_not_poc(p_cp, numcomps, p_tile_no, l_tx0, l_tx1, + l_ty0, l_ty1, l_max_prec, l_max_res, l_dx_min, l_dy_min); + } + + return l_pi; +} + +void opj_pi_create_encode(opj_pi_iterator_t *pi, + opj_cp_t *cp, + OPJ_UINT32 tileno, + OPJ_UINT32 pino, + OPJ_UINT32 tpnum, + OPJ_INT32 tppos, + J2K_T2_MODE t2_mode) +{ + const OPJ_CHAR *prog; + OPJ_INT32 i; + OPJ_UINT32 incr_top = 1, resetX = 0; + opj_tcp_t *tcps = &cp->tcps[tileno]; + opj_poc_t *tcp = &tcps->pocs[pino]; + + prog = opj_j2k_convert_progression_order(tcp->prg); + + pi[pino].first = 1; + pi[pino].poc.prg = tcp->prg; + + if (!(cp->m_specific_param.m_enc.m_tp_on && ((!OPJ_IS_CINEMA(cp->rsiz) && + !OPJ_IS_IMF(cp->rsiz) && + (t2_mode == FINAL_PASS)) || OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)))) { + pi[pino].poc.resno0 = tcp->resS; + pi[pino].poc.resno1 = tcp->resE; + pi[pino].poc.compno0 = tcp->compS; + pi[pino].poc.compno1 = tcp->compE; + pi[pino].poc.layno0 = tcp->layS; + pi[pino].poc.layno1 = tcp->layE; + pi[pino].poc.precno0 = tcp->prcS; + pi[pino].poc.precno1 = tcp->prcE; + pi[pino].poc.tx0 = tcp->txS; + pi[pino].poc.ty0 = tcp->tyS; + pi[pino].poc.tx1 = tcp->txE; + pi[pino].poc.ty1 = tcp->tyE; + } else { + for (i = tppos + 1; i < 4; i++) { + switch (prog[i]) { + case 'R': + pi[pino].poc.resno0 = tcp->resS; + pi[pino].poc.resno1 = tcp->resE; + break; + case 'C': + pi[pino].poc.compno0 = tcp->compS; + pi[pino].poc.compno1 = tcp->compE; + break; + case 'L': + pi[pino].poc.layno0 = tcp->layS; + pi[pino].poc.layno1 = tcp->layE; + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: + case OPJ_RLCP: + pi[pino].poc.precno0 = tcp->prcS; + pi[pino].poc.precno1 = tcp->prcE; + break; + default: + pi[pino].poc.tx0 = tcp->txS; + pi[pino].poc.ty0 = tcp->tyS; + pi[pino].poc.tx1 = tcp->txE; + pi[pino].poc.ty1 = tcp->tyE; + break; + } + break; + } + } + + if (tpnum == 0) { + for (i = tppos; i >= 0; i--) { + switch (prog[i]) { + case 'C': + tcp->comp_t = tcp->compS; + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t + 1; + tcp->comp_t += 1; + break; + case 'R': + tcp->res_t = tcp->resS; + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t + 1; + tcp->res_t += 1; + break; + case 'L': + tcp->lay_t = tcp->layS; + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t + 1; + tcp->lay_t += 1; + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: + case OPJ_RLCP: + tcp->prc_t = tcp->prcS; + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t + 1; + tcp->prc_t += 1; + break; + default: + tcp->tx0_t = tcp->txS; + tcp->ty0_t = tcp->tyS; + pi[pino].poc.tx0 = tcp->tx0_t; + pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx); + pi[pino].poc.ty0 = tcp->ty0_t; + pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy); + tcp->tx0_t = (OPJ_UINT32)pi[pino].poc.tx1; + tcp->ty0_t = (OPJ_UINT32)pi[pino].poc.ty1; + break; + } + break; + } + } + incr_top = 1; + } else { + for (i = tppos; i >= 0; i--) { + switch (prog[i]) { + case 'C': + pi[pino].poc.compno0 = tcp->comp_t - 1; + pi[pino].poc.compno1 = tcp->comp_t; + break; + case 'R': + pi[pino].poc.resno0 = tcp->res_t - 1; + pi[pino].poc.resno1 = tcp->res_t; + break; + case 'L': + pi[pino].poc.layno0 = tcp->lay_t - 1; + pi[pino].poc.layno1 = tcp->lay_t; + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: + case OPJ_RLCP: + pi[pino].poc.precno0 = tcp->prc_t - 1; + pi[pino].poc.precno1 = tcp->prc_t; + break; + default: + pi[pino].poc.tx0 = tcp->tx0_t - tcp->dx - (tcp->tx0_t % tcp->dx); + pi[pino].poc.tx1 = tcp->tx0_t ; + pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy); + pi[pino].poc.ty1 = tcp->ty0_t ; + break; + } + break; + } + if (incr_top == 1) { + switch (prog[i]) { + case 'R': + if (tcp->res_t == tcp->resE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->res_t = tcp->resS; + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t + 1; + tcp->res_t += 1; + incr_top = 1; + } else { + incr_top = 0; + } + } else { + pi[pino].poc.resno0 = tcp->res_t; + pi[pino].poc.resno1 = tcp->res_t + 1; + tcp->res_t += 1; + incr_top = 0; + } + break; + case 'C': + if (tcp->comp_t == tcp->compE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->comp_t = tcp->compS; + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t + 1; + tcp->comp_t += 1; + incr_top = 1; + } else { + incr_top = 0; + } + } else { + pi[pino].poc.compno0 = tcp->comp_t; + pi[pino].poc.compno1 = tcp->comp_t + 1; + tcp->comp_t += 1; + incr_top = 0; + } + break; + case 'L': + if (tcp->lay_t == tcp->layE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->lay_t = tcp->layS; + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t + 1; + tcp->lay_t += 1; + incr_top = 1; + } else { + incr_top = 0; + } + } else { + pi[pino].poc.layno0 = tcp->lay_t; + pi[pino].poc.layno1 = tcp->lay_t + 1; + tcp->lay_t += 1; + incr_top = 0; + } + break; + case 'P': + switch (tcp->prg) { + case OPJ_LRCP: + case OPJ_RLCP: + if (tcp->prc_t == tcp->prcE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->prc_t = tcp->prcS; + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t + 1; + tcp->prc_t += 1; + incr_top = 1; + } else { + incr_top = 0; + } + } else { + pi[pino].poc.precno0 = tcp->prc_t; + pi[pino].poc.precno1 = tcp->prc_t + 1; + tcp->prc_t += 1; + incr_top = 0; + } + break; + default: + if (tcp->tx0_t >= tcp->txE) { + if (tcp->ty0_t >= tcp->tyE) { + if (opj_pi_check_next_level(i - 1, cp, tileno, pino, prog)) { + tcp->ty0_t = tcp->tyS; + pi[pino].poc.ty0 = tcp->ty0_t; + pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy); + tcp->ty0_t = (OPJ_UINT32)pi[pino].poc.ty1; + incr_top = 1; + resetX = 1; + } else { + incr_top = 0; + resetX = 0; + } + } else { + pi[pino].poc.ty0 = tcp->ty0_t; + pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy); + tcp->ty0_t = (OPJ_UINT32)pi[pino].poc.ty1; + incr_top = 0; + resetX = 1; + } + if (resetX == 1) { + tcp->tx0_t = tcp->txS; + pi[pino].poc.tx0 = tcp->tx0_t; + pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx); + tcp->tx0_t = (OPJ_UINT32)pi[pino].poc.tx1; + } + } else { + pi[pino].poc.tx0 = tcp->tx0_t; + pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx); + tcp->tx0_t = (OPJ_UINT32)pi[pino].poc.tx1; + incr_top = 0; + } + break; + } + break; + } + } + } + } + } +} + +void opj_pi_destroy(opj_pi_iterator_t *p_pi, + OPJ_UINT32 p_nb_elements) +{ + OPJ_UINT32 compno, pino; + opj_pi_iterator_t *l_current_pi = p_pi; + if (p_pi) { + if (p_pi->include) { + opj_free(p_pi->include); + p_pi->include = 00; + } + for (pino = 0; pino < p_nb_elements; ++pino) { + if (l_current_pi->comps) { + opj_pi_comp_t *l_current_component = l_current_pi->comps; + for (compno = 0; compno < l_current_pi->numcomps; compno++) { + if (l_current_component->resolutions) { + opj_free(l_current_component->resolutions); + l_current_component->resolutions = 00; + } + + ++l_current_component; + } + opj_free(l_current_pi->comps); + l_current_pi->comps = 0; + } + ++l_current_pi; + } + opj_free(p_pi); + } +} + + + +void opj_pi_update_encoding_parameters(const opj_image_t *p_image, + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no) +{ + /* encoding parameters to set */ + OPJ_UINT32 l_max_res; + OPJ_UINT32 l_max_prec; + OPJ_UINT32 l_tx0, l_tx1, l_ty0, l_ty1; + OPJ_UINT32 l_dx_min, l_dy_min; + + /* pointers */ + opj_tcp_t *l_tcp = 00; + + /* preconditions */ + assert(p_cp != 00); + assert(p_image != 00); + assert(p_tile_no < p_cp->tw * p_cp->th); + + l_tcp = &(p_cp->tcps[p_tile_no]); + + /* get encoding parameters */ + opj_get_encoding_parameters(p_image, p_cp, p_tile_no, &l_tx0, &l_tx1, &l_ty0, + &l_ty1, &l_dx_min, &l_dy_min, &l_max_prec, &l_max_res); + + if (l_tcp->POC) { + opj_pi_update_encode_poc_and_final(p_cp, p_tile_no, l_tx0, l_tx1, l_ty0, l_ty1, + l_max_prec, l_max_res, l_dx_min, l_dy_min); + } else { + opj_pi_update_encode_not_poc(p_cp, p_image->numcomps, p_tile_no, l_tx0, l_tx1, + l_ty0, l_ty1, l_max_prec, l_max_res, l_dx_min, l_dy_min); + } +} + +OPJ_BOOL opj_pi_next(opj_pi_iterator_t * pi) +{ + switch (pi->poc.prg) { + case OPJ_LRCP: + return opj_pi_next_lrcp(pi); + case OPJ_RLCP: + return opj_pi_next_rlcp(pi); + case OPJ_RPCL: + return opj_pi_next_rpcl(pi); + case OPJ_PCRL: + return opj_pi_next_pcrl(pi); + case OPJ_CPRL: + return opj_pi_next_cprl(pi); + case OPJ_PROG_UNKNOWN: + return OPJ_FALSE; + } + + return OPJ_FALSE; +} diff --git a/client/deps/openjpeg/pi.h b/client/deps/openjpeg/pi.h new file mode 100644 index 000000000..0320523b7 --- /dev/null +++ b/client/deps/openjpeg/pi.h @@ -0,0 +1,207 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_PI_H +#define OPJ_PI_H +/** +@file pi.h +@brief Implementation of a packet iterator (PI) + +The functions in PI.C have for goal to realize a packet iterator that permits to get the next +packet following the progression order and change of it. The functions in PI.C are used +by some function in T2.C. +*/ + +/** @defgroup PI PI - Implementation of a packet iterator */ +/*@{*/ + +/** +FIXME DOC +*/ +typedef struct opj_pi_resolution { + OPJ_UINT32 pdx, pdy; + OPJ_UINT32 pw, ph; +} opj_pi_resolution_t; + +/** +FIXME DOC +*/ +typedef struct opj_pi_comp { + OPJ_UINT32 dx, dy; + /** number of resolution levels */ + OPJ_UINT32 numresolutions; + opj_pi_resolution_t *resolutions; +} opj_pi_comp_t; + +/** +Packet iterator +*/ +typedef struct opj_pi_iterator { + /** Enabling Tile part generation*/ + OPJ_BYTE tp_on; + /** precise if the packet has been already used (useful for progression order change) */ + OPJ_INT16 *include; + /** Number of elements in include array */ + OPJ_UINT32 include_size; + /** layer step used to localize the packet in the include vector */ + OPJ_UINT32 step_l; + /** resolution step used to localize the packet in the include vector */ + OPJ_UINT32 step_r; + /** component step used to localize the packet in the include vector */ + OPJ_UINT32 step_c; + /** precinct step used to localize the packet in the include vector */ + OPJ_UINT32 step_p; + /** component that identify the packet */ + OPJ_UINT32 compno; + /** resolution that identify the packet */ + OPJ_UINT32 resno; + /** precinct that identify the packet */ + OPJ_UINT32 precno; + /** layer that identify the packet */ + OPJ_UINT32 layno; + /** 0 if the first packet */ + OPJ_BOOL first; + /** progression order change information */ + opj_poc_t poc; + /** number of components in the image */ + OPJ_UINT32 numcomps; + /** Components*/ + opj_pi_comp_t *comps; + /** FIXME DOC*/ + OPJ_UINT32 tx0, ty0, tx1, ty1; + /** FIXME DOC*/ + OPJ_UINT32 x, y; + /** FIXME DOC*/ + OPJ_UINT32 dx, dy; + /** event manager */ + opj_event_mgr_t* manager; +} opj_pi_iterator_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** + * Creates a packet iterator for encoding. + * + * @param image the image being encoded. + * @param cp the coding parameters. + * @param tileno index of the tile being encoded. + * @param t2_mode the type of pass for generating the packet iterator + * @param manager Event manager + * + * @return a list of packet iterator that points to the first packet of the tile (not true). +*/ +opj_pi_iterator_t *opj_pi_initialise_encode(const opj_image_t *image, + opj_cp_t *cp, + OPJ_UINT32 tileno, + J2K_T2_MODE t2_mode, + opj_event_mgr_t* manager); + +/** + * Updates the encoding parameters of the codec. + * + * @param p_image the image being encoded. + * @param p_cp the coding parameters. + * @param p_tile_no index of the tile being encoded. +*/ +void opj_pi_update_encoding_parameters(const opj_image_t *p_image, + opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no); + +/** +Modify the packet iterator for enabling tile part generation +@param pi Handle to the packet iterator generated in pi_initialise_encode +@param cp Coding parameters +@param tileno Number that identifies the tile for which to list the packets +@param pino FIXME DOC +@param tpnum Tile part number of the current tile +@param tppos The position of the tile part flag in the progression order +@param t2_mode FIXME DOC +*/ +void opj_pi_create_encode(opj_pi_iterator_t *pi, + opj_cp_t *cp, + OPJ_UINT32 tileno, + OPJ_UINT32 pino, + OPJ_UINT32 tpnum, + OPJ_INT32 tppos, + J2K_T2_MODE t2_mode); + +/** +Create a packet iterator for Decoder +@param image Raw image for which the packets will be listed +@param cp Coding parameters +@param tileno Number that identifies the tile for which to list the packets +@param manager Event manager +@return Returns a packet iterator that points to the first packet of the tile +@see opj_pi_destroy +*/ +opj_pi_iterator_t *opj_pi_create_decode(opj_image_t * image, + opj_cp_t * cp, + OPJ_UINT32 tileno, + opj_event_mgr_t* manager); +/** + * Destroys a packet iterator array. + * + * @param p_pi the packet iterator array to destroy. + * @param p_nb_elements the number of elements in the array. + */ +void opj_pi_destroy(opj_pi_iterator_t *p_pi, + OPJ_UINT32 p_nb_elements); + +/** +Modify the packet iterator to point to the next packet +@param pi Packet iterator to modify +@return Returns false if pi pointed to the last packet or else returns true +*/ +OPJ_BOOL opj_pi_next(opj_pi_iterator_t * pi); + +/** + * Return the number of packets in the tile. + * @param image the image being encoded. + * @param cp Coding parameters + * @param tileno Number that identifies the tile. + */ +OPJ_UINT32 opj_get_encoding_packet_count(const opj_image_t *p_image, + const opj_cp_t *p_cp, + OPJ_UINT32 p_tile_no); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_PI_H */ diff --git a/client/deps/openjpeg/sparse_array.c b/client/deps/openjpeg/sparse_array.c new file mode 100644 index 000000000..50d1a9041 --- /dev/null +++ b/client/deps/openjpeg/sparse_array.c @@ -0,0 +1,346 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2017, IntoPix SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + + +struct opj_sparse_array_int32 { + OPJ_UINT32 width; + OPJ_UINT32 height; + OPJ_UINT32 block_width; + OPJ_UINT32 block_height; + OPJ_UINT32 block_count_hor; + OPJ_UINT32 block_count_ver; + OPJ_INT32** data_blocks; +}; + +opj_sparse_array_int32_t* opj_sparse_array_int32_create(OPJ_UINT32 width, + OPJ_UINT32 height, + OPJ_UINT32 block_width, + OPJ_UINT32 block_height) +{ + opj_sparse_array_int32_t* sa; + + if (width == 0 || height == 0 || block_width == 0 || block_height == 0) { + return NULL; + } + if (block_width > ((OPJ_UINT32)~0U) / block_height / sizeof(OPJ_INT32)) { + return NULL; + } + + sa = (opj_sparse_array_int32_t*) opj_calloc(1, + sizeof(opj_sparse_array_int32_t)); + sa->width = width; + sa->height = height; + sa->block_width = block_width; + sa->block_height = block_height; + sa->block_count_hor = opj_uint_ceildiv(width, block_width); + sa->block_count_ver = opj_uint_ceildiv(height, block_height); + if (sa->block_count_hor > ((OPJ_UINT32)~0U) / sa->block_count_ver) { + opj_free(sa); + return NULL; + } + sa->data_blocks = (OPJ_INT32**) opj_calloc(sizeof(OPJ_INT32*), + (size_t) sa->block_count_hor * sa->block_count_ver); + if (sa->data_blocks == NULL) { + opj_free(sa); + return NULL; + } + + return sa; +} + +void opj_sparse_array_int32_free(opj_sparse_array_int32_t* sa) +{ + if (sa) { + OPJ_UINT32 i; + for (i = 0; i < sa->block_count_hor * sa->block_count_ver; i++) { + if (sa->data_blocks[i]) { + opj_free(sa->data_blocks[i]); + } + } + opj_free(sa->data_blocks); + opj_free(sa); + } +} + +OPJ_BOOL opj_sparse_array_is_region_valid(const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1) +{ + return !(x0 >= sa->width || x1 <= x0 || x1 > sa->width || + y0 >= sa->height || y1 <= y0 || y1 > sa->height); +} + +static OPJ_BOOL opj_sparse_array_int32_read_or_write( + const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + OPJ_INT32* buf, + OPJ_UINT32 buf_col_stride, + OPJ_UINT32 buf_line_stride, + OPJ_BOOL forgiving, + OPJ_BOOL is_read_op) +{ + OPJ_UINT32 y, block_y; + OPJ_UINT32 y_incr = 0; + const OPJ_UINT32 block_width = sa->block_width; + + if (!opj_sparse_array_is_region_valid(sa, x0, y0, x1, y1)) { + return forgiving; + } + + block_y = y0 / sa->block_height; + for (y = y0; y < y1; block_y ++, y += y_incr) { + OPJ_UINT32 x, block_x; + OPJ_UINT32 x_incr = 0; + OPJ_UINT32 block_y_offset; + y_incr = (y == y0) ? sa->block_height - (y0 % sa->block_height) : + sa->block_height; + block_y_offset = sa->block_height - y_incr; + y_incr = opj_uint_min(y_incr, y1 - y); + block_x = x0 / block_width; + for (x = x0; x < x1; block_x ++, x += x_incr) { + OPJ_UINT32 j; + OPJ_UINT32 block_x_offset; + OPJ_INT32* src_block; + x_incr = (x == x0) ? block_width - (x0 % block_width) : block_width; + block_x_offset = block_width - x_incr; + x_incr = opj_uint_min(x_incr, x1 - x); + src_block = sa->data_blocks[block_y * sa->block_count_hor + block_x]; + if (is_read_op) { + if (src_block == NULL) { + if (buf_col_stride == 1) { + OPJ_INT32* dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride + + (x - x0) * buf_col_stride; + for (j = 0; j < y_incr; j++) { + memset(dest_ptr, 0, sizeof(OPJ_INT32) * x_incr); + dest_ptr += buf_line_stride; + } + } else { + OPJ_INT32* dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride + + (x - x0) * buf_col_stride; + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < x_incr; k++) { + dest_ptr[k * buf_col_stride] = 0; + } + dest_ptr += buf_line_stride; + } + } + } else { + const OPJ_INT32* OPJ_RESTRICT src_ptr = src_block + block_y_offset * + (OPJ_SIZE_T)block_width + block_x_offset; + if (buf_col_stride == 1) { + OPJ_INT32* OPJ_RESTRICT dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride + + + (x - x0) * buf_col_stride; + if (x_incr == 4) { + /* Same code as general branch, but the compiler */ + /* can have an efficient memcpy() */ + (void)(x_incr); /* trick to silent cppcheck duplicateBranch warning */ + for (j = 0; j < y_incr; j++) { + memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr); + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } else { + for (j = 0; j < y_incr; j++) { + memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr); + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } + } else { + OPJ_INT32* OPJ_RESTRICT dest_ptr = buf + (y - y0) * (OPJ_SIZE_T)buf_line_stride + + + (x - x0) * buf_col_stride; + if (x_incr == 1) { + for (j = 0; j < y_incr; j++) { + *dest_ptr = *src_ptr; + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } else if (y_incr == 1 && buf_col_stride == 2) { + OPJ_UINT32 k; + for (k = 0; k < (x_incr & ~3U); k += 4) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + dest_ptr[(k + 1) * buf_col_stride] = src_ptr[k + 1]; + dest_ptr[(k + 2) * buf_col_stride] = src_ptr[k + 2]; + dest_ptr[(k + 3) * buf_col_stride] = src_ptr[k + 3]; + } + for (; k < x_incr; k++) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + } + } else if (x_incr >= 8 && buf_col_stride == 8) { + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < (x_incr & ~3U); k += 4) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + dest_ptr[(k + 1) * buf_col_stride] = src_ptr[k + 1]; + dest_ptr[(k + 2) * buf_col_stride] = src_ptr[k + 2]; + dest_ptr[(k + 3) * buf_col_stride] = src_ptr[k + 3]; + } + for (; k < x_incr; k++) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + } + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } else { + /* General case */ + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < x_incr; k++) { + dest_ptr[k * buf_col_stride] = src_ptr[k]; + } + dest_ptr += buf_line_stride; + src_ptr += block_width; + } + } + } + } + } else { + if (src_block == NULL) { + src_block = (OPJ_INT32*) opj_calloc(1, + (size_t) sa->block_width * sa->block_height * sizeof(OPJ_INT32)); + if (src_block == NULL) { + return OPJ_FALSE; + } + sa->data_blocks[block_y * sa->block_count_hor + block_x] = src_block; + } + + if (buf_col_stride == 1) { + OPJ_INT32* OPJ_RESTRICT dest_ptr = src_block + block_y_offset * + (OPJ_SIZE_T)block_width + block_x_offset; + const OPJ_INT32* OPJ_RESTRICT src_ptr = buf + (y - y0) * + (OPJ_SIZE_T)buf_line_stride + (x - x0) * buf_col_stride; + if (x_incr == 4) { + /* Same code as general branch, but the compiler */ + /* can have an efficient memcpy() */ + (void)(x_incr); /* trick to silent cppcheck duplicateBranch warning */ + for (j = 0; j < y_incr; j++) { + memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr); + dest_ptr += block_width; + src_ptr += buf_line_stride; + } + } else { + for (j = 0; j < y_incr; j++) { + memcpy(dest_ptr, src_ptr, sizeof(OPJ_INT32) * x_incr); + dest_ptr += block_width; + src_ptr += buf_line_stride; + } + } + } else { + OPJ_INT32* OPJ_RESTRICT dest_ptr = src_block + block_y_offset * + (OPJ_SIZE_T)block_width + block_x_offset; + const OPJ_INT32* OPJ_RESTRICT src_ptr = buf + (y - y0) * + (OPJ_SIZE_T)buf_line_stride + (x - x0) * buf_col_stride; + if (x_incr == 1) { + for (j = 0; j < y_incr; j++) { + *dest_ptr = *src_ptr; + src_ptr += buf_line_stride; + dest_ptr += block_width; + } + } else if (x_incr >= 8 && buf_col_stride == 8) { + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < (x_incr & ~3U); k += 4) { + dest_ptr[k] = src_ptr[k * buf_col_stride]; + dest_ptr[k + 1] = src_ptr[(k + 1) * buf_col_stride]; + dest_ptr[k + 2] = src_ptr[(k + 2) * buf_col_stride]; + dest_ptr[k + 3] = src_ptr[(k + 3) * buf_col_stride]; + } + for (; k < x_incr; k++) { + dest_ptr[k] = src_ptr[k * buf_col_stride]; + } + src_ptr += buf_line_stride; + dest_ptr += block_width; + } + } else { + /* General case */ + for (j = 0; j < y_incr; j++) { + OPJ_UINT32 k; + for (k = 0; k < x_incr; k++) { + dest_ptr[k] = src_ptr[k * buf_col_stride]; + } + src_ptr += buf_line_stride; + dest_ptr += block_width; + } + } + } + } + } + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_sparse_array_int32_read(const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + OPJ_INT32* dest, + OPJ_UINT32 dest_col_stride, + OPJ_UINT32 dest_line_stride, + OPJ_BOOL forgiving) +{ + return opj_sparse_array_int32_read_or_write( + (opj_sparse_array_int32_t*)sa, x0, y0, x1, y1, + dest, + dest_col_stride, + dest_line_stride, + forgiving, + OPJ_TRUE); +} + +OPJ_BOOL opj_sparse_array_int32_write(opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + const OPJ_INT32* src, + OPJ_UINT32 src_col_stride, + OPJ_UINT32 src_line_stride, + OPJ_BOOL forgiving) +{ + return opj_sparse_array_int32_read_or_write(sa, x0, y0, x1, y1, + (OPJ_INT32*)src, + src_col_stride, + src_line_stride, + forgiving, + OPJ_FALSE); +} diff --git a/client/deps/openjpeg/sparse_array.h b/client/deps/openjpeg/sparse_array.h new file mode 100644 index 000000000..fd927eaa0 --- /dev/null +++ b/client/deps/openjpeg/sparse_array.h @@ -0,0 +1,141 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2017, IntoPix SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +#ifndef OPJ_SPARSE_ARRAY_H +#define OPJ_SPARSE_ARRAY_H +/** +@file sparse_array.h +@brief Sparse array management + +The functions in this file manage sparse arrays. Sparse arrays are arrays with +potential big dimensions, but with very few samples actually set. Such sparse +arrays require allocating a low amount of memory, by just allocating memory +for blocks of the array that are set. The minimum memory allocation unit is a +a block. There is a trade-off to pick up an appropriate dimension for blocks. +If it is too big, and pixels set are far from each other, too much memory will +be used. If blocks are too small, the book-keeping costs of blocks will raise. +*/ + +/** @defgroup SPARSE_ARRAY SPARSE ARRAYS - Sparse arrays */ +/*@{*/ + +/** Opaque type for sparse arrays that contain int32 values */ +typedef struct opj_sparse_array_int32 opj_sparse_array_int32_t; + +/** Creates a new sparse array. + * @param width total width of the array. + * @param height total height of the array + * @param block_width width of a block. + * @param block_height height of a block. + * @return a new sparse array instance, or NULL in case of failure. + */ +opj_sparse_array_int32_t* opj_sparse_array_int32_create(OPJ_UINT32 width, + OPJ_UINT32 height, + OPJ_UINT32 block_width, + OPJ_UINT32 block_height); + +/** Frees a sparse array. + * @param sa sparse array instance. + */ +void opj_sparse_array_int32_free(opj_sparse_array_int32_t* sa); + +/** Returns whether region bounds are valid (non empty and within array bounds) + * @param sa sparse array instance. + * @param x0 left x coordinate of the region. + * @param y0 top x coordinate of the region. + * @param x1 right x coordinate (not included) of the region. Must be greater than x0. + * @param y1 bottom y coordinate (not included) of the region. Must be greater than y0. + * @return OPJ_TRUE or OPJ_FALSE. + */ +OPJ_BOOL opj_sparse_array_is_region_valid(const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1); + +/** Read the content of a rectangular region of the sparse array into a + * user buffer. + * + * Regions not written with opj_sparse_array_int32_write() are read as 0. + * + * @param sa sparse array instance. + * @param x0 left x coordinate of the region to read in the sparse array. + * @param y0 top x coordinate of the region to read in the sparse array. + * @param x1 right x coordinate (not included) of the region to read in the sparse array. Must be greater than x0. + * @param y1 bottom y coordinate (not included) of the region to read in the sparse array. Must be greater than y0. + * @param dest user buffer to fill. Must be at least sizeof(int32) * ( (y1 - y0 - 1) * dest_line_stride + (x1 - x0 - 1) * dest_col_stride + 1) bytes large. + * @param dest_col_stride spacing (in elements, not in bytes) in x dimension between consecutive elements of the user buffer. + * @param dest_line_stride spacing (in elements, not in bytes) in y dimension between consecutive elements of the user buffer. + * @param forgiving if set to TRUE and the region is invalid, OPJ_TRUE will still be returned. + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_sparse_array_int32_read(const opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + OPJ_INT32* dest, + OPJ_UINT32 dest_col_stride, + OPJ_UINT32 dest_line_stride, + OPJ_BOOL forgiving); + + +/** Write the content of a rectangular region into the sparse array from a + * user buffer. + * + * Blocks intersecting the region are allocated, if not already done. + * + * @param sa sparse array instance. + * @param x0 left x coordinate of the region to write into the sparse array. + * @param y0 top x coordinate of the region to write into the sparse array. + * @param x1 right x coordinate (not included) of the region to write into the sparse array. Must be greater than x0. + * @param y1 bottom y coordinate (not included) of the region to write into the sparse array. Must be greater than y0. + * @param src user buffer to fill. Must be at least sizeof(int32) * ( (y1 - y0 - 1) * src_line_stride + (x1 - x0 - 1) * src_col_stride + 1) bytes large. + * @param src_col_stride spacing (in elements, not in bytes) in x dimension between consecutive elements of the user buffer. + * @param src_line_stride spacing (in elements, not in bytes) in y dimension between consecutive elements of the user buffer. + * @param forgiving if set to TRUE and the region is invalid, OPJ_TRUE will still be returned. + * @return OPJ_TRUE in case of success. + */ +OPJ_BOOL opj_sparse_array_int32_write(opj_sparse_array_int32_t* sa, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1, + const OPJ_INT32* src, + OPJ_UINT32 src_col_stride, + OPJ_UINT32 src_line_stride, + OPJ_BOOL forgiving); + +/*@}*/ + +#endif /* OPJ_SPARSE_ARRAY_H */ diff --git a/client/deps/openjpeg/t1.c b/client/deps/openjpeg/t1.c new file mode 100644 index 000000000..98dce47f5 --- /dev/null +++ b/client/deps/openjpeg/t1.c @@ -0,0 +1,2741 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2007, Callum Lerwick + * Copyright (c) 2012, Carl Hetherington + * Copyright (c) 2017, IntoPIX SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#define OPJ_SKIP_POISON +#include "opj_includes.h" + +#ifdef __SSE__ +#include +#endif +#ifdef __SSE2__ +#include +#endif +#if (defined(__AVX2__) || defined(__AVX512F__)) +#include +#endif + +#if defined(__GNUC__) +#pragma GCC poison malloc calloc realloc free +#endif + +#include "t1_luts.h" + +/** @defgroup T1 T1 - Implementation of the tier-1 coding */ +/*@{*/ + +#define T1_FLAGS(x, y) (t1->flags[x + 1 + ((y / 4) + 1) * (t1->w+2)]) + +#define opj_t1_setcurctx(curctx, ctxno) curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)] + +/* Macros to deal with signed integer with just MSB bit set for + * negative values (smr = signed magnitude representation) */ +#define opj_smr_abs(x) (((OPJ_UINT32)(x)) & 0x7FFFFFFFU) +#define opj_smr_sign(x) (((OPJ_UINT32)(x)) >> 31) +#define opj_to_smr(x) ((x) >= 0 ? (OPJ_UINT32)(x) : ((OPJ_UINT32)(-x) | 0x80000000U)) + + +/** @name Local static functions */ +/*@{*/ + +static INLINE OPJ_BYTE opj_t1_getctxno_zc(opj_mqc_t *mqc, OPJ_UINT32 f); +static INLINE OPJ_UINT32 opj_t1_getctxno_mag(OPJ_UINT32 f); +static OPJ_INT16 opj_t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos); +static OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos); +static INLINE void opj_t1_update_flags(opj_flag_t *flagsp, OPJ_UINT32 ci, + OPJ_UINT32 s, OPJ_UINT32 stride, + OPJ_UINT32 vsc); + + +/** +Decode significant pass +*/ + +static INLINE void opj_t1_dec_sigpass_step_raw( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 vsc, + OPJ_UINT32 row); +static INLINE void opj_t1_dec_sigpass_step_mqc( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 row, + OPJ_UINT32 flags_stride, + OPJ_UINT32 vsc); + +/** +Encode significant pass +*/ +static void opj_t1_enc_sigpass(opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 cblksty); + +/** +Decode significant pass +*/ +static void opj_t1_dec_sigpass_raw( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 cblksty); + +/** +Encode refinement pass +*/ +static void opj_t1_enc_refpass(opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type); + +/** +Decode refinement pass +*/ +static void opj_t1_dec_refpass_raw( + opj_t1_t *t1, + OPJ_INT32 bpno); + + +/** +Decode refinement pass +*/ + +static INLINE void opj_t1_dec_refpass_step_raw( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_UINT32 row); +static INLINE void opj_t1_dec_refpass_step_mqc( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_UINT32 row); + + +/** +Decode clean-up pass +*/ + +static void opj_t1_dec_clnpass_step( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 row, + OPJ_UINT32 vsc); + +/** +Encode clean-up pass +*/ +static void opj_t1_enc_clnpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_UINT32 cblksty); + +static OPJ_FLOAT64 opj_t1_getwmsedec( + OPJ_INT32 nmsedec, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 numcomps, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps); + +/** Return "cumwmsedec" that should be used to increase tile->distotile */ +static double opj_t1_encode_cblk(opj_t1_t *t1, + opj_tcd_cblk_enc_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 cblksty, + OPJ_UINT32 numcomps, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps); + +/** +Decode 1 code-block +@param t1 T1 handle +@param cblk Code-block coding parameters +@param orient +@param roishift Region of interest shifting value +@param cblksty Code-block style +@param p_manager the event manager +@param p_manager_mutex mutex for the event manager +@param check_pterm whether PTERM correct termination should be checked +*/ +static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm); + +/** +Decode 1 HT code-block +@param t1 T1 handle +@param cblk Code-block coding parameters +@param orient +@param roishift Region of interest shifting value +@param cblksty Code-block style +@param p_manager the event manager +@param p_manager_mutex mutex for the event manager +@param check_pterm whether PTERM correct termination should be checked +*/ +OPJ_BOOL opj_t1_ht_decode_cblk(opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm); + + +static OPJ_BOOL opj_t1_allocate_buffers(opj_t1_t *t1, + OPJ_UINT32 w, + OPJ_UINT32 h); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +static INLINE OPJ_BYTE opj_t1_getctxno_zc(opj_mqc_t *mqc, OPJ_UINT32 f) +{ + return mqc->lut_ctxno_zc_orient[(f & T1_SIGMA_NEIGHBOURS)]; +} + +static INLINE OPJ_UINT32 opj_t1_getctxtno_sc_or_spb_index(OPJ_UINT32 fX, + OPJ_UINT32 pfX, + OPJ_UINT32 nfX, + OPJ_UINT32 ci) +{ + /* + 0 pfX T1_CHI_THIS T1_LUT_SGN_W + 1 tfX T1_SIGMA_1 T1_LUT_SIG_N + 2 nfX T1_CHI_THIS T1_LUT_SGN_E + 3 tfX T1_SIGMA_3 T1_LUT_SIG_W + 4 fX T1_CHI_(THIS - 1) T1_LUT_SGN_N + 5 tfX T1_SIGMA_5 T1_LUT_SIG_E + 6 fX T1_CHI_(THIS + 1) T1_LUT_SGN_S + 7 tfX T1_SIGMA_7 T1_LUT_SIG_S + */ + + OPJ_UINT32 lu = (fX >> (ci * 3U)) & (T1_SIGMA_1 | T1_SIGMA_3 | T1_SIGMA_5 | + T1_SIGMA_7); + + lu |= (pfX >> (T1_CHI_THIS_I + (ci * 3U))) & (1U << 0); + lu |= (nfX >> (T1_CHI_THIS_I - 2U + (ci * 3U))) & (1U << 2); + if (ci == 0U) { + lu |= (fX >> (T1_CHI_0_I - 4U)) & (1U << 4); + } else { + lu |= (fX >> (T1_CHI_1_I - 4U + ((ci - 1U) * 3U))) & (1U << 4); + } + lu |= (fX >> (T1_CHI_2_I - 6U + (ci * 3U))) & (1U << 6); + return lu; +} + +static INLINE OPJ_BYTE opj_t1_getctxno_sc(OPJ_UINT32 lu) +{ + return lut_ctxno_sc[lu]; +} + +static INLINE OPJ_UINT32 opj_t1_getctxno_mag(OPJ_UINT32 f) +{ + OPJ_UINT32 tmp = (f & T1_SIGMA_NEIGHBOURS) ? T1_CTXNO_MAG + 1 : T1_CTXNO_MAG; + OPJ_UINT32 tmp2 = (f & T1_MU_0) ? T1_CTXNO_MAG + 2 : tmp; + return tmp2; +} + +static INLINE OPJ_BYTE opj_t1_getspb(OPJ_UINT32 lu) +{ + return lut_spb[lu]; +} + +static OPJ_INT16 opj_t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos) +{ + if (bitpos > 0) { + return lut_nmsedec_sig[(x >> (bitpos)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +static OPJ_INT16 opj_t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos) +{ + if (bitpos > 0) { + return lut_nmsedec_ref[(x >> (bitpos)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +#define opj_t1_update_flags_macro(flags, flagsp, ci, s, stride, vsc) \ +{ \ + /* east */ \ + flagsp[-1] |= T1_SIGMA_5 << (3U * ci); \ + \ + /* mark target as significant */ \ + flags |= ((s << T1_CHI_1_I) | T1_SIGMA_4) << (3U * ci); \ + \ + /* west */ \ + flagsp[1] |= T1_SIGMA_3 << (3U * ci); \ + \ + /* north-west, north, north-east */ \ + if (ci == 0U && !(vsc)) { \ + opj_flag_t* north = flagsp - (stride); \ + *north |= (s << T1_CHI_5_I) | T1_SIGMA_16; \ + north[-1] |= T1_SIGMA_17; \ + north[1] |= T1_SIGMA_15; \ + } \ + \ + /* south-west, south, south-east */ \ + if (ci == 3U) { \ + opj_flag_t* south = flagsp + (stride); \ + *south |= (s << T1_CHI_0_I) | T1_SIGMA_1; \ + south[-1] |= T1_SIGMA_2; \ + south[1] |= T1_SIGMA_0; \ + } \ +} + + +static INLINE void opj_t1_update_flags(opj_flag_t *flagsp, OPJ_UINT32 ci, + OPJ_UINT32 s, OPJ_UINT32 stride, + OPJ_UINT32 vsc) +{ + opj_t1_update_flags_macro(*flagsp, flagsp, ci, s, stride, vsc); +} + +/** +Encode significant pass +*/ +#define opj_t1_enc_sigpass_step_macro(mqc, curctx, a, c, ct, flagspIn, datapIn, bpno, one, nmsedec, type, ciIn, vscIn) \ +{ \ + OPJ_UINT32 v; \ + const OPJ_UINT32 ci = (ciIn); \ + const OPJ_UINT32 vsc = (vscIn); \ + const OPJ_INT32* l_datap = (datapIn); \ + opj_flag_t* flagsp = (flagspIn); \ + OPJ_UINT32 const flags = *flagsp; \ + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && \ + (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { \ + OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); \ + v = (opj_smr_abs(*l_datap) & (OPJ_UINT32)one) ? 1 : 0; \ +/* #ifdef DEBUG_ENC_SIG */ \ +/* fprintf(stderr, " ctxt1=%d\n", ctxt1); */ \ +/* #endif */ \ + opj_t1_setcurctx(curctx, ctxt1); \ + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ \ + opj_mqc_bypass_enc_macro(mqc, c, ct, v); \ + } else { \ + opj_mqc_encode_macro(mqc, curctx, a, c, ct, v); \ + } \ + if (v) { \ + OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \ + *flagsp, \ + flagsp[-1], flagsp[1], \ + ci); \ + OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu); \ + v = opj_smr_sign(*l_datap); \ + *nmsedec += opj_t1_getnmsedec_sig(opj_smr_abs(*l_datap), \ + (OPJ_UINT32)bpno); \ +/* #ifdef DEBUG_ENC_SIG */ \ +/* fprintf(stderr, " ctxt2=%d\n", ctxt2); */ \ +/* #endif */ \ + opj_t1_setcurctx(curctx, ctxt2); \ + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ \ + opj_mqc_bypass_enc_macro(mqc, c, ct, v); \ + } else { \ + OPJ_UINT32 spb = opj_t1_getspb(lu); \ +/* #ifdef DEBUG_ENC_SIG */ \ +/* fprintf(stderr, " spb=%d\n", spb); */ \ +/* #endif */ \ + opj_mqc_encode_macro(mqc, curctx, a, c, ct, v ^ spb); \ + } \ + opj_t1_update_flags(flagsp, ci, v, t1->w + 2, vsc); \ + } \ + *flagsp |= T1_PI_THIS << (ci * 3U); \ + } \ +} + +static INLINE void opj_t1_dec_sigpass_step_raw( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 vsc, + OPJ_UINT32 ci) +{ + OPJ_UINT32 v; + opj_mqc_t *mqc = &(t1->mqc); /* RAW component */ + + OPJ_UINT32 const flags = *flagsp; + + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && + (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { + if (opj_mqc_raw_decode(mqc)) { + v = opj_mqc_raw_decode(mqc); + *datap = v ? -oneplushalf : oneplushalf; + opj_t1_update_flags(flagsp, ci, v, t1->w + 2, vsc); + } + *flagsp |= T1_PI_THIS << (ci * 3U); + } +} + +#define opj_t1_dec_sigpass_step_mqc_macro(flags, flagsp, flags_stride, data, \ + data_stride, ci, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc) \ +{ \ + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == 0U && \ + (flags & (T1_SIGMA_NEIGHBOURS << (ci * 3U))) != 0U) { \ + OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); \ + opj_t1_setcurctx(curctx, ctxt1); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + if (v) { \ + OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \ + flags, \ + flagsp[-1], flagsp[1], \ + ci); \ + OPJ_UINT32 ctxt2 = opj_t1_getctxno_sc(lu); \ + OPJ_UINT32 spb = opj_t1_getspb(lu); \ + opj_t1_setcurctx(curctx, ctxt2); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + v = v ^ spb; \ + data[ci*data_stride] = v ? -oneplushalf : oneplushalf; \ + opj_t1_update_flags_macro(flags, flagsp, ci, v, flags_stride, vsc); \ + } \ + flags |= T1_PI_THIS << (ci * 3U); \ + } \ +} + +static INLINE void opj_t1_dec_sigpass_step_mqc( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 ci, + OPJ_UINT32 flags_stride, + OPJ_UINT32 vsc) +{ + OPJ_UINT32 v; + + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + opj_t1_dec_sigpass_step_mqc_macro(*flagsp, flagsp, flags_stride, datap, + 0, ci, mqc, mqc->curctx, + v, mqc->a, mqc->c, mqc->ct, oneplushalf, vsc); +} + +static void opj_t1_enc_sigpass(opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type, + OPJ_UINT32 cblksty + ) +{ + OPJ_UINT32 i, k; + OPJ_INT32 const one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + opj_flag_t* f = &T1_FLAGS(0, 0); + OPJ_UINT32 const extra = 2; + opj_mqc_t* mqc = &(t1->mqc); + DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); + const OPJ_INT32* datap = t1->data; + + *nmsedec = 0; +#ifdef DEBUG_ENC_SIG + fprintf(stderr, "enc_sigpass: bpno=%d\n", bpno); +#endif + for (k = 0; k < (t1->h & ~3U); k += 4, f += extra) { + const OPJ_UINT32 w = t1->w; +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " k=%d\n", k); +#endif + for (i = 0; i < w; ++i, ++f, datap += 4) { +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " i=%d\n", i); +#endif + if (*f == 0U) { + /* Nothing to do for any of the 4 data points */ + continue; + } + opj_t1_enc_sigpass_step_macro( + mqc, curctx, a, c, ct, + f, + &datap[0], + bpno, + one, + nmsedec, + type, + 0, cblksty & J2K_CCP_CBLKSTY_VSC); + opj_t1_enc_sigpass_step_macro( + mqc, curctx, a, c, ct, + f, + &datap[1], + bpno, + one, + nmsedec, + type, + 1, 0); + opj_t1_enc_sigpass_step_macro( + mqc, curctx, a, c, ct, + f, + &datap[2], + bpno, + one, + nmsedec, + type, + 2, 0); + opj_t1_enc_sigpass_step_macro( + mqc, curctx, a, c, ct, + f, + &datap[3], + bpno, + one, + nmsedec, + type, + 3, 0); + } + } + + if (k < t1->h) { + OPJ_UINT32 j; +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i, ++f) { +#ifdef DEBUG_ENC_SIG + fprintf(stderr, " i=%d\n", i); +#endif + if (*f == 0U) { + /* Nothing to do for any of the 4 data points */ + datap += (t1->h - k); + continue; + } + for (j = k; j < t1->h; ++j, ++datap) { + opj_t1_enc_sigpass_step_macro( + mqc, curctx, a, c, ct, + f, + &datap[0], + bpno, + one, + nmsedec, + type, + j - k, + (j == k && (cblksty & J2K_CCP_CBLKSTY_VSC) != 0)); + } + } + } + + UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); +} + +static void opj_t1_dec_sigpass_raw( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 cblksty) +{ + OPJ_INT32 one, half, oneplushalf; + OPJ_UINT32 i, j, k; + OPJ_INT32 *data = t1->data; + opj_flag_t *flagsp = &T1_FLAGS(0, 0); + const OPJ_UINT32 l_w = t1->w; + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + + for (k = 0; k < (t1->h & ~3U); k += 4, flagsp += 2, data += 3 * l_w) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + opj_flag_t flags = *flagsp; + if (flags != 0) { + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data, + oneplushalf, + cblksty & J2K_CCP_CBLKSTY_VSC, /* vsc */ + 0U); + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data + l_w, + oneplushalf, + OPJ_FALSE, /* vsc */ + 1U); + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data + 2 * l_w, + oneplushalf, + OPJ_FALSE, /* vsc */ + 2U); + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data + 3 * l_w, + oneplushalf, + OPJ_FALSE, /* vsc */ + 3U); + } + } + } + if (k < t1->h) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + for (j = 0; j < t1->h - k; ++j) { + opj_t1_dec_sigpass_step_raw( + t1, + flagsp, + data + j * l_w, + oneplushalf, + cblksty & J2K_CCP_CBLKSTY_VSC, /* vsc */ + j); + } + } + } +} + +#define opj_t1_dec_sigpass_mqc_internal(t1, bpno, vsc, w, h, flags_stride) \ +{ \ + OPJ_INT32 one, half, oneplushalf; \ + OPJ_UINT32 i, j, k; \ + register OPJ_INT32 *data = t1->data; \ + register opj_flag_t *flagsp = &t1->flags[(flags_stride) + 1]; \ + const OPJ_UINT32 l_w = w; \ + opj_mqc_t* mqc = &(t1->mqc); \ + DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \ + register OPJ_UINT32 v; \ + one = 1 << bpno; \ + half = one >> 1; \ + oneplushalf = one | half; \ + for (k = 0; k < (h & ~3u); k += 4, data += 3*l_w, flagsp += 2) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + opj_flag_t flags = *flagsp; \ + if( flags != 0 ) { \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 0, mqc, curctx, v, a, c, ct, oneplushalf, vsc); \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 1, mqc, curctx, v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 2, mqc, curctx, v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_sigpass_step_mqc_macro( \ + flags, flagsp, flags_stride, data, \ + l_w, 3, mqc, curctx, v, a, c, ct, oneplushalf, OPJ_FALSE); \ + *flagsp = flags; \ + } \ + } \ + } \ + UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \ + if( k < h ) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + for (j = 0; j < h - k; ++j) { \ + opj_t1_dec_sigpass_step_mqc(t1, flagsp, \ + data + j * l_w, oneplushalf, j, flags_stride, vsc); \ + } \ + } \ + } \ +} + +static void opj_t1_dec_sigpass_mqc_64x64_novsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_FALSE, 64, 64, 66); +} + +static void opj_t1_dec_sigpass_mqc_64x64_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_TRUE, 64, 64, 66); +} + +static void opj_t1_dec_sigpass_mqc_generic_novsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_FALSE, t1->w, t1->h, + t1->w + 2U); +} + +static void opj_t1_dec_sigpass_mqc_generic_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_sigpass_mqc_internal(t1, bpno, OPJ_TRUE, t1->w, t1->h, + t1->w + 2U); +} + +static void opj_t1_dec_sigpass_mqc( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 cblksty) +{ + if (t1->w == 64 && t1->h == 64) { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_sigpass_mqc_64x64_vsc(t1, bpno); + } else { + opj_t1_dec_sigpass_mqc_64x64_novsc(t1, bpno); + } + } else { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_sigpass_mqc_generic_vsc(t1, bpno); + } else { + opj_t1_dec_sigpass_mqc_generic_novsc(t1, bpno); + } + } +} + +/** +Encode refinement pass step +*/ +#define opj_t1_enc_refpass_step_macro(mqc, curctx, a, c, ct, flags, flagsUpdated, datap, bpno, one, nmsedec, type, ci) \ +{\ + OPJ_UINT32 v; \ + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << ((ci) * 3U))) == (T1_SIGMA_THIS << ((ci) * 3U))) { \ + const OPJ_UINT32 shift_flags = (flags >> ((ci) * 3U)); \ + OPJ_UINT32 ctxt = opj_t1_getctxno_mag(shift_flags); \ + OPJ_UINT32 abs_data = opj_smr_abs(*datap); \ + *nmsedec += opj_t1_getnmsedec_ref(abs_data, \ + (OPJ_UINT32)bpno); \ + v = ((OPJ_INT32)abs_data & one) ? 1 : 0; \ +/* #ifdef DEBUG_ENC_REF */ \ +/* fprintf(stderr, " ctxt=%d\n", ctxt); */ \ +/* #endif */ \ + opj_t1_setcurctx(curctx, ctxt); \ + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ \ + opj_mqc_bypass_enc_macro(mqc, c, ct, v); \ + } else { \ + opj_mqc_encode_macro(mqc, curctx, a, c, ct, v); \ + } \ + flagsUpdated |= T1_MU_THIS << ((ci) * 3U); \ + } \ +} + + +static INLINE void opj_t1_dec_refpass_step_raw( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_UINT32 ci) +{ + OPJ_UINT32 v; + + opj_mqc_t *mqc = &(t1->mqc); /* RAW component */ + + if ((*flagsp & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == + (T1_SIGMA_THIS << (ci * 3U))) { + v = opj_mqc_raw_decode(mqc); + *datap += (v ^ (*datap < 0)) ? poshalf : -poshalf; + *flagsp |= T1_MU_THIS << (ci * 3U); + } +} + +#define opj_t1_dec_refpass_step_mqc_macro(flags, data, data_stride, ci, \ + mqc, curctx, v, a, c, ct, poshalf) \ +{ \ + if ((flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U))) == \ + (T1_SIGMA_THIS << (ci * 3U))) { \ + OPJ_UINT32 ctxt = opj_t1_getctxno_mag(flags >> (ci * 3U)); \ + opj_t1_setcurctx(curctx, ctxt); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + data[ci*data_stride] += (v ^ (data[ci*data_stride] < 0)) ? poshalf : -poshalf; \ + flags |= T1_MU_THIS << (ci * 3U); \ + } \ +} + +static INLINE void opj_t1_dec_refpass_step_mqc( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 poshalf, + OPJ_UINT32 ci) +{ + OPJ_UINT32 v; + + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + opj_t1_dec_refpass_step_mqc_macro(*flagsp, datap, 0, ci, + mqc, mqc->curctx, v, mqc->a, mqc->c, + mqc->ct, poshalf); +} + +static void opj_t1_enc_refpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_BYTE type) +{ + OPJ_UINT32 i, k; + const OPJ_INT32 one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + opj_flag_t* f = &T1_FLAGS(0, 0); + const OPJ_UINT32 extra = 2U; + opj_mqc_t* mqc = &(t1->mqc); + DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); + const OPJ_INT32* datap = t1->data; + + *nmsedec = 0; +#ifdef DEBUG_ENC_REF + fprintf(stderr, "enc_refpass: bpno=%d\n", bpno); +#endif + for (k = 0; k < (t1->h & ~3U); k += 4, f += extra) { +#ifdef DEBUG_ENC_REF + fprintf(stderr, " k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i, f++, datap += 4) { + const OPJ_UINT32 flags = *f; + OPJ_UINT32 flagsUpdated = flags; +#ifdef DEBUG_ENC_REF + fprintf(stderr, " i=%d\n", i); +#endif + if ((flags & (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13)) == 0) { + /* none significant */ + continue; + } + if ((flags & (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3)) == + (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3)) { + /* all processed by sigpass */ + continue; + } + + opj_t1_enc_refpass_step_macro( + mqc, curctx, a, c, ct, + flags, flagsUpdated, + &datap[0], + bpno, + one, + nmsedec, + type, + 0); + opj_t1_enc_refpass_step_macro( + mqc, curctx, a, c, ct, + flags, flagsUpdated, + &datap[1], + bpno, + one, + nmsedec, + type, + 1); + opj_t1_enc_refpass_step_macro( + mqc, curctx, a, c, ct, + flags, flagsUpdated, + &datap[2], + bpno, + one, + nmsedec, + type, + 2); + opj_t1_enc_refpass_step_macro( + mqc, curctx, a, c, ct, + flags, flagsUpdated, + &datap[3], + bpno, + one, + nmsedec, + type, + 3); + *f = flagsUpdated; + } + } + + if (k < t1->h) { + OPJ_UINT32 j; + const OPJ_UINT32 remaining_lines = t1->h - k; +#ifdef DEBUG_ENC_REF + fprintf(stderr, " k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i, ++f) { +#ifdef DEBUG_ENC_REF + fprintf(stderr, " i=%d\n", i); +#endif + if ((*f & (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13)) == 0) { + /* none significant */ + datap += remaining_lines; + continue; + } + for (j = 0; j < remaining_lines; ++j, datap ++) { + opj_t1_enc_refpass_step_macro( + mqc, curctx, a, c, ct, + *f, *f, + &datap[0], + bpno, + one, + nmsedec, + type, + j); + } + } + } + + UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); +} + + +static void opj_t1_dec_refpass_raw( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + OPJ_INT32 one, poshalf; + OPJ_UINT32 i, j, k; + OPJ_INT32 *data = t1->data; + opj_flag_t *flagsp = &T1_FLAGS(0, 0); + const OPJ_UINT32 l_w = t1->w; + one = 1 << bpno; + poshalf = one >> 1; + for (k = 0; k < (t1->h & ~3U); k += 4, flagsp += 2, data += 3 * l_w) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + opj_flag_t flags = *flagsp; + if (flags != 0) { + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data, + poshalf, + 0U); + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + l_w, + poshalf, + 1U); + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + 2 * l_w, + poshalf, + 2U); + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + 3 * l_w, + poshalf, + 3U); + } + } + } + if (k < t1->h) { + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { + for (j = 0; j < t1->h - k; ++j) { + opj_t1_dec_refpass_step_raw( + t1, + flagsp, + data + j * l_w, + poshalf, + j); + } + } + } +} + +#define opj_t1_dec_refpass_mqc_internal(t1, bpno, w, h, flags_stride) \ +{ \ + OPJ_INT32 one, poshalf; \ + OPJ_UINT32 i, j, k; \ + register OPJ_INT32 *data = t1->data; \ + register opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \ + const OPJ_UINT32 l_w = w; \ + opj_mqc_t* mqc = &(t1->mqc); \ + DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \ + register OPJ_UINT32 v; \ + one = 1 << bpno; \ + poshalf = one >> 1; \ + for (k = 0; k < (h & ~3u); k += 4, data += 3*l_w, flagsp += 2) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + opj_flag_t flags = *flagsp; \ + if( flags != 0 ) { \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 0, \ + mqc, curctx, v, a, c, ct, poshalf); \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 1, \ + mqc, curctx, v, a, c, ct, poshalf); \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 2, \ + mqc, curctx, v, a, c, ct, poshalf); \ + opj_t1_dec_refpass_step_mqc_macro( \ + flags, data, l_w, 3, \ + mqc, curctx, v, a, c, ct, poshalf); \ + *flagsp = flags; \ + } \ + } \ + } \ + UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \ + if( k < h ) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + for (j = 0; j < h - k; ++j) { \ + opj_t1_dec_refpass_step_mqc(t1, flagsp, data + j * l_w, poshalf, j); \ + } \ + } \ + } \ +} + +static void opj_t1_dec_refpass_mqc_64x64( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_refpass_mqc_internal(t1, bpno, 64, 64, 66); +} + +static void opj_t1_dec_refpass_mqc_generic( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_refpass_mqc_internal(t1, bpno, t1->w, t1->h, t1->w + 2U); +} + +static void opj_t1_dec_refpass_mqc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + if (t1->w == 64 && t1->h == 64) { + opj_t1_dec_refpass_mqc_64x64(t1, bpno); + } else { + opj_t1_dec_refpass_mqc_generic(t1, bpno); + } +} + +/** +Encode clean-up pass step +*/ +#define opj_t1_enc_clnpass_step_macro(mqc, curctx, a, c, ct, flagspIn, datapIn, bpno, one, nmsedec, agg, runlen, lim, cblksty) \ +{ \ + OPJ_UINT32 v; \ + OPJ_UINT32 ci; \ + opj_flag_t* const flagsp = (flagspIn); \ + const OPJ_INT32* l_datap = (datapIn); \ + const OPJ_UINT32 check = (T1_SIGMA_4 | T1_SIGMA_7 | T1_SIGMA_10 | T1_SIGMA_13 | \ + T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ + \ + if ((*flagsp & check) == check) { \ + if (runlen == 0) { \ + *flagsp &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ + } else if (runlen == 1) { \ + *flagsp &= ~(T1_PI_1 | T1_PI_2 | T1_PI_3); \ + } else if (runlen == 2) { \ + *flagsp &= ~(T1_PI_2 | T1_PI_3); \ + } else if (runlen == 3) { \ + *flagsp &= ~(T1_PI_3); \ + } \ + } \ + else \ + for (ci = runlen; ci < lim; ++ci) { \ + OPJ_BOOL goto_PARTIAL = OPJ_FALSE; \ + if ((agg != 0) && (ci == runlen)) { \ + goto_PARTIAL = OPJ_TRUE; \ + } \ + else if (!(*flagsp & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U)))) { \ + OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, *flagsp >> (ci * 3U)); \ +/* #ifdef DEBUG_ENC_CLN */ \ +/* printf(" ctxt1=%d\n", ctxt1); */ \ +/* #endif */ \ + opj_t1_setcurctx(curctx, ctxt1); \ + v = (opj_smr_abs(*l_datap) & (OPJ_UINT32)one) ? 1 : 0; \ + opj_mqc_encode_macro(mqc, curctx, a, c, ct, v); \ + if (v) { \ + goto_PARTIAL = OPJ_TRUE; \ + } \ + } \ + if( goto_PARTIAL ) { \ + OPJ_UINT32 vsc; \ + OPJ_UINT32 ctxt2, spb; \ + OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \ + *flagsp, \ + flagsp[-1], flagsp[1], \ + ci); \ + *nmsedec += opj_t1_getnmsedec_sig(opj_smr_abs(*l_datap), \ + (OPJ_UINT32)bpno); \ + ctxt2 = opj_t1_getctxno_sc(lu); \ +/* #ifdef DEBUG_ENC_CLN */ \ +/* printf(" ctxt2=%d\n", ctxt2); */ \ +/* #endif */ \ + opj_t1_setcurctx(curctx, ctxt2); \ + \ + v = opj_smr_sign(*l_datap); \ + spb = opj_t1_getspb(lu); \ +/* #ifdef DEBUG_ENC_CLN */ \ +/* printf(" spb=%d\n", spb); */\ +/* #endif */ \ + opj_mqc_encode_macro(mqc, curctx, a, c, ct, v ^ spb); \ + vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (ci == 0)) ? 1 : 0; \ + opj_t1_update_flags(flagsp, ci, v, t1->w + 2U, vsc); \ + } \ + *flagsp &= ~(T1_PI_THIS << (3U * ci)); \ + l_datap ++; \ + } \ +} + +#define opj_t1_dec_clnpass_step_macro(check_flags, partial, \ + flags, flagsp, flags_stride, data, \ + data_stride, ci, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc) \ +{ \ + if ( !check_flags || !(flags & ((T1_SIGMA_THIS | T1_PI_THIS) << (ci * 3U)))) {\ + do { \ + if( !partial ) { \ + OPJ_UINT32 ctxt1 = opj_t1_getctxno_zc(mqc, flags >> (ci * 3U)); \ + opj_t1_setcurctx(curctx, ctxt1); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + if( !v ) \ + break; \ + } \ + { \ + OPJ_UINT32 lu = opj_t1_getctxtno_sc_or_spb_index( \ + flags, flagsp[-1], flagsp[1], \ + ci); \ + opj_t1_setcurctx(curctx, opj_t1_getctxno_sc(lu)); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + v = v ^ opj_t1_getspb(lu); \ + data[ci*data_stride] = v ? -oneplushalf : oneplushalf; \ + opj_t1_update_flags_macro(flags, flagsp, ci, v, flags_stride, vsc); \ + } \ + } while(0); \ + } \ +} + +static void opj_t1_dec_clnpass_step( + opj_t1_t *t1, + opj_flag_t *flagsp, + OPJ_INT32 *datap, + OPJ_INT32 oneplushalf, + OPJ_UINT32 ci, + OPJ_UINT32 vsc) +{ + OPJ_UINT32 v; + + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, + *flagsp, flagsp, t1->w + 2U, datap, + 0, ci, mqc, mqc->curctx, + v, mqc->a, mqc->c, mqc->ct, oneplushalf, vsc); +} + +static void opj_t1_enc_clnpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 *nmsedec, + OPJ_UINT32 cblksty) +{ + OPJ_UINT32 i, k; + const OPJ_INT32 one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + opj_mqc_t* mqc = &(t1->mqc); + DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); + const OPJ_INT32* datap = t1->data; + opj_flag_t *f = &T1_FLAGS(0, 0); + const OPJ_UINT32 extra = 2U; + + *nmsedec = 0; +#ifdef DEBUG_ENC_CLN + printf("enc_clnpass: bpno=%d\n", bpno); +#endif + for (k = 0; k < (t1->h & ~3U); k += 4, f += extra) { +#ifdef DEBUG_ENC_CLN + printf(" k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i, f++) { + OPJ_UINT32 agg, runlen; +#ifdef DEBUG_ENC_CLN + printf(" i=%d\n", i); +#endif + agg = !*f; +#ifdef DEBUG_ENC_CLN + printf(" agg=%d\n", agg); +#endif + if (agg) { + for (runlen = 0; runlen < 4; ++runlen, ++datap) { + if (opj_smr_abs(*datap) & (OPJ_UINT32)one) { + break; + } + } + opj_t1_setcurctx(curctx, T1_CTXNO_AGG); + opj_mqc_encode_macro(mqc, curctx, a, c, ct, runlen != 4); + if (runlen == 4) { + continue; + } + opj_t1_setcurctx(curctx, T1_CTXNO_UNI); + opj_mqc_encode_macro(mqc, curctx, a, c, ct, runlen >> 1); + opj_mqc_encode_macro(mqc, curctx, a, c, ct, runlen & 1); + } else { + runlen = 0; + } + opj_t1_enc_clnpass_step_macro( + mqc, curctx, a, c, ct, + f, + datap, + bpno, + one, + nmsedec, + agg, + runlen, + 4U, + cblksty); + datap += 4 - runlen; + } + } + if (k < t1->h) { + const OPJ_UINT32 agg = 0; + const OPJ_UINT32 runlen = 0; +#ifdef DEBUG_ENC_CLN + printf(" k=%d\n", k); +#endif + for (i = 0; i < t1->w; ++i, f++) { +#ifdef DEBUG_ENC_CLN + printf(" i=%d\n", i); + printf(" agg=%d\n", agg); +#endif + opj_t1_enc_clnpass_step_macro( + mqc, curctx, a, c, ct, + f, + datap, + bpno, + one, + nmsedec, + agg, + runlen, + t1->h - k, + cblksty); + datap += t1->h - k; + } + } + + UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); +} + +#define opj_t1_dec_clnpass_internal(t1, bpno, vsc, w, h, flags_stride) \ +{ \ + OPJ_INT32 one, half, oneplushalf; \ + OPJ_UINT32 runlen; \ + OPJ_UINT32 i, j, k; \ + const OPJ_UINT32 l_w = w; \ + opj_mqc_t* mqc = &(t1->mqc); \ + register OPJ_INT32 *data = t1->data; \ + register opj_flag_t *flagsp = &t1->flags[flags_stride + 1]; \ + DOWNLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \ + register OPJ_UINT32 v; \ + one = 1 << bpno; \ + half = one >> 1; \ + oneplushalf = one | half; \ + for (k = 0; k < (h & ~3u); k += 4, data += 3*l_w, flagsp += 2) { \ + for (i = 0; i < l_w; ++i, ++data, ++flagsp) { \ + opj_flag_t flags = *flagsp; \ + if (flags == 0) { \ + OPJ_UINT32 partial = OPJ_TRUE; \ + opj_t1_setcurctx(curctx, T1_CTXNO_AGG); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + if (!v) { \ + continue; \ + } \ + opj_t1_setcurctx(curctx, T1_CTXNO_UNI); \ + opj_mqc_decode_macro(runlen, mqc, curctx, a, c, ct); \ + opj_mqc_decode_macro(v, mqc, curctx, a, c, ct); \ + runlen = (runlen << 1) | v; \ + switch(runlen) { \ + case 0: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, OPJ_TRUE,\ + flags, flagsp, flags_stride, data, \ + l_w, 0, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc); \ + partial = OPJ_FALSE; \ + /* FALLTHRU */ \ + case 1: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, partial,\ + flags, flagsp, flags_stride, data, \ + l_w, 1, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + partial = OPJ_FALSE; \ + /* FALLTHRU */ \ + case 2: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, partial,\ + flags, flagsp, flags_stride, data, \ + l_w, 2, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + partial = OPJ_FALSE; \ + /* FALLTHRU */ \ + case 3: \ + opj_t1_dec_clnpass_step_macro(OPJ_FALSE, partial,\ + flags, flagsp, flags_stride, data, \ + l_w, 3, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + break; \ + } \ + } else { \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 0, mqc, curctx, \ + v, a, c, ct, oneplushalf, vsc); \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 1, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 2, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + opj_t1_dec_clnpass_step_macro(OPJ_TRUE, OPJ_FALSE, \ + flags, flagsp, flags_stride, data, \ + l_w, 3, mqc, curctx, \ + v, a, c, ct, oneplushalf, OPJ_FALSE); \ + } \ + *flagsp = flags & ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ + } \ + } \ + UPLOAD_MQC_VARIABLES(mqc, curctx, a, c, ct); \ + if( k < h ) { \ + for (i = 0; i < l_w; ++i, ++flagsp, ++data) { \ + for (j = 0; j < h - k; ++j) { \ + opj_t1_dec_clnpass_step(t1, flagsp, data + j * l_w, oneplushalf, j, vsc); \ + } \ + *flagsp &= ~(T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); \ + } \ + } \ +} + +static void opj_t1_dec_clnpass_check_segsym(opj_t1_t *t1, OPJ_INT32 cblksty) +{ + if (cblksty & J2K_CCP_CBLKSTY_SEGSYM) { + opj_mqc_t* mqc = &(t1->mqc); + OPJ_UINT32 v, v2; + opj_mqc_setcurctx(mqc, T1_CTXNO_UNI); + opj_mqc_decode(v, mqc); + opj_mqc_decode(v2, mqc); + v = (v << 1) | v2; + opj_mqc_decode(v2, mqc); + v = (v << 1) | v2; + opj_mqc_decode(v2, mqc); + v = (v << 1) | v2; + /* + if (v!=0xa) { + opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v); + } + */ + } +} + +static void opj_t1_dec_clnpass_64x64_novsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_FALSE, 64, 64, 66); +} + +static void opj_t1_dec_clnpass_64x64_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_TRUE, 64, 64, 66); +} + +static void opj_t1_dec_clnpass_generic_novsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_FALSE, t1->w, t1->h, + t1->w + 2U); +} + +static void opj_t1_dec_clnpass_generic_vsc( + opj_t1_t *t1, + OPJ_INT32 bpno) +{ + opj_t1_dec_clnpass_internal(t1, bpno, OPJ_TRUE, t1->w, t1->h, + t1->w + 2U); +} + +static void opj_t1_dec_clnpass( + opj_t1_t *t1, + OPJ_INT32 bpno, + OPJ_INT32 cblksty) +{ + if (t1->w == 64 && t1->h == 64) { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_clnpass_64x64_vsc(t1, bpno); + } else { + opj_t1_dec_clnpass_64x64_novsc(t1, bpno); + } + } else { + if (cblksty & J2K_CCP_CBLKSTY_VSC) { + opj_t1_dec_clnpass_generic_vsc(t1, bpno); + } else { + opj_t1_dec_clnpass_generic_novsc(t1, bpno); + } + } + opj_t1_dec_clnpass_check_segsym(t1, cblksty); +} + + +static OPJ_FLOAT64 opj_t1_getwmsedec( + OPJ_INT32 nmsedec, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 orient, + OPJ_INT32 bpno, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 numcomps, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps) +{ + OPJ_FLOAT64 w1 = 1, w2, wmsedec; + OPJ_ARG_NOT_USED(numcomps); + + if (mct_norms && (compno < mct_numcomps)) { + w1 = mct_norms[compno]; + } + + if (qmfbid == 1) { + w2 = opj_dwt_getnorm(level, orient); + } else { /* if (qmfbid == 0) */ + const OPJ_INT32 log2_gain = (orient == 0) ? 0 : + (orient == 3) ? 2 : 1; + w2 = opj_dwt_getnorm_real(level, orient); + /* Not sure this is right. But preserves past behaviour */ + stepsize /= (1 << log2_gain); + } + + wmsedec = w1 * w2 * stepsize * (1 << bpno); + wmsedec *= wmsedec * nmsedec / 8192.0; + + return wmsedec; +} + +static OPJ_BOOL opj_t1_allocate_buffers( + opj_t1_t *t1, + OPJ_UINT32 w, + OPJ_UINT32 h) +{ + OPJ_UINT32 flagssize; + OPJ_UINT32 flags_stride; + + /* No risk of overflow. Prior checks ensure those assert are met */ + /* They are per the specification */ + assert(w <= 1024); + assert(h <= 1024); + assert(w * h <= 4096); + + /* encoder uses tile buffer, so no need to allocate */ + { + OPJ_UINT32 datasize = w * h; + + if (datasize > t1->datasize) { + opj_aligned_free(t1->data); + t1->data = (OPJ_INT32*) opj_aligned_malloc(datasize * sizeof(OPJ_INT32)); + if (!t1->data) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + t1->datasize = datasize; + } + /* memset first arg is declared to never be null by gcc */ + if (t1->data != NULL) { + memset(t1->data, 0, datasize * sizeof(OPJ_INT32)); + } + } + + flags_stride = w + 2U; /* can't be 0U */ + + flagssize = (h + 3U) / 4U + 2U; + + flagssize *= flags_stride; + { + opj_flag_t* p; + OPJ_UINT32 x; + OPJ_UINT32 flags_height = (h + 3U) / 4U; + + if (flagssize > t1->flagssize) { + + opj_aligned_free(t1->flags); + t1->flags = (opj_flag_t*) opj_aligned_malloc(flagssize * sizeof( + opj_flag_t)); + if (!t1->flags) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + } + t1->flagssize = flagssize; + + memset(t1->flags, 0, flagssize * sizeof(opj_flag_t)); + + p = &t1->flags[0]; + for (x = 0; x < flags_stride; ++x) { + /* magic value to hopefully stop any passes being interested in this entry */ + *p++ = (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); + } + + p = &t1->flags[((flags_height + 1) * flags_stride)]; + for (x = 0; x < flags_stride; ++x) { + /* magic value to hopefully stop any passes being interested in this entry */ + *p++ = (T1_PI_0 | T1_PI_1 | T1_PI_2 | T1_PI_3); + } + + if (h % 4) { + OPJ_UINT32 v = 0; + p = &t1->flags[((flags_height) * flags_stride)]; + if (h % 4 == 1) { + v |= T1_PI_1 | T1_PI_2 | T1_PI_3; + } else if (h % 4 == 2) { + v |= T1_PI_2 | T1_PI_3; + } else if (h % 4 == 3) { + v |= T1_PI_3; + } + for (x = 0; x < flags_stride; ++x) { + *p++ = v; + } + } + } + + t1->w = w; + t1->h = h; + + return OPJ_TRUE; +} + +/* ----------------------------------------------------------------------- */ + +/* ----------------------------------------------------------------------- */ +/** + * Creates a new Tier 1 handle + * and initializes the look-up tables of the Tier-1 coder/decoder + * @return a new T1 handle if successful, returns NULL otherwise +*/ +opj_t1_t* opj_t1_create(OPJ_BOOL isEncoder) +{ + opj_t1_t *l_t1 = 00; + + l_t1 = (opj_t1_t*) opj_calloc(1, sizeof(opj_t1_t)); + if (!l_t1) { + return 00; + } + + l_t1->encoder = isEncoder; + + return l_t1; +} + + +/** + * Destroys a previously created T1 handle + * + * @param p_t1 Tier 1 handle to destroy +*/ +void opj_t1_destroy(opj_t1_t *p_t1) +{ + if (! p_t1) { + return; + } + + if (p_t1->data) { + opj_aligned_free(p_t1->data); + p_t1->data = 00; + } + + if (p_t1->flags) { + opj_aligned_free(p_t1->flags); + p_t1->flags = 00; + } + + opj_free(p_t1->cblkdatabuffer); + + opj_free(p_t1); +} + +typedef struct { + OPJ_BOOL whole_tile_decoding; + OPJ_UINT32 resno; + opj_tcd_cblk_dec_t* cblk; + opj_tcd_band_t* band; + opj_tcd_tilecomp_t* tilec; + opj_tccp_t* tccp; + OPJ_BOOL mustuse_cblkdatabuffer; + volatile OPJ_BOOL* pret; + opj_event_mgr_t *p_manager; + opj_mutex_t* p_manager_mutex; + OPJ_BOOL check_pterm; +} opj_t1_cblk_decode_processing_job_t; + +static void opj_t1_destroy_wrapper(void* t1) +{ + opj_t1_destroy((opj_t1_t*) t1); +} + +static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls) +{ + opj_tcd_cblk_dec_t* cblk; + opj_tcd_band_t* band; + opj_tcd_tilecomp_t* tilec; + opj_tccp_t* tccp; + OPJ_INT32* OPJ_RESTRICT datap; + OPJ_UINT32 cblk_w, cblk_h; + OPJ_INT32 x, y; + OPJ_UINT32 i, j; + opj_t1_cblk_decode_processing_job_t* job; + opj_t1_t* t1; + OPJ_UINT32 resno; + OPJ_UINT32 tile_w; + + job = (opj_t1_cblk_decode_processing_job_t*) user_data; + + cblk = job->cblk; + + if (!job->whole_tile_decoding) { + cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0); + cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0); + + cblk->decoded_data = (OPJ_INT32*)opj_aligned_malloc(sizeof(OPJ_INT32) * + cblk_w * cblk_h); + if (cblk->decoded_data == NULL) { + if (job->p_manager_mutex) { + opj_mutex_lock(job->p_manager_mutex); + } + opj_event_msg(job->p_manager, EVT_ERROR, + "Cannot allocate cblk->decoded_data\n"); + if (job->p_manager_mutex) { + opj_mutex_unlock(job->p_manager_mutex); + } + *(job->pret) = OPJ_FALSE; + opj_free(job); + return; + } + /* Zero-init required */ + memset(cblk->decoded_data, 0, sizeof(OPJ_INT32) * cblk_w * cblk_h); + } else if (cblk->decoded_data) { + /* Not sure if that code path can happen, but better be */ + /* safe than sorry */ + opj_aligned_free(cblk->decoded_data); + cblk->decoded_data = NULL; + } + + resno = job->resno; + band = job->band; + tilec = job->tilec; + tccp = job->tccp; + tile_w = (OPJ_UINT32)(tilec->resolutions[tilec->minimum_num_resolutions - 1].x1 + - + tilec->resolutions[tilec->minimum_num_resolutions - 1].x0); + + if (!*(job->pret)) { + opj_free(job); + return; + } + + t1 = (opj_t1_t*) opj_tls_get(tls, OPJ_TLS_KEY_T1); + if (t1 == NULL) { + t1 = opj_t1_create(OPJ_FALSE); + if (t1 == NULL) { + opj_event_msg(job->p_manager, EVT_ERROR, + "Cannot allocate Tier 1 handle\n"); + *(job->pret) = OPJ_FALSE; + opj_free(job); + return; + } + if (!opj_tls_set(tls, OPJ_TLS_KEY_T1, t1, opj_t1_destroy_wrapper)) { + opj_event_msg(job->p_manager, EVT_ERROR, + "Unable to set t1 handle as TLS\n"); + opj_t1_destroy(t1); + *(job->pret) = OPJ_FALSE; + opj_free(job); + return; + } + } + t1->mustuse_cblkdatabuffer = job->mustuse_cblkdatabuffer; + + if ((tccp->cblksty & J2K_CCP_CBLKSTY_HT) != 0) { + if (OPJ_FALSE == opj_t1_ht_decode_cblk( + t1, + cblk, + band->bandno, + (OPJ_UINT32)tccp->roishift, + tccp->cblksty, + job->p_manager, + job->p_manager_mutex, + job->check_pterm)) { + *(job->pret) = OPJ_FALSE; + opj_free(job); + return; + } + } else { + if (OPJ_FALSE == opj_t1_decode_cblk( + t1, + cblk, + band->bandno, + (OPJ_UINT32)tccp->roishift, + tccp->cblksty, + job->p_manager, + job->p_manager_mutex, + job->check_pterm)) { + *(job->pret) = OPJ_FALSE; + opj_free(job); + return; + } + } + + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + if (band->bandno & 1) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + x += pres->x1 - pres->x0; + } + if (band->bandno & 2) { + opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1]; + y += pres->y1 - pres->y0; + } + + datap = cblk->decoded_data ? cblk->decoded_data : t1->data; + cblk_w = t1->w; + cblk_h = t1->h; + + if (tccp->roishift) { + if (tccp->roishift >= 31) { + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + datap[(j * cblk_w) + i] = 0; + } + } + } else { + OPJ_INT32 thresh = 1 << tccp->roishift; + for (j = 0; j < cblk_h; ++j) { + for (i = 0; i < cblk_w; ++i) { + OPJ_INT32 val = datap[(j * cblk_w) + i]; + OPJ_INT32 mag = abs(val); + if (mag >= thresh) { + mag >>= tccp->roishift; + datap[(j * cblk_w) + i] = val < 0 ? -mag : mag; + } + } + } + } + } + + /* Both can be non NULL if for example decoding a full tile and then */ + /* partially a tile. In which case partial decoding should be the */ + /* priority */ + assert((cblk->decoded_data != NULL) || (tilec->data != NULL)); + + if (cblk->decoded_data) { + OPJ_UINT32 cblk_size = cblk_w * cblk_h; + if (tccp->qmfbid == 1) { + for (i = 0; i < cblk_size; ++i) { + datap[i] /= 2; + } + } else { /* if (tccp->qmfbid == 0) */ + const float stepsize = 0.5f * band->stepsize; + i = 0; +#ifdef __SSE2__ + { + const __m128 xmm_stepsize = _mm_set1_ps(stepsize); + for (; i < (cblk_size & ~15U); i += 16) { + __m128 xmm0_data = _mm_cvtepi32_ps(_mm_load_si128((__m128i * const)( + datap + 0))); + __m128 xmm1_data = _mm_cvtepi32_ps(_mm_load_si128((__m128i * const)( + datap + 4))); + __m128 xmm2_data = _mm_cvtepi32_ps(_mm_load_si128((__m128i * const)( + datap + 8))); + __m128 xmm3_data = _mm_cvtepi32_ps(_mm_load_si128((__m128i * const)( + datap + 12))); + _mm_store_ps((float*)(datap + 0), _mm_mul_ps(xmm0_data, xmm_stepsize)); + _mm_store_ps((float*)(datap + 4), _mm_mul_ps(xmm1_data, xmm_stepsize)); + _mm_store_ps((float*)(datap + 8), _mm_mul_ps(xmm2_data, xmm_stepsize)); + _mm_store_ps((float*)(datap + 12), _mm_mul_ps(xmm3_data, xmm_stepsize)); + datap += 16; + } + } +#endif + for (; i < cblk_size; ++i) { + OPJ_FLOAT32 tmp = ((OPJ_FLOAT32)(*datap)) * stepsize; + memcpy(datap, &tmp, sizeof(tmp)); + datap++; + } + } + } else if (tccp->qmfbid == 1) { + OPJ_INT32* OPJ_RESTRICT tiledp = &tilec->data[(OPJ_SIZE_T)y * tile_w + + (OPJ_SIZE_T)x]; + for (j = 0; j < cblk_h; ++j) { + //positive -> round down aka. (83)/2 = 41.5 -> 41 + //negative -> round up aka. (-83)/2 = -41.5 -> -41 +#if defined(__AVX512F__) + OPJ_INT32* ptr_in = datap + (j * cblk_w); + OPJ_INT32* ptr_out = tiledp + (j * (OPJ_SIZE_T)tile_w); + for (i = 0; i < cblk_w / 16; ++i) { + __m512i in_avx = _mm512_loadu_si512((__m512i*)(ptr_in)); + const __m512i add_avx = _mm512_srli_epi32(in_avx, 31); + in_avx = _mm512_add_epi32(in_avx, add_avx); + _mm512_storeu_si512((__m512i*)(ptr_out), _mm512_srai_epi32(in_avx, 1)); + ptr_in += 16; + ptr_out += 16; + } + + for (i = 0; i < cblk_w % 16; ++i) { + ptr_out[i] = ptr_in[i] / 2; + } +#elif defined(__AVX2__) + OPJ_INT32* ptr_in = datap + (j * cblk_w); + OPJ_INT32* ptr_out = tiledp + (j * (OPJ_SIZE_T)tile_w); + for (i = 0; i < cblk_w / 8; ++i) { + __m256i in_avx = _mm256_loadu_si256((__m256i*)(ptr_in)); + const __m256i add_avx = _mm256_srli_epi32(in_avx, 31); + in_avx = _mm256_add_epi32(in_avx, add_avx); + _mm256_storeu_si256((__m256i*)(ptr_out), _mm256_srai_epi32(in_avx, 1)); + ptr_in += 8; + ptr_out += 8; + } + + for (i = 0; i < cblk_w % 8; ++i) { + ptr_out[i] = ptr_in[i] / 2; + } +#else + i = 0; + for (; i < (cblk_w & ~(OPJ_UINT32)3U); i += 4U) { + OPJ_INT32 tmp0 = datap[(j * cblk_w) + i + 0U]; + OPJ_INT32 tmp1 = datap[(j * cblk_w) + i + 1U]; + OPJ_INT32 tmp2 = datap[(j * cblk_w) + i + 2U]; + OPJ_INT32 tmp3 = datap[(j * cblk_w) + i + 3U]; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i + 0U] = tmp0 / 2; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i + 1U] = tmp1 / 2; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i + 2U] = tmp2 / 2; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i + 3U] = tmp3 / 2; + } + for (; i < cblk_w; ++i) { + OPJ_INT32 tmp = datap[(j * cblk_w) + i]; + ((OPJ_INT32*)tiledp)[(j * (OPJ_SIZE_T)tile_w) + i] = tmp / 2; + } +#endif + } + } else { /* if (tccp->qmfbid == 0) */ + const float stepsize = 0.5f * band->stepsize; + OPJ_FLOAT32* OPJ_RESTRICT tiledp = (OPJ_FLOAT32*) &tilec->data[(OPJ_SIZE_T)y * + tile_w + (OPJ_SIZE_T)x]; + for (j = 0; j < cblk_h; ++j) { + OPJ_FLOAT32* OPJ_RESTRICT tiledp2 = tiledp; + for (i = 0; i < cblk_w; ++i) { + OPJ_FLOAT32 tmp = (OPJ_FLOAT32) * datap * stepsize; + *tiledp2 = tmp; + datap++; + tiledp2++; + } + tiledp += tile_w; + } + } + + opj_free(job); +} + + +void opj_t1_decode_cblks(opj_tcd_t* tcd, + volatile OPJ_BOOL* pret, + opj_tcd_tilecomp_t* tilec, + opj_tccp_t* tccp, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm + ) +{ + opj_thread_pool_t* tp = tcd->thread_pool; + OPJ_UINT32 resno, bandno, precno, cblkno; + +#ifdef DEBUG_VERBOSE + OPJ_UINT32 codeblocks_decoded = 0; + printf("Enter opj_t1_decode_cblks()\n"); +#endif + + for (resno = 0; resno < tilec->minimum_num_resolutions; ++resno) { + opj_tcd_resolution_t* res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* OPJ_RESTRICT band = &res->bands[bandno]; + + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t* precinct = &band->precincts[precno]; + + if (!opj_tcd_is_subband_area_of_interest(tcd, + tilec->compno, + resno, + band->bandno, + (OPJ_UINT32)precinct->x0, + (OPJ_UINT32)precinct->y0, + (OPJ_UINT32)precinct->x1, + (OPJ_UINT32)precinct->y1)) { + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; + if (cblk->decoded_data) { +#ifdef DEBUG_VERBOSE + printf("Discarding codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + opj_aligned_free(cblk->decoded_data); + cblk->decoded_data = NULL; + } + } + continue; + } + + for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) { + opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; + opj_t1_cblk_decode_processing_job_t* job; + + if (!opj_tcd_is_subband_area_of_interest(tcd, + tilec->compno, + resno, + band->bandno, + (OPJ_UINT32)cblk->x0, + (OPJ_UINT32)cblk->y0, + (OPJ_UINT32)cblk->x1, + (OPJ_UINT32)cblk->y1)) { + if (cblk->decoded_data) { +#ifdef DEBUG_VERBOSE + printf("Discarding codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + opj_aligned_free(cblk->decoded_data); + cblk->decoded_data = NULL; + } + continue; + } + + if (!tcd->whole_tile_decoding) { + OPJ_UINT32 cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0); + OPJ_UINT32 cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0); + if (cblk->decoded_data != NULL) { +#ifdef DEBUG_VERBOSE + printf("Reusing codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + continue; + } + if (cblk_w == 0 || cblk_h == 0) { + continue; + } +#ifdef DEBUG_VERBOSE + printf("Decoding codeblock %d,%d at resno=%d, bandno=%d\n", + cblk->x0, cblk->y0, resno, bandno); +#endif + } + + job = (opj_t1_cblk_decode_processing_job_t*) opj_calloc(1, + sizeof(opj_t1_cblk_decode_processing_job_t)); + if (!job) { + *pret = OPJ_FALSE; + return; + } + job->whole_tile_decoding = tcd->whole_tile_decoding; + job->resno = resno; + job->cblk = cblk; + job->band = band; + job->tilec = tilec; + job->tccp = tccp; + job->pret = pret; + job->p_manager_mutex = p_manager_mutex; + job->p_manager = p_manager; + job->check_pterm = check_pterm; + job->mustuse_cblkdatabuffer = opj_thread_pool_get_thread_count(tp) > 1; + opj_thread_pool_submit_job(tp, opj_t1_clbl_decode_processor, job); +#ifdef DEBUG_VERBOSE + codeblocks_decoded ++; +#endif + if (!(*pret)) { + return; + } + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ + +#ifdef DEBUG_VERBOSE + printf("Leave opj_t1_decode_cblks(). Number decoded: %d\n", codeblocks_decoded); +#endif + return; +} + + +static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1, + opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 roishift, + OPJ_UINT32 cblksty, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm) +{ + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + + OPJ_INT32 bpno_plus_one; + OPJ_UINT32 passtype; + OPJ_UINT32 segno, passno; + OPJ_BYTE* cblkdata = NULL; + OPJ_UINT32 cblkdataindex = 0; + OPJ_BYTE type = T1_TYPE_MQ; /* BYPASS mode */ + OPJ_INT32* original_t1_data = NULL; + + mqc->lut_ctxno_zc_orient = lut_ctxno_zc + (orient << 9); + + if (!opj_t1_allocate_buffers( + t1, + (OPJ_UINT32)(cblk->x1 - cblk->x0), + (OPJ_UINT32)(cblk->y1 - cblk->y0))) { + return OPJ_FALSE; + } + + bpno_plus_one = (OPJ_INT32)(roishift + cblk->numbps); + if (bpno_plus_one >= 31) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, + "opj_t1_decode_cblk(): unsupported bpno_plus_one = %d >= 31\n", + bpno_plus_one); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + return OPJ_FALSE; + } + passtype = 2; + + opj_mqc_resetstates(mqc); + opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + + if (cblk->corrupted) { + assert(cblk->numchunks == 0); + return OPJ_TRUE; + } + + /* Even if we have a single chunk, in multi-threaded decoding */ + /* the insertion of our synthetic marker might potentially override */ + /* valid codestream of other codeblocks decoded in parallel. */ + if (cblk->numchunks > 1 || (t1->mustuse_cblkdatabuffer && + cblk->numchunks > 0)) { + OPJ_UINT32 i; + OPJ_UINT32 cblk_len; + + /* Compute whole codeblock length from chunk lengths */ + cblk_len = 0; + for (i = 0; i < cblk->numchunks; i++) { + cblk_len += cblk->chunks[i].len; + } + + /* Allocate temporary memory if needed */ + if (cblk_len + OPJ_COMMON_CBLK_DATA_EXTRA > t1->cblkdatabuffersize) { + cblkdata = (OPJ_BYTE*)opj_realloc(t1->cblkdatabuffer, + cblk_len + OPJ_COMMON_CBLK_DATA_EXTRA); + if (cblkdata == NULL) { + return OPJ_FALSE; + } + t1->cblkdatabuffer = cblkdata; + memset(t1->cblkdatabuffer + cblk_len, 0, OPJ_COMMON_CBLK_DATA_EXTRA); + t1->cblkdatabuffersize = cblk_len + OPJ_COMMON_CBLK_DATA_EXTRA; + } + + /* Concatenate all chunks */ + cblkdata = t1->cblkdatabuffer; + cblk_len = 0; + for (i = 0; i < cblk->numchunks; i++) { + memcpy(cblkdata + cblk_len, cblk->chunks[i].data, cblk->chunks[i].len); + cblk_len += cblk->chunks[i].len; + } + } else if (cblk->numchunks == 1) { + cblkdata = cblk->chunks[0].data; + } else { + /* Not sure if that can happen in practice, but avoid Coverity to */ + /* think we will dereference a null cblkdta pointer */ + return OPJ_TRUE; + } + + /* For subtile decoding, directly decode in the decoded_data buffer of */ + /* the code-block. Hack t1->data to point to it, and restore it later */ + if (cblk->decoded_data) { + original_t1_data = t1->data; + t1->data = cblk->decoded_data; + } + + for (segno = 0; segno < cblk->real_num_segs; ++segno) { + opj_tcd_seg_t *seg = &cblk->segs[segno]; + + /* BYPASS mode */ + type = ((bpno_plus_one <= ((OPJ_INT32)(cblk->numbps)) - 4) && (passtype < 2) && + (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + + if (type == T1_TYPE_RAW) { + opj_mqc_raw_init_dec(mqc, cblkdata + cblkdataindex, seg->len, + OPJ_COMMON_CBLK_DATA_EXTRA); + } else { + opj_mqc_init_dec(mqc, cblkdata + cblkdataindex, seg->len, + OPJ_COMMON_CBLK_DATA_EXTRA); + } + cblkdataindex += seg->len; + + for (passno = 0; (passno < seg->real_num_passes) && + (bpno_plus_one >= 1); ++passno) { + switch (passtype) { + case 0: + if (type == T1_TYPE_RAW) { + opj_t1_dec_sigpass_raw(t1, bpno_plus_one, (OPJ_INT32)cblksty); + } else { + opj_t1_dec_sigpass_mqc(t1, bpno_plus_one, (OPJ_INT32)cblksty); + } + break; + case 1: + if (type == T1_TYPE_RAW) { + opj_t1_dec_refpass_raw(t1, bpno_plus_one); + } else { + opj_t1_dec_refpass_mqc(t1, bpno_plus_one); + } + break; + case 2: + opj_t1_dec_clnpass(t1, bpno_plus_one, (OPJ_INT32)cblksty); + break; + } + + if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { + opj_mqc_resetstates(mqc); + opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + } + if (++passtype == 3) { + passtype = 0; + bpno_plus_one--; + } + } + + opq_mqc_finish_dec(mqc); + } + + if (check_pterm) { + if (mqc->bp + 2 < mqc->end) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, + "PTERM check failure: %d remaining bytes in code block (%d used / %d)\n", + (int)(mqc->end - mqc->bp) - 2, + (int)(mqc->bp - mqc->start), + (int)(mqc->end - mqc->start)); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + } else if (mqc->end_of_byte_stream_counter > 2) { + if (p_manager_mutex) { + opj_mutex_lock(p_manager_mutex); + } + opj_event_msg(p_manager, EVT_WARNING, + "PTERM check failure: %d synthesized 0xFF markers read\n", + mqc->end_of_byte_stream_counter); + if (p_manager_mutex) { + opj_mutex_unlock(p_manager_mutex); + } + } + } + + /* Restore original t1->data is needed */ + if (cblk->decoded_data) { + t1->data = original_t1_data; + } + + return OPJ_TRUE; +} + + +typedef struct { + OPJ_UINT32 compno; + OPJ_UINT32 resno; + opj_tcd_cblk_enc_t* cblk; + opj_tcd_tile_t *tile; + opj_tcd_band_t* band; + opj_tcd_tilecomp_t* tilec; + opj_tccp_t* tccp; + const OPJ_FLOAT64 * mct_norms; + OPJ_UINT32 mct_numcomps; + volatile OPJ_BOOL* pret; + opj_mutex_t* mutex; +} opj_t1_cblk_encode_processing_job_t; + +/** Procedure to deal with a asynchronous code-block encoding job. + * + * @param user_data Pointer to a opj_t1_cblk_encode_processing_job_t* structure + * @param tls TLS handle. + */ +static void opj_t1_cblk_encode_processor(void* user_data, opj_tls_t* tls) +{ + opj_t1_cblk_encode_processing_job_t* job = + (opj_t1_cblk_encode_processing_job_t*)user_data; + opj_tcd_cblk_enc_t* cblk = job->cblk; + const opj_tcd_band_t* band = job->band; + const opj_tcd_tilecomp_t* tilec = job->tilec; + const opj_tccp_t* tccp = job->tccp; + const OPJ_UINT32 resno = job->resno; + opj_t1_t* t1; + const OPJ_UINT32 tile_w = (OPJ_UINT32)(tilec->x1 - tilec->x0); + + OPJ_INT32* OPJ_RESTRICT tiledp; + OPJ_UINT32 cblk_w; + OPJ_UINT32 cblk_h; + OPJ_UINT32 i, j; + + OPJ_INT32 x = cblk->x0 - band->x0; + OPJ_INT32 y = cblk->y0 - band->y0; + + if (!*(job->pret)) { + opj_free(job); + return; + } + + t1 = (opj_t1_t*) opj_tls_get(tls, OPJ_TLS_KEY_T1); + if (t1 == NULL) { + t1 = opj_t1_create(OPJ_TRUE); /* OPJ_TRUE == T1 for encoding */ + opj_tls_set(tls, OPJ_TLS_KEY_T1, t1, opj_t1_destroy_wrapper); + } + + if (band->bandno & 1) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x += pres->x1 - pres->x0; + } + if (band->bandno & 2) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + y += pres->y1 - pres->y0; + } + + if (!opj_t1_allocate_buffers( + t1, + (OPJ_UINT32)(cblk->x1 - cblk->x0), + (OPJ_UINT32)(cblk->y1 - cblk->y0))) { + *(job->pret) = OPJ_FALSE; + opj_free(job); + return; + } + + cblk_w = t1->w; + cblk_h = t1->h; + + tiledp = &tilec->data[(OPJ_SIZE_T)y * tile_w + (OPJ_SIZE_T)x]; + + if (tccp->qmfbid == 1) { + /* Do multiplication on unsigned type, even if the + * underlying type is signed, to avoid potential + * int overflow on large value (the output will be + * incorrect in such situation, but whatever...) + * This assumes complement-to-2 signed integer + * representation + * Fixes https://github.com/uclouvain/openjpeg/issues/1053 + */ + OPJ_UINT32* OPJ_RESTRICT tiledp_u = (OPJ_UINT32*) tiledp; + OPJ_UINT32* OPJ_RESTRICT t1data = (OPJ_UINT32*) t1->data; + /* Change from "natural" order to "zigzag" order of T1 passes */ + for (j = 0; j < (cblk_h & ~3U); j += 4) { +#if defined(__AVX512F__) + const __m512i perm1 = _mm512_setr_epi64(2, 3, 10, 11, 4, 5, 12, 13); + const __m512i perm2 = _mm512_setr_epi64(6, 7, 14, 15, 0, 0, 0, 0); + OPJ_UINT32* ptr = tiledp_u; + for (i = 0; i < cblk_w / 16; ++i) { + // INPUT OUTPUT + // 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33 + // 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37 + // 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B + // 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F + __m512i in1 = _mm512_slli_epi32(_mm512_loadu_si512((__m512i*)(ptr + + (j + 0) * tile_w)), T1_NMSEDEC_FRACBITS); + __m512i in2 = _mm512_slli_epi32(_mm512_loadu_si512((__m512i*)(ptr + + (j + 1) * tile_w)), T1_NMSEDEC_FRACBITS); + __m512i in3 = _mm512_slli_epi32(_mm512_loadu_si512((__m512i*)(ptr + + (j + 2) * tile_w)), T1_NMSEDEC_FRACBITS); + __m512i in4 = _mm512_slli_epi32(_mm512_loadu_si512((__m512i*)(ptr + + (j + 3) * tile_w)), T1_NMSEDEC_FRACBITS); + + __m512i tmp1 = _mm512_unpacklo_epi32(in1, in2); + __m512i tmp2 = _mm512_unpacklo_epi32(in3, in4); + __m512i tmp3 = _mm512_unpackhi_epi32(in1, in2); + __m512i tmp4 = _mm512_unpackhi_epi32(in3, in4); + + in1 = _mm512_unpacklo_epi64(tmp1, tmp2); + in2 = _mm512_unpacklo_epi64(tmp3, tmp4); + in3 = _mm512_unpackhi_epi64(tmp1, tmp2); + in4 = _mm512_unpackhi_epi64(tmp3, tmp4); + + _mm_storeu_si128((__m128i*)(t1data + 0), _mm512_castsi512_si128(in1)); + _mm_storeu_si128((__m128i*)(t1data + 4), _mm512_castsi512_si128(in3)); + _mm_storeu_si128((__m128i*)(t1data + 8), _mm512_castsi512_si128(in2)); + _mm_storeu_si128((__m128i*)(t1data + 12), _mm512_castsi512_si128(in4)); + + tmp1 = _mm512_permutex2var_epi64(in1, perm1, in3); + tmp2 = _mm512_permutex2var_epi64(in2, perm1, in4); + + _mm256_storeu_si256((__m256i*)(t1data + 16), _mm512_castsi512_si256(tmp1)); + _mm256_storeu_si256((__m256i*)(t1data + 24), _mm512_castsi512_si256(tmp2)); + _mm256_storeu_si256((__m256i*)(t1data + 32), _mm512_extracti64x4_epi64(tmp1, + 0x1)); + _mm256_storeu_si256((__m256i*)(t1data + 40), _mm512_extracti64x4_epi64(tmp2, + 0x1)); + _mm256_storeu_si256((__m256i*)(t1data + 48), + _mm512_castsi512_si256(_mm512_permutex2var_epi64(in1, perm2, in3))); + _mm256_storeu_si256((__m256i*)(t1data + 56), + _mm512_castsi512_si256(_mm512_permutex2var_epi64(in2, perm2, in4))); + t1data += 64; + ptr += 16; + } + for (i = 0; i < cblk_w % 16; ++i) { + t1data[0] = ptr[(j + 0) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[1] = ptr[(j + 1) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[2] = ptr[(j + 2) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[3] = ptr[(j + 3) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data += 4; + ptr += 1; + } +#elif defined(__AVX2__) + OPJ_UINT32* ptr = tiledp_u; + for (i = 0; i < cblk_w / 8; ++i) { + // INPUT OUTPUT + // 00 01 02 03 04 05 06 07 00 10 20 30 01 11 21 31 + // 10 11 12 13 14 15 16 17 02 12 22 32 03 13 23 33 + // 20 21 22 23 24 25 26 27 04 14 24 34 05 15 25 35 + // 30 31 32 33 34 35 36 37 06 16 26 36 07 17 27 37 + __m256i in1 = _mm256_slli_epi32(_mm256_loadu_si256((__m256i*)(ptr + + (j + 0) * tile_w)), T1_NMSEDEC_FRACBITS); + __m256i in2 = _mm256_slli_epi32(_mm256_loadu_si256((__m256i*)(ptr + + (j + 1) * tile_w)), T1_NMSEDEC_FRACBITS); + __m256i in3 = _mm256_slli_epi32(_mm256_loadu_si256((__m256i*)(ptr + + (j + 2) * tile_w)), T1_NMSEDEC_FRACBITS); + __m256i in4 = _mm256_slli_epi32(_mm256_loadu_si256((__m256i*)(ptr + + (j + 3) * tile_w)), T1_NMSEDEC_FRACBITS); + + __m256i tmp1 = _mm256_unpacklo_epi32(in1, in2); + __m256i tmp2 = _mm256_unpacklo_epi32(in3, in4); + __m256i tmp3 = _mm256_unpackhi_epi32(in1, in2); + __m256i tmp4 = _mm256_unpackhi_epi32(in3, in4); + + in1 = _mm256_unpacklo_epi64(tmp1, tmp2); + in2 = _mm256_unpacklo_epi64(tmp3, tmp4); + in3 = _mm256_unpackhi_epi64(tmp1, tmp2); + in4 = _mm256_unpackhi_epi64(tmp3, tmp4); + + _mm_storeu_si128((__m128i*)(t1data + 0), _mm256_castsi256_si128(in1)); + _mm_storeu_si128((__m128i*)(t1data + 4), _mm256_castsi256_si128(in3)); + _mm_storeu_si128((__m128i*)(t1data + 8), _mm256_castsi256_si128(in2)); + _mm_storeu_si128((__m128i*)(t1data + 12), _mm256_castsi256_si128(in4)); + _mm256_storeu_si256((__m256i*)(t1data + 16), _mm256_permute2x128_si256(in1, in3, + 0x31)); + _mm256_storeu_si256((__m256i*)(t1data + 24), _mm256_permute2x128_si256(in2, in4, + 0x31)); + t1data += 32; + ptr += 8; + } + for (i = 0; i < cblk_w % 8; ++i) { + t1data[0] = ptr[(j + 0) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[1] = ptr[(j + 1) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[2] = ptr[(j + 2) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data[3] = ptr[(j + 3) * tile_w] << T1_NMSEDEC_FRACBITS; + t1data += 4; + ptr += 1; + } +#else + for (i = 0; i < cblk_w; ++i) { + t1data[0] = tiledp_u[(j + 0) * tile_w + i] << T1_NMSEDEC_FRACBITS; + t1data[1] = tiledp_u[(j + 1) * tile_w + i] << T1_NMSEDEC_FRACBITS; + t1data[2] = tiledp_u[(j + 2) * tile_w + i] << T1_NMSEDEC_FRACBITS; + t1data[3] = tiledp_u[(j + 3) * tile_w + i] << T1_NMSEDEC_FRACBITS; + t1data += 4; + } +#endif + } + if (j < cblk_h) { + for (i = 0; i < cblk_w; ++i) { + OPJ_UINT32 k; + for (k = j; k < cblk_h; k++) { + t1data[0] = tiledp_u[k * tile_w + i] << T1_NMSEDEC_FRACBITS; + t1data ++; + } + } + } + } else { /* if (tccp->qmfbid == 0) */ + OPJ_FLOAT32* OPJ_RESTRICT tiledp_f = (OPJ_FLOAT32*) tiledp; + OPJ_INT32* OPJ_RESTRICT t1data = t1->data; + /* Change from "natural" order to "zigzag" order of T1 passes */ + for (j = 0; j < (cblk_h & ~3U); j += 4) { + for (i = 0; i < cblk_w; ++i) { + t1data[0] = (OPJ_INT32)opj_lrintf((tiledp_f[(j + 0) * tile_w + i] / + band->stepsize) * (1 << T1_NMSEDEC_FRACBITS)); + t1data[1] = (OPJ_INT32)opj_lrintf((tiledp_f[(j + 1) * tile_w + i] / + band->stepsize) * (1 << T1_NMSEDEC_FRACBITS)); + t1data[2] = (OPJ_INT32)opj_lrintf((tiledp_f[(j + 2) * tile_w + i] / + band->stepsize) * (1 << T1_NMSEDEC_FRACBITS)); + t1data[3] = (OPJ_INT32)opj_lrintf((tiledp_f[(j + 3) * tile_w + i] / + band->stepsize) * (1 << T1_NMSEDEC_FRACBITS)); + t1data += 4; + } + } + if (j < cblk_h) { + for (i = 0; i < cblk_w; ++i) { + OPJ_UINT32 k; + for (k = j; k < cblk_h; k++) { + t1data[0] = (OPJ_INT32)opj_lrintf((tiledp_f[k * tile_w + i] / band->stepsize) + * (1 << T1_NMSEDEC_FRACBITS)); + t1data ++; + } + } + } + } + + { + OPJ_FLOAT64 cumwmsedec = + opj_t1_encode_cblk( + t1, + cblk, + band->bandno, + job->compno, + tilec->numresolutions - 1 - resno, + tccp->qmfbid, + band->stepsize, + tccp->cblksty, + job->tile->numcomps, + job->mct_norms, + job->mct_numcomps); + if (job->mutex) { + opj_mutex_lock(job->mutex); + } + job->tile->distotile += cumwmsedec; + if (job->mutex) { + opj_mutex_unlock(job->mutex); + } + } + + opj_free(job); +} + + +OPJ_BOOL opj_t1_encode_cblks(opj_tcd_t* tcd, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps + ) +{ + volatile OPJ_BOOL ret = OPJ_TRUE; + opj_thread_pool_t* tp = tcd->thread_pool; + OPJ_UINT32 compno, resno, bandno, precno, cblkno; + opj_mutex_t* mutex = opj_mutex_create(); + + tile->distotile = 0; + + for (compno = 0; compno < tile->numcomps; ++compno) { + opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; + opj_tccp_t* tccp = &tcp->tccps[compno]; + + for (resno = 0; resno < tilec->numresolutions; ++resno) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* OPJ_RESTRICT band = &res->bands[bandno]; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + for (precno = 0; precno < res->pw * res->ph; ++precno) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) { + opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno]; + + opj_t1_cblk_encode_processing_job_t* job = + (opj_t1_cblk_encode_processing_job_t*) opj_calloc(1, + sizeof(opj_t1_cblk_encode_processing_job_t)); + if (!job) { + ret = OPJ_FALSE; + goto end; + } + job->compno = compno; + job->tile = tile; + job->resno = resno; + job->cblk = cblk; + job->band = band; + job->tilec = tilec; + job->tccp = tccp; + job->mct_norms = mct_norms; + job->mct_numcomps = mct_numcomps; + job->pret = &ret; + job->mutex = mutex; + opj_thread_pool_submit_job(tp, opj_t1_cblk_encode_processor, job); + + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ + +end: + opj_thread_pool_wait_completion(tcd->thread_pool, 0); + if (mutex) { + opj_mutex_destroy(mutex); + } + + return ret; +} + +/* Returns whether the pass (bpno, passtype) is terminated */ +static int opj_t1_enc_is_term_pass(opj_tcd_cblk_enc_t* cblk, + OPJ_UINT32 cblksty, + OPJ_INT32 bpno, + OPJ_UINT32 passtype) +{ + /* Is it the last cleanup pass ? */ + if (passtype == 2 && bpno == 0) { + return OPJ_TRUE; + } + + if (cblksty & J2K_CCP_CBLKSTY_TERMALL) { + return OPJ_TRUE; + } + + if ((cblksty & J2K_CCP_CBLKSTY_LAZY)) { + /* For bypass arithmetic bypass, terminate the 4th cleanup pass */ + if ((bpno == ((OPJ_INT32)cblk->numbps - 4)) && (passtype == 2)) { + return OPJ_TRUE; + } + /* and beyond terminate all the magnitude refinement passes (in raw) */ + /* and cleanup passes (in MQC) */ + if ((bpno < ((OPJ_INT32)(cblk->numbps) - 4)) && (passtype > 0)) { + return OPJ_TRUE; + } + } + + return OPJ_FALSE; +} + + +static OPJ_FLOAT64 opj_t1_encode_cblk(opj_t1_t *t1, + opj_tcd_cblk_enc_t* cblk, + OPJ_UINT32 orient, + OPJ_UINT32 compno, + OPJ_UINT32 level, + OPJ_UINT32 qmfbid, + OPJ_FLOAT64 stepsize, + OPJ_UINT32 cblksty, + OPJ_UINT32 numcomps, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps) +{ + OPJ_FLOAT64 cumwmsedec = 0.0; + + opj_mqc_t *mqc = &(t1->mqc); /* MQC component */ + + OPJ_UINT32 passno; + OPJ_INT32 bpno; + OPJ_UINT32 passtype; + OPJ_INT32 nmsedec = 0; + OPJ_INT32 max; + OPJ_UINT32 i, j; + OPJ_BYTE type = T1_TYPE_MQ; + OPJ_FLOAT64 tempwmsedec; + OPJ_INT32* datap; + +#ifdef EXTRA_DEBUG + printf("encode_cblk(x=%d,y=%d,x1=%d,y1=%d,orient=%d,compno=%d,level=%d\n", + cblk->x0, cblk->y0, cblk->x1, cblk->y1, orient, compno, level); +#endif + + mqc->lut_ctxno_zc_orient = lut_ctxno_zc + (orient << 9); + + max = 0; + datap = t1->data; + for (j = 0; j < t1->h; ++j) { + const OPJ_UINT32 w = t1->w; + for (i = 0; i < w; ++i, ++datap) { + OPJ_INT32 tmp = *datap; + if (tmp < 0) { + OPJ_UINT32 tmp_unsigned; + if (tmp == INT_MIN) { + /* To avoid undefined behaviour when negating INT_MIN */ + /* but if we go here, it means we have supplied an input */ + /* with more bit depth than we we can really support. */ + /* Cf https://github.com/uclouvain/openjpeg/issues/1432 */ + tmp = INT_MIN + 1; + } + max = opj_int_max(max, -tmp); + tmp_unsigned = opj_to_smr(tmp); + memcpy(datap, &tmp_unsigned, sizeof(OPJ_INT32)); + } else { + max = opj_int_max(max, tmp); + } + } + } + + cblk->numbps = max ? (OPJ_UINT32)((opj_int_floorlog2(max) + 1) - + T1_NMSEDEC_FRACBITS) : 0; + if (cblk->numbps == 0) { + cblk->totalpasses = 0; + return cumwmsedec; + } + + bpno = (OPJ_INT32)(cblk->numbps - 1); + passtype = 2; + + opj_mqc_resetstates(mqc); + opj_mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); + opj_mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); + opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); + opj_mqc_init_enc(mqc, cblk->data); + + for (passno = 0; bpno >= 0; ++passno) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + type = ((bpno < ((OPJ_INT32)(cblk->numbps) - 4)) && (passtype < 2) && + (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + + /* If the previous pass was terminating, we need to reset the encoder */ + if (passno > 0 && cblk->passes[passno - 1].term) { + if (type == T1_TYPE_RAW) { + opj_mqc_bypass_init_enc(mqc); + } else { + opj_mqc_restart_init_enc(mqc); + } + } + + switch (passtype) { + case 0: + opj_t1_enc_sigpass(t1, bpno, &nmsedec, type, cblksty); + break; + case 1: + opj_t1_enc_refpass(t1, bpno, &nmsedec, type); + break; + case 2: + opj_t1_enc_clnpass(t1, bpno, &nmsedec, cblksty); + /* code switch SEGMARK (i.e. SEGSYM) */ + if (cblksty & J2K_CCP_CBLKSTY_SEGSYM) { + opj_mqc_segmark_enc(mqc); + } + break; + } + + tempwmsedec = opj_t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, + stepsize, numcomps, mct_norms, mct_numcomps) ; + cumwmsedec += tempwmsedec; + pass->distortiondec = cumwmsedec; + + if (opj_t1_enc_is_term_pass(cblk, cblksty, bpno, passtype)) { + /* If it is a terminated pass, terminate it */ + if (type == T1_TYPE_RAW) { + opj_mqc_bypass_flush_enc(mqc, cblksty & J2K_CCP_CBLKSTY_PTERM); + } else { + if (cblksty & J2K_CCP_CBLKSTY_PTERM) { + opj_mqc_erterm_enc(mqc); + } else { + opj_mqc_flush(mqc); + } + } + pass->term = 1; + pass->rate = opj_mqc_numbytes(mqc); + } else { + /* Non terminated pass */ + OPJ_UINT32 rate_extra_bytes; + if (type == T1_TYPE_RAW) { + rate_extra_bytes = opj_mqc_bypass_get_extra_bytes( + mqc, (cblksty & J2K_CCP_CBLKSTY_PTERM)); + } else { + rate_extra_bytes = 3; + } + pass->term = 0; + pass->rate = opj_mqc_numbytes(mqc) + rate_extra_bytes; + } + + if (++passtype == 3) { + passtype = 0; + bpno--; + } + + /* Code-switch "RESET" */ + if (cblksty & J2K_CCP_CBLKSTY_RESET) { + opj_mqc_reset_enc(mqc); + } + } + + cblk->totalpasses = passno; + + if (cblk->totalpasses) { + /* Make sure that pass rates are increasing */ + OPJ_UINT32 last_pass_rate = opj_mqc_numbytes(mqc); + for (passno = cblk->totalpasses; passno > 0;) { + opj_tcd_pass_t *pass = &cblk->passes[--passno]; + if (pass->rate > last_pass_rate) { + pass->rate = last_pass_rate; + } else { + last_pass_rate = pass->rate; + } + } + } + + for (passno = 0; passno < cblk->totalpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + + /* Prevent generation of FF as last data byte of a pass*/ + /* For terminating passes, the flushing procedure ensured this already */ + assert(pass->rate > 0); + if (cblk->data[pass->rate - 1] == 0xFF) { + pass->rate--; + } + pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate); + } + +#ifdef EXTRA_DEBUG + printf(" len=%d\n", (cblk->totalpasses) ? opj_mqc_numbytes(mqc) : 0); + + /* Check that there not 0xff >=0x90 sequences */ + if (cblk->totalpasses) { + OPJ_UINT32 i; + OPJ_UINT32 len = opj_mqc_numbytes(mqc); + for (i = 1; i < len; ++i) { + if (cblk->data[i - 1] == 0xff && cblk->data[i] >= 0x90) { + printf("0xff %02x at offset %d\n", cblk->data[i], i - 1); + abort(); + } + } + } +#endif + + return cumwmsedec; +} diff --git a/client/deps/openjpeg/t1.h b/client/deps/openjpeg/t1.h new file mode 100644 index 000000000..ce43658ba --- /dev/null +++ b/client/deps/openjpeg/t1.h @@ -0,0 +1,268 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2012, Carl Hetherington + * Copyright (c) 2017, IntoPIX SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_T1_H +#define OPJ_T1_H +/** +@file t1.h +@brief Implementation of the tier-1 coding (coding of code-block coefficients) (T1) + +The functions in T1.C have for goal to realize the tier-1 coding operation. The functions +in T1.C are used by some function in TCD.C. +*/ + +/** @defgroup T1 T1 - Implementation of the tier-1 coding */ +/*@{*/ + +/* ----------------------------------------------------------------------- */ +#define T1_NMSEDEC_BITS 7 + +#define T1_NUMCTXS_ZC 9 +#define T1_NUMCTXS_SC 5 +#define T1_NUMCTXS_MAG 3 +#define T1_NUMCTXS_AGG 1 +#define T1_NUMCTXS_UNI 1 + +#define T1_CTXNO_ZC 0 +#define T1_CTXNO_SC (T1_CTXNO_ZC+T1_NUMCTXS_ZC) +#define T1_CTXNO_MAG (T1_CTXNO_SC+T1_NUMCTXS_SC) +#define T1_CTXNO_AGG (T1_CTXNO_MAG+T1_NUMCTXS_MAG) +#define T1_CTXNO_UNI (T1_CTXNO_AGG+T1_NUMCTXS_AGG) +#define T1_NUMCTXS (T1_CTXNO_UNI+T1_NUMCTXS_UNI) + +#define T1_NMSEDEC_FRACBITS (T1_NMSEDEC_BITS-1) + +#define T1_TYPE_MQ 0 /**< Normal coding using entropy coder */ +#define T1_TYPE_RAW 1 /**< No encoding the information is store under raw format in codestream (mode switch RAW)*/ + +/* BEGINNING of flags that apply to opj_flag_t */ +/** We hold the state of individual data points for the T1 encoder using + * a single 32-bit flags word to hold the state of 4 data points. This corresponds + * to the 4-point-high columns that the data is processed in. + * + * These \#defines declare the layout of a 32-bit flags word. + * + * This is currently done for encoding only. + * The values must NOT be changed, otherwise this is going to break a lot of + * assumptions. + */ + +/* SIGMA: significance state (3 cols x 6 rows) + * CHI: state for negative sample value (1 col x 6 rows) + * MU: state for visited in refinement pass (1 col x 4 rows) + * PI: state for visited in significance pass (1 col * 4 rows) + */ + +#define T1_SIGMA_0 (1U << 0) +#define T1_SIGMA_1 (1U << 1) +#define T1_SIGMA_2 (1U << 2) +#define T1_SIGMA_3 (1U << 3) +#define T1_SIGMA_4 (1U << 4) +#define T1_SIGMA_5 (1U << 5) +#define T1_SIGMA_6 (1U << 6) +#define T1_SIGMA_7 (1U << 7) +#define T1_SIGMA_8 (1U << 8) +#define T1_SIGMA_9 (1U << 9) +#define T1_SIGMA_10 (1U << 10) +#define T1_SIGMA_11 (1U << 11) +#define T1_SIGMA_12 (1U << 12) +#define T1_SIGMA_13 (1U << 13) +#define T1_SIGMA_14 (1U << 14) +#define T1_SIGMA_15 (1U << 15) +#define T1_SIGMA_16 (1U << 16) +#define T1_SIGMA_17 (1U << 17) + +#define T1_CHI_0 (1U << 18) +#define T1_CHI_0_I 18 +#define T1_CHI_1 (1U << 19) +#define T1_CHI_1_I 19 +#define T1_MU_0 (1U << 20) +#define T1_PI_0 (1U << 21) +#define T1_CHI_2 (1U << 22) +#define T1_CHI_2_I 22 +#define T1_MU_1 (1U << 23) +#define T1_PI_1 (1U << 24) +#define T1_CHI_3 (1U << 25) +#define T1_MU_2 (1U << 26) +#define T1_PI_2 (1U << 27) +#define T1_CHI_4 (1U << 28) +#define T1_MU_3 (1U << 29) +#define T1_PI_3 (1U << 30) +#define T1_CHI_5 (1U << 31) +#define T1_CHI_5_I 31 + +/** As an example, the bits T1_SIGMA_3, T1_SIGMA_4 and T1_SIGMA_5 + * indicate the significance state of the west neighbour of data point zero + * of our four, the point itself, and its east neighbour respectively. + * Many of the bits are arranged so that given a flags word, you can + * look at the values for the data point 0, then shift the flags + * word right by 3 bits and look at the same bit positions to see the + * values for data point 1. + * + * The \#defines below help a bit with this; say you have a flags word + * f, you can do things like + * + * (f & T1_SIGMA_THIS) + * + * to see the significance bit of data point 0, then do + * + * ((f >> 3) & T1_SIGMA_THIS) + * + * to see the significance bit of data point 1. + */ + +#define T1_SIGMA_NW T1_SIGMA_0 +#define T1_SIGMA_N T1_SIGMA_1 +#define T1_SIGMA_NE T1_SIGMA_2 +#define T1_SIGMA_W T1_SIGMA_3 +#define T1_SIGMA_THIS T1_SIGMA_4 +#define T1_SIGMA_E T1_SIGMA_5 +#define T1_SIGMA_SW T1_SIGMA_6 +#define T1_SIGMA_S T1_SIGMA_7 +#define T1_SIGMA_SE T1_SIGMA_8 +#define T1_SIGMA_NEIGHBOURS (T1_SIGMA_NW | T1_SIGMA_N | T1_SIGMA_NE | T1_SIGMA_W | T1_SIGMA_E | T1_SIGMA_SW | T1_SIGMA_S | T1_SIGMA_SE) + +#define T1_CHI_THIS T1_CHI_1 +#define T1_CHI_THIS_I T1_CHI_1_I +#define T1_MU_THIS T1_MU_0 +#define T1_PI_THIS T1_PI_0 +#define T1_CHI_S T1_CHI_2 + +#define T1_LUT_SGN_W (1U << 0) +#define T1_LUT_SIG_N (1U << 1) +#define T1_LUT_SGN_E (1U << 2) +#define T1_LUT_SIG_W (1U << 3) +#define T1_LUT_SGN_N (1U << 4) +#define T1_LUT_SIG_E (1U << 5) +#define T1_LUT_SGN_S (1U << 6) +#define T1_LUT_SIG_S (1U << 7) +/* END of flags that apply to opj_flag_t */ + +/* ----------------------------------------------------------------------- */ + +/** Flags for 4 consecutive rows of a column */ +typedef OPJ_UINT32 opj_flag_t; + +/** +Tier-1 coding (coding of code-block coefficients) +*/ +typedef struct opj_t1 { + + /** MQC component */ + opj_mqc_t mqc; + + OPJ_INT32 *data; + /** Flags used by decoder and encoder. + * Such that flags[1+0] is for state of col=0,row=0..3, + flags[1+1] for col=1, row=0..3, flags[1+flags_stride] for col=0,row=4..7, ... + This array avoids too much cache trashing when processing by 4 vertical samples + as done in the various decoding steps. */ + opj_flag_t *flags; + + OPJ_UINT32 w; + OPJ_UINT32 h; + OPJ_UINT32 datasize; + OPJ_UINT32 flagssize; + OPJ_BOOL encoder; + + /* The 3 variables below are only used by the decoder */ + /* set to TRUE in multithreaded context */ + OPJ_BOOL mustuse_cblkdatabuffer; + /* Temporary buffer to concatenate all chunks of a codebock */ + OPJ_BYTE *cblkdatabuffer; + /* Maximum size available in cblkdatabuffer */ + OPJ_UINT32 cblkdatabuffersize; +} opj_t1_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Encode the code-blocks of a tile +@param tcd TCD handle +@param tile The tile to encode +@param tcp Tile coding parameters +@param mct_norms FIXME DOC +@param mct_numcomps Number of components used for MCT +*/ +OPJ_BOOL opj_t1_encode_cblks(opj_tcd_t* tcd, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + const OPJ_FLOAT64 * mct_norms, + OPJ_UINT32 mct_numcomps); + +/** +Decode the code-blocks of a tile +@param tcd TCD handle +@param pret Pointer to return value +@param tilec The tile to decode +@param tccp Tile coding parameters +@param p_manager the event manager +@param p_manager_mutex mutex for the event manager +@param check_pterm whether PTERM correct termination should be checked +*/ +void opj_t1_decode_cblks(opj_tcd_t* tcd, + volatile OPJ_BOOL* pret, + opj_tcd_tilecomp_t* tilec, + opj_tccp_t* tccp, + opj_event_mgr_t *p_manager, + opj_mutex_t* p_manager_mutex, + OPJ_BOOL check_pterm); + + + +/** + * Creates a new Tier 1 handle + * and initializes the look-up tables of the Tier-1 coder/decoder + * @return a new T1 handle if successful, returns NULL otherwise +*/ +opj_t1_t* opj_t1_create(OPJ_BOOL isEncoder); + +/** + * Destroys a previously created T1 handle + * + * @param p_t1 Tier 1 handle to destroy +*/ +void opj_t1_destroy(opj_t1_t *p_t1); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_T1_H */ diff --git a/client/deps/openjpeg/t1_ht_luts.h b/client/deps/openjpeg/t1_ht_luts.h new file mode 100644 index 000000000..f39d5d057 --- /dev/null +++ b/client/deps/openjpeg/t1_ht_luts.h @@ -0,0 +1,261 @@ +static const OPJ_UINT16 vlc_tbl0[1024] = { + 0x0023, 0x00a5, 0x0043, 0x0066, 0x0083, 0xa8ee, 0x0014, 0xd8df, + 0x0023, 0x10be, 0x0043, 0xf5ff, 0x0083, 0x207e, 0x0055, 0x515f, + 0x0023, 0x0035, 0x0043, 0x444e, 0x0083, 0xc4ce, 0x0014, 0xcccf, + 0x0023, 0xe2fe, 0x0043, 0x99ff, 0x0083, 0x0096, 0x00c5, 0x313f, + 0x0023, 0x00a5, 0x0043, 0x445e, 0x0083, 0xc8ce, 0x0014, 0x11df, + 0x0023, 0xf4fe, 0x0043, 0xfcff, 0x0083, 0x009e, 0x0055, 0x0077, + 0x0023, 0x0035, 0x0043, 0xf1ff, 0x0083, 0x88ae, 0x0014, 0x00b7, + 0x0023, 0xf8fe, 0x0043, 0xe4ef, 0x0083, 0x888e, 0x00c5, 0x111f, + 0x0023, 0x00a5, 0x0043, 0x0066, 0x0083, 0xa8ee, 0x0014, 0x54df, + 0x0023, 0x10be, 0x0043, 0x22ef, 0x0083, 0x207e, 0x0055, 0x227f, + 0x0023, 0x0035, 0x0043, 0x444e, 0x0083, 0xc4ce, 0x0014, 0x11bf, + 0x0023, 0xe2fe, 0x0043, 0x00f7, 0x0083, 0x0096, 0x00c5, 0x223f, + 0x0023, 0x00a5, 0x0043, 0x445e, 0x0083, 0xc8ce, 0x0014, 0x00d7, + 0x0023, 0xf4fe, 0x0043, 0xbaff, 0x0083, 0x009e, 0x0055, 0x006f, + 0x0023, 0x0035, 0x0043, 0xe6ff, 0x0083, 0x88ae, 0x0014, 0xa2af, + 0x0023, 0xf8fe, 0x0043, 0x00e7, 0x0083, 0x888e, 0x00c5, 0x222f, + 0x0002, 0x00c5, 0x0084, 0x207e, 0x0002, 0xc4ce, 0x0024, 0x00f7, + 0x0002, 0xa2fe, 0x0044, 0x0056, 0x0002, 0x009e, 0x0014, 0x00d7, + 0x0002, 0x10be, 0x0084, 0x0066, 0x0002, 0x88ae, 0x0024, 0x11df, + 0x0002, 0xa8ee, 0x0044, 0x0036, 0x0002, 0x888e, 0x0014, 0x111f, + 0x0002, 0x00c5, 0x0084, 0x006e, 0x0002, 0x88ce, 0x0024, 0x88ff, + 0x0002, 0xb8fe, 0x0044, 0x444e, 0x0002, 0x0096, 0x0014, 0x00b7, + 0x0002, 0xe4fe, 0x0084, 0x445e, 0x0002, 0x00a6, 0x0024, 0x00e7, + 0x0002, 0x54de, 0x0044, 0x222e, 0x0002, 0x003e, 0x0014, 0x0077, + 0x0002, 0x00c5, 0x0084, 0x207e, 0x0002, 0xc4ce, 0x0024, 0xf1ff, + 0x0002, 0xa2fe, 0x0044, 0x0056, 0x0002, 0x009e, 0x0014, 0x11bf, + 0x0002, 0x10be, 0x0084, 0x0066, 0x0002, 0x88ae, 0x0024, 0x22ef, + 0x0002, 0xa8ee, 0x0044, 0x0036, 0x0002, 0x888e, 0x0014, 0x227f, + 0x0002, 0x00c5, 0x0084, 0x006e, 0x0002, 0x88ce, 0x0024, 0xe4ef, + 0x0002, 0xb8fe, 0x0044, 0x444e, 0x0002, 0x0096, 0x0014, 0xa2af, + 0x0002, 0xe4fe, 0x0084, 0x445e, 0x0002, 0x00a6, 0x0024, 0xd8df, + 0x0002, 0x54de, 0x0044, 0x222e, 0x0002, 0x003e, 0x0014, 0x515f, + 0x0002, 0x0055, 0x0084, 0x0066, 0x0002, 0x88de, 0x0024, 0x32ff, + 0x0002, 0x11fe, 0x0044, 0x444e, 0x0002, 0x00ae, 0x0014, 0x00b7, + 0x0002, 0x317e, 0x0084, 0x515e, 0x0002, 0x00c6, 0x0024, 0x00d7, + 0x0002, 0x20ee, 0x0044, 0x111e, 0x0002, 0x009e, 0x0014, 0x0077, + 0x0002, 0x0055, 0x0084, 0x545e, 0x0002, 0x44ce, 0x0024, 0x00e7, + 0x0002, 0xf1fe, 0x0044, 0x0036, 0x0002, 0x00a6, 0x0014, 0x555f, + 0x0002, 0x74fe, 0x0084, 0x113e, 0x0002, 0x20be, 0x0024, 0x747f, + 0x0002, 0xc4de, 0x0044, 0xf8ff, 0x0002, 0x0096, 0x0014, 0x222f, + 0x0002, 0x0055, 0x0084, 0x0066, 0x0002, 0x88de, 0x0024, 0x00f7, + 0x0002, 0x11fe, 0x0044, 0x444e, 0x0002, 0x00ae, 0x0014, 0x888f, + 0x0002, 0x317e, 0x0084, 0x515e, 0x0002, 0x00c6, 0x0024, 0xc8cf, + 0x0002, 0x20ee, 0x0044, 0x111e, 0x0002, 0x009e, 0x0014, 0x006f, + 0x0002, 0x0055, 0x0084, 0x545e, 0x0002, 0x44ce, 0x0024, 0xd1df, + 0x0002, 0xf1fe, 0x0044, 0x0036, 0x0002, 0x00a6, 0x0014, 0x227f, + 0x0002, 0x74fe, 0x0084, 0x113e, 0x0002, 0x20be, 0x0024, 0x22bf, + 0x0002, 0xc4de, 0x0044, 0x22ef, 0x0002, 0x0096, 0x0014, 0x323f, + 0x0003, 0xd4de, 0xf4fd, 0xfcff, 0x0014, 0x113e, 0x0055, 0x888f, + 0x0003, 0x32be, 0x0085, 0x00e7, 0x0025, 0x515e, 0xaafe, 0x727f, + 0x0003, 0x44ce, 0xf8fd, 0x44ef, 0x0014, 0x647e, 0x0045, 0xa2af, + 0x0003, 0x00a6, 0x555d, 0x99df, 0xf1fd, 0x0036, 0xf5fe, 0x626f, + 0x0003, 0xd1de, 0xf4fd, 0xe6ff, 0x0014, 0x717e, 0x0055, 0xb1bf, + 0x0003, 0x88ae, 0x0085, 0xd5df, 0x0025, 0x444e, 0xf2fe, 0x667f, + 0x0003, 0x00c6, 0xf8fd, 0xe2ef, 0x0014, 0x545e, 0x0045, 0x119f, + 0x0003, 0x0096, 0x555d, 0xc8cf, 0xf1fd, 0x111e, 0xc8ee, 0x0067, + 0x0003, 0xd4de, 0xf4fd, 0xf3ff, 0x0014, 0x113e, 0x0055, 0x11bf, + 0x0003, 0x32be, 0x0085, 0xd8df, 0x0025, 0x515e, 0xaafe, 0x222f, + 0x0003, 0x44ce, 0xf8fd, 0x00f7, 0x0014, 0x647e, 0x0045, 0x989f, + 0x0003, 0x00a6, 0x555d, 0x00d7, 0xf1fd, 0x0036, 0xf5fe, 0x446f, + 0x0003, 0xd1de, 0xf4fd, 0xb9ff, 0x0014, 0x717e, 0x0055, 0x00b7, + 0x0003, 0x88ae, 0x0085, 0xdcdf, 0x0025, 0x444e, 0xf2fe, 0x0077, + 0x0003, 0x00c6, 0xf8fd, 0xe4ef, 0x0014, 0x545e, 0x0045, 0x737f, + 0x0003, 0x0096, 0x555d, 0xb8bf, 0xf1fd, 0x111e, 0xc8ee, 0x323f, + 0x0002, 0x00a5, 0x0084, 0x407e, 0x0002, 0x10de, 0x0024, 0x11df, + 0x0002, 0x72fe, 0x0044, 0x0056, 0x0002, 0xa8ae, 0x0014, 0xb2bf, + 0x0002, 0x0096, 0x0084, 0x0066, 0x0002, 0x00c6, 0x0024, 0x00e7, + 0x0002, 0xc8ee, 0x0044, 0x222e, 0x0002, 0x888e, 0x0014, 0x0077, + 0x0002, 0x00a5, 0x0084, 0x006e, 0x0002, 0x88ce, 0x0024, 0x00f7, + 0x0002, 0x91fe, 0x0044, 0x0036, 0x0002, 0xa2ae, 0x0014, 0xaaaf, + 0x0002, 0xb8fe, 0x0084, 0x005e, 0x0002, 0x00be, 0x0024, 0xc4cf, + 0x0002, 0x44ee, 0x0044, 0xf4ff, 0x0002, 0x223e, 0x0014, 0x111f, + 0x0002, 0x00a5, 0x0084, 0x407e, 0x0002, 0x10de, 0x0024, 0x99ff, + 0x0002, 0x72fe, 0x0044, 0x0056, 0x0002, 0xa8ae, 0x0014, 0x00b7, + 0x0002, 0x0096, 0x0084, 0x0066, 0x0002, 0x00c6, 0x0024, 0x00d7, + 0x0002, 0xc8ee, 0x0044, 0x222e, 0x0002, 0x888e, 0x0014, 0x444f, + 0x0002, 0x00a5, 0x0084, 0x006e, 0x0002, 0x88ce, 0x0024, 0xe2ef, + 0x0002, 0x91fe, 0x0044, 0x0036, 0x0002, 0xa2ae, 0x0014, 0x447f, + 0x0002, 0xb8fe, 0x0084, 0x005e, 0x0002, 0x00be, 0x0024, 0x009f, + 0x0002, 0x44ee, 0x0044, 0x76ff, 0x0002, 0x223e, 0x0014, 0x313f, + 0x0003, 0x00c6, 0x0085, 0xd9ff, 0xf2fd, 0x647e, 0xf1fe, 0x99bf, + 0x0003, 0xa2ae, 0x0025, 0x66ef, 0xf4fd, 0x0056, 0xe2ee, 0x737f, + 0x0003, 0x98be, 0x0045, 0x00f7, 0xf8fd, 0x0066, 0x76fe, 0x889f, + 0x0003, 0x888e, 0x0015, 0xd5df, 0x00a5, 0x222e, 0x98de, 0x444f, + 0x0003, 0xb2be, 0x0085, 0xfcff, 0xf2fd, 0x226e, 0x0096, 0x00b7, + 0x0003, 0xaaae, 0x0025, 0xd1df, 0xf4fd, 0x0036, 0xd4de, 0x646f, + 0x0003, 0xa8ae, 0x0045, 0xeaef, 0xf8fd, 0x445e, 0xe8ee, 0x717f, + 0x0003, 0x323e, 0x0015, 0xc4cf, 0x00a5, 0xfaff, 0x88ce, 0x313f, + 0x0003, 0x00c6, 0x0085, 0x77ff, 0xf2fd, 0x647e, 0xf1fe, 0xb3bf, + 0x0003, 0xa2ae, 0x0025, 0x00e7, 0xf4fd, 0x0056, 0xe2ee, 0x0077, + 0x0003, 0x98be, 0x0045, 0xe4ef, 0xf8fd, 0x0066, 0x76fe, 0x667f, + 0x0003, 0x888e, 0x0015, 0x00d7, 0x00a5, 0x222e, 0x98de, 0x333f, + 0x0003, 0xb2be, 0x0085, 0x75ff, 0xf2fd, 0x226e, 0x0096, 0x919f, + 0x0003, 0xaaae, 0x0025, 0x99df, 0xf4fd, 0x0036, 0xd4de, 0x515f, + 0x0003, 0xa8ae, 0x0045, 0xecef, 0xf8fd, 0x445e, 0xe8ee, 0x727f, + 0x0003, 0x323e, 0x0015, 0xb1bf, 0x00a5, 0xf3ff, 0x88ce, 0x111f, + 0x0003, 0x54de, 0xf2fd, 0x111e, 0x0014, 0x647e, 0xf8fe, 0xcccf, + 0x0003, 0x91be, 0x0045, 0x22ef, 0x0025, 0x222e, 0xf3fe, 0x888f, + 0x0003, 0x00c6, 0x0085, 0x00f7, 0x0014, 0x115e, 0xfcfe, 0xa8af, + 0x0003, 0x00a6, 0x0035, 0xc8df, 0xf1fd, 0x313e, 0x66fe, 0x646f, + 0x0003, 0xc8ce, 0xf2fd, 0xf5ff, 0x0014, 0x0066, 0xf4fe, 0xbabf, + 0x0003, 0x22ae, 0x0045, 0x00e7, 0x0025, 0x323e, 0xeafe, 0x737f, + 0x0003, 0xb2be, 0x0085, 0x55df, 0x0014, 0x0056, 0x717e, 0x119f, + 0x0003, 0x0096, 0x0035, 0xc4cf, 0xf1fd, 0x333e, 0xe8ee, 0x444f, + 0x0003, 0x54de, 0xf2fd, 0x111e, 0x0014, 0x647e, 0xf8fe, 0x99bf, + 0x0003, 0x91be, 0x0045, 0xe2ef, 0x0025, 0x222e, 0xf3fe, 0x667f, + 0x0003, 0x00c6, 0x0085, 0xe4ef, 0x0014, 0x115e, 0xfcfe, 0x989f, + 0x0003, 0x00a6, 0x0035, 0x00d7, 0xf1fd, 0x313e, 0x66fe, 0x226f, + 0x0003, 0xc8ce, 0xf2fd, 0xb9ff, 0x0014, 0x0066, 0xf4fe, 0x00b7, + 0x0003, 0x22ae, 0x0045, 0xd1df, 0x0025, 0x323e, 0xeafe, 0x0077, + 0x0003, 0xb2be, 0x0085, 0xecef, 0x0014, 0x0056, 0x717e, 0x727f, + 0x0003, 0x0096, 0x0035, 0xb8bf, 0xf1fd, 0x333e, 0xe8ee, 0x545f, + 0xf1fc, 0xd1de, 0xfafd, 0x00d7, 0xf8fc, 0x0016, 0xfffd, 0x747f, + 0xf4fc, 0x717e, 0xf3fd, 0xb3bf, 0xf2fc, 0xeaef, 0xe8ee, 0x444f, + 0xf1fc, 0x22ae, 0x0005, 0xb8bf, 0xf8fc, 0x00f7, 0xfcfe, 0x0077, + 0xf4fc, 0x115e, 0xf5fd, 0x757f, 0xf2fc, 0xd8df, 0xe2ee, 0x333f, + 0xf1fc, 0xb2be, 0xfafd, 0x88cf, 0xf8fc, 0xfbff, 0xfffd, 0x737f, + 0xf4fc, 0x006e, 0xf3fd, 0x00b7, 0xf2fc, 0x66ef, 0xf9fe, 0x313f, + 0xf1fc, 0x009e, 0x0005, 0xbabf, 0xf8fc, 0xfdff, 0xf6fe, 0x0067, + 0xf4fc, 0x0026, 0xf5fd, 0x888f, 0xf2fc, 0xdcdf, 0xd4de, 0x222f, + 0xf1fc, 0xd1de, 0xfafd, 0xc4cf, 0xf8fc, 0x0016, 0xfffd, 0x727f, + 0xf4fc, 0x717e, 0xf3fd, 0x99bf, 0xf2fc, 0xecef, 0xe8ee, 0x0047, + 0xf1fc, 0x22ae, 0x0005, 0x00a7, 0xf8fc, 0xf7ff, 0xfcfe, 0x0057, + 0xf4fc, 0x115e, 0xf5fd, 0x0097, 0xf2fc, 0xd5df, 0xe2ee, 0x0037, + 0xf1fc, 0xb2be, 0xfafd, 0x00c7, 0xf8fc, 0xfeff, 0xfffd, 0x667f, + 0xf4fc, 0x006e, 0xf3fd, 0xa8af, 0xf2fc, 0x00e7, 0xf9fe, 0x323f, + 0xf1fc, 0x009e, 0x0005, 0xb1bf, 0xf8fc, 0xe4ef, 0xf6fe, 0x545f, + 0xf4fc, 0x0026, 0xf5fd, 0x0087, 0xf2fc, 0x99df, 0xd4de, 0x111f +}; + +static const OPJ_UINT16 vlc_tbl1[1024] = { + 0x0013, 0x0065, 0x0043, 0x00de, 0x0083, 0x888d, 0x0023, 0x444e, + 0x0013, 0x00a5, 0x0043, 0x88ae, 0x0083, 0x0035, 0x0023, 0x00d7, + 0x0013, 0x00c5, 0x0043, 0x009e, 0x0083, 0x0055, 0x0023, 0x222e, + 0x0013, 0x0095, 0x0043, 0x007e, 0x0083, 0x10fe, 0x0023, 0x0077, + 0x0013, 0x0065, 0x0043, 0x88ce, 0x0083, 0x888d, 0x0023, 0x111e, + 0x0013, 0x00a5, 0x0043, 0x005e, 0x0083, 0x0035, 0x0023, 0x00e7, + 0x0013, 0x00c5, 0x0043, 0x00be, 0x0083, 0x0055, 0x0023, 0x11ff, + 0x0013, 0x0095, 0x0043, 0x003e, 0x0083, 0x40ee, 0x0023, 0xa2af, + 0x0013, 0x0065, 0x0043, 0x00de, 0x0083, 0x888d, 0x0023, 0x444e, + 0x0013, 0x00a5, 0x0043, 0x88ae, 0x0083, 0x0035, 0x0023, 0x44ef, + 0x0013, 0x00c5, 0x0043, 0x009e, 0x0083, 0x0055, 0x0023, 0x222e, + 0x0013, 0x0095, 0x0043, 0x007e, 0x0083, 0x10fe, 0x0023, 0x00b7, + 0x0013, 0x0065, 0x0043, 0x88ce, 0x0083, 0x888d, 0x0023, 0x111e, + 0x0013, 0x00a5, 0x0043, 0x005e, 0x0083, 0x0035, 0x0023, 0xc4cf, + 0x0013, 0x00c5, 0x0043, 0x00be, 0x0083, 0x0055, 0x0023, 0x00f7, + 0x0013, 0x0095, 0x0043, 0x003e, 0x0083, 0x40ee, 0x0023, 0x006f, + 0x0001, 0x0084, 0x0001, 0x0056, 0x0001, 0x0014, 0x0001, 0x00d7, + 0x0001, 0x0024, 0x0001, 0x0096, 0x0001, 0x0045, 0x0001, 0x0077, + 0x0001, 0x0084, 0x0001, 0x00c6, 0x0001, 0x0014, 0x0001, 0x888f, + 0x0001, 0x0024, 0x0001, 0x00f7, 0x0001, 0x0035, 0x0001, 0x222f, + 0x0001, 0x0084, 0x0001, 0x40fe, 0x0001, 0x0014, 0x0001, 0x00b7, + 0x0001, 0x0024, 0x0001, 0x00bf, 0x0001, 0x0045, 0x0001, 0x0067, + 0x0001, 0x0084, 0x0001, 0x00a6, 0x0001, 0x0014, 0x0001, 0x444f, + 0x0001, 0x0024, 0x0001, 0x00e7, 0x0001, 0x0035, 0x0001, 0x113f, + 0x0001, 0x0084, 0x0001, 0x0056, 0x0001, 0x0014, 0x0001, 0x00cf, + 0x0001, 0x0024, 0x0001, 0x0096, 0x0001, 0x0045, 0x0001, 0x006f, + 0x0001, 0x0084, 0x0001, 0x00c6, 0x0001, 0x0014, 0x0001, 0x009f, + 0x0001, 0x0024, 0x0001, 0x00ef, 0x0001, 0x0035, 0x0001, 0x323f, + 0x0001, 0x0084, 0x0001, 0x40fe, 0x0001, 0x0014, 0x0001, 0x00af, + 0x0001, 0x0024, 0x0001, 0x44ff, 0x0001, 0x0045, 0x0001, 0x005f, + 0x0001, 0x0084, 0x0001, 0x00a6, 0x0001, 0x0014, 0x0001, 0x007f, + 0x0001, 0x0024, 0x0001, 0x00df, 0x0001, 0x0035, 0x0001, 0x111f, + 0x0001, 0x0024, 0x0001, 0x0056, 0x0001, 0x0085, 0x0001, 0x00bf, + 0x0001, 0x0014, 0x0001, 0x00f7, 0x0001, 0x00c6, 0x0001, 0x0077, + 0x0001, 0x0024, 0x0001, 0xf8ff, 0x0001, 0x0045, 0x0001, 0x007f, + 0x0001, 0x0014, 0x0001, 0x00df, 0x0001, 0x00a6, 0x0001, 0x313f, + 0x0001, 0x0024, 0x0001, 0x222e, 0x0001, 0x0085, 0x0001, 0x00b7, + 0x0001, 0x0014, 0x0001, 0x44ef, 0x0001, 0xa2ae, 0x0001, 0x0067, + 0x0001, 0x0024, 0x0001, 0x51ff, 0x0001, 0x0045, 0x0001, 0x0097, + 0x0001, 0x0014, 0x0001, 0x00cf, 0x0001, 0x0036, 0x0001, 0x223f, + 0x0001, 0x0024, 0x0001, 0x0056, 0x0001, 0x0085, 0x0001, 0xb2bf, + 0x0001, 0x0014, 0x0001, 0x40ef, 0x0001, 0x00c6, 0x0001, 0x006f, + 0x0001, 0x0024, 0x0001, 0x72ff, 0x0001, 0x0045, 0x0001, 0x009f, + 0x0001, 0x0014, 0x0001, 0x00d7, 0x0001, 0x00a6, 0x0001, 0x444f, + 0x0001, 0x0024, 0x0001, 0x222e, 0x0001, 0x0085, 0x0001, 0xa8af, + 0x0001, 0x0014, 0x0001, 0x00e7, 0x0001, 0xa2ae, 0x0001, 0x005f, + 0x0001, 0x0024, 0x0001, 0x44ff, 0x0001, 0x0045, 0x0001, 0x888f, + 0x0001, 0x0014, 0x0001, 0xaaaf, 0x0001, 0x0036, 0x0001, 0x111f, + 0x0002, 0xf8fe, 0x0024, 0x0056, 0x0002, 0x00b6, 0x0085, 0x66ff, + 0x0002, 0x00ce, 0x0014, 0x111e, 0x0002, 0x0096, 0x0035, 0xa8af, + 0x0002, 0x00f6, 0x0024, 0x313e, 0x0002, 0x00a6, 0x0045, 0xb3bf, + 0x0002, 0xb2be, 0x0014, 0xf5ff, 0x0002, 0x0066, 0x517e, 0x545f, + 0x0002, 0xf2fe, 0x0024, 0x222e, 0x0002, 0x22ae, 0x0085, 0x44ef, + 0x0002, 0x00c6, 0x0014, 0xf4ff, 0x0002, 0x0076, 0x0035, 0x447f, + 0x0002, 0x40de, 0x0024, 0x323e, 0x0002, 0x009e, 0x0045, 0x00d7, + 0x0002, 0x88be, 0x0014, 0xfaff, 0x0002, 0x115e, 0xf1fe, 0x444f, + 0x0002, 0xf8fe, 0x0024, 0x0056, 0x0002, 0x00b6, 0x0085, 0xc8ef, + 0x0002, 0x00ce, 0x0014, 0x111e, 0x0002, 0x0096, 0x0035, 0x888f, + 0x0002, 0x00f6, 0x0024, 0x313e, 0x0002, 0x00a6, 0x0045, 0x44df, + 0x0002, 0xb2be, 0x0014, 0xa8ff, 0x0002, 0x0066, 0x517e, 0x006f, + 0x0002, 0xf2fe, 0x0024, 0x222e, 0x0002, 0x22ae, 0x0085, 0x00e7, + 0x0002, 0x00c6, 0x0014, 0xe2ef, 0x0002, 0x0076, 0x0035, 0x727f, + 0x0002, 0x40de, 0x0024, 0x323e, 0x0002, 0x009e, 0x0045, 0xb1bf, + 0x0002, 0x88be, 0x0014, 0x73ff, 0x0002, 0x115e, 0xf1fe, 0x333f, + 0x0001, 0x0084, 0x0001, 0x20ee, 0x0001, 0x00c5, 0x0001, 0xc4cf, + 0x0001, 0x0044, 0x0001, 0x32ff, 0x0001, 0x0015, 0x0001, 0x888f, + 0x0001, 0x0084, 0x0001, 0x0066, 0x0001, 0x0025, 0x0001, 0x00af, + 0x0001, 0x0044, 0x0001, 0x22ef, 0x0001, 0x00a6, 0x0001, 0x005f, + 0x0001, 0x0084, 0x0001, 0x444e, 0x0001, 0x00c5, 0x0001, 0xcccf, + 0x0001, 0x0044, 0x0001, 0x00f7, 0x0001, 0x0015, 0x0001, 0x006f, + 0x0001, 0x0084, 0x0001, 0x0056, 0x0001, 0x0025, 0x0001, 0x009f, + 0x0001, 0x0044, 0x0001, 0x00df, 0x0001, 0x30fe, 0x0001, 0x222f, + 0x0001, 0x0084, 0x0001, 0x20ee, 0x0001, 0x00c5, 0x0001, 0xc8cf, + 0x0001, 0x0044, 0x0001, 0x11ff, 0x0001, 0x0015, 0x0001, 0x0077, + 0x0001, 0x0084, 0x0001, 0x0066, 0x0001, 0x0025, 0x0001, 0x007f, + 0x0001, 0x0044, 0x0001, 0x00e7, 0x0001, 0x00a6, 0x0001, 0x0037, + 0x0001, 0x0084, 0x0001, 0x444e, 0x0001, 0x00c5, 0x0001, 0x00b7, + 0x0001, 0x0044, 0x0001, 0x00bf, 0x0001, 0x0015, 0x0001, 0x003f, + 0x0001, 0x0084, 0x0001, 0x0056, 0x0001, 0x0025, 0x0001, 0x0097, + 0x0001, 0x0044, 0x0001, 0x00d7, 0x0001, 0x30fe, 0x0001, 0x111f, + 0x0002, 0xa8ee, 0x0044, 0x888e, 0x0002, 0x00d6, 0x00c5, 0xf3ff, + 0x0002, 0xfcfe, 0x0025, 0x003e, 0x0002, 0x00b6, 0x0055, 0xd8df, + 0x0002, 0xf8fe, 0x0044, 0x0066, 0x0002, 0x207e, 0x0085, 0x99ff, + 0x0002, 0x00e6, 0x00f5, 0x0036, 0x0002, 0x00a6, 0x0015, 0x009f, + 0x0002, 0xf2fe, 0x0044, 0x0076, 0x0002, 0x44ce, 0x00c5, 0x76ff, + 0x0002, 0xf1fe, 0x0025, 0x444e, 0x0002, 0x00ae, 0x0055, 0xc8cf, + 0x0002, 0xf4fe, 0x0044, 0x445e, 0x0002, 0x10be, 0x0085, 0xe4ef, + 0x0002, 0x54de, 0x00f5, 0x111e, 0x0002, 0x0096, 0x0015, 0x222f, + 0x0002, 0xa8ee, 0x0044, 0x888e, 0x0002, 0x00d6, 0x00c5, 0xfaff, + 0x0002, 0xfcfe, 0x0025, 0x003e, 0x0002, 0x00b6, 0x0055, 0x11bf, + 0x0002, 0xf8fe, 0x0044, 0x0066, 0x0002, 0x207e, 0x0085, 0x22ef, + 0x0002, 0x00e6, 0x00f5, 0x0036, 0x0002, 0x00a6, 0x0015, 0x227f, + 0x0002, 0xf2fe, 0x0044, 0x0076, 0x0002, 0x44ce, 0x00c5, 0xd5ff, + 0x0002, 0xf1fe, 0x0025, 0x444e, 0x0002, 0x00ae, 0x0055, 0x006f, + 0x0002, 0xf4fe, 0x0044, 0x445e, 0x0002, 0x10be, 0x0085, 0x11df, + 0x0002, 0x54de, 0x00f5, 0x111e, 0x0002, 0x0096, 0x0015, 0x515f, + 0x0003, 0x00f6, 0x0014, 0x111e, 0x0044, 0x888e, 0x00a5, 0xd4df, + 0x0003, 0xa2ae, 0x0055, 0x76ff, 0x0024, 0x223e, 0x00b6, 0xaaaf, + 0x0003, 0x00e6, 0x0014, 0xf5ff, 0x0044, 0x0066, 0x0085, 0xcccf, + 0x0003, 0x009e, 0x00c5, 0x44ef, 0x0024, 0x0036, 0xf8fe, 0x317f, + 0x0003, 0xe8ee, 0x0014, 0xf1ff, 0x0044, 0x0076, 0x00a5, 0xc4cf, + 0x0003, 0x227e, 0x0055, 0xd1df, 0x0024, 0x444e, 0xf4fe, 0x515f, + 0x0003, 0x00d6, 0x0014, 0xe2ef, 0x0044, 0x445e, 0x0085, 0x22bf, + 0x0003, 0x0096, 0x00c5, 0xc8df, 0x0024, 0x222e, 0xf2fe, 0x226f, + 0x0003, 0x00f6, 0x0014, 0x111e, 0x0044, 0x888e, 0x00a5, 0xb1bf, + 0x0003, 0xa2ae, 0x0055, 0x33ff, 0x0024, 0x223e, 0x00b6, 0xa8af, + 0x0003, 0x00e6, 0x0014, 0xb9ff, 0x0044, 0x0066, 0x0085, 0xa8bf, + 0x0003, 0x009e, 0x00c5, 0xe4ef, 0x0024, 0x0036, 0xf8fe, 0x646f, + 0x0003, 0xe8ee, 0x0014, 0xfcff, 0x0044, 0x0076, 0x00a5, 0xc8cf, + 0x0003, 0x227e, 0x0055, 0xeaef, 0x0024, 0x444e, 0xf4fe, 0x747f, + 0x0003, 0x00d6, 0x0014, 0xfaff, 0x0044, 0x445e, 0x0085, 0xb2bf, + 0x0003, 0x0096, 0x00c5, 0x44df, 0x0024, 0x222e, 0xf2fe, 0x313f, + 0x00f3, 0xfafe, 0xf1fd, 0x0036, 0x0004, 0x32be, 0x0075, 0x11df, + 0x00f3, 0x54de, 0xf2fd, 0xe4ef, 0x00d5, 0x717e, 0xfcfe, 0x737f, + 0x00f3, 0xf3fe, 0xf8fd, 0x111e, 0x0004, 0x0096, 0x0055, 0xb1bf, + 0x00f3, 0x00ce, 0x00b5, 0xd8df, 0xf4fd, 0x0066, 0xb9fe, 0x545f, + 0x00f3, 0x76fe, 0xf1fd, 0x0026, 0x0004, 0x00a6, 0x0075, 0x009f, + 0x00f3, 0x00ae, 0xf2fd, 0xf7ff, 0x00d5, 0x0046, 0xf5fe, 0x747f, + 0x00f3, 0x00e6, 0xf8fd, 0x0016, 0x0004, 0x0086, 0x0055, 0x888f, + 0x00f3, 0x00c6, 0x00b5, 0xe2ef, 0xf4fd, 0x115e, 0xa8ee, 0x113f, + 0x00f3, 0xfafe, 0xf1fd, 0x0036, 0x0004, 0x32be, 0x0075, 0xd1df, + 0x00f3, 0x54de, 0xf2fd, 0xfbff, 0x00d5, 0x717e, 0xfcfe, 0x447f, + 0x00f3, 0xf3fe, 0xf8fd, 0x111e, 0x0004, 0x0096, 0x0055, 0x727f, + 0x00f3, 0x00ce, 0x00b5, 0x22ef, 0xf4fd, 0x0066, 0xb9fe, 0x444f, + 0x00f3, 0x76fe, 0xf1fd, 0x0026, 0x0004, 0x00a6, 0x0075, 0x11bf, + 0x00f3, 0x00ae, 0xf2fd, 0xffff, 0x00d5, 0x0046, 0xf5fe, 0x323f, + 0x00f3, 0x00e6, 0xf8fd, 0x0016, 0x0004, 0x0086, 0x0055, 0x006f, + 0x00f3, 0x00c6, 0x00b5, 0xb8bf, 0xf4fd, 0x115e, 0xa8ee, 0x222f +}; \ No newline at end of file diff --git a/client/deps/openjpeg/t1_luts.h b/client/deps/openjpeg/t1_luts.h new file mode 100644 index 000000000..1a5e7844f --- /dev/null +++ b/client/deps/openjpeg/t1_luts.h @@ -0,0 +1,175 @@ +/* This file was automatically generated by t1_generate_luts.c */ + +static const OPJ_BYTE lut_ctxno_zc[2048] = { + 0, 1, 3, 3, 1, 2, 3, 3, 5, 6, 7, 7, 6, 6, 7, 7, 0, 1, 3, 3, 1, 2, 3, 3, 5, 6, 7, 7, 6, 6, 7, 7, + 5, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 5, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 2, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 2, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 1, 5, 6, 1, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, 0, 1, 5, 6, 1, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, + 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, + 1, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, 1, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, + 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, + 5, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 5, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 1, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, 1, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, + 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, + 2, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, 2, 2, 6, 6, 2, 2, 6, 6, 3, 3, 7, 7, 3, 3, 7, 7, + 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, 3, 3, 7, 7, 3, 3, 7, 7, 4, 4, 7, 7, 4, 4, 7, 7, + 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 6, 6, 8, 8, 6, 6, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, 7, 7, 8, 8, + 0, 1, 3, 3, 1, 2, 3, 3, 5, 6, 7, 7, 6, 6, 7, 7, 0, 1, 3, 3, 1, 2, 3, 3, 5, 6, 7, 7, 6, 6, 7, 7, + 5, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 5, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 1, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 2, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, 2, 2, 3, 3, 2, 2, 3, 3, 6, 6, 7, 7, 6, 6, 7, 7, + 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 6, 6, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3, 3, 4, 4, 3, 3, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, + 0, 3, 1, 4, 3, 6, 4, 7, 1, 4, 2, 5, 4, 7, 5, 7, 0, 3, 1, 4, 3, 6, 4, 7, 1, 4, 2, 5, 4, 7, 5, 7, + 1, 4, 2, 5, 4, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, 1, 4, 2, 5, 4, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, + 3, 6, 4, 7, 6, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 3, 6, 4, 7, 6, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, + 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 1, 4, 2, 5, 4, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, 1, 4, 2, 5, 4, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, + 2, 5, 2, 5, 5, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, 2, 5, 2, 5, 5, 7, 5, 7, + 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 3, 6, 4, 7, 6, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 3, 6, 4, 7, 6, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, + 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 6, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 6, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, + 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, + 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 4, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, 5, 7, 5, 7, 7, 8, 7, 8, + 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, + 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8 +}; + +static const OPJ_BYTE lut_ctxno_sc[256] = { + 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xc, 0xc, 0xd, 0xb, 0xc, 0xc, 0xd, 0xb, + 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xc, 0xc, 0xb, 0xd, 0xc, 0xc, 0xb, 0xd, + 0xc, 0xc, 0xd, 0xd, 0xc, 0xc, 0xb, 0xb, 0xc, 0x9, 0xd, 0xa, 0x9, 0xc, 0xa, 0xb, + 0xc, 0xc, 0xb, 0xb, 0xc, 0xc, 0xd, 0xd, 0xc, 0x9, 0xb, 0xa, 0x9, 0xc, 0xa, 0xd, + 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xc, 0xc, 0xd, 0xb, 0xc, 0xc, 0xd, 0xb, + 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0xc, 0xc, 0xb, 0xd, 0xc, 0xc, 0xb, 0xd, + 0xc, 0xc, 0xd, 0xd, 0xc, 0xc, 0xb, 0xb, 0xc, 0x9, 0xd, 0xa, 0x9, 0xc, 0xa, 0xb, + 0xc, 0xc, 0xb, 0xb, 0xc, 0xc, 0xd, 0xd, 0xc, 0x9, 0xb, 0xa, 0x9, 0xc, 0xa, 0xd, + 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xd, 0xb, 0xd, 0xb, 0xd, 0xb, 0xd, 0xb, + 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xd, 0xb, 0xc, 0xc, 0xd, 0xb, 0xc, 0xc, + 0xd, 0xd, 0xd, 0xd, 0xb, 0xb, 0xb, 0xb, 0xd, 0xa, 0xd, 0xa, 0xa, 0xb, 0xa, 0xb, + 0xd, 0xd, 0xc, 0xc, 0xb, 0xb, 0xc, 0xc, 0xd, 0xa, 0xc, 0x9, 0xa, 0xb, 0x9, 0xc, + 0xa, 0xa, 0x9, 0x9, 0xa, 0xa, 0x9, 0x9, 0xb, 0xd, 0xc, 0xc, 0xb, 0xd, 0xc, 0xc, + 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xa, 0xb, 0xd, 0xb, 0xd, 0xb, 0xd, 0xb, 0xd, + 0xb, 0xb, 0xc, 0xc, 0xd, 0xd, 0xc, 0xc, 0xb, 0xa, 0xc, 0x9, 0xa, 0xd, 0x9, 0xc, + 0xb, 0xb, 0xb, 0xb, 0xd, 0xd, 0xd, 0xd, 0xb, 0xa, 0xb, 0xa, 0xa, 0xd, 0xa, 0xd +}; + +static const OPJ_BYTE lut_spb[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, + 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1 +}; + +static const OPJ_INT16 lut_nmsedec_sig[1U << T1_NMSEDEC_BITS] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0180, 0x0300, 0x0480, 0x0600, 0x0780, 0x0900, 0x0a80, + 0x0c00, 0x0d80, 0x0f00, 0x1080, 0x1200, 0x1380, 0x1500, 0x1680, + 0x1800, 0x1980, 0x1b00, 0x1c80, 0x1e00, 0x1f80, 0x2100, 0x2280, + 0x2400, 0x2580, 0x2700, 0x2880, 0x2a00, 0x2b80, 0x2d00, 0x2e80, + 0x3000, 0x3180, 0x3300, 0x3480, 0x3600, 0x3780, 0x3900, 0x3a80, + 0x3c00, 0x3d80, 0x3f00, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, + 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5100, 0x5280, + 0x5400, 0x5580, 0x5700, 0x5880, 0x5a00, 0x5b80, 0x5d00, 0x5e80, + 0x6000, 0x6180, 0x6300, 0x6480, 0x6600, 0x6780, 0x6900, 0x6a80, + 0x6c00, 0x6d80, 0x6f00, 0x7080, 0x7200, 0x7380, 0x7500, 0x7680 +}; + +static const OPJ_INT16 lut_nmsedec_sig0[1U << T1_NMSEDEC_BITS] = { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, + 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, + 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, + 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, + 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, + 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00, + 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2680, 0x2780, + 0x2880, 0x2980, 0x2b00, 0x2c00, 0x2d00, 0x2e80, 0x2f80, 0x3100, + 0x3200, 0x3380, 0x3480, 0x3600, 0x3700, 0x3880, 0x3a00, 0x3b00, + 0x3c80, 0x3e00, 0x3f80, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680, + 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5180, 0x5300, + 0x5480, 0x5600, 0x5800, 0x5980, 0x5b00, 0x5d00, 0x5e80, 0x6080, + 0x6200, 0x6400, 0x6580, 0x6780, 0x6900, 0x6b00, 0x6d00, 0x6e80, + 0x7080, 0x7280, 0x7480, 0x7600, 0x7800, 0x7a00, 0x7c00, 0x7e00 +}; + +static const OPJ_INT16 lut_nmsedec_ref[1U << T1_NMSEDEC_BITS] = { + 0x1800, 0x1780, 0x1700, 0x1680, 0x1600, 0x1580, 0x1500, 0x1480, + 0x1400, 0x1380, 0x1300, 0x1280, 0x1200, 0x1180, 0x1100, 0x1080, + 0x1000, 0x0f80, 0x0f00, 0x0e80, 0x0e00, 0x0d80, 0x0d00, 0x0c80, + 0x0c00, 0x0b80, 0x0b00, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, + 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0500, 0x0480, + 0x0400, 0x0380, 0x0300, 0x0280, 0x0200, 0x0180, 0x0100, 0x0080, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, + 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b00, 0x0b80, + 0x0c00, 0x0c80, 0x0d00, 0x0d80, 0x0e00, 0x0e80, 0x0f00, 0x0f80, + 0x1000, 0x1080, 0x1100, 0x1180, 0x1200, 0x1280, 0x1300, 0x1380, + 0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780 +}; + +static const OPJ_INT16 lut_nmsedec_ref0[1U << T1_NMSEDEC_BITS] = { + 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x1b00, 0x1a80, 0x1980, + 0x1880, 0x1780, 0x1700, 0x1600, 0x1500, 0x1480, 0x1380, 0x1300, + 0x1200, 0x1180, 0x1080, 0x1000, 0x0f00, 0x0e80, 0x0e00, 0x0d00, + 0x0c80, 0x0c00, 0x0b80, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880, + 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0580, 0x0500, + 0x0480, 0x0400, 0x0400, 0x0380, 0x0300, 0x0300, 0x0280, 0x0280, + 0x0200, 0x0200, 0x0180, 0x0180, 0x0100, 0x0100, 0x0100, 0x0080, + 0x0080, 0x0080, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080, + 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200, + 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400, + 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780, + 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00, + 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180, + 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780, + 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00 +}; + diff --git a/client/deps/openjpeg/t2.c b/client/deps/openjpeg/t2.c new file mode 100644 index 000000000..4e8cf6018 --- /dev/null +++ b/client/deps/openjpeg/t2.c @@ -0,0 +1,1705 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" +#include "opj_common.h" + + +/** @defgroup T2 T2 - Implementation of a tier-2 coding */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +static void opj_t2_putcommacode(opj_bio_t *bio, OPJ_INT32 n); + +static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio); +/** +Variable length code for signalling delta Zil (truncation point) +@param bio Bit Input/Output component +@param n delta Zil +*/ +static void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n); +static OPJ_UINT32 opj_t2_getnumpasses(opj_bio_t *bio); + +/** +Encode a packet of a tile to a destination buffer +@param tileno Number of the tile encoded +@param tile Tile for which to write the packets +@param tcp Tile coding parameters +@param pi Packet identity +@param dest Destination buffer +@param p_data_written FIXME DOC +@param len Length of the destination buffer +@param cstr_info Codestream information structure +@param p_t2_mode If == THRESH_CALC In Threshold calculation ,If == FINAL_PASS Final pass +@param p_manager the user event manager +@return +*/ +static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + opj_pi_iterator_t *pi, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len, + opj_codestream_info_t *cstr_info, + J2K_T2_MODE p_t2_mode, + opj_event_mgr_t *p_manager); + +/** +Decode a packet of a tile from a source buffer +@param t2 T2 handle +@param tile Tile for which to write the packets +@param tcp Tile coding parameters +@param pi Packet identity +@param src Source buffer +@param data_read FIXME DOC +@param max_length FIXME DOC +@param pack_info Packet information +@param p_manager the user event manager + +@return FIXME DOC +*/ +static OPJ_BOOL opj_t2_decode_packet(opj_t2_t* t2, + opj_tcd_tile_t *tile, + opj_tcp_t *tcp, + opj_pi_iterator_t *pi, + OPJ_BYTE *src, + OPJ_UINT32 * data_read, + OPJ_UINT32 max_length, + opj_packet_info_t *pack_info, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_t2_skip_packet(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_t2_read_packet_header(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BOOL * p_is_data_present, + OPJ_BYTE *p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *pack_info, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_pi_iterator_t *p_pi, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *pack_info, + opj_event_mgr_t *p_manager); + +/** +@param cblk +@param index +@param cblksty +@param first +*/ +static OPJ_BOOL opj_t2_init_seg(opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 index, + OPJ_UINT32 cblksty, + OPJ_UINT32 first); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +/* #define RESTART 0x04 */ +static void opj_t2_putcommacode(opj_bio_t *bio, OPJ_INT32 n) +{ + while (--n >= 0) { + opj_bio_putbit(bio, 1); + } + opj_bio_putbit(bio, 0); +} + +static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio) +{ + OPJ_UINT32 n = 0; + while (opj_bio_read(bio, 1)) { + ++n; + } + return n; +} + +static void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n) +{ + if (n == 1) { + opj_bio_putbit(bio, 0); + } else if (n == 2) { + opj_bio_write(bio, 2, 2); + } else if (n <= 5) { + opj_bio_write(bio, 0xc | (n - 3), 4); + } else if (n <= 36) { + opj_bio_write(bio, 0x1e0 | (n - 6), 9); + } else if (n <= 164) { + opj_bio_write(bio, 0xff80 | (n - 37), 16); + } +} + +static OPJ_UINT32 opj_t2_getnumpasses(opj_bio_t *bio) +{ + OPJ_UINT32 n; + if (!opj_bio_read(bio, 1)) { + return 1; + } + if (!opj_bio_read(bio, 1)) { + return 2; + } + if ((n = opj_bio_read(bio, 2)) != 3) { + return (3 + n); + } + if ((n = opj_bio_read(bio, 5)) != 31) { + return (6 + n); + } + return (37 + opj_bio_read(bio, 7)); +} + +/* ----------------------------------------------------------------------- */ + +OPJ_BOOL opj_t2_encode_packets(opj_t2_t* p_t2, + OPJ_UINT32 p_tile_no, + opj_tcd_tile_t *p_tile, + OPJ_UINT32 p_maxlayers, + OPJ_BYTE *p_dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_len, + opj_codestream_info_t *cstr_info, + opj_tcd_marker_info_t* p_marker_info, + OPJ_UINT32 p_tp_num, + OPJ_INT32 p_tp_pos, + OPJ_UINT32 p_pino, + J2K_T2_MODE p_t2_mode, + opj_event_mgr_t *p_manager) +{ + OPJ_BYTE *l_current_data = p_dest; + OPJ_UINT32 l_nb_bytes = 0; + OPJ_UINT32 compno; + OPJ_UINT32 poc; + opj_pi_iterator_t *l_pi = 00; + opj_pi_iterator_t *l_current_pi = 00; + opj_image_t *l_image = p_t2->image; + opj_cp_t *l_cp = p_t2->cp; + opj_tcp_t *l_tcp = &l_cp->tcps[p_tile_no]; + OPJ_UINT32 pocno = (l_cp->rsiz == OPJ_PROFILE_CINEMA_4K) ? 2 : 1; + OPJ_UINT32 l_max_comp = l_cp->m_specific_param.m_enc.m_max_comp_size > 0 ? + l_image->numcomps : 1; + OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; + + l_pi = opj_pi_initialise_encode(l_image, l_cp, p_tile_no, p_t2_mode, p_manager); + if (!l_pi) { + return OPJ_FALSE; + } + + * p_data_written = 0; + + if (p_t2_mode == THRESH_CALC) { /* Calculating threshold */ + l_current_pi = l_pi; + + for (compno = 0; compno < l_max_comp; ++compno) { + OPJ_UINT32 l_comp_len = 0; + l_current_pi = l_pi; + + for (poc = 0; poc < pocno ; ++poc) { + OPJ_UINT32 l_tp_num = compno; + + /* TODO MSD : check why this function cannot fail (cf. v1) */ + opj_pi_create_encode(l_pi, l_cp, p_tile_no, poc, l_tp_num, p_tp_pos, p_t2_mode); + + if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { + /* TODO ADE : add an error */ + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + while (opj_pi_next(l_current_pi)) { + if (l_current_pi->layno < p_maxlayers) { + l_nb_bytes = 0; + + if (! opj_t2_encode_packet(p_tile_no, p_tile, l_tcp, l_current_pi, + l_current_data, &l_nb_bytes, + p_max_len, cstr_info, + p_t2_mode, + p_manager)) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + + l_comp_len += l_nb_bytes; + l_current_data += l_nb_bytes; + p_max_len -= l_nb_bytes; + + * p_data_written += l_nb_bytes; + } + } + + if (l_cp->m_specific_param.m_enc.m_max_comp_size) { + if (l_comp_len > l_cp->m_specific_param.m_enc.m_max_comp_size) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + } + + ++l_current_pi; + } + } + } else { /* t2_mode == FINAL_PASS */ + opj_pi_create_encode(l_pi, l_cp, p_tile_no, p_pino, p_tp_num, p_tp_pos, + p_t2_mode); + + l_current_pi = &l_pi[p_pino]; + if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { + /* TODO ADE : add an error */ + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + + if (p_marker_info && p_marker_info->need_PLT) { + /* One time use intended */ + assert(p_marker_info->packet_count == 0); + assert(p_marker_info->p_packet_size == NULL); + + p_marker_info->p_packet_size = (OPJ_UINT32*) opj_malloc( + opj_get_encoding_packet_count(l_image, l_cp, p_tile_no) * sizeof(OPJ_UINT32)); + if (p_marker_info->p_packet_size == NULL) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + } + + while (opj_pi_next(l_current_pi)) { + if (l_current_pi->layno < p_maxlayers) { + l_nb_bytes = 0; + + if (! opj_t2_encode_packet(p_tile_no, p_tile, l_tcp, l_current_pi, + l_current_data, &l_nb_bytes, p_max_len, + cstr_info, p_t2_mode, p_manager)) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + + l_current_data += l_nb_bytes; + p_max_len -= l_nb_bytes; + + * p_data_written += l_nb_bytes; + + if (p_marker_info && p_marker_info->need_PLT) { + p_marker_info->p_packet_size[p_marker_info->packet_count] = l_nb_bytes; + p_marker_info->packet_count ++; + } + + /* INDEX >> */ + if (cstr_info) { + if (cstr_info->index_write) { + opj_tile_info_t *info_TL = &cstr_info->tile[p_tile_no]; + opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno]; + if (!cstr_info->packno) { + info_PK->start_pos = info_TL->end_header + 1; + } else { + info_PK->start_pos = ((l_cp->m_specific_param.m_enc.m_tp_on | l_tcp->POC) && + info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - + 1].end_pos + 1; + } + info_PK->end_pos = info_PK->start_pos + l_nb_bytes - 1; + info_PK->end_ph_pos += info_PK->start_pos - + 1; /* End of packet header which now only represents the distance + to start of packet is incremented by value of start of packet*/ + } + + cstr_info->packno++; + } + /* << INDEX */ + ++p_tile->packno; + } + } + } + + opj_pi_destroy(l_pi, l_nb_pocs); + + return OPJ_TRUE; +} + +/* see issue 80 */ +#if 0 +#define JAS_FPRINTF fprintf +#else +/* issue 290 */ +static void opj_null_jas_fprintf(FILE* file, const char * format, ...) +{ + (void)file; + (void)format; +} +#define JAS_FPRINTF opj_null_jas_fprintf +#endif + +OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd, + opj_t2_t *p_t2, + OPJ_UINT32 p_tile_no, + opj_tcd_tile_t *p_tile, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_len, + opj_codestream_index_t *p_cstr_index, + opj_event_mgr_t *p_manager) +{ + OPJ_BYTE *l_current_data = p_src; + opj_pi_iterator_t *l_pi = 00; + OPJ_UINT32 pino; + opj_image_t *l_image = p_t2->image; + opj_cp_t *l_cp = p_t2->cp; + opj_tcp_t *l_tcp = &(p_t2->cp->tcps[p_tile_no]); + OPJ_UINT32 l_nb_bytes_read; + OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1; + opj_pi_iterator_t *l_current_pi = 00; +#ifdef TODO_MSD + OPJ_UINT32 curtp = 0; + OPJ_UINT32 tp_start_packno; +#endif + opj_packet_info_t *l_pack_info = 00; + opj_image_comp_t* l_img_comp = 00; + + OPJ_ARG_NOT_USED(p_cstr_index); + +#ifdef TODO_MSD + if (p_cstr_index) { + l_pack_info = p_cstr_index->tile_index[p_tile_no].packet; + } +#endif + + /* create a packet iterator */ + l_pi = opj_pi_create_decode(l_image, l_cp, p_tile_no, p_manager); + if (!l_pi) { + return OPJ_FALSE; + } + + + l_current_pi = l_pi; + + for (pino = 0; pino <= l_tcp->numpocs; ++pino) { + + /* if the resolution needed is too low, one dim of the tilec could be equal to zero + * and no packets are used to decode this resolution and + * l_current_pi->resno is always >= p_tile->comps[l_current_pi->compno].minimum_num_resolutions + * and no l_img_comp->resno_decoded are computed + */ + OPJ_BOOL* first_pass_failed = NULL; + + if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) { + /* TODO ADE : add an error */ + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + + first_pass_failed = (OPJ_BOOL*)opj_malloc(l_image->numcomps * sizeof(OPJ_BOOL)); + if (!first_pass_failed) { + opj_pi_destroy(l_pi, l_nb_pocs); + return OPJ_FALSE; + } + memset(first_pass_failed, OPJ_TRUE, l_image->numcomps * sizeof(OPJ_BOOL)); + + while (opj_pi_next(l_current_pi)) { + OPJ_BOOL skip_packet = OPJ_FALSE; + JAS_FPRINTF(stderr, + "packet offset=00000166 prg=%d cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d\n\n", + l_current_pi->poc.prg1, l_current_pi->compno, l_current_pi->resno, + l_current_pi->precno, l_current_pi->layno); + + /* If the packet layer is greater or equal than the maximum */ + /* number of layers, skip the packet */ + if (l_current_pi->layno >= l_tcp->num_layers_to_decode) { + skip_packet = OPJ_TRUE; + } + /* If the packet resolution number is greater than the minimum */ + /* number of resolution allowed, skip the packet */ + else if (l_current_pi->resno >= + p_tile->comps[l_current_pi->compno].minimum_num_resolutions) { + skip_packet = OPJ_TRUE; + } else { + /* If no precincts of any band intersects the area of interest, */ + /* skip the packet */ + OPJ_UINT32 bandno; + opj_tcd_tilecomp_t *tilec = &p_tile->comps[l_current_pi->compno]; + opj_tcd_resolution_t *res = &tilec->resolutions[l_current_pi->resno]; + + skip_packet = OPJ_TRUE; + for (bandno = 0; bandno < res->numbands; ++bandno) { + opj_tcd_band_t* band = &res->bands[bandno]; + opj_tcd_precinct_t* prec = &band->precincts[l_current_pi->precno]; + + if (opj_tcd_is_subband_area_of_interest(tcd, + l_current_pi->compno, + l_current_pi->resno, + band->bandno, + (OPJ_UINT32)prec->x0, + (OPJ_UINT32)prec->y0, + (OPJ_UINT32)prec->x1, + (OPJ_UINT32)prec->y1)) { + skip_packet = OPJ_FALSE; + break; + } + } + /* + printf("packet cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d -> %s\n", + l_current_pi->compno, l_current_pi->resno, + l_current_pi->precno, l_current_pi->layno, skip_packet ? "skipped" : "kept"); + */ + } + if (!skip_packet) { + l_nb_bytes_read = 0; + + first_pass_failed[l_current_pi->compno] = OPJ_FALSE; + + if (! opj_t2_decode_packet(p_t2, p_tile, l_tcp, l_current_pi, l_current_data, + &l_nb_bytes_read, p_max_len, l_pack_info, p_manager)) { + opj_pi_destroy(l_pi, l_nb_pocs); + opj_free(first_pass_failed); + return OPJ_FALSE; + } + + l_img_comp = &(l_image->comps[l_current_pi->compno]); + l_img_comp->resno_decoded = opj_uint_max(l_current_pi->resno, + l_img_comp->resno_decoded); + } else { + l_nb_bytes_read = 0; + if (! opj_t2_skip_packet(p_t2, p_tile, l_tcp, l_current_pi, l_current_data, + &l_nb_bytes_read, p_max_len, l_pack_info, p_manager)) { + opj_pi_destroy(l_pi, l_nb_pocs); + opj_free(first_pass_failed); + return OPJ_FALSE; + } + } + + if (first_pass_failed[l_current_pi->compno]) { + l_img_comp = &(l_image->comps[l_current_pi->compno]); + if (l_img_comp->resno_decoded == 0) { + l_img_comp->resno_decoded = + p_tile->comps[l_current_pi->compno].minimum_num_resolutions - 1; + } + } + + l_current_data += l_nb_bytes_read; + p_max_len -= l_nb_bytes_read; + + /* INDEX >> */ +#ifdef TODO_MSD + if (p_cstr_info) { + opj_tile_info_v2_t *info_TL = &p_cstr_info->tile[p_tile_no]; + opj_packet_info_t *info_PK = &info_TL->packet[p_cstr_info->packno]; + tp_start_packno = 0; + if (!p_cstr_info->packno) { + info_PK->start_pos = info_TL->end_header + 1; + } else if (info_TL->packet[p_cstr_info->packno - 1].end_pos >= + (OPJ_INT32) + p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_pos) { /* New tile part */ + info_TL->tp[curtp].tp_numpacks = p_cstr_info->packno - + tp_start_packno; /* Number of packets in previous tile-part */ + tp_start_packno = p_cstr_info->packno; + curtp++; + info_PK->start_pos = p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_header + 1; + } else { + info_PK->start_pos = (l_cp->m_specific_param.m_enc.m_tp_on && + info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[p_cstr_info->packno - + 1].end_pos + 1; + } + info_PK->end_pos = info_PK->start_pos + l_nb_bytes_read - 1; + info_PK->end_ph_pos += info_PK->start_pos - + 1; /* End of packet header which now only represents the distance */ + ++p_cstr_info->packno; + } +#endif + /* << INDEX */ + } + ++l_current_pi; + + opj_free(first_pass_failed); + } + /* INDEX >> */ +#ifdef TODO_MSD + if + (p_cstr_info) { + p_cstr_info->tile[p_tile_no].tp[curtp].tp_numpacks = p_cstr_info->packno - + tp_start_packno; /* Number of packets in last tile-part */ + } +#endif + /* << INDEX */ + + /* don't forget to release pi */ + opj_pi_destroy(l_pi, l_nb_pocs); + *p_data_read = (OPJ_UINT32)(l_current_data - p_src); + return OPJ_TRUE; +} + +/* ----------------------------------------------------------------------- */ + +/** + * Creates a Tier 2 handle + * + * @param p_image Source or destination image + * @param p_cp Image coding parameters. + * @return a new T2 handle if successful, NULL otherwise. +*/ +opj_t2_t* opj_t2_create(opj_image_t *p_image, opj_cp_t *p_cp) +{ + /* create the t2 structure */ + opj_t2_t *l_t2 = (opj_t2_t*)opj_calloc(1, sizeof(opj_t2_t)); + if (!l_t2) { + return NULL; + } + + l_t2->image = p_image; + l_t2->cp = p_cp; + + return l_t2; +} + +void opj_t2_destroy(opj_t2_t *t2) +{ + if (t2) { + opj_free(t2); + } +} + +static OPJ_BOOL opj_t2_decode_packet(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager) +{ + OPJ_BOOL l_read_data; + OPJ_UINT32 l_nb_bytes_read = 0; + OPJ_UINT32 l_nb_total_bytes_read = 0; + + *p_data_read = 0; + + if (! opj_t2_read_packet_header(p_t2, p_tile, p_tcp, p_pi, &l_read_data, p_src, + &l_nb_bytes_read, p_max_length, p_pack_info, p_manager)) { + return OPJ_FALSE; + } + + p_src += l_nb_bytes_read; + l_nb_total_bytes_read += l_nb_bytes_read; + p_max_length -= l_nb_bytes_read; + + /* we should read data for the packet */ + if (l_read_data) { + l_nb_bytes_read = 0; + + if (! opj_t2_read_packet_data(p_t2, p_tile, p_pi, p_src, &l_nb_bytes_read, + p_max_length, p_pack_info, p_manager)) { + return OPJ_FALSE; + } + + l_nb_total_bytes_read += l_nb_bytes_read; + } + + *p_data_read = l_nb_total_bytes_read; + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno, + opj_tcd_tile_t * tile, + opj_tcp_t * tcp, + opj_pi_iterator_t *pi, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 length, + opj_codestream_info_t *cstr_info, + J2K_T2_MODE p_t2_mode, + opj_event_mgr_t *p_manager) +{ + OPJ_UINT32 bandno, cblkno; + OPJ_BYTE* c = dest; + OPJ_UINT32 l_nb_bytes; + OPJ_UINT32 compno = pi->compno; /* component value */ + OPJ_UINT32 resno = pi->resno; /* resolution level value */ + OPJ_UINT32 precno = pi->precno; /* precinct value */ + OPJ_UINT32 layno = pi->layno; /* quality layer value */ + OPJ_UINT32 l_nb_blocks; + opj_tcd_band_t *band = 00; + opj_tcd_cblk_enc_t* cblk = 00; + opj_tcd_pass_t *pass = 00; + + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + opj_bio_t *bio = 00; /* BIO component */ +#ifdef ENABLE_EMPTY_PACKET_OPTIMIZATION + OPJ_BOOL packet_empty = OPJ_TRUE; +#else + OPJ_BOOL packet_empty = OPJ_FALSE; +#endif + +#ifdef DEBUG_VERBOSE + if (p_t2_mode == FINAL_PASS) { + fprintf(stderr, + "encode packet compono=%d, resno=%d, precno=%d, layno=%d\n", + compno, resno, precno, layno); + } +#endif + + /* */ + if (tcp->csty & J2K_CP_CSTY_SOP) { + if (length < 6) { + if (p_t2_mode == FINAL_PASS) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_t2_encode_packet(): only %u bytes remaining in " + "output buffer. %u needed.\n", + length, 6); + } + return OPJ_FALSE; + } + c[0] = 255; + c[1] = 145; + c[2] = 0; + c[3] = 4; +#if 0 + c[4] = (tile->packno % 65536) / 256; + c[5] = (tile->packno % 65536) % 256; +#else + c[4] = (tile->packno >> 8) & 0xff; /* packno is uint32_t */ + c[5] = tile->packno & 0xff; +#endif + c += 6; + length -= 6; + } + /* */ + + if (!layno) { + band = res->bands; + + for (bandno = 0; bandno < res->numbands; ++bandno, ++band) { + opj_tcd_precinct_t *prc; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + /* Avoid out of bounds access of https://github.com/uclouvain/openjpeg/issues/1294 */ + /* but likely not a proper fix. */ + if (precno >= res->pw * res->ph) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_t2_encode_packet(): accessing precno=%u >= %u\n", + precno, res->pw * res->ph); + return OPJ_FALSE; + } + + prc = &band->precincts[precno]; + opj_tgt_reset(prc->incltree); + opj_tgt_reset(prc->imsbtree); + + l_nb_blocks = prc->cw * prc->ch; + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { + cblk = &prc->cblks.enc[cblkno]; + + cblk->numpasses = 0; + opj_tgt_setvalue(prc->imsbtree, cblkno, band->numbps - (OPJ_INT32)cblk->numbps); + } + } + } + + bio = opj_bio_create(); + if (!bio) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + opj_bio_init_enc(bio, c, length); + +#ifdef ENABLE_EMPTY_PACKET_OPTIMIZATION + /* WARNING: this code branch is disabled, since it has been reported that */ + /* such packets cause decoding issues with cinema J2K hardware */ + /* decoders: https://groups.google.com/forum/#!topic/openjpeg/M7M_fLX_Bco */ + + /* Check if the packet is empty */ + /* Note: we could also skip that step and always write a packet header */ + band = res->bands; + for (bandno = 0; bandno < res->numbands; ++bandno, ++band) { + opj_tcd_precinct_t *prc; + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + prc = &band->precincts[precno]; + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; + for (cblkno = 0; cblkno < l_nb_blocks; cblkno++, ++cblk) { + opj_tcd_layer_t *layer = &cblk->layers[layno]; + + /* if cblk not included, go to the next cblk */ + if (!layer->numpasses) { + continue; + } + packet_empty = OPJ_FALSE; + break; + } + if (!packet_empty) { + break; + } + } +#endif + opj_bio_putbit(bio, packet_empty ? 0 : 1); /* Empty header bit */ + + /* Writing Packet header */ + band = res->bands; + for (bandno = 0; !packet_empty && + bandno < res->numbands; ++bandno, ++band) { + opj_tcd_precinct_t *prc; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + /* Avoid out of bounds access of https://github.com/uclouvain/openjpeg/issues/1297 */ + /* but likely not a proper fix. */ + if (precno >= res->pw * res->ph) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_t2_encode_packet(): accessing precno=%u >= %u\n", + precno, res->pw * res->ph); + return OPJ_FALSE; + } + + prc = &band->precincts[precno]; + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; + + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { + opj_tcd_layer_t *layer = &cblk->layers[layno]; + + if (!cblk->numpasses && layer->numpasses) { + opj_tgt_setvalue(prc->incltree, cblkno, (OPJ_INT32)layno); + } + + ++cblk; + } + + cblk = prc->cblks.enc; + for (cblkno = 0; cblkno < l_nb_blocks; cblkno++) { + opj_tcd_layer_t *layer = &cblk->layers[layno]; + OPJ_UINT32 increment = 0; + OPJ_UINT32 nump = 0; + OPJ_UINT32 len = 0, passno; + OPJ_UINT32 l_nb_passes; + + /* cblk inclusion bits */ + if (!cblk->numpasses) { + opj_tgt_encode(bio, prc->incltree, cblkno, (OPJ_INT32)(layno + 1)); + } else { + opj_bio_putbit(bio, layer->numpasses != 0); + } + + /* if cblk not included, go to the next cblk */ + if (!layer->numpasses) { + ++cblk; + continue; + } + + /* if first instance of cblk --> zero bit-planes information */ + if (!cblk->numpasses) { + cblk->numlenbits = 3; + opj_tgt_encode(bio, prc->imsbtree, cblkno, 999); + } + + /* number of coding passes included */ + opj_t2_putnumpasses(bio, layer->numpasses); + l_nb_passes = cblk->numpasses + layer->numpasses; + pass = cblk->passes + cblk->numpasses; + + /* computation of the increase of the length indicator and insertion in the header */ + for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) { + ++nump; + len += pass->len; + + if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { + increment = (OPJ_UINT32)opj_int_max((OPJ_INT32)increment, + opj_int_floorlog2((OPJ_INT32)len) + 1 + - ((OPJ_INT32)cblk->numlenbits + opj_int_floorlog2((OPJ_INT32)nump))); + len = 0; + nump = 0; + } + + ++pass; + } + opj_t2_putcommacode(bio, (OPJ_INT32)increment); + + /* computation of the new Length indicator */ + cblk->numlenbits += increment; + + pass = cblk->passes + cblk->numpasses; + /* insertion of the codeword segment length */ + for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) { + nump++; + len += pass->len; + + if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) { + opj_bio_write(bio, (OPJ_UINT32)len, + cblk->numlenbits + (OPJ_UINT32)opj_int_floorlog2((OPJ_INT32)nump)); + len = 0; + nump = 0; + } + ++pass; + } + + ++cblk; + } + } + + if (!opj_bio_flush(bio)) { + opj_bio_destroy(bio); + return OPJ_FALSE; /* modified to eliminate longjmp !! */ + } + + l_nb_bytes = (OPJ_UINT32)opj_bio_numbytes(bio); + c += l_nb_bytes; + length -= l_nb_bytes; + + opj_bio_destroy(bio); + + /* */ + if (tcp->csty & J2K_CP_CSTY_EPH) { + if (length < 2) { + if (p_t2_mode == FINAL_PASS) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_t2_encode_packet(): only %u bytes remaining in " + "output buffer. %u needed.\n", + length, 2); + } + return OPJ_FALSE; + } + c[0] = 255; + c[1] = 146; + c += 2; + length -= 2; + } + /* */ + + /* << INDEX */ + /* End of packet header position. Currently only represents the distance to start of packet + Will be updated later by incrementing with packet start value*/ + if (cstr_info && cstr_info->index_write) { + opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; + info_PK->end_ph_pos = (OPJ_INT32)(c - dest); + } + /* INDEX >> */ + + /* Writing the packet body */ + band = res->bands; + for (bandno = 0; !packet_empty && bandno < res->numbands; bandno++, ++band) { + opj_tcd_precinct_t *prc; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + prc = &band->precincts[precno]; + l_nb_blocks = prc->cw * prc->ch; + cblk = prc->cblks.enc; + + for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) { + opj_tcd_layer_t *layer = &cblk->layers[layno]; + + if (!layer->numpasses) { + ++cblk; + continue; + } + + if (layer->len > length) { + if (p_t2_mode == FINAL_PASS) { + opj_event_msg(p_manager, EVT_ERROR, + "opj_t2_encode_packet(): only %u bytes remaining in " + "output buffer. %u needed.\n", + length, layer->len); + } + return OPJ_FALSE; + } + + if (p_t2_mode == FINAL_PASS) { + memcpy(c, layer->data, layer->len); + } + cblk->numpasses += layer->numpasses; + c += layer->len; + length -= layer->len; + + /* << INDEX */ + if (cstr_info && cstr_info->index_write) { + opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno]; + info_PK->disto += layer->disto; + if (cstr_info->D_max < info_PK->disto) { + cstr_info->D_max = info_PK->disto; + } + } + + ++cblk; + /* INDEX >> */ + } + } + + assert(c >= dest); + * p_data_written += (OPJ_UINT32)(c - dest); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_t2_skip_packet(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager) +{ + OPJ_BOOL l_read_data; + OPJ_UINT32 l_nb_bytes_read = 0; + OPJ_UINT32 l_nb_total_bytes_read = 0; + + *p_data_read = 0; + + if (! opj_t2_read_packet_header(p_t2, p_tile, p_tcp, p_pi, &l_read_data, p_src, + &l_nb_bytes_read, p_max_length, p_pack_info, p_manager)) { + return OPJ_FALSE; + } + + p_src += l_nb_bytes_read; + l_nb_total_bytes_read += l_nb_bytes_read; + p_max_length -= l_nb_bytes_read; + + /* we should read data for the packet */ + if (l_read_data) { + l_nb_bytes_read = 0; + + if (! opj_t2_skip_packet_data(p_t2, p_tile, p_pi, &l_nb_bytes_read, + p_max_length, p_pack_info, p_manager)) { + return OPJ_FALSE; + } + + l_nb_total_bytes_read += l_nb_bytes_read; + } + *p_data_read = l_nb_total_bytes_read; + + return OPJ_TRUE; +} + + +static OPJ_BOOL opj_t2_read_packet_header(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_tcp_t *p_tcp, + opj_pi_iterator_t *p_pi, + OPJ_BOOL * p_is_data_present, + OPJ_BYTE *p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *p_pack_info, + opj_event_mgr_t *p_manager) + +{ + /* loop */ + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_code_blocks; + OPJ_UINT32 l_remaining_length; + OPJ_UINT32 l_header_length; + OPJ_UINT32 * l_modified_length_ptr = 00; + OPJ_BYTE *l_current_data = p_src_data; + opj_cp_t *l_cp = p_t2->cp; + opj_bio_t *l_bio = 00; /* BIO component */ + opj_tcd_band_t *l_band = 00; + opj_tcd_cblk_dec_t* l_cblk = 00; + opj_tcd_resolution_t* l_res = + &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; + + OPJ_BYTE *l_header_data = 00; + OPJ_BYTE **l_header_data_start = 00; + + OPJ_UINT32 l_present; + + if (p_pi->layno == 0) { + l_band = l_res->bands; + + /* reset tagtrees */ + for (bandno = 0; bandno < l_res->numbands; ++bandno) { + if (!opj_tcd_is_band_empty(l_band)) { + opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + if (!(p_pi->precno < (l_band->precincts_data_size / sizeof( + opj_tcd_precinct_t)))) { + opj_event_msg(p_manager, EVT_ERROR, "Invalid precinct\n"); + return OPJ_FALSE; + } + + + opj_tgt_reset(l_prc->incltree); + opj_tgt_reset(l_prc->imsbtree); + l_cblk = l_prc->cblks.dec; + + l_nb_code_blocks = l_prc->cw * l_prc->ch; + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + l_cblk->numsegs = 0; + l_cblk->real_num_segs = 0; + ++l_cblk; + } + } + + ++l_band; + } + } + + /* SOP markers */ + + if (p_tcp->csty & J2K_CP_CSTY_SOP) { + /* SOP markers are allowed (i.e. optional), just warn */ + if (p_max_length < 6) { + opj_event_msg(p_manager, EVT_WARNING, + "Not enough space for expected SOP marker\n"); + } else if ((*l_current_data) != 0xff || (*(l_current_data + 1) != 0x91)) { + opj_event_msg(p_manager, EVT_WARNING, "Expected SOP marker\n"); + } else { + l_current_data += 6; + } + + /** TODO : check the Nsop value */ + } + + /* + When the marker PPT/PPM is used the packet header are store in PPT/PPM marker + This part deal with this characteristic + step 1: Read packet header in the saved structure + step 2: Return to codestream for decoding + */ + + l_bio = opj_bio_create(); + if (! l_bio) { + return OPJ_FALSE; + } + + if (l_cp->ppm == 1) { /* PPM */ + l_header_data_start = &l_cp->ppm_data; + l_header_data = *l_header_data_start; + l_modified_length_ptr = &(l_cp->ppm_len); + + } else if (p_tcp->ppt == 1) { /* PPT */ + l_header_data_start = &(p_tcp->ppt_data); + l_header_data = *l_header_data_start; + l_modified_length_ptr = &(p_tcp->ppt_len); + } else { /* Normal Case */ + l_header_data_start = &(l_current_data); + l_header_data = *l_header_data_start; + l_remaining_length = (OPJ_UINT32)(p_src_data + p_max_length - l_header_data); + l_modified_length_ptr = &(l_remaining_length); + } + + opj_bio_init_dec(l_bio, l_header_data, *l_modified_length_ptr); + + l_present = opj_bio_read(l_bio, 1); + JAS_FPRINTF(stderr, "present=%d \n", l_present); + if (!l_present) { + /* TODO MSD: no test to control the output of this function*/ + opj_bio_inalign(l_bio); + l_header_data += opj_bio_numbytes(l_bio); + opj_bio_destroy(l_bio); + + /* EPH markers */ + if (p_tcp->csty & J2K_CP_CSTY_EPH) { + /* EPH markers are required */ + if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - + *l_header_data_start)) < 2U) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough space for required EPH marker\n"); + return OPJ_FALSE; + } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { + opj_event_msg(p_manager, EVT_ERROR, "Expected EPH marker\n"); + return OPJ_FALSE; + } else { + l_header_data += 2; + } + } + + l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start); + *l_modified_length_ptr -= l_header_length; + *l_header_data_start += l_header_length; + + /* << INDEX */ + /* End of packet header position. Currently only represents the distance to start of packet + Will be updated later by incrementing with packet start value */ + if (p_pack_info) { + p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data); + } + /* INDEX >> */ + + * p_is_data_present = OPJ_FALSE; + *p_data_read = (OPJ_UINT32)(l_current_data - p_src_data); + return OPJ_TRUE; + } + + l_band = l_res->bands; + for (bandno = 0; bandno < l_res->numbands; ++bandno, ++l_band) { + opj_tcd_precinct_t *l_prc = &(l_band->precincts[p_pi->precno]); + + if (opj_tcd_is_band_empty(l_band)) { + continue; + } + + l_nb_code_blocks = l_prc->cw * l_prc->ch; + l_cblk = l_prc->cblks.dec; + for (cblkno = 0; cblkno < l_nb_code_blocks; cblkno++) { + OPJ_UINT32 l_included, l_increment, l_segno; + OPJ_INT32 n; + + /* if cblk not yet included before --> inclusion tagtree */ + if (!l_cblk->numsegs) { + l_included = opj_tgt_decode(l_bio, l_prc->incltree, cblkno, + (OPJ_INT32)(p_pi->layno + 1)); + /* else one bit */ + } else { + l_included = opj_bio_read(l_bio, 1); + } + + /* if cblk not included */ + if (!l_included) { + l_cblk->numnewpasses = 0; + ++l_cblk; + JAS_FPRINTF(stderr, "included=%d \n", l_included); + continue; + } + + /* if cblk not yet included --> zero-bitplane tagtree */ + if (!l_cblk->numsegs) { + OPJ_UINT32 i = 0; + + while (!opj_tgt_decode(l_bio, l_prc->imsbtree, cblkno, (OPJ_INT32)i)) { + ++i; + } + l_cblk->Mb = (OPJ_UINT32)l_band->numbps; + if ((OPJ_UINT32)l_band->numbps + 1 < i) { + /* Not totally sure what we should do in that situation, + * but that avoids the integer overflow of + * https://github.com/uclouvain/openjpeg/pull/1488 + * while keeping the regression test suite happy. + */ + l_cblk->numbps = (OPJ_UINT32)(l_band->numbps + 1 - (int)i); + } else { + l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i; + } + l_cblk->numlenbits = 3; + } + + /* number of coding passes */ + l_cblk->numnewpasses = opj_t2_getnumpasses(l_bio); + l_increment = opj_t2_getcommacode(l_bio); + + /* length indicator increment */ + l_cblk->numlenbits += l_increment; + l_segno = 0; + + if (!l_cblk->numsegs) { + if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 1)) { + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + } else { + l_segno = l_cblk->numsegs - 1; + if (l_cblk->segs[l_segno].numpasses == l_cblk->segs[l_segno].maxpasses) { + ++l_segno; + if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) { + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + } + } + n = (OPJ_INT32)l_cblk->numnewpasses; + + if ((p_tcp->tccps[p_pi->compno].cblksty & J2K_CCP_CBLKSTY_HT) != 0) + do { + OPJ_UINT32 bit_number; + l_cblk->segs[l_segno].numnewpasses = l_segno == 0 ? 1 : (OPJ_UINT32)n; + bit_number = l_cblk->numlenbits + opj_uint_floorlog2( + l_cblk->segs[l_segno].numnewpasses); + if (bit_number > 32) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid bit number %d in opj_t2_read_packet_header()\n", + bit_number); + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + l_cblk->segs[l_segno].newlen = opj_bio_read(l_bio, bit_number); + JAS_FPRINTF(stderr, "included=%d numnewpasses=%d increment=%d len=%d \n", + l_included, l_cblk->segs[l_segno].numnewpasses, l_increment, + l_cblk->segs[l_segno].newlen); + + n -= (OPJ_INT32)l_cblk->segs[l_segno].numnewpasses; + if (n > 0) { + ++l_segno; + + if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) { + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + } + } while (n > 0); + else + do { + OPJ_UINT32 bit_number; + l_cblk->segs[l_segno].numnewpasses = (OPJ_UINT32)opj_int_min((OPJ_INT32)( + l_cblk->segs[l_segno].maxpasses - l_cblk->segs[l_segno].numpasses), n); + bit_number = l_cblk->numlenbits + opj_uint_floorlog2( + l_cblk->segs[l_segno].numnewpasses); + if (bit_number > 32) { + opj_event_msg(p_manager, EVT_ERROR, + "Invalid bit number %d in opj_t2_read_packet_header()\n", + bit_number); + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + l_cblk->segs[l_segno].newlen = opj_bio_read(l_bio, bit_number); + JAS_FPRINTF(stderr, "included=%d numnewpasses=%d increment=%d len=%d \n", + l_included, l_cblk->segs[l_segno].numnewpasses, l_increment, + l_cblk->segs[l_segno].newlen); + + n -= (OPJ_INT32)l_cblk->segs[l_segno].numnewpasses; + if (n > 0) { + ++l_segno; + + if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) { + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + } + } while (n > 0); + + ++l_cblk; + } + } + + if (!opj_bio_inalign(l_bio)) { + opj_bio_destroy(l_bio); + return OPJ_FALSE; + } + + l_header_data += opj_bio_numbytes(l_bio); + opj_bio_destroy(l_bio); + + /* EPH markers */ + if (p_tcp->csty & J2K_CP_CSTY_EPH) { + /* EPH markers are required */ + if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - + *l_header_data_start)) < 2U) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough space for required EPH marker\n"); + return OPJ_FALSE; + } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { + opj_event_msg(p_manager, EVT_ERROR, "Expected EPH marker\n"); + return OPJ_FALSE; + } else { + l_header_data += 2; + } + } + + l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start); + JAS_FPRINTF(stderr, "hdrlen=%d \n", l_header_length); + if (!l_header_length) { + return OPJ_FALSE; + } + JAS_FPRINTF(stderr, "packet body\n"); + *l_modified_length_ptr -= l_header_length; + *l_header_data_start += l_header_length; + + /* << INDEX */ + /* End of packet header position. Currently only represents the distance to start of packet + Will be updated later by incrementing with packet start value */ + if (p_pack_info) { + p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data); + } + /* INDEX >> */ + + *p_is_data_present = OPJ_TRUE; + *p_data_read = (OPJ_UINT32)(l_current_data - p_src_data); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_pi_iterator_t *p_pi, + OPJ_BYTE *p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *pack_info, + opj_event_mgr_t* p_manager) +{ + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_code_blocks; + OPJ_BYTE *l_current_data = p_src_data; + opj_tcd_band_t *l_band = 00; + opj_tcd_cblk_dec_t* l_cblk = 00; + opj_tcd_resolution_t* l_res = + &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; + OPJ_BOOL partial_buffer = OPJ_FALSE; + + OPJ_ARG_NOT_USED(p_t2); + OPJ_ARG_NOT_USED(pack_info); + + l_band = l_res->bands; + for (bandno = 0; bandno < l_res->numbands; ++bandno) { + opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + + if ((l_band->x1 - l_band->x0 == 0) || (l_band->y1 - l_band->y0 == 0)) { + ++l_band; + continue; + } + + l_nb_code_blocks = l_prc->cw * l_prc->ch; + l_cblk = l_prc->cblks.dec; + + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno, ++l_cblk) { + opj_tcd_seg_t *l_seg = 00; + + if (!l_cblk->numnewpasses) { + /* nothing to do */ + continue; + } + + if (partial_buffer || l_cblk->corrupted) { + /* if a previous segment in this packet couldn't be decoded, + * or if this code block was corrupted in a previous layer, + * then mark it as corrupted. + */ + l_cblk->numchunks = 0; + l_cblk->corrupted = OPJ_TRUE; + continue; + } + + if (!l_cblk->numsegs) { + l_seg = l_cblk->segs; + ++l_cblk->numsegs; + } else { + l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; + + if (l_seg->numpasses == l_seg->maxpasses) { + ++l_seg; + ++l_cblk->numsegs; + } + } + + do { + /* Check possible overflow (on l_current_data only, assumes input args already checked) then size */ + if ((((OPJ_SIZE_T)l_current_data + (OPJ_SIZE_T)l_seg->newlen) < + (OPJ_SIZE_T)l_current_data) || + (l_current_data + l_seg->newlen > p_src_data + p_max_length) || + (partial_buffer)) { + if (p_t2->cp->strict) { + opj_event_msg(p_manager, EVT_ERROR, + "read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, + p_pi->compno); + return OPJ_FALSE; + } else { + opj_event_msg(p_manager, EVT_WARNING, + "read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, + p_pi->compno); + /* skip this codeblock (and following ones in this + * packet) since it is a partial read + */ + partial_buffer = OPJ_TRUE; + l_cblk->corrupted = OPJ_TRUE; + l_cblk->numchunks = 0; + break; + } + } + +#ifdef USE_JPWL + /* we need here a j2k handle to verify if making a check to + the validity of cblocks parameters is selected from user (-W) */ + + /* let's check that we are not exceeding */ + if ((l_cblk->len + l_seg->newlen) > 8192) { + opj_event_msg(p_manager, EVT_WARNING, + "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return OPJ_FALSE; + } + l_seg->newlen = 8192 - l_cblk->len; + opj_event_msg(p_manager, EVT_WARNING, " - truncating segment to %d\n", + l_seg->newlen); + break; + }; + +#endif /* USE_JPWL */ + + if (l_cblk->numchunks == l_cblk->numchunksalloc) { + OPJ_UINT32 l_numchunksalloc = l_cblk->numchunksalloc * 2 + 1; + opj_tcd_seg_data_chunk_t* l_chunks = + (opj_tcd_seg_data_chunk_t*)opj_realloc(l_cblk->chunks, + l_numchunksalloc * sizeof(opj_tcd_seg_data_chunk_t)); + if (l_chunks == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "cannot allocate opj_tcd_seg_data_chunk_t* array"); + return OPJ_FALSE; + } + l_cblk->chunks = l_chunks; + l_cblk->numchunksalloc = l_numchunksalloc; + } + + l_cblk->chunks[l_cblk->numchunks].data = l_current_data; + l_cblk->chunks[l_cblk->numchunks].len = l_seg->newlen; + l_cblk->numchunks ++; + + l_current_data += l_seg->newlen; + l_seg->len += l_seg->newlen; + l_seg->numpasses += l_seg->numnewpasses; + l_cblk->numnewpasses -= l_seg->numnewpasses; + + l_seg->real_num_passes = l_seg->numpasses; + + if (l_cblk->numnewpasses > 0) { + ++l_seg; + ++l_cblk->numsegs; + } + } while (l_cblk->numnewpasses > 0); + + l_cblk->real_num_segs = l_cblk->numsegs; + + } /* next code_block */ + + ++l_band; + } + + // return the number of bytes read + if (partial_buffer) { + *(p_data_read) = p_max_length; + } else { + *(p_data_read) = (OPJ_UINT32)(l_current_data - p_src_data); + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2, + opj_tcd_tile_t *p_tile, + opj_pi_iterator_t *p_pi, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_length, + opj_packet_info_t *pack_info, + opj_event_mgr_t *p_manager) +{ + OPJ_UINT32 bandno, cblkno; + OPJ_UINT32 l_nb_code_blocks; + opj_tcd_band_t *l_band = 00; + opj_tcd_cblk_dec_t* l_cblk = 00; + opj_tcd_resolution_t* l_res = + &p_tile->comps[p_pi->compno].resolutions[p_pi->resno]; + + OPJ_ARG_NOT_USED(p_t2); + OPJ_ARG_NOT_USED(pack_info); + + *p_data_read = 0; + l_band = l_res->bands; + + for (bandno = 0; bandno < l_res->numbands; ++bandno) { + opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno]; + + if ((l_band->x1 - l_band->x0 == 0) || (l_band->y1 - l_band->y0 == 0)) { + ++l_band; + continue; + } + + l_nb_code_blocks = l_prc->cw * l_prc->ch; + l_cblk = l_prc->cblks.dec; + + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + opj_tcd_seg_t *l_seg = 00; + + if (!l_cblk->numnewpasses) { + /* nothing to do */ + ++l_cblk; + continue; + } + + if (!l_cblk->numsegs) { + l_seg = l_cblk->segs; + ++l_cblk->numsegs; + } else { + l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; + + if (l_seg->numpasses == l_seg->maxpasses) { + ++l_seg; + ++l_cblk->numsegs; + } + } + + do { + /* Check possible overflow then size */ + if (((*p_data_read + l_seg->newlen) < (*p_data_read)) || + ((*p_data_read + l_seg->newlen) > p_max_length)) { + if (p_t2->cp->strict) { + opj_event_msg(p_manager, EVT_ERROR, + "skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, + p_pi->compno); + return OPJ_FALSE; + } else { + opj_event_msg(p_manager, EVT_WARNING, + "skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno, + p_pi->compno); + + *p_data_read = p_max_length; + return OPJ_TRUE; + } + } + +#ifdef USE_JPWL + /* we need here a j2k handle to verify if making a check to + the validity of cblocks parameters is selected from user (-W) */ + + /* let's check that we are not exceeding */ + if ((l_cblk->len + l_seg->newlen) > 8192) { + opj_event_msg(p_manager, EVT_WARNING, + "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", + l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno); + if (!JPWL_ASSUME) { + opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n"); + return -999; + } + l_seg->newlen = 8192 - l_cblk->len; + opj_event_msg(p_manager, EVT_WARNING, " - truncating segment to %d\n", + l_seg->newlen); + break; + }; + +#endif /* USE_JPWL */ + JAS_FPRINTF(stderr, "p_data_read (%d) newlen (%d) \n", *p_data_read, + l_seg->newlen); + *(p_data_read) += l_seg->newlen; + + l_seg->numpasses += l_seg->numnewpasses; + l_cblk->numnewpasses -= l_seg->numnewpasses; + if (l_cblk->numnewpasses > 0) { + ++l_seg; + ++l_cblk->numsegs; + } + } while (l_cblk->numnewpasses > 0); + + ++l_cblk; + } + + ++l_band; + } + + return OPJ_TRUE; +} + + +static OPJ_BOOL opj_t2_init_seg(opj_tcd_cblk_dec_t* cblk, + OPJ_UINT32 index, + OPJ_UINT32 cblksty, + OPJ_UINT32 first) +{ + opj_tcd_seg_t* seg = 00; + OPJ_UINT32 l_nb_segs = index + 1; + + if (l_nb_segs > cblk->m_current_max_segs) { + opj_tcd_seg_t* new_segs; + OPJ_UINT32 l_m_current_max_segs = cblk->m_current_max_segs + + OPJ_J2K_DEFAULT_NB_SEGS; + + new_segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, + l_m_current_max_segs * sizeof(opj_tcd_seg_t)); + if (! new_segs) { + /* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to initialize segment %d\n", l_nb_segs); */ + return OPJ_FALSE; + } + cblk->segs = new_segs; + memset(new_segs + cblk->m_current_max_segs, + 0, OPJ_J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t)); + cblk->m_current_max_segs = l_m_current_max_segs; + } + + seg = &cblk->segs[index]; + opj_tcd_reinit_segment(seg); + + if (cblksty & J2K_CCP_CBLKSTY_TERMALL) { + seg->maxpasses = 1; + } else if (cblksty & J2K_CCP_CBLKSTY_LAZY) { + if (first) { + seg->maxpasses = 10; + } else { + seg->maxpasses = (((seg - 1)->maxpasses == 1) || + ((seg - 1)->maxpasses == 10)) ? 2 : 1; + } + } else { + /* See paragraph "B.10.6 Number of coding passes" of the standard. + * Probably that 109 must be interpreted a (Mb-1)*3 + 1 with Mb=37, + * Mb being the maximum number of bit-planes available for the + * representation of coefficients in the sub-band */ + seg->maxpasses = 109; + } + + return OPJ_TRUE; +} diff --git a/client/deps/openjpeg/t2.h b/client/deps/openjpeg/t2.h new file mode 100644 index 000000000..becfa91a4 --- /dev/null +++ b/client/deps/openjpeg/t2.h @@ -0,0 +1,142 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_T2_H +#define OPJ_T2_H +/** +@file t2.h +@brief Implementation of a tier-2 coding (packetization of code-block data) (T2) + +*/ + +/** @defgroup T2 T2 - Implementation of a tier-2 coding */ +/*@{*/ + +/** +Tier-2 coding +*/ +typedef struct opj_t2 { + + /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */ + opj_image_t *image; + /** pointer to the image coding parameters */ + opj_cp_t *cp; +} opj_t2_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Encode the packets of a tile to a destination buffer +@param t2 T2 handle +@param tileno number of the tile encoded +@param tile the tile for which to write the packets +@param maxlayers maximum number of layers +@param dest the destination buffer +@param p_data_written FIXME DOC +@param len the length of the destination buffer +@param cstr_info Codestream information structure +@param p_marker_info Marker information structure +@param tpnum Tile part number of the current tile +@param tppos The position of the tile part flag in the progression order +@param pino FIXME DOC +@param t2_mode If == THRESH_CALC In Threshold calculation ,If == FINAL_PASS Final pass +@param p_manager the user event manager +*/ +OPJ_BOOL opj_t2_encode_packets(opj_t2_t* t2, + OPJ_UINT32 tileno, + opj_tcd_tile_t *tile, + OPJ_UINT32 maxlayers, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len, + opj_codestream_info_t *cstr_info, + opj_tcd_marker_info_t* p_marker_info, + OPJ_UINT32 tpnum, + OPJ_INT32 tppos, + OPJ_UINT32 pino, + J2K_T2_MODE t2_mode, + opj_event_mgr_t *p_manager); + +/** +Decode the packets of a tile from a source buffer +@param tcd TCD handle +@param t2 T2 handle +@param tileno number that identifies the tile for which to decode the packets +@param tile tile for which to decode the packets +@param src FIXME DOC +@param p_data_read the source buffer +@param len length of the source buffer +@param cstr_info FIXME DOC +@param p_manager the user event manager + +@return FIXME DOC + */ +OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd, + opj_t2_t *t2, + OPJ_UINT32 tileno, + opj_tcd_tile_t *tile, + OPJ_BYTE *src, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 len, + opj_codestream_index_t *cstr_info, + opj_event_mgr_t *p_manager); + +/** + * Creates a Tier 2 handle + * + * @param p_image Source or destination image + * @param p_cp Image coding parameters. + * @return a new T2 handle if successful, NULL otherwise. +*/ +opj_t2_t* opj_t2_create(opj_image_t *p_image, opj_cp_t *p_cp); + +/** +Destroy a T2 handle +@param t2 T2 handle to destroy +*/ +void opj_t2_destroy(opj_t2_t *t2); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_T2_H */ diff --git a/client/deps/openjpeg/tcd.c b/client/deps/openjpeg/tcd.c new file mode 100644 index 000000000..8ca259b71 --- /dev/null +++ b/client/deps/openjpeg/tcd.c @@ -0,0 +1,2930 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006-2007, Parvatha Elangovan + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" +#include "opj_common.h" + +// #define DEBUG_RATE_ALLOC + +/* ----------------------------------------------------------------------- */ + +/* TODO MSD: */ +#ifdef TODO_MSD +void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) +{ + int tileno, compno, resno, bandno, precno;/*, cblkno;*/ + + fprintf(fd, "image {\n"); + fprintf(fd, " tw=%d, th=%d x0=%d x1=%d y0=%d y1=%d\n", + img->tw, img->th, tcd->image->x0, tcd->image->x1, tcd->image->y0, + tcd->image->y1); + + for (tileno = 0; tileno < img->th * img->tw; tileno++) { + opj_tcd_tile_t *tile = &tcd->tcd_image->tiles[tileno]; + fprintf(fd, " tile {\n"); + fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d, numcomps=%d\n", + tile->x0, tile->y0, tile->x1, tile->y1, tile->numcomps); + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + fprintf(fd, " tilec {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, numresolutions=%d\n", + tilec->x0, tilec->y0, tilec->x1, tilec->y1, tilec->numresolutions); + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + fprintf(fd, "\n res {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, pw=%d, ph=%d, numbands=%d\n", + res->x0, res->y0, res->x1, res->y1, res->pw, res->ph, res->numbands); + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + fprintf(fd, " band {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, stepsize=%f, numbps=%d\n", + band->x0, band->y0, band->x1, band->y1, band->stepsize, band->numbps); + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prec = &band->precincts[precno]; + fprintf(fd, " prec {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d, cw=%d, ch=%d\n", + prec->x0, prec->y0, prec->x1, prec->y1, prec->cw, prec->ch); + /* + for (cblkno = 0; cblkno < prec->cw * prec->ch; cblkno++) { + opj_tcd_cblk_t *cblk = &prec->cblks[cblkno]; + fprintf(fd, " cblk {\n"); + fprintf(fd, + " x0=%d, y0=%d, x1=%d, y1=%d\n", + cblk->x0, cblk->y0, cblk->x1, cblk->y1); + fprintf(fd, " }\n"); + } + */ + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, "}\n"); +} +#endif + +/** + * Initializes tile coding/decoding + */ +static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + OPJ_BOOL isEncoder, OPJ_SIZE_T sizeof_block, + opj_event_mgr_t* manager); + +/** +* Allocates memory for a decoding code block. +*/ +static OPJ_BOOL opj_tcd_code_block_dec_allocate(opj_tcd_cblk_dec_t * + p_code_block); + +/** + * Deallocates the decoding data of the given precinct. + */ +static void opj_tcd_code_block_dec_deallocate(opj_tcd_precinct_t * p_precinct); + +/** + * Allocates memory for an encoding code block (but not data). + */ +static OPJ_BOOL opj_tcd_code_block_enc_allocate(opj_tcd_cblk_enc_t * + p_code_block); + +/** + * Allocates data for an encoding code block + */ +static OPJ_BOOL opj_tcd_code_block_enc_allocate_data(opj_tcd_cblk_enc_t * + p_code_block); + +/** + * Deallocates the encoding data of the given precinct. + */ +static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct); + +static +void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, + OPJ_UINT32 final); + +/** +Free the memory allocated for encoding +@param tcd TCD handle +*/ +static void opj_tcd_free_tile(opj_tcd_t *tcd); + + +static OPJ_BOOL opj_tcd_t2_decode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_src_size, + opj_codestream_index_t *p_cstr_index, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_tcd_t1_decode(opj_tcd_t *p_tcd, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd); + +static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd); + + +static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd); + +static OPJ_BOOL opj_tcd_mct_encode(opj_tcd_t *p_tcd); + +static OPJ_BOOL opj_tcd_dwt_encode(opj_tcd_t *p_tcd); + +static OPJ_BOOL opj_tcd_t1_encode(opj_tcd_t *p_tcd); + +static OPJ_BOOL opj_tcd_t2_encode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info, + opj_tcd_marker_info_t* p_marker_info, + opj_event_mgr_t *p_manager); + +static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info, + opj_event_mgr_t *p_manager); + + +static OPJ_BOOL opj_tcd_is_whole_tilecomp_decoding(opj_tcd_t *tcd, + OPJ_UINT32 compno); + +/* ----------------------------------------------------------------------- */ + +/** +Create a new TCD handle +*/ +opj_tcd_t* opj_tcd_create(OPJ_BOOL p_is_decoder) +{ + opj_tcd_t *l_tcd = 00; + + /* create the tcd structure */ + l_tcd = (opj_tcd_t*) opj_calloc(1, sizeof(opj_tcd_t)); + if (!l_tcd) { + return 00; + } + + l_tcd->m_is_decoder = p_is_decoder ? 1 : 0; + + l_tcd->tcd_image = (opj_tcd_image_t*)opj_calloc(1, sizeof(opj_tcd_image_t)); + if (!l_tcd->tcd_image) { + opj_free(l_tcd); + return 00; + } + + return l_tcd; +} + + +/* ----------------------------------------------------------------------- */ + +static +void opj_tcd_rateallocate_fixed(opj_tcd_t *tcd) +{ + OPJ_UINT32 layno; + + for (layno = 0; layno < tcd->tcp->numlayers; layno++) { + opj_tcd_makelayer_fixed(tcd, layno, 1); + } +} + + +/* ----------------------------------------------------------------------- */ + +/** Returns OPJ_TRUE if the layer allocation is unchanged w.r.t to the previous + * invocation with a different threshold */ +static +OPJ_BOOL opj_tcd_makelayer(opj_tcd_t *tcd, + OPJ_UINT32 layno, + OPJ_FLOAT64 thresh, + OPJ_UINT32 final) +{ + OPJ_UINT32 compno, resno, bandno, precno, cblkno; + OPJ_UINT32 passno; + + opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + OPJ_BOOL layer_allocation_is_same = OPJ_TRUE; + + tcd_tile->distolayer[layno] = 0; + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + OPJ_UINT32 n; + + if (layno == 0) { + cblk->numpassesinlayers = 0; + } + + n = cblk->numpassesinlayers; + + if (thresh < 0) { + /* Special value to indicate to use all passes */ + n = cblk->totalpasses; + } else { + for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { + OPJ_UINT32 dr; + OPJ_FLOAT64 dd; + opj_tcd_pass_t *pass = &cblk->passes[passno]; + + if (n == 0) { + dr = pass->rate; + dd = pass->distortiondec; + } else { + dr = pass->rate - cblk->passes[n - 1].rate; + dd = pass->distortiondec - cblk->passes[n - 1].distortiondec; + } + + if (!dr) { + if (dd != 0) { + n = passno + 1; + } + continue; + } + if (thresh - (dd / dr) < + DBL_EPSILON) { /* do not rely on float equality, check with DBL_EPSILON margin */ + n = passno + 1; + } + } + } + + if (layer->numpasses != n - cblk->numpassesinlayers) { + layer_allocation_is_same = OPJ_FALSE; + layer->numpasses = n - cblk->numpassesinlayers; + } + + if (!layer->numpasses) { + layer->disto = 0; + continue; + } + + if (cblk->numpassesinlayers == 0) { + layer->len = cblk->passes[n - 1].rate; + layer->data = cblk->data; + layer->disto = cblk->passes[n - 1].distortiondec; + } else { + layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - + 1].rate; + layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; + layer->disto = cblk->passes[n - 1].distortiondec - + cblk->passes[cblk->numpassesinlayers - 1].distortiondec; + } + + tcd_tile->distolayer[layno] += layer->disto; + + if (final) { + cblk->numpassesinlayers = n; + } + } + } + } + } + } + return layer_allocation_is_same; +} + +/** For m_quality_layer_alloc_strategy == FIXED_LAYER */ +static +void opj_tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, + OPJ_UINT32 final) +{ + OPJ_UINT32 compno, resno, bandno, precno, cblkno; + OPJ_INT32 value; /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */ + OPJ_INT32 matrice[J2K_TCD_MATRIX_MAX_LAYER_COUNT][J2K_TCD_MATRIX_MAX_RESOLUTION_COUNT][3]; + OPJ_UINT32 i, j, k; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + opj_tcp_t *tcd_tcp = tcd->tcp; + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + + for (i = 0; i < tcd_tcp->numlayers; i++) { + for (j = 0; j < tilec->numresolutions; j++) { + for (k = 0; k < 3; k++) { + matrice[i][j][k] = + (OPJ_INT32)((OPJ_FLOAT32)cp->m_specific_param.m_enc.m_matrice[i * + tilec->numresolutions * 3 + j * 3 + k] + * (OPJ_FLOAT32)(tcd->image->comps[compno].prec / 16.0)); + } + } + } + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + OPJ_UINT32 n; + OPJ_INT32 imsb = (OPJ_INT32)(tcd->image->comps[compno].prec - + cblk->numbps); /* number of bit-plan equal to zero */ + + /* Correction of the matrix of coefficient to include the IMSB information */ + if (layno == 0) { + value = matrice[layno][resno][bandno]; + if (imsb >= value) { + value = 0; + } else { + value -= imsb; + } + } else { + value = matrice[layno][resno][bandno] - matrice[layno - 1][resno][bandno]; + if (imsb >= matrice[layno - 1][resno][bandno]) { + value -= (imsb - matrice[layno - 1][resno][bandno]); + if (value < 0) { + value = 0; + } + } + } + + if (layno == 0) { + cblk->numpassesinlayers = 0; + } + + n = cblk->numpassesinlayers; + if (cblk->numpassesinlayers == 0) { + if (value != 0) { + n = 3 * (OPJ_UINT32)value - 2 + cblk->numpassesinlayers; + } else { + n = cblk->numpassesinlayers; + } + } else { + n = 3 * (OPJ_UINT32)value + cblk->numpassesinlayers; + } + + layer->numpasses = n - cblk->numpassesinlayers; + + if (!layer->numpasses) { + continue; + } + + if (cblk->numpassesinlayers == 0) { + layer->len = cblk->passes[n - 1].rate; + layer->data = cblk->data; + } else { + layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - + 1].rate; + layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate; + } + + if (final) { + cblk->numpassesinlayers = n; + } + } + } + } + } + } +} + +/** Rate allocation for the following methods: + * - allocation by rate/distortio (m_quality_layer_alloc_strategy == RATE_DISTORTION_RATIO) + * - allocation by fixed quality (m_quality_layer_alloc_strategy == FIXED_DISTORTION_RATIO) + */ +static +OPJ_BOOL opj_tcd_rateallocate(opj_tcd_t *tcd, + OPJ_BYTE *dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 len, + opj_codestream_info_t *cstr_info, + opj_event_mgr_t *p_manager) +{ + OPJ_UINT32 compno, resno, bandno, precno, cblkno, layno; + OPJ_UINT32 passno; + OPJ_FLOAT64 min, max; + OPJ_FLOAT64 cumdisto[100]; + const OPJ_FLOAT64 K = 1; + OPJ_FLOAT64 maxSE = 0; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_image->tiles; + opj_tcp_t *tcd_tcp = tcd->tcp; + + min = DBL_MAX; + max = 0; + + tcd_tile->numpix = 0; + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + tilec->numpix = 0; + + for (resno = 0; resno < tilec->numresolutions; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + + /* Skip empty bands */ + if (opj_tcd_is_band_empty(band)) { + continue; + } + + for (precno = 0; precno < res->pw * res->ph; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) { + opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno]; + + for (passno = 0; passno < cblk->totalpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + OPJ_INT32 dr; + OPJ_FLOAT64 dd, rdslope; + + if (passno == 0) { + dr = (OPJ_INT32)pass->rate; + dd = pass->distortiondec; + } else { + dr = (OPJ_INT32)(pass->rate - cblk->passes[passno - 1].rate); + dd = pass->distortiondec - cblk->passes[passno - 1].distortiondec; + } + + if (dr == 0) { + continue; + } + + rdslope = dd / dr; + if (rdslope < min) { + min = rdslope; + } + + if (rdslope > max) { + max = rdslope; + } + } /* passno */ + + { + const OPJ_SIZE_T cblk_pix_count = (OPJ_SIZE_T)((cblk->x1 - cblk->x0) * + (cblk->y1 - cblk->y0)); + tcd_tile->numpix += cblk_pix_count; + tilec->numpix += cblk_pix_count; + } + } /* cbklno */ + } /* precno */ + } /* bandno */ + } /* resno */ + + maxSE += (((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) - 1.0) + * ((OPJ_FLOAT64)(1 << tcd->image->comps[compno].prec) - 1.0)) + * ((OPJ_FLOAT64)(tilec->numpix)); + } /* compno */ + + /* index file */ + if (cstr_info) { + opj_tile_info_t *tile_info = &cstr_info->tile[tcd->tcd_tileno]; + tile_info->numpix = (int)tcd_tile->numpix; + tile_info->distotile = (int)tcd_tile->distotile; + tile_info->thresh = (OPJ_FLOAT64 *) opj_malloc(tcd_tcp->numlayers * sizeof( + OPJ_FLOAT64)); + if (!tile_info->thresh) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + } + + for (layno = 0; layno < tcd_tcp->numlayers; layno++) { + OPJ_FLOAT64 lo = min; + OPJ_FLOAT64 hi = max; + OPJ_UINT32 maxlen = tcd_tcp->rates[layno] > 0.0f ? opj_uint_min((( + OPJ_UINT32) ceil(tcd_tcp->rates[layno])), len) : len; + OPJ_FLOAT64 goodthresh = 0; + OPJ_FLOAT64 stable_thresh = 0; + OPJ_UINT32 i; + OPJ_FLOAT64 distotarget; + + distotarget = tcd_tile->distotile - ((K * maxSE) / pow((OPJ_FLOAT32)10, + tcd_tcp->distoratio[layno] / 10)); + + /* Don't try to find an optimal threshold but rather take everything not included yet, if + -r xx,yy,zz,0 (m_quality_layer_alloc_strategy == RATE_DISTORTION_RATIO and rates == NULL) + -q xx,yy,zz,0 (m_quality_layer_alloc_strategy == FIXED_DISTORTION_RATIO and distoratio == NULL) + ==> possible to have some lossy layers and the last layer for sure lossless */ + if (((cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + RATE_DISTORTION_RATIO) && + (tcd_tcp->rates[layno] > 0.0f)) || + ((cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + FIXED_DISTORTION_RATIO) && + (tcd_tcp->distoratio[layno] > 0.0))) { + opj_t2_t*t2 = opj_t2_create(tcd->image, cp); + OPJ_FLOAT64 thresh = 0; + OPJ_BOOL last_layer_allocation_ok = OPJ_FALSE; + + if (t2 == 00) { + return OPJ_FALSE; + } + + for (i = 0; i < 128; ++i) { + OPJ_FLOAT64 distoachieved = 0; + OPJ_BOOL layer_allocation_is_same; + + OPJ_FLOAT64 new_thresh = (lo + hi) / 2; + /* Stop iterating when the threshold has stabilized enough */ + /* 0.5 * 1e-5 is somewhat arbitrary, but has been selected */ + /* so that this doesn't change the results of the regression */ + /* test suite. */ + if (fabs(new_thresh - thresh) <= 0.5 * 1e-5 * thresh) { + break; + } + thresh = new_thresh; +#ifdef DEBUG_RATE_ALLOC + opj_event_msg(p_manager, EVT_INFO, "layno=%u, iter=%u, thresh=%g", + layno, i, new_thresh); +#endif + + layer_allocation_is_same = opj_tcd_makelayer(tcd, layno, thresh, 0) && i != 0; +#ifdef DEBUG_RATE_ALLOC + opj_event_msg(p_manager, EVT_INFO, "--> layer_allocation_is_same = %d", + layer_allocation_is_same); +#endif + if (cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + FIXED_DISTORTION_RATIO) { + if (OPJ_IS_CINEMA(cp->rsiz) || OPJ_IS_IMF(cp->rsiz)) { + if (! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, + p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos, + tcd->cur_pino, + THRESH_CALC, p_manager)) { + + lo = thresh; + continue; + } else { + distoachieved = layno == 0 ? + tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno]; + + if (distoachieved < distotarget) { + hi = thresh; + stable_thresh = thresh; + continue; + } else { + lo = thresh; + } + } + } else { + distoachieved = (layno == 0) ? + tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + + if (distoachieved < distotarget) { + hi = thresh; + stable_thresh = thresh; + continue; + } + lo = thresh; + } + } else { /* Disto/rate based optimization */ + /* Check if the layer allocation done by opj_tcd_makelayer() + * is compatible of the maximum rate allocation. If not, + * retry with a higher threshold. + * If OK, try with a lower threshold. + * Call opj_t2_encode_packets() only if opj_tcd_makelayer() + * has resulted in different truncation points since its last + * call. */ + if ((layer_allocation_is_same && !last_layer_allocation_ok) || + (!layer_allocation_is_same && + ! opj_t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, + p_data_written, maxlen, cstr_info, NULL, tcd->cur_tp_num, tcd->tp_pos, + tcd->cur_pino, + THRESH_CALC, p_manager))) { + +#ifdef DEBUG_RATE_ALLOC + if (!layer_allocation_is_same) { + opj_event_msg(p_manager, EVT_INFO, + "--> check rate alloc failed (> maxlen=%u)\n", maxlen); + } +#endif + last_layer_allocation_ok = OPJ_FALSE; + lo = thresh; + continue; + } + +#ifdef DEBUG_RATE_ALLOC + if (!layer_allocation_is_same) { + opj_event_msg(p_manager, EVT_INFO, + "--> check rate alloc success (len=%u <= maxlen=%u)\n", *p_data_written, + maxlen); + } +#endif + + last_layer_allocation_ok = OPJ_TRUE; + hi = thresh; + stable_thresh = thresh; + } + } + + goodthresh = stable_thresh == 0 ? thresh : stable_thresh; + + opj_t2_destroy(t2); + } else { + /* Special value to indicate to use all passes */ + goodthresh = -1; + } + + if (cstr_info) { /* Threshold for Marcela Index */ + cstr_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh; + } + + opj_tcd_makelayer(tcd, layno, goodthresh, 1); + + cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : + (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_tcd_init(opj_tcd_t *p_tcd, + opj_image_t * p_image, + opj_cp_t * p_cp, + opj_thread_pool_t* p_tp) +{ + p_tcd->image = p_image; + p_tcd->cp = p_cp; + + p_tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_calloc(1, + sizeof(opj_tcd_tile_t)); + if (! p_tcd->tcd_image->tiles) { + return OPJ_FALSE; + } + + p_tcd->tcd_image->tiles->comps = (opj_tcd_tilecomp_t *) opj_calloc( + p_image->numcomps, sizeof(opj_tcd_tilecomp_t)); + if (! p_tcd->tcd_image->tiles->comps) { + return OPJ_FALSE; + } + + p_tcd->tcd_image->tiles->numcomps = p_image->numcomps; + p_tcd->tp_pos = p_cp->m_specific_param.m_enc.m_tp_pos; + p_tcd->thread_pool = p_tp; + + return OPJ_TRUE; +} + +/** +Destroy a previously created TCD handle +*/ +void opj_tcd_destroy(opj_tcd_t *tcd) +{ + if (tcd) { + opj_tcd_free_tile(tcd); + + if (tcd->tcd_image) { + opj_free(tcd->tcd_image); + tcd->tcd_image = 00; + } + + opj_free(tcd->used_component); + + opj_free(tcd); + } +} + +OPJ_BOOL opj_alloc_tile_component_data(opj_tcd_tilecomp_t *l_tilec) +{ + if ((l_tilec->data == 00) || + ((l_tilec->data_size_needed > l_tilec->data_size) && + (l_tilec->ownsData == OPJ_FALSE))) { + l_tilec->data = (OPJ_INT32 *) opj_image_data_alloc(l_tilec->data_size_needed); + if (!l_tilec->data && l_tilec->data_size_needed != 0) { + return OPJ_FALSE; + } + /*fprintf(stderr, "tAllocate data of tilec (int): %d x OPJ_UINT32n",l_data_size);*/ + l_tilec->data_size = l_tilec->data_size_needed; + l_tilec->ownsData = OPJ_TRUE; + } else if (l_tilec->data_size_needed > l_tilec->data_size) { + /* We don't need to keep old data */ + opj_image_data_free(l_tilec->data); + l_tilec->data = (OPJ_INT32 *) opj_image_data_alloc(l_tilec->data_size_needed); + if (! l_tilec->data) { + l_tilec->data_size = 0; + l_tilec->data_size_needed = 0; + l_tilec->ownsData = OPJ_FALSE; + return OPJ_FALSE; + } + /*fprintf(stderr, "tReallocate data of tilec (int): from %d to %d x OPJ_UINT32n", l_tilec->data_size, l_data_size);*/ + l_tilec->data_size = l_tilec->data_size_needed; + l_tilec->ownsData = OPJ_TRUE; + } + return OPJ_TRUE; +} + +/* ----------------------------------------------------------------------- */ + +static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + OPJ_BOOL isEncoder, OPJ_SIZE_T sizeof_block, + opj_event_mgr_t* manager) +{ + OPJ_UINT32 compno, resno, bandno, precno, cblkno; + opj_tcp_t * l_tcp = 00; + opj_cp_t * l_cp = 00; + opj_tcd_tile_t * l_tile = 00; + opj_tccp_t *l_tccp = 00; + opj_tcd_tilecomp_t *l_tilec = 00; + opj_image_comp_t * l_image_comp = 00; + opj_tcd_resolution_t *l_res = 00; + opj_tcd_band_t *l_band = 00; + opj_stepsize_t * l_step_size = 00; + opj_tcd_precinct_t *l_current_precinct = 00; + opj_image_t *l_image = 00; + OPJ_UINT32 p, q; + OPJ_UINT32 l_level_no; + OPJ_UINT32 l_pdx, l_pdy; + OPJ_INT32 l_x0b, l_y0b; + OPJ_UINT32 l_tx0, l_ty0; + /* extent of precincts , top left, bottom right**/ + OPJ_INT32 l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end, l_br_prc_y_end; + /* number of precinct for a resolution */ + OPJ_UINT32 l_nb_precincts; + /* room needed to store l_nb_precinct precinct for a resolution */ + OPJ_UINT32 l_nb_precinct_size; + /* number of code blocks for a precinct*/ + OPJ_UINT32 l_nb_code_blocks; + /* room needed to store l_nb_code_blocks code blocks for a precinct*/ + OPJ_UINT32 l_nb_code_blocks_size; + /* size of data for a tile */ + OPJ_UINT32 l_data_size; + + l_cp = p_tcd->cp; + l_tcp = &(l_cp->tcps[p_tile_no]); + l_tile = p_tcd->tcd_image->tiles; + l_tccp = l_tcp->tccps; + l_tilec = l_tile->comps; + l_image = p_tcd->image; + l_image_comp = p_tcd->image->comps; + + p = p_tile_no % l_cp->tw; /* tile coordinates */ + q = p_tile_no / l_cp->tw; + /*fprintf(stderr, "Tile coordinate = %d,%d\n", p, q);*/ + + /* 4 borders of the tile rescale on the image if necessary */ + l_tx0 = l_cp->tx0 + p * + l_cp->tdx; /* can't be greater than l_image->x1 so won't overflow */ + l_tile->x0 = (OPJ_INT32)opj_uint_max(l_tx0, l_image->x0); + l_tile->x1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_tx0, l_cp->tdx), + l_image->x1); + /* all those OPJ_UINT32 are casted to OPJ_INT32, let's do some sanity check */ + if ((l_tile->x0 < 0) || (l_tile->x1 <= l_tile->x0)) { + opj_event_msg(manager, EVT_ERROR, "Tile X coordinates are not supported\n"); + return OPJ_FALSE; + } + l_ty0 = l_cp->ty0 + q * + l_cp->tdy; /* can't be greater than l_image->y1 so won't overflow */ + l_tile->y0 = (OPJ_INT32)opj_uint_max(l_ty0, l_image->y0); + l_tile->y1 = (OPJ_INT32)opj_uint_min(opj_uint_adds(l_ty0, l_cp->tdy), + l_image->y1); + /* all those OPJ_UINT32 are casted to OPJ_INT32, let's do some sanity check */ + if ((l_tile->y0 < 0) || (l_tile->y1 <= l_tile->y0)) { + opj_event_msg(manager, EVT_ERROR, "Tile Y coordinates are not supported\n"); + return OPJ_FALSE; + } + + + /* testcase 1888.pdf.asan.35.988 */ + if (l_tccp->numresolutions == 0) { + opj_event_msg(manager, EVT_ERROR, "tiles require at least one resolution\n"); + return OPJ_FALSE; + } + /*fprintf(stderr, "Tile border = %d,%d,%d,%d\n", l_tile->x0, l_tile->y0,l_tile->x1,l_tile->y1);*/ + + /*tile->numcomps = image->numcomps; */ + for (compno = 0; compno < l_tile->numcomps; ++compno) { + /*fprintf(stderr, "compno = %d/%d\n", compno, l_tile->numcomps);*/ + l_image_comp->resno_decoded = 0; + /* border of each l_tile component (global) */ + l_tilec->x0 = opj_int_ceildiv(l_tile->x0, (OPJ_INT32)l_image_comp->dx); + l_tilec->y0 = opj_int_ceildiv(l_tile->y0, (OPJ_INT32)l_image_comp->dy); + l_tilec->x1 = opj_int_ceildiv(l_tile->x1, (OPJ_INT32)l_image_comp->dx); + l_tilec->y1 = opj_int_ceildiv(l_tile->y1, (OPJ_INT32)l_image_comp->dy); + l_tilec->compno = compno; + /*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/ + + l_tilec->numresolutions = l_tccp->numresolutions; + if (l_tccp->numresolutions < l_cp->m_specific_param.m_dec.m_reduce) { + l_tilec->minimum_num_resolutions = 1; + } else { + l_tilec->minimum_num_resolutions = l_tccp->numresolutions - + l_cp->m_specific_param.m_dec.m_reduce; + } + + if (isEncoder) { + OPJ_SIZE_T l_tile_data_size; + + /* compute l_data_size with overflow check */ + OPJ_SIZE_T w = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0); + OPJ_SIZE_T h = (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0); + + /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */ + if (h > 0 && w > SIZE_MAX / h) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_tile_data_size = w * h; + + if (SIZE_MAX / sizeof(OPJ_UINT32) < l_tile_data_size) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_tile_data_size = l_tile_data_size * sizeof(OPJ_UINT32); + + l_tilec->data_size_needed = l_tile_data_size; + } + + l_data_size = l_tilec->numresolutions * (OPJ_UINT32)sizeof( + opj_tcd_resolution_t); + + opj_image_data_free(l_tilec->data_win); + l_tilec->data_win = NULL; + l_tilec->win_x0 = 0; + l_tilec->win_y0 = 0; + l_tilec->win_x1 = 0; + l_tilec->win_y1 = 0; + + if (l_tilec->resolutions == 00) { + l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size); + if (! l_tilec->resolutions) { + return OPJ_FALSE; + } + /*fprintf(stderr, "\tAllocate resolutions of tilec (opj_tcd_resolution_t): %d\n",l_data_size);*/ + l_tilec->resolutions_size = l_data_size; + memset(l_tilec->resolutions, 0, l_data_size); + } else if (l_data_size > l_tilec->resolutions_size) { + opj_tcd_resolution_t* new_resolutions = (opj_tcd_resolution_t *) opj_realloc( + l_tilec->resolutions, l_data_size); + if (! new_resolutions) { + opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile resolutions\n"); + opj_free(l_tilec->resolutions); + l_tilec->resolutions = NULL; + l_tilec->resolutions_size = 0; + return OPJ_FALSE; + } + l_tilec->resolutions = new_resolutions; + /*fprintf(stderr, "\tReallocate data of tilec (int): from %d to %d x OPJ_UINT32\n", l_tilec->resolutions_size, l_data_size);*/ + memset(((OPJ_BYTE*) l_tilec->resolutions) + l_tilec->resolutions_size, 0, + l_data_size - l_tilec->resolutions_size); + l_tilec->resolutions_size = l_data_size; + } + + l_level_no = l_tilec->numresolutions; + l_res = l_tilec->resolutions; + l_step_size = l_tccp->stepsizes; + /*fprintf(stderr, "\tlevel_no=%d\n",l_level_no);*/ + + for (resno = 0; resno < l_tilec->numresolutions; ++resno) { + /*fprintf(stderr, "\t\tresno = %d/%d\n", resno, l_tilec->numresolutions);*/ + OPJ_INT32 tlcbgxstart, tlcbgystart /*, brcbgxend, brcbgyend*/; + OPJ_UINT32 cbgwidthexpn, cbgheightexpn; + OPJ_UINT32 cblkwidthexpn, cblkheightexpn; + + --l_level_no; + + /* border for each resolution level (global) */ + l_res->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no); + l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no); + l_res->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no); + l_res->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no); + + /*fprintf(stderr, "\t\t\tres_x0= %d, res_y0 =%d, res_x1=%d, res_y1=%d\n", l_res->x0, l_res->y0, l_res->x1, l_res->y1);*/ + /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */ + l_pdx = l_tccp->prcw[resno]; + l_pdy = l_tccp->prch[resno]; + /*fprintf(stderr, "\t\t\tpdx=%d, pdy=%d\n", l_pdx, l_pdy);*/ + /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ + l_tl_prc_x_start = opj_int_floordivpow2(l_res->x0, (OPJ_INT32)l_pdx) << l_pdx; + l_tl_prc_y_start = opj_int_floordivpow2(l_res->y0, (OPJ_INT32)l_pdy) << l_pdy; + { + OPJ_UINT32 tmp = ((OPJ_UINT32)opj_int_ceildivpow2(l_res->x1, + (OPJ_INT32)l_pdx)) << l_pdx; + if (tmp > (OPJ_UINT32)INT_MAX) { + opj_event_msg(manager, EVT_ERROR, "Integer overflow\n"); + return OPJ_FALSE; + } + l_br_prc_x_end = (OPJ_INT32)tmp; + } + { + OPJ_UINT32 tmp = ((OPJ_UINT32)opj_int_ceildivpow2(l_res->y1, + (OPJ_INT32)l_pdy)) << l_pdy; + if (tmp > (OPJ_UINT32)INT_MAX) { + opj_event_msg(manager, EVT_ERROR, "Integer overflow\n"); + return OPJ_FALSE; + } + l_br_prc_y_end = (OPJ_INT32)tmp; + } + /*fprintf(stderr, "\t\t\tprc_x_start=%d, prc_y_start=%d, br_prc_x_end=%d, br_prc_y_end=%d \n", l_tl_prc_x_start, l_tl_prc_y_start, l_br_prc_x_end ,l_br_prc_y_end );*/ + + l_res->pw = (l_res->x0 == l_res->x1) ? 0U : (OPJ_UINT32)(( + l_br_prc_x_end - l_tl_prc_x_start) >> l_pdx); + l_res->ph = (l_res->y0 == l_res->y1) ? 0U : (OPJ_UINT32)(( + l_br_prc_y_end - l_tl_prc_y_start) >> l_pdy); + /*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/ + + if ((l_res->pw != 0U) && ((((OPJ_UINT32) - 1) / l_res->pw) < l_res->ph)) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_nb_precincts = l_res->pw * l_res->ph; + + if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof(opj_tcd_precinct_t)) < + l_nb_precincts) { + opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_nb_precinct_size = l_nb_precincts * (OPJ_UINT32)sizeof(opj_tcd_precinct_t); + + if (resno == 0) { + tlcbgxstart = l_tl_prc_x_start; + tlcbgystart = l_tl_prc_y_start; + /*brcbgxend = l_br_prc_x_end;*/ + /* brcbgyend = l_br_prc_y_end;*/ + cbgwidthexpn = l_pdx; + cbgheightexpn = l_pdy; + l_res->numbands = 1; + } else { + tlcbgxstart = opj_int_ceildivpow2(l_tl_prc_x_start, 1); + tlcbgystart = opj_int_ceildivpow2(l_tl_prc_y_start, 1); + /*brcbgxend = opj_int_ceildivpow2(l_br_prc_x_end, 1);*/ + /*brcbgyend = opj_int_ceildivpow2(l_br_prc_y_end, 1);*/ + cbgwidthexpn = l_pdx - 1; + cbgheightexpn = l_pdy - 1; + l_res->numbands = 3; + } + + cblkwidthexpn = opj_uint_min(l_tccp->cblkw, cbgwidthexpn); + cblkheightexpn = opj_uint_min(l_tccp->cblkh, cbgheightexpn); + l_band = l_res->bands; + + for (bandno = 0; bandno < l_res->numbands; ++bandno, ++l_band, ++l_step_size) { + /*fprintf(stderr, "\t\t\tband_no=%d/%d\n", bandno, l_res->numbands );*/ + + if (resno == 0) { + l_band->bandno = 0 ; + l_band->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no); + l_band->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no); + l_band->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no); + l_band->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no); + } else { + l_band->bandno = bandno + 1; + /* x0b = 1 if bandno = 1 or 3 */ + l_x0b = l_band->bandno & 1; + /* y0b = 1 if bandno = 2 or 3 */ + l_y0b = (OPJ_INT32)((l_band->bandno) >> 1); + /* l_band border (global) */ + l_band->x0 = opj_int64_ceildivpow2(l_tilec->x0 - ((OPJ_INT64)l_x0b << + l_level_no), (OPJ_INT32)(l_level_no + 1)); + l_band->y0 = opj_int64_ceildivpow2(l_tilec->y0 - ((OPJ_INT64)l_y0b << + l_level_no), (OPJ_INT32)(l_level_no + 1)); + l_band->x1 = opj_int64_ceildivpow2(l_tilec->x1 - ((OPJ_INT64)l_x0b << + l_level_no), (OPJ_INT32)(l_level_no + 1)); + l_band->y1 = opj_int64_ceildivpow2(l_tilec->y1 - ((OPJ_INT64)l_y0b << + l_level_no), (OPJ_INT32)(l_level_no + 1)); + } + + if (isEncoder) { + /* Skip empty bands */ + if (opj_tcd_is_band_empty(l_band)) { + /* Do not zero l_band->precints to avoid leaks */ + /* but make sure we don't use it later, since */ + /* it will point to precincts of previous bands... */ + continue; + } + } + + { + /* Table E-1 - Sub-band gains */ + /* BUG_WEIRD_TWO_INVK (look for this identifier in dwt.c): */ + /* the test (!isEncoder && l_tccp->qmfbid == 0) is strongly */ + /* linked to the use of two_invK instead of invK */ + const OPJ_INT32 log2_gain = (!isEncoder && + l_tccp->qmfbid == 0) ? 0 : (l_band->bandno == 0) ? 0 : + (l_band->bandno == 3) ? 2 : 1; + + /* Nominal dynamic range. Equation E-4 */ + const OPJ_INT32 Rb = (OPJ_INT32)l_image_comp->prec + log2_gain; + + /* Delta_b value of Equation E-3 in "E.1 Inverse quantization + * procedure" of the standard */ + l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0, + (OPJ_INT32)(Rb - l_step_size->expn)))); + } + + /* Mb value of Equation E-2 in "E.1 Inverse quantization + * procedure" of the standard */ + l_band->numbps = l_step_size->expn + (OPJ_INT32)l_tccp->numgbits - + 1; + + if (!l_band->precincts && (l_nb_precincts > 0U)) { + l_band->precincts = (opj_tcd_precinct_t *) opj_malloc(/*3 * */ + l_nb_precinct_size); + if (! l_band->precincts) { + opj_event_msg(manager, EVT_ERROR, + "Not enough memory to handle band precints\n"); + return OPJ_FALSE; + } + /*fprintf(stderr, "\t\t\t\tAllocate precincts of a band (opj_tcd_precinct_t): %d\n",l_nb_precinct_size); */ + memset(l_band->precincts, 0, l_nb_precinct_size); + l_band->precincts_data_size = l_nb_precinct_size; + } else if (l_band->precincts_data_size < l_nb_precinct_size) { + + opj_tcd_precinct_t * new_precincts = (opj_tcd_precinct_t *) opj_realloc( + l_band->precincts,/*3 * */ l_nb_precinct_size); + if (! new_precincts) { + opj_event_msg(manager, EVT_ERROR, + "Not enough memory to handle band precints\n"); + opj_free(l_band->precincts); + l_band->precincts = NULL; + l_band->precincts_data_size = 0; + return OPJ_FALSE; + } + l_band->precincts = new_precincts; + /*fprintf(stderr, "\t\t\t\tReallocate precincts of a band (opj_tcd_precinct_t): from %d to %d\n",l_band->precincts_data_size, l_nb_precinct_size);*/ + memset(((OPJ_BYTE *) l_band->precincts) + l_band->precincts_data_size, 0, + l_nb_precinct_size - l_band->precincts_data_size); + l_band->precincts_data_size = l_nb_precinct_size; + } + + l_current_precinct = l_band->precincts; + for (precno = 0; precno < l_nb_precincts; ++precno) { + OPJ_INT32 tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend; + OPJ_INT32 cbgxstart = tlcbgxstart + (OPJ_INT32)(precno % l_res->pw) * + (1 << cbgwidthexpn); + OPJ_INT32 cbgystart = tlcbgystart + (OPJ_INT32)(precno / l_res->pw) * + (1 << cbgheightexpn); + OPJ_INT32 cbgxend = cbgxstart + (1 << cbgwidthexpn); + OPJ_INT32 cbgyend = cbgystart + (1 << cbgheightexpn); + /*fprintf(stderr, "\t precno=%d; bandno=%d, resno=%d; compno=%d\n", precno, bandno , resno, compno);*/ + /*fprintf(stderr, "\t tlcbgxstart(=%d) + (precno(=%d) percent res->pw(=%d)) * (1 << cbgwidthexpn(=%d)) \n",tlcbgxstart,precno,l_res->pw,cbgwidthexpn);*/ + + /* precinct size (global) */ + /*fprintf(stderr, "\t cbgxstart=%d, l_band->x0 = %d \n",cbgxstart, l_band->x0);*/ + + l_current_precinct->x0 = opj_int_max(cbgxstart, l_band->x0); + l_current_precinct->y0 = opj_int_max(cbgystart, l_band->y0); + l_current_precinct->x1 = opj_int_min(cbgxend, l_band->x1); + l_current_precinct->y1 = opj_int_min(cbgyend, l_band->y1); + /*fprintf(stderr, "\t prc_x0=%d; prc_y0=%d, prc_x1=%d; prc_y1=%d\n",l_current_precinct->x0, l_current_precinct->y0 ,l_current_precinct->x1, l_current_precinct->y1);*/ + + tlcblkxstart = opj_int_floordivpow2(l_current_precinct->x0, + (OPJ_INT32)cblkwidthexpn) << cblkwidthexpn; + /*fprintf(stderr, "\t tlcblkxstart =%d\n",tlcblkxstart );*/ + tlcblkystart = opj_int_floordivpow2(l_current_precinct->y0, + (OPJ_INT32)cblkheightexpn) << cblkheightexpn; + /*fprintf(stderr, "\t tlcblkystart =%d\n",tlcblkystart );*/ + brcblkxend = opj_int_ceildivpow2(l_current_precinct->x1, + (OPJ_INT32)cblkwidthexpn) << cblkwidthexpn; + /*fprintf(stderr, "\t brcblkxend =%d\n",brcblkxend );*/ + brcblkyend = opj_int_ceildivpow2(l_current_precinct->y1, + (OPJ_INT32)cblkheightexpn) << cblkheightexpn; + /*fprintf(stderr, "\t brcblkyend =%d\n",brcblkyend );*/ + l_current_precinct->cw = (OPJ_UINT32)((brcblkxend - tlcblkxstart) >> + cblkwidthexpn); + l_current_precinct->ch = (OPJ_UINT32)((brcblkyend - tlcblkystart) >> + cblkheightexpn); + + l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch; + /*fprintf(stderr, "\t\t\t\t precinct_cw = %d x recinct_ch = %d\n",l_current_precinct->cw, l_current_precinct->ch); */ + if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof_block) < + l_nb_code_blocks) { + opj_event_msg(manager, EVT_ERROR, + "Size of code block data exceeds system limits\n"); + return OPJ_FALSE; + } + l_nb_code_blocks_size = l_nb_code_blocks * (OPJ_UINT32)sizeof_block; + + if (!l_current_precinct->cblks.blocks && (l_nb_code_blocks > 0U)) { + l_current_precinct->cblks.blocks = opj_malloc(l_nb_code_blocks_size); + if (! l_current_precinct->cblks.blocks) { + return OPJ_FALSE; + } + /*fprintf(stderr, "\t\t\t\tAllocate cblks of a precinct (opj_tcd_cblk_dec_t): %d\n",l_nb_code_blocks_size);*/ + + memset(l_current_precinct->cblks.blocks, 0, l_nb_code_blocks_size); + + l_current_precinct->block_size = l_nb_code_blocks_size; + } else if (l_nb_code_blocks_size > l_current_precinct->block_size) { + void *new_blocks = opj_realloc(l_current_precinct->cblks.blocks, + l_nb_code_blocks_size); + if (! new_blocks) { + opj_free(l_current_precinct->cblks.blocks); + l_current_precinct->cblks.blocks = NULL; + l_current_precinct->block_size = 0; + opj_event_msg(manager, EVT_ERROR, + "Not enough memory for current precinct codeblock element\n"); + return OPJ_FALSE; + } + l_current_precinct->cblks.blocks = new_blocks; + /*fprintf(stderr, "\t\t\t\tReallocate cblks of a precinct (opj_tcd_cblk_dec_t): from %d to %d\n",l_current_precinct->block_size, l_nb_code_blocks_size); */ + + memset(((OPJ_BYTE *) l_current_precinct->cblks.blocks) + + l_current_precinct->block_size + , 0 + , l_nb_code_blocks_size - l_current_precinct->block_size); + + l_current_precinct->block_size = l_nb_code_blocks_size; + } + + if (! l_current_precinct->incltree) { + l_current_precinct->incltree = opj_tgt_create(l_current_precinct->cw, + l_current_precinct->ch, manager); + } else { + l_current_precinct->incltree = opj_tgt_init(l_current_precinct->incltree, + l_current_precinct->cw, l_current_precinct->ch, manager); + } + + if (! l_current_precinct->imsbtree) { + l_current_precinct->imsbtree = opj_tgt_create(l_current_precinct->cw, + l_current_precinct->ch, manager); + } else { + l_current_precinct->imsbtree = opj_tgt_init(l_current_precinct->imsbtree, + l_current_precinct->cw, l_current_precinct->ch, manager); + } + + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + OPJ_INT32 cblkxstart = tlcblkxstart + (OPJ_INT32)(cblkno % + l_current_precinct->cw) * (1 << cblkwidthexpn); + OPJ_INT32 cblkystart = tlcblkystart + (OPJ_INT32)(cblkno / + l_current_precinct->cw) * (1 << cblkheightexpn); + OPJ_INT32 cblkxend = cblkxstart + (1 << cblkwidthexpn); + OPJ_INT32 cblkyend = cblkystart + (1 << cblkheightexpn); + + if (isEncoder) { + opj_tcd_cblk_enc_t* l_code_block = l_current_precinct->cblks.enc + cblkno; + + if (! opj_tcd_code_block_enc_allocate(l_code_block)) { + return OPJ_FALSE; + } + /* code-block size (global) */ + l_code_block->x0 = opj_int_max(cblkxstart, l_current_precinct->x0); + l_code_block->y0 = opj_int_max(cblkystart, l_current_precinct->y0); + l_code_block->x1 = opj_int_min(cblkxend, l_current_precinct->x1); + l_code_block->y1 = opj_int_min(cblkyend, l_current_precinct->y1); + + if (! opj_tcd_code_block_enc_allocate_data(l_code_block)) { + return OPJ_FALSE; + } + } else { + opj_tcd_cblk_dec_t* l_code_block = l_current_precinct->cblks.dec + cblkno; + + if (! opj_tcd_code_block_dec_allocate(l_code_block)) { + return OPJ_FALSE; + } + /* code-block size (global) */ + l_code_block->x0 = opj_int_max(cblkxstart, l_current_precinct->x0); + l_code_block->y0 = opj_int_max(cblkystart, l_current_precinct->y0); + l_code_block->x1 = opj_int_min(cblkxend, l_current_precinct->x1); + l_code_block->y1 = opj_int_min(cblkyend, l_current_precinct->y1); + } + } + ++l_current_precinct; + } /* precno */ + } /* bandno */ + ++l_res; + } /* resno */ + ++l_tccp; + ++l_tilec; + ++l_image_comp; + } /* compno */ + return OPJ_TRUE; +} + +OPJ_BOOL opj_tcd_init_encode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + opj_event_mgr_t* p_manager) +{ + return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_TRUE, + sizeof(opj_tcd_cblk_enc_t), p_manager); +} + +OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + opj_event_mgr_t* p_manager) +{ + return opj_tcd_init_tile(p_tcd, p_tile_no, OPJ_FALSE, + sizeof(opj_tcd_cblk_dec_t), p_manager); +} + +/** + * Allocates memory for an encoding code block (but not data memory). + */ +static OPJ_BOOL opj_tcd_code_block_enc_allocate(opj_tcd_cblk_enc_t * + p_code_block) +{ + if (! p_code_block->layers) { + /* no memset since data */ + p_code_block->layers = (opj_tcd_layer_t*) opj_calloc(100, + sizeof(opj_tcd_layer_t)); + if (! p_code_block->layers) { + return OPJ_FALSE; + } + } + if (! p_code_block->passes) { + p_code_block->passes = (opj_tcd_pass_t*) opj_calloc(100, + sizeof(opj_tcd_pass_t)); + if (! p_code_block->passes) { + return OPJ_FALSE; + } + } + return OPJ_TRUE; +} + +/** + * Allocates data memory for an encoding code block. + */ +static OPJ_BOOL opj_tcd_code_block_enc_allocate_data(opj_tcd_cblk_enc_t * + p_code_block) +{ + OPJ_UINT32 l_data_size; + + /* +1 is needed for https://github.com/uclouvain/openjpeg/issues/835 */ + /* and actually +2 required for https://github.com/uclouvain/openjpeg/issues/982 */ + /* and +7 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 3) */ + /* and +26 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 7) */ + /* and +28 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 44) */ + /* and +33 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 4) */ + /* and +63 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 4 -IMF 2K) */ + /* and +74 for https://github.com/uclouvain/openjpeg/issues/1283 (-M 4 -n 8 -s 7,7 -I) */ + /* TODO: is there a theoretical upper-bound for the compressed code */ + /* block size ? */ + l_data_size = 74 + (OPJ_UINT32)((p_code_block->x1 - p_code_block->x0) * + (p_code_block->y1 - p_code_block->y0) * (OPJ_INT32)sizeof(OPJ_UINT32)); + + if (l_data_size > p_code_block->data_size) { + if (p_code_block->data) { + /* We refer to data - 1 since below we incremented it */ + opj_free(p_code_block->data - 1); + } + p_code_block->data = (OPJ_BYTE*) opj_malloc(l_data_size + 1); + if (! p_code_block->data) { + p_code_block->data_size = 0U; + return OPJ_FALSE; + } + p_code_block->data_size = l_data_size; + + /* We reserve the initial byte as a fake byte to a non-FF value */ + /* and increment the data pointer, so that opj_mqc_init_enc() */ + /* can do bp = data - 1, and opj_mqc_byteout() can safely dereference */ + /* it. */ + p_code_block->data[0] = 0; + p_code_block->data += 1; /*why +1 ?*/ + } + return OPJ_TRUE; +} + + +void opj_tcd_reinit_segment(opj_tcd_seg_t* seg) +{ + memset(seg, 0, sizeof(opj_tcd_seg_t)); +} + +/** + * Allocates memory for a decoding code block. + */ +static OPJ_BOOL opj_tcd_code_block_dec_allocate(opj_tcd_cblk_dec_t * + p_code_block) +{ + if (! p_code_block->segs) { + + p_code_block->segs = (opj_tcd_seg_t *) opj_calloc(OPJ_J2K_DEFAULT_NB_SEGS, + sizeof(opj_tcd_seg_t)); + if (! p_code_block->segs) { + return OPJ_FALSE; + } + /*fprintf(stderr, "Allocate %d elements of code_block->data\n", OPJ_J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t));*/ + + p_code_block->m_current_max_segs = OPJ_J2K_DEFAULT_NB_SEGS; + /*fprintf(stderr, "m_current_max_segs of code_block->data = %d\n", p_code_block->m_current_max_segs);*/ + } else { + /* sanitize */ + opj_tcd_seg_t * l_segs = p_code_block->segs; + OPJ_UINT32 l_current_max_segs = p_code_block->m_current_max_segs; + opj_tcd_seg_data_chunk_t* l_chunks = p_code_block->chunks; + OPJ_UINT32 l_numchunksalloc = p_code_block->numchunksalloc; + OPJ_UINT32 i; + + opj_aligned_free(p_code_block->decoded_data); + p_code_block->decoded_data = 00; + + memset(p_code_block, 0, sizeof(opj_tcd_cblk_dec_t)); + p_code_block->segs = l_segs; + p_code_block->m_current_max_segs = l_current_max_segs; + for (i = 0; i < l_current_max_segs; ++i) { + opj_tcd_reinit_segment(&l_segs[i]); + } + p_code_block->chunks = l_chunks; + p_code_block->numchunksalloc = l_numchunksalloc; + } + + return OPJ_TRUE; +} + +OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd, + OPJ_BOOL take_into_account_partial_decoding) +{ + OPJ_UINT32 i; + OPJ_UINT32 l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tile_comp = 00; + opj_tcd_resolution_t * l_res = 00; + OPJ_UINT32 l_size_comp, l_remaining; + OPJ_UINT32 l_temp; + + l_tile_comp = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + + for (i = 0; i < p_tcd->image->numcomps; ++i) { + OPJ_UINT32 w, h; + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + + if (l_remaining) { + ++l_size_comp; + } + + if (l_size_comp == 3) { + l_size_comp = 4; + } + + l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1; + if (take_into_account_partial_decoding && !p_tcd->whole_tile_decoding) { + w = l_res->win_x1 - l_res->win_x0; + h = l_res->win_y1 - l_res->win_y0; + } else { + w = (OPJ_UINT32)(l_res->x1 - l_res->x0); + h = (OPJ_UINT32)(l_res->y1 - l_res->y0); + } + if (h > 0 && UINT_MAX / w < h) { + return UINT_MAX; + } + l_temp = w * h; + if (l_size_comp && UINT_MAX / l_size_comp < l_temp) { + return UINT_MAX; + } + l_temp *= l_size_comp; + + if (l_temp > UINT_MAX - l_data_size) { + return UINT_MAX; + } + l_data_size += l_temp; + ++l_img_comp; + ++l_tile_comp; + } + + return l_data_size; +} + +OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd, + OPJ_UINT32 p_tile_no, + OPJ_BYTE *p_dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_length, + opj_codestream_info_t *p_cstr_info, + opj_tcd_marker_info_t* p_marker_info, + opj_event_mgr_t *p_manager) +{ + + if (p_tcd->cur_tp_num == 0) { + + p_tcd->tcd_tileno = p_tile_no; + p_tcd->tcp = &p_tcd->cp->tcps[p_tile_no]; + + /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */ + if (p_cstr_info) { + OPJ_UINT32 l_num_packs = 0; + OPJ_UINT32 i; + opj_tcd_tilecomp_t *l_tilec_idx = + &p_tcd->tcd_image->tiles->comps[0]; /* based on component 0 */ + opj_tccp_t *l_tccp = p_tcd->tcp->tccps; /* based on component 0 */ + + for (i = 0; i < l_tilec_idx->numresolutions; i++) { + opj_tcd_resolution_t *l_res_idx = &l_tilec_idx->resolutions[i]; + + p_cstr_info->tile[p_tile_no].pw[i] = (int)l_res_idx->pw; + p_cstr_info->tile[p_tile_no].ph[i] = (int)l_res_idx->ph; + + l_num_packs += l_res_idx->pw * l_res_idx->ph; + p_cstr_info->tile[p_tile_no].pdx[i] = (int)l_tccp->prcw[i]; + p_cstr_info->tile[p_tile_no].pdy[i] = (int)l_tccp->prch[i]; + } + p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t*) opj_calloc(( + OPJ_SIZE_T)p_cstr_info->numcomps * (OPJ_SIZE_T)p_cstr_info->numlayers * + l_num_packs, + sizeof(opj_packet_info_t)); + if (!p_cstr_info->tile[p_tile_no].packet) { + /* FIXME event manager error callback */ + return OPJ_FALSE; + } + } + /* << INDEX */ + + /* FIXME _ProfStart(PGROUP_DC_SHIFT); */ + /*---------------TILE-------------------*/ + if (! opj_tcd_dc_level_shift_encode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_DC_SHIFT); */ + + /* FIXME _ProfStart(PGROUP_MCT); */ + if (! opj_tcd_mct_encode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_MCT); */ + + /* FIXME _ProfStart(PGROUP_DWT); */ + if (! opj_tcd_dwt_encode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_DWT); */ + + /* FIXME _ProfStart(PGROUP_T1); */ + if (! opj_tcd_t1_encode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_T1); */ + + /* FIXME _ProfStart(PGROUP_RATE); */ + if (! opj_tcd_rate_allocate_encode(p_tcd, p_dest, p_max_length, + p_cstr_info, p_manager)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_RATE); */ + + } + /*--------------TIER2------------------*/ + + /* INDEX */ + if (p_cstr_info) { + p_cstr_info->index_write = 1; + } + /* FIXME _ProfStart(PGROUP_T2); */ + + if (! opj_tcd_t2_encode(p_tcd, p_dest, p_data_written, p_max_length, + p_cstr_info, p_marker_info, p_manager)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_T2); */ + + /*---------------CLEAN-------------------*/ + + return OPJ_TRUE; +} + +OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd, + OPJ_UINT32 win_x0, + OPJ_UINT32 win_y0, + OPJ_UINT32 win_x1, + OPJ_UINT32 win_y1, + OPJ_UINT32 numcomps_to_decode, + const OPJ_UINT32 *comps_indices, + OPJ_BYTE *p_src, + OPJ_UINT32 p_max_length, + OPJ_UINT32 p_tile_no, + opj_codestream_index_t *p_cstr_index, + opj_event_mgr_t *p_manager + ) +{ + OPJ_UINT32 l_data_read; + OPJ_UINT32 compno; + + p_tcd->tcd_tileno = p_tile_no; + p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]); + p_tcd->win_x0 = win_x0; + p_tcd->win_y0 = win_y0; + p_tcd->win_x1 = win_x1; + p_tcd->win_y1 = win_y1; + p_tcd->whole_tile_decoding = OPJ_TRUE; + + opj_free(p_tcd->used_component); + p_tcd->used_component = NULL; + + if (numcomps_to_decode) { + OPJ_BOOL* used_component = (OPJ_BOOL*) opj_calloc(sizeof(OPJ_BOOL), + p_tcd->image->numcomps); + if (used_component == NULL) { + return OPJ_FALSE; + } + for (compno = 0; compno < numcomps_to_decode; compno++) { + used_component[ comps_indices[compno] ] = OPJ_TRUE; + } + + p_tcd->used_component = used_component; + } + + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + if (!opj_tcd_is_whole_tilecomp_decoding(p_tcd, compno)) { + p_tcd->whole_tile_decoding = OPJ_FALSE; + break; + } + } + + if (p_tcd->whole_tile_decoding) { + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_tcd_resolution_t *l_res = & + (tilec->resolutions[tilec->minimum_num_resolutions - 1]); + OPJ_SIZE_T l_data_size; + + /* compute l_data_size with overflow check */ + OPJ_SIZE_T res_w = (OPJ_SIZE_T)(l_res->x1 - l_res->x0); + OPJ_SIZE_T res_h = (OPJ_SIZE_T)(l_res->y1 - l_res->y0); + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */ + if (res_h > 0 && res_w > SIZE_MAX / res_h) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size = res_w * res_h; + + if (SIZE_MAX / sizeof(OPJ_UINT32) < l_data_size) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size *= sizeof(OPJ_UINT32); + + tilec->data_size_needed = l_data_size; + + if (!opj_alloc_tile_component_data(tilec)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + } + } else { + /* Compute restricted tile-component and tile-resolution coordinates */ + /* of the window of interest, but defer the memory allocation until */ + /* we know the resno_decoded */ + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + OPJ_UINT32 resno; + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]); + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + tilec->win_x0 = opj_uint_max( + (OPJ_UINT32)tilec->x0, + opj_uint_ceildiv(p_tcd->win_x0, image_comp->dx)); + tilec->win_y0 = opj_uint_max( + (OPJ_UINT32)tilec->y0, + opj_uint_ceildiv(p_tcd->win_y0, image_comp->dy)); + tilec->win_x1 = opj_uint_min( + (OPJ_UINT32)tilec->x1, + opj_uint_ceildiv(p_tcd->win_x1, image_comp->dx)); + tilec->win_y1 = opj_uint_min( + (OPJ_UINT32)tilec->y1, + opj_uint_ceildiv(p_tcd->win_y1, image_comp->dy)); + if (tilec->win_x1 < tilec->win_x0 || + tilec->win_y1 < tilec->win_y0) { + /* We should not normally go there. The circumstance is when */ + /* the tile coordinates do not intersect the area of interest */ + /* Upper level logic should not even try to decode that tile */ + opj_event_msg(p_manager, EVT_ERROR, + "Invalid tilec->win_xxx values\n"); + return OPJ_FALSE; + } + + for (resno = 0; resno < tilec->numresolutions; ++resno) { + opj_tcd_resolution_t *res = tilec->resolutions + resno; + res->win_x0 = opj_uint_ceildivpow2(tilec->win_x0, + tilec->numresolutions - 1 - resno); + res->win_y0 = opj_uint_ceildivpow2(tilec->win_y0, + tilec->numresolutions - 1 - resno); + res->win_x1 = opj_uint_ceildivpow2(tilec->win_x1, + tilec->numresolutions - 1 - resno); + res->win_y1 = opj_uint_ceildivpow2(tilec->win_y1, + tilec->numresolutions - 1 - resno); + } + } + } + +#ifdef TODO_MSD /* FIXME */ + /* INDEX >> */ + if (p_cstr_info) { + OPJ_UINT32 resno, compno, numprec = 0; + for (compno = 0; compno < (OPJ_UINT32) p_cstr_info->numcomps; compno++) { + opj_tcp_t *tcp = &p_tcd->cp->tcps[0]; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_tcd_tilecomp_t *tilec_idx = &p_tcd->tcd_image->tiles->comps[compno]; + for (resno = 0; resno < tilec_idx->numresolutions; resno++) { + opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[resno]; + p_cstr_info->tile[p_tile_no].pw[resno] = res_idx->pw; + p_cstr_info->tile[p_tile_no].ph[resno] = res_idx->ph; + numprec += res_idx->pw * res_idx->ph; + p_cstr_info->tile[p_tile_no].pdx[resno] = tccp->prcw[resno]; + p_cstr_info->tile[p_tile_no].pdy[resno] = tccp->prch[resno]; + } + } + p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t *) opj_malloc( + p_cstr_info->numlayers * numprec * sizeof(opj_packet_info_t)); + p_cstr_info->packno = 0; + } + /* << INDEX */ +#endif + + /*--------------TIER2------------------*/ + /* FIXME _ProfStart(PGROUP_T2); */ + l_data_read = 0; + if (! opj_tcd_t2_decode(p_tcd, p_src, &l_data_read, p_max_length, p_cstr_index, + p_manager)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_T2); */ + + /*------------------TIER1-----------------*/ + + /* FIXME _ProfStart(PGROUP_T1); */ + if (! opj_tcd_t1_decode(p_tcd, p_manager)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_T1); */ + + + /* For subtile decoding, now we know the resno_decoded, we can allocate */ + /* the tile data buffer */ + if (!p_tcd->whole_tile_decoding) { + for (compno = 0; compno < p_tcd->image->numcomps; compno++) { + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]); + opj_tcd_resolution_t *res = tilec->resolutions + image_comp->resno_decoded; + OPJ_SIZE_T w = res->win_x1 - res->win_x0; + OPJ_SIZE_T h = res->win_y1 - res->win_y0; + OPJ_SIZE_T l_data_size; + + opj_image_data_free(tilec->data_win); + tilec->data_win = NULL; + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + if (w > 0 && h > 0) { + if (w > SIZE_MAX / h) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size = w * h; + if (l_data_size > SIZE_MAX / sizeof(OPJ_INT32)) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + l_data_size *= sizeof(OPJ_INT32); + + tilec->data_win = (OPJ_INT32*) opj_image_data_alloc(l_data_size); + if (tilec->data_win == NULL) { + opj_event_msg(p_manager, EVT_ERROR, + "Size of tile data exceeds system limits\n"); + return OPJ_FALSE; + } + } + } + } + + /*----------------DWT---------------------*/ + + /* FIXME _ProfStart(PGROUP_DWT); */ + if + (! opj_tcd_dwt_decode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_DWT); */ + + /*----------------MCT-------------------*/ + /* FIXME _ProfStart(PGROUP_MCT); */ + if + (! opj_tcd_mct_decode(p_tcd, p_manager)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_MCT); */ + + /* FIXME _ProfStart(PGROUP_DC_SHIFT); */ + if + (! opj_tcd_dc_level_shift_decode(p_tcd)) { + return OPJ_FALSE; + } + /* FIXME _ProfStop(PGROUP_DC_SHIFT); */ + + + /*---------------TILE-------------------*/ + return OPJ_TRUE; +} + +OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest, + OPJ_UINT32 p_dest_length + ) +{ + OPJ_UINT32 i, j, k, l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tilec = 00; + opj_tcd_resolution_t * l_res; + OPJ_UINT32 l_size_comp, l_remaining; + OPJ_UINT32 l_stride, l_width, l_height; + + l_data_size = opj_tcd_get_decoded_tile_size(p_tcd, OPJ_TRUE); + if (l_data_size == UINT_MAX || l_data_size > p_dest_length) { + return OPJ_FALSE; + } + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + + for (i = 0; i < p_tcd->image->numcomps; ++i) { + const OPJ_INT32* l_src_data; + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + l_res = l_tilec->resolutions + l_img_comp->resno_decoded; + if (p_tcd->whole_tile_decoding) { + l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); + l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); + l_stride = (OPJ_UINT32)(l_tilec->resolutions[l_tilec->minimum_num_resolutions - + 1].x1 - + l_tilec->resolutions[l_tilec->minimum_num_resolutions - 1].x0) - l_width; + l_src_data = l_tilec->data; + } else { + l_width = l_res->win_x1 - l_res->win_x0; + l_height = l_res->win_y1 - l_res->win_y0; + l_stride = 0; + l_src_data = l_tilec->data_win; + } + + if (l_remaining) { + ++l_size_comp; + } + + if (l_size_comp == 3) { + l_size_comp = 4; + } + + switch (l_size_comp) { + case 1: { + OPJ_CHAR * l_dest_ptr = (OPJ_CHAR *) p_dest; + const OPJ_INT32 * l_src_ptr = l_src_data; + + if (l_img_comp->sgnd) { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = (OPJ_CHAR)(*(l_src_ptr++)); + } + l_src_ptr += l_stride; + } + } else { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + *(l_dest_ptr++) = (OPJ_CHAR)((*(l_src_ptr++)) & 0xff); + } + l_src_ptr += l_stride; + } + } + + p_dest = (OPJ_BYTE *)l_dest_ptr; + } + break; + case 2: { + const OPJ_INT32 * l_src_ptr = l_src_data; + OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_dest; + + if (l_img_comp->sgnd) { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + OPJ_INT16 val = (OPJ_INT16)(*(l_src_ptr++)); + memcpy(l_dest_ptr, &val, sizeof(val)); + l_dest_ptr ++; + } + l_src_ptr += l_stride; + } + } else { + for (j = 0; j < l_height; ++j) { + for (k = 0; k < l_width; ++k) { + OPJ_INT16 val = (OPJ_INT16)((*(l_src_ptr++)) & 0xffff); + memcpy(l_dest_ptr, &val, sizeof(val)); + l_dest_ptr ++; + } + l_src_ptr += l_stride; + } + } + + p_dest = (OPJ_BYTE*) l_dest_ptr; + } + break; + case 4: { + OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_dest; + const OPJ_INT32 * l_src_ptr = l_src_data; + + for (j = 0; j < l_height; ++j) { + memcpy(l_dest_ptr, l_src_ptr, l_width * sizeof(OPJ_INT32)); + l_dest_ptr += l_width; + l_src_ptr += l_width + l_stride; + } + + p_dest = (OPJ_BYTE*) l_dest_ptr; + } + break; + } + + ++l_img_comp; + ++l_tilec; + } + + return OPJ_TRUE; +} + + + + +static void opj_tcd_free_tile(opj_tcd_t *p_tcd) +{ + OPJ_UINT32 compno, resno, bandno, precno; + opj_tcd_tile_t *l_tile = 00; + opj_tcd_tilecomp_t *l_tile_comp = 00; + opj_tcd_resolution_t *l_res = 00; + opj_tcd_band_t *l_band = 00; + opj_tcd_precinct_t *l_precinct = 00; + OPJ_UINT32 l_nb_resolutions, l_nb_precincts; + void (* l_tcd_code_block_deallocate)(opj_tcd_precinct_t *) = 00; + + if (! p_tcd) { + return; + } + + if (! p_tcd->tcd_image) { + return; + } + + if (p_tcd->m_is_decoder) { + l_tcd_code_block_deallocate = opj_tcd_code_block_dec_deallocate; + } else { + l_tcd_code_block_deallocate = opj_tcd_code_block_enc_deallocate; + } + + l_tile = p_tcd->tcd_image->tiles; + if (! l_tile) { + return; + } + + l_tile_comp = l_tile->comps; + + for (compno = 0; compno < l_tile->numcomps; ++compno) { + l_res = l_tile_comp->resolutions; + if (l_res) { + + l_nb_resolutions = l_tile_comp->resolutions_size / (OPJ_UINT32)sizeof( + opj_tcd_resolution_t); + for (resno = 0; resno < l_nb_resolutions; ++resno) { + l_band = l_res->bands; + for (bandno = 0; bandno < 3; ++bandno) { + l_precinct = l_band->precincts; + if (l_precinct) { + + l_nb_precincts = l_band->precincts_data_size / (OPJ_UINT32)sizeof( + opj_tcd_precinct_t); + for (precno = 0; precno < l_nb_precincts; ++precno) { + opj_tgt_destroy(l_precinct->incltree); + l_precinct->incltree = 00; + opj_tgt_destroy(l_precinct->imsbtree); + l_precinct->imsbtree = 00; + (*l_tcd_code_block_deallocate)(l_precinct); + ++l_precinct; + } + + opj_free(l_band->precincts); + l_band->precincts = 00; + } + ++l_band; + } /* for (resno */ + ++l_res; + } + + opj_free(l_tile_comp->resolutions); + l_tile_comp->resolutions = 00; + } + + if (l_tile_comp->ownsData && l_tile_comp->data) { + opj_image_data_free(l_tile_comp->data); + l_tile_comp->data = 00; + l_tile_comp->ownsData = 0; + l_tile_comp->data_size = 0; + l_tile_comp->data_size_needed = 0; + } + + opj_image_data_free(l_tile_comp->data_win); + + ++l_tile_comp; + } + + opj_free(l_tile->comps); + l_tile->comps = 00; + opj_free(p_tcd->tcd_image->tiles); + p_tcd->tcd_image->tiles = 00; +} + + +static OPJ_BOOL opj_tcd_t2_decode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_src_data, + OPJ_UINT32 * p_data_read, + OPJ_UINT32 p_max_src_size, + opj_codestream_index_t *p_cstr_index, + opj_event_mgr_t *p_manager + ) +{ + opj_t2_t * l_t2; + + l_t2 = opj_t2_create(p_tcd->image, p_tcd->cp); + if (l_t2 == 00) { + return OPJ_FALSE; + } + + if (! opj_t2_decode_packets( + p_tcd, + l_t2, + p_tcd->tcd_tileno, + p_tcd->tcd_image->tiles, + p_src_data, + p_data_read, + p_max_src_size, + p_cstr_index, + p_manager)) { + opj_t2_destroy(l_t2); + return OPJ_FALSE; + } + + opj_t2_destroy(l_t2); + + /*---------------CLEAN-------------------*/ + return OPJ_TRUE; +} + +static OPJ_BOOL opj_tcd_t1_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager) +{ + OPJ_UINT32 compno; + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t* l_tile_comp = l_tile->comps; + opj_tccp_t * l_tccp = p_tcd->tcp->tccps; + volatile OPJ_BOOL ret = OPJ_TRUE; + OPJ_BOOL check_pterm = OPJ_FALSE; + opj_mutex_t* p_manager_mutex = NULL; + + p_manager_mutex = opj_mutex_create(); + + /* Only enable PTERM check if we decode all layers */ + if (p_tcd->tcp->num_layers_to_decode == p_tcd->tcp->numlayers && + (l_tccp->cblksty & J2K_CCP_CBLKSTY_PTERM) != 0) { + check_pterm = OPJ_TRUE; + } + + for (compno = 0; compno < l_tile->numcomps; + ++compno, ++l_tile_comp, ++l_tccp) { + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + opj_t1_decode_cblks(p_tcd, &ret, l_tile_comp, l_tccp, + p_manager, p_manager_mutex, check_pterm); + if (!ret) { + break; + } + } + + opj_thread_pool_wait_completion(p_tcd->thread_pool, 0); + if (p_manager_mutex) { + opj_mutex_destroy(p_manager_mutex); + } + return ret; +} + + +static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd) +{ + OPJ_UINT32 compno; + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps; + opj_tccp_t * l_tccp = p_tcd->tcp->tccps; + opj_image_comp_t * l_img_comp = p_tcd->image->comps; + + for (compno = 0; compno < l_tile->numcomps; + compno++, ++l_tile_comp, ++l_img_comp, ++l_tccp) { + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + if (l_tccp->qmfbid == 1) { + if (! opj_dwt_decode(p_tcd, l_tile_comp, + l_img_comp->resno_decoded + 1)) { + return OPJ_FALSE; + } + } else { + if (! opj_dwt_decode_real(p_tcd, l_tile_comp, + l_img_comp->resno_decoded + 1)) { + return OPJ_FALSE; + } + } + + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager) +{ + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcp_t * l_tcp = p_tcd->tcp; + opj_tcd_tilecomp_t * l_tile_comp = l_tile->comps; + OPJ_SIZE_T l_samples; + OPJ_UINT32 i; + + if (l_tcp->mct == 0 || p_tcd->used_component != NULL) { + return OPJ_TRUE; + } + + if (p_tcd->whole_tile_decoding) { + opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions + + l_tile_comp->minimum_num_resolutions - 1; + + /* A bit inefficient: we process more data than needed if */ + /* resno_decoded < l_tile_comp->minimum_num_resolutions-1, */ + /* but we would need to take into account a stride then */ + l_samples = (OPJ_SIZE_T)(res_comp0->x1 - res_comp0->x0) * + (OPJ_SIZE_T)(res_comp0->y1 - res_comp0->y0); + if (l_tile->numcomps >= 3) { + if (l_tile_comp->minimum_num_resolutions != + l_tile->comps[1].minimum_num_resolutions || + l_tile_comp->minimum_num_resolutions != + l_tile->comps[2].minimum_num_resolutions) { + opj_event_msg(p_manager, EVT_ERROR, + "Tiles don't all have the same dimension. Skip the MCT step.\n"); + return OPJ_FALSE; + } + } + if (l_tile->numcomps >= 3) { + opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions + + l_tile_comp->minimum_num_resolutions - 1; + opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions + + l_tile_comp->minimum_num_resolutions - 1; + /* testcase 1336.pdf.asan.47.376 */ + if (p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[1].resno_decoded || + p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[2].resno_decoded || + (OPJ_SIZE_T)(res_comp1->x1 - res_comp1->x0) * + (OPJ_SIZE_T)(res_comp1->y1 - res_comp1->y0) != l_samples || + (OPJ_SIZE_T)(res_comp2->x1 - res_comp2->x0) * + (OPJ_SIZE_T)(res_comp2->y1 - res_comp2->y0) != l_samples) { + opj_event_msg(p_manager, EVT_ERROR, + "Tiles don't all have the same dimension. Skip the MCT step.\n"); + return OPJ_FALSE; + } + } + } else { + opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions + + p_tcd->image->comps[0].resno_decoded; + + l_samples = (OPJ_SIZE_T)(res_comp0->win_x1 - res_comp0->win_x0) * + (OPJ_SIZE_T)(res_comp0->win_y1 - res_comp0->win_y0); + if (l_tile->numcomps >= 3) { + opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions + + p_tcd->image->comps[1].resno_decoded; + opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions + + p_tcd->image->comps[2].resno_decoded; + /* testcase 1336.pdf.asan.47.376 */ + if (p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[1].resno_decoded || + p_tcd->image->comps[0].resno_decoded != + p_tcd->image->comps[2].resno_decoded || + (OPJ_SIZE_T)(res_comp1->win_x1 - res_comp1->win_x0) * + (OPJ_SIZE_T)(res_comp1->win_y1 - res_comp1->win_y0) != l_samples || + (OPJ_SIZE_T)(res_comp2->win_x1 - res_comp2->win_x0) * + (OPJ_SIZE_T)(res_comp2->win_y1 - res_comp2->win_y0) != l_samples) { + opj_event_msg(p_manager, EVT_ERROR, + "Tiles don't all have the same dimension. Skip the MCT step.\n"); + return OPJ_FALSE; + } + } + } + + if (l_tile->numcomps >= 3) { + if (l_tcp->mct == 2) { + OPJ_BYTE ** l_data; + + if (! l_tcp->m_mct_decoding_matrix) { + return OPJ_TRUE; + } + + l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps * sizeof(OPJ_BYTE*)); + if (! l_data) { + return OPJ_FALSE; + } + + for (i = 0; i < l_tile->numcomps; ++i) { + if (p_tcd->whole_tile_decoding) { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data; + } else { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data_win; + } + ++l_tile_comp; + } + + if (! opj_mct_decode_custom(/* MCT data */ + (OPJ_BYTE*) l_tcp->m_mct_decoding_matrix, + /* size of components */ + l_samples, + /* components */ + l_data, + /* nb of components (i.e. size of pData) */ + l_tile->numcomps, + /* tells if the data is signed */ + p_tcd->image->comps->sgnd)) { + opj_free(l_data); + return OPJ_FALSE; + } + + opj_free(l_data); + } else { + if (l_tcp->tccps->qmfbid == 1) { + if (p_tcd->whole_tile_decoding) { + opj_mct_decode(l_tile->comps[0].data, + l_tile->comps[1].data, + l_tile->comps[2].data, + l_samples); + } else { + opj_mct_decode(l_tile->comps[0].data_win, + l_tile->comps[1].data_win, + l_tile->comps[2].data_win, + l_samples); + } + } else { + if (p_tcd->whole_tile_decoding) { + opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data, + (OPJ_FLOAT32*)l_tile->comps[1].data, + (OPJ_FLOAT32*)l_tile->comps[2].data, + l_samples); + } else { + opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data_win, + (OPJ_FLOAT32*)l_tile->comps[1].data_win, + (OPJ_FLOAT32*)l_tile->comps[2].data_win, + l_samples); + } + } + } + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Number of components (%d) is inconsistent with a MCT. Skip the MCT step.\n", + l_tile->numcomps); + } + + return OPJ_TRUE; +} + + +static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd) +{ + OPJ_UINT32 compno; + opj_tcd_tilecomp_t * l_tile_comp = 00; + opj_tccp_t * l_tccp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_resolution_t* l_res = 00; + opj_tcd_tile_t * l_tile; + OPJ_UINT32 l_width, l_height, i, j; + OPJ_INT32 * l_current_ptr; + OPJ_INT32 l_min, l_max; + OPJ_UINT32 l_stride; + + l_tile = p_tcd->tcd_image->tiles; + l_tile_comp = l_tile->comps; + l_tccp = p_tcd->tcp->tccps; + l_img_comp = p_tcd->image->comps; + + for (compno = 0; compno < l_tile->numcomps; + compno++, ++l_img_comp, ++l_tccp, ++l_tile_comp) { + + if (p_tcd->used_component != NULL && !p_tcd->used_component[compno]) { + continue; + } + + l_res = l_tile_comp->resolutions + l_img_comp->resno_decoded; + + if (!p_tcd->whole_tile_decoding) { + l_width = l_res->win_x1 - l_res->win_x0; + l_height = l_res->win_y1 - l_res->win_y0; + l_stride = 0; + l_current_ptr = l_tile_comp->data_win; + } else { + l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0); + l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0); + l_stride = (OPJ_UINT32)( + l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x1 - + l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x0) + - l_width; + l_current_ptr = l_tile_comp->data; + + assert(l_height == 0 || + l_width + l_stride <= l_tile_comp->data_size / l_height); /*MUPDF*/ + } + + if (l_img_comp->sgnd) { + l_min = -(1 << (l_img_comp->prec - 1)); + l_max = (1 << (l_img_comp->prec - 1)) - 1; + } else { + l_min = 0; + l_max = (OPJ_INT32)((1U << l_img_comp->prec) - 1); + } + + if (l_width == 0 || l_height == 0) { + continue; + } + + if (l_tccp->qmfbid == 1) { + for (j = 0; j < l_height; ++j) { + for (i = 0; i < l_width; ++i) { + /* TODO: do addition on int64 ? */ + *l_current_ptr = opj_int_clamp(*l_current_ptr + l_tccp->m_dc_level_shift, l_min, + l_max); + ++l_current_ptr; + } + l_current_ptr += l_stride; + } + } else { + for (j = 0; j < l_height; ++j) { + for (i = 0; i < l_width; ++i) { + OPJ_FLOAT32 l_value = *((OPJ_FLOAT32 *) l_current_ptr); + if (l_value > (OPJ_FLOAT32)INT_MAX) { + *l_current_ptr = l_max; + } else if (l_value < INT_MIN) { + *l_current_ptr = l_min; + } else { + /* Do addition on int64 to avoid overflows */ + OPJ_INT64 l_value_int = (OPJ_INT64)opj_lrintf(l_value); + *l_current_ptr = (OPJ_INT32)opj_int64_clamp( + l_value_int + l_tccp->m_dc_level_shift, l_min, l_max); + } + ++l_current_ptr; + } + l_current_ptr += l_stride; + } + } + } + + return OPJ_TRUE; +} + + + +/** + * Deallocates the encoding data of the given precinct. + */ +static void opj_tcd_code_block_dec_deallocate(opj_tcd_precinct_t * p_precinct) +{ + OPJ_UINT32 cblkno, l_nb_code_blocks; + + opj_tcd_cblk_dec_t * l_code_block = p_precinct->cblks.dec; + if (l_code_block) { + /*fprintf(stderr,"deallocate codeblock:{\n");*/ + /*fprintf(stderr,"\t x0=%d, y0=%d, x1=%d, y1=%d\n",l_code_block->x0, l_code_block->y0, l_code_block->x1, l_code_block->y1);*/ + /*fprintf(stderr,"\t numbps=%d, numlenbits=%d, len=%d, numnewpasses=%d, real_num_segs=%d, m_current_max_segs=%d\n ", + l_code_block->numbps, l_code_block->numlenbits, l_code_block->len, l_code_block->numnewpasses, l_code_block->real_num_segs, l_code_block->m_current_max_segs );*/ + + + l_nb_code_blocks = p_precinct->block_size / (OPJ_UINT32)sizeof( + opj_tcd_cblk_dec_t); + /*fprintf(stderr,"nb_code_blocks =%d\t}\n", l_nb_code_blocks);*/ + + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + + if (l_code_block->segs) { + opj_free(l_code_block->segs); + l_code_block->segs = 00; + } + + if (l_code_block->chunks) { + opj_free(l_code_block->chunks); + l_code_block->chunks = 00; + } + + opj_aligned_free(l_code_block->decoded_data); + l_code_block->decoded_data = NULL; + + ++l_code_block; + } + + opj_free(p_precinct->cblks.dec); + p_precinct->cblks.dec = 00; + } +} + +/** + * Deallocates the encoding data of the given precinct. + */ +static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct) +{ + OPJ_UINT32 cblkno, l_nb_code_blocks; + + opj_tcd_cblk_enc_t * l_code_block = p_precinct->cblks.enc; + if (l_code_block) { + l_nb_code_blocks = p_precinct->block_size / (OPJ_UINT32)sizeof( + opj_tcd_cblk_enc_t); + + for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) { + if (l_code_block->data) { + /* We refer to data - 1 since below we incremented it */ + /* in opj_tcd_code_block_enc_allocate_data() */ + opj_free(l_code_block->data - 1); + l_code_block->data = 00; + } + + if (l_code_block->layers) { + opj_free(l_code_block->layers); + l_code_block->layers = 00; + } + + if (l_code_block->passes) { + opj_free(l_code_block->passes); + l_code_block->passes = 00; + } + ++l_code_block; + } + + opj_free(p_precinct->cblks.enc); + + p_precinct->cblks.enc = 00; + } +} + +OPJ_SIZE_T opj_tcd_get_encoder_input_buffer_size(opj_tcd_t *p_tcd) +{ + OPJ_UINT32 i; + OPJ_SIZE_T l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tilec = 00; + OPJ_UINT32 l_size_comp, l_remaining; + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + for (i = 0; i < p_tcd->image->numcomps; ++i) { + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + + if (l_remaining) { + ++l_size_comp; + } + + if (l_size_comp == 3) { + l_size_comp = 4; + } + + l_data_size += l_size_comp * ((OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) * + (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0)); + ++l_img_comp; + ++l_tilec; + } + + return l_data_size; +} + +static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd) +{ + OPJ_UINT32 compno; + opj_tcd_tilecomp_t * l_tile_comp = 00; + opj_tccp_t * l_tccp = 00; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tile_t * l_tile; + OPJ_SIZE_T l_nb_elem, i; + OPJ_INT32 * l_current_ptr; + + l_tile = p_tcd->tcd_image->tiles; + l_tile_comp = l_tile->comps; + l_tccp = p_tcd->tcp->tccps; + l_img_comp = p_tcd->image->comps; + + for (compno = 0; compno < l_tile->numcomps; compno++) { + l_current_ptr = l_tile_comp->data; + l_nb_elem = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) * + (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0); + + if (l_tccp->qmfbid == 1) { + for (i = 0; i < l_nb_elem; ++i) { + *l_current_ptr -= l_tccp->m_dc_level_shift ; + ++l_current_ptr; + } + } else { + for (i = 0; i < l_nb_elem; ++i) { + *((OPJ_FLOAT32 *) l_current_ptr) = (OPJ_FLOAT32)(*l_current_ptr - + l_tccp->m_dc_level_shift); + ++l_current_ptr; + } + } + + ++l_img_comp; + ++l_tccp; + ++l_tile_comp; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_tcd_mct_encode(opj_tcd_t *p_tcd) +{ + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps; + OPJ_SIZE_T samples = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) * + (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0); + OPJ_UINT32 i; + OPJ_BYTE ** l_data = 00; + opj_tcp_t * l_tcp = p_tcd->tcp; + + if (!p_tcd->tcp->mct) { + return OPJ_TRUE; + } + + if (p_tcd->tcp->mct == 2) { + if (! p_tcd->tcp->m_mct_coding_matrix) { + return OPJ_TRUE; + } + + l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps * sizeof(OPJ_BYTE*)); + if (! l_data) { + return OPJ_FALSE; + } + + for (i = 0; i < l_tile->numcomps; ++i) { + l_data[i] = (OPJ_BYTE*) l_tile_comp->data; + ++l_tile_comp; + } + + if (! opj_mct_encode_custom(/* MCT data */ + (OPJ_BYTE*) p_tcd->tcp->m_mct_coding_matrix, + /* size of components */ + samples, + /* components */ + l_data, + /* nb of components (i.e. size of pData) */ + l_tile->numcomps, + /* tells if the data is signed */ + p_tcd->image->comps->sgnd)) { + opj_free(l_data); + return OPJ_FALSE; + } + + opj_free(l_data); + } else if (l_tcp->tccps->qmfbid == 0) { + opj_mct_encode_real( + (OPJ_FLOAT32*)l_tile->comps[0].data, + (OPJ_FLOAT32*)l_tile->comps[1].data, + (OPJ_FLOAT32*)l_tile->comps[2].data, + samples); + } else { + opj_mct_encode(l_tile->comps[0].data, l_tile->comps[1].data, + l_tile->comps[2].data, samples); + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_tcd_dwt_encode(opj_tcd_t *p_tcd) +{ + opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles; + opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps; + opj_tccp_t * l_tccp = p_tcd->tcp->tccps; + OPJ_UINT32 compno; + + for (compno = 0; compno < l_tile->numcomps; ++compno) { + if (l_tccp->qmfbid == 1) { + if (! opj_dwt_encode(p_tcd, l_tile_comp)) { + return OPJ_FALSE; + } + } else if (l_tccp->qmfbid == 0) { + if (! opj_dwt_encode_real(p_tcd, l_tile_comp)) { + return OPJ_FALSE; + } + } + + ++l_tile_comp; + ++l_tccp; + } + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_tcd_t1_encode(opj_tcd_t *p_tcd) +{ + const OPJ_FLOAT64 * l_mct_norms; + OPJ_UINT32 l_mct_numcomps = 0U; + opj_tcp_t * l_tcp = p_tcd->tcp; + + if (l_tcp->mct == 1) { + l_mct_numcomps = 3U; + /* irreversible encoding */ + if (l_tcp->tccps->qmfbid == 0) { + l_mct_norms = opj_mct_get_mct_norms_real(); + } else { + l_mct_norms = opj_mct_get_mct_norms(); + } + } else { + l_mct_numcomps = p_tcd->image->numcomps; + l_mct_norms = (const OPJ_FLOAT64 *)(l_tcp->mct_norms); + } + + return opj_t1_encode_cblks(p_tcd, + p_tcd->tcd_image->tiles, l_tcp, l_mct_norms, + l_mct_numcomps); + + return OPJ_TRUE; +} + +static OPJ_BOOL opj_tcd_t2_encode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info, + opj_tcd_marker_info_t* p_marker_info, + opj_event_mgr_t *p_manager) +{ + opj_t2_t * l_t2; + + l_t2 = opj_t2_create(p_tcd->image, p_tcd->cp); + if (l_t2 == 00) { + return OPJ_FALSE; + } + + if (! opj_t2_encode_packets( + l_t2, + p_tcd->tcd_tileno, + p_tcd->tcd_image->tiles, + p_tcd->tcp->numlayers, + p_dest_data, + p_data_written, + p_max_dest_size, + p_cstr_info, + p_marker_info, + p_tcd->tp_num, + p_tcd->tp_pos, + p_tcd->cur_pino, + FINAL_PASS, + p_manager)) { + opj_t2_destroy(l_t2); + return OPJ_FALSE; + } + + opj_t2_destroy(l_t2); + + /*---------------CLEAN-------------------*/ + return OPJ_TRUE; +} + + +static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest_data, + OPJ_UINT32 p_max_dest_size, + opj_codestream_info_t *p_cstr_info, + opj_event_mgr_t *p_manager) +{ + opj_cp_t * l_cp = p_tcd->cp; + OPJ_UINT32 l_nb_written = 0; + + if (p_cstr_info) { + p_cstr_info->index_write = 0; + } + + if (l_cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + RATE_DISTORTION_RATIO || + l_cp->m_specific_param.m_enc.m_quality_layer_alloc_strategy == + FIXED_DISTORTION_RATIO) { + if (! opj_tcd_rateallocate(p_tcd, p_dest_data, &l_nb_written, p_max_dest_size, + p_cstr_info, p_manager)) { + return OPJ_FALSE; + } + } else { + /* Fixed layer allocation */ + opj_tcd_rateallocate_fixed(p_tcd); + } + + return OPJ_TRUE; +} + + +OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd, + OPJ_BYTE * p_src, + OPJ_SIZE_T p_src_length) +{ + OPJ_UINT32 i; + OPJ_SIZE_T j; + OPJ_SIZE_T l_data_size = 0; + opj_image_comp_t * l_img_comp = 00; + opj_tcd_tilecomp_t * l_tilec = 00; + OPJ_UINT32 l_size_comp, l_remaining; + OPJ_SIZE_T l_nb_elem; + + l_data_size = opj_tcd_get_encoder_input_buffer_size(p_tcd); + if (l_data_size != p_src_length) { + return OPJ_FALSE; + } + + l_tilec = p_tcd->tcd_image->tiles->comps; + l_img_comp = p_tcd->image->comps; + for (i = 0; i < p_tcd->image->numcomps; ++i) { + l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ + l_remaining = l_img_comp->prec & 7; /* (%8) */ + l_nb_elem = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) * + (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0); + + if (l_remaining) { + ++l_size_comp; + } + + if (l_size_comp == 3) { + l_size_comp = 4; + } + + switch (l_size_comp) { + case 1: { + OPJ_CHAR * l_src_ptr = (OPJ_CHAR *) p_src; + OPJ_INT32 * l_dest_ptr = l_tilec->data; + + if (l_img_comp->sgnd) { + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (OPJ_INT32)(*(l_src_ptr++)); + } + } else { + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (*(l_src_ptr++)) & 0xff; + } + } + + p_src = (OPJ_BYTE*) l_src_ptr; + } + break; + case 2: { + OPJ_INT32 * l_dest_ptr = l_tilec->data; + OPJ_INT16 * l_src_ptr = (OPJ_INT16 *) p_src; + + if (l_img_comp->sgnd) { + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (OPJ_INT32)(*(l_src_ptr++)); + } + } else { + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (*(l_src_ptr++)) & 0xffff; + } + } + + p_src = (OPJ_BYTE*) l_src_ptr; + } + break; + case 4: { + OPJ_INT32 * l_src_ptr = (OPJ_INT32 *) p_src; + OPJ_INT32 * l_dest_ptr = l_tilec->data; + + for (j = 0; j < l_nb_elem; ++j) { + *(l_dest_ptr++) = (OPJ_INT32)(*(l_src_ptr++)); + } + + p_src = (OPJ_BYTE*) l_src_ptr; + } + break; + } + + ++l_img_comp; + ++l_tilec; + } + + return OPJ_TRUE; +} + +OPJ_BOOL opj_tcd_is_band_empty(opj_tcd_band_t* band) +{ + return (band->x1 - band->x0 == 0) || (band->y1 - band->y0 == 0); +} + +OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd, + OPJ_UINT32 compno, + OPJ_UINT32 resno, + OPJ_UINT32 bandno, + OPJ_UINT32 band_x0, + OPJ_UINT32 band_y0, + OPJ_UINT32 band_x1, + OPJ_UINT32 band_y1) +{ + /* Note: those values for filter_margin are in part the result of */ + /* experimentation. The value 2 for QMFBID=1 (5x3 filter) can be linked */ + /* to the maximum left/right extension given in tables F.2 and F.3 of the */ + /* standard. The value 3 for QMFBID=0 (9x7 filter) is more suspicious, */ + /* since F.2 and F.3 would lead to 4 instead, so the current 3 might be */ + /* needed to be bumped to 4, in case inconsistencies are found while */ + /* decoding parts of irreversible coded images. */ + /* See opj_dwt_decode_partial_53 and opj_dwt_decode_partial_97 as well */ + OPJ_UINT32 filter_margin = (tcd->tcp->tccps[compno].qmfbid == 1) ? 2 : 3; + opj_tcd_tilecomp_t *tilec = &(tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(tcd->image->comps[compno]); + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 tcx0 = opj_uint_max( + (OPJ_UINT32)tilec->x0, + opj_uint_ceildiv(tcd->win_x0, image_comp->dx)); + OPJ_UINT32 tcy0 = opj_uint_max( + (OPJ_UINT32)tilec->y0, + opj_uint_ceildiv(tcd->win_y0, image_comp->dy)); + OPJ_UINT32 tcx1 = opj_uint_min( + (OPJ_UINT32)tilec->x1, + opj_uint_ceildiv(tcd->win_x1, image_comp->dx)); + OPJ_UINT32 tcy1 = opj_uint_min( + (OPJ_UINT32)tilec->y1, + opj_uint_ceildiv(tcd->win_y1, image_comp->dy)); + /* Compute number of decomposition for this band. See table F-1 */ + OPJ_UINT32 nb = (resno == 0) ? + tilec->numresolutions - 1 : + tilec->numresolutions - resno; + /* Map above tile-based coordinates to sub-band-based coordinates per */ + /* equation B-15 of the standard */ + OPJ_UINT32 x0b = bandno & 1; + OPJ_UINT32 y0b = bandno >> 1; + OPJ_UINT32 tbx0 = (nb == 0) ? tcx0 : + (tcx0 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx0 - (1U << (nb - 1)) * x0b, nb); + OPJ_UINT32 tby0 = (nb == 0) ? tcy0 : + (tcy0 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy0 - (1U << (nb - 1)) * y0b, nb); + OPJ_UINT32 tbx1 = (nb == 0) ? tcx1 : + (tcx1 <= (1U << (nb - 1)) * x0b) ? 0 : + opj_uint_ceildivpow2(tcx1 - (1U << (nb - 1)) * x0b, nb); + OPJ_UINT32 tby1 = (nb == 0) ? tcy1 : + (tcy1 <= (1U << (nb - 1)) * y0b) ? 0 : + opj_uint_ceildivpow2(tcy1 - (1U << (nb - 1)) * y0b, nb); + OPJ_BOOL intersects; + + if (tbx0 < filter_margin) { + tbx0 = 0; + } else { + tbx0 -= filter_margin; + } + if (tby0 < filter_margin) { + tby0 = 0; + } else { + tby0 -= filter_margin; + } + tbx1 = opj_uint_adds(tbx1, filter_margin); + tby1 = opj_uint_adds(tby1, filter_margin); + + intersects = band_x0 < tbx1 && band_y0 < tby1 && band_x1 > tbx0 && + band_y1 > tby0; + +#ifdef DEBUG_VERBOSE + printf("compno=%u resno=%u nb=%u bandno=%u x0b=%u y0b=%u band=%u,%u,%u,%u tb=%u,%u,%u,%u -> %u\n", + compno, resno, nb, bandno, x0b, y0b, + band_x0, band_y0, band_x1, band_y1, + tbx0, tby0, tbx1, tby1, intersects); +#endif + return intersects; +} + +/** Returns whether a tile component is fully decoded, taking into account + * p_tcd->win_* members. + * + * @param p_tcd TCD handle. + * @param compno Component number + * @return OPJ_TRUE whether the tile component is fully decoded + */ +static OPJ_BOOL opj_tcd_is_whole_tilecomp_decoding(opj_tcd_t *p_tcd, + OPJ_UINT32 compno) +{ + opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]); + opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]); + /* Compute the intersection of the area of interest, expressed in tile coordinates */ + /* with the tile coordinates */ + OPJ_UINT32 tcx0 = opj_uint_max( + (OPJ_UINT32)tilec->x0, + opj_uint_ceildiv(p_tcd->win_x0, image_comp->dx)); + OPJ_UINT32 tcy0 = opj_uint_max( + (OPJ_UINT32)tilec->y0, + opj_uint_ceildiv(p_tcd->win_y0, image_comp->dy)); + OPJ_UINT32 tcx1 = opj_uint_min( + (OPJ_UINT32)tilec->x1, + opj_uint_ceildiv(p_tcd->win_x1, image_comp->dx)); + OPJ_UINT32 tcy1 = opj_uint_min( + (OPJ_UINT32)tilec->y1, + opj_uint_ceildiv(p_tcd->win_y1, image_comp->dy)); + + OPJ_UINT32 shift = tilec->numresolutions - tilec->minimum_num_resolutions; + /* Tolerate small margin within the reduced resolution factor to consider if */ + /* the whole tile path must be taken */ + return (tcx0 >= (OPJ_UINT32)tilec->x0 && + tcy0 >= (OPJ_UINT32)tilec->y0 && + tcx1 <= (OPJ_UINT32)tilec->x1 && + tcy1 <= (OPJ_UINT32)tilec->y1 && + (shift >= 32 || + (((tcx0 - (OPJ_UINT32)tilec->x0) >> shift) == 0 && + ((tcy0 - (OPJ_UINT32)tilec->y0) >> shift) == 0 && + (((OPJ_UINT32)tilec->x1 - tcx1) >> shift) == 0 && + (((OPJ_UINT32)tilec->y1 - tcy1) >> shift) == 0))); +} + +/* ----------------------------------------------------------------------- */ + +opj_tcd_marker_info_t* opj_tcd_marker_info_create(OPJ_BOOL need_PLT) +{ + opj_tcd_marker_info_t *l_tcd_marker_info = + (opj_tcd_marker_info_t*) opj_calloc(1, sizeof(opj_tcd_marker_info_t)); + if (!l_tcd_marker_info) { + return NULL; + } + + l_tcd_marker_info->need_PLT = need_PLT; + + return l_tcd_marker_info; +} + +/* ----------------------------------------------------------------------- */ + +void opj_tcd_marker_info_destroy(opj_tcd_marker_info_t *p_tcd_marker_info) +{ + if (p_tcd_marker_info) { + opj_free(p_tcd_marker_info->p_packet_size); + opj_free(p_tcd_marker_info); + } +} + +/* ----------------------------------------------------------------------- */ diff --git a/client/deps/openjpeg/tcd.h b/client/deps/openjpeg/tcd.h new file mode 100644 index 000000000..3371b08cb --- /dev/null +++ b/client/deps/openjpeg/tcd.h @@ -0,0 +1,512 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * Copyright (c) 2017, IntoPIX SA + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ +#ifndef OPJ_TCD_H +#define OPJ_TCD_H +/** +@file tcd.h +@brief Implementation of a tile coder/decoder (TCD) + +The functions in TCD.C encode or decode each tile independently from +each other. The functions in TCD.C are used by other functions in J2K.C. +*/ + +/** @defgroup TCD TCD - Implementation of a tile coder/decoder */ +/*@{*/ + + +/** +FIXME DOC +*/ +typedef struct opj_tcd_pass { + OPJ_UINT32 rate; + OPJ_FLOAT64 distortiondec; + OPJ_UINT32 len; + OPJ_BITFIELD term : 1; +} opj_tcd_pass_t; + +/** +FIXME DOC +*/ +typedef struct opj_tcd_layer { + OPJ_UINT32 numpasses; /* Number of passes in the layer */ + OPJ_UINT32 len; /* len of information */ + OPJ_FLOAT64 disto; /* add for index (Cfr. Marcela) */ + OPJ_BYTE *data; /* data */ +} opj_tcd_layer_t; + +/** +FIXME DOC +*/ +typedef struct opj_tcd_cblk_enc { + OPJ_BYTE* data; /* Data */ + opj_tcd_layer_t* layers; /* layer information */ + opj_tcd_pass_t* passes; /* information about the passes */ + OPJ_INT32 x0, y0, x1, + y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_UINT32 numbps; + OPJ_UINT32 numlenbits; + OPJ_UINT32 data_size; /* Size of allocated data buffer */ + OPJ_UINT32 + numpasses; /* number of pass already done for the code-blocks */ + OPJ_UINT32 numpassesinlayers; /* number of passes in the layer */ + OPJ_UINT32 totalpasses; /* total number of passes */ +} opj_tcd_cblk_enc_t; + + +/** Chunk of codestream data that is part of a code block */ +typedef struct opj_tcd_seg_data_chunk { + /* Point to tilepart buffer. We don't make a copy ! + So the tilepart buffer must be kept alive + as long as we need to decode the codeblocks */ + OPJ_BYTE * data; + OPJ_UINT32 len; /* Usable length of data */ +} opj_tcd_seg_data_chunk_t; + +/** Segment of a code-block. + * A segment represent a number of consecutive coding passes, without termination + * of MQC or RAW between them. */ +typedef struct opj_tcd_seg { + OPJ_UINT32 len; /* Size of data related to this segment */ + /* Number of passes decoded. Including those that we skip */ + OPJ_UINT32 numpasses; + /* Number of passes actually to be decoded. To be used for code-block decoding */ + OPJ_UINT32 real_num_passes; + /* Maximum number of passes for this segment */ + OPJ_UINT32 maxpasses; + /* Number of new passes for current packed. Transitory value */ + OPJ_UINT32 numnewpasses; + /* Codestream length for this segment for current packed. Transitory value */ + OPJ_UINT32 newlen; +} opj_tcd_seg_t; + +/** Code-block for decoding */ +typedef struct opj_tcd_cblk_dec { + opj_tcd_seg_t* segs; /* segments information */ + opj_tcd_seg_data_chunk_t* chunks; /* Array of chunks */ + /* position of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + /* Mb is The maximum number of bit-planes available for the representation of + coefficients in any sub-band, b, as defined in Equation (E-2). See + Section B.10.5 of the standard */ + OPJ_UINT32 Mb; /* currently used only to check if HT decoding is correct */ + /* numbps is Mb - P as defined in Section B.10.5 of the standard */ + OPJ_UINT32 numbps; + /* number of bits for len, for the current packet. Transitory value */ + OPJ_UINT32 numlenbits; + /* number of pass added to the code-blocks, for the current packet. Transitory value */ + OPJ_UINT32 numnewpasses; + /* number of segments, including those of packet we skip */ + OPJ_UINT32 numsegs; + /* number of segments, to be used for code block decoding */ + OPJ_UINT32 real_num_segs; + OPJ_UINT32 m_current_max_segs; /* allocated number of segs[] items */ + OPJ_UINT32 numchunks; /* Number of valid chunks items */ + OPJ_UINT32 numchunksalloc; /* Number of chunks item allocated */ + /* Decoded code-block. Only used for subtile decoding. Otherwise tilec->data is directly updated */ + OPJ_INT32* decoded_data; + OPJ_BOOL corrupted; /* whether the code block data is corrupted */ +} opj_tcd_cblk_dec_t; + +/** Precinct structure */ +typedef struct opj_tcd_precinct { + /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + OPJ_UINT32 cw, ch; /* number of code-blocks, in width and height */ + union { /* code-blocks information */ + opj_tcd_cblk_enc_t* enc; + opj_tcd_cblk_dec_t* dec; + void* blocks; + } cblks; + OPJ_UINT32 block_size; /* size taken by cblks (in bytes) */ + opj_tgt_tree_t *incltree; /* inclusion tree */ + opj_tgt_tree_t *imsbtree; /* IMSB tree */ +} opj_tcd_precinct_t; + +/** Sub-band structure */ +typedef struct opj_tcd_band { + /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + /* band number: for lowest resolution level (0=LL), otherwise (1=HL, 2=LH, 3=HH) */ + OPJ_UINT32 bandno; + /* precinct information */ + opj_tcd_precinct_t *precincts; + /* size of data taken by precincts */ + OPJ_UINT32 precincts_data_size; + OPJ_INT32 numbps; + OPJ_FLOAT32 stepsize; +} opj_tcd_band_t; + +/** Tile-component resolution structure */ +typedef struct opj_tcd_resolution { + /* dimension of the resolution level : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + /* number of precincts, in width and height, for this resolution level */ + OPJ_UINT32 pw, ph; + /* number of sub-bands for the resolution level (1 for lowest resolution level, 3 otherwise) */ + OPJ_UINT32 numbands; + /* subband information */ + opj_tcd_band_t bands[3]; + + /* dimension of the resolution limited to window of interest. Only valid if tcd->whole_tile_decoding is set */ + OPJ_UINT32 win_x0; + OPJ_UINT32 win_y0; + OPJ_UINT32 win_x1; + OPJ_UINT32 win_y1; +} opj_tcd_resolution_t; + +/** Tile-component structure */ +typedef struct opj_tcd_tilecomp { + /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + /* component number */ + OPJ_UINT32 compno; + /* number of resolutions level */ + OPJ_UINT32 numresolutions; + /* number of resolutions level to decode (at max)*/ + OPJ_UINT32 minimum_num_resolutions; + /* resolutions information */ + opj_tcd_resolution_t *resolutions; + /* size of data for resolutions (in bytes) */ + OPJ_UINT32 resolutions_size; + + /* data of the component. For decoding, only valid if tcd->whole_tile_decoding is set (so exclusive of data_win member) */ + OPJ_INT32 *data; + /* if true, then need to free after usage, otherwise do not free */ + OPJ_BOOL ownsData; + /* we may either need to allocate this amount of data, or re-use image data and ignore this value */ + size_t data_size_needed; + /* size of the data of the component */ + size_t data_size; + + /** data of the component limited to window of interest. Only valid for decoding and if tcd->whole_tile_decoding is NOT set (so exclusive of data member) */ + OPJ_INT32 *data_win; + /* dimension of the component limited to window of interest. Only valid for decoding and if tcd->whole_tile_decoding is NOT set */ + OPJ_UINT32 win_x0; + OPJ_UINT32 win_y0; + OPJ_UINT32 win_x1; + OPJ_UINT32 win_y1; + + /* number of pixels */ + OPJ_SIZE_T numpix; +} opj_tcd_tilecomp_t; + + +/** +FIXME DOC +*/ +typedef struct opj_tcd_tile { + /* dimension of the tile : left upper corner (x0, y0) right low corner (x1,y1) */ + OPJ_INT32 x0, y0, x1, y1; + OPJ_UINT32 numcomps; /* number of components in tile */ + opj_tcd_tilecomp_t *comps; /* Components information */ + OPJ_SIZE_T numpix; /* number of pixels */ + OPJ_FLOAT64 distotile; /* distortion of the tile */ + OPJ_FLOAT64 distolayer[100]; /* distortion per layer */ + OPJ_UINT32 packno; /* packet number */ +} opj_tcd_tile_t; + +/** +FIXME DOC +*/ +typedef struct opj_tcd_image { + opj_tcd_tile_t *tiles; /* Tiles information */ +} +opj_tcd_image_t; + + +/** +Tile coder/decoder +*/ +typedef struct opj_tcd { + /** Position of the tilepart flag in Progression order*/ + OPJ_INT32 tp_pos; + /** Tile part number*/ + OPJ_UINT32 tp_num; + /** Current tile part number*/ + OPJ_UINT32 cur_tp_num; + /** Total number of tileparts of the current tile*/ + OPJ_UINT32 cur_totnum_tp; + /** Current Packet iterator number */ + OPJ_UINT32 cur_pino; + /** info on each image tile */ + opj_tcd_image_t *tcd_image; + /** image header */ + opj_image_t *image; + /** coding parameters */ + opj_cp_t *cp; + /** coding/decoding parameters common to all tiles */ + opj_tcp_t *tcp; + /** current encoded/decoded tile */ + OPJ_UINT32 tcd_tileno; + /** tell if the tcd is a decoder. */ + OPJ_BITFIELD m_is_decoder : 1; + /** Thread pool */ + opj_thread_pool_t* thread_pool; + /** Coordinates of the window of interest, in grid reference space */ + OPJ_UINT32 win_x0; + OPJ_UINT32 win_y0; + OPJ_UINT32 win_x1; + OPJ_UINT32 win_y1; + /** Only valid for decoding. Whether the whole tile is decoded, or just the region in win_x0/win_y0/win_x1/win_y1 */ + OPJ_BOOL whole_tile_decoding; + /* Array of size image->numcomps indicating if a component must be decoded. NULL if all components must be decoded */ + OPJ_BOOL* used_component; +} opj_tcd_t; + +/** + * Structure to hold information needed to generate some markers. + * Used by encoder. + */ +typedef struct opj_tcd_marker_info { + /** In: Whether information to generate PLT markers in needed */ + OPJ_BOOL need_PLT; + + /** OUT: Number of elements in p_packet_size[] array */ + OPJ_UINT32 packet_count; + + /** OUT: Array of size packet_count, such that p_packet_size[i] is + * the size in bytes of the ith packet */ + OPJ_UINT32* p_packet_size; +} opj_tcd_marker_info_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Dump the content of a tcd structure +*/ +/*void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t *img);*/ /* TODO MSD should use the new v2 structures */ + +/** +Create a new TCD handle +@param p_is_decoder FIXME DOC +@return Returns a new TCD handle if successful returns NULL otherwise +*/ +opj_tcd_t* opj_tcd_create(OPJ_BOOL p_is_decoder); + +/** +Destroy a previously created TCD handle +@param tcd TCD handle to destroy +*/ +void opj_tcd_destroy(opj_tcd_t *tcd); + + +/** + * Create a new opj_tcd_marker_info_t* structure + * @param need_PLT Whether information is needed to generate PLT markers. + */ +opj_tcd_marker_info_t* opj_tcd_marker_info_create(OPJ_BOOL need_PLT); + + +/** +Destroy a previously created opj_tcd_marker_info_t* structure +@param p_tcd_marker_info Structure to destroy +*/ +void opj_tcd_marker_info_destroy(opj_tcd_marker_info_t *p_tcd_marker_info); + + +/** + * Initialize the tile coder and may reuse some memory. + * @param p_tcd TCD handle. + * @param p_image raw image. + * @param p_cp coding parameters. + * @param p_tp thread pool + * + * @return true if the encoding values could be set (false otherwise). +*/ +OPJ_BOOL opj_tcd_init(opj_tcd_t *p_tcd, + opj_image_t * p_image, + opj_cp_t * p_cp, + opj_thread_pool_t* p_tp); + +/** + * Allocates memory for decoding a specific tile. + * + * @param p_tcd the tile decoder. + * @param p_tile_no the index of the tile received in sequence. This not necessarily lead to the + * tile at index p_tile_no. + * @param p_manager the event manager. + * + * @return true if the remaining data is sufficient. + */ +OPJ_BOOL opj_tcd_init_decode_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, + opj_event_mgr_t* p_manager); + +/** + * Gets the maximum tile size that will be taken by the tile once decoded. + */ +OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd, + OPJ_BOOL take_into_account_partial_decoding); + +/** + * Encodes a tile from the raw image into the given buffer. + * @param p_tcd Tile Coder handle + * @param p_tile_no Index of the tile to encode. + * @param p_dest Destination buffer + * @param p_data_written pointer to an int that is incremented by the number of bytes really written on p_dest + * @param p_len Maximum length of the destination buffer + * @param p_cstr_info Codestream information structure + * @param p_marker_info Marker information structure + * @param p_manager the user event manager + * @return true if the coding is successful. +*/ +OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd, + OPJ_UINT32 p_tile_no, + OPJ_BYTE *p_dest, + OPJ_UINT32 * p_data_written, + OPJ_UINT32 p_len, + struct opj_codestream_info *p_cstr_info, + opj_tcd_marker_info_t* p_marker_info, + opj_event_mgr_t *p_manager); + + +/** +Decode a tile from a buffer into a raw image +@param tcd TCD handle +@param win_x0 Upper left x of region to decode (in grid coordinates) +@param win_y0 Upper left y of region to decode (in grid coordinates) +@param win_x1 Lower right x of region to decode (in grid coordinates) +@param win_y1 Lower right y of region to decode (in grid coordinates) +@param numcomps_to_decode Size of the comps_indices array, or 0 if decoding all components. +@param comps_indices Array of numcomps values representing the indices + of the components to decode (relative to the + codestream, starting at 0). Or NULL if decoding all components. +@param src Source buffer +@param len Length of source buffer +@param tileno Number that identifies one of the tiles to be decoded +@param cstr_info FIXME DOC +@param manager the event manager. +*/ +OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *tcd, + OPJ_UINT32 win_x0, + OPJ_UINT32 win_y0, + OPJ_UINT32 win_x1, + OPJ_UINT32 win_y1, + OPJ_UINT32 numcomps_to_decode, + const OPJ_UINT32 *comps_indices, + OPJ_BYTE *src, + OPJ_UINT32 len, + OPJ_UINT32 tileno, + opj_codestream_index_t *cstr_info, + opj_event_mgr_t *manager); + + +/** + * Copies tile data from the system onto the given memory block. + */ +OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd, + OPJ_BYTE * p_dest, + OPJ_UINT32 p_dest_length); + +/** + * Get the size in bytes of the input buffer provided before encoded. + * This must be the size provided to the p_src_length argument of + * opj_tcd_copy_tile_data() + */ +OPJ_SIZE_T opj_tcd_get_encoder_input_buffer_size(opj_tcd_t *p_tcd); + +/** + * Initialize the tile coder and may reuse some memory. + * + * @param p_tcd TCD handle. + * @param p_tile_no current tile index to encode. + * @param p_manager the event manager. + * + * @return true if the encoding values could be set (false otherwise). +*/ +OPJ_BOOL opj_tcd_init_encode_tile(opj_tcd_t *p_tcd, + OPJ_UINT32 p_tile_no, opj_event_mgr_t* p_manager); + +/** + * Copies tile data from the given memory block onto the system. + * + * p_src_length must be equal to opj_tcd_get_encoder_input_buffer_size() + */ +OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd, + OPJ_BYTE * p_src, + OPJ_SIZE_T p_src_length); + +/** + * Allocates tile component data + * + * + */ +OPJ_BOOL opj_alloc_tile_component_data(opj_tcd_tilecomp_t *l_tilec); + +/** Returns whether a sub-band is empty (i.e. whether it has a null area) + * @param band Sub-band handle. + * @return OPJ_TRUE whether the sub-band is empty. + */ +OPJ_BOOL opj_tcd_is_band_empty(opj_tcd_band_t* band); + +/** Reinitialize a segment */ +void opj_tcd_reinit_segment(opj_tcd_seg_t* seg); + + +/** Returns whether a sub-band region contributes to the area of interest + * tcd->win_x0,tcd->win_y0,tcd->win_x1,tcd->win_y1. + * + * @param tcd TCD handle. + * @param compno Component number + * @param resno Resolution number + * @param bandno Band number (*not* band index, ie 0, 1, 2 or 3) + * @param x0 Upper left x in subband coordinates + * @param y0 Upper left y in subband coordinates + * @param x1 Lower right x in subband coordinates + * @param y1 Lower right y in subband coordinates + * @return OPJ_TRUE whether the sub-band region contributes to the area of + * interest. + */ +OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd, + OPJ_UINT32 compno, + OPJ_UINT32 resno, + OPJ_UINT32 bandno, + OPJ_UINT32 x0, + OPJ_UINT32 y0, + OPJ_UINT32 x1, + OPJ_UINT32 y1); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_TCD_H */ diff --git a/client/deps/openjpeg/tgt.c b/client/deps/openjpeg/tgt.c new file mode 100644 index 000000000..711d753f4 --- /dev/null +++ b/client/deps/openjpeg/tgt.c @@ -0,0 +1,344 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include "opj_includes.h" + +/* +========================================================== + Tag-tree coder interface +========================================================== +*/ + +opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv, + opj_event_mgr_t *p_manager) +{ + OPJ_INT32 nplh[32]; + OPJ_INT32 nplv[32]; + opj_tgt_node_t *node = 00; + opj_tgt_node_t *l_parent_node = 00; + opj_tgt_node_t *l_parent_node0 = 00; + opj_tgt_tree_t *tree = 00; + OPJ_UINT32 i; + OPJ_INT32 j, k; + OPJ_UINT32 numlvls; + OPJ_UINT32 n; + + tree = (opj_tgt_tree_t *) opj_calloc(1, sizeof(opj_tgt_tree_t)); + if (!tree) { + opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to create Tag-tree\n"); + return 00; + } + + tree->numleafsh = numleafsh; + tree->numleafsv = numleafsv; + + numlvls = 0; + nplh[0] = (OPJ_INT32)numleafsh; + nplv[0] = (OPJ_INT32)numleafsv; + tree->numnodes = 0; + do { + n = (OPJ_UINT32)(nplh[numlvls] * nplv[numlvls]); + nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2; + nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2; + tree->numnodes += n; + ++numlvls; + } while (n > 1); + + /* ADD */ + if (tree->numnodes == 0) { + opj_free(tree); + return 00; + } + + tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, + sizeof(opj_tgt_node_t)); + if (!tree->nodes) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to create Tag-tree nodes\n"); + opj_free(tree); + return 00; + } + tree->nodes_size = tree->numnodes * (OPJ_UINT32)sizeof(opj_tgt_node_t); + + node = tree->nodes; + l_parent_node = &tree->nodes[tree->numleafsh * tree->numleafsv]; + l_parent_node0 = l_parent_node; + + for (i = 0; i < numlvls - 1; ++i) { + for (j = 0; j < nplv[i]; ++j) { + k = nplh[i]; + while (--k >= 0) { + node->parent = l_parent_node; + ++node; + if (--k >= 0) { + node->parent = l_parent_node; + ++node; + } + ++l_parent_node; + } + if ((j & 1) || j == nplv[i] - 1) { + l_parent_node0 = l_parent_node; + } else { + l_parent_node = l_parent_node0; + l_parent_node0 += nplh[i]; + } + } + } + node->parent = 0; + opj_tgt_reset(tree); + return tree; +} + +/** + * Reinitialises a tag-tree from an existing one. + * + * @param p_tree the tree to reinitialize. + * @param p_num_leafs_h the width of the array of leafs of the tree + * @param p_num_leafs_v the height of the array of leafs of the tree + * @return a new tag-tree if successful, NULL otherwise +*/ +opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree, OPJ_UINT32 p_num_leafs_h, + OPJ_UINT32 p_num_leafs_v, opj_event_mgr_t *p_manager) +{ + OPJ_INT32 l_nplh[32]; + OPJ_INT32 l_nplv[32]; + opj_tgt_node_t *l_node = 00; + opj_tgt_node_t *l_parent_node = 00; + opj_tgt_node_t *l_parent_node0 = 00; + OPJ_UINT32 i; + OPJ_INT32 j, k; + OPJ_UINT32 l_num_levels; + OPJ_UINT32 n; + OPJ_UINT32 l_node_size; + + if (! p_tree) { + return 00; + } + + if ((p_tree->numleafsh != p_num_leafs_h) || + (p_tree->numleafsv != p_num_leafs_v)) { + p_tree->numleafsh = p_num_leafs_h; + p_tree->numleafsv = p_num_leafs_v; + + l_num_levels = 0; + l_nplh[0] = (OPJ_INT32)p_num_leafs_h; + l_nplv[0] = (OPJ_INT32)p_num_leafs_v; + p_tree->numnodes = 0; + do { + n = (OPJ_UINT32)(l_nplh[l_num_levels] * l_nplv[l_num_levels]); + l_nplh[l_num_levels + 1] = (l_nplh[l_num_levels] + 1) / 2; + l_nplv[l_num_levels + 1] = (l_nplv[l_num_levels] + 1) / 2; + p_tree->numnodes += n; + ++l_num_levels; + } while (n > 1); + + /* ADD */ + if (p_tree->numnodes == 0) { + opj_tgt_destroy(p_tree); + return 00; + } + l_node_size = p_tree->numnodes * (OPJ_UINT32)sizeof(opj_tgt_node_t); + + if (l_node_size > p_tree->nodes_size) { + opj_tgt_node_t* new_nodes = (opj_tgt_node_t*) opj_realloc(p_tree->nodes, + l_node_size); + if (! new_nodes) { + opj_event_msg(p_manager, EVT_ERROR, + "Not enough memory to reinitialize the tag tree\n"); + opj_tgt_destroy(p_tree); + return 00; + } + p_tree->nodes = new_nodes; + memset(((char *) p_tree->nodes) + p_tree->nodes_size, 0, + l_node_size - p_tree->nodes_size); + p_tree->nodes_size = l_node_size; + } + l_node = p_tree->nodes; + l_parent_node = &p_tree->nodes[p_tree->numleafsh * p_tree->numleafsv]; + l_parent_node0 = l_parent_node; + + for (i = 0; i < l_num_levels - 1; ++i) { + for (j = 0; j < l_nplv[i]; ++j) { + k = l_nplh[i]; + while (--k >= 0) { + l_node->parent = l_parent_node; + ++l_node; + if (--k >= 0) { + l_node->parent = l_parent_node; + ++l_node; + } + ++l_parent_node; + } + if ((j & 1) || j == l_nplv[i] - 1) { + l_parent_node0 = l_parent_node; + } else { + l_parent_node = l_parent_node0; + l_parent_node0 += l_nplh[i]; + } + } + } + l_node->parent = 0; + } + opj_tgt_reset(p_tree); + + return p_tree; +} + +void opj_tgt_destroy(opj_tgt_tree_t *p_tree) +{ + if (! p_tree) { + return; + } + + if (p_tree->nodes) { + opj_free(p_tree->nodes); + p_tree->nodes = 00; + } + opj_free(p_tree); +} + +void opj_tgt_reset(opj_tgt_tree_t *p_tree) +{ + OPJ_UINT32 i; + opj_tgt_node_t * l_current_node = 00;; + + if (! p_tree) { + return; + } + + l_current_node = p_tree->nodes; + for (i = 0; i < p_tree->numnodes; ++i) { + l_current_node->value = 999; + l_current_node->low = 0; + l_current_node->known = 0; + ++l_current_node; + } +} + +void opj_tgt_setvalue(opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 value) +{ + opj_tgt_node_t *node; + node = &tree->nodes[leafno]; + while (node && node->value > value) { + node->value = value; + node = node->parent; + } +} + +void opj_tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, + OPJ_INT32 threshold) +{ + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + OPJ_INT32 low; + + stkptr = stk; + node = &tree->nodes[leafno]; + while (node->parent) { + *stkptr++ = node; + node = node->parent; + } + + low = 0; + for (;;) { + if (low > node->low) { + node->low = low; + } else { + low = node->low; + } + + while (low < threshold) { + if (low >= node->value) { + if (!node->known) { + opj_bio_putbit(bio, 1); + node->known = 1; + } + break; + } + opj_bio_putbit(bio, 0); + ++low; + } + + node->low = low; + if (stkptr == stk) { + break; + } + node = *--stkptr; + } +} + +OPJ_UINT32 opj_tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, + OPJ_UINT32 leafno, OPJ_INT32 threshold) +{ + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + OPJ_INT32 low; + + stkptr = stk; + node = &tree->nodes[leafno]; + while (node->parent) { + *stkptr++ = node; + node = node->parent; + } + + low = 0; + for (;;) { + if (low > node->low) { + node->low = low; + } else { + low = node->low; + } + while (low < threshold && low < node->value) { + if (opj_bio_read(bio, 1)) { + node->value = low; + } else { + ++low; + } + } + node->low = low; + if (stkptr == stk) { + break; + } + node = *--stkptr; + } + + return (node->value < threshold) ? 1 : 0; +} diff --git a/client/deps/openjpeg/tgt.h b/client/deps/openjpeg/tgt.h new file mode 100644 index 000000000..9818208b8 --- /dev/null +++ b/client/deps/openjpeg/tgt.h @@ -0,0 +1,148 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2007, Francois-Olivier Devaux + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2008, Jerome Fimes, Communications & Systemes + * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France + * Copyright (c) 2012, CS Systemes d'Information, France + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_TGT_H +#define OPJ_TGT_H +/** +@file tgt.h +@brief Implementation of a tag-tree coder (TGT) + +The functions in TGT.C have for goal to realize a tag-tree coder. The functions in TGT.C +are used by some function in T2.C. +*/ + +/** @defgroup TGT TGT - Implementation of a tag-tree coder */ +/*@{*/ + +/** +Tag node +*/ +typedef struct opj_tgt_node { + struct opj_tgt_node *parent; + OPJ_INT32 value; + OPJ_INT32 low; + OPJ_UINT32 known; +} opj_tgt_node_t; + +/** +Tag tree +*/ +typedef struct opj_tgt_tree { + OPJ_UINT32 numleafsh; + OPJ_UINT32 numleafsv; + OPJ_UINT32 numnodes; + opj_tgt_node_t *nodes; + OPJ_UINT32 nodes_size; /* maximum size taken by nodes */ +} opj_tgt_tree_t; + + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a tag-tree +@param numleafsh Width of the array of leafs of the tree +@param numleafsv Height of the array of leafs of the tree +@param p_manager the event manager +@return Returns a new tag-tree if successful, returns NULL otherwise +*/ +opj_tgt_tree_t *opj_tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv, + opj_event_mgr_t *p_manager); + +/** + * Reinitialises a tag-tree from an exixting one. + * + * @param p_tree the tree to reinitialize. + * @param p_num_leafs_h the width of the array of leafs of the tree + * @param p_num_leafs_v the height of the array of leafs of the tree + * @param p_manager the event manager + * @return a new tag-tree if successful, NULL otherwise +*/ +opj_tgt_tree_t *opj_tgt_init(opj_tgt_tree_t * p_tree, + OPJ_UINT32 p_num_leafs_h, + OPJ_UINT32 p_num_leafs_v, opj_event_mgr_t *p_manager); +/** +Destroy a tag-tree, liberating memory +@param tree Tag-tree to destroy +*/ +void opj_tgt_destroy(opj_tgt_tree_t *tree); +/** +Reset a tag-tree (set all leaves to 0) +@param tree Tag-tree to reset +*/ +void opj_tgt_reset(opj_tgt_tree_t *tree); +/** +Set the value of a leaf of a tag-tree +@param tree Tag-tree to modify +@param leafno Number that identifies the leaf to modify +@param value New value of the leaf +*/ +void opj_tgt_setvalue(opj_tgt_tree_t *tree, + OPJ_UINT32 leafno, + OPJ_INT32 value); +/** +Encode the value of a leaf of the tag-tree up to a given threshold +@param bio Pointer to a BIO handle +@param tree Tag-tree to modify +@param leafno Number that identifies the leaf to encode +@param threshold Threshold to use when encoding value of the leaf +*/ +void opj_tgt_encode(opj_bio_t *bio, + opj_tgt_tree_t *tree, + OPJ_UINT32 leafno, + OPJ_INT32 threshold); +/** +Decode the value of a leaf of the tag-tree up to a given threshold +@param bio Pointer to a BIO handle +@param tree Tag-tree to decode +@param leafno Number that identifies the leaf to decode +@param threshold Threshold to use when decoding value of the leaf +@return Returns 1 if the node's value < threshold, returns 0 otherwise +*/ +OPJ_UINT32 opj_tgt_decode(opj_bio_t *bio, + opj_tgt_tree_t *tree, + OPJ_UINT32 leafno, + OPJ_INT32 threshold); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* OPJ_TGT_H */ diff --git a/client/deps/openjpeg/thread.c b/client/deps/openjpeg/thread.c new file mode 100644 index 000000000..240810b1c --- /dev/null +++ b/client/deps/openjpeg/thread.c @@ -0,0 +1,954 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2016, Even Rouault + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#include + +#ifdef MUTEX_win32 + +/* Some versions of x86_64-w64-mingw32-gc -m32 resolve InterlockedCompareExchange() */ +/* as __sync_val_compare_and_swap_4 but fails to link it. As this protects against */ +/* a rather unlikely race, skip it */ +#if !(defined(__MINGW32__) && defined(__i386__)) +#define HAVE_INTERLOCKED_COMPARE_EXCHANGE 1 +#endif + +#include +#include + +#include "opj_includes.h" + +OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void) +{ + return OPJ_TRUE; +} + +int OPJ_CALLCONV opj_get_num_cpus(void) +{ + SYSTEM_INFO info; + DWORD dwNum; + GetSystemInfo(&info); + dwNum = info.dwNumberOfProcessors; + if (dwNum < 1) { + return 1; + } + return (int)dwNum; +} + +struct opj_mutex_t { + CRITICAL_SECTION cs; +}; + +opj_mutex_t* opj_mutex_create(void) +{ + opj_mutex_t* mutex = (opj_mutex_t*) opj_malloc(sizeof(opj_mutex_t)); + if (!mutex) { + return NULL; + } + InitializeCriticalSectionAndSpinCount(&(mutex->cs), 4000); + return mutex; +} + +void opj_mutex_lock(opj_mutex_t* mutex) +{ + EnterCriticalSection(&(mutex->cs)); +} + +void opj_mutex_unlock(opj_mutex_t* mutex) +{ + LeaveCriticalSection(&(mutex->cs)); +} + +void opj_mutex_destroy(opj_mutex_t* mutex) +{ + if (!mutex) { + return; + } + DeleteCriticalSection(&(mutex->cs)); + opj_free(mutex); +} + +struct opj_cond_waiter_list_t { + HANDLE hEvent; + struct opj_cond_waiter_list_t* next; +}; +typedef struct opj_cond_waiter_list_t opj_cond_waiter_list_t; + +struct opj_cond_t { + opj_mutex_t *internal_mutex; + opj_cond_waiter_list_t *waiter_list; +}; + +static DWORD TLSKey = 0; +static volatile LONG inTLSLockedSection = 0; +static volatile int TLSKeyInit = OPJ_FALSE; + +opj_cond_t* opj_cond_create(void) +{ + opj_cond_t* cond = (opj_cond_t*) opj_malloc(sizeof(opj_cond_t)); + if (!cond) { + return NULL; + } + + /* Make sure that the TLS key is allocated in a thread-safe way */ + /* We cannot use a global mutex/critical section since its creation itself would not be */ + /* thread-safe, so use InterlockedCompareExchange trick */ + while (OPJ_TRUE) { + +#if HAVE_INTERLOCKED_COMPARE_EXCHANGE + if (InterlockedCompareExchange(&inTLSLockedSection, 1, 0) == 0) +#endif + { + if (!TLSKeyInit) { + TLSKey = TlsAlloc(); + TLSKeyInit = OPJ_TRUE; + } +#if HAVE_INTERLOCKED_COMPARE_EXCHANGE + InterlockedCompareExchange(&inTLSLockedSection, 0, 1); +#endif + break; + } + } + + if (TLSKey == TLS_OUT_OF_INDEXES) { + opj_free(cond); + return NULL; + } + cond->internal_mutex = opj_mutex_create(); + if (cond->internal_mutex == NULL) { + opj_free(cond); + return NULL; + } + cond->waiter_list = NULL; + return cond; +} + +void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex) +{ + opj_cond_waiter_list_t* item; + HANDLE hEvent = (HANDLE) TlsGetValue(TLSKey); + if (hEvent == NULL) { + hEvent = CreateEvent(NULL, /* security attributes */ + 0, /* manual reset = no */ + 0, /* initial state = unsignaled */ + NULL /* no name */); + assert(hEvent); + + TlsSetValue(TLSKey, hEvent); + } + + /* Insert the waiter into the waiter list of the condition */ + opj_mutex_lock(cond->internal_mutex); + + item = (opj_cond_waiter_list_t*)opj_malloc(sizeof(opj_cond_waiter_list_t)); + assert(item != NULL); + + item->hEvent = hEvent; + item->next = cond->waiter_list; + + cond->waiter_list = item; + + opj_mutex_unlock(cond->internal_mutex); + + /* Release the client mutex before waiting for the event being signaled */ + opj_mutex_unlock(mutex); + + /* Ideally we would check that we do not get WAIT_FAILED but it is hard */ + /* to report a failure. */ + WaitForSingleObject(hEvent, INFINITE); + + /* Reacquire the client mutex */ + opj_mutex_lock(mutex); +} + +void opj_cond_signal(opj_cond_t* cond) +{ + opj_cond_waiter_list_t* psIter; + + /* Signal the first registered event, and remove it from the list */ + opj_mutex_lock(cond->internal_mutex); + + psIter = cond->waiter_list; + if (psIter != NULL) { + SetEvent(psIter->hEvent); + cond->waiter_list = psIter->next; + opj_free(psIter); + } + + opj_mutex_unlock(cond->internal_mutex); +} + +void opj_cond_destroy(opj_cond_t* cond) +{ + if (!cond) { + return; + } + opj_mutex_destroy(cond->internal_mutex); + assert(cond->waiter_list == NULL); + opj_free(cond); +} + +struct opj_thread_t { + opj_thread_fn thread_fn; + void* user_data; + HANDLE hThread; +}; + +static unsigned int __stdcall opj_thread_callback_adapter(void *info) +{ + opj_thread_t* thread = (opj_thread_t*) info; + HANDLE hEvent = NULL; + + thread->thread_fn(thread->user_data); + + /* Free the handle possible allocated by a cond */ + while (OPJ_TRUE) { + /* Make sure TLSKey is not being created just at that moment... */ +#if HAVE_INTERLOCKED_COMPARE_EXCHANGE + if (InterlockedCompareExchange(&inTLSLockedSection, 1, 0) == 0) +#endif + { + if (TLSKeyInit) { + hEvent = (HANDLE) TlsGetValue(TLSKey); + } +#if HAVE_INTERLOCKED_COMPARE_EXCHANGE + InterlockedCompareExchange(&inTLSLockedSection, 0, 1); +#endif + break; + } + } + if (hEvent) { + CloseHandle(hEvent); + } + + return 0; +} + +opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data) +{ + opj_thread_t* thread; + + assert(thread_fn); + + thread = (opj_thread_t*) opj_malloc(sizeof(opj_thread_t)); + if (!thread) { + return NULL; + } + thread->thread_fn = thread_fn; + thread->user_data = user_data; + + thread->hThread = (HANDLE)_beginthreadex(NULL, 0, + opj_thread_callback_adapter, thread, 0, NULL); + + if (thread->hThread == NULL) { + opj_free(thread); + return NULL; + } + return thread; +} + +void opj_thread_join(opj_thread_t* thread) +{ + WaitForSingleObject(thread->hThread, INFINITE); + CloseHandle(thread->hThread); + + opj_free(thread); +} + +#elif MUTEX_pthread + +#include +#include +#include + +/* Moved after all system includes, and in particular pthread.h, so as to */ +/* avoid poisoning issuing with malloc() use in pthread.h with ulibc (#1013) */ +#include "opj_includes.h" + +OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void) +{ + return OPJ_TRUE; +} + +int OPJ_CALLCONV opj_get_num_cpus(void) +{ +#ifdef _SC_NPROCESSORS_ONLN + return (int)sysconf(_SC_NPROCESSORS_ONLN); +#else + return 1; +#endif +} + +struct opj_mutex_t { + pthread_mutex_t mutex; +}; + +opj_mutex_t* opj_mutex_create(void) +{ + opj_mutex_t* mutex = (opj_mutex_t*) opj_calloc(1U, sizeof(opj_mutex_t)); + if (mutex != NULL) { + if (pthread_mutex_init(&mutex->mutex, NULL) != 0) { + opj_free(mutex); + mutex = NULL; + } + } + return mutex; +} + +void opj_mutex_lock(opj_mutex_t* mutex) +{ + pthread_mutex_lock(&(mutex->mutex)); +} + +void opj_mutex_unlock(opj_mutex_t* mutex) +{ + pthread_mutex_unlock(&(mutex->mutex)); +} + +void opj_mutex_destroy(opj_mutex_t* mutex) +{ + if (!mutex) { + return; + } + pthread_mutex_destroy(&(mutex->mutex)); + opj_free(mutex); +} + +struct opj_cond_t { + pthread_cond_t cond; +}; + +opj_cond_t* opj_cond_create(void) +{ + opj_cond_t* cond = (opj_cond_t*) opj_malloc(sizeof(opj_cond_t)); + if (!cond) { + return NULL; + } + if (pthread_cond_init(&(cond->cond), NULL) != 0) { + opj_free(cond); + return NULL; + } + return cond; +} + +void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex) +{ + pthread_cond_wait(&(cond->cond), &(mutex->mutex)); +} + +void opj_cond_signal(opj_cond_t* cond) +{ + int ret = pthread_cond_signal(&(cond->cond)); + (void)ret; + assert(ret == 0); +} + +void opj_cond_destroy(opj_cond_t* cond) +{ + if (!cond) { + return; + } + pthread_cond_destroy(&(cond->cond)); + opj_free(cond); +} + + +struct opj_thread_t { + opj_thread_fn thread_fn; + void* user_data; + pthread_t thread; +}; + +static void* opj_thread_callback_adapter(void* info) +{ + opj_thread_t* thread = (opj_thread_t*) info; + thread->thread_fn(thread->user_data); + return NULL; +} + +opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data) +{ + pthread_attr_t attr; + opj_thread_t* thread; + + assert(thread_fn); + + thread = (opj_thread_t*) opj_malloc(sizeof(opj_thread_t)); + if (!thread) { + return NULL; + } + thread->thread_fn = thread_fn; + thread->user_data = user_data; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + if (pthread_create(&(thread->thread), &attr, + opj_thread_callback_adapter, (void *) thread) != 0) { + opj_free(thread); + return NULL; + } + return thread; +} + +void opj_thread_join(opj_thread_t* thread) +{ + void* status; + pthread_join(thread->thread, &status); + + opj_free(thread); +} + +#else +/* Stub implementation */ + +#include "opj_includes.h" + +OPJ_BOOL OPJ_CALLCONV opj_has_thread_support(void) +{ + return OPJ_FALSE; +} + +int OPJ_CALLCONV opj_get_num_cpus(void) +{ + return 1; +} + +opj_mutex_t* opj_mutex_create(void) +{ + return NULL; +} + +void opj_mutex_lock(opj_mutex_t* mutex) +{ + (void) mutex; +} + +void opj_mutex_unlock(opj_mutex_t* mutex) +{ + (void) mutex; +} + +void opj_mutex_destroy(opj_mutex_t* mutex) +{ + (void) mutex; +} + +opj_cond_t* opj_cond_create(void) +{ + return NULL; +} + +void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex) +{ + (void) cond; + (void) mutex; +} + +void opj_cond_signal(opj_cond_t* cond) +{ + (void) cond; +} + +void opj_cond_destroy(opj_cond_t* cond) +{ + (void) cond; +} + +opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data) +{ + (void) thread_fn; + (void) user_data; + return NULL; +} + +void opj_thread_join(opj_thread_t* thread) +{ + (void) thread; +} + +#endif + +typedef struct { + int key; + void* value; + opj_tls_free_func opj_free_func; +} opj_tls_key_val_t; + +struct opj_tls_t { + opj_tls_key_val_t* key_val; + int key_val_count; +}; + +static opj_tls_t* opj_tls_new(void) +{ + return (opj_tls_t*) opj_calloc(1, sizeof(opj_tls_t)); +} + +static void opj_tls_destroy(opj_tls_t* tls) +{ + int i; + if (!tls) { + return; + } + for (i = 0; i < tls->key_val_count; i++) { + if (tls->key_val[i].opj_free_func) { + tls->key_val[i].opj_free_func(tls->key_val[i].value); + } + } + opj_free(tls->key_val); + opj_free(tls); +} + +void* opj_tls_get(opj_tls_t* tls, int key) +{ + int i; + for (i = 0; i < tls->key_val_count; i++) { + if (tls->key_val[i].key == key) { + return tls->key_val[i].value; + } + } + return NULL; +} + +OPJ_BOOL opj_tls_set(opj_tls_t* tls, int key, void* value, + opj_tls_free_func opj_free_func) +{ + opj_tls_key_val_t* new_key_val; + int i; + + if (tls->key_val_count == INT_MAX) { + return OPJ_FALSE; + } + for (i = 0; i < tls->key_val_count; i++) { + if (tls->key_val[i].key == key) { + if (tls->key_val[i].opj_free_func) { + tls->key_val[i].opj_free_func(tls->key_val[i].value); + } + tls->key_val[i].value = value; + tls->key_val[i].opj_free_func = opj_free_func; + return OPJ_TRUE; + } + } + new_key_val = (opj_tls_key_val_t*) opj_realloc(tls->key_val, + ((size_t)tls->key_val_count + 1U) * sizeof(opj_tls_key_val_t)); + if (!new_key_val) { + return OPJ_FALSE; + } + tls->key_val = new_key_val; + new_key_val[tls->key_val_count].key = key; + new_key_val[tls->key_val_count].value = value; + new_key_val[tls->key_val_count].opj_free_func = opj_free_func; + tls->key_val_count ++; + return OPJ_TRUE; +} + + +typedef struct { + opj_job_fn job_fn; + void *user_data; +} opj_worker_thread_job_t; + +typedef struct { + opj_thread_pool_t *tp; + opj_thread_t *thread; + int marked_as_waiting; + + opj_mutex_t *mutex; + opj_cond_t *cond; +} opj_worker_thread_t; + +typedef enum { + OPJWTS_OK, + OPJWTS_STOP, + OPJWTS_ERROR +} opj_worker_thread_state; + +struct opj_job_list_t { + opj_worker_thread_job_t* job; + struct opj_job_list_t* next; +}; +typedef struct opj_job_list_t opj_job_list_t; + +struct opj_worker_thread_list_t { + opj_worker_thread_t* worker_thread; + struct opj_worker_thread_list_t* next; +}; +typedef struct opj_worker_thread_list_t opj_worker_thread_list_t; + +struct opj_thread_pool_t { + opj_worker_thread_t* worker_threads; + int worker_threads_count; + opj_cond_t* cond; + opj_mutex_t* mutex; + volatile opj_worker_thread_state state; + opj_job_list_t* job_queue; + volatile int pending_jobs_count; + opj_worker_thread_list_t* waiting_worker_thread_list; + int waiting_worker_thread_count; + opj_tls_t* tls; + int signaling_threshold; +}; + +static OPJ_BOOL opj_thread_pool_setup(opj_thread_pool_t* tp, int num_threads); +static opj_worker_thread_job_t* opj_thread_pool_get_next_job( + opj_thread_pool_t* tp, + opj_worker_thread_t* worker_thread, + OPJ_BOOL signal_job_finished); + +opj_thread_pool_t* opj_thread_pool_create(int num_threads) +{ + opj_thread_pool_t* tp; + + tp = (opj_thread_pool_t*) opj_calloc(1, sizeof(opj_thread_pool_t)); + if (!tp) { + return NULL; + } + tp->state = OPJWTS_OK; + + if (num_threads <= 0) { + tp->tls = opj_tls_new(); + if (!tp->tls) { + opj_free(tp); + tp = NULL; + } + return tp; + } + + tp->mutex = opj_mutex_create(); + if (!tp->mutex) { + opj_free(tp); + return NULL; + } + if (!opj_thread_pool_setup(tp, num_threads)) { + opj_thread_pool_destroy(tp); + return NULL; + } + return tp; +} + +static void opj_worker_thread_function(void* user_data) +{ + opj_worker_thread_t* worker_thread; + opj_thread_pool_t* tp; + opj_tls_t* tls; + OPJ_BOOL job_finished = OPJ_FALSE; + + worker_thread = (opj_worker_thread_t*) user_data; + tp = worker_thread->tp; + tls = opj_tls_new(); + + while (OPJ_TRUE) { + opj_worker_thread_job_t* job = opj_thread_pool_get_next_job(tp, worker_thread, + job_finished); + if (job == NULL) { + break; + } + + if (job->job_fn) { + job->job_fn(job->user_data, tls); + } + opj_free(job); + job_finished = OPJ_TRUE; + } + + opj_tls_destroy(tls); +} + +static OPJ_BOOL opj_thread_pool_setup(opj_thread_pool_t* tp, int num_threads) +{ + int i; + OPJ_BOOL bRet = OPJ_TRUE; + + assert(num_threads > 0); + + tp->cond = opj_cond_create(); + if (tp->cond == NULL) { + return OPJ_FALSE; + } + + tp->worker_threads = (opj_worker_thread_t*) opj_calloc((size_t)num_threads, + sizeof(opj_worker_thread_t)); + if (tp->worker_threads == NULL) { + return OPJ_FALSE; + } + tp->worker_threads_count = num_threads; + + for (i = 0; i < num_threads; i++) { + tp->worker_threads[i].tp = tp; + + tp->worker_threads[i].mutex = opj_mutex_create(); + if (tp->worker_threads[i].mutex == NULL) { + tp->worker_threads_count = i; + bRet = OPJ_FALSE; + break; + } + + tp->worker_threads[i].cond = opj_cond_create(); + if (tp->worker_threads[i].cond == NULL) { + opj_mutex_destroy(tp->worker_threads[i].mutex); + tp->worker_threads_count = i; + bRet = OPJ_FALSE; + break; + } + + tp->worker_threads[i].marked_as_waiting = OPJ_FALSE; + + tp->worker_threads[i].thread = opj_thread_create(opj_worker_thread_function, + &(tp->worker_threads[i])); + if (tp->worker_threads[i].thread == NULL) { + opj_mutex_destroy(tp->worker_threads[i].mutex); + opj_cond_destroy(tp->worker_threads[i].cond); + tp->worker_threads_count = i; + bRet = OPJ_FALSE; + break; + } + } + + /* Wait all threads to be started */ + /* printf("waiting for all threads to be started\n"); */ + opj_mutex_lock(tp->mutex); + while (tp->waiting_worker_thread_count < tp->worker_threads_count) { + opj_cond_wait(tp->cond, tp->mutex); + } + opj_mutex_unlock(tp->mutex); + /* printf("all threads started\n"); */ + + if (tp->state == OPJWTS_ERROR) { + bRet = OPJ_FALSE; + } + + return bRet; +} + +/* +void opj_waiting() +{ + printf("waiting!\n"); +} +*/ + +static opj_worker_thread_job_t* opj_thread_pool_get_next_job( + opj_thread_pool_t* tp, + opj_worker_thread_t* worker_thread, + OPJ_BOOL signal_job_finished) +{ + while (OPJ_TRUE) { + opj_job_list_t* top_job_iter; + + opj_mutex_lock(tp->mutex); + + if (signal_job_finished) { + signal_job_finished = OPJ_FALSE; + tp->pending_jobs_count --; + /*printf("tp=%p, remaining jobs: %d\n", tp, tp->pending_jobs_count);*/ + if (tp->pending_jobs_count <= tp->signaling_threshold) { + opj_cond_signal(tp->cond); + } + } + + if (tp->state == OPJWTS_STOP) { + opj_mutex_unlock(tp->mutex); + return NULL; + } + top_job_iter = tp->job_queue; + if (top_job_iter) { + opj_worker_thread_job_t* job; + tp->job_queue = top_job_iter->next; + + job = top_job_iter->job; + opj_mutex_unlock(tp->mutex); + opj_free(top_job_iter); + return job; + } + + /* opj_waiting(); */ + if (!worker_thread->marked_as_waiting) { + opj_worker_thread_list_t* item; + + worker_thread->marked_as_waiting = OPJ_TRUE; + tp->waiting_worker_thread_count ++; + assert(tp->waiting_worker_thread_count <= tp->worker_threads_count); + + item = (opj_worker_thread_list_t*) opj_malloc(sizeof(opj_worker_thread_list_t)); + if (item == NULL) { + tp->state = OPJWTS_ERROR; + opj_cond_signal(tp->cond); + + opj_mutex_unlock(tp->mutex); + return NULL; + } + + item->worker_thread = worker_thread; + item->next = tp->waiting_worker_thread_list; + tp->waiting_worker_thread_list = item; + } + + /* printf("signaling that worker thread is ready\n"); */ + opj_cond_signal(tp->cond); + + opj_mutex_lock(worker_thread->mutex); + opj_mutex_unlock(tp->mutex); + + /* printf("waiting for job\n"); */ + opj_cond_wait(worker_thread->cond, worker_thread->mutex); + + opj_mutex_unlock(worker_thread->mutex); + /* printf("got job\n"); */ + } +} + +OPJ_BOOL opj_thread_pool_submit_job(opj_thread_pool_t* tp, + opj_job_fn job_fn, + void* user_data) +{ + opj_worker_thread_job_t* job; + opj_job_list_t* item; + + if (tp->mutex == NULL) { + job_fn(user_data, tp->tls); + return OPJ_TRUE; + } + + job = (opj_worker_thread_job_t*)opj_malloc(sizeof(opj_worker_thread_job_t)); + if (job == NULL) { + return OPJ_FALSE; + } + job->job_fn = job_fn; + job->user_data = user_data; + + item = (opj_job_list_t*) opj_malloc(sizeof(opj_job_list_t)); + if (item == NULL) { + opj_free(job); + return OPJ_FALSE; + } + item->job = job; + + opj_mutex_lock(tp->mutex); + + tp->signaling_threshold = 100 * tp->worker_threads_count; + while (tp->pending_jobs_count > tp->signaling_threshold) { + /* printf("%d jobs enqueued. Waiting\n", tp->pending_jobs_count); */ + opj_cond_wait(tp->cond, tp->mutex); + /* printf("...%d jobs enqueued.\n", tp->pending_jobs_count); */ + } + + item->next = tp->job_queue; + tp->job_queue = item; + tp->pending_jobs_count ++; + + if (tp->waiting_worker_thread_list) { + opj_worker_thread_t* worker_thread; + opj_worker_thread_list_t* next; + opj_worker_thread_list_t* to_opj_free; + + worker_thread = tp->waiting_worker_thread_list->worker_thread; + + assert(worker_thread->marked_as_waiting); + worker_thread->marked_as_waiting = OPJ_FALSE; + + next = tp->waiting_worker_thread_list->next; + to_opj_free = tp->waiting_worker_thread_list; + tp->waiting_worker_thread_list = next; + tp->waiting_worker_thread_count --; + + opj_mutex_lock(worker_thread->mutex); + opj_mutex_unlock(tp->mutex); + opj_cond_signal(worker_thread->cond); + opj_mutex_unlock(worker_thread->mutex); + + opj_free(to_opj_free); + } else { + opj_mutex_unlock(tp->mutex); + } + + return OPJ_TRUE; +} + +void opj_thread_pool_wait_completion(opj_thread_pool_t* tp, + int max_remaining_jobs) +{ + if (tp->mutex == NULL) { + return; + } + + if (max_remaining_jobs < 0) { + max_remaining_jobs = 0; + } + opj_mutex_lock(tp->mutex); + tp->signaling_threshold = max_remaining_jobs; + while (tp->pending_jobs_count > max_remaining_jobs) { + /*printf("tp=%p, jobs before wait = %d, max_remaining_jobs = %d\n", tp, tp->pending_jobs_count, max_remaining_jobs);*/ + opj_cond_wait(tp->cond, tp->mutex); + /*printf("tp=%p, jobs after wait = %d\n", tp, tp->pending_jobs_count);*/ + } + opj_mutex_unlock(tp->mutex); +} + +int opj_thread_pool_get_thread_count(opj_thread_pool_t* tp) +{ + return tp->worker_threads_count; +} + +void opj_thread_pool_destroy(opj_thread_pool_t* tp) +{ + if (!tp) { + return; + } + if (tp->cond) { + int i; + opj_thread_pool_wait_completion(tp, 0); + + opj_mutex_lock(tp->mutex); + tp->state = OPJWTS_STOP; + opj_mutex_unlock(tp->mutex); + + for (i = 0; i < tp->worker_threads_count; i++) { + opj_mutex_lock(tp->worker_threads[i].mutex); + opj_cond_signal(tp->worker_threads[i].cond); + opj_mutex_unlock(tp->worker_threads[i].mutex); + opj_thread_join(tp->worker_threads[i].thread); + opj_cond_destroy(tp->worker_threads[i].cond); + opj_mutex_destroy(tp->worker_threads[i].mutex); + } + + opj_free(tp->worker_threads); + + while (tp->waiting_worker_thread_list != NULL) { + opj_worker_thread_list_t* next = tp->waiting_worker_thread_list->next; + opj_free(tp->waiting_worker_thread_list); + tp->waiting_worker_thread_list = next; + } + + opj_cond_destroy(tp->cond); + } + opj_mutex_destroy(tp->mutex); + opj_tls_destroy(tp->tls); + opj_free(tp); +} diff --git a/client/deps/openjpeg/thread.h b/client/deps/openjpeg/thread.h new file mode 100644 index 000000000..c89e19b4a --- /dev/null +++ b/client/deps/openjpeg/thread.h @@ -0,0 +1,256 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2016, Even Rouault + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef THREAD_H +#define THREAD_H + +#include "openjpeg.h" + +/** +@file thread.h +@brief Thread API + +The functions in thread.c have for goal to manage mutex, conditions, thread +creation and thread pools that accept jobs. +*/ + +/** @defgroup THREAD THREAD - Mutex, conditions, threads and thread pools */ +/*@{*/ + +/** @name Mutex */ +/*@{*/ + +/** Opaque type for a mutex */ +typedef struct opj_mutex_t opj_mutex_t; + +/** Creates a mutex. + * @return the mutex or NULL in case of error (can for example happen if the library + * is built without thread support) + */ +opj_mutex_t* opj_mutex_create(void); + +/** Lock/acquire the mutex. + * @param mutex the mutex to acquire. + */ +void opj_mutex_lock(opj_mutex_t* mutex); + +/** Unlock/release the mutex. + * @param mutex the mutex to release. + */ +void opj_mutex_unlock(opj_mutex_t* mutex); + +/** Destroy a mutex + * @param mutex the mutex to destroy. + */ +void opj_mutex_destroy(opj_mutex_t* mutex); + +/*@}*/ + +/** @name Condition */ +/*@{*/ + +/** Opaque type for a condition */ +typedef struct opj_cond_t opj_cond_t; + +/** Creates a condition. + * @return the condition or NULL in case of error (can for example happen if the library + * is built without thread support) + */ +opj_cond_t* opj_cond_create(void); + +/** Wait for the condition to be signaled. + * The semantics is the same as the POSIX pthread_cond_wait. + * The provided mutex *must* be acquired before calling this function, and + * released afterwards. + * The mutex will be released by this function while it must wait for the condition + * and reacquired afterwards. + * In some particular situations, the function might return even if the condition is not signaled + * with opj_cond_signal(), hence the need to check with an application level + * mechanism. + * + * Waiting thread : + * \code + * opj_mutex_lock(mutex); + * while( !some_application_level_condition ) + * { + * opj_cond_wait(cond, mutex); + * } + * opj_mutex_unlock(mutex); + * \endcode + * + * Signaling thread : + * \code + * opj_mutex_lock(mutex); + * some_application_level_condition = TRUE; + * opj_cond_signal(cond); + * opj_mutex_unlock(mutex); + * \endcode + * + * @param cond the condition to wait. + * @param mutex the mutex (in acquired state before calling this function) + */ +void opj_cond_wait(opj_cond_t* cond, opj_mutex_t* mutex); + +/** Signal waiting threads on a condition. + * One of the thread waiting with opj_cond_wait() will be waken up. + * It is strongly advised that this call is done with the mutex that is used + * by opj_cond_wait(), in a acquired state. + * @param cond the condition to signal. + */ +void opj_cond_signal(opj_cond_t* cond); + +/** Destroy a condition + * @param cond the condition to destroy. + */ +void opj_cond_destroy(opj_cond_t* cond); + +/*@}*/ + +/** @name Thread */ +/*@{*/ + +/** Opaque type for a thread handle */ +typedef struct opj_thread_t opj_thread_t; + +/** User function to execute in a thread + * @param user_data user data provided with opj_thread_create() + */ +typedef void (*opj_thread_fn)(void* user_data); + +/** Creates a new thread. + * @param thread_fn Function to run in the new thread. + * @param user_data user data provided to the thread function. Might be NULL. + * @return a thread handle or NULL in case of failure (can for example happen if the library + * is built without thread support) + */ +opj_thread_t* opj_thread_create(opj_thread_fn thread_fn, void* user_data); + +/** Wait for a thread to be finished and release associated resources to the + * thread handle. + * @param thread the thread to wait for being finished. + */ +void opj_thread_join(opj_thread_t* thread); + +/*@}*/ + +/** @name Thread local storage */ +/*@{*/ +/** Opaque type for a thread local storage */ +typedef struct opj_tls_t opj_tls_t; + +/** Get a thread local value corresponding to the provided key. + * @param tls thread local storage handle + * @param key key whose value to retrieve. + * @return value associated with the key, or NULL is missing. + */ +void* opj_tls_get(opj_tls_t* tls, int key); + +/** Type of the function used to free a TLS value */ +typedef void (*opj_tls_free_func)(void* value); + +/** Set a thread local value corresponding to the provided key. + * @param tls thread local storage handle + * @param key key whose value to set. + * @param value value to set (may be NULL). + * @param free_func function to call currently installed value. + * @return OPJ_TRUE if successful. + */ +OPJ_BOOL opj_tls_set(opj_tls_t* tls, int key, void* value, + opj_tls_free_func free_func); + +/*@}*/ + +/** @name Thread pool */ +/*@{*/ + +/** Opaque type for a thread pool */ +typedef struct opj_thread_pool_t opj_thread_pool_t; + +/** Create a new thread pool. + * num_thread must nominally be >= 1 to create a real thread pool. If num_threads + * is negative or null, then a dummy thread pool will be created. All functions + * operating on the thread pool will work, but job submission will be run + * synchronously in the calling thread. + * + * @param num_threads the number of threads to allocate for this thread pool. + * @return a thread pool handle, or NULL in case of failure (can for example happen if the library + * is built without thread support) + */ +opj_thread_pool_t* opj_thread_pool_create(int num_threads); + +/** User function to execute in a thread + * @param user_data user data provided with opj_thread_create() + * @param tls handle to thread local storage + */ +typedef void (*opj_job_fn)(void* user_data, opj_tls_t* tls); + + +/** Submit a new job to be run by one of the thread in the thread pool. + * The job ( thread_fn, user_data ) will be added in the queue of jobs managed + * by the thread pool, and run by the first thread that is no longer busy. + * + * @param tp the thread pool handle. + * @param job_fn Function to run. Must not be NULL. + * @param user_data User data provided to thread_fn. + * @return OPJ_TRUE if the job was successfully submitted. + */ +OPJ_BOOL opj_thread_pool_submit_job(opj_thread_pool_t* tp, opj_job_fn job_fn, + void* user_data); + +/** Wait that no more than max_remaining_jobs jobs are remaining in the queue of + * the thread pool. The aim of this function is to avoid submitting too many + * jobs while the thread pool cannot cope fast enough with them, which would + * result potentially in out-of-memory situations with too many job descriptions + * being queued. + * + * @param tp the thread pool handle + * @param max_remaining_jobs maximum number of jobs allowed to be queued without waiting. + */ +void opj_thread_pool_wait_completion(opj_thread_pool_t* tp, + int max_remaining_jobs); + +/** Return the number of threads associated with the thread pool. + * + * @param tp the thread pool handle. + * @return number of threads associated with the thread pool. + */ +int opj_thread_pool_get_thread_count(opj_thread_pool_t* tp); + +/** Destroy a thread pool. + * @param tp the thread pool handle. + */ +void opj_thread_pool_destroy(opj_thread_pool_t* tp); + +/*@}*/ + +/*@}*/ + +#endif /* THREAD_H */ diff --git a/client/deps/openjpeg/tls_keys.h b/client/deps/openjpeg/tls_keys.h new file mode 100644 index 000000000..23f847541 --- /dev/null +++ b/client/deps/openjpeg/tls_keys.h @@ -0,0 +1,37 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2016, Even Rouault + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. + */ + +#ifndef OPJ_TLS_KEYS_H +#define OPJ_TLS_KEYS_H + +#define OPJ_TLS_KEY_T1 0 + +#endif /* OPJ_TLS_KEY_H */ diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index f9546aa1f..d097569c1 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1531,8 +1531,21 @@ static int emrtd_print_image(const char *title, uint8_t *data, size_t datalen) { bool found = false; size_t offset = 0; for (offset = 0; offset < datalen - 6; offset++) { - if ((data[offset] == 0xFF && memcmp(jpeg_header, data + offset, 4) == 0) || - (data[offset] == 0x00 && memcmp(jpeg2k_header, data + offset, 6) == 0)) { + + if (data[offset] == 0xFF) { + // JPEG SOI + any APPn marker, JFIF (FFE0) is the common one but + // Exif (FFE1) / raw DQT (FFDB) show up as well + if (memcmp(jpeg_header, data + offset, 3) == 0) { + found = true; + break; + } + // JPEG2000 raw codestream, no JP2 container + if (memcmp(jpeg2k_cs_header, data + offset, 4) == 0) { + found = true; + break; + } + } else if (data[offset] == 0x00 && memcmp(jpeg2k_header, data + offset, 6) == 0) { + // JPEG2000 in a JP2 container found = true; break; } diff --git a/client/src/proxgui.cpp b/client/src/proxgui.cpp index b14e8100b..e6a1ffcc3 100644 --- a/client/src/proxgui.cpp +++ b/client/src/proxgui.cpp @@ -21,7 +21,8 @@ #include #include "proxguiqt.h" #include "proxmark3.h" -#include "ui.h" // for prints +#include "ui.h" // for prints +#include "imgjp2.h" // JPEG2000 static ProxGuiQT *gui = NULL; static WorkerThread *main_loop_thread = NULL; @@ -77,11 +78,33 @@ static void show_no_gui_notice(void) { // hook up picture viewer extern "C" void ShowPictureWindow(const char *title, uint8_t *data, int len) { + + if (data == NULL || len <= 0) { + return; + } + + QImage img; + // No support for jpeg2000 in Qt Image since a while... // https://doc.qt.io/qt-5/qtimageformats-index.html - QImage img = QImage::fromData(data, len); + // and the distros ship no replacement plugin, so decode it ourselves with + // the vendored openjpeg. Most eMRTD EF_DG2 portraits are jpeg2000. + if (jp2_is_jpeg2000(data, (size_t)len)) { + + int w = 0, h = 0; + uint8_t *rgb = jp2_decode_rgb(data, (size_t)len, &w, &h); + if (rgb) { + // QImage doesn't take ownership of the buffer, copy() detaches it + img = QImage(rgb, w, h, w * 3, QImage::Format_RGB888).copy(); + free(rgb); + } + + } else { + img = QImage::fromData(data, len); + } + if (img.isNull()) { - PrintAndLogEx(WARNING, "Failed to decode image ( %s ), Qt lacks support for this format (jpeg2000?)", (title) ? title : "n/a"); + PrintAndLogEx(WARNING, "Failed to decode image ( %s )", (title) ? title : "n/a"); return; }