From e3bf8781c6797a2c69aae78c27d643e11e3cad44 Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Mon, 2 Dec 2024 14:54:17 -0500 Subject: [PATCH 1/7] ENH: openjpeg: remove sources to make room for fresh import --- .../OpenJPEG/src/openjpeg/CMakeLists.txt | 107 - .../ThirdParty/OpenJPEG/src/openjpeg/bio.c | 192 - .../ThirdParty/OpenJPEG/src/openjpeg/bio.h | 126 - .../ThirdParty/OpenJPEG/src/openjpeg/cio.c | 829 -- .../ThirdParty/OpenJPEG/src/openjpeg/cio.h | 360 - .../ThirdParty/OpenJPEG/src/openjpeg/dwt.c | 878 -- .../ThirdParty/OpenJPEG/src/openjpeg/dwt.h | 118 - .../ThirdParty/OpenJPEG/src/openjpeg/event.c | 98 - .../ThirdParty/OpenJPEG/src/openjpeg/event.h | 86 - .../ThirdParty/OpenJPEG/src/openjpeg/fix.h | 60 - .../OpenJPEG/src/openjpeg/function_list.c | 149 - .../OpenJPEG/src/openjpeg/function_list.h | 130 - .../ThirdParty/OpenJPEG/src/openjpeg/image.c | 175 - .../ThirdParty/OpenJPEG/src/openjpeg/image.h | 58 - .../ThirdParty/OpenJPEG/src/openjpeg/int.h | 159 - .../ThirdParty/OpenJPEG/src/openjpeg/invert.c | 291 - .../ThirdParty/OpenJPEG/src/openjpeg/invert.h | 39 - .../ThirdParty/OpenJPEG/src/openjpeg/j2k.c | 9406 ----------------- .../ThirdParty/OpenJPEG/src/openjpeg/j2k.h | 737 -- .../OpenJPEG/src/openjpeg/j2k_lib.c | 65 - .../OpenJPEG/src/openjpeg/j2k_lib.h | 54 - .../ThirdParty/OpenJPEG/src/openjpeg/jp2.c | 2236 ---- .../ThirdParty/OpenJPEG/src/openjpeg/jp2.h | 342 - .../ThirdParty/OpenJPEG/src/openjpeg/jpt.c | 249 - .../ThirdParty/OpenJPEG/src/openjpeg/jpt.h | 83 - .../ThirdParty/OpenJPEG/src/openjpeg/mct.c | 303 - .../ThirdParty/OpenJPEG/src/openjpeg/mct.h | 130 - .../ThirdParty/OpenJPEG/src/openjpeg/mqc.c | 544 - .../ThirdParty/OpenJPEG/src/openjpeg/mqc.h | 198 - .../OpenJPEG/src/openjpeg/openjpeg.c | 908 -- .../OpenJPEG/src/openjpeg/openjpeg.h | 1080 -- .../src/openjpeg/openjpegDllConfig.h.in | 8 - .../src/openjpeg/openjpeg_mangle.h.in | 357 - .../OpenJPEG/src/openjpeg/opj_configure.h.in | 32 - .../OpenJPEG/src/openjpeg/opj_includes.h | 124 - .../OpenJPEG/src/openjpeg/opj_malloc.h | 149 - Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.c | 2000 ---- Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.h | 181 - .../OpenJPEG/src/openjpeg/profile.c | 177 - .../OpenJPEG/src/openjpeg/profile.h | 83 - .../ThirdParty/OpenJPEG/src/openjpeg/raw.c | 89 - .../ThirdParty/OpenJPEG/src/openjpeg/raw.h | 101 - Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.c | 1284 --- Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.h | 156 - .../OpenJPEG/src/openjpeg/t1_luts.h | 142 - Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.c | 1287 --- Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.h | 120 - .../ThirdParty/OpenJPEG/src/openjpeg/tcd.c | 2123 ---- .../ThirdParty/OpenJPEG/src/openjpeg/tcd.h | 344 - .../ThirdParty/OpenJPEG/src/openjpeg/tgt.c | 344 - .../ThirdParty/OpenJPEG/src/openjpeg/tgt.h | 130 - 51 files changed, 29421 deletions(-) delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/CMakeLists.txt delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/bio.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/bio.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/cio.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/cio.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/dwt.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/dwt.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/event.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/event.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/fix.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/function_list.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/function_list.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/image.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/image.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/int.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/invert.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/invert.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k_lib.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k_lib.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/jp2.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/jp2.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/jpt.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/jpt.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/mct.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/mct.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/mqc.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/mqc.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpegDllConfig.h.in delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg_mangle.h.in delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_configure.h.in delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_includes.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_malloc.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/profile.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/profile.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/raw.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/raw.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/t1_luts.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/tcd.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/tcd.h delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/tgt.c delete mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/tgt.h diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/CMakeLists.txt b/Modules/ThirdParty/OpenJPEG/src/openjpeg/CMakeLists.txt deleted file mode 100644 index e62e43eda21..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/CMakeLists.txt +++ /dev/null @@ -1,107 +0,0 @@ -PROJECT(ITK3P_OpenJPEG C) -INCLUDE_REGULAR_EXPRESSION("^.*$") - -# Defines the source code for the library -SET(OpenJPEG_SRCS - tcd.c - bio.c - cio.c - dwt.c - event.c - image.c - j2k.c - j2k_lib.c - jp2.c - jpt.c - mct.c - mqc.c - openjpeg.c - pi.c - raw.c - t1.c - tgt.c - profile.c - invert.c - function_list.c - t2.c - bio.h - cio.h - dwt.h - event.h - image.h - j2k.h - j2k_lib.h - jp2.h - jpt.h - mct.h - mqc.h - openjpeg.h - pi.h - int.h - raw.h - t1.h - t2.h - tcd.h - tgt.h - profile.h - invert.h - function_list.h -) - -# Pass proper definition to preprocessor to generate shared lib -IF(BUILD_SHARED_LIBS) - SET(OPJ_STATIC 0) - IF(WIN32) - ADD_DEFINITIONS(-DOPJ_EXPORTS) - ENDIF(WIN32) -ELSE(BUILD_SHARED_LIBS) - SET(OPJ_STATIC 1) -ENDIF(BUILD_SHARED_LIBS) - -CONFIGURE_FILE(${ITK3P_OpenJPEG_SOURCE_DIR}/openjpegDllConfig.h.in - ${ITK3P_OpenJPEG_BINARY_DIR}/openjpegDllConfig.h) - -CONFIGURE_FILE(${ITK3P_OpenJPEG_SOURCE_DIR}/opj_configure.h.in - ${ITK3P_OpenJPEG_BINARY_DIR}/opj_configure.h) - -#----------------------------------------------------------------------------- -# configure name mangling to allow multiple libraries to coexist -# peacefully -if(EXISTS ${ITK3P_OpenJPEG_SOURCE_DIR}/openjpeg_mangle.h.in) -set(MANGLE_PREFIX itk) -configure_file(${ITK3P_OpenJPEG_SOURCE_DIR}/openjpeg_mangle.h.in - ${ITK3P_OpenJPEG_BINARY_DIR}/openjpeg_mangle.h - @ONLY) -else() - file(WRITE ${ITK3P_OpenJPEG_BINARY_DIR}/openjpeg_mangle.h "/* No mangling used */\n") -endif() - -INCLUDE_DIRECTORIES("${ITK3P_OpenJPEG_BINARY_DIR}") - -# Create the library -SET(OPENJPEG_LIBRARY_NAME ${OPJ_PREFIX}openjpeg ) -ADD_LIBRARY(${OPENJPEG_LIBRARY_NAME} ${OpenJPEG_SRCS}) - -IF(UNIX) - TARGET_LINK_LIBRARIES(${OPENJPEG_LIBRARY_NAME} m) -ENDIF(UNIX) - -# Install library -IF(ITK_LIBRARY_PROPERTIES) - SET_TARGET_PROPERTIES(${OPENJPEG_LIBRARY_NAME} PROPERTIES ${ITK_LIBRARY_PROPERTIES}) -ENDIF(ITK_LIBRARY_PROPERTIES) - -INSTALL(TARGETS ${OPENJPEG_LIBRARY_NAME} - EXPORT ${ITK3P_INSTALL_EXPORT_NAME} - RUNTIME DESTINATION ${ITK3P_INSTALL_RUNTIME_DIR} COMPONENT RuntimeLibraries - LIBRARY DESTINATION ${ITK3P_INSTALL_LIBRARY_DIR} COMPONENT RuntimeLibraries - ARCHIVE DESTINATION ${ITK3P_INSTALL_ARCHIVE_DIR} COMPONENT Development - ) - -install(FILES - ${ITK3P_OpenJPEG_BINARY_DIR}/openjpegDllConfig.h - ${ITK3P_OpenJPEG_SOURCE_DIR}/openjpeg.h - ${ITK3P_OpenJPEG_BINARY_DIR}/openjpeg_mangle.h - DESTINATION ${ITK3P_INSTALL_INCLUDE_DIR} - COMPONENT Development - ) diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/bio.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/bio.c deleted file mode 100644 index 3a7c4d8e5d2..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/bio.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 "bio.h" -#include "opj_malloc.h" - -/** @defgroup BIO BIO - Individual bit input-output stream */ -/*@{*/ - -/** @name Local static functions */ -/*@{*/ - -/** -Write a bit -@param bio BIO handle -@param b Bit to write (0 or 1) -*/ -static void bio_putbit(opj_bio_t *bio, OPJ_UINT32 b); -/** -Read a bit -@param bio BIO handle -@return Returns the read bit -*/ -static OPJ_UINT32 bio_getbit(opj_bio_t *bio); -/** -Write a byte -@param bio BIO handle -@return Returns 0 if successful, returns 1 otherwise -*/ -static bool bio_byteout(opj_bio_t *bio); -/** -Read a byte -@param bio BIO handle -@return Returns 0 if successful, returns 1 otherwise -*/ -static bool bio_bytein(opj_bio_t *bio); - -/*@}*/ - -/*@}*/ - -/* -========================================================== - local functions -========================================================== -*/ - -static bool bio_byteout(opj_bio_t *bio) { - bio->buf = (bio->buf << 8) & 0xffff; - bio->ct = bio->buf == 0xff00 ? 7 : 8; - if (bio->bp >= bio->end) { - return true; - } - *bio->bp++ = bio->buf >> 8; - return false; -} - -static bool bio_bytein(opj_bio_t *bio) { - bio->buf = (bio->buf << 8) & 0xffff; - bio->ct = bio->buf == 0xff00 ? 7 : 8; - if (bio->bp >= bio->end) { - return true; - } - bio->buf |= *bio->bp++; - return false; -} - -static void bio_putbit(opj_bio_t *bio, OPJ_UINT32 b) { - if (bio->ct == 0) { - bio_byteout(bio); - } - bio->ct--; - bio->buf |= b << bio->ct; -} - -static OPJ_UINT32 bio_getbit(opj_bio_t *bio) { - if (bio->ct == 0) { - bio_bytein(bio); - } - bio->ct--; - return (bio->buf >> bio->ct) & 1; -} - -/* -========================================================== - Bit Input/Output interface -========================================================== -*/ - -opj_bio_t* bio_create(void) { - opj_bio_t *bio = (opj_bio_t*)opj_malloc(sizeof(opj_bio_t)); - return bio; -} - -void bio_destroy(opj_bio_t *bio) { - if(bio) { - opj_free(bio); - } -} - -OPJ_UINT32 bio_numbytes(opj_bio_t *bio) { - return (OPJ_UINT32)( bio->bp - bio->start ); -} - -void 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 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 bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n) { - OPJ_INT32 i; - for (i = n - 1; i != -1 ; --i) { - OPJ_UINT32 j = i; - bio_putbit(bio, (v >> j) & 1); - } -} - -OPJ_UINT32 bio_read(opj_bio_t *bio, OPJ_UINT32 n) { - OPJ_INT32 i; - OPJ_UINT32 v; - v = 0; - for (i = n - 1; i != -1 ; --i) { - OPJ_UINT32 j = i; - v += bio_getbit(bio) << j; - } - return v; -} - -bool bio_flush(opj_bio_t *bio) { - bio->ct = 0; - if (bio_byteout(bio)) { - return true; - } - if (bio->ct == 7) { - bio->ct = 0; - if (bio_byteout(bio)) { - return true; - } - } - return false; -} - -bool bio_inalign(opj_bio_t *bio) { - bio->ct = 0; - if ((bio->buf & 0xff) == 0xff) { - if (bio_bytein(bio)) { - return true; - } - bio->ct = 0; - } - return false; -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/bio.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/bio.h deleted file mode 100644 index 127a3e4bc99..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/bio.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __BIO_H -#define __BIO_H -/** -@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. -*/ -#include "openjpeg.h" -/** @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* bio_create(void); -/** -Destroy a previously created BIO handle -@param bio BIO handle to destroy -*/ -void bio_destroy(opj_bio_t *bio); -/** -Number of bytes written. -@param bio BIO handle -@return Returns the number of bytes written -*/ -OPJ_UINT32 bio_numbytes(opj_bio_t *bio); -/** -Init encoder -@param bio BIO handle -@param bp Output buffer -@param len Output buffer length -*/ -void 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 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 bio_write(opj_bio_t *bio, OPJ_UINT32 v, OPJ_UINT32 n); -/** -Read bits -@param bio BIO handle -@param n Number of bits to read -@return Returns the corresponding read number -*/ -OPJ_UINT32 bio_read(opj_bio_t *bio, OPJ_UINT32 n); -/** -Flush bits -@param bio BIO handle -@return Returns 1 if successful, returns 0 otherwise -*/ -bool bio_flush(opj_bio_t *bio); -/** -Passes the ending bits (coming from flushing) -@param bio BIO handle -@return Returns 1 if successful, returns 0 otherwise -*/ -bool bio_inalign(opj_bio_t *bio); -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __BIO_H */ - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/cio.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/cio.c deleted file mode 100644 index ceb25356bb8..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/cio.c +++ /dev/null @@ -1,829 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 "cio.h" -#include "opj_includes.h" -#include "opj_malloc.h" -#include "event.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) -{ - const OPJ_BYTE * l_data_ptr = ((const OPJ_BYTE *) &p_value) + p_nb_bytes; - assert(p_nb_bytes > 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); - memcpy(p_buffer,l_data_ptr,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 occured -*/ -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 0 && p_nb_bytes <= sizeof(OPJ_UINT32)); - *p_value = 0; - memcpy(l_data_ptr+4-p_nb_bytes,p_buffer,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 occured. - */ -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;im_buffer_size = p_size; - l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_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_e_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_e_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; -} - -/** - * Creates an abstract stream. This function does nothing except allocating memory and initializing the abstract stream. - * @return a stream object. -*/ -OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_default_create(bool l_is_input) -{ - return opj_stream_create(J2K_STREAM_CHUNK_SIZE,l_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. - */ -OPJ_API 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) - { - opj_free(l_stream->m_stored_data); - l_stream->m_stored_data = 00; - opj_free(l_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) -{ - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - if - ((!l_stream) || (! (l_stream->m_status & opj_stream_e_input))) - { - return; - } - l_stream->m_read_fn = p_function; -} - -OPJ_API 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; -} - -/** - * 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) -{ - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - if - ((!l_stream )|| (! (l_stream->m_status & opj_stream_e_output))) - { - return; - } - l_stream->m_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) -{ - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - if - (! l_stream) - { - return; - } - l_stream->m_skip_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. -*/ -OPJ_API void OPJ_CALLCONV opj_stream_set_user_data(opj_stream_t* p_stream, void * p_data) -{ - opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream; - l_stream->m_user_data = p_data; -} - -/** - * 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 occured or if the stream is at the end. - */ -OPJ_INT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_UINT32 p_size, opj_event_mgr_t * p_event_mgr) -{ - OPJ_INT32 l_read_nb_bytes = 0; - if - (p_stream->m_bytes_in_buffer >= (OPJ_INT32)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 += 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_e_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 += p_stream->m_bytes_in_buffer; - p_stream->m_bytes_in_buffer = 0; - return l_read_nb_bytes ? l_read_nb_bytes : -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 += 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; - } - - - while - (true) - { - // 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 == -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_e_end; - // end of stream - return l_read_nb_bytes ? l_read_nb_bytes : -1; - } - else if - (p_stream->m_bytes_in_buffer < (OPJ_INT32)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 += 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 += 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 == -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_e_end; - // end of stream - return l_read_nb_bytes ? l_read_nb_bytes : -1; - } - else if - (p_stream->m_bytes_in_buffer < (OPJ_INT32)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 += 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 += 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; - } - } - } -} - -/** - * Writes some bytes from 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 occured. - */ -OPJ_INT32 opj_stream_write_data (opj_stream_private_t * p_stream,const OPJ_BYTE * p_buffer,OPJ_UINT32 p_size, opj_event_mgr_t * p_event_mgr) -{ - OPJ_UINT32 l_remaining_bytes = 0; - OPJ_UINT32 l_write_nb_bytes = 0; - - if - (p_stream->m_status & opj_stream_e_error) - { - return -1; - } - - while - (true) - { - 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 += 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 += l_remaining_bytes; - } - if - (! opj_stream_flush(p_stream, p_event_mgr)) - { - return -1; - } - } - -} - -/** - * 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 the number of bytes written, or -1 if an error occured. - */ -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. - // must be signed becuse "-1" is used to indicate an error in return values. - OPJ_INT32 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 == -1) - { - p_stream->m_status |= opj_stream_e_error; - opj_event_msg(p_event_mgr, EVT_INFO, "Error on writting stream!\n"); - return 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 true; -} - -/** - * 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 occured. - */ -OPJ_SIZE_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) -{ - OPJ_SIZE_T l_skip_nb_bytes = 0; - OPJ_SIZE_T l_current_skip_nb_bytes = 0; - - if - (p_stream->m_bytes_in_buffer >= (OPJ_INT32)p_size) - { - p_stream->m_current_data += p_size; - p_stream->m_bytes_in_buffer -= 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_e_end) - { - l_skip_nb_bytes += 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_SIZE_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 += p_stream->m_bytes_in_buffer; - p_stream->m_current_data = p_stream->m_stored_data; - p_size -= p_stream->m_bytes_in_buffer; - p_stream->m_bytes_in_buffer = 0; - } - - 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_SIZE_T) -1) - { - opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); - p_stream->m_status |= opj_stream_e_end; - p_stream->m_byte_offset += l_skip_nb_bytes; - // end if stream - return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_SIZE_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; -} - -/** - * 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 occured. - */ -OPJ_SIZE_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) -{ - bool l_is_written = 0; - OPJ_SIZE_T l_current_skip_nb_bytes = 0; - OPJ_SIZE_T l_skip_nb_bytes = 0; - - if - (p_stream->m_status & opj_stream_e_error) - { - return (OPJ_SIZE_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_e_error; - p_stream->m_bytes_in_buffer = 0; - p_stream->m_current_data = p_stream->m_current_data; - return (OPJ_SIZE_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_SIZE_T)-1) - { - opj_event_msg(p_event_mgr, EVT_INFO, "Stream error!\n"); - p_stream->m_status |= opj_stream_e_error; - p_stream->m_byte_offset += l_skip_nb_bytes; - // end if stream - return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_SIZE_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; -} - -/** - * 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_SIZE_T opj_stream_tell (const opj_stream_private_t * p_stream) -{ - return p_stream->m_byte_offset; -} - -/** - * 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 occured. - */ -OPJ_SIZE_T opj_stream_skip (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr) -{ - return p_stream->m_opj_skip(p_stream,p_size,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 occured. - */ -bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, opj_event_mgr_t * 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_e_end; - return false; - } - else - { - // reset stream status - p_stream->m_status &= (~opj_stream_e_end); - p_stream->m_byte_offset = p_size; - - } - return true; -} - -/** - * 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 occured. - */ -bool opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_SIZE_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_e_error; - return 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_e_error; - return false; - } - else - { - p_stream->m_byte_offset = p_size; - } - return true; -} - - -/** - * 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. - */ -bool opj_stream_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr) -{ - return p_stream->m_opj_seek(p_stream,p_size,p_event_mgr); -} - -/** - * Tells if the given stream is seekable. - */ -bool opj_stream_has_seek (const opj_stream_private_t * p_stream) -{ - return p_stream->m_seek_fn != opj_stream_default_seek; -} - - - - - -OPJ_UINT32 opj_stream_default_read (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data) -{ - return (OPJ_UINT32) -1; -} -OPJ_UINT32 opj_stream_default_write (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data) -{ - return (OPJ_UINT32) -1; -} -OPJ_SIZE_T opj_stream_default_skip (OPJ_SIZE_T p_nb_bytes, void * p_user_data) -{ - return (OPJ_SIZE_T) -1; -} - -bool opj_stream_default_seek (OPJ_SIZE_T p_nb_bytes, void * p_user_data) -{ - return false; -} - - - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/cio.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/cio.h deleted file mode 100644 index 89fb6cf2764..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/cio.h +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __CIO_H -#define __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 "openjpeg.h" -#include "opj_configure.h" -struct opj_event_mgr; -/** @name Exported functions (see also openjpeg.h) */ -/*@{*/ -/* ----------------------------------------------------------------------- */ - -#if defined(OPJ_BIG_ENDIAN) - #if !defined(OPJ_LITTLE_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 - #error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not both." - #endif -#else - #if defined(OPJ_LITTLE_ENDIAN) - #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 - #else - #error "Either BIG_ENDIAN or LITTLE_ENDIAN must be #defined, but not none." - #endif -#endif - - - -typedef enum -{ - opj_stream_e_output = 0x1, - opj_stream_e_input = 0x2, - opj_stream_e_end = 0x4, - opj_stream_e_error = 0x8 -} -opj_stream_flag ; - -/** -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 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 readed 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; - - OPJ_SIZE_T (* m_opj_skip)(struct opj_stream_private * ,OPJ_SIZE_T , struct opj_event_mgr *); - - bool (* m_opj_seek) (struct opj_stream_private * , OPJ_SIZE_T , struct opj_event_mgr *); - - /** - * Number of bytes containing in the buffer. - * It is unsigned because -1 is used as an error value. - */ - OPJ_INT32 m_bytes_in_buffer; - - /** - * The number of bytes read/written. - */ - OPJ_SIZE_T m_byte_offset; - - /** - * The size of the buffer. - */ - OPJ_UINT32 m_buffer_size; - - /** - * Flags to tell the status of the stream. - */ - OPJ_UINT32 m_status; - -} -opj_stream_private_t; - - -/** - * 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 occured. - */ -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 occured -*/ -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 occured. - */ -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 occured or if the stream is at the end. - */ -OPJ_INT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_UINT32 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 occured. - */ -OPJ_INT32 opj_stream_write_data (opj_stream_private_t * p_stream,const OPJ_BYTE * p_buffer, OPJ_UINT32 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. - */ -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 occured. - */ -OPJ_SIZE_T opj_stream_skip (opj_stream_private_t * p_stream,OPJ_SIZE_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_SIZE_T opj_stream_tell (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 occured. - */ -OPJ_SIZE_T opj_stream_write_skip (opj_stream_private_t * p_stream, OPJ_SIZE_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 occured. - */ -OPJ_SIZE_T opj_stream_read_skip (opj_stream_private_t * p_stream, OPJ_SIZE_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 occured. - */ -bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_SIZE_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 occured. - */ -bool opj_stream_write_seek (opj_stream_private_t * p_stream, OPJ_SIZE_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. - */ -bool opj_stream_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr); - -/** - * Tells if the given stream is seekable. - */ -bool opj_stream_has_seek (const opj_stream_private_t * p_stream); - -OPJ_UINT32 opj_stream_default_read (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data); -OPJ_UINT32 opj_stream_default_write (void * p_buffer, OPJ_UINT32 p_nb_bytes, void * p_user_data); -OPJ_SIZE_T opj_stream_default_skip (OPJ_SIZE_T p_nb_bytes, void * p_user_data); -bool opj_stream_default_seek (OPJ_SIZE_T p_nb_bytes, void * p_user_data); - -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __CIO_H */ - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/dwt.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/dwt.c deleted file mode 100644 index c1571dca546..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/dwt.c +++ /dev/null @@ -1,878 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2007, Jonathan Ballard - * Copyright (c) 2007, Callum Lerwick - * 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. - */ - -#ifdef __SSE__ -#include -#endif - -#include "dwt.h" -#include "j2k.h" -#include "tcd.h" -#include "fix.h" -#include "opj_malloc.h" -#include "int.h" - -/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ -/*@{*/ - -#define WS(i) v->mem[(i)*2] -#define WD(i) v->mem[(1+(i)*2)] - -/** @name Local data structures */ -/*@{*/ - -typedef struct dwt_local { - OPJ_INT32* mem; - OPJ_INT32 dn; - OPJ_INT32 sn; - OPJ_INT32 cas; -} dwt_t; - -typedef union { - OPJ_FLOAT32 f[4]; -} v4; - -typedef struct v4dwt_local { - v4* wavelet ; - OPJ_INT32 dn ; - OPJ_INT32 sn ; - OPJ_INT32 cas ; -} v4dwt_t ; - -static const OPJ_FLOAT32 dwt_alpha = 1.586134342f; // 12994 -static const OPJ_FLOAT32 dwt_beta = 0.052980118f; // 434 -static const OPJ_FLOAT32 dwt_gamma = -0.882911075f; // -7233 -static const OPJ_FLOAT32 delta = -0.443506852f; // -3633 - -static const OPJ_FLOAT32 K = 1.230174105f; // 10078 -/* FIXME: What is this constant? */ -static const OPJ_FLOAT32 c13318 = 1.625732422f; - -/*@}*/ - -/** -Virtual function type for wavelet transform in 1-D -*/ -typedef void (*DWT1DFN)(dwt_t* v); - -/** @name Local static functions */ -/*@{*/ - -/** -Forward lazy transform (horizontal) -*/ -static void dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); -/** -Forward lazy transform (vertical) -*/ -static void dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas); -/** -Inverse lazy transform (horizontal) -*/ -static void dwt_interleave_h(dwt_t* h, OPJ_INT32 *a); -/** -Inverse lazy transform (vertical) -*/ -static void dwt_interleave_v(dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x); -/** -Forward 5-3 wavelet transform in 1-D -*/ -static void dwt_encode_1(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); -/** -Inverse 5-3 wavelet transform in 1-D -*/ -static void dwt_decode_1(dwt_t *v); -/** -Forward 9-7 wavelet transform in 1-D -*/ -static void dwt_encode_1_real(OPJ_INT32 *a, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas); -/** -Explicit calculation of the Quantization Stepsizes -*/ -static void dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_stepsize_t *bandno_stepsize); -/** -Inverse wavelet transform in 2-D. -*/ -static bool dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT1DFN fn); - -static OPJ_UINT32 dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i); - -static bool dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) ); -/*@}*/ - -/*@}*/ - -#define S(i) a[(i)*2] -#define D(i) a[(1+(i)*2)] -#define S_(i) ((i)<0?S(0):((i)>=sn?S(sn-1):S(i))) -#define D_(i) ((i)<0?D(0):((i)>=dn?D(dn-1):D(i))) -/* new */ -#define SS_(i) ((i)<0?S(0):((i)>=dn?S(dn-1):S(i))) -#define DD_(i) ((i)<0?D(0):((i)>=sn?D(sn-1):D(i))) - -/* */ -/* This table contains the norms of the 5-3 wavelets for different bands. */ -/* */ -static const OPJ_FLOAT64 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. */ -/* */ -static const OPJ_FLOAT64 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 dwt_deinterleave_h(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 cas) { - OPJ_INT32 i; - - OPJ_INT32 * l_dest = b; - OPJ_INT32 * l_src = a+cas; - for - (i=0; i */ -/* Forward lazy transform (vertical). */ -/* */ -static void dwt_deinterleave_v(OPJ_INT32 *a, OPJ_INT32 *b, OPJ_INT32 dn, OPJ_INT32 sn, OPJ_INT32 x, OPJ_INT32 cas) { - OPJ_INT32 i = sn; - OPJ_INT32 * l_dest = b; - OPJ_INT32 * l_src = a+cas; - - while - (i--) - { - *l_dest = *l_src; - l_dest += x; - l_src += 2; - /* b[i*x]=a[2*i+cas]; */ - } - l_dest = b + sn * x; - l_src = a + 1 - cas; - - i = dn; - while - (i--) - { - *l_dest = *l_src; - l_dest += x; - l_src += 2; - /*b[(sn+i)*x]=a[(2*i+1-cas)];*/ - } -} - -/* */ -/* Inverse lazy transform (horizontal). */ -/* */ -static void dwt_interleave_h(dwt_t* h, OPJ_INT32 *a) { - 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 dwt_interleave_v(dwt_t* v, OPJ_INT32 *a, OPJ_INT32 x) { - 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 * x); - bi = v->mem + 1 - v->cas; - i = v->dn ; - while( i-- ) { - *bi = *ai; - bi += 2; - ai += x; - } -} - - -/* */ -/* Forward 5-3 wavelet transform in 1-D. */ -/* */ -static void dwt_encode_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 < dn; i++) D(i) -= (S_(i) + S_(i + 1)) >> 1; - for (i = 0; i < sn; i++) S(i) += (D_(i - 1) + D_(i) + 2) >> 2; - } - } else { - if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */ - S(0) *= 2; - else { - for (i = 0; i < dn; i++) S(i) -= (DD_(i) + DD_(i - 1)) >> 1; - for (i = 0; i < sn; i++) D(i) += (SS_(i) + SS_(i + 1) + 2) >> 2; - } - } -} - -/* */ -/* Inverse 5-3 wavelet transform in 1-D. */ -/* */ -static void 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++) S(i) -= (D_(i - 1) + D_(i) + 2) >> 2; - for (i = 0; i < dn; i++) D(i) += (S_(i) + S_(i + 1)) >> 1; - } - } else { - if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */ - S(0) /= 2; - else { - for (i = 0; i < sn; i++) D(i) -= (SS_(i) + SS_(i + 1) + 2) >> 2; - for (i = 0; i < dn; i++) S(i) += (DD_(i) + DD_(i - 1)) >> 1; - } - } -} - -/* */ -/* Inverse 5-3 wavelet transform in 1-D. */ -/* */ -static void dwt_decode_1(dwt_t *v) { - dwt_decode_1_(v->mem, v->dn, v->sn, v->cas); -} - -/* */ -/* Forward 9-7 wavelet transform in 1-D. */ -/* */ -static void dwt_encode_1_real(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 < dn; i++) - D(i) -= fix_mul(S_(i) + S_(i + 1), 12993); - for (i = 0; i < sn; i++) - S(i) -= fix_mul(D_(i - 1) + D_(i), 434); - for (i = 0; i < dn; i++) - D(i) += fix_mul(S_(i) + S_(i + 1), 7233); - for (i = 0; i < sn; i++) - S(i) += fix_mul(D_(i - 1) + D_(i), 3633); - for (i = 0; i < dn; i++) - D(i) = fix_mul(D(i), 5038); /*5038 */ - for (i = 0; i < sn; i++) - S(i) = fix_mul(S(i), 6659); /*6660 */ - } - } else { - if ((sn > 0) || (dn > 1)) { /* NEW : CASE ONE ELEMENT */ - for (i = 0; i < dn; i++) - S(i) -= fix_mul(DD_(i) + DD_(i - 1), 12993); - for (i = 0; i < sn; i++) - D(i) -= fix_mul(SS_(i) + SS_(i + 1), 434); - for (i = 0; i < dn; i++) - S(i) += fix_mul(DD_(i) + DD_(i - 1), 7233); - for (i = 0; i < sn; i++) - D(i) += fix_mul(SS_(i) + SS_(i + 1), 3633); - for (i = 0; i < dn; i++) - S(i) = fix_mul(S(i), 5038); /*5038 */ - for (i = 0; i < sn; i++) - D(i) = fix_mul(D(i), 6659); /*6660 */ - } - } -} - -static void dwt_encode_stepsize(OPJ_INT32 stepsize, OPJ_INT32 numbps, opj_stepsize_t *bandno_stepsize) { - OPJ_INT32 p, n; - p = int_floorlog2(stepsize) - 13; - n = 11 - int_floorlog2(stepsize); - bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff; - bandno_stepsize->expn = numbps - p; -} - -/* -========================================================== - DWT interface -========================================================== -*/ - -/* */ -/* Forward 5-3 wavelet transform in 2-D. */ -/* */ -INLINE bool dwt_encode_procedure(opj_tcd_tilecomp_t * tilec,void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) ) -{ - OPJ_INT32 i, j, k; - OPJ_INT32 *a = 00; - OPJ_INT32 *aj = 00; - OPJ_INT32 *bj = 00; - OPJ_INT32 w, l; - - OPJ_INT32 rw; /* width of the resolution level computed */ - OPJ_INT32 rh; /* height of the resolution level computed */ - OPJ_INT32 l_data_size; - - opj_tcd_resolution_t * l_cur_res = 0; - opj_tcd_resolution_t * l_last_res = 0; - - w = tilec->x1-tilec->x0; - l = tilec->numresolutions-1; - a = tilec->data; - - l_cur_res = tilec->resolutions + l; - l_last_res = l_cur_res - 1; - - rw = l_cur_res->x1 - l_cur_res->x0; - rh = l_cur_res->y1 - l_cur_res->y0; - - l_data_size = dwt_max_resolution( tilec->resolutions,tilec->numresolutions) * sizeof(OPJ_INT32); - bj = (OPJ_INT32*)opj_malloc(l_data_size); - if - (! bj) - { - return false; - } - i = l; - - while - (i--) - { - OPJ_INT32 rw1; /* width of the resolution level once lower than computed one */ - OPJ_INT32 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 = l_cur_res->x1 - l_cur_res->x0; - rh = l_cur_res->y1 - l_cur_res->y0; - rw1 = l_last_res->x1 - l_last_res->x0; - rh1 = l_last_res->y1 - l_last_res->y0; - - cas_row = l_cur_res->x0 & 1; - cas_col = l_cur_res->y0 & 1; - - sn = rh1; - dn = rh - rh1; - for - (j = 0; j < rw; ++j) - { - aj = a + j; - for - (k = 0; k < rh; ++k) - { - bj[k] = aj[k*w]; - } - (*p_function) (bj, dn, sn, cas_col); - dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); - } - sn = rw1; - dn = rw - rw1; - for (j = 0; j < rh; j++) - { - aj = a + j * w; - for (k = 0; k < rw; k++) bj[k] = aj[k]; - (*p_function) (bj, dn, sn, cas_row); - dwt_deinterleave_h(bj, aj, dn, sn, cas_row); - } - l_cur_res = l_last_res; - --l_last_res; - } - opj_free(bj); - return true; -} -/* Forward 5-3 wavelet transform in 2-D. */ -/* */ -bool dwt_encode(opj_tcd_tilecomp_t * tilec) -{ - return dwt_encode_procedure(tilec,dwt_encode_1); -} - -/* */ -/* Inverse 5-3 wavelet transform in 2-D. */ -/* */ -bool dwt_decode(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) { - return dwt_decode_tile(tilec, numres, &dwt_decode_1); -} - - -/* */ -/* Get gain of 5-3 wavelet transform. */ -/* */ -OPJ_UINT32 dwt_getgain(OPJ_UINT32 orient) { - if (orient == 0) - return 0; - if (orient == 1 || orient == 2) - return 1; - return 2; -} - -/* */ -/* Get norm of 5-3 wavelet. */ -/* */ -OPJ_FLOAT64 dwt_getnorm(OPJ_UINT32 level, OPJ_UINT32 orient) { - return dwt_norms[orient][level]; -} - -/* */ -/* Forward 9-7 wavelet transform in 2-D. */ -/* */ -bool dwt_encode_real(opj_tcd_tilecomp_t * tilec) -{ - return dwt_encode_procedure(tilec,dwt_encode_1_real); -} - - - -/* */ -/* Get gain of 9-7 wavelet transform. */ -/* */ -OPJ_UINT32 dwt_getgain_real(OPJ_UINT32 orient) { - (void)orient; - return 0; -} - -/* */ -/* Get norm of 9-7 wavelet. */ -/* */ -OPJ_FLOAT64 dwt_getnorm_real(OPJ_UINT32 level, OPJ_UINT32 orient) { - return dwt_norms_real[orient][level]; -} - -void 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 = dwt_norms_real[orient][level]; - stepsize = (1 << (gain)) / norm; - } - dwt_encode_stepsize((OPJ_INT32) floor(stepsize * 8192.0), prec + gain, &tccp->stepsizes[bandno]); - } -} - - -/* */ -/* Determine maximum computed resolution level for inverse wavelet transform */ -/* */ -static OPJ_UINT32 dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i) { - OPJ_UINT32 mr = 0; - OPJ_UINT32 w; - while( --i ) { - ++r; - if( mr < ( w = r->x1 - r->x0 ) ) - mr = w ; - if( mr < ( w = r->y1 - r->y0 ) ) - mr = w ; - } - return mr ; -} - - -/* */ -/* Inverse wavelet transform in 2-D. */ -/* */ -static bool dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres, DWT1DFN dwt_1D) { - dwt_t h; - dwt_t v; - - opj_tcd_resolution_t* tr = tilec->resolutions; - - OPJ_UINT32 rw = tr->x1 - tr->x0; /* width of the resolution level computed */ - OPJ_UINT32 rh = tr->y1 - tr->y0; /* height of the resolution level computed */ - - OPJ_UINT32 w = tilec->x1 - tilec->x0; - - h.mem = (OPJ_INT32*) - opj_aligned_malloc(dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32)); - if - (! h.mem) - { - return false; - } - - v.mem = h.mem; - - while( --numres) { - OPJ_INT32 * restrict tiledp = tilec->data; - OPJ_UINT32 j; - - ++tr; - h.sn = rw; - v.sn = rh; - - rw = tr->x1 - tr->x0; - rh = tr->y1 - tr->y0; - - h.dn = rw - h.sn; - h.cas = tr->x0 % 2; - - for(j = 0; j < rh; ++j) { - dwt_interleave_h(&h, &tiledp[j*w]); - (dwt_1D)(&h); - memcpy(&tiledp[j*w], h.mem, rw * sizeof(OPJ_INT32)); - } - - v.dn = rh - v.sn; - v.cas = tr->y0 % 2; - - for(j = 0; j < rw; ++j){ - OPJ_UINT32 k; - dwt_interleave_v(&v, &tiledp[j], w); - (dwt_1D)(&v); - for(k = 0; k < rh; ++k) { - tiledp[k * w + j] = v.mem[k]; - } - } - } - opj_aligned_free(h.mem); - return true; -} - -static void v4dwt_interleave_h(v4dwt_t* restrict w, OPJ_FLOAT32* restrict a, OPJ_INT32 x, OPJ_INT32 size){ - OPJ_FLOAT32* restrict bi = (OPJ_FLOAT32*) (w->wavelet + w->cas); - OPJ_INT32 count = w->sn; - OPJ_INT32 i, k; - for(k = 0; k < 2; ++k){ - for(i = 0; i < count; ++i){ - OPJ_INT32 j = i; - bi[i*8 ] = a[j]; - j += x; - if(j >= size) continue; - bi[i*8 + 1] = a[j]; - j += x; - if(j >= size) continue; - bi[i*8 + 2] = a[j]; - j += x; - if(j >= size) continue; - bi[i*8 + 3] = a[j]; - } - bi = (OPJ_FLOAT32*) (w->wavelet + 1 - w->cas); - a += w->sn; - size -= w->sn; - count = w->dn; - } -} - -static void v4dwt_interleave_v(v4dwt_t* restrict v , OPJ_FLOAT32* restrict a , OPJ_INT32 x){ - v4* restrict bi = v->wavelet + v->cas; - OPJ_INT32 i; - for(i = 0; i < v->sn; ++i){ - memcpy(&bi[i*2], &a[i*x], 4 * sizeof(OPJ_FLOAT32)); - } - a += v->sn * x; - bi = v->wavelet + 1 - v->cas; - for(i = 0; i < v->dn; ++i){ - memcpy(&bi[i*2], &a[i*x], 4 * sizeof(OPJ_FLOAT32)); - } -} - -#ifdef __SSE__ - -static void v4dwt_decode_step1_sse(v4* w, OPJ_INT32 count, const __m128 c){ - __m128* restrict vw = (__m128*) w; - OPJ_INT32 i; - for(i = 0; i < count; ++i){ - __m128 tmp = vw[i*2]; - // vw[i*2] = temp * c - vw[i*2] = _mm_mul_ps(tmp, c); - } -} - -static void v4dwt_decode_step2_sse(v4* l, v4* w, OPJ_INT32 k, OPJ_INT32 m, __m128 c){ - __m128* restrict vl = (__m128*) l; - __m128* restrict vw = (__m128*) w; - OPJ_INT32 i; - for(i = 0; i < m; ++i){ - __m128 tmp1 = vl[ 0]; - __m128 tmp2 = vw[-1]; - __m128 tmp3 = vw[ 0]; - // vw[-1] = tmp2 + ((tmp1 + tmp3) * c); - vw[-1] = _mm_add_ps( tmp2, _mm_mul_ps( _mm_add_ps( tmp1, tmp3), c ) ); - vl = vw; - vw += 2; - } - if(m >= k){ - return; - } - // c += c; - c = _mm_add_ps( c, c); - // c *= vl[0]; - c = _mm_mul_ps( c, vl[0] ); - for(; m < k; ++m){ - __m128 tmp = vw[-1]; - // vw[-1] = tmp + c; - vw[-1] = _mm_add_ps( tmp, c ); - vw += 2; - } -} - -#else - -static void v4dwt_decode_step1(v4* w, OPJ_INT32 count, const OPJ_FLOAT32 c){ - OPJ_FLOAT32* restrict fw = (OPJ_FLOAT32*) w; - OPJ_INT32 i; - for(i = 0; i < count; ++i){ - OPJ_FLOAT32 tmp1 = fw[i*8 ]; - OPJ_FLOAT32 tmp2 = fw[i*8 + 1]; - OPJ_FLOAT32 tmp3 = fw[i*8 + 2]; - OPJ_FLOAT32 tmp4 = fw[i*8 + 3]; - fw[i*8 ] = tmp1 * c; - fw[i*8 + 1] = tmp2 * c; - fw[i*8 + 2] = tmp3 * c; - fw[i*8 + 3] = tmp4 * c; - } -} - -static void v4dwt_decode_step2(v4* l, v4* w, OPJ_INT32 k, OPJ_INT32 m, OPJ_FLOAT32 c){ - OPJ_FLOAT32* restrict fl = (OPJ_FLOAT32*) l; - OPJ_FLOAT32* restrict fw = (OPJ_FLOAT32*) w; - OPJ_INT32 i; - for(i = 0; i < m; ++i){ - OPJ_FLOAT32 tmp1_1 = fl[0]; - OPJ_FLOAT32 tmp1_2 = fl[1]; - OPJ_FLOAT32 tmp1_3 = fl[2]; - OPJ_FLOAT32 tmp1_4 = fl[3]; - OPJ_FLOAT32 tmp2_1 = fw[-4]; - OPJ_FLOAT32 tmp2_2 = fw[-3]; - OPJ_FLOAT32 tmp2_3 = fw[-2]; - OPJ_FLOAT32 tmp2_4 = fw[-1]; - OPJ_FLOAT32 tmp3_1 = fw[0]; - OPJ_FLOAT32 tmp3_2 = fw[1]; - OPJ_FLOAT32 tmp3_3 = fw[2]; - OPJ_FLOAT32 tmp3_4 = fw[3]; - fw[-4] = tmp2_1 + ((tmp1_1 + tmp3_1) * c); - fw[-3] = tmp2_2 + ((tmp1_2 + tmp3_2) * c); - fw[-2] = tmp2_3 + ((tmp1_3 + tmp3_3) * c); - fw[-1] = tmp2_4 + ((tmp1_4 + tmp3_4) * c); - fl = fw; - fw += 8; - } - if(m < k){ - OPJ_FLOAT32 c1; - OPJ_FLOAT32 c2; - OPJ_FLOAT32 c3; - OPJ_FLOAT32 c4; - c += c; - c1 = fl[0] * c; - c2 = fl[1] * c; - c3 = fl[2] * c; - c4 = fl[3] * c; - for(; m < k; ++m){ - OPJ_FLOAT32 tmp1 = fw[-4]; - OPJ_FLOAT32 tmp2 = fw[-3]; - OPJ_FLOAT32 tmp3 = fw[-2]; - OPJ_FLOAT32 tmp4 = fw[-1]; - fw[-4] = tmp1 + c1; - fw[-3] = tmp2 + c2; - fw[-2] = tmp3 + c3; - fw[-1] = tmp4 + c4; - fw += 8; - } - } -} - -#endif - -/* */ -/* Inverse 9-7 wavelet transform in 1-D. */ -/* */ -static void v4dwt_decode(v4dwt_t* restrict dwt){ - OPJ_INT32 a, b; - 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__ - v4dwt_decode_step1_sse(dwt->wavelet+a, dwt->sn, _mm_set1_ps(K)); - v4dwt_decode_step1_sse(dwt->wavelet+b, dwt->dn, _mm_set1_ps(c13318)); - v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(delta)); - v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_gamma)); - v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_beta)); - v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_alpha)); -#else - v4dwt_decode_step1(dwt->wavelet+a, dwt->sn, K); - v4dwt_decode_step1(dwt->wavelet+b, dwt->dn, c13318); - v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), delta); - v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_gamma); - v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_beta); - v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_alpha); -#endif -} - -/* */ -/* Inverse 9-7 wavelet transform in 2-D. */ -/* */ -bool dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, OPJ_UINT32 numres){ - v4dwt_t h; - v4dwt_t v; - - opj_tcd_resolution_t* res = tilec->resolutions; - - OPJ_UINT32 rw = res->x1 - res->x0; /* width of the resolution level computed */ - OPJ_UINT32 rh = res->y1 - res->y0; /* height of the resolution level computed */ - - OPJ_UINT32 w = tilec->x1 - tilec->x0; - - h.wavelet = (v4*) opj_aligned_malloc((dwt_max_resolution(res, numres)+5) * sizeof(v4)); - v.wavelet = h.wavelet; - - while( --numres) { - OPJ_FLOAT32 * restrict aj = (OPJ_FLOAT32*) tilec->data; - OPJ_UINT32 bufsize = (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0); - OPJ_INT32 j; - - h.sn = rw; - v.sn = rh; - - ++res; - - rw = res->x1 - res->x0; /* width of the resolution level computed */ - rh = res->y1 - res->y0; /* height of the resolution level computed */ - - h.dn = rw - h.sn; - h.cas = res->x0 & 1; - - for(j = rh; j > 0; j -= 4){ - v4dwt_interleave_h(&h, aj, w, bufsize); - v4dwt_decode(&h); - if(j >= 4){ - OPJ_INT32 k = rw; - while - (--k >= 0) - { - aj[k ] = h.wavelet[k].f[0]; - aj[k+w ] = h.wavelet[k].f[1]; - aj[k+w*2] = h.wavelet[k].f[2]; - aj[k+w*3] = h.wavelet[k].f[3]; - } - }else{ - OPJ_INT32 k = rw; - while - (--k >= 0) - { - switch(j) { - case 3: aj[k+w*2] = h.wavelet[k].f[2]; - case 2: aj[k+w ] = h.wavelet[k].f[1]; - case 1: aj[k ] = h.wavelet[k].f[0]; - } - } - } - aj += w*4; - bufsize -= w*4; - } - - v.dn = rh - v.sn; - v.cas = res->y0 % 2; - - aj = (OPJ_FLOAT32*) tilec->data; - for(j = rw; j > 0; j -= 4){ - v4dwt_interleave_v(&v, aj, w); - v4dwt_decode(&v); - if(j >= 4){ - OPJ_UINT32 k; - for(k = 0; k < rh; ++k){ - memcpy(&aj[k*w], &v.wavelet[k], 4 * sizeof(OPJ_FLOAT32)); - } - }else{ - OPJ_UINT32 k; - for(k = 0; k < rh; ++k){ - memcpy(&aj[k*w], &v.wavelet[k], j * sizeof(OPJ_FLOAT32)); - } - } - aj += 4; - } - } - - opj_aligned_free(h.wavelet); - return true; -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/dwt.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/dwt.h deleted file mode 100644 index 32714e4768d..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/dwt.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __DWT_H -#define __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. -*/ -#include "openjpeg.h" - -struct opj_tcd_tilecomp; -struct opj_tccp; - -/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ -/*@{*/ - - -/** @name Exported functions */ -/*@{*/ -/* ----------------------------------------------------------------------- */ -/** -Forward 5-3 wavelet tranform in 2-D. -Apply a reversible DWT transform to a component of an image. -@param tilec Tile component information (current tile) -*/ -bool dwt_encode(struct opj_tcd_tilecomp * tilec); -/** -Inverse 5-3 wavelet tranform in 2-D. -Apply a reversible inverse DWT transform to a component of an image. -@param tilec Tile component information (current tile) -@param numres Number of resolution levels to decode -*/ -bool dwt_decode(struct opj_tcd_tilecomp* tilec, OPJ_UINT32 numres); -/** -Get the gain of a subband for the reversible 5-3 DWT. -@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) -@return Returns 0 if orient = 0, returns 1 if orient = 1 or 2, returns 2 otherwise -*/ -OPJ_UINT32 dwt_getgain(OPJ_UINT32 orient); -/** -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 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 tilec Tile component information (current tile) -*/ -bool dwt_encode_real(struct opj_tcd_tilecomp * tilec); -/** -Inverse 9-7 wavelet transform in 2-D. -Apply an irreversible inverse DWT transform to a component of an image. -@param tilec Tile component information (current tile) -@param numres Number of resolution levels to decode -*/ -bool dwt_decode_real(struct opj_tcd_tilecomp* tilec, OPJ_UINT32 numres); -/** -Get the gain of a subband for the irreversible 9-7 DWT. -@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH) -@return Returns the gain of the 9-7 wavelet transform -*/ -OPJ_UINT32 dwt_getgain_real(OPJ_UINT32 orient); -/** -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 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 dwt_calc_explicit_stepsizes(struct opj_tccp * tccp, OPJ_UINT32 prec); -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __DWT_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/event.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/event.c deleted file mode 100644 index 9a52cd9b8a7..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/event.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2005, Herv� 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 "event.h" -#include "openjpeg.h" -#include "opj_includes.h" - - -/* ========================================================== - Utility functions - ==========================================================*/ - -#ifdef THIS_CODE_IS_NEVER_USED_AND_IT_IS_DECLARED_STATIC -#if !defined(_MSC_VER) && !defined(__MINGW32__) -static OPJ_CHAR* -i2a(OPJ_UINT32 i, OPJ_CHAR *a, OPJ_UINT32 r) { - if (i/r > 0) a = i2a(i/r,a,r); - *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r]; - return a+1; -} -#endif -#endif -/* ----------------------------------------------------------------------- */ - -bool opj_event_msg(opj_event_mgr_t * p_event_mgr, OPJ_INT32 event_type, const OPJ_CHAR *fmt, ...) { -#define 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 false; - } - } else { - return false; - } - - if ((fmt != 00) && (p_event_mgr != 00)) { - va_list arg; - OPJ_INT32 str_length/*, i, j*/; /* UniPG */ - OPJ_CHAR message[MSG_SIZE]; - memset(message, 0, MSG_SIZE); - /* initialize the optional parameter list */ - va_start(arg, fmt); - /* check the length of the format string */ - str_length = (OPJ_INT32)( (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt) ); - /* parse the format string and put the result in 'message' */ - vsprintf(message, fmt, arg); /* UniPG */ - /* deinitialize the optional parameter list */ - va_end(arg); - - /* output the message to the user program */ - msg_handler(message, l_data); - } - - return true; -} - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/event.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/event.h deleted file mode 100644 index f121a3458c2..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/event.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2005, Herv� 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 __EVENT_H -#define __EVENT_H - -#include "openjpeg.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) */ -/*@{*/ -/* ----------------------------------------------------------------------- */ -/** - * Writes formatted data to a string and send the string to a user callback. - * @param p_event_mgr the event manager to display messages. - * @param event_type Event type of the message - * @param fmt Format-control string (plus optionnal arguments) - * @return Returns true if successful, returns false otherwise -*/ -bool opj_event_msg(struct opj_event_mgr * p_event_mgr, OPJ_INT32 event_type, const OPJ_CHAR *fmt, ...); -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __EVENT_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/fix.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/fix.h deleted file mode 100644 index f4bb87f66e6..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/fix.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __FIX_H -#define __FIX_H - -#include "openjpeg.h" -#include "opj_includes.h" - -/** -@file fix.h -@brief Implementation of operations of specific multiplication (FIX) - -The functions in FIX.H have for goal to realize specific multiplication. -*/ -/** @defgroup FIX FIX - Implementation of operations of specific multiplication */ -/*@{*/ - -/** -Multiply two fixed-precision rational numbers. -@param a -@param b -@return Returns a * b -*/ -static INLINE int fix_mul(int a, int b) { - OPJ_INT64 temp = (OPJ_INT64) a * (OPJ_INT64) b ; - temp += temp & 4096; - return (int) (temp >> 13) ; -} - -/*@}*/ - -#endif /* __FIX_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/function_list.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/function_list.c deleted file mode 100644 index a249719c9ec..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/function_list.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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 "function_list.h" -#include "opj_includes.h" -#include "opj_malloc.h" -/** - * Default size of the validation list, if not sufficient, data will be reallocated with a double size. - */ -#define OPJ_VALIDATION_SIZE 10 - -/** - * Creates a validation list. - * - * @return the newly created validation list. - */ -opj_procedure_list_t * opj_procedure_list_create() -{ - /* memory allocation */ - opj_procedure_list_t * l_validation = (opj_procedure_list_t *) opj_malloc(sizeof(opj_procedure_list_t)); - if - (! l_validation) - { - return 00; - } - /* initialization */ - memset(l_validation,0,sizeof(opj_procedure_list_t)); - l_validation->m_nb_max_procedures = OPJ_VALIDATION_SIZE; - l_validation->m_procedures = (void**)opj_malloc( - OPJ_VALIDATION_SIZE * sizeof(opj_procedure)); - if - (! l_validation->m_procedures) - { - opj_free(l_validation); - return 00; - } - memset(l_validation->m_procedures,0,OPJ_VALIDATION_SIZE * sizeof(opj_procedure)); - return l_validation; -} - - - -/** - * Destroys a validation list. - * - * @param p_list the list to destroy. - */ -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); -} - -/** - * Adds a new validation procedure. - * - * @param p_validation_list the list of procedure to modify. - * @param p_procedure the procedure to add. - */ -bool opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure) -{ - if - (p_validation_list->m_nb_max_procedures == p_validation_list->m_nb_procedures) - { - p_validation_list->m_nb_max_procedures += OPJ_VALIDATION_SIZE; - p_validation_list->m_procedures = (void**)opj_realloc( - p_validation_list->m_procedures,p_validation_list->m_nb_max_procedures * sizeof(opj_procedure)); - if - (! p_validation_list->m_procedures) - { - p_validation_list->m_nb_max_procedures = 0; - p_validation_list->m_nb_procedures = 0; - return false; - } - } - p_validation_list->m_procedures[p_validation_list->m_nb_procedures] = p_procedure; - ++p_validation_list->m_nb_procedures; - return true; -} - -/** - * 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) -{ - return p_validation_list->m_nb_procedures; -} - -/** - * 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) -{ - return p_validation_list->m_procedures; -} - -/** - * 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) -{ - p_validation_list->m_nb_procedures = 0; -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/function_list.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/function_list.h deleted file mode 100644 index e3e39156cfa..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/function_list.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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 __FUNCTION_LIST_H -#define __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 validation validation procedure*/ -/*@{*/ - -#include "openjpeg.h" -/************************************************************************************************** - ***************************************** FORWARD DECLARATION ************************************ - **************************************************************************************************/ -struct opj_jp2; - -/** - * ARGGGG, when will the template be added to the C language ??? - * in order not to have to duplicate the code in a vast number of times, use void * and downcast - * it after => UGLY but faster and easier - * TODO : make the class template in C++, use STL vector or duplicate code for each procedure type. - */ -typedef void * opj_procedure; - -/** - * 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(); - -/** - * 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. - * - * @return true if the procedure could ne added. - */ -bool opj_procedure_list_add_procedure (opj_procedure_list_t * p_validation_list, opj_procedure p_procedure); - -/** - * 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 /* __FUNCTION_LIST_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/image.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/image.c deleted file mode 100644 index 84f9edbf814..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/image.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2005, Herv� 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 "image.h" -#include "openjpeg.h" -#include "opj_malloc.h" -#include "j2k.h" -#include "int.h" - -opj_image_t* opj_image_create0(void) { - opj_image_t *image = (opj_image_t*)opj_malloc(sizeof(opj_image_t)); - memset(image,0,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 = 00; - - image = (opj_image_t*) opj_malloc(sizeof(opj_image_t)); - if - (image) - { - memset(image,0,sizeof(opj_image_t)); - image->color_space = clrspc; - image->numcomps = numcmpts; - /* allocate memory for the per-component information */ - image->comps = (opj_image_comp_t*)opj_malloc(image->numcomps * sizeof(opj_image_comp_t)); - if - (!image->comps) - { - opj_image_destroy(image); - return 00; - } - memset(image->comps,0,image->numcomps * sizeof(opj_image_comp_t)); - /* 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 = (OPJ_INT32*) opj_calloc(comp->w * comp->h, sizeof(OPJ_INT32)); - if - (!comp->data) - { - opj_image_destroy(image); - return 00; - } - } - } - return image; -} - -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_malloc(sizeof(opj_image_t)); - if - (image) - { - memset(image,0,sizeof(opj_image_t)); - image->color_space = clrspc; - image->numcomps = numcmpts; - /* allocate memory for the per-component information */ - image->comps = (opj_image_comp_t*)opj_malloc(image->numcomps * sizeof(opj_image_comp_t)); - if - (!image->comps) - { - opj_image_destroy(image); - return 00; - } - memset(image->comps,0,image->numcomps * sizeof(opj_image_comp_t)); - /* 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; -} - -void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) { - OPJ_UINT32 i; - if - (image) - { - if - (image->comps) - { - /* image components */ - for(i = 0; i < image->numcomps; i++) { - opj_image_comp_t *image_comp = &image->comps[i]; - if(image_comp->data) { - opj_free(image_comp->data); - } - } - opj_free(image->comps); - } - opj_free(image); - } -} - -/** - * Updates the components of the image from the coding parameters. - * - * @param p_image the image to update. - * @param p_cp the coding parameters from which to update the image. - */ -void opj_image_comp_update(opj_image_t * p_image,const opj_cp_t * p_cp) -{ - OPJ_UINT32 i, l_width, l_height; - OPJ_INT32 l_x0,l_y0,l_x1,l_y1; - OPJ_INT32 l_comp_x0,l_comp_y0,l_comp_x1,l_comp_y1; - opj_image_comp_t * l_img_comp = 00; - - l_x0 = int_max(p_cp->tx0 , p_image->x0); - l_y0 = int_max(p_cp->ty0 , p_image->y0); - l_x1 = int_min(p_cp->tx0 + p_cp->tw * p_cp->tdx, p_image->x1); - l_y1 = int_min(p_cp->ty0 + p_cp->th * p_cp->tdy, p_image->y1); - - l_img_comp = p_image->comps; - for - (i = 0; i < p_image->numcomps; ++i) - { - l_comp_x0 = int_ceildiv(l_x0, l_img_comp->dx); - l_comp_y0 = int_ceildiv(l_y0, l_img_comp->dy); - l_comp_x1 = int_ceildiv(l_x1, l_img_comp->dx); - l_comp_y1 = int_ceildiv(l_y1, l_img_comp->dy); - l_width = int_ceildivpow2(l_comp_x1 - l_comp_x0, l_img_comp->factor); - l_height = int_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_x0; - l_img_comp->y0 = l_y0; - ++l_img_comp; - } -} - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/image.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/image.h deleted file mode 100644 index 0f1f1b4ab51..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/image.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2005, Herv� 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 __IMAGE_H -#define __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 -@todo this function should be removed -@return returns an empty image if successful, returns NULL otherwise -*/ -struct opj_image* opj_image_create0(void); - -/** - * Updates the components of the image from the coding parameters. - * - * @param p_image the image to update. - * @param p_cp the coding parameters from which to update the image. - */ -void opj_image_comp_update(struct opj_image * p_image,const struct opj_cp * p_cp); - -/*@}*/ - -#endif /* __IMAGE_H */ - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/int.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/int.h deleted file mode 100644 index 43e576fb8ac..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/int.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __INT_H -#define __INT_H -/** -@file int.h -@brief Implementation of operations on integers (INT) - -The functions in INT.H have for goal to realize operations on integers. -*/ -#include "openjpeg.h" -#include "opj_includes.h" -/** @defgroup INT INT - Implementation of operations on integers */ -/*@{*/ - -/** @name Exported functions (see also openjpeg.h) */ -/*@{*/ -/* ----------------------------------------------------------------------- */ -/** -Get the minimum of two integers -@return Returns a if a < b else b -*/ -static INLINE OPJ_INT32 int_min(OPJ_INT32 a, OPJ_INT32 b) { - return a < b ? a : b; -} - -/** -Get the minimum of two integers -@return Returns a if a < b else b -*/ -static INLINE OPJ_UINT32 uint_min(OPJ_UINT32 a, OPJ_UINT32 b) { - return a < b ? a : b; -} - -/** -Get the maximum of two integers -@return Returns a if a > b else b -*/ -static INLINE OPJ_INT32 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 uint_max(OPJ_UINT32 a, OPJ_UINT32 b) { - return (a > b) ? a : b; -} -/** -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 int_clamp(OPJ_INT32 a, OPJ_INT32 min, OPJ_INT32 max) { - if (a < min) - return min; - if (a > max) - return max; - return a; -} -/** -@return Get absolute value of integer -*/ -static INLINE OPJ_INT32 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 int_ceildiv(OPJ_INT32 a, OPJ_INT32 b) { - return (a + b - 1) / b; -} - -/** -Divide an integer and round upwards -@return Returns a divided by b -*/ -static INLINE OPJ_UINT32 uint_ceildiv(OPJ_UINT32 a, OPJ_UINT32 b) { - return (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 int_ceildivpow2(OPJ_INT32 a, OPJ_INT32 b) { - return (a + (1 << b) - 1) >> b; -} -/** -Divide an integer by a power of 2 and round downwards -@return Returns a divided by 2^b -*/ -static INLINE OPJ_INT32 int_floordivpow2(OPJ_INT32 a, OPJ_INT32 b) { - return a >> b; -} -/** -Get logarithm of an integer and round downwards -@return Returns log2(a) -*/ -static INLINE OPJ_INT32 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 uint_floorlog2(OPJ_UINT32 a) { - OPJ_UINT32 l; - for (l = 0; a > 1; ++l) - { - a >>= 1; - } - return l; -} -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/invert.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/invert.c deleted file mode 100644 index 4245c648615..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/invert.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * 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 "invert.h" -#include "opj_malloc.h" - - -bool opj_lupDecompose(OPJ_FLOAT32 * matrix,OPJ_UINT32 * permutations, OPJ_FLOAT32 * p_swap_area,OPJ_UINT32 n); -void opj_lupSolve(OPJ_FLOAT32 * pResult, OPJ_FLOAT32* pMatrix, OPJ_FLOAT32* pVector, OPJ_UINT32* pPermutations, OPJ_UINT32 n,OPJ_FLOAT32 * p_intermediate_data); -void opj_lupInvert (OPJ_FLOAT32 * pSrcMatrix, - OPJ_FLOAT32 * pDestMatrix, - OPJ_UINT32 n, - OPJ_UINT32 * pPermutations, - OPJ_FLOAT32 * p_src_temp, - OPJ_FLOAT32 * p_dest_temp, - OPJ_FLOAT32 * p_swap_area); - -/** - * Matrix inversion. - */ -bool opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix,OPJ_FLOAT32 * pDestMatrix, OPJ_UINT32 n) -{ - OPJ_BYTE * l_data = 00; - OPJ_UINT32 l_permutation_size = n * sizeof(OPJ_UINT32); - OPJ_UINT32 l_swap_size = n * 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 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,n)) - { - opj_free(l_data); - return false; - } - opj_lupInvert(pSrcMatrix,pDestMatrix,n,lPermutations,l_double_data,l_double_data + n,l_double_data + 2*n); - opj_free(l_data); - return true; -} - - -/** - * LUP decomposition - */ -bool opj_lupDecompose(OPJ_FLOAT32 * matrix,OPJ_UINT32 * permutations, OPJ_FLOAT32 * p_swap_area,OPJ_UINT32 n) -{ - 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 = n - 1; - OPJ_UINT32 lSwapSize = n * sizeof(OPJ_FLOAT32); - OPJ_FLOAT32 * lTmpMatrix = matrix; - OPJ_FLOAT32 * lColumnMatrix,* lDestMatrix; - OPJ_UINT32 offset = 1; - OPJ_UINT32 lStride = n-1; - - //initialize permutations - for - (i = 0; i < n; ++i) - { - *tmpPermutations++ = i; - } - - - - // now make a pivot with colum 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 < n; ++i) - { - temp = ((*lColumnMatrix > 0) ? *lColumnMatrix : -(*lColumnMatrix)); - if - (temp > p) - { - p = temp; - k2 = i; - } - // next line - lColumnMatrix += n; - } - - // a whole rest of 0 -> non singular - if - (p == 0.0) - { - return 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) * n; - 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 + n; - // take the middle element - temp = *(lDestMatrix++); - - // now compute up data (i.e. coeff up of the diagonal). - for (i = offset; i < n; ++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 < n; ++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+=n; - // next permutation element - ++tmpPermutations; - } - return true; -} - - - -/** - * LUP solving - */ -void opj_lupSolve (OPJ_FLOAT32 * pResult, OPJ_FLOAT32 * pMatrix, OPJ_FLOAT32 * pVector, OPJ_UINT32* pPermutations, OPJ_UINT32 n,OPJ_FLOAT32 * p_intermediate_data) -{ - OPJ_UINT32 i,j; - OPJ_INT32 k; - OPJ_FLOAT32 sum; - OPJ_FLOAT32 u; - OPJ_UINT32 lStride = n+1; - OPJ_FLOAT32 * lCurrentPtr; - OPJ_FLOAT32 * lIntermediatePtr; - OPJ_FLOAT32 * lDestPtr; - OPJ_FLOAT32 * lTmpMatrix; - OPJ_FLOAT32 * lLineMatrix = pMatrix; - OPJ_FLOAT32 * lBeginPtr = pResult + n - 1; - OPJ_FLOAT32 * lGeneratedData; - OPJ_UINT32 * lCurrentPermutationPtr = pPermutations; - - - lIntermediatePtr = p_intermediate_data; - lGeneratedData = p_intermediate_data + n - 1; - - for - (i = 0; i < n; ++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 += n; - } - - // we take the last point of the matrix - lLineMatrix = pMatrix + n*n - 1; - - // and we take after the last point of the destination vector - lDestPtr = pResult + n; - - for - (k = n - 1; k != -1 ; --k) - { - sum = 0.0; - lTmpMatrix = lLineMatrix; - u = *(lTmpMatrix++); - lCurrentPtr = lDestPtr--; - for - (j = k + 1; j < n; ++j) - { - // sum += matrix[k][j] * x[j] - sum += (*(lTmpMatrix++)) * (*(lCurrentPtr++)); - } - //x[k] = (y[k] - sum) / u; - *(lBeginPtr--) = (*(lGeneratedData--) - sum) / u; - lLineMatrix -= lStride; - } -} - -/** LUP inversion (call with the result of lupDecompose) - */ -void opj_lupInvert ( - OPJ_FLOAT32 * pSrcMatrix, - OPJ_FLOAT32 * pDestMatrix, - OPJ_UINT32 n, - 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 = n * sizeof(OPJ_FLOAT32); - - for - (j = 0; j < n; ++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, n , p_swap_area); - - for - (i = 0; i < n; ++i) - { - *(lCurrentPtr) = p_dest_temp[i]; - lCurrentPtr+=n; - } - } -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/invert.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/invert.h deleted file mode 100644 index a6ebe720c96..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/invert.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 __INVERT_H -#define __INVERT_H -#include "openjpeg.h" -/** - * 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. - * @return 1 if the inversion is successful, 0 if the matrix is singular. - */ -bool opj_matrix_inversion_f(OPJ_FLOAT32 * pSrcMatrix,OPJ_FLOAT32 * pDestMatrix, OPJ_UINT32 n); -#endif diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k.c deleted file mode 100644 index c0c95c14887..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k.c +++ /dev/null @@ -1,9406 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2006-2007, Parvatha Elangovan - * 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 "j2k.h" -#include "opj_malloc.h" -#include "opj_includes.h" -#include "pi.h" -#include "event.h" -#include "cio.h" -#include "int.h" -#include "tcd.h" -#include "function_list.h" -#include "invert.h" -#include "dwt.h" -#include "mct.h" -#include "image.h" - -/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */ -/*@{*/ - - -/*************************************************************************** - ********************** TYPEDEFS ******************************************* - ***************************************************************************/ -/** - * Correspondance prog order <-> string representation - */ -typedef struct j2k_prog_order -{ - OPJ_PROG_ORDER enum_prog; - OPJ_CHAR str_prog[5]; -} -j2k_prog_order_t; - -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 */ - bool (*handler) ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ); -} -opj_dec_memory_marker_handler_t; - - - -/** @name Local static functions */ -/*@{*/ -/** - * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. - * - * @param p_comp_no the component number to output. - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. - * -*/ -static bool 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 - ); - -/** - * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. - * @param p_header_data the data contained in the COM box. - * @param p_j2k the jpeg2000 codec. - * @param p_header_size the size of the data contained in the COM marker. - * @param p_manager the user event manager. -*/ -static bool j2k_read_SPCod_SPCoc( - opj_j2k_t *p_j2k, - OPJ_UINT32 compno, - OPJ_BYTE * p_header_data, - OPJ_UINT32 * p_header_size, - struct opj_event_mgr * p_manager - ); - -/** - * Gets the size taken by writting a SPCod or SPCoc for the given tile and component. - * - * @param p_tile_no the tile indix. - * @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 j2k_get_SPCod_SPCoc_size ( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_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 bool 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 - ); - -/** - * Reads 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 bool j2k_read_SQcd_SQcc( - opj_j2k_t *p_j2k, - OPJ_UINT32 compno, - OPJ_BYTE * p_header_data, - OPJ_UINT32 * p_header_size, - struct opj_event_mgr * p_manager - ); -/** - * Updates the Tile Length Marker. - */ -static void j2k_update_tlm ( - opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_part_size); - -/** - * Gets the size taken by writting SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. - * - * @param p_tile_no the tile indix. - * @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 j2k_get_SQcd_SQcc_size ( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no - - ); - -/** - * Copies the tile component parameters of all the component from the first tile component. - * - * @param p_j2k the J2k codec. - */ -static void j2k_copy_tile_component_parameters( - 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 bool j2k_write_soc( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Reads a SOC marker (Start of Codestream) - * @param p_header_data the data contained in the SOC box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the SOC marker. - * @param p_manager the user event manager. -*/ -static bool j2k_read_soc( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Writes the SIZ marker (image and tile size) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -static bool j2k_write_siz( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * 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 bool j2k_write_mct_data_group( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); - -/** - * Reads a SIZ marker (image and tile size) - * @param p_header_data the data contained in the SIZ box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the SIZ marker. - * @param p_manager the user event manager. -*/ -static bool j2k_read_siz ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_write_com( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Reads a COM marker (comments) - * @param p_header_data the data contained in the COM box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the COM marker. - * @param p_manager the user event manager. -*/ -static bool j2k_read_com ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_write_cod( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Reads a COD marker (Coding Styke 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 bool j2k_read_cod ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ); - -/** - * Writes the COC marker (Coding style component) - * - * @param p_comp_number 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 bool j2k_write_coc( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_number, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); - -/** - * Writes the COC marker (Coding style 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 void j2k_write_coc_in_memory( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - struct opj_event_mgr * p_manager - ); -/** - * Gets the maximum size taken by a coc. - * - * @param p_j2k the jpeg2000 codec to use. - */ -static OPJ_UINT32 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 bool j2k_read_coc ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ); - -/** - * Writes the QCD marker (quantization default) - * - * @param p_comp_number 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 bool j2k_write_qcd( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 bool j2k_read_qcd ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ); -/** - * 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 bool j2k_write_qcc( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * 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 void j2k_write_qcc_in_memory( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - struct opj_event_mgr * p_manager - ); -/** - * Gets the maximum size taken by a qcc. - */ -static OPJ_UINT32 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 bool j2k_read_qcc( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_write_poc( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 bool j2k_write_updated_tlm( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 void j2k_write_poc_in_memory( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - struct opj_event_mgr * p_manager - ); - -/** - * Gets the maximum size taken by the writting of a POC. - */ -static OPJ_UINT32 j2k_get_max_poc_size(opj_j2k_t *p_j2k); - -/** - * Gets the maximum size taken by the toc headers of all the tile parts of any given tile. - */ -static OPJ_UINT32 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 j2k_get_specific_header_sizes(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 bool j2k_read_poc ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ); -/** - * 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 bool j2k_read_crg ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_read_tlm ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_read_plm ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_read_plt ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ); -/** - * 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 bool j2k_read_ppm ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_read_ppt ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_write_tlm( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Writes the SOT marker (Start of tile-part) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -static bool j2k_write_sot( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - const struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 bool j2k_read_sot ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ); -/** - * Writes the SOD marker (Start of data) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -static bool j2k_write_sod( - opj_j2k_t *p_j2k, - struct opj_tcd * p_tile_coder, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - const struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Reads a SOD marker (Start Of Data) - * - * @param p_header_data the data contained in the SOD box. - * @param p_j2k the jpeg2000 codec. - * @param p_header_size the size of the data contained in the SOD marker. - * @param p_manager the user event manager. -*/ -static bool j2k_read_sod ( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Writes the RGN marker (Region Of Interest) - * - * @param p_tile_no the tile to output - * @param p_comp_no 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 bool j2k_write_rgn( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 bool j2k_read_rgn ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_write_eoc( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); - -/** - * Copies the tile component parameters of all the component from the first tile component. - * - * @param p_j2k the J2k codec. - */ -static void j2k_copy_tile_quantization_parameters( - opj_j2k_t *p_j2k - ); - -#ifdef THIS_CODE_IS_NEVER_USED_AND_IT_IS_DECLARED_STATIC -/** - * Reads a EOC marker (End Of Codestream) - * - * @param p_header_data the data contained in the SOD box. - * @param p_j2k the jpeg2000 codec. - * @param p_header_size the size of the data contained in the SOD marker. - * @param p_manager the user event manager. -*/ -static bool j2k_read_eoc ( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) ; -#endif -/** - * 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 bool j2k_init_info( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -#ifdef THIS_CODE_IS_NEVER_USED_AND_IT_IS_DECLARED_STATIC -/** - * Reads an unknown marker - * - * @param p_stream the stream object to read from. - * @param p_j2k the jpeg2000 codec. - * @param p_manager the user event manager. - * - * @return true if the marker could be deduced. -*/ -static bool j2k_read_unk ( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -#endif -/** - * 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 bool j2k_end_encoding( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 bool j2k_write_cbd( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 bool j2k_read_cbd ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager); - -/** - * Writes the MCT marker (Multiple Component Transform) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -static bool 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 - ); - -/** - * 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 bool j2k_read_mct ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ); - -/** - * Writes the MCC marker (Multiple Component Collection) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -static bool 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 - ); - -/** - * 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 bool j2k_read_mcc ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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 bool j2k_write_mco( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 bool j2k_read_mco ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ); -/** - * Writes the image components. - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -static bool j2k_write_image_components( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 bool j2k_write_regions( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 bool j2k_write_epc( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 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. - * - * @return true if the pocs are valid. - */ -static bool j2k_check_poc_val( - const opj_poc_t *p_pocs, - 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 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 bool 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 bool j2k_write_first_tile_part ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - opj_stream_private_t *p_stream, - struct opj_event_mgr * p_manager - ); -static bool j2k_write_all_tile_parts( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - opj_stream_private_t *p_stream, - struct opj_event_mgr * 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 * 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 j2k_tcp_destroy (opj_tcp_t *p_tcp); - -static void j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data); - -/** - * Destroys a coding parameter structure. - * - * @param p_cp the coding parameter to destroy. - */ -static void j2k_cp_destroy (opj_cp_t *p_cp); - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -static void j2k_setup_encoding_validation (opj_j2k_t *p_j2k); - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -static void j2k_setup_decoding_validation (opj_j2k_t *p_j2k); - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -static void j2k_setup_end_compress (opj_j2k_t *p_j2k); - -/** - * Creates a tile-coder decoder. - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -static bool j2k_create_tcd( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); - -/** - * Excutes 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 bool 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 bool j2k_update_rates( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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. - */ -bool j2k_encoding_validation ( - opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ); -/** - * The read header procedure. - */ -bool j2k_read_header_procedure( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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. - */ -bool j2k_decoding_validation ( - opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ); -/** - * Reads the tiles. - */ -bool j2k_decode_tiles ( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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. - */ -bool 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. - */ -bool 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. - */ -bool j2k_build_encoder ( - 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. - */ -bool 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. - */ -bool j2k_destroy_header_memory ( - opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ); - -/** - * Sets up the procedures to do on writting header. Developpers wanting to extend the library can add their own writting procedures. - */ -void j2k_setup_header_writting (opj_j2k_t *p_j2k); - -/** - * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures. - */ -void j2k_setup_header_reading (opj_j2k_t *p_j2k); - -/** - * Writes a tile. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -static bool j2k_post_write_tile ( - opj_j2k_t * p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ); - -static bool 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 bool j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data); - -static bool j2k_add_mct(opj_tcp_t * p_tcp,opj_image_t * p_image, OPJ_UINT32 p_index); -/** - * 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 bool j2k_get_end_header( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); - -static void j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void j2k_read_int32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void j2k_read_float32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void j2k_read_float64_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); - -static void j2k_read_int16_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void j2k_read_int32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void j2k_read_float32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void j2k_read_float64_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); - -static void j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); -static void j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); - - - -/*@}*/ - -/*@}*/ - -/* ----------------------------------------------------------------------- */ - - - -/**************************************************************************** - ********************* CONSTANTS ******************************************** - ****************************************************************************/ - - - - -/** - * List of progression orders. - */ -const j2k_prog_order_t j2k_prog_order_list [] = -{ - {CPRL, "CPRL"}, - {LRCP, "LRCP"}, - {PCRL, "PCRL"}, - {RLCP, "RLCP"}, - {RPCL, "RPCL"}, - {(OPJ_PROG_ORDER)-1, ""} -}; - -const OPJ_UINT32 MCT_ELEMENT_SIZE [] = -{ - 2, - 4, - 4, - 8 -}; - -typedef void (* j2k_mct_function) (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem); - -const j2k_mct_function j2k_mct_read_functions_to_float [] = -{ - j2k_read_int16_to_float, - j2k_read_int32_to_float, - j2k_read_float32_to_float, - j2k_read_float64_to_float -}; - -const j2k_mct_function j2k_mct_read_functions_to_int32 [] = -{ - j2k_read_int16_to_int32, - j2k_read_int32_to_int32, - j2k_read_float32_to_int32, - j2k_read_float64_to_int32 -}; - -const j2k_mct_function j2k_mct_write_functions_from_float [] = -{ - j2k_write_float_to_int16, - j2k_write_float_to_int32, - j2k_write_float_to_float, - j2k_write_float_to_float64 -}; - - - - -/*const opj_dec_stream_marker_handler_t j2k_stream_marker_handler_tab[] = -{ - {J2K_MS_SOC, J2K_DEC_STATE_MHSOC, j2k_read_soc}, - {J2K_MS_SOD, J2K_DEC_STATE_TPH, j2k_read_sod}, - {J2K_MS_EOC, J2K_DEC_STATE_TPHSOT, j2k_read_eoc}, - {J2K_MS_SOP, 0, 0}, -#ifdef USE_JPWL - {J2K_MS_EPC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_epc}, - {J2K_MS_EPB, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_epb}, - {J2K_MS_ESD, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_esd}, - {J2K_MS_RED, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_red}, -#endif -#ifdef USE_JPSEC - {J2K_MS_SEC, J2K_DEC_STATE_MH, j2k_read_sec}, - {J2K_MS_INSEC, 0, j2k_read_insec}, -#endif - - {0, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_unk} -};*/ - -const opj_dec_memory_marker_handler_t j2k_memory_marker_handler_tab [] = -{ - {J2K_MS_SOT, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPHSOT, j2k_read_sot}, - {J2K_MS_COD, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_cod}, - {J2K_MS_COC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_coc}, - {J2K_MS_RGN, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_rgn}, - {J2K_MS_QCD, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_qcd}, - {J2K_MS_QCC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_qcc}, - {J2K_MS_POC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_poc}, - {J2K_MS_SIZ, J2K_DEC_STATE_MHSIZ , j2k_read_siz}, - {J2K_MS_TLM, J2K_DEC_STATE_MH, j2k_read_tlm}, - {J2K_MS_PLM, J2K_DEC_STATE_MH, j2k_read_plm}, - {J2K_MS_PLT, J2K_DEC_STATE_TPH, j2k_read_plt}, - {J2K_MS_PPM, J2K_DEC_STATE_MH, j2k_read_ppm}, - {J2K_MS_PPT, J2K_DEC_STATE_TPH, j2k_read_ppt}, - {J2K_MS_SOP, 0, 0}, - {J2K_MS_CRG, J2K_DEC_STATE_MH, j2k_read_crg}, - {J2K_MS_COM, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_com}, - {J2K_MS_MCT, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_mct}, - {J2K_MS_CBD, J2K_DEC_STATE_MH , j2k_read_cbd}, - {J2K_MS_MCC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_mcc}, - {J2K_MS_MCO, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_mco} -#ifdef USE_JPWL - {J2K_MS_EPC, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_epc}, - {J2K_MS_EPB, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_epb}, - {J2K_MS_ESD, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_esd}, - {J2K_MS_RED, J2K_DEC_STATE_MH | J2K_DEC_STATE_TPH, j2k_read_red}, -#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 */ -}; - -void 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;ienum_prog != -1; ++po ) - { - if - (po->enum_prog == p_prg_order) - { - return po->str_prog; - } - } - return po->str_prog; -} - - - - - - - -/** - * Checks the progression order changes values. Tells if the poc given as input are valid. - * - * @param p_pocs the progression order changes. - * @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. - */ -bool j2k_check_poc_val(const opj_poc_t *p_pocs, 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 indexvalue , 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; - bool loss = false; - OPJ_UINT32 layno0 = 0; - - packet_array = (OPJ_UINT32*) opj_calloc(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 false; - } - memset(packet_array,0,step_l * p_num_layers* sizeof(OPJ_UINT32)); - if - (p_nb_pocs == 0) - { - return true; - } - - indexvalue = step_r * p_pocs->resno0; - // take each resolution for each poc - for - (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) - { - OPJ_UINT32 res_index = indexvalue + p_pocs->compno0 * step_c; - // take each comp of each resolution for each poc - for - (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) - { - OPJ_UINT32 comp_index = res_index + layno0 * step_l; - // and finally take each layer of each res of ... - for - (layno = layno0; layno < p_pocs->layno1 ; ++layno) - { - //indexvalue = step_r * resno + step_c * compno + step_l * layno; - packet_array[comp_index] = 1; - comp_index += step_l; - } - res_index += step_c; - } - indexvalue += step_r; - } - ++p_pocs; - // iterate through all the pocs - for - (i = 1; i < p_nb_pocs ; ++i) - { - OPJ_UINT32 l_last_layno1 = (p_pocs-1)->layno1 ; - layno0 = (p_pocs->layno1 > l_last_layno1)? l_last_layno1 : 0; - indexvalue = step_r * p_pocs->resno0; - // take each resolution for each poc - for - (resno = p_pocs->resno0 ; resno < p_pocs->resno1 ; ++resno) - { - OPJ_UINT32 res_index = indexvalue + p_pocs->compno0 * step_c; - // take each comp of each resolution for each poc - for - (compno = p_pocs->compno0 ; compno < p_pocs->compno1 ; ++compno) - { - OPJ_UINT32 comp_index = res_index + layno0 * step_l; - // and finally take each layer of each res of ... - for - (layno = layno0; layno < p_pocs->layno1 ; ++layno) - { - //indexvalue = step_r * resno + step_c * compno + step_l * layno; - packet_array[comp_index] = 1; - comp_index += step_l; - } - res_index += step_c; - } - indexvalue += step_r; - } - ++p_pocs; - } - - indexvalue = 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[indexvalue]!=1); - //indexvalue = step_r * resno + step_c * compno + step_l * layno; - indexvalue += step_c; - } - } - } - if - (loss) - { - opj_event_msg(p_manager , EVT_ERROR, "Missing packets possible loss of data\n"); - } - opj_free(packet_array); - return !loss; -} - - -/* ----------------------------------------------------------------------- */ - -/** - * 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. - */ -OPJ_UINT32 j2k_get_num_tp(opj_cp_t *cp,OPJ_UINT32 pino,OPJ_UINT32 tileno) -{ - const OPJ_CHAR *prog = 00; - OPJ_UINT32 i; - OPJ_UINT32 tpnum = 1; - opj_tcp_t *tcp = 00; - opj_poc_t * l_current_poc = 00; - - // preconditions only in debug - 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 = 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; - } - // whould 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; -} - -/** - * 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. - */ -bool 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); - - l_nb_tiles = cp->tw * cp->th; - * p_nb_tiles = 0; - tcp = cp->tcps; - - /* INDEX >> */ - 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; - pi_update_encoding_parameters(image,cp,tileno); - for - (pino = 0; pino <= tcp->numpocs; ++pino) - { - OPJ_UINT32 tp_num = 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 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; - pi_update_encoding_parameters(image,cp,tileno); - for - (pino = 0; pino <= tcp->numpocs; ++pino) - { - OPJ_UINT32 tp_num=0; - tp_num = 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 true; -} - -/** - * 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. -*/ - -bool j2k_write_soc( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 false; - } -/* UniPG>> */ -#ifdef USE_JPWL - /* update markers struct */ - j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOC, p_stream_tell(p_stream) - 2, 2); -#endif /* USE_JPWL */ - return true; -/* <m_specific_param.m_decoder.m_state = J2K_DEC_STATE_MHSIZ; - /* Index */ - if - (p_j2k->cstr_info) - { - //TODO p_j2k->cstr_info->main_head_start = opj_stream_tell(p_stream) - 2; // why - 2 ? - p_j2k->cstr_info->codestream_size = 0;/*p_stream_numbytesleft(p_j2k->p_stream) + 2 - p_j2k->cstr_info->main_head_start*/; - } - return true; -} - -/** - * Writes the SIZ marker (image and tile size) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool j2k_write_siz( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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_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) - { - 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_size_len); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - 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) != (OPJ_INT32)l_size_len) - { - return false; - } - return true; -} - -/** - * Reads a SIZ marker (image and tile size) - * @param p_header_data the data contained in the SIZ box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the SIZ marker. - * @param p_manager the user event manager. -*/ -bool j2k_read_siz ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ) -{ - OPJ_UINT32 l_size, 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; - 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_image; - l_cp = &(p_j2k->m_cp); - if - (p_header_size < 36) - { - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); - return 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 false; - } - l_size = p_header_size + 2; /* Lsiz */ - - opj_read_bytes(p_header_data,&l_tmp ,2); /* Rsiz (capabilities) */ - p_header_data+=2; - l_cp->rsiz = (OPJ_RSIZ_CAPABILITIES) 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, (&l_cp->tdx),4); /* XTsiz */ - p_header_data+=4; - opj_read_bytes(p_header_data,&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,(&l_image->numcomps),2); /* Csiz */ - p_header_data+=2; - if - (l_image->numcomps != l_nb_comp) - { - opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker size\n"); - return false; - } - -#ifdef USE_JPWL - if (p_j2k->m_cp->correct) { - /* if JPWL is on, we check whether TX errors have damaged - too much the SIZ parameters */ - if (!(image->x1 * image->y1)) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, - "JPWL: bad image size (%d x %d)\n", - image->x1, image->y1); - if (!JPWL_ASSUME || JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - } - if (image->numcomps != ((len - 38) / 3)) { - opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, - "JPWL: Csiz is %d => space in SIZ only for %d comps.!!!\n", - image->numcomps, ((len - 38) / 3)); - if (!JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - /* we try to correct */ - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust this\n"); - if (image->numcomps < ((len - 38) / 3)) { - len = 38 + 3 * image->numcomps; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting Lsiz to %d => HYPOTHESIS!!!\n", - len); - } else { - image->numcomps = ((len - 38) / 3); - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting Csiz to %d => HYPOTHESIS!!!\n", - image->numcomps); - } - } - - /* update components number in the jpwl_exp_comps filed */ - cp->exp_comps = image->numcomps; - } -#endif /* USE_JPWL */ - - 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 false; - } - memset(l_image->comps,0,l_image->numcomps * sizeof(opj_image_comp_t)); - l_img_comp = l_image->comps; - 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; - opj_read_bytes(p_header_data,&l_img_comp->dx,1); /* XRsiz_i */ - ++p_header_data; - opj_read_bytes(p_header_data,&l_img_comp->dy,1); /* YRsiz_i */ - ++p_header_data; -#ifdef USE_JPWL - if (p_j2k->m_cp->correct) { - /* if JPWL is on, we check whether TX errors have damaged - too much the SIZ parameters, again */ - if (!(image->comps[i].dx * image->comps[i].dy)) { - opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, - "JPWL: bad XRsiz_%d/YRsiz_%d (%d x %d)\n", - i, i, image->comps[i].dx, image->comps[i].dy); - if (!JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - /* we try to correct */ - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust them\n"); - if (!image->comps[i].dx) { - image->comps[i].dx = 1; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting XRsiz_%d to %d => HYPOTHESIS!!!\n", - i, image->comps[i].dx); - } - if (!image->comps[i].dy) { - image->comps[i].dy = 1; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting YRsiz_%d to %d => HYPOTHESIS!!!\n", - i, 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; - } - - l_cp->tw = int_ceildiv(l_image->x1 - l_cp->tx0, l_cp->tdx); - l_cp->th = int_ceildiv(l_image->y1 - l_cp->ty0, l_cp->tdy); - l_nb_tiles = l_cp->tw * l_cp->th; - 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 = int_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 = int_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 (p_j2k->m_cp->correct) { - /* if JPWL is on, we check whether TX errors have damaged - too much the SIZ parameters */ - if ((cp->tw < 1) || (cp->th < 1) || (cp->tw > cp->max_tiles) || (cp->th > cp->max_tiles)) { - opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, - "JPWL: bad number of tiles (%d x %d)\n", - cp->tw, cp->th); - if (!JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - /* we try to correct */ - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust them\n"); - if (cp->tw < 1) { - cp->tw= 1; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting %d tiles in x => HYPOTHESIS!!!\n", - cp->tw); - } - if (cp->tw > cp->max_tiles) { - cp->tw= 1; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- too large x, increase expectance of %d\n" - "- setting %d tiles in x => HYPOTHESIS!!!\n", - cp->max_tiles, cp->tw); - } - if (cp->th < 1) { - cp->th= 1; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- setting %d tiles in y => HYPOTHESIS!!!\n", - cp->th); - } - if (cp->th > cp->max_tiles) { - cp->th= 1; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- too large y, increase expectance of %d to continue\n", - "- setting %d tiles in y => HYPOTHESIS!!!\n", - cp->max_tiles, 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 false; - } - memset(l_cp->tcps,0,l_nb_tiles*sizeof(opj_tcp_t)); - -#ifdef USE_JPWL - if (p_j2k->m_cp->correct) { - if (!cp->tcps) { - opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, - "JPWL: could not alloc tcps field of cp\n"); - if (!JPWL_ASSUME || JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - } - } -#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 false; - } - memset(p_j2k->m_specific_param.m_decoder.m_default_tcp->tccps ,0,l_image->numcomps*sizeof(opj_tccp_t)); - - p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records = - (opj_mct_data_t*)opj_malloc(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 false; - } - memset(p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mct_records,0,J2K_MCT_DEFAULT_NB_RECORDS * sizeof(opj_mct_data_t)); - p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mct_records = 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_malloc(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 false; - } - memset(p_j2k->m_specific_param.m_decoder.m_default_tcp->m_mcc_records,0,J2K_MCC_DEFAULT_NB_RECORDS * sizeof(opj_simple_mcc_decorrelation_data_t)); - p_j2k->m_specific_param.m_decoder.m_default_tcp->m_nb_max_mcc_records = J2K_MCC_DEFAULT_NB_RECORDS; - - /* set up default dc level shift */ - for - (i=0;inumcomps;++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_malloc(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 false; - } - memset(l_current_tile_param->tccps,0,l_image->numcomps * sizeof(opj_tccp_t)); - - ++l_current_tile_param; - - } - p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_MH; - opj_image_comp_update(l_image,l_cp); - - /* Index */ - if - (p_j2k->cstr_info) - { - opj_codestream_info_t *cstr_info = p_j2k->cstr_info; - cstr_info->image_w = l_image->x1 - l_image->x0; - cstr_info->image_h = l_image->y1 - l_image->y0; - cstr_info->numcomps = l_image->numcomps; - cstr_info->tw = l_cp->tw; - cstr_info->th = l_cp->th; - cstr_info->tile_x = l_cp->tdx; - cstr_info->tile_y = l_cp->tdy; - cstr_info->tile_Ox = l_cp->tx0; - cstr_info->tile_Oy = l_cp->ty0; - cstr_info->tile = (opj_tile_info_t*) opj_calloc(l_nb_tiles, sizeof(opj_tile_info_t)); - if - (cstr_info->tile == 00) - { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to take in charge SIZ marker\n"); - return false; - } - memset(cstr_info->tile,0,l_nb_tiles * sizeof(opj_tile_info_t)); - } - return true; -} - -/** - * 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. -*/ -bool j2k_write_com( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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) - { - 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_total_com_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - 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) != (OPJ_INT32)l_total_com_size) - { - return false; - } - return true; -} - -/** - * Reads a COM marker (comments) - * @param p_header_data the data contained in the COM box. - * @param jp2 the jpeg2000 file codec. - * @param p_header_size the size of the data contained in the COM marker. - * @param p_manager the user event manager. -*/ -bool j2k_read_com ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ) -{ - // preconditions - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_header_data != 00); - return true; -} - -/** - * Gets the size taken by writting a SPCod or SPCoc for the given tile and component. - * - * @param p_tile_no the tile indix. - * @param p_comp_no the component being outputted. - * @param p_j2k the J2K codec. - * - * @return the number of bytes taken by the SPCod element. - */ -OPJ_UINT32 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_image->numcomps); - - if - (l_tccp->csty & J2K_CCP_CSTY_PRT) - { - return 5 + l_tccp->numresolutions; - } - else - { - return 5; - } -} - - -/** - * Writes a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. - * - * @param p_comp_no the component number to output. - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. - * -*/ -bool 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_image->numcomps)); - - if - (*p_header_size < 5) - { - opj_event_msg(p_manager, EVT_ERROR, "Error writting SPCod SPCoc element\n"); - return 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 writting SPCod SPCoc element\n"); - return 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 true; -} - - -/** - * Reads a SPCod or SPCoc element, i.e. the coding style of a given component of a tile. - * @param p_header_data the data contained in the COM box. - * @param p_j2k the jpeg2000 codec. - * @param p_header_size the size of the data contained in the COM marker. - * @param p_manager the user event manager. -*/ -bool j2k_read_SPCod_SPCoc( - opj_j2k_t *p_j2k, - OPJ_UINT32 compno, - OPJ_BYTE * p_header_data, - OPJ_UINT32 * p_header_size, - struct opj_event_mgr * p_manager - ) -{ - // loop - OPJ_UINT32 i; - - 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; - - // 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_DEC_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_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 false; - } - opj_read_bytes(l_current_ptr, &l_tccp->numresolutions ,1); /* SPcox (D) */ - ++l_tccp->numresolutions; /* tccp->numresolutions = read() + 1 */ - ++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 is higher than the number " - "of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno); - p_j2k->m_specific_param.m_decoder.m_state |= J2K_DEC_STATE_ERR; - return false; - } - - opj_read_bytes(l_current_ptr,&l_tccp->cblkw ,1); /* SPcoc (E) */ - ++l_current_ptr; - l_tccp->cblkw += 2; - - opj_read_bytes(l_current_ptr,&l_tccp->cblkh ,1); /* SPcoc (F) */ - ++l_current_ptr; - l_tccp->cblkh += 2; - - opj_read_bytes(l_current_ptr,&l_tccp->cblksty ,1); /* SPcoc (G) */ - ++l_current_ptr; - - opj_read_bytes(l_current_ptr,&l_tccp->qmfbid ,1); /* SPcoc (H) */ - ++l_current_ptr; - - * 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 false; - } - for - (i = 0; i < l_tccp->numresolutions; ++i) - { - opj_read_bytes(l_current_ptr,&l_tmp ,1); /* SPcoc (I_i) */ - ++l_current_ptr; - 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; - } - } - - /* INDEX >> */ - if - (p_j2k->cstr_info && compno == 0) - { - OPJ_UINT32 l_data_size = l_tccp->numresolutions * sizeof(OPJ_UINT32); - 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 */ - return true; -} - -/** - * Copies the tile component parameters of all the component from the first tile component. - * - * @param p_j2k the J2k codec. - */ -void j2k_copy_tile_component_parameters( - opj_j2k_t *p_j2k - ) -{ - // loop - OPJ_UINT32 i; - - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_tccp_t *l_ref_tccp = 00; - opj_tccp_t *l_copied_tccp = 00; - 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_DEC_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 * sizeof(OPJ_UINT32); - - for - (i=1;im_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; - } -} - - - -/** - * 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. -*/ -bool j2k_write_cod( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 + 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) - { - 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_code_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - 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,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 - (! 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 writting COD marker\n"); - return false; - } - if - (l_remaining_size != 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error writting COD marker\n"); - return false; - } - - if - (opj_stream_write_data(p_stream,p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_code_size,p_manager) != (OPJ_INT32)l_code_size) - { - return false; - } - return true; -} - -/** - * Reads a COD marker (Coding Styke 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. -*/ -bool j2k_read_cod ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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_cp = &(p_j2k->m_cp); - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_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_image; - - // make sure room is sufficient - if - (p_header_size < 5) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); - return false; - } - - opj_read_bytes(p_header_data,&l_tcp->csty,1); /* Scod */ - ++p_header_data; - opj_read_bytes(p_header_data,&l_tmp,1); /* SGcod (A) */ - ++p_header_data; - l_tcp->prg = (OPJ_PROG_ORDER) l_tmp; - opj_read_bytes(p_header_data,&l_tcp->numlayers,2); /* SGcod (B) */ - p_header_data+=2; - 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; - - 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 - (! 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 false; - } - if - (p_header_size != 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n"); - return false; - } - j2k_copy_tile_component_parameters(p_j2k); - - - /* Index */ - if - (p_j2k->cstr_info) - { - opj_codestream_info_t *l_cstr_info = p_j2k->cstr_info; - l_cstr_info->prog = l_tcp->prg; - l_cstr_info->numlayers = l_tcp->numlayers; - l_cstr_info->numdecompos = (OPJ_INT32*) opj_malloc(l_image->numcomps * sizeof(OPJ_UINT32)); - for - (i = 0; i < l_image->numcomps; ++i) - { - l_cstr_info->numdecompos[i] = l_tcp->tccps[i].numresolutions - 1; - } - } - return true; -} - -/** - * Writes the COC marker (Coding style 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. -*/ -bool j2k_write_coc( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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_image->numcomps <= 256) ? 1 : 2; - - l_coc_size = 5 + l_comp_room + 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) - { - 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); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_coc_size; - } - - 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) != (OPJ_INT32)l_coc_size) - { - return false; - } - return true; -} - -/** - * Gets the maximum size taken by a coc. - * - * @param p_j2k the jpeg2000 codec to use. - */ -OPJ_UINT32 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_image->numcomps; - - for - (i=0;im_cp.tcps; - l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th ; - - for - (i=0;im_nb_tile_parts); - ++l_tcp; - } - return 12 * l_max; -} - - -/** - * Gets the maximum size taken by the headers of the SOT. - * - * @param p_j2k the jpeg2000 codec to use. - */ -OPJ_UINT32 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_image->numcomps - 1; - l_nb_bytes += j2k_get_max_toc_size(p_j2k); - if - (p_j2k->m_cp.m_specific_param.m_enc.m_cinema == 0) - { - l_coc_bytes = j2k_get_max_coc_size(p_j2k); - l_nb_bytes += l_nb_comps * l_coc_bytes; - l_qcc_bytes = j2k_get_max_qcc_size(p_j2k); - l_nb_bytes += l_nb_comps * l_qcc_bytes; - } - l_nb_bytes += j2k_get_max_poc_size(p_j2k); - /*** DEVELOPER CORNER, Add room for your headers ***/ - - - return l_nb_bytes; -} - - -/** - * Writes the COC marker (Coding style 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. -*/ -void j2k_write_coc_in_memory( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - struct opj_event_mgr * 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_image; - l_comp_room = (l_image->numcomps <= 256) ? 1 : 2; - - l_coc_size = 5 + l_comp_room + 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); - 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; -} - - -/** - * 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. -*/ -bool j2k_read_coc ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ) -{ - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_image_t *l_image = 00; - 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_DEC_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_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 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 false; - } - opj_read_bytes(p_header_data,&l_tcp->tccps[l_comp_no].csty,1); /* Scoc */ - ++p_header_data ; - - if - (! 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 false; - } - if - (p_header_size != 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading COC marker\n"); - return false; - } - return true; -} - -/** - * Gets the size taken by writting SQcd or SQcc element, i.e. the quantization values of a band in the QCD or QCC. - * - * @param p_tile_no the tile indix. - * @param p_comp_no the component being outputted. - * @param p_j2k the J2K codec. - * - * @return the number of bytes taken by the SPCod element. - */ -OPJ_UINT32 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_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; - } -} - -/** - * Writes a SQcd or SQcc element, i.e. the quantization values of a band. - * - * @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. - * -*/ -bool 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 m_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 writting SQcd SQcc element\n"); - return 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 = 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 writting SQcd SQcc element\n"); - return 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 = l_tccp->stepsizes[l_band_no].expn; - l_mant = 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 true; -} - -/** - * Reads a SQcd or SQcc element, i.e. the quantization values of a band. - * - * @param p_comp_no the component being targeted. - * @param p_header_data the data contained in the COM box. - * @param p_j2k the jpeg2000 codec. - * @param p_header_size the size of the data contained in the COM marker. - * @param p_manager the user event manager. -*/ -bool j2k_read_SQcd_SQcc( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE* p_header_data, - OPJ_UINT32 * p_header_size, - struct opj_event_mgr * 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; - OPJ_UINT32 l_num_band; - - // 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_DEC_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_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 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 > J2K_MAXBANDS ) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading CCP_QNTSTY element\n"); - return false; - } - } - -#ifdef USE_JPWL - if (p_j2k->m_cp->correct) { - - /* if JPWL is on, we check whether there are too many subbands */ - if ((numbands < 0) || (numbands >= J2K_MAXBANDS)) { - opj_event_msg(p_j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR, - "JPWL: bad number of subbands in Sqcx (%d)\n", - numbands); - if (!JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - /* we try to correct */ - numbands = 1; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust them\n" - "- setting number of bands to %d => HYPOTHESIS!!!\n", - numbands); - }; - - }; -#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; - l_tccp->stepsizes[l_band_no].expn = l_tmp>>3; - l_tccp->stepsizes[l_band_no].mant = 0; - } - * 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; - l_tccp->stepsizes[l_band_no].expn = l_tmp >> 11; - l_tccp->stepsizes[l_band_no].mant = l_tmp & 0x7ff; - } - * 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 < J2K_MAXBANDS; l_band_no++) - { - l_tccp->stepsizes[l_band_no].expn = - ((l_tccp->stepsizes[0].expn) - ((l_band_no - 1) / 3) > 0) ? - (l_tccp->stepsizes[0].expn) - ((l_band_no - 1) / 3) : 0; - l_tccp->stepsizes[l_band_no].mant = l_tccp->stepsizes[0].mant; - } - - } - return true; -} - - - -/** - * Copies the tile component parameters of all the component from the first tile component. - * - * @param p_j2k the J2k codec. - */ -void j2k_copy_tile_quantization_parameters( - opj_j2k_t *p_j2k - ) -{ - // loop - OPJ_UINT32 i; - - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_tccp_t *l_ref_tccp = 00; - opj_tccp_t *l_copied_tccp = 00; - 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_DEC_STATE_TPH ? &l_cp->tcps[p_j2k->m_current_tile_number] : p_j2k->m_specific_param.m_decoder.m_default_tcp; - // precondition again - l_ref_tccp = &l_tcp->tccps[0]; - l_copied_tccp = l_ref_tccp + 1; - l_size = J2K_MAXBANDS * sizeof(opj_stepsize_t); - - for - (i=1;im_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; - } -} - - - -/** - * Writes the QCD marker (quantization default) - * - * @param p_comp_number 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. -*/ -bool j2k_write_qcd( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) -{ - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - 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_cp = &(p_j2k->m_cp); - l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; - l_qcd_size = 4 + 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) - { - 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_qcd_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - 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 - (! 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 writting QCD marker\n"); - return false; - } - if - (l_remaining_size != 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error writting QCD marker\n"); - return false; - } - - if - (opj_stream_write_data(p_stream, p_j2k->m_specific_param.m_encoder.m_header_tile_data,l_qcd_size,p_manager) != (OPJ_INT32)l_qcd_size) - { - return false; - } - return 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. -*/ -bool j2k_read_qcd ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ) -{ - // preconditions - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - if - (! 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 false; - } - if - (p_header_size != 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading QCD marker\n"); - return false; - } - j2k_copy_tile_quantization_parameters(p_j2k); - return true; -} - - -/** - * 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. -*/ -bool j2k_write_qcc( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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 = 6 + j2k_get_SQcd_SQcc_size(p_j2k,p_j2k->m_current_tile_number,p_comp_no); - l_remaining_size = l_qcc_size; - if - (l_qcc_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) - { - 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_qcc_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_qcc_size; - } - 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) != (OPJ_INT32)l_qcc_size) - { - return false; - } - return true; -} - - -/** - * 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. -*/ -void j2k_write_qcc_in_memory( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_comp_no, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - struct opj_event_mgr * 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 + 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_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; - } - 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; -} - -/** - * Gets the maximum size taken by a qcc. - */ -OPJ_UINT32 j2k_get_max_qcc_size (opj_j2k_t *p_j2k) -{ - return 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. -*/ -bool j2k_read_qcc( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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_image->numcomps; - -#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 ((compno < 0) || (compno >= numcomp)) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, - "JPWL: bad component number in QCC (%d out of a maximum of %d)\n", - compno, numcomp); - if (!JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - /* we try to correct */ - compno = backup_compno % numcomp; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust this\n" - "- setting component number to %d\n", - compno); - } - - /* keep your private count of tiles */ - backup_compno++; - }; -#endif /* USE_JPWL */ - if - (l_num_comp <= 256) - { - if - (p_header_size < 1) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); - return 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 false; - } - opj_read_bytes(p_header_data,&l_comp_no,2); - p_header_data+=2; - p_header_size-=2; - } - if - (! 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 false; - } - if - (p_header_size != 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading QCC marker\n"); - return false; - } - return true; - -} - - -/** - * 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. -*/ -bool 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_image; - l_cbd_size = 6 + p_j2k->m_image->numcomps; - - if - (l_cbd_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) - { - 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_cbd_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - 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;inumcomps;++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) != (OPJ_INT32)l_cbd_size) - { - return false; - } - return 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. -*/ -bool j2k_read_cbd ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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_image->numcomps; - - if - (p_header_size != (p_j2k->m_image->numcomps + 2)) - { - opj_event_msg(p_manager, EVT_ERROR, "Crror reading CBD marker\n"); - return 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 false; - } - - l_comp = p_j2k->m_image->comps; - for - (i=0;isgnd = (l_comp_def>>7) & 1; - l_comp->prec = (l_comp_def&0x7f) + 1; - ++l_comp; - } - return true; -} - -/** - * Writes the MCC marker (Multiple Component Collection) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool 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) - { - 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_mcc_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - 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;im_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;im_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)&1)<<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) != (OPJ_INT32)l_mcc_size) - { - return false; - } - return true; -} - - -/** - * 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. -*/ -bool j2k_read_mcc ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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; - - - // 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_DEC_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 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 true; - } - if - (p_header_size < 7) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); - return 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;im_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) - { - l_tcp->m_nb_max_mcc_records += J2K_MCC_DEFAULT_NB_RECORDS; - l_tcp->m_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 - (! l_tcp->m_mcc_records) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); - return false; - } - 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_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 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 true; - } - p_header_size -= 7; - for - (i=0;i 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 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 false; - } - p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 2); - for - (j=0;jm_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 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 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 false; - } - p_header_size -= (l_nb_bytes_by_comp * l_mcc_record->m_nb_comps + 3); - for - (j=0;jm_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 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;jm_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 false; - } - } - l_indix = (l_tmp >> 8) & 0xff; - if - (l_indix != 0) - { - l_mct_data = l_tcp->m_mct_records; - for - (j=0;jm_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 false; - } - } - } - if - (p_header_size != 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCC marker\n"); - return false; - } - ++l_tcp->m_nb_mcc_records; - return true; -} - -/** - * Writes the MCT marker (Multiple Component Transform) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool 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) - { - 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_mct_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - 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) != (OPJ_INT32)l_mct_size) - { - return false; - } - return 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. -*/ -bool j2k_read_mct ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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_DEC_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 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 true; - } - if - (p_header_size <= 6) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); - return false; - } - opj_read_bytes(p_header_data,&l_tmp,2); /* Imct -> no need for other values, take the first, type is double with decorrelation x0000 1101 0000 0000*/ - p_header_data += 2; - - l_indix = l_tmp & 0xff; - l_mct_data = l_tcp->m_mct_records; - for - (i=0;im_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) - { - l_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS; - l_tcp->m_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 - (! l_tcp->m_mct_records) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading MCT marker\n"); - return false; - } - 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; - } - if - (l_mct_data->m_data) - { - opj_free(l_mct_data->m_data); - l_mct_data->m_data = 00; - } - 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 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 false; - } - memcpy(l_mct_data->m_data,p_header_data,p_header_size); - l_mct_data->m_data_size = p_header_size; - ++l_tcp->m_nb_mct_records; - return true; -} - -bool 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 true; - } - - if - (p_tcp->m_mct_decoding_matrix) - { - if - (p_tcp->m_nb_mct_records == p_tcp->m_nb_max_mct_records) - { - p_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS; - p_tcp->m_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 - (! p_tcp->m_mct_records) - { - return false; - } - 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 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) - { - p_tcp->m_nb_max_mct_records += J2K_MCT_DEFAULT_NB_RECORDS; - p_tcp->m_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 - (! p_tcp->m_mct_records) - { - return false; - } - 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 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 false; - } - l_tccp = p_tcp->tccps; - l_current_data = l_data; - for - (i=0;im_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) - { - p_tcp->m_nb_max_mcc_records += J2K_MCT_DEFAULT_NB_RECORDS; - p_tcp->m_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 - (! p_tcp->m_mcc_records) - { - return false; - } - 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 true; -} - -/** - * 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. -*/ -bool 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_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data; - 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) - { - 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_mco_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_mco_size; - } - - 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 tranform stage*/ - ++l_current_data; - - l_mcc_record = l_tcp->m_mcc_records; - for - (i=0;im_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) != (OPJ_INT32)l_mco_size) - { - return false; - } - return 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. -*/ -bool j2k_read_mco ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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; - opj_image_comp_t * l_img_comp; - - // preconditions - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - l_image = p_j2k->m_image; - l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_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 false; - } - - opj_read_bytes(p_header_data,&l_nb_stages,1); /* Nmco : only one tranform 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 true; - } - if - (p_header_size != l_nb_stages + 1) - { - opj_event_msg(p_manager, EVT_WARNING, "Error reading MCO marker\n"); - return false; - } - - l_tccp = l_tcp->tccps; - l_img_comp = l_image->comps; - for - (i=0;inumcomps;++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;im_image,l_tmp)) - { - return false; - } - } - return true; -} - -bool 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;im_nb_mcc_records;++i) - { - if - (l_mcc_record->m_index == p_index) - { - break; - } - } - if - (i==p_tcp->m_nb_mcc_records) - { - /** element discarded **/ - return true; - } - if - (l_mcc_record->m_nb_comps != p_image->numcomps) - { - /** do not support number of comps != image */ - return 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 false; - } - l_nb_elem = p_image->numcomps * p_image->numcomps; - l_mct_size = l_nb_elem * sizeof(OPJ_FLOAT32); - p_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size); - if - (! p_tcp->m_mct_decoding_matrix ) - { - return 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 false; - } - l_nb_elem = p_image->numcomps; - l_offset_size = l_nb_elem * sizeof(OPJ_UINT32); - l_offset_data = (OPJ_UINT32*)opj_malloc(l_offset_size); - if - (! l_offset_data ) - { - return 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;inumcomps;++i) - { - l_tccp->m_dc_level_shift = *(l_current_offset_data++); - ++l_tccp; - } - opj_free(l_offset_data); - } - return true; -} - -/** - * Writes the MCT marker (Multiple Component Transform) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool 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 - (! j2k_write_cbd(p_j2k,p_stream,p_manager)) - { - return 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;im_nb_mct_records;++i) - { - if - (! j2k_write_mct_record(p_j2k,l_mct_record,p_stream,p_manager)) - { - return false; - } - ++l_mct_record; - } - l_mcc_record = l_tcp->m_mcc_records; - for - (i=0;im_nb_mcc_records;++i) - { - if - (! j2k_write_mcc_record(p_j2k,l_mcc_record,p_stream,p_manager)) - { - return false; - } - ++l_mcc_record; - } - if - (! j2k_write_mco(p_j2k,p_stream,p_manager)) - { - return false; - } - return true; -} - - -/** - * 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. -*/ -bool j2k_write_poc( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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_tccp_t *l_tccp = 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_tccp = &l_tcp->tccps[0]; - l_nb_comp = p_j2k->m_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) - { - 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_poc_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_poc_size; - } - - 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) != (OPJ_INT32)l_poc_size) - { - return false; - } - return true; -} - - -/** - * Writes EPC ???? - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool j2k_write_epc( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) -{ - opj_codestream_info_t * l_info = 00; - - // preconditions - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_info = p_j2k->cstr_info; - if - (l_info) - { - l_info->codestream_size = 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_info->codestream_size -= l_info->main_head_start; - /* <epc_on) { - - /* encode according to JPWL */ - jpwl_encode(p_j2k, p_stream, image); - - } -#endif /* USE_JPWL */ - return true; -} - - -/** - * Gets the maximum size taken by the writting of a POC. - */ -OPJ_UINT32 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;inumpocs); - ++l_tcp; - } - ++l_max_poc; - return 4 + 9 * l_max_poc; -} - - -/** - * 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. -*/ -void j2k_write_poc_in_memory( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - struct opj_event_mgr * 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); - - l_tcp = &p_j2k->m_cp.tcps[p_j2k->m_current_tile_number]; - l_tccp = &l_tcp->tccps[0]; - l_image = p_j2k->m_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,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 = int_min(l_current_poc->layno1, l_tcp->numlayers); - l_current_poc->resno1 = int_min(l_current_poc->resno1, l_tccp->numresolutions); - l_current_poc->compno1 = int_min(l_current_poc->compno1, l_nb_comp); - ++l_current_poc; - } - * p_data_written = l_poc_size; -} - - -/** - * 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. -*/ -bool j2k_read_poc ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ) -{ - OPJ_UINT32 i; - OPJ_UINT32 l_nb_comp; - 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; - OPJ_UINT32 l_tmp; - - opj_cp_t *l_cp = 00; - opj_tcp_t *l_tcp = 00; - opj_poc_t *l_current_poc = 00; - OPJ_UINT32 l_comp_room; - - // preconditions - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - l_image = p_j2k->m_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 false; - } - - l_cp = &(p_j2k->m_cp); - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_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; - assert(l_current_poc_nb < 32); - - /* 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 */ - 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 = uint_min(l_current_poc->compno1, l_nb_comp); - ++l_current_poc; - } - l_tcp->numpocs = l_current_poc_nb - 1; - return true; -} - -/** - * Writes the RGN marker (Region Of Interest) - * - * @param p_tile_no the tile to output - * @param p_comp_no 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. -*/ -bool j2k_write_rgn( - opj_j2k_t *p_j2k, - OPJ_UINT32 p_tile_no, - OPJ_UINT32 p_comp_no, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) -{ - OPJ_BYTE * l_current_data = 00; - OPJ_UINT32 l_nb_comp; - OPJ_UINT32 l_rgn_size; - opj_image_t *l_image = 00; - 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]; - - l_nb_comp = l_image->numcomps; - - if - (l_nb_comp <= 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, 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) != (OPJ_INT32)l_rgn_size) - { - return false; - } - return 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. -*/ -bool j2k_read_rgn ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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; - OPJ_UINT32 l_comp_no; - OPJ_UINT32 l_roi_sty; - - // preconditions - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - l_image = p_j2k->m_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 false; - } - - l_cp = &(p_j2k->m_cp); - l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_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 (p_j2k->m_cp->correct) { - /* totlen is negative or larger than the bytes left!!! */ - if (compno >= numcomps) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, - "JPWL: bad component number in RGN (%d when there are only %d)\n", - compno, numcomps); - if (!JPWL_ASSUME || JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - } - }; -#endif /* USE_JPWL */ - - opj_read_bytes(p_header_data,(OPJ_UINT32 *) (&(l_tcp->tccps[l_comp_no].roishift)),1); /* SPrgn */ - ++p_header_data; - return true; - -} - -/** - * 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. -*/ -bool j2k_write_tlm( - 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_tlm_size; - - // preconditions - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_tlm_size = 6 + (5*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) - { - 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_tlm_size); - if - (! p_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - return false; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 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; - opj_write_bytes(l_current_data,0x50,1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */ - ++l_current_data; - /* do nothing on the 5 * 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) != (OPJ_INT32)l_tlm_size) - { - return false; - } - return 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. -*/ -bool j2k_read_tlm ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ) -{ - OPJ_UINT32 l_Ztlm, l_Stlm, l_ST, l_SP, l_tot_num_tp, l_tot_num_tp_remaining, l_quotient, l_Ptlm_size; - // preconditions - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - if - (p_header_size < 2) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); - return false; - } - p_header_size -= 2; - - - 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); - l_SP = (l_Stlm >> 6) & 0x1; - - l_Ptlm_size = (l_SP + 1) * 2; - l_quotient = l_Ptlm_size + l_ST; - - l_tot_num_tp = p_header_size / l_quotient; - l_tot_num_tp_remaining = p_header_size % l_quotient; - if - (l_tot_num_tp_remaining != 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); - return false; - } - /* Do not care of this at the moment since only local variables are set here */ - /* - for - (i = 0; i < l_tot_num_tp; ++i) - { - opj_read_bytes(p_header_data,&l_Ttlm_i,l_ST); // Ttlm_i - p_header_data += l_ST; - opj_read_bytes(p_header_data,&l_Ptlm_i,l_Ptlm_size); // Ptlm_i - p_header_data += l_Ptlm_size; - }*/ - return 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. -*/ -bool j2k_read_crg ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ) -{ - OPJ_UINT32 l_nb_comp; - // preconditions - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - l_nb_comp = p_j2k->m_image->numcomps; - - if - (p_header_size != l_nb_comp *4) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading CRG marker\n"); - return 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 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. -*/ -bool j2k_read_plm ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ) -{ - // preconditions - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - if - (p_header_size < 1) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); - return 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 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. -*/ -bool j2k_read_plt ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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); - - if - (p_header_size < 1) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PLM marker\n"); - return 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); // 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 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. -*/ -bool j2k_read_ppm ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * p_manager - ) -{ - - opj_cp_t *l_cp = 00; - OPJ_UINT32 l_remaining_data, l_Z_ppm, l_N_ppm; - - // preconditions - assert(p_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - if - (p_header_size < 1) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading RGN marker\n"); - return 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; - - // first PPM marker - if - (l_Z_ppm == 0) - { - if - (p_header_size < 4) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PPM marker\n"); - return false; - } - // read a N_ppm - opj_read_bytes(p_header_data,&l_N_ppm,4); /* N_ppm */ - p_header_data+=4; - p_header_size-=4; - /* First PPM marker */ - l_cp->ppm_len = l_N_ppm; - l_cp->ppm_data_size = 0; - l_cp->ppm_buffer = (OPJ_BYTE *) opj_malloc(l_cp->ppm_len); - l_cp->ppm_data = l_cp->ppm_buffer; - if - (l_cp->ppm_buffer == 00) - { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading ppm marker\n"); - return false; - } - memset(l_cp->ppm_buffer,0,l_cp->ppm_len); - } - - while - (true) - { - if - (l_cp->ppm_data_size == l_cp->ppm_len) - { - if - (p_header_size >= 4) - { - // read a N_ppm - opj_read_bytes(p_header_data,&l_N_ppm,4); /* N_ppm */ - p_header_data+=4; - p_header_size-=4; - l_cp->ppm_len += l_N_ppm ; - l_cp->ppm_buffer = (OPJ_BYTE *) opj_realloc(l_cp->ppm_buffer, l_cp->ppm_len); - l_cp->ppm_data = l_cp->ppm_buffer; - if - (l_cp->ppm_buffer == 00) - { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading ppm marker\n"); - return false; - } - memset(l_cp->ppm_buffer+l_cp->ppm_data_size,0,l_N_ppm); - } - else - { - return false; - } - } - l_remaining_data = l_cp->ppm_len - l_cp->ppm_data_size; - if - (l_remaining_data <= p_header_size) - { - /* we must store less information than available in the packet */ - memcpy(l_cp->ppm_buffer + l_cp->ppm_data_size , p_header_data , l_remaining_data); - l_cp->ppm_data_size = l_cp->ppm_len; - p_header_size -= l_remaining_data; - p_header_data += l_remaining_data; - } - else - { - memcpy(l_cp->ppm_buffer + l_cp->ppm_data_size , p_header_data , p_header_size); - l_cp->ppm_data_size += p_header_size; - p_header_data += p_header_size; - p_header_size = 0; - break; - } - } - return 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. -*/ -bool j2k_read_ppt ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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); - - if - (p_header_size < 1) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading PPT marker\n"); - return false; - } - - l_cp = &(p_j2k->m_cp); - 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; - - // first PPM marker - if - (l_Z_ppt == 0) - { - /* First PPM marker */ - l_tcp->ppt_len = p_header_size; - l_tcp->ppt_data_size = 0; - l_tcp->ppt_buffer = (OPJ_BYTE *) opj_malloc(l_tcp->ppt_len); - l_tcp->ppt_data = l_tcp->ppt_buffer; - if - (l_tcp->ppt_buffer == 00) - { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading PPT marker\n"); - return false; - } - memset(l_tcp->ppt_buffer,0,l_tcp->ppt_len); - } - else - { - l_tcp->ppt_len += p_header_size; - l_tcp->ppt_buffer = (OPJ_BYTE *) opj_realloc(l_tcp->ppt_buffer,l_tcp->ppt_len); - if - (l_tcp->ppt_buffer == 00) - { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory reading PPT marker\n"); - return false; - } - l_tcp->ppt_data = l_tcp->ppt_buffer; - memset(l_tcp->ppt_buffer+l_tcp->ppt_data_size,0,p_header_size); - } - memcpy(l_tcp->ppt_buffer+l_tcp->ppt_data_size,p_header_data,p_header_size); - l_tcp->ppt_data_size += p_header_size; - return true; -} - -/** - * Writes the SOT marker (Start of tile-part) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool j2k_write_sot( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - const 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_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 */ - j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOT, p_j2k->sot_start, len + 2); -#endif /* USE_JPWL */ - - * p_data_written = 12; - return 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. -*/ -bool j2k_read_sot ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_header_data, - OPJ_UINT32 p_header_size, - struct opj_event_mgr * 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_header_data != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - if - (p_header_size != 8) - { - opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n"); - return false; - } - l_cp = &(p_j2k->m_cp); - opj_read_bytes(p_header_data,&(p_j2k->m_current_tile_number),2); /* Isot */ - p_header_data+=2; - - - 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; - -#ifdef USE_JPWL - if (p_j2k->m_cp->correct) { - - static int backup_tileno = 0; - - /* tileno is negative or larger than the number of tiles!!! */ - if ((tileno < 0) || (tileno > (cp->tw * cp->th))) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, - "JPWL: bad tile number (%d out of a maximum of %d)\n", - tileno, (cp->tw * cp->th)); - if (!JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - /* we try to correct */ - tileno = backup_tileno; - opj_event_msg(p_j2k->cinfo, 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 */ - - opj_read_bytes(p_header_data,&l_tot_len,4); /* Psot */ - p_header_data+=4; - -#ifdef USE_JPWL - if (p_j2k->m_cp->correct) { - - /* totlen is negative or larger than the bytes left!!! */ - if ((totlen < 0) || (totlen > (p_stream_numbytesleft(p_stream) + 8))) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, - "JPWL: bad tile byte size (%d bytes against %d bytes left)\n", - totlen, p_stream_numbytesleft(p_stream) + 8); - if (!JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return; - } - /* we try to correct */ - totlen = 0; - opj_event_msg(p_j2k->cinfo, EVT_WARNING, "- trying to adjust this\n" - "- setting Psot to %d => assuming it is the last tile\n", - totlen); - } - - }; -#endif /* USE_JPWL */ - - if - (!l_tot_len) - { - opj_event_msg(p_manager, EVT_ERROR, "Cannot read data with no size known, giving up\n"); - return false; - } - - opj_read_bytes(p_header_data,&l_current_part ,1); /* Psot */ - ++p_header_data; - - opj_read_bytes(p_header_data,&l_num_parts ,1); /* Psot */ - ++p_header_data; - - if - (l_num_parts != 0) - { - l_tcp->m_nb_tile_parts = l_num_parts; - } - 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; - } - } - p_j2k->m_specific_param.m_decoder.m_sot_length = l_tot_len - 12; - p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_TPH; - 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); - /* Index */ - - /* move this onto a separate method to call before reading any SOT */ - /*if - TODO - (p_j2k->cstr_info) - { - if - (l_tcp->first) - { - if - (tileno == 0) - { - p_j2k->cstr_info->main_head_end = p_stream_tell(p_stream) - 13; - } - p_j2k->cstr_info->tile[tileno].tileno = tileno; - p_j2k->cstr_info->tile[tileno].start_pos = p_stream_tell(p_stream) - 12; - p_j2k->cstr_info->tile[tileno].end_pos = p_j2k->cstr_info->tile[tileno].start_pos + totlen - 1; - p_j2k->cstr_info->tile[tileno].num_tps = numparts; - if - (numparts) - { - p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(numparts * sizeof(opj_tp_info_t)); - } - else - { - p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(10 * sizeof(opj_tp_info_t)); // Fixme (10) - } - } - else - { - p_j2k->cstr_info->tile[tileno].end_pos += totlen; - } - p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = p_stream_tell(p_stream) - 12; - p_j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos = - p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1; - }*/ - return true; -} - -/** - * Writes the SOD marker (Start of data) - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool j2k_write_sod( - opj_j2k_t *p_j2k, - struct opj_tcd * p_tile_coder, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - const struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) -{ - opj_tcp_t *l_tcp = 00; - opj_codestream_info_t *l_cstr_info = 00; - opj_cp_t *l_cp = 00; - - OPJ_UINT32 l_size_tile; - OPJ_UINT32 l_remaining_data; - - // preconditions - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - opj_write_bytes(p_data,J2K_MS_SOD,2); /* SOD */ - p_data += 2; - - /* make room for the EOF marker */ - l_remaining_data = p_total_data_size - 4; - - l_cp = &(p_j2k->m_cp); - l_tcp = &l_cp->tcps[p_j2k->m_current_tile_number]; - l_cstr_info = p_j2k->cstr_info; - - /* 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; - l_size_tile = l_cp->th * l_cp->tw; - - /* INDEX >> */ - 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 */ - j2k_add_marker(p_j2k->cstr_info, J2K_MS_SOD, p_j2k->sod_start, 2); -#endif /* USE_JPWL */ - /* <m_specific_param.m_encoder.m_current_tile_part_number == 0) - { - p_tile_coder->tcd_image->tiles->packno = 0; - if - (l_cstr_info) - { - l_cstr_info->packno = 0; - } - } - *p_data_written = 0; - if - (! tcd_encode_tile(p_tile_coder, p_j2k->m_current_tile_number, p_data, p_data_written, l_remaining_data , l_cstr_info)) - { - opj_event_msg(p_manager, EVT_ERROR, "Cannot encode tile\n"); - return false; - } - *p_data_written += 2; - return true; -} - -/** - * Updates the Tile Length Marker. - */ -void j2k_update_tlm ( - opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_part_size - ) -{ - opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,p_j2k->m_current_tile_number,1); /* PSOT */ - ++p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current; - 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; -} - - -/** - * Reads a SOD marker (Start Of Data) - * - * @param p_header_data the data contained in the SOD box. - * @param p_j2k the jpeg2000 codec. - * @param p_header_size the size of the data contained in the SOD marker. - * @param p_manager the user event manager. -*/ -bool j2k_read_sod ( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) -{ - OPJ_UINT32 l_current_read_size; - opj_codestream_info_t * l_cstr_info = 00; - OPJ_BYTE ** l_current_data = 00; - opj_tcp_t * l_tcp = 00; - OPJ_UINT32 * l_tile_len = 00; - - // 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]); - p_j2k->m_specific_param.m_decoder.m_sot_length -= 2; - l_cstr_info = p_j2k->cstr_info; - - l_current_data = &(l_tcp->m_data); - l_tile_len = &l_tcp->m_data_size; - - if - (! *l_current_data) - { - *l_current_data = (OPJ_BYTE*) my_opj_malloc(p_j2k->m_specific_param.m_decoder.m_sot_length); - } - else - { - *l_current_data = (OPJ_BYTE*) my_opj_realloc(*l_current_data, *l_tile_len + p_j2k->m_specific_param.m_decoder.m_sot_length); - } - if - (*l_current_data == 00) - { - opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile\n"); - return false; - } - - /* Index */ - if - (l_cstr_info) - { - OPJ_SIZE_T l_current_pos = opj_stream_tell(p_stream)-1; - l_cstr_info->tile[p_j2k->m_current_tile_number].tp[p_j2k->m_specific_param.m_encoder.m_current_tile_part_number].tp_end_header = l_current_pos; - if - (p_j2k->m_specific_param.m_encoder.m_current_tile_part_number == 0) - { - l_cstr_info->tile[p_j2k->m_current_tile_number].end_header = l_current_pos; - } - l_cstr_info->packno = 0; - } - 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); - if - (l_current_read_size != p_j2k->m_specific_param.m_decoder.m_sot_length) - { - p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_NEOC; - } - else - { - p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_TPHSOT; - } - *l_tile_len += l_current_read_size; - return true; -} - -/** - * 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. -*/ -bool j2k_write_eoc( - 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_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 */ - 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 false; - } - if - (! opj_stream_flush(p_stream,p_manager)) - { - return false; - } - return true; -} - - -/** - * Inits the Info - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool 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); - 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 j2k_calculate_tp(p_j2k,&(p_j2k->m_cp),&p_j2k->m_specific_param.m_encoder.m_total_tile_parts,p_j2k->m_image,p_manager); -} - -/** - * Creates a tile-coder decoder. - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool j2k_create_tcd( - 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); - - p_j2k->m_tcd = tcd_create(false); - if - (! p_j2k->m_tcd) - { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to create Tile Coder\n"); - return false; - } - if - (! tcd_init(p_j2k->m_tcd,p_j2k->m_image,&p_j2k->m_cp)) - { - tcd_destroy(p_j2k->m_tcd); - p_j2k->m_tcd = 00; - return false; - } - return true; -} - -OPJ_FLOAT32 get_tp_stride (opj_tcp_t * p_tcp) -{ - return (OPJ_FLOAT32) ((p_tcp->m_nb_tile_parts - 1) * 14); -} - -OPJ_FLOAT32 get_default_stride (opj_tcp_t * p_tcp) -{ - return 0; -} - -/** - * 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. -*/ -bool j2k_update_rates( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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_UINT32 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); - - - l_cp = &(p_j2k->m_cp); - l_image = p_j2k->m_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)) / (l_cp->th * l_cp->tw); - - if - (l_cp->m_specific_param.m_enc.m_tp_on) - { - l_tp_stride_func = get_tp_stride; - } - else - { - l_tp_stride_func = get_default_stride; - } - - for - (i=0;ith;++i) - { - for - (j=0;jtw;++j) - { - OPJ_FLOAT32 l_offset = ((*l_tp_stride_func)(l_tcp)) / l_tcp->numlayers; - /* 4 borders of the tile rescale on the image if necessary */ - l_x0 = int_max(l_cp->tx0 + j * l_cp->tdx, l_image->x0); - l_y0 = int_max(l_cp->ty0 + i * l_cp->tdy, l_image->y0); - l_x1 = int_min(l_cp->tx0 + (j + 1) * l_cp->tdx, l_image->x1); - l_y1 = int_min(l_cp->ty0 + (i + 1) * l_cp->tdy, l_image->y1); - l_rates = l_tcp->rates; - - /* Modification of the RATE >> */ - if - (*l_rates) - { - *l_rates = (( (float) (l_size_pixel * (l_x1 - l_x0) * (l_y1 - l_y0))) - / - ((*l_rates) * l_bits_empty) - ) - - - l_offset; - } - ++l_rates; - for - (k = 1; k < l_tcp->numlayers; ++k) - { - if - (*l_rates) - { - *l_rates = (( (OPJ_FLOAT32) (l_size_pixel * (l_x1 - l_x0) * (l_y1 - l_y0))) - / - ((*l_rates) * l_bits_empty) - ) - - - l_offset; - } - ++l_rates; - } - ++l_tcp; - } - } - - l_tcp = l_cp->tcps; - for - (i=0;ith;++i) - { - for - (j=0;jtw;++j) - { - l_rates = l_tcp->rates; - if - (*l_rates) - { - *l_rates -= l_sot_remove; - if - (*l_rates < 30) - { - *l_rates = 30; - } - } - ++l_rates; - l_last_res = l_tcp->numlayers - 1; - for - (k = 1; k < l_last_res; ++k) - { - if - (*l_rates) - { - *l_rates -= l_sot_remove; - if - (*l_rates < *(l_rates - 1) + 10) - { - *l_rates = (*(l_rates - 1)) + 20; - } - } - ++l_rates; - } - if - (*l_rates) - { - *l_rates -= (l_sot_remove + 2.f); - if - (*l_rates < *(l_rates - 1) + 10) - { - *l_rates = (*(l_rates - 1)) + 20; - } - } - ++l_tcp; - } - } - - l_img_comp = l_image->comps; - l_tile_size = 0; - for - (i=0;inumcomps;++i) - { - l_tile_size += ( uint_ceildiv(l_cp->tdx,l_img_comp->dx) - * - uint_ceildiv(l_cp->tdy,l_img_comp->dy) - * - l_img_comp->prec - ); - ++l_img_comp; - } - - l_tile_size = (OPJ_UINT32) (l_tile_size * 0.1625); /* 1.3/8 = 0.1625 */ - l_tile_size += j2k_get_specific_header_sizes(p_j2k); - - p_j2k->m_specific_param.m_encoder.m_encoded_tile_size = l_tile_size; - p_j2k->m_specific_param.m_encoder.m_encoded_tile_data = (OPJ_BYTE *) my_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) - { - return false; - } - if - (l_cp->m_specific_param.m_enc.m_cinema) - { - p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer = (OPJ_BYTE *) opj_malloc(5*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 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 true; -} - -#ifdef THIS_CODE_IS_NEVER_USED_AND_IT_IS_DECLARED_STATIC -/** - * Reads a EOC marker (End Of Codestream) - * - * @param p_header_data the data contained in the SOD box. - * @param p_j2k the jpeg2000 codec. - * @param p_header_size the size of the data contained in the SOD marker. - * @param p_manager the user event manager. -*/ -bool j2k_read_eoc ( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) -{ - OPJ_UINT32 i; - opj_tcd_t * l_tcd = 00; - OPJ_UINT32 l_nb_tiles; - opj_tcp_t * l_tcp = 00; - 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 = tcd_create(true); - if - (l_tcd == 00) - { - opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); - return false; - } - - - - for - (i = 0; i < l_nb_tiles; ++i) - { - if - (l_tcp->m_data) - { - if - (! tcd_init_decode_tile(l_tcd, i)) - { - tcd_destroy(l_tcd); - opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); - return false; - } - l_success = tcd_decode_tile(l_tcd, l_tcp->m_data, l_tcp->m_data_size, i, p_j2k->cstr_info); - /* cleanup */ - if - (! l_success) - { - p_j2k->m_specific_param.m_decoder.m_state |= J2K_DEC_STATE_ERR; - break; - } - } - j2k_tcp_destroy(l_tcp); - ++l_tcp; - } - tcd_destroy(l_tcd); - return true; -} -#endif - -/** - * Writes the image components. - * - * @param p_stream the stream to write data to. - * @param p_j2k J2K codec. - * @param p_manager the user event manager. -*/ -bool j2k_write_image_components( - 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_image->numcomps; ++compno) - { - if - (! j2k_write_coc(p_j2k,compno,p_stream, p_manager)) - { - return false; - } - if - (! j2k_write_qcc(p_j2k,compno,p_stream, p_manager)) - { - return false; - } - } - return true; -} - -/** - * 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. -*/ -bool 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_image->numcomps; ++compno) - { - if - (l_tccp->roishift) - { - if - (! j2k_write_rgn(p_j2k,0,compno,p_stream,p_manager)) - { - return false; - } - } - ++l_tccp; - } - return true; -} -/** - * 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. -*/ -bool 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_SIZE_T l_tlm_position, l_current_position; - - // preconditions - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - l_tlm_size = 5 * 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 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) != (OPJ_INT32)l_tlm_size) - { - return false; - } - if - (! opj_stream_seek(p_stream,l_current_position,p_manager)) - { - return false; - } - return true; -} - -/** - * 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. -*/ -bool 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); - - 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 true; -} - -/** - * 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. -*/ -bool 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); - - p_j2k->cstr_info->main_head_end = opj_stream_tell(p_stream); - return true; -} - - - - -#ifdef THIS_CODE_IS_NEVER_USED_AND_IT_IS_DECLARED_STATIC -/** - * Reads an unknown marker - * - * @param p_stream the stream object to read from. - * @param p_j2k the jpeg2000 codec. - * @param p_manager the user event manager. - * - * @return true if the marker could be deduced. -*/ -bool j2k_read_unk ( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) -{ - OPJ_BYTE l_data [2]; - OPJ_UINT32 l_unknown_size; - // preconditions - assert(p_j2k != 00); - assert(p_manager != 00); - assert(p_stream != 00); - - opj_event_msg(p_manager, EVT_WARNING, "Unknown marker\n"); - -#ifdef USE_JPWL - if (p_j2k->m_cp->correct) { - OPJ_INT32 m = 0, id, i; - OPJ_INT32 min_id = 0, min_dist = 17, cur_dist = 0, tmp_id; - p_stream_seek(p_j2k->p_stream, p_stream_tell(p_j2k->p_stream) - 2); - id = p_stream_read(p_j2k->p_stream, 2); - opj_event_msg(p_j2k->cinfo, EVT_ERROR, - "JPWL: really don't know this marker %x\n", - id); - if (!JPWL_ASSUME) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, - "- possible synch loss due to uncorrectable codestream errors => giving up\n"); - return; - } - /* OK, activate this at your own risk!!! */ - /* we look for the marker at the minimum hamming distance from this */ - while (j2k_dec_mstab[m].id) { - - /* 1's where they differ */ - tmp_id = j2k_dec_mstab[m].id ^ id; - - /* compute the hamming distance between our id and the current */ - cur_dist = 0; - for (i = 0; i < 16; i++) { - if ((tmp_id >> i) & 0x0001) { - cur_dist++; - } - } - - /* if current distance is smaller, set the minimum */ - if (cur_dist < min_dist) { - min_dist = cur_dist; - min_id = j2k_dec_mstab[m].id; - } - - /* jump to the next marker */ - m++; - } - - /* do we substitute the marker? */ - if (min_dist < JPWL_MAXIMUM_HAMMING) { - opj_event_msg(p_j2k->cinfo, EVT_ERROR, - "- marker %x is at distance %d from the read %x\n", - min_id, min_dist, id); - opj_event_msg(p_j2k->cinfo, EVT_ERROR, - "- trying to substitute in place and crossing fingers!\n"); - p_stream_seek(p_j2k->p_stream, p_stream_tell(p_j2k->p_stream) - 2); - p_stream_write(p_j2k->p_stream, min_id, 2); - - /* rewind */ - p_stream_seek(p_j2k->p_stream, p_stream_tell(p_j2k->p_stream) - 2); - - } - - }; -#endif /* USE_JPWL */ - if - (opj_stream_read_data(p_stream,l_data,2,p_manager) != 2) - { - opj_event_msg(p_manager, EVT_WARNING, "Unknown marker\n"); - return false; - } - opj_read_bytes(l_data,&l_unknown_size,2); - if - (l_unknown_size < 2) - { - return false; - } - l_unknown_size-=2; - - if - (opj_stream_skip(p_stream,l_unknown_size,p_manager) != l_unknown_size) - { - return false; - } - return true; -} -#endif -/** - * 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. -*/ -const opj_dec_memory_marker_handler_t * 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; - } - } - return e; -} - -/** - * Destroys a tile coding parameter structure. - * - * @param p_tcp the tile coding parameter to destroy. - */ -void j2k_tcp_destroy (opj_tcp_t *p_tcp) -{ - if - (p_tcp == 00) - { - return; - } - 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;im_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; - } - if - (p_tcp->m_data) - { - opj_free(p_tcp->m_data); - p_tcp->m_data = 00; - } -} - -/** - * Destroys a coding parameter structure. - * - * @param p_cp the coding parameter to destroy. - */ -void j2k_cp_destroy (opj_cp_t *p_cp) -{ - OPJ_UINT32 l_nb_tiles; - opj_tcp_t * l_current_tile = 00; - OPJ_UINT32 i; - - if - (p_cp == 00) - { - return; - } - if - (p_cp->tcps != 00) - { - l_current_tile = p_cp->tcps; - l_nb_tiles = p_cp->th * p_cp->tw; - - for - (i = 0; i < l_nb_tiles; ++i) - { - j2k_tcp_destroy(l_current_tile); - ++l_current_tile; - } - opj_free(p_cp->tcps); - p_cp->tcps = 00; - } - if - (p_cp->ppm_buffer != 00) - { - opj_free(p_cp->ppm_buffer); - p_cp->ppm_buffer = 00; - } - if - (p_cp->comment != 00) - { - opj_free(p_cp->comment); - p_cp->comment = 00; - } - if - (! p_cp->m_is_decoder) - { - if - (p_cp->m_specific_param.m_enc.m_matrice) - { - opj_free(p_cp->m_specific_param.m_enc.m_matrice); - p_cp->m_specific_param.m_enc.m_matrice = 00; - } - } -} - -/* ----------------------------------------------------------------------- */ -/* J2K / JPT decoder interface */ -/* ----------------------------------------------------------------------- */ -/** - * Creates a J2K decompression structure. - * - * @return a handle to a J2K decompressor if successful, NULL otherwise. -*/ -opj_j2k_t* j2k_create_decompress() -{ - opj_j2k_t *l_j2k = (opj_j2k_t*) opj_malloc(sizeof(opj_j2k_t)); - if - (!l_j2k) - { - return 00; - } - memset(l_j2k,0,sizeof(opj_j2k_t)); - l_j2k->m_is_decoder = 1; - l_j2k->m_cp.m_is_decoder = 1; - l_j2k->m_specific_param.m_decoder.m_default_tcp = (opj_tcp_t*) opj_malloc(sizeof(opj_tcp_t)); - if - (!l_j2k->m_specific_param.m_decoder.m_default_tcp) - { - opj_free(l_j2k); - return 00; - } - memset(l_j2k->m_specific_param.m_decoder.m_default_tcp,0,sizeof(opj_tcp_t)); - - l_j2k->m_specific_param.m_decoder.m_header_data = (OPJ_BYTE *) opj_malloc(J2K_DEFAULT_HEADER_SIZE); - if - (! l_j2k->m_specific_param.m_decoder.m_header_data) - { - j2k_destroy(l_j2k); - return 00; - } - l_j2k->m_specific_param.m_decoder.m_header_data_size = J2K_DEFAULT_HEADER_SIZE; - - // validation list creation - l_j2k->m_validation_list = opj_procedure_list_create(); - if - (! l_j2k->m_validation_list) - { - j2k_destroy(l_j2k); - return 00; - } - - // execution list creation - l_j2k->m_procedure_list = opj_procedure_list_create(); - if - (! l_j2k->m_procedure_list) - { - j2k_destroy(l_j2k); - return 00; - } - return l_j2k; -} - -opj_j2k_t* j2k_create_compress() -{ - opj_j2k_t *l_j2k = (opj_j2k_t*) opj_malloc(sizeof(opj_j2k_t)); - if - (!l_j2k) - { - return 00; - } - memset(l_j2k,0,sizeof(opj_j2k_t)); - 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(J2K_DEFAULT_HEADER_SIZE); - if - (! l_j2k->m_specific_param.m_encoder.m_header_tile_data) - { - j2k_destroy(l_j2k); - return 00; - } - l_j2k->m_specific_param.m_encoder.m_header_tile_data_size = J2K_DEFAULT_HEADER_SIZE; - - // validation list creation - l_j2k->m_validation_list = opj_procedure_list_create(); - if - (! l_j2k->m_validation_list) - { - j2k_destroy(l_j2k); - return 00; - } - - // execution list creation - l_j2k->m_procedure_list = opj_procedure_list_create(); - if - (! l_j2k->m_procedure_list) - { - j2k_destroy(l_j2k); - return 00; - } - return l_j2k; -} - - -/** - * Destroys a jpeg2000 codec. - * - * @param p_j2k the jpeg20000 structure to destroy. - */ -void 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) - { - 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; - } - - } - 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; - } - } - tcd_destroy(p_j2k->m_tcd); - - 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; - - opj_free(p_j2k); -} - -/** - * 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_manager the user event manager. - * - * @return true if the codec is valid. - */ -bool 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_image = p_image; - - - /* customization of the validation */ - j2k_setup_encoding_validation (p_j2k); - - /* validation of the parameters codec */ - if - (! j2k_exec(p_j2k,p_j2k->m_validation_list,p_stream,p_manager)) - { - return false; - } - - /* customization of the encoding */ - j2k_setup_header_writting(p_j2k); - - /* write header */ - if - (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) - { - return false; - } - return true; -} -/** - * Sets up the procedures to do on reading header. Developpers wanting to extend the library can add their own reading procedures. - */ -void j2k_setup_header_reading (opj_j2k_t *p_j2k) -{ - // preconditions - assert(p_j2k != 00); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_read_header_procedure); - - /* DEVELOPER CORNER, add your custom procedures */ - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_copy_default_tcp_and_create_tcd); - -} - -/** - * Sets up the procedures to do on decoding data. Developpers wanting to extend the library can add their own reading procedures. - */ -void j2k_setup_decoding (opj_j2k_t *p_j2k) -{ - // preconditions - assert(p_j2k != 00); - - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_decode_tiles); - /* DEVELOPER CORNER, add your custom procedures */ - -} - -/** - * Sets up the procedures to do on writting header. Developpers wanting to extend the library can add their own writting procedures. - */ -void j2k_setup_header_writting (opj_j2k_t *p_j2k) -{ - // preconditions - assert(p_j2k != 00); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_init_info ); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_soc ); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_siz ); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_cod ); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_qcd ); - - - if - (p_j2k->m_cp.m_specific_param.m_enc.m_cinema) - { - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_image_components ); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_tlm ); - if - (p_j2k->m_cp.m_specific_param.m_enc.m_cinema == CINEMA4K_24) - { - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_poc ); - } - } - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_regions); - - if - (p_j2k->m_cp.comment != 00) - { - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_com); - } - - /* DEVELOPER CORNER, insert your custom procedures */ - if - (p_j2k->m_cp.rsiz & MCT) - { - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_mct_data_group ); - } - /* End of Developer Corner */ - - if - (p_j2k->cstr_info) - { - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_get_end_header ); - } - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_create_tcd); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_update_rates); -} - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -void j2k_setup_end_compress (opj_j2k_t *p_j2k) -{ - // preconditions - assert(p_j2k != 00); - - /* DEVELOPER CORNER, insert your custom procedures */ - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_eoc ); - if - (p_j2k->m_cp.m_specific_param.m_enc.m_cinema) - { - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_updated_tlm); - } - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_write_epc ); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_end_encoding ); - opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_destroy_header_memory); -} - - - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -void j2k_setup_encoding_validation (opj_j2k_t *p_j2k) -{ - // preconditions - assert(p_j2k != 00); - opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_build_encoder); - opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_encoding_validation); - - - /* DEVELOPER CORNER, add your custom validation procedure */ - opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_mct_validation); -} - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -void j2k_setup_decoding_validation (opj_j2k_t *p_j2k) -{ - // preconditions - assert(p_j2k != 00); - opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_build_decoder); - opj_procedure_list_add_procedure(p_j2k->m_validation_list, (void*)j2k_decoding_validation); - /* DEVELOPER CORNER, add your custom validation procedure */ - -} - - -/** - * Excutes 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. - */ -bool 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 - ) -{ - bool (** l_procedure) (opj_j2k_t * ,opj_stream_private_t *,opj_event_mgr_t *) = 00; - bool l_result = 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 = (bool (**) (opj_j2k_t * ,opj_stream_private_t *,opj_event_mgr_t *)) opj_procedure_list_get_first_procedure(p_procedure_list); - for - (i=0;im_specific_param.m_decoder.m_state == J2K_DEC_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); - - if - ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) - { - opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); - return false; - } - if - ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) - { - opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n"); - return false; - } - - /* PARAMETER VALIDATION */ - return l_is_valid; -} - -/** - * 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. - */ -bool j2k_decoding_validation ( - opj_j2k_t *p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - bool l_is_valid = true; - - // preconditions - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - /* STATE checking */ - /* make sure the state is at 0 */ - l_is_valid &= (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_NONE); - - /* 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; -} - -/** - * 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. - */ -bool j2k_mct_validation ( - opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - bool l_is_valid = true; - OPJ_UINT32 i,j; - - // preconditions - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - 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;imct == 2) - { - opj_tccp_t * l_tccp = l_tcp->tccps; - l_is_valid &= (l_tcp->m_mct_coding_matrix != 00); - for - (j=0;jm_image->numcomps;++j) - { - l_is_valid &= ! (l_tccp->qmfbid & 1); - ++l_tccp; - } - } - ++l_tcp; - } - } - return l_is_valid; -} - -/** - * Builds the cp decoder parameters to use to decode tile. - */ -bool 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 - return true; -} - -/** - * Builds the cp encoder parameters to use to encode tile. - */ -bool 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 - return true; -} - -bool 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 in debug - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - l_image = p_j2k->m_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 * 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 * sizeof(OPJ_FLOAT32); - for - (i=0;itccps; - memcpy(l_tcp,l_default_tcp, sizeof(opj_tcp_t)); - l_tcp->ppt = 0; - l_tcp->ppt_data = 00; - l_tcp->tccps = l_current_tccp; - 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 false; - } - memcpy(l_tcp->m_mct_decoding_matrix,l_default_tcp->m_mct_decoding_matrix,l_mct_size); - } - l_mct_records_size = l_default_tcp->m_nb_max_mct_records * 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 false; - } - memcpy(l_tcp->m_mct_records, l_default_tcp->m_mct_records,l_mct_records_size); - l_src_mct_rec = l_default_tcp->m_mct_records; - l_dest_mct_rec = l_tcp->m_mct_records; - for - (j=0;jm_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 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; - } - l_mcc_records_size = l_default_tcp->m_nb_max_mcc_records * 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 false; - } - memcpy(l_tcp->m_mcc_records,l_default_tcp->m_mcc_records,l_mcc_records_size); - l_src_mcc_rec = l_default_tcp->m_mcc_records; - l_dest_mcc_rec = l_tcp->m_mcc_records; - for - (j=0;jm_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; - } - memcpy(l_current_tccp,l_default_tcp->tccps,l_tccp_size); - ++l_tcp; - } - p_j2k->m_tcd = tcd_create(true); - if - (! p_j2k->m_tcd ) - { - return false; - } - if - (! tcd_init(p_j2k->m_tcd, l_image, &(p_j2k->m_cp))) - { - 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 false; - } - return true; -} - -/** - * Destroys the memory associated with the decoding of headers. - */ -bool j2k_destroy_header_memory ( - opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - // preconditions in debug - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 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 = 0; - } - p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = 0; - return true; -} - -/** - * Sets up the decoder decoding parameters using user parameters. - * Decoding parameters are stored in p_j2k->m_cp. - * - * @param p_j2k J2K codec - * @param p_parameters decompression parameters - * @deprecated -*/ -void j2k_setup_decoder( - opj_j2k_t *p_j2k, - opj_dparameters_t *p_parameters - ) -{ - if - (p_j2k && p_parameters) - { - /* create and initialize the coding parameters structure */ - p_j2k->m_cp.m_specific_param.m_dec.m_reduce = p_parameters->cp_reduce; - p_j2k->m_cp.m_specific_param.m_dec.m_layer = p_parameters->cp_layer; - p_j2k->m_specific_param.m_decoder.m_discard_tiles = p_parameters->m_use_restrict_decode; - if - (p_parameters->m_use_restrict_decode) - { - p_j2k->m_specific_param.m_decoder.m_start_tile_x = p_parameters->m_decode_start_x; - p_j2k->m_specific_param.m_decoder.m_start_tile_y = p_parameters->m_decode_start_y; - p_j2k->m_specific_param.m_decoder.m_end_tile_x = p_parameters->m_decode_end_x; - p_j2k->m_specific_param.m_decoder.m_end_tile_y = p_parameters->m_decode_end_y; - } - -#ifdef USE_JPWL - cp->correct = parameters->jpwl_correct; - cp->exp_comps = parameters->jpwl_exp_comps; - cp->max_tiles = parameters->jpwl_max_tiles; -#endif /* USE_JPWL */ - } -} - -void j2k_setup_encoder(opj_j2k_t *p_j2k, opj_cparameters_t *parameters, opj_image_t *image, struct opj_event_mgr * p_manager) { - OPJ_UINT32 j, numpocs_tile; - OPJ_INT32 i; - OPJ_INT32 tileno; // must be signed because -1 is a potential error code - OPJ_INT32 jk; - opj_cp_t *cp = 00; - bool l_res; - if(!p_j2k || !parameters || ! image) { - return; - } - - /* 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; - - /* - copy user encoding parameters - */ - cp->m_specific_param.m_enc.m_cinema = parameters->cp_cinema; - cp->m_specific_param.m_enc.m_max_comp_size = parameters->max_comp_size; - cp->rsiz = parameters->cp_rsiz; - cp->m_specific_param.m_enc.m_disto_alloc = parameters->cp_disto_alloc; - cp->m_specific_param.m_enc.m_fixed_alloc = parameters->cp_fixed_alloc; - cp->m_specific_param.m_enc.m_fixed_quality = parameters->cp_fixed_quality; - - /* mod fixed_quality */ - if - (parameters->cp_matrice) - { - size_t array_size = parameters->tcp_numlayers * parameters->numresolution * 3 * sizeof(OPJ_INT32); - cp->m_specific_param.m_enc.m_matrice = (OPJ_INT32 *) opj_malloc(array_size); - memcpy(cp->m_specific_param.m_enc.m_matrice, parameters->cp_matrice, array_size); - } - - /* tiles */ - cp->tdx = parameters->cp_tdx; - cp->tdy = parameters->cp_tdy; - - /* tile offset */ - cp->tx0 = parameters->cp_tx0; - cp->ty0 = parameters->cp_ty0; - - /* comment string */ - if(parameters->cp_comment) { - cp->comment = (char*)opj_malloc(strlen(parameters->cp_comment) + 1); - if(cp->comment) { - strcpy(cp->comment, parameters->cp_comment); - } - } - - /* - calculate other encoding parameters - */ - - if (parameters->tile_size_on) { - cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx); - cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy); - } 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 = 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) { - - /* set JPWL on */ - cp->epc_on = true; - cp->info_on = false; /* no informative technique */ - - /* set EPB on */ - if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) { - cp->epb_on = 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 = 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 = false; - - } else { - cp->epc_on = false; - } -#endif /* USE_JPWL */ - - - /* initialize the mutiple tiles */ - /* ---------------------------- */ - cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); - if - (parameters->numpocs) - { - /* initialisation of POC */ - l_res = j2k_check_poc_val(parameters->POC,parameters->numpocs, parameters->numresolution, image->numcomps, parameters->tcp_numlayers, p_manager); - // TODO - } - for (tileno = 0; tileno < (OPJ_INT32)(cp->tw * cp->th); tileno++) { - opj_tcp_t *tcp = &cp->tcps[tileno]; - tcp->numlayers = parameters->tcp_numlayers; - for (j = 0; j < tcp->numlayers; j++) { - if(cp->m_specific_param.m_enc.m_cinema){ - if (cp->m_specific_param.m_enc.m_fixed_quality) { - tcp->distoratio[j] = parameters->tcp_distoratio[j]; - } - tcp->rates[j] = parameters->tcp_rates[j]; - }else{ - if (cp->m_specific_param.m_enc.m_fixed_quality) { /* add fixed_quality */ - tcp->distoratio[j] = parameters->tcp_distoratio[j]; - } else { - tcp->rates[j] = parameters->tcp_rates[j]; - } - } - } - tcp->csty = parameters->csty; - tcp->prg = parameters->prog_order; - tcp->mct = parameters->tcp_mct; - - - - numpocs_tile = 0; - tcp->POC = 0; - if - (parameters->numpocs) - { - /* initialisation of POC */ - tcp->POC = 1; - // TODO - for (i = 0; i < parameters->numpocs; i++) { - if((tileno == parameters->POC[i].tile - 1) || (parameters->POC[i].tile == -1)) { - opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile]; - 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 = parameters->POC[numpocs_tile].compno1; - tcp_poc->prg1 = parameters->POC[numpocs_tile].prg1; - tcp_poc->tile = parameters->POC[numpocs_tile].tile; - numpocs_tile++; - } - } - tcp->numpocs = numpocs_tile -1 ; - }else{ - tcp->numpocs = 0; - } - - tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t)); - if - (parameters->mct_data) - { - OPJ_UINT32 lMctSize = image->numcomps * image->numcomps * sizeof(OPJ_FLOAT32); - OPJ_FLOAT32 * lTmpBuf = (OPJ_FLOAT32*)opj_malloc(lMctSize); - OPJ_INT32 * l_dc_shift = (OPJ_INT32 *) ((OPJ_BYTE *) parameters->mct_data + lMctSize); - tcp->mct = 2; - tcp->m_mct_coding_matrix = (OPJ_FLOAT32*)opj_malloc(lMctSize); - 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); - assert(opj_matrix_inversion_f(lTmpBuf,(tcp->m_mct_decoding_matrix),image->numcomps)); - tcp->mct_norms = (OPJ_FLOAT64*) - opj_malloc(image->numcomps * sizeof(OPJ_FLOAT64)); - opj_calculate_norms(tcp->mct_norms,image->numcomps,tcp->m_mct_decoding_matrix); - opj_free(lTmpBuf); - for - (j = 0; j < image->numcomps; j++) - { - opj_tccp_t *tccp = &tcp->tccps[j]; - tccp->m_dc_level_shift = l_dc_shift[j]; - } - j2k_setup_mct_encoding(tcp,image); - } - else - { - for - (j = 0; j < image->numcomps; j++) - { - opj_tccp_t *tccp = &tcp->tccps[j]; - opj_image_comp_t * l_comp = &(image->comps[j]); - if - (! l_comp->sgnd) - { - tccp->m_dc_level_shift = 1 << (l_comp->prec - 1); - } - } - } - - - for (i = 0; i < (OPJ_INT32)(image->numcomps); i++) { - opj_tccp_t *tccp = &tcp->tccps[i]; - tccp->csty = parameters->csty & 0x01; /* 0 => one precinct || 1 => custom precinct */ - tccp->numresolutions = parameters->numresolution; - tccp->cblkw = int_floorlog2(parameters->cblockw_init); - tccp->cblkh = int_floorlog2(parameters->cblockh_init); - tccp->cblksty = parameters->mode; - tccp->qmfbid = parameters->irreversible ? 0 : 1; - tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT; - tccp->numgbits = 2; - if (i == parameters->roi_compno) { - tccp->roishift = parameters->roi_shift; - } else { - tccp->roishift = 0; - } - - if(parameters->cp_cinema) - { - //Precinct size for lowest frequency subband=128 - tccp->prcw[0] = 7; - tccp->prch[0] = 7; - //Precinct size at all other resolutions = 256 - for (j = 1; j < tccp->numresolutions; j++) { - tccp->prcw[j] = 8; - tccp->prch[j] = 8; - } - }else{ - if (parameters->csty & J2K_CCP_CSTY_PRT) { - int p = 0; - for (jk = tccp->numresolutions - 1; jk >= 0; jk--) { - if (p < parameters->res_spec) { - - if (parameters->prcw_init[p] < 1) { - tccp->prcw[jk] = 1; - } else { - tccp->prcw[jk] = int_floorlog2(parameters->prcw_init[p]); - } - - if (parameters->prch_init[p] < 1) { - tccp->prch[jk] = 1; - }else { - tccp->prch[jk] = int_floorlog2(parameters->prch_init[p]); - } - - } else { - int res_spec = parameters->res_spec; - int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1)); - int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1)); - - if (size_prcw < 1) { - tccp->prcw[jk] = 1; - } else { - tccp->prcw[jk] = int_floorlog2(size_prcw); - } - - if (size_prch < 1) { - tccp->prch[jk] = 1; - } else { - tccp->prch[jk] = int_floorlog2(size_prch); - } - } - p++; - /*printf("\nsize precinct for level %d : %d,%d\n", jk,tccp->prcw[jk], tccp->prch[jk]); */ - } //end for - } else { - for (j = 0; j < tccp->numresolutions; j++) { - tccp->prcw[j] = 15; - tccp->prch[j] = 15; - } - } - } - - dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec); - } - } - if - (parameters->mct_data) - { - opj_free(parameters->mct_data); - parameters->mct_data = 00; - } -} - -bool j2k_write_first_tile_part ( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_total_data_size, - opj_stream_private_t *p_stream, - struct opj_event_mgr * p_manager - ) -{ - OPJ_UINT32 compno; - OPJ_UINT32 l_nb_bytes_written = 0; - OPJ_UINT32 l_current_nb_bytes_written; - OPJ_BYTE * l_begin_data = 00; - - 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; - - 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 - (! j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) - { - return false; - } - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - - if - (l_cp->m_specific_param.m_enc.m_cinema == 0) - { - for - (compno = 1; compno < p_j2k->m_image->numcomps; compno++) - { - l_current_nb_bytes_written = 0; - 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; - p_total_data_size -= l_current_nb_bytes_written; - - l_current_nb_bytes_written = 0; - 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; - p_total_data_size -= l_current_nb_bytes_written; - } - if - (l_cp->tcps[p_j2k->m_current_tile_number].numpocs) - { - l_current_nb_bytes_written = 0; - 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; - p_total_data_size -= l_current_nb_bytes_written; - } - } - l_current_nb_bytes_written = 0; - if - (! j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) - { - return 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 - (l_cp->m_specific_param.m_enc.m_cinema) - { - j2k_update_tlm(p_j2k,l_nb_bytes_written); - } - return true; -} - -bool j2k_write_all_tile_parts( - opj_j2k_t *p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 * p_data_written, - OPJ_UINT32 p_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 = j2k_get_num_tp(l_cp,0,p_j2k->m_current_tile_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 - (! j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) - { - return false; - } - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - l_part_tile_size += l_nb_bytes_written; - - l_current_nb_bytes_written = 0; - if - (! j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) - { - return false; - } - p_data += l_current_nb_bytes_written; - l_nb_bytes_written += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - l_part_tile_size += l_nb_bytes_written; - - /* Writing Psot in SOT marker */ - opj_write_bytes(l_begin_data + 6,l_part_tile_size,4); /* PSOT */ - - if - (l_cp->m_specific_param.m_enc.m_cinema) - { - 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 = 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 - (! j2k_write_sot(p_j2k,p_data,&l_current_nb_bytes_written,p_stream,p_manager)) - { - return false; - } - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_total_data_size -= l_current_nb_bytes_written; - l_part_tile_size += l_current_nb_bytes_written; - - l_current_nb_bytes_written = 0; - if - (! j2k_write_sod(p_j2k,l_tcd,p_data,&l_current_nb_bytes_written,p_total_data_size,p_stream,p_manager)) - { - return false; - } - l_nb_bytes_written += l_current_nb_bytes_written; - p_data += l_current_nb_bytes_written; - p_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 - (l_cp->m_specific_param.m_enc.m_cinema) - { - 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 true; -} - - -bool 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 - ) -{ - 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 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 - (! tcd_init_encode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) - { - return false; - } - return true; -} - -/** - * Writes a tile. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool 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 - (! j2k_pre_write_tile(p_j2k,p_tile_index,p_stream,p_manager)) - { - return false; - } - return j2k_post_write_tile(p_j2k,p_data,p_data_size,p_stream,p_manager); -} - -/** - * Writes a tile. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool j2k_post_write_tile ( - opj_j2k_t * p_j2k, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - opj_tcd_t * l_tcd = 00; - opj_cp_t * l_cp = 00; - opj_tcp_t * l_tcp = 00; - OPJ_UINT32 l_nb_bytes_written; - OPJ_BYTE * l_current_data = 00; - OPJ_UINT32 l_tile_size = 0; - OPJ_UINT32 l_available_data; - - assert(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data); - - l_tcd = p_j2k->m_tcd; - l_cp = &(p_j2k->m_cp); - l_tcp = l_cp->tcps + p_j2k->m_current_tile_number; - - 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; - if - (! tcd_copy_tile_data(l_tcd,p_data,p_data_size)) - { - opj_event_msg(p_manager, EVT_ERROR, "Size mismtach between tile data and sent data." ); - return false; - } - - l_nb_bytes_written = 0; - if - (! j2k_write_first_tile_part(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) - { - return false; - } - l_current_data += l_nb_bytes_written; - l_available_data -= l_nb_bytes_written; - - l_nb_bytes_written = 0; - if - (! j2k_write_all_tile_parts(p_j2k,l_current_data,&l_nb_bytes_written,l_available_data,p_stream,p_manager)) - { - return 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) != (OPJ_INT32)l_nb_bytes_written) - { - return false; - } - ++p_j2k->m_current_tile_number; - return true; -} - -/** - * Reads a tile header. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool 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, - 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 = 00; - OPJ_UINT32 l_nb_tiles; - - // preconditions - assert(p_stream != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - if - (p_j2k->m_specific_param.m_decoder.m_state == J2K_DEC_STATE_EOC) - { - l_current_marker = J2K_MS_EOC; - } - else if - (p_j2k->m_specific_param.m_decoder.m_state != J2K_DEC_STATE_TPHSOT) - { - return false; - } - - while - (! p_j2k->m_specific_param.m_decoder.m_can_decode && l_current_marker != J2K_MS_EOC) - { - while - (l_current_marker != J2K_MS_SOD) - { - 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 false; - } - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2); - if - (p_j2k->m_specific_param.m_decoder.m_state & J2K_DEC_STATE_TPH) - { - p_j2k->m_specific_param.m_decoder.m_sot_length -= (l_marker_size + 2); - } - l_marker_size -= 2; - - l_marker_handler = j2k_get_marker_handler(l_current_marker); - // Check if the marker is known - 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 false; - } - if - (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) - { - p_j2k->m_specific_param.m_decoder.m_header_data = (OPJ_BYTE*) - opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size); - if - (p_j2k->m_specific_param.m_decoder.m_header_data == 00) - { - return false; - } - p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; - - } - if - (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager) != (OPJ_INT32)l_marker_size) - { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return false; - } - 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 is not compliant with its position\n"); - return false; - } - if - (p_j2k->m_specific_param.m_decoder.m_skip_data) - { - 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 false; - } - l_current_marker = J2K_MS_SOD; - } - else - { - 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 false; - } - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); - } - } - - if - (! p_j2k->m_specific_param.m_decoder.m_skip_data) - { - if - (! j2k_read_sod(p_j2k,p_stream,p_manager)) - { - return false; - } - } - else - { - 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_DEC_STATE_TPHSOT; - 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 false; - } - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); - } - } - - if - (l_current_marker == J2K_MS_EOC) - { - if - (p_j2k->m_specific_param.m_decoder.m_state != J2K_DEC_STATE_EOC) - { - p_j2k->m_current_tile_number = 0; - p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_EOC; - } - } - if - ( ! p_j2k->m_specific_param.m_decoder.m_can_decode) - { - l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number; - l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - 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 = false; - return true; - } - } - if - (! tcd_init_decode_tile(p_j2k->m_tcd, p_j2k->m_current_tile_number)) - { - opj_event_msg(p_manager, EVT_ERROR, "Cannot decode tile, memory error\n"); - return false; - } - *p_tile_index = p_j2k->m_current_tile_number; - *p_go_on = true; - *p_data_size = tcd_get_decoded_tile_size(p_j2k->m_tcd); - * 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_DEC_STATE_DATA; - return true; -} - -bool 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; - - // preconditions - assert(p_stream != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - if - (! (p_j2k->m_specific_param.m_decoder.m_state & J2K_DEC_STATE_DATA) || p_tile_index != p_j2k->m_current_tile_number) - { - return false; - } - l_tcp = &(p_j2k->m_cp.tcps[p_tile_index]); - if - (! l_tcp->m_data) - { - j2k_tcp_destroy(&(p_j2k->m_cp.tcps[p_tile_index])); - return false; - } - if - (! tcd_decode_tile(p_j2k->m_tcd, l_tcp->m_data, l_tcp->m_data_size, p_tile_index, p_j2k->cstr_info)) - { - j2k_tcp_destroy(l_tcp); - p_j2k->m_specific_param.m_decoder.m_state |= J2K_DEC_STATE_ERR; - return false; - } - if - (! tcd_update_tile_data(p_j2k->m_tcd,p_data,p_data_size)) - { - return false; - } - j2k_tcp_destroy(l_tcp); - p_j2k->m_tcd->tcp = 0; - - p_j2k->m_specific_param.m_decoder.m_can_decode = 0; - p_j2k->m_specific_param.m_decoder.m_state &= (~J2K_DEC_STATE_DATA); - if - (p_j2k->m_specific_param.m_decoder.m_state != J2K_DEC_STATE_EOC) - { - if - (opj_stream_read_data(p_stream,l_data,2,p_manager) != 2) - { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return false; - } - 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_DEC_STATE_EOC; - } - else if - (l_current_marker != J2K_MS_SOT) - { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short, expected SOT\n"); - return false; - } - } - return true; -} - - -/** - * Ends the compression procedures and possibiliy add data to be read after the - * codestream. - */ -bool j2k_end_compress(opj_j2k_t *p_j2k, struct opj_stream_private *p_stream, struct opj_event_mgr * p_manager) -{ - /* customization of the encoding */ - j2k_setup_end_compress(p_j2k); - - if - (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) - { - return false; - } - return true; -} - -/** - * Reads a jpeg2000 codestream header structure. - * - * @param p_stream the stream to read data from. - * @param p_j2k the jpeg2000 codec. - * @param p_manager the user event manager. - * - * @return true if the box is valid. - */ -bool j2k_read_header( - opj_j2k_t *p_j2k, - struct opj_image ** p_image, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_UINT32 * p_tile_width, - OPJ_UINT32 * p_tile_height, - OPJ_UINT32 * p_nb_tiles_x, - OPJ_UINT32 * p_nb_tiles_y, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) -{ - // preconditions - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - *p_image = 00; - /* create an empty image */ - p_j2k->m_image = opj_image_create0(); - if - (! p_j2k->m_image) - { - return false; - } - - /* customization of the validation */ - j2k_setup_decoding_validation (p_j2k); - - /* validation of the parameters codec */ - if - (! j2k_exec(p_j2k,p_j2k->m_validation_list,p_stream,p_manager)) - { - opj_image_destroy(p_j2k->m_image); - p_j2k->m_image = 00; - return false; - } - - /* customization of the encoding */ - j2k_setup_header_reading(p_j2k); - - /* read header */ - if - (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) - { - opj_image_destroy(p_j2k->m_image); - p_j2k->m_image = 00; - return false; - } - *p_image = p_j2k->m_image; - * p_tile_x0 = p_j2k->m_cp.tx0; - * p_tile_y0 = p_j2k->m_cp.ty0; - * p_tile_width = p_j2k->m_cp.tdx; - * p_tile_height = p_j2k->m_cp.tdy; - * p_nb_tiles_x = p_j2k->m_cp.tw; - * p_nb_tiles_y = p_j2k->m_cp.th; - return true; -} - -/** - * The read header procedure. - */ -bool j2k_read_header_procedure( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager) -{ - OPJ_UINT32 l_current_marker; - OPJ_UINT32 l_marker_size; - const opj_dec_memory_marker_handler_t * l_marker_handler = 00; - - // preconditions - assert(p_stream != 00); - assert(p_j2k != 00); - assert(p_manager != 00); - - p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_MHSOC; - - if - (! j2k_read_soc(p_j2k,p_stream,p_manager)) - { - opj_event_msg(p_manager, EVT_ERROR, "Expected a SOC marker \n"); - return false; - } - 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 false; - } - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); - - while - (l_current_marker != J2K_MS_SOT) - { - 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 false; - } - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_marker_size,2); - l_marker_size -= 2; - /*if - (l_current_marker < 0xff00) - { - opj_event_msg(p_manager, EVT_ERROR, "%.8x: expected a marker instead of %x\n", opj_stream_tell(p_stream) - 2, l_current_marker); - return 0; - } - */ - l_marker_handler = j2k_get_marker_handler(l_current_marker); - // Check if the marker is known - 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 false; - } - if - (l_marker_size > p_j2k->m_specific_param.m_decoder.m_header_data_size) - { - p_j2k->m_specific_param.m_decoder.m_header_data = (OPJ_BYTE*) - opj_realloc(p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size); - if - (p_j2k->m_specific_param.m_decoder.m_header_data == 00) - { - return false; - } - p_j2k->m_specific_param.m_decoder.m_header_data_size = l_marker_size; - } - if - (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,l_marker_size,p_manager) != (OPJ_INT32)l_marker_size) - { - opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n"); - return false; - } - 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 is not compliant with its position\n"); - return false; - } - 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 false; - } - opj_read_bytes(p_j2k->m_specific_param.m_decoder.m_header_data,&l_current_marker,2); - } - p_j2k->m_specific_param.m_decoder.m_state = J2K_DEC_STATE_TPHSOT; - return true; -} - - - -/** - * Reads the tiles. - */ -bool j2k_decode_tiles ( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager) -{ - bool l_go_on = true; - OPJ_UINT32 l_current_tile_no; - OPJ_UINT32 l_data_size,l_max_data_size; - OPJ_INT32 l_tile_x0,l_tile_y0,l_tile_x1,l_tile_y1; - OPJ_UINT32 l_nb_comps; - OPJ_BYTE * l_current_data; - - l_current_data = (OPJ_BYTE*)opj_malloc(1000); - if - (! l_current_data) - { - return false; - } - l_max_data_size = 1000; - - while - (true) - { - if - (! j2k_read_tile_header( - p_j2k,&l_current_tile_no, - &l_data_size, - &l_tile_x0, - &l_tile_y0, - &l_tile_x1, - &l_tile_y1, - &l_nb_comps, - &l_go_on, - p_stream, - p_manager)) - { - return false; - } - if - (! l_go_on) - { - break; - } - if - (l_data_size > l_max_data_size) - { - l_current_data = (OPJ_BYTE*)opj_realloc(l_current_data,l_data_size); - if - (! l_current_data) - { - return false; - } - l_max_data_size = l_data_size; - } - if - (! j2k_decode_tile(p_j2k,l_current_tile_no,l_current_data,l_data_size,p_stream,p_manager)) - { - opj_free(l_current_data); - return false; - } - if - (! j2k_update_image_data(p_j2k->m_tcd,l_current_data)) - { - opj_free(l_current_data); - return false; - } - - } - opj_free(l_current_data); - return true; -} - - - - - - -/** - * Decodes the tiles of the stream. - */ -opj_image_t * j2k_decode( - opj_j2k_t * p_j2k, - opj_stream_private_t * p_stream, - opj_event_mgr_t * p_manager) -{ - /* customization of the encoding */ - j2k_setup_decoding(p_j2k); - - /* write header */ - if - (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) - { - opj_image_destroy(p_j2k->m_image); - p_j2k->m_image = 00; - } - return p_j2k->m_image; -} - -/** - * Encodes all the tiles in a row. - */ -bool j2k_encode( - opj_j2k_t * p_j2k, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - OPJ_UINT32 i; - OPJ_UINT32 l_nb_tiles; - OPJ_UINT32 l_max_tile_size, l_current_tile_size; - OPJ_BYTE * l_current_data; - - // preconditions - assert(p_j2k != 00); - assert(p_stream != 00); - assert(p_manager != 00); - - l_current_data = (OPJ_BYTE*)opj_malloc(1000); - if - (! l_current_data) - { - return false; - } - l_max_tile_size = 1000; - - l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw; - for - (i=0;im_tcd); - if - (l_current_tile_size > l_max_tile_size) - { - l_current_data = (OPJ_BYTE*)opj_realloc(l_current_data,l_current_tile_size); - if - (! l_current_data) - { - return false; - } - l_max_tile_size = l_current_tile_size; - } - j2k_get_tile_data(p_j2k->m_tcd,l_current_data); - if - (! j2k_post_write_tile (p_j2k,l_current_data,l_current_tile_size,p_stream,p_manager)) - { - return false; - } - } - opj_free(l_current_data); - return true; -} - - - -/** - * Ends the decompression procedures and possibiliy add data to be read after the - * codestream. - */ -bool j2k_end_decompress( - opj_j2k_t *p_j2k, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager) -{ - return true; -} - - - -void j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data) -{ - OPJ_UINT32 i,j,k = 0; - OPJ_UINT32 l_width,l_height,l_stride, l_offset_x,l_offset_y, l_image_width; - opj_image_comp_t * l_img_comp = 00; - opj_tcd_tilecomp_t * l_tilec = 00; - opj_image_t * l_image = 00; - OPJ_UINT32 l_size_comp, l_remaining; - OPJ_INT32 * l_src_ptr; - l_tilec = p_tcd->tcd_image->tiles->comps; - l_image = p_tcd->image; - l_img_comp = l_image->comps; - for - (i=0;iimage->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_width = (l_tilec->x1 - l_tilec->x0); - l_height = (l_tilec->y1 - l_tilec->y0); - l_offset_x = int_ceildiv(l_image->x0, l_img_comp->dx); - l_offset_y = int_ceildiv(l_image->y0, l_img_comp->dy); - l_image_width = int_ceildiv(l_image->x1 - l_image->x0, l_img_comp->dx); - l_stride = l_image_width - l_width; - l_src_ptr = l_img_comp->data + (l_tilec->x0 - l_offset_x) + (l_tilec->y0 - l_offset_y) * l_image_width; - - switch - (l_size_comp) - { - case 1: - { - OPJ_CHAR * l_dest_ptr = (OPJ_CHAR*) p_data; - if - (l_img_comp->sgnd) - { - for - (j=0;jsgnd) - { - for - (j=0;jtcd_image->tiles->comps; - l_image = p_tcd->image; - l_img_comp = l_image->comps; - for - (i=0;iimage->numcomps;++i) - { - if - (!l_img_comp->data) - { - l_img_comp->data = (OPJ_INT32*) opj_malloc(l_img_comp->w * l_img_comp->h * sizeof(OPJ_INT32)); - if - (! l_img_comp->data) - { - return false; - } - memset(l_img_comp->data,0,l_img_comp->w * l_img_comp->h * sizeof(OPJ_INT32)); - } - - 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 - (l_remaining) - { - ++l_size_comp; - } - if - (l_size_comp == 3) - { - l_size_comp = 4; - } - l_width = (l_res->x1 - l_res->x0); - l_height = (l_res->y1 - l_res->y0); - l_dest_stride = (l_img_comp->w) - l_width; - l_offset_x = int_ceildivpow2(l_img_comp->x0, l_img_comp->factor); - l_offset_y = int_ceildivpow2(l_img_comp->y0, l_img_comp->factor); - l_dest_ptr = l_img_comp->data + (l_res->x0 - l_offset_x) + (l_res->y0 - l_offset_y) * l_img_comp->w; - - switch - (l_size_comp) - { - case 1: - { - OPJ_CHAR * l_src_ptr = (OPJ_CHAR*) p_data; - if - (l_img_comp->sgnd) - { - for - (j=0;jsgnd) - { - for - (j=0;jm_cp); - - if - (p_j2k->m_specific_param.m_decoder.m_state != J2K_DEC_STATE_TPHSOT) - { - return false; - } - p_j2k->m_specific_param.m_decoder.m_start_tile_x = (p_start_x - l_cp->tx0) / l_cp->tdx; - p_j2k->m_specific_param.m_decoder.m_start_tile_y = (p_start_y - l_cp->ty0) / l_cp->tdy; - p_j2k->m_specific_param.m_decoder.m_end_tile_x = int_ceildiv((p_end_x - l_cp->tx0), l_cp->tdx); - p_j2k->m_specific_param.m_decoder.m_end_tile_y = int_ceildiv((p_end_y - l_cp->ty0), l_cp->tdy); - p_j2k->m_specific_param.m_decoder.m_discard_tiles = 1; - return true; -} - -void j2k_dump_image(FILE *fd, opj_image_t * img) { - OPJ_UINT32 compno; - fprintf(fd, "image {\n"); - fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d\n", img->x0, img->y0, img->x1, img->y1); - fprintf(fd, " numcomps=%d\n", img->numcomps); - for (compno = 0; compno < img->numcomps; compno++) { - opj_image_comp_t *comp = &img->comps[compno]; - fprintf(fd, " comp %d {\n", compno); - fprintf(fd, " dx=%d, dy=%d\n", comp->dx, comp->dy); - fprintf(fd, " prec=%d\n", comp->prec); - //fprintf(fd, " bpp=%d\n", comp->bpp); - fprintf(fd, " sgnd=%d\n", comp->sgnd); - fprintf(fd, " }\n"); - } - fprintf(fd, "}\n"); -} - -/* -void j2k_dump_cp(FILE *fd, opj_image_t * img, opj_cp_t * cp) { - int tileno, compno, layno, bandno, resno, numbands; - fprintf(fd, "coding parameters {\n"); - fprintf(fd, " tx0=%d, ty0=%d\n", cp->tx0, cp->ty0); - fprintf(fd, " tdx=%d, tdy=%d\n", cp->tdx, cp->tdy); - fprintf(fd, " tw=%d, th=%d\n", cp->tw, cp->th); - for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { - opj_tcp_t *tcp = &cp->tcps[tileno]; - fprintf(fd, " tile %d {\n", tileno); - fprintf(fd, " csty=%x\n", tcp->csty); - fprintf(fd, " prg=%d\n", tcp->prg); - fprintf(fd, " numlayers=%d\n", tcp->numlayers); - fprintf(fd, " mct=%d\n", tcp->mct); - fprintf(fd, " rates="); - for (layno = 0; layno < tcp->numlayers; layno++) { - fprintf(fd, "%.1f ", tcp->rates[layno]); - } - fprintf(fd, "\n"); - for (compno = 0; compno < img->numcomps; compno++) { - opj_tccp_t *tccp = &tcp->tccps[compno]; - fprintf(fd, " comp %d {\n", compno); - fprintf(fd, " csty=%x\n", tccp->csty); - fprintf(fd, " numresolutions=%d\n", tccp->numresolutions); - fprintf(fd, " cblkw=%d\n", tccp->cblkw); - fprintf(fd, " cblkh=%d\n", tccp->cblkh); - fprintf(fd, " cblksty=%x\n", tccp->cblksty); - fprintf(fd, " qmfbid=%d\n", tccp->qmfbid); - fprintf(fd, " qntsty=%d\n", tccp->qntsty); - fprintf(fd, " numgbits=%d\n", tccp->numgbits); - fprintf(fd, " roishift=%d\n", tccp->roishift); - fprintf(fd, " stepsizes="); - numbands = tccp->qntsty == J2K_CCP_QNTSTY_SIQNT ? 1 : tccp->numresolutions * 3 - 2; - for (bandno = 0; bandno < numbands; bandno++) { - fprintf(fd, "(%d,%d) ", tccp->stepsizes[bandno].mant, - tccp->stepsizes[bandno].expn); - } - fprintf(fd, "\n"); - - if (tccp->csty & J2K_CCP_CSTY_PRT) { - fprintf(fd, " prcw="); - for (resno = 0; resno < tccp->numresolutions; resno++) { - fprintf(fd, "%d ", tccp->prcw[resno]); - } - fprintf(fd, "\n"); - fprintf(fd, " prch="); - for (resno = 0; resno < tccp->numresolutions; resno++) { - fprintf(fd, "%d ", tccp->prch[resno]); - } - fprintf(fd, "\n"); - } - fprintf(fd, " }\n"); - } - fprintf(fd, " }\n"); - } - fprintf(fd, "}\n"); -} -*/ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k.h deleted file mode 100644 index 7b145384b49..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k.h +++ /dev/null @@ -1,737 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2006-2007, Parvatha Elangovan - * 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 __J2K_H -#define __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. -*/ - -#include "openjpeg.h" - -struct opj_dparameters; -struct opj_stream_private; -struct opj_event_mgr; -/** @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 -#define J2K_CCP_CBLKSTY_RESET 0x02 -#define J2K_CCP_CBLKSTY_TERMALL 0x04 -#define J2K_CCP_CBLKSTY_VSC 0x08 -#define J2K_CCP_CBLKSTY_PTERM 0x10 -#define J2K_CCP_CBLKSTY_SEGSYM 0x20 -#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_SIZ 0xff51 /**< SIZ marker value */ -#define J2K_MS_COD 0xff52 /**< COD marker value */ -#define J2K_MS_COC 0xff53 /**< COC 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 */ - -/* 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 */ -/* < there was a PPT marker for the present tile */ - OPJ_UINT32 ppt : 1; - /** indicates if a POC marker has been used O:NO, 1:YES */ - OPJ_UINT32 POC : 1; -} opj_tcp_t; - -typedef struct opj_encoding_param -{ - /** Digital cinema profile*/ - OPJ_CINEMA_MODE m_cinema; - /** 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; - /** allocation by rate/distortion */ - OPJ_UINT32 m_disto_alloc : 1; - /** allocation by fixed layer */ - OPJ_UINT32 m_fixed_alloc : 1; - /** add fixed_quality */ - OPJ_UINT32 m_fixed_quality : 1; - /** Enabling Tile part generation*/ - OPJ_UINT32 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_RSIZ_CAPABILITIES rsiz; - /** XTOsiz */ - OPJ_INT32 tx0; - /** YTOsiz */ - OPJ_INT32 ty0; - /** XTsiz */ - OPJ_UINT32 tdx; - /** YTsiz */ - OPJ_UINT32 tdy; - /** comment */ - OPJ_CHAR *comment; - /** number of tiles in width */ - OPJ_UINT32 tw; - /** number of tiles in heigth */ - OPJ_UINT32 th; - /** packet header storage original buffer */ - OPJ_BYTE *ppm_buffer; - /** packet header store there for futur use in t2_decode_packet */ - OPJ_BYTE *ppm_data; - /** size of the ppm_data*/ - OPJ_UINT32 ppm_len; - /** Number of bytes actually stored inside the ppm_data */ - OPJ_UINT32 ppm_data_size; - /** tile coding parameters */ - opj_tcp_t *tcps; - union - { - opj_decoding_param_t m_dec; - opj_encoding_param_t m_enc; - } - m_specific_param; - - -/* UniPG>> */ -#ifdef USE_JPWL - /** enables writing of EPC in MH, thus activating JPWL */ - bool epc_on; - /** enables writing of EPB, in case of activated JPWL */ - bool epb_on; - /** enables writing of ESD, in case of activated JPWL */ - bool esd_on; - /** enables writing of informative techniques of ESD, in case of activated JPWL */ - bool info_on; - /** enables writing of RED, in case of activated JPWL */ - 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 */ - bool correct; - /** expected number of components at the decoder */ - int exp_comps; - /** maximum number of tiles at the decoder */ - int max_tiles; -#endif /* USE_JPWL */ - - /******** FLAGS *********/ - /** if ppm == 1 --> there was a PPM marker*/ - OPJ_UINT32 ppm : 1; - /** tells if the parameter is a coding or decoding one */ - OPJ_UINT32 m_is_decoder : 1; -/* <cp. - * - * @param p_j2k J2K codec - * @param p_parameters decompression parameters - * @deprecated -*/ -void j2k_setup_decoder( - opj_j2k_t *p_j2k, - struct opj_dparameters *p_parameters - ); -/** - * Reads a jpeg2000 codestream header structure. - * - * @param cio the stream to read data from. - * @param p_j2k the jpeg2000 codec. - * @param p_manager the user event manager. - * - * @return true if the box is valid. - */ -bool j2k_read_header( - opj_j2k_t *p_j2k, - struct opj_image ** p_image, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_UINT32 * p_tile_width, - OPJ_UINT32 * p_tile_height, - OPJ_UINT32 * p_nb_tiles_x, - OPJ_UINT32 * p_nb_tiles_y, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ); -/** -Decode an image from a JPEG-2000 codestream -@param j2k J2K decompressor handle -@param cio Input buffer stream -@param cstr_info Codestream information structure if required, NULL otherwise -@return Returns a decoded image if successful, returns NULL otherwise -*/ -opj_image_t* j2k_decode(opj_j2k_t *j2k, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); - -/** - * Ends the decompression procedures and possibiliy add data to be read after the - * codestream. - */ -bool j2k_end_decompress(opj_j2k_t *j2k, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); - -/** -Decode an image form a JPT-stream (JPEG 2000, JPIP) -@param j2k J2K decompressor handle -@param cio Input buffer stream -@param cstr_info Codestream information structure if required, NULL otherwise -@return Returns a decoded image if successful, returns NULL otherwise -*/ -opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, struct opj_stream_private *cio, struct opj_codestream_info *cstr_info); - -/** -Creates a J2K compression structure -@param cinfo Codec context info -@return Returns a handle to a J2K compressor if successful, returns NULL otherwise -*/ -opj_j2k_t* j2k_create_compress(); - -/** -Setup the encoder parameters using the current image and using user parameters. -Coding parameters are returned in j2k->cp. -@param j2k J2K compressor handle -@param parameters compression parameters -@param image input filled image -*/ -void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_t *image, struct opj_event_mgr * p_manager); - -/** - * Writes a tile. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool j2k_write_tile ( - opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); - -/** - * Converts an enum type progression order to string type. - * - * @param prg_order the progression order to get. - * - * @return the string representation of the gicen progression order. - */ -const char * j2k_convert_progression_order(OPJ_PROG_ORDER prg_order); - - -/** - * Encodes an image into a JPEG-2000 codestream - */ -bool j2k_encode( - opj_j2k_t * p_j2k, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ); -bool j2k_setup_mct_encoding (opj_tcp_t * p_tcp,opj_image_t * p_image); - -/** - * Decode tile data. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool j2k_decode_tile ( - opj_j2k_t * p_j2k, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Reads a tile header. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool 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, - bool * p_go_on, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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_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). - * @param p_manager the user event manager - * - * @return true if the area could be set. - */ -bool j2k_set_decode_area( - opj_j2k_t *p_j2k, - OPJ_INT32 p_start_x, - OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, - OPJ_INT32 p_end_y, - struct opj_event_mgr * p_manager - ); - -void j2k_dump_image(FILE *fd, opj_image_t * img); - -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __J2K_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k_lib.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k_lib.c deleted file mode 100644 index 0c3c2c83089..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k_lib.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2005, Herv� 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. - */ - -#ifdef WIN32 -#include -#else -/*#include -#include -#include -*/ -#endif /* WIN32 */ -#include "j2k_lib.h" - - -OPJ_FLOAT64 opj_clock(void) { -#if 0 -#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 ( t.QuadPart /(double) freq.QuadPart ) ; -#else - /* Unix or Linux: use resource usage */ - struct rusage t; - double 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 = t.ru_utime.tv_sec + t.ru_stime.tv_sec; - /* (2b) More precisely! Get the microseconds part ! */ - return ( procTime + (t.ru_utime.tv_usec + t.ru_stime.tv_usec) * 1e-6 ) ; -#endif - -#endif - return 0; -} - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k_lib.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k_lib.h deleted file mode 100644 index c78c4f214be..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/j2k_lib.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2005, Herv� 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 __J2K_LIB_H -#define __J2K_LIB_H -/** -@file j2k_lib.h -@brief Internal functions - -The functions in J2K_LIB.C are internal utilities mainly used for timing. -*/ -#include "openjpeg.h" -/** @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 /* __J2K_LIB_H */ - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/jp2.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/jp2.c deleted file mode 100644 index 2c7d2b858c9..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/jp2.c +++ /dev/null @@ -1,2236 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 "jp2.h" -#include "cio.h" -#include "opj_malloc.h" -#include "event.h" -#include "j2k.h" -#include "function_list.h" -#include "assert.h" - -/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */ -/*@{*/ - -#define BOX_SIZE 1024 - - - -/** @name Local static functions */ -/*@{*/ - - - -/** - * Writes the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). - * - * @param cio the stream to write data to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager user event manager. - * - * @return true if writting was successful. -*/ -bool jp2_write_jp2h( - opj_jp2_t *jp2, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ); - -/** - * Skips the Jpeg2000 Codestream Header box - JP2C Header box. - * - * @param cio the stream to write data to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager user event manager. - * - * @return true if writting was successful. -*/ -bool jp2_skip_jp2c( - opj_jp2_t *jp2, - struct opj_stream_private *cio, - struct opj_event_mgr * 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 reconized. -*/ -bool jp2_read_jp2h( - opj_jp2_t *jp2, - unsigned char * p_header_data, - unsigned int p_header_size, - struct opj_event_mgr * 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 writting was successful. -*/ -static bool jp2_write_jp2c( - opj_jp2_t *jp2, - struct opj_stream_private *cio, - struct opj_event_mgr * 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 reconized, false otherwise -*/ -static bool jp2_read_boxhdr( - opj_jp2_box_t *box, - OPJ_UINT32 * p_number_bytes_read, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ); - -/** - * 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 p_data the character string 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_box_max_size the maximum number of bytes in the box. - * - * @return true if the box is reconized, false otherwise -*/ -static bool 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, - struct opj_event_mgr * p_manager - ); - -/** - * 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 bool jp2_read_jp( - opj_jp2_t *jp2, - unsigned char * p_header_data, - unsigned int p_header_size, - struct opj_event_mgr * 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 writting was successful. - */ -static bool jp2_write_jp( - opj_jp2_t *jp2, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ); - -/** - * 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 writting was successful. - */ -static bool jp2_write_ftyp( - opj_jp2_t *jp2, - struct opj_stream_private *cio, - struct opj_event_mgr * 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 bool jp2_read_ftyp( - opj_jp2_t *jp2, - unsigned char * p_header_data, - unsigned int p_header_size, - struct opj_event_mgr * p_manager - ); - -/** - * 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, fale else. - */ -static bool jp2_read_ihdr( - opj_jp2_t *jp2, - unsigned char * p_image_header_data, - unsigned int p_image_header_size, - struct opj_event_mgr * 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 unsigned char * jp2_write_ihdr( - opj_jp2_t *jp2, - unsigned int * 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, fale else. - */ -static bool jp2_read_bpcc( - opj_jp2_t *jp2, - unsigned char * p_bpc_header_data, - unsigned int p_bpc_header_size, - struct opj_event_mgr * p_manager - ); - - -/** - * 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 unsigned char * jp2_write_bpcc( - opj_jp2_t *jp2, - unsigned int * p_nb_bytes_written - ); - -/** - * Reads the Colour 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, fale else. -*/ -static bool jp2_read_colr( - opj_jp2_t *jp2, - unsigned char * p_colr_header_data, - unsigned int p_colr_header_size, - struct opj_event_mgr * p_manager - ); - -/** - * 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 unsigned char *jp2_write_colr( - opj_jp2_t *jp2, - unsigned int * p_nb_bytes_written - ); - - -/** - * Reads a jpeg2000 file header structure. - * - * @param cio the stream to read data from. - * @param jp2 the jpeg2000 file header structure. - * @param p_manager the user event manager. - * - * @return true if the box is valid. - */ -bool jp2_read_header_procedure( - opj_jp2_t *jp2, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ); -/** - * Excutes 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 cio the stream to execute the procedures on. - * @param p_manager the user manager. - * - * @return true if all the procedures were successfully executed. - */ -static bool jp2_exec ( - opj_jp2_t * jp2, - struct opj_procedure_list * p_procedure_list, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ); -/** - * 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 * jp2_find_handler (int p_id); - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -static void jp2_setup_encoding_validation (opj_jp2_t *jp2); - -/** - * Sets up the procedures to do on writting header. Developpers wanting to extend the library can add their own writting procedures. - */ -static void jp2_setup_header_writting (opj_jp2_t *jp2); - -/** - * The default validation procedure without any extension. - * - * @param jp2 the jpeg2000 codec to validate. - * @param cio the input stream to validate. - * @param p_manager the user event manager. - * - * @return true if the parameters are correct. - */ -bool jp2_default_validation ( - opj_jp2_t * jp2, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ); - -/** - * 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 * jp2_find_handler ( - int p_id - ); - -/** - * 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 * jp2_img_find_handler ( - int p_id - ); - -/** - * Sets up the procedures to do on writting header after the codestream. - * Developpers wanting to extend the library can add their own writting procedures. - */ -static void jp2_setup_end_header_writting (opj_jp2_t *jp2); - -/** - * Sets up the procedures to do on reading header after the codestream. - * Developpers wanting to extend the library can add their own writting procedures. - */ -static void jp2_setup_end_header_reading (opj_jp2_t *jp2); - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -static void jp2_setup_decoding_validation (opj_jp2_t *jp2); - -/** - * Sets up the procedures to do on reading header. - * Developpers wanting to extend the library can add their own writting procedures. - */ -static void jp2_setup_header_reading (opj_jp2_t *jp2); -/*@}*/ - -/*@}*/ - -/* ----------------------------------------------------------------------- */ -const opj_jp2_header_handler_t jp2_header [] = -{ - {JP2_JP,jp2_read_jp}, - {JP2_FTYP,jp2_read_ftyp}, - {JP2_JP2H,jp2_read_jp2h} -}; - -const opj_jp2_header_handler_t jp2_img_header [] = -{ - {JP2_IHDR,jp2_read_ihdr}, - {JP2_COLR,jp2_read_colr}, - {JP2_BPCC,jp2_read_bpcc} -}; -/** - * 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 00 if it could not be found. - */ -const opj_jp2_header_handler_t * jp2_find_handler ( - int p_id - ) -{ - unsigned int i, l_handler_size = sizeof(jp2_header) / sizeof(opj_jp2_header_handler_t); - for - (i=0;ijp2_state & JP2_STATE_HEADER) - { - jp2->jp2_state |= JP2_STATE_CODESTREAM; - opj_free(l_current_data); - return true; - } - else - { - opj_event_msg(p_manager, EVT_ERROR, "bad placed jpeg codestream\n"); - opj_free(l_current_data); - return 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 false; - } - - l_current_handler = jp2_find_handler(box.type); - l_current_data_size = box.length - l_nb_bytes_read; - - if - (l_current_handler != 00) - { - if - (l_current_data_size > l_last_data_size) - { - l_current_data = (unsigned char*)opj_realloc(l_current_data,l_current_data_size); - l_last_data_size = l_current_data_size; - } - l_nb_bytes_read = opj_stream_read_data(cio,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 false; - } - if - (! l_current_handler->handler(jp2,l_current_data,l_current_data_size,p_manager)) - { - opj_free(l_current_data); - return false; - } - } - else - { - jp2->jp2_state |= JP2_STATE_UNKNOWN; - if - (opj_stream_skip(cio,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 false; - } - } - } - opj_free(l_current_data); - return true; -} - -/** - * 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 (should usually be 8). - * @param p_manager user event manager. - * - * @return true if the box is reconized, false otherwise -*/ -bool 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 */ - unsigned char 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_stream_read_data(cio,l_data_header,8,p_manager); - if - (*p_number_bytes_read != 8) - { - return false; - } - /* process read data */ - opj_read_bytes(l_data_header,&(box->length), 4); - opj_read_bytes(l_data_header+4,&(box->type), 4); - - // 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_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 false; - } - 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 false; - } - opj_read_bytes(l_data_header,&(box->length), 4); - } - return true; -} - -/** - * 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 p_data the character string 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_box_max_size the maximum number of bytes in the box. - * - * @return true if the box is reconized, false otherwise -*/ -static bool 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 - ) -{ - // 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 false; - } - /* process read data */ - opj_read_bytes(p_data,&(box->length), 4); - p_data += 4; - opj_read_bytes(p_data,&(box->type), 4); - p_data += 4; - *p_number_bytes_read = 8; - - // do we have a "special very large box ?" - // read then the XLBox - if - (box->length == 1) - { - unsigned int 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 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 false; - } - opj_read_bytes(p_data,&(box->length), 4); - *p_number_bytes_read += 4; - if - (box->length == 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); - return false; - } - - } - else if - (box->length == 0) - { - opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box of undefined sizes\n"); - return false; - } - return true; -} - - -/** - * 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. - */ -bool jp2_read_jp( - opj_jp2_t *jp2, - unsigned char * p_header_data, - unsigned int p_header_size, - opj_event_mgr_t * p_manager - ) -{ - unsigned int 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 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 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 false; - } - jp2->jp2_state |= JP2_STATE_SIGNATURE; - return 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. - */ -bool jp2_read_ftyp( - opj_jp2_t *jp2, - unsigned char * p_header_data, - unsigned int p_header_size, - opj_event_mgr_t * p_manager - ) -{ - unsigned int i; - unsigned int 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 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 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 false; - } - /* div by 4 */ - jp2->numcl = l_remaining_bytes >> 2; - if - (jp2->numcl) - { - jp2->cl = (unsigned int *) opj_malloc(jp2->numcl * sizeof(unsigned int)); - if - (jp2->cl == 00) - { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory with FTYP Box\n"); - return false; - } - memset(jp2->cl,0,jp2->numcl * sizeof(unsigned int)); - } - - - 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 true; -} - -/** - * 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 writting was successful. - */ -bool jp2_write_jp ( - opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager - ) -{ - /* 12 bytes will be read */ - unsigned char l_signature_data [12]; - - // preconditions - assert(cio != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - - /* 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 false; - } - return true; -} - - -/** - * 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 writting was successful. - */ -bool jp2_write_ftyp( - opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager - ) -{ - unsigned int i; - unsigned int l_ftyp_size = 16 + 4 * jp2->numcl; - unsigned char * l_ftyp_data, * l_current_data_ptr; - bool l_result; - - // preconditions - assert(cio != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - l_ftyp_data = (unsigned char *) opj_malloc(l_ftyp_size); - - if - (l_ftyp_data == 00) - { - opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle ftyp data\n"); - return false; - } - memset(l_ftyp_data,0,l_ftyp_size); - - 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) == (OPJ_INT32)l_ftyp_size); - if - (! l_result) - { - opj_event_msg(p_manager, EVT_ERROR, "Error while writting ftyp data to stream\n"); - } - opj_free(l_ftyp_data); - return l_result; -} - -/** - * Writes the Jpeg2000 file Header box - JP2 Header box (warning, this is a super box). - * - * @param cio the stream to write data to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager user event manager. - * - * @return true if writting was successful. -*/ -bool jp2_write_jp2h( - opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager - ) -{ - opj_jp2_img_header_writer_handler_t l_writers [3]; - opj_jp2_img_header_writer_handler_t * l_current_writer; - - int i, l_nb_pass; - /* size of data for super box*/ - int l_jp2h_size = 8; - bool l_result = true; - - /* to store the data of the super box */ - unsigned char l_jp2h_data [8]; - - // preconditions - assert(cio != 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 = jp2_write_ihdr; - l_writers[1].handler = jp2_write_bpcc; - l_writers[2].handler = jp2_write_colr; - } - else - { - l_nb_pass = 2; - l_writers[0].handler = jp2_write_ihdr; - l_writers[1].handler = jp2_write_colr; - } - - /* write box header */ - /* write JP2H type */ - opj_write_bytes(l_jp2h_data+4,JP2_JP2H,4); - - l_current_writer = l_writers; - for - (i=0;im_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 = false; - break; - } - l_jp2h_size += l_current_writer->m_size; - ++l_current_writer; - } - - if - (! l_result) - { - l_current_writer = l_writers; - for - (i=0;im_data != 00) - { - opj_free(l_current_writer->m_data ); - } - ++l_current_writer; - } - return 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(cio,l_jp2h_data,8,p_manager) != 8) - { - opj_event_msg(p_manager, EVT_ERROR, "Stream error while writting JP2 Header box\n"); - l_result = false; - } - - if - (l_result) - { - l_current_writer = l_writers; - for - (i=0;im_data,l_current_writer->m_size,p_manager) != (OPJ_INT32)(l_current_writer->m_size) ) - { - opj_event_msg(p_manager, EVT_ERROR, "Stream error while writting JP2 Header box\n"); - l_result = false; - break; - } - ++l_current_writer; - } - } - l_current_writer = l_writers; - /* cleanup */ - for - (i=0;im_data != 00) - { - opj_free(l_current_writer->m_data ); - } - ++l_current_writer; - } - return l_result; -} - -/** - * 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 reconized. -*/ -bool jp2_read_jp2h( - opj_jp2_t *jp2, - unsigned char * p_header_data, - unsigned int p_header_size, - opj_event_mgr_t * p_manager - ) -{ - unsigned int l_box_size=0, l_current_data_size = 0; - opj_jp2_box_t box; - const opj_jp2_header_handler_t * l_current_handler; - - // 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 false; - } - jp2->jp2_img_state = JP2_IMG_STATE_NONE; - - /* iterate while remaining data */ - while - (p_header_size > 0) - { - if - (! 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 false; - } - if - (box.length > p_header_size) - { - opj_event_msg(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box\n"); - return false; - } - l_current_handler = 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 false; - } - } - else - { - jp2->jp2_img_state |= JP2_IMG_STATE_UNKNOWN; - } - p_header_data += l_current_data_size; - p_header_size -= box.length; - } - jp2->jp2_state |= JP2_STATE_HEADER; - return true; -} - -/** - * 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_image_header_max_size maximum size of the header, any size bigger than this value should result the function to output false. - * @param p_manager the user event manager. - * - * @return true if the image header is valid, fale else. - */ -bool jp2_read_ihdr( - opj_jp2_t *jp2, - unsigned char * p_image_header_data, - unsigned int 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 - (p_image_header_size != 14) - { - opj_event_msg(p_manager, EVT_ERROR, "Bad image header box (bad size)\n"); - return 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; - - /* allocate memory for components */ - jp2->comps = (opj_jp2_comps_t*) opj_malloc(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 false; - } - memset(jp2->comps,0,jp2->numcomps * sizeof(opj_jp2_comps_t)); - - 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; - 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; - return true; -} - -/** - * 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 unsigned char * jp2_write_ihdr( - opj_jp2_t *jp2, - unsigned int * p_nb_bytes_written - ) -{ - unsigned char * 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 = (unsigned char *) opj_malloc(22); - if - (l_ihdr_data == 00) - { - return 00; - } - memset(l_ihdr_data,0,22); - - 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; -} - -/** - * 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. -*/ -unsigned char * jp2_write_bpcc( - opj_jp2_t *jp2, - unsigned int * p_nb_bytes_written - ) -{ - unsigned int i; - /* room for 8 bytes for box and 1 byte for each component */ - int l_bpcc_size = 8 + jp2->numcomps; - unsigned char * l_bpcc_data,* l_current_bpcc_ptr; - - // preconditions - assert(jp2 != 00); - assert(p_nb_bytes_written != 00); - - l_bpcc_data = (unsigned char *) opj_malloc(l_bpcc_size); - if - (l_bpcc_data == 00) - { - return 00; - } - memset(l_bpcc_data,0,l_bpcc_size); - - 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; -} - -/** - * 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 pointer that will hold the size of the bpc header - * @param p_bpc_header_max_size maximum size of the header, any size bigger than this value should result the function to output false. - * @param p_manager the user event manager. - * - * @return true if the bpc header is valid, fale else. - */ -bool jp2_read_bpcc( - opj_jp2_t *jp2, - unsigned char * p_bpc_header_data, - unsigned int p_bpc_header_size, - opj_event_mgr_t * p_manager - ) -{ - unsigned int i; - - // preconditions - assert(p_bpc_header_data != 00); - assert(jp2 != 00); - assert(p_manager != 00); - - // 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 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 true; -} - -/** - * 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. -*/ -unsigned char *jp2_write_colr( - opj_jp2_t *jp2, - unsigned int * p_nb_bytes_written - ) -{ - /* room for 8 bytes for box 3 for common data and variable upon profile*/ - unsigned int l_colr_size = 11; - unsigned char * l_colr_data,* l_current_colr_ptr; - - // preconditions - assert(jp2 != 00); - assert(p_nb_bytes_written != 00); - - switch - (jp2->meth) - { - case 1 : - l_colr_size += 4; - break; - case 2 : - ++l_colr_size; - break; - default : - return 00; - } - - l_colr_data = (unsigned char *) opj_malloc(l_colr_size); - if - (l_colr_data == 00) - { - return 00; - } - memset(l_colr_data,0,l_colr_size); - 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) - { - opj_write_bytes(l_current_colr_ptr, jp2->enumcs,4); /* EnumCS */ - } - else - { - opj_write_bytes(l_current_colr_ptr, 0, 1); /* PROFILE (??) */ - } - *p_nb_bytes_written = l_colr_size; - return l_colr_data; -} - -/** - * Reads the Colour 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 pointer that will hold the size of the color header - * @param p_colr_header_max_size maximum size of the header, any size bigger than this value should result the function to output false. - * @param p_manager the user event manager. - * - * @return true if the bpc header is valid, fale else. -*/ -bool jp2_read_colr( - opj_jp2_t * jp2, - unsigned char * p_colr_header_data, - unsigned int p_colr_header_size, - opj_event_mgr_t * p_manager - ) -{ - // 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 BPCC header box (bad size)\n"); - return false; - } - - 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 BPCC header box (bad size)\n"); - return false; - } - opj_read_bytes(p_colr_header_data,&jp2->enumcs ,4); /* EnumCS */ - } - /*else - { - // do not care with profiles. - }*/ - return true; -} - -/** - * Writes the Jpeg2000 codestream Header box - JP2C Header box. - * - * @param cio the stream to write data to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager user event manager. - * - * @return true if writting was successful. -*/ -bool jp2_write_jp2c( - opj_jp2_t *jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager - ) -{ - unsigned int j2k_codestream_exit; - unsigned char 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,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 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 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 false; - } - return true; -} - -/** - * Destroys a jpeg2000 file decompressor. - * - * @param jp2 a jpeg2000 file decompressor. - */ -void jp2_destroy(opj_jp2_t *jp2) -{ - if - (jp2) - { - /* destroy the J2K codec */ - 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->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); - } -} - - - - - -/* ----------------------------------------------------------------------- */ -/* JP2 encoder interface */ -/* ----------------------------------------------------------------------- */ - -opj_jp2_t* jp2_create(bool p_is_decoder) -{ - opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t)); - if - (jp2) - { - memset(jp2,0,sizeof(opj_jp2_t)); - /* create the J2K codec */ - if - (! p_is_decoder) - { - jp2->j2k = j2k_create_compress(); - } - else - { - jp2->j2k = j2k_create_decompress(); - } - if - (jp2->j2k == 00) - { - jp2_destroy(jp2); - return 00; - } - // validation list creation - jp2->m_validation_list = opj_procedure_list_create(); - if - (! jp2->m_validation_list) - { - jp2_destroy(jp2); - return 00; - } - - // execution list creation - jp2->m_procedure_list = opj_procedure_list_create(); - if - (! jp2->m_procedure_list) - { - jp2_destroy(jp2); - return 00; - } - } - return jp2; -} - -/** - * Excutes 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 cio the stream to execute the procedures on. - * @param p_manager the user manager. - * - * @return true if all the procedures were successfully executed. - */ -bool jp2_exec ( - opj_jp2_t * jp2, - opj_procedure_list_t * p_procedure_list, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager - ) -{ - bool (** l_procedure) (opj_jp2_t * jp2,opj_stream_private_t *,opj_event_mgr_t *) = 00; - bool l_result = true; - unsigned int l_nb_proc, i; - - // preconditions - assert(p_procedure_list != 00); - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - - l_nb_proc = opj_procedure_list_get_nb_procedures(p_procedure_list); - l_procedure = (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;im_validation_list,cio,p_manager)) - { - return false; - } - - /* customization of the encoding */ - jp2_setup_header_writting(jp2); - - /* write header */ - if - (! jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) - { - return false; - } - return j2k_start_compress(jp2->j2k,cio,p_image,p_manager); -} - -/** - * Reads a jpeg2000 file header structure. - * - * @param cio the stream to read data from. - * @param jp2 the jpeg2000 file header structure. - * @param p_manager the user event manager. - * - * @return true if the box is valid. - */ -bool jp2_read_header( - opj_jp2_t *jp2, - opj_image_t ** p_image, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_UINT32 * p_tile_width, - OPJ_UINT32 * p_tile_height, - OPJ_UINT32 * p_nb_tiles_x, - OPJ_UINT32 * p_nb_tiles_y, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ) -{ - // preconditions - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - - /* customization of the validation */ - jp2_setup_decoding_validation (jp2); - - /* customization of the encoding */ - jp2_setup_header_reading(jp2); - - /* validation of the parameters codec */ - if - (! jp2_exec(jp2,jp2->m_validation_list,cio,p_manager)) - { - return false; - } - - /* read header */ - if - (! jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) - { - return false; - } - return j2k_read_header( - jp2->j2k, - p_image, - p_tile_x0, - p_tile_y0, - p_tile_width, - p_tile_height, - p_nb_tiles_x, - p_nb_tiles_y, - cio, - p_manager); -} - -/** - * Ends the decompression procedures and possibiliy add data to be read after the - * codestream. - */ -bool 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 */ - jp2_setup_end_header_reading(jp2); - - /* write header */ - if - (! jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager)) - { - return false; - } - return j2k_end_decompress(jp2->j2k, cio, p_manager); -} - - -/** - * Ends the compression procedures and possibiliy add data to be read after the - * codestream. - */ -bool 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 */ - jp2_setup_end_header_writting(jp2); - - if - (! j2k_end_compress(jp2->j2k,cio,p_manager)) - { - return false; - } - /* write header */ - return jp2_exec (jp2,jp2->m_procedure_list,cio,p_manager); -} - -/** -Encode an image into a JPEG-2000 file stream -@param jp2 JP2 compressor handle -@param cio Output buffer stream -@param image Image to encode -@param cstr_info Codestream information structure if required, NULL otherwise -@return Returns true if successful, returns false otherwise -*/ -bool jp2_encode(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager) -{ - return j2k_encode(jp2->j2k,cio,p_manager); -} -/** - * Writes a tile. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool jp2_write_tile ( - opj_jp2_t *p_jp2, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ) -{ - return j2k_write_tile (p_jp2->j2k,p_tile_index,p_data,p_data_size,p_stream,p_manager); -} - -/** - * Decode tile data. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool 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 j2k_decode_tile (p_jp2->j2k,p_tile_index,p_data,p_data_size,p_stream,p_manager); -} -/** - * Reads a tile header. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool 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, - bool * p_go_on, - opj_stream_private_t *p_stream, - opj_event_mgr_t * p_manager - ) -{ - return 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); -} - -/** - * Sets up the procedures to do on writting header after the codestream. - * Developpers wanting to extend the library can add their own writting procedures. - */ -void jp2_setup_end_header_writting (opj_jp2_t *jp2) -{ - // preconditions - assert(jp2 != 00); - - opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_write_jp2c ); - /* DEVELOPER CORNER, add your custom procedures */ -} - -/** - * Sets up the procedures to do on reading header. - * Developpers wanting to extend the library can add their own writting procedures. - */ -void jp2_setup_header_reading (opj_jp2_t *jp2) -{ - // preconditions - assert(jp2 != 00); - - opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_read_header_procedure ); - /* DEVELOPER CORNER, add your custom procedures */ -} - -/** - * Sets up the procedures to do on reading header after the codestream. - * Developpers wanting to extend the library can add their own writting procedures. - */ -void jp2_setup_end_header_reading (opj_jp2_t *jp2) -{ - // preconditions - assert(jp2 != 00); - opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_read_header_procedure ); - /* DEVELOPER CORNER, add your custom procedures */ -} - - -/** - * The default validation procedure without any extension. - * - * @param jp2 the jpeg2000 codec to validate. - * @param cio the input stream to validate. - * @param p_manager the user event manager. - * - * @return true if the parameters are correct. - */ -bool jp2_default_validation ( - opj_jp2_t * jp2, - opj_stream_private_t *cio, - opj_event_mgr_t * p_manager - ) -{ - bool l_is_valid = true; - unsigned int i; - - // preconditions - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - /* JPEG2000 codec validation */ - /*TODO*/ - - /* 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 > 0); - } - /* 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; - -} - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -void jp2_setup_encoding_validation (opj_jp2_t *jp2) -{ - // preconditions - assert(jp2 != 00); - opj_procedure_list_add_procedure(jp2->m_validation_list, (void*)jp2_default_validation); - /* DEVELOPER CORNER, add your custom validation procedure */ -} - -/** - * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters - * are valid. Developpers wanting to extend the library can add their own validation procedures. - */ -void jp2_setup_decoding_validation (opj_jp2_t *jp2) -{ - // preconditions - assert(jp2 != 00); - /* DEVELOPER CORNER, add your custom validation procedure */ -} - -/** - * Sets up the procedures to do on writting header. Developpers wanting to extend the library can add their own writting procedures. - */ -void jp2_setup_header_writting (opj_jp2_t *jp2) -{ - // preconditions - assert(jp2 != 00); - opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_write_jp ); - opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_write_ftyp ); - opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_write_jp2h ); - opj_procedure_list_add_procedure(jp2->m_procedure_list,(void*)jp2_skip_jp2c ); - - /* DEVELOPER CORNER, insert your custom procedures */ - -} - - -/** - * Skips the Jpeg2000 Codestream Header box - JP2C Header box. - * - * @param cio the stream to write data to. - * @param jp2 the jpeg2000 file codec. - * @param p_manager user event manager. - * - * @return true if writting was successful. -*/ -bool jp2_skip_jp2c( - opj_jp2_t *jp2, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ) -{ - // preconditions - assert(jp2 != 00); - assert(cio != 00); - assert(p_manager != 00); - - jp2->j2k_codestream_offset = opj_stream_tell(cio); - if - (opj_stream_skip(cio,8,p_manager) != 8) - { - return false; - } - return true; -} - -struct opj_image * jp2_decode(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager) -{ - /* J2K decoding */ - struct opj_image * image = j2k_decode(jp2->j2k, cio, p_manager); - if - (!image) - { - opj_event_msg(p_manager, EVT_ERROR, "Failed to decode J2K image\n"); - return false; - } - - /* Set Image Color Space */ - if (jp2->enumcs == 16) - image->color_space = CLRSPC_SRGB; - else if (jp2->enumcs == 17) - image->color_space = CLRSPC_GRAY; - else if (jp2->enumcs == 18) - image->color_space = CLRSPC_SYCC; - else - image->color_space = CLRSPC_UNKNOWN; - return image; -} - -void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image,opj_event_mgr_t * p_manager) -{ - unsigned int i; - int depth_0, sign; - - if(!jp2 || !parameters || !image) - return; - - /* 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; - } - - j2k_setup_encoder(jp2->j2k, parameters, image,p_manager); - - /* setup the JP2 codec */ - /* ------------------- */ - - /* Profile box */ - - jp2->brand = JP2_JP2; /* BR */ - jp2->minversion = 0; /* MinV */ - jp2->numcl = 1; - jp2->cl = (unsigned int*) opj_malloc(jp2->numcl * sizeof(unsigned int)); - 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)); - 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++) { - int 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->numcomps == 1 || image->numcomps == 3) && (jp2->bpc != 255)) { - jp2->meth = 1; /* METH: Enumerated colourspace */ - } else { - jp2->meth = 2; /* METH: Restricted ICC profile */ - } - if (jp2->meth == 1) { - if (image->color_space == 1) - jp2->enumcs = 16; /* sRGB as defined by IEC 61966�2�1 */ - else if (image->color_space == 2) - jp2->enumcs = 17; /* greyscale */ - else if (image->color_space == 3) - jp2->enumcs = 18; /* YUV */ - } else { - jp2->enumcs = 0; /* PROFILE (??) */ - } - jp2->precedence = 0; /* PRECEDENCE */ - jp2->approx = 0; /* APPROX */ - -} - -void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) -{ - if(!jp2 || !parameters) - return; - - /* setup the J2K codec */ - /* ------------------- */ - j2k_setup_decoder(jp2->j2k, parameters); -} -/** - * 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_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). - * @param p_manager the user event manager - * - * @return true if the area could be set. - */ -bool jp2_set_decode_area( - opj_jp2_t *p_jp2, - OPJ_INT32 p_start_x, - OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, - OPJ_INT32 p_end_y, - struct opj_event_mgr * p_manager - ) -{ - return j2k_set_decode_area(p_jp2->j2k,p_start_x,p_start_y,p_end_x,p_end_y,p_manager); -} - -#if 0 - - - - - -static void jp2_write_url(opj_cio_t *cio, char *Idx_file) { - unsigned int 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 diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/jp2.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/jp2.h deleted file mode 100644 index a73a05f555a..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/jp2.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2002-2003, Yannick Verschueren - * 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 __JP2_H -#define __JP2_H -/** -@file jp2.h -@brief The JPEG-2000 file format Reader/Writer (JP2) - -*/ -#include "openjpeg.h" - - - - -/********************************************************************************** - ********************************* FORWARD DECLARATIONS *************************** - **********************************************************************************/ -struct opj_j2k; -struct opj_procedure_list; -struct opj_event_mgr; -struct opj_stream_private; -struct opj_dparameters; -struct opj_cparameters; - -/** @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 */ -#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 /**< URL box */ -#define JP2_DBTL 0x6474626c /**< ??? */ -#define JP2_BPCC 0x62706363 /**< Bits per component box */ -#define JP2_JP2 0x6a703220 /**< File type fields */ - -/* ----------------------------------------------------------------------- */ - - -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 = 0x10000000 -} -JP2_STATE; - -typedef enum -{ - JP2_IMG_STATE_NONE = 0x0, - JP2_IMG_STATE_UNKNOWN = 0x10000000 -} -JP2_IMG_STATE; - -/** -JP2 component -*/ -typedef struct opj_jp2_comps -{ - unsigned int depth; - int sgnd; - unsigned int bpcc; -} -opj_jp2_comps_t; - -/** -JPEG-2000 file format reader/writer -*/ -typedef struct opj_jp2 -{ - /** handle to the J2K codec */ - struct opj_j2k *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 */ - unsigned int w; - /* height of image */ - unsigned int h; - /* number of components in the image */ - unsigned int numcomps; - unsigned int bpc; - unsigned int C; - unsigned int UnkC; - unsigned int IPR; - unsigned int meth; - unsigned int approx; - unsigned int enumcs; - unsigned int precedence; - unsigned int brand; - unsigned int minversion; - unsigned int numcl; - unsigned int *cl; - opj_jp2_comps_t *comps; - unsigned int j2k_codestream_offset; - unsigned int jp2_state; - unsigned int jp2_img_state; - -} -opj_jp2_t; - -/** -JP2 Box -*/ -typedef struct opj_jp2_box -{ - unsigned int length; - unsigned int type; -} -opj_jp2_box_t; - -typedef struct opj_jp2_header_handler -{ - /* marker value */ - int id; - /* action linked to the marker */ - bool (*handler) (opj_jp2_t *jp2,unsigned char * p_header_data, unsigned int p_header_size,struct opj_event_mgr * p_manager); -} -opj_jp2_header_handler_t; - - -typedef struct opj_jp2_img_header_writer_handler -{ - /* action to perform */ - unsigned char* (*handler) (opj_jp2_t *jp2, unsigned int * p_data_size); - /* result of the action : data */ - unsigned char * m_data; - /* size of data */ - unsigned int m_size; -} -opj_jp2_img_header_writer_handler_t; - - - - - -/** @name Exported functions */ -/*@{*/ -/* ----------------------------------------------------------------------- */ - -/** - * Creates a jpeg2000 file decompressor. - * - * @return an empty jpeg2000 file codec. - */ -opj_jp2_t* jp2_create (bool p_is_decoder); - -/** -Destroy a JP2 decompressor handle -@param jp2 JP2 decompressor handle to destroy -*/ -void jp2_destroy(opj_jp2_t *jp2); - -/** -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 jp2_setup_decoder(opj_jp2_t *jp2, struct opj_dparameters *parameters); - -/** - * Decode an image from a JPEG-2000 file stream - * @param jp2 JP2 decompressor handle - * @param cio Input buffer stream - * @param cstr_info Codestream information structure if required, NULL otherwise - * @return Returns a decoded image if successful, returns NULL otherwise -*/ -struct opj_image* jp2_decode(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * 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 -*/ -void jp2_setup_encoder(opj_jp2_t *jp2, struct opj_cparameters *parameters, struct opj_image *image,struct opj_event_mgr * p_manager); - -/** - * Starts a compression scheme, i.e. validates the codec parameters, writes the header. - * - * @param jp2 the jpeg2000 file codec. - * @param cio the stream object. - * - * @return true if the codec is valid. - */ -bool jp2_start_compress(opj_jp2_t *jp2, struct opj_stream_private *cio,struct opj_image * p_image,struct opj_event_mgr * p_manager); - -/** - * Ends the compression procedures and possibiliy add data to be read after the - * codestream. - */ -bool jp2_end_compress(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); - -/** -Encode an image into a JPEG-2000 file stream -@param jp2 JP2 compressor handle -@param cio Output buffer stream -@param image Image to encode -@param cstr_info Codestream information structure if required, NULL otherwise -@return Returns true if successful, returns false otherwise -*/ -bool jp2_encode(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); - -/** - * Reads a jpeg2000 file header structure. - * - * @param cio the stream to read data from. - * @param jp2 the jpeg2000 file header structure. - * @param p_manager the user event manager. - * - * @return true if the box is valid. - */ -bool jp2_read_header( - opj_jp2_t *jp2, - struct opj_image ** p_image, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_UINT32 * p_tile_width, - OPJ_UINT32 * p_tile_height, - OPJ_UINT32 * p_nb_tiles_x, - OPJ_UINT32 * p_nb_tiles_y, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager - ); -/** - * Ends the decompression procedures and possibiliy add data to be read after the - * codestream. - */ -bool jp2_end_decompress(opj_jp2_t *jp2, struct opj_stream_private *cio, struct opj_event_mgr * p_manager); - -/** - * Writes a tile. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool jp2_write_tile ( - opj_jp2_t *p_jp2, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Decode tile data. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool jp2_decode_tile ( - opj_jp2_t * p_jp2, - OPJ_UINT32 p_tile_index, - OPJ_BYTE * p_data, - OPJ_UINT32 p_data_size, - struct opj_stream_private *p_stream, - struct opj_event_mgr * p_manager - ); -/** - * Reads a tile header. - * @param p_j2k the jpeg2000 codec. - * @param p_stream the stream to write data to. - * @param p_manager the user event manager. - */ -bool jp2_read_tile_header ( - opj_jp2_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, - bool * p_go_on, - struct opj_stream_private *p_stream, - struct opj_event_mgr * 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_jp2 the jpeg2000 codec. - * @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). - * @param p_manager the user event manager - * - * @return true if the area could be set. - */ -bool jp2_set_decode_area( - opj_jp2_t *p_jp2, - OPJ_INT32 p_start_x, - OPJ_INT32 p_start_y, - OPJ_INT32 p_end_x, - OPJ_INT32 p_end_y, - struct opj_event_mgr * p_manager - ); - -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __JP2_H */ - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/jpt.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/jpt.c deleted file mode 100644 index 0cfe44f3d2c..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/jpt.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2002-2003, Yannick Verschueren - * 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 "jpt.h" -#include "openjpeg.h" -#include "cio.h" -#include "event.h" -/* - * Read the information contains in VBAS [JPP/JPT stream message header] - * Store information (7 bits) in value - * @param p_cio the stream to read from. - * @param p_value the data to update - * @return the nb of bytes read or -1 if an io error occurred. - */ -bool jpt_read_VBAS_info(opj_stream_private_t * p_cio, OPJ_UINT32 * p_nb_bytes_read, OPJ_UINT32 * p_value, opj_event_mgr_t * p_manager) -{ - OPJ_BYTE l_elmt; - OPJ_UINT32 l_nb_bytes_read = 0; - - // read data till the MSB of the current byte is 1. - // concatenate 7 bits of data, last bit is finish flag - - // read data from the stream - - if - (opj_stream_read_data(p_cio,&l_elmt,1,p_manager) != 1) - { - opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data.\n"); - return false; - } - ++l_nb_bytes_read; - - // is the MSB equal to 1 ? - while - (l_elmt & 0x80) - { - // concatenate 7 bits of data, last bit is finish flag - *p_value = (*p_value << 7) | (l_elmt & 0x7f); - if - (opj_stream_read_data(p_cio,&l_elmt,1,p_manager) != 1) - { - opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data.\n"); - return false; - } - ++l_nb_bytes_read; - } - // concatenate 7 bits of data, last bit is finish flag - *p_value = (*p_value << 7) | (l_elmt & 0x7f); - * p_nb_bytes_read = l_nb_bytes_read; - return true; -} - -/* - * Initialize the value of the message header structure - * - */ -void jpt_init_msg_header(opj_jpt_msg_header_t * header) -{ - header->Id = 0; /* In-class Identifier */ - header->last_byte = 0; /* Last byte information */ - header->Class_Id = 0; /* Class Identifier */ - header->CSn_Id = 0; /* CSn : index identifier */ - header->Msg_offset = 0; /* Message offset */ - header->Msg_length = 0; /* Message length */ - header->Layer_nb = 0; /* Auxiliary for JPP case */ -} - -/* - * Re-initialize the value of the message header structure - * - * Only parameters always present in message header - * - */ -void jpt_reinit_msg_header(opj_jpt_msg_header_t * header) -{ - header->Id = 0; /* In-class Identifier */ - header->last_byte = 0; /* Last byte information */ - header->Msg_offset = 0; /* Message offset */ - header->Msg_length = 0; /* Message length */ -} - -/* - * Read the message header for a JPP/JPT - stream - * - */ -bool jpt_read_msg_header(opj_stream_private_t *cio, opj_jpt_msg_header_t *header, OPJ_UINT32 * p_nb_bytes_read, opj_event_mgr_t * p_manager) -{ - OPJ_BYTE elmt, Class = 0, CSn = 0; - OPJ_UINT32 l_nb_bytes_read = 0; - OPJ_UINT32 l_last_nb_bytes_read; - - - jpt_reinit_msg_header(header); - - /* ------------- */ - /* VBAS : Bin-ID */ - /* ------------- */ - if - (opj_stream_read_data(cio,&elmt,1,p_manager) != 1) - { - opj_event_msg(p_manager, EVT_ERROR, "Forbidden value encounter in message header !!\n"); - return false; - } - ++l_nb_bytes_read; - - /* See for Class and CSn */ - switch ((elmt >> 5) & 0x03) - { - case 0: - opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); - break; - case 1: - Class = 0; - CSn = 0; - break; - case 2: - Class = 1; - CSn = 0; - break; - case 3: - Class = 1; - CSn = 1; - break; - default: - break; - } - - /* see information on bits 'c' [p 10 : A.2.1 general, ISO/IEC FCD 15444-9] */ - if - (((elmt >> 4) & 0x01) == 1) - { - header->last_byte = 1; - } - - /* In-class identifier */ - header->Id |= (elmt & 0x0f); - if - ((elmt >> 7) == 1) - { - l_last_nb_bytes_read = 0; - if - (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Id), p_manager)) - { - opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); - return false; - } - l_nb_bytes_read += l_last_nb_bytes_read; - } - - /* ------------ */ - /* VBAS : Class */ - /* ------------ */ - if (Class == 1) - { - header->Class_Id = 0; - l_last_nb_bytes_read = 0; - if - (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Class_Id), p_manager)) - { - opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); - return false; - } - l_nb_bytes_read += l_last_nb_bytes_read; - } - - /* ---------- */ - /* VBAS : CSn */ - /* ---------- */ - if (CSn == 1) - { - header->CSn_Id = 0; - l_last_nb_bytes_read = 0; - if - (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->CSn_Id), p_manager)) - { - opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); - return false; - } - l_nb_bytes_read += l_last_nb_bytes_read; - } - - /* ----------------- */ - /* VBAS : Msg_offset */ - /* ----------------- */ - l_last_nb_bytes_read = 0; - if - (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Msg_offset), p_manager)) - { - opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); - return false; - } - l_nb_bytes_read += l_last_nb_bytes_read; - - /* ----------------- */ - /* VBAS : Msg_length */ - /* ----------------- */ - l_last_nb_bytes_read = 0; - if - (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Msg_length), p_manager)) - { - opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); - return false; - } - l_nb_bytes_read += l_last_nb_bytes_read; - - /* ---------- */ - /* VBAS : Aux */ - /* ---------- */ - if ((header->Class_Id & 0x01) == 1) - { - header->Layer_nb = 0; - if - (! jpt_read_VBAS_info(cio, &l_last_nb_bytes_read, &(header->Layer_nb), p_manager)) - { - opj_event_msg(p_manager, EVT_ERROR, "Error trying to read a byte of data!!!\n"); - return false; - } - l_nb_bytes_read += l_last_nb_bytes_read; - } - * p_nb_bytes_read = l_nb_bytes_read; - return true; -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/jpt.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/jpt.h deleted file mode 100644 index 7c67cfffdfd..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/jpt.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2002-2003, Yannick Verschueren - * 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 __JPT_H -#define __JPT_H -/** -@file jpt.h -@brief JPT-stream reader (JPEG 2000, JPIP) - -JPT-stream functions are implemented in J2K.C. -*/ -#include "openjpeg.h" -struct opj_stream_private; -struct opj_event_mgr; -/** -Message Header JPT stream structure -*/ -typedef struct opj_jpt_msg_header -{ - /** In-class Identifier */ - OPJ_UINT32 Id; - /** Last byte information */ - OPJ_UINT32 last_byte; - /** Class Identifier */ - OPJ_UINT32 Class_Id; - /** CSn : index identifier */ - OPJ_UINT32 CSn_Id; - /** Message offset */ - OPJ_UINT32 Msg_offset; - /** Message length */ - OPJ_UINT32 Msg_length; - /** Auxiliary for JPP case */ - OPJ_UINT32 Layer_nb; -} opj_jpt_msg_header_t; - -/* ----------------------------------------------------------------------- */ - -/** -Initialize the value of the message header structure -@param header Message header structure -*/ -void jpt_init_msg_header(opj_jpt_msg_header_t * header); - -/** - * Read the message header for a JPP/JPT - stream - * @param p_cio stream handle - * @param header JPT Message header structure - * @param p_manager user event manager to display nice messages. -*/ -bool jpt_read_msg_header( - struct opj_stream_private * p_cio, - opj_jpt_msg_header_t * p_header, - OPJ_UINT32 * p_nb_bytes_read, - struct opj_event_mgr * p_manager); - -#endif diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/mct.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/mct.c deleted file mode 100644 index 5eadc21d599..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/mct.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 "mct.h" -#include "fix.h" -#include "opj_malloc.h" - -/* */ -/* This table contains the norms of the basis function of the reversible MCT. */ -/* */ -static const OPJ_FLOAT64 mct_norms[3] = { 1.732, .8292, .8292 }; - -/* */ -/* This table contains the norms of the basis function of the irreversible MCT. */ -/* */ -static const OPJ_FLOAT64 mct_norms_real[3] = { 1.732, 1.805, 1.573 }; - - - -const OPJ_FLOAT64 * get_mct_norms () -{ - return mct_norms; -} - -const OPJ_FLOAT64 * get_mct_norms_real () -{ - return mct_norms_real; -} - - - -/* */ -/* Foward reversible MCT. */ -/* */ -void mct_encode( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, - OPJ_INT32* restrict c2, - OPJ_UINT32 n) -{ - OPJ_UINT32 i; - for(i = 0; i < n; ++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; - } -} - -/* */ -/* Inverse reversible MCT. */ -/* */ -void mct_decode( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, - OPJ_INT32* restrict c2, - OPJ_UINT32 n) -{ - OPJ_UINT32 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; - } -} - -/* */ -/* Get norm of basis function of reversible MCT. */ -/* */ -OPJ_FLOAT64 mct_getnorm(OPJ_UINT32 compno) { - return mct_norms[compno]; -} - -/* */ -/* Foward irreversible MCT. */ -/* */ -void mct_encode_real( - OPJ_INT32* restrict c0, - OPJ_INT32* restrict c1, - OPJ_INT32* restrict c2, - OPJ_UINT32 n) -{ - OPJ_UINT32 i; - for(i = 0; i < n; ++i) { - OPJ_INT32 r = c0[i]; - OPJ_INT32 g = c1[i]; - OPJ_INT32 b = c2[i]; - OPJ_INT32 y = fix_mul(r, 2449) + fix_mul(g, 4809) + fix_mul(b, 934); - OPJ_INT32 u = -fix_mul(r, 1382) - fix_mul(g, 2714) + fix_mul(b, 4096); - OPJ_INT32 v = fix_mul(r, 4096) - fix_mul(g, 3430) - fix_mul(b, 666); - c0[i] = y; - c1[i] = u; - c2[i] = v; - } -} - -/* */ -/* Inverse irreversible MCT. */ -/* */ -void mct_decode_real( - OPJ_FLOAT32* restrict c0, - OPJ_FLOAT32* restrict c1, - OPJ_FLOAT32* restrict c2, - OPJ_UINT32 n) -{ - OPJ_UINT32 i; - 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 mct_getnorm_real(OPJ_UINT32 compno) { - return mct_norms_real[compno]; -} - -bool mct_encode_custom( - // MCT data - OPJ_BYTE * pCodingdata, - // size of components - OPJ_UINT32 n, - // components - OPJ_BYTE ** pData, - // nb of components (i.e. size of pData) - OPJ_UINT32 pNbComp, - // tells if the data is signed - OPJ_UINT32 isSigned) -{ - OPJ_FLOAT32 * lMct = (OPJ_FLOAT32 *) pCodingdata; - OPJ_UINT32 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; - - lCurrentData = (OPJ_INT32 *) opj_malloc((pNbComp + lNbMatCoeff) * sizeof(OPJ_INT32)); - if - (! lCurrentData) - { - return false; - } - lCurrentMatrix = lCurrentData + pNbComp; - for - (i =0;i - * 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 __MCT_H -#define __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. -*/ -#include "openjpeg.h" -/** @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 mct_encode(OPJ_INT32 *c0, OPJ_INT32 *c1, OPJ_INT32 *c2, OPJ_UINT32 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 mct_decode(OPJ_INT32 *c0, OPJ_INT32 *c1, OPJ_INT32 *c2, OPJ_UINT32 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 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 mct_encode_real(OPJ_INT32 *c0, OPJ_INT32 *c1, OPJ_INT32 *c2, OPJ_UINT32 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 mct_decode_real(OPJ_FLOAT32* c0, OPJ_FLOAT32* c1, OPJ_FLOAT32* c2, OPJ_UINT32 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 mct_getnorm_real(OPJ_UINT32 compno); - -bool mct_encode_custom( - // MCT data - OPJ_BYTE * p_coding_data, - // size of components - OPJ_UINT32 n, - // components - OPJ_BYTE ** p_data, - // nb of components (i.e. size of p_data) - OPJ_UINT32 p_nb_comp, - // tells if the data is signed - OPJ_UINT32 is_signed); - -bool mct_decode_custom( - // MCT data - OPJ_BYTE * pDecodingData, - // size of components - OPJ_UINT32 n, - // components - OPJ_BYTE ** pData, - // nb of components (i.e. size of pData) - OPJ_UINT32 pNbComp, - // tells if the data is signed - OPJ_UINT32 isSigned); - -void opj_calculate_norms(OPJ_FLOAT64 * pNorms,OPJ_UINT32 p_nb_comps,OPJ_FLOAT32 * pMatrix); - -const OPJ_FLOAT64 * get_mct_norms (); -const OPJ_FLOAT64 * get_mct_norms_real (); - - -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __MCT_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/mqc.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/mqc.c deleted file mode 100644 index d7adc10df23..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/mqc.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 "mqc.h" -#include "t1.h" -#include "opj_malloc.h" - -/** @defgroup MQC MQC - Implementation of an MQ-Coder */ -/*@{*/ - -/** @name Local static functions */ -/*@{*/ - -/** -Output a byte, doing bit-stuffing if necessary. -After a 0xff byte, the next byte must be smaller than 0x90. -@param mqc MQC handle -*/ -static void 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 -*/ -static void mqc_renorme(opj_mqc_t *mqc); -/** -Encode the most probable symbol -@param mqc MQC handle -*/ -static void mqc_codemps(opj_mqc_t *mqc); -/** -Encode the most least symbol -@param mqc MQC handle -*/ -static void mqc_codelps(opj_mqc_t *mqc); -/** -Fill mqc->c with 1's for flushing -@param mqc MQC handle -*/ -static void mqc_setbits(opj_mqc_t *mqc); -/** -FIXME: documentation ??? -@param mqc MQC handle -@return -*/ -static OPJ_INT32 mqc_mpsexchange(opj_mqc_t *mqc); -/** -FIXME: documentation ??? -@param mqc MQC handle -@return -*/ -static OPJ_INT32 mqc_lpsexchange(opj_mqc_t *mqc); -/** -Input a byte -@param mqc MQC handle -*/ -static void mqc_bytein(opj_mqc_t *mqc); -/** -Renormalize mqc->a and mqc->c while decoding -@param mqc MQC handle -*/ -static void mqc_renormd(opj_mqc_t *mqc); - -/*@}*/ - -/*@}*/ - -/* */ -/* This array defines all the possible states for a context. */ -/* */ -static 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 mqc_byteout(opj_mqc_t *mqc) { - if (*mqc->bp == 0xff) { - mqc->bp++; - *mqc->bp = mqc->c >> 20; - mqc->c &= 0xfffff; - mqc->ct = 7; - } else { - if ((mqc->c & 0x8000000) == 0) { /* ((mqc->c&0x8000000)==0) CHANGE */ - mqc->bp++; - *mqc->bp = mqc->c >> 19; - mqc->c &= 0x7ffff; - mqc->ct = 8; - } else { - (*mqc->bp)++; - if (*mqc->bp == 0xff) { - mqc->c &= 0x7ffffff; - mqc->bp++; - *mqc->bp = mqc->c >> 20; - mqc->c &= 0xfffff; - mqc->ct = 7; - } else { - mqc->bp++; - *mqc->bp = mqc->c >> 19; - mqc->c &= 0x7ffff; - mqc->ct = 8; - } - } - } -} - -static void mqc_renorme(opj_mqc_t *mqc) { - do { - mqc->a <<= 1; - mqc->c <<= 1; - mqc->ct--; - if (mqc->ct == 0) { - mqc_byteout(mqc); - } - } while ((mqc->a & 0x8000) == 0); -} - -static void mqc_codemps(opj_mqc_t *mqc) { - mqc->a -= (*mqc->curctx)->qeval; - if ((mqc->a & 0x8000) == 0) { - if (mqc->a < (*mqc->curctx)->qeval) { - mqc->a = (*mqc->curctx)->qeval; - } else { - mqc->c += (*mqc->curctx)->qeval; - } - *mqc->curctx = (*mqc->curctx)->nmps; - mqc_renorme(mqc); - } else { - mqc->c += (*mqc->curctx)->qeval; - } -} - -static void mqc_codelps(opj_mqc_t *mqc) { - mqc->a -= (*mqc->curctx)->qeval; - if (mqc->a < (*mqc->curctx)->qeval) { - mqc->c += (*mqc->curctx)->qeval; - } else { - mqc->a = (*mqc->curctx)->qeval; - } - *mqc->curctx = (*mqc->curctx)->nlps; - mqc_renorme(mqc); -} - -static void mqc_setbits(opj_mqc_t *mqc) { - OPJ_UINT32 tempc = mqc->c + mqc->a; - mqc->c |= 0xffff; - if (mqc->c >= tempc) { - mqc->c -= 0x8000; - } -} - -static OPJ_INT32 mqc_mpsexchange(opj_mqc_t *mqc) { - OPJ_INT32 d; - if (mqc->a < (*mqc->curctx)->qeval) { - d = 1 - (*mqc->curctx)->mps; - *mqc->curctx = (*mqc->curctx)->nlps; - } else { - d = (*mqc->curctx)->mps; - *mqc->curctx = (*mqc->curctx)->nmps; - } - - return d; -} - -static OPJ_INT32 mqc_lpsexchange(opj_mqc_t *mqc) { - OPJ_INT32 d; - if (mqc->a < (*mqc->curctx)->qeval) { - mqc->a = (*mqc->curctx)->qeval; - d = (*mqc->curctx)->mps; - *mqc->curctx = (*mqc->curctx)->nmps; - } else { - mqc->a = (*mqc->curctx)->qeval; - d = 1 - (*mqc->curctx)->mps; - *mqc->curctx = (*mqc->curctx)->nlps; - } - - return d; -} - -static void mqc_bytein(opj_mqc_t *mqc) { - if (mqc->bp != mqc->end) { - OPJ_UINT32 c; - if (mqc->bp + 1 != mqc->end) { - c = *(mqc->bp + 1); - } else { - c = 0xff; - } - if (*mqc->bp == 0xff) { - if (c > 0x8f) { - mqc->c += 0xff00; - mqc->ct = 8; - } else { - mqc->bp++; - mqc->c += c << 9; - mqc->ct = 7; - } - } else { - mqc->bp++; - mqc->c += c << 8; - mqc->ct = 8; - } - } else { - mqc->c += 0xff00; - mqc->ct = 8; - } -} - -static void mqc_renormd(opj_mqc_t *mqc) { - do { - if (mqc->ct == 0) { - mqc_bytein(mqc); - } - mqc->a <<= 1; - mqc->c <<= 1; - mqc->ct--; - } while (mqc->a < 0x8000); -} - -/* -========================================================== - MQ-Coder interface -========================================================== -*/ - -opj_mqc_t* mqc_create(void) { - opj_mqc_t *mqc = (opj_mqc_t*)opj_malloc(sizeof(opj_mqc_t)); - return mqc; -} - -void mqc_destroy(opj_mqc_t *mqc) { - if - (mqc) - { - opj_free(mqc); - } -} - -OPJ_UINT32 mqc_numbytes(opj_mqc_t *mqc) { - return (OPJ_UINT32)( mqc->bp - mqc->start ); -} - -void mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp) { - mqc_setcurctx(mqc, 0); - mqc->a = 0x8000; - mqc->c = 0; - mqc->bp = bp - 1; - *(mqc->bp) = 0; - mqc->ct = 12; - /*if (*mqc->bp == 0xff) { - mqc->ct = 13; - }*/ - mqc->start = bp; -} - -void mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d) { - if ((*mqc->curctx)->mps == d) { - mqc_codemps(mqc); - } else { - mqc_codelps(mqc); - } -} - -void mqc_flush(opj_mqc_t *mqc) { - mqc_setbits(mqc); - mqc->c <<= mqc->ct; - mqc_byteout(mqc); - mqc->c <<= mqc->ct; - mqc_byteout(mqc); - - if (*mqc->bp != 0xff) { - mqc->bp++; - } -} - -void mqc_bypass_init_enc(opj_mqc_t *mqc) { - mqc->c = 0; - mqc->ct = 8; - /*if (*mqc->bp == 0xff) { - mqc->ct = 7; - } */ -} - -void mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d) { - mqc->ct--; - mqc->c = mqc->c + (d << mqc->ct); - if (mqc->ct == 0) { - mqc->bp++; - *mqc->bp = mqc->c; - mqc->ct = 8; - if (*mqc->bp == 0xff) { - mqc->ct = 7; - } - mqc->c = 0; - } -} - -OPJ_UINT32 mqc_bypass_flush_enc(opj_mqc_t *mqc) { - OPJ_BYTE bit_padding; - - bit_padding = 0; - - if (mqc->ct != 0) { - while (mqc->ct > 0) { - mqc->ct--; - mqc->c += bit_padding << mqc->ct; - bit_padding = (bit_padding + 1) & 0x01; - } - mqc->bp++; - *mqc->bp = mqc->c; - mqc->ct = 8; - mqc->c = 0; - } - - return 1; -} - -void mqc_reset_enc(opj_mqc_t *mqc) { - mqc_resetstates(mqc); - mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); -} - -OPJ_UINT32 mqc_restart_enc(opj_mqc_t *mqc) { - OPJ_UINT32 correction = 1; - - /* */ - OPJ_INT32 n = 27 - 15 - mqc->ct; - mqc->c <<= mqc->ct; - while (n > 0) { - mqc_byteout(mqc); - n -= mqc->ct; - mqc->c <<= mqc->ct; - } - mqc_byteout(mqc); - - return correction; -} - -void mqc_restart_init_enc(opj_mqc_t *mqc) { - /* */ - mqc_setcurctx(mqc, 0); - mqc->a = 0x8000; - mqc->c = 0; - mqc->ct = 12; - mqc->bp--; - if (*mqc->bp == 0xff) { - mqc->ct = 13; - } -} - -void mqc_erterm_enc(opj_mqc_t *mqc) { - OPJ_INT32 k = 11 - mqc->ct + 1; - - while (k > 0) { - mqc->c <<= mqc->ct; - mqc->ct = 0; - mqc_byteout(mqc); - k -= mqc->ct; - } - - if (*mqc->bp != 0xff) { - mqc_byteout(mqc); - } -} - -void mqc_segmark_enc(opj_mqc_t *mqc) { - OPJ_UINT32 i; - mqc_setcurctx(mqc, 18); - - for (i = 1; i < 5; i++) { - mqc_encode(mqc, i % 2); - } -} - -void mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len) { - mqc_setcurctx(mqc, 0); - mqc->start = bp; - mqc->end = bp + len; - mqc->bp = bp; - if (len==0) mqc->c = 0xff << 16; - else mqc->c = *mqc->bp << 16; - mqc_bytein(mqc); - mqc->c <<= 7; - mqc->ct -= 7; - mqc->a = 0x8000; -} - -OPJ_UINT32 mqc_decode(opj_mqc_t *mqc) { - OPJ_INT32 d; - mqc->a -= (*mqc->curctx)->qeval; - if ((mqc->c >> 16) < (*mqc->curctx)->qeval) { - d = mqc_lpsexchange(mqc); - mqc_renormd(mqc); - } else { - mqc->c -= (*mqc->curctx)->qeval << 16; - if ((mqc->a & 0x8000) == 0) { - d = mqc_mpsexchange(mqc); - mqc_renormd(mqc); - } else { - d = (*mqc->curctx)->mps; - } - } - - return (OPJ_UINT32)d; -} - -void mqc_resetstates(opj_mqc_t *mqc) { - OPJ_UINT32 i; - for (i = 0; i < MQC_NUMCTXS; i++) { - mqc->ctxs[i] = mqc_states; - } -} - -void mqc_setstate(opj_mqc_t *mqc, OPJ_UINT32 ctxno, OPJ_UINT32 msb, OPJ_INT32 prob) { - mqc->ctxs[ctxno] = &mqc_states[msb + (prob << 1)]; -} - - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/mqc.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/mqc.h deleted file mode 100644 index 279f0a12c93..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/mqc.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __MQC_H -#define __MQC_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. -*/ -#include "openjpeg.h" -/** @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 */ - struct opj_mqc_state *nmps; - /** next state if the next encoded symbol is the LPS */ - struct opj_mqc_state *nlps; -} opj_mqc_state_t; - -#define MQC_NUMCTXS 32 - -/** -MQ coder -*/ -typedef struct opj_mqc { - OPJ_UINT32 c; - OPJ_UINT32 a; - OPJ_UINT32 ct; - OPJ_BYTE *bp; - OPJ_BYTE *start; - OPJ_BYTE *end; - opj_mqc_state_t *ctxs[MQC_NUMCTXS]; - opj_mqc_state_t **curctx; -} opj_mqc_t; - -/** @name Exported functions */ -/*@{*/ -/* ----------------------------------------------------------------------- */ -/** -Create a new MQC handle -@return Returns a new MQC handle if successful, returns NULL otherwise -*/ -opj_mqc_t* mqc_create(void); -/** -Destroy a previously created MQC handle -@param mqc MQC handle to destroy -*/ -void mqc_destroy(opj_mqc_t *mqc); -/** -Return the number of bytes written/read since initialisation -@param mqc MQC handle -@return Returns the number of bytes already encoded -*/ -OPJ_UINT32 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 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 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 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 mqc_setcurctx(mqc, ctxno) (mqc)->curctx = &(mqc)->ctxs[(OPJ_UINT32)(ctxno)] -/** -Encode a symbol using the MQ-coder -@param mqc MQC handle -@param d The symbol to be encoded (0 or 1) -*/ -void mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d); -/** -Flush the encoder, so that all remaining data is written -@param mqc MQC handle -*/ -void mqc_flush(opj_mqc_t *mqc); -/** -BYPASS mode switch, initialization operation. -JPEG 2000 p 505. -

Not fully implemented and tested !!

-@param mqc MQC handle -*/ -void mqc_bypass_init_enc(opj_mqc_t *mqc); -/** -BYPASS mode switch, coding operation. -JPEG 2000 p 505. -

Not fully implemented and tested !!

-@param mqc MQC handle -@param d The symbol to be encoded (0 or 1) -*/ -void mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d); -/** -BYPASS mode switch, flush operation -

Not fully implemented and tested !!

-@param mqc MQC handle -@return Returns 1 (always) -*/ -OPJ_UINT32 mqc_bypass_flush_enc(opj_mqc_t *mqc); -/** -RESET mode switch -@param mqc MQC handle -*/ -void mqc_reset_enc(opj_mqc_t *mqc); -/** -RESTART mode switch (TERMALL) -@param mqc MQC handle -@return Returns 1 (always) -*/ -OPJ_UINT32 mqc_restart_enc(opj_mqc_t *mqc); -/** -RESTART mode switch (TERMALL) reinitialisation -@param mqc MQC handle -*/ -void mqc_restart_init_enc(opj_mqc_t *mqc); -/** -ERTERM mode switch (PTERM) -@param mqc MQC handle -*/ -void mqc_erterm_enc(opj_mqc_t *mqc); -/** -SEGMARK mode switch (SEGSYM) -@param mqc MQC handle -*/ -void mqc_segmark_enc(opj_mqc_t *mqc); -/** -Initialize the decoder -@param mqc MQC handle -@param bp Pointer to the start of the buffer from which the bytes will be read -@param len Length of the input buffer -*/ -void mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len); -/** -Decode a symbol -@param mqc MQC handle -@return Returns the decoded symbol (0 or 1) -*/ -OPJ_UINT32 mqc_decode(opj_mqc_t *mqc); -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __MQC_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg.c deleted file mode 100644 index 61293c08fb2..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg.c +++ /dev/null @@ -1,908 +0,0 @@ -/* - * Copyright (c) 2005, Herv� 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. - */ - -#ifdef WIN32 -#include -#endif /* WIN32 */ - -#include "openjpeg.h" -#include "opj_malloc.h" -#include "j2k.h" -#include "jp2.h" -#include "event.h" -#include "cio.h" - -typedef struct opj_decompression -{ - bool (* opj_read_header) ( - void *p_codec, - opj_image_t **, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_UINT32 * p_tile_width, - OPJ_UINT32 * p_tile_height, - OPJ_UINT32 * p_nb_tiles_x, - OPJ_UINT32 * p_nb_tiles_y, - struct opj_stream_private *cio, - struct opj_event_mgr * p_manager); - opj_image_t* (* opj_decode) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager); - 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, - bool * p_should_go_on, - struct opj_stream_private *p_cio, - struct opj_event_mgr * p_manager); - 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); - bool (* opj_end_decompress) (void *p_codec,struct opj_stream_private *cio,struct opj_event_mgr * p_manager); - void (* opj_destroy) (void * p_codec); - void (*opj_setup_decoder) (void * p_codec,opj_dparameters_t * p_param); - bool (*opj_set_decode_area) (void * p_codec,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); - - -}opj_decompression_t; - -typedef struct opj_compression -{ - bool (* opj_start_compress) (void *p_codec,struct opj_stream_private *cio,struct opj_image * p_image, struct opj_event_mgr * p_manager); - bool (* opj_encode) (void * p_codec, struct opj_stream_private *p_cio, struct opj_event_mgr * p_manager); - 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); - 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); - void (*opj_setup_encoder) (void * p_codec,opj_cparameters_t * p_param,struct opj_image * p_image, struct opj_event_mgr * p_manager); - -}opj_compression_t; - - - -typedef struct opj_codec_private -{ - union - { /* code-blocks informations */ - opj_decompression_t m_decompression; - opj_compression_t m_compression; - } m_codec_data; - void * m_codec; - opj_event_mgr_t m_event_mgr; - unsigned is_decompressor : 1; -} -opj_codec_private_t; - - - -/** - * Default callback function. - * Do nothing. - */ -void opj_default_callback (const char *msg, void *client_data) -{ -} - -void 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; -} - -OPJ_INT32 opj_read_from_file (void * p_buffer, OPJ_UINT32 p_nb_bytes, FILE * p_file) -{ - OPJ_INT32 l_nb_read = (OPJ_INT32)( fread(p_buffer,1,p_nb_bytes,p_file) ); - return l_nb_read ? l_nb_read : -1; -} - -OPJ_UINT32 opj_write_from_file (void * p_buffer, OPJ_UINT32 p_nb_bytes, FILE * p_file) -{ - return (OPJ_UINT32)( fwrite(p_buffer,1,p_nb_bytes,p_file) ); -} - -OPJ_SIZE_T opj_skip_from_file (OPJ_SIZE_T p_nb_bytes, FILE * p_user_data) -{ - if - (fseek(p_user_data,p_nb_bytes,SEEK_CUR)) - { - return -1; - } - return p_nb_bytes; -} - -bool opj_seek_from_file (OPJ_SIZE_T p_nb_bytes, FILE * p_user_data) -{ - if - (fseek(p_user_data,p_nb_bytes,SEEK_SET)) - { - return false; - } - return true; -} - -/* ---------------------------------------------------------------------- */ -#ifdef WIN32 -#ifndef OPJ_STATIC -BOOL APIENTRY -DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { - 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 OPENJPEG_VERSION; -} - -opj_codec_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT p_format) -{ - opj_codec_private_t *l_info = 00; - - l_info = (opj_codec_private_t*) opj_calloc(1, sizeof(opj_codec_private_t)); - if - (!l_info) - { - return 00; - } - memset(l_info, 0, sizeof(opj_codec_private_t)); - l_info->is_decompressor = 1; - switch - (p_format) - { - case CODEC_J2K: - l_info->m_codec_data.m_decompression.opj_decode = (opj_image_t* (*) (void *, struct opj_stream_private *, struct opj_event_mgr * ))j2k_decode; - l_info->m_codec_data.m_decompression.opj_end_decompress = (bool (*) (void *,struct opj_stream_private *,struct opj_event_mgr *))j2k_end_decompress; - l_info->m_codec_data.m_decompression.opj_read_header = (bool (*) ( - void *, - opj_image_t **, - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_UINT32 * , - OPJ_UINT32 * , - OPJ_UINT32 * , - OPJ_UINT32 * , - struct opj_stream_private *, - struct opj_event_mgr * )) j2k_read_header; - l_info->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))j2k_destroy; - l_info->m_codec_data.m_decompression.opj_setup_decoder = (void (*) (void * ,opj_dparameters_t * )) j2k_setup_decoder; - l_info->m_codec_data.m_decompression.opj_read_tile_header = (bool (*) ( - void *, - OPJ_UINT32*, - OPJ_UINT32*, - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_UINT32 * , - bool *, - struct opj_stream_private *, - struct opj_event_mgr * )) j2k_read_tile_header; - l_info->m_codec_data.m_decompression.opj_decode_tile_data = (bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr * )) j2k_decode_tile; - l_info->m_codec_data.m_decompression.opj_set_decode_area = (bool (*) (void *,OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) j2k_set_decode_area; - l_info->m_codec = j2k_create_decompress(); - if - (! l_info->m_codec) - { - opj_free(l_info); - return 00; - } - break; - - case CODEC_JP2: - /* get a JP2 decoder handle */ - l_info->m_codec_data.m_decompression.opj_decode = (opj_image_t* (*) (void *, struct opj_stream_private *, struct opj_event_mgr * ))jp2_decode; - l_info->m_codec_data.m_decompression.opj_end_decompress = (bool (*) (void *,struct opj_stream_private *,struct opj_event_mgr *)) jp2_end_decompress; - l_info->m_codec_data.m_decompression.opj_read_header = (bool (*) ( - void *, - opj_image_t **, - - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_UINT32 * , - OPJ_UINT32 * , - OPJ_UINT32 * , - OPJ_UINT32 * , - struct opj_stream_private *, - struct opj_event_mgr * )) jp2_read_header; - - l_info->m_codec_data.m_decompression.opj_read_tile_header = ( - bool (*) ( - void *, - OPJ_UINT32*, - OPJ_UINT32*, - OPJ_INT32*, - OPJ_INT32*, - OPJ_INT32 * , - OPJ_INT32 * , - OPJ_UINT32 * , - bool *, - struct opj_stream_private *, - struct opj_event_mgr * )) jp2_read_tile_header; - - l_info->m_codec_data.m_decompression.opj_decode_tile_data = (bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr * )) jp2_decode_tile; - - l_info->m_codec_data.m_decompression.opj_destroy = (void (*) (void *))jp2_destroy; - l_info->m_codec_data.m_decompression.opj_setup_decoder = (void (*) (void * ,opj_dparameters_t * )) jp2_setup_decoder; - l_info->m_codec_data.m_decompression.opj_set_decode_area = (bool (*) (void *,OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) jp2_set_decode_area; - - - l_info->m_codec = jp2_create(true); - if - (! l_info->m_codec) - { - opj_free(l_info); - return 00; - } - break; - case CODEC_UNKNOWN: - case CODEC_JPT: - default: - opj_free(l_info); - return 00; - } - set_default_event_handler(&(l_info->m_event_mgr)); - return (opj_codec_t*) l_info; -} - -void OPJ_CALLCONV opj_destroy_codec(opj_codec_t *p_info) -{ - if - (p_info) - { - opj_codec_private_t * l_info = (opj_codec_private_t *) p_info; - if - (l_info->is_decompressor) - { - l_info->m_codec_data.m_decompression.opj_destroy(l_info->m_codec); - } - else - { - l_info->m_codec_data.m_compression.opj_destroy(l_info->m_codec); - } - l_info->m_codec = 00; - opj_free(l_info); - } -} - -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; -/* UniPG>> */ -#ifdef USE_JPWL - parameters->jpwl_correct = false; - parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS; - parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES; -#endif /* USE_JPWL */ -/* <is_decompressor) - { - return false; - } - l_info->m_codec_data.m_decompression.opj_setup_decoder(l_info->m_codec,parameters); - return true; - } - return false; -} - -opj_image_t* OPJ_CALLCONV opj_decode(opj_codec_t *p_info, opj_stream_t *cio) -{ - if - (p_info && cio) - { - opj_codec_private_t * l_info = (opj_codec_private_t *) p_info; - opj_stream_private_t * l_cio = (opj_stream_private_t *) cio; - if - (! l_info->is_decompressor) - { - return 00; - } - return l_info->m_codec_data.m_decompression.opj_decode(l_info->m_codec,l_cio,&(l_info->m_event_mgr)); - } - return 00; -} - -/** - * Writes a tile with the given data. - * - * @param p_compressor 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. - */ -bool 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_info = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_cio = (opj_stream_private_t *) p_stream; - if - (l_info->is_decompressor) - { - return false; - } - return l_info->m_codec_data.m_compression.opj_write_tile(l_info->m_codec,p_tile_index,p_data,p_data_size,l_cio,&(l_info->m_event_mgr)); - } - return false; -} - -/** - * Reads a tile header. This function is compulsory and allows one to know the size of the tile thta 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. - */ -bool opj_read_tile_header( - opj_codec_t *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, - bool * p_should_go_on, - opj_stream_t * p_stream) -{ - if - (p_codec && p_stream && p_data_size && p_tile_index) - { - opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_cio = (opj_stream_private_t *) p_stream; - if - (! l_info->is_decompressor) - { - return false; - } - return l_info->m_codec_data.m_decompression.opj_read_tile_header( - l_info->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_cio,&(l_info->m_event_mgr)); - } - return false; -} - -/** - * 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. - * - * @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. - */ -bool 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_info = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_cio = (opj_stream_private_t *) p_stream; - if - (! l_info->is_decompressor) - { - return false; - } - return l_info->m_codec_data.m_decompression.opj_decode_tile_data(l_info->m_codec,p_tile_index,p_data,p_data_size,l_cio,&(l_info->m_event_mgr)); - } - return false; -} - -bool OPJ_CALLCONV opj_read_header ( - opj_codec_t *p_codec, - opj_image_t ** p_image, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_UINT32 * p_tile_width, - OPJ_UINT32 * p_tile_height, - OPJ_UINT32 * p_nb_tiles_x, - OPJ_UINT32 * p_nb_tiles_y, - opj_stream_t *p_cio) -{ - if - (p_codec && p_cio) - { - opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio; - if - (! l_info->is_decompressor) - { - return false; - } - return l_info->m_codec_data.m_decompression.opj_read_header( - l_info->m_codec, - p_image, - p_tile_x0, - p_tile_y0, - p_tile_width, - p_tile_height, - p_nb_tiles_x, - p_nb_tiles_y, - l_cio, - &(l_info->m_event_mgr)); - } - return false; -} - -/** - * 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_codec the jpeg2000 codec. - * @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. - */ -bool opj_set_decode_area( - opj_codec_t *p_codec, - 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_info = (opj_codec_private_t *) p_codec; - if - (! l_info->is_decompressor) - { - return false; - } - return l_info->m_codec_data.m_decompression.opj_set_decode_area( - l_info->m_codec, - p_start_x, - p_start_y, - p_end_x, - p_end_y, - &(l_info->m_event_mgr)); - - } - return false; - -} - -bool OPJ_CALLCONV opj_end_decompress (opj_codec_t *p_codec,opj_stream_t *p_cio) -{ - if - (p_codec && p_cio) - { - opj_codec_private_t * l_info = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio; - if - (! l_info->is_decompressor) - { - return false; - } - return l_info->m_codec_data.m_decompression.opj_end_decompress(l_info->m_codec,l_cio,&(l_info->m_event_mgr)); - } - return false; -} - - -opj_codec_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT p_format) -{ - opj_codec_private_t *l_info = 00; - - l_info = (opj_codec_private_t*)opj_calloc(1, sizeof(opj_codec_private_t)); - if - (!l_info) - { - return 00; - } - memset(l_info, 0, sizeof(opj_codec_private_t)); - l_info->is_decompressor = 0; - switch - (p_format) - { - case CODEC_J2K: - l_info->m_codec_data.m_compression.opj_encode = (bool (*) (void *, struct opj_stream_private *, struct opj_event_mgr * )) j2k_encode; - l_info->m_codec_data.m_compression.opj_end_compress = (bool (*) (void *, struct opj_stream_private *, struct opj_event_mgr *)) j2k_end_compress; - l_info->m_codec_data.m_compression.opj_start_compress = (bool (*) (void *,struct opj_stream_private *,struct opj_image * , struct opj_event_mgr *)) j2k_start_compress; - l_info->m_codec_data.m_compression.opj_write_tile = (bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr *)) j2k_write_tile; - l_info->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) j2k_destroy; - l_info->m_codec_data.m_compression.opj_setup_encoder = (void (*) (void *,opj_cparameters_t *,struct opj_image *, struct opj_event_mgr * )) j2k_setup_encoder; - - l_info->m_codec = j2k_create_compress(); - if - (! l_info->m_codec) - { - opj_free(l_info); - return 00; - } - break; - - case CODEC_JP2: - /* get a JP2 decoder handle */ - l_info->m_codec_data.m_compression.opj_encode = (bool (*) (void *, struct opj_stream_private *, struct opj_event_mgr * )) jp2_encode; - l_info->m_codec_data.m_compression.opj_end_compress = (bool (*) (void *, struct opj_stream_private *, struct opj_event_mgr *)) jp2_end_compress; - l_info->m_codec_data.m_compression.opj_start_compress = (bool (*) (void *,struct opj_stream_private *,struct opj_image * , struct opj_event_mgr *)) jp2_start_compress; - l_info->m_codec_data.m_compression.opj_write_tile = (bool (*) (void *,OPJ_UINT32,OPJ_BYTE*,OPJ_UINT32,struct opj_stream_private *, struct opj_event_mgr *)) jp2_write_tile; - l_info->m_codec_data.m_compression.opj_destroy = (void (*) (void *)) jp2_destroy; - l_info->m_codec_data.m_compression.opj_setup_encoder = (void (*) (void *,opj_cparameters_t *,struct opj_image *, struct opj_event_mgr * )) jp2_setup_encoder; - - l_info->m_codec = jp2_create(false); - if - (! l_info->m_codec) - { - opj_free(l_info); - return 00; - } - break; - case CODEC_UNKNOWN: - case CODEC_JPT: - default: - opj_free(l_info); - return 00; - } - set_default_event_handler(&(l_info->m_event_mgr)); - return (opj_codec_t*) l_info; -} - -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 = OFF; - parameters->max_comp_size = 0; - parameters->numresolution = 6; - parameters->cp_rsiz = STD_RSIZ; - parameters->cblockw_init = 64; - parameters->cblockh_init = 64; - parameters->prog_order = LRCP; - 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; -/* UniPG>> */ -#ifdef USE_JPWL - parameters->jpwl_epc_on = 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) - { - l_codec->m_codec_data.m_compression.opj_setup_encoder(l_codec->m_codec,parameters,image,&(l_codec->m_event_mgr)); - return true; - } - } - return false; -} - -bool OPJ_CALLCONV opj_encode(opj_codec_t *p_info, opj_stream_t *cio) -{ - if - (p_info && cio) - { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_info; - opj_stream_private_t * l_cio = (opj_stream_private_t *) cio; - if - (! l_codec->is_decompressor) - { - l_codec->m_codec_data.m_compression.opj_encode(l_codec->m_codec,l_cio,&(l_codec->m_event_mgr)); - return true; - } - } - return false; - -} - -bool OPJ_CALLCONV opj_start_compress (opj_codec_t *p_codec,opj_image_t * p_image,opj_stream_t *p_cio) -{ - if - (p_codec && p_cio) - { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio; - if - (! l_codec->is_decompressor) - { - return l_codec->m_codec_data.m_compression.opj_start_compress(l_codec->m_codec,l_cio,p_image,&(l_codec->m_event_mgr)); - } - } - return false; -} - -bool OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec,opj_stream_t *p_cio) -{ - if - (p_codec && p_cio) - { - opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec; - opj_stream_private_t * l_cio = (opj_stream_private_t *) p_cio; - if - (! l_codec->is_decompressor) - { - return l_codec->m_codec_data.m_compression.opj_end_compress(l_codec->m_codec,l_cio,&(l_codec->m_event_mgr)); - } - } - return false; - -} - -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 false; - } - l_codec->m_event_mgr.info_handler = p_callback; - l_codec->m_event_mgr.m_info_data = p_user_data; - return true; -} - -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 false; - } - l_codec->m_event_mgr.warning_handler = p_callback; - l_codec->m_event_mgr.m_warning_data = p_user_data; - return true; -} - -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 false; - } - l_codec->m_event_mgr.error_handler = p_callback; - l_codec->m_event_mgr.m_error_data = p_user_data; - return true; -} - -/*bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_stream_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) { - if(cinfo && cio && image) { - switch(cinfo->codec_format) { - case CODEC_J2K: - return j2k_encode((opj_j2k_t*)cinfo->j2k_handle, (opj_stream_private_t *) cio, image, cstr_info); - case CODEC_JP2: - return jp2_encode((opj_jp2_t*)cinfo->jp2_handle, (opj_stream_private_t *) cio, image, cstr_info); - case CODEC_JPT: - case CODEC_UNKNOWN: - default: - break; - } - } - return false; -}*/ - -void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) { - if - (cstr_info) - { - int tileno; - for (tileno = 0; tileno < cstr_info->tw * cstr_info->th; tileno++) { - opj_tile_info_t *tile_info = &cstr_info->tile[tileno]; - opj_free(tile_info->thresh); - opj_free(tile_info->packet); - opj_free(tile_info->tp); - } - opj_free(cstr_info->tile); - opj_free(cstr_info->marker); - } -} - -bool 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 * sizeof(OPJ_FLOAT32); - OPJ_UINT32 l_dc_shift_size = pNbComp * sizeof(OPJ_INT32); - OPJ_UINT32 l_mct_total_size = l_matrix_size + l_dc_shift_size; - // add MCT capability - int rsiz = (int)parameters->cp_rsiz | (int)MCT; - parameters->cp_rsiz = (OPJ_RSIZ_CAPABILITIES)rsiz; - 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 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 true; -} - -/** - * Restricts the decoding to the given image area. - * - * @param parameters the parameters to update. - * @param p_start_x the starting x position of the area to decode. - * @param p_start_y the starting y position of the area to decode. - * @param p_end_x the x end position of the area to decode. - * @param p_end_x the y end position of the area to decode. - */ -OPJ_API bool OPJ_CALLCONV opj_restrict_decoding (opj_dparameters_t *parameters,OPJ_INT32 p_start_x,OPJ_INT32 p_start_y,OPJ_INT32 p_end_x,OPJ_INT32 p_end_y) -{ - parameters->m_use_restrict_decode = 1; - parameters->m_decode_start_x = p_start_x; - parameters->m_decode_start_y = p_start_y; - parameters->m_decode_end_x = p_end_x; - parameters->m_decode_end_y = p_end_y; - return true; -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg.h deleted file mode 100644 index 7ff74420222..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg.h +++ /dev/null @@ -1,1080 +0,0 @@ - /* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2006-2007, Parvatha Elangovan - * 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 OPENJPEG_H -#define OPENJPEG_H - -#include "openjpeg_mangle.h" - -#include "openjpegDllConfig.h" - -#if defined(OPJ_STATIC) || (!defined(WIN32) && !defined(__MINGW32__)) || defined(__WIN32__) - #define OPJ_API - #define OPJ_CALLCONV -#else - #define OPJ_CALLCONV __stdcall - #ifdef OPJ_EXPORTS - #define OPJ_API __declspec(dllexport) - #else - #define OPJ_API __declspec(dllimport) - #endif /* OPJ_EXPORTS */ -#endif /* !OPJ_STATIC || !WIN32 */ - -#ifndef __cplusplus - #if defined(HAVE_STDBOOL_H) - #include - #else - #if !defined(bool) - // Note: this is a hack, and incorrect matching of types may - // cause undefined behavior. - #if defined(__APPLE__) && defined( __ppc__ ) - // Mac_OS_X_ABI_Function_Calls.pdf - // only ppc sizeof(bool) is 4 bytes - #define bool unsigned int - #else - #define bool unsigned char - #endif - #endif - #if !defined(true) - #define true 1 - #endif - #if !defined(false) - #define false 0 - #endif - #endif -#endif /* __cplusplus */ -typedef unsigned int OPJ_UINT32; -typedef int OPJ_INT32; -typedef unsigned short OPJ_UINT16; -typedef short OPJ_INT16; -typedef char OPJ_CHAR; -typedef unsigned char OPJ_BYTE; -typedef unsigned int OPJ_SIZE_T; -typedef double OPJ_FLOAT64; -typedef float OPJ_FLOAT32; -#if defined(_MSC_VER) || defined(__BORLANDC__) - typedef __int64 OPJ_INT64; -#else - typedef long long OPJ_INT64; -#endif - -#define OPENJPEG_VERSION "1.2.0" -/* -========================================================== - Compiler directives -========================================================== -*/ -#include - - - - - -/* -========================================================== - Useful constant definitions -========================================================== -*/ - -#define OPJ_PATH_LEN 4096 /**< Maximum allowed size for filenames */ -#define J2K_MAXRLVLS 33 /**< Number of maximum resolution level authorized */ -#define J2K_MAXBANDS (3*J2K_MAXRLVLS-2) /**< Number of maximum sub-band linked to number of resolution level */ -#define J2K_DEFAULT_NB_SEGS 10 -#define J2K_STREAM_CHUNK_SIZE 0x100000 /** 1 mega by default */ -#define J2K_DEFAULT_HEADER_SIZE 1000 -#define J2K_MCC_DEFAULT_NB_RECORDS 10 -#define J2K_MCT_DEFAULT_NB_RECORDS 10 - -/* UniPG>> */ -#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 */ -/* <> */ - /**@name JPWL encoding parameters */ - /*@{*/ - /** enables writing of EPC in MH, thus activating JPWL */ - 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]; - /*@}*/ -/* <> */ - /**@name JPWL decoding parameters */ - /*@{*/ - /** activates the JPWL correction capabilities */ - bool jpwl_correct; - /** expected number of components */ - int jpwl_exp_comps; - /** maximum number of tiles */ - int jpwl_max_tiles; - - /** use restrictive decoding ? */ - OPJ_UINT32 m_use_restrict_decode : 1; - /*@}*/ -/* <> */ -/** -Marker structure -*/ -typedef struct opj_marker_info_t { - /** marker type */ - unsigned short int type; - /** position in codestream */ - int 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; -/* <cp. -@param dinfo decompressor handle -@param parameters decompression parameters -*/ -OPJ_API bool OPJ_CALLCONV opj_setup_decoder(opj_codec_t *dinfo, opj_dparameters_t *parameters); -#endif - -/** -Decode an image from a JPEG-2000 codestream -@param dinfo decompressor handle -@param cio Input buffer stream -@return Returns a decoded image if successful, returns NULL otherwise -*/ -OPJ_API opj_image_t* OPJ_CALLCONV opj_decode(opj_codec_t *p_decompressor, opj_stream_t * cio); - -/** - * Writes a tile with the given data. - * - * @param p_compressor 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 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 thta 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 bool OPJ_CALLCONV opj_read_tile_header( - opj_codec_t *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, - bool * p_should_go_on, - opj_stream_t * p_stream); - - -/** - * 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. - * - * @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 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 - ); - -/** - * 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_codec the jpeg2000 codec. - * @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 bool OPJ_CALLCONV opj_set_decode_area( - opj_codec_t *p_codec, - 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 and extract the codestream information -@param dinfo decompressor handle -@param cio Input buffer stream -@param cstr_info Codestream information structure if needed afterwards, NULL otherwise -@return Returns a decoded image if successful, returns NULL otherwise -*/ -//OPJ_API opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_stream_t cio, opj_codestream_info_t *cstr_info); -/** -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); - -/** -Destroy a decompressor handle -@param dinfo decompressor handle to destroy -*/ -OPJ_API void OPJ_CALLCONV opj_destroy_codec(opj_codec_t * p_codec); - -/** -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); - -/** - * 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 bool OPJ_CALLCONV opj_set_MCT(opj_cparameters_t *parameters,OPJ_FLOAT32 * pEncodingMatrix,OPJ_INT32 * p_dc_shift,OPJ_UINT32 pNbComp); - -/** - * Restricts the decoding to the given image area. - * - * @param parameters the parameters to update. - * @param p_start_x the starting x position of the area to decode. - * @param p_start_y the starting y position of the area to decode. - * @param p_end_x the x end position of the area to decode. - * @param p_end_x the y end position of the area to decode. - */ -OPJ_API bool OPJ_CALLCONV opj_restrict_decoding (opj_dparameters_t *parameters,OPJ_INT32 p_start_x,OPJ_INT32 p_start_y,OPJ_INT32 p_end_x,OPJ_INT32 p_end_y); - -#ifdef USE_OPJ_DEPRECATED -/** -Setup the encoder parameters using the current image and using user parameters. -@param cinfo Compressor handle -@param parameters Compression parameters -@param image Input filled image -*/ -OPJ_API bool OPJ_CALLCONV opj_setup_encoder(opj_codec_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image); -#endif - -/** - * Decodes an image header. - * - * @param p_codec codec to use to decode the image. - * @param p_image pointer to a previously created image. - * @param p_tile_x0 pointer to a value that will hold the reference point x0 of the tiling grid. - * @param p_tile_y0 pointer to a value that will hold the reference point y0 of the tiling grid. - * @param p_tile_width pointer to a value that will hold the size in x of a tile in the grid. - * @param p_tile_height pointer to a value that will hold the size in y of a tile in the grid. - * @param p_nb_tiles_x pointer to a value that will hold the number of tiles in the x direction. - * @param p_nb_tiles_y pointer to a value that will hold the number of tiles in the y direction. - */ -OPJ_API bool OPJ_CALLCONV opj_read_header ( - opj_codec_t *p_codec, - opj_image_t ** p_image, - OPJ_INT32 * p_tile_x0, - OPJ_INT32 * p_tile_y0, - OPJ_UINT32 * p_tile_width, - OPJ_UINT32 * p_tile_height, - OPJ_UINT32 * p_nb_tiles_x, - OPJ_UINT32 * p_nb_tiles_y, - opj_stream_t *p_cio); - - -OPJ_API bool OPJ_CALLCONV opj_end_decompress (opj_codec_t *p_codec,opj_stream_t *p_cio); -/** -Encode an image into a JPEG-2000 codestream -@param cinfo compressor handle -@param cio Output buffer stream -@param image Image to encode -@param index Depreacted -> Set to NULL. To extract index, used opj_encode_wci() -@return Returns true if successful, returns false otherwise -*/ -OPJ_API bool OPJ_CALLCONV opj_encode(opj_codec_t *cinfo, opj_stream_t * cio); - -OPJ_API bool OPJ_CALLCONV opj_start_compress (opj_codec_t *p_codec,opj_image_t * p_image,opj_stream_t *p_cio); - -OPJ_API bool OPJ_CALLCONV opj_end_compress (opj_codec_t *p_codec,opj_stream_t *p_cio); -/** -Encode an image into a JPEG-2000 codestream and extract the codestream information -@param cinfo compressor handle -@param cio Output buffer stream -@param image Image to encode -@param cstr_info Codestream information structure if needed afterwards, NULL otherwise -@return Returns true if successful, returns false otherwise -*/ -//OPJ_API bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_stream_t cio, opj_image_t *image, opj_codestream_info_t *cstr_info); -/** -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_t *cstr_info); - -//============================================================================== -//============================================================================== -/** profiling part */ -#ifdef _PROFILE -void _ProfInit(void); -void _ProfPrint(void); -#define PROFINIT() _ProfInit(); -#define PROFSAVE(file) _ProfSave(file); -#define PROFPRINT() _ProfPrint(); -#else -#define PROFINIT() -#define PROFSAVE(file) -#define PROFPRINT() -#endif // !_PROFILE - -#ifdef __cplusplus -} -#endif - -#endif /* OPENJPEG_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpegDllConfig.h.in b/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpegDllConfig.h.in deleted file mode 100644 index 04006ea14c3..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpegDllConfig.h.in +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef _openjpegDllConfig_h -#define _openjpegDllConfig_h - -#ifndef OPJ_STATIC -#cmakedefine OPJ_STATIC -#endif - -#endif diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg_mangle.h.in b/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg_mangle.h.in deleted file mode 100644 index 32619a29dbc..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/openjpeg_mangle.h.in +++ /dev/null @@ -1,357 +0,0 @@ -/* mangling test */ -#ifndef openjpeg_mangle_h -#define openjpeg_mangle_h - -#define allocate_buffers @MANGLE_PREFIX@_allocate_buffers -#define bio_create @MANGLE_PREFIX@_bio_create -#define bio_destroy @MANGLE_PREFIX@_bio_destroy -#define bio_flush @MANGLE_PREFIX@_bio_flush -#define bio_inalign @MANGLE_PREFIX@_bio_inalign -#define bio_init_dec @MANGLE_PREFIX@_bio_init_dec -#define bio_init_enc @MANGLE_PREFIX@_bio_init_enc -#define bio_numbytes @MANGLE_PREFIX@_bio_numbytes -#define bio_read @MANGLE_PREFIX@_bio_read -#define bio_write @MANGLE_PREFIX@_bio_write -#define dwt_calc_explicit_stepsizes @MANGLE_PREFIX@_dwt_calc_explicit_stepsizes -#define dwt_decode @MANGLE_PREFIX@_dwt_decode -#define dwt_decode_1 @MANGLE_PREFIX@_dwt_decode_1 -#define dwt_decode_1_ @MANGLE_PREFIX@_dwt_decode_1_ -#define dwt_decode_real @MANGLE_PREFIX@_dwt_decode_real -#define dwt_encode @MANGLE_PREFIX@_dwt_encode -#define dwt_encode_1 @MANGLE_PREFIX@_dwt_encode_1 -#define dwt_encode_1_real @MANGLE_PREFIX@_dwt_encode_1_real -#define dwt_encode_real @MANGLE_PREFIX@_dwt_encode_real -#define dwt_getgain @MANGLE_PREFIX@_dwt_getgain -#define dwt_getgain_real @MANGLE_PREFIX@_dwt_getgain_real -#define dwt_getnorm @MANGLE_PREFIX@_dwt_getnorm -#define dwt_getnorm_real @MANGLE_PREFIX@_dwt_getnorm_real -#define get_all_encoding_parameters @MANGLE_PREFIX@_get_all_encoding_parameters -#define get_default_stride @MANGLE_PREFIX@_get_default_stride -#define get_encoding_parameters @MANGLE_PREFIX@_get_encoding_parameters -#define get_mct_norms @MANGLE_PREFIX@_get_mct_norms -#define get_mct_norms_real @MANGLE_PREFIX@_get_mct_norms_real -#define get_tp_stride @MANGLE_PREFIX@_get_tp_stride -#define j2k_build_decoder @MANGLE_PREFIX@_j2k_build_decoder -#define j2k_build_encoder @MANGLE_PREFIX@_j2k_build_encoder -#define j2k_convert_progression_order @MANGLE_PREFIX@_j2k_convert_progression_order -#define j2k_copy_default_tcp_and_create_tcd @MANGLE_PREFIX@_j2k_copy_default_tcp_and_create_tcd -#define j2k_create_compress @MANGLE_PREFIX@_j2k_create_compress -#define j2k_create_decompress @MANGLE_PREFIX@_j2k_create_decompress -#define j2k_create_tcd @MANGLE_PREFIX@_j2k_create_tcd -#define j2k_decode @MANGLE_PREFIX@_j2k_decode -#define j2k_decode_tile @MANGLE_PREFIX@_j2k_decode_tile -#define j2k_decode_tiles @MANGLE_PREFIX@_j2k_decode_tiles -#define j2k_decoding_validation @MANGLE_PREFIX@_j2k_decoding_validation -#define j2k_destroy @MANGLE_PREFIX@_j2k_destroy -#define j2k_destroy_header_memory @MANGLE_PREFIX@_j2k_destroy_header_memory -#define j2k_dump_image @MANGLE_PREFIX@_j2k_dump_image -#define j2k_encode @MANGLE_PREFIX@_j2k_encode -#define j2k_encoding_validation @MANGLE_PREFIX@_j2k_encoding_validation -#define j2k_end_compress @MANGLE_PREFIX@_j2k_end_compress -#define j2k_end_decompress @MANGLE_PREFIX@_j2k_end_decompress -#define j2k_end_encoding @MANGLE_PREFIX@_j2k_end_encoding -#define j2k_get_end_header @MANGLE_PREFIX@_j2k_get_end_header -#define j2k_init_info @MANGLE_PREFIX@_j2k_init_info -#define j2k_mct_validation @MANGLE_PREFIX@_j2k_mct_validation -#define j2k_post_write_tile @MANGLE_PREFIX@_j2k_post_write_tile -#define j2k_read_cbd @MANGLE_PREFIX@_j2k_read_cbd -#define j2k_read_coc @MANGLE_PREFIX@_j2k_read_coc -#define j2k_read_cod @MANGLE_PREFIX@_j2k_read_cod -#define j2k_read_com @MANGLE_PREFIX@_j2k_read_com -#define j2k_read_crg @MANGLE_PREFIX@_j2k_read_crg -#define j2k_read_float32_to_float @MANGLE_PREFIX@_j2k_read_float32_to_float -#define j2k_read_float32_to_int32 @MANGLE_PREFIX@_j2k_read_float32_to_int32 -#define j2k_read_float64_to_float @MANGLE_PREFIX@_j2k_read_float64_to_float -#define j2k_read_float64_to_int32 @MANGLE_PREFIX@_j2k_read_float64_to_int32 -#define j2k_read_header @MANGLE_PREFIX@_j2k_read_header -#define j2k_read_header_procedure @MANGLE_PREFIX@_j2k_read_header_procedure -#define j2k_read_int16_to_float @MANGLE_PREFIX@_j2k_read_int16_to_float -#define j2k_read_int16_to_int32 @MANGLE_PREFIX@_j2k_read_int16_to_int32 -#define j2k_read_int32_to_float @MANGLE_PREFIX@_j2k_read_int32_to_float -#define j2k_read_int32_to_int32 @MANGLE_PREFIX@_j2k_read_int32_to_int32 -#define j2k_read_mcc @MANGLE_PREFIX@_j2k_read_mcc -#define j2k_read_mco @MANGLE_PREFIX@_j2k_read_mco -#define j2k_read_mct @MANGLE_PREFIX@_j2k_read_mct -#define j2k_read_plm @MANGLE_PREFIX@_j2k_read_plm -#define j2k_read_plt @MANGLE_PREFIX@_j2k_read_plt -#define j2k_read_poc @MANGLE_PREFIX@_j2k_read_poc -#define j2k_read_ppm @MANGLE_PREFIX@_j2k_read_ppm -#define j2k_read_ppt @MANGLE_PREFIX@_j2k_read_ppt -#define j2k_read_qcc @MANGLE_PREFIX@_j2k_read_qcc -#define j2k_read_qcd @MANGLE_PREFIX@_j2k_read_qcd -#define j2k_read_rgn @MANGLE_PREFIX@_j2k_read_rgn -#define j2k_read_siz @MANGLE_PREFIX@_j2k_read_siz -#define j2k_read_sot @MANGLE_PREFIX@_j2k_read_sot -#define j2k_read_SPCod_SPCoc @MANGLE_PREFIX@_j2k_read_SPCod_SPCoc -#define j2k_read_SQcd_SQcc @MANGLE_PREFIX@_j2k_read_SQcd_SQcc -#define j2k_read_tile_header @MANGLE_PREFIX@_j2k_read_tile_header -#define j2k_read_tlm @MANGLE_PREFIX@_j2k_read_tlm -#define j2k_set_decode_area @MANGLE_PREFIX@_j2k_set_decode_area -#define j2k_setup_decoder @MANGLE_PREFIX@_j2k_setup_decoder -#define j2k_setup_decoding @MANGLE_PREFIX@_j2k_setup_decoding -#define j2k_setup_encoder @MANGLE_PREFIX@_j2k_setup_encoder -#define j2k_setup_header_reading @MANGLE_PREFIX@_j2k_setup_header_reading -#define j2k_setup_header_writting @MANGLE_PREFIX@_j2k_setup_header_writting -#define j2k_setup_mct_encoding @MANGLE_PREFIX@_j2k_setup_mct_encoding -#define j2k_start_compress @MANGLE_PREFIX@_j2k_start_compress -#define j2k_tcp_destroy @MANGLE_PREFIX@_j2k_tcp_destroy -#define j2k_update_rates @MANGLE_PREFIX@_j2k_update_rates -#define j2k_write_coc_in_memory @MANGLE_PREFIX@_j2k_write_coc_in_memory -#define j2k_write_cod @MANGLE_PREFIX@_j2k_write_cod -#define j2k_write_com @MANGLE_PREFIX@_j2k_write_com -#define j2k_write_eoc @MANGLE_PREFIX@_j2k_write_eoc -#define j2k_write_epc @MANGLE_PREFIX@_j2k_write_epc -#define j2k_write_float_to_float @MANGLE_PREFIX@_j2k_write_float_to_float -#define j2k_write_float_to_float64 @MANGLE_PREFIX@_j2k_write_float_to_float64 -#define j2k_write_float_to_int16 @MANGLE_PREFIX@_j2k_write_float_to_int16 -#define j2k_write_float_to_int32 @MANGLE_PREFIX@_j2k_write_float_to_int32 -#define j2k_write_image_components @MANGLE_PREFIX@_j2k_write_image_components -#define j2k_write_mct_data_group @MANGLE_PREFIX@_j2k_write_mct_data_group -#define j2k_write_poc @MANGLE_PREFIX@_j2k_write_poc -#define j2k_write_poc_in_memory @MANGLE_PREFIX@_j2k_write_poc_in_memory -#define j2k_write_qcc_in_memory @MANGLE_PREFIX@_j2k_write_qcc_in_memory -#define j2k_write_qcd @MANGLE_PREFIX@_j2k_write_qcd -#define j2k_write_regions @MANGLE_PREFIX@_j2k_write_regions -#define j2k_write_siz @MANGLE_PREFIX@_j2k_write_siz -#define j2k_write_soc @MANGLE_PREFIX@_j2k_write_soc -#define j2k_write_SQcd_SQcc @MANGLE_PREFIX@_j2k_write_SQcd_SQcc -#define j2k_write_tile @MANGLE_PREFIX@_j2k_write_tile -#define j2k_write_tlm @MANGLE_PREFIX@_j2k_write_tlm -#define j2k_write_updated_tlm @MANGLE_PREFIX@_j2k_write_updated_tlm -#define jp2_create @MANGLE_PREFIX@_jp2_create -#define jp2_decode @MANGLE_PREFIX@_jp2_decode -#define jp2_decode_tile @MANGLE_PREFIX@_jp2_decode_tile -#define jp2_default_validation @MANGLE_PREFIX@_jp2_default_validation -#define jp2_destroy @MANGLE_PREFIX@_jp2_destroy -#define jp2_encode @MANGLE_PREFIX@_jp2_encode -#define jp2_end_compress @MANGLE_PREFIX@_jp2_end_compress -#define jp2_end_decompress @MANGLE_PREFIX@_jp2_end_decompress -#define jp2_read_bpcc @MANGLE_PREFIX@_jp2_read_bpcc -#define jp2_read_colr @MANGLE_PREFIX@_jp2_read_colr -#define jp2_read_ftyp @MANGLE_PREFIX@_jp2_read_ftyp -#define jp2_read_header @MANGLE_PREFIX@_jp2_read_header -#define jp2_read_header_procedure @MANGLE_PREFIX@_jp2_read_header_procedure -#define jp2_read_ihdr @MANGLE_PREFIX@_jp2_read_ihdr -#define jp2_read_jp @MANGLE_PREFIX@_jp2_read_jp -#define jp2_read_jp2h @MANGLE_PREFIX@_jp2_read_jp2h -#define jp2_read_tile_header @MANGLE_PREFIX@_jp2_read_tile_header -#define jp2_set_decode_area @MANGLE_PREFIX@_jp2_set_decode_area -#define jp2_setup_decoder @MANGLE_PREFIX@_jp2_setup_decoder -#define jp2_setup_encoder @MANGLE_PREFIX@_jp2_setup_encoder -#define jp2_skip_jp2c @MANGLE_PREFIX@_jp2_skip_jp2c -#define jp2_start_compress @MANGLE_PREFIX@_jp2_start_compress -#define jp2_write_bpcc @MANGLE_PREFIX@_jp2_write_bpcc -#define jp2_write_colr @MANGLE_PREFIX@_jp2_write_colr -#define jp2_write_ftyp @MANGLE_PREFIX@_jp2_write_ftyp -#define jp2_write_ihdr @MANGLE_PREFIX@_jp2_write_ihdr -#define jp2_write_jp @MANGLE_PREFIX@_jp2_write_jp -#define jp2_write_jp2c @MANGLE_PREFIX@_jp2_write_jp2c -#define jp2_write_jp2h @MANGLE_PREFIX@_jp2_write_jp2h -#define jp2_write_tile @MANGLE_PREFIX@_jp2_write_tile -#define jpt_init_msg_header @MANGLE_PREFIX@_jpt_init_msg_header -#define jpt_read_msg_header @MANGLE_PREFIX@_jpt_read_msg_header -#define jpt_read_VBAS_info @MANGLE_PREFIX@_jpt_read_VBAS_info -#define jpt_reinit_msg_header @MANGLE_PREFIX@_jpt_reinit_msg_header -#define mct_decode @MANGLE_PREFIX@_mct_decode -#define mct_decode_custom @MANGLE_PREFIX@_mct_decode_custom -#define mct_decode_real @MANGLE_PREFIX@_mct_decode_real -#define mct_encode @MANGLE_PREFIX@_mct_encode -#define mct_encode_custom @MANGLE_PREFIX@_mct_encode_custom -#define mct_encode_real @MANGLE_PREFIX@_mct_encode_real -#define mct_getnorm @MANGLE_PREFIX@_mct_getnorm -#define mct_getnorm_real @MANGLE_PREFIX@_mct_getnorm_real -#define mqc_bypass_enc @MANGLE_PREFIX@_mqc_bypass_enc -#define mqc_bypass_flush_enc @MANGLE_PREFIX@_mqc_bypass_flush_enc -#define mqc_bypass_init_enc @MANGLE_PREFIX@_mqc_bypass_init_enc -#define mqc_create @MANGLE_PREFIX@_mqc_create -#define mqc_decode @MANGLE_PREFIX@_mqc_decode -#define mqc_destroy @MANGLE_PREFIX@_mqc_destroy -#define mqc_encode @MANGLE_PREFIX@_mqc_encode -#define mqc_erterm_enc @MANGLE_PREFIX@_mqc_erterm_enc -#define mqc_flush @MANGLE_PREFIX@_mqc_flush -#define mqc_init_dec @MANGLE_PREFIX@_mqc_init_dec -#define mqc_init_enc @MANGLE_PREFIX@_mqc_init_enc -#define mqc_numbytes @MANGLE_PREFIX@_mqc_numbytes -#define mqc_reset_enc @MANGLE_PREFIX@_mqc_reset_enc -#define mqc_resetstates @MANGLE_PREFIX@_mqc_resetstates -#define mqc_restart_enc @MANGLE_PREFIX@_mqc_restart_enc -#define mqc_restart_init_enc @MANGLE_PREFIX@_mqc_restart_init_enc -#define mqc_segmark_enc @MANGLE_PREFIX@_mqc_segmark_enc -#define mqc_setstate @MANGLE_PREFIX@_mqc_setstate -#define opj_calculate_norms @MANGLE_PREFIX@_opj_calculate_norms -#define opj_clock @MANGLE_PREFIX@_opj_clock -#define opj_create_compress @MANGLE_PREFIX@_opj_create_compress -#define opj_create_decompress @MANGLE_PREFIX@_opj_create_decompress -#define opj_decode @MANGLE_PREFIX@_opj_decode -#define opj_decode_tile_data @MANGLE_PREFIX@_opj_decode_tile_data -#define opj_default_callback @MANGLE_PREFIX@_opj_default_callback -#define opj_destroy_codec @MANGLE_PREFIX@_opj_destroy_codec -#define opj_destroy_cstr_info @MANGLE_PREFIX@_opj_destroy_cstr_info -#define opj_encode @MANGLE_PREFIX@_opj_encode -#define opj_end_compress @MANGLE_PREFIX@_opj_end_compress -#define opj_end_decompress @MANGLE_PREFIX@_opj_end_decompress -#define opj_event_msg @MANGLE_PREFIX@_opj_event_msg -#define opj_image_comp_update @MANGLE_PREFIX@_opj_image_comp_update -#define opj_image_create @MANGLE_PREFIX@_opj_image_create -#define opj_image_create0 @MANGLE_PREFIX@_opj_image_create0 -#define opj_image_destroy @MANGLE_PREFIX@_opj_image_destroy -#define opj_image_tile_create @MANGLE_PREFIX@_opj_image_tile_create -#define opj_lupDecompose @MANGLE_PREFIX@_opj_lupDecompose -#define opj_lupInvert @MANGLE_PREFIX@_opj_lupInvert -#define opj_lupSolve @MANGLE_PREFIX@_opj_lupSolve -#define opj_matrix_inversion_f @MANGLE_PREFIX@_opj_matrix_inversion_f -#define opj_procedure_list_add_procedure @MANGLE_PREFIX@_opj_procedure_list_add_procedure -#define opj_procedure_list_clear @MANGLE_PREFIX@_opj_procedure_list_clear -#define opj_procedure_list_create @MANGLE_PREFIX@_opj_procedure_list_create -#define opj_procedure_list_destroy @MANGLE_PREFIX@_opj_procedure_list_destroy -#define opj_procedure_list_get_first_procedure @MANGLE_PREFIX@_opj_procedure_list_get_first_procedure -#define opj_procedure_list_get_nb_procedures @MANGLE_PREFIX@_opj_procedure_list_get_nb_procedures -#define opj_read_bytes_BE @MANGLE_PREFIX@_opj_read_bytes_BE -#define opj_read_bytes_LE @MANGLE_PREFIX@_opj_read_bytes_LE -#define opj_read_double_BE @MANGLE_PREFIX@_opj_read_double_BE -#define opj_read_double_LE @MANGLE_PREFIX@_opj_read_double_LE -#define opj_read_float_BE @MANGLE_PREFIX@_opj_read_float_BE -#define opj_read_float_LE @MANGLE_PREFIX@_opj_read_float_LE -#define opj_read_from_file @MANGLE_PREFIX@_opj_read_from_file -#define opj_read_header @MANGLE_PREFIX@_opj_read_header -#define opj_read_tile_header @MANGLE_PREFIX@_opj_read_tile_header -#define opj_restrict_decoding @MANGLE_PREFIX@_opj_restrict_decoding -#define opj_seek_from_file @MANGLE_PREFIX@_opj_seek_from_file -#define opj_set_decode_area @MANGLE_PREFIX@_opj_set_decode_area -#define opj_set_default_decoder_parameters @MANGLE_PREFIX@_opj_set_default_decoder_parameters -#define opj_set_default_encoder_parameters @MANGLE_PREFIX@_opj_set_default_encoder_parameters -#define opj_set_error_handler @MANGLE_PREFIX@_opj_set_error_handler -#define opj_set_info_handler @MANGLE_PREFIX@_opj_set_info_handler -#define opj_set_MCT @MANGLE_PREFIX@_opj_set_MCT -#define opj_setup_decoder @MANGLE_PREFIX@_opj_setup_decoder -#define opj_setup_encoder @MANGLE_PREFIX@_opj_setup_encoder -#define opj_set_warning_handler @MANGLE_PREFIX@_opj_set_warning_handler -#define opj_skip_from_file @MANGLE_PREFIX@_opj_skip_from_file -#define opj_start_compress @MANGLE_PREFIX@_opj_start_compress -#define opj_stream_create @MANGLE_PREFIX@_opj_stream_create -#define opj_stream_create_default_file_stream @MANGLE_PREFIX@_opj_stream_create_default_file_stream -#define opj_stream_create_file_stream @MANGLE_PREFIX@_opj_stream_create_file_stream -#define opj_stream_default_create @MANGLE_PREFIX@_opj_stream_default_create -#define opj_stream_default_read @MANGLE_PREFIX@_opj_stream_default_read -#define opj_stream_default_seek @MANGLE_PREFIX@_opj_stream_default_seek -#define opj_stream_default_skip @MANGLE_PREFIX@_opj_stream_default_skip -#define opj_stream_default_write @MANGLE_PREFIX@_opj_stream_default_write -#define opj_stream_destroy @MANGLE_PREFIX@_opj_stream_destroy -#define opj_stream_flush @MANGLE_PREFIX@_opj_stream_flush -#define opj_stream_has_seek @MANGLE_PREFIX@_opj_stream_has_seek -#define opj_stream_read_data @MANGLE_PREFIX@_opj_stream_read_data -#define opj_stream_read_seek @MANGLE_PREFIX@_opj_stream_read_seek -#define opj_stream_read_skip @MANGLE_PREFIX@_opj_stream_read_skip -#define opj_stream_seek @MANGLE_PREFIX@_opj_stream_seek -#define opj_stream_set_read_function @MANGLE_PREFIX@_opj_stream_set_read_function -#define opj_stream_set_seek_function @MANGLE_PREFIX@_opj_stream_set_seek_function -#define opj_stream_set_skip_function @MANGLE_PREFIX@_opj_stream_set_skip_function -#define opj_stream_set_user_data @MANGLE_PREFIX@_opj_stream_set_user_data -#define opj_stream_set_write_function @MANGLE_PREFIX@_opj_stream_set_write_function -#define opj_stream_skip @MANGLE_PREFIX@_opj_stream_skip -#define opj_stream_tell @MANGLE_PREFIX@_opj_stream_tell -#define opj_stream_write_data @MANGLE_PREFIX@_opj_stream_write_data -#define opj_stream_write_seek @MANGLE_PREFIX@_opj_stream_write_seek -#define opj_stream_write_skip @MANGLE_PREFIX@_opj_stream_write_skip -#define opj_version @MANGLE_PREFIX@_opj_version -#define opj_write_bytes_BE @MANGLE_PREFIX@_opj_write_bytes_BE -#define opj_write_bytes_LE @MANGLE_PREFIX@_opj_write_bytes_LE -#define opj_write_double_BE @MANGLE_PREFIX@_opj_write_double_BE -#define opj_write_double_LE @MANGLE_PREFIX@_opj_write_double_LE -#define opj_write_float_BE @MANGLE_PREFIX@_opj_write_float_BE -#define opj_write_float_LE @MANGLE_PREFIX@_opj_write_float_LE -#define opj_write_from_file @MANGLE_PREFIX@_opj_write_from_file -#define opj_write_tile @MANGLE_PREFIX@_opj_write_tile -#define pi_check_next_level @MANGLE_PREFIX@_pi_check_next_level -#define pi_create @MANGLE_PREFIX@_pi_create -#define pi_create_decode @MANGLE_PREFIX@_pi_create_decode -#define pi_create_encode @MANGLE_PREFIX@_pi_create_encode -#define pi_destroy @MANGLE_PREFIX@_pi_destroy -#define pi_initialise_encode @MANGLE_PREFIX@_pi_initialise_encode -#define pi_next @MANGLE_PREFIX@_pi_next -#define pi_update_decode_not_poc @MANGLE_PREFIX@_pi_update_decode_not_poc -#define pi_update_decode_poc @MANGLE_PREFIX@_pi_update_decode_poc -#define pi_update_encode_not_poc @MANGLE_PREFIX@_pi_update_encode_not_poc -#define pi_update_encode_poc_and_final @MANGLE_PREFIX@_pi_update_encode_poc_and_final -#define pi_update_encoding_parameters @MANGLE_PREFIX@_pi_update_encoding_parameters -#define _ProfInit @MANGLE_PREFIX@__ProfInit -#define _ProfPrint @MANGLE_PREFIX@__ProfPrint -#define _ProfSave @MANGLE_PREFIX@__ProfSave -#define _ProfStart @MANGLE_PREFIX@__ProfStart -#define _ProfStop @MANGLE_PREFIX@__ProfStop -#define raw_create @MANGLE_PREFIX@_raw_create -#define raw_decode @MANGLE_PREFIX@_raw_decode -#define raw_destroy @MANGLE_PREFIX@_raw_destroy -#define raw_init_dec @MANGLE_PREFIX@_raw_init_dec -#define raw_numbytes @MANGLE_PREFIX@_raw_numbytes -#define set_default_event_handler @MANGLE_PREFIX@_set_default_event_handler -#define t1_create @MANGLE_PREFIX@_t1_create -#define t1_decode_cblks @MANGLE_PREFIX@_t1_decode_cblks -#define t1_destroy @MANGLE_PREFIX@_t1_destroy -#define t1_encode_cblks @MANGLE_PREFIX@_t1_encode_cblks -#define t1_updateflags @MANGLE_PREFIX@_t1_updateflags -#define t2_create @MANGLE_PREFIX@_t2_create -#define t2_decode_packets @MANGLE_PREFIX@_t2_decode_packets -#define t2_destroy @MANGLE_PREFIX@_t2_destroy -#define t2_encode_packet @MANGLE_PREFIX@_t2_encode_packet -#define t2_encode_packets @MANGLE_PREFIX@_t2_encode_packets -#define t2_read_packet_header @MANGLE_PREFIX@_t2_read_packet_header -#define tcd_code_block_dec_deallocate @MANGLE_PREFIX@_tcd_code_block_dec_deallocate -#define tcd_code_block_enc_deallocate @MANGLE_PREFIX@_tcd_code_block_enc_deallocate -#define tcd_copy_tile_data @MANGLE_PREFIX@_tcd_copy_tile_data -#define tcd_create @MANGLE_PREFIX@_tcd_create -#define tcd_dc_level_shift_decode @MANGLE_PREFIX@_tcd_dc_level_shift_decode -#define tcd_dc_level_shift_encode @MANGLE_PREFIX@_tcd_dc_level_shift_encode -#define tcd_decode_tile @MANGLE_PREFIX@_tcd_decode_tile -#define tcd_destroy @MANGLE_PREFIX@_tcd_destroy -#define tcd_dwt_decode @MANGLE_PREFIX@_tcd_dwt_decode -#define tcd_dwt_encode @MANGLE_PREFIX@_tcd_dwt_encode -#define tcd_encode_tile @MANGLE_PREFIX@_tcd_encode_tile -#define tcd_get_decoded_tile_size @MANGLE_PREFIX@_tcd_get_decoded_tile_size -#define tcd_get_encoded_tile_size @MANGLE_PREFIX@_tcd_get_encoded_tile_size -#define tcd_init @MANGLE_PREFIX@_tcd_init -#define tcd_init_decode_tile @MANGLE_PREFIX@_tcd_init_decode_tile -#define tcd_init_encode_tile @MANGLE_PREFIX@_tcd_init_encode_tile -#define tcd_makelayer @MANGLE_PREFIX@_tcd_makelayer -#define tcd_makelayer_fixed @MANGLE_PREFIX@_tcd_makelayer_fixed -#define tcd_mct_decode @MANGLE_PREFIX@_tcd_mct_decode -#define tcd_mct_encode @MANGLE_PREFIX@_tcd_mct_encode -#define tcd_rateallocate @MANGLE_PREFIX@_tcd_rateallocate -#define tcd_rate_allocate_encode @MANGLE_PREFIX@_tcd_rate_allocate_encode -#define tcd_rateallocate_fixed @MANGLE_PREFIX@_tcd_rateallocate_fixed -#define tcd_t1_decode @MANGLE_PREFIX@_tcd_t1_decode -#define tcd_t1_encode @MANGLE_PREFIX@_tcd_t1_encode -#define tcd_t2_decode @MANGLE_PREFIX@_tcd_t2_decode -#define tcd_t2_encode @MANGLE_PREFIX@_tcd_t2_encode -#define tcd_update_tile_data @MANGLE_PREFIX@_tcd_update_tile_data -#define tgt_create @MANGLE_PREFIX@_tgt_create -#define tgt_decode @MANGLE_PREFIX@_tgt_decode -#define tgt_destroy @MANGLE_PREFIX@_tgt_destroy -#define tgt_encode @MANGLE_PREFIX@_tgt_encode -#define tgt_init @MANGLE_PREFIX@_tgt_init -#define tgt_reset @MANGLE_PREFIX@_tgt_reset -#define tgt_setvalue @MANGLE_PREFIX@_tgt_setvalue -#define v4dwt_decode @MANGLE_PREFIX@_v4dwt_decode -#define dwt_norms @MANGLE_PREFIX@_dwt_norms -#define dwt_norms_real @MANGLE_PREFIX@_dwt_norms_real -#define mct_norms @MANGLE_PREFIX@_mct_norms -#define mct_norms_real @MANGLE_PREFIX@_mct_norms_real -#define lut_ctxno_zc @MANGLE_PREFIX@_lut_ctxno_zc -#define lut_ctxno_sc @MANGLE_PREFIX@_lut_ctxno_sc -#define lut_spb @MANGLE_PREFIX@_lut_spb -#define lut_nmsedec_sig @MANGLE_PREFIX@_lut_nmsedec_sig -#define lut_nmsedec_sig0 @MANGLE_PREFIX@_lut_nmsedec_sig0 -#define lut_nmsedec_ref @MANGLE_PREFIX@_lut_nmsedec_ref -#define lut_nmsedec_ref0 @MANGLE_PREFIX@_lut_nmsedec_ref0 -#define MCT_ELEMENT_SIZE @MANGLE_PREFIX@_MCT_ELEMENT_SIZE -#define j2k_prog_order_list @MANGLE_PREFIX@_j2k_prog_order_list -#define mqc_states @MANGLE_PREFIX@_mqc_states -#define j2k_memory_marker_handler_tab @MANGLE_PREFIX@_j2k_memory_marker_handler_tab -#define j2k_mct_read_functions_to_int32 @MANGLE_PREFIX@_j2k_mct_read_functions_to_int32 -#define j2k_mct_write_functions_from_float @MANGLE_PREFIX@_j2k_mct_write_functions_from_float -#define jp2_header @MANGLE_PREFIX@_jp2_header -#define j2k_mct_read_functions_to_float @MANGLE_PREFIX@_j2k_mct_read_functions_to_float -#define jp2_img_header @MANGLE_PREFIX@_jp2_img_header -#define group_list @MANGLE_PREFIX@_group_list - -#endif diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_configure.h.in b/Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_configure.h.in deleted file mode 100644 index 6943184b832..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_configure.h.in +++ /dev/null @@ -1,32 +0,0 @@ -/* - * here is where system comupted values get stored these values should only - * change when the target compile platform changes - */ - -/* what byte order */ -#ifndef __OPJ_CONFIGURE_H -#define __OPJ_CONFIGURE_H - -/* All compilers that support Mac OS X define either __BIG_ENDIAN__ or - __LITTLE_ENDIAN__ to match the endianness of the architecture being - compiled for. This is not necessarily the same as the architecture of - the machine doing the building. In order to support Universal Binaries on - Mac OS X, we prefer those defines to decide the endianness. - Elsewhere use the platform check result. */ -#if !defined(__APPLE__) - #cmakedefine CMAKE_WORDS_BIGENDIAN - #ifdef CMAKE_WORDS_BIGENDIAN - #define OPJ_BIG_ENDIAN - #else - #define OPJ_LITTLE_ENDIAN - #endif -#else - #if defined(__BIG_ENDIAN__) - #define OPJ_BIG_ENDIAN - #else - #define OPJ_LITTLE_ENDIAN - #endif -#endif - - -#endif /* __OPJ_CONFIGURE_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_includes.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_includes.h deleted file mode 100644 index ed1a06a0db9..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_includes.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2005, Hervé 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_INCLUDES_H -#define OPJ_INCLUDES_H - -/* - ========================================================== - Standard includes used by the library - ========================================================== -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - ========================================================== - OpenJPEG interface - ========================================================== - */ - -/* - ========================================================== - OpenJPEG modules - ========================================================== -*/ - -/* Ignore GCC attributes if this is not GCC */ -#ifndef __GNUC__ - #define __attribute__(x) /* __attribute__(x) */ -#endif - -/* -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 __inline - #elif defined(__GNUC__) - #define INLINE __inline__ - #elif defined(__MWERKS__) - #define INLINE inline - #else - /* add other compilers here ... */ - #define INLINE - #endif /* defined() */ -#endif /* INLINE */ - -/* Are restricted pointers available? (C99) */ -#if (__STDC_VERSION__ != 199901L) - /* Not a C99 compiler */ - #ifdef __GNUC__ - #define restrict __restrict__ - #else - #define restrict /* restrict */ - #endif -#endif - -/* MSVC and Borland C do not have lrintf */ -#if defined(_MSC_VER) || defined(__BORLANDC__) - -/* MSVC 64bits doesn't support _asm */ -#if !defined(_WIN64) -static INLINE long opj_lrintf(float f){ - int i; - - _asm{ - fld f - fistp i - }; - - return i; -} -#else -static INLINE long opj_lrintf(float x){ - long r; - if (x>=0.f) - { - x+=0.5f; - } - else - { - x-=0.5f; - } - r = (long)(x); - if ( x != (float)(r) ) return r; - return 2*(r/2); -} -#endif - -#endif - -#endif /* OPJ_INCLUDES_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_malloc.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_malloc.h deleted file mode 100644 index a5cdedd1365..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/opj_malloc.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2005, Hervé Drolon, FreeImage Team - * Copyright (c) 2007, Callum Lerwick - * 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_MALLOC_H -#define __OPJ_MALLOC_H -/** -@file opj_malloc.h -@brief Internal functions - -The functions in opj_malloc.h are internal utilities used for memory management. -*/ -#include "openjpeg.h" -#include "opj_includes.h" -/** @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 -*/ -#define opj_malloc(size) malloc(size) -#define my_opj_malloc(size) malloc(size) - -/** -Allocate a memory block with elements initialized to 0 -@param num Blocks to allocate -@param size Bytes per block to allocate -@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available -*/ -#define opj_calloc(num, size) calloc(num, size) - -/** -Allocate memory aligned to a 16 byte boundry -@param size Bytes to allocate -@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available -*/ -/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */ -#ifdef _WIN32 - /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */ - #ifdef __GNUC__ - #include - #define HAVE_MM_MALLOC - #else /* MSVC, Intel C++ */ - #include - #ifdef _mm_malloc - #define HAVE_MM_MALLOC - #endif - #endif -#else /* Not _WIN32 */ - #if defined(__sun) - #define HAVE_MEMALIGN - /* Linux x86_64 and OSX always align allocations to 16 bytes */ - #elif !defined(__amd64__) && !defined(__APPLE__) && !defined(__ANDROID__) - /* FIXME: Yes, this is a big assumption */ - #define HAVE_POSIX_MEMALIGN - #endif -#endif - -#define opj_aligned_malloc(size) malloc(size) -#define opj_aligned_free(m) free(m) - -#ifdef HAVE_MM_MALLOC - #undef opj_aligned_malloc - #define opj_aligned_malloc(size) _mm_malloc(size, 16) - #undef opj_aligned_free - #define opj_aligned_free(m) _mm_free(m) -#endif - -#ifdef HAVE_MEMALIGN - extern void* memalign(size_t, size_t); - #undef opj_aligned_malloc - #define opj_aligned_malloc(size) memalign(16, (size)) - #undef opj_aligned_free - #define opj_aligned_free(m) free(m) -#endif - -#ifdef HAVE_POSIX_MEMALIGN - #undef opj_aligned_malloc - extern int posix_memalign(void**, size_t, size_t); - - static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){ - void* mem = NULL; - int ret = posix_memalign(&mem, 16, size); - if( ret != 0 ) - { - printf("The alignment argument was not a power of two, or was not a multiple of sizeof(void *)," - " or there was insufficient memory to fulfill the allocation request, code %d",ret); - } - return mem; - } - #undef opj_aligned_free - #define opj_aligned_free(m) free(m) -#endif - -/** -Reallocate memory blocks. -@param memblock Pointer to previously allocated memory block -@param size New size in bytes -@return Returns a void pointer to the reallocated (and possibly moved) memory block -*/ -#define opj_realloc(m, s) realloc(m, s) -#define my_opj_realloc(m,s) realloc(m,s) - - -/** -Deallocates or frees a memory block. -@param memblock Previously allocated memory block to be freed -*/ -#define opj_free(m) free(m) - -#ifdef __GNUC__ -#pragma GCC poison malloc calloc realloc free -#endif - -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __OPJ_MALLOC_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.c deleted file mode 100644 index 74ce5dc5b5c..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.c +++ /dev/null @@ -1,2000 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2006-2007, Parvatha Elangovan - * 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 "pi.h" -#include "int.h" -#include "opj_malloc.h" -#include "j2k.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 bool 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 bool 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 bool 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 bool 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 bool 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 dx_min the minimum dx of all the components of all the resolutions for the tile. - * @param dy_min the minimum dy of all the components of all the resolutions for the tile. - */ -void pi_update_encode_poc_and_final ( - opj_cp_t *p_cp, - OPJ_UINT32 p_tileno, - OPJ_INT32 p_tx0, - OPJ_INT32 p_tx1, - OPJ_INT32 p_ty0, - OPJ_INT32 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_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 dx_min the minimum dx of all the components of all the resolutions for the tile. - * @param dy_min the minimum dy of all the components of all the resolutions for the tile. - */ -void pi_update_encode_not_poc ( - opj_cp_t *p_cp, - OPJ_UINT32 p_num_comps, - OPJ_UINT32 p_tileno, - OPJ_INT32 p_tx0, - OPJ_INT32 p_tx1, - OPJ_INT32 p_ty0, - OPJ_INT32 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 the maximum precision for all the bands of the tile - * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. - * @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. - * @param dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile. - */ -void get_encoding_parameters( - const opj_image_t *p_image, - const opj_cp_t *p_cp, - OPJ_UINT32 tileno, - OPJ_INT32 * p_tx0, - OPJ_INT32 * p_tx1, - OPJ_INT32 * p_ty0, - OPJ_INT32 * 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 the maximum precision for all the bands of the tile - * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. - * @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. - * @param dy_min pointer that will hold the 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. - */ -void get_all_encoding_parameters( - const opj_image_t *p_image, - const opj_cp_t *p_cp, - OPJ_UINT32 tileno, - OPJ_INT32 * p_tx0, - OPJ_INT32 * p_tx1, - OPJ_INT32 * p_ty0, - OPJ_INT32 * 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 p_tile_no the index of the tile from which creating the packet iterator. - */ -opj_pi_iterator_t * pi_create( - const opj_image_t *image, - const opj_cp_t *cp, - OPJ_UINT32 tileno - ); -void 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); -void 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); - - -/*@}*/ - -/*@}*/ - -/* -========================================================== - local functions -========================================================== -*/ - -static bool pi_next_lrcp(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = 00; - opj_pi_resolution_t *res = 00; - OPJ_UINT32 indexvalue = 0; - - 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++) { - indexvalue = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[indexvalue]) { - pi->include[indexvalue] = 1; - return true; - } -LABEL_SKIP:; - } - } - } - } - - return false; -} - -static bool pi_next_rlcp(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = 00; - opj_pi_resolution_t *res = 00; - OPJ_UINT32 indexvalue = 0; - - 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++) { - indexvalue = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[indexvalue]) { - pi->include[indexvalue] = 1; - return true; - } -LABEL_SKIP:; - } - } - } - } - - return false; -} - -static bool pi_next_rpcl(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = 00; - opj_pi_resolution_t *res = 00; - OPJ_UINT32 indexvalue = 0; - - 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_INT32 dx, dy; // comp->dx is signed, so dx,dy must be as well. - res = &comp->resolutions[resno]; - dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); - dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); - pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); - pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); - } - } - } -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 = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) { - for (pi->x = pi->poc.tx0; pi->x < 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_INT32 trx0, try0; - OPJ_INT32 trx1, try1; - OPJ_UINT32 rpx, rpy; - OPJ_INT32 prci, prcj; - comp = &pi->comps[pi->compno]; - if (pi->resno >= comp->numresolutions) { - continue; - } - res = &comp->resolutions[pi->resno]; - levelno = comp->numresolutions - 1 - pi->resno; - trx0 = int_ceildiv(pi->tx0, comp->dx << levelno); - try0 = int_ceildiv(pi->ty0, comp->dy << levelno); - trx1 = int_ceildiv(pi->tx1, comp->dx << levelno); - try1 = int_ceildiv(pi->ty1, comp->dy << levelno); - rpx = res->pdx + levelno; - rpy = res->pdy + levelno; - if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpy))))){ - continue; - } - if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ - continue; - } - - if ((res->pw==0)||(res->ph==0)) continue; - - if ((trx0==trx1)||(try0==try1)) continue; - - prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) - - int_floordivpow2(trx0, res->pdx); - prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) - - int_floordivpow2(try0, res->pdy); - pi->precno = prci + prcj * res->pw; - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - indexvalue = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[indexvalue]) { - pi->include[indexvalue] = 1; - return true; - } -LABEL_SKIP:; - } - } - } - } - } - - return false; -} - -static bool pi_next_pcrl(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = 00; - opj_pi_resolution_t *res = 00; - OPJ_UINT32 indexvalue = 0; - - 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_INT32 dx, dy; // comp->dx is signed, so dx,dy must be as well. - res = &comp->resolutions[resno]; - dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); - dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); - pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); - pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); - } - } - } - 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 = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) { - for (pi->x = pi->poc.tx0; pi->x < 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]; - // TODO - for (pi->resno = pi->poc.resno0; pi->resno < uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { - OPJ_UINT32 levelno; - OPJ_INT32 trx0, try0; - OPJ_INT32 trx1, try1; - OPJ_UINT32 rpx, rpy; - OPJ_INT32 prci, prcj; - res = &comp->resolutions[pi->resno]; - levelno = comp->numresolutions - 1 - pi->resno; - trx0 = int_ceildiv(pi->tx0, comp->dx << levelno); - try0 = int_ceildiv(pi->ty0, comp->dy << levelno); - trx1 = int_ceildiv(pi->tx1, comp->dx << levelno); - try1 = int_ceildiv(pi->ty1, comp->dy << levelno); - rpx = res->pdx + levelno; - rpy = res->pdy + levelno; - if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpy))))){ - continue; - } - if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ - continue; - } - - if ((res->pw==0)||(res->ph==0)) continue; - - if ((trx0==trx1)||(try0==try1)) continue; - - prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) - - int_floordivpow2(trx0, res->pdx); - prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) - - int_floordivpow2(try0, res->pdy); - pi->precno = prci + prcj * res->pw; - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - indexvalue = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[indexvalue]) { - pi->include[indexvalue] = 1; - return true; - } -LABEL_SKIP:; - } - } - } - } - } - - return false; -} - -static bool pi_next_cprl(opj_pi_iterator_t * pi) { - opj_pi_comp_t *comp = 00; - opj_pi_resolution_t *res = 00; - OPJ_UINT32 indexvalue = 0; - - 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_INT32 dx, dy; // comp->dx is signed, so dx,dy must be as well. - res = &comp->resolutions[resno]; - dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno)); - dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno)); - pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); - pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); - } - 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 = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) { - for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) { - // TODO - for (pi->resno = pi->poc.resno0; pi->resno < uint_min(pi->poc.resno1, comp->numresolutions); pi->resno++) { - OPJ_UINT32 levelno; - OPJ_INT32 trx0, try0; - OPJ_INT32 trx1, try1; - OPJ_UINT32 rpx, rpy; - OPJ_INT32 prci, prcj; - res = &comp->resolutions[pi->resno]; - levelno = comp->numresolutions - 1 - pi->resno; - trx0 = int_ceildiv(pi->tx0, comp->dx << levelno); - try0 = int_ceildiv(pi->ty0, comp->dy << levelno); - trx1 = int_ceildiv(pi->tx1, comp->dx << levelno); - try1 = int_ceildiv(pi->ty1, comp->dy << levelno); - rpx = res->pdx + levelno; - rpy = res->pdy + levelno; - if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpy))))){ - continue; - } - if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){ - continue; - } - - if ((res->pw==0)||(res->ph==0)) continue; - - if ((trx0==trx1)||(try0==try1)) continue; - - prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx) - - int_floordivpow2(trx0, res->pdx); - prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy) - - int_floordivpow2(try0, res->pdy); - pi->precno = prci + prcj * res->pw; - for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) { - indexvalue = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; - if (!pi->include[indexvalue]) { - pi->include[indexvalue] = 1; - return true; - } -LABEL_SKIP:; - } - } - } - } - } - - return false; -} - -/* -========================================================== - Packet iterator interface -========================================================== -*/ -opj_pi_iterator_t *pi_create_decode( - opj_image_t *p_image, - opj_cp_t *p_cp, - OPJ_UINT32 p_tile_no - ) -{ - // loop - OPJ_UINT32 pino; - OPJ_UINT32 compno, resno; - - // to store w, h, dx and dy fro all components and resolutions - OPJ_UINT32 * l_tmp_data; - OPJ_UINT32 ** l_tmp_ptr; - - // encoding prameters to set - OPJ_UINT32 l_max_res; - OPJ_UINT32 l_max_prec; - OPJ_INT32 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 * J2K_MAXRLVLS; - l_tmp_data = (OPJ_UINT32*)opj_malloc( - l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32)); - if - (! l_tmp_data) - { - return 00; - } - l_tmp_ptr = (OPJ_UINT32**)opj_malloc( - p_image->numcomps * sizeof(OPJ_UINT32 *)); - if - (! l_tmp_ptr) - { - opj_free(l_tmp_data); - return 00; - } - - // memory allocation for pi - l_pi = pi_create(p_image,p_cp,p_tile_no); - 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 < p_image->numcomps; ++compno) - { - l_tmp_ptr[compno] = l_encoding_value_ptr; - l_encoding_value_ptr += l_data_stride; - } - // get encoding parameters - 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 = p_image->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 - l_current_pi->include = (OPJ_INT16*) opj_calloc(l_tcp->numlayers * l_step_l, sizeof(OPJ_INT16)); - if - (!l_current_pi->include) - { - opj_free(l_tmp_data); - opj_free(l_tmp_ptr); - pi_destroy(l_pi, l_bound); - return 00; - } - memset(l_current_pi->include,0,l_tcp->numlayers * l_step_l* sizeof(OPJ_INT16)); - - // 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 pi_create */ - for - (compno = 0; compno < l_current_pi->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 ; pinocomps; - opj_image_comp_t * l_img_comp_v = 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 pi_create */ - for - (compno = 0; compno < l_current_pi->numcomps; ++compno) - { - opj_pi_resolution_t *l_res = l_current_comp_v->resolutions; - l_encoding_value_ptr = l_tmp_ptr[compno]; - - l_current_comp_v->dx = l_img_comp_v->dx; - l_current_comp_v->dy = l_img_comp_v->dy; - /* resolutions have already been initialized */ - for - (resno = 0; resno < l_current_comp_v->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_v; - ++l_img_comp_v; - ++l_tccp; - } - // special treatment - l_current_pi->include = (l_current_pi-1)->include; - ++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) - { - pi_update_decode_poc (l_pi,l_tcp,l_max_prec,l_max_res); - } - else - { - pi_update_decode_not_poc(l_pi,l_tcp,l_max_prec,l_max_res); - } - return l_pi; -} - -void 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 prameters to set - OPJ_UINT32 l_bound; - - opj_pi_iterator_t * l_current_pi = 00; - opj_poc_t* l_current_poc = 0; - - // 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;pinopoc.prg = l_current_poc->prg; - l_current_pi->first = 1; - - l_current_pi->poc.resno0 = l_current_poc->resno0; - l_current_pi->poc.compno0 = l_current_poc->compno0; - l_current_pi->poc.layno0 = 0; - l_current_pi->poc.precno0 = 0; - l_current_pi->poc.resno1 = l_current_poc->resno1; - l_current_pi->poc.compno1 = l_current_poc->compno1; - l_current_pi->poc.layno1 = l_current_poc->layno1; - l_current_pi->poc.precno1 = p_max_precision; - ++l_current_pi; - ++l_current_poc; - } -} - -void 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 prameters 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;pinopoc.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; - } -} - -/** - * Creates a packet iterator for encoding. - * - * @param p_image the image being encoded. - * @param p_cp the coding parameters. - * @param p_tile_no index of the tile being encoded. - * @param p_t2_mode the type of pass for generating the packet iterator - * @return a list of packet iterator that points to the first packet of the tile (not true). -*/ -opj_pi_iterator_t *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 - ) -{ - // loop - OPJ_UINT32 pino; - OPJ_UINT32 compno, resno; - - // to store w, h, dx and dy fro all components and resolutions - OPJ_UINT32 * l_tmp_data; - OPJ_UINT32 ** l_tmp_ptr; - - // encoding prameters to set - OPJ_UINT32 l_max_res; - OPJ_UINT32 l_max_prec; - OPJ_INT32 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 * J2K_MAXRLVLS; - l_tmp_data = (OPJ_UINT32*)opj_malloc( - l_data_stride * p_image->numcomps * sizeof(OPJ_UINT32)); - if - (! l_tmp_data) - { - return 00; - } - l_tmp_ptr = (OPJ_UINT32**)opj_malloc( - p_image->numcomps * sizeof(OPJ_UINT32 *)); - if - (! l_tmp_ptr) - { - opj_free(l_tmp_data); - return 00; - } - - // memory allocation for pi - l_pi = pi_create(p_image,p_cp,p_tile_no); - 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 < p_image->numcomps; ++compno) - { - l_tmp_ptr[compno] = l_encoding_value_ptr; - l_encoding_value_ptr += l_data_stride; - } - // get encoding parameters - 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 = p_image->numcomps * l_step_c; - l_step_l = l_max_res * l_step_r; - - // set values for first packet iterator - l_pi->tp_on = p_cp->m_specific_param.m_enc.m_tp_on; - l_current_pi = l_pi; - - // memory allocation for include - l_current_pi->include = (OPJ_INT16*) opj_calloc(l_tcp->numlayers * l_step_l, sizeof(OPJ_INT16)); - if - (!l_current_pi->include) - { - opj_free(l_tmp_data); - opj_free(l_tmp_ptr); - pi_destroy(l_pi, l_bound); - return 00; - } - memset(l_current_pi->include,0,l_tcp->numlayers * l_step_l* sizeof(OPJ_INT16)); - - // 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 pi_create */ - for - (compno = 0; compno < l_current_pi->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 ; pinocomps; - opj_image_comp_t * l_img_comp_v = 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 pi_create */ - for - (compno = 0; compno < l_current_pi->numcomps; ++compno) - { - opj_pi_resolution_t *l_res = l_current_comp_v->resolutions; - l_encoding_value_ptr = l_tmp_ptr[compno]; - - l_current_comp_v->dx = l_img_comp_v->dx; - l_current_comp_v->dy = l_img_comp_v->dy; - /* resolutions have already been initialized */ - for - (resno = 0; resno < l_current_comp_v->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_v; - ++l_img_comp_v; - ++l_tccp; - } - // special treatment - l_current_pi->include = (l_current_pi-1)->include; - ++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 && ( p_cp->m_specific_param.m_enc.m_cinema || p_t2_mode == FINAL_PASS)) - { - 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 - { - 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); - } - return l_pi; -} - -/** - * 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 pi_update_encoding_parameters( - const opj_image_t *p_image, - opj_cp_t *p_cp, - OPJ_UINT32 p_tile_no - ) -{ - // encoding prameters to set - OPJ_UINT32 l_max_res; - OPJ_UINT32 l_max_prec; - OPJ_INT32 l_tx0,l_tx1,l_ty0,l_ty1; - OPJ_UINT32 l_dx_min,l_dy_min; - - // pointers - opj_tcp_t *l_tcp = 00; - - // preconditions in debug - 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 - 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) - { - 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 - { - 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); - } -} - - -/** - * 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 p_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 the maximum precision for all the bands of the tile - * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. - * @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. - * @param dy_min pointer that will hold the the minimum dy of all the components of all the resolutions for the tile. - */ -void get_encoding_parameters( - const opj_image_t *p_image, - const opj_cp_t *p_cp, - OPJ_UINT32 p_tileno, - OPJ_INT32 * p_tx0, - OPJ_INT32 * p_tx1, - OPJ_INT32 * p_ty0, - OPJ_INT32 * 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; - - // preconditions in debug - 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 - *p_tx0 = int_max(p_cp->tx0 + p * p_cp->tdx, p_image->x0); - *p_tx1 = int_min(p_cp->tx0 + (p + 1) * p_cp->tdx, p_image->x1); - *p_ty0 = int_max(p_cp->ty0 + q * p_cp->tdy, p_image->y0); - *p_ty1 = int_min(p_cp->ty0 + (q + 1) * 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) - { - // aritmetic variables to calculate - OPJ_UINT32 l_level_no; - OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1; - OPJ_INT32 l_px0, l_py0, l_px1, py1; - OPJ_UINT32 l_pdx, l_pdy; - OPJ_UINT32 l_pw, l_ph; - OPJ_UINT32 l_product; - OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; - - l_tcx0 = int_ceildiv(*p_tx0, l_img_comp->dx); - l_tcy0 = int_ceildiv(*p_ty0, l_img_comp->dy); - l_tcx1 = int_ceildiv(*p_tx1, l_img_comp->dx); - l_tcy1 = int_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_UINT32 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 * (1 << (l_pdx + l_tccp->numresolutions - 1 - resno)); - l_dy = l_img_comp->dy * (1 << (l_pdy + l_tccp->numresolutions - 1 - resno)); - // take the minimum size for dx for each comp and resolution - *p_dx_min = uint_min(*p_dx_min, l_dx); - *p_dy_min = uint_min(*p_dy_min, l_dy); - // various calculations of extents - l_level_no = l_tccp->numresolutions - 1 - resno; - l_rx0 = int_ceildivpow2(l_tcx0, l_level_no); - l_ry0 = int_ceildivpow2(l_tcy0, l_level_no); - l_rx1 = int_ceildivpow2(l_tcx1, l_level_no); - l_ry1 = int_ceildivpow2(l_tcy1, l_level_no); - l_px0 = int_floordivpow2(l_rx0, l_pdx) << l_pdx; - l_py0 = int_floordivpow2(l_ry0, l_pdy) << l_pdy; - l_px1 = int_ceildivpow2(l_rx1, l_pdx) << l_pdx; - py1 = int_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; - } -} - -/** - * 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 the maximum precision for all the bands of the tile - * @param p_max_res pointer that will hold the the maximum number of resolutions for all the poc inside the tile. - * @param dx_min pointer that will hold the the minimum dx of all the components of all the resolutions for the tile. - * @param dy_min pointer that will hold the 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. - */ -void get_all_encoding_parameters( - const opj_image_t *p_image, - const opj_cp_t *p_cp, - OPJ_UINT32 tileno, - OPJ_INT32 * p_tx0, - OPJ_INT32 * p_tx1, - OPJ_INT32 * p_ty0, - OPJ_INT32 * 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; - - // 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 */ - *p_tx0 = int_max(p_cp->tx0 + p * p_cp->tdx, p_image->x0); - *p_tx1 = int_min(p_cp->tx0 + (p + 1) * p_cp->tdx, p_image->x1); - *p_ty0 = int_max(p_cp->ty0 + q * p_cp->tdy, p_image->y0); - *p_ty1 = int_min(p_cp->ty0 + (q + 1) * 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) - { - // aritmetic variables to calculate - OPJ_UINT32 l_level_no; - OPJ_INT32 l_rx0, l_ry0, l_rx1, l_ry1; - OPJ_INT32 l_px0, l_py0, l_px1, py1; - OPJ_UINT32 l_product; - OPJ_INT32 l_tcx0, l_tcy0, l_tcx1, l_tcy1; - OPJ_UINT32 l_pdx, l_pdy , l_pw , l_ph; - - lResolutionPtr = p_resolutions[compno]; - - l_tcx0 = int_ceildiv(*p_tx0, l_img_comp->dx); - l_tcy0 = int_ceildiv(*p_ty0, l_img_comp->dy); - l_tcx1 = int_ceildiv(*p_tx1, l_img_comp->dx); - l_tcy1 = int_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 - 1; - for - (resno = 0; resno < l_tccp->numresolutions; ++resno) - { - OPJ_UINT32 l_dx, l_dy; - // precinct width and height - l_pdx = l_tccp->prcw[resno]; - l_pdy = l_tccp->prch[resno]; - *lResolutionPtr++ = l_pdx; - *lResolutionPtr++ = l_pdy; - l_dx = l_img_comp->dx * (1 << (l_pdx + l_level_no)); - l_dy = l_img_comp->dy * (1 << (l_pdy + l_level_no)); - // take the minimum size for l_dx for each comp and resolution - *p_dx_min = int_min(*p_dx_min, l_dx); - *p_dy_min = int_min(*p_dy_min, l_dy); - // various calculations of extents - - l_rx0 = int_ceildivpow2(l_tcx0, l_level_no); - l_ry0 = int_ceildivpow2(l_tcy0, l_level_no); - l_rx1 = int_ceildivpow2(l_tcx1, l_level_no); - l_ry1 = int_ceildivpow2(l_tcy1, l_level_no); - l_px0 = int_floordivpow2(l_rx0, l_pdx) << l_pdx; - l_py0 = int_floordivpow2(l_ry0, l_pdy) << l_pdy; - l_px1 = int_ceildivpow2(l_rx1, l_pdx) << l_pdx; - py1 = int_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); - *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_level_no; - } - ++l_tccp; - ++l_img_comp; - } -} - -/** - * 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 p_tile_no the index of the tile from which creating the packet iterator. - */ -opj_pi_iterator_t * pi_create( - const opj_image_t *image, - const opj_cp_t *cp, - OPJ_UINT32 tileno - ) -{ - // 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 00; - } - memset(l_pi,0,l_poc_bound * sizeof(opj_pi_iterator_t)); - l_current_pi = l_pi; - for - (pino = 0; pino < l_poc_bound ; ++pino) - { - l_current_pi->comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t)); - if - (! l_current_pi->comps) - { - pi_destroy(l_pi, l_poc_bound); - return 00; - } - l_current_pi->numcomps = image->numcomps; - memset(l_current_pi->comps,0,image->numcomps * sizeof(opj_pi_comp_t)); - 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_malloc(tccp->numresolutions * sizeof(opj_pi_resolution_t)); - if - (!comp->resolutions) - { - pi_destroy(l_pi, l_poc_bound); - return 00; - } - comp->numresolutions = tccp->numresolutions; - memset(comp->resolutions,0,tccp->numresolutions * sizeof(opj_pi_resolution_t)); - } - ++l_current_pi; - } - return l_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 dx_min the minimum dx of all the components of all the resolutions for the tile. - * @param dy_min the minimum dy of all the components of all the resolutions for the tile. - */ -void pi_update_encode_poc_and_final ( - opj_cp_t *p_cp, - OPJ_UINT32 p_tileno, - OPJ_INT32 p_tx0, - OPJ_INT32 p_tx1, - OPJ_INT32 p_ty0, - OPJ_INT32 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; - - 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 = 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; - 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 = 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; - } -} - -/** - * 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_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 dx_min the minimum dx of all the components of all the resolutions for the tile. - * @param dy_min the minimum dy of all the components of all the resolutions for the tile. - */ -void pi_update_encode_not_poc ( - opj_cp_t *p_cp, - OPJ_UINT32 p_num_comps, - OPJ_UINT32 p_tileno, - OPJ_INT32 p_tx0, - OPJ_INT32 p_tx1, - OPJ_INT32 p_ty0, - OPJ_INT32 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; - } -} - -/** - * 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 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; - } - // TODO - 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); - } -} - -bool pi_next(opj_pi_iterator_t * pi) { - switch (pi->poc.prg) { - case LRCP: - return pi_next_lrcp(pi); - case RLCP: - return pi_next_rlcp(pi); - case RPCL: - return pi_next_rpcl(pi); - case PCRL: - return pi_next_pcrl(pi); - case CPRL: - return pi_next_cprl(pi); - case PROG_UNKNOWN: - return false; - } - - return false; -} - -OPJ_INT32 pi_check_next_level(OPJ_INT32 pos,opj_cp_t *cp,OPJ_UINT32 tileno, OPJ_UINT32 pino, const OPJ_CHAR *prog) -{ - OPJ_INT32 i,l; - opj_tcp_t *tcps =&cp->tcps[tileno]; - opj_poc_t *tcp = &tcps->pocs[pino]; - if(pos>=0){ - for(i=pos;pos>=0;i--){ - switch(prog[i]){ - case 'R': - if(tcp->res_t==tcp->resE){ - l=pi_check_next_level(pos-1,cp,tileno,pino,prog); - if(l==1){ - return 1; - }else{ - return 0; - } - }else{ - return 1; - } - break; - case 'C': - if(tcp->comp_t==tcp->compE){ - l=pi_check_next_level(pos-1,cp,tileno,pino,prog); - if(l==1){ - return 1; - }else{ - return 0; - } - }else{ - return 1; - } - break; - case 'L': - if(tcp->lay_t==tcp->layE){ - l=pi_check_next_level(pos-1,cp,tileno,pino,prog); - if(l==1){ - return 1; - }else{ - return 0; - } - }else{ - return 1; - } - break; - case 'P': - switch(tcp->prg){ - case LRCP||RLCP: - if(tcp->prc_t == tcp->prcE){ - l=pi_check_next_level(i-1,cp,tileno,pino,prog); - if(l==1){ - return 1; - }else{ - return 0; - } - }else{ - return 1; - } - break; - default: - if(tcp->tx0_t == tcp->txE){ - //TY - if(tcp->ty0_t == tcp->tyE){ - l=pi_check_next_level(i-1,cp,tileno,pino,prog); - if(l==1){ - return 1; - }else{ - return 0; - } - }else{ - return 1; - }//TY - }else{ - return 1; - } - break; - }//end case P - }//end switch - }//end for - }//end if - return 0; -} - - -void 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,l; - OPJ_UINT32 incr_top=1,resetX=0; - opj_tcp_t *tcps =&cp->tcps[tileno]; - opj_poc_t *tcp= &tcps->pocs[pino]; - - prog = 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&& ((!cp->m_specific_param.m_enc.m_cinema && (t2_mode == FINAL_PASS)) || cp->m_specific_param.m_enc.m_cinema))){ - 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 LRCP: - case 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 LRCP: - case 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 = pi[pino].poc.tx1; - tcp->ty0_t = 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 LRCP: - case 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){ - l=pi_check_next_level(i-1,cp,tileno,pino,prog); - if(l==1){ - 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){ - l=pi_check_next_level(i-1,cp,tileno,pino,prog); - if(l==1){ - 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){ - l=pi_check_next_level(i-1,cp,tileno,pino,prog); - if(l==1){ - 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 LRCP: - case RLCP: - if(tcp->prc_t == tcp->prcE){ - l=pi_check_next_level(i-1,cp,tileno,pino,prog); - if(l==1){ - 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){ - l=pi_check_next_level(i-1,cp,tileno,pino,prog); - if(l==1){ - 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 = 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 = 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 = 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 = pi[pino].poc.tx1; - incr_top=0; - } - break; - } - break; - } - } - } - } - } -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.h deleted file mode 100644 index 0ddd0badb60..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/pi.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __PI_H -#define __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. -*/ -#include "openjpeg.h" -#include "t2.h" -/** @defgroup PI PI - Implementation of a packet iterator */ -/*@{*/ -struct opj_poc; -struct opj_image; -struct opj_cp; - -/** -FIXME: documentation -*/ -typedef struct opj_pi_resolution { - OPJ_UINT32 pdx, pdy; - OPJ_UINT32 pw, ph; -} opj_pi_resolution_t; - -/** -FIXME: documentation -*/ -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 (usefull for progression order change) */ - OPJ_INT16 *include; - /** 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; - /** progression order change information */ - struct opj_poc poc; - /** number of components in the image */ - OPJ_UINT32 numcomps; - /** Components*/ - opj_pi_comp_t *comps; - OPJ_INT32 tx0, ty0, tx1, ty1; - OPJ_INT32 x, y; - OPJ_UINT32 dx, dy; - /** 0 if the first packet */ - OPJ_UINT32 first : 1; -} opj_pi_iterator_t; - -/** @name Exported functions */ -/*@{*/ -/* ----------------------------------------------------------------------- */ -/** - * Creates a packet iterator for encoding. - * - * @param p_image the image being encoded. - * @param p_cp the coding parameters. - * @param p_tile_no index of the tile being encoded. - * @param p_t2_mode the type of pass for generating the packet iterator - * @return a list of packet iterator that points to the first packet of the tile (not true). -*/ -opj_pi_iterator_t *pi_initialise_encode(const struct opj_image *image,struct opj_cp *cp, OPJ_UINT32 tileno,J2K_T2_MODE t2_mode); - -/** - * 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 pi_update_encoding_parameters( - const struct opj_image *p_image, - struct opj_cp *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 tpnum Tile part number of the current tile -@param tppos The position of the tile part flag in the progression order -*/ -void pi_create_encode( opj_pi_iterator_t *pi, struct opj_cp *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 -@return Returns a packet iterator that points to the first packet of the tile -@see pi_destroy -*/ -opj_pi_iterator_t *pi_create_decode(struct opj_image * image, struct opj_cp * cp, OPJ_UINT32 tileno); - - - -/** - * 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 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 -*/ -bool pi_next(opj_pi_iterator_t * pi); - - -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __PI_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/profile.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/profile.c deleted file mode 100644 index 3f931217776..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/profile.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * 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. - */ - -/** - * Adapted from Herb Marselas -"Profiling, Data Analysis, Scalability, and Magic Numbers: Meeting the Minimum System Requirements for AGE OF EMPIRES 2: THE AGE OF KINGS" -Game Developer magazine -June, 2000 issue. -*/ - -#include "profile.h" -#include -#include -#include -//============================================================================== -static OPJ_PROFILE_LIST group_list [PGROUP_LASTGROUP]; - -//============================================================================== -static void GetTimeStamp(OPJ_UINT32 *pdwtime); - -//============================================================================== -#define SetMajorSection(entry, major) \ - { group_list[ entry ].section = entry ; \ - group_list[ entry ].sectionName = #major ; } - -//============================================================================== -void _ProfInit(void) -{ - // clear everything out - memset(group_list, 0, sizeof(group_list)); - - // set groups and parents for timing - SetMajorSection(PGROUP_DWT,PGROUP_DWT); - SetMajorSection(PGROUP_T1, PGROUP_T1); - SetMajorSection(PGROUP_T2, PGROUP_T2); -} // ProfInit - -//============================================================================== -void _ProfStart (OPJ_PROFILE_GROUP group) -{ - // make sure this hasn't been incorrectly started twice - if (group_list[group].start) - { - return; - } - - // get the start time - GetTimeStamp(&(group_list[group].start)); - -} // _ProfStart - -//============================================================================== -void _ProfStop(OPJ_PROFILE_GROUP group) -{ - // make sure we called start first - if (!group_list[group].start) - { - return; - } - - // get ending time - GetTimeStamp(&(group_list[group].end)); - - // calculate this latest elapsed interval - group_list[group].total_time += group_list[group].end - group_list[group].start; - - // reset starting time - group_list[group].start = 0; - - // incr the number of calls made - ++group_list[group].totalCalls; - -} // _ProfStop - -//============================================================================== -#define proftracef(id,totalTime) \ - fprintf(p, #id "\t%u\t\t%6.6f\t\t%12.6f\t%2.2f%%\n", \ - group_list[ id ].totalCalls, \ - (OPJ_FLOAT64) group_list[ id ].total_time / CLOCKS_PER_SEC, \ - ((OPJ_FLOAT64) group_list[ id ].total_time / (group_list[ id ].totalCalls ? group_list[ id ].totalCalls : 1)), \ - ((OPJ_FLOAT64) group_list[ id ].total_time / totalTime * 100)) - -#define proftracep(id,totalTime) \ - printf(#id "\t%u\t\t%6.6f\t\t%12.6f\t%2.2f%%\n", \ - group_list[ id ].totalCalls, \ - (OPJ_FLOAT64) group_list[ id ].total_time / CLOCKS_PER_SEC, \ - ((OPJ_FLOAT64) group_list[ id ].total_time / (group_list[ id ].totalCalls ? group_list[ id ].totalCalls : 1)), \ - ((OPJ_FLOAT64) group_list[ id ].total_time / totalTime * 100)) - -//============================================================================== -void _ProfSave(const OPJ_CHAR * pFileName) -{ - FILE *p = fopen(pFileName, "wt"); - OPJ_FLOAT64 totalTime = 0.; - OPJ_UINT32 i; - - if (!p) - { - return; - } - - for - (i=0;i - * 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. - */ - -/** - * Adapted from Herb Marselas -"Profiling, Data Analysis, Scalability, and Magic Numbers: Meeting the Minimum System Requirements for AGE OF EMPIRES 2: THE AGE OF KINGS" -Game Developer magazine -June, 2000 issue. -*/ - - -#ifndef __PROFILE_H -#define __PROFILE_H - -#include "openjpeg.h" -//============================================================================== -typedef enum -{ - PGROUP_RATE, - PGROUP_DC_SHIFT, - PGROUP_MCT, - PGROUP_DWT, - PGROUP_T1, - PGROUP_T2, - PGROUP_LASTGROUP -} OPJ_PROFILE_GROUP; - -//============================================================================== -typedef struct PROFILELIST -{ - OPJ_UINT32 start; - OPJ_UINT32 end; - OPJ_UINT32 total_time; - OPJ_UINT32 totalCalls; - OPJ_PROFILE_GROUP section; - const OPJ_CHAR *sectionName; // string name of the profile group -} OPJ_PROFILE_LIST; - -//============================================================================== -void _ProfStart(OPJ_PROFILE_GROUP group); -void _ProfStop (OPJ_PROFILE_GROUP group); - -//============================================================================== -//============================================================================== -#ifdef _PROFILE -#define PROFINIT() _ProfInit(); -#define PROFSTART (group) _ProfStart (group); -#define PROFSTOP (group) _ProfStop (group); -#define PROFSAVE(file) _ProfSave(file); -#define PROFPRINT() _ProfPrint(); -#else -#define PROFINIT() -#define PROFSTART(group) -#define PROFSTOP (group) -#define PROFSAVE(file) -#define PROFPRINT() -#endif // !_PROFILE - -//============================================================================== -#endif // __PROFILE_H diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/raw.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/raw.c deleted file mode 100644 index e3b9807ae28..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/raw.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 "raw.h" -#include "opj_malloc.h" - -/* -========================================================== - local functions -========================================================== -*/ - - -/* -========================================================== - RAW encoding interface -========================================================== -*/ - -opj_raw_t* raw_create(void) { - opj_raw_t *raw = (opj_raw_t*)opj_malloc(sizeof(opj_raw_t)); - return raw; -} - -void raw_destroy(opj_raw_t *raw) { - if(raw) { - opj_free(raw); - } -} - -OPJ_UINT32 raw_numbytes(opj_raw_t *raw) { - return (OPJ_UINT32)(raw->bp - raw->start); -} - -void raw_init_dec(opj_raw_t *raw, OPJ_BYTE *bp, OPJ_UINT32 len) { - raw->start = bp; - raw->lenmax = len; - raw->len = 0; - raw->c = 0; - raw->ct = 0; -} - -OPJ_UINT32 raw_decode(opj_raw_t *raw) { - OPJ_UINT32 d; - if (raw->ct == 0) { - raw->ct = 8; - if (raw->len == raw->lenmax) { - raw->c = 0xff; - } else { - if (raw->c == 0xff) { - raw->ct = 7; - } - raw->c = *(raw->start + raw->len); - raw->len++; - } - } - raw->ct--; - d = (raw->c >> raw->ct) & 0x01; - - return d; -} - diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/raw.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/raw.h deleted file mode 100644 index 7f02052625f..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/raw.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __RAW_H -#define __RAW_H -/** -@file raw.h -@brief Implementation of operations for raw encoding (RAW) - -The functions in RAW.C have for goal to realize the operation of raw encoding linked -with the corresponding mode switch. -*/ -#include "openjpeg.h" -/** @defgroup RAW RAW - Implementation of operations for raw encoding */ -/*@{*/ - -/** -RAW encoding operations -*/ -typedef struct opj_raw { - /** temporary buffer where bits are coded or decoded */ - OPJ_BYTE c; - /** number of bits already read or free to write */ - OPJ_UINT32 ct; - /** maximum length to decode */ - OPJ_UINT32 lenmax; - /** length decoded */ - OPJ_UINT32 len; - /** 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 */ - unsigned char *end; -} opj_raw_t; - -/** @name Exported functions */ -/*@{*/ -/* ----------------------------------------------------------------------- */ -/** -Create a new RAW handle -@return Returns a new RAW handle if successful, returns NULL otherwise -*/ -opj_raw_t* raw_create(void); -/** -Destroy a previously created RAW handle -@param raw RAW handle to destroy -*/ -void raw_destroy(opj_raw_t *raw); -/** -Return the number of bytes written/read since initialisation -@param raw RAW handle to destroy -@return Returns the number of bytes already encoded -*/ -OPJ_UINT32 raw_numbytes(opj_raw_t *raw); -/** -Initialize the decoder -@param raw RAW handle -@param bp Pointer to the start of the buffer from which the bytes will be read -@param len Length of the input buffer -*/ -void raw_init_dec(opj_raw_t *raw, OPJ_BYTE *bp, OPJ_UINT32 len); -/** -Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN -@param raw RAW handle -@return Returns the decoded symbol (0 or 1) -*/ -OPJ_UINT32 raw_decode(opj_raw_t *raw); -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __RAW_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.c deleted file mode 100644 index 46db5f55910..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.c +++ /dev/null @@ -1,1284 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2007, Callum Lerwick - * 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 "t1.h" -#include "t1_luts.h" -#include "opj_includes.h" -#include "j2k.h" -#include "tcd.h" -#include "mqc.h" -#include "raw.h" -#include "opj_malloc.h" -#include "int.h" -#include "dwt.h" -#include "fix.h" -/** @defgroup T1 T1 - Implementation of the tier-1 coding */ -/*@{*/ - -/** @name Local static functions */ -/*@{*/ - -static INLINE OPJ_BYTE t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient); -static OPJ_BYTE t1_getctxno_sc(OPJ_UINT32 f); -static INLINE OPJ_UINT32 t1_getctxno_mag(OPJ_UINT32 f); -static OPJ_BYTE t1_getspb(OPJ_UINT32 f); -static OPJ_INT16 t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos); -static OPJ_INT16 t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos); -static void t1_updateflags(flag_t *flagsp, OPJ_UINT32 s, OPJ_UINT32 stride); -/** -Encode significant pass -*/ -static void t1_enc_sigpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 vsc); -/** -Decode significant pass -*/ -static void t1_dec_sigpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 oneplushalf, - OPJ_BYTE type, - OPJ_UINT32 vsc); -/** -Encode significant pass -*/ -static void t1_enc_sigpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty); -/** -Decode significant pass -*/ -static void t1_dec_sigpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_BYTE type, - OPJ_UINT32 cblksty); -/** -Encode refinement pass -*/ -static void t1_enc_refpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 vsc); -/** -Decode refinement pass -*/ -static void t1_dec_refpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf, - OPJ_BYTE type, - OPJ_UINT32 vsc); -/** -Encode refinement pass -*/ -static void t1_enc_refpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty); -/** -Decode refinement pass -*/ -static void t1_dec_refpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_BYTE type, - OPJ_UINT32 cblksty); -/** -Encode clean-up pass -*/ -static void t1_enc_clnpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_UINT32 partial, - OPJ_UINT32 vsc); -/** -Decode clean-up pass -*/ -static void t1_dec_clnpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 oneplushalf, - OPJ_UINT32 partial, - OPJ_UINT32 vsc); -/** -Encode clean-up pass -*/ -static void t1_enc_clnpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_INT32 *nmsedec, - OPJ_UINT32 cblksty); -/** -Decode clean-up pass -*/ -static void t1_dec_clnpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_UINT32 cblksty); - -static OPJ_FLOAT64 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); -/** -Encode 1 code-block -@param t1 T1 handle -@param cblk Code-block coding parameters -@param orient -@param compno Component number -@param level -@param qmfbid -@param stepsize -@param cblksty Code-block style -@param numcomps -@param tile -*/ -static void 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, - opj_tcd_tile_t * tile, - const OPJ_FLOAT64 * mct_norms); -/** -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 -*/ -static void t1_decode_cblk( - opj_t1_t *t1, - opj_tcd_cblk_dec_t* cblk, - OPJ_UINT32 orient, - OPJ_UINT32 roishift, - OPJ_UINT32 cblksty); - -/*@}*/ - -/*@}*/ - -/* ----------------------------------------------------------------------- */ - -static OPJ_BYTE t1_getctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient) { - return lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)]; -} - -static OPJ_BYTE t1_getctxno_sc(OPJ_UINT32 f) { - return lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; -} - -static OPJ_UINT32 t1_getctxno_mag(OPJ_UINT32 f) { - OPJ_UINT32 tmp1 = (f & T1_SIG_OTH) ? T1_CTXNO_MAG + 1 : T1_CTXNO_MAG; - OPJ_UINT32 tmp2 = (f & T1_REFINE) ? T1_CTXNO_MAG + 2 : tmp1; - return (tmp2); -} - -static OPJ_BYTE t1_getspb(OPJ_UINT32 f) { - return lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; -} - -static OPJ_INT16 t1_getnmsedec_sig(OPJ_UINT32 x, OPJ_UINT32 bitpos) -{ - if (bitpos > T1_NMSEDEC_FRACBITS) { - return lut_nmsedec_sig[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; - } - - return lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; -} - -static OPJ_INT16 t1_getnmsedec_ref(OPJ_UINT32 x, OPJ_UINT32 bitpos) { - if (bitpos > T1_NMSEDEC_FRACBITS) { - return lut_nmsedec_ref[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; - } - - return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; -} - -static void t1_updateflags(flag_t *flagsp, OPJ_UINT32 s, OPJ_UINT32 stride) { - flag_t *np = flagsp - stride; - flag_t *sp = flagsp + stride; - - static const flag_t mod[] = { - T1_SIG_S, T1_SIG_S|T1_SGN_S, - T1_SIG_E, T1_SIG_E|T1_SGN_E, - T1_SIG_W, T1_SIG_W|T1_SGN_W, - T1_SIG_N, T1_SIG_N|T1_SGN_N - }; - - np[-1] |= T1_SIG_SE; - np[0] |= mod[s]; - np[1] |= T1_SIG_SW; - - flagsp[-1] |= mod[s+2]; - flagsp[0] |= T1_SIG; - flagsp[1] |= mod[s+4]; - - sp[-1] |= T1_SIG_NE; - sp[0] |= mod[s+6]; - sp[1] |= T1_SIG_NW; -} - -static void t1_enc_sigpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 vsc) -{ - OPJ_INT32 v; - OPJ_UINT32 flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { - v = int_abs(*datap) & one ? 1 : 0; - mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); /* ESSAI */ - if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ - mqc_bypass_enc(mqc, v); - } else { - mqc_encode(mqc, v); - } - if (v) { - v = *datap < 0 ? 1 : 0; - *nmsedec += t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS); - mqc_setcurctx(mqc, t1_getctxno_sc(flag)); /* ESSAI */ - if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ - mqc_bypass_enc(mqc, v); - } else { - mqc_encode(mqc, v ^ t1_getspb(flag)); - } - t1_updateflags(flagsp, v, t1->flags_stride); - } - *flagsp |= T1_VISIT; - } -} - -static void t1_dec_sigpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 oneplushalf, - OPJ_BYTE type, - OPJ_UINT32 vsc) -{ - OPJ_UINT32 v, flag; - - opj_raw_t *raw = t1->raw; /* RAW component */ - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { - if (type == T1_TYPE_RAW) { - if (raw_decode(raw)) { - v = raw_decode(raw); /* ESSAI */ - *datap = v ? -oneplushalf : oneplushalf; - t1_updateflags(flagsp, v, t1->flags_stride); - } - } else { - mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); - if (mqc_decode(mqc)) { - mqc_setcurctx(mqc, t1_getctxno_sc(flag)); - v = mqc_decode(mqc) ^ t1_getspb(flag); - *datap = v ? -oneplushalf : oneplushalf; - t1_updateflags(flagsp, v, t1->flags_stride); - } - } - *flagsp |= T1_VISIT; - } -} /* VSC and BYPASS by Antonin */ - -static void t1_enc_sigpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty) -{ - OPJ_UINT32 i, j, k, vsc; - OPJ_INT32 one; - - *nmsedec = 0; - one = 1 << (bpno + T1_NMSEDEC_FRACBITS); - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - t1_enc_sigpass_step( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - orient, - bpno, - one, - nmsedec, - type, - vsc); - } - } - } -} - -static void t1_dec_sigpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_BYTE type, - OPJ_UINT32 cblksty) -{ - OPJ_UINT32 i, j, k, vsc; - OPJ_INT32 one, half, oneplushalf; - one = 1 << bpno; - half = one >> 1; - oneplushalf = one | half; - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - t1_dec_sigpass_step( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - orient, - oneplushalf, - type, - vsc); - } - } - } -} /* VSC and BYPASS by Antonin */ - -static void t1_enc_refpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 vsc) -{ - OPJ_INT32 v; - OPJ_UINT32 flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { - *nmsedec += t1_getnmsedec_ref(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS); - v = int_abs(*datap) & one ? 1 : 0; - mqc_setcurctx(mqc, t1_getctxno_mag(flag)); /* ESSAI */ - if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ - mqc_bypass_enc(mqc, v); - } else { - mqc_encode(mqc, v); - } - *flagsp |= T1_REFINE; - } -} - -static void t1_dec_refpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_INT32 poshalf, - OPJ_INT32 neghalf, - OPJ_BYTE type, - OPJ_UINT32 vsc) -{ - OPJ_INT32 t; - OPJ_UINT32 v,flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - opj_raw_t *raw = t1->raw; /* RAW component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { - mqc_setcurctx(mqc, t1_getctxno_mag(flag)); /* ESSAI */ - if (type == T1_TYPE_RAW) { - v = raw_decode(raw); - } else { - v = mqc_decode(mqc); - } - t = v ? poshalf : neghalf; - *datap += *datap < 0 ? -t : t; - *flagsp |= T1_REFINE; - } -} /* VSC and BYPASS by Antonin */ - -static void t1_enc_refpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_INT32 *nmsedec, - OPJ_BYTE type, - OPJ_UINT32 cblksty) -{ - OPJ_UINT32 i, j, k, vsc; - OPJ_INT32 one; - - *nmsedec = 0; - one = 1 << (bpno + T1_NMSEDEC_FRACBITS); - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - t1_enc_refpass_step( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - bpno, - one, - nmsedec, - type, - vsc); - } - } - } -} - -static void t1_dec_refpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_BYTE type, - OPJ_UINT32 cblksty) -{ - OPJ_UINT32 i, j, k; - OPJ_INT32 one, poshalf, neghalf; - OPJ_UINT32 vsc; - one = 1 << bpno; - poshalf = one >> 1; - neghalf = bpno > 0 ? -poshalf : -1; - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - for (j = k; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - t1_dec_refpass_step( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - poshalf, - neghalf, - type, - vsc); - } - } - } -} /* VSC and BYPASS by Antonin */ - -static void t1_enc_clnpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 bpno, - OPJ_INT32 one, - OPJ_INT32 *nmsedec, - OPJ_UINT32 partial, - OPJ_UINT32 vsc) -{ - OPJ_INT32 v; - OPJ_UINT32 flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if (partial) { - goto LABEL_PARTIAL; - } - if (!(*flagsp & (T1_SIG | T1_VISIT))) { - mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); - v = int_abs(*datap) & one ? 1 : 0; - mqc_encode(mqc, v); - if (v) { -LABEL_PARTIAL: - *nmsedec += t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS); - mqc_setcurctx(mqc, t1_getctxno_sc(flag)); - v = *datap < 0 ? 1 : 0; - mqc_encode(mqc, v ^ t1_getspb(flag)); - t1_updateflags(flagsp, v, t1->flags_stride); - } - } - *flagsp &= ~T1_VISIT; -} - -static void t1_dec_clnpass_step( - opj_t1_t *t1, - flag_t *flagsp, - OPJ_INT32 *datap, - OPJ_UINT32 orient, - OPJ_INT32 oneplushalf, - OPJ_UINT32 partial, - OPJ_UINT32 vsc) -{ - OPJ_INT32 v; - OPJ_UINT32 flag; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp); - if (partial) { - goto LABEL_PARTIAL; - } - if (!(flag & (T1_SIG | T1_VISIT))) { - mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); - if (mqc_decode(mqc)) { -LABEL_PARTIAL: - mqc_setcurctx(mqc, t1_getctxno_sc(flag)); - v = mqc_decode(mqc) ^ t1_getspb(flag); - *datap = v ? -oneplushalf : oneplushalf; - t1_updateflags(flagsp, v, t1->flags_stride); - } - } - *flagsp &= ~T1_VISIT; -} /* VSC and BYPASS by Antonin */ - -static void t1_enc_clnpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_INT32 *nmsedec, - OPJ_UINT32 cblksty) -{ - OPJ_UINT32 i, j, k; - OPJ_INT32 one; - OPJ_UINT32 agg, runlen, vsc; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - *nmsedec = 0; - one = 1 << (bpno + T1_NMSEDEC_FRACBITS); - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - if (k + 3 < t1->h) { - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || (MACRO_t1_flags(1 + k + 3,1 + i) - & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); - } else { - agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); - } - } else { - agg = 0; - } - if (agg) { - for (runlen = 0; runlen < 4; ++runlen) { - if (int_abs(t1->data[((k + runlen)*t1->w) + i]) & one) - break; - } - mqc_setcurctx(mqc, T1_CTXNO_AGG); - mqc_encode(mqc, runlen != 4); - if (runlen == 4) { - continue; - } - mqc_setcurctx(mqc, T1_CTXNO_UNI); - mqc_encode(mqc, runlen >> 1); - mqc_encode(mqc, runlen & 1); - } else { - runlen = 0; - } - for (j = k + runlen; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - t1_enc_clnpass_step( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - orient, - bpno, - one, - nmsedec, - agg && (j == k + runlen), - vsc); - } - } - } -} - -static void t1_dec_clnpass( - opj_t1_t *t1, - OPJ_INT32 bpno, - OPJ_UINT32 orient, - OPJ_UINT32 cblksty) -{ - OPJ_UINT32 i, j, k, one; - OPJ_INT32 half, oneplushalf; - OPJ_UINT32 agg, runlen, vsc; - OPJ_UINT32 segsym = cblksty & J2K_CCP_CBLKSTY_SEGSYM; - - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - one = 1 << bpno; - half = one >> 1; - oneplushalf = one | half; - for (k = 0; k < t1->h; k += 4) { - for (i = 0; i < t1->w; ++i) { - if (k + 3 < t1->h) { - if (cblksty & J2K_CCP_CBLKSTY_VSC) { - agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || (MACRO_t1_flags(1 + k + 3,1 + i) - & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); - } else { - agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH) - || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)); - } - } else { - agg = 0; - } - if (agg) { - mqc_setcurctx(mqc, T1_CTXNO_AGG); - if (!mqc_decode(mqc)) { - continue; - } - mqc_setcurctx(mqc, T1_CTXNO_UNI); - runlen = mqc_decode(mqc); - runlen = (runlen << 1) | mqc_decode(mqc); - } else { - runlen = 0; - } - for (j = k + runlen; j < k + 4 && j < t1->h; ++j) { - vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0; - t1_dec_clnpass_step( - t1, - &t1->flags[((j+1) * t1->flags_stride) + i + 1], - &t1->data[(j * t1->w) + i], - orient, - oneplushalf, - agg && (j == k + runlen), - vsc); - } - } - } - if (segsym) { - OPJ_UINT32 v = 0; - mqc_setcurctx(mqc, T1_CTXNO_UNI); - v = mqc_decode(mqc); - v = (v << 1) | mqc_decode(mqc); - v = (v << 1) | mqc_decode(mqc); - v = (v << 1) | mqc_decode(mqc); - /* - if (v!=0xa) { - opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v); - } - */ - } -} /* VSC and BYPASS by Antonin */ - - -/** mod fixed_quality */ -static OPJ_FLOAT64 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_FLOAT64 w1 = 1, w2, wmsedec; - if - (mct_norms) - { - w1 = mct_norms[compno]; - } - if (qmfbid == 1) - { - w2 = dwt_getnorm(level, orient); - } else { /* if (qmfbid == 0) */ - w2 = dwt_getnorm_real(level, orient); - } - wmsedec = w1 * w2 * stepsize * (1 << bpno); - wmsedec *= wmsedec * nmsedec / 8192.0; - return wmsedec; -} - -static bool allocate_buffers( - opj_t1_t *t1, - OPJ_UINT32 w, - OPJ_UINT32 h) -{ - OPJ_UINT32 datasize=w * h; - OPJ_UINT32 flagssize; - - if(datasize > t1->datasize){ - opj_aligned_free(t1->data); - t1->data = (OPJ_INT32*) opj_aligned_malloc(datasize * sizeof(OPJ_INT32)); - if(!t1->data){ - return false; - } - t1->datasize=datasize; - } - memset(t1->data,0,datasize * sizeof(OPJ_INT32)); - - t1->flags_stride=w+2; - flagssize=t1->flags_stride * (h+2); - - if(flagssize > t1->flagssize){ - opj_aligned_free(t1->flags); - t1->flags = (flag_t*) opj_aligned_malloc(flagssize * sizeof(flag_t)); - if(!t1->flags){ - return false; - } - t1->flagssize=flagssize; - } - memset(t1->flags,0,flagssize * sizeof(flag_t)); - - t1->w=w; - t1->h=h; - - return true; -} - -/** mod fixed_quality */ -static void 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, - opj_tcd_tile_t * tile, - const OPJ_FLOAT64 * mct_norms) -{ - 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; - OPJ_BYTE type = T1_TYPE_MQ; - OPJ_FLOAT64 tempwmsedec; - - max = 0; - for (i = 0; i < t1->w * t1->h; ++i) { - OPJ_INT32 tmp = abs(t1->data[i]); - max = int_max(max, tmp); - } - - cblk->numbps = max ? (int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS : 0; - - bpno = cblk->numbps - 1; - passtype = 2; - - mqc_resetstates(mqc); - mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); - mqc_init_enc(mqc, cblk->data); - - for (passno = 0; bpno >= 0; ++passno) { - opj_tcd_pass_t *pass = &cblk->passes[passno]; - OPJ_UINT32 correction = 3; - type = ((bpno < ((OPJ_INT32) (cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; - - switch (passtype) { - case 0: - t1_enc_sigpass(t1, bpno, orient, &nmsedec, type, cblksty); - break; - case 1: - t1_enc_refpass(t1, bpno, &nmsedec, type, cblksty); - break; - case 2: - t1_enc_clnpass(t1, bpno, orient, &nmsedec, cblksty); - /* code switch SEGMARK (i.e. SEGSYM) */ - if (cblksty & J2K_CCP_CBLKSTY_SEGSYM) - mqc_segmark_enc(mqc); - break; - } - - /* fixed_quality */ - tempwmsedec = t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps,mct_norms) ; - cumwmsedec += tempwmsedec; - tile->distotile += tempwmsedec; - - /* Code switch "RESTART" (i.e. TERMALL) */ - if ((cblksty & J2K_CCP_CBLKSTY_TERMALL) && !((passtype == 2) && (bpno - 1 < 0))) { - if (type == T1_TYPE_RAW) { - mqc_flush(mqc); - correction = 1; - /* correction = mqc_bypass_flush_enc(); */ - } else { /* correction = mqc_restart_enc(); */ - mqc_flush(mqc); - correction = 1; - } - pass->term = 1; - } else { - if (((bpno < ((OPJ_INT32) (cblk->numbps) - 4) && (passtype > 0)) - || ((bpno == (OPJ_INT32)(cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) { - if (type == T1_TYPE_RAW) { - mqc_flush(mqc); - correction = 1; - /* correction = mqc_bypass_flush_enc(); */ - } else { /* correction = mqc_restart_enc(); */ - mqc_flush(mqc); - correction = 1; - } - pass->term = 1; - } else { - pass->term = 0; - } - } - - if (++passtype == 3) { - passtype = 0; - bpno--; - } - - if (pass->term && bpno > 0) { - type = ((bpno < ((OPJ_INT32) (cblk->numbps) - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; - if (type == T1_TYPE_RAW) - mqc_bypass_init_enc(mqc); - else - mqc_restart_init_enc(mqc); - } - - pass->distortiondec = cumwmsedec; - pass->rate = mqc_numbytes(mqc) + correction; /* FIXME */ - - /* Code-switch "RESET" */ - if (cblksty & J2K_CCP_CBLKSTY_RESET) - mqc_reset_enc(mqc); - } - - /* Code switch "ERTERM" (i.e. PTERM) */ - if (cblksty & J2K_CCP_CBLKSTY_PTERM) - mqc_erterm_enc(mqc); - else /* Default coding */ if (!(cblksty & J2K_CCP_CBLKSTY_LAZY)) - mqc_flush(mqc); - - cblk->totalpasses = passno; - - for (passno = 0; passnototalpasses; passno++) { - opj_tcd_pass_t *pass = &cblk->passes[passno]; - if (pass->rate > mqc_numbytes(mqc)) - pass->rate = mqc_numbytes(mqc); - /*Preventing generation of FF as last data byte of a pass*/ - if((pass->rate>1) && (cblk->data[pass->rate - 1] == 0xFF)){ - pass->rate--; - } - pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate); - } -} - -static void t1_decode_cblk( - opj_t1_t *t1, - opj_tcd_cblk_dec_t* cblk, - OPJ_UINT32 orient, - OPJ_UINT32 roishift, - OPJ_UINT32 cblksty) -{ - opj_raw_t *raw = t1->raw; /* RAW component */ - opj_mqc_t *mqc = t1->mqc; /* MQC component */ - - OPJ_INT32 bpno; - OPJ_UINT32 passtype; - OPJ_UINT32 segno, passno; - OPJ_BYTE type = T1_TYPE_MQ; /* BYPASS mode */ - - if(!allocate_buffers( - t1, - cblk->x1 - cblk->x0, - cblk->y1 - cblk->y0)) - { - return; - } - - bpno = roishift + cblk->numbps - 1; - passtype = 2; - - mqc_resetstates(mqc); - mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); - - for (segno = 0; segno < cblk->real_num_segs; ++segno) { - opj_tcd_seg_t *seg = &cblk->segs[segno]; - - /* BYPASS mode */ - type = ((bpno <= ((OPJ_INT32) (cblk->numbps) - 1) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; - /* FIXME: slviewer gets here with a null pointer. Why? Partially downloaded and/or corrupt textures? */ - if(seg->data == 00){ - continue; - } - if (type == T1_TYPE_RAW) { - raw_init_dec(raw, (*seg->data) + seg->dataindex, seg->len); - } else { - mqc_init_dec(mqc, (*seg->data) + seg->dataindex, seg->len); - } - - for (passno = 0; passno < seg->real_num_passes; ++passno) { - switch (passtype) { - case 0: - t1_dec_sigpass(t1, bpno+1, orient, type, cblksty); - break; - case 1: - t1_dec_refpass(t1, bpno+1, type, cblksty); - break; - case 2: - t1_dec_clnpass(t1, bpno+1, orient, cblksty); - break; - } - - if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { - mqc_resetstates(mqc); - mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46); - mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3); - mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4); - } - if (++passtype == 3) { - passtype = 0; - bpno--; - } - } - } -} - -/* ----------------------------------------------------------------------- */ -/** - * 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* t1_create() -{ - opj_t1_t *l_t1 = 00; - - l_t1 = (opj_t1_t*) opj_malloc(sizeof(opj_t1_t)); - if - (!l_t1) - { - return 00; - } - memset(l_t1,0,sizeof(opj_t1_t)); - - /* create MQC and RAW handles */ - l_t1->mqc = mqc_create(); - if - (! l_t1->mqc) - { - t1_destroy(l_t1); - return 00; - } - l_t1->raw = raw_create(); - if - (! l_t1->raw) - { - t1_destroy(l_t1); - return 00; - } - return l_t1; -} - -/** - * Destroys a previously created T1 handle - * - * @param p_t1 Tier 1 handle to destroy -*/ -void t1_destroy(opj_t1_t *p_t1) -{ - if - (! p_t1) - { - return; - } - - /* destroy MQC and RAW handles */ - mqc_destroy(p_t1->mqc); - p_t1->mqc = 00; - raw_destroy(p_t1->raw); - p_t1->raw = 00; - 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); -} - -bool t1_encode_cblks( - opj_t1_t *t1, - opj_tcd_tile_t *tile, - opj_tcp_t *tcp, - const OPJ_FLOAT64 * mct_norms) -{ - OPJ_UINT32 compno, resno, bandno, precno, cblkno; - - tile->distotile = 0; /* fixed_quality */ - - for (compno = 0; compno < tile->numcomps; ++compno) { - opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; - opj_tccp_t* tccp = &tcp->tccps[compno]; - OPJ_UINT32 tile_w = tilec->x1 - tilec->x0; - - 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* restrict band = &res->bands[bandno]; - - 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_INT32 * restrict datap; - OPJ_INT32* 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 (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(!allocate_buffers( - t1, - cblk->x1 - cblk->x0, - cblk->y1 - cblk->y0)) - { - return false; - } - - datap=t1->data; - cblk_w = t1->w; - cblk_h = t1->h; - - tiledp=&tilec->data[(y * tile_w) + x]; - if (tccp->qmfbid == 1) { - for (j = 0; j < cblk_h; ++j) { - for (i = 0; i < cblk_w; ++i) { - OPJ_INT32 tmp = tiledp[(j * tile_w) + i]; - datap[(j * cblk_w) + i] = tmp << T1_NMSEDEC_FRACBITS; - } - } - } else { /* if (tccp->qmfbid == 0) */ - for (j = 0; j < cblk_h; ++j) { - for (i = 0; i < cblk_w; ++i) { - OPJ_INT32 tmp = tiledp[(j * tile_w) + i]; - datap[(j * cblk_w) + i] = - fix_mul( - tmp, - 8192 * 8192 / ((OPJ_INT32) floor(band->stepsize * 8192))) >> (11 - T1_NMSEDEC_FRACBITS); - } - } - } - - t1_encode_cblk( - t1, - cblk, - band->bandno, - compno, - tilec->numresolutions - 1 - resno, - tccp->qmfbid, - band->stepsize, - tccp->cblksty, - tile->numcomps, - tile, - mct_norms); - - } /* cblkno */ - } /* precno */ - } /* bandno */ - } /* resno */ - } /* compno */ - return true; -} - -void t1_decode_cblks( - opj_t1_t* t1, - opj_tcd_tilecomp_t* tilec, - opj_tccp_t* tccp) -{ - OPJ_UINT32 resno, bandno, precno, cblkno; - - OPJ_UINT32 tile_w = tilec->x1 - tilec->x0; - - 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* restrict 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]; - OPJ_INT32* restrict datap; - void* restrict tiledp; - OPJ_UINT32 cblk_w, cblk_h; - OPJ_INT32 x, y; - OPJ_UINT32 i, j; - - t1_decode_cblk( - t1, - cblk, - band->bandno, - tccp->roishift, - tccp->cblksty); - - 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=t1->data; - cblk_w = t1->w; - cblk_h = t1->h; - - if (tccp->roishift) { - 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; - } - } - } - } - - tiledp=(void*)&tilec->data[(y * tile_w) + x]; - if (tccp->qmfbid == 1) { - for (j = 0; j < cblk_h; ++j) { - for (i = 0; i < cblk_w; ++i) { - OPJ_INT32 tmp = datap[(j * cblk_w) + i]; - ((OPJ_INT32*)tiledp)[(j * tile_w) + i] = tmp / 2; - } - } - } else { /* if (tccp->qmfbid == 0) */ - for (j = 0; j < cblk_h; ++j) { - for (i = 0; i < cblk_w; ++i) { - float tmp = datap[(j * cblk_w) + i] * band->stepsize; - ((float*)tiledp)[(j * tile_w) + i] = tmp; - } - } - } - //opj_free(cblk->segs); - //cblk->segs = 00; - } /* cblkno */ - } /* precno */ - } /* bandno */ - } /* resno */ -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.h deleted file mode 100644 index b98eca2ec37..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/t1.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __T1_H -#define __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. -*/ -#include "openjpeg.h" -/** @defgroup T1 T1 - Implementation of the tier-1 coding */ -/*@{*/ -//#include "raw.h" -/* ----------------------------------------------------------------------- */ -#define T1_NMSEDEC_BITS 7 - -#define T1_SIG_NE 0x0001 /**< Context orientation : North-East direction */ -#define T1_SIG_SE 0x0002 /**< Context orientation : South-East direction */ -#define T1_SIG_SW 0x0004 /**< Context orientation : South-West direction */ -#define T1_SIG_NW 0x0008 /**< Context orientation : North-West direction */ -#define T1_SIG_N 0x0010 /**< Context orientation : North direction */ -#define T1_SIG_E 0x0020 /**< Context orientation : East direction */ -#define T1_SIG_S 0x0040 /**< Context orientation : South direction */ -#define T1_SIG_W 0x0080 /**< Context orientation : West direction */ -#define T1_SIG_OTH (T1_SIG_N|T1_SIG_NE|T1_SIG_E|T1_SIG_SE|T1_SIG_S|T1_SIG_SW|T1_SIG_W|T1_SIG_NW) -#define T1_SIG_PRIM (T1_SIG_N|T1_SIG_E|T1_SIG_S|T1_SIG_W) - -#define T1_SGN_N 0x0100 -#define T1_SGN_E 0x0200 -#define T1_SGN_S 0x0400 -#define T1_SGN_W 0x0800 -#define T1_SGN (T1_SGN_N|T1_SGN_E|T1_SGN_S|T1_SGN_W) - -#define T1_SIG 0x1000 -#define T1_REFINE 0x2000 -#define T1_VISIT 0x4000 - -#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)*/ - -/* ----------------------------------------------------------------------- */ -struct opj_common_struct; -struct opj_tcd_tile; -struct opj_tcp; -struct opj_tcd_tilecomp; -struct opj_mqc; -struct opj_raw; -struct opj_tccp; - - -typedef short flag_t; - -/** -Tier-1 coding (coding of code-block coefficients) -*/ -typedef struct opj_t1 { - /** MQC component */ - struct opj_mqc *mqc; - /** RAW component */ - struct opj_raw *raw; - - OPJ_INT32 *data; - flag_t *flags; - OPJ_UINT32 w; - OPJ_UINT32 h; - OPJ_UINT32 datasize; - OPJ_UINT32 flagssize; - OPJ_UINT32 flags_stride; -} opj_t1_t; - -#define MACRO_t1_flags(x,y) t1->flags[((x)*(t1->flags_stride))+(y)] - -/** @name Exported functions */ -/*@{*/ -/* ----------------------------------------------------------------------- */ - -/** - * 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* t1_create(); - -/** - * Destroys a previously created T1 handle - * - * @param p_t1 Tier 1 handle to destroy -*/ -void t1_destroy(opj_t1_t *p_t1); - -/** -Encode the code-blocks of a tile -@param t1 T1 handle -@param tile The tile to encode -@param tcp Tile coding parameters -*/ -bool t1_encode_cblks(opj_t1_t *t1, struct opj_tcd_tile *tile, struct opj_tcp *tcp,const OPJ_FLOAT64 * mct_norms); -/** -Decode the code-blocks of a tile -@param t1 T1 handle -@param tile The tile to decode -@param tcp Tile coding parameters -*/ -void t1_decode_cblks(opj_t1_t* t1, struct opj_tcd_tilecomp* tilec, struct opj_tccp* tccp); -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __T1_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/t1_luts.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/t1_luts.h deleted file mode 100644 index da400ae7f9d..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/t1_luts.h +++ /dev/null @@ -1,142 +0,0 @@ -/* This file was automatically generated by t1_generate_luts.c */ - -static char lut_ctxno_zc[1024] = { - 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 0, 3, 3, 6, 3, 6, 6, 8, 3, 6, 6, 8, 6, 8, 8, 8, 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, - 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, - 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8 -}; - -static char lut_ctxno_sc[256] = { - 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd, - 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc, - 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa, - 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9, - 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc, - 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb, - 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9, - 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa, - 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa, - 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9, - 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb, - 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc, - 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9, - 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa, - 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc, - 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd -}; - -static char lut_spb[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, - 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, - 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -}; - -static short lut_nmsedec_sig[1 << 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 short lut_nmsedec_sig0[1 << 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 short lut_nmsedec_ref[1 << 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 short lut_nmsedec_ref0[1 << 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/Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.c deleted file mode 100644 index d45ccfda3d5..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 "openjpeg.h" -#include "opj_includes.h" -#include "t2.h" -#include "bio.h" -#include "tcd.h" -#include "pi.h" -#include "event.h" -#include "j2k.h" -#include "tgt.h" -#include "int.h" -#include "opj_malloc.h" -#include "pi.h" - - -/** @defgroup T2 T2 - Implementation of a tier-2 coding */ -/*@{*/ - -/** @name Local static functions */ -/*@{*/ - -static void t2_putcommacode(opj_bio_t *bio, OPJ_UINT32 n); -static OPJ_UINT32 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 t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n); -static OPJ_UINT32 t2_getnumpasses(opj_bio_t *bio); -/** -Encode a packet of a tile to a destination buffer -@param tile Tile for which to write the packets -@param tcp Tile coding parameters -@param pi Packet identity -@param dest Destination buffer -@param len Length of the destination buffer -@param cstr_info Codestream information structure -@param tileno Number of the tile encoded -@return -*/ -static bool 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); -/** -@param seg -@param cblksty -@param first -*/ -static bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 index, OPJ_UINT32 cblksty, OPJ_UINT32 first); -/** -Decode a packet of a tile from a source buffer -@param t2 T2 handle -@param src Source buffer -@param len Length of the source buffer -@param tile Tile for which to write the packets -@param tcp Tile coding parameters -@param pi Packet identity -@return -*/ -static bool 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); - -/*@}*/ - -/*@}*/ - -/* ----------------------------------------------------------------------- */ - -/* #define RESTART 0x04 */ - -static void t2_putcommacode(opj_bio_t *bio, OPJ_UINT32 n) { - while - (n != 0) - { - bio_write(bio, 1, 1); - n--; - } - bio_write(bio, 0, 1); -} - -static OPJ_UINT32 t2_getcommacode(opj_bio_t *bio) { - OPJ_UINT32 n = 0; - while - (bio_read(bio, 1)) - { - ++n; - } - return n; -} - -static void t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n) { - if (n == 1) { - bio_write(bio, 0, 1); - } else if (n == 2) { - bio_write(bio, 2, 2); - } else if (n <= 5) { - bio_write(bio, 0xc | (n - 3), 4); - } else if (n <= 36) { - bio_write(bio, 0x1e0 | (n - 6), 9); - } else if (n <= 164) { - bio_write(bio, 0xff80 | (n - 37), 16); - } -} - -static OPJ_UINT32 t2_getnumpasses(opj_bio_t *bio) { - OPJ_UINT32 n; - if (!bio_read(bio, 1)) - return 1; - if (!bio_read(bio, 1)) - return 2; - if ((n = bio_read(bio, 2)) != 3) - return (3 + n); - if ((n = bio_read(bio, 5)) != 31) - return (6 + n); - return (37 + bio_read(bio, 7)); -} - -static bool 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) -{ - 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 */ - - /* */ - if (tcp->csty & J2K_CP_CSTY_SOP) { - c[0] = 255; - c[1] = 145; - c[2] = 0; - c[3] = 4; - c[4] = (tile->packno % 65536) / 256; - c[5] = (tile->packno % 65536) % 256; - c += 6; - length -= 6; - } - /* */ - - if (!layno) { - band = res->bands; - for - (bandno = 0; bandno < res->numbands; ++bandno) - { - opj_tcd_precinct_t *prc = &band->precincts[precno]; - tgt_reset(prc->incltree); - tgt_reset(prc->imsbtree); - l_nb_blocks = prc->cw * prc->ch; - for - (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) - { - opj_tcd_cblk_enc_t* cblk_v = &prc->cblks.enc[cblkno]; - cblk_v->numpasses = 0; - tgt_setvalue(prc->imsbtree, cblkno, band->numbps - cblk_v->numbps); - } - ++band; - } - } - - bio = bio_create(); - bio_init_enc(bio, c, length); - bio_write(bio, 1, 1); /* Empty header bit */ - - /* Writing Packet header */ - band = res->bands; - for - (bandno = 0; bandno < res->numbands; ++bandno) - { - opj_tcd_precinct_t *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) - { - tgt_setvalue(prc->incltree, cblkno, 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) { - tgt_encode(bio, prc->incltree, cblkno, layno + 1); - } else { - bio_write(bio, layer->numpasses != 0, 1); - } - /* 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; - tgt_encode(bio, prc->imsbtree, cblkno, 999); - } - /* number of coding passes included */ - 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 = int_max(increment, int_floorlog2(len) + 1 - (cblk->numlenbits + int_floorlog2(nump))); - len = 0; - nump = 0; - } - ++pass; - } - t2_putcommacode(bio, 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) - { - bio_write(bio, len, cblk->numlenbits + int_floorlog2(nump)); - len = 0; - nump = 0; - } - ++pass; - } - ++cblk; - } - ++band; - } - - if - (bio_flush(bio)) - { - bio_destroy(bio); - return false; /* modified to eliminate longjmp !! */ - } - l_nb_bytes = bio_numbytes(bio); - c += l_nb_bytes; - length -= l_nb_bytes; - bio_destroy(bio); - - /* */ - if (tcp->csty & J2K_CP_CSTY_EPH) { - 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; bandno < res->numbands; bandno++) - { - opj_tcd_precinct_t *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) - { - return false; - } - 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 >> */ - } - ++band; - } - * p_data_written += (OPJ_INT32)(c - dest); - return true; -} - -static bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, OPJ_UINT32 indexvalue, OPJ_UINT32 cblksty, OPJ_UINT32 first) -{ - opj_tcd_seg_t* seg = 00; - OPJ_UINT32 l_nb_segs = indexvalue + 1; - - if - (l_nb_segs > cblk->m_current_max_segs) - { - cblk->m_current_max_segs += J2K_DEFAULT_NB_SEGS; - cblk->segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, cblk->m_current_max_segs * sizeof(opj_tcd_seg_t)); - if - (! cblk->segs) - { - return false; - } - } - seg = &cblk->segs[indexvalue]; - memset(seg,0,sizeof(opj_tcd_seg_t)); - - 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 { - seg->maxpasses = 109; - } - return true; -} - -static bool 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, - 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) -{ - /* 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) - { - 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))) - { - tgt_reset(l_prc->incltree); - 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) { - if ((*l_current_data) != 0xff || (*(l_current_data + 1) != 0x91)) { - // TODO opj_event_msg(t2->cinfo->event_mgr, 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 caracteristic - step 1: Read packet header in the saved structure - step 2: Return to codestream for decoding - */ - - l_bio = bio_create(); - if - (! l_bio) - { - return 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); - } - bio_init_dec(l_bio, l_header_data,*l_modified_length_ptr); - l_present = bio_read(l_bio, 1); - if - (!l_present) - { - bio_inalign(l_bio); - l_header_data += bio_numbytes(l_bio); - bio_destroy(l_bio); - /* EPH markers */ - if (p_tcp->csty & J2K_CP_CSTY_EPH) { - if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { - printf("Error : expected EPH marker\n"); - } 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 = false; - *p_data_read = (OPJ_INT32)( l_current_data - p_src_data ); - return true; - } - - 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_UINT32 l_included,l_increment, l_segno; - OPJ_INT32 n; - /* if cblk not yet included before --> inclusion tagtree */ - if - (!l_cblk->numsegs) - { - l_included = tgt_decode(l_bio, l_prc->incltree, cblkno, p_pi->layno + 1); - /* else one bit */ - } - else - { - l_included = bio_read(l_bio, 1); - } - /* if cblk not included */ - if - (!l_included) - { - l_cblk->numnewpasses = 0; - ++l_cblk; - continue; - } - /* if cblk not yet included --> zero-bitplane tagtree */ - if - (!l_cblk->numsegs) - { - OPJ_UINT32 i = 0; - while - (!tgt_decode(l_bio, l_prc->imsbtree, cblkno, i)) - { - ++i; - } - l_cblk->numbps = l_band->numbps + 1 - i; - l_cblk->numlenbits = 3; - } - /* number of coding passes */ - l_cblk->numnewpasses = t2_getnumpasses(l_bio); - l_increment = t2_getcommacode(l_bio); - /* length indicator increment */ - l_cblk->numlenbits += l_increment; - l_segno = 0; - if - (!l_cblk->numsegs) - { - if - (! t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 1)) - { - bio_destroy(l_bio); - return false; - } - - } - else - { - l_segno = l_cblk->numsegs - 1; - if - (l_cblk->segs[l_segno].numpasses == l_cblk->segs[l_segno].maxpasses) - { - ++l_segno; - if - (! t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) - { - bio_destroy(l_bio); - return false; - } - } - } - n = l_cblk->numnewpasses; - - do { - l_cblk->segs[l_segno].numnewpasses = int_min(l_cblk->segs[l_segno].maxpasses - l_cblk->segs[l_segno].numpasses, n); - l_cblk->segs[l_segno].newlen = bio_read(l_bio, l_cblk->numlenbits + uint_floorlog2(l_cblk->segs[l_segno].numnewpasses)); - n -= l_cblk->segs[l_segno].numnewpasses; - if - (n > 0) - { - ++l_segno; - if - (! t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) - { - bio_destroy(l_bio); - return false; - } - } - } - while (n > 0); - ++l_cblk; - } - ++l_band; - } - - if - (bio_inalign(l_bio)) - { - bio_destroy(l_bio); - return false; - } - - l_header_data += bio_numbytes(l_bio); - bio_destroy(l_bio); - - /* EPH markers */ - if (p_tcp->csty & J2K_CP_CSTY_EPH) { - if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { - // TODO opj_event_msg(t2->cinfo->event_mgr, EVT_ERROR, "Expected EPH marker\n"); - } 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 = true; - *p_data_read = (OPJ_UINT32)( l_current_data - p_src_data ); - return true; -} - -static bool 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_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]; - - 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; - l_cblk->len = 0; - } - else - { - l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; - if - (l_seg->numpasses == l_seg->maxpasses) - { - ++l_seg; - ++l_cblk->numsegs; - } - } - - do - { - if - (l_current_data + l_seg->newlen > p_src_data + p_max_length) - { - return false; - } - -#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 ((cblk->len + seg->newlen) > 8192) { - opj_event_msg(t2->cinfo, EVT_WARNING, - "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", - seg->newlen, cblkno, precno, bandno, resno, compno); - if (!JPWL_ASSUME) { - opj_event_msg(t2->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return -999; - } - seg->newlen = 8192 - cblk->len; - opj_event_msg(t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", seg->newlen); - break; - }; - -#endif /* USE_JPWL */ - - memcpy(l_cblk->data + l_cblk->len, l_current_data, l_seg->newlen); - if - (l_seg->numpasses == 0) - { - l_seg->data = &l_cblk->data; - l_seg->dataindex = l_cblk->len; - } - l_current_data += l_seg->newlen; - l_seg->numpasses += l_seg->numnewpasses; - l_cblk->numnewpasses -= l_seg->numnewpasses; - - l_seg->real_num_passes = l_seg->numpasses; - l_cblk->len += l_seg->newlen; - l_seg->len += l_seg->newlen; - if - (l_cblk->numnewpasses > 0) - { - ++l_seg; - ++l_cblk->numsegs; - } - } - while (l_cblk->numnewpasses > 0); - l_cblk->real_num_segs = l_cblk->numsegs; - ++l_cblk; - } - ++l_band; - } - *(p_data_read) = (OPJ_UINT32)( l_current_data - p_src_data ); - return true; -} - - -static bool 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_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]; - - *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; - l_cblk->len = 0; - } - else - { - l_seg = &l_cblk->segs[l_cblk->numsegs - 1]; - if - (l_seg->numpasses == l_seg->maxpasses) - { - ++l_seg; - ++l_cblk->numsegs; - } - } - - do - { - if - (* p_data_read + l_seg->newlen > p_max_length) - { - return false; - } - -#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 ((cblk->len + seg->newlen) > 8192) { - opj_event_msg(t2->cinfo, EVT_WARNING, - "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n", - seg->newlen, cblkno, precno, bandno, resno, compno); - if (!JPWL_ASSUME) { - opj_event_msg(t2->cinfo, EVT_ERROR, "JPWL: giving up\n"); - return -999; - } - seg->newlen = 8192 - cblk->len; - opj_event_msg(t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", seg->newlen); - break; - }; - -#endif /* USE_JPWL */ - *(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; - } - } - return true; -} - -static bool 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) -{ - bool l_read_data; - OPJ_UINT32 l_nb_bytes_read = 0; - OPJ_UINT32 l_nb_total_bytes_read = 0; - - *p_data_read = 0; - - if - (! 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)) - { - return 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 - (! t2_read_packet_data(p_t2,p_tile,p_pi,p_src,&l_nb_bytes_read,p_max_length,p_pack_info)) - { - return false; - } - l_nb_total_bytes_read += l_nb_bytes_read; - } - *p_data_read = l_nb_total_bytes_read; - return true; -} - -static bool 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) -{ - bool l_read_data; - OPJ_UINT32 l_nb_bytes_read = 0; - OPJ_UINT32 l_nb_total_bytes_read = 0; - - *p_data_read = 0; - - if - (! 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)) - { - return 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 - (! t2_skip_packet_data(p_t2,p_tile,p_pi,&l_nb_bytes_read,p_max_length,p_pack_info)) - { - return false; - } - l_nb_total_bytes_read += l_nb_bytes_read; - } - *p_data_read = l_nb_total_bytes_read; - return true; -} - -/* ----------------------------------------------------------------------- */ - -bool 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_UINT32 p_tp_num, - OPJ_INT32 p_tp_pos, - OPJ_UINT32 p_pino, - J2K_T2_MODE p_t2_mode) -{ - 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->m_specific_param.m_enc.m_cinema == CINEMA4K_24? 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 = pi_initialise_encode(l_image, l_cp, p_tile_no, p_t2_mode); - if - (!l_pi) - { - return 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; - pi_create_encode(l_pi, l_cp,p_tile_no,poc,l_tp_num,p_tp_pos,p_t2_mode); - while - (pi_next(l_current_pi)) - { - if - (l_current_pi->layno < p_maxlayers) - { - l_nb_bytes = 0; - if - (! t2_encode_packet(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) - { - pi_destroy(l_pi, l_nb_pocs); - return 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) - { - pi_destroy(l_pi, l_nb_pocs); - return false; - } - } - ++l_current_pi; - } - } - } - else - { /* t2_mode == FINAL_PASS */ - 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]; - while - (pi_next(l_current_pi)) - { - if - (l_current_pi->layno < p_maxlayers) - { - l_nb_bytes=0; - if - (! t2_encode_packet(p_tile_no,p_tile, l_tcp, l_current_pi, l_current_data, &l_nb_bytes, p_max_len, cstr_info)) - { - pi_destroy(l_pi, l_nb_pocs); - return false; - } - l_current_data += l_nb_bytes; - p_max_len -= l_nb_bytes; - * p_data_written += l_nb_bytes; - - /* 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; - } - } - } - pi_destroy(l_pi, l_nb_pocs); - return true; -} - -bool t2_decode_packets( - opj_t2_t *p_t2, - OPJ_UINT32 p_tile_no, - struct opj_tcd_tile *p_tile, - OPJ_BYTE *p_src, - OPJ_UINT32 * p_data_read, - OPJ_UINT32 p_max_len, - struct opj_codestream_info *p_cstr_info) -{ - 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_cp_t *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; - OPJ_UINT32 curtp = 0; - OPJ_UINT32 tp_start_packno; - opj_packet_info_t *l_pack_info = 00; - opj_image_comp_t* l_img_comp = 00; - - - if - (p_cstr_info) - { - l_pack_info = p_cstr_info->tile[p_tile_no].packet; - } - - /* create a packet iterator */ - l_pi = pi_create_decode(l_image, l_cp, p_tile_no); - if - (!l_pi) - { - return false; - } - - tp_start_packno = 0; - l_current_pi = l_pi; - - for - (pino = 0; pino <= l_tcp->numpocs; ++pino) - { - while - (pi_next(l_current_pi)) - { - - if - (l_tcp->num_layers_to_decode > l_current_pi->layno && l_current_pi->resno < p_tile->comps[l_current_pi->compno].minimum_num_resolutions) - { - l_nb_bytes_read = 0; - if - (! 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)) - { - pi_destroy(l_pi,l_nb_pocs); - return false; - } - l_img_comp = &(l_image->comps[l_current_pi->compno]); - l_img_comp->resno_decoded = uint_max(l_current_pi->resno, l_img_comp->resno_decoded); - } - else - { - l_nb_bytes_read = 0; - if - (! 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)) - { - pi_destroy(l_pi,l_nb_pocs); - return false; - } - } - l_current_data += l_nb_bytes_read; - p_max_len -= l_nb_bytes_read; - - /* INDEX >> */ - if(p_cstr_info) { - opj_tile_info_t *info_TL = &p_cstr_info->tile[p_tile_no]; - opj_packet_info_t *info_PK = &info_TL->packet[p_cstr_info->packno]; - 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 = (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; - } - /* << INDEX */ - } - ++l_current_pi; - } - /* INDEX >> */ - 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 - } - /* << INDEX */ - - /* don't forget to release pi */ - pi_destroy(l_pi,l_nb_pocs); - *p_data_read = (OPJ_UINT32)( l_current_data - p_src ); - return 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* t2_create( - opj_image_t *p_image, - opj_cp_t *p_cp) -{ - /* create the tcd structure */ - opj_t2_t *l_t2 = (opj_t2_t*)opj_malloc(sizeof(opj_t2_t)); - if - (!l_t2) - { - return 00; - } - memset(l_t2,0,sizeof(opj_t2_t)); - l_t2->image = p_image; - l_t2->cp = p_cp; - return l_t2; -} - -/** - * Destroys a Tier 2 handle. - * - * @param p_t2 the Tier 2 handle to destroy -*/ -void t2_destroy(opj_t2_t *p_t2) -{ - if - (p_t2) - { - opj_free(p_t2); - } -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.h deleted file mode 100644 index 050a2643d57..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/t2.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __T2_H -#define __T2_H -/** -@file t2.h -@brief Implementation of a tier-2 coding (packetization of code-block data) (T2) - -*/ -#include "openjpeg.h" - -struct opj_common_struct; -struct opj_image; -struct opj_cp; -struct opj_tcd_tile; -struct opj_codestream_info; - -/** @defgroup T2 T2 - Implementation of a tier-2 coding */ -/*@{*/ - -/** -T2 encoding mode -*/ -typedef enum T2_MODE -{ - THRESH_CALC = 0, /** Function called in Rate allocation process*/ - FINAL_PASS = 1 /** Function called in Tier 2 process*/ -} -J2K_T2_MODE; - -/** -Tier-2 coding -*/ - -typedef struct opj_t2 { - /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */ - struct opj_image *image; - /** pointer to the image coding parameters */ - struct opj_cp *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 len the length of the destination buffer -@param cstr_info Codestream 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 t2_mode If == 0 In Threshold calculation ,If == 1 Final pass -*/ -bool t2_encode_packets(opj_t2_t* t2,OPJ_UINT32 tileno, struct opj_tcd_tile *tile, OPJ_UINT32 maxlayers, OPJ_BYTE *dest, OPJ_UINT32 * p_data_written, OPJ_UINT32 len, struct opj_codestream_info *cstr_info,OPJ_UINT32 tpnum, OPJ_INT32 tppos,OPJ_UINT32 pino,J2K_T2_MODE t2_mode); -/** -Decode the packets of a tile from a source buffer -@param t2 T2 handle -@param src the source buffer -@param len length of the source buffer -@param tileno number that identifies the tile for which to decode the packets -@param tile tile for which to decode the packets - */ -bool t2_decode_packets(opj_t2_t *t2, OPJ_UINT32 tileno,struct opj_tcd_tile *tile, OPJ_BYTE *src, OPJ_UINT32 * p_data_read, OPJ_UINT32 len, struct opj_codestream_info *cstr_info); - -/** - * 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* t2_create(struct opj_image *p_image, struct opj_cp *p_cp); - -/** - * Destroys a Tier 2 handle. - * - * @param p_t2 the Tier 2 handle to destroy -*/ -void t2_destroy(opj_t2_t *t2); - -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __T2_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/tcd.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/tcd.c deleted file mode 100644 index 1264988d212..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/tcd.c +++ /dev/null @@ -1,2123 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe - * Copyright (c) 2005, Herve Drolon, FreeImage Team - * Copyright (c) 2006-2007, Parvatha Elangovan - * 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 "tcd.h" -#include "openjpeg.h" -#include "j2k.h" -#include "opj_includes.h" -#include "event.h" -#include "t2.h" -#include "t1.h" -#include "opj_malloc.h" -#include "int.h" -#include "tgt.h" -#include "dwt.h" -#include "mct.h" -#include "j2k_lib.h" -#include "profile.h" - -#include // lrintf - -/** - * Deallocates the encoding data of the given precinct. - */ -static void tcd_code_block_enc_deallocate (opj_tcd_precinct_t * p_precinct); -/** - * Allocates memory for an encoding code block. - */ -static bool tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block); -/** - * Allocates memory for a decoding code block. - */ -static bool tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block); -/** -Free the memory allocated for encoding -@param tcd TCD handle -*/ -static void tcd_free_tile(opj_tcd_t *tcd); - -/* ----------------------------------------------------------------------- */ - -/** -Create a new TCD handle -*/ -opj_tcd_t* tcd_create(bool p_is_decoder) -{ - opj_tcd_t *l_tcd = 00; - - /* create the tcd structure */ - l_tcd = (opj_tcd_t*) opj_malloc(sizeof(opj_tcd_t)); - if - (!l_tcd) - { - return 00; - } - memset(l_tcd,0,sizeof(opj_tcd_t)); - l_tcd->m_is_decoder = p_is_decoder ? 1 : 0; - l_tcd->tcd_image = (opj_tcd_image_t*)opj_malloc(sizeof(opj_tcd_image_t)); - if - (!l_tcd->tcd_image) - { - opj_free(l_tcd); - return 00; - } - memset(l_tcd->tcd_image,0,sizeof(opj_tcd_image_t)); - return l_tcd; -} - -/** -Destroy a previously created TCD handle -*/ -void tcd_destroy(opj_tcd_t *tcd) { - if - (tcd) - { - tcd_free_tile(tcd); - if - (tcd->tcd_image) - { - opj_free(tcd->tcd_image); - tcd->tcd_image = 00; - } - opj_free(tcd); - } -} - -/* ----------------------------------------------------------------------- */ -/** - * Initialize the tile coder and may reuse some meory. - * @param p_tcd TCD handle. - * @param p_image raw image. - * @param p_cp coding parameters. - * @param p_tile_no current tile index to encode. - * - * @return true if the encoding values could be set (false otherwise). -*/ -#define MACRO_TCD_ALLOCATE(FUNCTION,TYPE,FRACTION,ELEMENT,FUNCTION_ELEMENT) \ -bool FUNCTION \ - ( \ - opj_tcd_t *p_tcd, \ - OPJ_UINT32 p_tile_no \ - ) \ -{ \ - OPJ_UINT32 (*l_gain_ptr)(OPJ_UINT32) = 00; \ - 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; \ - TYPE* l_code_block = 00; \ - opj_image_t * l_image = 00; \ - OPJ_UINT32 p,q; \ - OPJ_UINT32 l_level_no; \ - OPJ_UINT32 l_pdx, l_pdy; \ - OPJ_UINT32 l_gain; \ - OPJ_INT32 l_x0b, l_y0b; \ - /* 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; \ - \ - /* 4 borders of the tile rescale on the image if necessary */ \ - l_tile->x0 = int_max(l_cp->tx0 + p * l_cp->tdx, l_image->x0); \ - l_tile->y0 = int_max(l_cp->ty0 + q * l_cp->tdy, l_image->y0); \ - l_tile->x1 = int_min(l_cp->tx0 + (p + 1) * l_cp->tdx, l_image->x1); \ - l_tile->y1 = int_min(l_cp->ty0 + (q + 1) * l_cp->tdy, l_image->y1); \ - /*tile->numcomps = image->numcomps; */ \ - for \ - (compno = 0; compno < l_tile->numcomps; ++compno) \ - { \ - /* border of each l_tile component (global) */ \ - l_tilec->x0 = int_ceildiv(l_tile->x0, l_image_comp->dx); \ - l_tilec->y0 = int_ceildiv(l_tile->y0, l_image_comp->dy); \ - l_tilec->x1 = int_ceildiv(l_tile->x1, l_image_comp->dx); \ - l_tilec->y1 = int_ceildiv(l_tile->y1, l_image_comp->dy); \ - \ - l_data_size = (l_tilec->x1 - l_tilec->x0) \ - * (l_tilec->y1 - l_tilec->y0) * sizeof(OPJ_UINT32 ); \ - 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 \ - (l_tilec->data == 00) \ - { \ - l_tilec->data = (OPJ_INT32 *) opj_aligned_malloc(l_data_size); \ - if \ - (! l_tilec->data ) \ - { \ - return false; \ - } \ - l_tilec->data_size = l_data_size; \ - } \ - else if \ - (l_data_size > l_tilec->data_size) \ - { \ - l_tilec->data = (OPJ_INT32 *) opj_realloc(l_tilec->data, l_data_size);\ - if \ - (! l_tilec->data) \ - { \ - return false; \ - } \ - l_tilec->data_size = l_data_size; \ - } \ - l_data_size = l_tilec->numresolutions * sizeof(opj_tcd_resolution_t);\ - if \ - (l_tilec->resolutions == 00) \ - { \ - l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size);\ - if \ - (! l_tilec->resolutions ) \ - { \ - return false; \ - } \ - l_tilec->resolutions_size = l_data_size; \ - memset(l_tilec->resolutions,0,l_data_size); \ - } \ - else if \ - (l_data_size > l_tilec->resolutions_size) \ - { \ - l_tilec->resolutions = (opj_tcd_resolution_t *) opj_realloc(l_tilec->resolutions, l_data_size);\ - if \ - (! l_tilec->resolutions) \ - { \ - return false; \ - } \ - 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 - 1; \ - l_res = l_tilec->resolutions; \ - l_step_size = l_tccp->stepsizes; \ - if \ - (l_tccp->qmfbid == 0) \ - { \ - l_gain_ptr = &dwt_getgain_real; \ - } \ - else \ - { \ - l_gain_ptr = &dwt_getgain; \ - } \ - for \ - (resno = 0; resno < l_tilec->numresolutions; ++resno) \ - { \ - OPJ_INT32 tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend; \ - OPJ_UINT32 cbgwidthexpn, cbgheightexpn; \ - OPJ_UINT32 cblkwidthexpn, cblkheightexpn; \ - /* border for each resolution level (global) */ \ - l_res->x0 = int_ceildivpow2(l_tilec->x0, l_level_no); \ - l_res->y0 = int_ceildivpow2(l_tilec->y0, l_level_no); \ - l_res->x1 = int_ceildivpow2(l_tilec->x1, l_level_no); \ - l_res->y1 = int_ceildivpow2(l_tilec->y1, l_level_no); \ - /* 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]; \ - /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */ \ - l_tl_prc_x_start = int_floordivpow2(l_res->x0, l_pdx) << l_pdx; \ - l_tl_prc_y_start = int_floordivpow2(l_res->y0, l_pdy) << l_pdy; \ - l_br_prc_x_end = int_ceildivpow2(l_res->x1, l_pdx) << l_pdx; \ - l_br_prc_y_end = int_ceildivpow2(l_res->y1, l_pdy) << l_pdy; \ - \ - l_res->pw = (l_res->x0 == l_res->x1) ? 0 : ((l_br_prc_x_end - l_tl_prc_x_start) >> l_pdx);\ - l_res->ph = (l_res->y0 == l_res->y1) ? 0 : ((l_br_prc_y_end - l_tl_prc_y_start) >> l_pdy);\ - l_nb_precincts = l_res->pw * l_res->ph; \ - l_nb_precinct_size = l_nb_precincts * 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 = int_ceildivpow2(l_tl_prc_x_start, 1); \ - tlcbgystart = int_ceildivpow2(l_tl_prc_y_start, 1); \ - brcbgxend = int_ceildivpow2(l_br_prc_x_end, 1); \ - brcbgyend = int_ceildivpow2(l_br_prc_y_end, 1); \ - cbgwidthexpn = l_pdx - 1; \ - cbgheightexpn = l_pdy - 1; \ - l_res->numbands = 3; \ - } \ - \ - cblkwidthexpn = uint_min(l_tccp->cblkw, cbgwidthexpn); \ - cblkheightexpn = uint_min(l_tccp->cblkh, cbgheightexpn); \ - l_band = l_res->bands; \ - for \ - (bandno = 0; bandno < l_res->numbands; ++bandno) \ - { \ - OPJ_INT32 numbps; \ - if \ - (resno == 0) \ - { \ - l_band->bandno = 0 ; \ - l_band->x0 = int_ceildivpow2(l_tilec->x0, l_level_no); \ - l_band->y0 = int_ceildivpow2(l_tilec->y0, l_level_no); \ - l_band->x1 = int_ceildivpow2(l_tilec->x1, l_level_no); \ - l_band->y1 = int_ceildivpow2(l_tilec->y1, 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 = (l_band->bandno)>>1; \ - /* l_band border (global) */ \ - l_band->x0 = int_ceildivpow2(l_tilec->x0 - (1 << l_level_no) * l_x0b, l_level_no + 1);\ - l_band->y0 = int_ceildivpow2(l_tilec->y0 - (1 << l_level_no) * l_y0b, l_level_no + 1);\ - l_band->x1 = int_ceildivpow2(l_tilec->x1 - (1 << l_level_no) * l_x0b, l_level_no + 1);\ - l_band->y1 = int_ceildivpow2(l_tilec->y1 - (1 << l_level_no) * l_y0b, l_level_no + 1);\ - } \ - /** avoid an if with storing function pointer */ \ - l_gain = (*l_gain_ptr) (l_band->bandno); \ - numbps = l_image_comp->prec + l_gain; \ - l_band->stepsize = (OPJ_FLOAT32)(((1.0 + l_step_size->mant / 2048.0) * pow(2.0, (OPJ_INT32) (numbps - l_step_size->expn)))) * FRACTION;\ - l_band->numbps = l_step_size->expn + l_tccp->numgbits - 1; /* WHY -1 ? */\ - if \ - (! l_band->precincts) \ - { \ - l_band->precincts = (opj_tcd_precinct_t *) opj_malloc(/*3 * */ l_nb_precinct_size);\ - if \ - (! l_band->precincts) \ - { \ - return false; \ - } \ - 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) \ - { \ - l_band->precincts = (opj_tcd_precinct_t *) opj_realloc(l_band->precincts,/*3 * */ l_nb_precinct_size);\ - if \ - (! l_band->precincts) \ - { \ - return false; \ - } \ - 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 + (precno % l_res->pw) * (1 << cbgwidthexpn);\ - OPJ_INT32 cbgystart = tlcbgystart + (precno / l_res->pw) * (1 << cbgheightexpn);\ - OPJ_INT32 cbgxend = cbgxstart + (1 << cbgwidthexpn); \ - OPJ_INT32 cbgyend = cbgystart + (1 << cbgheightexpn); \ - /* precinct size (global) */ \ - l_current_precinct->x0 = int_max(cbgxstart, l_band->x0);\ - l_current_precinct->y0 = int_max(cbgystart, l_band->y0);\ - l_current_precinct->x1 = int_min(cbgxend, l_band->x1); \ - l_current_precinct->y1 = int_min(cbgyend, l_band->y1); \ - tlcblkxstart = int_floordivpow2(l_current_precinct->x0, cblkwidthexpn) << cblkwidthexpn;\ - tlcblkystart = int_floordivpow2(l_current_precinct->y0, cblkheightexpn) << cblkheightexpn;\ - brcblkxend = int_ceildivpow2(l_current_precinct->x1, cblkwidthexpn) << cblkwidthexpn;\ - brcblkyend = int_ceildivpow2(l_current_precinct->y1, cblkheightexpn) << cblkheightexpn;\ - l_current_precinct->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn;\ - l_current_precinct->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn;\ - l_nb_code_blocks = l_current_precinct->cw * l_current_precinct->ch;\ - l_nb_code_blocks_size = l_nb_code_blocks * sizeof(TYPE);\ - if \ - (! l_current_precinct->cblks.ELEMENT) \ - { \ - l_current_precinct->cblks.ELEMENT = (TYPE*) opj_malloc(l_nb_code_blocks_size);\ - if \ - (! l_current_precinct->cblks.ELEMENT ) \ - { \ - return false; \ - } \ - memset(l_current_precinct->cblks.ELEMENT,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)\ - { \ - l_current_precinct->cblks.ELEMENT = (TYPE*) \ - opj_realloc(l_current_precinct->cblks.ELEMENT, l_nb_code_blocks_size);\ - if \ - (! l_current_precinct->cblks.ELEMENT ) \ - { \ - return false; \ - } \ - memset(((OPJ_BYTE *) l_current_precinct->cblks.ELEMENT) + 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 = tgt_create(l_current_precinct->cw,\ - l_current_precinct->ch);\ - } \ - else \ - { \ - l_current_precinct->incltree = tgt_init(l_current_precinct->incltree,\ - l_current_precinct->cw, \ - l_current_precinct->ch);\ - } \ - if \ - (! l_current_precinct->incltree) \ - { \ - return false; \ - } \ - if \ - (! l_current_precinct->imsbtree) \ - { \ - l_current_precinct->imsbtree = tgt_create( \ - l_current_precinct->cw,\ - l_current_precinct->ch);\ - } \ - else \ - { \ - l_current_precinct->imsbtree = tgt_init( \ - l_current_precinct->imsbtree,\ - l_current_precinct->cw,\ - l_current_precinct->ch);\ - } \ - if \ - (! l_current_precinct->imsbtree) \ - { \ - return false; \ - } \ - l_code_block = l_current_precinct->cblks.ELEMENT; \ - for \ - (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) \ - { \ - OPJ_INT32 cblkxstart = tlcblkxstart + (cblkno % l_current_precinct->cw) * (1 << cblkwidthexpn);\ - OPJ_INT32 cblkystart = tlcblkystart + (cblkno / l_current_precinct->cw) * (1 << cblkheightexpn);\ - OPJ_INT32 cblkxend = cblkxstart + (1 << cblkwidthexpn); \ - OPJ_INT32 cblkyend = cblkystart + (1 << cblkheightexpn); \ - /* code-block size (global) */ \ - l_code_block->x0 = int_max(cblkxstart, l_current_precinct->x0);\ - l_code_block->y0 = int_max(cblkystart, l_current_precinct->y0);\ - l_code_block->x1 = int_min(cblkxend, l_current_precinct->x1);\ - l_code_block->y1 = int_min(cblkyend, l_current_precinct->y1);\ - if \ - (! FUNCTION_ELEMENT(l_code_block)) \ - { \ - return false; \ - } \ - ++l_code_block; \ - } \ - ++l_current_precinct; \ - } /* precno */ \ - ++l_band; \ - ++l_step_size; \ - } /* bandno */ \ - ++l_res; \ - --l_level_no; \ - } /* resno */ \ - ++l_tccp; \ - ++l_tilec; \ - ++l_image_comp; \ - } /* compno */ \ - return true; \ -} \ - -MACRO_TCD_ALLOCATE(tcd_init_encode_tile,opj_tcd_cblk_enc_t,1.f,enc,tcd_code_block_enc_allocate) -MACRO_TCD_ALLOCATE(tcd_init_decode_tile,opj_tcd_cblk_dec_t,0.5f,dec,tcd_code_block_dec_allocate) - -#undef MACRO_TCD_ALLOCATE - -/** - * Allocates memory for an encoding code block. - */ -bool tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_block) -{ - if - (! p_code_block->data) - { - p_code_block->data = (OPJ_BYTE*) opj_malloc(8192+1); - if - (! p_code_block->data) - { - return false; - } - p_code_block->data+=1; - /* no memset since data */ - p_code_block->layers = (opj_tcd_layer_t*) opj_malloc(100 * sizeof(opj_tcd_layer_t)); - if - (! p_code_block->layers) - { - return false; - } - p_code_block->passes = (opj_tcd_pass_t*) opj_malloc(100 * sizeof(opj_tcd_pass_t)); - if - (! p_code_block->passes) - { - return false; - } - } - memset(p_code_block->layers,0,100 * sizeof(opj_tcd_layer_t)); - memset(p_code_block->passes,0,100 * sizeof(opj_tcd_pass_t)); - return true; -} - -/** - * Allocates memory for a decoding code block. - */ -bool tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block) -{ - OPJ_UINT32 l_seg_size; - - if - (! p_code_block->data) - { - p_code_block->data = (OPJ_BYTE*) opj_malloc(8192); - if - (! p_code_block->data) - { - return false; - } - l_seg_size = J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t); - p_code_block->segs = (opj_tcd_seg_t *) opj_malloc(l_seg_size); - if - (! p_code_block->segs) - { - return false; - } - memset(p_code_block->segs,0,l_seg_size); - p_code_block->m_current_max_segs = J2K_DEFAULT_NB_SEGS; - } - // TODO - //p_code_block->numsegs = 0; - return true; -} - -/** - * Deallocates the encoding data of the given precinct. - */ -void 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 / sizeof(opj_tcd_cblk_enc_t); - for - (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) - { - if - (l_code_block->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; - } -} - -/** - * Deallocates the encoding data of the given precinct. - */ -void 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) - { - l_nb_code_blocks = p_precinct->block_size / sizeof(opj_tcd_cblk_dec_t); - for - (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) - { - if - (l_code_block->data) - { - opj_free(l_code_block->data); - l_code_block->data = 00; - } - if - (l_code_block->segs) - { - opj_free(l_code_block->segs ); - l_code_block->segs = 00; - } - ++l_code_block; - } - opj_free(p_precinct->cblks.dec); - p_precinct->cblks.dec = 00; - } -} - -void 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 = tcd_code_block_dec_deallocate; - } - else - { - l_tcd_code_block_deallocate = 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 / 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 / sizeof(opj_tcd_precinct_t); - for - (precno = 0; precno < l_nb_precincts; ++precno) - { - tgt_destroy(l_precinct->incltree); - l_precinct->incltree = 00; - 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->data) - { - opj_aligned_free(l_tile_comp->data); - l_tile_comp->data = 00; - } - ++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; -} - -bool tcd_init( - opj_tcd_t *p_tcd, - opj_image_t * p_image, - opj_cp_t * p_cp - ) -{ - OPJ_UINT32 l_tile_comp_size; - - p_tcd->image = p_image; - p_tcd->cp = p_cp; - p_tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(sizeof(opj_tcd_tile_t)); - - if - (! p_tcd->tcd_image->tiles) - { - return false; - } - memset(p_tcd->tcd_image->tiles,0, sizeof(opj_tcd_tile_t)); - - l_tile_comp_size = p_image->numcomps * sizeof(opj_tcd_tilecomp_t); - p_tcd->tcd_image->tiles->comps = (opj_tcd_tilecomp_t *) opj_malloc(l_tile_comp_size); - if - (! p_tcd->tcd_image->tiles->comps ) - { - return false; - } - memset( p_tcd->tcd_image->tiles->comps , 0 , l_tile_comp_size); - p_tcd->tcd_image->tiles->numcomps = p_image->numcomps; - p_tcd->tp_pos = p_cp->m_specific_param.m_enc.m_tp_pos; - return true; -} - -void 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[10][10][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) (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]; - 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 = 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 * value - 2 + cblk->numpassesinlayers; - } else { - n = cblk->numpassesinlayers; - } - } else { - n = 3 * 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; - } - } - } - } - } -} - -void tcd_rateallocate_fixed(opj_tcd_t *tcd) { - OPJ_UINT32 layno; - for (layno = 0; layno < tcd->tcp->numlayers; layno++) { - tcd_makelayer_fixed(tcd, layno, 1); - } -} - -void 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; - - tcd_tile->distolayer[layno] = 0; /* fixed_quality */ - - 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]; - 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; - for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { - OPJ_INT32 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 (dd / dr >= thresh) - n = passno + 1; - } - 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; /* fixed_quality */ - - if (final) - cblk->numpassesinlayers = n; - } - } - } - } - } -} - -bool tcd_rateallocate(opj_tcd_t *tcd, OPJ_BYTE *dest, OPJ_UINT32 * p_data_written, OPJ_UINT32 len, opj_codestream_info_t *cstr_info) { - OPJ_UINT32 compno, resno, bandno, precno, cblkno, layno; - OPJ_UINT32 passno; - OPJ_FLOAT64 min, max; - OPJ_FLOAT64 cumdisto[100]; /* fixed_quality */ - const OPJ_FLOAT64 K = 1; /* 1.1; fixed_quality */ - 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; /* fixed_quality */ - - 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]; - - 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 = pass->rate; - dd = pass->distortiondec; - } else { - dr = 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 */ - - /* fixed_quality */ - tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); - tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0)); - } /* 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 = tcd_tile->numpix; - tile_info->distotile = tcd_tile->distotile; - tile_info->thresh = (OPJ_FLOAT64 *) opj_malloc(tcd_tcp->numlayers * sizeof(OPJ_FLOAT64)); - } - - for (layno = 0; layno < tcd_tcp->numlayers; layno++) { - OPJ_FLOAT64 lo = min; - OPJ_FLOAT64 hi = max; - bool success = false; - OPJ_UINT32 maxlen = tcd_tcp->rates[layno] ? 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; /* fixed_quality */ - - /* fixed_quality */ - 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 (disto_alloc == 1 and rates == 0) - -q xx,yy,zz,0 (fixed_quality == 1 and distoratio == 0) - ==> possible to have some lossy layers and the last layer for sure lossless */ - if ( ((cp->m_specific_param.m_enc.m_disto_alloc==1) && (tcd_tcp->rates[layno]>0)) || ((cp->m_specific_param.m_enc.m_fixed_quality==1) && (tcd_tcp->distoratio[layno]>0))) { - opj_t2_t *t2 = t2_create(tcd->image, cp); - OPJ_FLOAT64 thresh = 0; - if - (t2 == 00) - { - return false; - } - - for - (i = 0; i < 128; ++i) - { - OPJ_FLOAT64 distoachieved = 0; /* fixed_quality */ - thresh = (lo + hi) / 2; - - tcd_makelayer(tcd, layno, thresh, 0); - - if (cp->m_specific_param.m_enc.m_fixed_quality) { /* fixed_quality */ - if(cp->m_specific_param.m_enc.m_cinema){ - if - (! t2_encode_packets(t2,tcd->tcd_tileno, tcd_tile, layno + 1, dest, p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC)) - { - 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 { - if - (! t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest,p_data_written, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC)) - { - /* TODO: what to do with l ??? seek / tell ??? */ - /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */ - lo = thresh; - continue; - } - hi = thresh; - stable_thresh = thresh; - } - } - success = true; - goodthresh = stable_thresh == 0? thresh : stable_thresh; - t2_destroy(t2); - } else { - success = true; - goodthresh = min; - } - - if (!success) { - return false; - } - - if(cstr_info) { /* Threshold for Marcela Index */ - cstr_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh; - } - tcd_makelayer(tcd, layno, goodthresh, 1); - - /* fixed_quality */ - cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]); - } - - return true; -} - -OPJ_UINT32 tcd_get_encoded_tile_size ( - opj_tcd_t *p_tcd - ) -{ - OPJ_UINT32 i,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;iimage->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 * (l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 - l_tilec->y0); - ++l_img_comp; - ++l_tilec; - } - return l_data_size; -} - -bool tcd_copy_tile_data ( - opj_tcd_t *p_tcd, - OPJ_BYTE * p_src, - OPJ_UINT32 p_src_length - ) -{ - OPJ_UINT32 i,j,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_UINT32 l_nb_elem; - - l_data_size = tcd_get_encoded_tile_size(p_tcd); - if - (l_data_size != p_src_length) - { - return false; - } - l_tilec = p_tcd->tcd_image->tiles->comps; - l_img_comp = p_tcd->image->comps; - for - (i=0;iimage->numcomps;++i) - { - l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/ - l_remaining = l_img_comp->prec & 7; /* (%8) */ - l_nb_elem = (l_tilec->x1 - l_tilec->x0) * (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;jdata; - OPJ_INT16 * l_src_ptr = (OPJ_INT16 *) p_src; - if - (l_img_comp->sgnd) - { - for - (j=0;jdata; - for - (j=0;j p_dest_length) - { - return false; - } - - l_tilec = p_tcd->tcd_image->tiles->comps; - l_img_comp = p_tcd->image->comps; - for - (i=0;iimage->numcomps;++i) - { - 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; - l_width = (l_res->x1 - l_res->x0); - l_height = (l_res->y1 - l_res->y0); - l_stride = (l_tilec->x1 - l_tilec->x0) - l_width; - 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_tilec->data; - if - (l_img_comp->sgnd) - { - for - (j=0;jdata; - OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_dest; - if - (l_img_comp->sgnd) - { - for - (j=0;jdata; - for - (j=0;jtcd_image->tiles->comps; - l_img_comp = p_tcd->image->comps; - for - (i=0;iimage->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_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1; - l_data_size += l_size_comp * (l_res->x1 - l_res->x0) * (l_res->y1 - l_res->y0); - ++l_img_comp; - ++l_tile_comp; - } - return l_data_size; -} - -bool 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_tcp_t * l_tcp = 00; - opj_tcd_tile_t * l_tile; - OPJ_UINT32 l_nb_elem,i; - OPJ_INT32 * l_current_ptr; - - l_tile = p_tcd->tcd_image->tiles; - l_tile_comp = l_tile->comps; - l_tcp = p_tcd->tcp; - 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 = (l_tile_comp->x1 - l_tile_comp->x0) * (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) - { - *l_current_ptr = (*l_current_ptr - l_tccp->m_dc_level_shift) << 11 ; - ++l_current_ptr; - } - } - ++l_img_comp; - ++l_tccp; - ++l_tile_comp; - } - return true; -} - -bool 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_UINT32 samples = (l_tile_comp->x1 - l_tile_comp->x0) * (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 true; - } - - if - (p_tcd->tcp->mct == 2) - { - if - (! p_tcd->tcp->m_mct_coding_matrix) - { - return true; - } - l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*)); - if - (! l_data) - { - return false; - } - for - (i=0;inumcomps;++i) - { - l_data[i] = (OPJ_BYTE*) l_tile_comp->data; - ++l_tile_comp; - } - if - (! 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 false; - } - opj_free(l_data); - } - else if (l_tcp->tccps->qmfbid == 0) - { - mct_encode_real(l_tile->comps[0].data, l_tile->comps[1].data, l_tile->comps[2].data, samples); - } - else - { - mct_encode(l_tile->comps[0].data, l_tile->comps[1].data, l_tile->comps[2].data, samples); - } - return true; -} - -bool 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 - (! dwt_encode(l_tile_comp)) - { - return false; - } - } - else if - (l_tccp->qmfbid == 0) - { - if - (! dwt_encode_real(l_tile_comp)) - { - return false; - } - } - ++l_tile_comp; - ++l_tccp; - } - return true; -} - -bool tcd_t1_encode ( - opj_tcd_t *p_tcd - ) -{ - opj_t1_t * l_t1; - const OPJ_FLOAT64 * l_mct_norms; - opj_tcp_t * l_tcp = p_tcd->tcp; - - l_t1 = t1_create(); - if - (l_t1 == 00) - { - return false; - } - if - (l_tcp->mct == 1) - { - // irreversible encoding - if - (l_tcp->tccps->qmfbid == 0) - { - l_mct_norms = get_mct_norms_real(); - } - else - { - l_mct_norms = get_mct_norms(); - } - } - else - { - l_mct_norms = (const OPJ_FLOAT64 *) (l_tcp->mct_norms); - } - - if - (! t1_encode_cblks(l_t1, p_tcd->tcd_image->tiles , l_tcp, l_mct_norms)) - { - t1_destroy(l_t1); - return false; - } - t1_destroy(l_t1); - return true; -} - -bool 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_t2_t * l_t2; - - l_t2 = t2_create(p_tcd->image, p_tcd->cp); - if - (l_t2 == 00) - { - return false; - } - - if - (! 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_tcd->tp_num, - p_tcd->tp_pos, - p_tcd->cur_pino, - FINAL_PASS)) - { - t2_destroy(l_t2); - return false; - } - t2_destroy(l_t2); - - /*---------------CLEAN-------------------*/ - return true; -} - -bool 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_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_disto_alloc|| l_cp->m_specific_param.m_enc.m_fixed_quality) - { /* fixed_quality */ - /* Normal Rate/distortion allocation */ - if - (! tcd_rateallocate(p_tcd, p_dest_data,&l_nb_written, p_max_dest_size, p_cstr_info)) - { - return false; - } - } - else - { - /* Fixed layer allocation */ - tcd_rateallocate_fixed(p_tcd); - } - return true; -} - -bool 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_info_t *p_cstr_info - ) -{ - opj_t2_t * l_t2; - - l_t2 = t2_create(p_tcd->image, p_tcd->cp); - if - (l_t2 == 00) - { - return false; - } - - if - (! t2_decode_packets( - l_t2, - p_tcd->tcd_tileno, - p_tcd->tcd_image->tiles, - p_src_data, - p_data_read, - p_max_src_size, - p_cstr_info)) - { - t2_destroy(l_t2); - return false; - } - t2_destroy(l_t2); - - /*---------------CLEAN-------------------*/ - return true; -} - -bool tcd_t1_decode ( - opj_tcd_t *p_tcd - ) -{ - OPJ_UINT32 compno; - opj_t1_t * l_t1; - 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; - - - l_t1 = t1_create(); - if - (l_t1 == 00) - { - return false; - } - for - (compno = 0; compno < l_tile->numcomps; ++compno) - { - /* The +3 is headroom required by the vectorized DWT */ - t1_decode_cblks(l_t1, l_tile_comp, l_tccp); - ++l_tile_comp; - ++l_tccp; - } - t1_destroy(l_t1); - return true; -} - -bool 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++) - { - /* - if (tcd->cp->reduce != 0) { - tcd->image->comps[compno].resno_decoded = - tile->comps[compno].numresolutions - tcd->cp->reduce - 1; - if (tcd->image->comps[compno].resno_decoded < 0) - { - return false; - } - } - numres2decode = tcd->image->comps[compno].resno_decoded + 1; - if(numres2decode > 0){ - */ - if - (l_tccp->qmfbid == 1) - { - if - (! dwt_decode(l_tile_comp, l_img_comp->resno_decoded+1)) - { - return false; - } - } - else - { - if - (! dwt_decode_real(l_tile_comp, l_img_comp->resno_decoded+1)) - { - return false; - } - } - ++l_tile_comp; - ++l_img_comp; - ++l_tccp; - } - return true; -} -bool tcd_mct_decode ( - opj_tcd_t *p_tcd - ) -{ - 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_UINT32 l_samples,i; - - if - (! l_tcp->mct) - { - return true; - } - l_samples = (l_tile_comp->x1 - l_tile_comp->x0) * (l_tile_comp->y1 - l_tile_comp->y0); - if - (l_tcp->mct == 2) - { - OPJ_BYTE ** l_data; - if - (! l_tcp->m_mct_decoding_matrix) - { - return true; - } - l_data = (OPJ_BYTE **) opj_malloc(l_tile->numcomps*sizeof(OPJ_BYTE*)); - if - (! l_data) - { - return false; - } - for - (i=0;inumcomps;++i) - { - l_data[i] = (OPJ_BYTE*) l_tile_comp->data; - ++l_tile_comp; - } - if - (! 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 false; - } - opj_free(l_data); - } - else - { - if - (l_tcp->tccps->qmfbid == 1) - { - mct_decode( - l_tile->comps[0].data, - l_tile->comps[1].data, - l_tile->comps[2].data, - l_samples); - } - else - { - mct_decode_real( - (float*)l_tile->comps[0].data, - (float*)l_tile->comps[1].data, - (float*)l_tile->comps[2].data, - l_samples); - } - } - return true; -} - -bool 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_tcp_t * l_tcp = 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_tcp = p_tcd->tcp; - l_tccp = p_tcd->tcp->tccps; - l_img_comp = p_tcd->image->comps; - - for - (compno = 0; compno < l_tile->numcomps; compno++) - { - l_res = l_tile_comp->resolutions + l_img_comp->resno_decoded; - l_width = (l_res->x1 - l_res->x0); - l_height = (l_res->y1 - l_res->y0); - l_stride = (l_tile_comp->x1 - l_tile_comp->x0) - l_width; - 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 = (1 << l_img_comp->prec) - 1; - } - l_current_ptr = l_tile_comp->data; - if - (l_tccp->qmfbid == 1) - { - for - (j=0;jm_dc_level_shift, l_min, l_max); - ++l_current_ptr; - } - l_current_ptr += l_stride; - } - } - else - { - for - (j=0;jm_dc_level_shift, l_min, l_max); ; - ++l_current_ptr; - } - l_current_ptr += l_stride; - } - } - ++l_img_comp; - ++l_tccp; - ++l_tile_comp; - } - return true; -} - -bool 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) -{ - - 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] = l_res_idx->pw; - p_cstr_info->tile[p_tile_no].ph[i] = l_res_idx->ph; - - l_num_packs += l_res_idx->pw * l_res_idx->ph; - p_cstr_info->tile[p_tile_no].pdx[i] = l_tccp->prcw[i]; - p_cstr_info->tile[p_tile_no].pdy[i] = l_tccp->prch[i]; - } - p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t*) opj_calloc(p_cstr_info->numcomps * p_cstr_info->numlayers * l_num_packs, sizeof(opj_packet_info_t)); - } - /* << INDEX */ - _ProfStart(PGROUP_DC_SHIFT); - /*---------------TILE-------------------*/ - if - (! tcd_dc_level_shift_encode(p_tcd)) - { - return false; - } - _ProfStop(PGROUP_DC_SHIFT); - - _ProfStart(PGROUP_MCT); - if - (! tcd_mct_encode(p_tcd)) - { - return false; - } - _ProfStop(PGROUP_MCT); - - _ProfStart(PGROUP_DWT); - if - (! tcd_dwt_encode(p_tcd)) - { - return false; - } - _ProfStop(PGROUP_DWT); - - _ProfStart(PGROUP_T1); - if - (! tcd_t1_encode(p_tcd)) - { - return false; - } - _ProfStop(PGROUP_T1); - - _ProfStart(PGROUP_RATE); - if - (! tcd_rate_allocate_encode(p_tcd,p_dest,p_max_length,p_cstr_info)) - { - return false; - } - _ProfStop(PGROUP_RATE); - - } - /*--------------TIER2------------------*/ - - /* INDEX */ - if - (p_cstr_info) - { - p_cstr_info->index_write = 1; - } - _ProfStart(PGROUP_T2); - if - (! tcd_t2_encode(p_tcd,p_dest,p_data_written,p_max_length,p_cstr_info)) - { - return false; - } - _ProfStop(PGROUP_T2); - /*---------------CLEAN-------------------*/ - return true; -} - -bool tcd_decode_tile( - opj_tcd_t *p_tcd, - OPJ_BYTE *p_src, - OPJ_UINT32 p_max_length, - OPJ_UINT32 p_tile_no, - opj_codestream_info_t *p_cstr_info) -{ - OPJ_UINT32 l_data_read; - p_tcd->tcd_tileno = p_tile_no; - p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]); - - /* 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 */ - - /*--------------TIER2------------------*/ - _ProfStart(PGROUP_T2); - l_data_read = 0; - if - (! tcd_t2_decode(p_tcd,p_src,&l_data_read,p_max_length,p_cstr_info)) - { - return false; - } - _ProfStop(PGROUP_T2); - - /*------------------TIER1-----------------*/ - - _ProfStart(PGROUP_T1); - if - (! tcd_t1_decode(p_tcd)) - { - return false; - } - _ProfStop(PGROUP_T1); - - /*----------------DWT---------------------*/ - - _ProfStart(PGROUP_DWT); - if - (! tcd_dwt_decode(p_tcd)) - { - return false; - } - _ProfStop(PGROUP_DWT); - - /*----------------MCT-------------------*/ - _ProfStart(PGROUP_MCT); - if - (! tcd_mct_decode(p_tcd)) - { - return false; - } - _ProfStop(PGROUP_MCT); - - _ProfStart(PGROUP_DC_SHIFT); - if - (! tcd_dc_level_shift_decode(p_tcd)) - { - return false; - } - _ProfStop(PGROUP_DC_SHIFT); - - - /*---------------TILE-------------------*/ - return true; -} diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/tcd.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/tcd.h deleted file mode 100644 index 62bbdb7bcbd..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/tcd.h +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __TCD_H -#define __TCD_H -/** -@file tcd.h -@brief Implementation of a tile coder/decoder (TCD) - -The functions in TCD.C have for goal to encode or decode each tile independently from -each other. The functions in TCD.C are used by some function in J2K.C. -*/ -#include "openjpeg.h" -/** @defgroup TCD TCD - Implementation of a tile coder/decoder */ -/*@{*/ -struct opj_common_struct; -struct opj_codestream_info; -struct opj_image; -struct opj_tcp; -struct opj_cp; -struct opj_tgt_tree; - -/** -FIXME: documentation -*/ -typedef struct opj_tcd_seg { - OPJ_BYTE ** data; - OPJ_UINT32 dataindex; - OPJ_UINT32 numpasses; - OPJ_UINT32 real_num_passes; - OPJ_UINT32 len; - OPJ_UINT32 maxpasses; - OPJ_UINT32 numnewpasses; - OPJ_UINT32 newlen; -} opj_tcd_seg_t; - -/** -FIXME: documentation -*/ -typedef struct opj_tcd_pass { - OPJ_UINT32 rate; - OPJ_FLOAT64 distortiondec; - OPJ_UINT32 len; - OPJ_UINT32 term : 1; -} opj_tcd_pass_t; - -/** -FIXME: documentation -*/ -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: documentation -*/ -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 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; - -typedef struct opj_tcd_cblk_dec { - OPJ_BYTE * data; /* Data */ - opj_tcd_seg_t* segs; /* segments informations */ - 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 len; /* length */ - OPJ_UINT32 numnewpasses; /* number of pass added to the code-blocks */ - OPJ_UINT32 numsegs; /* number of segments */ - OPJ_UINT32 real_num_segs; - OPJ_UINT32 m_current_max_segs; -} opj_tcd_cblk_dec_t; - -/** -FIXME: documentation -*/ -typedef struct opj_tcd_precinct { - OPJ_INT32 x0, y0, x1, y1; /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 cw, ch; /* number of precinct in width and heigth */ - union{ /* code-blocks informations */ - opj_tcd_cblk_enc_t* enc; - opj_tcd_cblk_dec_t* dec; - } cblks; - OPJ_UINT32 block_size; /* size taken by cblks (in bytes) */ - struct opj_tgt_tree *incltree; /* inclusion tree */ - struct opj_tgt_tree *imsbtree; /* IMSB tree */ -} opj_tcd_precinct_t; - -/** -FIXME: documentation -*/ -typedef struct opj_tcd_band { - OPJ_INT32 x0, y0, x1, y1; /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 bandno; - opj_tcd_precinct_t *precincts; /* precinct information */ - OPJ_UINT32 precincts_data_size; /* size of data taken by precincts */ - OPJ_INT32 numbps; - OPJ_FLOAT32 stepsize; -} opj_tcd_band_t; - -/** -FIXME: documentation -*/ -typedef struct opj_tcd_resolution { - OPJ_INT32 x0, y0, x1, y1; /* dimension of the resolution level : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 pw, ph; - OPJ_UINT32 numbands; /* number sub-band for the resolution level */ - opj_tcd_band_t bands[3]; /* subband information */ -} opj_tcd_resolution_t; - -/** -FIXME: documentation -*/ -typedef struct opj_tcd_tilecomp -{ - OPJ_INT32 x0, y0, x1, y1; /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 numresolutions; /* number of resolutions level */ - OPJ_UINT32 minimum_num_resolutions; /* number of resolutions level to decode (at max)*/ - opj_tcd_resolution_t *resolutions; /* resolutions information */ - OPJ_UINT32 resolutions_size; /* size of data for resolutions (in bytes) */ - OPJ_INT32 *data; /* data of the component */ - OPJ_UINT32 data_size; /* size of the data of the component */ - OPJ_INT32 numpix; /* add fixed_quality */ -} opj_tcd_tilecomp_t; - -/** -FIXME: documentation -*/ -typedef struct opj_tcd_tile { - OPJ_INT32 x0, y0, x1, y1; /* dimension of the tile : left upper corner (x0, y0) right low corner (x1,y1) */ - OPJ_UINT32 numcomps; /* number of components in tile */ - opj_tcd_tilecomp_t *comps; /* Components information */ - OPJ_INT32 numpix; /* add fixed_quality */ - OPJ_FLOAT64 distotile; /* add fixed_quality */ - OPJ_FLOAT64 distolayer[100]; /* add fixed_quality */ - /** packet number */ - OPJ_UINT32 packno; -} opj_tcd_tile_t; - -/** -FIXME: documentation -*/ -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 */ - struct opj_tcd_image *tcd_image; - /** image */ - struct opj_image *image; - /** coding parameters */ - struct opj_cp *cp; - /** coding/decoding parameters common to all tiles */ - struct opj_tcp *tcp; - /** current encoded/decoded tile */ - OPJ_UINT32 tcd_tileno; - /** tell if the tcd is a decoder. */ - OPJ_UINT32 m_is_decoder : 1; -} opj_tcd_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); -/** -Create a new TCD handle -@param cinfo Codec context info -@return Returns a new TCD handle if successful returns NULL otherwise -*/ -opj_tcd_t* tcd_create(bool p_is_decoder); - -/** -Destroy a previously created TCD handle -@param tcd TCD handle to destroy -*/ -void tcd_destroy(opj_tcd_t *tcd); - - - - -/** - * Initialize the tile coder and may reuse some meory. - * @param p_tcd TCD handle. - * @param p_image raw image. - * @param p_cp coding parameters. - * @param p_tile_no current tile index to encode. - * - * @return true if the encoding values could be set (false otherwise). -*/ -bool tcd_init( - opj_tcd_t *p_tcd, - struct opj_image * p_image, - struct opj_cp * p_cp - ); - - -/** - * Allocates memory for decoding a specific tile. - * - * @param p_tcd the tile decoder. - * @param p_image the image to decode. - * @param p_cp the decoding parameters. - * @param p_tile_no the index of the tile received in sequence. This not necesseraly lead to the - * tile at index p_tile_no. - * @param p_cstr_info codestream info (if any). - * - * @return true if the remaining data is sufficient.s - */ -bool tcd_init_decode_tile( - opj_tcd_t *p_tcd, - OPJ_UINT32 p_tile_no - ); -/** - * Initialize the tile coder and may reuse some meory. - * @param p_tcd TCD handle. - * @param p_image raw image. - * @param p_cp coding parameters. - * @param p_tile_no current tile index to encode. - * - * @return true if the encoding values could be set (false otherwise). -*/ -bool tcd_init_encode_tile - ( - opj_tcd_t *p_tcd, - OPJ_UINT32 p_tile_no - ); - -void tcd_makelayer_fixed(opj_tcd_t *tcd, OPJ_UINT32 layno, OPJ_UINT32 final); -void tcd_rateallocate_fixed(opj_tcd_t *tcd); -void tcd_makelayer(opj_tcd_t *tcd, OPJ_UINT32 layno, OPJ_FLOAT64 thresh, OPJ_UINT32 final); -bool tcd_rateallocate(opj_tcd_t *tcd, OPJ_BYTE *dest, OPJ_UINT32 * p_data_written, OPJ_UINT32 len, struct opj_codestream_info *cstr_info); -/** - * 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 - * @return true if the coding is successfull. -*/ -bool 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); - -/** -Decode a tile from a buffer into a raw image -@param tcd TCD handle -@param src Source buffer -@param len Length of source buffer -@param tileno Number that identifies one of the tiles to be decoded -*/ -bool tcd_decode_tile(opj_tcd_t *tcd, OPJ_BYTE *src, OPJ_UINT32 len, OPJ_UINT32 tileno, struct opj_codestream_info *cstr_info); - -/** - * Copies tile data from the given memory block onto the system. - */ -bool tcd_copy_tile_data ( - opj_tcd_t *p_tcd, - OPJ_BYTE * p_src, - OPJ_UINT32 p_src_length - ); -/** - * Copies tile data from the system onto the given memory block. - */ -bool tcd_update_tile_data ( - opj_tcd_t *p_tcd, - OPJ_BYTE * p_dest, - OPJ_UINT32 p_dest_length - ); -/** - * Gets the maximum tile size that will be taken by the tile once decoded. - */ -OPJ_UINT32 tcd_get_decoded_tile_size ( - opj_tcd_t *p_tcd - ); - -OPJ_UINT32 tcd_get_encoded_tile_size ( - opj_tcd_t *p_tcd - ); -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __TCD_H */ diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/tgt.c b/Modules/ThirdParty/OpenJPEG/src/openjpeg/tgt.c deleted file mode 100644 index 120d5ae2700..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/tgt.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 "tgt.h" -#include "bio.h" -#include "opj_malloc.h" - -/* -========================================================== - Tag-tree coder interface -========================================================== -*/ - -opj_tgt_tree_t *tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv) { - 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_malloc(sizeof(opj_tgt_tree_t)); - if(!tree) return 00; - memset(tree,0,sizeof(opj_tgt_tree_t)); - - tree->numleafsh = numleafsh; - tree->numleafsv = numleafsv; - - numlvls = 0; - nplh[0] = numleafsh; - nplv[0] = numleafsv; - tree->numnodes = 0; - do { - n = 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_free(tree); - return 00; - } - memset(tree->nodes,0,tree->numnodes * sizeof(opj_tgt_node_t)); - tree->nodes_size = tree->numnodes * 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; - tgt_reset(tree); - return tree; -} -/** - * 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 - * @return a new tag-tree if successful, NULL otherwise -*/ -opj_tgt_tree_t *tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v) -{ - 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] = p_num_leafs_h; - l_nplv[0] = p_num_leafs_v; - p_tree->numnodes = 0; - do - { - n = 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) - { - tgt_destroy(p_tree); - return 00; - } - l_node_size = p_tree->numnodes * sizeof(opj_tgt_node_t); - if - (l_node_size > p_tree->nodes_size) - { - p_tree->nodes = (opj_tgt_node_t*) opj_realloc(p_tree->nodes, l_node_size); - if - (! p_tree->nodes) - { - tgt_destroy(p_tree); - return 00; - } - 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; - } - tgt_reset(p_tree); - - return p_tree; -} - -void 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 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 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 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) { - bio_write(bio, 1, 1); - node->known = 1; - } - break; - } - bio_write(bio, 0, 1); - ++low; - } - - node->low = low; - if (stkptr == stk) - break; - node = *--stkptr; - } -} - -OPJ_UINT32 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 (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/Modules/ThirdParty/OpenJPEG/src/openjpeg/tgt.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/tgt.h deleted file mode 100644 index 2aa8dc9d085..00000000000 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/tgt.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium - * Copyright (c) 2002-2007, Professor Benoit Macq - * Copyright (c) 2001-2003, David Janssens - * Copyright (c) 2002-2003, Yannick Verschueren - * Copyright (c) 2003-2007, Francois-Olivier Devaux and 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 __TGT_H -#define __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. -*/ -#include "openjpeg.h" -/** @defgroup TGT TGT - Implementation of a tag-tree coder */ -/*@{*/ -struct opj_bio; - -/** -Tag node -*/ -typedef struct opj_tgt_node -{ - struct opj_tgt_node *parent; - OPJ_INT32 value; - OPJ_INT32 low; - OPJ_UINT32 known : 1; -} 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 -@return Returns a new tag-tree if successful, returns NULL otherwise -*/ -opj_tgt_tree_t *tgt_create(OPJ_UINT32 numleafsh, OPJ_UINT32 numleafsv); - -/** - * 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 - * @return a new tag-tree if successful, NULL otherwise -*/ -opj_tgt_tree_t *tgt_init(opj_tgt_tree_t * p_tree,OPJ_UINT32 p_num_leafs_h, OPJ_UINT32 p_num_leafs_v); - -/** -Destroy a tag-tree, liberating memory -@param tree Tag-tree to destroy -*/ -void tgt_destroy(opj_tgt_tree_t *tree); -/** -Reset a tag-tree (set all leaves to 0) -@param tree Tag-tree to reset -*/ -void 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 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 tgt_encode(struct opj_bio *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 tgt_decode(struct opj_bio *bio, opj_tgt_tree_t *tree, OPJ_UINT32 leafno, OPJ_INT32 threshold); -/* ----------------------------------------------------------------------- */ -/*@}*/ - -/*@}*/ - -#endif /* __TGT_H */ From 4cfb52e3e378aa8ea649eff401e75a8054f30fca Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Mon, 2 Dec 2024 14:59:45 -0500 Subject: [PATCH 2/7] ENH: openjpeg: add script to import from upstream --- Modules/ThirdParty/OpenJPEG/.gitattributes | 1 + .../ThirdParty/OpenJPEG/UpdateFromUpstream.sh | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 Modules/ThirdParty/OpenJPEG/.gitattributes create mode 100755 Modules/ThirdParty/OpenJPEG/UpdateFromUpstream.sh diff --git a/Modules/ThirdParty/OpenJPEG/.gitattributes b/Modules/ThirdParty/OpenJPEG/.gitattributes new file mode 100644 index 00000000000..ceefff00c09 --- /dev/null +++ b/Modules/ThirdParty/OpenJPEG/.gitattributes @@ -0,0 +1 @@ +src/openjpeg/src/lib/openjp2/j2k.c hooks-max-size=500000 diff --git a/Modules/ThirdParty/OpenJPEG/UpdateFromUpstream.sh b/Modules/ThirdParty/OpenJPEG/UpdateFromUpstream.sh new file mode 100755 index 00000000000..5ea781b073b --- /dev/null +++ b/Modules/ThirdParty/OpenJPEG/UpdateFromUpstream.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -e +set -x +shopt -s dotglob + +readonly name="openjpeg" +readonly ownership="OpenJPEG Upstream " +readonly subtree="Modules/ThirdParty/OpenJPEG/src/$name" +readonly repo="https://github.com/uclouvain/openjpeg.git" +readonly tag="v2.5.2" +readonly paths=" +CMakeLists.txt +README.md +LICENSE + +cmake/EnsureFileInclude.cmake +cmake/TestLargeFiles.cmake + +src/lib/CMakeLists.txt +src/lib/openjp2/CMakeLists.txt +src/lib/openjp2/*.c +src/lib/openjp2/*.h +src/lib/openjp2/*.cmake.in +" + +extract_source () { + git_archive + pushd "${extractdir}/${name}-reduced" + echo "* -whitespace" >> .gitattributes + echo "" >> src/lib/openjp2/mqc.c + echo "" >> src/lib/openjp2/t1_ht_luts.h + popd +} + +. "${BASH_SOURCE%/*}/../../../Utilities/Maintenance/update-third-party.bash" From e80e9b252c5f04c110fe61adae4b5ff7f5411d88 Mon Sep 17 00:00:00 2001 From: OpenJPEG Upstream Date: Wed, 28 Feb 2024 14:32:43 +0100 Subject: [PATCH 3/7] openjpeg 2024-02-28 (39e8c50a) Code extracted from: https://github.com/uclouvain/openjpeg.git at commit 39e8c50a2f9bdcf36810ee3d41bcbf1cc78968ae (v2.5.2). --- .gitattributes | 1 + CMakeLists.txt | 346 + LICENSE | 39 + README.md | 83 + cmake/EnsureFileInclude.cmake | 26 + cmake/TestLargeFiles.cmake | 134 + src/lib/CMakeLists.txt | 7 + src/lib/openjp2/CMakeLists.txt | 218 + src/lib/openjp2/bench_dwt.c | 353 + src/lib/openjp2/bio.c | 211 + src/lib/openjp2/bio.h | 142 + src/lib/openjp2/cidx_manager.c | 259 + src/lib/openjp2/cidx_manager.h | 70 + src/lib/openjp2/cio.c | 683 + src/lib/openjp2/cio.h | 412 + src/lib/openjp2/dwt.c | 3769 +++++ src/lib/openjp2/dwt.h | 120 + src/lib/openjp2/event.c | 151 + src/lib/openjp2/event.h | 108 + src/lib/openjp2/function_list.c | 117 + src/lib/openjp2/function_list.h | 134 + src/lib/openjp2/ht_dec.c | 2689 ++++ src/lib/openjp2/image.c | 263 + src/lib/openjp2/image.h | 70 + src/lib/openjp2/indexbox_manager.h | 157 + src/lib/openjp2/invert.c | 295 + src/lib/openjp2/invert.h | 64 + src/lib/openjp2/j2k.c | 13217 ++++++++++++++++ src/lib/openjp2/j2k.h | 924 ++ src/lib/openjp2/jp2.c | 3414 ++++ src/lib/openjp2/jp2.h | 521 + src/lib/openjp2/libopenjp2.pc.cmake.in | 15 + src/lib/openjp2/mct.c | 464 + src/lib/openjp2/mct.h | 160 + src/lib/openjp2/mqc.c | 524 + src/lib/openjp2/mqc.h | 268 + src/lib/openjp2/mqc_inl.h | 282 + src/lib/openjp2/openjpeg.c | 1144 ++ src/lib/openjp2/openjpeg.h | 1779 +++ src/lib/openjp2/opj_clock.c | 67 + src/lib/openjp2/opj_clock.h | 59 + src/lib/openjp2/opj_codec.h | 179 + src/lib/openjp2/opj_common.h | 47 + src/lib/openjp2/opj_config.h.cmake.in | 14 + src/lib/openjp2/opj_config_private.h.cmake.in | 50 + src/lib/openjp2/opj_includes.h | 266 + src/lib/openjp2/opj_intmath.h | 333 + src/lib/openjp2/opj_malloc.c | 249 + src/lib/openjp2/opj_malloc.h | 106 + src/lib/openjp2/phix_manager.c | 210 + src/lib/openjp2/pi.c | 2149 +++ src/lib/openjp2/pi.h | 207 + src/lib/openjp2/ppix_manager.c | 215 + src/lib/openjp2/sparse_array.c | 346 + src/lib/openjp2/sparse_array.h | 141 + src/lib/openjp2/t1.c | 2592 +++ src/lib/openjp2/t1.h | 268 + src/lib/openjp2/t1_generate_luts.c | 323 + src/lib/openjp2/t1_ht_generate_luts.c | 971 ++ src/lib/openjp2/t1_ht_luts.h | 261 + src/lib/openjp2/t1_luts.h | 175 + src/lib/openjp2/t2.c | 1695 ++ src/lib/openjp2/t2.h | 142 + src/lib/openjp2/tcd.c | 2930 ++++ src/lib/openjp2/tcd.h | 511 + src/lib/openjp2/test_sparse_array.c | 174 + src/lib/openjp2/tgt.c | 344 + src/lib/openjp2/tgt.h | 148 + src/lib/openjp2/thix_manager.c | 146 + src/lib/openjp2/thread.c | 954 ++ src/lib/openjp2/thread.h | 256 + src/lib/openjp2/tls_keys.h | 37 + src/lib/openjp2/tpix_manager.c | 190 + 73 files changed, 50388 insertions(+) create mode 100644 .gitattributes create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmake/EnsureFileInclude.cmake create mode 100644 cmake/TestLargeFiles.cmake create mode 100644 src/lib/CMakeLists.txt create mode 100644 src/lib/openjp2/CMakeLists.txt create mode 100644 src/lib/openjp2/bench_dwt.c create mode 100644 src/lib/openjp2/bio.c create mode 100644 src/lib/openjp2/bio.h create mode 100644 src/lib/openjp2/cidx_manager.c create mode 100644 src/lib/openjp2/cidx_manager.h create mode 100644 src/lib/openjp2/cio.c create mode 100644 src/lib/openjp2/cio.h create mode 100644 src/lib/openjp2/dwt.c create mode 100644 src/lib/openjp2/dwt.h create mode 100644 src/lib/openjp2/event.c create mode 100644 src/lib/openjp2/event.h create mode 100644 src/lib/openjp2/function_list.c create mode 100644 src/lib/openjp2/function_list.h create mode 100644 src/lib/openjp2/ht_dec.c create mode 100644 src/lib/openjp2/image.c create mode 100644 src/lib/openjp2/image.h create mode 100644 src/lib/openjp2/indexbox_manager.h create mode 100644 src/lib/openjp2/invert.c create mode 100644 src/lib/openjp2/invert.h create mode 100644 src/lib/openjp2/j2k.c create mode 100644 src/lib/openjp2/j2k.h create mode 100644 src/lib/openjp2/jp2.c create mode 100644 src/lib/openjp2/jp2.h create mode 100644 src/lib/openjp2/libopenjp2.pc.cmake.in create mode 100644 src/lib/openjp2/mct.c create mode 100644 src/lib/openjp2/mct.h create mode 100644 src/lib/openjp2/mqc.c create mode 100644 src/lib/openjp2/mqc.h create mode 100644 src/lib/openjp2/mqc_inl.h create mode 100644 src/lib/openjp2/openjpeg.c create mode 100644 src/lib/openjp2/openjpeg.h create mode 100644 src/lib/openjp2/opj_clock.c create mode 100644 src/lib/openjp2/opj_clock.h create mode 100644 src/lib/openjp2/opj_codec.h create mode 100644 src/lib/openjp2/opj_common.h create mode 100644 src/lib/openjp2/opj_config.h.cmake.in create mode 100644 src/lib/openjp2/opj_config_private.h.cmake.in create mode 100644 src/lib/openjp2/opj_includes.h create mode 100644 src/lib/openjp2/opj_intmath.h create mode 100644 src/lib/openjp2/opj_malloc.c create mode 100644 src/lib/openjp2/opj_malloc.h create mode 100644 src/lib/openjp2/phix_manager.c create mode 100644 src/lib/openjp2/pi.c create mode 100644 src/lib/openjp2/pi.h create mode 100644 src/lib/openjp2/ppix_manager.c create mode 100644 src/lib/openjp2/sparse_array.c create mode 100644 src/lib/openjp2/sparse_array.h create mode 100644 src/lib/openjp2/t1.c create mode 100644 src/lib/openjp2/t1.h create mode 100644 src/lib/openjp2/t1_generate_luts.c create mode 100644 src/lib/openjp2/t1_ht_generate_luts.c create mode 100644 src/lib/openjp2/t1_ht_luts.h create mode 100644 src/lib/openjp2/t1_luts.h create mode 100644 src/lib/openjp2/t2.c create mode 100644 src/lib/openjp2/t2.h create mode 100644 src/lib/openjp2/tcd.c create mode 100644 src/lib/openjp2/tcd.h create mode 100644 src/lib/openjp2/test_sparse_array.c create mode 100644 src/lib/openjp2/tgt.c create mode 100644 src/lib/openjp2/tgt.h create mode 100644 src/lib/openjp2/thix_manager.c create mode 100644 src/lib/openjp2/thread.c create mode 100644 src/lib/openjp2/thread.h create mode 100644 src/lib/openjp2/tls_keys.h create mode 100644 src/lib/openjp2/tpix_manager.c diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..562b12e16eb --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000000..65570b4452b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,346 @@ +# Main CMakeLists.txt to build the OpenJPEG project using CMake (www.cmake.org) +# Written by Mathieu Malaterre + +# This CMake project will by default create a library called openjpeg +# But if you want to use this project within your own (CMake) project +# you will eventually like to prefix the library to avoid linking confusion +# For this purpose you can define a CMake var: OPENJPEG_NAMESPACE to whatever you like +# e.g.: +# set(OPENJPEG_NAMESPACE "GDCMOPENJPEG") +cmake_minimum_required(VERSION 3.5) + +if(NOT OPENJPEG_NAMESPACE) + set(OPENJPEG_NAMESPACE "OPENJPEG") + set(OPENJPEG_STANDALONE 1) +endif() +# In all cases: +#string(TOLOWER ${OPENJPEG_NAMESPACE} OPENJPEG_LIBRARY_NAME) +set(OPENJPEG_LIBRARY_NAME openjp2) + +project(${OPENJPEG_NAMESPACE} C) + +# Do full dependency headers. +include_regular_expression("^.*$") + +#----------------------------------------------------------------------------- +# OPENJPEG version number, useful for packaging and doxygen doc: +set(OPENJPEG_VERSION_MAJOR 2) +set(OPENJPEG_VERSION_MINOR 5) +set(OPENJPEG_VERSION_BUILD 2) +set(OPENJPEG_VERSION + "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}") +set(PACKAGE_VERSION + "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}") + +# Because autotools does not support X.Y notation for SOVERSION, we have to use +# two numbering, one for the openjpeg version and one for openjpeg soversion +# version | soversion +# 1.0 | 0 +# 1.1 | 1 +# 1.2 | 2 +# 1.3 | 3 +# 1.4 | 4 +# 1.5 | 5 +# 1.5.1 | 5 +# 2.0 | 6 +# 2.0.1 | 6 +# 2.1 | 7 +# 2.1.1 | 7 +# 2.1.2 | 7 +# 2.2.0 | 7 +# 2.3.0 | 7 +# 2.3.1 | 7 +# 2.4.0 | 7 +# 2.5.0 | 7 +# 2.5.1 | 7 +# 2.5.2 | 7 +# above is the recommendation by the OPJ team. If you really need to override this default, +# you can specify your own OPENJPEG_SOVERSION at cmake configuration time: +# cmake -DOPENJPEG_SOVERSION:STRING=42 /path/to/openjpeg +if(NOT OPENJPEG_SOVERSION) + set(OPENJPEG_SOVERSION 7) +endif(NOT OPENJPEG_SOVERSION) +set(OPENJPEG_LIBRARY_PROPERTIES + VERSION "${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}.${OPENJPEG_VERSION_BUILD}" + SOVERSION "${OPENJPEG_SOVERSION}" +) + +# -------------------------------------------------------------------------- +# Path to additional CMake modules +set(CMAKE_MODULE_PATH + ${${OPENJPEG_NAMESPACE}_SOURCE_DIR}/cmake + ${CMAKE_MODULE_PATH}) + +# -------------------------------------------------------------------------- +# On Visual Studio 8 MS deprecated C. This removes all 1.276E1265 security +# warnings +if(WIN32) + if(NOT BORLAND) + if(NOT CYGWIN) + if(NOT MINGW) + if(NOT ITK_ENABLE_VISUAL_STUDIO_DEPRECATED_C_WARNINGS) + add_definitions( + -D_CRT_FAR_MAPPINGS_NO_DEPRECATE + -D_CRT_IS_WCTYPE_NO_DEPRECATE + -D_CRT_MANAGED_FP_NO_DEPRECATE + -D_CRT_NONSTDC_NO_DEPRECATE + -D_CRT_SECURE_NO_DEPRECATE + -D_CRT_SECURE_NO_DEPRECATE_GLOBALS + -D_CRT_SETERRORMODE_BEEP_SLEEP_NO_DEPRECATE + -D_CRT_TIME_FUNCTIONS_NO_DEPRECATE + -D_CRT_VCCLRIT_NO_DEPRECATE + -D_SCL_SECURE_NO_DEPRECATE + ) + endif() + endif() + endif() + endif() +endif() + + +# -------------------------------------------------------------------------- +# Install directories +string(TOLOWER ${PROJECT_NAME} PROJECT_NAME) +include(GNUInstallDirs) + +# Build DOCUMENTATION (not in ALL target and only if Doxygen is found) +option(BUILD_DOC "Build the HTML documentation (with doxygen if available)." OFF) + +set(OPENJPEG_INSTALL_SUBDIR "${PROJECT_NAME}-${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}") + +if(NOT OPENJPEG_INSTALL_JNI_DIR) + if(WIN32) + set(OPENJPEG_INSTALL_JNI_DIR ${CMAKE_INSTALL_BINDIR}) + else() + set(OPENJPEG_INSTALL_JNI_DIR ${CMAKE_INSTALL_LIBDIR}) + endif() +endif() + +if(NOT OPENJPEG_INSTALL_PACKAGE_DIR) + set(OPENJPEG_INSTALL_PACKAGE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${OPENJPEG_INSTALL_SUBDIR}") +endif() + +if (APPLE) + option(OPJ_USE_DSYMUTIL "Call dsymutil on binaries after build." OFF) +endif() + +#----------------------------------------------------------------------------- +# Big endian test: +if (NOT EMSCRIPTEN) +include (${CMAKE_ROOT}/Modules/TestBigEndian.cmake) +TEST_BIG_ENDIAN(OPJ_BIG_ENDIAN) +endif() + +#----------------------------------------------------------------------------- +# Setup file for setting custom ctest vars +configure_file( + ${${OPENJPEG_NAMESPACE}_SOURCE_DIR}/cmake/CTestCustom.cmake.in + ${${OPENJPEG_NAMESPACE}_BINARY_DIR}/CTestCustom.cmake + @ONLY + ) + +#----------------------------------------------------------------------------- +# OpenJPEG build configuration options. +option(BUILD_SHARED_LIBS "Build OpenJPEG shared library and link executables against it." ON) +option(BUILD_STATIC_LIBS "Build OpenJPEG static library." ON) +set (EXECUTABLE_OUTPUT_PATH ${OPENJPEG_BINARY_DIR}/bin CACHE PATH "Single output directory for building all executables.") +set (LIBRARY_OUTPUT_PATH ${OPENJPEG_BINARY_DIR}/bin CACHE PATH "Single output directory for building all libraries.") +mark_as_advanced(LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH) + +#----------------------------------------------------------------------------- +# configure name mangling to allow multiple libraries to coexist +# peacefully +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/openjpeg_mangle.h.in) +set(MANGLE_PREFIX ${OPENJPEG_LIBRARY_NAME}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/openjpeg_mangle.h.in + ${CMAKE_CURRENT_BINARY_DIR}/openjpeg_mangle.h + @ONLY) +endif() + +#----------------------------------------------------------------------------- +# Compiler specific flags: +if(CMAKE_COMPILER_IS_GNUCC) + # For all builds, make sure openjpeg is std99 compliant: + # set(CMAKE_C_FLAGS "-Wall -std=c99 ${CMAKE_C_FLAGS}") # FIXME: this setting prevented us from setting a coverage build. + # Do not use ffast-math for all build, it would produce incorrect results, only set for release: + set(OPENJPEG_LIBRARY_COMPILE_OPTIONS ${OPENJPEG_LIBRARY_COMPILE_OPTIONS} "$<$:-ffast-math>") + set(OPENJP2_COMPILE_OPTIONS ${OPENJP2_COMPILE_OPTIONS} "$<$:-ffast-math>" -Wall -Wextra -Wconversion -Wunused-parameter -Wdeclaration-after-statement -Werror=declaration-after-statement -Wstrict-prototypes -Werror=strict-prototypes -Wmissing-prototypes -Werror=missing-prototypes) +endif() + +#----------------------------------------------------------------------------- +# opj_config.h generation (1/2) + +# Check if some include files are provided by the system +include(EnsureFileInclude) +# These files are mandatory +ensure_file_include("string.h" HAVE_STRING_H YES) +ensure_file_include("memory.h" HAVE_MEMORY_H YES) +ensure_file_include("stdlib.h" HAVE_STDLIB_H YES) +ensure_file_include("stdio.h" HAVE_STDIO_H YES) +ensure_file_include("math.h" HAVE_MATH_H YES) +ensure_file_include("float.h" HAVE_FLOAT_H YES) +ensure_file_include("time.h" HAVE_TIME_H YES) +ensure_file_include("stdarg.h" HAVE_STDARG_H YES) +ensure_file_include("ctype.h" HAVE_CTYPE_H YES) +ensure_file_include("assert.h" HAVE_ASSERT_H YES) +ensure_file_include("stdint.h" HAVE_STDINT_H YES) +ensure_file_include("inttypes.h" HAVE_INTTYPES_H YES) + +# why check this one ? for openjpip ? +include (${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake) +CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H) +CHECK_INCLUDE_FILE("sys/stat.h" HAVE_SYS_STAT_H) +CHECK_INCLUDE_FILE("sys/types.h" HAVE_SYS_TYPES_H) +CHECK_INCLUDE_FILE("unistd.h" HAVE_UNISTD_H) + +# Enable Large file support +include(TestLargeFiles) +OPJ_TEST_LARGE_FILES(OPJ_HAVE_LARGEFILES) + +# Allocating Aligned Memory Blocks +include(CheckIncludeFiles) +check_include_files(malloc.h OPJ_HAVE_MALLOC_H) +include(CheckSymbolExists) +# _aligned_alloc https://msdn.microsoft.com/en-us/library/8z34s9c6.aspx +check_symbol_exists(_aligned_malloc malloc.h OPJ_HAVE__ALIGNED_MALLOC) +# posix_memalign (needs _POSIX_C_SOURCE >= 200112L on Linux) +set(CMAKE_REQUIRED_DEFINITIONS -D_POSIX_C_SOURCE=200112L) +check_symbol_exists(posix_memalign stdlib.h OPJ_HAVE_POSIX_MEMALIGN) +unset(CMAKE_REQUIRED_DEFINITIONS) +# memalign (obsolete) +check_symbol_exists(memalign malloc.h OPJ_HAVE_MEMALIGN) +#----------------------------------------------------------------------------- +# Build Library +if(BUILD_JPIP_SERVER) + find_package(CURL REQUIRED) + find_package(FCGI REQUIRED) + find_package(Threads REQUIRED) + if(NOT CMAKE_USE_PTHREADS_INIT) + message(FATAL_ERROR "Only pthread are supported") + endif() +endif() +add_subdirectory(src/lib) +option(BUILD_LUTS_GENERATOR "Build utility to generate t1_luts.h" OFF) +if(UNIX) +option(BUILD_UNIT_TESTS "Build unit tests (bench_dwt, test_sparse_array, etc..)" OFF) +endif() + +#----------------------------------------------------------------------------- +# Build Applications +option(BUILD_CODEC "Build the CODEC executables" ON) +option(BUILD_JPIP "Build the JPIP library and executables." OFF) +if(BUILD_JPIP) + option(BUILD_JPIP_SERVER "Build the JPIP server." OFF) +endif() +option(BUILD_VIEWER "Build the OPJViewer executable (C++)" OFF) +option(BUILD_JAVA "Build the openjpeg jar (Java)" OFF) +mark_as_advanced(BUILD_VIEWER) +mark_as_advanced(BUILD_JAVA) + +if(BUILD_CODEC) + # OFF: It will only build 3rd party libs if they are not found on the system + # ON: 3rd party libs will ALWAYS be build, and used + option(BUILD_THIRDPARTY "Build the thirdparty executables if it is needed" OFF) + add_subdirectory(thirdparty) + add_subdirectory(src/bin) +endif () +add_subdirectory(wrapping) + +#----------------------------------------------------------------------------- +# opj_config.h generation (2/2) +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_config.h.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/src/lib/openjp2/opj_config.h + @ONLY + ) + + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/opj_config_private.h.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/src/lib/openjp2/opj_config_private.h + @ONLY + ) + +#----------------------------------------------------------------------------- +# build documentation in doc subdir: +if(BUILD_DOC) + add_subdirectory(doc) +endif() + +#----------------------------------------------------------------------------- +# Build Testing +option(BUILD_TESTING "Build the tests." OFF) +if(BUILD_TESTING) + if(BUILD_CODEC) + enable_testing() + include(CTest) + + # Search openjpeg data needed for the tests + # They could be found via git on the OpenJPEG GitHub code project + # git clone https://github.com/uclouvain/openjpeg-data.git + find_path(OPJ_DATA_ROOT README-OPJ-Data + PATHS $ENV{OPJ_DATA_ROOT} ${CMAKE_SOURCE_DIR}/../data + NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH + ) + + # Add repository where to find tests + add_subdirectory(tests) + + else() + message(FATAL_ERROR "You need build codec to run the tests") + endif() +endif() + +#----------------------------------------------------------------------------- +# install all targets referenced as OPENJPEGTargets (relocatable with CMake 3.0+) +install(EXPORT OpenJPEGTargets DESTINATION ${OPENJPEG_INSTALL_PACKAGE_DIR}) +include(CMakePackageConfigHelpers) +configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/cmake/OpenJPEGConfig.cmake.in + ${OPENJPEG_BINARY_DIR}/OpenJPEGConfig.cmake + INSTALL_DESTINATION ${OPENJPEG_INSTALL_PACKAGE_DIR} + PATH_VARS CMAKE_INSTALL_INCLUDEDIR) +write_basic_package_version_file( + ${OPENJPEG_BINARY_DIR}/OpenJPEGConfigVersion.cmake + COMPATIBILITY SameMajorVersion + VERSION ${OPENJPEG_VERSION}) +install( + FILES + ${OPENJPEG_BINARY_DIR}/OpenJPEGConfig.cmake + ${OPENJPEG_BINARY_DIR}/OpenJPEGConfigVersion.cmake + DESTINATION ${OPENJPEG_INSTALL_PACKAGE_DIR}) + +#----------------------------------------------------------------------------- + +include (cmake/OpenJPEGCPack.cmake) + +#----------------------------------------------------------------------------- +# pkgconfig support +macro(set_variable_from_rel_or_absolute_path var root rel_or_abs_path) + if(IS_ABSOLUTE "${rel_or_abs_path}") + set(${var} "${rel_or_abs_path}") + else() + set(${var} "${root}/${rel_or_abs_path}") + endif() +endmacro() +set_variable_from_rel_or_absolute_path("bindir" "\\\${prefix}" "${CMAKE_INSTALL_BINDIR}") +set_variable_from_rel_or_absolute_path("mandir" "\\\${prefix}" "${CMAKE_INSTALL_MANDIR}") +set_variable_from_rel_or_absolute_path("docdir" "\\\${prefix}" "${CMAKE_INSTALL_DOCDIR}") +set_variable_from_rel_or_absolute_path("libdir" "\\\${prefix}" "${CMAKE_INSTALL_LIBDIR}") +set_variable_from_rel_or_absolute_path("includedir" "\\\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}/${OPENJPEG_INSTALL_SUBDIR}") + +# install in lib and not share (CMAKE_INSTALL_LIBDIR takes care of it for multi-arch) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjp2/libopenjp2.pc.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/libopenjp2.pc @ONLY) +install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libopenjp2.pc DESTINATION + ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) +# +if(BUILD_JPIP) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/lib/openjpip/libopenjpip.pc.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/libopenjpip.pc @ONLY) + install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libopenjpip.pc DESTINATION + ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) +endif() + +#----------------------------------------------------------------------------- + +# build our version of astyle +SET (WITH_ASTYLE FALSE CACHE BOOL "If you plan to contribute you should reindent with scripts/prepare-commit.sh (using 'our' astyle)") diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000000..e8fa41040df --- /dev/null +++ b/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/README.md b/README.md new file mode 100644 index 00000000000..75ba171048e --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ + +# OPENJPEG Library and Applications + +## What is OpenJPEG ? + +OpenJPEG is an open-source JPEG 2000 codec written in C language. It has been developed in order to promote the use of [JPEG 2000](http://www.jpeg.org/jpeg2000), a still-image compression standard from the Joint Photographic Experts Group ([JPEG](http://www.jpeg.org)). Since April 2015, it is officially recognized by ISO/IEC and ITU-T as a [JPEG 2000 Reference Software](http://www.itu.int/rec/T-REC-T.804-201504-I!Amd2). + +## Who can use the code ? +[![badge-license]][link-license] + +Anyone. As the OpenJPEG code is released under the [BSD 2-clause "Simplified" License][link-license], anyone can use or modify the code, even for commercial applications. The only restriction is to retain the copyright in the sources or in the binaries documentation. Of course, if you modified the code in a way that might be of interest for other users, you are encouraged to share it (through a [github pull request](https://github.com/uclouvain/openjpeg/pulls) or by filling an [issue](https://github.com/uclouvain/openjpeg/issues)) but this is not a requirement. + +## How to install and use OpenJPEG ? +API Documentation needs a major refactoring. Meanwhile, you can check [installation](https://github.com/uclouvain/openjpeg/wiki/Installation) instructions and [codec documentation](https://github.com/uclouvain/openjpeg/wiki/DocJ2KCodec). + +## Current Status +[![badge-build]][link-build] + +[![badge-msvc-build]][link-msvc-build] + +[![badge-coverity]][link-coverity] + +## Who are the developers ? + +The library is developed and maintained by the Image and Signal Processing Group ([ISPGroup](http://sites.uclouvain.be/ispgroup/)), in the Université catholique de Louvain ([UCL](http://www.uclouvain.be/en-index.html), with the support of the [CNES](https://cnes.fr/), the [CS](http://www.c-s.fr/) company and the [intoPIX](http://www.intopix.com) company. The JPWL module has been developed by the Digital Signal Processing Lab ([DSPLab](http://dsplab.diei.unipg.it/)) of the University of Perugia, Italy ([UNIPG](http://www.unipg.it/)). + +## Details on folders hierarchy + +* src + * lib + * openjp2: contains the sources of the openjp2 library (Part 1 & 2) + * openjpip: complete client-server architecture for remote browsing of jpeg 2000 images. + * bin: contains all applications that use the openjpeg library + * common: common files to all applications + * jp2: a basic codec + * jpip: OpenJPIP applications (server and dec server) + * java: a Java client viewer for JPIP + * wx + * OPJViewer: gui for displaying j2k files (based on wxWidget) +* wrapping + * java: java jni to use openjpeg in a java program +* thirdparty: thirdparty libraries used by some applications. These libraries will be built only if there are not found on the system. Note that libopenjpeg itself does not have any dependency. +* doc: doxygen documentation setup file and man pages +* tests: configuration files and utilities for the openjpeg test suite. All test images are located in [openjpeg-data](https://github.com/uclouvain/openjpeg-data) repository. +* cmake: cmake related files +* scripts: scripts for developers + +See [LICENSE][link-license] for license and copyright information. + +See [INSTALL](https://github.com/uclouvain/openjpeg/blob/master/INSTALL.md) for installation procedures. + +See [NEWS](https://github.com/uclouvain/openjpeg/blob/master/NEWS.md) for user visible changes in successive releases. + +## Deprecated components + +The openjpwl, openjp3d and openmj2 components have been removed after the +2.4.0 release. Their building and working state is unknown. People interested +in them should start from the 2.4.0 tag. + +## API/ABI + +An API/ABI timeline is automatically updated [here][link-api-timeline]. + +OpenJPEG strives to provide a stable API/ABI for your applications. As such it +only exposes a limited subset of its functions. It uses a mechanism of +exporting/hiding functions. If you are unsure which functions you can use in +your applications, you should compile OpenJPEG using something similar to gcc: +`-fvisibility=hidden` compilation flag. +See also: http://gcc.gnu.org/wiki/Visibility + +On windows, MSVC directly supports export/hiding function and as such the only +API available is the one supported by OpenJPEG. + +[comment-license]: https://img.shields.io/github/license/uclouvain/openjpeg.svg "https://img.shields.io/badge/license-BSD--2--Clause-blue.svg" +[badge-license]: https://img.shields.io/badge/license-BSD--2--Clause-blue.svg "BSD 2-clause \"Simplified\" License" +[link-license]: https://github.com/uclouvain/openjpeg/blob/master/LICENSE "BSD 2-clause \"Simplified\" License" +[badge-build]: https://github.com/uclouvain/openjpeg/actions/workflows/build.yml/badge.svg "Build Status" +[link-build]: https://github.com/uclouvain/openjpeg/actions/workflows/build.yml "Build Status" +[badge-msvc-build]: https://ci.appveyor.com/api/projects/status/github/uclouvain/openjpeg?branch=master&svg=true "Windows Build Status" +[link-msvc-build]: https://ci.appveyor.com/project/detonin/openjpeg/branch/master "Windows Build Status" +[badge-coverity]: https://scan.coverity.com/projects/6383/badge.svg "Coverity Scan Build Status" +[link-coverity]: https://scan.coverity.com/projects/uclouvain-openjpeg "Coverity Scan Build Status" +[link-api-timeline]: http://www.openjpeg.org/abi-check/timeline/openjpeg "OpenJPEG API/ABI timeline" diff --git a/cmake/EnsureFileInclude.cmake b/cmake/EnsureFileInclude.cmake new file mode 100644 index 00000000000..a4c064bbeca --- /dev/null +++ b/cmake/EnsureFileInclude.cmake @@ -0,0 +1,26 @@ +# Ensure that an include file is provided by the system +# Add the check about the mandatory status to the check_include_file macro +# provided by cmake + +include (${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake) + +macro(ensure_file_include INCLUDE_FILENAME VARIABLE_NAME MANDATORY_STATUS) + +#message(WARNING "INCLUDE_FILENAME=${INCLUDE_FILENAME} \n" +# "VARIABLE_NAME=${VARIABLE_NAME} \n" +# "MANDATORY_STATUS=${MANDATORY_STATUS}") + +CHECK_INCLUDE_FILE(${INCLUDE_FILENAME} ${VARIABLE_NAME}) + +#message(WARNING "INCLUDE_FILENAME=${INCLUDE_FILENAME} \n" +# "VARIABLE_NAME=${VARIABLE_NAME} \n" +# "VARIABLE_NAME_VALUE=${${VARIABLE_NAME}} \n" +# "MANDATORY_STATUS=${MANDATORY_STATUS}") + +if (NOT ${${VARIABLE_NAME}}) + if (${MANDATORY_STATUS}) + message(FATAL_ERROR "The file ${INCLUDE_FILENAME} is mandatory but not found on your system") + endif() +endif() + +endmacro() diff --git a/cmake/TestLargeFiles.cmake b/cmake/TestLargeFiles.cmake new file mode 100644 index 00000000000..01e4ea70f77 --- /dev/null +++ b/cmake/TestLargeFiles.cmake @@ -0,0 +1,134 @@ +# - Define macro to check large file support +# +# OPJ_TEST_LARGE_FILES(VARIABLE) +# +# VARIABLE will be set to true if off_t is 64 bits, and fseeko/ftello present. +# This macro will also defines the necessary variable enable large file support, for instance +# _LARGE_FILES +# _LARGEFILE_SOURCE +# _FILE_OFFSET_BITS 64 +# OPJ_HAVE_FSEEKO +# +# However, it is YOUR job to make sure these defines are set in a #cmakedefine so they +# end up in a config.h file that is included in your source if necessary! +# +# Adapted from Gromacs project (http://www.gromacs.org/) +# by Julien Malik +# + +macro(OPJ_TEST_LARGE_FILES VARIABLE) + if(NOT DEFINED ${VARIABLE}) + + # On most platforms it is probably overkill to first test the flags for 64-bit off_t, + # and then separately fseeko. However, in the future we might have 128-bit filesystems + # (ZFS), so it might be dangerous to indiscriminately set e.g. _FILE_OFFSET_BITS=64. + + message(STATUS "Checking for 64-bit off_t") + + # First check without any special flags + try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c") + if(FILE64_OK) + message(STATUS "Checking for 64-bit off_t - present") + endif() + + if(NOT FILE64_OK) + # Test with _FILE_OFFSET_BITS=64 + try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c" + COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" ) + if(FILE64_OK) + message(STATUS "Checking for 64-bit off_t - present with _FILE_OFFSET_BITS=64") + set(_FILE_OFFSET_BITS 64) + endif() + endif() + + if(NOT FILE64_OK) + # Test with _LARGE_FILES + try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c" + COMPILE_DEFINITIONS "-D_LARGE_FILES" ) + if(FILE64_OK) + message(STATUS "Checking for 64-bit off_t - present with _LARGE_FILES") + set(_LARGE_FILES 1) + endif() + endif() + + if(NOT FILE64_OK) + # Test with _LARGEFILE_SOURCE + try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/cmake/TestFileOffsetBits.c" + COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" ) + if(FILE64_OK) + message(STATUS "Checking for 64-bit off_t - present with _LARGEFILE_SOURCE") + set(_LARGEFILE_SOURCE 1) + endif() + endif() + + + #if(NOT FILE64_OK) + # # now check for Windows stuff + # try_compile(FILE64_OK "${PROJECT_BINARY_DIR}" + # "${PROJECT_SOURCE_DIR}/cmake/TestWindowsFSeek.c") + # if(FILE64_OK) + # message(STATUS "Checking for 64-bit off_t - present with _fseeki64") + # set(HAVE__FSEEKI64 1) + # endif() + #endif() + + if(NOT FILE64_OK) + message(STATUS "Checking for 64-bit off_t - not present") + endif() + + set(_FILE_OFFSET_BITS ${_FILE_OFFSET_BITS} CACHE INTERNAL "Result of test for needed _FILE_OFFSET_BITS=64") + set(_LARGE_FILES ${_LARGE_FILES} CACHE INTERNAL "Result of test for needed _LARGE_FILES") + set(_LARGEFILE_SOURCE ${_LARGEFILE_SOURCE} CACHE INTERNAL "Result of test for needed _LARGEFILE_SOURCE") + + # Set the flags we might have determined to be required above + configure_file("${PROJECT_SOURCE_DIR}/cmake/TestLargeFiles.c.cmake.in" + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") + + message(STATUS "Checking for fseeko/ftello") + + # Test if ftello/fseeko are available + try_compile(FSEEKO_COMPILE_OK + "${PROJECT_BINARY_DIR}" + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c") + + if(FSEEKO_COMPILE_OK) + message(STATUS "Checking for fseeko/ftello - present") + endif() + + if(NOT FSEEKO_COMPILE_OK) + # glibc 2.2 needs _LARGEFILE_SOURCE for fseeko (but not for 64-bit off_t...) + try_compile(FSEEKO_COMPILE_OK + "${PROJECT_BINARY_DIR}" + "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestLargeFiles.c" + COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE" ) + + if(FSEEKO_COMPILE_OK) + message(STATUS "Checking for fseeko/ftello - present with _LARGEFILE_SOURCE") + set(_LARGEFILE_SOURCE ${_LARGEFILE_SOURCE} CACHE INTERNAL "Result of test for needed _LARGEFILE_SOURCE") + endif() + endif() + + if(FSEEKO_COMPILE_OK) + set(OPJ_HAVE_FSEEKO ON CACHE INTERNAL "Result of test for fseeko/ftello") + else() + message(STATUS "Checking for fseeko/ftello - not found") + set(OPJ_HAVE_FSEEKO OFF CACHE INTERNAL "Result of test for fseeko/ftello") + endif() + + if(FILE64_OK AND FSEEKO_COMPILE_OK) + message(STATUS "Large File support - found") + set(${VARIABLE} ON CACHE INTERNAL "Result of test for large file support") + else() + message(STATUS "Large File support - not found") + set(${VARIABLE} OFF CACHE INTERNAL "Result of test for large file support") + endif() + + endif() +endmacro() + + + diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt new file mode 100644 index 00000000000..212d92206eb --- /dev/null +++ b/src/lib/CMakeLists.txt @@ -0,0 +1,7 @@ +# source code for openjpeg project: +# Part 1 & 2: +add_subdirectory(openjp2) + +if(BUILD_JPIP) + add_subdirectory(openjpip) +endif() diff --git a/src/lib/openjp2/CMakeLists.txt b/src/lib/openjp2/CMakeLists.txt new file mode 100644 index 00000000000..99cf580a4d1 --- /dev/null +++ b/src/lib/openjp2/CMakeLists.txt @@ -0,0 +1,218 @@ +include_regular_expression("^.*$") + +# +install( FILES ${CMAKE_CURRENT_BINARY_DIR}/opj_config.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${OPENJPEG_INSTALL_SUBDIR} COMPONENT Headers) + +include_directories( + ${${OPENJPEG_NAMESPACE}_BINARY_DIR}/src/lib/openjp2 # opj_config.h and opj_config_private.h +) +# Defines the source code for the library +set(OPENJPEG_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/thread.c + ${CMAKE_CURRENT_SOURCE_DIR}/thread.h + ${CMAKE_CURRENT_SOURCE_DIR}/bio.c + ${CMAKE_CURRENT_SOURCE_DIR}/bio.h + ${CMAKE_CURRENT_SOURCE_DIR}/cio.c + ${CMAKE_CURRENT_SOURCE_DIR}/cio.h + ${CMAKE_CURRENT_SOURCE_DIR}/dwt.c + ${CMAKE_CURRENT_SOURCE_DIR}/dwt.h + ${CMAKE_CURRENT_SOURCE_DIR}/event.c + ${CMAKE_CURRENT_SOURCE_DIR}/event.h + ${CMAKE_CURRENT_SOURCE_DIR}/ht_dec.c + ${CMAKE_CURRENT_SOURCE_DIR}/image.c + ${CMAKE_CURRENT_SOURCE_DIR}/image.h + ${CMAKE_CURRENT_SOURCE_DIR}/invert.c + ${CMAKE_CURRENT_SOURCE_DIR}/invert.h + ${CMAKE_CURRENT_SOURCE_DIR}/j2k.c + ${CMAKE_CURRENT_SOURCE_DIR}/j2k.h + ${CMAKE_CURRENT_SOURCE_DIR}/jp2.c + ${CMAKE_CURRENT_SOURCE_DIR}/jp2.h + ${CMAKE_CURRENT_SOURCE_DIR}/mct.c + ${CMAKE_CURRENT_SOURCE_DIR}/mct.h + ${CMAKE_CURRENT_SOURCE_DIR}/mqc.c + ${CMAKE_CURRENT_SOURCE_DIR}/mqc.h + ${CMAKE_CURRENT_SOURCE_DIR}/mqc_inl.h + ${CMAKE_CURRENT_SOURCE_DIR}/openjpeg.c + ${CMAKE_CURRENT_SOURCE_DIR}/openjpeg.h + ${CMAKE_CURRENT_SOURCE_DIR}/opj_clock.c + ${CMAKE_CURRENT_SOURCE_DIR}/opj_clock.h + ${CMAKE_CURRENT_SOURCE_DIR}/pi.c + ${CMAKE_CURRENT_SOURCE_DIR}/pi.h + ${CMAKE_CURRENT_SOURCE_DIR}/t1.c + ${CMAKE_CURRENT_SOURCE_DIR}/t1.h + ${CMAKE_CURRENT_SOURCE_DIR}/t2.c + ${CMAKE_CURRENT_SOURCE_DIR}/t2.h + ${CMAKE_CURRENT_SOURCE_DIR}/tcd.c + ${CMAKE_CURRENT_SOURCE_DIR}/tcd.h + ${CMAKE_CURRENT_SOURCE_DIR}/tgt.c + ${CMAKE_CURRENT_SOURCE_DIR}/tgt.h + ${CMAKE_CURRENT_SOURCE_DIR}/function_list.c + ${CMAKE_CURRENT_SOURCE_DIR}/function_list.h + ${CMAKE_CURRENT_SOURCE_DIR}/opj_codec.h + ${CMAKE_CURRENT_SOURCE_DIR}/opj_includes.h + ${CMAKE_CURRENT_SOURCE_DIR}/opj_intmath.h + ${CMAKE_CURRENT_SOURCE_DIR}/opj_malloc.c + ${CMAKE_CURRENT_SOURCE_DIR}/opj_malloc.h + ${CMAKE_CURRENT_SOURCE_DIR}/sparse_array.c + ${CMAKE_CURRENT_SOURCE_DIR}/sparse_array.h +) +if(BUILD_JPIP) + add_definitions(-DUSE_JPIP) + set(OPENJPEG_SRCS + ${OPENJPEG_SRCS} + ${CMAKE_CURRENT_SOURCE_DIR}/cidx_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/cidx_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/phix_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/ppix_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/thix_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/tpix_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/indexbox_manager.h + ) +endif() + +option(OPJ_DISABLE_TPSOT_FIX "Disable TPsot==TNsot fix. See https://github.com/uclouvain/openjpeg/issues/254." OFF) +if(OPJ_DISABLE_TPSOT_FIX) + add_definitions(-DOPJ_DISABLE_TPSOT_FIX) +endif() + +# Special case for old i586-mingw32msvc-gcc cross compiler +if(NOT WIN32 AND CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER MATCHES ".*mingw32msvc.*" ) + set(WIN32 YES) +endif() + +# Build the library +if(WIN32) + if(BUILD_SHARED_LIBS) + add_definitions(-DOPJ_EXPORTS) + else() + add_definitions(-DOPJ_STATIC) + endif() + add_library(${OPENJPEG_LIBRARY_NAME} ${OPENJPEG_SRCS}) + set(INSTALL_LIBS ${OPENJPEG_LIBRARY_NAME}) +else() + if(BUILD_SHARED_LIBS AND BUILD_STATIC_LIBS) + # Builds both static and dynamic libs + add_library(${OPENJPEG_LIBRARY_NAME} SHARED ${OPENJPEG_SRCS}) + add_library(openjp2_static STATIC ${OPENJPEG_SRCS}) + set_target_properties(openjp2_static PROPERTIES OUTPUT_NAME ${OPENJPEG_LIBRARY_NAME}) + set(INSTALL_LIBS ${OPENJPEG_LIBRARY_NAME} openjp2_static) + target_include_directories(openjp2_static PUBLIC $) + else() + add_library(${OPENJPEG_LIBRARY_NAME} ${OPENJPEG_SRCS}) + set(INSTALL_LIBS ${OPENJPEG_LIBRARY_NAME}) + endif() +endif() + +target_include_directories(${OPENJPEG_LIBRARY_NAME} PUBLIC $) +if(UNIX) + target_link_libraries(${OPENJPEG_LIBRARY_NAME} m) +endif() +set_target_properties(${OPENJPEG_LIBRARY_NAME} PROPERTIES ${OPENJPEG_LIBRARY_PROPERTIES}) +target_compile_options(${OPENJPEG_LIBRARY_NAME} PRIVATE ${OPENJP2_COMPILE_OPTIONS}) + +# Install library +install(TARGETS ${INSTALL_LIBS} + EXPORT OpenJPEGTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Applications + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Libraries + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Libraries +) + +# Install includes files +install(FILES openjpeg.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${OPENJPEG_INSTALL_SUBDIR} COMPONENT Headers +) + +if(BUILD_DOC) +# install man page of the library +install( + FILES ${OPENJPEG_SOURCE_DIR}/doc/man/man3/libopenjp2.3 + DESTINATION ${CMAKE_INSTALL_MANDIR}/man3) +endif() + +if(BUILD_LUTS_GENERATOR) +# internal utility to generate t1_luts.h and t1_ht_luts.h (part of the jp2 lib) +# no need to install: + add_executable(t1_generate_luts t1_generate_luts.c t1_ht_generate_luts.c) + if(UNIX) + target_link_libraries(t1_generate_luts m) + endif() +endif() + +# Experimental option; let's how cppcheck performs +# Implementation details: +# I could not figure out how to easily upload a file to CDash. Instead simply +# pretend cppcheck is part of the Build step. Technically cppcheck can even +# output gcc formatted error/warning report +# Another implementation detail: I could not redirect error to the error +# catching mechanism something is busted in cmake 2.8.5, I had to use the +# warning regex to catch them. +if(OPENJPEG_CPPCHECK) + find_package(CPPCHECK REQUIRED) + foreach(f ${OPENJPEG_SRCS}) + # cppcheck complains about too many configuration, pretend to be WIN32: + add_custom_command(TARGET ${OPENJPEG_LIBRARY_NAME} + COMMAND ${CPPCHECK_EXECUTABLE} -DWIN32 ${f}) + endforeach() +endif() + +if(OPJ_USE_DSYMUTIL) + if(BUILD_SHARED_LIBS) + add_custom_command(TARGET ${OPENJPEG_LIBRARY_NAME} POST_BUILD + COMMAND "dsymutil" "$" + COMMENT "dsymutil $" + DEPENDS ${OPENJPEG_LIBRARY_NAME}) + endif() +endif() + +################################################################################# +# threading configuration +################################################################################# +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) + +option(OPJ_USE_THREAD "Build with thread/mutex support " ON) +if(NOT OPJ_USE_THREAD) + add_definitions( -DMUTEX_stub) +endif(NOT OPJ_USE_THREAD) + +find_package(Threads QUIET) + +if(OPJ_USE_THREAD AND WIN32 AND NOT Threads_FOUND ) + add_definitions( -DMUTEX_win32) + set(Threads_FOUND YES) +endif() + +if(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_WIN32_THREADS_INIT ) + add_definitions( -DMUTEX_win32) +endif(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_WIN32_THREADS_INIT ) + +if(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT ) + add_definitions( -DMUTEX_pthread) +endif(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT ) + +if(OPJ_USE_THREAD AND NOT Threads_FOUND) + message(FATAL_ERROR "No thread library found and thread/mutex support is required by OPJ_USE_THREAD option") +endif(OPJ_USE_THREAD AND NOT Threads_FOUND) + +if(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) + TARGET_LINK_LIBRARIES(${OPENJPEG_LIBRARY_NAME} ${CMAKE_THREAD_LIBS_INIT}) +endif(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) + +if(BUILD_UNIT_TESTS AND UNIX) + add_executable(bench_dwt bench_dwt.c) + if(UNIX) + target_link_libraries(bench_dwt m ${OPENJPEG_LIBRARY_NAME}) + endif() + if(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) + target_link_libraries(bench_dwt ${CMAKE_THREAD_LIBS_INIT}) + endif(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) + + add_executable(test_sparse_array test_sparse_array.c) + if(UNIX) + target_link_libraries(test_sparse_array m ${OPENJPEG_LIBRARY_NAME}) + endif() + if(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) + target_link_libraries(test_sparse_array ${CMAKE_THREAD_LIBS_INIT}) + endif(OPJ_USE_THREAD AND Threads_FOUND AND CMAKE_USE_PTHREADS_INIT) +endif(BUILD_UNIT_TESTS AND UNIX) diff --git a/src/lib/openjp2/bench_dwt.c b/src/lib/openjp2/bench_dwt.c new file mode 100644 index 00000000000..4f2ea9fbd11 --- /dev/null +++ b/src/lib/openjp2/bench_dwt.c @@ -0,0 +1,353 @@ +/* + * 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" + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif /* _WIN32 */ + +OPJ_INT32 getValue(OPJ_UINT32 i) +{ + return ((OPJ_INT32)i % 511) - 256; +} + +void init_tilec(opj_tcd_tilecomp_t * l_tilec, + OPJ_INT32 x0, + OPJ_INT32 y0, + OPJ_INT32 x1, + OPJ_INT32 y1, + OPJ_UINT32 numresolutions, + OPJ_BOOL irreversible) +{ + opj_tcd_resolution_t* l_res; + OPJ_UINT32 resno, l_level_no; + size_t i, nValues; + + memset(l_tilec, 0, sizeof(*l_tilec)); + l_tilec->x0 = x0; + l_tilec->y0 = y0; + l_tilec->x1 = x1; + l_tilec->y1 = y1; + nValues = (size_t)(l_tilec->x1 - l_tilec->x0) * + (size_t)(l_tilec->y1 - l_tilec->y0); + l_tilec->data = (OPJ_INT32*) opj_malloc(sizeof(OPJ_INT32) * nValues); + for (i = 0; i < nValues; i++) { + OPJ_INT32 val = getValue((OPJ_UINT32)i); + if (irreversible) { + OPJ_FLOAT32 fVal = (OPJ_FLOAT32)val; + memcpy(&l_tilec->data[i], &fVal, sizeof(OPJ_FLOAT32)); + } else { + l_tilec->data[i] = val; + } + } + l_tilec->numresolutions = numresolutions; + l_tilec->minimum_num_resolutions = numresolutions; + l_tilec->resolutions = (opj_tcd_resolution_t*) opj_calloc( + l_tilec->numresolutions, + sizeof(opj_tcd_resolution_t)); + + l_level_no = l_tilec->numresolutions; + l_res = l_tilec->resolutions; + + /* Adapted from opj_tcd_init_tile() */ + for (resno = 0; resno < l_tilec->numresolutions; ++resno) { + + --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); + + ++l_res; + } +} + +void free_tilec(opj_tcd_tilecomp_t * l_tilec) +{ + opj_free(l_tilec->data); + opj_free(l_tilec->resolutions); +} + +void usage(void) +{ + printf( + "bench_dwt [-decode|encode] [-I] [-size value] [-check] [-display]\n"); + printf( + " [-num_resolutions val] [-offset x y] [-num_threads val]\n"); + exit(1); +} + + +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 freq.QuadPart ? (t.QuadPart / (OPJ_FLOAT64) freq.QuadPart) : 0 ; +#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 +} + +static OPJ_FLOAT64 opj_wallclock(void) +{ +#ifdef _WIN32 + return opj_clock(); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return (OPJ_FLOAT64)tv.tv_sec + 1e-6 * (OPJ_FLOAT64)tv.tv_usec; +#endif +} + +int main(int argc, char** argv) +{ + int num_threads = 0; + opj_tcd_t tcd; + opj_tcd_image_t tcd_image; + opj_tcd_tile_t tcd_tile; + opj_tcd_tilecomp_t tilec; + opj_image_t image; + opj_image_comp_t image_comp; + opj_thread_pool_t* tp; + OPJ_INT32 i, j, k; + OPJ_BOOL display = OPJ_FALSE; + OPJ_BOOL check = OPJ_FALSE; + OPJ_INT32 size = 16384 - 1; + OPJ_FLOAT64 start, stop; + OPJ_FLOAT64 start_wc, stop_wc; + OPJ_UINT32 offset_x = ((OPJ_UINT32)size + 1) / 2 - 1; + OPJ_UINT32 offset_y = ((OPJ_UINT32)size + 1) / 2 - 1; + OPJ_UINT32 num_resolutions = 6; + OPJ_BOOL bench_decode = OPJ_TRUE; + OPJ_BOOL irreversible = OPJ_FALSE; + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-encode") == 0) { + bench_decode = OPJ_FALSE; + } else if (strcmp(argv[i], "-decode") == 0) { + bench_decode = OPJ_TRUE; + } else if (strcmp(argv[i], "-display") == 0) { + display = OPJ_TRUE; + } else if (strcmp(argv[i], "-check") == 0) { + check = OPJ_TRUE; + } else if (strcmp(argv[i], "-I") == 0) { + irreversible = OPJ_TRUE; + } else if (strcmp(argv[i], "-size") == 0 && i + 1 < argc) { + size = atoi(argv[i + 1]); + i ++; + } else if (strcmp(argv[i], "-num_threads") == 0 && i + 1 < argc) { + num_threads = atoi(argv[i + 1]); + i ++; + } else if (strcmp(argv[i], "-num_resolutions") == 0 && i + 1 < argc) { + num_resolutions = (OPJ_UINT32)atoi(argv[i + 1]); + if (num_resolutions == 0 || num_resolutions > 32) { + fprintf(stderr, + "Invalid value for num_resolutions. Should be >= 1 and <= 32\n"); + exit(1); + } + i ++; + } else if (strcmp(argv[i], "-offset") == 0 && i + 2 < argc) { + offset_x = (OPJ_UINT32)atoi(argv[i + 1]); + offset_y = (OPJ_UINT32)atoi(argv[i + 2]); + i += 2; + } else { + usage(); + } + } + + if (irreversible && check) { + /* Due to irreversible inverse DWT not being symmetric of forward */ + /* See BUG_WEIRD_TWO_INVK in dwt.c */ + printf("-I and -check aren't compatible\n"); + exit(1); + } + + tp = opj_thread_pool_create(num_threads); + + init_tilec(&tilec, (OPJ_INT32)offset_x, (OPJ_INT32)offset_y, + (OPJ_INT32)offset_x + size, (OPJ_INT32)offset_y + size, + num_resolutions, irreversible); + + if (display) { + printf("Before\n"); + k = 0; + for (j = 0; j < tilec.y1 - tilec.y0; j++) { + for (i = 0; i < tilec.x1 - tilec.x0; i++) { + if (irreversible) { + printf("%f ", ((OPJ_FLOAT32*)tilec.data)[k]); + } else { + printf("%d ", tilec.data[k]); + } + k ++; + } + printf("\n"); + } + } + + memset(&tcd, 0, sizeof(tcd)); + tcd.thread_pool = tp; + tcd.whole_tile_decoding = OPJ_TRUE; + tcd.win_x0 = (OPJ_UINT32)tilec.x0; + tcd.win_y0 = (OPJ_UINT32)tilec.y0; + tcd.win_x1 = (OPJ_UINT32)tilec.x1; + tcd.win_y1 = (OPJ_UINT32)tilec.y1; + tcd.tcd_image = &tcd_image; + memset(&tcd_image, 0, sizeof(tcd_image)); + tcd_image.tiles = &tcd_tile; + memset(&tcd_tile, 0, sizeof(tcd_tile)); + tcd_tile.x0 = tilec.x0; + tcd_tile.y0 = tilec.y0; + tcd_tile.x1 = tilec.x1; + tcd_tile.y1 = tilec.y1; + tcd_tile.numcomps = 1; + tcd_tile.comps = &tilec; + tcd.image = ℑ + memset(&image, 0, sizeof(image)); + image.numcomps = 1; + image.comps = &image_comp; + memset(&image_comp, 0, sizeof(image_comp)); + image_comp.dx = 1; + image_comp.dy = 1; + + start = opj_clock(); + start_wc = opj_wallclock(); + if (bench_decode) { + if (irreversible) { + opj_dwt_decode_real(&tcd, &tilec, tilec.numresolutions); + } else { + opj_dwt_decode(&tcd, &tilec, tilec.numresolutions); + } + } else { + if (irreversible) { + opj_dwt_encode_real(&tcd, &tilec); + } else { + opj_dwt_encode(&tcd, &tilec); + } + } + stop = opj_clock(); + stop_wc = opj_wallclock(); + printf("time for %s: total = %.03f s, wallclock = %.03f s\n", + bench_decode ? "dwt_decode" : "dwt_encode", + stop - start, + stop_wc - start_wc); + + if (display) { + if (bench_decode) { + printf("After IDWT\n"); + } else { + printf("After FDWT\n"); + } + k = 0; + for (j = 0; j < tilec.y1 - tilec.y0; j++) { + for (i = 0; i < tilec.x1 - tilec.x0; i++) { + if (irreversible) { + printf("%f ", ((OPJ_FLOAT32*)tilec.data)[k]); + } else { + printf("%d ", tilec.data[k]); + } + k ++; + } + printf("\n"); + } + } + + if ((display || check) && !irreversible) { + + if (bench_decode) { + opj_dwt_encode(&tcd, &tilec); + } else { + opj_dwt_decode(&tcd, &tilec, tilec.numresolutions); + } + + + if (display && !irreversible) { + if (bench_decode) { + printf("After FDWT\n"); + } else { + printf("After IDWT\n"); + } + k = 0; + for (j = 0; j < tilec.y1 - tilec.y0; j++) { + for (i = 0; i < tilec.x1 - tilec.x0; i++) { + if (irreversible) { + printf("%f ", ((OPJ_FLOAT32*)tilec.data)[k]); + } else { + printf("%d ", tilec.data[k]); + } + k ++; + } + printf("\n"); + } + } + + } + + if (check) { + + size_t idx; + size_t nValues = (size_t)(tilec.x1 - tilec.x0) * + (size_t)(tilec.y1 - tilec.y0); + for (idx = 0; idx < nValues; idx++) { + if (tilec.data[idx] != getValue((OPJ_UINT32)idx)) { + printf("Difference found at idx = %u\n", (OPJ_UINT32)idx); + exit(1); + } + } + } + + free_tilec(&tilec); + + opj_thread_pool_destroy(tp); + return 0; +} diff --git a/src/lib/openjp2/bio.c b/src/lib/openjp2/bio.c new file mode 100644 index 00000000000..8106df754ed --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/bio.h b/src/lib/openjp2/bio.h new file mode 100644 index 00000000000..d482f9ead5a --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/cidx_manager.c b/src/lib/openjp2/cidx_manager.c new file mode 100644 index 00000000000..c273f9a0fca --- /dev/null +++ b/src/lib/openjp2/cidx_manager.c @@ -0,0 +1,259 @@ +/* + * $Id: cidx_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * 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" + + +/* + * Write CPTR Codestream finder box + * + * @param[in] coff offset of j2k codestream + * @param[in] clen length of j2k codestream + * @param[in] cio file output handle + */ + +void opj_write_cptr(int coff, int clen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + + + + + +int opj_write_cidx(int offset, opj_stream_private_t *cio, + opj_codestream_info_t cstr_info, int j2klen, + opj_event_mgr_t * p_manager) +{ + int i; + OPJ_OFF_T lenp; + OPJ_UINT32 len; + opj_jp2_box_t *box; + int num_box = 0; + OPJ_BOOL EPHused; + OPJ_BYTE l_data_header [4]; + + lenp = -1; + box = (opj_jp2_box_t *)opj_calloc(32, sizeof(opj_jp2_box_t)); + if (box == NULL) { + return 0; + } + for (i = 0; i < 2; i++) { + + if (i) { + opj_stream_seek(cio, lenp, p_manager); + } + + + lenp = opj_stream_tell(cio); + + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + + opj_write_bytes(l_data_header, JPIP_CIDX, 4); /* CIDX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + opj_write_cptr(offset, cstr_info.codestream_size, cio, p_manager); + + opj_write_manf(i, num_box, box, cio, p_manager); + + num_box = 0; + box[num_box].length = (OPJ_UINT32)opj_write_mainmhix(offset, cstr_info, cio, + p_manager); + box[num_box].type = JPIP_MHIX; + num_box++; + + box[num_box].length = (OPJ_UINT32)opj_write_tpix(offset, cstr_info, j2klen, cio, + p_manager); + box[num_box].type = JPIP_TPIX; + num_box++; + + box[num_box].length = (OPJ_UINT32)opj_write_thix(offset, cstr_info, cio, + p_manager); + box[num_box].type = JPIP_THIX; + num_box++; + + EPHused = opj_check_EPHuse(offset, cstr_info.marker, cstr_info.marknum, cio, + p_manager); + + box[num_box].length = (OPJ_UINT32)opj_write_ppix(offset, cstr_info, EPHused, + j2klen, cio, p_manager); + box[num_box].type = JPIP_PPIX; + num_box++; + + box[num_box].length = (OPJ_UINT32)opj_write_phix(offset, cstr_info, EPHused, + j2klen, cio, p_manager); + box[num_box].type = JPIP_PHIX; + num_box++; + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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); + } + + opj_free(box); + + return (int)len; +} + + + +void opj_write_cptr(int coff, int clen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [3 * 8]; + OPJ_UINT32 len; + OPJ_OFF_T lenp; + + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_CPTR, 4); /* T */ + opj_write_bytes(l_data_header + 4, 0, 2); /* DR A PRECISER !! */ + opj_write_bytes(l_data_header + 6, 0, 2); /* CONT */ + opj_write_bytes(l_data_header + 8, (OPJ_UINT32)coff, + 8); /* COFF A PRECISER !! */ + opj_write_bytes(l_data_header + 16, (OPJ_UINT32)clen, + 8); /* CLEN */ + opj_stream_write_data(cio, l_data_header, 3 * 8, p_manager); + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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); + +} + + + +void opj_write_manf(int second, + int v, + opj_jp2_box_t *box, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [4]; + int i; + OPJ_UINT32 len; + OPJ_OFF_T lenp; + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_MANF, 4); /* T */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + if (second) { /* Write only during the second pass */ + for (i = 0; i < v; i++) { + opj_write_bytes(l_data_header, box[i].length, + 4); /* Box length */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + opj_write_bytes(l_data_header, box[i].type, + 4); /* Box type */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + } + } + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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); +} + + +int opj_write_mainmhix(int coff, opj_codestream_info_t cstr_info, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [8]; + OPJ_UINT32 i; + OPJ_UINT32 len; + OPJ_OFF_T lenp; + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, + p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_MHIX, + 4); /* MHIX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + opj_write_bytes(l_data_header, + (OPJ_UINT32)(cstr_info.main_head_end - cstr_info.main_head_start + 1), + 8); /* TLEN */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + + for (i = 1; i < (OPJ_UINT32)cstr_info.marknum; + i++) { /* Marker restricted to 1 apparition, skip SOC marker */ + opj_write_bytes(l_data_header, cstr_info.marker[i].type, 2); + opj_write_bytes(l_data_header + 2, 0, 2); + opj_stream_write_data(cio, l_data_header, 4, p_manager); + opj_write_bytes(l_data_header, (OPJ_UINT32)(cstr_info.marker[i].pos - coff), 8); + opj_stream_write_data(cio, l_data_header, 8, p_manager); + opj_write_bytes(l_data_header, (OPJ_UINT32)cstr_info.marker[i].len, 2); + opj_stream_write_data(cio, l_data_header, 2, p_manager); + } + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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 (int)len; +} + +OPJ_BOOL opj_check_EPHuse(int coff, opj_marker_info_t *markers, int marknum, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [4]; + OPJ_BOOL EPHused = OPJ_FALSE; + int i = 0; + OPJ_OFF_T org_pos; + unsigned int Scod; + + for (i = 0; i < marknum; i++) { + if (markers[i].type == J2K_MS_COD) { + org_pos = opj_stream_tell(cio); + opj_stream_seek(cio, coff + markers[i].pos + 2, p_manager); + + opj_stream_read_data(cio, l_data_header, 1, p_manager); + opj_read_bytes(l_data_header, &Scod, 1); + if (((Scod >> 2) & 1)) { + EPHused = OPJ_TRUE; + } + opj_stream_seek(cio, org_pos, p_manager); + + break; + } + } + return EPHused; +} diff --git a/src/lib/openjp2/cidx_manager.h b/src/lib/openjp2/cidx_manager.h new file mode 100644 index 00000000000..a353252189c --- /dev/null +++ b/src/lib/openjp2/cidx_manager.h @@ -0,0 +1,70 @@ +/* + * $Id: cidx_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * 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. + */ + +/*! \file + * \brief Modification of jpip.h from 2KAN indexer + */ + + +#ifndef CIDX_MANAGER_H_ +# define CIDX_MANAGER_H_ + +#include "openjpeg.h" + + +/* + * Write Codestream index box (superbox) + * + * @param[in] offset offset of j2k codestream + * @param[in] cio file output handle + * @param[in] image image data + * @param[in] cstr_info codestream information + * @param[in] j2klen length of j2k codestream + * @return length of cidx box + */ +int opj_write_cidx(int offset, opj_stream_private_t *cio, + opj_codestream_info_t cstr_info, int j2klen, + opj_event_mgr_t * p_manager); + +/* + * Check if EPH option is used + * + * @param[in] coff offset of j2k codestream + * @param[in] markers marker information + * @param[in] marknum number of markers + * @param[in] cio file output handle + * @return true if EPH is used + */ +OPJ_BOOL opj_check_EPHuse(int coff, opj_marker_info_t *markers, int marknum, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +#endif /* !CIDX_MANAGER_H_ */ diff --git a/src/lib/openjp2/cio.c b/src/lib/openjp2/cio.c new file mode 100644 index 00000000000..4fde9fe239b --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/cio.h b/src/lib/openjp2/cio.h new file mode 100644 index 00000000000..7caee30af9c --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/dwt.c b/src/lib/openjp2/dwt.c new file mode 100644 index 00000000000..6b18c5dd6e9 --- /dev/null +++ b/src/lib/openjp2/dwt.c @@ -0,0 +1,3769 @@ +/* + * 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 +#ifdef __AVX2__ +#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)] + +#ifdef __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(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 + 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 + 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(STANDARD_SLOW_VERSION) + +/* Conveniency macros to improve the readability of the formulas */ +#if __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 __AVX2__ + assert(PARALLEL_COLS_53 == 16); + assert(VREG_INT_COUNT == 8); +#else + assert(PARALLEL_COLS_53 == 8); + assert(VREG_INT_COUNT == 4); +#endif + + /* 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); + + 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 __AVX2__ + assert(PARALLEL_COLS_53 == 16); + assert(VREG_INT_COUNT == 8); +#else + assert(PARALLEL_COLS_53 == 8); + assert(VREG_INT_COUNT == 4); +#endif + + /* 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); + + 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/src/lib/openjp2/dwt.h b/src/lib/openjp2/dwt.h new file mode 100644 index 00000000000..215061e6b9c --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/event.c b/src/lib/openjp2/event.c new file mode 100644 index 00000000000..aad9d76c98d --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/event.h b/src/lib/openjp2/event.h new file mode 100644 index 00000000000..d880388d074 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/function_list.c b/src/lib/openjp2/function_list.c new file mode 100644 index 00000000000..e1c1af3897c --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/function_list.h b/src/lib/openjp2/function_list.h new file mode 100644 index 00000000000..81a3954a163 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/ht_dec.c b/src/lib/openjp2/ht_dec.c new file mode 100644 index 00000000000..a554b24a6a2 --- /dev/null +++ b/src/lib/openjp2/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 cofficients 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 cofficients 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/src/lib/openjp2/image.c b/src/lib/openjp2/image.c new file mode 100644 index 00000000000..017201a002b --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/image.h b/src/lib/openjp2/image.h new file mode 100644 index 00000000000..bad83c61359 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/indexbox_manager.h b/src/lib/openjp2/indexbox_manager.h new file mode 100644 index 00000000000..238114bd133 --- /dev/null +++ b/src/lib/openjp2/indexbox_manager.h @@ -0,0 +1,157 @@ +/* + * $Id: indexbox_manager.h 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * 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. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#ifndef INDEXBOX_MANAGER_H_ +# define INDEXBOX_MANAGER_H_ + +#include "openjpeg.h" +#include "j2k.h" /* needed to use jp2.h */ +#include "jp2.h" + +#define JPIP_CIDX 0x63696478 /* Codestream index */ +#define JPIP_CPTR 0x63707472 /* Codestream Finder Box */ +#define JPIP_MANF 0x6d616e66 /* Manifest Box */ +#define JPIP_FAIX 0x66616978 /* Fragment array Index box */ +#define JPIP_MHIX 0x6d686978 /* Main Header Index Table */ +#define JPIP_TPIX 0x74706978 /* Tile-part Index Table box */ +#define JPIP_THIX 0x74686978 /* Tile header Index Table box */ +#define JPIP_PPIX 0x70706978 /* Precinct Packet Index Table box */ +#define JPIP_PHIX 0x70686978 /* Packet Header index Table */ +#define JPIP_FIDX 0x66696478 /* File Index */ +#define JPIP_FPTR 0x66707472 /* File Finder */ +#define JPIP_PRXY 0x70727879 /* Proxy boxes */ +#define JPIP_IPTR 0x69707472 /* Index finder box */ +#define JPIP_PHLD 0x70686c64 /* Place holder */ + + +/* + * Write tile-part Index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of tpix box + */ +int opj_write_tpix(int coff, opj_codestream_info_t cstr_info, int j2klen, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + + +/* + * Write tile header index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information pointer + * @param[in] cio file output handle + * @return length of thix box + */ +int opj_write_thix(int coff, opj_codestream_info_t cstr_info, + opj_stream_private_t *cio, opj_event_mgr_t * p_manager); + + +/* + * Write precinct packet index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] EPHused true if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of ppix box + */ +int opj_write_ppix(int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, + int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + + +/* + * Write packet header index table box (superbox) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] EPHused true if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of ppix box + */ +int opj_write_phix(int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, + int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/* + * Write manifest box (box) + * + * @param[in] second number to be visited + * @param[in] v number of boxes + * @param[in] box box to be manifested + * @param[in] cio file output handle + */ + +void opj_write_manf(int second, + int v, + opj_jp2_box_t *box, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +/* + * Write main header index table (box) + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] cio file output handle + * @return length of mainmhix box + */ +int opj_write_mainmhix(int coff, opj_codestream_info_t cstr_info, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +int opj_write_phixfaix(int coff, int compno, opj_codestream_info_t cstr_info, + OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +int opj_write_ppixfaix(int coff, int compno, opj_codestream_info_t cstr_info, + OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +int opj_write_tilemhix(int coff, opj_codestream_info_t cstr_info, int tileno, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +int opj_write_tpixfaix(int coff, int compno, opj_codestream_info_t cstr_info, + int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager); + +#endif /* !INDEXBOX_MANAGER_H_ */ diff --git a/src/lib/openjp2/invert.c b/src/lib/openjp2/invert.c new file mode 100644 index 00000000000..89f607155fd --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/invert.h b/src/lib/openjp2/invert.h new file mode 100644 index 00000000000..70402135593 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c new file mode 100644 index 00000000000..c0551870b2b --- /dev/null +++ b/src/lib/openjp2/j2k.c @@ -0,0 +1,13217 @@ +/* + * 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; + } + + 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_tot_num_tp_remaining, l_quotient, + l_Ptlm_size; + /* preconditions */ + assert(p_header_data != 00); + assert(p_j2k != 00); + assert(p_manager != 00); + + OPJ_UNUSED(p_j2k); + + if (p_header_size < 2) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); + return OPJ_FALSE; + } + p_header_size -= 2; + + 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); + l_SP = (l_Stlm >> 6) & 0x1; + + l_Ptlm_size = (l_SP + 1) * 2; + l_quotient = l_Ptlm_size + l_ST; + + l_tot_num_tp_remaining = p_header_size % l_quotient; + + if (l_tot_num_tp_remaining != 0) { + opj_event_msg(p_manager, EVT_ERROR, "Error reading TLM marker\n"); + return OPJ_FALSE; + } + /* FIXME Do not care of this at the moment since only local variables are set here */ + /* + for + (i = 0; i < l_tot_num_tp; ++i) + { + opj_read_bytes(p_header_data,&l_Ttlm_i,l_ST); // Ttlm_i + p_header_data += l_ST; + opj_read_bytes(p_header_data,&l_Ptlm_i,l_Ptlm_size); // Ptlm_i + p_header_data += l_Ptlm_size; + }*/ + 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 */ + if (p_j2k->cstr_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 (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; + } + } + + } + + } + + /* FIXME move this onto a separate method to call before reading any SOT, remove part about main_end header, use a index struct inside p_j2k */ + /* if (p_j2k->cstr_info) { + if (l_tcp->first) { + if (tileno == 0) { + p_j2k->cstr_info->main_head_end = p_stream_tell(p_stream) - 13; + } + + p_j2k->cstr_info->tile[tileno].tileno = tileno; + p_j2k->cstr_info->tile[tileno].start_pos = p_stream_tell(p_stream) - 12; + p_j2k->cstr_info->tile[tileno].end_pos = p_j2k->cstr_info->tile[tileno].start_pos + totlen - 1; + p_j2k->cstr_info->tile[tileno].num_tps = numparts; + + if (numparts) { + p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(numparts * sizeof(opj_tp_info_t)); + } + else { + p_j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(10 * sizeof(opj_tp_info_t)); // Fixme (10) + } + } + else { + p_j2k->cstr_info->tile[tileno].end_pos += totlen; + } + + p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = p_stream_tell(p_stream) - 12; + p_j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos = + p_j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1; + }*/ + 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; + if (l_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) { + 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; + } +} + +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; + 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) { + 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); + + /*Allocate and initialize some elements of codestrem index*/ + if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)) { + opj_image_destroy(*p_image); + *p_image = NULL; + return OPJ_FALSE; + } + + 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; +} + +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; + + /* 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; + + } 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)) { + + /* 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 -= (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; + } + 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; + + p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1; + 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; + } + + 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 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; + + /* 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 (! 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; + } + + 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 (! 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; + + /*Allocate and initialize some elements of codestrem index if not already done*/ + if (!p_j2k->cstr_index->tile_index) { + if (!opj_j2k_allocate_tile_element_cstr_index(p_j2k)) { + return OPJ_FALSE; + } + } + /* 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 { + if (!(opj_stream_read_seek(p_stream, + p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos + 2, + p_manager))) { + opj_event_msg(p_manager, EVT_ERROR, "Problem with seek function\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/src/lib/openjp2/j2k.h b/src/lib/openjp2/j2k.h new file mode 100644 index 00000000000..e0b9688a353 --- /dev/null +++ b/src/lib/openjp2/j2k.h @@ -0,0 +1,924 @@ +/* + * 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/src/lib/openjp2/jp2.c b/src/lib/openjp2/jp2.c new file mode 100644 index 00000000000..6015190e1f5 --- /dev/null +++ b/src/lib/openjp2/jp2.c @@ -0,0 +1,3414 @@ +/* + * 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; + } else { + jp2->meth = 1; + if (image->color_space == 1) { + jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2-1 */ + } else if (image->color_space == 2) { + jp2->enumcs = 17; /* greyscale */ + } else if (image->color_space == 3) { + jp2->enumcs = 18; /* YUV */ + } + } + + /* 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 (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/src/lib/openjp2/jp2.h b/src/lib/openjp2/jp2.h new file mode 100644 index 00000000000..173f25119ba --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/libopenjp2.pc.cmake.in b/src/lib/openjp2/libopenjp2.pc.cmake.in new file mode 100644 index 00000000000..2ade312b294 --- /dev/null +++ b/src/lib/openjp2/libopenjp2.pc.cmake.in @@ -0,0 +1,15 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +bindir=@bindir@ +mandir=@mandir@ +docdir=@docdir@ +libdir=@libdir@ +includedir=@includedir@ + +Name: openjp2 +Description: JPEG2000 library (Part 1 and 2) +URL: http://www.openjpeg.org/ +Version: @OPENJPEG_VERSION@ +Libs: -L${libdir} -lopenjp2 +Libs.private: -lm +Cflags: -I${includedir} +Cflags.private: -DOPJ_STATIC diff --git a/src/lib/openjp2/mct.c b/src/lib/openjp2/mct.c new file mode 100644 index 00000000000..7805812801a --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/mct.h b/src/lib/openjp2/mct.h new file mode 100644 index 00000000000..3e1f5e4946c --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/mqc.c b/src/lib/openjp2/mqc.c new file mode 100644 index 00000000000..ed118402382 --- /dev/null +++ b/src/lib/openjp2/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; + } + } + } +} diff --git a/src/lib/openjp2/mqc.h b/src/lib/openjp2/mqc.h new file mode 100644 index 00000000000..9850fed0316 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/mqc_inl.h b/src/lib/openjp2/mqc_inl.h new file mode 100644 index 00000000000..0031b94be31 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/openjpeg.c b/src/lib/openjp2/openjpeg.c new file mode 100644 index 00000000000..382d8f4f0f1 --- /dev/null +++ b/src/lib/openjp2/openjpeg.c @@ -0,0 +1,1144 @@ +/* + * 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. + */ + +#ifdef _WIN32 +#include +#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/src/lib/openjp2/openjpeg.h b/src/lib/openjp2/openjpeg.h new file mode 100644 index 00000000000..67d168bb578 --- /dev/null +++ b/src/lib/openjp2/openjpeg.h @@ -0,0 +1,1779 @@ +/* +* 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. If strict decoding is disabled, the decoder will decode partial + * bitstreams as much as possible without erroring + * + * @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. + * + * 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/src/lib/openjp2/opj_clock.c b/src/lib/openjp2/opj_clock.c new file mode 100644 index 00000000000..24f79a9ae75 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/opj_clock.h b/src/lib/openjp2/opj_clock.h new file mode 100644 index 00000000000..76366f53b50 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/opj_codec.h b/src/lib/openjp2/opj_codec.h new file mode 100644 index 00000000000..7cff6708246 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/opj_common.h b/src/lib/openjp2/opj_common.h new file mode 100644 index 00000000000..ee8adf4725c --- /dev/null +++ b/src/lib/openjp2/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_COMMMON_H +#define OPJ_COMMMON_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_COMMMON_H */ diff --git a/src/lib/openjp2/opj_config.h.cmake.in b/src/lib/openjp2/opj_config.h.cmake.in new file mode 100644 index 00000000000..64884b65248 --- /dev/null +++ b/src/lib/openjp2/opj_config.h.cmake.in @@ -0,0 +1,14 @@ +#ifndef OPJ_CONFIG_H_INCLUDED +#define OPJ_CONFIG_H_INCLUDED + +/* create opj_config.h for CMake */ + +/*--------------------------------------------------------------------------*/ +/* OpenJPEG Versioning */ + +/* Version number. */ +#define OPJ_VERSION_MAJOR @OPENJPEG_VERSION_MAJOR@ +#define OPJ_VERSION_MINOR @OPENJPEG_VERSION_MINOR@ +#define OPJ_VERSION_BUILD @OPENJPEG_VERSION_BUILD@ + +#endif diff --git a/src/lib/openjp2/opj_config_private.h.cmake.in b/src/lib/openjp2/opj_config_private.h.cmake.in new file mode 100644 index 00000000000..c559282c578 --- /dev/null +++ b/src/lib/openjp2/opj_config_private.h.cmake.in @@ -0,0 +1,50 @@ +/* create opj_config_private.h for CMake */ + +#define OPJ_PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* Not used by openjp2*/ +/*#cmakedefine HAVE_MEMORY_H @HAVE_MEMORY_H@*/ +/*#cmakedefine HAVE_STDLIB_H @HAVE_STDLIB_H@*/ +/*#cmakedefine HAVE_STRINGS_H @HAVE_STRINGS_H@*/ +/*#cmakedefine HAVE_STRING_H @HAVE_STRING_H@*/ +/*#cmakedefine HAVE_SYS_STAT_H @HAVE_SYS_STAT_H@*/ +/*#cmakedefine HAVE_SYS_TYPES_H @HAVE_SYS_TYPES_H@ */ +/*#cmakedefine HAVE_UNISTD_H @HAVE_UNISTD_H@*/ +/*#cmakedefine HAVE_INTTYPES_H @HAVE_INTTYPES_H@ */ +/*#cmakedefine HAVE_STDINT_H @HAVE_STDINT_H@ */ + +#cmakedefine _LARGEFILE_SOURCE +#cmakedefine _LARGE_FILES +#cmakedefine _FILE_OFFSET_BITS @_FILE_OFFSET_BITS@ +#cmakedefine OPJ_HAVE_FSEEKO @OPJ_HAVE_FSEEKO@ + +/* find whether or not have */ +#cmakedefine OPJ_HAVE_MALLOC_H +/* check if function `aligned_alloc` exists */ +#cmakedefine OPJ_HAVE_ALIGNED_ALLOC +/* check if function `_aligned_malloc` exists */ +#cmakedefine OPJ_HAVE__ALIGNED_MALLOC +/* check if function `memalign` exists */ +#cmakedefine OPJ_HAVE_MEMALIGN +/* check if function `posix_memalign` exists */ +#cmakedefine OPJ_HAVE_POSIX_MEMALIGN + +#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. */ +/* All compilers that support Mac OS X define either __BIG_ENDIAN__ or +__LITTLE_ENDIAN__ to match the endianness of the architecture being +compiled for. This is not necessarily the same as the architecture of the +machine doing the building. In order to support Universal Binaries on +Mac OS X, we prefer those defines to decide the endianness. +On other platforms we use the result of the TRY_RUN. */ +#if !defined(__APPLE__) +#cmakedefine OPJ_BIG_ENDIAN +#elif defined(__BIG_ENDIAN__) +# define OPJ_BIG_ENDIAN +#endif diff --git a/src/lib/openjp2/opj_includes.h b/src/lib/openjp2/opj_includes.h new file mode 100644 index 00000000000..13613ce521c --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/opj_malloc.c b/src/lib/openjp2/opj_malloc.c new file mode 100644 index 00000000000..dca91bfcbe9 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/opj_malloc.h b/src/lib/openjp2/opj_malloc.h new file mode 100644 index 00000000000..cbc4106c7c4 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/phix_manager.c b/src/lib/openjp2/phix_manager.c new file mode 100644 index 00000000000..796ce7eb646 --- /dev/null +++ b/src/lib/openjp2/phix_manager.c @@ -0,0 +1,210 @@ +/* + * $Id: phix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * 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. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include "opj_includes.h" + + +/* + * Write faix box of phix + * + * @param[in] coff offset of j2k codestream + * @param[in] compno component number + * @param[in] cstr_info codestream information + * @param[in] EPHused true if if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of faix box + */ + +int opj_write_phix(int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, + int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [8]; + OPJ_UINT32 len, compno, i; + opj_jp2_box_t *box; + OPJ_OFF_T lenp = 0; + + box = (opj_jp2_box_t *)opj_calloc((size_t)cstr_info.numcomps, + sizeof(opj_jp2_box_t)); + if (box == NULL) { + return 0; + } + for (i = 0; i < 2; i++) { + if (i) { + opj_stream_seek(cio, lenp, p_manager); + } + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_PHIX, 4); /* PHIX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + opj_write_manf((int)i, cstr_info.numcomps, box, cio, p_manager); + + for (compno = 0; compno < (OPJ_UINT32)cstr_info.numcomps; compno++) { + box[compno].length = (OPJ_UINT32)opj_write_phixfaix(coff, (int)compno, + cstr_info, EPHused, j2klen, cio, p_manager); + box[compno].type = JPIP_FAIX; + } + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(cio, 4, 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); + } + + opj_free(box); + + return (int)len; +} + + +int opj_write_phixfaix(int coff, int compno, opj_codestream_info_t cstr_info, + OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 tileno, version, i, nmax, size_of_coding; /* 4 or 8 */ + opj_tile_info_t *tile_Idx; + opj_packet_info_t packet; + int resno, precno, layno; + OPJ_UINT32 num_packet; + int numOfres, numOfprec, numOflayers; + OPJ_BYTE l_data_header [8]; + OPJ_OFF_T lenp; + OPJ_UINT32 len; + + packet.end_ph_pos = packet.start_pos = -1; + (void)EPHused; /* unused ? */ + + + if (j2klen > pow(2, 32)) { + size_of_coding = 8; + version = 1; + } else { + size_of_coding = 4; + version = 0; + } + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_FAIX, 4); /* FAIX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + opj_write_bytes(l_data_header, version, 1); /* Version 0 = 4 bytes */ + opj_stream_write_data(cio, l_data_header, 1, p_manager); + + nmax = 0; + for (i = 0; i <= (OPJ_UINT32)cstr_info.numdecompos[compno]; i++) { + nmax += (OPJ_UINT32)(cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * + cstr_info.numlayers); + } + + opj_write_bytes(l_data_header, nmax, size_of_coding); /* NMAX */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + opj_write_bytes(l_data_header, (OPJ_UINT32)(cstr_info.tw * cstr_info.th), + size_of_coding); /* M */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + + for (tileno = 0; tileno < (OPJ_UINT32)(cstr_info.tw * cstr_info.th); tileno++) { + tile_Idx = &cstr_info.tile[ tileno]; + + num_packet = 0; + numOfres = cstr_info.numdecompos[compno] + 1; + + for (resno = 0; resno < numOfres ; resno++) { + numOfprec = tile_Idx->pw[resno] * tile_Idx->ph[resno]; + for (precno = 0; precno < numOfprec; precno++) { + numOflayers = cstr_info.numlayers; + for (layno = 0; layno < numOflayers; layno++) { + + switch (cstr_info.prog) { + case OPJ_LRCP: + packet = tile_Idx->packet[((layno * numOfres + resno) * cstr_info.numcomps + + compno) * numOfprec + precno]; + break; + case OPJ_RLCP: + packet = tile_Idx->packet[((resno * numOflayers + layno) * cstr_info.numcomps + + compno) * numOfprec + precno]; + break; + case OPJ_RPCL: + packet = tile_Idx->packet[((resno * numOfprec + precno) * cstr_info.numcomps + + compno) * numOflayers + layno]; + break; + case OPJ_PCRL: + packet = tile_Idx->packet[((precno * cstr_info.numcomps + compno) * numOfres + + resno) * numOflayers + layno]; + break; + case OPJ_CPRL: + packet = tile_Idx->packet[((compno * numOfprec + precno) * numOfres + resno) * + numOflayers + layno]; + break; + default: + fprintf(stderr, "failed to ppix indexing\n"); + } + + opj_write_bytes(l_data_header, (OPJ_UINT32)(packet.start_pos - coff), + size_of_coding); /* start position */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + opj_write_bytes(l_data_header, + (OPJ_UINT32)(packet.end_ph_pos - packet.start_pos + 1), + size_of_coding); /* length */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + + num_packet++; + } + } + } + + /* PADDING */ + while (num_packet < nmax) { + opj_write_bytes(l_data_header, 0, + size_of_coding); /* start position */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + opj_write_bytes(l_data_header, 0, + size_of_coding); /* length */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + num_packet++; + } + } + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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 (int)len; +} diff --git a/src/lib/openjp2/pi.c b/src/lib/openjp2/pi.c new file mode 100644 index 00000000000..15ac331425d --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/pi.h b/src/lib/openjp2/pi.h new file mode 100644 index 00000000000..0320523b769 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/ppix_manager.c b/src/lib/openjp2/ppix_manager.c new file mode 100644 index 00000000000..2f0ce66b205 --- /dev/null +++ b/src/lib/openjp2/ppix_manager.c @@ -0,0 +1,215 @@ +/* + * $Id: ppix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * 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. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include "opj_includes.h" + +/* + * Write faix box of ppix + * + * @param[in] coff offset of j2k codestream + * @param[in] compno component number + * @param[in] cstr_info codestream information + * @param[in] EPHused true if if EPH option used + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of faix box + */ + + +int opj_write_ppix(int coff, opj_codestream_info_t cstr_info, OPJ_BOOL EPHused, + int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [4]; + int compno, i; + opj_jp2_box_t *box; + OPJ_OFF_T lenp; + OPJ_UINT32 len; + + /* printf("cstr_info.packno %d\n", cstr_info.packno); //NMAX? */ + + lenp = -1; + box = (opj_jp2_box_t *)opj_calloc((size_t)cstr_info.numcomps, + sizeof(opj_jp2_box_t)); + if (box == NULL) { + return 0; + } + for (i = 0; i < 2; i++) { + if (i) + + { + opj_stream_seek(cio, lenp, p_manager); + } + + lenp = (OPJ_UINT32)(opj_stream_tell(cio)); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_PPIX, 4); /* PPIX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + opj_write_manf(i, cstr_info.numcomps, box, cio, p_manager); + + for (compno = 0; compno < cstr_info.numcomps; compno++) { + box[compno].length = (OPJ_UINT32)opj_write_ppixfaix(coff, compno, cstr_info, + EPHused, j2klen, cio, p_manager); + box[compno].type = JPIP_FAIX; + } + + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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); + } + + opj_free(box); + + return (int)len; +} + + + +int opj_write_ppixfaix(int coff, int compno, opj_codestream_info_t cstr_info, + OPJ_BOOL EPHused, int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [8]; + OPJ_UINT32 tileno, version, i, nmax, size_of_coding; /* 4 or 8*/ + OPJ_UINT32 len; + OPJ_OFF_T lenp; + opj_tile_info_t *tile_Idx; + opj_packet_info_t packet; + int resno, precno, layno; + OPJ_UINT32 num_packet; + int numOfres, numOfprec, numOflayers; + packet.end_pos = packet.end_ph_pos = packet.start_pos = -1; + (void)EPHused; /* unused ? */ + + if (j2klen > pow(2, 32)) { + size_of_coding = 8; + version = 1; + } else { + size_of_coding = 4; + version = 0; + } + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_FAIX, 4); /* FAIX */ + opj_write_bytes(l_data_header, version, 1); + opj_stream_write_data(cio, l_data_header, 1, + p_manager); /* Version 0 = 4 bytes */ + + nmax = 0; + for (i = 0; i <= (OPJ_UINT32)cstr_info.numdecompos[compno]; i++) { + nmax += (OPJ_UINT32)(cstr_info.tile[0].ph[i] * cstr_info.tile[0].pw[i] * + cstr_info.numlayers); + } + + opj_write_bytes(l_data_header, nmax, size_of_coding); /* NMAX */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + opj_write_bytes(l_data_header, (OPJ_UINT32)(cstr_info.tw * cstr_info.th), + size_of_coding); /* M */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + + for (tileno = 0; tileno < (OPJ_UINT32)(cstr_info.tw * cstr_info.th); tileno++) { + tile_Idx = &cstr_info.tile[ tileno]; + + num_packet = 0; + numOfres = cstr_info.numdecompos[compno] + 1; + + for (resno = 0; resno < numOfres ; resno++) { + numOfprec = tile_Idx->pw[resno] * tile_Idx->ph[resno]; + for (precno = 0; precno < numOfprec; precno++) { + numOflayers = cstr_info.numlayers; + for (layno = 0; layno < numOflayers; layno++) { + + switch (cstr_info.prog) { + case OPJ_LRCP: + packet = tile_Idx->packet[((layno * numOfres + resno) * cstr_info.numcomps + + compno) * numOfprec + precno]; + break; + case OPJ_RLCP: + packet = tile_Idx->packet[((resno * numOflayers + layno) * cstr_info.numcomps + + compno) * numOfprec + precno]; + break; + case OPJ_RPCL: + packet = tile_Idx->packet[((resno * numOfprec + precno) * cstr_info.numcomps + + compno) * numOflayers + layno]; + break; + case OPJ_PCRL: + packet = tile_Idx->packet[((precno * cstr_info.numcomps + compno) * numOfres + + resno) * numOflayers + layno]; + break; + case OPJ_CPRL: + packet = tile_Idx->packet[((compno * numOfprec + precno) * numOfres + resno) * + numOflayers + layno]; + break; + default: + fprintf(stderr, "failed to ppix indexing\n"); + } + + opj_write_bytes(l_data_header, (OPJ_UINT32)(packet.start_pos - coff), + size_of_coding); /* start position */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + opj_write_bytes(l_data_header, + (OPJ_UINT32)(packet.end_pos - packet.start_pos + 1), + size_of_coding); /* length */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + + num_packet++; + } + } + } + + while (num_packet < nmax) { /* PADDING */ + opj_write_bytes(l_data_header, 0, + size_of_coding); /* start position */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + opj_write_bytes(l_data_header, 0, + size_of_coding); /* length */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + num_packet++; + } + } + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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 (int)len; +} diff --git a/src/lib/openjp2/sparse_array.c b/src/lib/openjp2/sparse_array.c new file mode 100644 index 00000000000..50d1a9041a4 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/sparse_array.h b/src/lib/openjp2/sparse_array.h new file mode 100644 index 00000000000..fd927eaa0b6 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/t1.c b/src/lib/openjp2/t1.c new file mode 100644 index 00000000000..52e466eb974 --- /dev/null +++ b/src/lib/openjp2/t1.c @@ -0,0 +1,2592 @@ +/* + * 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(__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) { + 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; + } + } + } 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); + + /* 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) { + 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 synthetized 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) { + 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; + } + } + 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/src/lib/openjp2/t1.h b/src/lib/openjp2/t1.h new file mode 100644 index 00000000000..ce43658ba38 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/t1_generate_luts.c b/src/lib/openjp2/t1_generate_luts.c new file mode 100644 index 00000000000..99c8c12fd93 --- /dev/null +++ b/src/lib/openjp2/t1_generate_luts.c @@ -0,0 +1,323 @@ +/* + * 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 + * 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" + +// defined elsewhere +extern OPJ_BOOL vlc_init_tables(); +extern OPJ_BOOL vlc_tables_initialized; +extern int vlc_tbl0[1024]; +extern int vlc_tbl1[1024]; + +static int t1_init_ctxno_zc(OPJ_UINT32 f, OPJ_UINT32 orient) +{ + int h, v, d, n, t, hv; + n = 0; + h = ((f & T1_SIGMA_3) != 0) + ((f & T1_SIGMA_5) != 0); + v = ((f & T1_SIGMA_1) != 0) + ((f & T1_SIGMA_7) != 0); + d = ((f & T1_SIGMA_0) != 0) + ((f & T1_SIGMA_2) != 0) + (( + f & T1_SIGMA_8) != 0) + ((f & T1_SIGMA_6) != 0); + + switch (orient) { + case 2: + t = h; + h = v; + v = t; + case 0: + case 1: + if (!h) { + if (!v) { + if (!d) { + n = 0; + } else if (d == 1) { + n = 1; + } else { + n = 2; + } + } else if (v == 1) { + n = 3; + } else { + n = 4; + } + } else if (h == 1) { + if (!v) { + if (!d) { + n = 5; + } else { + n = 6; + } + } else { + n = 7; + } + } else { + n = 8; + } + break; + case 3: + hv = h + v; + if (!d) { + if (!hv) { + n = 0; + } else if (hv == 1) { + n = 1; + } else { + n = 2; + } + } else if (d == 1) { + if (!hv) { + n = 3; + } else if (hv == 1) { + n = 4; + } else { + n = 5; + } + } else if (d == 2) { + if (!hv) { + n = 6; + } else { + n = 7; + } + } else { + n = 8; + } + break; + } + + return (T1_CTXNO_ZC + n); +} + +static int t1_init_ctxno_sc(OPJ_UINT32 f) +{ + int hc, vc, n; + n = 0; + + hc = opj_int_min(((f & (T1_LUT_SIG_E | T1_LUT_SGN_E)) == + T1_LUT_SIG_E) + ((f & (T1_LUT_SIG_W | T1_LUT_SGN_W)) == T1_LUT_SIG_W), + 1) - opj_int_min(((f & (T1_LUT_SIG_E | T1_LUT_SGN_E)) == + (T1_LUT_SIG_E | T1_LUT_SGN_E)) + + ((f & (T1_LUT_SIG_W | T1_LUT_SGN_W)) == + (T1_LUT_SIG_W | T1_LUT_SGN_W)), 1); + + vc = opj_int_min(((f & (T1_LUT_SIG_N | T1_LUT_SGN_N)) == + T1_LUT_SIG_N) + ((f & (T1_LUT_SIG_S | T1_LUT_SGN_S)) == T1_LUT_SIG_S), + 1) - opj_int_min(((f & (T1_LUT_SIG_N | T1_LUT_SGN_N)) == + (T1_LUT_SIG_N | T1_LUT_SGN_N)) + + ((f & (T1_LUT_SIG_S | T1_LUT_SGN_S)) == + (T1_LUT_SIG_S | T1_LUT_SGN_S)), 1); + + if (hc < 0) { + hc = -hc; + vc = -vc; + } + if (!hc) { + if (vc == -1) { + n = 1; + } else if (!vc) { + n = 0; + } else { + n = 1; + } + } else if (hc == 1) { + if (vc == -1) { + n = 2; + } else if (!vc) { + n = 3; + } else { + n = 4; + } + } + + return (T1_CTXNO_SC + n); +} + +static int t1_init_spb(OPJ_UINT32 f) +{ + int hc, vc, n; + + hc = opj_int_min(((f & (T1_LUT_SIG_E | T1_LUT_SGN_E)) == + T1_LUT_SIG_E) + ((f & (T1_LUT_SIG_W | T1_LUT_SGN_W)) == T1_LUT_SIG_W), + 1) - opj_int_min(((f & (T1_LUT_SIG_E | T1_LUT_SGN_E)) == + (T1_LUT_SIG_E | T1_LUT_SGN_E)) + + ((f & (T1_LUT_SIG_W | T1_LUT_SGN_W)) == + (T1_LUT_SIG_W | T1_LUT_SGN_W)), 1); + + vc = opj_int_min(((f & (T1_LUT_SIG_N | T1_LUT_SGN_N)) == + T1_LUT_SIG_N) + ((f & (T1_LUT_SIG_S | T1_LUT_SGN_S)) == T1_LUT_SIG_S), + 1) - opj_int_min(((f & (T1_LUT_SIG_N | T1_LUT_SGN_N)) == + (T1_LUT_SIG_N | T1_LUT_SGN_N)) + + ((f & (T1_LUT_SIG_S | T1_LUT_SGN_S)) == + (T1_LUT_SIG_S | T1_LUT_SGN_S)), 1); + + if (!hc && !vc) { + n = 0; + } else { + n = (!(hc > 0 || (!hc && vc > 0))); + } + + return n; +} + +static void dump_array16(int array[], int size) +{ + int i; + --size; + for (i = 0; i < size; ++i) { + printf("0x%04x,", array[i]); + if (!((i + 1) & 0x7)) { + printf("\n "); + } else { + printf(" "); + } + } + printf("0x%04x\n};\n\n", array[size]); +} + +int main(int argc, char **argv) +{ + unsigned int i, j; + double u, v, t; + + int lut_ctxno_zc[2048]; + int lut_nmsedec_sig[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_ref[1 << T1_NMSEDEC_BITS]; + int lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS]; + (void)argc; + (void)argv; + + printf("/* This file was automatically generated by t1_generate_luts.c */\n\n"); + + /* lut_ctxno_zc */ + for (j = 0; j < 4; ++j) { + for (i = 0; i < 512; ++i) { + OPJ_UINT32 orient = j; + if (orient == 2) { + orient = 1; + } else if (orient == 1) { + orient = 2; + } + lut_ctxno_zc[(orient << 9) | i] = t1_init_ctxno_zc(i, j); + } + } + + printf("static const OPJ_BYTE lut_ctxno_zc[2048] = {\n "); + for (i = 0; i < 2047; ++i) { + printf("%i,", lut_ctxno_zc[i]); + if (!((i + 1) & 0x1f)) { + printf("\n "); + } else { + printf(" "); + } + } + printf("%i\n};\n\n", lut_ctxno_zc[2047]); + + /* lut_ctxno_sc */ + printf("static const OPJ_BYTE lut_ctxno_sc[256] = {\n "); + for (i = 0; i < 255; ++i) { + printf("0x%x,", t1_init_ctxno_sc(i)); + if (!((i + 1) & 0xf)) { + printf("\n "); + } else { + printf(" "); + } + } + printf("0x%x\n};\n\n", t1_init_ctxno_sc(255)); + + /* lut_spb */ + printf("static const OPJ_BYTE lut_spb[256] = {\n "); + for (i = 0; i < 255; ++i) { + printf("%i,", t1_init_spb(i)); + if (!((i + 1) & 0x1f)) { + printf("\n "); + } else { + printf(" "); + } + } + printf("%i\n};\n\n", t1_init_spb(255)); + + /* FIXME FIXME FIXME */ + /* fprintf(stdout,"nmsedec luts:\n"); */ + for (i = 0U; i < (1U << T1_NMSEDEC_BITS); ++i) { + t = i / pow(2, T1_NMSEDEC_FRACBITS); + u = t; + v = t - 1.5; + lut_nmsedec_sig[i] = + opj_int_max(0, + (int)(floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, + T1_NMSEDEC_FRACBITS) * 8192.0)); + lut_nmsedec_sig0[i] = + opj_int_max(0, + (int)(floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, + T1_NMSEDEC_FRACBITS) * 8192.0)); + u = t - 1.0; + if (i & (1 << (T1_NMSEDEC_BITS - 1))) { + v = t - 1.5; + } else { + v = t - 0.5; + } + lut_nmsedec_ref[i] = + opj_int_max(0, + (int)(floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, + T1_NMSEDEC_FRACBITS) * 8192.0)); + lut_nmsedec_ref0[i] = + opj_int_max(0, + (int)(floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, + T1_NMSEDEC_FRACBITS) * 8192.0)); + } + + printf("static const OPJ_INT16 lut_nmsedec_sig[1U << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_sig, 1U << T1_NMSEDEC_BITS); + + printf("static const OPJ_INT16 lut_nmsedec_sig0[1U << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_sig0, 1U << T1_NMSEDEC_BITS); + + printf("static const OPJ_INT16 lut_nmsedec_ref[1U << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_ref, 1U << T1_NMSEDEC_BITS); + + printf("static const OPJ_INT16 lut_nmsedec_ref0[1U << T1_NMSEDEC_BITS] = {\n "); + dump_array16(lut_nmsedec_ref0, 1U << T1_NMSEDEC_BITS); + + vlc_tables_initialized = vlc_init_tables(); + printf("static const OPJ_UINT16 vlc_tbl0[1024] = {\n "); + dump_array16(vlc_tbl0, 1024); + printf("static const OPJ_UINT16 vlc_tbl1[1024] = {\n "); + dump_array16(vlc_tbl1, 1024); + + return 0; +} diff --git a/src/lib/openjp2/t1_ht_generate_luts.c b/src/lib/openjp2/t1_ht_generate_luts.c new file mode 100644 index 00000000000..22382a5a4af --- /dev/null +++ b/src/lib/openjp2/t1_ht_generate_luts.c @@ -0,0 +1,971 @@ +//***************************************************************************/ +// 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: t1_ht_generate_luts.c +// Author: Aous Naman +// Date: 01 September 2021 +//***************************************************************************/ + +#include +#include +#include +#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 int OPJ_BOOL; +#define OPJ_TRUE 1 +#define OPJ_FALSE 0 + +//************************************************************************/ +/** @brief HT decoding tables, as given in the standard + * + * Data in the table is arranged in this format: + * c_q is the context for a quad + * rho is the signficance pattern for a quad + * u_off indicate if u value is 0 (u_off is 0), or communicated + * e_k, e_1 EMB patterns + * cwd VLC codeword + * cwd VLC codeword length + */ +typedef struct vlc_src_table { + int c_q, rho, u_off, e_k, e_1, cwd, cwd_len; +} +vlc_src_table_t; + +// initial quad rows +static vlc_src_table_t tbl0[] = { + {0, 0x1, 0x0, 0x0, 0x0, 0x06, 4}, + {0, 0x1, 0x1, 0x1, 0x1, 0x3F, 7}, + {0, 0x2, 0x0, 0x0, 0x0, 0x00, 3}, + {0, 0x2, 0x1, 0x2, 0x2, 0x7F, 7}, + {0, 0x3, 0x0, 0x0, 0x0, 0x11, 5}, + {0, 0x3, 0x1, 0x2, 0x2, 0x5F, 7}, + {0, 0x3, 0x1, 0x3, 0x1, 0x1F, 7}, + {0, 0x4, 0x0, 0x0, 0x0, 0x02, 3}, + {0, 0x4, 0x1, 0x4, 0x4, 0x13, 6}, + {0, 0x5, 0x0, 0x0, 0x0, 0x0E, 5}, + {0, 0x5, 0x1, 0x4, 0x4, 0x23, 6}, + {0, 0x5, 0x1, 0x5, 0x1, 0x0F, 7}, + {0, 0x6, 0x0, 0x0, 0x0, 0x03, 6}, + {0, 0x6, 0x1, 0x0, 0x0, 0x6F, 7}, + {0, 0x7, 0x0, 0x0, 0x0, 0x2F, 7}, + {0, 0x7, 0x1, 0x2, 0x2, 0x4F, 7}, + {0, 0x7, 0x1, 0x2, 0x0, 0x0D, 6}, + {0, 0x8, 0x0, 0x0, 0x0, 0x04, 3}, + {0, 0x8, 0x1, 0x8, 0x8, 0x3D, 6}, + {0, 0x9, 0x0, 0x0, 0x0, 0x1D, 6}, + {0, 0x9, 0x1, 0x0, 0x0, 0x2D, 6}, + {0, 0xA, 0x0, 0x0, 0x0, 0x01, 5}, + {0, 0xA, 0x1, 0x8, 0x8, 0x35, 6}, + {0, 0xA, 0x1, 0xA, 0x2, 0x77, 7}, + {0, 0xB, 0x0, 0x0, 0x0, 0x37, 7}, + {0, 0xB, 0x1, 0x1, 0x1, 0x57, 7}, + {0, 0xB, 0x1, 0x1, 0x0, 0x09, 6}, + {0, 0xC, 0x0, 0x0, 0x0, 0x1E, 5}, + {0, 0xC, 0x1, 0xC, 0xC, 0x17, 7}, + {0, 0xC, 0x1, 0xC, 0x4, 0x15, 6}, + {0, 0xC, 0x1, 0xC, 0x8, 0x25, 6}, + {0, 0xD, 0x0, 0x0, 0x0, 0x67, 7}, + {0, 0xD, 0x1, 0x1, 0x1, 0x27, 7}, + {0, 0xD, 0x1, 0x5, 0x4, 0x47, 7}, + {0, 0xD, 0x1, 0xD, 0x8, 0x07, 7}, + {0, 0xE, 0x0, 0x0, 0x0, 0x7B, 7}, + {0, 0xE, 0x1, 0x2, 0x2, 0x4B, 7}, + {0, 0xE, 0x1, 0xA, 0x8, 0x05, 6}, + {0, 0xE, 0x1, 0xE, 0x4, 0x3B, 7}, + {0, 0xF, 0x0, 0x0, 0x0, 0x5B, 7}, + {0, 0xF, 0x1, 0x9, 0x9, 0x1B, 7}, + {0, 0xF, 0x1, 0xB, 0xA, 0x6B, 7}, + {0, 0xF, 0x1, 0xF, 0xC, 0x2B, 7}, + {0, 0xF, 0x1, 0xF, 0x8, 0x39, 6}, + {0, 0xF, 0x1, 0xE, 0x6, 0x73, 7}, + {0, 0xF, 0x1, 0xE, 0x2, 0x19, 6}, + {0, 0xF, 0x1, 0xF, 0x5, 0x0B, 7}, + {0, 0xF, 0x1, 0xF, 0x4, 0x29, 6}, + {0, 0xF, 0x1, 0xF, 0x1, 0x33, 7}, + {1, 0x0, 0x0, 0x0, 0x0, 0x00, 2}, + {1, 0x1, 0x0, 0x0, 0x0, 0x0E, 4}, + {1, 0x1, 0x1, 0x1, 0x1, 0x1F, 7}, + {1, 0x2, 0x0, 0x0, 0x0, 0x06, 4}, + {1, 0x2, 0x1, 0x2, 0x2, 0x3B, 6}, + {1, 0x3, 0x0, 0x0, 0x0, 0x1B, 6}, + {1, 0x3, 0x1, 0x0, 0x0, 0x3D, 6}, + {1, 0x4, 0x0, 0x0, 0x0, 0x0A, 4}, + {1, 0x4, 0x1, 0x4, 0x4, 0x2B, 6}, + {1, 0x5, 0x0, 0x0, 0x0, 0x0B, 6}, + {1, 0x5, 0x1, 0x4, 0x4, 0x33, 6}, + {1, 0x5, 0x1, 0x5, 0x1, 0x7F, 7}, + {1, 0x6, 0x0, 0x0, 0x0, 0x13, 6}, + {1, 0x6, 0x1, 0x0, 0x0, 0x23, 6}, + {1, 0x7, 0x0, 0x0, 0x0, 0x3F, 7}, + {1, 0x7, 0x1, 0x2, 0x2, 0x5F, 7}, + {1, 0x7, 0x1, 0x2, 0x0, 0x03, 6}, + {1, 0x8, 0x0, 0x0, 0x0, 0x02, 4}, + {1, 0x8, 0x1, 0x8, 0x8, 0x1D, 6}, + {1, 0x9, 0x0, 0x0, 0x0, 0x2D, 6}, + {1, 0x9, 0x1, 0x0, 0x0, 0x0D, 6}, + {1, 0xA, 0x0, 0x0, 0x0, 0x35, 6}, + {1, 0xA, 0x1, 0x8, 0x8, 0x15, 6}, + {1, 0xA, 0x1, 0xA, 0x2, 0x6F, 7}, + {1, 0xB, 0x0, 0x0, 0x0, 0x2F, 7}, + {1, 0xB, 0x1, 0x1, 0x1, 0x4F, 7}, + {1, 0xB, 0x1, 0x1, 0x0, 0x11, 6}, + {1, 0xC, 0x0, 0x0, 0x0, 0x01, 5}, + {1, 0xC, 0x1, 0x8, 0x8, 0x25, 6}, + {1, 0xC, 0x1, 0xC, 0x4, 0x05, 6}, + {1, 0xD, 0x0, 0x0, 0x0, 0x0F, 7}, + {1, 0xD, 0x1, 0x1, 0x1, 0x17, 7}, + {1, 0xD, 0x1, 0x5, 0x4, 0x39, 6}, + {1, 0xD, 0x1, 0xD, 0x8, 0x77, 7}, + {1, 0xE, 0x0, 0x0, 0x0, 0x37, 7}, + {1, 0xE, 0x1, 0x2, 0x2, 0x57, 7}, + {1, 0xE, 0x1, 0xA, 0x8, 0x19, 6}, + {1, 0xE, 0x1, 0xE, 0x4, 0x67, 7}, + {1, 0xF, 0x0, 0x0, 0x0, 0x07, 7}, + {1, 0xF, 0x1, 0xB, 0x8, 0x29, 6}, + {1, 0xF, 0x1, 0x8, 0x8, 0x27, 7}, + {1, 0xF, 0x1, 0xA, 0x2, 0x09, 6}, + {1, 0xF, 0x1, 0xE, 0x4, 0x31, 6}, + {1, 0xF, 0x1, 0xF, 0x1, 0x47, 7}, + {2, 0x0, 0x0, 0x0, 0x0, 0x00, 2}, + {2, 0x1, 0x0, 0x0, 0x0, 0x0E, 4}, + {2, 0x1, 0x1, 0x1, 0x1, 0x1B, 6}, + {2, 0x2, 0x0, 0x0, 0x0, 0x06, 4}, + {2, 0x2, 0x1, 0x2, 0x2, 0x3F, 7}, + {2, 0x3, 0x0, 0x0, 0x0, 0x2B, 6}, + {2, 0x3, 0x1, 0x1, 0x1, 0x33, 6}, + {2, 0x3, 0x1, 0x3, 0x2, 0x7F, 7}, + {2, 0x4, 0x0, 0x0, 0x0, 0x0A, 4}, + {2, 0x4, 0x1, 0x4, 0x4, 0x0B, 6}, + {2, 0x5, 0x0, 0x0, 0x0, 0x01, 5}, + {2, 0x5, 0x1, 0x5, 0x5, 0x2F, 7}, + {2, 0x5, 0x1, 0x5, 0x1, 0x13, 6}, + {2, 0x5, 0x1, 0x5, 0x4, 0x23, 6}, + {2, 0x6, 0x0, 0x0, 0x0, 0x03, 6}, + {2, 0x6, 0x1, 0x0, 0x0, 0x5F, 7}, + {2, 0x7, 0x0, 0x0, 0x0, 0x1F, 7}, + {2, 0x7, 0x1, 0x2, 0x2, 0x6F, 7}, + {2, 0x7, 0x1, 0x3, 0x1, 0x11, 6}, + {2, 0x7, 0x1, 0x7, 0x4, 0x37, 7}, + {2, 0x8, 0x0, 0x0, 0x0, 0x02, 4}, + {2, 0x8, 0x1, 0x8, 0x8, 0x4F, 7}, + {2, 0x9, 0x0, 0x0, 0x0, 0x3D, 6}, + {2, 0x9, 0x1, 0x0, 0x0, 0x1D, 6}, + {2, 0xA, 0x0, 0x0, 0x0, 0x2D, 6}, + {2, 0xA, 0x1, 0x0, 0x0, 0x0D, 6}, + {2, 0xB, 0x0, 0x0, 0x0, 0x0F, 7}, + {2, 0xB, 0x1, 0x2, 0x2, 0x77, 7}, + {2, 0xB, 0x1, 0x2, 0x0, 0x35, 6}, + {2, 0xC, 0x0, 0x0, 0x0, 0x15, 6}, + {2, 0xC, 0x1, 0x4, 0x4, 0x25, 6}, + {2, 0xC, 0x1, 0xC, 0x8, 0x57, 7}, + {2, 0xD, 0x0, 0x0, 0x0, 0x17, 7}, + {2, 0xD, 0x1, 0x8, 0x8, 0x05, 6}, + {2, 0xD, 0x1, 0xC, 0x4, 0x39, 6}, + {2, 0xD, 0x1, 0xD, 0x1, 0x67, 7}, + {2, 0xE, 0x0, 0x0, 0x0, 0x27, 7}, + {2, 0xE, 0x1, 0x2, 0x2, 0x7B, 7}, + {2, 0xE, 0x1, 0x2, 0x0, 0x19, 6}, + {2, 0xF, 0x0, 0x0, 0x0, 0x47, 7}, + {2, 0xF, 0x1, 0xF, 0x1, 0x29, 6}, + {2, 0xF, 0x1, 0x1, 0x1, 0x09, 6}, + {2, 0xF, 0x1, 0x3, 0x2, 0x07, 7}, + {2, 0xF, 0x1, 0x7, 0x4, 0x31, 6}, + {2, 0xF, 0x1, 0xF, 0x8, 0x3B, 7}, + {3, 0x0, 0x0, 0x0, 0x0, 0x00, 3}, + {3, 0x1, 0x0, 0x0, 0x0, 0x04, 4}, + {3, 0x1, 0x1, 0x1, 0x1, 0x3D, 6}, + {3, 0x2, 0x0, 0x0, 0x0, 0x0C, 5}, + {3, 0x2, 0x1, 0x2, 0x2, 0x4F, 7}, + {3, 0x3, 0x0, 0x0, 0x0, 0x1D, 6}, + {3, 0x3, 0x1, 0x1, 0x1, 0x05, 6}, + {3, 0x3, 0x1, 0x3, 0x2, 0x7F, 7}, + {3, 0x4, 0x0, 0x0, 0x0, 0x16, 5}, + {3, 0x4, 0x1, 0x4, 0x4, 0x2D, 6}, + {3, 0x5, 0x0, 0x0, 0x0, 0x06, 5}, + {3, 0x5, 0x1, 0x5, 0x5, 0x1A, 5}, + {3, 0x5, 0x1, 0x5, 0x1, 0x0D, 6}, + {3, 0x5, 0x1, 0x5, 0x4, 0x35, 6}, + {3, 0x6, 0x0, 0x0, 0x0, 0x3F, 7}, + {3, 0x6, 0x1, 0x4, 0x4, 0x5F, 7}, + {3, 0x6, 0x1, 0x6, 0x2, 0x1F, 7}, + {3, 0x7, 0x0, 0x0, 0x0, 0x6F, 7}, + {3, 0x7, 0x1, 0x6, 0x6, 0x2F, 7}, + {3, 0x7, 0x1, 0x6, 0x4, 0x15, 6}, + {3, 0x7, 0x1, 0x7, 0x3, 0x77, 7}, + {3, 0x7, 0x1, 0x7, 0x1, 0x25, 6}, + {3, 0x7, 0x1, 0x7, 0x2, 0x0F, 7}, + {3, 0x8, 0x0, 0x0, 0x0, 0x0A, 5}, + {3, 0x8, 0x1, 0x8, 0x8, 0x07, 7}, + {3, 0x9, 0x0, 0x0, 0x0, 0x39, 6}, + {3, 0x9, 0x1, 0x1, 0x1, 0x37, 7}, + {3, 0x9, 0x1, 0x9, 0x8, 0x57, 7}, + {3, 0xA, 0x0, 0x0, 0x0, 0x19, 6}, + {3, 0xA, 0x1, 0x8, 0x8, 0x29, 6}, + {3, 0xA, 0x1, 0xA, 0x2, 0x17, 7}, + {3, 0xB, 0x0, 0x0, 0x0, 0x67, 7}, + {3, 0xB, 0x1, 0xB, 0x1, 0x27, 7}, + {3, 0xB, 0x1, 0x1, 0x1, 0x47, 7}, + {3, 0xB, 0x1, 0x3, 0x2, 0x09, 6}, + {3, 0xB, 0x1, 0xB, 0x8, 0x7B, 7}, + {3, 0xC, 0x0, 0x0, 0x0, 0x31, 6}, + {3, 0xC, 0x1, 0x4, 0x4, 0x11, 6}, + {3, 0xC, 0x1, 0xC, 0x8, 0x3B, 7}, + {3, 0xD, 0x0, 0x0, 0x0, 0x5B, 7}, + {3, 0xD, 0x1, 0x9, 0x9, 0x1B, 7}, + {3, 0xD, 0x1, 0xD, 0x5, 0x2B, 7}, + {3, 0xD, 0x1, 0xD, 0x1, 0x21, 6}, + {3, 0xD, 0x1, 0xD, 0xC, 0x6B, 7}, + {3, 0xD, 0x1, 0xD, 0x4, 0x01, 6}, + {3, 0xD, 0x1, 0xD, 0x8, 0x4B, 7}, + {3, 0xE, 0x0, 0x0, 0x0, 0x0B, 7}, + {3, 0xE, 0x1, 0xE, 0x4, 0x73, 7}, + {3, 0xE, 0x1, 0x4, 0x4, 0x13, 7}, + {3, 0xE, 0x1, 0xC, 0x8, 0x3E, 6}, + {3, 0xE, 0x1, 0xE, 0x2, 0x33, 7}, + {3, 0xF, 0x0, 0x0, 0x0, 0x53, 7}, + {3, 0xF, 0x1, 0xA, 0xA, 0x0E, 6}, + {3, 0xF, 0x1, 0xB, 0x9, 0x63, 7}, + {3, 0xF, 0x1, 0xF, 0xC, 0x03, 7}, + {3, 0xF, 0x1, 0xF, 0x8, 0x12, 5}, + {3, 0xF, 0x1, 0xE, 0x6, 0x23, 7}, + {3, 0xF, 0x1, 0xF, 0x5, 0x1E, 6}, + {3, 0xF, 0x1, 0xF, 0x4, 0x02, 5}, + {3, 0xF, 0x1, 0xF, 0x3, 0x43, 7}, + {3, 0xF, 0x1, 0xF, 0x1, 0x1C, 5}, + {3, 0xF, 0x1, 0xF, 0x2, 0x2E, 6}, + {4, 0x0, 0x0, 0x0, 0x0, 0x00, 2}, + {4, 0x1, 0x0, 0x0, 0x0, 0x0E, 4}, + {4, 0x1, 0x1, 0x1, 0x1, 0x3F, 7}, + {4, 0x2, 0x0, 0x0, 0x0, 0x06, 4}, + {4, 0x2, 0x1, 0x2, 0x2, 0x1B, 6}, + {4, 0x3, 0x0, 0x0, 0x0, 0x2B, 6}, + {4, 0x3, 0x1, 0x2, 0x2, 0x3D, 6}, + {4, 0x3, 0x1, 0x3, 0x1, 0x7F, 7}, + {4, 0x4, 0x0, 0x0, 0x0, 0x0A, 4}, + {4, 0x4, 0x1, 0x4, 0x4, 0x5F, 7}, + {4, 0x5, 0x0, 0x0, 0x0, 0x0B, 6}, + {4, 0x5, 0x1, 0x0, 0x0, 0x33, 6}, + {4, 0x6, 0x0, 0x0, 0x0, 0x13, 6}, + {4, 0x6, 0x1, 0x0, 0x0, 0x23, 6}, + {4, 0x7, 0x0, 0x0, 0x0, 0x1F, 7}, + {4, 0x7, 0x1, 0x4, 0x4, 0x6F, 7}, + {4, 0x7, 0x1, 0x4, 0x0, 0x03, 6}, + {4, 0x8, 0x0, 0x0, 0x0, 0x02, 4}, + {4, 0x8, 0x1, 0x8, 0x8, 0x1D, 6}, + {4, 0x9, 0x0, 0x0, 0x0, 0x11, 6}, + {4, 0x9, 0x1, 0x0, 0x0, 0x77, 7}, + {4, 0xA, 0x0, 0x0, 0x0, 0x01, 5}, + {4, 0xA, 0x1, 0xA, 0xA, 0x2F, 7}, + {4, 0xA, 0x1, 0xA, 0x2, 0x2D, 6}, + {4, 0xA, 0x1, 0xA, 0x8, 0x0D, 6}, + {4, 0xB, 0x0, 0x0, 0x0, 0x4F, 7}, + {4, 0xB, 0x1, 0xB, 0x2, 0x0F, 7}, + {4, 0xB, 0x1, 0x0, 0x0, 0x35, 6}, + {4, 0xC, 0x0, 0x0, 0x0, 0x15, 6}, + {4, 0xC, 0x1, 0x8, 0x8, 0x25, 6}, + {4, 0xC, 0x1, 0xC, 0x4, 0x37, 7}, + {4, 0xD, 0x0, 0x0, 0x0, 0x57, 7}, + {4, 0xD, 0x1, 0x1, 0x1, 0x07, 7}, + {4, 0xD, 0x1, 0x1, 0x0, 0x05, 6}, + {4, 0xE, 0x0, 0x0, 0x0, 0x17, 7}, + {4, 0xE, 0x1, 0x4, 0x4, 0x39, 6}, + {4, 0xE, 0x1, 0xC, 0x8, 0x19, 6}, + {4, 0xE, 0x1, 0xE, 0x2, 0x67, 7}, + {4, 0xF, 0x0, 0x0, 0x0, 0x27, 7}, + {4, 0xF, 0x1, 0x9, 0x9, 0x47, 7}, + {4, 0xF, 0x1, 0x9, 0x1, 0x29, 6}, + {4, 0xF, 0x1, 0x7, 0x6, 0x7B, 7}, + {4, 0xF, 0x1, 0x7, 0x2, 0x09, 6}, + {4, 0xF, 0x1, 0xB, 0x8, 0x31, 6}, + {4, 0xF, 0x1, 0xF, 0x4, 0x3B, 7}, + {5, 0x0, 0x0, 0x0, 0x0, 0x00, 3}, + {5, 0x1, 0x0, 0x0, 0x0, 0x1A, 5}, + {5, 0x1, 0x1, 0x1, 0x1, 0x7F, 7}, + {5, 0x2, 0x0, 0x0, 0x0, 0x0A, 5}, + {5, 0x2, 0x1, 0x2, 0x2, 0x1D, 6}, + {5, 0x3, 0x0, 0x0, 0x0, 0x2D, 6}, + {5, 0x3, 0x1, 0x3, 0x3, 0x5F, 7}, + {5, 0x3, 0x1, 0x3, 0x2, 0x39, 6}, + {5, 0x3, 0x1, 0x3, 0x1, 0x3F, 7}, + {5, 0x4, 0x0, 0x0, 0x0, 0x12, 5}, + {5, 0x4, 0x1, 0x4, 0x4, 0x1F, 7}, + {5, 0x5, 0x0, 0x0, 0x0, 0x0D, 6}, + {5, 0x5, 0x1, 0x4, 0x4, 0x35, 6}, + {5, 0x5, 0x1, 0x5, 0x1, 0x6F, 7}, + {5, 0x6, 0x0, 0x0, 0x0, 0x15, 6}, + {5, 0x6, 0x1, 0x2, 0x2, 0x25, 6}, + {5, 0x6, 0x1, 0x6, 0x4, 0x2F, 7}, + {5, 0x7, 0x0, 0x0, 0x0, 0x4F, 7}, + {5, 0x7, 0x1, 0x6, 0x6, 0x57, 7}, + {5, 0x7, 0x1, 0x6, 0x4, 0x05, 6}, + {5, 0x7, 0x1, 0x7, 0x3, 0x0F, 7}, + {5, 0x7, 0x1, 0x7, 0x2, 0x77, 7}, + {5, 0x7, 0x1, 0x7, 0x1, 0x37, 7}, + {5, 0x8, 0x0, 0x0, 0x0, 0x02, 5}, + {5, 0x8, 0x1, 0x8, 0x8, 0x19, 6}, + {5, 0x9, 0x0, 0x0, 0x0, 0x26, 6}, + {5, 0x9, 0x1, 0x8, 0x8, 0x17, 7}, + {5, 0x9, 0x1, 0x9, 0x1, 0x67, 7}, + {5, 0xA, 0x0, 0x0, 0x0, 0x1C, 5}, + {5, 0xA, 0x1, 0xA, 0xA, 0x29, 6}, + {5, 0xA, 0x1, 0xA, 0x2, 0x09, 6}, + {5, 0xA, 0x1, 0xA, 0x8, 0x31, 6}, + {5, 0xB, 0x0, 0x0, 0x0, 0x27, 7}, + {5, 0xB, 0x1, 0x9, 0x9, 0x07, 7}, + {5, 0xB, 0x1, 0x9, 0x8, 0x11, 6}, + {5, 0xB, 0x1, 0xB, 0x3, 0x47, 7}, + {5, 0xB, 0x1, 0xB, 0x2, 0x21, 6}, + {5, 0xB, 0x1, 0xB, 0x1, 0x7B, 7}, + {5, 0xC, 0x0, 0x0, 0x0, 0x01, 6}, + {5, 0xC, 0x1, 0x8, 0x8, 0x3E, 6}, + {5, 0xC, 0x1, 0xC, 0x4, 0x3B, 7}, + {5, 0xD, 0x0, 0x0, 0x0, 0x5B, 7}, + {5, 0xD, 0x1, 0x9, 0x9, 0x6B, 7}, + {5, 0xD, 0x1, 0x9, 0x8, 0x1E, 6}, + {5, 0xD, 0x1, 0xD, 0x5, 0x1B, 7}, + {5, 0xD, 0x1, 0xD, 0x4, 0x2E, 6}, + {5, 0xD, 0x1, 0xD, 0x1, 0x2B, 7}, + {5, 0xE, 0x0, 0x0, 0x0, 0x4B, 7}, + {5, 0xE, 0x1, 0x6, 0x6, 0x0B, 7}, + {5, 0xE, 0x1, 0xE, 0xA, 0x33, 7}, + {5, 0xE, 0x1, 0xE, 0x2, 0x0E, 6}, + {5, 0xE, 0x1, 0xE, 0xC, 0x73, 7}, + {5, 0xE, 0x1, 0xE, 0x8, 0x36, 6}, + {5, 0xE, 0x1, 0xE, 0x4, 0x53, 7}, + {5, 0xF, 0x0, 0x0, 0x0, 0x13, 7}, + {5, 0xF, 0x1, 0x7, 0x7, 0x43, 7}, + {5, 0xF, 0x1, 0x7, 0x6, 0x16, 6}, + {5, 0xF, 0x1, 0x7, 0x5, 0x63, 7}, + {5, 0xF, 0x1, 0xF, 0xC, 0x23, 7}, + {5, 0xF, 0x1, 0xF, 0x4, 0x0C, 5}, + {5, 0xF, 0x1, 0xD, 0x9, 0x03, 7}, + {5, 0xF, 0x1, 0xF, 0xA, 0x3D, 7}, + {5, 0xF, 0x1, 0xF, 0x8, 0x14, 5}, + {5, 0xF, 0x1, 0xF, 0x3, 0x7D, 7}, + {5, 0xF, 0x1, 0xF, 0x2, 0x04, 5}, + {5, 0xF, 0x1, 0xF, 0x1, 0x06, 6}, + {6, 0x0, 0x0, 0x0, 0x0, 0x00, 3}, + {6, 0x1, 0x0, 0x0, 0x0, 0x04, 4}, + {6, 0x1, 0x1, 0x1, 0x1, 0x03, 6}, + {6, 0x2, 0x0, 0x0, 0x0, 0x0C, 5}, + {6, 0x2, 0x1, 0x2, 0x2, 0x0D, 6}, + {6, 0x3, 0x0, 0x0, 0x0, 0x1A, 5}, + {6, 0x3, 0x1, 0x3, 0x3, 0x3D, 6}, + {6, 0x3, 0x1, 0x3, 0x1, 0x1D, 6}, + {6, 0x3, 0x1, 0x3, 0x2, 0x2D, 6}, + {6, 0x4, 0x0, 0x0, 0x0, 0x0A, 5}, + {6, 0x4, 0x1, 0x4, 0x4, 0x3F, 7}, + {6, 0x5, 0x0, 0x0, 0x0, 0x35, 6}, + {6, 0x5, 0x1, 0x1, 0x1, 0x15, 6}, + {6, 0x5, 0x1, 0x5, 0x4, 0x7F, 7}, + {6, 0x6, 0x0, 0x0, 0x0, 0x25, 6}, + {6, 0x6, 0x1, 0x2, 0x2, 0x5F, 7}, + {6, 0x6, 0x1, 0x6, 0x4, 0x1F, 7}, + {6, 0x7, 0x0, 0x0, 0x0, 0x6F, 7}, + {6, 0x7, 0x1, 0x6, 0x6, 0x4F, 7}, + {6, 0x7, 0x1, 0x6, 0x4, 0x05, 6}, + {6, 0x7, 0x1, 0x7, 0x3, 0x2F, 7}, + {6, 0x7, 0x1, 0x7, 0x1, 0x36, 6}, + {6, 0x7, 0x1, 0x7, 0x2, 0x77, 7}, + {6, 0x8, 0x0, 0x0, 0x0, 0x12, 5}, + {6, 0x8, 0x1, 0x8, 0x8, 0x0F, 7}, + {6, 0x9, 0x0, 0x0, 0x0, 0x39, 6}, + {6, 0x9, 0x1, 0x1, 0x1, 0x37, 7}, + {6, 0x9, 0x1, 0x9, 0x8, 0x57, 7}, + {6, 0xA, 0x0, 0x0, 0x0, 0x19, 6}, + {6, 0xA, 0x1, 0x2, 0x2, 0x29, 6}, + {6, 0xA, 0x1, 0xA, 0x8, 0x17, 7}, + {6, 0xB, 0x0, 0x0, 0x0, 0x67, 7}, + {6, 0xB, 0x1, 0x9, 0x9, 0x47, 7}, + {6, 0xB, 0x1, 0x9, 0x1, 0x09, 6}, + {6, 0xB, 0x1, 0xB, 0xA, 0x27, 7}, + {6, 0xB, 0x1, 0xB, 0x2, 0x31, 6}, + {6, 0xB, 0x1, 0xB, 0x8, 0x7B, 7}, + {6, 0xC, 0x0, 0x0, 0x0, 0x11, 6}, + {6, 0xC, 0x1, 0xC, 0xC, 0x07, 7}, + {6, 0xC, 0x1, 0xC, 0x8, 0x21, 6}, + {6, 0xC, 0x1, 0xC, 0x4, 0x3B, 7}, + {6, 0xD, 0x0, 0x0, 0x0, 0x5B, 7}, + {6, 0xD, 0x1, 0x5, 0x5, 0x33, 7}, + {6, 0xD, 0x1, 0x5, 0x4, 0x01, 6}, + {6, 0xD, 0x1, 0xC, 0x8, 0x1B, 7}, + {6, 0xD, 0x1, 0xD, 0x1, 0x6B, 7}, + {6, 0xE, 0x0, 0x0, 0x0, 0x2B, 7}, + {6, 0xE, 0x1, 0xE, 0x2, 0x4B, 7}, + {6, 0xE, 0x1, 0x2, 0x2, 0x0B, 7}, + {6, 0xE, 0x1, 0xE, 0xC, 0x73, 7}, + {6, 0xE, 0x1, 0xE, 0x8, 0x3E, 6}, + {6, 0xE, 0x1, 0xE, 0x4, 0x53, 7}, + {6, 0xF, 0x0, 0x0, 0x0, 0x13, 7}, + {6, 0xF, 0x1, 0x6, 0x6, 0x1E, 6}, + {6, 0xF, 0x1, 0xE, 0xA, 0x2E, 6}, + {6, 0xF, 0x1, 0xF, 0x3, 0x0E, 6}, + {6, 0xF, 0x1, 0xF, 0x2, 0x02, 5}, + {6, 0xF, 0x1, 0xB, 0x9, 0x63, 7}, + {6, 0xF, 0x1, 0xF, 0xC, 0x16, 6}, + {6, 0xF, 0x1, 0xF, 0x8, 0x06, 6}, + {6, 0xF, 0x1, 0xF, 0x5, 0x23, 7}, + {6, 0xF, 0x1, 0xF, 0x1, 0x1C, 5}, + {6, 0xF, 0x1, 0xF, 0x4, 0x26, 6}, + {7, 0x0, 0x0, 0x0, 0x0, 0x12, 5}, + {7, 0x1, 0x0, 0x0, 0x0, 0x05, 6}, + {7, 0x1, 0x1, 0x1, 0x1, 0x7F, 7}, + {7, 0x2, 0x0, 0x0, 0x0, 0x39, 6}, + {7, 0x2, 0x1, 0x2, 0x2, 0x3F, 7}, + {7, 0x3, 0x0, 0x0, 0x0, 0x5F, 7}, + {7, 0x3, 0x1, 0x3, 0x3, 0x1F, 7}, + {7, 0x3, 0x1, 0x3, 0x2, 0x6F, 7}, + {7, 0x3, 0x1, 0x3, 0x1, 0x2F, 7}, + {7, 0x4, 0x0, 0x0, 0x0, 0x4F, 7}, + {7, 0x4, 0x1, 0x4, 0x4, 0x0F, 7}, + {7, 0x5, 0x0, 0x0, 0x0, 0x57, 7}, + {7, 0x5, 0x1, 0x1, 0x1, 0x19, 6}, + {7, 0x5, 0x1, 0x5, 0x4, 0x77, 7}, + {7, 0x6, 0x0, 0x0, 0x0, 0x37, 7}, + {7, 0x6, 0x1, 0x0, 0x0, 0x29, 6}, + {7, 0x7, 0x0, 0x0, 0x0, 0x17, 7}, + {7, 0x7, 0x1, 0x6, 0x6, 0x67, 7}, + {7, 0x7, 0x1, 0x7, 0x3, 0x27, 7}, + {7, 0x7, 0x1, 0x7, 0x2, 0x47, 7}, + {7, 0x7, 0x1, 0x7, 0x5, 0x1B, 7}, + {7, 0x7, 0x1, 0x7, 0x1, 0x09, 6}, + {7, 0x7, 0x1, 0x7, 0x4, 0x07, 7}, + {7, 0x8, 0x0, 0x0, 0x0, 0x7B, 7}, + {7, 0x8, 0x1, 0x8, 0x8, 0x3B, 7}, + {7, 0x9, 0x0, 0x0, 0x0, 0x5B, 7}, + {7, 0x9, 0x1, 0x0, 0x0, 0x31, 6}, + {7, 0xA, 0x0, 0x0, 0x0, 0x53, 7}, + {7, 0xA, 0x1, 0x2, 0x2, 0x11, 6}, + {7, 0xA, 0x1, 0xA, 0x8, 0x6B, 7}, + {7, 0xB, 0x0, 0x0, 0x0, 0x2B, 7}, + {7, 0xB, 0x1, 0x9, 0x9, 0x4B, 7}, + {7, 0xB, 0x1, 0xB, 0x3, 0x0B, 7}, + {7, 0xB, 0x1, 0xB, 0x1, 0x73, 7}, + {7, 0xB, 0x1, 0xB, 0xA, 0x33, 7}, + {7, 0xB, 0x1, 0xB, 0x2, 0x21, 6}, + {7, 0xB, 0x1, 0xB, 0x8, 0x13, 7}, + {7, 0xC, 0x0, 0x0, 0x0, 0x63, 7}, + {7, 0xC, 0x1, 0x8, 0x8, 0x23, 7}, + {7, 0xC, 0x1, 0xC, 0x4, 0x43, 7}, + {7, 0xD, 0x0, 0x0, 0x0, 0x03, 7}, + {7, 0xD, 0x1, 0x9, 0x9, 0x7D, 7}, + {7, 0xD, 0x1, 0xD, 0x5, 0x5D, 7}, + {7, 0xD, 0x1, 0xD, 0x1, 0x01, 6}, + {7, 0xD, 0x1, 0xD, 0xC, 0x3D, 7}, + {7, 0xD, 0x1, 0xD, 0x4, 0x3E, 6}, + {7, 0xD, 0x1, 0xD, 0x8, 0x1D, 7}, + {7, 0xE, 0x0, 0x0, 0x0, 0x6D, 7}, + {7, 0xE, 0x1, 0x6, 0x6, 0x2D, 7}, + {7, 0xE, 0x1, 0xE, 0xA, 0x0D, 7}, + {7, 0xE, 0x1, 0xE, 0x2, 0x1E, 6}, + {7, 0xE, 0x1, 0xE, 0xC, 0x4D, 7}, + {7, 0xE, 0x1, 0xE, 0x8, 0x0E, 6}, + {7, 0xE, 0x1, 0xE, 0x4, 0x75, 7}, + {7, 0xF, 0x0, 0x0, 0x0, 0x15, 7}, + {7, 0xF, 0x1, 0xF, 0xF, 0x06, 5}, + {7, 0xF, 0x1, 0xF, 0xD, 0x35, 7}, + {7, 0xF, 0x1, 0xF, 0x7, 0x55, 7}, + {7, 0xF, 0x1, 0xF, 0x5, 0x1A, 5}, + {7, 0xF, 0x1, 0xF, 0xB, 0x25, 7}, + {7, 0xF, 0x1, 0xF, 0x3, 0x0A, 5}, + {7, 0xF, 0x1, 0xF, 0x9, 0x2E, 6}, + {7, 0xF, 0x1, 0xF, 0x1, 0x00, 4}, + {7, 0xF, 0x1, 0xF, 0xE, 0x65, 7}, + {7, 0xF, 0x1, 0xF, 0x6, 0x36, 6}, + {7, 0xF, 0x1, 0xF, 0xA, 0x02, 5}, + {7, 0xF, 0x1, 0xF, 0x2, 0x0C, 4}, + {7, 0xF, 0x1, 0xF, 0xC, 0x16, 6}, + {7, 0xF, 0x1, 0xF, 0x8, 0x04, 4}, + {7, 0xF, 0x1, 0xF, 0x4, 0x08, 4} +}; + +// nono-initial quad rows +static vlc_src_table_t tbl1[] = { + {0, 0x1, 0x0, 0x0, 0x0, 0x00, 3}, + {0, 0x1, 0x1, 0x1, 0x1, 0x27, 6}, + {0, 0x2, 0x0, 0x0, 0x0, 0x06, 3}, + {0, 0x2, 0x1, 0x2, 0x2, 0x17, 6}, + {0, 0x3, 0x0, 0x0, 0x0, 0x0D, 5}, + {0, 0x3, 0x1, 0x0, 0x0, 0x3B, 6}, + {0, 0x4, 0x0, 0x0, 0x0, 0x02, 3}, + {0, 0x4, 0x1, 0x4, 0x4, 0x07, 6}, + {0, 0x5, 0x0, 0x0, 0x0, 0x15, 5}, + {0, 0x5, 0x1, 0x0, 0x0, 0x2B, 6}, + {0, 0x6, 0x0, 0x0, 0x0, 0x01, 5}, + {0, 0x6, 0x1, 0x0, 0x0, 0x7F, 7}, + {0, 0x7, 0x0, 0x0, 0x0, 0x1F, 7}, + {0, 0x7, 0x1, 0x0, 0x0, 0x1B, 6}, + {0, 0x8, 0x0, 0x0, 0x0, 0x04, 3}, + {0, 0x8, 0x1, 0x8, 0x8, 0x05, 5}, + {0, 0x9, 0x0, 0x0, 0x0, 0x19, 5}, + {0, 0x9, 0x1, 0x0, 0x0, 0x13, 6}, + {0, 0xA, 0x0, 0x0, 0x0, 0x09, 5}, + {0, 0xA, 0x1, 0x8, 0x8, 0x0B, 6}, + {0, 0xA, 0x1, 0xA, 0x2, 0x3F, 7}, + {0, 0xB, 0x0, 0x0, 0x0, 0x5F, 7}, + {0, 0xB, 0x1, 0x0, 0x0, 0x33, 6}, + {0, 0xC, 0x0, 0x0, 0x0, 0x11, 5}, + {0, 0xC, 0x1, 0x8, 0x8, 0x23, 6}, + {0, 0xC, 0x1, 0xC, 0x4, 0x6F, 7}, + {0, 0xD, 0x0, 0x0, 0x0, 0x0F, 7}, + {0, 0xD, 0x1, 0x0, 0x0, 0x03, 6}, + {0, 0xE, 0x0, 0x0, 0x0, 0x2F, 7}, + {0, 0xE, 0x1, 0x4, 0x4, 0x4F, 7}, + {0, 0xE, 0x1, 0x4, 0x0, 0x3D, 6}, + {0, 0xF, 0x0, 0x0, 0x0, 0x77, 7}, + {0, 0xF, 0x1, 0x1, 0x1, 0x37, 7}, + {0, 0xF, 0x1, 0x1, 0x0, 0x1D, 6}, + {1, 0x0, 0x0, 0x0, 0x0, 0x00, 1}, + {1, 0x1, 0x0, 0x0, 0x0, 0x05, 4}, + {1, 0x1, 0x1, 0x1, 0x1, 0x7F, 7}, + {1, 0x2, 0x0, 0x0, 0x0, 0x09, 4}, + {1, 0x2, 0x1, 0x2, 0x2, 0x1F, 7}, + {1, 0x3, 0x0, 0x0, 0x0, 0x1D, 5}, + {1, 0x3, 0x1, 0x1, 0x1, 0x3F, 7}, + {1, 0x3, 0x1, 0x3, 0x2, 0x5F, 7}, + {1, 0x4, 0x0, 0x0, 0x0, 0x0D, 5}, + {1, 0x4, 0x1, 0x4, 0x4, 0x37, 7}, + {1, 0x5, 0x0, 0x0, 0x0, 0x03, 6}, + {1, 0x5, 0x1, 0x0, 0x0, 0x6F, 7}, + {1, 0x6, 0x0, 0x0, 0x0, 0x2F, 7}, + {1, 0x6, 0x1, 0x0, 0x0, 0x4F, 7}, + {1, 0x7, 0x0, 0x0, 0x0, 0x0F, 7}, + {1, 0x7, 0x1, 0x0, 0x0, 0x77, 7}, + {1, 0x8, 0x0, 0x0, 0x0, 0x01, 4}, + {1, 0x8, 0x1, 0x8, 0x8, 0x17, 7}, + {1, 0x9, 0x0, 0x0, 0x0, 0x0B, 6}, + {1, 0x9, 0x1, 0x0, 0x0, 0x57, 7}, + {1, 0xA, 0x0, 0x0, 0x0, 0x33, 6}, + {1, 0xA, 0x1, 0x0, 0x0, 0x67, 7}, + {1, 0xB, 0x0, 0x0, 0x0, 0x27, 7}, + {1, 0xB, 0x1, 0x0, 0x0, 0x2B, 7}, + {1, 0xC, 0x0, 0x0, 0x0, 0x13, 6}, + {1, 0xC, 0x1, 0x0, 0x0, 0x47, 7}, + {1, 0xD, 0x0, 0x0, 0x0, 0x07, 7}, + {1, 0xD, 0x1, 0x0, 0x0, 0x7B, 7}, + {1, 0xE, 0x0, 0x0, 0x0, 0x3B, 7}, + {1, 0xE, 0x1, 0x0, 0x0, 0x5B, 7}, + {1, 0xF, 0x0, 0x0, 0x0, 0x1B, 7}, + {1, 0xF, 0x1, 0x4, 0x4, 0x6B, 7}, + {1, 0xF, 0x1, 0x4, 0x0, 0x23, 6}, + {2, 0x0, 0x0, 0x0, 0x0, 0x00, 1}, + {2, 0x1, 0x0, 0x0, 0x0, 0x09, 4}, + {2, 0x1, 0x1, 0x1, 0x1, 0x7F, 7}, + {2, 0x2, 0x0, 0x0, 0x0, 0x01, 4}, + {2, 0x2, 0x1, 0x2, 0x2, 0x23, 6}, + {2, 0x3, 0x0, 0x0, 0x0, 0x3D, 6}, + {2, 0x3, 0x1, 0x2, 0x2, 0x3F, 7}, + {2, 0x3, 0x1, 0x3, 0x1, 0x1F, 7}, + {2, 0x4, 0x0, 0x0, 0x0, 0x15, 5}, + {2, 0x4, 0x1, 0x4, 0x4, 0x5F, 7}, + {2, 0x5, 0x0, 0x0, 0x0, 0x03, 6}, + {2, 0x5, 0x1, 0x0, 0x0, 0x6F, 7}, + {2, 0x6, 0x0, 0x0, 0x0, 0x2F, 7}, + {2, 0x6, 0x1, 0x0, 0x0, 0x4F, 7}, + {2, 0x7, 0x0, 0x0, 0x0, 0x0F, 7}, + {2, 0x7, 0x1, 0x0, 0x0, 0x17, 7}, + {2, 0x8, 0x0, 0x0, 0x0, 0x05, 5}, + {2, 0x8, 0x1, 0x8, 0x8, 0x77, 7}, + {2, 0x9, 0x0, 0x0, 0x0, 0x37, 7}, + {2, 0x9, 0x1, 0x0, 0x0, 0x57, 7}, + {2, 0xA, 0x0, 0x0, 0x0, 0x1D, 6}, + {2, 0xA, 0x1, 0xA, 0xA, 0x7B, 7}, + {2, 0xA, 0x1, 0xA, 0x2, 0x2D, 6}, + {2, 0xA, 0x1, 0xA, 0x8, 0x67, 7}, + {2, 0xB, 0x0, 0x0, 0x0, 0x27, 7}, + {2, 0xB, 0x1, 0xB, 0x2, 0x47, 7}, + {2, 0xB, 0x1, 0x0, 0x0, 0x07, 7}, + {2, 0xC, 0x0, 0x0, 0x0, 0x0D, 6}, + {2, 0xC, 0x1, 0x0, 0x0, 0x3B, 7}, + {2, 0xD, 0x0, 0x0, 0x0, 0x5B, 7}, + {2, 0xD, 0x1, 0x0, 0x0, 0x1B, 7}, + {2, 0xE, 0x0, 0x0, 0x0, 0x6B, 7}, + {2, 0xE, 0x1, 0x4, 0x4, 0x2B, 7}, + {2, 0xE, 0x1, 0x4, 0x0, 0x4B, 7}, + {2, 0xF, 0x0, 0x0, 0x0, 0x0B, 7}, + {2, 0xF, 0x1, 0x4, 0x4, 0x73, 7}, + {2, 0xF, 0x1, 0x5, 0x1, 0x33, 7}, + {2, 0xF, 0x1, 0x7, 0x2, 0x53, 7}, + {2, 0xF, 0x1, 0xF, 0x8, 0x13, 7}, + {3, 0x0, 0x0, 0x0, 0x0, 0x00, 2}, + {3, 0x1, 0x0, 0x0, 0x0, 0x0A, 4}, + {3, 0x1, 0x1, 0x1, 0x1, 0x0B, 6}, + {3, 0x2, 0x0, 0x0, 0x0, 0x02, 4}, + {3, 0x2, 0x1, 0x2, 0x2, 0x23, 6}, + {3, 0x3, 0x0, 0x0, 0x0, 0x0E, 5}, + {3, 0x3, 0x1, 0x3, 0x3, 0x7F, 7}, + {3, 0x3, 0x1, 0x3, 0x2, 0x33, 6}, + {3, 0x3, 0x1, 0x3, 0x1, 0x13, 6}, + {3, 0x4, 0x0, 0x0, 0x0, 0x16, 5}, + {3, 0x4, 0x1, 0x4, 0x4, 0x3F, 7}, + {3, 0x5, 0x0, 0x0, 0x0, 0x03, 6}, + {3, 0x5, 0x1, 0x1, 0x1, 0x3D, 6}, + {3, 0x5, 0x1, 0x5, 0x4, 0x1F, 7}, + {3, 0x6, 0x0, 0x0, 0x0, 0x1D, 6}, + {3, 0x6, 0x1, 0x0, 0x0, 0x5F, 7}, + {3, 0x7, 0x0, 0x0, 0x0, 0x2D, 6}, + {3, 0x7, 0x1, 0x4, 0x4, 0x2F, 7}, + {3, 0x7, 0x1, 0x5, 0x1, 0x1E, 6}, + {3, 0x7, 0x1, 0x7, 0x2, 0x6F, 7}, + {3, 0x8, 0x0, 0x0, 0x0, 0x06, 5}, + {3, 0x8, 0x1, 0x8, 0x8, 0x4F, 7}, + {3, 0x9, 0x0, 0x0, 0x0, 0x0D, 6}, + {3, 0x9, 0x1, 0x0, 0x0, 0x35, 6}, + {3, 0xA, 0x0, 0x0, 0x0, 0x15, 6}, + {3, 0xA, 0x1, 0x2, 0x2, 0x25, 6}, + {3, 0xA, 0x1, 0xA, 0x8, 0x0F, 7}, + {3, 0xB, 0x0, 0x0, 0x0, 0x05, 6}, + {3, 0xB, 0x1, 0x8, 0x8, 0x39, 6}, + {3, 0xB, 0x1, 0xB, 0x3, 0x17, 7}, + {3, 0xB, 0x1, 0xB, 0x2, 0x19, 6}, + {3, 0xB, 0x1, 0xB, 0x1, 0x77, 7}, + {3, 0xC, 0x0, 0x0, 0x0, 0x29, 6}, + {3, 0xC, 0x1, 0x0, 0x0, 0x09, 6}, + {3, 0xD, 0x0, 0x0, 0x0, 0x37, 7}, + {3, 0xD, 0x1, 0x4, 0x4, 0x57, 7}, + {3, 0xD, 0x1, 0x4, 0x0, 0x31, 6}, + {3, 0xE, 0x0, 0x0, 0x0, 0x67, 7}, + {3, 0xE, 0x1, 0x4, 0x4, 0x27, 7}, + {3, 0xE, 0x1, 0xC, 0x8, 0x47, 7}, + {3, 0xE, 0x1, 0xE, 0x2, 0x6B, 7}, + {3, 0xF, 0x0, 0x0, 0x0, 0x11, 6}, + {3, 0xF, 0x1, 0x6, 0x6, 0x07, 7}, + {3, 0xF, 0x1, 0x7, 0x3, 0x7B, 7}, + {3, 0xF, 0x1, 0xF, 0xA, 0x3B, 7}, + {3, 0xF, 0x1, 0xF, 0x2, 0x21, 6}, + {3, 0xF, 0x1, 0xF, 0x8, 0x01, 6}, + {3, 0xF, 0x1, 0xA, 0x8, 0x5B, 7}, + {3, 0xF, 0x1, 0xF, 0x5, 0x1B, 7}, + {3, 0xF, 0x1, 0xF, 0x1, 0x3E, 6}, + {3, 0xF, 0x1, 0xF, 0x4, 0x2B, 7}, + {4, 0x0, 0x0, 0x0, 0x0, 0x00, 1}, + {4, 0x1, 0x0, 0x0, 0x0, 0x0D, 5}, + {4, 0x1, 0x1, 0x1, 0x1, 0x7F, 7}, + {4, 0x2, 0x0, 0x0, 0x0, 0x15, 5}, + {4, 0x2, 0x1, 0x2, 0x2, 0x3F, 7}, + {4, 0x3, 0x0, 0x0, 0x0, 0x5F, 7}, + {4, 0x3, 0x1, 0x0, 0x0, 0x6F, 7}, + {4, 0x4, 0x0, 0x0, 0x0, 0x09, 4}, + {4, 0x4, 0x1, 0x4, 0x4, 0x23, 6}, + {4, 0x5, 0x0, 0x0, 0x0, 0x33, 6}, + {4, 0x5, 0x1, 0x0, 0x0, 0x1F, 7}, + {4, 0x6, 0x0, 0x0, 0x0, 0x13, 6}, + {4, 0x6, 0x1, 0x0, 0x0, 0x2F, 7}, + {4, 0x7, 0x0, 0x0, 0x0, 0x4F, 7}, + {4, 0x7, 0x1, 0x0, 0x0, 0x57, 7}, + {4, 0x8, 0x0, 0x0, 0x0, 0x01, 4}, + {4, 0x8, 0x1, 0x8, 0x8, 0x0F, 7}, + {4, 0x9, 0x0, 0x0, 0x0, 0x77, 7}, + {4, 0x9, 0x1, 0x0, 0x0, 0x37, 7}, + {4, 0xA, 0x0, 0x0, 0x0, 0x1D, 6}, + {4, 0xA, 0x1, 0x0, 0x0, 0x17, 7}, + {4, 0xB, 0x0, 0x0, 0x0, 0x67, 7}, + {4, 0xB, 0x1, 0x0, 0x0, 0x6B, 7}, + {4, 0xC, 0x0, 0x0, 0x0, 0x05, 5}, + {4, 0xC, 0x1, 0xC, 0xC, 0x27, 7}, + {4, 0xC, 0x1, 0xC, 0x8, 0x47, 7}, + {4, 0xC, 0x1, 0xC, 0x4, 0x07, 7}, + {4, 0xD, 0x0, 0x0, 0x0, 0x7B, 7}, + {4, 0xD, 0x1, 0x0, 0x0, 0x3B, 7}, + {4, 0xE, 0x0, 0x0, 0x0, 0x5B, 7}, + {4, 0xE, 0x1, 0x2, 0x2, 0x1B, 7}, + {4, 0xE, 0x1, 0x2, 0x0, 0x03, 6}, + {4, 0xF, 0x0, 0x0, 0x0, 0x2B, 7}, + {4, 0xF, 0x1, 0x1, 0x1, 0x4B, 7}, + {4, 0xF, 0x1, 0x3, 0x2, 0x0B, 7}, + {4, 0xF, 0x1, 0x3, 0x0, 0x3D, 6}, + {5, 0x0, 0x0, 0x0, 0x0, 0x00, 2}, + {5, 0x1, 0x0, 0x0, 0x0, 0x1E, 5}, + {5, 0x1, 0x1, 0x1, 0x1, 0x3B, 6}, + {5, 0x2, 0x0, 0x0, 0x0, 0x0A, 5}, + {5, 0x2, 0x1, 0x2, 0x2, 0x3F, 7}, + {5, 0x3, 0x0, 0x0, 0x0, 0x1B, 6}, + {5, 0x3, 0x1, 0x0, 0x0, 0x0B, 6}, + {5, 0x4, 0x0, 0x0, 0x0, 0x02, 4}, + {5, 0x4, 0x1, 0x4, 0x4, 0x2B, 6}, + {5, 0x5, 0x0, 0x0, 0x0, 0x0E, 5}, + {5, 0x5, 0x1, 0x4, 0x4, 0x33, 6}, + {5, 0x5, 0x1, 0x5, 0x1, 0x7F, 7}, + {5, 0x6, 0x0, 0x0, 0x0, 0x13, 6}, + {5, 0x6, 0x1, 0x0, 0x0, 0x6F, 7}, + {5, 0x7, 0x0, 0x0, 0x0, 0x23, 6}, + {5, 0x7, 0x1, 0x2, 0x2, 0x5F, 7}, + {5, 0x7, 0x1, 0x2, 0x0, 0x15, 6}, + {5, 0x8, 0x0, 0x0, 0x0, 0x16, 5}, + {5, 0x8, 0x1, 0x8, 0x8, 0x03, 6}, + {5, 0x9, 0x0, 0x0, 0x0, 0x3D, 6}, + {5, 0x9, 0x1, 0x0, 0x0, 0x1F, 7}, + {5, 0xA, 0x0, 0x0, 0x0, 0x1D, 6}, + {5, 0xA, 0x1, 0x0, 0x0, 0x2D, 6}, + {5, 0xB, 0x0, 0x0, 0x0, 0x0D, 6}, + {5, 0xB, 0x1, 0x1, 0x1, 0x4F, 7}, + {5, 0xB, 0x1, 0x1, 0x0, 0x35, 6}, + {5, 0xC, 0x0, 0x0, 0x0, 0x06, 5}, + {5, 0xC, 0x1, 0x4, 0x4, 0x25, 6}, + {5, 0xC, 0x1, 0xC, 0x8, 0x2F, 7}, + {5, 0xD, 0x0, 0x0, 0x0, 0x05, 6}, + {5, 0xD, 0x1, 0x1, 0x1, 0x77, 7}, + {5, 0xD, 0x1, 0x5, 0x4, 0x39, 6}, + {5, 0xD, 0x1, 0xD, 0x8, 0x0F, 7}, + {5, 0xE, 0x0, 0x0, 0x0, 0x19, 6}, + {5, 0xE, 0x1, 0x2, 0x2, 0x57, 7}, + {5, 0xE, 0x1, 0xA, 0x8, 0x01, 6}, + {5, 0xE, 0x1, 0xE, 0x4, 0x37, 7}, + {5, 0xF, 0x0, 0x0, 0x0, 0x1A, 5}, + {5, 0xF, 0x1, 0x9, 0x9, 0x17, 7}, + {5, 0xF, 0x1, 0xD, 0x5, 0x67, 7}, + {5, 0xF, 0x1, 0xF, 0x3, 0x07, 7}, + {5, 0xF, 0x1, 0xF, 0x1, 0x29, 6}, + {5, 0xF, 0x1, 0x7, 0x6, 0x27, 7}, + {5, 0xF, 0x1, 0xF, 0xC, 0x09, 6}, + {5, 0xF, 0x1, 0xF, 0x4, 0x31, 6}, + {5, 0xF, 0x1, 0xF, 0xA, 0x47, 7}, + {5, 0xF, 0x1, 0xF, 0x8, 0x11, 6}, + {5, 0xF, 0x1, 0xF, 0x2, 0x21, 6}, + {6, 0x0, 0x0, 0x0, 0x0, 0x00, 3}, + {6, 0x1, 0x0, 0x0, 0x0, 0x02, 4}, + {6, 0x1, 0x1, 0x1, 0x1, 0x03, 6}, + {6, 0x2, 0x0, 0x0, 0x0, 0x0C, 4}, + {6, 0x2, 0x1, 0x2, 0x2, 0x3D, 6}, + {6, 0x3, 0x0, 0x0, 0x0, 0x1D, 6}, + {6, 0x3, 0x1, 0x2, 0x2, 0x0D, 6}, + {6, 0x3, 0x1, 0x3, 0x1, 0x7F, 7}, + {6, 0x4, 0x0, 0x0, 0x0, 0x04, 4}, + {6, 0x4, 0x1, 0x4, 0x4, 0x2D, 6}, + {6, 0x5, 0x0, 0x0, 0x0, 0x0A, 5}, + {6, 0x5, 0x1, 0x4, 0x4, 0x35, 6}, + {6, 0x5, 0x1, 0x5, 0x1, 0x2F, 7}, + {6, 0x6, 0x0, 0x0, 0x0, 0x15, 6}, + {6, 0x6, 0x1, 0x2, 0x2, 0x3F, 7}, + {6, 0x6, 0x1, 0x6, 0x4, 0x5F, 7}, + {6, 0x7, 0x0, 0x0, 0x0, 0x25, 6}, + {6, 0x7, 0x1, 0x2, 0x2, 0x29, 6}, + {6, 0x7, 0x1, 0x3, 0x1, 0x1F, 7}, + {6, 0x7, 0x1, 0x7, 0x4, 0x6F, 7}, + {6, 0x8, 0x0, 0x0, 0x0, 0x16, 5}, + {6, 0x8, 0x1, 0x8, 0x8, 0x05, 6}, + {6, 0x9, 0x0, 0x0, 0x0, 0x39, 6}, + {6, 0x9, 0x1, 0x0, 0x0, 0x19, 6}, + {6, 0xA, 0x0, 0x0, 0x0, 0x06, 5}, + {6, 0xA, 0x1, 0xA, 0xA, 0x0F, 7}, + {6, 0xA, 0x1, 0xA, 0x2, 0x09, 6}, + {6, 0xA, 0x1, 0xA, 0x8, 0x4F, 7}, + {6, 0xB, 0x0, 0x0, 0x0, 0x0E, 6}, + {6, 0xB, 0x1, 0xB, 0x2, 0x77, 7}, + {6, 0xB, 0x1, 0x2, 0x2, 0x37, 7}, + {6, 0xB, 0x1, 0xA, 0x8, 0x57, 7}, + {6, 0xB, 0x1, 0xB, 0x1, 0x47, 7}, + {6, 0xC, 0x0, 0x0, 0x0, 0x1A, 5}, + {6, 0xC, 0x1, 0xC, 0xC, 0x17, 7}, + {6, 0xC, 0x1, 0xC, 0x8, 0x67, 7}, + {6, 0xC, 0x1, 0xC, 0x4, 0x27, 7}, + {6, 0xD, 0x0, 0x0, 0x0, 0x31, 6}, + {6, 0xD, 0x1, 0xD, 0x4, 0x07, 7}, + {6, 0xD, 0x1, 0x4, 0x4, 0x7B, 7}, + {6, 0xD, 0x1, 0xC, 0x8, 0x3B, 7}, + {6, 0xD, 0x1, 0xD, 0x1, 0x2B, 7}, + {6, 0xE, 0x0, 0x0, 0x0, 0x11, 6}, + {6, 0xE, 0x1, 0xE, 0x4, 0x5B, 7}, + {6, 0xE, 0x1, 0x4, 0x4, 0x1B, 7}, + {6, 0xE, 0x1, 0xE, 0xA, 0x6B, 7}, + {6, 0xE, 0x1, 0xE, 0x8, 0x21, 6}, + {6, 0xE, 0x1, 0xE, 0x2, 0x33, 7}, + {6, 0xF, 0x0, 0x0, 0x0, 0x01, 6}, + {6, 0xF, 0x1, 0x3, 0x3, 0x4B, 7}, + {6, 0xF, 0x1, 0x7, 0x6, 0x0B, 7}, + {6, 0xF, 0x1, 0xF, 0xA, 0x73, 7}, + {6, 0xF, 0x1, 0xF, 0x2, 0x3E, 6}, + {6, 0xF, 0x1, 0xB, 0x9, 0x53, 7}, + {6, 0xF, 0x1, 0xF, 0xC, 0x63, 7}, + {6, 0xF, 0x1, 0xF, 0x8, 0x1E, 6}, + {6, 0xF, 0x1, 0xF, 0x5, 0x13, 7}, + {6, 0xF, 0x1, 0xF, 0x4, 0x2E, 6}, + {6, 0xF, 0x1, 0xF, 0x1, 0x23, 7}, + {7, 0x0, 0x0, 0x0, 0x0, 0x04, 4}, + {7, 0x1, 0x0, 0x0, 0x0, 0x33, 6}, + {7, 0x1, 0x1, 0x1, 0x1, 0x13, 6}, + {7, 0x2, 0x0, 0x0, 0x0, 0x23, 6}, + {7, 0x2, 0x1, 0x2, 0x2, 0x7F, 7}, + {7, 0x3, 0x0, 0x0, 0x0, 0x03, 6}, + {7, 0x3, 0x1, 0x1, 0x1, 0x3F, 7}, + {7, 0x3, 0x1, 0x3, 0x2, 0x6F, 7}, + {7, 0x4, 0x0, 0x0, 0x0, 0x2D, 6}, + {7, 0x4, 0x1, 0x4, 0x4, 0x5F, 7}, + {7, 0x5, 0x0, 0x0, 0x0, 0x16, 5}, + {7, 0x5, 0x1, 0x1, 0x1, 0x3D, 6}, + {7, 0x5, 0x1, 0x5, 0x4, 0x1F, 7}, + {7, 0x6, 0x0, 0x0, 0x0, 0x1D, 6}, + {7, 0x6, 0x1, 0x0, 0x0, 0x77, 7}, + {7, 0x7, 0x0, 0x0, 0x0, 0x06, 5}, + {7, 0x7, 0x1, 0x7, 0x4, 0x2F, 7}, + {7, 0x7, 0x1, 0x4, 0x4, 0x4F, 7}, + {7, 0x7, 0x1, 0x7, 0x3, 0x0F, 7}, + {7, 0x7, 0x1, 0x7, 0x1, 0x0D, 6}, + {7, 0x7, 0x1, 0x7, 0x2, 0x57, 7}, + {7, 0x8, 0x0, 0x0, 0x0, 0x35, 6}, + {7, 0x8, 0x1, 0x8, 0x8, 0x37, 7}, + {7, 0x9, 0x0, 0x0, 0x0, 0x15, 6}, + {7, 0x9, 0x1, 0x0, 0x0, 0x27, 7}, + {7, 0xA, 0x0, 0x0, 0x0, 0x25, 6}, + {7, 0xA, 0x1, 0x0, 0x0, 0x29, 6}, + {7, 0xB, 0x0, 0x0, 0x0, 0x1A, 5}, + {7, 0xB, 0x1, 0xB, 0x1, 0x17, 7}, + {7, 0xB, 0x1, 0x1, 0x1, 0x67, 7}, + {7, 0xB, 0x1, 0x3, 0x2, 0x05, 6}, + {7, 0xB, 0x1, 0xB, 0x8, 0x7B, 7}, + {7, 0xC, 0x0, 0x0, 0x0, 0x39, 6}, + {7, 0xC, 0x1, 0x0, 0x0, 0x19, 6}, + {7, 0xD, 0x0, 0x0, 0x0, 0x0C, 5}, + {7, 0xD, 0x1, 0xD, 0x1, 0x47, 7}, + {7, 0xD, 0x1, 0x1, 0x1, 0x07, 7}, + {7, 0xD, 0x1, 0x5, 0x4, 0x09, 6}, + {7, 0xD, 0x1, 0xD, 0x8, 0x1B, 7}, + {7, 0xE, 0x0, 0x0, 0x0, 0x31, 6}, + {7, 0xE, 0x1, 0xE, 0x2, 0x3B, 7}, + {7, 0xE, 0x1, 0x2, 0x2, 0x5B, 7}, + {7, 0xE, 0x1, 0xA, 0x8, 0x3E, 6}, + {7, 0xE, 0x1, 0xE, 0x4, 0x0B, 7}, + {7, 0xF, 0x0, 0x0, 0x0, 0x00, 3}, + {7, 0xF, 0x1, 0xF, 0xF, 0x6B, 7}, + {7, 0xF, 0x1, 0xF, 0x7, 0x2B, 7}, + {7, 0xF, 0x1, 0xF, 0xB, 0x4B, 7}, + {7, 0xF, 0x1, 0xF, 0x3, 0x11, 6}, + {7, 0xF, 0x1, 0x7, 0x6, 0x21, 6}, + {7, 0xF, 0x1, 0xF, 0xA, 0x01, 6}, + {7, 0xF, 0x1, 0xF, 0x2, 0x0A, 5}, + {7, 0xF, 0x1, 0xB, 0x9, 0x1E, 6}, + {7, 0xF, 0x1, 0xF, 0xC, 0x0E, 6}, + {7, 0xF, 0x1, 0xF, 0x8, 0x12, 5}, + {7, 0xF, 0x1, 0xF, 0x5, 0x2E, 6}, + {7, 0xF, 0x1, 0xF, 0x1, 0x02, 5}, + {7, 0xF, 0x1, 0xF, 0x4, 0x1C, 5} +}; + +//************************************************************************/ +/** @defgroup vlc_decoding_tables_grp VLC decoding tables + * @{ + * VLC tables to decode VLC codewords to these fields: (in order) \n + * \li \c cwd_len : 3bits -> the codeword length of the VLC codeword; + * the VLC cwd is in the LSB of bitstream \n + * \li \c u_off : 1bit -> u_offset, which is 1 if u value is not 0 \n + * \li \c rho : 4bits -> significant samples within a quad \n + * \li \c e_1 : 4bits -> EMB e_1 \n + * \li \c e_k : 4bits -> EMB e_k \n + * \n + * The table index is 10 bits and composed of two parts: \n + * The 7 LSBs contain a codeword which might be shorter than 7 bits; + * this word is the next decoable bits in the bitstream. \n + * The 3 MSB is the context of for the codeword. \n + */ + +/// @brief vlc_tbl0 contains decoding information for initial row of quads +int vlc_tbl0[1024] = { 0 }; +/// @brief vlc_tbl1 contains decoding information for non-initial row of +/// quads +int vlc_tbl1[1024] = { 0 }; +/// @} + +//************************************************************************/ +/** @ingroup vlc_decoding_tables_grp + * @brief Initializes vlc_tbl0 and vlc_tbl1 tables, from table0.h and + * table1.h + */ +OPJ_BOOL vlc_init_tables() +{ + const OPJ_BOOL debug = OPJ_FALSE; //useful for checking + + // number of entries in the table + size_t tbl0_size = sizeof(tbl0) / sizeof(vlc_src_table_t); + + // number of entries in the table + size_t tbl1_size = sizeof(tbl1) / sizeof(vlc_src_table_t); + + if (debug) { + memset(vlc_tbl0, 0, sizeof(vlc_tbl0)); //unnecessary + } + + // this is to convert table entries into values for decoder look up + // There can be at most 1024 possibilities, not all of them are valid. + // + for (int i = 0; i < 1024; ++i) { + int cwd = i & 0x7F; // from i extract codeword + int c_q = i >> 7; // from i extract context + // See if this case exist in the table, if so then set the entry in + // vlc_tbl0 + for (size_t j = 0; j < tbl0_size; ++j) + if (tbl0[j].c_q == c_q) // this is an and operation + if (tbl0[j].cwd == (cwd & ((1 << tbl0[j].cwd_len) - 1))) { + if (debug) { + assert(vlc_tbl0[i] == 0); + } + // Put this entry into the table + vlc_tbl0[i] = (tbl0[j].rho << 4) | (tbl0[j].u_off << 3) + | (tbl0[j].e_k << 12) | (tbl0[j].e_1 << 8) | tbl0[j].cwd_len; + } + } + + if (debug) { + memset(vlc_tbl1, 0, sizeof(vlc_tbl1)); //unnecessary + } + + // this the same as above but for non-initial rows + for (int i = 0; i < 1024; ++i) { + int cwd = i & 0x7F; //7 bits + int c_q = i >> 7; + for (size_t j = 0; j < tbl1_size; ++j) + if (tbl1[j].c_q == c_q) // this is an and operation + if (tbl1[j].cwd == (cwd & ((1 << tbl1[j].cwd_len) - 1))) { + if (debug) { + assert(vlc_tbl1[i] == 0); + } + vlc_tbl1[i] = (tbl1[j].rho << 4) | (tbl1[j].u_off << 3) + | (tbl1[j].e_k << 12) | (tbl1[j].e_1 << 8) | tbl1[j].cwd_len; + } + } + + return OPJ_TRUE; +} + +//************************************************************************/ +/** @ingroup vlc_decoding_tables_grp + * @brief Initializes VLC tables vlc_tbl0 and vlc_tbl1 + */ +OPJ_BOOL vlc_tables_initialized = OPJ_FALSE; + diff --git a/src/lib/openjp2/t1_ht_luts.h b/src/lib/openjp2/t1_ht_luts.h new file mode 100644 index 00000000000..393a987b029 --- /dev/null +++ b/src/lib/openjp2/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 +}; diff --git a/src/lib/openjp2/t1_luts.h b/src/lib/openjp2/t1_luts.h new file mode 100644 index 00000000000..1a5e7844f76 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/t2.c b/src/lib/openjp2/t2.c new file mode 100644 index 00000000000..781a6a59a16 --- /dev/null +++ b/src/lib/openjp2/t2.c @@ -0,0 +1,1695 @@ +/* + * 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) { + 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) { + if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - + *l_header_data_start)) < 2U) { + opj_event_msg(p_manager, EVT_WARNING, + "Not enough space for expected EPH marker\n"); + } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { + opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n"); + } 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) { + if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data - + *l_header_data_start)) < 2U) { + opj_event_msg(p_manager, EVT_WARNING, + "Not enough space for expected EPH marker\n"); + } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) { + opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n"); + } 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); + 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) { + opj_tcd_seg_t *l_seg = 00; + + // if we have a partial data stream, set numchunks to zero + // since we have no data to actually decode. + if (partial_buffer) { + l_cblk->numchunks = 0; + } + + 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 (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 since it is a partial read + partial_buffer = OPJ_TRUE; + l_cblk->numchunks = 0; + + l_seg->numpasses += l_seg->numnewpasses; + l_cblk->numnewpasses -= l_seg->numnewpasses; + if (l_cblk->numnewpasses > 0) { + ++l_seg; + ++l_cblk->numsegs; + break; + } + continue; + } + } + +#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; + ++l_cblk; + } /* 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); + 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/src/lib/openjp2/t2.h b/src/lib/openjp2/t2.h new file mode 100644 index 00000000000..becfa91a4de --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/tcd.c b/src/lib/openjp2/tcd.c new file mode 100644 index 00000000000..687aa61bb09 --- /dev/null +++ b/src/lib/openjp2/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 + * invokation 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 componenent 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 componenent 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/src/lib/openjp2/tcd.h b/src/lib/openjp2/tcd.h new file mode 100644 index 00000000000..f659869a134 --- /dev/null +++ b/src/lib/openjp2/tcd.h @@ -0,0 +1,511 @@ +/* + * 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_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 shoul 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 meory. + * + * @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 contributs 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/src/lib/openjp2/test_sparse_array.c b/src/lib/openjp2/test_sparse_array.c new file mode 100644 index 00000000000..8e1364515d7 --- /dev/null +++ b/src/lib/openjp2/test_sparse_array.c @@ -0,0 +1,174 @@ +/* + * 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. + */ + +#undef NDEBUG + +#include "opj_includes.h" + +int main() +{ + OPJ_UINT32 i, j, w, h; + OPJ_INT32 buffer[ 99 * 101 ]; + OPJ_BOOL ret; + opj_sparse_array_int32_t* sa; + + sa = opj_sparse_array_int32_create(0, 1, 1, 1); + assert(sa == NULL); + opj_sparse_array_int32_free(sa); + + sa = opj_sparse_array_int32_create(1, 0, 1, 1); + assert(sa == NULL); + + sa = opj_sparse_array_int32_create(1, 1, 0, 1); + assert(sa == NULL); + + sa = opj_sparse_array_int32_create(1, 1, 1, 0); + assert(sa == NULL); + + sa = opj_sparse_array_int32_create(99, 101, ~0U, ~0U); + assert(sa == NULL); + + sa = opj_sparse_array_int32_create(99, 101, 15, 17); + opj_sparse_array_int32_free(sa); + + sa = opj_sparse_array_int32_create(99, 101, 15, 17); + ret = opj_sparse_array_int32_read(sa, 0, 0, 0, 1, buffer, 1, 1, OPJ_FALSE); + assert(!ret); + ret = opj_sparse_array_int32_read(sa, 0, 0, 1, 0, buffer, 1, 1, OPJ_FALSE); + assert(!ret); + ret = opj_sparse_array_int32_read(sa, 0, 0, 100, 1, buffer, 1, 1, OPJ_FALSE); + assert(!ret); + ret = opj_sparse_array_int32_read(sa, 0, 0, 1, 102, buffer, 1, 1, OPJ_FALSE); + assert(!ret); + ret = opj_sparse_array_int32_read(sa, 1, 0, 0, 1, buffer, 1, 1, OPJ_FALSE); + assert(!ret); + ret = opj_sparse_array_int32_read(sa, 0, 1, 1, 0, buffer, 1, 1, OPJ_FALSE); + assert(!ret); + ret = opj_sparse_array_int32_read(sa, 99, 101, 99, 101, buffer, 1, 1, + OPJ_FALSE); + assert(!ret); + + buffer[0] = 1; + ret = opj_sparse_array_int32_read(sa, 0, 0, 1, 1, buffer, 1, 1, OPJ_FALSE); + assert(ret); + assert(buffer[0] == 0); + + memset(buffer, 0xFF, sizeof(buffer)); + ret = opj_sparse_array_int32_read(sa, 0, 0, 99, 101, buffer, 1, 99, OPJ_FALSE); + assert(ret); + for (i = 0; i < 99 * 101; i++) { + assert(buffer[i] == 0); + } + + buffer[0] = 1; + ret = opj_sparse_array_int32_write(sa, 4, 5, 4 + 1, 5 + 1, buffer, 1, 1, + OPJ_FALSE); + assert(ret); + + buffer[0] = 2; + ret = opj_sparse_array_int32_write(sa, 4, 5, 4 + 1, 5 + 1, buffer, 1, 1, + OPJ_FALSE); + assert(ret); + + buffer[0] = 0; + buffer[1] = 0xFF; + ret = opj_sparse_array_int32_read(sa, 4, 5, 4 + 1, 5 + 1, buffer, 1, 1, + OPJ_FALSE); + assert(ret); + assert(buffer[0] == 2); + assert(buffer[1] == 0xFF); + + buffer[0] = 0xFF; + buffer[1] = 0xFF; + buffer[2] = 0xFF; + ret = opj_sparse_array_int32_read(sa, 4, 5, 4 + 1, 5 + 2, buffer, 0, 1, + OPJ_FALSE); + assert(ret); + assert(buffer[0] == 2); + assert(buffer[1] == 0); + assert(buffer[2] == 0xFF); + + buffer[0] = 3; + ret = opj_sparse_array_int32_write(sa, 4, 5, 4 + 1, 5 + 1, buffer, 0, 1, + OPJ_FALSE); + assert(ret); + + buffer[0] = 0; + buffer[1] = 0xFF; + ret = opj_sparse_array_int32_read(sa, 4, 5, 4 + 1, 5 + 1, buffer, 1, 1, + OPJ_FALSE); + assert(ret); + assert(buffer[0] == 3); + assert(buffer[1] == 0xFF); + + w = 15 + 1; + h = 17 + 1; + memset(buffer, 0xFF, sizeof(buffer)); + ret = opj_sparse_array_int32_read(sa, 2, 1, 2 + w, 1 + h, buffer, 1, w, + OPJ_FALSE); + assert(ret); + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + if (i == 4 - 2 && j == 5 - 1) { + assert(buffer[ j * w + i ] == 3); + } else { + assert(buffer[ j * w + i ] == 0); + } + } + } + + opj_sparse_array_int32_free(sa); + + + sa = opj_sparse_array_int32_create(99, 101, 15, 17); + memset(buffer, 0xFF, sizeof(buffer)); + ret = opj_sparse_array_int32_read(sa, 0, 0, 2, 1, buffer, 2, 4, OPJ_FALSE); + assert(ret); + assert(buffer[0] == 0); + assert(buffer[1] == -1); + assert(buffer[2] == 0); + + buffer[0] = 1; + buffer[2] = 3; + ret = opj_sparse_array_int32_write(sa, 0, 0, 2, 1, buffer, 2, 4, OPJ_FALSE); + assert(ret); + + memset(buffer, 0xFF, sizeof(buffer)); + ret = opj_sparse_array_int32_read(sa, 0, 0, 2, 1, buffer, 2, 4, OPJ_FALSE); + assert(ret); + assert(buffer[0] == 1); + assert(buffer[1] == -1); + assert(buffer[2] == 3); + + opj_sparse_array_int32_free(sa); + + return 0; +} diff --git a/src/lib/openjp2/tgt.c b/src/lib/openjp2/tgt.c new file mode 100644 index 00000000000..711d753f46c --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/tgt.h b/src/lib/openjp2/tgt.h new file mode 100644 index 00000000000..9818208b820 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/thix_manager.c b/src/lib/openjp2/thix_manager.c new file mode 100644 index 00000000000..8a2f4f268e5 --- /dev/null +++ b/src/lib/openjp2/thix_manager.c @@ -0,0 +1,146 @@ +/* + * $Id: thix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * 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. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include "opj_includes.h" + + + +int opj_write_thix(int coff, opj_codestream_info_t cstr_info, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [4]; + int i; + int tileno; + opj_jp2_box_t *box; + OPJ_UINT32 len; + OPJ_OFF_T lenp; + + lenp = 0; + box = (opj_jp2_box_t *)opj_calloc((size_t)(cstr_info.tw * cstr_info.th), + sizeof(opj_jp2_box_t)); + if (box == NULL) { + return 0; + } + for (i = 0; i < 2 ; i++) { + if (i) { + opj_stream_seek(cio, lenp, p_manager); + } + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_THIX, 4); /* THIX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + opj_write_manf(i, cstr_info.tw * cstr_info.th, box, cio, p_manager); + + for (tileno = 0; tileno < cstr_info.tw * cstr_info.th; tileno++) { + box[tileno].length = (OPJ_UINT32)opj_write_tilemhix(coff, cstr_info, tileno, + cio, p_manager); + box[tileno].type = JPIP_MHIX; + } + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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); + + } + + opj_free(box); + + return (int)len; +} + +/* + * Write tile-part headers mhix box + * + * @param[in] coff offset of j2k codestream + * @param[in] cstr_info codestream information + * @param[in] tileno tile number + * @param[in] cio file output handle + * @return length of mhix box + */ +int opj_write_tilemhix(int coff, opj_codestream_info_t cstr_info, int tileno, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [8]; + int i; + opj_tile_info_t tile; + opj_tp_info_t tp; + opj_marker_info_t *marker; + OPJ_UINT32 len; + OPJ_OFF_T lenp; + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, + p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_MHIX, + 4); /* MHIX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + tile = cstr_info.tile[tileno]; + tp = tile.tp[0]; + + opj_write_bytes(l_data_header, + (OPJ_UINT32)(tp.tp_end_header - tp.tp_start_pos + 1), + 8); /* TLEN */ + opj_stream_write_data(cio, l_data_header, 8, p_manager); + + marker = cstr_info.tile[tileno].marker; + + for (i = 0; i < cstr_info.tile[tileno].marknum; + i++) { /* Marker restricted to 1 apparition */ + opj_write_bytes(l_data_header, marker[i].type, 2); + opj_write_bytes(l_data_header + 2, 0, 2); + opj_stream_write_data(cio, l_data_header, 4, p_manager); + opj_write_bytes(l_data_header, (OPJ_UINT32)(marker[i].pos - coff), 8); + opj_stream_write_data(cio, l_data_header, 8, p_manager); + opj_write_bytes(l_data_header, (OPJ_UINT32)marker[i].len, 2); + opj_stream_write_data(cio, l_data_header, 2, p_manager); + } + + /* free( marker);*/ + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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 (int)len; +} diff --git a/src/lib/openjp2/thread.c b/src/lib/openjp2/thread.c new file mode 100644 index 00000000000..240810b1c44 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/thread.h b/src/lib/openjp2/thread.h new file mode 100644 index 00000000000..c89e19b4a6a --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/tls_keys.h b/src/lib/openjp2/tls_keys.h new file mode 100644 index 00000000000..23f84754184 --- /dev/null +++ b/src/lib/openjp2/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/src/lib/openjp2/tpix_manager.c b/src/lib/openjp2/tpix_manager.c new file mode 100644 index 00000000000..86701f32ace --- /dev/null +++ b/src/lib/openjp2/tpix_manager.c @@ -0,0 +1,190 @@ +/* + * $Id: tpix_manager.c 897 2011-08-28 21:43:57Z Kaori.Hagihara@gmail.com $ + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2004, Yannick Verschueren + * Copyright (c) 2010-2011, Kaori Hagihara + * 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. + */ + +/*! \file + * \brief Modification of jpip.c from 2KAN indexer + */ + +#include "opj_includes.h" + +#define MAX(a,b) ((a)>(b)?(a):(b)) + +/* + * Get number of maximum tile parts per tile + * + * @param[in] cstr_info codestream information + * @return number of maximum tile parts per tile + */ +int get_num_max_tile_parts(opj_codestream_info_t cstr_info); + + +/* + * Write faix box of tpix + * + * @param[in] coff offset of j2k codestream + * @param[in] compno component number + * @param[in] cstr_info codestream information + * @param[in] j2klen length of j2k codestream + * @param[in] cio file output handle + * @return length of faix box + */ + +int opj_write_tpix(int coff, + opj_codestream_info_t cstr_info, + int j2klen, opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_BYTE l_data_header [4]; + OPJ_UINT32 len; + OPJ_OFF_T lenp; + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); + opj_write_bytes(l_data_header, JPIP_TPIX, 4); /* TPIX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + opj_write_tpixfaix(coff, 0, cstr_info, j2klen, cio, p_manager); + + len = (OPJ_UINT32)(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 (int)len; +} + +int opj_write_tpixfaix(int coff, + int compno, + opj_codestream_info_t cstr_info, + int j2klen, + opj_stream_private_t *cio, + opj_event_mgr_t * p_manager) +{ + OPJ_UINT32 len; + OPJ_OFF_T lenp; + OPJ_UINT32 i, j; + OPJ_UINT32 Aux; + OPJ_UINT32 num_max_tile_parts; + OPJ_UINT32 size_of_coding; /* 4 or 8 */ + opj_tp_info_t tp; + OPJ_BYTE l_data_header [8]; + OPJ_UINT32 version; + + num_max_tile_parts = (OPJ_UINT32)get_num_max_tile_parts(cstr_info); + + if (j2klen > pow(2, 32)) { + size_of_coding = 8; + version = num_max_tile_parts == 1 ? 1 : 3; + } else { + size_of_coding = 4; + version = num_max_tile_parts == 1 ? 0 : 2; + } + + lenp = opj_stream_tell(cio); + opj_stream_skip(cio, 4, p_manager); /* L [at the end] */ + opj_write_bytes(l_data_header, JPIP_FAIX, 4); /* FAIX */ + opj_stream_write_data(cio, l_data_header, 4, p_manager); + opj_write_bytes(l_data_header, version, 1); /* Version 0 = 4 bytes */ + opj_stream_write_data(cio, l_data_header, 1, p_manager); + + opj_write_bytes(l_data_header, num_max_tile_parts, + size_of_coding); /* NMAX */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + opj_write_bytes(l_data_header, (OPJ_UINT32)(cstr_info.tw * cstr_info.th), + size_of_coding); /* M */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + + for (i = 0; i < (OPJ_UINT32)(cstr_info.tw * cstr_info.th); i++) { + for (j = 0; j < (OPJ_UINT32)cstr_info.tile[i].num_tps; j++) { + tp = cstr_info.tile[i].tp[j]; + + opj_write_bytes(l_data_header, (OPJ_UINT32)(tp.tp_start_pos - coff), + size_of_coding); /* start position */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + opj_write_bytes(l_data_header, + (OPJ_UINT32)(tp.tp_end_pos - tp.tp_start_pos + 1), + size_of_coding); /* length */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + + if (version & 0x02) { + if (cstr_info.tile[i].num_tps == 1 && cstr_info.numdecompos[compno] > 1) { + Aux = (OPJ_UINT32)(cstr_info.numdecompos[compno] + 1); + } else { + Aux = j + 1; + } + + opj_write_bytes(l_data_header, Aux, 4); + opj_stream_write_data(cio, l_data_header, 4, p_manager); + + /*cio_write(img.tile[i].tile_parts[j].num_reso_AUX,4);*/ /* Aux_i,j : Auxiliary value */ + /* fprintf(stderr,"AUX value %d\n",Aux);*/ + } + /*cio_write(0,4);*/ + } + /* PADDING */ + while (j < num_max_tile_parts) { + + opj_write_bytes(l_data_header, 0, + size_of_coding); /* start position */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + opj_write_bytes(l_data_header, 0, + size_of_coding); /* length */ + opj_stream_write_data(cio, l_data_header, size_of_coding, p_manager); + + if (version & 0x02) { + opj_write_bytes(l_data_header, 0, 4); /* Aux_i,j : Auxiliary value */ + } + opj_stream_write_data(cio, l_data_header, 4, p_manager); + j++; + } + } + + len = (OPJ_UINT32)(opj_stream_tell(cio) - lenp); + opj_stream_seek(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 (int)len; +} + +int get_num_max_tile_parts(opj_codestream_info_t cstr_info) +{ + int num_max_tp = 0, i; + + for (i = 0; i < cstr_info.tw * cstr_info.th; i++) { + num_max_tp = MAX(cstr_info.tile[i].num_tps, num_max_tp); + } + + return num_max_tp; +} From 239e2c4a441cf2ea3d17f9b600c3f65543b20b1d Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Tue, 3 Dec 2024 12:10:43 -0500 Subject: [PATCH 4/7] ENH: openjpeg: customize build for ITK integration --- Modules/ThirdParty/OpenJPEG/CMakeLists.txt | 5 ++- .../ThirdParty/OpenJPEG/src/itk_openjpeg.h | 4 +- .../OpenJPEG/src/openjpeg/CMakeLists.txt | 40 +++++++++++++++++-- .../OpenJPEG/src/openjpeg/src/CMakeLists.txt | 12 ++++++ .../openjpeg/src/lib/openjp2/CMakeLists.txt | 26 +++++++++++- .../src/openjpeg/src/lib/openjp2/openjpeg.h | 5 +++ 6 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/src/CMakeLists.txt diff --git a/Modules/ThirdParty/OpenJPEG/CMakeLists.txt b/Modules/ThirdParty/OpenJPEG/CMakeLists.txt index 103eaa9dd57..51ab3a86395 100644 --- a/Modules/ThirdParty/OpenJPEG/CMakeLists.txt +++ b/Modules/ThirdParty/OpenJPEG/CMakeLists.txt @@ -2,8 +2,9 @@ project(ITKOpenJPEG) set(ITKOpenJPEG_THIRD_PARTY 1) set(ITKOpenJPEG_INCLUDE_DIRS - ${ITKOpenJPEG_BINARY_DIR}/src/openjpeg - ${ITKOpenJPEG_SOURCE_DIR}/src/openjpeg + ${ITKOpenJPEG_SOURCE_DIR}/src/ + ${ITKOpenJPEG_BINARY_DIR}/src/openjpeg/src/lib/openjp2 + ${ITKOpenJPEG_SOURCE_DIR}/src/openjpeg/src/lib/openjp2 ) set(ITKOpenJPEG_LIBRARIES itkopenjpeg) set(ITK_LIBRARY_PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS FALSE) diff --git a/Modules/ThirdParty/OpenJPEG/src/itk_openjpeg.h b/Modules/ThirdParty/OpenJPEG/src/itk_openjpeg.h index 2ad00098a16..cb734f93d2a 100644 --- a/Modules/ThirdParty/OpenJPEG/src/itk_openjpeg.h +++ b/Modules/ThirdParty/OpenJPEG/src/itk_openjpeg.h @@ -25,6 +25,8 @@ #ifndef itk_openjpeg_h #define itk_openjpeg_h -#include +#include +#include + #endif diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/CMakeLists.txt b/Modules/ThirdParty/OpenJPEG/src/openjpeg/CMakeLists.txt index 65570b4452b..39b940b9e0b 100644 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/CMakeLists.txt +++ b/Modules/ThirdParty/OpenJPEG/src/openjpeg/CMakeLists.txt @@ -6,7 +6,7 @@ # you will eventually like to prefix the library to avoid linking confusion # For this purpose you can define a CMake var: OPENJPEG_NAMESPACE to whatever you like # e.g.: -# set(OPENJPEG_NAMESPACE "GDCMOPENJPEG") +set(OPENJPEG_NAMESPACE "ITKOPENJPEG") cmake_minimum_required(VERSION 3.5) if(NOT OPENJPEG_NAMESPACE) @@ -14,8 +14,8 @@ if(NOT OPENJPEG_NAMESPACE) set(OPENJPEG_STANDALONE 1) endif() # In all cases: -#string(TOLOWER ${OPENJPEG_NAMESPACE} OPENJPEG_LIBRARY_NAME) -set(OPENJPEG_LIBRARY_NAME openjp2) +string(TOLOWER ${OPENJPEG_NAMESPACE} OPENJPEG_LIBRARY_NAME) +#set(OPENJPEG_LIBRARY_NAME openjp2) project(${OPENJPEG_NAMESPACE} C) @@ -103,8 +103,11 @@ endif() string(TOLOWER ${PROJECT_NAME} PROJECT_NAME) include(GNUInstallDirs) +#[[ --ITK # Build DOCUMENTATION (not in ALL target and only if Doxygen is found) option(BUILD_DOC "Build the HTML documentation (with doxygen if available)." OFF) +# -- ITK ]] +set(BUILD_DOC OFF) set(OPENJPEG_INSTALL_SUBDIR "${PROJECT_NAME}-${OPENJPEG_VERSION_MAJOR}.${OPENJPEG_VERSION_MINOR}") @@ -121,7 +124,10 @@ if(NOT OPENJPEG_INSTALL_PACKAGE_DIR) endif() if (APPLE) + #[[ --ITK option(OPJ_USE_DSYMUTIL "Call dsymutil on binaries after build." OFF) + # --ITK ]] + set(OPJ_USE_DSYMUTIL OFF) endif() #----------------------------------------------------------------------------- @@ -133,12 +139,15 @@ endif() #----------------------------------------------------------------------------- # Setup file for setting custom ctest vars +#[[ --ITK configure_file( ${${OPENJPEG_NAMESPACE}_SOURCE_DIR}/cmake/CTestCustom.cmake.in ${${OPENJPEG_NAMESPACE}_BINARY_DIR}/CTestCustom.cmake @ONLY ) +# --ITK ]] +#[[ --ITK #----------------------------------------------------------------------------- # OpenJPEG build configuration options. option(BUILD_SHARED_LIBS "Build OpenJPEG shared library and link executables against it." ON) @@ -146,6 +155,12 @@ option(BUILD_STATIC_LIBS "Build OpenJPEG static library." ON) set (EXECUTABLE_OUTPUT_PATH ${OPENJPEG_BINARY_DIR}/bin CACHE PATH "Single output directory for building all executables.") set (LIBRARY_OUTPUT_PATH ${OPENJPEG_BINARY_DIR}/bin CACHE PATH "Single output directory for building all libraries.") mark_as_advanced(LIBRARY_OUTPUT_PATH EXECUTABLE_OUTPUT_PATH) +# --ITK ]] +if (BUILD_SHARED_LIBS) + set(BUILD_STATIC_LIBS OFF) +else() + set(BUILD_STATIC_LIBS ON) +endif () #----------------------------------------------------------------------------- # configure name mangling to allow multiple libraries to coexist @@ -220,13 +235,18 @@ if(BUILD_JPIP_SERVER) endif() endif() add_subdirectory(src/lib) +#[[ --ITK option(BUILD_LUTS_GENERATOR "Build utility to generate t1_luts.h" OFF) if(UNIX) option(BUILD_UNIT_TESTS "Build unit tests (bench_dwt, test_sparse_array, etc..)" OFF) endif() +# --ITK ]] +set(BUILD_LUTS_GENERATOR OFF) +set(BUILD_UNIT_TESTS OFF) #----------------------------------------------------------------------------- # Build Applications +#[[ --ITK option(BUILD_CODEC "Build the CODEC executables" ON) option(BUILD_JPIP "Build the JPIP library and executables." OFF) if(BUILD_JPIP) @@ -236,6 +256,12 @@ option(BUILD_VIEWER "Build the OPJViewer executable (C++)" OFF) option(BUILD_JAVA "Build the openjpeg jar (Java)" OFF) mark_as_advanced(BUILD_VIEWER) mark_as_advanced(BUILD_JAVA) +# --ITK ]] +set(BUILD_CODEC OFF) +set(BUILD_JPIP OFF) +set(BUILD_JPIP_SERVER OFF) +set(BUILD_VIEWER OFF) +set(BUILD_JAVA OFF) if(BUILD_CODEC) # OFF: It will only build 3rd party libs if they are not found on the system @@ -244,7 +270,9 @@ if(BUILD_CODEC) add_subdirectory(thirdparty) add_subdirectory(src/bin) endif () +#[[ --ITK add_subdirectory(wrapping) +# --ITK ]] #----------------------------------------------------------------------------- # opj_config.h generation (2/2) @@ -268,7 +296,10 @@ endif() #----------------------------------------------------------------------------- # Build Testing +#[[ --ITK option(BUILD_TESTING "Build the tests." OFF) +# --ITK ]] +set(BUILD_TESTING OFF) if(BUILD_TESTING) if(BUILD_CODEC) enable_testing() @@ -290,6 +321,9 @@ if(BUILD_TESTING) endif() endif() +# -- ITK - skip OpenJPEG installation +return() + #----------------------------------------------------------------------------- # install all targets referenced as OPENJPEGTargets (relocatable with CMake 3.0+) install(EXPORT OpenJPEGTargets DESTINATION ${OPENJPEG_INSTALL_PACKAGE_DIR}) diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/CMakeLists.txt b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/CMakeLists.txt new file mode 100644 index 00000000000..87526cfc494 --- /dev/null +++ b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/CMakeLists.txt @@ -0,0 +1,12 @@ +# required dep for server: +#if(BUILD_JPIP_SERVER) +# find_package(CURL REQUIRED) +# find_package(FCGI REQUIRED) +# find_package(Threads REQUIRED) +# if(NOT CMAKE_USE_PTHREADS_INIT) +# message(FATAL_ERROR "Only pthread are supported") +# endif() +#endif() + +#add_subdirectory(lib) +#add_subdirectory(bin) diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/CMakeLists.txt b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/CMakeLists.txt index 99cf580a4d1..5979ee1a005 100644 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/CMakeLists.txt +++ b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/CMakeLists.txt @@ -1,9 +1,9 @@ include_regular_expression("^.*$") -# +#[[ --ITK install( FILES ${CMAKE_CURRENT_BINARY_DIR}/opj_config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${OPENJPEG_INSTALL_SUBDIR} COMPONENT Headers) - +# -- ITK]] include_directories( ${${OPENJPEG_NAMESPACE}_BINARY_DIR}/src/lib/openjp2 # opj_config.h and opj_config_private.h ) @@ -71,7 +71,10 @@ if(BUILD_JPIP) ) endif() +#[[ -- ITK option(OPJ_DISABLE_TPSOT_FIX "Disable TPsot==TNsot fix. See https://github.com/uclouvain/openjpeg/issues/254." OFF) +# -- ITK]] +set(OPJ_DISABLE_TPSOT_FIX OFF) if(OPJ_DISABLE_TPSOT_FIX) add_definitions(-DOPJ_DISABLE_TPSOT_FIX) endif() @@ -111,6 +114,7 @@ endif() set_target_properties(${OPENJPEG_LIBRARY_NAME} PROPERTIES ${OPENJPEG_LIBRARY_PROPERTIES}) target_compile_options(${OPENJPEG_LIBRARY_NAME} PRIVATE ${OPENJP2_COMPILE_OPTIONS}) +#[[ --ITK # Install library install(TARGETS ${INSTALL_LIBS} EXPORT OpenJPEGTargets @@ -118,12 +122,27 @@ install(TARGETS ${INSTALL_LIBS} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Libraries ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT Libraries ) +# --ITK]] # Install includes files install(FILES openjpeg.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${OPENJPEG_INSTALL_SUBDIR} COMPONENT Headers ) +# -- ITK Begin +# Apply user-defined properties to the library target. +if(ITK_LIBRARY_PROPERTIES) + set_target_properties(${INSTALL_LIBS} PROPERTIES ${ITK_LIBRARY_PROPERTIES}) +endif(ITK_LIBRARY_PROPERTIES) + +install(TARGETS ${INSTALL_LIBS} + EXPORT ${ITK3P_INSTALL_EXPORT_NAME} + RUNTIME DESTINATION ${ITK3P_INSTALL_RUNTIME_DIR} COMPONENT RuntimeLibraries + LIBRARY DESTINATION ${ITK3P_INSTALL_LIBRARY_DIR} COMPONENT RuntimeLibraries + ARCHIVE DESTINATION ${ITK3P_INSTALL_ARCHIVE_DIR} COMPONENT Development +) +#-- ITK End + if(BUILD_DOC) # install man page of the library install( @@ -171,7 +190,10 @@ endif() ################################################################################# set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +#[[ -- ITK option(OPJ_USE_THREAD "Build with thread/mutex support " ON) +# -- ITK]] +set(OPJ_USE_THREAD OFF) if(NOT OPJ_USE_THREAD) add_definitions( -DMUTEX_stub) endif(NOT OPJ_USE_THREAD) diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg.h index 67d168bb578..a8c2681beb8 100644 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg.h +++ b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg.h @@ -106,11 +106,16 @@ that uses this DLL. This way any other project whose source files include this f OPJ_API functions as being imported from a DLL, whereas this DLL sees symbols defined with this macro as being exported. */ +#if 0 /* --ITK */ + ITK We only build static on windows, and the following incorrectly sets OBJ_API to import for static libs. # if defined(OPJ_EXPORTS) || defined(DLL_EXPORT) # define OPJ_API __declspec(dllexport) # else # define OPJ_API __declspec(dllimport) # endif /* OPJ_EXPORTS */ +#else +# define OPJ_API +#endif /* --ITK */ #endif /* !OPJ_STATIC || !_WIN32 */ typedef int OPJ_BOOL; From fea810ae48b0581b8120a004ab09b06180c8fc74 Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Wed, 4 Dec 2024 08:29:47 -0500 Subject: [PATCH 5/7] ENH: openjpeg and symbol mangling to interface --- .../openjpeg/src/lib/openjp2/CMakeLists.txt | 13 + .../src/openjpeg/src/lib/openjp2/openjpeg.h | 1 + .../src/lib/openjp2/openjpeg_mangle.h.in | 278 ++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg_mangle.h.in diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/CMakeLists.txt b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/CMakeLists.txt index 5979ee1a005..395d868932f 100644 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/CMakeLists.txt +++ b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/CMakeLists.txt @@ -1,5 +1,10 @@ include_regular_expression("^.*$") +set(MANGLE_PREFIX ${OPENJPEG_LIBRARY_NAME}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/openjpeg_mangle.h.in + ${CMAKE_CURRENT_BINARY_DIR}/openjpeg_mangle.h + @ONLY) + #[[ --ITK install( FILES ${CMAKE_CURRENT_BINARY_DIR}/opj_config.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${OPENJPEG_INSTALL_SUBDIR} COMPONENT Headers) @@ -141,6 +146,14 @@ install(TARGETS ${INSTALL_LIBS} LIBRARY DESTINATION ${ITK3P_INSTALL_LIBRARY_DIR} COMPONENT RuntimeLibraries ARCHIVE DESTINATION ${ITK3P_INSTALL_ARCHIVE_DIR} COMPONENT Development ) + +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/openjpeg.h + ${CMAKE_CURRENT_BINARY_DIR}/openjpeg_mangle.h + ${CMAKE_CURRENT_BINARY_DIR}/opj_config.h + DESTINATION ${ITK3P_INSTALL_INCLUDE_DIR} + COMPONENT Development +) #-- ITK End if(BUILD_DOC) diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg.h b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg.h index a8c2681beb8..97ed27d0c0e 100644 --- a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg.h +++ b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg.h @@ -127,6 +127,7 @@ typedef float OPJ_FLOAT32; typedef double OPJ_FLOAT64; typedef unsigned char OPJ_BYTE; +#include "openjpeg_mangle.h" #include typedef int8_t OPJ_INT8; diff --git a/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg_mangle.h.in b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg_mangle.h.in new file mode 100644 index 00000000000..e42140e7189 --- /dev/null +++ b/Modules/ThirdParty/OpenJPEG/src/openjpeg/src/lib/openjp2/openjpeg_mangle.h.in @@ -0,0 +1,278 @@ +#ifndef openjpeg_mangle_h +#define openjpeg_mangle_h + +/* + +OpenJPEG has a well defined versioned API and ABI that is consistent across platforms. + +The following command was used to obtain the symbol list on macOS: + +Mac: nm -g lib/libitkopenjpeg* 2> /dev/null | grep " [TDRS] " | awk '{ print substr($3, 2); }' | awk '{ sub(/@MANGLE_PREFIX@_/, ""); print }' | sed 's/\(.*\)/#define \1\ @MANGLE_PREFIX@_\1/' | sort + +The following command was used to obtain the symbol list on Linux: + +Linux: nm -g lib/libitktiff* 2> /dev/null | grep " [TDRS] " | awk '{ print $3 }' | awk '{ sub(/@MANGLE_PREFIX@_/, ""); print }' | sed 's/\(.*\)/#define \1\ @MANGLE_PREFIX@_\1/' | sort +*/ + +#define j2k_destroy_cstr_index @MANGLE_PREFIX@_j2k_destroy_cstr_index +#define j2k_dump @MANGLE_PREFIX@_j2k_dump +#define j2k_dump_image_comp_header @MANGLE_PREFIX@_j2k_dump_image_comp_header +#define j2k_dump_image_header @MANGLE_PREFIX@_j2k_dump_image_header +#define j2k_get_cstr_index @MANGLE_PREFIX@_j2k_get_cstr_index +#define j2k_get_cstr_info @MANGLE_PREFIX@_j2k_get_cstr_info +#define jp2_dump @MANGLE_PREFIX@_jp2_dump +#define jp2_get_cstr_index @MANGLE_PREFIX@_jp2_get_cstr_index +#define jp2_get_cstr_info @MANGLE_PREFIX@_jp2_get_cstr_info +#define opj_aligned_32_malloc @MANGLE_PREFIX@_opj_aligned_32_malloc +#define opj_aligned_32_realloc @MANGLE_PREFIX@_opj_aligned_32_realloc +#define opj_aligned_free @MANGLE_PREFIX@_opj_aligned_free +#define opj_aligned_malloc @MANGLE_PREFIX@_opj_aligned_malloc +#define opj_aligned_realloc @MANGLE_PREFIX@_opj_aligned_realloc +#define opj_alloc_tile_component_data @MANGLE_PREFIX@_opj_alloc_tile_component_data +#define opj_bio_create @MANGLE_PREFIX@_opj_bio_create +#define opj_bio_destroy @MANGLE_PREFIX@_opj_bio_destroy +#define opj_bio_flush @MANGLE_PREFIX@_opj_bio_flush +#define opj_bio_inalign @MANGLE_PREFIX@_opj_bio_inalign +#define opj_bio_init_dec @MANGLE_PREFIX@_opj_bio_init_dec +#define opj_bio_init_enc @MANGLE_PREFIX@_opj_bio_init_enc +#define opj_bio_numbytes @MANGLE_PREFIX@_opj_bio_numbytes +#define opj_bio_putbit @MANGLE_PREFIX@_opj_bio_putbit +#define opj_bio_read @MANGLE_PREFIX@_opj_bio_read +#define opj_bio_write @MANGLE_PREFIX@_opj_bio_write +#define opj_calculate_norms @MANGLE_PREFIX@_opj_calculate_norms +#define opj_calloc @MANGLE_PREFIX@_opj_calloc +#define opj_clock @MANGLE_PREFIX@_opj_clock +#define opj_codec_set_threads @MANGLE_PREFIX@_opj_codec_set_threads +#define opj_cond_create @MANGLE_PREFIX@_opj_cond_create +#define opj_cond_destroy @MANGLE_PREFIX@_opj_cond_destroy +#define opj_cond_signal @MANGLE_PREFIX@_opj_cond_signal +#define opj_cond_wait @MANGLE_PREFIX@_opj_cond_wait +#define opj_copy_image_header @MANGLE_PREFIX@_opj_copy_image_header +#define opj_create_compress @MANGLE_PREFIX@_opj_create_compress +#define opj_create_decompress @MANGLE_PREFIX@_opj_create_decompress +#define opj_decode @MANGLE_PREFIX@_opj_decode +#define opj_decode_tile_data @MANGLE_PREFIX@_opj_decode_tile_data +#define opj_decoder_set_strict_mode @MANGLE_PREFIX@_opj_decoder_set_strict_mode +#define opj_destroy_codec @MANGLE_PREFIX@_opj_destroy_codec +#define opj_destroy_cstr_index @MANGLE_PREFIX@_opj_destroy_cstr_index +#define opj_destroy_cstr_info @MANGLE_PREFIX@_opj_destroy_cstr_info +#define opj_dump_codec @MANGLE_PREFIX@_opj_dump_codec +#define opj_dwt_calc_explicit_stepsizes @MANGLE_PREFIX@_opj_dwt_calc_explicit_stepsizes +#define opj_dwt_decode @MANGLE_PREFIX@_opj_dwt_decode +#define opj_dwt_decode_real @MANGLE_PREFIX@_opj_dwt_decode_real +#define opj_dwt_encode @MANGLE_PREFIX@_opj_dwt_encode +#define opj_dwt_encode_real @MANGLE_PREFIX@_opj_dwt_encode_real +#define opj_dwt_getnorm @MANGLE_PREFIX@_opj_dwt_getnorm +#define opj_dwt_getnorm_real @MANGLE_PREFIX@_opj_dwt_getnorm_real +#define opj_encode @MANGLE_PREFIX@_opj_encode +#define opj_encoder_set_extra_options @MANGLE_PREFIX@_opj_encoder_set_extra_options +#define opj_end_compress @MANGLE_PREFIX@_opj_end_compress +#define opj_end_decompress @MANGLE_PREFIX@_opj_end_decompress +#define opj_event_msg @MANGLE_PREFIX@_opj_event_msg +#define opj_free @MANGLE_PREFIX@_opj_free +#define opj_get_cstr_index @MANGLE_PREFIX@_opj_get_cstr_index +#define opj_get_cstr_info @MANGLE_PREFIX@_opj_get_cstr_info +#define opj_get_decoded_tile @MANGLE_PREFIX@_opj_get_decoded_tile +#define opj_get_encoding_packet_count @MANGLE_PREFIX@_opj_get_encoding_packet_count +#define opj_get_num_cpus @MANGLE_PREFIX@_opj_get_num_cpus +#define opj_has_thread_support @MANGLE_PREFIX@_opj_has_thread_support +#define opj_image_comp_header_update @MANGLE_PREFIX@_opj_image_comp_header_update +#define opj_image_create @MANGLE_PREFIX@_opj_image_create +#define opj_image_create0 @MANGLE_PREFIX@_opj_image_create0 +#define opj_image_data_alloc @MANGLE_PREFIX@_opj_image_data_alloc +#define opj_image_data_free @MANGLE_PREFIX@_opj_image_data_free +#define opj_image_destroy @MANGLE_PREFIX@_opj_image_destroy +#define opj_image_tile_create @MANGLE_PREFIX@_opj_image_tile_create +#define opj_j2k_convert_progression_order @MANGLE_PREFIX@_opj_j2k_convert_progression_order +#define opj_j2k_create_compress @MANGLE_PREFIX@_opj_j2k_create_compress +#define opj_j2k_create_decompress @MANGLE_PREFIX@_opj_j2k_create_decompress +#define opj_j2k_decode @MANGLE_PREFIX@_opj_j2k_decode +#define opj_j2k_decode_tile @MANGLE_PREFIX@_opj_j2k_decode_tile +#define opj_j2k_decoder_set_strict_mode @MANGLE_PREFIX@_opj_j2k_decoder_set_strict_mode +#define opj_j2k_destroy @MANGLE_PREFIX@_opj_j2k_destroy +#define opj_j2k_encode @MANGLE_PREFIX@_opj_j2k_encode +#define opj_j2k_encoder_set_extra_options @MANGLE_PREFIX@_opj_j2k_encoder_set_extra_options +#define opj_j2k_end_compress @MANGLE_PREFIX@_opj_j2k_end_compress +#define opj_j2k_end_decompress @MANGLE_PREFIX@_opj_j2k_end_decompress +#define opj_j2k_get_tile @MANGLE_PREFIX@_opj_j2k_get_tile +#define opj_j2k_read_header @MANGLE_PREFIX@_opj_j2k_read_header +#define opj_j2k_read_tile_header @MANGLE_PREFIX@_opj_j2k_read_tile_header +#define opj_j2k_set_decode_area @MANGLE_PREFIX@_opj_j2k_set_decode_area +#define opj_j2k_set_decoded_components @MANGLE_PREFIX@_opj_j2k_set_decoded_components +#define opj_j2k_set_decoded_resolution_factor @MANGLE_PREFIX@_opj_j2k_set_decoded_resolution_factor +#define opj_j2k_set_threads @MANGLE_PREFIX@_opj_j2k_set_threads +#define opj_j2k_setup_decoder @MANGLE_PREFIX@_opj_j2k_setup_decoder +#define opj_j2k_setup_encoder @MANGLE_PREFIX@_opj_j2k_setup_encoder +#define opj_j2k_setup_mct_encoding @MANGLE_PREFIX@_opj_j2k_setup_mct_encoding +#define opj_j2k_start_compress @MANGLE_PREFIX@_opj_j2k_start_compress +#define opj_j2k_write_tile @MANGLE_PREFIX@_opj_j2k_write_tile +#define opj_jp2_create @MANGLE_PREFIX@_opj_jp2_create +#define opj_jp2_decode @MANGLE_PREFIX@_opj_jp2_decode +#define opj_jp2_decode_tile @MANGLE_PREFIX@_opj_jp2_decode_tile +#define opj_jp2_decoder_set_strict_mode @MANGLE_PREFIX@_opj_jp2_decoder_set_strict_mode +#define opj_jp2_destroy @MANGLE_PREFIX@_opj_jp2_destroy +#define opj_jp2_encode @MANGLE_PREFIX@_opj_jp2_encode +#define opj_jp2_encoder_set_extra_options @MANGLE_PREFIX@_opj_jp2_encoder_set_extra_options +#define opj_jp2_end_compress @MANGLE_PREFIX@_opj_jp2_end_compress +#define opj_jp2_end_decompress @MANGLE_PREFIX@_opj_jp2_end_decompress +#define opj_jp2_get_tile @MANGLE_PREFIX@_opj_jp2_get_tile +#define opj_jp2_read_header @MANGLE_PREFIX@_opj_jp2_read_header +#define opj_jp2_read_tile_header @MANGLE_PREFIX@_opj_jp2_read_tile_header +#define opj_jp2_set_decode_area @MANGLE_PREFIX@_opj_jp2_set_decode_area +#define opj_jp2_set_decoded_components @MANGLE_PREFIX@_opj_jp2_set_decoded_components +#define opj_jp2_set_decoded_resolution_factor @MANGLE_PREFIX@_opj_jp2_set_decoded_resolution_factor +#define opj_jp2_set_threads @MANGLE_PREFIX@_opj_jp2_set_threads +#define opj_jp2_setup_decoder @MANGLE_PREFIX@_opj_jp2_setup_decoder +#define opj_jp2_setup_encoder @MANGLE_PREFIX@_opj_jp2_setup_encoder +#define opj_jp2_start_compress @MANGLE_PREFIX@_opj_jp2_start_compress +#define opj_jp2_write_tile @MANGLE_PREFIX@_opj_jp2_write_tile +#define opj_malloc @MANGLE_PREFIX@_opj_malloc +#define opj_matrix_inversion_f @MANGLE_PREFIX@_opj_matrix_inversion_f +#define opj_mct_decode @MANGLE_PREFIX@_opj_mct_decode +#define opj_mct_decode_custom @MANGLE_PREFIX@_opj_mct_decode_custom +#define opj_mct_decode_real @MANGLE_PREFIX@_opj_mct_decode_real +#define opj_mct_encode @MANGLE_PREFIX@_opj_mct_encode +#define opj_mct_encode_custom @MANGLE_PREFIX@_opj_mct_encode_custom +#define opj_mct_encode_real @MANGLE_PREFIX@_opj_mct_encode_real +#define opj_mct_get_mct_norms @MANGLE_PREFIX@_opj_mct_get_mct_norms +#define opj_mct_get_mct_norms_real @MANGLE_PREFIX@_opj_mct_get_mct_norms_real +#define opj_mct_getnorm @MANGLE_PREFIX@_opj_mct_getnorm +#define opj_mct_getnorm_real @MANGLE_PREFIX@_opj_mct_getnorm_real +#define opj_mqc_bypass_enc @MANGLE_PREFIX@_opj_mqc_bypass_enc +#define opj_mqc_bypass_flush_enc @MANGLE_PREFIX@_opj_mqc_bypass_flush_enc +#define opj_mqc_bypass_get_extra_bytes @MANGLE_PREFIX@_opj_mqc_bypass_get_extra_bytes +#define opj_mqc_bypass_init_enc @MANGLE_PREFIX@_opj_mqc_bypass_init_enc +#define opj_mqc_byteout @MANGLE_PREFIX@_opj_mqc_byteout +#define opj_mqc_erterm_enc @MANGLE_PREFIX@_opj_mqc_erterm_enc +#define opj_mqc_flush @MANGLE_PREFIX@_opj_mqc_flush +#define opj_mqc_init_dec @MANGLE_PREFIX@_opj_mqc_init_dec +#define opj_mqc_init_enc @MANGLE_PREFIX@_opj_mqc_init_enc +#define opj_mqc_numbytes @MANGLE_PREFIX@_opj_mqc_numbytes +#define opj_mqc_raw_init_dec @MANGLE_PREFIX@_opj_mqc_raw_init_dec +#define opj_mqc_reset_enc @MANGLE_PREFIX@_opj_mqc_reset_enc +#define opj_mqc_resetstates @MANGLE_PREFIX@_opj_mqc_resetstates +#define opj_mqc_restart_init_enc @MANGLE_PREFIX@_opj_mqc_restart_init_enc +#define opj_mqc_segmark_enc @MANGLE_PREFIX@_opj_mqc_segmark_enc +#define opj_mqc_setstate @MANGLE_PREFIX@_opj_mqc_setstate +#define opj_mutex_create @MANGLE_PREFIX@_opj_mutex_create +#define opj_mutex_destroy @MANGLE_PREFIX@_opj_mutex_destroy +#define opj_mutex_lock @MANGLE_PREFIX@_opj_mutex_lock +#define opj_mutex_unlock @MANGLE_PREFIX@_opj_mutex_unlock +#define opj_pi_create_decode @MANGLE_PREFIX@_opj_pi_create_decode +#define opj_pi_create_encode @MANGLE_PREFIX@_opj_pi_create_encode +#define opj_pi_destroy @MANGLE_PREFIX@_opj_pi_destroy +#define opj_pi_initialise_encode @MANGLE_PREFIX@_opj_pi_initialise_encode +#define opj_pi_next @MANGLE_PREFIX@_opj_pi_next +#define opj_pi_update_encoding_parameters @MANGLE_PREFIX@_opj_pi_update_encoding_parameters +#define opj_procedure_list_add_procedure @MANGLE_PREFIX@_opj_procedure_list_add_procedure +#define opj_procedure_list_clear @MANGLE_PREFIX@_opj_procedure_list_clear +#define opj_procedure_list_create @MANGLE_PREFIX@_opj_procedure_list_create +#define opj_procedure_list_destroy @MANGLE_PREFIX@_opj_procedure_list_destroy +#define opj_procedure_list_get_first_procedure @MANGLE_PREFIX@_opj_procedure_list_get_first_procedure +#define opj_procedure_list_get_nb_procedures @MANGLE_PREFIX@_opj_procedure_list_get_nb_procedures +#define opj_read_bytes_BE @MANGLE_PREFIX@_opj_read_bytes_BE +#define opj_read_bytes_LE @MANGLE_PREFIX@_opj_read_bytes_LE +#define opj_read_double_BE @MANGLE_PREFIX@_opj_read_double_BE +#define opj_read_double_LE @MANGLE_PREFIX@_opj_read_double_LE +#define opj_read_float_BE @MANGLE_PREFIX@_opj_read_float_BE +#define opj_read_float_LE @MANGLE_PREFIX@_opj_read_float_LE +#define opj_read_header @MANGLE_PREFIX@_opj_read_header +#define opj_read_tile_header @MANGLE_PREFIX@_opj_read_tile_header +#define opj_realloc @MANGLE_PREFIX@_opj_realloc +#define opj_set_MCT @MANGLE_PREFIX@_opj_set_MCT +#define opj_set_decode_area @MANGLE_PREFIX@_opj_set_decode_area +#define opj_set_decoded_components @MANGLE_PREFIX@_opj_set_decoded_components +#define opj_set_decoded_resolution_factor @MANGLE_PREFIX@_opj_set_decoded_resolution_factor +#define opj_set_default_decoder_parameters @MANGLE_PREFIX@_opj_set_default_decoder_parameters +#define opj_set_default_encoder_parameters @MANGLE_PREFIX@_opj_set_default_encoder_parameters +#define opj_set_default_event_handler @MANGLE_PREFIX@_opj_set_default_event_handler +#define opj_set_error_handler @MANGLE_PREFIX@_opj_set_error_handler +#define opj_set_info_handler @MANGLE_PREFIX@_opj_set_info_handler +#define opj_set_warning_handler @MANGLE_PREFIX@_opj_set_warning_handler +#define opj_setup_decoder @MANGLE_PREFIX@_opj_setup_decoder +#define opj_setup_encoder @MANGLE_PREFIX@_opj_setup_encoder +#define opj_sparse_array_int32_create @MANGLE_PREFIX@_opj_sparse_array_int32_create +#define opj_sparse_array_int32_free @MANGLE_PREFIX@_opj_sparse_array_int32_free +#define opj_sparse_array_int32_read @MANGLE_PREFIX@_opj_sparse_array_int32_read +#define opj_sparse_array_int32_write @MANGLE_PREFIX@_opj_sparse_array_int32_write +#define opj_sparse_array_is_region_valid @MANGLE_PREFIX@_opj_sparse_array_is_region_valid +#define opj_start_compress @MANGLE_PREFIX@_opj_start_compress +#define opj_stream_create @MANGLE_PREFIX@_opj_stream_create +#define opj_stream_create_default_file_stream @MANGLE_PREFIX@_opj_stream_create_default_file_stream +#define opj_stream_create_file_stream @MANGLE_PREFIX@_opj_stream_create_file_stream +#define opj_stream_default_create @MANGLE_PREFIX@_opj_stream_default_create +#define opj_stream_default_read @MANGLE_PREFIX@_opj_stream_default_read +#define opj_stream_default_seek @MANGLE_PREFIX@_opj_stream_default_seek +#define opj_stream_default_skip @MANGLE_PREFIX@_opj_stream_default_skip +#define opj_stream_default_write @MANGLE_PREFIX@_opj_stream_default_write +#define opj_stream_destroy @MANGLE_PREFIX@_opj_stream_destroy +#define opj_stream_flush @MANGLE_PREFIX@_opj_stream_flush +#define opj_stream_get_number_byte_left @MANGLE_PREFIX@_opj_stream_get_number_byte_left +#define opj_stream_has_seek @MANGLE_PREFIX@_opj_stream_has_seek +#define opj_stream_read_data @MANGLE_PREFIX@_opj_stream_read_data +#define opj_stream_read_seek @MANGLE_PREFIX@_opj_stream_read_seek +#define opj_stream_read_skip @MANGLE_PREFIX@_opj_stream_read_skip +#define opj_stream_seek @MANGLE_PREFIX@_opj_stream_seek +#define opj_stream_set_read_function @MANGLE_PREFIX@_opj_stream_set_read_function +#define opj_stream_set_seek_function @MANGLE_PREFIX@_opj_stream_set_seek_function +#define opj_stream_set_skip_function @MANGLE_PREFIX@_opj_stream_set_skip_function +#define opj_stream_set_user_data @MANGLE_PREFIX@_opj_stream_set_user_data +#define opj_stream_set_user_data_length @MANGLE_PREFIX@_opj_stream_set_user_data_length +#define opj_stream_set_write_function @MANGLE_PREFIX@_opj_stream_set_write_function +#define opj_stream_skip @MANGLE_PREFIX@_opj_stream_skip +#define opj_stream_tell @MANGLE_PREFIX@_opj_stream_tell +#define opj_stream_write_data @MANGLE_PREFIX@_opj_stream_write_data +#define opj_stream_write_seek @MANGLE_PREFIX@_opj_stream_write_seek +#define opj_stream_write_skip @MANGLE_PREFIX@_opj_stream_write_skip +#define opj_t1_create @MANGLE_PREFIX@_opj_t1_create +#define opj_t1_decode_cblks @MANGLE_PREFIX@_opj_t1_decode_cblks +#define opj_t1_destroy @MANGLE_PREFIX@_opj_t1_destroy +#define opj_t1_encode_cblks @MANGLE_PREFIX@_opj_t1_encode_cblks +#define opj_t1_ht_decode_cblk @MANGLE_PREFIX@_opj_t1_ht_decode_cblk +#define opj_t2_create @MANGLE_PREFIX@_opj_t2_create +#define opj_t2_decode_packets @MANGLE_PREFIX@_opj_t2_decode_packets +#define opj_t2_destroy @MANGLE_PREFIX@_opj_t2_destroy +#define opj_t2_encode_packets @MANGLE_PREFIX@_opj_t2_encode_packets +#define opj_tcd_copy_tile_data @MANGLE_PREFIX@_opj_tcd_copy_tile_data +#define opj_tcd_create @MANGLE_PREFIX@_opj_tcd_create +#define opj_tcd_decode_tile @MANGLE_PREFIX@_opj_tcd_decode_tile +#define opj_tcd_destroy @MANGLE_PREFIX@_opj_tcd_destroy +#define opj_tcd_encode_tile @MANGLE_PREFIX@_opj_tcd_encode_tile +#define opj_tcd_get_decoded_tile_size @MANGLE_PREFIX@_opj_tcd_get_decoded_tile_size +#define opj_tcd_get_encoder_input_buffer_size @MANGLE_PREFIX@_opj_tcd_get_encoder_input_buffer_size +#define opj_tcd_init @MANGLE_PREFIX@_opj_tcd_init +#define opj_tcd_init_decode_tile @MANGLE_PREFIX@_opj_tcd_init_decode_tile +#define opj_tcd_init_encode_tile @MANGLE_PREFIX@_opj_tcd_init_encode_tile +#define opj_tcd_is_band_empty @MANGLE_PREFIX@_opj_tcd_is_band_empty +#define opj_tcd_is_subband_area_of_interest @MANGLE_PREFIX@_opj_tcd_is_subband_area_of_interest +#define opj_tcd_marker_info_create @MANGLE_PREFIX@_opj_tcd_marker_info_create +#define opj_tcd_marker_info_destroy @MANGLE_PREFIX@_opj_tcd_marker_info_destroy +#define opj_tcd_reinit_segment @MANGLE_PREFIX@_opj_tcd_reinit_segment +#define opj_tcd_update_tile_data @MANGLE_PREFIX@_opj_tcd_update_tile_data +#define opj_tgt_create @MANGLE_PREFIX@_opj_tgt_create +#define opj_tgt_decode @MANGLE_PREFIX@_opj_tgt_decode +#define opj_tgt_destroy @MANGLE_PREFIX@_opj_tgt_destroy +#define opj_tgt_encode @MANGLE_PREFIX@_opj_tgt_encode +#define opj_tgt_init @MANGLE_PREFIX@_opj_tgt_init +#define opj_tgt_reset @MANGLE_PREFIX@_opj_tgt_reset +#define opj_tgt_setvalue @MANGLE_PREFIX@_opj_tgt_setvalue +#define opj_thread_create @MANGLE_PREFIX@_opj_thread_create +#define opj_thread_join @MANGLE_PREFIX@_opj_thread_join +#define opj_thread_pool_create @MANGLE_PREFIX@_opj_thread_pool_create +#define opj_thread_pool_destroy @MANGLE_PREFIX@_opj_thread_pool_destroy +#define opj_thread_pool_get_thread_count @MANGLE_PREFIX@_opj_thread_pool_get_thread_count +#define opj_thread_pool_submit_job @MANGLE_PREFIX@_opj_thread_pool_submit_job +#define opj_thread_pool_wait_completion @MANGLE_PREFIX@_opj_thread_pool_wait_completion +#define opj_tls_get @MANGLE_PREFIX@_opj_tls_get +#define opj_tls_set @MANGLE_PREFIX@_opj_tls_set +#define opj_version @MANGLE_PREFIX@_opj_version +#define opj_write_bytes_BE @MANGLE_PREFIX@_opj_write_bytes_BE +#define opj_write_bytes_LE @MANGLE_PREFIX@_opj_write_bytes_LE +#define opj_write_double_BE @MANGLE_PREFIX@_opj_write_double_BE +#define opj_write_double_LE @MANGLE_PREFIX@_opj_write_double_LE +#define opj_write_float_BE @MANGLE_PREFIX@_opj_write_float_BE +#define opj_write_float_LE @MANGLE_PREFIX@_opj_write_float_LE +#define opj_write_tile @MANGLE_PREFIX@_opj_write_tile +#define opq_mqc_finish_dec @MANGLE_PREFIX@_opq_mqc_finish_dec + +#endif // openjpeg_mangle_h \ No newline at end of file From 4cb465dceaab063977578e362e637ca05c7a70ef Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Tue, 3 Dec 2024 12:12:11 -0500 Subject: [PATCH 6/7] ENH: Update JPEG2000 IO for openjpeg 2.5 interface --- .../IO/JPEG2000/src/itkJPEG2000ImageIO.cxx | 200 +++++++----------- 1 file changed, 74 insertions(+), 126 deletions(-) diff --git a/Modules/IO/JPEG2000/src/itkJPEG2000ImageIO.cxx b/Modules/IO/JPEG2000/src/itkJPEG2000ImageIO.cxx index 10760d3d744..799b30c6e99 100644 --- a/Modules/IO/JPEG2000/src/itkJPEG2000ImageIO.cxx +++ b/Modules/IO/JPEG2000/src/itkJPEG2000ImageIO.cxx @@ -26,7 +26,7 @@ extern "C" { -#include "openjpeg.h" +#include "itk_openjpeg.h" #include "j2k.h" #include "jp2.h" } @@ -139,21 +139,10 @@ JPEG2000ImageIO::ReadImageInformation() { itkDebugMacro("ReadImageInformation()"); - FILE * l_file = fopen(this->m_FileName.c_str(), "rb"); - - /* decompression parameters */ - - if (!l_file) - { - itkExceptionMacro("JPEG2000ImageIO failed to open file for reading: " << this->GetFileName() << std::endl - << "Reason: " - << itksys::SystemTools::GetLastSystemError()); - } - /* set decoding parameters to default values */ opj_set_default_decoder_parameters(&(this->m_Internal->m_DecompressionParameters)); - opj_stream_t * cio = opj_stream_create_default_file_stream(l_file, true); + opj_stream_t * cio = opj_stream_create_default_file_stream(this->m_FileName.c_str(), true); this->m_Internal->m_Dinfo = nullptr; /* handle to a decompressor */ @@ -187,11 +176,11 @@ JPEG2000ImageIO::ReadImageInformation() /* JPEG-2000 codestream */ /* get a decoder handle */ - this->m_Internal->m_Dinfo = opj_create_decompress(CODEC_J2K); + + this->m_Internal->m_Dinfo = opj_create_decompress(OPJ_CODEC_J2K); if (!this->m_Internal->m_Dinfo) { opj_stream_destroy(cio); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: opj_create_decompress(CODEC_J2K) returns nullptr"); @@ -202,11 +191,10 @@ JPEG2000ImageIO::ReadImageInformation() { /* JPEG 2000 compressed image data */ /* get a decoder handle */ - this->m_Internal->m_Dinfo = opj_create_decompress(CODEC_JP2); + this->m_Internal->m_Dinfo = opj_create_decompress(OPJ_CODEC_JP2); if (!this->m_Internal->m_Dinfo) { opj_stream_destroy(cio); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: opj_create_decompress(CODEC_JP2) returns nullptr"); @@ -217,11 +205,10 @@ JPEG2000ImageIO::ReadImageInformation() { /* JPEG 2000, JPIP */ /* get a decoder handle */ - this->m_Internal->m_Dinfo = opj_create_decompress(CODEC_JPT); + this->m_Internal->m_Dinfo = opj_create_decompress(OPJ_CODEC_JPT); if (!this->m_Internal->m_Dinfo) { opj_stream_destroy(cio); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: opj_create_decompress(CODEC_JPT) returns nullptr"); @@ -230,7 +217,6 @@ JPEG2000ImageIO::ReadImageInformation() } default: opj_stream_destroy(cio); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: " @@ -243,35 +229,21 @@ JPEG2000ImageIO::ReadImageInformation() if (!bResult) { opj_stream_destroy(cio); + opj_destroy_codec(this->m_Internal->m_Dinfo); + this->m_Internal->m_Dinfo = nullptr; itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: opj_setup_decoder returns false"); } - // Image parameters - first tile - OPJ_INT32 l_tile_x0; - OPJ_INT32 l_tile_y0; - - // Image parameters - tile width, height and number of tiles - OPJ_UINT32 l_tile_width; - OPJ_UINT32 l_tile_height; - OPJ_UINT32 l_nb_tiles_x; - OPJ_UINT32 l_nb_tiles_y; - itkDebugMacro("Trying to read header now..."); - bResult = opj_read_header(this->m_Internal->m_Dinfo, - &l_image, - &l_tile_x0, - &l_tile_y0, - &l_tile_width, - &l_tile_height, - &l_nb_tiles_x, - &l_nb_tiles_y, - cio); + bResult = opj_read_header(cio, this->m_Internal->m_Dinfo, &l_image); if (!bResult) { opj_stream_destroy(cio); + opj_destroy_codec(this->m_Internal->m_Dinfo); + this->m_Internal->m_Dinfo = nullptr; itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: opj_read_header returns false"); } @@ -279,18 +251,40 @@ JPEG2000ImageIO::ReadImageInformation() if (!l_image) { opj_stream_destroy(cio); + opj_destroy_codec(this->m_Internal->m_Dinfo); + this->m_Internal->m_Dinfo = nullptr; itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: Error whle reading image header"); } - this->m_Internal->m_TileStartX = l_tile_x0; - this->m_Internal->m_TileStartY = l_tile_y0; + // get the code stream information + opj_codestream_info_v2_t * cstr_info = nullptr; + cstr_info = opj_get_cstr_info(this->m_Internal->m_Dinfo); + + if (!cstr_info) + { + opj_stream_destroy(cio); + opj_destroy_codec(this->m_Internal->m_Dinfo); + this->m_Internal->m_Dinfo = nullptr; + itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl + << "Reason: Error while reading codestream information"); + } + + // Image parameters - first tile + this->m_Internal->m_TileStartX = cstr_info->tx0; + this->m_Internal->m_TileStartY = cstr_info->ty0; + + // Image parameters - tile width, height and number of tiles + this->m_Internal->m_TileWidth = cstr_info->tdx; + this->m_Internal->m_TileHeight = cstr_info->tdy; - this->m_Internal->m_TileWidth = l_tile_width; - this->m_Internal->m_TileHeight = l_tile_height; + this->m_Internal->m_NumberOfTilesInX = cstr_info->tw; + this->m_Internal->m_NumberOfTilesInY = cstr_info->th; - this->m_Internal->m_NumberOfTilesInX = l_nb_tiles_x; - this->m_Internal->m_NumberOfTilesInY = l_nb_tiles_y; + if (cstr_info) + { + opj_destroy_cstr_info(&cstr_info); + } itkDebugMacro("Number of Components = " << l_image->numcomps); @@ -319,7 +313,7 @@ JPEG2000ImageIO::ReadImageInformation() this->SetPixelType(IOPixelEnum::SCALAR); break; case 3: - if (l_image->color_space != CLRSPC_SRGB) + if (l_image->color_space != OPJ_CLRSPC_SRGB) { itkWarningMacro("file does not specify color space, assuming sRGB"); } @@ -349,7 +343,6 @@ JPEG2000ImageIO::ReadImageInformation() /* close the byte stream */ opj_stream_destroy(cio); - fclose(l_file); if (this->m_Internal->m_Dinfo) { @@ -368,16 +361,7 @@ JPEG2000ImageIO::Read(void * buffer) { itkDebugMacro("JPEG2000ImageIO::Read() Begin"); - FILE * l_file = fopen(this->m_FileName.c_str(), "rb"); - - if (!l_file) - { - itkExceptionMacro("JPEG2000ImageIO failed to open file for reading: " << this->GetFileName() << std::endl - << "Reason: " - << itksys::SystemTools::GetLastSystemError()); - } - - opj_stream_t * l_stream = opj_stream_create_default_file_stream(l_file, true); + opj_stream_t * l_stream = opj_stream_create_default_file_stream(this->m_FileName.c_str(), true); if (!l_stream) { itkExceptionMacro("JPEG2000ImageIO failed to read file: " @@ -397,7 +381,7 @@ JPEG2000ImageIO::Read(void * buffer) { /* JPEG-2000 codestream */ /* get a decoder handle */ - this->m_Internal->m_Dinfo = opj_create_decompress(CODEC_J2K); + this->m_Internal->m_Dinfo = opj_create_decompress(OPJ_CODEC_J2K); if (!this->m_Internal->m_Dinfo) { itkExceptionMacro("JPEG2000ImageIO failed to read file: " @@ -410,7 +394,7 @@ JPEG2000ImageIO::Read(void * buffer) { /* JPEG 2000 compressed image data */ /* get a decoder handle */ - this->m_Internal->m_Dinfo = opj_create_decompress(CODEC_JP2); + this->m_Internal->m_Dinfo = opj_create_decompress(OPJ_CODEC_JP2); if (!this->m_Internal->m_Dinfo) { itkExceptionMacro("JPEG2000ImageIO failed to read file: " @@ -423,7 +407,7 @@ JPEG2000ImageIO::Read(void * buffer) { /* JPEG 2000, JPIP */ /* get a decoder handle */ - this->m_Internal->m_Dinfo = opj_create_decompress(CODEC_JPT); + this->m_Internal->m_Dinfo = opj_create_decompress(OPJ_CODEC_JPT); if (!this->m_Internal->m_Dinfo) { itkExceptionMacro("JPEG2000ImageIO failed to read file: " @@ -433,7 +417,6 @@ JPEG2000ImageIO::Read(void * buffer) break; } default: - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: " @@ -448,34 +431,18 @@ JPEG2000ImageIO::Read(void * buffer) << "Reason: opj_setup_decoder returns false"); } - OPJ_INT32 l_tile_x0; - OPJ_INT32 l_tile_y0; - - OPJ_UINT32 l_tile_width; - OPJ_UINT32 l_tile_height; - OPJ_UINT32 l_nb_tiles_x; - OPJ_UINT32 l_nb_tiles_y; - - bool bResult = opj_read_header(this->m_Internal->m_Dinfo, - &l_image, - &l_tile_x0, - &l_tile_y0, - &l_tile_width, - &l_tile_height, - &l_nb_tiles_x, - &l_nb_tiles_y, - l_stream); + bool bResult = opj_read_header(l_stream, this->m_Internal->m_Dinfo, &l_image); if (!bResult) { opj_destroy_codec(this->m_Internal->m_Dinfo); this->m_Internal->m_Dinfo = nullptr; opj_stream_destroy(l_stream); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: opj_read_header returns false"); } + ImageIORegion regionToRead = this->GetIORegion(); ImageIORegion::SizeType size = regionToRead.GetSize(); @@ -500,7 +467,7 @@ JPEG2000ImageIO::Read(void * buffer) itkDebugMacro("p_end_x = " << p_end_x); itkDebugMacro("p_end_y = " << p_end_y); - bResult = opj_set_decode_area(this->m_Internal->m_Dinfo, p_start_x, p_start_y, p_end_x, p_end_y); + bResult = opj_set_decode_area(this->m_Internal->m_Dinfo, l_image, p_start_x, p_start_y, p_end_x, p_end_y); itkDebugMacro("opj_set_decode_area() after"); @@ -509,7 +476,6 @@ JPEG2000ImageIO::Read(void * buffer) opj_destroy_codec(this->m_Internal->m_Dinfo); this->m_Internal->m_Dinfo = nullptr; opj_stream_destroy(l_stream); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: opj_set_decode_area returns false"); } @@ -526,28 +492,27 @@ JPEG2000ImageIO::Read(void * buffer) OPJ_UINT32 l_max_data_size = 1000; - bool l_go_on = true; + OPJ_BOOL l_go_on = true; - auto * l_data = (OPJ_BYTE *)malloc(1000); + auto * l_data = (OPJ_BYTE *)opj_malloc(1000); while (l_go_on) { - bool tileHeaderRead = opj_read_tile_header(this->m_Internal->m_Dinfo, - &l_tile_index, - &l_data_size, - &l_current_tile_x0, - &l_current_tile_y0, - &l_current_tile_x1, - &l_current_tile_y1, - &l_nb_comps, - &l_go_on, - l_stream); + OPJ_BOOL tileHeaderRead = opj_read_tile_header(this->m_Internal->m_Dinfo, + l_stream, + &l_tile_index, + &l_data_size, + &l_current_tile_x0, + &l_current_tile_y0, + &l_current_tile_x1, + &l_current_tile_y1, + &l_nb_comps, + &l_go_on); if (!tileHeaderRead) { - free(l_data); + opj_free(l_data); opj_stream_destroy(l_stream); - fclose(l_file); opj_destroy_codec(this->m_Internal->m_Dinfo); opj_image_destroy(l_image); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl @@ -567,12 +532,11 @@ JPEG2000ImageIO::Read(void * buffer) { if (l_data_size > l_max_data_size) { - l_data = (OPJ_BYTE *)realloc(l_data, l_data_size); + l_data = (OPJ_BYTE *)opj_realloc(l_data, l_data_size); if (!l_data) { opj_stream_destroy(l_stream); - fclose(l_file); opj_destroy_codec(this->m_Internal->m_Dinfo); opj_image_destroy(l_image); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl @@ -589,9 +553,8 @@ JPEG2000ImageIO::Read(void * buffer) if (!decodeTileData) { - free(l_data); + opj_free(l_data); opj_stream_destroy(l_stream); - fclose(l_file); opj_destroy_codec(this->m_Internal->m_Dinfo); opj_image_destroy(l_image); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl @@ -653,9 +616,8 @@ JPEG2000ImageIO::Read(void * buffer) if (!opj_end_decompress(this->m_Internal->m_Dinfo, l_stream)) { - free(l_data); + opj_free(l_data); opj_stream_destroy(l_stream); - fclose(l_file); opj_destroy_codec(this->m_Internal->m_Dinfo); opj_image_destroy(l_image); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl @@ -667,14 +629,12 @@ JPEG2000ImageIO::Read(void * buffer) opj_destroy_codec(this->m_Internal->m_Dinfo); this->m_Internal->m_Dinfo = nullptr; opj_stream_destroy(l_stream); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to read file: " << this->GetFileName() << std::endl << "Reason: error whle reading image"); } /* close the byte stream */ opj_stream_destroy(l_stream); - fclose(l_file); if (this->m_Internal->m_Dinfo) { @@ -689,7 +649,7 @@ JPEG2000ImageIO::Read(void * buffer) if (l_data) { - free(l_data); + opj_free(l_data); } itkDebugMacro("JPEG2000ImageIO::Read() End"); @@ -775,7 +735,7 @@ JPEG2000ImageIO::Write(const void * buffer) << parameters.cp_ty0 << ") <= IMG_Y0( " << parameters.image_offset_y0 << ") "); } - for (int i = 0; i < parameters.numpocs; ++i) + for (OPJ_UINT32 i = 0; i < parameters.numpocs; ++i) { if (parameters.POC[i].prg == -1) { @@ -800,7 +760,7 @@ JPEG2000ImageIO::Write(const void * buffer) snprintf(parameters.cp_comment, commentLength, "%s%s with JPWL", comment, version); #else size_t commentLength = clen + strlen(version) + 11; - parameters.cp_comment = (char *)malloc(commentLength); + parameters.cp_comment = (char *)opj_malloc(commentLength); snprintf(parameters.cp_comment, commentLength, "%s%s", comment, version); #endif /* <GetNumberOfComponents() == 3) { - color_space = (this->GetPixelType() == IOPixelEnum::RGB) ? CLRSPC_SRGB : CLRSPC_UNSPECIFIED; + color_space = (this->GetPixelType() == IOPixelEnum::RGB) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_UNSPECIFIED; /* initialize image components */ memset(&cmptparms[0], 0, 3 * sizeof(opj_image_cmptparm_t)); @@ -868,7 +828,7 @@ JPEG2000ImageIO::Write(const void * buffer) if (this->GetNumberOfComponents() == 1) { - color_space = CLRSPC_GRAY; + color_space = OPJ_CLRSPC_GRAY; /* initialize image components */ memset(&cmptparms[0], 0, sizeof(opj_image_cmptparm_t)); @@ -944,7 +904,7 @@ JPEG2000ImageIO::Write(const void * buffer) opj_codec_t * cinfo = nullptr; if (extension == ".j2k") { - cinfo = opj_create_compress(CODEC_J2K); + cinfo = opj_create_compress(OPJ_CODEC_J2K); if (!cinfo) { itkExceptionMacro("JPEG2000ImageIO failed to write file: " @@ -954,7 +914,7 @@ JPEG2000ImageIO::Write(const void * buffer) } else if (extension == ".jp2") { - cinfo = opj_create_compress(CODEC_JP2); + cinfo = opj_create_compress(OPJ_CODEC_JP2); if (!cinfo) { itkExceptionMacro("JPEG2000ImageIO failed to write file: " @@ -964,7 +924,7 @@ JPEG2000ImageIO::Write(const void * buffer) } else if (extension == ".jpt") { - cinfo = opj_create_compress(CODEC_JPT); + cinfo = opj_create_compress(OPJ_CODEC_JPT); if (!cinfo) { itkExceptionMacro("JPEG2000ImageIO failed to write file: " @@ -993,17 +953,9 @@ JPEG2000ImageIO::Write(const void * buffer) << "Reason: opj_setup_encoder returns false"); } - FILE * l_file = fopen(parameters.outfile, "wb"); - if (!l_file) - { - itkExceptionMacro("JPEG2000ImageIO failed to open file for writing: " << this->GetFileName() << std::endl - << "Reason: " - << itksys::SystemTools::GetLastSystemError()); - } - /* open a byte stream for writing */ /* allocate memory for all tiles */ - opj_stream_t * cio = opj_stream_create_default_file_stream(l_file, false); + opj_stream_t * cio = opj_stream_create_default_file_stream(parameters.outfile, false); if (!cio) { itkExceptionMacro("JPEG2000ImageIO failed to write file: " @@ -1014,14 +966,13 @@ JPEG2000ImageIO::Write(const void * buffer) if (parameters.cp_comment) { - free(parameters.cp_comment); + opj_free(parameters.cp_comment); } bSuccess = opj_start_compress(cinfo, l_image, cio); if (!bSuccess) { opj_stream_destroy(cio); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to write file: " << this->GetFileName() << std::endl << "Reason: opj_start_compress returns false"); } @@ -1030,7 +981,6 @@ JPEG2000ImageIO::Write(const void * buffer) if (!bSuccess) { opj_stream_destroy(cio); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to write file: " << this->GetFileName() << std::endl << "Reason: opj_encode returns false"); } @@ -1039,14 +989,12 @@ JPEG2000ImageIO::Write(const void * buffer) if (!bSuccess) { opj_stream_destroy(cio); - fclose(l_file); itkExceptionMacro("JPEG2000ImageIO failed to write file: " << this->GetFileName() << std::endl << "Reason: opj_end_compress returns false"); } /* close and free the byte stream */ opj_stream_destroy(cio); - fclose(l_file); /* free remaining compression structures */ opj_destroy_codec(cinfo); From 823a55f100a459429d3505d545e4c5c615e6cb9b Mon Sep 17 00:00:00 2001 From: Bradley Lowekamp Date: Wed, 4 Dec 2024 13:58:47 -0500 Subject: [PATCH 7/7] ENH: Add HTJP2K support for jph files --- Modules/IO/JPEG2000/src/itkJPEG2000ImageIO.cxx | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Modules/IO/JPEG2000/src/itkJPEG2000ImageIO.cxx b/Modules/IO/JPEG2000/src/itkJPEG2000ImageIO.cxx index 799b30c6e99..1ea17e42b8a 100644 --- a/Modules/IO/JPEG2000/src/itkJPEG2000ImageIO.cxx +++ b/Modules/IO/JPEG2000/src/itkJPEG2000ImageIO.cxx @@ -96,6 +96,11 @@ JPEG2000ImageIO::JPEG2000ImageIO() this->AddSupportedWriteExtension(ext); this->AddSupportedReadExtension(ext); } + +#if OPJ_VERSION_MAJOR >= 2 && OPJ_VERSION_MINOR >= 5 + // HTJ2K with JP2 boxes OpenJPEG only support decoding as of 2.5.0 + this->AddSupportedReadExtension(".jph"); +#endif } JPEG2000ImageIO::~JPEG2000ImageIO() = default; @@ -112,7 +117,7 @@ JPEG2000ImageIO::CanReadFile(const char * filename) itkDebugMacro("JPEG2000ImageIO::CanReadFile()"); // - // If the file exists, and have extension .j2k or jp2 or jpt, then we are good + // If the file exists, and have extension j2k or jp2 or jpt or jph, then we are good // to read it. // if (!itksys::SystemTools::FileExists(filename)) @@ -168,6 +173,11 @@ JPEG2000ImageIO::ReadImageInformation() this->m_Internal->m_DecompressionParameters.decod_format = static_cast(JPEG2000ImageIOInternal::DecodingFormatEnum::JPT_CFMT); } + else if (extension == ".jph") + { + this->m_Internal->m_DecompressionParameters.decod_format = + static_cast(JPEG2000ImageIOInternal::DecodingFormatEnum::JP2_CFMT); + } switch (this->m_Internal->m_DecompressionParameters.decod_format) { @@ -817,7 +827,7 @@ JPEG2000ImageIO::Write(const void * buffer) for (auto & cmptparm : cmptparms) { cmptparm.prec = 8; - cmptparm.bpp = 8; + /* cmptparm.bpp = 8; deprecated "Use prec instead" */ cmptparm.sgnd = 0; cmptparm.dx = 1; cmptparm.dy = 1; // this->GetSpacing( 1 ) @@ -836,13 +846,13 @@ JPEG2000ImageIO::Write(const void * buffer) if (this->GetComponentType() == IOComponentEnum::UCHAR) { cmptparms[0].prec = 8; - cmptparms[0].bpp = 8; + /* cmptparms[0].bpp = 8; deprecated "Use prec instead" */ } if (this->GetComponentType() == IOComponentEnum::USHORT) { cmptparms[0].prec = 16; - cmptparms[0].bpp = 16; + /* cmptparms[0].bpp = 16; deprecated "Use prec instead" */ } cmptparms[0].sgnd = 0;