From 3e62f8d9b73f712f82e6d3d186f03a3e581bc465 Mon Sep 17 00:00:00 2001 From: Mathieu Malaterre Date: Fri, 28 Sep 2012 08:32:34 +0000 Subject: [trunk] FolderReorgProposal task: add JP3D Update issue 177 --- src/lib/openjp3d/CMakeLists.txt | 40 + src/lib/openjp3d/Makefile.am | 88 ++ src/lib/openjp3d/bio.c | 189 ++++ src/lib/openjp3d/bio.h | 132 +++ src/lib/openjp3d/cio.c | 217 ++++ src/lib/openjp3d/cio.h | 100 ++ src/lib/openjp3d/dwt.c | 1016 +++++++++++++++++ src/lib/openjp3d/dwt.h | 100 ++ src/lib/openjp3d/event.c | 181 +++ src/lib/openjp3d/event.h | 58 + src/lib/openjp3d/fix.h | 62 ++ src/lib/openjp3d/int.h | 122 ++ src/lib/openjp3d/jp3d.c | 2328 +++++++++++++++++++++++++++++++++++++++ src/lib/openjp3d/jp3d.h | 518 +++++++++ src/lib/openjp3d/jp3d_lib.c | 76 ++ src/lib/openjp3d/jp3d_lib.h | 75 ++ src/lib/openjp3d/mct.c | 131 +++ src/lib/openjp3d/mct.h | 97 ++ src/lib/openjp3d/mqc.c | 548 +++++++++ src/lib/openjp3d/mqc.h | 201 ++++ src/lib/openjp3d/openjp3d.c | 207 ++++ src/lib/openjp3d/openjp3d.h | 713 ++++++++++++ src/lib/openjp3d/opj_includes.h | 81 ++ src/lib/openjp3d/pi.c | 630 +++++++++++ src/lib/openjp3d/pi.h | 145 +++ src/lib/openjp3d/raw.c | 86 ++ src/lib/openjp3d/raw.h | 99 ++ src/lib/openjp3d/t1.c | 1181 ++++++++++++++++++++ src/lib/openjp3d/t1.h | 173 +++ src/lib/openjp3d/t1_3d.c | 1230 +++++++++++++++++++++ src/lib/openjp3d/t1_3d.h | 173 +++ src/lib/openjp3d/t2.c | 675 ++++++++++++ src/lib/openjp3d/t2.h | 101 ++ src/lib/openjp3d/tcd.c | 1738 +++++++++++++++++++++++++++++ src/lib/openjp3d/tcd.h | 334 ++++++ src/lib/openjp3d/tgt.c | 256 +++++ src/lib/openjp3d/tgt.h | 124 +++ src/lib/openjp3d/volume.c | 89 ++ src/lib/openjp3d/volume.h | 43 + 39 files changed, 14357 insertions(+) create mode 100644 src/lib/openjp3d/CMakeLists.txt create mode 100644 src/lib/openjp3d/Makefile.am create mode 100755 src/lib/openjp3d/bio.c create mode 100755 src/lib/openjp3d/bio.h create mode 100755 src/lib/openjp3d/cio.c create mode 100755 src/lib/openjp3d/cio.h create mode 100755 src/lib/openjp3d/dwt.c create mode 100755 src/lib/openjp3d/dwt.h create mode 100755 src/lib/openjp3d/event.c create mode 100755 src/lib/openjp3d/event.h create mode 100755 src/lib/openjp3d/fix.h create mode 100755 src/lib/openjp3d/int.h create mode 100755 src/lib/openjp3d/jp3d.c create mode 100755 src/lib/openjp3d/jp3d.h create mode 100755 src/lib/openjp3d/jp3d_lib.c create mode 100755 src/lib/openjp3d/jp3d_lib.h create mode 100755 src/lib/openjp3d/mct.c create mode 100755 src/lib/openjp3d/mct.h create mode 100755 src/lib/openjp3d/mqc.c create mode 100755 src/lib/openjp3d/mqc.h create mode 100755 src/lib/openjp3d/openjp3d.c create mode 100755 src/lib/openjp3d/openjp3d.h create mode 100755 src/lib/openjp3d/opj_includes.h create mode 100755 src/lib/openjp3d/pi.c create mode 100755 src/lib/openjp3d/pi.h create mode 100755 src/lib/openjp3d/raw.c create mode 100755 src/lib/openjp3d/raw.h create mode 100755 src/lib/openjp3d/t1.c create mode 100755 src/lib/openjp3d/t1.h create mode 100755 src/lib/openjp3d/t1_3d.c create mode 100755 src/lib/openjp3d/t1_3d.h create mode 100755 src/lib/openjp3d/t2.c create mode 100755 src/lib/openjp3d/t2.h create mode 100755 src/lib/openjp3d/tcd.c create mode 100755 src/lib/openjp3d/tcd.h create mode 100755 src/lib/openjp3d/tgt.c create mode 100755 src/lib/openjp3d/tgt.h create mode 100755 src/lib/openjp3d/volume.c create mode 100755 src/lib/openjp3d/volume.h (limited to 'src/lib') diff --git a/src/lib/openjp3d/CMakeLists.txt b/src/lib/openjp3d/CMakeLists.txt new file mode 100644 index 00000000..a7b00965 --- /dev/null +++ b/src/lib/openjp3d/CMakeLists.txt @@ -0,0 +1,40 @@ + +INCLUDE_REGULAR_EXPRESSION("^.*$") + +SET(OPENJP3D_LIBRARY_NAME openjp3d) +# Defines the source code for the library +SET(OPENJP3D_SRCS +bio.c cio.c dwt.c event.c jp3d.c jp3d_lib.c mct.c mqc.c openjp3d.c pi.c raw.c t1.c t1_3d.c t2.c tcd.c tgt.c volume.c +) + +# Build the library +IF(WIN32) + IF(BUILD_SHARED_LIBS) + ADD_DEFINITIONS(-DOPJ_EXPORTS) + ELSE(BUILD_SHARED_LIBS) + ADD_DEFINITIONS(-DOPJ_STATIC) + ENDIF(BUILD_SHARED_LIBS) +ENDIF(WIN32) + +# build jp3d lib: +ADD_LIBRARY(${OPENJP3D_LIBRARY_NAME} ${OPENJP3D_SRCS}) +IF(UNIX) + TARGET_LINK_LIBRARIES(${OPENJP3D_LIBRARY_NAME} m) +ENDIF(UNIX) +SET_TARGET_PROPERTIES(${OPENJP3D_LIBRARY_NAME} PROPERTIES ${OPENJPEG_LIBRARY_PROPERTIES}) + +# Install library +INSTALL(TARGETS ${OPENJP3D_LIBRARY_NAME} + EXPORT OpenJP3DTargets + DESTINATION ${OPENJPEG_INSTALL_LIB_DIR} + COMPONENT Libraries +) + +# Install includes files +INSTALL(FILES openjp3d.h + DESTINATION ${OPENJP3D_INSTALL_INCLUDE_DIR}/${subdir} + COMPONENT Headers +) +#INSTALL(CODE +# "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${subdir}/openjp3d.h \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${OPENJP3D_INSTALL_INCLUDE_DIR}/openjp3d.h)") +# diff --git a/src/lib/openjp3d/Makefile.am b/src/lib/openjp3d/Makefile.am new file mode 100644 index 00000000..578bcac2 --- /dev/null +++ b/src/lib/openjp3d/Makefile.am @@ -0,0 +1,88 @@ +MAINTAINERCLEANFILES = Makefile.in + +lib_LTLIBRARIES = libopenjp3dvm.la + +includesdir = ${includedir}/openjp3d-@JP3D_MAJOR_NR@.@JP3D_MINOR_NR@ +includes_HEADERS = openjp3d.h + +libopenjp3dvm_la_LDFLAGS = -no-undefined -version-info @lt_version_jp3d@ + +libopenjp3dvm_la_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/jp3d/libjp3dvm \ +-I$(top_builddir)/jp3d/libjp3dvm +libopenjp3dvm_la_CFLAGS = +libopenjp3dvm_la_LIBADD = -lm +libopenjp3dvm_la_SOURCES = \ +bio.c \ +cio.c \ +dwt.c \ +event.c \ +jp3d.c \ +jp3d_lib.c \ +volume.c \ +mct.c \ +mqc.c \ +openjp3d.c \ +pi.c \ +raw.c \ +t1.c \ +t1_3d.c \ +t2.c \ +tcd.c \ +tgt.c \ +bio.h \ +cio.h \ +dwt.h \ +event.h \ +fix.h \ +int.h \ +jp3d.h \ +jp3d_lib.h \ +mct.h \ +mqc.h \ +opj_includes.h \ +pi.h \ +raw.h \ +t1.h \ +t1_3d.h \ +t2.h \ +tcd.h \ +tgt.h \ +volume.h + +EXTRA_DIST = \ +CMakeLists.txt + +install-data-hook: + cd $(DESTDIR)$(includedir) && \ + rm -f openjp3d.h && \ + $(LN_S) openjp3d-@JP3D_MAJOR_NR@.@JP3D_MINOR_NR@/openjp3d.h \ + openjp3d.h + @echo -e " (LA)\t$(libdir)/libopenjp3dvm.la" >> $(top_builddir)/report.txt + @( $(call solist) ) >> $(top_builddir)/report.txt + @echo -e " (A)\t$(base)/$(a)" >> $(top_builddir)/report.txt + @echo -e " (H)\t$(includedir)/openjp3d-$(MAJOR_NR).$(MINOR_NR)/openjp3d.h" >> $(top_builddir)/report.txt + @echo -e " (LN)\t$(includedir)/openjp3d.h" >> $(top_builddir)/report.txt + +uninstall-hook: + rm -f $(DESTDIR)$(includedir)/openjp3d.h + +solist = $(foreach f, $(dll) $(so), echo -e ' $(SO_PREFIX)\t$(base)/$(f)' ;) +get_tok = $(shell grep -E "^$(1)=" $(lib_LTLIBRARIES) | cut -d "'" -f 2) +base = $(call get_tok,libdir) +so = $(call get_tok,library_names) +a = $(call get_tok,old_library) + +if HAVE_WIN32 +SO_PREFIX = (DLL) +dll = $(call get_tok,dlname) +else +if HAVE_DARWIN +SO_PREFIX = (DY) +dll = +else +SO_PREFIX = (SO) +dll = +endif +endif diff --git a/src/lib/openjp3d/bio.c b/src/lib/openjp3d/bio.c new file mode 100755 index 00000000..bc3b1138 --- /dev/null +++ b/src/lib/openjp3d/bio.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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 */ +/*@{*/ + +/** +Write a bit +@param bio BIO handle +@param b Bit to write (0 or 1) +*/ +static void bio_putbit(opj_bio_t *bio, int b); +/** +Read a bit +@param bio BIO handle +@return Returns the read bit +*/ +static int bio_getbit(opj_bio_t *bio); +/** +Write a byte +@param bio BIO handle +@return Returns 0 if successful, returns 1 otherwise +*/ +static int bio_byteout(opj_bio_t *bio); +/** +Read a byte +@param bio BIO handle +@return Returns 0 if successful, returns 1 otherwise +*/ +static int bio_bytein(opj_bio_t *bio); + +/*@}*/ + +/*@}*/ + + +/* +========================================================== + local functions +========================================================== +*/ + +static int 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 1; + } + *bio->bp++ = bio->buf >> 8; + return 0; +} + +static int 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 1; + } + bio->buf |= *bio->bp++; + return 0; +} + +static void bio_putbit(opj_bio_t *bio, int b) { + if (bio->ct == 0) { + bio_byteout(bio); + } + bio->ct--; + bio->buf |= b << bio->ct; +} + +/* MOD antonin */ +static int bio_getbit(opj_bio_t *bio) { +/* DOM */ + if (bio->ct == 0) { + bio_bytein(bio); + } + bio->ct--; + return (bio->buf >> bio->ct) & 1; +} + +/* +========================================================== + Bit Input/Output interface +========================================================== +*/ + +opj_bio_t* bio_create() { + 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); + } +} + +int bio_numbytes(opj_bio_t *bio) { + return (bio->bp - bio->start); +} + +void bio_init_enc(opj_bio_t *bio, unsigned char *bp, int 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, unsigned char *bp, int len) { + bio->start = bp; + bio->end = bp + len; + bio->bp = bp; + bio->buf = 0; + bio->ct = 0; +} + +void bio_write(opj_bio_t *bio, int v, int n) { + int i; + for (i = n - 1; i >= 0; i--) { + bio_putbit(bio, (v >> i) & 1); + } +} + +int bio_read(opj_bio_t *bio, int n) { + int i, v; + v = 0; + for (i = n - 1; i >= 0; i--) { + v += bio_getbit(bio) << i; + } + return v; +} + +int bio_flush(opj_bio_t *bio) { + bio->ct = 0; + if (bio_byteout(bio)) { + return 1; + } + if (bio->ct == 7) { + bio->ct = 0; + if (bio_byteout(bio)) { + return 1; + } + } + return 0; +} + +int bio_inalign(opj_bio_t *bio) { + bio->ct = 0; + if ((bio->buf & 0xff) == 0xff) { + if (bio_bytein(bio)) { + return 1; + } + bio->ct = 0; + } + return 0; +} diff --git a/src/lib/openjp3d/bio.h b/src/lib/openjp3d/bio.h new file mode 100755 index 00000000..36bb942b --- /dev/null +++ b/src/lib/openjp3d/bio.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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. +*/ + +/** @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 */ + unsigned char *start; +/** pointer to the end of the buffer */ + unsigned char *end; +/** pointer to the present position in the buffer */ + unsigned char *bp; +/** temporary place where each byte is read or written */ + unsigned int buf; +/** coder : number of bits free to write. decoder : number of bits read */ + int ct; +} opj_bio_t; + +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new BIO handle +@return Returns a new BIO handle if successful, returns NULL otherwise +*/ +opj_bio_t* bio_create(); +/** +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 +*/ +int 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, unsigned char *bp, int len); +/** +Init decoder +@param bio BIO handle +@param bp Input buffer +@param len Input buffer length +*/ +void bio_init_dec(opj_bio_t *bio, unsigned char *bp, int 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, int v, int n); +/** +Read bits +@param bio BIO handle +@param n Number of bits to read +@return Returns the corresponding read number +*/ +int bio_read(opj_bio_t *bio, int n); +/** +Flush bits +@param bio BIO handle +@return Returns 1 if successful, returns 0 otherwise +*/ +int 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 +*/ +int bio_inalign(opj_bio_t *bio); +/** +Read a bit +@param bio BIO handle +@return Returns the read bit +*/ +/* MOD antonin */ +//int bio_getbit(opj_bio_t *bio); +/* DOM */ +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __BIO_H */ + diff --git a/src/lib/openjp3d/cio.c b/src/lib/openjp3d/cio.c new file mode 100755 index 00000000..4ac64fd3 --- /dev/null +++ b/src/lib/openjp3d/cio.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length) { + opj_cp_t *cp = NULL; + opj_cio_t *cio = (opj_cio_t*)opj_malloc(sizeof(opj_cio_t)); + if(!cio) return NULL; + cio->cinfo = cinfo; + if(buffer && length) { + /* wrap a user buffer containing the encoded image */ + cio->openmode = OPJ_STREAM_READ; + cio->buffer = buffer; + cio->length = length; + } + else if(!buffer && !length && cinfo) { + /* allocate a buffer for the encoded image */ + cio->openmode = OPJ_STREAM_WRITE; + switch(cinfo->codec_format) { + case CODEC_J3D: + case CODEC_J2K: + cp = ((opj_j3d_t*)cinfo->j3d_handle)->cp; + break; + default: + opj_free(cio); + return NULL; + } + cio->length = cp->tdx * cp->tdy * cp->tdz * cp->tw * cp->th * cp->tl * 4; + cio->buffer = (unsigned char *)opj_malloc(cio->length); + if(!cio->buffer) { + opj_free(cio); + return NULL; + } + } + else { + opj_free(cio); + return NULL; + } + + /* Initialize byte IO */ + cio->start = cio->buffer; + cio->end = cio->buffer + cio->length; + cio->bp = cio->buffer; + + return cio; +} + +void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio) { + if(cio) { + if(cio->openmode == OPJ_STREAM_WRITE) { + /* destroy the allocated buffer */ + opj_free(cio->buffer); + } + /* destroy the cio */ + opj_free(cio); + } +} + + +/* ----------------------------------------------------------------------- */ + +/* + * Get position in byte stream. + */ +int OPJ_CALLCONV cio_tell(opj_cio_t *cio) { + return cio->bp - cio->start; +} + +/* + * Set position in byte stream. + * + * pos : position, in number of bytes, from the beginning of the stream + */ +void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) { + cio->bp = cio->start + pos; +} + +/* + * Number of bytes left before the end of the stream. + */ +int cio_numbytesleft(opj_cio_t *cio) { + return cio->end - cio->bp; +} + +/* + * Get pointer to the current position in the stream. + */ +unsigned char *cio_getbp(opj_cio_t *cio) { + return cio->bp; +} + +/* + * Write a byte. + */ +bool cio_byteout(opj_cio_t *cio, unsigned char v) { + if (cio->bp >= cio->end) { + opj_event_msg(cio->cinfo, EVT_ERROR, "write error\n"); + return false; + } + *cio->bp++ = v; + return true; +} + +/* + * Read a byte. + */ +unsigned char cio_bytein(opj_cio_t *cio) { + if (cio->bp >= cio->end) { + opj_event_msg(cio->cinfo, EVT_ERROR, "read error\n"); + return 0; + } + return *cio->bp++; +} + +/* + * Write some bytes. + * + * v : value to write + * n : number of bytes to write + */ +unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n) { + int i; + for (i = n - 1; i >= 0; i--) { + if( !cio_byteout(cio, (unsigned char) ((v >> (i << 3)) & 0xff)) ) + return 0; + } + return n; +} + +/* + * Read some bytes. + * + * n : number of bytes to read + * + * return : value of the n bytes read + */ +unsigned int cio_read(opj_cio_t *cio, int n) { + int i; + unsigned int v; + v = 0; + for (i = n - 1; i >= 0; i--) { + v += cio_bytein(cio) << (i << 3); + } + return v; +} + +/* + * Skip some bytes. + * + * n : number of bytes to skip + */ +void cio_skip(opj_cio_t *cio, int n) { + cio->bp += n; +} + +/* + * Write some bytes. + * + * v : value to write + * n : number of bytes to write + */ +int cio_write_int(opj_cio_t *cio, int v, int n) { + int i; + for (i = n - 1; i >= 0; i--) { + if( !cio_byteout(cio, (char) ((v >> (i << 3)) & 0xff)) ) + return 0; + } + return n; +} + +/* + * Read some bytes. + * + * n : number of bytes to read + * + * return : value of the n bytes read + */ +int cio_read_int(opj_cio_t *cio, int n) { + int i; + int v; + v = 0; + for (i = n - 1; i >= 0; i--) { + v += cio_bytein(cio) << (i << 3); + } + return v; +} + diff --git a/src/lib/openjp3d/cio.h b/src/lib/openjp3d/cio.h new file mode 100755 index 00000000..b7b0c416 --- /dev/null +++ b/src/lib/openjp3d/cio.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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 */ +/*@{*/ + +/** @name Funciones generales (see also openjp3d.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Number of bytes left before the end of the stream +@param cio CIO handle +@return Returns the number of bytes before the end of the stream +*/ +int cio_numbytesleft(opj_cio_t *cio); +/** +Get pointer to the current position in the stream +@param cio CIO handle +@return Returns a pointer to the current position +*/ +unsigned char *cio_getbp(opj_cio_t *cio); +/** +Write some bytes +@param cio CIO handle +@param v Value to write +@param n Number of bytes to write +@return Returns the number of bytes written or 0 if an error occured +*/ +unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n); +/** +Read some bytes +@param cio CIO handle +@param n Number of bytes to read +@return Returns the value of the n bytes read +*/ +unsigned int cio_read(opj_cio_t *cio, int n); +/** +Skip some bytes +@param cio CIO handle +@param n Number of bytes to skip +*/ +void cio_skip(opj_cio_t *cio, int n); +/** +Write some bytes +@param cio CIO handle +@param v Signed integer value to write +@param n Number of bytes to write +@return Returns the number of bytes written or 0 if an error occured +*/ +int cio_write_int(opj_cio_t *cio, int v, int n); +/** +Read some bytes +@param cio CIO handle +@param n Number of bytes to read +@return Returns the value of the n bytes read +*/ +int cio_read_int(opj_cio_t *cio, int n); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __CIO_H */ + diff --git a/src/lib/openjp3d/dwt.c b/src/lib/openjp3d/dwt.c new file mode 100755 index 00000000..8f30daeb --- /dev/null +++ b/src/lib/openjp3d/dwt.c @@ -0,0 +1,1016 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyrigth (c) 2006, Mónica Díez, LPI-UVA, Spain + * 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. + */ + +/* + * NOTE: + * This is a modified version of the openjpeg dwt.c file. + * Average speed improvement compared to the original file (measured on + * my own machine, a P4 running at 3.0 GHz): + * 5x3 wavelets about 2 times faster + * 9x7 wavelets about 3 times faster + * for both, encoding and decoding. + * + * The better performance is caused by doing the 1-dimensional DWT + * within a temporary buffer where the data can be accessed sequential + * for both directions, horizontal and vertical. The 2d vertical DWT was + * the major bottleneck in the former version. + * + * I have also removed the "Add Patrick" part because it is not longer + * needed. + * + * 6/6/2005 + * -Ive (aka Reiner Wahler) + * mail: ive@lilysoft.com + */ + +#include "opj_includes.h" + +/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ +unsigned int ops; +/** +Forward lazy transform (horizontal) +*/ +static void dwt_deinterleave_h(int *a, int *b, int dn, int sn, int cas); +/** +Forward lazy transform (vertical) +*/ +static void dwt_deinterleave_v(int *a, int *b, int dn, int sn, int x, int cas); +/** +Forward lazy transform (axial) +*/ +static void dwt_deinterleave_z(int *a, int *b, int dn, int sn, int xy, int cas); +/** +Inverse lazy transform (horizontal) +*/ +static void dwt_interleave_h(int *a, int *b, int dn, int sn, int cas); +/** +Inverse lazy transform (vertical) +*/ +static void dwt_interleave_v(int *a, int *b, int dn, int sn, int x, int cas); +/** +Inverse lazy transform (axial) +*/ +static void dwt_interleave_z(int *a, int *b, int dn, int sn, int xy, int cas); +/** +Forward 5-3 wavelet tranform in 1-D +*/ +static void dwt_encode_53(int *a, int dn, int sn, int cas); +static void dwt_encode_97(int *a, int dn, int sn, int cas); +/** +Inverse 5-3 wavelet tranform in 1-D +*/ +static void dwt_decode_53(int *a, int dn, int sn, int cas); +static void dwt_decode_97(int *a, int dn, int sn, int cas); +/** +Computing of wavelet transform L2 norms for arbitrary transforms +*/ +static double dwt_calc_wtnorms(int orient, int level[3], int dwtid[3], opj_wtfilt_t *wtfiltx, opj_wtfilt_t *wtfilty, opj_wtfilt_t *wtfiltz); +/** +Encoding of quantification stepsize +*/ +static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno_stepsize); +/*@}*/ + +/*@}*/ + +#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 double dwt_norm[10][10][10][8]; +static int flagnorm[10][10][10][8]; + +/*static const double dwt_norms[5][8][10] = { + {//ResZ=1 + {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} + },{//ResZ=2 + {1.000, 1.8371, 2.750, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3}, + {1.2717, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {1.2717, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {.8803, .9218, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93}, + {1.2717}, + {.8803}, + {.8803}, + {.6093}, + },{ //ResZ=3 + {1.000, 1.8371, 4.5604, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3}, + {1.2717, 2.6403, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {1.2717, 2.6403, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {.8803, 1.5286, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93}, + {1.2717, 2.6403}, + {.8803, 1.5286}, + {.8803, 1.5286}, + {.6093, 0.8850}, + },{ //ResZ=4 + {1.000, 1.8371, 4.5604, 12.4614, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3}, + {1.2717, 2.6403, 6.7691 , 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {1.2717, 2.6403, 6.7691 , 5.703, 11.33, 22.64, 45.25, 90.48, 180.9}, + {.8803, 1.5286, 3.6770 , 3.043, 6.019, 12.01, 24.00, 47.97, 95.93}, + {1.2717, 2.6403, 6.7691 }, + {.8803, 1.5286, 3.6770 }, + {.8803, 1.5286, 3.6770 }, + {.6093, 0.8850, 1.9974 }, + },{ //ResZ=5 + {1.000, 1.8371, 4.5604, 12.4614, 34.9025, 21.34, 42.67, 85.33, 170.7, 341.3}, + {1.2717, 2.6403, 6.7691 , 18.6304 , 11.33, 22.64, 45.25, 90.48, 180.9}, + {1.2717, 2.6403, 6.7691 , 18.6304, 11.33, 22.64, 45.25, 90.48, 180.9}, + {.8803, 1.5286, 3.6770 , 9.9446, 6.019, 12.01, 24.00, 47.97, 95.93}, + {1.2717, 2.6403, 6.7691, 18.6304}, + {.8803, 1.5286, 3.6770, 9.9446 }, + {.8803, 1.5286, 3.6770, 9.9446 }, + {.6093, 0.8850, 1.9974, 5.3083 }, + } +};*/ + +/* */ +/* This table contains the norms of the 9-7 wavelets for different bands. */ +/* */ +/*static const double dwt_norms_real[5][8][10] = { + {//ResZ==1 + {1.000, 1.9659, 4.1224, 8.4167, 16.9356, 33.9249, 67.8772, 135.7680, 271.5430, 543.0894}, + {1.0113, 1.9968, 4.1834, 8.5341, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {1.0113, 1.9968, 4.1834, 8.5341, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {0.5202, 0.9672, 2.0793, 4.3005, 8.6867, 17.4188, 34.8608, 69.7332, 139.4722} + }, { //ResZ==2 + {1.000, 2.7564, 4.1224, 8.4167, 16.9356, 33.9249, 67.8772, 135.7680, 271.5430, 543.0894}, + {1.4179, 1.9968, 4.1834, 8.5341, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {1.4179, 1.9968, 4.1834, 8.5341, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {0.7294, 0.9672, 2.0793, 4.3005, 8.6867, 17.4188, 34.8608, 69.7332, 139.4722}, + {1.4179}, + {0.7294}, + {0.7294}, + {0.3752} //HHH + },{ //ResZ==3 + {1.000, 2.7564, 8.3700, 8.4167, 16.9356, 33.9249, 67.8772, 135.7680, 271.5430, 543.0894}, + {1.4179, 4.0543, 4.1834, 8.5341, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {1.4179, 4.0543, 4.1834, 8.5341, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {0.7294, 1.9638, 2.0793, 4.3005, 8.6867, 17.4188, 34.8608, 69.7332, 139.4722}, + {1.4179, 4.0543}, + {0.7294, 1.9638}, + {0.7294, 1.9638}, + {0.3752, 0.9512} //HHH + },{ //ResZ==4 + {1.000, 2.7564, 8.3700, 24.4183, 16.9356, 33.9249, 67.8772, 135.7680, 271.5430, 543.0894}, + {1.4179, 4.0543, 12.1366, 8.5341, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {1.4179, 4.0543, 12.1366, 8.5341, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {0.7294, 1.9638, 6.0323, 4.3005, 8.6867, 17.4188, 34.8608, 69.7332, 139.4722}, + {1.4179, 4.0543, 12.1366}, + {0.7294, 1.9638, 6.0323}, + {0.7294, 1.9638, 6.0323}, + {0.3752, 0.9512, 2.9982} //HHH + },{ //ResZ==5 + {1.000, 2.7564, 8.3700, 24.4183, 69.6947, 33.9249, 67.8772, 135.7680, 271.5430, 543.0894}, + {1.4179, 4.0543, 12.1366, 35.1203, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {1.4179, 4.0543, 12.1366, 35.1203, 17.1667, 34.3852, 68.7967, 137.6065, 275.2196}, + {0.7294, 1.9638, 6.0323, 17.6977, 8.6867, 17.4188, 34.8608, 69.7332, 139.4722}, + {1.4179, 4.0543, 12.1366, 35.1203}, + {0.7294, 1.9638, 6.0323, 17.6977}, + {0.7294, 1.9638, 6.0323, 17.6977}, + {0.3752, 0.9512, 2.9982, 8.9182} //HHH + } +};*/ + +static opj_atk_t atk_info_wt[] = { + {0, 1, J3D_ATK_WS, J3D_ATK_IRR, 0, J3D_ATK_WS, 1.230174104, 4, {0}, {0}, {0}, {1,1,1,1}, {-1.586134342059924, -0.052980118572961, 0.882911075530934, 0.443506852043971}},/* WT 9-7 IRR*/ + {1, 0, J3D_ATK_WS, J3D_ATK_REV, 0, J3D_ATK_WS, 0, 2, {0}, {1,2}, {1,2}, {1,1}, {-1,1}},/* WT 5-3 REV*/ + {2, 0, J3D_ATK_ARB, J3D_ATK_REV, 0, J3D_ATK_CON, 0, 2, {0,0}, {0,1}, {0,1}, {1,1}, {{-1},{1}}}, /* WT 2-2 REV*/ + {3, 0, J3D_ATK_ARB, J3D_ATK_REV, 1, J3D_ATK_CON, 0, 3, {0,0,-1}, {0,1,2}, {0,1,2}, {1,1,3}, {{-1},{1},{1,0,-1}}}, /* WT 2-6 REV*/ + {4, 0, J3D_ATK_ARB, J3D_ATK_REV, 1, J3D_ATK_CON, 0, 3, {0,0,-2}, {0,1,6}, {0,1,32}, {1,1,5}, {{-1},{1},{-3,22,0,-22,3}}}, /* WT 2-10 REV*/ + {5, 1, J3D_ATK_ARB, J3D_ATK_IRR, 1, J3D_ATK_WS, 1, 7, {0}, {0}, {0}, {1,1,2,1,2,1,3},{{-1},{1.58613434206},{-0.460348209828, 0.460348209828},{0.25},{0.374213867768,-0.374213867768},{-1.33613434206},{0.29306717103,0,-0.29306717103}}}, /* WT 6-10 IRR*/ + {6, 1, J3D_ATK_ARB, J3D_ATK_IRR, 0, J3D_ATK_WS, 1, 11, {0}, {0}, {0}, {1,1,2,1,2,1,2,1,2,1,5},{{-1},{0,99715069105},{-1.00573127827, 1.00573127827},{-0.27040357631},{2.20509972343, -2.20509972343},{0.08059995736}, + {-1.62682532350, 1.62682532350},{0.52040357631},{0.60404664250, -0.60404664250},{-0.82775064841},{-0.06615812964, 0.29402137720, 0, -0.29402137720, 0.06615812964}}}, /* WT 10-18 IRR*/ + {7, 1, J3D_ATK_WS, J3D_ATK_IRR, 0, J3D_ATK_WS, 1, 2, {0}, {0}, {0}, {1,1}, {-0.5, 0.25}}, /* WT 5-3 IRR*/ + {8, 0, J3D_ATK_WS, J3D_ATK_REV, 0, J3D_ATK_WS, 0, 2, {0}, {4,4}, {8,8}, {2,2}, {{-9,1},{5,-1}}} /* WT 13-7 REV*/ +}; +/* +========================================================== + local functions +========================================================== +*/ + +/* */ +/* Forward lazy transform (horizontal). */ +/* */ +static void dwt_deinterleave_h(int *a, int *b, int dn, int sn, int cas) { + int i; + for (i=0; i */ +/* Forward lazy transform (vertical). */ +/* */ +static void dwt_deinterleave_v(int *a, int *b, int dn, int sn, int x, int cas) { + int i; + for (i=0; i */ +/* Forward lazy transform (axial). */ +/* */ +static void dwt_deinterleave_z(int *a, int *b, int dn, int sn, int xy, int cas) { + int i; + for (i=0; i */ +/* Inverse lazy transform (horizontal). */ +/* */ +static void dwt_interleave_h(int *a, int *b, int dn, int sn, int cas) { + int i; + int *ai = NULL; + int *bi = NULL; + ai = a; + bi = b + cas; + for (i = 0; i < sn; i++) { + *bi = *ai; + bi += 2; + ai++; + } + ai = a + sn; + bi = b + 1 - cas; + for (i = 0; i < dn; i++) { + *bi = *ai; + bi += 2; + ai++; + } +} + +/* */ +/* Inverse lazy transform (vertical). */ +/* */ +static void dwt_interleave_v(int *a, int *b, int dn, int sn, int x, int cas) { + int i; + int *ai = NULL; + int *bi = NULL; + ai = a; + bi = b + cas; + for (i = 0; i < sn; i++) { + *bi = *ai; + bi += 2; + ai += x; + } + ai = a + (sn * x); + bi = b + 1 - cas; + for (i = 0; i < dn; i++) { + *bi = *ai; + bi += 2; + ai += x; + } +} + +/* */ +/* Inverse lazy transform (axial). */ +/* */ +static void dwt_interleave_z(int *a, int *b, int dn, int sn, int xy, int cas) { + int i; + int *ai = NULL; + int *bi = NULL; + ai = a; + bi = b + cas; + for (i = 0; i < sn; i++) { + *bi = *ai; + bi += 2; + ai += xy; + } + ai = a + (sn * xy); + bi = b + 1 - cas; + for (i = 0; i < dn; i++) { + *bi = *ai; + bi += 2; + ai += xy; + } +} + + +/* */ +/* Forward 5-3 or 9-7 wavelet tranform in 1-D. */ +/* */ +static void dwt_encode_53(int *a, int dn, int sn, int cas) { + int 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; + for (i = 0; i < dn; i++){ + D(i) -= (S_(i) + S_(i + 1)) >> 1; + //ops += 2; + } + for (i = 0; i < sn; i++){ + S(i) += (D_(i - 1) + D_(i) + 2) >> 2; + //ops += 3; + } + } + } else { + /*if (!sn && dn == 1) + 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; + }*/ + if (!sn && dn == 1){ + S(0) *= 2; + //ops++; + } else { + for (i = 0; i < dn; i++){ + S(i) -= (DD_(i) + DD_(i - 1)) >> 1; + // ops += 2; + } + for (i = 0; i < sn; i++){ + D(i) += (SS_(i) + SS_(i + 1) + 2) >> 2; + // ops += 3; + } + } + } +} +static void dwt_encode_97(int *a, int dn, int sn, int cas) { + int 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 */ + } + } +} +/* */ +/* Inverse 5-3 or 9-7 wavelet tranform in 1-D. */ +/* */ +static void dwt_decode_53(int *a, int dn, int sn, int cas) { + int 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; + } + } +} +static void dwt_decode_97(int *a, int dn, int sn, int cas) { + int i; + + if (!cas) { + if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < sn; i++) + S(i) = fix_mul(S(i), 10078); /* 10076 */ + for (i = 0; i < dn; i++) + D(i) = fix_mul(D(i), 13318); /* 13320 */ + 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(S_(i) + S_(i + 1), 7233); + 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), 12994); /* 12993 */ + } + } else { + if ((sn > 0) || (dn > 1)) { /* NEW : CASE ONE ELEMENT */ + for (i = 0; i < sn; i++) + D(i) = fix_mul(D(i), 10078); /* 10076 */ + for (i = 0; i < dn; i++) + S(i) = fix_mul(S(i), 13318); /* 13320 */ + 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(DD_(i) + DD_(i - 1), 7233); + 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), 12994); /* 12993 */ + } + } +} + + +/* */ +/* Get norm of arbitrary wavelet transform. */ +/* */ +static int upandconv(double *nXPS, double *LPS, int lenXPS, int lenLPS) { + /* Perform the convolution of the vectors. */ + int i,j; + double *tmp = (double *)opj_malloc(2*lenXPS * sizeof(double)); + //Upsample + memset(tmp, 0, 2*lenXPS*sizeof(double)); + for (i = 0; i < lenXPS; i++) { + *(tmp + 2*i) = *(nXPS + i); + *(nXPS + i) = 0; + } + //Convolution + for (i = 0; i < 2*lenXPS; i++) { + for (j = 0; j < lenLPS; j++) { + *(nXPS+i+j) = *(nXPS+i+j) + *(tmp + i) * *(LPS + j); + //fprintf(stdout,"*(tmp + %d) * *(LPS + %d) = %f * %f \n",i,j,*(tmp + i),*(LPS + j)); + } + } + free(tmp); + return 2*lenXPS+lenLPS-1; +} + +static double dwt_calc_wtnorms(int orient, int level[3], int dwtid[3], opj_wtfilt_t *wtfiltX, opj_wtfilt_t *wtfiltY, opj_wtfilt_t *wtfiltZ) { + int i, lenLPS, lenHPS; + double Lx = 0, Ly= 0, Hx= 0, Hy= 0, Lz= 0, Hz= 0; + double *nLPSx, *nHPSx,*nLPSy, *nHPSy,*nLPSz, *nHPSz; + int levelx, levely, levelz; + + levelx = (orient == 0) ? level[0]-1 : level[0]; + levely = (orient == 0) ? level[1]-1 : level[1]; + levelz = (orient == 0) ? level[2]-1 : level[2]; + + //X axis + lenLPS = wtfiltX->lenLPS; + lenHPS = wtfiltX->lenHPS; + for (i = 0; i < levelx; i++) { + lenLPS *= 2; + lenHPS *= 2; + lenLPS += wtfiltX->lenLPS - 1; + lenHPS += wtfiltX->lenLPS - 1; + } + nLPSx = (double *)opj_malloc(lenLPS * sizeof(double)); + nHPSx = (double *)opj_malloc(lenHPS * sizeof(double)); + + memcpy(nLPSx, wtfiltX->LPS, wtfiltX->lenLPS * sizeof(double)); + memcpy(nHPSx, wtfiltX->HPS, wtfiltX->lenHPS * sizeof(double)); + lenLPS = wtfiltX->lenLPS; + lenHPS = wtfiltX->lenHPS; + for (i = 0; i < levelx; i++) { + lenLPS = upandconv(nLPSx, wtfiltX->LPS, lenLPS, wtfiltX->lenLPS); + lenHPS = upandconv(nHPSx, wtfiltX->LPS, lenHPS, wtfiltX->lenLPS); + } + for (i = 0; i < lenLPS; i++) + Lx += nLPSx[i] * nLPSx[i]; + for (i = 0; i < lenHPS; i++) + Hx += nHPSx[i] * nHPSx[i]; + Lx = sqrt(Lx); + Hx = sqrt(Hx); + free(nLPSx); + free(nHPSx); + + //Y axis + if (dwtid[0] != dwtid[1] || level[0] != level[1]){ + lenLPS = wtfiltY->lenLPS; + lenHPS = wtfiltY->lenHPS; + for (i = 0; i < levely; i++) { + lenLPS *= 2; + lenHPS *= 2; + lenLPS += wtfiltY->lenLPS - 1; + lenHPS += wtfiltY->lenLPS - 1; + } + nLPSy = (double *)opj_malloc(lenLPS * sizeof(double)); + nHPSy = (double *)opj_malloc(lenHPS * sizeof(double)); + + memcpy(nLPSy, wtfiltY->LPS, wtfiltY->lenLPS * sizeof(double)); + memcpy(nHPSy, wtfiltY->HPS, wtfiltY->lenHPS * sizeof(double)); + lenLPS = wtfiltY->lenLPS; + lenHPS = wtfiltY->lenHPS; + for (i = 0; i < levely; i++) { + lenLPS = upandconv(nLPSy, wtfiltY->LPS, lenLPS, wtfiltY->lenLPS); + lenHPS = upandconv(nHPSy, wtfiltY->LPS, lenHPS, wtfiltY->lenLPS); + } + for (i = 0; i < lenLPS; i++) + Ly += nLPSy[i] * nLPSy[i]; + for (i = 0; i < lenHPS; i++) + Hy += nHPSy[i] * nHPSy[i]; + Ly = sqrt(Ly); + Hy = sqrt(Hy); + free(nLPSy); + free(nHPSy); + } else { + Ly = Lx; + Hy = Hx; + } + //Z axis + if (levelz >= 0) { + lenLPS = wtfiltZ->lenLPS; + lenHPS = wtfiltZ->lenHPS; + for (i = 0; i < levelz; i++) { + lenLPS *= 2; + lenHPS *= 2; + lenLPS += wtfiltZ->lenLPS - 1; + lenHPS += wtfiltZ->lenLPS - 1; + } + nLPSz = (double *)opj_malloc(lenLPS * sizeof(double)); + nHPSz = (double *)opj_malloc(lenHPS * sizeof(double)); + + memcpy(nLPSz, wtfiltZ->LPS, wtfiltZ->lenLPS * sizeof(double)); + memcpy(nHPSz, wtfiltZ->HPS, wtfiltZ->lenHPS * sizeof(double)); + lenLPS = wtfiltZ->lenLPS; + lenHPS = wtfiltZ->lenHPS; + for (i = 0; i < levelz; i++) { + lenLPS = upandconv(nLPSz, wtfiltZ->LPS, lenLPS, wtfiltZ->lenLPS); + lenHPS = upandconv(nHPSz, wtfiltZ->LPS, lenHPS, wtfiltZ->lenLPS); + } + for (i = 0; i < lenLPS; i++) + Lz += nLPSz[i] * nLPSz[i]; + for (i = 0; i < lenHPS; i++) + Hz += nHPSz[i] * nHPSz[i]; + Lz = sqrt(Lz); + Hz = sqrt(Hz); + free(nLPSz); + free(nHPSz); + } else { + Lz = 1.0; Hz = 1.0; + } + switch (orient) { + case 0: + return Lx * Ly * Lz; + case 1: + return Lx * Hy * Lz; + case 2: + return Hx * Ly * Lz; + case 3: + return Hx * Hy * Lz; + case 4: + return Lx * Ly * Hz; + case 5: + return Lx * Hy * Hz; + case 6: + return Hx * Ly * Hz; + case 7: + return Hx * Hy * Hz; + default: + return -1; + } + +} +static void dwt_getwtfilters(opj_wtfilt_t *wtfilt, int dwtid) { + if (dwtid == 0) { //DWT 9-7 + wtfilt->lenLPS = 7; wtfilt->lenHPS = 9; + wtfilt->LPS = (double *)opj_malloc(wtfilt->lenLPS * sizeof(double)); + wtfilt->HPS = (double *)opj_malloc(wtfilt->lenHPS * sizeof(double)); + wtfilt->LPS[0] = -0.091271763114; wtfilt->HPS[0] = 0.026748757411; + wtfilt->LPS[1] = -0.057543526228; wtfilt->HPS[1] = 0.016864118443; + wtfilt->LPS[2] = 0.591271763114; wtfilt->HPS[2] = -0.078223266529; + wtfilt->LPS[3] = 1.115087052457; wtfilt->HPS[3] = -0.266864118443; + wtfilt->LPS[4] = 0.591271763114; wtfilt->HPS[4] = 0.602949018236; + wtfilt->LPS[5] = -0.057543526228; wtfilt->HPS[5] = -0.266864118443; + wtfilt->LPS[6] = -0.091271763114; wtfilt->HPS[6] = -0.078223266529; + wtfilt->HPS[7] = 0.016864118443; + wtfilt->HPS[8] = 0.026748757411; + } else if (dwtid == 1) { //DWT 5-3 + wtfilt->lenLPS = 3; wtfilt->lenHPS = 5; + wtfilt->LPS = (double *)opj_malloc(wtfilt->lenLPS * sizeof(double)); + wtfilt->HPS = (double *)opj_malloc(wtfilt->lenHPS * sizeof(double)); + wtfilt->LPS[0] = 0.5; wtfilt->HPS[0] = -0.125; + wtfilt->LPS[1] = 1; wtfilt->HPS[1] = -0.25; + wtfilt->LPS[2] = 0.5; wtfilt->HPS[2] = 0.75; + wtfilt->HPS[3] = -0.25; + wtfilt->HPS[4] = -0.125; + } else { + fprintf(stdout,"[ERROR] Sorry, this wavelet hasn't been implemented so far ... Try another one :-)\n"); + exit(1); + } +} +/* */ +/* Encoding of quantization stepsize for each subband. */ +/* */ +static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno_stepsize) { + int 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; + //if J3D_CCP_QNTSTY_NOQNT --> stepsize = 8192.0 --> p = 0, n = -2 --> mant = 0; expn = (prec+gain) + //else --> bandno_stepsize = (1<<(numbps - expn)) + (1<<(numbps - expn - 11)) * Ub +} + +/* +========================================================== + DWT interface +========================================================== +*/ +/* */ +/* Forward 5-3 wavelet tranform in 3-D. */ +/* */ +void dwt_encode(opj_tcd_tilecomp_t * tilec, int dwtid[3]) { + int i, j, k; + int x, y, z; + int w, h, wh, d; + int level,levelx,levely,levelz,diff; + int *a = NULL; + int *aj = NULL; + int *bj = NULL; + int *cj = NULL; + + ops = 0; + + memset(flagnorm,0,8000*sizeof(int)); + w = tilec->x1-tilec->x0; + h = tilec->y1-tilec->y0; + d = tilec->z1-tilec->z0; + wh = w * h; + levelx = tilec->numresolution[0]-1; + levely = tilec->numresolution[1]-1; + levelz = tilec->numresolution[2]-1; + level = int_max(levelx,int_max(levely,levelz)); + diff = tilec->numresolution[0] - tilec->numresolution[2]; + + a = tilec->data; + + for (x = 0, y = 0, z = 0; (x < levelx) && (y < levely); x++, y++, z++) { + int rw; /* width of the resolution level computed */ + int rh; /* heigth of the resolution level computed */ + int rd; /* depth of the resolution level computed */ + int rw1; /* width of the resolution level once lower than computed one */ + int rh1; /* height of the resolution level once lower than computed one */ + int rd1; /* depth of the resolution level once lower than computed one */ + int cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ + int cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ + int cas_axl; /* 0 = non inversion on axial filtering 1 = inversion between low-pass and high-pass filtering */ + int dn, sn; + + rw = tilec->resolutions[level - x].x1 - tilec->resolutions[level - x].x0; + rh = tilec->resolutions[level - y].y1 - tilec->resolutions[level - y].y0; + rd = tilec->resolutions[level - z].z1 - tilec->resolutions[level - z].z0; + rw1= tilec->resolutions[level - x - 1].x1 - tilec->resolutions[level - x - 1].x0; + rh1= tilec->resolutions[level - y - 1].y1 - tilec->resolutions[level - y - 1].y0; + rd1= tilec->resolutions[level - z - 1].z1 - tilec->resolutions[level - z - 1].z0; + + cas_col = tilec->resolutions[level - x].x0 % 2; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ + cas_row = tilec->resolutions[level - y].y0 % 2; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ + cas_axl = tilec->resolutions[level - z].z0 % 2; + + /*fprintf(stdout," x %d y %d z %d \n",x,y,z); + fprintf(stdout," levelx %d levely %d levelz %d \n",levelx,levely,levelz); + fprintf(stdout," z1 %d z0 %d\n",tilec->resolutions[level - z].z1,tilec->resolutions[level - z].z0); + fprintf(stdout," rw %d rh %d rd %d \n rw1 %d rh1 %d rd1 %d \n",rw,rh,rd,rw1,rh1,rd1);*/ + + for (i = 0; i < rd; i++) { + + cj = a + (i * wh); + + //Horizontal + sn = rw1; + dn = rw - rw1; + bj = (int*)opj_malloc(rw * sizeof(int)); + if (dwtid[0] == 0) { + for (j = 0; j < rh; j++) { + aj = cj + j * w; + for (k = 0; k < rw; k++) bj[k] = aj[k]; + dwt_encode_97(bj, dn, sn, cas_row); + dwt_deinterleave_h(bj, aj, dn, sn, cas_row); + } + } else if (dwtid[0] == 1) { + for (j = 0; j < rh; j++) { + aj = cj + j * w; + for (k = 0; k < rw; k++) bj[k] = aj[k]; + dwt_encode_53(bj, dn, sn, cas_row); + dwt_deinterleave_h(bj, aj, dn, sn, cas_row); + } + } + opj_free(bj); + + //Vertical + sn = rh1; + dn = rh - rh1; + bj = (int*)opj_malloc(rh * sizeof(int)); + if (dwtid[1] == 0) { /*DWT 9-7*/ + for (j = 0; j < rw; j++) { + aj = cj + j; + for (k = 0; k < rh; k++) bj[k] = aj[k*w]; + dwt_encode_97(bj, dn, sn, cas_col); + dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); + } + } else if (dwtid[1] == 1) { /*DWT 5-3*/ + for (j = 0; j < rw; j++) { + aj = cj + j; + for (k = 0; k < rh; k++) bj[k] = aj[k*w]; + dwt_encode_53(bj, dn, sn, cas_col); + dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col); + } + } + opj_free(bj); + } + + if (z < levelz){ + //Axial fprintf(stdout,"Axial DWT Transform %d %d %d\n",z,rd,rd1); + sn = rd1; + dn = rd - rd1; + bj = (int*)opj_malloc(rd * sizeof(int)); + if (dwtid[2] == 0) { + for (j = 0; j < (rw*rh); j++) { + aj = a + j; + for (k = 0; k < rd; k++) bj[k] = aj[k*wh]; + dwt_encode_97(bj, dn, sn, cas_axl); + dwt_deinterleave_z(bj, aj, dn, sn, wh, cas_axl); + } + } else if (dwtid[2] == 1) { + for (j = 0; j < (rw*rh); j++) { + aj = a + j; + for (k = 0; k < rd; k++) bj[k] = aj[k*wh]; + dwt_encode_53(bj, dn, sn, cas_axl); + dwt_deinterleave_z(bj, aj, dn, sn, wh, cas_axl); + } + } + opj_free(bj); + } + } + + //fprintf(stdout,"[INFO] Ops: %d \n",ops); +} + + +/* */ +/* Inverse 5-3 wavelet tranform in 3-D. */ +/* */ +void dwt_decode(opj_tcd_tilecomp_t * tilec, int stops[3], int dwtid[3]) { + int i, j, k; + int x, y, z; + int w, h, wh, d; + int level, levelx, levely, levelz, diff; + int *a = NULL; + int *aj = NULL; + int *bj = NULL; + int *cj = NULL; + + a = tilec->data; + + w = tilec->x1-tilec->x0; + h = tilec->y1-tilec->y0; + d = tilec->z1-tilec->z0; + wh = w * h; + levelx = tilec->numresolution[0]-1; + levely = tilec->numresolution[1]-1; + levelz = tilec->numresolution[2]-1; + level = int_max(levelx,int_max(levely,levelz)); + diff = tilec->numresolution[0] - tilec->numresolution[2]; + +/* General lifting framework -- DCCS-LIWT */ + for (x = level - 1, y = level - 1, z = level - 1; (x >= stops[0]) && (y >= stops[1]); x--, y--, z--) { + int rw; /* width of the resolution level computed */ + int rh; /* heigth of the resolution level computed */ + int rd; /* depth of the resolution level computed */ + int rw1; /* width of the resolution level once lower than computed one */ + int rh1; /* height of the resolution level once lower than computed one */ + int rd1; /* depth of the resolution level once lower than computed one */ + int cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ + int cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ + int cas_axl; /* 0 = non inversion on axial filtering 1 = inversion between low-pass and high-pass filtering */ + int dn, sn; + + rw = tilec->resolutions[level - x].x1 - tilec->resolutions[level - x].x0; + rh = tilec->resolutions[level - y].y1 - tilec->resolutions[level - y].y0; + rd = tilec->resolutions[level - z].z1 - tilec->resolutions[level - z].z0; + rw1= tilec->resolutions[level - x - 1].x1 - tilec->resolutions[level - x - 1].x0; + rh1= tilec->resolutions[level - y - 1].y1 - tilec->resolutions[level - y - 1].y0; + rd1= tilec->resolutions[level - z - 1].z1 - tilec->resolutions[level - z - 1].z0; + + cas_col = tilec->resolutions[level - x].x0 % 2; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */ + cas_row = tilec->resolutions[level - y].y0 % 2; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */ + cas_axl = tilec->resolutions[level - z].z0 % 2; + + /*fprintf(stdout," x %d y %d z %d \n",x,y,z); + fprintf(stdout," levelx %d levely %d levelz %d \n",levelx,levely,levelz); + fprintf(stdout," dwtid[0] %d [1] %d [2] %d \n",dwtid[0],dwtid[1],dwtid[2]); + fprintf(stdout," rw %d rh %d rd %d \n rw1 %d rh1 %d rd1 %d \n",rw,rh,rd,rw1,rh1,rd1); + fprintf(stdout,"IDWT Transform %d %d %d %d\n",level, z, rd,rd1);*/ + + if (z >= stops[2] && rd != rd1) { + //fprintf(stdout,"Axial Transform %d %d %d %d\n",levelz, z, rd,rd1); + sn = rd1; + dn = rd - rd1; + bj = (int*)opj_malloc(rd * sizeof(int)); + if (dwtid[2] == 0) { + for (j = 0; j < (rw*rh); j++) { + aj = a + j; + dwt_interleave_z(aj, bj, dn, sn, wh, cas_axl); + dwt_decode_97(bj, dn, sn, cas_axl); + for (k = 0; k < rd; k++) aj[k * wh] = bj[k]; + } + } else if (dwtid[2] == 1) { + for (j = 0; j < (rw*rh); j++) { + aj = a + j; + dwt_interleave_z(aj, bj, dn, sn, wh, cas_axl); + dwt_decode_53(bj, dn, sn, cas_axl); + for (k = 0; k < rd; k++) aj[k * wh] = bj[k]; + } + } + opj_free(bj); + } + + for (i = 0; i < rd; i++) { + //Fetch corresponding slice for doing DWT-2D + cj = tilec->data + (i * wh); + + //Vertical + sn = rh1; + dn = rh - rh1; + bj = (int*)opj_malloc(rh * sizeof(int)); + if (dwtid[1] == 0) { + for (j = 0; j < rw; j++) { + aj = cj + j; + dwt_interleave_v(aj, bj, dn, sn, w, cas_col); + dwt_decode_97(bj, dn, sn, cas_col); + for (k = 0; k < rh; k++) aj[k * w] = bj[k]; + } + } else if (dwtid[1] == 1) { + for (j = 0; j < rw; j++) { + aj = cj + j; + dwt_interleave_v(aj, bj, dn, sn, w, cas_col); + dwt_decode_53(bj, dn, sn, cas_col); + for (k = 0; k < rh; k++) aj[k * w] = bj[k]; + } + } + opj_free(bj); + + //Horizontal + sn = rw1; + dn = rw - rw1; + bj = (int*)opj_malloc(rw * sizeof(int)); + if (dwtid[0]==0) { + for (j = 0; j < rh; j++) { + aj = cj + j*w; + dwt_interleave_h(aj, bj, dn, sn, cas_row); + dwt_decode_97(bj, dn, sn, cas_row); + for (k = 0; k < rw; k++) aj[k] = bj[k]; + } + } else if (dwtid[0]==1) { + for (j = 0; j < rh; j++) { + aj = cj + j*w; + dwt_interleave_h(aj, bj, dn, sn, cas_row); + dwt_decode_53(bj, dn, sn, cas_row); + for (k = 0; k < rw; k++) aj[k] = bj[k]; + } + } + opj_free(bj); + + } + + } + +} + + +/* */ +/* Get gain of wavelet transform. */ +/* */ +int dwt_getgain(int orient, int reversible) { + if (reversible == 1) { + if (orient == 0) + return 0; + else if (orient == 1 || orient == 2 || orient == 4 ) + return 1; + else if (orient == 3 || orient == 5 || orient == 6 ) + return 2; + else + return 3; + } + //else if (reversible == 0){ + return 0; +} + +/* */ +/* Get norm of wavelet transform. */ +/* */ +double dwt_getnorm(int orient, int level[3], int dwtid[3]) { + int levelx = level[0]; + int levely = level[1]; + int levelz = (level[2] < 0) ? 0 : level[2]; + double norm; + + if (flagnorm[levelx][levely][levelz][orient] == 1) { + norm = dwt_norm[levelx][levely][levelz][orient]; + //fprintf(stdout,"[INFO] Level: %d %d %d Orient %d Dwt_norm: %f \n",level[0],level[1],level[2],orient,norm); + } else { + opj_wtfilt_t *wtfiltx =(opj_wtfilt_t *) opj_malloc(sizeof(opj_wtfilt_t)); + opj_wtfilt_t *wtfilty =(opj_wtfilt_t *) opj_malloc(sizeof(opj_wtfilt_t)); + opj_wtfilt_t *wtfiltz =(opj_wtfilt_t *) opj_malloc(sizeof(opj_wtfilt_t)); + //Fetch equivalent filters for each dimension + dwt_getwtfilters(wtfiltx, dwtid[0]); + dwt_getwtfilters(wtfilty, dwtid[1]); + dwt_getwtfilters(wtfiltz, dwtid[2]); + //Calculate the corresponding norm + norm = dwt_calc_wtnorms(orient, level, dwtid, wtfiltx, wtfilty, wtfiltz); + //Save norm in array (no recalculation) + dwt_norm[levelx][levely][levelz][orient] = norm; + flagnorm[levelx][levely][levelz][orient] = 1; + //Free reserved space + opj_free(wtfiltx->LPS); opj_free(wtfilty->LPS); opj_free(wtfiltz->LPS); + opj_free(wtfiltx->HPS); opj_free(wtfilty->HPS); opj_free(wtfiltz->HPS); + opj_free(wtfiltx); opj_free(wtfilty); opj_free(wtfiltz); + //fprintf(stdout,"[INFO] Dwtid: %d %d %d Level: %d %d %d Orient %d Norm: %f \n",dwtid[0],dwtid[1],dwtid[2],level[0],level[1],level[2],orient,norm); + } + return norm; +} +/* */ +/* Calculate explicit stepsizes for DWT. */ +/* */ +void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec) { + int totnumbands, bandno, diff; + + assert(tccp->numresolution[0] >= tccp->numresolution[2]); + diff = tccp->numresolution[0] - tccp->numresolution[2]; /*if RESx=RESy != RESz */ + totnumbands = (7 * tccp->numresolution[0] - 6) - 4 * diff; /* 3-D */ + + for (bandno = 0; bandno < totnumbands; bandno++) { + double stepsize; + int resno, level[3], orient, gain; + + /* Bandno: 0 - LLL 1 - LHL + 2 - HLL 3 - HHL + 4 - LLH 5 - LHH + 6 - HLH 7 - HHH */ + + resno = (bandno == 0) ? 0 : ( (bandno <= 3 * diff) ? ((bandno - 1) / 3 + 1) : ((bandno + 4*diff - 1) / 7 + 1)); + orient = (bandno == 0) ? 0 : ( (bandno <= 3 * diff) ? ((bandno - 1) % 3 + 1) : ((bandno + 4*diff - 1) % 7 + 1)); + level[0] = tccp->numresolution[0] - 1 - resno; + level[1] = tccp->numresolution[1] - 1 - resno; + level[2] = tccp->numresolution[2] - 1 - resno; + + /* Gain: 0 - LLL 1 - LHL + 1 - HLL 2 - HHL + 1 - LLH 2 - LHH + 2 - HLH 3 - HHH */ + gain = (tccp->reversible == 0) ? 0 : ( (orient == 0) ? 0 : + ( ((orient == 1) || (orient == 2) || (orient == 4)) ? 1 : + (((orient == 3) || (orient == 5) || (orient == 6)) ? 2 : 3)) ); + + if (tccp->qntsty == J3D_CCP_QNTSTY_NOQNT) { + stepsize = 1.0; + } else { + double norm = dwt_getnorm(orient,level,tccp->dwtid); //Fetch norms if irreversible transform (by the moment only I9.7) + stepsize = (1 << (gain + 1)) / norm; + } + //fprintf(stdout,"[INFO] Bandno: %d Orient: %d Level: %d %d %d Stepsize: %f\n",bandno,orient,level[0],level[1],level[2],stepsize); + dwt_encode_stepsize((int) floor(stepsize * 8192.0), prec + gain, &tccp->stepsizes[bandno]); + } +} + + + diff --git a/src/lib/openjp3d/dwt.h b/src/lib/openjp3d/dwt.h new file mode 100755 index 00000000..d87f799f --- /dev/null +++ b/src/lib/openjp3d/dwt.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyrigth (c) 2006, Mónica Díez, LPI-UVA, Spain + * 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. +*/ + +/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */ +/*@{*/ + +/** +DCCS-LIWT properties +*/ + + +typedef struct opj_wtfilt { + double *LPS; + int lenLPS; + double *HPS; + int lenHPS; +} opj_wtfilt_t; +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Forward 5-3 wavelet tranform in 3-D. +Apply a reversible DWT transform to a component of an volume. +@param tilec Tile component information (current tile) +@param dwtid Number of identification of wavelet kernel(s) used in DWT in each direction +*/ +void dwt_encode(opj_tcd_tilecomp_t * tilec, int dwtid[3]); +/** +Inverse 5-3 wavelet tranform in 3-D. +Apply a reversible inverse DWT transform to a component of an volume. +@param tilec Tile component information (current tile) +@param stops Number of decoded resolution levels in each dimension +@param dwtid Number of identification of wavelet kernel(s) used in DWT in each dimension +*/ +void dwt_decode(opj_tcd_tilecomp_t * tilec, int stops[3], int dwtid[3]); +/* ----------------------------------------------------------------------- */ +/** +Get the gain of a subband for the reversible 3-D DWT. +@param orient Number that identifies the subband (0->LLL, 1->HLL, 2->LHL, 3->HHL, 4->LLH, 5->HLH, 6->LHH, 7->HHH) +@param reversible Wavelet transformation type +@return Returns 0 if orient = 0, returns 1 if orient = 1,2 or 4, returns 2 if orient = 3,5 or 6, returns 3 otherwise +*/ +int dwt_getgain(int orient, int reversible); +/** +Get the norm of a wavelet function of a subband at a specified level for the reversible 5-3 DWT or irreversible 9-7 in 3-D. +@param orient Band of the wavelet function +@param level Levels of the wavelet function in X,Y,Z axis +@param dwtid Wavelet transformation identifier +@return Returns the norm of the wavelet function +*/ +double dwt_getnorm(int orient, int level[3], int dwtid[3]); +/* ----------------------------------------------------------------------- */ +/** +Calcula el valor del escalón de cuantificación correspondiente a cada subbanda. +@param tccp Tile component coding parameters +@param prec Precision of data +*/ +void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec); +/*@}*/ + +#endif /* __DWT_H */ diff --git a/src/lib/openjp3d/event.c b/src/lib/openjp3d/event.c new file mode 100755 index 00000000..e27df654 --- /dev/null +++ b/src/lib/openjp3d/event.c @@ -0,0 +1,181 @@ +/* + * 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" + +// ========================================================== +// Utility functions +// ========================================================== + +#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 + +/* ----------------------------------------------------------------------- */ + +opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context) { + if(cinfo) { + opj_event_mgr_t *previous = cinfo->event_mgr; + cinfo->event_mgr = event_mgr; + cinfo->client_data = context; + return previous; + } + + return NULL; +} + +bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) { +#define MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */ + opj_msg_callback msg_handler = NULL; + + opj_event_mgr_t *event_mgr = cinfo->event_mgr; + if(event_mgr != NULL) { + switch(event_type) { + case EVT_ERROR: + msg_handler = event_mgr->error_handler; + break; + case EVT_WARNING: + msg_handler = event_mgr->warning_handler; + break; + case EVT_INFO: + msg_handler = event_mgr->info_handler; + break; + default: + break; + } + if(msg_handler == NULL) { + return false; + } + } else { + return false; + } + + if ((fmt != NULL) && (event_mgr != NULL)) { + va_list arg; + int str_length, i, j; + 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 = (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt); + /* parse the format string and put the result in 'message' */ + for (i = 0, j = 0; i < str_length; ++i) { + if (fmt[i] == '%') { + if (i + 1 < str_length) { + switch(tolower(fmt[i + 1])) { + case '%' : + message[j++] = '%'; + break; + case 'o' : /* octal numbers */ + { + char tmp[16]; + _itoa(va_arg(arg, int), tmp, 8); + strcat(message, tmp); + j += strlen(tmp); + ++i; + break; + } + case 'i' : /* decimal numbers */ + case 'd' : + { + char tmp[16]; + _itoa(va_arg(arg, int), tmp, 10); + strcat(message, tmp); + j += strlen(tmp); + ++i; + break; + } + case 'x' : /* hexadecimal numbers */ + { + char tmp[16]; + _itoa(va_arg(arg, int), tmp, 16); + strcat(message, tmp); + j += strlen(tmp); + ++i; + break; + } + case 's' : /* strings */ + { + char *tmp = va_arg(arg, char*); + strcat(message, tmp); + j += strlen(tmp); + ++i; + break; + } + case 'f' : /* floats */ + { + char tmp[16]; + double value = va_arg(arg, double); + sprintf(tmp, "%f", value); + strcat(message, tmp); + j += strlen(tmp); + ++i; + break; + } + }; + } else { + message[j++] = fmt[i]; + } + } else { + message[j++] = fmt[i]; + }; + } + /* deinitialize the optional parameter list */ + va_end(arg); + + /* output the message to the user program */ + msg_handler(message, cinfo->client_data); + } + + return true; +} + diff --git a/src/lib/openjp3d/event.h b/src/lib/openjp3d/event.h new file mode 100755 index 00000000..8f45452b --- /dev/null +++ b/src/lib/openjp3d/event.h @@ -0,0 +1,58 @@ +/* + * 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 __EVENT_H +#define __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. +*/ + +#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 Funciones generales (see also openjp3d.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Write formatted data to a string and send the string to a user callback. +@param cinfo Codec context info +@param event_type Event type or callback to use to send the message +@param fmt Format-control string (plus optionnal arguments) +@return Returns true if successful, returns false otherwise +*/ +bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __EVENT_H */ diff --git a/src/lib/openjp3d/fix.h b/src/lib/openjp3d/fix.h new file mode 100755 index 00000000..3b5e77ca --- /dev/null +++ b/src/lib/openjp3d/fix.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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 + +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define int64 __int64 +#else +#define int64 long long +#endif + +/** +@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 int fix_mul(int a, int b) { + int64 temp = (int64) a * (int64) b >> 12; + return (int) ((temp >> 1) + (temp & 1)) ; +} + +/*@}*/ + +#endif /* __FIX_H */ diff --git a/src/lib/openjp3d/int.h b/src/lib/openjp3d/int.h new file mode 100755 index 00000000..39b579a4 --- /dev/null +++ b/src/lib/openjp3d/int.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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. +*/ + +/** @defgroup INT INT - Implementation of operations on integers */ +/*@{*/ + +/** @name Funciones generales (see also openjp3d.h) */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Get the minimum of two integers +@return Returns a if a < b else b +*/ +static int int_min(int a, int b) { + return a < b ? a : b; +} +/** +Get the maximum of two integers +@return Returns a if a > b else b +*/ +static int int_max(int a, int 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 int int_clamp(int a, int min, int max) { + if (a < min) + return min; + if (a > max) + return max; + return a; +} +/** +@return Get absolute value of integer +*/ +static int int_abs(int a) { + return a < 0 ? -a : a; +} + +static double dbl_abs(double a) { + return a < 0 ? -a : a; +} +/** +Divide an integer and round upwards +@return Returns a divided by b +*/ +static int int_ceildiv(int a, int 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 int int_ceildivpow2(int a, int 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 int int_floordivpow2(int a, int b) { + return a >> b; +} +/** +Get logarithm of an integer and round downwards +@return Returns log2(a) +*/ +static int int_floorlog2(int a) { + int l; + for (l = 0; a > 1; l++) { + a >>= 1; + } + return l; +} +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif diff --git a/src/lib/openjp3d/jp3d.c b/src/lib/openjp3d/jp3d.c new file mode 100755 index 00000000..2fd5d02f --- /dev/null +++ b/src/lib/openjp3d/jp3d.c @@ -0,0 +1,2328 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyright (c) 2006, Mónica Díez García, Image Processing Laboratory, University of Valladolid, Spain + * 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 J3D J3D - JPEG-2000 PART 10 codestream reader/writer */ +/*@{*/ + +/** @name Funciones locales */ +/*@{*/ + +/** +Write the SOC marker (Start Of Codestream) +@param j3d J3D handle +*/ +static void j3d_write_soc(opj_j3d_t *j3d); +/** +Read the SOC marker (Start of Codestream) +@param j3d J3D handle +*/ +static void j3d_read_soc(opj_j3d_t *j3d); +/** +Write the SIZ marker (2D volume and tile size) +@param j3d J3D handle +*/ +static void j3d_write_siz(opj_j3d_t *j3d); +/** +Read the SIZ marker (2D volume and tile size) +@param j3d J3D handle +*/ +static void j3d_read_siz(opj_j3d_t *j3d); +/** +Write the ZSI marker (3rd volume and tile size) +@param j3d J3D handle +*/ +static void j3d_write_zsi(opj_j3d_t *j3d); +/** +Read the ZSI marker (3rd volume and tile size) +@param j3d J3D handle +*/ +static void j3d_read_zsi(opj_j3d_t *j3d); +/** +Write the COM marker (comment) +@param j3d J3D handle +*/ +static void j3d_write_com(opj_j3d_t *j3d); +/** +Read the COM marker (comment) +@param j3d J3D handle +*/ +static void j3d_read_com(opj_j3d_t *j3d); +/** +Write the value concerning the specified component in the marker COD and COC +@param j3d J3D handle +@param compno Number of the component concerned by the information written +*/ +static void j3d_write_cox(opj_j3d_t *j3d, int compno); +/** +Read the value concerning the specified component in the marker COD and COC +@param j3d J3D handle +@param compno Number of the component concerned by the information read +*/ +static void j3d_read_cox(opj_j3d_t *j3d, int compno); +/** +Write the COD marker (coding style default) +@param j3d J3D handle +*/ +static void j3d_write_cod(opj_j3d_t *j3d); +/** +Read the COD marker (coding style default) +@param j3d J3D handle +*/ +static void j3d_read_cod(opj_j3d_t *j3d); +/** +Write the COC marker (coding style component) +@param j3d J3D handle +@param compno Number of the component concerned by the information written +*/ +static void j3d_write_coc(opj_j3d_t *j3d, int compno); +/** +Read the COC marker (coding style component) +@param j3d J3D handle +*/ +static void j3d_read_coc(opj_j3d_t *j3d); +/** +Write the value concerning the specified component in the marker QCD and QCC +@param j3d J3D handle +@param compno Number of the component concerned by the information written +*/ +static void j3d_write_qcx(opj_j3d_t *j3d, int compno); +/** +Read the value concerning the specified component in the marker QCD and QCC +@param j3d J3D handle +@param compno Number of the component concern by the information read +@param len Length of the information in the QCX part of the marker QCD/QCC +*/ +static void j3d_read_qcx(opj_j3d_t *j3d, int compno, int len); +/** +Write the QCD marker (quantization default) +@param j3d J3D handle +*/ +static void j3d_write_qcd(opj_j3d_t *j3d); +/** +Read the QCD marker (quantization default) +@param j3d J3D handle +*/ +static void j3d_read_qcd(opj_j3d_t *j3d); +/** +Write the QCC marker (quantization component) +@param j3d J3D handle +@param compno Number of the component concerned by the information written +*/ +static void j3d_write_qcc(opj_j3d_t *j3d, int compno); +/** +Read the QCC marker (quantization component) +@param j3d J3D handle +*/ +static void j3d_read_qcc(opj_j3d_t *j3d); +/** +Write the POC marker (progression order change) +@param j3d J3D handle +*/ +static void j3d_write_poc(opj_j3d_t *j3d); +/** +Read the POC marker (progression order change) +@param j3d J3D handle +*/ +static void j3d_read_poc(opj_j3d_t *j3d); +/** +Read the CRG marker (component registration) +@param j3d J3D handle +*/ +static void j3d_read_crg(opj_j3d_t *j3d); +/** +Read the TLM marker (tile-part lengths) +@param j3d J3D handle +*/ +static void j3d_read_tlm(opj_j3d_t *j3d); +/** +Read the PLM marker (packet length, main header) +@param j3d J3D handle +*/ +static void j3d_read_plm(opj_j3d_t *j3d); +/** +Read the PLT marker (packet length, tile-part header) +@param j3d J3D handle +*/ +static void j3d_read_plt(opj_j3d_t *j3d); +/** +Read the PPM marker (packet packet headers, main header) +@param j3d J3D handle +*/ +static void j3d_read_ppm(opj_j3d_t *j3d); +/** +Read the PPT marker (packet packet headers, tile-part header) +@param j3d J3D handle +*/ +static void j3d_read_ppt(opj_j3d_t *j3d); +/** +Write the SOT marker (start of tile-part) +@param j3d J3D handle +*/ +static void j3d_write_sot(opj_j3d_t *j3d); +/** +Read the SOT marker (start of tile-part) +@param j3d J3D handle +*/ +static void j3d_read_sot(opj_j3d_t *j3d); +/** +Write the SOD marker (start of data) +@param j3d J3D handle +@param tile_coder Pointer to a TCD handle +*/ +static void j3d_write_sod(opj_j3d_t *j3d, void *tile_coder); +/** +Read the SOD marker (start of data) +@param j3d J3D handle +*/ +static void j3d_read_sod(opj_j3d_t *j3d); +/** +Write the RGN marker (region-of-interest) +@param j3d J3D handle +@param compno Number of the component concerned by the information written +@param tileno Number of the tile concerned by the information written +*/ +static void j3d_write_rgn(opj_j3d_t *j3d, int compno, int tileno); +/** +Read the RGN marker (region-of-interest) +@param j3d J3D handle +*/ +static void j3d_read_rgn(opj_j3d_t *j3d); +/** +Write the EOC marker (end of codestream) +@param j3d J3D handle +*/ +static void j3d_write_eoc(opj_j3d_t *j3d); +/** +Read the EOC marker (end of codestream) +@param j3d J3D handle +*/ +static void j3d_read_eoc(opj_j3d_t *j3d); +/** +Read an unknown marker +@param j3d J3D handle +*/ +static void j3d_read_unk(opj_j3d_t *j3d); +/** +Write the CAP marker (extended capabilities) +@param j3d J3D handle +*/ +static void j3d_write_cap(opj_j3d_t *j3d); +/** +Read the CAP marker (extended capabilities) +@param j3d J3D handle +*/ +static void j3d_read_cap(opj_j3d_t *j3d); +/** +Write the DCO marker (Variable DC offset) +@param j3d J3D handle +*/ +static void j3d_write_dco(opj_j3d_t *j3d); +/** +Read the DCO marker (Variable DC offset) +@param j3d J3D handle +*/ +static void j3d_read_dco(opj_j3d_t *j3d); +/** +Write the ATK marker (arbitrary transformation kernel) +@param j3d J3D handle +*/ +static void j3d_write_atk(opj_j3d_t *j3d); +/** +Read the ATK marker (arbitrary transformation kernel) +@param j3d J3D handle +*/ +static void j3d_read_atk(opj_j3d_t *j3d); +/** +Write the CBD marker (component bit depth definition) +@param j3d J3D handle +*/ +static void j3d_write_cbd(opj_j3d_t *j3d); +/** +Read the CBD marker (component bit depth definition) +@param j3d J3D handle +*/ +static void j3d_read_cbd(opj_j3d_t *j3d); +/** +Write the MCT marker (multiple component transfomation definition) +@param j3d J3D handle +*/ +static void j3d_write_mct(opj_j3d_t *j3d); +/** +Read the MCT marker (multiple component transfomation definition) +@param j3d J3D handle +*/ +static void j3d_read_mct(opj_j3d_t *j3d); +/** +Write the MCC marker (multiple component transfomation collection) +@param j3d J3D handle +*/ +static void j3d_write_mcc(opj_j3d_t *j3d); +/** +Read the MCC marker (multiple component transfomation collection) +@param j3d J3D handle +*/ +static void j3d_read_mcc(opj_j3d_t *j3d); +/** +Write the MCO marker (multiple component transfomation ordering) +@param j3d J3D handle +*/ +static void j3d_write_mco(opj_j3d_t *j3d); +/** +Read the MCO marker (multiple component transfomation ordering) +@param j3d J3D handle +*/ +static void j3d_read_mco(opj_j3d_t *j3d); +/** +Write the NLT marker (non-linearity point transformation) +@param j3d J3D handle +*/ +static void j3d_write_nlt(opj_j3d_t *j3d); +/** +Read the NLT marker (non-linearity point transformation) +@param j3d J3D handle +*/ +static void j3d_read_nlt(opj_j3d_t *j3d); +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +void j3d_dump_volume(FILE *fd, opj_volume_t * vol) { + int compno; + fprintf(fd, "volume {\n"); + fprintf(fd, " x0=%d, y0=%d, z0=%d, x1=%d, y1=%d, z1=%d\n", vol->x0, vol->y0, vol->z0,vol->x1, vol->y1, vol->z1); + fprintf(fd, " numcomps=%d\n", vol->numcomps); + for (compno = 0; compno < vol->numcomps; compno++) { + opj_volume_comp_t *comp = &vol->comps[compno]; + fprintf(fd, " comp %d {\n", compno); + fprintf(fd, " dx=%d, dy=%d, dz=%d\n", comp->dx, comp->dy, comp->dz); + fprintf(fd, " prec=%d\n", comp->prec); + fprintf(fd, " sgnd=%d\n", comp->sgnd); + fprintf(fd, " }\n"); + } + fprintf(fd, "}\n"); +} + +void j3d_dump_cp(FILE *fd, opj_volume_t * vol, opj_cp_t * cp) { + int tileno, compno, layno, bandno, resno, numbands; + fprintf(fd, "coding parameters {\n"); + fprintf(fd, " tx0=%d, ty0=%d, tz0=%d\n", cp->tx0, cp->ty0, cp->tz0); + fprintf(fd, " tdx=%d, tdy=%d, tdz=%d\n", cp->tdx, cp->tdy, cp->tdz); + fprintf(fd, " tw=%d, th=%d, tl=%d\n", cp->tw, cp->th, cp->tl); + fprintf(fd, " transform format: %d\n", cp->transform_format); + fprintf(fd, " encoding format: %d\n", cp->encoding_format); + for (tileno = 0; tileno < cp->tw * cp->th * cp->tl; 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, "%f ", tcp->rates[layno]); + } + fprintf(fd, "\n"); + fprintf(fd, " first=%d\n", tcp->first); + for (compno = 0; compno < vol->numcomps; compno++) { + opj_tccp_t *tccp = &tcp->tccps[compno]; + fprintf(fd, " comp %d {\n", compno); + fprintf(fd, " csty=%x\n", tccp->csty); + fprintf(fd, " numresx=%d, numresy=%d, numresz=%d\n", tccp->numresolution[0], tccp->numresolution[1], tccp->numresolution[2]); + fprintf(fd, " cblkw=%d, cblkh=%d, cblkl=%d\n", tccp->cblk[0], tccp->cblk[1], tccp->cblk[2]); + fprintf(fd, " cblksty=%x\n", tccp->cblksty); + fprintf(fd, " qntsty=%d\n", tccp->qntsty); + fprintf(fd, " numgbits=%d\n", tccp->numgbits); + fprintf(fd, " roishift=%d\n", tccp->roishift); + fprintf(fd, " reversible=%d\n", tccp->reversible); + fprintf(fd, " dwtidx=%d dwtidy=%d dwtidz=%d\n", tccp->dwtid[0], tccp->dwtid[1], tccp->dwtid[2]); + if (tccp->atk != NULL) { + fprintf(fd, " atk.index=%d\n", tccp->atk->index); + fprintf(fd, " atk.coeff_typ=%d\n", tccp->atk->coeff_typ); + fprintf(fd, " atk.filt_cat=%d\n", tccp->atk->filt_cat); + fprintf(fd, " atk.exten=%d\n", tccp->atk->exten); + fprintf(fd, " atk.minit=%d\n", tccp->atk->minit); + fprintf(fd, " atk.wt_typ=%d\n", tccp->atk->wt_typ); + } + fprintf(fd, " stepsizes of bands="); + numbands = (tccp->qntsty == J3D_CCP_QNTSTY_SIQNT) ? 1 : + ( (cp->transform_format == TRF_2D_DWT) ? (tccp->numresolution[0] * 3 - 2) : + (tccp->numresolution[0] * 7 - 6) - 4 *(tccp->numresolution[0] - tccp->numresolution[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 & J3D_CCP_CSTY_PRT) { + fprintf(fd, " prcw="); + for (resno = 0; resno < tccp->numresolution[0]; resno++) { + fprintf(fd, "%d ", tccp->prctsiz[0][resno]); + } + fprintf(fd, "\n"); + fprintf(fd, " prch="); + for (resno = 0; resno < tccp->numresolution[0]; resno++) { + fprintf(fd, "%d ", tccp->prctsiz[1][resno]); + } + fprintf(fd, "\n"); + fprintf(fd, " prcl="); + for (resno = 0; resno < tccp->numresolution[0]; resno++) { + fprintf(fd, "%d ", tccp->prctsiz[2][resno]); + } + fprintf(fd, "\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, "}\n"); +} + +/* ----------------------------------------------------------------------- +Extended capabilities +------------------------------------------------------------------------*/ + +static void j3d_write_cap(opj_j3d_t *j3d){ + int len,lenp; + + opj_cio_t *cio = j3d->cio; + cio_write(cio, J3D_MS_CAP, 2); /* CAP */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio,J3D_CAP_10, 4); + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lsiz */ + cio_seek(cio, lenp + len); + +} +static void j3d_read_cap(opj_j3d_t *j3d){ + int len, Cap; + opj_cio_t *cio = j3d->cio; + /*cio_read(cio, 2); CAP */ + len = cio_read(cio, 2); + Cap = cio_read(cio, 4); +} +static void j3d_write_zsi(opj_j3d_t *j3d) { + int i; + int lenp, len; + + opj_cio_t *cio = j3d->cio; + opj_volume_t *volume = j3d->volume; + opj_cp_t *cp = j3d->cp; + + cio_write(cio, J3D_MS_ZSI, 2); /* ZSI */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio, volume->z1, 4); /* Zsiz */ + cio_write(cio, volume->z0, 4); /* Z0siz */ + cio_write(cio, cp->tdz, 4); /* ZTsiz */ + cio_write(cio, cp->tz0, 4); /* ZT0siz */ + for (i = 0; i < volume->numcomps; i++) { + cio_write(cio, volume->comps[i].dz, 1); /* ZRsiz_i */ + } + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lsiz */ + cio_seek(cio, lenp + len); +} + +static void j3d_read_zsi(opj_j3d_t *j3d) { + int len, i; + + opj_cio_t *cio = j3d->cio; + opj_volume_t *volume = j3d->volume; + opj_cp_t *cp = j3d->cp; + + len = cio_read(cio, 2); /* Lsiz */ + volume->z1 = cio_read(cio, 4); /* Zsiz */ + volume->z0 = cio_read(cio, 4); /* Z0siz */ + cp->tdz = cio_read(cio, 4); /* ZTsiz */ + cp->tz0 = cio_read(cio, 4); /* ZT0siz */ + for (i = 0; i < volume->numcomps; i++) { + volume->comps[i].dz = cio_read(cio, 1); /* ZRsiz_i */ + } + + //Initialization of volume + cp->tw = int_ceildiv(volume->x1 - cp->tx0, cp->tdx); + cp->th = int_ceildiv(volume->y1 - cp->ty0, cp->tdy); + cp->tl = int_ceildiv(volume->z1 - cp->tz0, cp->tdz); + cp->tcps = (opj_tcp_t *) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(opj_tcp_t)); + cp->tileno = (int *) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(int)); + cp->tileno_size = 0; + + for (i = 0; i < cp->tw * cp->th * cp->tl ; i++) { + cp->tcps[i].POC = 0; + cp->tcps[i].numpocs = 0; + cp->tcps[i].first = 1; + } + + /* Initialization for PPM marker (Packets header)*/ + cp->ppm = 0; + cp->ppm_data = NULL; + cp->ppm_data_first = NULL; + cp->ppm_previous = 0; + cp->ppm_store = 0; + + j3d->default_tcp->tccps = (opj_tccp_t *) opj_malloc(sizeof(opj_tccp_t) * volume->numcomps); + for (i = 0; i < cp->tw * cp->th * cp->tl ; i++) { + cp->tcps[i].tccps = (opj_tccp_t *) opj_malloc(sizeof(opj_tccp_t) * volume->numcomps); + } + j3d->tile_data = (unsigned char **) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(unsigned char *)); + j3d->tile_len = (int *) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(int)); + j3d->state = J3D_STATE_MH; + +} +static void j3d_write_dco(opj_j3d_t *j3d){ + int lenp, len, i; + int dcotype; + + opj_cio_t *cio = j3d->cio; + opj_volume_t *volume = j3d->volume; + opj_cp_t *cp = j3d->cp; + + dcotype = 1; /* Offsets are 16bit signed integers Table A21 15444-2 */ + cio_write(cio, J3D_MS_DCO, 2); /* DCO */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio, dcotype, 1); + if (dcotype == 0) { + for (i = 0; i < volume->numcomps; i++) + cio_write(cio, volume->comps[i].dcoffset, 1); /* SPdco_i */ + } else if (dcotype == 1) { + for (i = 0; i < volume->numcomps; i++){ + cio_write(cio, volume->comps[i].dcoffset, 1); /* SPdco_i */ + opj_event_msg(j3d->cinfo, EVT_INFO, "dcotype %d DCO %d \n",dcotype,volume->comps[i].dcoffset); + } + } + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Ldco */ + cio_seek(cio, lenp + len); + +} +static void j3d_read_dco(opj_j3d_t *j3d){ + int len, i; + int dcotype; + + opj_cio_t *cio = j3d->cio; + opj_volume_t *volume = j3d->volume; + opj_cp_t *cp = j3d->cp; + + len = cio_read(cio, 2); /* Lsiz */ + dcotype = cio_read(cio, 1); //offset 8bit unsigned / 16bit signed integers + if (dcotype == 0) { + for (i = 0; i < volume->numcomps; i++) { + volume->comps[i].dcoffset = cio_read(cio, 1); + if (volume->comps[i].dcoffset > 128) + volume->comps[i].dcoffset = volume->comps[i].dcoffset - 256; + } + } else if (dcotype == 1) { + for (i = 0; i < volume->numcomps; i++) { + volume->comps[i].dcoffset = cio_read(cio, 1); + if (volume->comps[i].dcoffset > 128) + volume->comps[i].dcoffset = volume->comps[i].dcoffset - 256; + } + } + +} +static void j3d_write_atk(opj_j3d_t *j3d){ + int lenp, len, s, k; + + opj_cio_t *cio = j3d->cio; + opj_volume_t *volume = j3d->volume; + opj_atk_t *atk = j3d->cp->tcps->tccps->atk; + + cio_write(cio, J3D_MS_ATK, 2); /* ATK */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio, atk->index + (atk->coeff_typ << 8) + (atk->filt_cat << 11) + + (atk->wt_typ << 12) + (atk->minit << 13) + (atk->exten << 14), 2); /* Satk */ + if (atk->wt_typ == J3D_ATK_IRR) + cio_write(cio,(unsigned int) (atk->Katk * 8192.0), 1 << atk->coeff_typ); + cio_write(cio, atk->Natk, 1); + for (s = 0; s < atk->Natk; s++){ + if (atk->filt_cat == J3D_ATK_ARB) + cio_write(cio, atk->Oatk[s], 1); + if (atk->wt_typ == J3D_ATK_REV){ + cio_write(cio, atk->Eatk[s], 1); + cio_write(cio, atk->Batk[s], 1); + } + cio_write(cio, atk->LCatk[s], 1); + for (k = 0; k < atk->LCatk[s]; k++) + cio_write(cio,(unsigned int) (atk->Aatk[s][k] * 8192.0), 1 << atk->coeff_typ); + } + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Latk */ + cio_seek(cio, lenp + len); +} +static void j3d_read_atk(opj_j3d_t *j3d){ + int len, i, Satk, k; + + opj_cio_t *cio = j3d->cio; + opj_volume_t *volume = j3d->volume; + opj_cp_t *cp = j3d->cp; + opj_atk_t *atk = cp->tcps->tccps->atk; + + len = cio_read(cio, 2); /* Latk */ + Satk = cio_read(cio, 2); + atk->index = Satk & 0x00ff; + atk->coeff_typ = Satk >> 8 & 0x0007; + atk->filt_cat = Satk >> 11 & 0x0001; + atk->wt_typ = Satk >> 12 & 0x0001; + atk->minit = Satk >> 13 & 0x0001; + atk->exten = Satk >> 14 & 0x0001; + if (atk->wt_typ == J3D_ATK_IRR) + atk->Katk = ((double) cio_read(cio, 1 << atk->coeff_typ) / 8192.0); + atk->Natk = cio_read(cio, 1); + for (i = 0; i < atk->Natk; i++) { + if (atk->filt_cat == J3D_ATK_ARB) + atk->Oatk[i] = cio_read(cio, 1); + if (atk->wt_typ == J3D_ATK_REV){ + atk->Eatk[i] = cio_read(cio, 1); + atk->Batk[i] = cio_read(cio, 1); + } + atk->LCatk[i] = cio_read(cio, 1); + for (k = 0; k < atk->LCatk[i]; k++) + atk->Aatk[i][k] = ((double) cio_read(cio, 1 << atk->coeff_typ) / 8192.0); + } +} +static void j3d_write_cbd(opj_j3d_t *j3d){ +} +static void j3d_read_cbd(opj_j3d_t *j3d){ +} +static void j3d_write_mct(opj_j3d_t *j3d){ +} +static void j3d_read_mct(opj_j3d_t *j3d){ +} +static void j3d_write_mcc(opj_j3d_t *j3d){ +} +static void j3d_read_mcc(opj_j3d_t *j3d){ +} +static void j3d_write_mco(opj_j3d_t *j3d){ +} +static void j3d_read_mco(opj_j3d_t *j3d){ +} +static void j3d_write_nlt(opj_j3d_t *j3d){ +} +static void j3d_read_nlt(opj_j3d_t *j3d){ +} +/* ----------------------------------------------------------------------- +15444-1 codestream syntax +------------------------------------------------------------------------*/ +static void j3d_write_soc(opj_j3d_t *j3d) { + opj_cio_t *cio = j3d->cio; + cio_write(cio, J3D_MS_SOC, 2); +} + +static void j3d_read_soc(opj_j3d_t *j3d) { + j3d->state = J3D_STATE_MHSIZ; +} + +static void j3d_write_siz(opj_j3d_t *j3d) { + int i; + int lenp, len; + int Rsiz; + + opj_cio_t *cio = j3d->cio; + opj_volume_t *volume = j3d->volume; + opj_cp_t *cp = j3d->cp; + + cio_write(cio, J3D_MS_SIZ, 2); /* SIZ */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + //cio_write(cio, 0, 2); /* Rsiz (capabilities of 15444-1 only) */ + Rsiz = J3D_RSIZ_DCO | J3D_RSIZ_ATK; /** | J3D_RSIZ_MCT | J3D_RSIZ_NONLT (not implemented yet)*/ + cio_write(cio, Rsiz, 2); /* capabilities of WDv5.2*/ + cio_write(cio, volume->x1, 4); /* Xsiz */ + cio_write(cio, volume->y1, 4); /* Ysiz */ + cio_write(cio, volume->x0, 4); /* X0siz */ + cio_write(cio, volume->y0, 4); /* Y0siz */ + cio_write(cio, cp->tdx, 4); /* XTsiz */ + cio_write(cio, cp->tdy, 4); /* YTsiz */ + cio_write(cio, cp->tx0, 4); /* XT0siz */ + cio_write(cio, cp->ty0, 4); /* YT0siz */ + cio_write(cio, volume->numcomps, 2); /* Csiz */ + for (i = 0; i < volume->numcomps; i++) { + cio_write(cio, volume->comps[i].prec - 1 + (volume->comps[i].sgnd << 7), 1); /* Ssiz_i */ + cio_write(cio, volume->comps[i].dx, 1); /* XRsiz_i */ + cio_write(cio, volume->comps[i].dy, 1); /* YRsiz_i */ + } + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lsiz */ + cio_seek(cio, lenp + len); +} + +static void j3d_read_siz(opj_j3d_t *j3d) { + int len, i; + + opj_cio_t *cio = j3d->cio; + opj_volume_t *volume = j3d->volume; + opj_cp_t *cp = j3d->cp; + + len = cio_read(cio, 2); /* Lsiz */ + cp->rsiz = cio_read(cio, 2); /* Rsiz (capabilities) */ + volume->x1 = cio_read(cio, 4); /* Xsiz */ + volume->y1 = cio_read(cio, 4); /* Ysiz */ + volume->x0 = cio_read(cio, 4); /* X0siz */ + volume->y0 = cio_read(cio, 4); /* Y0siz */ + cp->tdx = cio_read(cio, 4); /* XTsiz */ + cp->tdy = cio_read(cio, 4); /* YTsiz */ + cp->tx0 = cio_read(cio, 4); /* XT0siz */ + cp->ty0 = cio_read(cio, 4); /* YT0siz */ + + volume->numcomps = cio_read(cio, 2); /* Csiz */ + volume->comps = (opj_volume_comp_t *) opj_malloc(volume->numcomps * sizeof(opj_volume_comp_t)); + for (i = 0; i < volume->numcomps; i++) { + int tmp, j; + tmp = cio_read(cio, 1); /* Ssiz_i */ + volume->comps[i].prec = (tmp & 0x7f) + 1; + volume->comps[i].sgnd = tmp >> 7; + volume->comps[i].dx = cio_read(cio, 1); /* XRsiz_i */ + volume->comps[i].dy = cio_read(cio, 1); /* YRsiz_i */ + for (j = 0; j < 3; j++) { + volume->comps[i].resno_decoded[j] = 0; /* number of resolution decoded */ + volume->comps[i].factor[j] = 0; /* reducing factor per component */ + } + } + + if (j3d->cinfo->codec_format == CODEC_J2K){ + volume->z1 = 1; + volume->z0 = 0; + volume->numslices = 1; + cp->tdz = 1; + cp->tz0 = 0; + for (i = 0; i < volume->numcomps; i++) + volume->comps[i].dz = 1; + + //Initialization of volume + cp->tw = int_ceildiv(volume->x1 - cp->tx0, cp->tdx); + cp->th = int_ceildiv(volume->y1 - cp->ty0, cp->tdy); + cp->tl = int_ceildiv(volume->z1 - cp->tz0, cp->tdz); + cp->tcps = (opj_tcp_t *) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(opj_tcp_t)); + cp->tileno = (int *) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(int)); + cp->tileno_size = 0; + + for (i = 0; i < cp->tw * cp->th * cp->tl ; i++) { + cp->tcps[i].POC = 0; + cp->tcps[i].numpocs = 0; + cp->tcps[i].first = 1; + } + + /* Initialization for PPM marker (Packets header)*/ + cp->ppm = 0; + cp->ppm_data = NULL; + cp->ppm_data_first = NULL; + cp->ppm_previous = 0; + cp->ppm_store = 0; + + j3d->default_tcp->tccps = (opj_tccp_t *) opj_malloc(sizeof(opj_tccp_t) * volume->numcomps); + for (i = 0; i < cp->tw * cp->th * cp->tl ; i++) { + cp->tcps[i].tccps = (opj_tccp_t *) opj_malloc(sizeof(opj_tccp_t) * volume->numcomps); + } + j3d->tile_data = (unsigned char **) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(unsigned char *)); + j3d->tile_len = (int *) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(int)); + j3d->state = J3D_STATE_MH; + } +} + + + +static void j3d_write_com(opj_j3d_t *j3d) { + unsigned int i; + int lenp, len; + + opj_cio_t *cio = j3d->cio; + + cio_write(cio, J3D_MS_COM, 2); + lenp = cio_tell(cio); + cio_skip(cio, 2); + //cio_write(cio, 0, 2); + cio_write(cio, j3d->cp->transform_format,1); + cio_write(cio, j3d->cp->encoding_format,1); + //opj_event_msg(j3d->cinfo, EVT_INFO, "TRF %D ENCOD %d\n",j3d->cp->transform_format,j3d->cp->encoding_format); + if (j3d->cp->comment != NULL) { + char *comment = j3d->cp->comment; + for (i = 0; i < strlen(comment); i++) { + cio_write(cio, comment[i], 1); + } + } + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); + cio_seek(cio, lenp + len); +} + +static void j3d_read_com(opj_j3d_t *j3d) { + int len; + opj_cio_t *cio = j3d->cio; + + len = cio_read(cio, 2); + + j3d->cp->transform_format = (OPJ_TRANSFORM) cio_read(cio, 1); + j3d->cp->encoding_format = (OPJ_ENTROPY_CODING) cio_read(cio, 1); + //opj_event_msg(j3d->cinfo, EVT_INFO, "TRF %D ENCOD %d\n",j3d->cp->transform_format,j3d->cp->encoding_format); + + cio_skip(cio, len - 4); //posible comments +} + +static void j3d_write_cox(opj_j3d_t *j3d, int compno) { + int i; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = &cp->tcps[j3d->curtileno]; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_cio_t *cio = j3d->cio; + + cio_write(cio, tccp->numresolution[0] - 1, 1); /* SPcox (D) No of decomposition levels in x-axis*/ + if (j3d->cinfo->codec_format == CODEC_J3D) { + cio_write(cio, tccp->numresolution[1] - 1, 1); /* SPcox (E) No of decomposition levels in y-axis*/ + cio_write(cio, tccp->numresolution[2] - 1, 1); /* SPcox (F) No of decomposition levels in z-axis*/ + } + /* (cblkw - 2) + (cblkh - 2) + (cblkl - 2) <= 18*/ + cio_write(cio, tccp->cblk[0] - 2, 1); /* SPcox (G) Cblk width entre 10 y 2 (8 y 0)*/ + cio_write(cio, tccp->cblk[1] - 2, 1); /* SPcox (H) Cblk height*/ + if (j3d->cinfo->codec_format == CODEC_J3D) { + cio_write(cio, tccp->cblk[2] - 2, 1); /* SPcox (I) Cblk depth*/ + } + cio_write(cio, tccp->cblksty, 1); /* SPcox (J) Cblk style*/ + cio_write(cio, tccp->dwtid[0], 1); /* SPcox (K) WT in x-axis 15444-2 Table A10*/ + if (j3d->cinfo->codec_format == CODEC_J3D) { + cio_write(cio, tccp->dwtid[1], 1); /* SPcox (L) WT in y-axis 15444-2 Table A10*/ + cio_write(cio, tccp->dwtid[2], 1); /* SPcox (M) WT in z-axis 15444-2 Table A10*/ + } + + if (tccp->csty & J3D_CCP_CSTY_PRT) { + for (i = 0; i < tccp->numresolution[0]; i++) { + if (i < tccp->numresolution[2]) + cio_write(cio, tccp->prctsiz[0][i] + (tccp->prctsiz[1][i] << 4) + (tccp->prctsiz[2][i] << 8), 2); /* SPcox (N_i) Table A9*/ + else + if (j3d->cinfo->codec_format == CODEC_J3D) + cio_write(cio, tccp->prctsiz[0][i] + (tccp->prctsiz[1][i] << 4), 2); /* SPcox (N_i) Table A9*/ + else + cio_write(cio, tccp->prctsiz[0][i] + (tccp->prctsiz[1][i] << 4), 1); /* SPcox (N_i) Table A9*/ } + } +} + +static void j3d_read_cox(opj_j3d_t *j3d, int compno) { + int i; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = j3d->state == J3D_STATE_TPH ? &cp->tcps[j3d->curtileno] : j3d->default_tcp; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_cio_t *cio = j3d->cio; + + tccp->numresolution[0] = cio_read(cio, 1) + 1; /* SPcox (D) No of decomposition levels in x-axis*/ + if (j3d->cinfo->codec_format == CODEC_J3D) { + tccp->numresolution[1] = cio_read(cio, 1) + 1; /* SPcox (E) No of decomposition levels in y-axis*/ + tccp->numresolution[2] = cio_read(cio, 1) + 1; /* SPcox (F) No of decomposition levels in z-axis*/ + }else if (j3d->cinfo->codec_format == CODEC_J2K) { + tccp->numresolution[1] = tccp->numresolution[0]; + tccp->numresolution[2] = 1; + } + /* check the reduce value */ + cp->reduce[0] = int_min((tccp->numresolution[0])-1, cp->reduce[0]); + cp->reduce[1] = int_min((tccp->numresolution[1])-1, cp->reduce[1]); + cp->reduce[2] = int_min((tccp->numresolution[2])-1, cp->reduce[2]); + + tccp->cblk[0] = cio_read(cio, 1) + 2; /* SPcox (G) */ + tccp->cblk[1] = cio_read(cio, 1) + 2; /* SPcox (H) */ + if (j3d->cinfo->codec_format == CODEC_J3D) + tccp->cblk[2] = cio_read(cio, 1) + 2; /* SPcox (I) */ + else + tccp->cblk[2] = tccp->cblk[0]; + + tccp->cblksty = cio_read(cio, 1); /* SPcox (J) */ + tccp->dwtid[0] = cio_read(cio, 1); /* SPcox (K) */ + if (j3d->cinfo->codec_format == CODEC_J3D) { + tccp->dwtid[1] = cio_read(cio, 1); /* SPcox (L) */ + tccp->dwtid[2] = cio_read(cio, 1); /* SPcox (M) */ + }else{ + tccp->dwtid[1] = tccp->dwtid[0]; /* SPcox (L) */ + tccp->dwtid[2] = tccp->dwtid[0]; /* SPcox (M) */ + } + tccp->reversible = (tccp->dwtid[0]>=1 && tccp->dwtid[1]>=1 && tccp->dwtid[2]>=1); //TODO: only valid for irreversible 9x7 WTs + if (tccp->csty & J3D_CP_CSTY_PRT) { + for (i = 0; i < tccp->numresolution[0]; i++) { + int tmp = cio_read(cio, 2); /* SPcox (N_i) */ + tccp->prctsiz[0][i] = tmp & 0xf; + tccp->prctsiz[1][i] = tmp >> 4; + tccp->prctsiz[2][i] = tmp >> 8; + } + } +} + +static void j3d_write_cod(opj_j3d_t *j3d) { + opj_cp_t *cp = NULL; + opj_tcp_t *tcp = NULL; + int lenp, len; + + opj_cio_t *cio = j3d->cio; + + cio_write(cio, J3D_MS_COD, 2); /* COD */ + + lenp = cio_tell(cio); + cio_skip(cio, 2); + + cp = j3d->cp; + tcp = &cp->tcps[j3d->curtileno]; + + /* Scod : Table A-4*/ + cio_write(cio, tcp->csty, 1); /* Scod : Coding style parameters */ + /* SGcod : Table A-5*/ + cio_write(cio, tcp->prg, 1); /* SGcod (A) : Progression order */ + cio_write(cio, tcp->numlayers, 2); /* SGcod (B) : No of layers */ + cio_write(cio, tcp->mct, 1); /* SGcod (C) : Multiple component transformation usage */ + /* SPcod : Table A-6*/ + j3d_write_cox(j3d, 0); + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lcod */ + cio_seek(cio, lenp + len); +} + +static void j3d_read_cod(opj_j3d_t *j3d) { + int len, i, pos; + + opj_cio_t *cio = j3d->cio; + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = j3d->state == J3D_STATE_TPH ? &cp->tcps[j3d->curtileno] : j3d->default_tcp; + opj_volume_t *volume = j3d->volume; + + /* Lcod */ + len = cio_read(cio, 2); + /* Scod : Table A-4*/ + tcp->csty = cio_read(cio, 1); + /* SGcod : Table A-5*/ + tcp->prg = (OPJ_PROG_ORDER)cio_read(cio, 1); + tcp->numlayers = cio_read(cio, 2); + tcp->mct = cio_read(cio, 1); + + pos = cio_tell(cio); + for (i = 0; i < volume->numcomps; i++) { + tcp->tccps[i].csty = tcp->csty & J3D_CP_CSTY_PRT; + cio_seek(cio, pos); + j3d_read_cox(j3d, i); + } +} + +static void j3d_write_coc(opj_j3d_t *j3d, int compno) { + int lenp, len; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = &cp->tcps[j3d->curtileno]; + opj_volume_t *volume = j3d->volume; + opj_cio_t *cio = j3d->cio; + + cio_write(cio, J3D_MS_COC, 2); /* COC */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio, compno, volume->numcomps <= 256 ? 1 : 2); /* Ccoc */ + cio_write(cio, tcp->tccps[compno].csty, 1); /* Scoc */ + + j3d_write_cox(j3d, compno); + + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lcoc */ + cio_seek(cio, lenp + len); +} + +static void j3d_read_coc(opj_j3d_t *j3d) { + int len, compno; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = j3d->state == J3D_STATE_TPH ? &cp->tcps[j3d->curtileno] : j3d->default_tcp; + opj_volume_t *volume = j3d->volume; + opj_cio_t *cio = j3d->cio; + + len = cio_read(cio, 2); /* Lcoc */ + compno = cio_read(cio, volume->numcomps <= 256 ? 1 : 2); /* Ccoc */ + tcp->tccps[compno].csty = cio_read(cio, 1); /* Scoc */ + j3d_read_cox(j3d, compno); +} + +static void j3d_write_qcx(opj_j3d_t *j3d, int compno) { + int bandno, numbands; + int expn, mant; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = &cp->tcps[j3d->curtileno]; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_cio_t *cio = j3d->cio; + + cio_write(cio, tccp->qntsty + (tccp->numgbits << 5), 1); /* Sqcx : Table A28 de 15444-1*/ + + if (j3d->cinfo->codec_format == CODEC_J2K) + numbands = tccp->qntsty == J3D_CCP_QNTSTY_SIQNT ? 1 : tccp->numresolution[0] * 3 - 2; + else if (j3d->cinfo->codec_format == CODEC_J3D) { + int diff = tccp->numresolution[0] - tccp->numresolution[2]; + numbands = (tccp->qntsty == J3D_CCP_QNTSTY_SIQNT) ? 1 : (tccp->numresolution[0] * 7 - 6) - 4 *diff; /* SIQNT vs. SEQNT */ + } + + for (bandno = 0; bandno < numbands; bandno++) { + expn = tccp->stepsizes[bandno].expn; + mant = tccp->stepsizes[bandno].mant; + + if (tccp->qntsty == J3D_CCP_QNTSTY_NOQNT) { + cio_write(cio, expn << 3, 1); /* SPqcx_i */ + } else { + cio_write(cio, (expn << 11) + mant, 2); /* SPqcx_i */ + } + } +} + +static void j3d_read_qcx(opj_j3d_t *j3d, int compno, int len) { + int tmp; + int bandno, numbands; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = j3d->state == J3D_STATE_TPH ? &cp->tcps[j3d->curtileno] : j3d->default_tcp; + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_cio_t *cio = j3d->cio; + + tmp = cio_read(cio, 1); /* Sqcx */ + tccp->qntsty = tmp & 0x1f; + tccp->numgbits = tmp >> 5; + + /*Numbands = 1 si SIQNT + len - 1 si NOQNT + (len - 1) / 2 si SEQNT */ + numbands = tccp->qntsty == J3D_CCP_QNTSTY_SIQNT ? 1 : ((tccp->qntsty == J3D_CCP_QNTSTY_NOQNT) ? len - 1 : (len - 1) / 2); + + for (bandno = 0; bandno < numbands; bandno++) { + int expn, mant; + if (tccp->qntsty == J3D_CCP_QNTSTY_NOQNT) { + expn = cio_read(cio, 1) >> 3; /* SPqcx_i */ + mant = 0; + } else { + tmp = cio_read(cio, 2); /* SPqcx_i */ + expn = tmp >> 11; + mant = tmp & 0x7ff; + } + tccp->stepsizes[bandno].expn = expn; + tccp->stepsizes[bandno].mant = mant; + } + + /* Add Antonin : if scalar_derived -> compute other stepsizes */ + if (tccp->qntsty == J3D_CCP_QNTSTY_SIQNT) { + for (bandno = 1; bandno < J3D_MAXBANDS; bandno++) { + int numbands = (cp->transform_format==TRF_2D_DWT) ? 3 : 7; + tccp->stepsizes[bandno].expn = tccp->stepsizes[0].expn - ((bandno - 1) / numbands); + tccp->stepsizes[bandno].mant = tccp->stepsizes[0].mant; + } + } + /* ddA */ +} + +static void j3d_write_qcd(opj_j3d_t *j3d) { + int lenp, len; + + opj_cio_t *cio = j3d->cio; + + cio_write(cio, J3D_MS_QCD, 2); /* QCD */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + j3d_write_qcx(j3d, 0); /* Sqcd*/ + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lqcd */ + cio_seek(cio, lenp + len); +} + +static void j3d_read_qcd(opj_j3d_t *j3d) { + int len, i, pos; + + opj_cio_t *cio = j3d->cio; + opj_volume_t *volume = j3d->volume; + + len = cio_read(cio, 2); /* Lqcd */ + pos = cio_tell(cio); + for (i = 0; i < volume->numcomps; i++) { + cio_seek(cio, pos); + j3d_read_qcx(j3d, i, len - 2); + } +} + +static void j3d_write_qcc(opj_j3d_t *j3d, int compno) { + int lenp, len; + + opj_cio_t *cio = j3d->cio; + + cio_write(cio, J3D_MS_QCC, 2); /* QCC */ + lenp = cio_tell(cio); + cio_skip(cio, 2); + cio_write(cio, compno, j3d->volume->numcomps <= 256 ? 1 : 2); /* Cqcc */ + j3d_write_qcx(j3d, compno); + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lqcc */ + cio_seek(cio, lenp + len); +} + +static void j3d_read_qcc(opj_j3d_t *j3d) { + int len, compno; + int numcomp = j3d->volume->numcomps; + opj_cio_t *cio = j3d->cio; + + len = cio_read(cio, 2); /* Lqcc */ + compno = cio_read(cio, numcomp <= 256 ? 1 : 2); /* Cqcc */ + j3d_read_qcx(j3d, compno, len - 2 - (numcomp <= 256 ? 1 : 2)); +} + +static void j3d_write_poc(opj_j3d_t *j3d) { + int len, numpchgs, i; + + int numcomps = j3d->volume->numcomps; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = &cp->tcps[j3d->curtileno]; + opj_tccp_t *tccp = &tcp->tccps[0]; + opj_cio_t *cio = j3d->cio; + + numpchgs = tcp->numpocs; + cio_write(cio, J3D_MS_POC, 2); /* POC */ + len = 2 + (5 + 2 * (numcomps <= 256 ? 1 : 2)) * numpchgs; + cio_write(cio, len, 2); /* Lpoc */ + for (i = 0; i < numpchgs; i++) { + opj_poc_t *poc = &tcp->pocs[i]; + cio_write(cio, poc->resno0, 1); /* RSpoc_i */ + cio_write(cio, poc->compno0, (numcomps <= 256 ? 1 : 2)); /* CSpoc_i */ + cio_write(cio, poc->layno1, 2); /* LYEpoc_i */ + poc->layno1 = int_min(poc->layno1, tcp->numlayers); + cio_write(cio, poc->resno1, 1); /* REpoc_i */ + poc->resno1 = int_min(poc->resno1, tccp->numresolution[0]); + cio_write(cio, poc->compno1, (numcomps <= 256 ? 1 : 2)); /* CEpoc_i */ + poc->compno1 = int_min(poc->compno1, numcomps); + cio_write(cio, poc->prg, 1); /* Ppoc_i */ + } +} + +static void j3d_read_poc(opj_j3d_t *j3d) { + int len, numpchgs, i, old_poc; + + int numcomps = j3d->volume->numcomps; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = j3d->state == J3D_STATE_TPH ? &cp->tcps[j3d->curtileno] : j3d->default_tcp; + opj_tccp_t *tccp = &tcp->tccps[0]; + opj_cio_t *cio = j3d->cio; + + old_poc = tcp->POC ? tcp->numpocs + 1 : 0; + tcp->POC = 1; + len = cio_read(cio, 2); /* Lpoc */ + numpchgs = (len - 2) / (5 + 2 * (numcomps <= 256 ? 1 : 2)); + + for (i = old_poc; i < numpchgs + old_poc; i++) { + opj_poc_t *poc; + poc = &tcp->pocs[i]; + poc->resno0 = cio_read(cio, 1); /* RSpoc_i */ + poc->compno0 = cio_read(cio, numcomps <= 256 ? 1 : 2); /* CSpoc_i */ + poc->layno1 = int_min(cio_read(cio, 2), (unsigned int) tcp->numlayers); /* LYEpoc_i */ + poc->resno1 = int_min(cio_read(cio, 1), (unsigned int) tccp->numresolution[0]); /* REpoc_i */ + poc->compno1 = int_min( + cio_read(cio, numcomps <= 256 ? 1 : 2), (unsigned int) numcomps); /* CEpoc_i */ + poc->prg = (OPJ_PROG_ORDER)cio_read(cio, 1); /* Ppoc_i */ + } + + tcp->numpocs = numpchgs + old_poc - 1; +} + +static void j3d_read_crg(opj_j3d_t *j3d) { + int len, i, Xcrg_i, Ycrg_i, Zcrg_i; + + opj_cio_t *cio = j3d->cio; + int numcomps = j3d->volume->numcomps; + + len = cio_read(cio, 2); /* Lcrg */ + for (i = 0; i < numcomps; i++) { + Xcrg_i = cio_read(cio, 2); /* Xcrg_i */ + Ycrg_i = cio_read(cio, 2); /* Ycrg_i */ + Zcrg_i = cio_read(cio, 2); /* Zcrg_i */ + } +} + +static void j3d_read_tlm(opj_j3d_t *j3d) { + int len, Ztlm, Stlm, ST, SP, tile_tlm, i; + long int Ttlm_i, Ptlm_i; + + opj_cio_t *cio = j3d->cio; + + len = cio_read(cio, 2); /* Ltlm */ + Ztlm = cio_read(cio, 1); /* Ztlm */ + Stlm = cio_read(cio, 1); /* Stlm */ + ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02); + SP = (Stlm >> 6) & 0x01; + tile_tlm = (len - 4) / ((SP + 1) * 2 + ST); + for (i = 0; i < tile_tlm; i++) { + Ttlm_i = cio_read(cio, ST); /* Ttlm_i */ + Ptlm_i = cio_read(cio, SP ? 4 : 2); /* Ptlm_i */ + } +} + +static void j3d_read_plm(opj_j3d_t *j3d) { + int len, i, Zplm, Nplm, add, packet_len = 0; + + opj_cio_t *cio = j3d->cio; + + len = cio_read(cio, 2); /* Lplm */ + Zplm = cio_read(cio, 1); /* Zplm */ + len -= 3; + while (len > 0) { + Nplm = cio_read(cio, 4); /* Nplm */ + len -= 4; + for (i = Nplm; i > 0; i--) { + add = cio_read(cio, 1); + len--; + packet_len = (packet_len << 7) + add; /* Iplm_ij */ + if ((add & 0x80) == 0) { + /* New packet */ + packet_len = 0; + } + if (len <= 0) + break; + } + } +} + +static void j3d_read_plt(opj_j3d_t *j3d) { + int len, i, Zplt, packet_len = 0, add; + + opj_cio_t *cio = j3d->cio; + + len = cio_read(cio, 2); /* Lplt */ + Zplt = cio_read(cio, 1); /* Zplt */ + for (i = len - 3; i > 0; i--) { + add = cio_read(cio, 1); + packet_len = (packet_len << 7) + add; /* Iplt_i */ + if ((add & 0x80) == 0) { + /* New packet */ + packet_len = 0; + } + } +} + +static void j3d_read_ppm(opj_j3d_t *j3d) { + int len, Z_ppm, i, j; + int N_ppm; + + opj_cp_t *cp = j3d->cp; + opj_cio_t *cio = j3d->cio; + + len = cio_read(cio, 2); + cp->ppm = 1; + + Z_ppm = cio_read(cio, 1); /* Z_ppm */ + len -= 3; + while (len > 0) { + if (cp->ppm_previous == 0) { + N_ppm = cio_read(cio, 4); /* N_ppm */ + len -= 4; + } else { + N_ppm = cp->ppm_previous; + } + j = cp->ppm_store; + if (Z_ppm == 0) { /* First PPM marker */ + cp->ppm_data = (unsigned char *) opj_malloc(N_ppm * sizeof(unsigned char)); + cp->ppm_data_first = cp->ppm_data; + cp->ppm_len = N_ppm; + } else { /* NON-first PPM marker */ + cp->ppm_data = (unsigned char *) opj_realloc(cp->ppm_data, (N_ppm + cp->ppm_store) * sizeof(unsigned char)); + cp->ppm_data_first = cp->ppm_data; + cp->ppm_len = N_ppm + cp->ppm_store; + } + for (i = N_ppm; i > 0; i--) { /* Read packet header */ + cp->ppm_data[j] = cio_read(cio, 1); + j++; + len--; + if (len == 0) + break; /* Case of non-finished packet header in present marker but finished in next one */ + } + cp->ppm_previous = i - 1; + cp->ppm_store = j; + } +} + +static void j3d_read_ppt(opj_j3d_t *j3d) { + int len, Z_ppt, i, j = 0; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = cp->tcps + j3d->curtileno; + opj_cio_t *cio = j3d->cio; + + len = cio_read(cio, 2); + Z_ppt = cio_read(cio, 1); + tcp->ppt = 1; + if (Z_ppt == 0) { /* First PPT marker */ + tcp->ppt_data = (unsigned char *) opj_malloc((len - 3) * sizeof(unsigned char)); + tcp->ppt_data_first = tcp->ppt_data; + tcp->ppt_store = 0; + tcp->ppt_len = len - 3; + } else { /* NON-first PPT marker */ + tcp->ppt_data = (unsigned char *) opj_realloc(tcp->ppt_data, (len - 3 + tcp->ppt_store) * sizeof(unsigned char)); + tcp->ppt_data_first = tcp->ppt_data; + tcp->ppt_len = len - 3 + tcp->ppt_store; + } + j = tcp->ppt_store; + for (i = len - 3; i > 0; i--) { + tcp->ppt_data[j] = cio_read(cio, 1); + j++; + } + tcp->ppt_store = j; +} + +static void j3d_write_sot(opj_j3d_t *j3d) { + int lenp, len; + + opj_cio_t *cio = j3d->cio; + + j3d->sot_start = cio_tell(cio); + cio_write(cio, J3D_MS_SOT, 2); /* SOT */ + lenp = cio_tell(cio); + cio_skip(cio, 2); /* Lsot (further) */ + cio_write(cio, j3d->curtileno, 2); /* Isot */ + cio_skip(cio, 4); /* Psot (further in j3d_write_sod) */ + cio_write(cio, 0, 1); /* TPsot */ + cio_write(cio, 1, 1); /* TNsot (no of tile-parts of this tile in this codestream)*/ + len = cio_tell(cio) - lenp; + cio_seek(cio, lenp); + cio_write(cio, len, 2); /* Lsot */ + cio_seek(cio, lenp + len); +} + +static void j3d_read_sot(opj_j3d_t *j3d) { + int len, tileno, totlen, partno, numparts, i; + opj_tcp_t *tcp = NULL; + char status = 0; + + opj_cp_t *cp = j3d->cp; + opj_cio_t *cio = j3d->cio; + + len = cio_read(cio, 2); + tileno = cio_read(cio, 2); + + if (cp->tileno_size == 0) { + cp->tileno[cp->tileno_size] = tileno; + cp->tileno_size++; + } else { + i = 0; + while (i < cp->tileno_size && status == 0) { + status = cp->tileno[i] == tileno ? 1 : 0; + i++; + } + if (status == 0) { + cp->tileno[cp->tileno_size] = tileno; + cp->tileno_size++; + } + } + + totlen = cio_read(cio, 4); + if (!totlen) + totlen = cio_numbytesleft(cio) + 8; + + partno = cio_read(cio, 1); + numparts = cio_read(cio, 1); + + j3d->curtileno = tileno; + j3d->eot = cio_getbp(cio) - 12 + totlen; + j3d->state = J3D_STATE_TPH; + tcp = &cp->tcps[j3d->curtileno]; + + if (tcp->first == 1) { + + /* Initialization PPT */ + opj_tccp_t *tmp = tcp->tccps; + memcpy(tcp, j3d->default_tcp, sizeof(opj_tcp_t)); + tcp->ppt = 0; + tcp->ppt_data = NULL; + tcp->ppt_data_first = NULL; + tcp->tccps = tmp; + + for (i = 0; i < j3d->volume->numcomps; i++) { + tcp->tccps[i] = j3d->default_tcp->tccps[i]; + } + cp->tcps[j3d->curtileno].first = 0; + } +} + +static void j3d_write_sod(opj_j3d_t *j3d, void *tile_coder) { + int l, layno; + int totlen; + opj_tcp_t *tcp = NULL; + opj_volume_info_t *volume_info = NULL; + + opj_tcd_t *tcd = (opj_tcd_t*)tile_coder; /* cast is needed because of conflicts in header inclusions */ + opj_cp_t *cp = j3d->cp; + opj_cio_t *cio = j3d->cio; + + cio_write(cio, J3D_MS_SOD, 2); + if (j3d->curtileno == 0) { + j3d->sod_start = cio_tell(cio) + j3d->pos_correction; + } + + /* INDEX >> */ + volume_info = j3d->volume_info; + if (volume_info && volume_info->index_on) { + volume_info->tile[j3d->curtileno].end_header = cio_tell(cio) + j3d->pos_correction - 1; + } + /* << INDEX */ + + tcp = &cp->tcps[j3d->curtileno]; + for (layno = 0; layno < tcp->numlayers; layno++) { + tcp->rates[layno] -= tcp->rates[layno] ? (j3d->sod_start / (cp->th * cp->tw * cp->tl)) : 0; + } + + if(volume_info) { + volume_info->num = 0; + } + + l = tcd_encode_tile(tcd, j3d->curtileno, cio_getbp(cio), cio_numbytesleft(cio) - 2, volume_info); + + /* Writing Psot in SOT marker */ + totlen = cio_tell(cio) + l - j3d->sot_start; + cio_seek(cio, j3d->sot_start + 6); + cio_write(cio, totlen, 4); + cio_seek(cio, j3d->sot_start + totlen); +} + +static void j3d_read_sod(opj_j3d_t *j3d) { + int len, truncate = 0, i; + unsigned char *data = NULL, *data_ptr = NULL; + + opj_cio_t *cio = j3d->cio; + int curtileno = j3d->curtileno; + + len = int_min(j3d->eot - cio_getbp(cio), cio_numbytesleft(cio) + 1); + + if (len == cio_numbytesleft(cio) + 1) { + truncate = 1; /* Case of a truncate codestream */ + } + + data = (unsigned char *) opj_malloc((j3d->tile_len[curtileno] + len) * sizeof(unsigned char)); + + for (i = 0; i < j3d->tile_len[curtileno]; i++) { + data[i] = j3d->tile_data[curtileno][i]; + } + + data_ptr = data + j3d->tile_len[curtileno]; + for (i = 0; i < len; i++) { + data_ptr[i] = cio_read(cio, 1); + } + + j3d->tile_len[curtileno] += len; + opj_free(j3d->tile_data[curtileno]); + j3d->tile_data[curtileno] = data; + + if (!truncate) { + j3d->state = J3D_STATE_TPHSOT; + } else { + j3d->state = J3D_STATE_NEOC; /* RAJOUTE !! */ + } +} + +static void j3d_write_rgn(opj_j3d_t *j3d, int compno, int tileno) { + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = &cp->tcps[tileno]; + opj_cio_t *cio = j3d->cio; + int numcomps = j3d->volume->numcomps; + + cio_write(cio, J3D_MS_RGN, 2); /* RGN */ + cio_write(cio, numcomps <= 256 ? 5 : 6, 2); /* Lrgn */ + cio_write(cio, compno, numcomps <= 256 ? 1 : 2); /* Crgn */ + cio_write(cio, 0, 1); /* Srgn */ + cio_write(cio, tcp->tccps[compno].roishift, 1); /* SPrgn */ +} + +static void j3d_read_rgn(opj_j3d_t *j3d) { + int len, compno, roisty; + + opj_cp_t *cp = j3d->cp; + opj_tcp_t *tcp = j3d->state == J3D_STATE_TPH ? &cp->tcps[j3d->curtileno] : j3d->default_tcp; + opj_cio_t *cio = j3d->cio; + int numcomps = j3d->volume->numcomps; + + len = cio_read(cio, 2); /* Lrgn */ + compno = cio_read(cio, numcomps <= 256 ? 1 : 2); /* Crgn */ + roisty = cio_read(cio, 1); /* Srgn */ + tcp->tccps[compno].roishift = cio_read(cio, 1); /* SPrgn */ +} + +static void j3d_write_eoc(opj_j3d_t *j3d) { + opj_cio_t *cio = j3d->cio; + /* opj_event_msg(j3d->cinfo, "%.8x: EOC\n", cio_tell(cio) + j3d->pos_correction); */ + cio_write(cio, J3D_MS_EOC, 2); +} + +static void j3d_read_eoc(opj_j3d_t *j3d) { + int i, tileno; + +#ifndef NO_PACKETS_DECODING + opj_tcd_t *tcd = tcd_create(j3d->cinfo); + tcd_malloc_decode(tcd, j3d->volume, j3d->cp); + /*j3d_dump_volume(stdout, tcd->volume); + j3d_dump_cp(stdout, tcd->volume, tcd->cp);*/ + for (i = 0; i < j3d->cp->tileno_size; i++) { + tileno = j3d->cp->tileno[i]; + //opj_event_msg(j3d->cinfo, EVT_INFO, "tcd_decode_tile \n"); + tcd_decode_tile(tcd, j3d->tile_data[tileno], j3d->tile_len[tileno], tileno); + opj_free(j3d->tile_data[tileno]); + j3d->tile_data[tileno] = NULL; + } + tcd_free_decode(tcd); + tcd_destroy(tcd); +#else + for (i = 0; i < j3d->cp->tileno_size; i++) { + tileno = j3d->cp->tileno[i]; + opj_free(j3d->tile_data[tileno]); + j3d->tile_data[tileno] = NULL; + } +#endif + + j3d->state = J3D_STATE_MT; +} + +static void j3d_read_unk(opj_j3d_t *j3d) { + opj_event_msg(j3d->cinfo, EVT_WARNING, "Unknown marker\n"); +} + +static opj_atk_t atk_info_wt[] = { + {0, 1, J3D_ATK_WS, J3D_ATK_IRR, 0, J3D_ATK_WS, 1.230174104, 4, {0}, {0}, {0}, {1,1,1,1}, {-1.586134342059924, -0.052980118572961, 0.882911075530934, 0.443506852043971}},/* WT 9-7 IRR*/ + {1, 0, J3D_ATK_WS, J3D_ATK_REV, 0, J3D_ATK_WS, 0, 2, {0}, {1,2}, {1,2}, {1,1}, {-1.0,1.0}},/* WT 5-3 REV*/ + {2, 0, J3D_ATK_ARB, J3D_ATK_REV, 0, J3D_ATK_CON, 0, 2, {0,0}, {0,1}, {0,1}, {1,1}, {{-1.0},{1.0}}}, /* WT 2-2 REV*/ + {3, 0, J3D_ATK_ARB, J3D_ATK_REV, 1, J3D_ATK_CON, 0, 3, {0,0,-1}, {0,1,2}, {0,1,2}, {1,1,3}, {{-1.0},{1.0},{1.0,0.0,-1.0}}}, /* WT 2-6 REV*/ + {4, 0, J3D_ATK_ARB, J3D_ATK_REV, 1, J3D_ATK_CON, 0, 3, {0,0,-2}, {0,1,6}, {0,1,32}, {1,1,5}, {{-1},{1},{-3.0,22.0,0.0,-22.0,3.0}}}, /* WT 2-10 REV*/ + {5, 1, J3D_ATK_ARB, J3D_ATK_IRR, 1, J3D_ATK_WS, 1, 7, {0}, {0}, {0}, {1,1,2,1,2,1,3},{{-1},{1.58613434206},{-0.460348209828, 0.460348209828},{0.25},{0.374213867768,-0.374213867768},{-1.33613434206},{0.29306717103,0,-0.29306717103}}}, /* WT 6-10 IRR*/ + {6, 1, J3D_ATK_ARB, J3D_ATK_IRR, 0, J3D_ATK_WS, 1, 11, {0}, {0}, {0}, {1,1,2,1,2,1,2,1,2,1,5},{{-1},{0,99715069105},{-1.00573127827, 1.00573127827},{-0.27040357631},{2.20509972343, -2.20509972343},{0.08059995736}, + {-1.62682532350, 1.62682532350},{0.52040357631},{0.60404664250, -0.60404664250},{-0.82775064841},{-0.06615812964, 0.29402137720, 0, -0.29402137720, 0.06615812964}}}, /* WT 10-18 IRR*/ + {7, 1, J3D_ATK_WS, J3D_ATK_IRR, 0, J3D_ATK_WS, 1, 2, {0}, {0}, {0}, {1,1}, {-0.5, 0.25}}, /* WT 5-3 IRR*/ + {8, 0, J3D_ATK_WS, J3D_ATK_REV, 0, J3D_ATK_WS, 0, 2, {0}, {4,4}, {8,8}, {2,2}, {{-9,1},{5,-1}}} /* WT 13-7 REV*/ +}; + +typedef struct opj_dec_mstabent { + /** marker value */ + int id; + /** value of the state when the marker can appear */ + int states; + /** action linked to the marker */ + void (*handler) (opj_j3d_t *j3d); +} opj_dec_mstabent_t; + +opj_dec_mstabent_t j3d_dec_mstab[] = { + {J3D_MS_SOC, J3D_STATE_MHSOC, j3d_read_soc}, + {J3D_MS_SOT, J3D_STATE_MH | J3D_STATE_TPHSOT, j3d_read_sot}, + {J3D_MS_SOD, J3D_STATE_TPH, j3d_read_sod}, + {J3D_MS_EOC, J3D_STATE_TPHSOT, j3d_read_eoc}, + {J3D_MS_CAP, J3D_STATE_MHSIZ, j3d_read_cap}, + {J3D_MS_SIZ, J3D_STATE_MHSIZ, j3d_read_siz}, + {J3D_MS_ZSI, J3D_STATE_MHSIZ, j3d_read_zsi}, + {J3D_MS_COD, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_cod}, + {J3D_MS_COC, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_coc}, + {J3D_MS_RGN, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_rgn}, + {J3D_MS_QCD, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_qcd}, + {J3D_MS_QCC, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_qcc}, + {J3D_MS_POC, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_poc}, + {J3D_MS_TLM, J3D_STATE_MH, j3d_read_tlm}, + {J3D_MS_PLM, J3D_STATE_MH, j3d_read_plm}, + {J3D_MS_PLT, J3D_STATE_TPH, j3d_read_plt}, + {J3D_MS_PPM, J3D_STATE_MH, j3d_read_ppm}, + {J3D_MS_PPT, J3D_STATE_TPH, j3d_read_ppt}, + {J3D_MS_SOP, 0, 0}, + {J3D_MS_CRG, J3D_STATE_MH, j3d_read_crg}, + {J3D_MS_COM, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_com}, + {J3D_MS_DCO, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_dco}, + {J3D_MS_ATK, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_atk}, + {0, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_unk} + /*, -->must define the j3d_read functions + {J3D_MS_CBD, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_cbd}, + {J3D_MS_MCT, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_mct}, + {J3D_MS_MCC, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_mcc}, + {J3D_MS_MCO, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_mco}, + {J3D_MS_NLT, J3D_STATE_MH | J3D_STATE_TPH, j3d_read_nlt}, + {J3D_MS_VMS, J3D_STATE_MH, j3d_read_vms}, + {J3D_MS_DFS, J3D_STATE_MH, j3d_read_dfs}, + {J3D_MS_ADS, J3D_STATE_MH, j3d_read_ads}, + {J3D_MS_QPD, J3D_STATE_MH, j3d_read_qpd}, + {J3D_MS_QPC, J3D_STATE_TPH, j3d_read_qpc}*/ +}; + +/** +Read the lookup table containing all the marker, status and action +@param id Marker value +*/ +static opj_dec_mstabent_t *j3d_dec_mstab_lookup(int id) { + opj_dec_mstabent_t *e; + for (e = j3d_dec_mstab; e->id != 0; e++) { + if (e->id == id) { + break; + } + } + return e; +} + +/* ----------------------------------------------------------------------- */ +/* J3D / JPT decoder interface */ +/* ----------------------------------------------------------------------- */ + +opj_j3d_t* j3d_create_decompress(opj_common_ptr cinfo) { + opj_j3d_t *j3d = (opj_j3d_t*)opj_malloc(sizeof(opj_j3d_t)); + if(j3d) { + j3d->cinfo = cinfo; + j3d->default_tcp = (opj_tcp_t*)opj_malloc(sizeof(opj_tcp_t)); + if(!j3d->default_tcp) { + opj_free(j3d); + return NULL; + } + } + return j3d; +} + +void j3d_destroy_decompress(opj_j3d_t *j3d) { + int i = 0; + + if(j3d->tile_len != NULL) { + opj_free(j3d->tile_len); + } + if(j3d->tile_data != NULL) { + opj_free(j3d->tile_data); + } + if(j3d->default_tcp != NULL) { + opj_tcp_t *default_tcp = j3d->default_tcp; + if(default_tcp->ppt_data_first != NULL) { + opj_free(default_tcp->ppt_data_first); + } + if(j3d->default_tcp->tccps != NULL) { + opj_free(j3d->default_tcp->tccps); + } + opj_free(j3d->default_tcp); + } + if(j3d->cp != NULL) { + opj_cp_t *cp = j3d->cp; + if(cp->tcps != NULL) { + for(i = 0; i < cp->tw * cp->th * cp->tl; i++) { + if(cp->tcps[i].ppt_data_first != NULL) { + opj_free(cp->tcps[i].ppt_data_first); + } + if(cp->tcps[i].tccps != NULL) { + opj_free(cp->tcps[i].tccps); + } + } + opj_free(cp->tcps); + } + if(cp->ppm_data_first != NULL) { + opj_free(cp->ppm_data_first); + } + if(cp->tileno != NULL) { + opj_free(cp->tileno); + } + if(cp->comment != NULL) { + opj_free(cp->comment); + } + + opj_free(cp); + } + + opj_free(j3d); +} + +void j3d_setup_decoder(opj_j3d_t *j3d, opj_dparameters_t *parameters) { + if(j3d && parameters) { + /* create and initialize the coding parameters structure */ + opj_cp_t *cp = (opj_cp_t*)opj_malloc(sizeof(opj_cp_t)); + cp->reduce[0] = parameters->cp_reduce[0]; + cp->reduce[1] = parameters->cp_reduce[1]; + cp->reduce[2] = parameters->cp_reduce[2]; + cp->layer = parameters->cp_layer; + cp->bigendian = parameters->bigendian; + + + cp->encoding_format = ENCOD_2EB; + cp->transform_format = TRF_2D_DWT; + + /* keep a link to cp so that we can destroy it later in j3d_destroy_decompress */ + j3d->cp = cp; + } +} + +opj_volume_t* j3d_decode(opj_j3d_t *j3d, opj_cio_t *cio) { + opj_volume_t *volume = NULL; + + opj_common_ptr cinfo = j3d->cinfo; + + j3d->cio = cio; + + /* create an empty volume */ + volume = (opj_volume_t*)opj_malloc(sizeof(opj_volume_t)); + j3d->volume = volume; + + j3d->state = J3D_STATE_MHSOC; + + for (;;) { + opj_dec_mstabent_t *e; + int id = cio_read(cio, 2); + if (id >> 8 != 0xff) { + opj_volume_destroy(volume); + opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id); + return 0; + } + e = j3d_dec_mstab_lookup(id); + //opj_event_msg(cinfo, EVT_INFO, "MARKER %x PREVSTATE %d E->STATE %d\n",e->id,j3d->state,e->states); + if (!(j3d->state & e->states)) { + opj_volume_destroy(volume); + opj_event_msg(cinfo, EVT_ERROR, "%.8x: unexpected marker %x\n", cio_tell(cio) - 2, id); + return 0; + } + if (e->handler) { + (*e->handler)(j3d); + } + //opj_event_msg(cinfo, EVT_INFO, "POSTSTATE %d\n",j3d->state); + if (j3d->state == J3D_STATE_MT) { + break; + } + if (j3d->state == J3D_STATE_NEOC) { + break; + } + } + if (j3d->state == J3D_STATE_NEOC) { + j3d_read_eoc(j3d); + } + + if (j3d->state != J3D_STATE_MT) { + opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n"); + } + + return volume; +} + +/* ----------------------------------------------------------------------- */ +/* J3D encoder interface */ +/* ----------------------------------------------------------------------- */ + +opj_j3d_t* j3d_create_compress(opj_common_ptr cinfo) { + opj_j3d_t *j3d = (opj_j3d_t*)opj_malloc(sizeof(opj_j3d_t)); + if(j3d) { + j3d->cinfo = cinfo; + } + return j3d; +} + +void j3d_destroy_compress(opj_j3d_t *j3d) { + int tileno; + + if(!j3d) return; + + if(j3d->volume_info != NULL) { + opj_volume_info_t *volume_info = j3d->volume_info; + if (volume_info->index_on && j3d->cp) { + opj_cp_t *cp = j3d->cp; + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + opj_tile_info_t *tile_info = &volume_info->tile[tileno]; + opj_free(tile_info->thresh); + opj_free(tile_info->packet); + } + opj_free(volume_info->tile); + } + opj_free(volume_info); + } + if(j3d->cp != NULL) { + opj_cp_t *cp = j3d->cp; + + if(cp->comment) { + opj_free(cp->comment); + } + if(cp->matrice) { + opj_free(cp->matrice); + } + for (tileno = 0; tileno < cp->tw * cp->th; tileno++) { + opj_free(cp->tcps[tileno].tccps); + } + opj_free(cp->tcps); + opj_free(cp); + } + + opj_free(j3d); +} + +void j3d_setup_encoder(opj_j3d_t *j3d, opj_cparameters_t *parameters, opj_volume_t *volume) { + int i, j, tileno, numpocs_tile; + opj_cp_t *cp = NULL; + + if(!j3d || !parameters || ! volume) { + return; + } + + /* create and initialize the coding parameters structure */ + cp = (opj_cp_t*)opj_malloc(sizeof(opj_cp_t)); + + /* keep a link to cp so that we can destroy it later in j3d_destroy_compress */ + j3d->cp = cp; + + /* set default values for cp */ + cp->tw = 1; + cp->th = 1; + cp->tl = 1; + + /* copy user encoding parameters */ + cp->disto_alloc = parameters->cp_disto_alloc; + cp->fixed_alloc = parameters->cp_fixed_alloc; + cp->fixed_quality = parameters->cp_fixed_quality; + + /* transform and coding method */ + cp->transform_format = parameters->transform_format; + cp->encoding_format = parameters->encoding_format; + + /* mod fixed_quality */ + if(parameters->cp_matrice) { + size_t array_size = parameters->tcp_numlayers * 3 * parameters->numresolution[0] * sizeof(int); + cp->matrice = (int *) opj_malloc(array_size); + memcpy(cp->matrice, parameters->cp_matrice, array_size); + } + + /* creation of an index file ? */ + cp->index_on = parameters->index_on; + if(cp->index_on) { + j3d->volume_info = (opj_volume_info_t*)opj_malloc(sizeof(opj_volume_info_t)); + } + + /* tiles */ + cp->tdx = parameters->cp_tdx; + cp->tdy = parameters->cp_tdy; + cp->tdz = parameters->cp_tdz; + /* tile offset */ + cp->tx0 = parameters->cp_tx0; + cp->ty0 = parameters->cp_ty0; + cp->tz0 = parameters->cp_tz0; + /* 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(volume->x1 - cp->tx0, cp->tdx); + cp->th = int_ceildiv(volume->y1 - cp->ty0, cp->tdy); + cp->tl = int_ceildiv(volume->z1 - cp->tz0, cp->tdz); + } else { + cp->tdx = volume->x1 - cp->tx0; + cp->tdy = volume->y1 - cp->ty0; + cp->tdz = volume->z1 - cp->tz0; + } + + /* initialize the multiple tiles */ + /* ---------------------------- */ + cp->tcps = (opj_tcp_t *) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(opj_tcp_t)); + + for (tileno = 0; tileno < cp->tw * cp->th * cp->tl; tileno++) { + opj_tcp_t *tcp = &cp->tcps[tileno]; + tcp->numlayers = parameters->tcp_numlayers; + for (j = 0; j < tcp->numlayers; j++) { + if (cp->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 = volume->numcomps == 3 ? 1 : 0; + + numpocs_tile = 0; + tcp->POC = 0; + if (parameters->numpocs) { + /* initialisation of POC */ + tcp->POC = 1; + 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->prg = parameters->POC[numpocs_tile].prg; + tcp_poc->tile = parameters->POC[numpocs_tile].tile; + numpocs_tile++; + } + } + } + tcp->numpocs = numpocs_tile; + + tcp->tccps = (opj_tccp_t *) opj_malloc(volume->numcomps * sizeof(opj_tccp_t)); + + for (i = 0; i < volume->numcomps; i++) { + opj_tccp_t *tccp = &tcp->tccps[i]; + tccp->csty = parameters->csty & J3D_CCP_CSTY_PRT; /* 0 => standard precint || 1 => custom-defined precinct */ + tccp->numresolution[0] = parameters->numresolution[0]; + tccp->numresolution[1] = parameters->numresolution[1]; + tccp->numresolution[2] = parameters->numresolution[2]; + assert (parameters->cblock_init[0] <= T1_MAXCBLKW); + assert (parameters->cblock_init[0] >= T1_MINCBLKW); + assert (parameters->cblock_init[1] <= T1_MAXCBLKH); + assert (parameters->cblock_init[1] >= T1_MINCBLKH); + assert (parameters->cblock_init[2] <= T1_MAXCBLKD); + assert (parameters->cblock_init[2] >= T1_MINCBLKD); + tccp->cblk[0] = int_floorlog2(parameters->cblock_init[0]); + tccp->cblk[1] = int_floorlog2(parameters->cblock_init[1]); + tccp->cblk[2] = int_floorlog2(parameters->cblock_init[2]); + assert (tccp->cblk[0]+tccp->cblk[1]+tccp->cblk[1] <= T1_MAXWHD); + tccp->cblksty = parameters->mode; //Codeblock style --> Table A.19 (default 0) + + /*ATK / transform */ + tccp->reversible = parameters->irreversible ? 0 : 1; /* 0 => DWT 9-7 || 1 => DWT 5-3 */ + for (j = 0; j < 3; j++) { + tccp->dwtid[j] = parameters->irreversible ? 0 : 1; /* 0 => DWT 9-7 || 1 => DWT 5-3 */ + } + + /* Quantification: SEQNT (Scalar Expounded, value for each subband) / NOQNT (no quant)*/ + tccp->qntsty = parameters->irreversible ? J3D_CCP_QNTSTY_SEQNT : J3D_CCP_QNTSTY_NOQNT; + tccp->numgbits = 2; + if (i == parameters->roi_compno) { + tccp->roishift = parameters->roi_shift; + } else { + tccp->roishift = 0; + } + /* Custom defined precints */ + if (parameters->csty & J3D_CCP_CSTY_PRT) { + int k; + for (k = 0; k < 3; k++) { + int p = 0; + for (j = tccp->numresolution[k] - 1; j >= 0; j--) { + if (p < parameters->res_spec) {/* p < number of precinct size specifications */ + if (parameters->prct_init[k][p] < 1) { + tccp->prctsiz[k][j] = 1; + } else { + tccp->prctsiz[k][j] = int_floorlog2(parameters->prct_init[k][p]); + } + } else { + int res_spec = parameters->res_spec; + int size_prct = parameters->prct_init[k][res_spec - 1] >> (p - (res_spec - 1)); + if (size_prct < 1) { + tccp->prctsiz[k][j] = 1; + } else { + tccp->prctsiz[k][j] = int_floorlog2(size_prct); + } + } + } + p++; + } + } else { + int k; + for (k = 0; k < 3; k++) { + for (j = 0; j < tccp->numresolution[k]; j++) { + tccp->prctsiz[k][j] = 15; + } + } + } + //Calcular stepsize for each subband (if NOQNT -->stepsize = 1.0) + dwt_calc_explicit_stepsizes(tccp, volume->comps[i].prec); + } + } +} + +/** +Create an index file +@param j3d +@param cio +@param volume_info +@param index Index filename +@return Returns 1 if successful, returns 0 otherwise +*/ +static int j3d_create_index(opj_j3d_t *j3d, opj_cio_t *cio, opj_volume_info_t *volume_info, char *index) { + + int tileno, compno, layno, resno, precno, pack_nb, x, y, z; + FILE *stream = NULL; + double total_disto = 0; + + volume_info->codestream_size = cio_tell(cio) + j3d->pos_correction; /* Correction 14/4/03 suite rmq de Patrick */ + + stream = fopen(index, "w"); + if (!stream) { + opj_event_msg(j3d->cinfo, EVT_ERROR, "failed to open %s for writing\n", index); + return 0; + } + + fprintf(stream, "w %d\t h %d\t l %d\n", volume_info->volume_w, volume_info->volume_h, volume_info->volume_l); + fprintf(stream, "TRASNFORM\t%d\n", volume_info->transform_format); + fprintf(stream, "ENTROPY CODING\t%d\n", volume_info->encoding_format); + fprintf(stream, "PROG\t%d\n", volume_info->prog); + fprintf(stream, "TILE\tx %d y %d z %d\n", volume_info->tile_x, volume_info->tile_y, volume_info->tile_z); + fprintf(stream, "NOTILE\tx %d y %d z %d\n", volume_info->tw, volume_info->th, volume_info->tl); + fprintf(stream, "COMPONENTS\t%d\n", volume_info->comp); + fprintf(stream, "LAYER\t%d\n", volume_info->layer); + fprintf(stream, "RESOLUTIONS\tx %d y %d z %d\n", volume_info->decomposition[0], volume_info->decomposition[1], volume_info->decomposition[2]); + + fprintf(stream, "Precint sizes for each resolution:\n"); + for (resno = volume_info->decomposition[0]; resno >= 0; resno--) { + fprintf(stream, "Resno %d \t [%d,%d,%d] \n", resno, + (1 << volume_info->tile[0].prctsiz[0][resno]), (1 << volume_info->tile[0].prctsiz[0][resno]), (1 << volume_info->tile[0].prctsiz[2][resno])); /* based on tile 0 */ + } + fprintf(stream, "HEADER_END\t%d\n", volume_info->main_head_end); + fprintf(stream, "CODESTREAM\t%d\n", volume_info->codestream_size); + fprintf(stream, "Num_tile Start_pos End_header End_pos Distotile Nbpix Ratio\n"); + for (tileno = 0; tileno < (volume_info->tw * volume_info->th * volume_info->tl); tileno++) { + fprintf(stream, "%4d\t%9d\t%9d\t%9d\t%9e\t%9d\t%9e\n", + volume_info->tile[tileno].num_tile, + volume_info->tile[tileno].start_pos, + volume_info->tile[tileno].end_header, + volume_info->tile[tileno].end_pos, + volume_info->tile[tileno].distotile, volume_info->tile[tileno].nbpix, + volume_info->tile[tileno].distotile / volume_info->tile[tileno].nbpix); + } + + for (tileno = 0; tileno < (volume_info->tw * volume_info->th * volume_info->tl); tileno++) { + int start_pos, end_pos; + double disto = 0; + pack_nb = 0; + if (volume_info->prog == LRCP) { /* LRCP */ + fprintf(stream, "pack_nb tileno layno resno compno precno start_pos end_pos disto\n"); + for (layno = 0; layno < volume_info->layer; layno++) { + for (resno = 0; resno < volume_info->decomposition[0] + 1; resno++) { + for (compno = 0; compno < volume_info->comp; compno++) { + int prec_max = volume_info->tile[tileno].prctno[0][resno] * volume_info->tile[tileno].prctno[1][resno] * volume_info->tile[tileno].prctno[2][resno]; + for (precno = 0; precno < prec_max; precno++) { + start_pos = volume_info->tile[tileno].packet[pack_nb].start_pos; + end_pos = volume_info->tile[tileno].packet[pack_nb].end_pos; + disto = volume_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %7d %5d %6d %6d %9d %9d %8e\n",pack_nb, tileno, layno, resno, compno, precno, start_pos, end_pos, disto); + total_disto += disto; + pack_nb++; + } + } + } + } + } /* LRCP */ + else if (volume_info->prog == RLCP) { /* RLCP */ + /* + fprintf(stream, "pack_nb tileno resno layno compno precno start_pos end_pos disto"); + */ + for (resno = 0; resno < volume_info->decomposition[0] + 1; resno++) { + for (layno = 0; layno < volume_info->layer; layno++) { + for (compno = 0; compno < volume_info->comp; compno++) { + int prec_max = volume_info->tile[tileno].prctno[0][resno] * volume_info->tile[tileno].prctno[1][resno]* volume_info->tile[tileno].prctno[2][resno]; + for (precno = 0; precno < prec_max; precno++) { + start_pos = volume_info->tile[tileno].packet[pack_nb].start_pos; + end_pos = volume_info->tile[tileno].packet[pack_nb].end_pos; + disto = volume_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %5d %7d %6d %6d %9d %9d %8e\n", + pack_nb, tileno, resno, layno, compno, precno, start_pos, end_pos, disto); + total_disto += disto; + pack_nb++; + } + } + } + } + } /* RLCP */ + else if (volume_info->prog == RPCL) { /* RPCL */ + /* + fprintf(stream, "\npack_nb tileno resno precno compno layno start_pos end_pos disto\n"); + */ + for (resno = 0; resno < volume_info->decomposition[0] + 1; resno++) { + /* I suppose components have same XRsiz, YRsiz */ + //int x0 = volume_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)volume_info->tw ) * volume_info->tw * volume_info->tile_x; + //int y0 = volume_info->tile_Ox + (int)floor( (float)tileno/(float)volume_info->tw ) * volume_info->tile_y; + int x0 = volume_info->tile_Ox + (int)floor( (float)tileno/(float)volume_info->tw ) * volume_info->tile_x; + int y0 = volume_info->tile_Oy + (int)floor( (float)tileno/(float)volume_info->th ) * volume_info->tile_y; + int z0 = volume_info->tile_Ox + (int)floor( (float)tileno/(float)volume_info->tl ) * volume_info->tile_z; + int x1 = x0 + volume_info->tile_x; + int y1 = y0 + volume_info->tile_y; + int z1 = z0 + volume_info->tile_z; + for(z = z0; z < z1; z++) { + for(y = y0; y < y1; y++) { + for(x = x0; x < x1; x++) { + for (compno = 0; compno < volume_info->comp; compno++) { + int prec_max = volume_info->tile[tileno].prctno[0][resno] * volume_info->tile[tileno].prctno[1][resno] * volume_info->tile[tileno].prctno[2][resno]; + for (precno = 0; precno < prec_max; precno++) { + int pcnx = volume_info->tile[tileno].prctno[0][resno]; + int pcx = (int) pow( 2, volume_info->tile[tileno].prctsiz[0][resno] + volume_info->decomposition[0] - resno ); + int pcy = (int) pow( 2, volume_info->tile[tileno].prctsiz[1][resno] + volume_info->decomposition[1] - resno ); + int pcz = (int) pow( 2, volume_info->tile[tileno].prctsiz[2][resno] + volume_info->decomposition[2] - resno ); + int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx; + int precno_y = (int) floor( (float)precno/(float)pcnx ); + if (precno_y*pcy == y ) { + if (precno_x*pcx == x ) { + for (layno = 0; layno < volume_info->layer; layno++) { + start_pos = volume_info->tile[tileno].packet[pack_nb].start_pos; + end_pos = volume_info->tile[tileno].packet[pack_nb].end_pos; + disto = volume_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %5d %6d %6d %7d %9d %9d %8e\n", + pack_nb, tileno, resno, precno, compno, layno, start_pos, end_pos, disto); + total_disto += disto; + pack_nb++; + } + } + } + } /* precno */ + } /* compno */ + } /* x = x0..x1 */ + } /* y = y0..y1 */ + } /* z = z0..z1 */ + } /* resno */ + } /* RPCL */ + else if (volume_info->prog == PCRL) { /* PCRL */ + /* I suppose components have same XRsiz, YRsiz */ + int x0 = volume_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)volume_info->tw ) * volume_info->tw * volume_info->tile_x; + int y0 = volume_info->tile_Ox + (int)floor( (float)tileno/(float)volume_info->tw ) * volume_info->tile_y; + int z0 = volume_info->tile_Oz + (int)floor( (float)tileno/(float)volume_info->tw ) * volume_info->tile_z; + int x1 = x0 + volume_info->tile_x; + int y1 = y0 + volume_info->tile_y; + int z1 = z0 + volume_info->tile_z; + /* + fprintf(stream, "\npack_nb tileno precno compno resno layno start_pos end_pos disto\n"); + */ + for(z = z0; z < z1; z++) { + for(y = y0; y < y1; y++) { + for(x = x0; x < x1; x++) { + for (compno = 0; compno < volume_info->comp; compno++) { + for (resno = 0; resno < volume_info->decomposition[0] + 1; resno++) { + int prec_max = volume_info->tile[tileno].prctno[0][resno] * volume_info->tile[tileno].prctno[1][resno]; + for (precno = 0; precno < prec_max; precno++) { + int pcnx = volume_info->tile[tileno].prctno[0][resno]; + int pcx = (int) pow( 2, volume_info->tile[tileno].prctsiz[0][resno] + volume_info->decomposition[0] - resno ); + int pcy = (int) pow( 2, volume_info->tile[tileno].prctsiz[1][resno] + volume_info->decomposition[1] - resno ); + int pcz = (int) pow( 2, volume_info->tile[tileno].prctsiz[2][resno] + volume_info->decomposition[2] - resno ); + int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx; + int precno_y = (int) floor( (float)precno/(float)pcnx ); + int precno_z = (int) floor( (float)precno/(float)pcnx ); + if (precno_z*pcz == z ) { + if (precno_y*pcy == y ) { + if (precno_x*pcx == x ) { + for (layno = 0; layno < volume_info->layer; layno++) { + start_pos = volume_info->tile[tileno].packet[pack_nb].start_pos; + end_pos = volume_info->tile[tileno].packet[pack_nb].end_pos; + disto = volume_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %6d %6d %5d %7d %9d %9d %8e\n", + pack_nb, tileno, precno, compno, resno, layno, start_pos, end_pos, disto); + total_disto += disto; + pack_nb++; + } + } + } + } + } /* precno */ + } /* resno */ + } /* compno */ + } /* x = x0..x1 */ + } /* y = y0..y1 */ + } + } /* PCRL */ + else { /* CPRL */ + /* + fprintf(stream, "\npack_nb tileno compno precno resno layno start_pos end_pos disto\n"); + */ + for (compno = 0; compno < volume_info->comp; compno++) { + /* I suppose components have same XRsiz, YRsiz */ + int x0 = volume_info->tile_Ox + tileno - (int)floor( (float)tileno/(float)volume_info->tw ) * volume_info->tw * volume_info->tile_x; + int y0 = volume_info->tile_Ox + (int)floor( (float)tileno/(float)volume_info->tw ) * volume_info->tile_y; + int z0 = volume_info->tile_Oz + (int)floor( (float)tileno/(float)volume_info->tw ) * volume_info->tile_z; + int x1 = x0 + volume_info->tile_x; + int y1 = y0 + volume_info->tile_y; + int z1 = z0 + volume_info->tile_z; + for(z = z0; z < z1; z++) { + for(y = y0; y < y1; y++) { + for(x = x0; x < x1; x++) { + for (resno = 0; resno < volume_info->decomposition[0] + 1; resno++) { + int prec_max = volume_info->tile[tileno].prctno[0][resno] * volume_info->tile[tileno].prctno[1][resno] * volume_info->tile[tileno].prctno[2][resno]; + for (precno = 0; precno < prec_max; precno++) { + int pcnx = volume_info->tile[tileno].prctno[0][resno]; + int pcny = volume_info->tile[tileno].prctno[1][resno]; + int pcx = (int) pow( 2, volume_info->tile[tileno].prctsiz[0][resno] + volume_info->decomposition[0] - resno ); + int pcy = (int) pow( 2, volume_info->tile[tileno].prctsiz[1][resno] + volume_info->decomposition[1] - resno ); + int pcz = (int) pow( 2, volume_info->tile[tileno].prctsiz[2][resno] + volume_info->decomposition[2] - resno ); + int precno_x = precno - (int) floor( (float)precno/(float)pcnx ) * pcnx; + int precno_y = (int) floor( (float)precno/(float)pcnx ); + int precno_z = 0; /*???*/ + if (precno_z*pcz == z ) { + if (precno_y*pcy == y ) { + if (precno_x*pcx == x ) { + for (layno = 0; layno < volume_info->layer; layno++) { + start_pos = volume_info->tile[tileno].packet[pack_nb].start_pos; + end_pos = volume_info->tile[tileno].packet[pack_nb].end_pos; + disto = volume_info->tile[tileno].packet[pack_nb].disto; + fprintf(stream, "%4d %6d %6d %6d %5d %7d %9d %9d %8e\n", + pack_nb, tileno, compno, precno, resno, layno, start_pos, end_pos, disto); + total_disto += disto; + pack_nb++; + } + } + } + } + } /* precno */ + } /* resno */ + } /* x = x0..x1 */ + } /* y = y0..y1 */ + } /* z = z0..z1 */ + } /* comno */ + } /* CPRL */ + } /* tileno */ + + fprintf(stream, "SE_MAX\t%8e\n", volume_info->D_max); /* SE max */ + fprintf(stream, "SE_TOTAL\t%.8e\n", total_disto); /* SE totale */ + + + fclose(stream); + + return 1; +} + +bool j3d_encode(opj_j3d_t *j3d, opj_cio_t *cio, opj_volume_t *volume, char *index) { + int tileno, compno; + opj_volume_info_t *volume_info = NULL; + opj_cp_t *cp = NULL; + opj_tcd_t *tcd = NULL; /* TCD component */ + + j3d->cio = cio; + j3d->volume = volume; + cp = j3d->cp; + + /*j3d_dump_volume(stdout, volume); + j3d_dump_cp(stdout, volume, cp);*/ + + /* INDEX >> */ + volume_info = j3d->volume_info; + if (volume_info && cp->index_on) { + volume_info->index_on = cp->index_on; + volume_info->tile = (opj_tile_info_t *) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(opj_tile_info_t)); + volume_info->volume_w = volume->x1 - volume->x0; + volume_info->volume_h = volume->y1 - volume->y0; + volume_info->volume_l = volume->z1 - volume->z0; + volume_info->prog = (&cp->tcps[0])->prg; + volume_info->tw = cp->tw; + volume_info->th = cp->th; + volume_info->tl = cp->tl; + volume_info->tile_x = cp->tdx; /* new version parser */ + volume_info->tile_y = cp->tdy; /* new version parser */ + volume_info->tile_z = cp->tdz; /* new version parser */ + volume_info->tile_Ox = cp->tx0; /* new version parser */ + volume_info->tile_Oy = cp->ty0; /* new version parser */ + volume_info->tile_Oz = cp->tz0; /* new version parser */ + volume_info->transform_format = cp->transform_format; + volume_info->encoding_format = cp->encoding_format; + volume_info->comp = volume->numcomps; + volume_info->layer = (&cp->tcps[0])->numlayers; + volume_info->decomposition[0] = (&cp->tcps[0])->tccps->numresolution[0] - 1; + volume_info->decomposition[1] = (&cp->tcps[0])->tccps->numresolution[1] - 1; + volume_info->decomposition[2] = (&cp->tcps[0])->tccps->numresolution[2] - 1; + volume_info->D_max = 0; /* ADD Marcela */ + } + /* << INDEX */ + + j3d_write_soc(j3d); + j3d_write_siz(j3d); + if (j3d->cinfo->codec_format == CODEC_J3D) { + j3d_write_cap(j3d); + j3d_write_zsi(j3d); + } + j3d_write_cod(j3d); + j3d_write_qcd(j3d); + for (compno = 0; compno < volume->numcomps; compno++) { + opj_tcp_t *tcp = &cp->tcps[0]; + if (tcp->tccps[compno].roishift) + j3d_write_rgn(j3d, compno, 0); + } + /*Optional 15444-2 markers*/ + if (j3d->cp->tcps->tccps[0].atk != NULL) + j3d_write_atk(j3d); + if (j3d->volume->comps[0].dcoffset != 0) + j3d_write_dco(j3d); + + if (j3d->cp->transform_format != TRF_2D_DWT || j3d->cp->encoding_format != ENCOD_2EB) + j3d_write_com(j3d); + + /* INDEX >> */ + if(volume_info && volume_info->index_on) { + volume_info->main_head_end = cio_tell(cio) - 1; + } + /* << INDEX */ + + /* create the tile encoder */ + tcd = tcd_create(j3d->cinfo); + + /* encode each tile */ + for (tileno = 0; tileno < cp->tw * cp->th * cp->tl; tileno++) { + opj_event_msg(j3d->cinfo, EVT_INFO, "tile number %d / %d\n", tileno + 1, cp->tw * cp->th * cp->tl); + + j3d->curtileno = tileno; + + /* initialisation before tile encoding */ + if (tileno == 0) { + tcd_malloc_encode(tcd, volume, cp, j3d->curtileno); + } else { + tcd_init_encode(tcd, volume, cp, j3d->curtileno); + } + + /* INDEX >> */ + if(volume_info && volume_info->index_on) { + volume_info->tile[j3d->curtileno].num_tile = j3d->curtileno; + volume_info->tile[j3d->curtileno].start_pos = cio_tell(cio) + j3d->pos_correction; + } + /* << INDEX */ + + j3d_write_sot(j3d); + + for (compno = 1; compno < volume->numcomps; compno++) { + j3d_write_coc(j3d, compno); + j3d_write_qcc(j3d, compno); + } + + if (cp->tcps[tileno].numpocs) { + j3d_write_poc(j3d); + } + j3d_write_sod(j3d, tcd); //--> tcd_encode_tile + + /* INDEX >> */ + if(volume_info && volume_info->index_on) { + volume_info->tile[j3d->curtileno].end_pos = cio_tell(cio) + j3d->pos_correction - 1; + } + /* << INDEX */ + } + + /* destroy the tile encoder */ + tcd_free_encode(tcd); + tcd_destroy(tcd); + + j3d_write_eoc(j3d); + + /* Creation of the index file */ + if(volume_info && volume_info->index_on) { + if(!j3d_create_index(j3d, cio, volume_info, index)) { + opj_event_msg(j3d->cinfo, EVT_ERROR, "failed to create index file %s\n", index); + return false; + } + } + + return true; +} + diff --git a/src/lib/openjp3d/jp3d.h b/src/lib/openjp3d/jp3d.h new file mode 100755 index 00000000..5d0978c0 --- /dev/null +++ b/src/lib/openjp3d/jp3d.h @@ -0,0 +1,518 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyright (c) 2006, Mónica Díez García, Image Processing Laboratory, University of Valladolid, Spain + * 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 __J3D_H +#define __J3D_H +/** +@file j3d.h +@brief The JPEG-2000 Codestream Reader/Writer (J3D) + +The functions in J3D.C have for goal to read/write the several parts of the codestream: markers and data. +*/ + +/** @defgroup J3D J3D - JPEG-2000 codestream reader/writer */ +/*@{*/ + +#define J3D_CP_CSTY_PRT 0x01 +#define J3D_CP_CSTY_SOP 0x02 +#define J3D_CP_CSTY_EPH 0x04 +#define J3D_CCP_CSTY_PRT 0x01 +/** Table A-8 */ +#define J3D_CCP_CBLKSTY_LAZY 0x01 /* Selective arithmetic coding bypass */ +#define J3D_CCP_CBLKSTY_RESET 0x02 /* Reset context probabilities on coding pass boundaries */ +#define J3D_CCP_CBLKSTY_TERMALL 0x04 /* Termination on each coding pass */ +#define J3D_CCP_CBLKSTY_VSC 0x08 /* Vertically causal context, add also hook for switching off and on 3D context models */ +#define J3D_CCP_CBLKSTY_PTERM 0x10 /* Predictable termination */ +#define J3D_CCP_CBLKSTY_SEGSYM 0x20 /* Segmentation symbols are used */ +#define J3D_CCP_CBLKSTY_3DCTXT 0x40 /* 3D context models (3D-EBCOT) vs 2D context models */ + +#define J3D_CCP_QNTSTY_NOQNT 0 /* Quantization style : no quantization */ +#define J3D_CCP_QNTSTY_SIQNT 1 /* Quantization style : scalar derived (values signalled only in LLL subband) */ +#define J3D_CCP_QNTSTY_SEQNT 2 /* Quantization style : scalar expounded (values signalled for each subband) */ + +/* ----------------------------------------------------------------------- */ + +#define J3D_MS_SOC 0xff4f /**< SOC marker value */ +#define J3D_MS_SOT 0xff90 /**< SOT marker value */ +#define J3D_MS_SOD 0xff93 /**< SOD marker value */ +#define J3D_MS_EOC 0xffd9 /**< EOC marker value */ +#define J3D_MS_CAP 0xff50 /**< CAP marker value */ +#define J3D_MS_SIZ 0xff51 /**< SIZ marker value */ +#define J3D_MS_ZSI 0xff54 /**< ZSI marker value */ +#define J3D_MS_COD 0xff52 /**< COD marker value */ +#define J3D_MS_COC 0xff53 /**< COC marker value */ +#define J3D_MS_RGN 0xff5e /**< RGN marker value */ +#define J3D_MS_QCD 0xff5c /**< QCD marker value */ +#define J3D_MS_QCC 0xff5d /**< QCC marker value */ +#define J3D_MS_POC 0xff5f /**< POC marker value */ +#define J3D_MS_TLM 0xff55 /**< TLM marker value */ +#define J3D_MS_PLM 0xff57 /**< PLM marker value */ +#define J3D_MS_PLT 0xff58 /**< PLT marker value */ +#define J3D_MS_PPM 0xff60 /**< PPM marker value */ +#define J3D_MS_PPT 0xff61 /**< PPT marker value */ +#define J3D_MS_SOP 0xff91 /**< SOP marker value */ +#define J3D_MS_EPH 0xff92 /**< EPH marker value */ +#define J3D_MS_CRG 0xff63 /**< CRG marker value */ +#define J3D_MS_COM 0xff64 /**< COM marker value */ +//15444-2 +#define J3D_MS_DCO 0xff70 /**< DCO marker value */ +#define J3D_MS_VMS 0xff71 /**< VMS marker value */ +#define J3D_MS_DFS 0xff72 /**< DFS marker value */ +#define J3D_MS_ADS 0xff73 /**< ADS marker value */ +#define J3D_MS_ATK 0xff79 /**< ATK marker value */ +#define J3D_MS_CBD 0xff78 /**< CBD marker value */ +#define J3D_MS_MCT 0xff74 /**< MCT marker value */ +#define J3D_MS_MCC 0xff75 /**< MCC marker value */ +#define J3D_MS_MCO 0xff77 /**< MCO marker value */ +#define J3D_MS_NLT 0xff76 /**< NLT marker value */ +#define J3D_MS_QPD 0xff5a /**< QPD marker value */ +#define J3D_MS_QPC 0xff5b /**< QPC marker value */ + +/* ----------------------------------------------------------------------- */ +/* Capability RSIZ parameter, extended */ +#define J3D_RSIZ_BASIC 0x0000 + +#define J3D_RSIZ_DCO 0x8001 /* Required */ +#define J3D_RSIZ_VSQNT 0x8002 +#define J3D_RSIZ_TCQNT 0x8004 +#define J3D_RSIZ_VMASK 0x8008 +#define J3D_RSIZ_SSOVL 0x8010 +#define J3D_RSIZ_ADECS 0x8020 +#define J3D_RSIZ_ATK 0x8040 /*Required*/ +#define J3D_RSIZ_SSYMK 0x8080 +#define J3D_RSIZ_MCT 0x8100 /*Not compatible with DCO*/ +#define J3D_RSIZ_NLT 0x8200 /*Required*/ +#define J3D_RSIZ_ASHAP 0x8400 +#define J3D_RSIZ_PRQNT 0x8800 + +#define J3D_CAP_10 0x00400000 +/* Arbitrary transformation kernel, 15444-2 */ +#define J3D_ATK_IRR 0 +#define J3D_ATK_REV 1 +#define J3D_ATK_ARB 0 +#define J3D_ATK_WS 1 +#define J3D_ATK_CON 0 +/* ----------------------------------------------------------------------- */ + +/** +Values that specify the status of the decoding process when decoding the main header. +These values may be combined with a | operator. +*/ +typedef enum J3D_STATUS { + /**< a SOC marker is expected */ + J3D_STATE_MHSOC = 0x0001, + /**< a SIZ marker is expected */ + J3D_STATE_MHSIZ = 0x0002, + /**< the decoding process is in the main header */ + J3D_STATE_MH = 0x0004, + /**< the decoding process is in a tile part header and expects a SOT marker */ + J3D_STATE_TPHSOT = 0x0008, + /**< the decoding process is in a tile part header */ + J3D_STATE_TPH = 0x0010, + /**< the EOC marker has just been read */ + J3D_STATE_MT = 0x0020, + /**< the decoding process must not expect a EOC marker because the codestream is truncated */ + J3D_STATE_NEOC = 0x0040 +} J3D_STATUS; + + + +/** +Arbitrary transformation kernel +*/ +typedef struct opj_atk { +/** index of wavelet kernel */ + int index; +/** Numerical type of scaling factor and lifting step parameters */ + int coeff_typ; +/** Wavelet filter category */ + int filt_cat; +/** Wavelet transformation type (REV/IRR) */ + int wt_typ; +/** Initial odd/even subsequence */ + int minit; +/** Boundary extension method (constant CON / whole-sample symmetric WS) */ + int exten; +/** Scaling factor. Only for wt_typ=IRR */ + double Katk; +/** Number of lifting steps */ + int Natk; +/** Offset for lifting step s. Only for filt_cat=ARB */ + int Oatk[256]; +/** Base 2 scaling exponent for lifting step s. Only for wt_typ=REV */ + int Eatk[256]; +/** Additive residue for lifting step s. Only for wt_typ=REV */ + int Batk[256]; +/** Number of lifting coefficients signaled for lifting step s */ + int LCatk[256]; +/** Lifting coefficient k for lifting step s */ + double Aatk[256][256]; +} opj_atk_t; + + +/** +Quantization stepsize +*/ +typedef struct opj_stepsize { +/** exponent */ + int expn; +/** mantissa */ + int mant; +} opj_stepsize_t; + +/** +Tile-component coding parameters +*/ +typedef struct opj_tccp { + /** coding style */ + int csty; + /** number of resolutions of x, y and z-axis */ + int numresolution[3]; + /** code-blocks width height & depth*/ + int cblk[3]; + /** code-block coding style */ + int cblksty; + /** 0: no ATK (only 9-7 or 5-3) 1: ATK defined WT*/ + int atk_wt[3]; + /** Arbitrary transformation kernel (15444-2)*/ + opj_atk_t *atk; + /** DWT identifier for x, y and z-axis (0:WT9-7 1:WT5-3 >1:WT-atk->index) */ + int dwtid[3]; + /** reversible/irreversible wavelet transfomation (0:irrev 1:reversible)*/ + int reversible; + /** quantisation style */ + int qntsty; + /** stepsizes used for quantization */ + opj_stepsize_t stepsizes[J3D_MAXBANDS]; + /** number of guard bits. Table A28 de 15444-1*/ + int numgbits; + /** Region Of Interest shift */ + int roishift; + /** precinct width heigth & depth*/ + int prctsiz[3][J3D_MAXRLVLS]; +} opj_tccp_t; + +/** +Tile coding parameters : coding/decoding parameters common to all tiles +(information like COD, COC in main header) +*/ +typedef struct opj_tcp { +/** 1 : first part-tile of a tile */ + int first; + /** coding style */ + int csty; + /** progression order */ + OPJ_PROG_ORDER prg; + /** number of layers */ + int numlayers; + /** multi-component transform identifier */ + int mct; + /** rates of layers */ + float rates[100]; + /** number of progression order changes */ + int numpocs; + /** indicates if a POC marker has been used O:NO, 1:YES */ + int POC; + /** progression order changes */ + opj_poc_t pocs[J3D_MAXRLVLS - 1]; + /** add fixed_quality */ + float distoratio[100]; + /** tile-component coding parameters */ + opj_tccp_t *tccps; +/** packet header store there for futur use in t2_decode_packet */ + unsigned char *ppt_data; + /** pointer remaining on the first byte of the first header if ppt is used */ + unsigned char *ppt_data_first; + /** If ppt == 1 --> there was a PPT marker for the present tile */ + int ppt; + /** used in case of multiple marker PPT (number of info already stored) */ + int ppt_store; + int ppt_len; +} opj_tcp_t; + +/** +Coding parameters +*/ +typedef struct opj_cp { +/** transform format 0: 2DWT, 1: 2D1P, 2: 3DWT, 3: 3RLS */ + OPJ_TRANSFORM transform_format; + /** entropy coding format 0: 2EB, 1: 3EB, 2: 2GR, 3: 3GR, 4: GRI*/ + OPJ_ENTROPY_CODING encoding_format; + /** allocation by rate/distortion */ + int disto_alloc; + /** allocation by fixed layer */ + int fixed_alloc; + /** add fixed_quality */ + int fixed_quality; + /** Rsiz: capabilities */ + int rsiz; + /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, volume is decoded to the full resolution */ + int reduce[3]; + /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */ + int layer; + /** 0 = no index || 1 = index */ + int index_on; + /** Big-Endian/Little-endian order */ + int bigendian; + /** XTOsiz */ + int tx0; + /** YTOsiz */ + int ty0; + /** ZTOsiz */ + int tz0; + /** XTsiz */ + int tdx; + /** YTsiz */ + int tdy; + /** ZTsiz */ + int tdz; + /** comment for coding */ + char *comment; + /** number of tiles in width, heigth and depth */ + int tw; + int th; + int tl; + /** ID number of the tiles present in the codestream */ + int *tileno; + /** size of the vector tileno */ + int tileno_size; + /** tile coding parameters */ + opj_tcp_t *tcps; + /** fixed layer */ + int *matrice; + + /** packet header store there for futur use in t2_decode_packet */ + unsigned char *ppm_data; + /** pointer remaining on the first byte of the first header if ppm is used */ + unsigned char *ppm_data_first; + /** if ppm == 1 --> there was a PPM marker for the present tile */ + int ppm; + /** use in case of multiple marker PPM (number of info already store) */ + int ppm_store; + /** use in case of multiple marker PPM (case on non-finished previous info) */ + int ppm_previous; + int ppm_len; +} opj_cp_t; + +/** +Information concerning a packet inside tile +*/ +typedef struct opj_packet_info { + /** start position */ + int start_pos; + /** end position */ + int end_pos; + /** distorsion introduced */ + double disto; +} opj_packet_info_t; + +/** +Index structure : information regarding tiles inside volume +*/ +typedef struct opj_tile_info { + /** value of thresh for each layer by tile cfr. Marcela */ + double *thresh; + /** number of tile */ + int num_tile; + /** start position */ + int start_pos; + /** end position of the header */ + int end_header; + /** end position */ + int end_pos; + /** precinct number for each resolution level (width, heigth and depth) */ + int prctno[3][J3D_MAXRLVLS]; + /** precinct size (in power of 2), in X for each resolution level */ + int prctsiz[3][J3D_MAXRLVLS]; + /** information concerning packets inside tile */ + opj_packet_info_t *packet; + + /** add fixed_quality */ + int nbpix; + /** add fixed_quality */ + double distotile; +} opj_tile_info_t; + +/** +Index structure +*/ +typedef struct opj_volume_info { + + /** transform format 0: 2DWT, 1: 2D1P, 2: 3DWT, 3: 3RLS */ + OPJ_TRANSFORM transform_format; + /** output file format 0: 2EB, 1: 3EB, 2: 2GR, 3: 3GR, 4: GRI*/ + OPJ_ENTROPY_CODING encoding_format; /** 0 = no index || 1 = index */ + int index_on; + /** 0 = wt 9-7 || 1 = wt 5-3 || >=2 wt atk defined */ + int dwtid[3]; + /** maximum distortion reduction on the whole volume (add for Marcela) */ + double D_max; + /** packet number */ + int num; + /** writing the packet in the index with t2_encode_packets */ + int index_write; + /** volume width, height and depth */ + int volume_w; + int volume_h; + int volume_l; + /** progression order */ + OPJ_PROG_ORDER prog; + /** tile size in x, y and z */ + int tile_x; + int tile_y; + int tile_z; + /** tile origin in x, y and z */ + int tile_Ox; + int tile_Oy; + int tile_Oz; + /** number of tiles in X, Y and Z */ + int tw; + int th; + int tl; + /** component numbers */ + int comp; + /** number of layer */ + int layer; + /** number of decomposition in X, Y and Z*/ + int decomposition[3]; + /** DC offset (15444-2) */ + int dcoffset; + /** main header position */ + int main_head_end; + /** codestream's size */ + int codestream_size; + /** information regarding tiles inside volume */ + opj_tile_info_t *tile; +} opj_volume_info_t; + +/** +JPEG-2000 codestream reader/writer +*/ +typedef struct opj_j3d { + /** codec context */ + opj_common_ptr cinfo; + /** locate in which part of the codestream the decoder is (main header, tile header, end) */ + int state; + /** number of the tile curently concern by coding/decoding */ + int curtileno; + /** locate the position of the end of the tile in the codestream, used to detect a truncated codestream (in j3d_read_sod) */ + unsigned char *eot; + /** locate the start position of the SOT marker of the current coded tile: */ + int sot_start; + /* after encoding the tile, a jump (in j3d_write_sod) is done to the SOT marker to store the value of its length. */ + int sod_start; + /** as the J3D-file is written in several parts during encoding, it enables to make the right correction in position return by cio_tell */ + int pos_correction; + /** array used to store the data of each tile */ + unsigned char **tile_data; + /** array used to store the length of each tile */ + int *tile_len; + + /** decompression only : store decoding parameters common to all tiles */ + opj_tcp_t *default_tcp; + /** pointer to the encoded / decoded volume */ + opj_volume_t *volume; + /** pointer to the coding parameters */ + opj_cp_t *cp; + /** helper used to write the index file */ + opj_volume_info_t *volume_info; + /** pointer to the byte i/o stream */ + opj_cio_t *cio; +} opj_j3d_t; + +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Creates a J3D decompression structure +@param cinfo Codec context info +@return Returns a handle to a J3D decompressor if successful, returns NULL otherwise +*/ +opj_j3d_t* j3d_create_decompress(opj_common_ptr cinfo); +/** +Destroy a J3D decompressor handle +@param j3d J3D decompressor handle to destroy +*/ +void j3d_destroy_decompress(opj_j3d_t *j3d); +/** +Setup the decoder decoding parameters using user parameters. +Decoding parameters are returned in j3d->cp. +@param j3d J3D decompressor handle +@param parameters decompression parameters +*/ +void j3d_setup_decoder(opj_j3d_t *j3d, opj_dparameters_t *parameters); +/** +Decode an volume from a JPEG-2000 codestream +@param j3d J3D decompressor handle +@param cio Input buffer stream +@return Returns a decoded volume if successful, returns NULL otherwise +*/ +opj_volume_t* j3d_decode(opj_j3d_t *j3d, opj_cio_t *cio); +/** +Decode an volume form a JPT-stream (JPEG 2000, JPIP) +@param j3d J3D decompressor handle +@param cio Input buffer stream +@return Returns a decoded volume if successful, returns NULL otherwise +*/ +opj_volume_t* j3d_decode_jpt_stream(opj_j3d_t *j3d, opj_cio_t *cio); +/** +Creates a J3D compression structure +@param cinfo Codec context info +@return Returns a handle to a J3D compressor if successful, returns NULL otherwise +*/ +opj_j3d_t* j3d_create_compress(opj_common_ptr cinfo); +/** +Destroy a J3D compressor handle +@param j3d J3D compressor handle to destroy +*/ +void j3d_destroy_compress(opj_j3d_t *j3d); +/** +Setup the encoder parameters using the current volume and using user parameters. +Coding parameters are returned in j3d->cp. +@param j3d J3D compressor handle +@param parameters compression parameters +@param volume input filled volume +*/ +void j3d_setup_encoder(opj_j3d_t *j3d, opj_cparameters_t *parameters, opj_volume_t *volume); +/** +Encode an volume into a JPEG-2000 codestream +@param j3d J3D compressor handle +@param cio Output buffer stream +@param volume Volume to encode +@param index Name of the index file if required, NULL otherwise +@return Returns true if successful, returns false otherwise +*/ +bool j3d_encode(opj_j3d_t *j3d, opj_cio_t *cio, opj_volume_t *volume, char *index); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __J3D_H */ diff --git a/src/lib/openjp3d/jp3d_lib.c b/src/lib/openjp3d/jp3d_lib.c new file mode 100755 index 00000000..4445e859 --- /dev/null +++ b/src/lib/openjp3d/jp3d_lib.c @@ -0,0 +1,76 @@ +/* + * 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. + */ + +#ifdef _WIN32 +#include +#else +#include +#include +#include +#endif /* _WIN32 */ +#include "opj_includes.h" + +double opj_clock() { +#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 /* _WIN32 */ +} + +void* opj_malloc( size_t size ) { + void *memblock = malloc(size); + if(memblock) { + memset(memblock, 0, size); + } + return memblock; +} + +void* opj_realloc( void *memblock, size_t size ) { + return realloc(memblock, size); +} + +void opj_free( void *memblock ) { + free(memblock); +} + + diff --git a/src/lib/openjp3d/jp3d_lib.h b/src/lib/openjp3d/jp3d_lib.h new file mode 100755 index 00000000..a2fb05ba --- /dev/null +++ b/src/lib/openjp3d/jp3d_lib.h @@ -0,0 +1,75 @@ +/* + * 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 __J3D_LIB_H +#define __J3D_LIB_H +/** +@file jp3d_lib.h +@brief Internal functions + +The functions in JP3D_LIB.C are internal utilities mainly used for memory management. +*/ + +/** @defgroup MISC MISC - Miscellaneous internal functions */ +/*@{*/ + +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Difference in successive opj_clock() calls tells you the elapsed time +@return Returns time in seconds +*/ +double opj_clock(); + +/** +Allocate a memory block with elements initialized to 0 +@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 ); + +/** +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 +*/ +void* opj_realloc( void *memblock, size_t size ); + +/** +Deallocates or frees a memory block. +@param memblock Previously allocated memory block to be freed +*/ +void opj_free( void *memblock ); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __J3D_LIB_H */ + diff --git a/src/lib/openjp3d/mct.c b/src/lib/openjp3d/mct.c new file mode 100755 index 00000000..e915e390 --- /dev/null +++ b/src/lib/openjp3d/mct.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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" + +/* */ +/* This table contains the norms of the basis function of the reversible MCT. */ +/* */ +static const double mct_norms[3] = { 1.732, .8292, .8292 }; + +/* */ +/* This table contains the norms of the basis function of the irreversible MCT. */ +/* */ +static const double mct_norms_real[3] = { 1.732, 1.805, 1.573 }; + +/* */ +/* Foward reversible MCT. */ +/* */ +void mct_encode(int *c0, int *c1, int *c2, int n) { + int i; + for (i = 0; i < n; i++) { + int r, g, b, y, u, v; + r = c0[i]; + g = c1[i]; + b = c2[i]; + y = (r + (g << 1) + b) >> 2; + u = b - g; + v = r - g; + c0[i] = y; + c1[i] = u; + c2[i] = v; + } +} + +/* */ +/* Inverse reversible MCT. */ +/* */ +void mct_decode(int *c0, int *c1, int *c2, int n) { + int i; + for (i = 0; i < n; i++) { + int y, u, v, r, g, b; + y = c0[i]; + u = c1[i]; + v = c2[i]; + g = y - ((u + v) >> 2); + r = v + g; + b = u + g; + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} + +/* */ +/* Get norm of basis function of reversible MCT. */ +/* */ +double mct_getnorm(int compno) { + return mct_norms[compno]; +} + +/* */ +/* Foward irreversible MCT. */ +/* */ +void mct_encode_real(int *c0, int *c1, int *c2, int n) { + int i; + for (i = 0; i < n; i++) { + int r, g, b, y, u, v; + r = c0[i]; + g = c1[i]; + b = c2[i]; + y = fix_mul(r, 2449) + fix_mul(g, 4809) + fix_mul(b, 934); + u = -fix_mul(r, 1382) - fix_mul(g, 2714) + fix_mul(b, 4096); + 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(int *c0, int *c1, int *c2, int n) { + int i; + for (i = 0; i < n; i++) { + int y, u, v, r, g, b; + y = c0[i]; + u = c1[i]; + v = c2[i]; + r = y + fix_mul(v, 11485); + g = y - fix_mul(u, 2819) - fix_mul(v, 5850); + b = y + fix_mul(u, 14516); + c0[i] = r; + c1[i] = g; + c2[i] = b; + } +} + +/* */ +/* Get norm of basis function of irreversible MCT. */ +/* */ +double mct_getnorm_real(int compno) { + return mct_norms_real[compno]; +} diff --git a/src/lib/openjp3d/mct.h b/src/lib/openjp3d/mct.h new file mode 100755 index 00000000..0b8edb7b --- /dev/null +++ b/src/lib/openjp3d/mct.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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. +*/ + +/** @defgroup MCT MCT - Implementation of a multi-component transform */ +/*@{*/ + +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +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(int *c0, int *c1, int *c2, int 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(int *c0, int *c1, int *c2, int 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 +*/ +double mct_getnorm(int 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(int *c0, int *c1, int *c2, int 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(int *c0, int *c1, int *c2, int 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 +*/ +double mct_getnorm_real(int compno); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __MCT_H */ diff --git a/src/lib/openjp3d/mqc.c b/src/lib/openjp3d/mqc.c new file mode 100755 index 00000000..12ac90d6 --- /dev/null +++ b/src/lib/openjp3d/mqc.c @@ -0,0 +1,548 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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 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); +/** +Exchange MPS with LPS +@param mqc MQC handle +@return +*/ +static int mqc_mpsexchange(opj_mqc_t *mqc); +/** +Exchange LPS with MPS +@param mqc MQC handle +@return +*/ +static int 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) { + unsigned int tempc = mqc->c + mqc->a; + mqc->c |= 0xffff; + if (mqc->c >= tempc) { + mqc->c -= 0x8000; + } +} + +static int mqc_mpsexchange(opj_mqc_t *mqc) { + int 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 int mqc_lpsexchange(opj_mqc_t *mqc) { + int 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) { + unsigned int 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() { + 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); + } +} + +int mqc_numbytes(opj_mqc_t *mqc) { + return mqc->bp - mqc->start; +} + +void mqc_init_enc(opj_mqc_t *mqc, unsigned char *bp) { + mqc_setcurctx(mqc, 0); + mqc->a = 0x8000; + mqc->c = 0; + mqc->bp = bp - 1; + mqc->ct = 12; + if (*mqc->bp == 0xff) { + mqc->ct = 13; + } + mqc->start = bp; +} + +void mqc_setcurctx(opj_mqc_t *mqc, int ctxno) { + mqc->curctx = &mqc->ctxs[ctxno]; +} + +void mqc_encode(opj_mqc_t *mqc, int 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, int 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; + } +} + +int mqc_bypass_flush_enc(opj_mqc_t *mqc) { + unsigned char 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, 18, 0, 46); + mqc_setstate(mqc, 0, 0, 3); + mqc_setstate(mqc, 1, 0, 4); +} + +void mqc_reset_enc_3(opj_mqc_t *mqc) { + mqc_resetstates(mqc); + mqc_setstate(mqc, T1_3D_CTXNO_UNI, 0, 46); + mqc_setstate(mqc, T1_3D_CTXNO_AGG, 0, 3); + mqc_setstate(mqc, T1_3D_CTXNO_ZC, 0, 4); +} + +int mqc_restart_enc(opj_mqc_t *mqc) { + int correction = 1; + + /* */ + int 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) { + int 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) { + int i; + mqc_setcurctx(mqc, 18); + + for (i = 1; i < 5; i++) { + mqc_encode(mqc, i % 2); + } +} + +void mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int 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; +} + +int mqc_decode(opj_mqc_t *mqc) { + int 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 d; +} + +void mqc_resetstates(opj_mqc_t *mqc) { + int i; + for (i = 0; i < MQC_NUMCTXS; i++) { + mqc->ctxs[i] = mqc_states; + } +} + +void mqc_setstate(opj_mqc_t *mqc, int ctxno, int msb, int prob) { + mqc->ctxs[ctxno] = &mqc_states[msb + (prob << 1)]; +} + + diff --git a/src/lib/openjp3d/mqc.h b/src/lib/openjp3d/mqc.h new file mode 100755 index 00000000..90253356 --- /dev/null +++ b/src/lib/openjp3d/mqc.h @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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. +*/ + +/** @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) */ + unsigned int qeval; + /** the Most Probable Symbol (0 or 1) */ + int 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 { + unsigned int c; + unsigned int a; + unsigned int ct; + unsigned char *bp; + unsigned char *start; + unsigned char *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(); +/** +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 +*/ +int 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, int ctxno, int msb, int 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, unsigned char *bp); +/** +Set the current context used for coding/decoding +@param mqc MQC handle +@param ctxno Number that identifies the context +*/ +void mqc_setcurctx(opj_mqc_t *mqc, int 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, int 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, int d); +/** +BYPASS mode switch, flush operation +

Not fully implemented and tested !!

+@param mqc MQC handle +@return Returns 1 (always) +*/ +int mqc_bypass_flush_enc(opj_mqc_t *mqc); +/** +RESET mode switch +@param mqc MQC handle +*/ +void mqc_reset_enc(opj_mqc_t *mqc); +/** +RESET mode switch +@param mqc MQC handle +*/ +void mqc_reset_enc_3(opj_mqc_t *mqc); +/** +RESTART mode switch (TERMALL) +@param mqc MQC handle +@return Returns 1 (always) +*/ +int 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, unsigned char *bp, int len); +/** +Decode a symbol +@param mqc MQC handle +@return Returns the decoded symbol (0 or 1) +*/ +int mqc_decode(opj_mqc_t *mqc); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __MQC_H */ diff --git a/src/lib/openjp3d/openjp3d.c b/src/lib/openjp3d/openjp3d.c new file mode 100755 index 00000000..ab2744e1 --- /dev/null +++ b/src/lib/openjp3d/openjp3d.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006, Mónica Díez García, Image Processing Laboratory, University of Valladolid, Spain + * 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" +#define JP3D_VERSION "1.3.0" +/* ---------------------------------------------------------------------- */ +#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() { + return JP3D_VERSION; +} +opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format) { + opj_dinfo_t *dinfo = (opj_dinfo_t*)opj_malloc(sizeof(opj_dinfo_t)); + if(!dinfo) return NULL; + dinfo->is_decompressor = true; + switch(format) { + case CODEC_J3D: + case CODEC_J2K: + /* get a J3D decoder handle */ + dinfo->j3d_handle = (void*)j3d_create_decompress((opj_common_ptr)dinfo); + if(!dinfo->j3d_handle) { + opj_free(dinfo); + return NULL; + } + break; + default: + opj_free(dinfo); + return NULL; + } + + dinfo->codec_format = format; + + return dinfo; +} + +void OPJ_CALLCONV opj_destroy_decompress(opj_dinfo_t *dinfo) { + if(dinfo) { + /* destroy the codec */ + if(dinfo->codec_format != CODEC_UNKNOWN) { + j3d_destroy_decompress((opj_j3d_t*)dinfo->j3d_handle); + } + /* destroy the decompressor */ + opj_free(dinfo); + } +} + +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] = 0; + parameters->cp_reduce[1] = 0; + parameters->cp_reduce[2] = 0; + parameters->bigendian = 0; + + parameters->decod_format = -1; + parameters->cod_format = -1; + } +} + +void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *parameters) { + if(dinfo && parameters) { + if (dinfo->codec_format != CODEC_UNKNOWN) { + j3d_setup_decoder((opj_j3d_t*)dinfo->j3d_handle, parameters); + } + } +} + +opj_volume_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio) { + if(dinfo && cio) { + if (dinfo->codec_format != CODEC_UNKNOWN) { + return j3d_decode((opj_j3d_t*)dinfo->j3d_handle, cio); + } + } + + return NULL; +} + +opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format) { + opj_cinfo_t *cinfo = (opj_cinfo_t*)opj_malloc(sizeof(opj_cinfo_t)); + if(!cinfo) return NULL; + cinfo->is_decompressor = false; + switch(format) { + case CODEC_J3D: + case CODEC_J2K: + /* get a J3D coder handle */ + cinfo->j3d_handle = (void*)j3d_create_compress((opj_common_ptr)cinfo); + if(!cinfo->j3d_handle) { + opj_free(cinfo); + return NULL; + } + break; + default: + opj_free(cinfo); + return NULL; + } + + cinfo->codec_format = format; + + return cinfo; +} + +void OPJ_CALLCONV opj_destroy_compress(opj_cinfo_t *cinfo) { + if(cinfo) { + /* destroy the codec */ + if (cinfo->codec_format != CODEC_UNKNOWN) { + j3d_destroy_compress((opj_j3d_t*)cinfo->j3d_handle); + } + /* destroy the decompressor */ + opj_free(cinfo); + } +} + +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->numresolution[0] = 3; + parameters->numresolution[1] = 3; + parameters->numresolution[2] = 1; + parameters->cblock_init[0] = 64; + parameters->cblock_init[1] = 64; + parameters->cblock_init[2] = 64; + parameters->prog_order = LRCP; + parameters->roi_compno = -1; /* no ROI */ + parameters->atk_wt[0] = 1; /* 5-3 WT */ + parameters->atk_wt[1] = 1; /* 5-3 WT */ + parameters->atk_wt[2] = 1; /* 5-3 WT */ + parameters->irreversible = 0; + parameters->subsampling_dx = 1; + parameters->subsampling_dy = 1; + parameters->subsampling_dz = 1; + + parameters->decod_format = -1; + parameters->cod_format = -1; + parameters->encoding_format = ENCOD_2EB; + parameters->transform_format = TRF_2D_DWT; + } +} + +void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_volume_t *volume) { + if(cinfo && parameters && volume) { + if (cinfo->codec_format != CODEC_UNKNOWN) { + j3d_setup_encoder((opj_j3d_t*)cinfo->j3d_handle, parameters, volume); + } + } +} + +bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_volume_t *volume, char *index) { + if(cinfo && cio && volume) { + if (cinfo->codec_format != CODEC_UNKNOWN) { + return j3d_encode((opj_j3d_t*)cinfo->j3d_handle, cio, volume, index); + } + } + + return false; +} + + diff --git a/src/lib/openjp3d/openjp3d.h b/src/lib/openjp3d/openjp3d.h new file mode 100755 index 00000000..e6829d91 --- /dev/null +++ b/src/lib/openjp3d/openjp3d.h @@ -0,0 +1,713 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyright (c) 2006, Mónica Díez García, Image Processing Laboratory, University of Valladolid, Spain + * 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 +========================================================== +*/ + +#if defined(OPJ_STATIC) || !defined(_WIN32) +#define OPJ_API +#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, wheras 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 */ + +#ifndef __cplusplus +#if defined(HAVE_STDBOOL_H) +/* +The C language implementation does correctly provide the standard header +file "stdbool.h". + */ +#include +#else +/* +The C language implementation does not provide the standard header file +"stdbool.h" as required by ISO/IEC 9899:1999. Try to compensate for this +braindamage below. +*/ +#if !defined(bool) +#define bool int +#endif +#if !defined(true) +#define true 1 +#endif +#if !defined(false) +#define false 0 +#endif +#endif +#endif /* __cplusplus */ + +/* +========================================================== + Useful constant definitions +========================================================== +*/ +#ifndef MAX_SLICES +#define MAX_SLICES 300 /**< Maximum allowed size for slices */ +#endif /* MAX_PATH */ + +#ifndef MAX_PATH +#define MAX_PATH 260 /**< Maximum allowed size for filenames */ +#endif /* MAX_PATH */ + +#define J3D_MAXRLVLS 32 /**< Number of maximum resolution level authorized */ +#define J3D_MAXBANDS (7*J3D_MAXRLVLS + 1) /**< Number of maximum sub-band linked to number of resolution level */ + +#define TINY 1.0E-20 +/* +========================================================== + enum definitions +========================================================== +*/ + +#define J2K_CFMT 0 +#define J3D_CFMT 1 +#define LSE_CFMT 2 + +#define BIN_DFMT 0 +#define PGX_DFMT 1 +#define IMG_DFMT 2 +/* ----------------------------------------------------------------------- */ + +/** Progression order */ +typedef enum PROG_ORDER { +/**< place-holder */ + PROG_UNKNOWN = -1, +/**< layer-resolution-component-precinct order */ + LRCP = 0, +/**< resolution-layer-component-precinct order */ + RLCP = 1, +/**< resolution-precinct-component-layer order */ + RPCL = 2, +/**< precinct-component-resolution-layer order */ + PCRL = 3, +/**< component-precinct-resolution-layer order */ + CPRL = 4 +} OPJ_PROG_ORDER; + +/** +Supported volume color spaces +*/ +typedef enum COLOR_SPACE { +/**< place-holder */ + CLRSPC_UNKNOWN = -1, +/**< sRGB */ + CLRSPC_SRGB = 1, +/**< grayscale */ + CLRSPC_GRAY = 2, +/**< YUV */ + CLRSPC_SYCC = 3 +} OPJ_COLOR_SPACE; + +/** +Supported codec +*/ +typedef enum CODEC_FORMAT { + /**< place-holder */ + CODEC_UNKNOWN = -1, +/**< JPEG-2000 codestream : read/write */ + CODEC_J2K = 0, +/**< JPEG-2000 Part 10 file format : read/write */ + CODEC_J3D = 1 +} OPJ_CODEC_FORMAT; + +/** +Supported entropy coding algorithms +*/ +typedef enum ENTROPY_CODING { +/**< place-holder */ + ENCOD_UNKNOWN = -1, +/**< 2D EBCOT encoding */ + ENCOD_2EB = 0, +/**< 3D EBCOT encoding */ + ENCOD_3EB = 1, +/**< Golomb-Rice coding with 2D context */ + ENCOD_2GR = 2, +/**< Golomb-Rice coding with 3D context */ + ENCOD_3GR = 3 +} OPJ_ENTROPY_CODING; + +/** +Supported transforms +*/ +typedef enum TRANSFORM { +/**< place-holder */ + TRF_UNKNOWN = -1, +/**< 2D DWT, no transform in axial dim */ + TRF_2D_DWT = 0, +/**< 3D DWT */ + TRF_3D_DWT = 1, +/**< 3D prediction*/ + TRF_3D_RLS = 2, + TRF_3D_LSE = 3 +} OPJ_TRANSFORM; +/* +========================================================== + event manager typedef definitions +========================================================== +*/ + +/** +Callback function prototype for events +@param msg Event message +@param client_data +*/ +typedef void (*opj_msg_callback) (const char *msg, void *client_data); + +/** +Message handler object +used for +
    +
  • Error messages +
  • Warning messages +
  • Debugging messages +
+*/ +typedef struct opj_event_mgr { + /** 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; + + +/* +========================================================== + codec typedef definitions +========================================================== +*/ + +/** +Progression order changes +*/ +typedef struct opj_poc { + int resno0, compno0; + int layno1, resno1, compno1; + OPJ_PROG_ORDER prg; + int tile; + char progorder[4]; +} opj_poc_t; + + +/** +Compression parameters +*/ +typedef struct opj_cparameters { +/** size of tile: tile_size_on = false (not in argument) or = true (in argument) */ + bool tile_size_on; +/** XTOsiz */ + int cp_tx0; +/** YTOsiz */ + int cp_ty0; +/** ZTOsiz */ + int cp_tz0; + +/** XTsiz */ + int cp_tdx; +/** YTsiz */ + int cp_tdy; +/** ZTsiz */ + int cp_tdz; + +/** allocation by rate/distortion */ + int cp_disto_alloc; +/** allocation by fixed layer */ + int cp_fixed_alloc; +/** add fixed_quality */ + int cp_fixed_quality; +/** fixed layer */ + int *cp_matrice; +/** number of layers */ + int tcp_numlayers; +/** rates for successive layers */ + float tcp_rates[100]; +/** psnr's for successive layers */ + float tcp_distoratio[100]; +/** comment for coding */ + char *cp_comment; +/** csty : coding style */ + int csty; +/** DC offset (DCO) */ + int dcoffset; +/** progression order (default LRCP) */ + OPJ_PROG_ORDER prog_order; +/** progression order changes */ + opj_poc_t POC[J3D_MAXRLVLS-1]; +/** number of progression order changes (POC), default to 0 */ + int numpocs; + +/** number of resolutions */ + int numresolution[3]; +/** initial code block width, height and depth, default to 64 */ + int cblock_init[3]; +/** mode switch (1=BYPASS(LAZY) 2=RESET 4=RESTART(TERMALL) 8=VSC 16=ERTERM(SEGTERM) 32=SEGMARK(SEGSYM)) */ + int mode; + +/** 1 : use the irreversible DWT 9-7, 0 : use lossless compression (default) */ + int irreversible; +/** WT from ATK, default to 0 (false), no of atk used */ + int atk_wt[3]; +/** 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 prct_init[3][J3D_MAXRLVLS]; + +/** transform format 0: 0: 2DWT, 1: 2D1P, 2: 3DWT, 3: 3RLS */ + OPJ_TRANSFORM transform_format; +/** output file format 0: 2EB, 1: 3EB, 2: 2GR, 3: 3GR, 4: GRI */ + OPJ_ENTROPY_CODING encoding_format; + + /**@name command line encoder parameters (not used inside the library) */ + /*@{*/ + char infile[MAX_PATH]; /** input file name */ + char outfile[MAX_PATH]; /** output file name */ + char imgfile[MAX_PATH]; /** IMG file name for BIN volumes*/ + int index_on; /** creation of an index file, default to 0 (false) */ + char index[MAX_PATH]; /** index file name */ + + int volume_offset_x0; /** subvolume encoding: origin volume offset in x, y and z direction */ + int volume_offset_y0; + int volume_offset_z0; + + int subsampling_dx; /** subsampling value for dx */ + int subsampling_dy; + int subsampling_dz; + + int decod_format; /** input file format 0: BIN, 1: PGX */ + int cod_format; /** output file format 0: JP3D */ + /*@}*/ +} opj_cparameters_t; + +/** +Decompression parameters +*/ +typedef struct opj_dparameters { +/** Set the number of highest resolution levels to be discarded. if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, volume is decoded to the full resolution */ + int cp_reduce[3]; +/** Set the maximum number of quality layers to decode. if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */ + int cp_layer; + int bigendian; + + /**@name command line encoder parameters (not used inside the library) */ + /*@{*/ +/** input file name */ + char infile[MAX_PATH]; +/** output file name */ + char outfile[MAX_PATH]; +/** IMG file name for BIN volumes*/ + char imgfile[MAX_PATH]; +/** Original file name for PSNR measures*/ + char original[MAX_PATH]; +/** input file format 0: J2K, 1: JP3D */ + int decod_format; +/** input file format 0: BIN, 1: PGM */ + int cod_format; +/** original file format 0: BIN, 1: PGM */ + int orig_format; + /*@}*/ +} opj_dparameters_t; + +/** Common fields between JPEG-2000 compression and decompression master structs. */ +#define opj_common_fields \ + opj_event_mgr_t *event_mgr; /**< pointer to the event manager */\ + void * client_data; /**< Available for use by application */\ + bool is_decompressor; /**< So common code can tell which is which */\ + OPJ_CODEC_FORMAT codec_format; /**< selected codec */\ + OPJ_ENTROPY_CODING encoding_format; /**< selected entropy coding */\ + OPJ_TRANSFORM transform_format; /**< selected transform */\ + void *j3d_handle /**< pointer to the J3D codec */ + +/* Routines that are to be used by both halves of the library are declared + * to receive a pointer to this structure. There are no actual instances of + * opj_common_struct_t, only of opj_cinfo_t and opj_dinfo_t. + */ +typedef struct opj_common_struct { + opj_common_fields; /* Fields common to both master struct types */ + /* Additional fields follow in an actual opj_cinfo_t or + * opj_dinfo_t. All three structs must agree on these + * initial fields! (This would be a lot cleaner in C++.) + */ +} opj_common_struct_t; + +typedef opj_common_struct_t * opj_common_ptr; + +/** +Compression context info +*/ +typedef struct opj_cinfo { + /** Fields shared with opj_dinfo_t */ + opj_common_fields; + /* other specific fields go here */ +} opj_cinfo_t; + +/** +Decompression context info +*/ +typedef struct opj_dinfo { + /** Fields shared with opj_cinfo_t */ + opj_common_fields; + /* other specific fields go here */ +} opj_dinfo_t; + +/* +========================================================== + I/O stream typedef definitions +========================================================== +*/ + +/* + * Stream open flags. + */ +/** The stream was opened for reading. */ +#define OPJ_STREAM_READ 0x0001 +/** The stream was opened for writing. */ +#define OPJ_STREAM_WRITE 0x0002 + +/** +Byte input-output stream (CIO) +*/ +typedef struct opj_cio { +/** codec context */ + opj_common_ptr cinfo; +/** open mode (read/write) either OPJ_STREAM_READ or OPJ_STREAM_WRITE */ + int openmode; +/** pointer to the start of the buffer */ + unsigned char *buffer; +/** buffer size in bytes */ + int length; +/** pointer to the start of the stream */ + unsigned char *start; +/** pointer to the end of the stream */ + unsigned char *end; +/** pointer to the current position */ + unsigned char *bp; +} opj_cio_t; + +/* +========================================================== + volume typedef definitions +========================================================== +*/ + +/** +Defines a single volume component +*/ +typedef struct opj_volume_comp { +/** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */ + int dx; +/** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */ + int dy; +/** ZRsiz: vertical separation of a sample of ith component with respect to the reference grid */ + int dz; +/** data width */ + int w; + /** data height */ + int h; + /** data length : no of slices */ + int l; + /** x component offset compared to the whole volume */ + int x0; + /** y component offset compared to the whole volume */ + int y0; + /** z component offset compared to the whole volume */ + int z0; + /** precision */ + int prec; + /** volume depth in bits */ + int bpp; + /** DC offset (15444-2) */ + int dcoffset; + /** signed (1) / unsigned (0) */ + int sgnd; + /** BE byte order (1) / LE byte order (0) */ + int bigendian; + /** number of decoded resolution */ + int resno_decoded[3]; + /** number of division by 2 of the out volume compared to the original size of volume */ + int factor[3]; + /** volume component data */ + int *data; +} opj_volume_comp_t; + +/** +Defines volume data and characteristics +*/ +typedef struct opj_volume { +/** XOsiz: horizontal offset from the origin of the reference grid to the left side of the volume area */ + int x0; +/** YOsiz: vertical offset from the origin of the reference grid to the top side of the volume area */ + int y0; +/** ZOsiz: vertical offset from the origin of the reference grid to the top side of the volume area */ + int z0; +/** Xsiz: width of the reference grid */ + int x1; +/** Ysiz: height of the reference grid */ + int y1; +/** Zsiz: length of the reference grid */ + int z1; +/** number of components in the volume */ + int numcomps; +/** number of slices in the volume */ + int numslices; +/** color space: sRGB, Greyscale or YUV */ + OPJ_COLOR_SPACE color_space; +/** volume components */ + opj_volume_comp_t *comps; +} opj_volume_t; + +/** +Component parameters structure used by the opj_volume_create function +*/ +typedef struct opj_volume_comptparm { + /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */ + int dx; + /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */ + int dy; + /** ZRsiz: axial separation of a sample of ith component with respect to the reference grid */ + int dz; + /** data width */ + int w; + /** data height */ + int h; + /** data length */ + int l; + /** x component offset compared to the whole volume */ + int x0; + /** y component offset compared to the whole volume */ + int y0; + /** z component offset compared to the whole volume */ + int z0; + /** precision */ + int prec; + /** volume depth in bits */ + int bpp; + /** signed (1) / unsigned (0) */ + int sgnd; + /** DC offset*/ + int dcoffset; + /** BE byte order (1) / LE byte order (0) */ + int bigendian; +} opj_volume_cmptparm_t; + +#ifdef __cplusplus +extern "C" { +#endif + + +/* +========================================================== + openjpeg version +========================================================== +*/ + +OPJ_API const char * OPJ_CALLCONV opj_version(); + +/* +========================================================== + volume functions definitions +========================================================== +*/ + +/** +Create an volume +@param numcmpts number of components +@param cmptparms components parameters +@param clrspc volume color space +@return returns a new volume structure if successful, returns NULL otherwise +*/ +OPJ_API opj_volume_t* OPJ_CALLCONV opj_volume_create(int numcmpts, opj_volume_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc); + +/** +Deallocate any resources associated with an volume +@param volume volume to be destroyed +*/ +OPJ_API void OPJ_CALLCONV opj_volume_destroy(opj_volume_t *volume); + +/* +========================================================== + stream functions definitions +========================================================== +*/ + +/** +Open and allocate a memory stream for read / write. +On reading, the user must provide a buffer containing encoded data. The buffer will be +wrapped by the returned CIO handle. +On writing, buffer parameters must be set to 0: a buffer will be allocated by the library +to contain encoded data. +@param cinfo Codec context info +@param buffer Reading: buffer address. Writing: NULL +@param length Reading: buffer length. Writing: 0 +@return Returns a CIO handle if successful, returns NULL otherwise +*/ +OPJ_API opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length); + +/** +Close and free a CIO handle +@param cio CIO handle to free +*/ +OPJ_API void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio); + +/** +Get position in byte stream +@param cio CIO handle +@return Returns the position in bytes +*/ +OPJ_API int OPJ_CALLCONV cio_tell(opj_cio_t *cio); +/** +Set position in byte stream +@param cio CIO handle +@param pos Position, in number of bytes, from the beginning of the stream +*/ +OPJ_API void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos); + +/* +========================================================== + event manager functions definitions +========================================================== +*/ + +OPJ_API opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context); + +/* +========================================================== + codec functions definitions +========================================================== +*/ +/** +Creates a J3D decompression structure +@param format Decoder to select +@return Returns a handle to a decompressor if successful, returns NULL otherwise +*/ +OPJ_API opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format); +/** +Destroy a decompressor handle +@param dinfo decompressor handle to destroy +*/ +OPJ_API void OPJ_CALLCONV opj_destroy_decompress(opj_dinfo_t *dinfo); +/** +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 decoding parameters using user parameters. +Decoding parameters are returned in j3d->cp. +@param dinfo decompressor handle +@param parameters decompression parameters +*/ +OPJ_API void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *parameters); +/** +Decode an volume from a JPEG-2000 codestream +@param dinfo decompressor handle +@param cio Input buffer stream +@return Returns a decoded volume if successful, returns NULL otherwise +*/ +OPJ_API opj_volume_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio); +/** +Creates a J3D/JP2 compression structure +@param format Coder to select +@return Returns a handle to a compressor if successful, returns NULL otherwise +*/ +OPJ_API opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format); +/** +Destroy a compressor handle +@param cinfo compressor handle to destroy +*/ +OPJ_API void OPJ_CALLCONV opj_destroy_compress(opj_cinfo_t *cinfo); +/** +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 volume +
  • 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 volume and using user parameters. +@param cinfo compressor handle +@param parameters compression parameters +@param volume input filled volume +*/ +OPJ_API void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_volume_t *volume); +/** +Encode an volume into a JPEG-2000 codestream +@param cinfo compressor handle +@param cio Output buffer stream +@param volume Volume to encode +@param index Name of the index file if required, NULL otherwise +@return Returns true if successful, returns false otherwise +*/ +OPJ_API bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_volume_t *volume, char *index); + +#ifdef __cplusplus +} +#endif + +#endif /* OPENJPEG_H */ diff --git a/src/lib/openjp3d/opj_includes.h b/src/lib/openjp3d/opj_includes.h new file mode 100755 index 00000000..40fecfc3 --- /dev/null +++ b/src/lib/openjp3d/opj_includes.h @@ -0,0 +1,81 @@ +/* + * 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_INCLUDES_H +#define OPJ_INCLUDES_H + +/* + ========================================================== + Standard includes used by the library + ========================================================== +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* + ========================================================== + OpenJPEG interface + ========================================================== + */ +#include "openjp3d.h" + +/* + ========================================================== + OpenJPEG modules + ========================================================== +*/ + +#include "jp3d_lib.h" +#include "event.h" +#include "cio.h" + +#include "volume.h" +#include "jp3d.h" + +#include "mqc.h" +#include "raw.h" +#include "bio.h" +#include "tgt.h" +#include "tcd.h" +#include "t1.h" +#include "t1_3d.h" +#include "dwt.h" +#include "pi.h" +#include "t2.h" +#include "mct.h" +#include "int.h" +#include "fix.h" + +//#include "pred.h" +//#include "golomb.h" + +#endif /* OPJ_INCLUDES_H */ diff --git a/src/lib/openjp3d/pi.c b/src/lib/openjp3d/pi.c new file mode 100755 index 00000000..f9b8a963 --- /dev/null +++ b/src/lib/openjp3d/pi.c @@ -0,0 +1,630 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyright (c) 2006, Mónica Díez, LPI-UVA, Spain + * 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 PI PI - Implementation of a packet iterator */ +/*@{*/ + +/** @name Funciones locales */ +/*@{*/ + +/** +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); + +/*@}*/ + +/*@}*/ + +/* +========================================================== + local functions +========================================================== +*/ + +static bool pi_next_lrcp(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + res = &comp->resolutions[pi->resno]; + goto LABEL_SKIP; + } else { + pi->first = 0; + } + + for (pi->layno = 0; 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->numresolution[0]) { + continue; + } + res = &comp->resolutions[pi->resno]; + //for (pi->precno = 0; pi->precno < (res->prctno[0] * res->prctno[1]); pi->precno++) { + for (pi->precno = 0; pi->precno < (res->prctno[0] * res->prctno[1] * res->prctno[2]); pi->precno++) { + index = pi->layno * pi->step_l + + pi->resno * pi->step_r + + pi->compno * pi->step_c + + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return true; + } +LABEL_SKIP:; + + } + } + } + } + + return false; +} + +static bool pi_next_rlcp(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 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 = 0; 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->numresolution[0]) { + continue; + } + res = &comp->resolutions[pi->resno]; + //for (pi->precno = 0; pi->precno < (res->prctno[0] * res->prctno[1]); pi->precno++) { + for (pi->precno = 0; pi->precno < (res->prctno[0] * res->prctno[1] * res->prctno[2]); pi->precno++) { + index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p; + if (!pi->include[index]) { + pi->include[index] = 1; + return true; + } +LABEL_SKIP:; + } + } + } + } + + return false; +} + +static bool pi_next_rpcl(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 0; + + if (!pi->first) { + goto LABEL_SKIP; + } else { + int 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->numresolution[0]; resno++) { + int dx, dy,dz; + res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolution[0] - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolution[1] - 1 - resno)); + dz = comp->dz * (1 << (res->pdz + comp->numresolution[2] - 1 - resno)); + pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); + pi->dz = !pi->dz ? dz : int_min(pi->dz, dz); + } + } + } + + for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) { + for (pi->z = pi->tz0; pi->z < pi->tz1; pi->z += pi->dz - (pi->z % pi->dz)) { + for (pi->y = pi->ty0; pi->y < pi->ty1; pi->y += pi->dy - (pi->y % pi->dy)) { + for (pi->x = pi->tx0; pi->x < pi->tx1; pi->x += pi->dx - (pi->x % pi->dx)) { + for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) { + int levelnox, levelnoy, levelnoz; + int trx0, try0, trz0; + int trx1, try1, trz1; + int rpx, rpy, rpz; + int prci, prcj, prck; + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolution[0]) { + continue; + } + res = &comp->resolutions[pi->resno]; + levelnox = comp->numresolution[0] - 1 - pi->resno; + levelnoy = comp->numresolution[1] - 1 - pi->resno; + levelnoz = comp->numresolution[2] - 1 - pi->resno; + trx0 = int_ceildiv(pi->tx0, comp->dx << levelnox); + try0 = int_ceildiv(pi->ty0, comp->dy << levelnoy); + trz0 = int_ceildiv(pi->tz0, comp->dz << levelnoz); + trx1 = int_ceildiv(pi->tx1, comp->dx << levelnox); + try1 = int_ceildiv(pi->ty1, comp->dy << levelnoy); + trz1 = int_ceildiv(pi->tz1, comp->dz << levelnoz); + rpx = res->pdx + levelnox; + rpy = res->pdy + levelnoy; + rpz = res->pdz + levelnoz; + if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && (trx0 << levelnox) % (1 << rpx)))) { + continue; + } + if ((!(pi->y % (comp->dy << rpy) == 0) || (pi->y == pi->ty0 && (try0 << levelnoy) % (1 << rpx)))) { + continue; + } + if ((!(pi->z % (comp->dz << rpz) == 0) || (pi->z == pi->tz0 && (trz0 << levelnoz) % (1 << rpx)))) { + continue; + } + if ((res->prctno[0]==0)||(res->prctno[1]==0)||(res->prctno[2]==0)) continue; + + if ((trx0==trx1)||(try0==try1)||(trz0==trz1)) continue; + + prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelnox), res->pdx) + - int_floordivpow2(trx0, res->pdx); + prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelnoy), res->pdy) + - int_floordivpow2(try0, res->pdy); + prck = int_floordivpow2(int_ceildiv(pi->z, comp->dz << levelnoz), res->pdz) + - int_floordivpow2(trz0, res->pdz); + pi->precno = prci + prcj * res->prctno[0] + prck * res->prctno[0] * res->prctno[1]; + for (pi->layno = 0; 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 (!pi->include[index]) { + pi->include[index] = 1; + return true; + } + LABEL_SKIP:; + } + } + } + } + } + } + + return false; +} + +static bool pi_next_pcrl(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 0; + + if (!pi->first) { + comp = &pi->comps[pi->compno]; + goto LABEL_SKIP; + } else { + int compno, resno; + pi->first = 0; + pi->dx = 0; + pi->dy = 0; + pi->dz = 0; + for (compno = 0; compno < pi->numcomps; compno++) { + comp = &pi->comps[compno]; + for (resno = 0; resno < comp->numresolution[0]; resno++) { + int dx, dy, dz; + res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolution[0] - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolution[1] - 1 - resno)); + dz = comp->dz * (1 << (res->pdy + comp->numresolution[2] - 1 - resno)); + pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); + pi->dz = !pi->dz ? dz : int_min(pi->dz, dz); + } + } + } + +for (pi->z = pi->tz0; pi->z < pi->tz1; pi->z += pi->dz - (pi->z % pi->dz)) { + for (pi->y = pi->ty0; pi->y < pi->ty1; pi->y += pi->dy - (pi->y % pi->dy)) { + for (pi->x = pi->tx0; pi->x < pi->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 < int_min(pi->poc.resno1, comp->numresolution[0]); pi->resno++) { + int levelnox, levelnoy, levelnoz; + int trx0, try0, trz0; + int trx1, try1, trz1; + int rpx, rpy, rpz; + int prci, prcj, prck; + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolution[0]) { + continue; + } + res = &comp->resolutions[pi->resno]; + levelnox = comp->numresolution[0] - 1 - pi->resno; + levelnoy = comp->numresolution[1] - 1 - pi->resno; + levelnoz = comp->numresolution[2] - 1 - pi->resno; + trx0 = int_ceildiv(pi->tx0, comp->dx << levelnox); + try0 = int_ceildiv(pi->ty0, comp->dy << levelnoy); + trz0 = int_ceildiv(pi->tz0, comp->dz << levelnoz); + trx1 = int_ceildiv(pi->tx1, comp->dx << levelnox); + try1 = int_ceildiv(pi->ty1, comp->dy << levelnoy); + trz1 = int_ceildiv(pi->tz1, comp->dz << levelnoz); + rpx = res->pdx + levelnox; + rpy = res->pdy + levelnoy; + rpz = res->pdz + levelnoz; + if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && (trx0 << levelnox) % (1 << rpx)))) { + continue; + } + if ((!(pi->y % (comp->dy << rpy) == 0) || (pi->y == pi->ty0 && (try0 << levelnoy) % (1 << rpx)))) { + continue; + } + if ((!(pi->z % (comp->dz << rpz) == 0) || (pi->z == pi->tz0 && (trz0 << levelnoz) % (1 << rpx)))) { + continue; + } + if ((res->prctno[0]==0)||(res->prctno[1]==0)||(res->prctno[2]==0)) continue; + + if ((trx0==trx1)||(try0==try1)||(trz0==trz1)) continue; + + prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelnox), res->pdx) + - int_floordivpow2(trx0, res->pdx); + prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelnoy), res->pdy) + - int_floordivpow2(try0, res->pdy); + prck = int_floordivpow2(int_ceildiv(pi->z, comp->dz << levelnoz), res->pdz) + - int_floordivpow2(trz0, res->pdz); + pi->precno = prci + prcj * res->prctno[0] + prck * res->prctno[0] * res->prctno[1]; + for (pi->layno = 0; 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 (!pi->include[index]) { + pi->include[index] = 1; + return true; + } +LABEL_SKIP:; + } + } + } + } + } +} + + return false; +} + +static bool pi_next_cprl(opj_pi_iterator_t * pi) { + opj_pi_comp_t *comp = NULL; + opj_pi_resolution_t *res = NULL; + long index = 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++) { + int resno; + comp = &pi->comps[pi->compno]; + pi->dx = 0; + pi->dy = 0; + for (resno = 0; resno < comp->numresolution[0]; resno++) { + int dx, dy; + res = &comp->resolutions[resno]; + dx = comp->dx * (1 << (res->pdx + comp->numresolution[0] - 1 - resno)); + dy = comp->dy * (1 << (res->pdy + comp->numresolution[0] - 1 - resno)); + pi->dx = !pi->dx ? dx : int_min(pi->dx, dx); + pi->dy = !pi->dy ? dy : int_min(pi->dy, dy); + } + for (pi->z = pi->tz0; pi->z < pi->tz1; pi->z += pi->dz - (pi->z % pi->dz)) { + for (pi->y = pi->ty0; pi->y < pi->ty1; pi->y += pi->dy - (pi->y % pi->dy)) { + for (pi->x = pi->tx0; pi->x < pi->tx1; pi->x += pi->dx - (pi->x % pi->dx)) { + for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolution[0]); pi->resno++) { + int levelnox, levelnoy, levelnoz; + int trx0, try0, trz0; + int trx1, try1, trz1; + int rpx, rpy, rpz; + int prci, prcj, prck; + comp = &pi->comps[pi->compno]; + if (pi->resno >= comp->numresolution[0]) { + continue; + } + res = &comp->resolutions[pi->resno]; + levelnox = comp->numresolution[0] - 1 - pi->resno; + levelnoy = comp->numresolution[1] - 1 - pi->resno; + levelnoz = comp->numresolution[2] - 1 - pi->resno; + trx0 = int_ceildiv(pi->tx0, comp->dx << levelnox); + try0 = int_ceildiv(pi->ty0, comp->dy << levelnoy); + trz0 = int_ceildiv(pi->tz0, comp->dz << levelnoz); + trx1 = int_ceildiv(pi->tx1, comp->dx << levelnox); + try1 = int_ceildiv(pi->ty1, comp->dy << levelnoy); + trz1 = int_ceildiv(pi->tz1, comp->dz << levelnoz); + rpx = res->pdx + levelnox; + rpy = res->pdy + levelnoy; + rpz = res->pdz + levelnoz; + if ((!(pi->x % (comp->dx << rpx) == 0) || (pi->x == pi->tx0 && (trx0 << levelnox) % (1 << rpx)))) { + continue; + } + if ((!(pi->y % (comp->dy << rpy) == 0) || (pi->y == pi->ty0 && (try0 << levelnoy) % (1 << rpx)))) { + continue; + } + if ((!(pi->z % (comp->dz << rpz) == 0) || (pi->z == pi->tz0 && (trz0 << levelnoz) % (1 << rpx)))) { + continue; + } + if ((res->prctno[0]==0)||(res->prctno[1]==0)||(res->prctno[2]==0)) continue; + + if ((trx0==trx1)||(try0==try1)||(trz0==trz1)) continue; + + prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelnox), res->pdx) + - int_floordivpow2(trx0, res->pdx); + prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelnoy), res->pdy) + - int_floordivpow2(try0, res->pdy); + prck = int_floordivpow2(int_ceildiv(pi->z, comp->dz << levelnoz), res->pdz) + - int_floordivpow2(trz0, res->pdz); + pi->precno = prci + prcj * res->prctno[0] + prck * res->prctno[0] * res->prctno[1]; + for (pi->layno = 0; 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 (!pi->include[index]) { + pi->include[index] = 1; + return true; + } + LABEL_SKIP:; + } + } + } + } + } + } + + return false; +} + +/* +========================================================== + Packet iterator interface +========================================================== +*/ + +opj_pi_iterator_t *pi_create(opj_volume_t *volume, opj_cp_t *cp, int tileno) { + int p, q, r; + int compno, resno, pino; + opj_pi_iterator_t *pi = NULL; + opj_tcp_t *tcp = NULL; + opj_tccp_t *tccp = NULL; + size_t array_size; + + tcp = &cp->tcps[tileno]; + + array_size = (tcp->numpocs + 1) * sizeof(opj_pi_iterator_t); + pi = (opj_pi_iterator_t *) opj_malloc(array_size); + if(!pi) { + fprintf(stdout,"[ERROR] Malloc of opj_pi_iterator failed \n"); + return NULL; + } + + for (pino = 0; pino < tcp->numpocs + 1; pino++) { /* change */ + int maxres = 0; + int maxprec = 0; + p = tileno % cp->tw; + q = tileno / cp->tw; + r = tileno / (cp->tw * cp->th); + + pi[pino].tx0 = int_max(cp->tx0 + p * cp->tdx, volume->x0); + pi[pino].ty0 = int_max(cp->ty0 + q * cp->tdy, volume->y0); + pi[pino].tz0 = int_max(cp->tz0 + r * cp->tdz, volume->z0); + pi[pino].tx1 = int_min(cp->tx0 + (p + 1) * cp->tdx, volume->x1); + pi[pino].ty1 = int_min(cp->ty0 + (q + 1) * cp->tdy, volume->y1); + pi[pino].tz1 = int_min(cp->tz0 + (r + 1) * cp->tdz, volume->z1); + pi[pino].numcomps = volume->numcomps; + + array_size = volume->numcomps * sizeof(opj_pi_comp_t); + pi[pino].comps = (opj_pi_comp_t *) opj_malloc(array_size); + if(!pi[pino].comps) { + fprintf(stdout,"[ERROR] Malloc of opj_pi_comp failed \n"); + pi_destroy(pi, cp, tileno); + return NULL; + } + memset(pi[pino].comps, 0, array_size); + + for (compno = 0; compno < pi->numcomps; compno++) { + int tcx0, tcx1, tcy0, tcy1, tcz0, tcz1; + int i; + opj_pi_comp_t *comp = &pi[pino].comps[compno]; + tccp = &tcp->tccps[compno]; + + comp->dx = volume->comps[compno].dx; + comp->dy = volume->comps[compno].dy; + comp->dz = volume->comps[compno].dz; + for (i = 0; i < 3; i++) { + comp->numresolution[i] = tccp->numresolution[i]; + if (comp->numresolution[i] > maxres) { + maxres = comp->numresolution[i]; + } + } + array_size = comp->numresolution[0] * sizeof(opj_pi_resolution_t); + comp->resolutions = (opj_pi_resolution_t *) opj_malloc(array_size); + if(!comp->resolutions) { + fprintf(stdout,"[ERROR] Malloc of opj_pi_resolution failed \n"); + pi_destroy(pi, cp, tileno); + return NULL; + } + + tcx0 = int_ceildiv(pi->tx0, comp->dx); + tcy0 = int_ceildiv(pi->ty0, comp->dy); + tcz0 = int_ceildiv(pi->tz0, comp->dz); + tcx1 = int_ceildiv(pi->tx1, comp->dx); + tcy1 = int_ceildiv(pi->ty1, comp->dy); + tcz1 = int_ceildiv(pi->tz1, comp->dz); + + for (resno = 0; resno < comp->numresolution[0]; resno++) { + int levelnox, levelnoy, levelnoz, diff; + int rx0, ry0, rz0, rx1, ry1, rz1; + int px0, py0, pz0, px1, py1, pz1; + opj_pi_resolution_t *res = &comp->resolutions[resno]; + if (tccp->csty & J3D_CCP_CSTY_PRT) { + res->pdx = tccp->prctsiz[0][resno]; + res->pdy = tccp->prctsiz[1][resno]; + res->pdz = tccp->prctsiz[2][resno]; + } else { + res->pdx = 15; + res->pdy = 15; + res->pdz = 15; + } + levelnox = comp->numresolution[0] - 1 - resno; + levelnoy = comp->numresolution[1] - 1 - resno; + levelnoz = comp->numresolution[2] - 1 - resno; + if (levelnoz < 0) levelnoz = 0; + diff = comp->numresolution[0] - comp->numresolution[2]; + + rx0 = int_ceildivpow2(tcx0, levelnox); + ry0 = int_ceildivpow2(tcy0, levelnoy); + rz0 = int_ceildivpow2(tcz0, levelnoz); + rx1 = int_ceildivpow2(tcx1, levelnox); + ry1 = int_ceildivpow2(tcy1, levelnoy); + rz1 = int_ceildivpow2(tcz1, levelnoz); + px0 = int_floordivpow2(rx0, res->pdx) << res->pdx; + py0 = int_floordivpow2(ry0, res->pdy) << res->pdy; + pz0 = int_floordivpow2(rz0, res->pdz) << res->pdz; + px1 = int_ceildivpow2(rx1, res->pdx) << res->pdx; + py1 = int_ceildivpow2(ry1, res->pdy) << res->pdy; + pz1 = int_ceildivpow2(rz1, res->pdz) << res->pdz; + res->prctno[0] = (rx0==rx1)? 0 : ((px1 - px0) >> res->pdx); + res->prctno[1] = (ry0==ry1)? 0 : ((py1 - py0) >> res->pdy); + res->prctno[2] = (rz0==rz1)? 0 : ((pz1 - pz0) >> res->pdz); + + if (res->prctno[0]*res->prctno[1]*res->prctno[2] > maxprec) { + maxprec = res->prctno[0]*res->prctno[1]*res->prctno[2]; + } + } + } + + tccp = &tcp->tccps[0]; + pi[pino].step_p = 1; + pi[pino].step_c = maxprec * pi[pino].step_p; + pi[pino].step_r = volume->numcomps * pi[pino].step_c; + pi[pino].step_l = maxres * pi[pino].step_r; + + if (pino == 0) { + array_size = volume->numcomps * maxres * tcp->numlayers * maxprec * sizeof(short int); + pi[pino].include = (short int *) opj_malloc(array_size); + if(!pi[pino].include) { + fprintf(stdout,"[ERROR] Malloc of pi[pino].include failed \n"); + pi_destroy(pi, cp, tileno); + return NULL; + } + } + else { + pi[pino].include = pi[pino - 1].include; + } + + if (tcp->POC == 0) { + pi[pino].first = 1; + pi[pino].poc.resno0 = 0; + pi[pino].poc.compno0 = 0; + pi[pino].poc.layno1 = tcp->numlayers; + pi[pino].poc.resno1 = maxres; + pi[pino].poc.compno1 = volume->numcomps; + pi[pino].poc.prg = tcp->prg; + } else { + pi[pino].first = 1; + pi[pino].poc.resno0 = tcp->pocs[pino].resno0; + pi[pino].poc.compno0 = tcp->pocs[pino].compno0; + pi[pino].poc.layno1 = tcp->pocs[pino].layno1; + pi[pino].poc.resno1 = tcp->pocs[pino].resno1; + pi[pino].poc.compno1 = tcp->pocs[pino].compno1; + pi[pino].poc.prg = tcp->pocs[pino].prg; + } + } + + return pi; +} + +void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno) { + int compno, pino; + opj_tcp_t *tcp = &cp->tcps[tileno]; + if(pi) { + for (pino = 0; pino < tcp->numpocs + 1; pino++) { + if(pi[pino].comps) { + for (compno = 0; compno < pi->numcomps; compno++) { + opj_pi_comp_t *comp = &pi[pino].comps[compno]; + if(comp->resolutions) { + opj_free(comp->resolutions); + } + } + opj_free(pi[pino].comps); + } + } + if(pi->include) { + opj_free(pi->include); + } + opj_free(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); + } + + return false; +} + diff --git a/src/lib/openjp3d/pi.h b/src/lib/openjp3d/pi.h new file mode 100755 index 00000000..1edcc5fc --- /dev/null +++ b/src/lib/openjp3d/pi.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyright (c) 2006, Mónica Díez García, Image Processing Laboratory, University of Valladolid, Spain + * 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. +*/ + +/** @defgroup PI PI - Implementation of a packet iterator */ +/*@{*/ + +/** +Packet iterator : resolution level information +*/ +typedef struct opj_pi_resolution { +/** Size of precints in horizontal axis */ + int pdx; +/** Size of precints in vertical axis */ + int pdy; +/** Size of precints in axial axis */ + int pdz; +/** Number of precints in each axis */ + int prctno[3]; +} opj_pi_resolution_t; + +/** +Packet iterator : component information +*/ +typedef struct opj_pi_comp { +/** Size in horizontal axis */ + int dx; +/** Size in vertical axis */ + int dy; +/** Size in axial axis */ + int dz; +/** Number of resolution levels */ + int numresolution[3]; +/** Packet iterator : resolution level information */ + opj_pi_resolution_t *resolutions; +} opj_pi_comp_t; + +/** +Packet iterator +*/ +typedef struct opj_pi_iterator { +/** precise if the packet has been already used (usefull for progression order change) */ + short int *include; +/** layer step used to localize the packet in the include vector */ + int step_l; +/** resolution step used to localize the packet in the include vector */ + int step_r; +/** component step used to localize the packet in the include vector */ + int step_c; +/** precinct step used to localize the packet in the include vector */ + int step_p; +/** component that identify the packet */ + int compno; +/** resolution that identify the packet */ + int resno; +/** precinct that identify the packet */ + int precno; +/** layer that identify the packet */ + int layno; +/** 0 if the first packet */ + int first; +/** progression order change information */ + opj_poc_t poc; +/** Packet iterator : component information */ +opj_pi_comp_t *comps; + + int numcomps; + int tx0, ty0, tz0; + int tx1, ty1, tz1; + int x, y, z; + int dx, dy, dz; +} opj_pi_iterator_t; + +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a packet iterator +@param volume Raw volume 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(opj_volume_t * volume, opj_cp_t * cp, int tileno); + +/** +Destroy a packet iterator +@param pi Previously created packet iterator +@param cp Coding parameters +@param tileno Number that identifies the tile for which the packets were listed +@see pi_create +*/ +void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno); + +/** +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/src/lib/openjp3d/raw.c b/src/lib/openjp3d/raw.c new file mode 100755 index 00000000..b6a58106 --- /dev/null +++ b/src/lib/openjp3d/raw.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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" + +/* +========================================================== + local functions +========================================================== +*/ + + +/* +========================================================== + RAW encoding interface +========================================================== +*/ + +opj_raw_t* raw_create() { + 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); + } +} + +int raw_numbytes(opj_raw_t *raw) { + return raw->bp - raw->start; +} + +void raw_init_dec(opj_raw_t *raw, unsigned char *bp, int len) { + raw->start = bp; + raw->lenmax = len; + raw->len = 0; + raw->c = 0; + raw->ct = 0; +} + +int raw_decode(opj_raw_t *raw) { + int 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/src/lib/openjp3d/raw.h b/src/lib/openjp3d/raw.h new file mode 100755 index 00000000..c26546ad --- /dev/null +++ b/src/lib/openjp3d/raw.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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. +*/ + +/** @defgroup RAW RAW - Implementation of operations for raw encoding */ +/*@{*/ + +/** +RAW encoding operations +*/ +typedef struct opj_raw { +/** Temporary buffer where bits are coded or decoded */ + unsigned char c; +/** Number of bits already read or free to write */ + unsigned int ct; +/** Maximum length to decode */ + unsigned int lenmax; +/** Length decoded */ + unsigned int len; +/** Pointer to the current position in the buffer */ + unsigned char *bp; +/** Pointer to the start of the buffer */ + unsigned char *start; +/** Pointer to the end of the buffer */ + unsigned char *end; +} opj_raw_t; + +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new RAW handle +@return Returns a new RAW handle if successful, returns NULL otherwise +*/ +opj_raw_t* raw_create(); +/** +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 +*/ +int 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, unsigned char *bp, int len); +/** +Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN +@param raw RAW handle +@return Returns the decoded symbol (0 or 1) +*/ +int raw_decode(opj_raw_t *raw); +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __RAW_H */ diff --git a/src/lib/openjp3d/t1.c b/src/lib/openjp3d/t1.c new file mode 100755 index 00000000..db1d2601 --- /dev/null +++ b/src/lib/openjp3d/t1.c @@ -0,0 +1,1181 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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 T1 T1 - Implementation of the tier-1 coding */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +static int t1_getctxno_zc(opj_t1_t *t1, int f, int orient); +static int t1_getctxno_sc(opj_t1_t *t1, int f); +static int t1_getctxno_mag(opj_t1_t *t1, int f); +static int t1_getspb(opj_t1_t *t1, int f); +static int t1_getnmsedec_sig(opj_t1_t *t1, int x, int bitpos); +static int t1_getnmsedec_ref(opj_t1_t *t1, int x, int bitpos); +static void t1_updateflags(int *fp, int s); +/** +Encode significant pass +*/ +static void t1_enc_sigpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int bpno, int one, int *nmsedec, char type, int vsc); +/** +Decode significant pass +*/ +static void t1_dec_sigpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int oneplushalf, char type, int vsc); +/** +Encode significant pass +*/ +static void t1_enc_sigpass(opj_t1_t *t1, int w, int h, int l, int bpno, int orient, int *nmsedec, char type, int cblksty); +/** +Decode significant pass +*/ +static void t1_dec_sigpass(opj_t1_t *t1, int w, int h, int l, int bpno, int orient, char type, int cblksty); +/** +Encode refinement pass +*/ +static void t1_enc_refpass_step(opj_t1_t *t1, int *fp, int *dp, int bpno, int one, int *nmsedec, char type, int vsc); +/** +Decode refinement pass +*/ +static void t1_dec_refpass_step(opj_t1_t *t1, int *fp, int *dp, int poshalf, int neghalf, char type, int vsc); +/** +Encode refinement pass +*/ +static void t1_enc_refpass(opj_t1_t *t1, int w, int h, int l, int bpno, int *nmsedec, char type, int cblksty); +/** +Decode refinement pass +*/ +static void t1_dec_refpass(opj_t1_t *t1, int w, int h, int l, int bpno, char type, int cblksty); +/** +Encode clean-up pass +*/ +static void t1_enc_clnpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int bpno, int one, int *nmsedec, int partial, int vsc); +/** +Decode clean-up pass +*/ +static void t1_dec_clnpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int oneplushalf, int partial, int vsc); +/** +Encode clean-up pass +*/ +static void t1_enc_clnpass(opj_t1_t *t1, int w, int h, int l, int bpno, int orient, int *nmsedec, int cblksty); +/** +Decode clean-up pass +*/ +static void t1_dec_clnpass(opj_t1_t *t1, int w, int h, int l, int bpno, int orient, int cblksty); +/** +Encode 1 code-block +@param t1 T1 handle +@param cblk Code-block coding parameters +@param orient +@param compno Component number +@param level +@param dwtid +@param stepsize +@param cblksty Code-block style +@param numcomps +@param tile +*/ +static void t1_encode_cblk(opj_t1_t *t1, opj_tcd_cblk_t * cblk, int orient, int compno, int level[3], int dwtid[3], double stepsize, int cblksty, int numcomps, opj_tcd_tile_t * tile); +/** +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_t * cblk, int orient, int roishift, int cblksty); + +static int t1_init_ctxno_zc(int f, int orient); +static int t1_init_ctxno_sc(int f); +static int t1_init_ctxno_mag(int f); +static int t1_init_spb(int f); +/** +Initialize the look-up tables of the Tier-1 coder/decoder +@param t1 T1 handle +*/ +static void t1_init_luts(opj_t1_t *t1); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +static int t1_getctxno_zc(opj_t1_t *t1, int f, int orient) { + return t1->lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)]; +} + +static int t1_getctxno_sc(opj_t1_t *t1, int f) { + return t1->lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; +} + +static int t1_getctxno_mag(opj_t1_t *t1, int f) { + return t1->lut_ctxno_mag[(f & T1_SIG_OTH) | (((f & T1_REFINE) != 0) << 11)]; +} + +static int t1_getspb(opj_t1_t *t1, int f) { + return t1->lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4]; +} + +static int t1_getnmsedec_sig(opj_t1_t *t1, int x, int bitpos) { + if (bitpos > T1_NMSEDEC_FRACBITS) { + return t1->lut_nmsedec_sig[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return t1->lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +static int t1_getnmsedec_ref(opj_t1_t *t1, int x, int bitpos) { + if (bitpos > T1_NMSEDEC_FRACBITS) { + return t1->lut_nmsedec_ref[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return t1->lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +static void t1_updateflags(int *fp, int s) { + int *np = fp - (T1_MAXCBLKW + 2); + int *sp = fp + (T1_MAXCBLKW + 2); + np[-1] |= T1_SIG_SE; + np[1] |= T1_SIG_SW; + sp[-1] |= T1_SIG_NE; + sp[1] |= T1_SIG_NW; + *np |= T1_SIG_S; + *sp |= T1_SIG_N; + fp[-1] |= T1_SIG_E; + fp[1] |= T1_SIG_W; + if (s) { + *np |= T1_SGN_S; + *sp |= T1_SGN_N; + fp[-1] |= T1_SGN_E; + fp[1] |= T1_SGN_W; + } +} + +static void t1_enc_sigpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int bpno, int one, int *nmsedec, char type, int vsc) { + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp); + if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { + v = int_abs(*dp) & one ? 1 : 0; + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient)); /* ESSAI */ + mqc_bypass_enc(mqc, v); + } else { + mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient)); + mqc_encode(mqc, v); + } + if (v) { + v = *dp < 0 ? 1 : 0; + *nmsedec += t1_getnmsedec_sig(t1, int_abs(*dp), bpno + T1_NMSEDEC_FRACBITS); + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag)); /* ESSAI */ + mqc_bypass_enc(mqc, v); + } else { + mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag)); + mqc_encode(mqc, v ^ t1_getspb(t1, flag)); + } + t1_updateflags(fp, v); + *fp |= T1_SIG; + } + *fp |= T1_VISIT; + } +} + +static void t1_dec_sigpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int oneplushalf, char type, int vsc) { + int v, flag; + + opj_raw_t *raw = t1->raw; /* RAW component */ + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp); + if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) { + if (type == T1_TYPE_RAW) { + if (raw_decode(raw)) { + v = raw_decode(raw); /* ESSAI */ + *dp = v ? -oneplushalf : oneplushalf; + t1_updateflags(fp, v); + *fp |= T1_SIG; + } + } else { + mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient)); + if (mqc_decode(mqc)) { + mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag)); + v = mqc_decode(mqc) ^ t1_getspb(t1, flag); + *dp = v ? -oneplushalf : oneplushalf; + t1_updateflags(fp, v); + *fp |= T1_SIG; + } + } + *fp |= T1_VISIT; + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_sigpass(opj_t1_t *t1, int w, int h, int l, int bpno, int orient, int *nmsedec, char type, int cblksty) { + int i, j, k, m, one, vsc; + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + for (j = k; j < k + 4 && j < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_enc_sigpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->data[m][j][i], orient, bpno, one, nmsedec, type, vsc); + } + } + } + } +} + +static void t1_dec_sigpass(opj_t1_t *t1, int w, int h, int l, int bpno, int orient, char type, int cblksty) { + int i, j, k, m, one, half, oneplushalf, vsc; + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + for (j = k; j < k + 4 && j < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_dec_sigpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->data[m][j][i], orient, oneplushalf, type, vsc); + } + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_refpass_step(opj_t1_t *t1, int *fp, int *dp, int bpno, int one, int *nmsedec, char type, int vsc) { + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp); + if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { + *nmsedec += t1_getnmsedec_ref(t1, int_abs(*dp), bpno + T1_NMSEDEC_FRACBITS); + v = int_abs(*dp) & one ? 1 : 0; + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_setcurctx(mqc, t1_getctxno_mag(t1, flag)); /* ESSAI */ + mqc_bypass_enc(mqc, v); + } else { + mqc_setcurctx(mqc, t1_getctxno_mag(t1, flag)); + mqc_encode(mqc, v); + } + *fp |= T1_REFINE; + } +} + +static void t1_dec_refpass_step(opj_t1_t *t1, int *fp, int *dp, int poshalf, int neghalf, char type, int vsc) { + int v, t, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + opj_raw_t *raw = t1->raw; /* RAW component */ + + flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp); + if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) { + if (type == T1_TYPE_RAW) { + mqc_setcurctx(mqc, t1_getctxno_mag(t1, flag)); /* ESSAI */ + v = raw_decode(raw); + } else { + mqc_setcurctx(mqc, t1_getctxno_mag(t1, flag)); + v = mqc_decode(mqc); + } + t = v ? poshalf : neghalf; + *dp += *dp < 0 ? -t : t; + *fp |= T1_REFINE; + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_refpass(opj_t1_t *t1, int w, int h, int l, int bpno, int *nmsedec, char type, int cblksty) { + int i, j, k, m, one, vsc; + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + for (j = k; j < k + 4 && j < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_enc_refpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->data[m][j][i], bpno, one, nmsedec, type, vsc); + } + } + } + } +} + +static void t1_dec_refpass(opj_t1_t *t1, int w, int h, int l, int bpno, char type, int cblksty) { + int i, j, k, m, one, poshalf, neghalf; + int vsc; + one = 1 << bpno; + poshalf = one >> 1; + neghalf = bpno > 0 ? -poshalf : -1; + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + for (j = k; j < k + 4 && j < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_dec_refpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->data[m][j][i], poshalf, neghalf, type, vsc); + } + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_clnpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int bpno, int one, int *nmsedec, int partial, int vsc) { + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp); + if (partial) { + goto LABEL_PARTIAL; + } + if (!(*fp & (T1_SIG | T1_VISIT))) { + mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient)); + v = int_abs(*dp) & one ? 1 : 0; + mqc_encode(mqc, v); + if (v) { +LABEL_PARTIAL: + *nmsedec += t1_getnmsedec_sig(t1, int_abs(*dp), bpno + T1_NMSEDEC_FRACBITS); + mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag)); + v = *dp < 0 ? 1 : 0; + mqc_encode(mqc, v ^ t1_getspb(t1, flag)); + t1_updateflags(fp, v); + *fp |= T1_SIG; + } + } + *fp &= ~T1_VISIT; +} + +static void t1_dec_clnpass_step(opj_t1_t *t1, int *fp, int *dp, int orient, int oneplushalf, int partial, int vsc) { + int v, flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*fp); + if (partial) { + goto LABEL_PARTIAL; + } + if (!(flag & (T1_SIG | T1_VISIT))) { + mqc_setcurctx(mqc, t1_getctxno_zc(t1, flag, orient)); + if (mqc_decode(mqc)) { +LABEL_PARTIAL: + mqc_setcurctx(mqc, t1_getctxno_sc(t1, flag)); + v = mqc_decode(mqc) ^ t1_getspb(t1, flag); + *dp = v ? -oneplushalf : oneplushalf; + t1_updateflags(fp, v); + *fp |= T1_SIG; + } + } + *fp &= ~T1_VISIT; +} /* VSC and BYPASS by Antonin */ + +static void t1_enc_clnpass(opj_t1_t *t1, int w, int h, int l, int bpno, int orient, int *nmsedec, int cblksty) { + int i, j, k, m, one, agg, runlen, vsc; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + if (k + 3 < h) { + if (cblksty & J3D_CCP_CBLKSTY_VSC) { + agg = !(t1->flags[1 + m][1 + k][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][1 + k + 1][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][1 + k + 2][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || (t1->flags[1 + m][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 = !(t1->flags[1 + m][1 + k][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][1 + k + 1][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][1 + k + 2][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][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[m][k + runlen][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 < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_enc_clnpass_step(t1, &(t1->flags[1 + m][1 + j][1 + i]), &(t1->data[m][j][i]), orient, bpno, one, nmsedec, agg && (j == k + runlen), vsc); + } + } + } + } +} + +static void t1_dec_clnpass(opj_t1_t *t1, int w, int h, int l, int bpno, int orient, int cblksty) { + int i, j, k, m, one, half, oneplushalf, agg, runlen, vsc; + int segsym = cblksty & J3D_CCP_CBLKSTY_SEGSYM; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + if (k + 3 < h) { + if (cblksty & J3D_CCP_CBLKSTY_VSC) { + agg = !(t1->flags[1 + m][1 + k][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][1 + k + 1][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][1 + k + 2][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || (t1->flags[1 + m][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 = !(t1->flags[1 + m][1 + k][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][1 + k + 1][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][1 + k + 2][1 + i] & (T1_SIG | T1_VISIT | T1_SIG_OTH) + || t1->flags[1 + m][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 < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_dec_clnpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->data[m][j][i], orient, oneplushalf, agg && (j == k + runlen), vsc); + } + } + } + } + if (segsym) { + int 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 */ + + +static void t1_encode_cblk(opj_t1_t *t1, opj_tcd_cblk_t * cblk, int orient, int compno, int level[3], int dwtid[3], double stepsize, int cblksty, int numcomps, opj_tcd_tile_t * tile) { + int i, j, k; + int w, h, l; + int passno; + int bpno, passtype; + int max; + int nmsedec = 0; + double cumwmsedec = 0; + char type = T1_TYPE_MQ; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + w = cblk->x1 - cblk->x0; + h = cblk->y1 - cblk->y0; + l = cblk->z1 - cblk->z0; + + max = 0; + for (k = 0; k < l; k++) { + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + max = int_max(max, int_abs(t1->data[k][j][i])); + } + } + } + for (k = 0; k <= l; k++) { + for (j = 0; j <= h; j++) { + for (i = 0; i <= w; i++) { + t1->flags[k][j][i] = 0; + } + } + } + + cblk->numbps = max ? (int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS : 0; + + bpno = cblk->numbps - 1; + passtype = 2; + + mqc_reset_enc(mqc); + mqc_init_enc(mqc, cblk->data); + + for (passno = 0; bpno >= 0; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + int correction = 3; + double tmpwmsedec; + type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J3D_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + //fprintf(stdout,"passno %d passtype %d w %d h %d l %d bpno %d orient %d type %d cblksty %d\n",passno,passtype,w,h,l,bpno,orient,type,cblksty); + + switch (passtype) { + case 0: + t1_enc_sigpass(t1, w, h, l, bpno, orient, &nmsedec, type, cblksty); + break; + case 1: + t1_enc_refpass(t1, w, h, l, bpno, &nmsedec, type, cblksty); + break; + case 2: + //fprintf(stdout,"w %d h %d l %d bpno %d orient %d \n",w,h,l,bpno,orient); + t1_enc_clnpass(t1, w, h, l, bpno, orient, &nmsedec, cblksty); + /* code switch SEGMARK (i.e. SEGSYM) */ + if (cblksty & J3D_CCP_CBLKSTY_SEGSYM) + mqc_segmark_enc(mqc); + break; + } + + /* fixed_quality */ + tmpwmsedec = t1_getwmsedec(nmsedec, compno, level, orient, bpno, stepsize, numcomps, dwtid); + cumwmsedec += tmpwmsedec; + tile->distotile += tmpwmsedec; + + /* Code switch "RESTART" (i.e. TERMALL) */ + if ((cblksty & J3D_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 < (cblk->numbps - 4) && (passtype > 0)) + || ((bpno == (cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J3D_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 < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J3D_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 */ + pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate); + + /* Code-switch "RESET" */ + if (cblksty & J3D_CCP_CBLKSTY_RESET) + mqc_reset_enc(mqc); + } + + /* Code switch "ERTERM" (i.e. PTERM) */ + if (cblksty & J3D_CCP_CBLKSTY_PTERM) + mqc_erterm_enc(mqc); + else /* Default coding */ if (!(cblksty & J3D_CCP_CBLKSTY_LAZY)) + mqc_flush(mqc); + + cblk->totalpasses = passno; +} + +static void t1_decode_cblk(opj_t1_t *t1, opj_tcd_cblk_t * cblk, int orient, int roishift, int cblksty) { + int i, j, k, w, h, l; + int bpno, passtype; + int segno, passno; + char type = T1_TYPE_MQ; /* BYPASS mode */ + + opj_raw_t *raw = t1->raw; /* RAW component */ + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + w = cblk->x1 - cblk->x0; + h = cblk->y1 - cblk->y0; + l = cblk->z1 - cblk->z0; + + for (k = 0; k < l; k++) { + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + t1->data[k][j][i] = 0; + } + } + } + + for (k = 0; k <= l; k++) { + for (j = 0; j <= h; j++) { + for (i = 0; i <= w; i++) { + t1->flags[k][j][i] = 0; + } + } + } + + bpno = roishift + cblk->numbps - 1; + passtype = 2; + + mqc_reset_enc(mqc); + + for (segno = 0; segno < cblk->numsegs; segno++) { + opj_tcd_seg_t *seg = &cblk->segs[segno]; + + /* BYPASS mode */ + type = ((bpno <= (cblk->numbps - 1) - 4) && (passtype < 2) && (cblksty & J3D_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + if (type == T1_TYPE_RAW) { + raw_init_dec(raw, seg->data, seg->len); + } else { + mqc_init_dec(mqc, seg->data, seg->len); + } + + for (passno = 0; passno < seg->numpasses; passno++) { + switch (passtype) { + case 0: + t1_dec_sigpass(t1, w, h, l, bpno+1, orient, type, cblksty); + break; + case 1: + t1_dec_refpass(t1, w, h, l, bpno+1, type, cblksty); + break; + case 2: + t1_dec_clnpass(t1, w, h, l, bpno+1, orient, cblksty); + break; + } + + if ((cblksty & J3D_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { + mqc_reset_enc(mqc); + } + if (++passtype == 3) { + passtype = 0; + bpno--; + } + } + } +} + +static int t1_init_ctxno_zc(int f, int orient) { + int h, v, d, n, t, hv; + n = 0; + h = ((f & T1_SIG_W) != 0) + ((f & T1_SIG_E) != 0); + v = ((f & T1_SIG_N) != 0) + ((f & T1_SIG_S) != 0); + d = ((f & T1_SIG_NW) != 0) + ((f & T1_SIG_NE) != 0) + ((f & T1_SIG_SE) != 0) + ((f & T1_SIG_SW) != 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(int f) { + int hc, vc, n; + n = 0; + + hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) == + T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), + 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) == + (T1_SIG_E | T1_SGN_E)) + + ((f & (T1_SIG_W | T1_SGN_W)) == + (T1_SIG_W | T1_SGN_W)), 1); + + vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) == + T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), + 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) == + (T1_SIG_N | T1_SGN_N)) + + ((f & (T1_SIG_S | T1_SGN_S)) == + (T1_SIG_S | T1_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_ctxno_mag(int f) { + int n; + if (!(f & T1_REFINE)) + n = (f & (T1_SIG_OTH)) ? 1 : 0; + else + n = 2; + + return (T1_CTXNO_MAG + n); +} + +static int t1_init_spb(int f) { + int hc, vc, n; + + hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) == + T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W), + 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) == + (T1_SIG_E | T1_SGN_E)) + + ((f & (T1_SIG_W | T1_SGN_W)) == + (T1_SIG_W | T1_SGN_W)), 1); + + vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) == + T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S), + 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) == + (T1_SIG_N | T1_SGN_N)) + + ((f & (T1_SIG_S | T1_SGN_S)) == + (T1_SIG_S | T1_SGN_S)), 1); + + if (!hc && !vc) + n = 0; + else + n = (!(hc > 0 || (!hc && vc > 0))); + + return n; +} + +static void t1_init_luts(opj_t1_t *t1) { + int i, j; + double u, v, t; + for (j = 0; j < 4; j++) { + for (i = 0; i < 256; ++i) { + t1->lut_ctxno_zc[(j << 8) | i] = t1_init_ctxno_zc(i, j); + } + } + for (i = 0; i < 256; i++) { + t1->lut_ctxno_sc[i] = t1_init_ctxno_sc(i << 4); + } + for (j = 0; j < 2; j++) { + for (i = 0; i < 2048; ++i) { + t1->lut_ctxno_mag[(j << 11) + i] = t1_init_ctxno_mag((j ? T1_REFINE : 0) | i); + } + } + for (i = 0; i < 256; ++i) { + t1->lut_spb[i] = t1_init_spb(i << 4); + } + /* FIXME FIXME FIXME */ + /* fprintf(stdout,"nmsedec luts:\n"); */ + for (i = 0; i < (1 << T1_NMSEDEC_BITS); i++) { + t = i / pow(2, T1_NMSEDEC_FRACBITS); + u = t; + v = t - 1.5; + t1->lut_nmsedec_sig[i] = + int_max(0, + (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + t1->lut_nmsedec_sig0[i] = + 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; + } + t1->lut_nmsedec_ref[i] = + int_max(0, + (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + t1->lut_nmsedec_ref0[i] = + int_max(0, + (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + } +} + +/* ----------------------------------------------------------------------- */ + +opj_t1_t* t1_create(opj_common_ptr cinfo) { + opj_t1_t *t1 = (opj_t1_t*)opj_malloc(sizeof(opj_t1_t)); + if(t1) { + t1->cinfo = cinfo; + /* create MQC and RAW handles */ + t1->mqc = mqc_create(); + t1->raw = raw_create(); + /* initialize the look-up tables of the Tier-1 coder/decoder */ + t1_init_luts(t1); + } + return t1; +} + +void t1_destroy(opj_t1_t *t1) { + if(t1) { + /* destroy MQC and RAW handles */ + mqc_destroy(t1->mqc); + raw_destroy(t1->raw); + //opj_free(t1->data); + //opj_free(t1->flags); + opj_free(t1); + } +} + +void t1_encode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp) { + int compno, resno, bandno, precno, cblkno; + int x, y, z, i, j, k, orient; + int n=0; + int level[3]; + FILE *fid = NULL; +// char filename[10]; + tile->distotile = 0; /* fixed_quality */ + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + + for (resno = 0; resno < tilec->numresolution[0]; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + /* Weighted first order entropy + sprintf(filename,"res%d.txt",resno); + if ((fid = fopen(filename,"w")) == 0){ + fprintf(stdout,"Error while opening %s\n", filename); + exit(1); + } + */ + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + for (precno = 0; precno < res->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + + //fprintf(stdout,"Precno %d Cblkno %d \n",precno,cblkno); + if (band->bandno == 0) { + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 1) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 2) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 3) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 4) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 5) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 6) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 7) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } + + if (tcp->tccps[compno].reversible == 1) { + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + t1->data[k][j][i] = + tilec->data[(x + i) + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)] << T1_NMSEDEC_FRACBITS; +//fprintf(fid," %d",t1->data[k][j][i]); + } + } + } + } else if (tcp->tccps[compno].reversible == 0) { + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + t1->data[k][j][i] = fix_mul( + tilec->data[(x + i) + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)], + 8192 * 8192 / ((int) floor(band->stepsize * 8192))) >> (13 - T1_NMSEDEC_FRACBITS); + } + } + } + } + + orient = band->bandno; /* FIXME */ + if (orient == 2) { + orient = 1; + } else if (orient == 1) { + orient = 2; + } + for (i = 0; i < 3; i++) + level[i] = tilec->numresolution[i] - 1 - resno; + //fprintf(stdout,"t1_encode_cblk(t1, cblk, %d, %d, %d %d %d, %d, %f, %d, %d, tile);\n", orient, compno, level[0], level[1], level[2], tcp->tccps[compno].reversible, band->stepsize, tcp->tccps[compno].cblksty, tile->numcomps); + t1_encode_cblk(t1, cblk, orient, compno, level, tcp->tccps[compno].dwtid, band->stepsize, tcp->tccps[compno].cblksty, tile->numcomps, tile); + + } /* cblkno */ + } /* precno */ +//fprintf(fid,"\n"); + } /* bandno */ +//fclose(fid); + } /* resno */ + } /* compno */ +} + +void t1_decode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp) { + int compno, resno, bandno, precno, cblkno; + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + + for (resno = 0; resno < tilec->numresolution[0]; 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->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + int x, y, k, i, j, z, orient; + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + + orient = band->bandno; /* FIXME */ + if (orient == 2) { + orient = 1; + } else if (orient == 1) { + orient = 2; + } + + t1_decode_cblk(t1, cblk, orient, tcp->tccps[compno].roishift, tcp->tccps[compno].cblksty); + + if (band->bandno == 0) { + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 1) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 2) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 3) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 4) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 5) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 6) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 7) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } + + if (tcp->tccps[compno].roishift) { + int thresh, val, mag; + thresh = 1 << tcp->tccps[compno].roishift; + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + val = t1->data[k][j][i]; + mag = int_abs(val); + if (mag >= thresh) { + mag >>= tcp->tccps[compno].roishift; + t1->data[k][j][i] = val < 0 ? -mag : mag; + } + } + } + } + } + + if (tcp->tccps[compno].reversible == 1) { + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + int tmp = t1->data[k][j][i]; + tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)] = tmp/2; + } + } + } + } else { /* if (tcp->tccps[compno].reversible == 0) */ + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + double tmp = (double)(t1->data[k][j][i] * band->stepsize * 4096.0); + if (t1->data[k][j][i] >> 1 == 0) { + tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)] = 0; + } else { + int tmp2 = ((int) (floor(fabs(tmp)))) + ((int) floor(fabs(tmp*2))%2); + tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)] = ((tmp<0)?-tmp2:tmp2); + } + } + } + } + } + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ +} + + +/** mod fixed_quality */ +double t1_getwmsedec(int nmsedec, int compno, int level[3], int orient, int bpno, double stepsize, int numcomps, int dwtid[3]) { + double w1, w2, wmsedec; + + if (dwtid[0] == 1 || dwtid[1] == 1 || dwtid[2] == 1) { + w1 = (numcomps > 1) ? mct_getnorm_real(compno) : 1; + } else { + w1 = (numcomps > 1) ? mct_getnorm(compno) : 1; + } + w2 = dwt_getnorm(orient, level, dwtid); + + //fprintf(stdout,"nmsedec %d level %d %d %d orient %d bpno %d stepsize %f \n",nmsedec ,level[0],level[1],level[2],orient,bpno,stepsize); + wmsedec = w1 * w2 * stepsize * (1 << bpno); + wmsedec *= wmsedec * nmsedec / 8192.0; + + return wmsedec; +} +/** mod fixed_quality */ diff --git a/src/lib/openjp3d/t1.h b/src/lib/openjp3d/t1.h new file mode 100755 index 00000000..7b4a18f5 --- /dev/null +++ b/src/lib/openjp3d/t1.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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. +*/ + +/** @defgroup T1 T1 - Implementation of the tier-1 coding */ +/*@{*/ + +/* ----------------------------------------------------------------------- */ +#define T1_NMSEDEC_BITS 7 + +#define T1_MAXCBLKW 256 /*< Maximum size of code-block (width) */ +#define T1_MAXCBLKH 256 /*< Maximum size of code-block (heigth) */ +#define T1_MAXCBLKD 256 /*< Maximum size of code-block (depth) */ +#define T1_MINCBLKW 4 /*< Minimum size of code-block (width) */ +#define T1_MINCBLKH 4 /*< Minimum size of code-block (heigth) */ +#define T1_MINCBLKD 4 /*< Minimum size of code-block (depth) */ +#define T1_MAXWHD 18 +#define T1_CBLKW 256 +#define T1_CBLKH 256 +#define T1_CBLKD 256 + +#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_AGG 1 +#define T1_NUMCTXS_ZC 9 +#define T1_NUMCTXS_MAG 3 +#define T1_NUMCTXS_SC 5 +#define T1_NUMCTXS_UNI 1 + +#define T1_CTXNO_AGG 0 +#define T1_CTXNO_ZC (T1_CTXNO_AGG+T1_NUMCTXS_AGG) +#define T1_CTXNO_MAG (T1_CTXNO_ZC+T1_NUMCTXS_ZC) +#define T1_CTXNO_SC (T1_CTXNO_MAG+T1_NUMCTXS_MAG) +#define T1_CTXNO_UNI (T1_CTXNO_SC+T1_NUMCTXS_SC) +#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)*/ + +/* ----------------------------------------------------------------------- */ + +/** +Tier-1 coding (coding of code-block coefficients) +*/ +typedef struct opj_t1 { + /** codec context */ + opj_common_ptr cinfo; + + /** MQC component */ + opj_mqc_t *mqc; + /** RAW component */ + opj_raw_t *raw; + /** LUTs for context-based coding */ + int lut_ctxno_zc[1024]; + int lut_ctxno_sc[256]; + int lut_ctxno_mag[4096]; + int lut_spb[256]; + /** LUTs for decoding normalised MSE */ + 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]; + /** Codeblock data */ + int data[T1_CBLKD][T1_CBLKH][T1_CBLKW];//int ***data; + /** Context information for each voxel in codeblock */ + int flags[T1_CBLKD + 2][T1_CBLKH + 2][T1_CBLKH + 2];//int ***flags; +} opj_t1_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new T1 handle +and initialize the look-up tables of the Tier-1 coder/decoder +@return Returns a new T1 handle if successful, returns NULL otherwise +@see t1_init_luts +*/ +opj_t1_t* t1_create(opj_common_ptr cinfo); +/** +Destroy a previously created T1 handle +@param t1 T1 handle to destroy +*/ +void t1_destroy(opj_t1_t *t1); +/** +Encode the code-blocks of a tile +@param t1 T1 handle +@param tile The tile to encode +@param tcp Tile coding parameters +*/ +void t1_encode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp); +/** +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, opj_tcd_tile_t *tile, opj_tcp_t *tcp); +/** +Get weigths of MSE decoding +@param nmsedec The normalized MSE reduction +@param compno +@param level +@param orient +@param bpno +@param stepsize +@param numcomps +@param dwtid +returns MSE associated to decoding pass +*/ +double t1_getwmsedec(int nmsedec, int compno, int level[3], int orient, int bpno, double stepsize, int numcomps, int dwtid[3]); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __T1_H */ diff --git a/src/lib/openjp3d/t1_3d.c b/src/lib/openjp3d/t1_3d.c new file mode 100755 index 00000000..efdf2efc --- /dev/null +++ b/src/lib/openjp3d/t1_3d.c @@ -0,0 +1,1230 @@ +/* + * Copyrigth (c) 2006, Mónica Díez, LPI-UVA, Spain + * 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 T1_3D T1_3D - Implementation of the tier-1 coding */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +static int t1_3d_getctxno_zc(unsigned int f, int orient); +static int t1_3d_getctxno_sc(unsigned int f); +static int t1_3d_getctxno_mag(unsigned int f, int fsvr); +static int t1_3d_getspb(unsigned int f); +static int t1_3d_getnmsedec_sig(opj_t1_3d_t *t1, int x, int bitpos); +static int t1_3d_getnmsedec_ref(opj_t1_3d_t *t1, int x, int bitpos); +static void t1_3d_updateflags(unsigned int *fp, int s); +/** +Encode significant pass +*/ +static void t1_3d_enc_sigpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int orient, int bpno, int one, int *nmsedec, char type, int vsc); +/** +Decode significant pass +*/ +static void t1_3d_dec_sigpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int orient, int oneplushalf, char type, int vsc); +/** +Encode significant pass +*/ +static void t1_3d_enc_sigpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int orient, int *nmsedec, char type, int cblksty); +/** +Decode significant pass +*/ +static void t1_3d_dec_sigpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int orient, char type, int cblksty); +/** +Encode refinement pass +*/ +static void t1_3d_enc_refpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int bpno, int one, int *nmsedec, char type, int vsc); +/** +Decode refinement pass +*/ +static void t1_3d_dec_refpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int poshalf, int neghalf, char type, int vsc); +/** +Encode refinement pass +*/ +static void t1_3d_enc_refpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int *nmsedec, char type, int cblksty); +/** +Decode refinement pass +*/ +static void t1_3d_dec_refpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, char type, int cblksty); +/** +Encode clean-up pass +*/ +static void t1_3d_enc_clnpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int orient, int bpno, int one, int *nmsedec, int partial, int vsc); +/** +Decode clean-up pass +*/ +static void t1_3d_dec_clnpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int orient, int oneplushalf, int partial, int vsc); +/** +Encode clean-up pass +*/ +static void t1_3d_enc_clnpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int orient, int *nmsedec, int cblksty); +/** +Decode clean-up pass +*/ +static void t1_3d_dec_clnpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int orient, int cblksty); +/** +Encode 1 code-block +@param t1 T1 handle +@param cblk Code-block coding parameters +@param orient +@param compno Component number +@param level[3] +@param dwtid[3] +@param stepsize +@param cblksty Code-block style +@param numcomps +@param tile +*/ +static void t1_3d_encode_cblk(opj_t1_3d_t *t1, opj_tcd_cblk_t * cblk, int orient, int compno, int level[3], int dwtid[3], double stepsize, int cblksty, int numcomps, opj_tcd_tile_t * tile); +/** +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_3d_decode_cblk(opj_t1_3d_t *t1, opj_tcd_cblk_t * cblk, int orient, int roishift, int cblksty); +static int t1_3d_init_ctxno_zc(unsigned int f, int orient); +static int t1_3d_init_ctxno_sc(unsigned int f); +static int t1_3d_init_ctxno_mag(unsigned int f, int f2); +static int t1_3d_init_spb(unsigned int f); +/** +Initialize the look-up tables of the Tier-1 coder/decoder +@param t1 T1 handle +*/ +static void t1_3d_init_luts(opj_t1_3d_t *t1); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +static int t1_3d_getctxno_zc(unsigned int f, int orient) { + return t1_3d_init_ctxno_zc((f & T1_3D_SIG_OTH), orient); +} + +static int t1_3d_getctxno_sc(unsigned int f) { + return t1_3d_init_ctxno_sc((f & T1_3D_SIG_PRIM) | ((f >> 16) & T1_3D_SGN)); + //return t1->lut_ctxno_sc[((f & T1_3D_SIG_PRIM) | ((f >> 16) & T1_3D_SGN)) >> 4]; +} + +static int t1_3d_getctxno_mag(unsigned int f, int fsvr) { + return t1_3d_init_ctxno_mag((f & T1_3D_SIG_OTH), fsvr); +} + +static int t1_3d_getspb(unsigned int f) { + return t1_3d_init_spb((f & T1_3D_SIG_PRIM) | ((f >> 16) & T1_3D_SGN)); + //return t1->lut_spb[((f & T1_3D_SIG_PRIM) | ((f >> 16) & T1_3D_SGN)) >> 4]; +} + +static int t1_3d_getnmsedec_sig(opj_t1_3d_t *t1, int x, int bitpos) { + if (bitpos > T1_NMSEDEC_FRACBITS) { + return t1->lut_nmsedec_sig[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return t1->lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +static int t1_3d_getnmsedec_ref(opj_t1_3d_t *t1, int x, int bitpos) { + if (bitpos > T1_NMSEDEC_FRACBITS) { + return t1->lut_nmsedec_ref[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)]; + } + + return t1->lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)]; +} + +static void t1_3d_updateflags(unsigned int *fp, int s) { + unsigned int *np = fp - (T1_MAXCBLKW + 2); + unsigned int *sp = fp + (T1_MAXCBLKW + 2); + + unsigned int *bwp = fp + ((T1_MAXCBLKW + 2)*(T1_MAXCBLKH +2)); + unsigned int *bnp = bwp - (T1_MAXCBLKW + 2); + unsigned int *bsp = bwp + (T1_MAXCBLKW + 2); + + unsigned int *fwp = fp - ((T1_MAXCBLKW + 2)*(T1_MAXCBLKH +2)); + unsigned int *fnp = fwp - (T1_MAXCBLKW + 2); + unsigned int *fsp = fwp + (T1_MAXCBLKW + 2); + + np[-1] |= T1_3D_SIG_SE; + np[1] |= T1_3D_SIG_SW; + sp[-1] |= T1_3D_SIG_NE; + sp[1] |= T1_3D_SIG_NW; + *np |= T1_3D_SIG_S; + *sp |= T1_3D_SIG_N; + fp[-1] |= T1_3D_SIG_E; + fp[1] |= T1_3D_SIG_W; + + *fwp |= T1_3D_SIG_FC; + *bwp |= T1_3D_SIG_BC; + + fnp[-1] |= T1_3D_SIG_FSE; + fnp[1] |= T1_3D_SIG_FSW; + fsp[-1] |= T1_3D_SIG_FNE; + fsp[1] |= T1_3D_SIG_FNW; + *fnp |= T1_3D_SIG_FS; + *fsp |= T1_3D_SIG_FN; + fwp[-1] |= T1_3D_SIG_FE; + fwp[1] |= T1_3D_SIG_FW; + + bnp[-1] |= T1_3D_SIG_BSE; + bnp[1] |= T1_3D_SIG_BSW; + bsp[-1] |= T1_3D_SIG_BNE; + bsp[1] |= T1_3D_SIG_BNW; + *bnp |= T1_3D_SIG_BS; + *bsp |= T1_3D_SIG_BN; + bwp[-1] |= T1_3D_SIG_BE; + bwp[1] |= T1_3D_SIG_BW; + + if (s) { + *np |= (T1_3D_SGN_S << 16); + *sp |= (T1_3D_SGN_N << 16); + fp[-1] |= (T1_3D_SGN_E << 16); + fp[1] |= (T1_3D_SGN_W << 16); + *fwp |= (T1_3D_SGN_F << 16); + *bwp |= (T1_3D_SGN_B << 16); + } +} + +static void t1_3d_enc_sigpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int orient, int bpno, int one, int *nmsedec, char type, int vsc) { + int v, flagsvr; + unsigned int flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_3D_SIG_S | T1_3D_SIG_SE | T1_3D_SIG_SW | (T1_3D_SGN_S << 16)))) : (*fp); + flagsvr = (*fsvr); + if ((flag & T1_3D_SIG_OTH) && !(flagsvr & (T1_3D_SIG | T1_3D_VISIT))) { + v = int_abs(*dp) & one ? 1 : 0; + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_setcurctx(mqc, t1_3d_getctxno_zc(flag, orient)); /* ESSAI */ + mqc_bypass_enc(mqc, v); + } else { + mqc_setcurctx(mqc, t1_3d_getctxno_zc(flag, orient)); + mqc_encode(mqc, v); + } + if (v) { + v = *dp < 0 ? 1 : 0; + *nmsedec += t1_3d_getnmsedec_sig(t1, int_abs(*dp), bpno + T1_NMSEDEC_FRACBITS); + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_setcurctx(mqc, t1_3d_getctxno_sc(flag)); /* ESSAI */ + mqc_bypass_enc(mqc, v); + } else { + mqc_setcurctx(mqc, t1_3d_getctxno_sc(flag)); + mqc_encode(mqc, v ^ t1_3d_getspb(flag)); + } + t1_3d_updateflags(fp, v); + *fsvr |= T1_3D_SIG; + } + *fsvr |= T1_3D_VISIT; + } +} + +static void t1_3d_dec_sigpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int orient, int oneplushalf, char type, int vsc) { + int v, flagsvr; + unsigned int flag; + + opj_raw_t *raw = t1->raw; /* RAW component */ + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_3D_SIG_S | T1_3D_SIG_SE | T1_3D_SIG_SW | (T1_3D_SGN_S << 16)))) : (*fp); + flagsvr = (*fsvr); + if ((flag & T1_3D_SIG_OTH) && !(flagsvr & (T1_3D_SIG | T1_3D_VISIT))) { + if (type == T1_TYPE_RAW) { + if (raw_decode(raw)) { + v = raw_decode(raw); /* ESSAI */ + *dp = v ? -oneplushalf : oneplushalf; + t1_3d_updateflags(fp, v); + *fsvr |= T1_3D_SIG; + } + } else { + mqc_setcurctx(mqc, t1_3d_getctxno_zc(flag, orient)); + if (mqc_decode(mqc)) { + mqc_setcurctx(mqc, t1_3d_getctxno_sc(flag)); + v = mqc_decode(mqc) ^ t1_3d_getspb(flag); + *dp = v ? -oneplushalf : oneplushalf; + t1_3d_updateflags(fp, v); + *fsvr |= T1_3D_SIG; + } + } + *fsvr |= T1_3D_VISIT; + } +} /* VSC and BYPASS by Antonin */ + +static void t1_3d_enc_sigpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int orient, int *nmsedec, char type, int cblksty) { + int i, j, k, m, one, vsc; + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + for (j = k; j < k + 4 && j < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_3d_enc_sigpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->flagSVR[1 + m][1 + j][1 + i], &t1->data[m][j][i], orient, bpno, one, nmsedec, type, vsc); + } + } + } + } +} + +static void t1_3d_dec_sigpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int orient, char type, int cblksty) { + int i, j, k, m, one, half, oneplushalf, vsc; + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + for (j = k; j < k + 4 && j < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_3d_dec_sigpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->flagSVR[1 + m][1 + j][1 + i], &t1->data[m][j][i], orient, oneplushalf, type, vsc); + } + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_3d_enc_refpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int bpno, int one, int *nmsedec, char type, int vsc) { + int v, flagsvr; + unsigned int flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_3D_SIG_S | T1_3D_SIG_SE | T1_3D_SIG_SW | (T1_3D_SGN_S << 16)))) : (*fp); + flagsvr = (*fsvr); + if ((flagsvr & (T1_3D_SIG | T1_3D_VISIT)) == T1_3D_SIG) { + *nmsedec += t1_3d_getnmsedec_ref(t1, int_abs(*dp), bpno + T1_NMSEDEC_FRACBITS); + v = int_abs(*dp) & one ? 1 : 0; + if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */ + mqc_setcurctx(mqc, t1_3d_getctxno_mag(flag, flagsvr)); /* ESSAI */ + mqc_bypass_enc(mqc, v); + } else { + mqc_setcurctx(mqc, t1_3d_getctxno_mag(flag, flagsvr)); + mqc_encode(mqc, v); + } + *fsvr |= T1_3D_REFINE; + } +} + +static void t1_3d_dec_refpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int poshalf, int neghalf, char type, int vsc) { + int v, t, flagsvr; + unsigned int flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + opj_raw_t *raw = t1->raw; /* RAW component */ + + flag = vsc ? ((*fp) & (~(T1_3D_SIG_S | T1_3D_SIG_SE | T1_3D_SIG_SW | (T1_3D_SGN_S << 16)))) : (*fp); + flagsvr = (*fsvr); + if ((flagsvr & (T1_3D_SIG | T1_3D_VISIT)) == T1_3D_SIG) { + if (type == T1_TYPE_RAW) { + mqc_setcurctx(mqc, t1_3d_getctxno_mag(flag, flagsvr)); /* ESSAI */ + v = raw_decode(raw); + } else { + mqc_setcurctx(mqc, t1_3d_getctxno_mag(flag, flagsvr)); + v = mqc_decode(mqc); + } + t = v ? poshalf : neghalf; + *dp += *dp < 0 ? -t : t; + *fsvr |= T1_3D_REFINE; + } +} /* VSC and BYPASS by Antonin */ + +static void t1_3d_enc_refpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int *nmsedec, char type, int cblksty) { + int i, j, k, m, one, vsc; + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (m = 0; m < l; m++){ + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + for (j = k; j < k + 4 && j < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_3d_enc_refpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->flagSVR[1 + m][1 + j][1 + i], &t1->data[m][j][i], bpno, one, nmsedec, type, vsc); + } + } + } + } +} + +static void t1_3d_dec_refpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, char type, int cblksty) { + int i, j, k, m, one, poshalf, neghalf; + int vsc; + one = 1 << bpno; + poshalf = one >> 1; + neghalf = bpno > 0 ? -poshalf : -1; + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + for (j = k; j < k + 4 && j < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_3d_dec_refpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->flagSVR[1 + m][1 + j][1 + i], &t1->data[m][j][i], poshalf, neghalf, type, vsc); + } + } + } + } +} /* VSC and BYPASS by Antonin */ + +static void t1_3d_enc_clnpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int orient, int bpno, int one, int *nmsedec, int partial, int vsc) { + int v, flagsvr; + unsigned int flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_3D_SIG_S | T1_3D_SIG_SE | T1_3D_SIG_SW | (T1_3D_SGN_S << 16)))) : (*fp); + flagsvr = (*fsvr); + if (partial) { + goto LABEL_PARTIAL; + } + if (!(*fsvr & (T1_3D_SIG | T1_3D_VISIT))) { + mqc_setcurctx(mqc, t1_3d_getctxno_zc(flag, orient)); + v = int_abs(*dp) & one ? 1 : 0; + mqc_encode(mqc, v); + if (v) { +LABEL_PARTIAL: + *nmsedec += t1_3d_getnmsedec_sig(t1, int_abs(*dp), bpno + T1_NMSEDEC_FRACBITS); + mqc_setcurctx(mqc, t1_3d_getctxno_sc(flag)); + v = *dp < 0 ? 1 : 0; + mqc_encode(mqc, v ^ t1_3d_getspb(flag)); + t1_3d_updateflags(fp, v); + *fsvr |= T1_3D_SIG; + } + } + *fsvr &= ~T1_3D_VISIT; +} + +static void t1_3d_dec_clnpass_step(opj_t1_3d_t *t1, unsigned int *fp, int *fsvr, int *dp, int orient, int oneplushalf, int partial, int vsc) { + int v, flagsvr; + unsigned int flag; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + flag = vsc ? ((*fp) & (~(T1_3D_SIG_S | T1_3D_SIG_SE | T1_3D_SIG_SW | (T1_3D_SGN_S << 16)))) : (*fp); + flagsvr = (*fsvr); + if (partial) { + goto LABEL_PARTIAL; + } + if (!(flagsvr & (T1_3D_SIG | T1_3D_VISIT))) { + mqc_setcurctx(mqc, t1_3d_getctxno_zc(flag, orient)); + if (mqc_decode(mqc)) { +LABEL_PARTIAL: + mqc_setcurctx(mqc, t1_3d_getctxno_sc(flag)); + v = mqc_decode(mqc) ^ t1_3d_getspb(flag); + *dp = v ? -oneplushalf : oneplushalf; + t1_3d_updateflags(fp, v); + *fsvr |= T1_3D_SIG; + } + } + *fsvr &= ~T1_3D_VISIT; +} /* VSC and BYPASS by Antonin */ + +static void t1_3d_enc_clnpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int orient, int *nmsedec, int cblksty) { + int i, j, k, m, one, agg, runlen, vsc; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + *nmsedec = 0; + one = 1 << (bpno + T1_NMSEDEC_FRACBITS); + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + if (k + 3 < h) { + if (cblksty & J3D_CCP_CBLKSTY_VSC) { + agg = !( ((t1->flagSVR[1 + m][1 + k][1 + i] | (T1_3D_SIG | T1_3D_VISIT)) & (t1->flags[1 + m][1 + k][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 1][1 + i] | (T1_3D_SIG | T1_3D_VISIT)) & (t1->flags[1 + m][1 + k + 1][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 2][1 + i] | (T1_3D_SIG | T1_3D_VISIT)) & (t1->flags[1 + m][1 + k + 2][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 3][1 + i] | (T1_3D_SIG | T1_3D_VISIT)) & ((t1->flags[1 + m][1 + k + 3][1 + i] & (~(T1_3D_SIG_S | T1_3D_SIG_SE | T1_3D_SIG_SW | (T1_3D_SGN_S << 16)))) & (T1_3D_SIG_OTH))) + ); + } else { + agg = !( + ((t1->flagSVR[1 + m][1 + k][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 1][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k + 1][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 2][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k + 2][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 3][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k + 3][1 + i] & T1_3D_SIG_OTH)) + ); + } + } else { + agg = 0; + } + if (agg) { + for (runlen = 0; runlen < 4; runlen++) { + if (int_abs(t1->data[m][k + runlen][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 < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_3d_enc_clnpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->flagSVR[1 + m][1 + j][1 + i], &t1->data[m][j][i], orient, bpno, one, nmsedec, agg && (j == k + runlen), vsc); + } + } + } + } +} + +static void t1_3d_dec_clnpass(opj_t1_3d_t *t1, int w, int h, int l, int bpno, int orient, int cblksty) { + int i, j, k, m, one, half, oneplushalf, agg, runlen, vsc; + int segsym = cblksty & J3D_CCP_CBLKSTY_SEGSYM; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + one = 1 << bpno; + half = one >> 1; + oneplushalf = one | half; + for (m = 0; m < l; m++) { + for (k = 0; k < h; k += 4) { + for (i = 0; i < w; i++) { + if (k + 3 < h) { + if (cblksty & J3D_CCP_CBLKSTY_VSC) { + agg = !( + ((t1->flagSVR[1 + m][1 + k][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 1][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k + 1][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 2][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k + 2][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 3][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | ((t1->flags[1 + m][1 + k + 3][1 + i] & (~(T1_3D_SIG_S | T1_3D_SIG_SE | T1_3D_SIG_SW | (T1_3D_SGN_S << 16)))) & (T1_3D_SIG_OTH))) + ); + } else { + agg = !( + ((t1->flagSVR[1 + m][1 + k][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 1][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k + 1][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 2][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k + 2][1 + i] & T1_3D_SIG_OTH)) + || ((t1->flagSVR[1 + m][1 + k + 3][1 + i] & (T1_3D_SIG | T1_3D_VISIT)) | (t1->flags[1 + m][1 + k + 3][1 + i] & T1_3D_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 < h; j++) { + vsc = ((cblksty & J3D_CCP_CBLKSTY_VSC) && (j == k + 3 || j == h - 1)) ? 1 : 0; + t1_3d_dec_clnpass_step(t1, &t1->flags[1 + m][1 + j][1 + i], &t1->flagSVR[1 + m][1 + j][1 + i], &t1->data[m][j][i], orient, oneplushalf, agg && (j == k + runlen), vsc); + } + } + } + } + if (segsym) { + int 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 */ + + +static void t1_3d_encode_cblk(opj_t1_3d_t *t1, opj_tcd_cblk_t * cblk, int orient, int compno, int level[3], int dwtid[3], double stepsize, int cblksty, int numcomps, opj_tcd_tile_t * tile) { + int i, j, k; + int w, h, l; + int passno; + int bpno, passtype; + int max; + int nmsedec = 0; + double cumwmsedec = 0; + char type = T1_TYPE_MQ; + + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + w = cblk->x1 - cblk->x0; + h = cblk->y1 - cblk->y0; + l = cblk->z1 - cblk->z0; + + max = 0; + for (k = 0; k < l; k++) { + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + max = int_max(max, int_abs(t1->data[k][j][i])); + } + } + } + for (k = 0; k <= l; k++) { + for (j = 0; j <= h; j++) { + for (i = 0; i <= w; i++) { + t1->flags[k][j][i] = 0; + t1->flagSVR[k][j][i] = 0; + } + } + } + + cblk->numbps = max ? (int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS : 0; + + bpno = cblk->numbps - 1; + passtype = 2; + + mqc_reset_enc(mqc); + mqc_init_enc(mqc, cblk->data); + + for (passno = 0; bpno >= 0; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + int correction = 3; + double tmpwmsedec; + type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J3D_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + + switch (passtype) { + case 0: + t1_3d_enc_sigpass(t1, w, h, l, bpno, orient, &nmsedec, type, cblksty); + break; + case 1: + t1_3d_enc_refpass(t1, w, h, l, bpno, &nmsedec, type, cblksty); + break; + case 2: + t1_3d_enc_clnpass(t1, w, h, l, bpno, orient, &nmsedec, cblksty); + /* code switch SEGMARK (i.e. SEGSYM) */ + if (cblksty & J3D_CCP_CBLKSTY_SEGSYM) + mqc_segmark_enc(mqc); + break; + } + + /* fixed_quality */ + tmpwmsedec = t1_getwmsedec(nmsedec, compno, level, orient, bpno, stepsize, numcomps, dwtid); + cumwmsedec += tmpwmsedec; + tile->distotile += tmpwmsedec; + + /* Code switch "RESTART" (i.e. TERMALL) */ + if ((cblksty & J3D_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 < (cblk->numbps - 4) && (passtype > 0)) + || ((bpno == (cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J3D_CCP_CBLKSTY_LAZY)) { + if (type == T1_TYPE_RAW) { + mqc_flush(mqc); + correction = 1; + } else { + 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 < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J3D_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 */ + pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate); + + /* Code-switch "RESET" */ + if (cblksty & J3D_CCP_CBLKSTY_RESET) + mqc_reset_enc(mqc); + } + + /* Code switch "ERTERM" (i.e. PTERM) */ + if (cblksty & J3D_CCP_CBLKSTY_PTERM) + mqc_erterm_enc(mqc); + else /* Default coding */ if (!(cblksty & J3D_CCP_CBLKSTY_LAZY)) + mqc_flush(mqc); + + cblk->totalpasses = passno; +} + +static void t1_3d_decode_cblk(opj_t1_3d_t *t1, opj_tcd_cblk_t * cblk, int orient, int roishift, int cblksty) { + int i, j, k; + int w, h, l; + int bpno, passtype; + int segno, passno; + char type = T1_TYPE_MQ; /* BYPASS mode */ + opj_raw_t *raw = t1->raw; /* RAW component */ + opj_mqc_t *mqc = t1->mqc; /* MQC component */ + + w = cblk->x1 - cblk->x0; + h = cblk->y1 - cblk->y0; + l = cblk->z1 - cblk->z0; + + for (k = 0; k < l; k++) { + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + t1->data[k][j][i] = 0; + } + } + } + + for (k = 0; k <= l; k++) { + for (j = 0; j <= h; j++) { + for (i = 0; i <= w; i++) { + t1->flags[k][j][i] = 0; + t1->flagSVR[k][j][i] = 0; + } + } + } + + + bpno = roishift + cblk->numbps - 1; + passtype = 2; + + mqc_reset_enc(mqc); + + for (segno = 0; segno < cblk->numsegs; segno++) { + opj_tcd_seg_t *seg = &cblk->segs[segno]; + + /* BYPASS mode */ + type = ((bpno <= (cblk->numbps - 1) - 4) && (passtype < 2) && (cblksty & J3D_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ; + if (type == T1_TYPE_RAW) { + raw_init_dec(raw, seg->data, seg->len); + } else { + mqc_init_dec(mqc, seg->data, seg->len); + } + + for (passno = 0; passno < seg->numpasses; passno++) { + switch (passtype) { + case 0: + t1_3d_dec_sigpass(t1, w, h, l, bpno+1, orient, type, cblksty); + break; + case 1: + t1_3d_dec_refpass(t1, w, h, l, bpno+1, type, cblksty); + break; + case 2: + t1_3d_dec_clnpass(t1, w, h, l, bpno+1, orient, cblksty); + break; + } + + if ((cblksty & J3D_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) { + mqc_reset_enc(mqc); + } + if (++passtype == 3) { + passtype = 0; + bpno--; + } + + } + } +} + +static int t1_3d_init_ctxno_zc(unsigned int f, int orient) { + unsigned int h, v, c; + unsigned int d2xy, d2xz, d2yz, d3; + int n; + unsigned int hvc, hc, d2, d2xy2yz, d2xy2xz; + n = 0; + h = ((f & T1_3D_SIG_W) != 0) + ((f & T1_3D_SIG_E) != 0); + v = ((f & T1_3D_SIG_N) != 0) + ((f & T1_3D_SIG_S) != 0); + c = ((f & T1_3D_SIG_FC) != 0) + ((f & T1_3D_SIG_BC) != 0); + d2xy = ((f & T1_3D_SIG_NW) != 0) + ((f & T1_3D_SIG_NE) != 0) + ((f & T1_3D_SIG_SE) != 0) + ((f & T1_3D_SIG_SW) != 0); + d2xz = ((f & T1_3D_SIG_FW) != 0) + ((f & T1_3D_SIG_BW) != 0) + ((f & T1_3D_SIG_FE) != 0) + ((f & T1_3D_SIG_BE) != 0); + d2yz = ((f & T1_3D_SIG_FN) != 0) + ((f & T1_3D_SIG_FS) != 0) + ((f & T1_3D_SIG_BN) != 0) + ((f & T1_3D_SIG_BS) != 0); + d3 = ((f & T1_3D_SIG_FNW) != 0) + ((f & T1_3D_SIG_FNE) != 0) + ((f & T1_3D_SIG_FSE) != 0) + ((f & T1_3D_SIG_FSW) != 0) + + ((f & T1_3D_SIG_BNW) != 0) + ((f & T1_3D_SIG_BNE) != 0) + ((f & T1_3D_SIG_BSE) != 0) + ((f & T1_3D_SIG_BSW) != 0); + + switch (orient) { + case 0: //LLL + case 7: //HHH + hvc = h + v + c; + d2 = d2xy + d2xz + d2yz; + if (!hvc) { + if (!d2) { + n = (!d3) ? 0 : 1; + } else if (d2 == 1) { + n = (!d3) ? 2 : 3; + } else { + n = (!d3) ? 4 : 5; + } + } else if (hvc == 1) { + if (!d2) { + n = (!d3) ? 6 : 7; + } else if (d2 == 1) { + n = (!d3) ? 8 : 9; + } else { + n = 10; + } + } else if (hvc == 2) { + if (!d2) { + n = (!d3) ? 11 : 12; + } else { + n = 13; + } + } else if (hvc == 3) { + n = 14; + } else { + n = 15; + } + break; + //LHL, HLL, LLH + case 1: + case 2: + case 4: + hc = h + c; + d2xy2yz = d2xy + d2yz; + if (!hc) { + if (!v) { + if (!d2xy) { + n = (!d2xy2yz) ? ((!d3) ? 0 : 1) : ((!d3) ? 2 : 3); + } else if (d2xy == 1) { + n = (!d2xy2yz) ? ((!d3) ? 4 : 5) : 6; + } else { //>=2 + n = 7; + } + } else { + n = (v == 1) ? 8 : 9; // =1 or =2 + } + } else if (hc == 1) { + n = (!v) ? ( (!d2xy) ? ( (!d2xy2yz) ? ( (!d3) ? 10 : 11) : (12) ) : (13) ) : (14); + } else { //if (hc >= 2) + n = 15; + } + break; + //HLH, HHL, LHH + case 3: + case 5: + case 6: + hc = h + c; + d2xy2xz = d2xy + d2xz; + if (!v) { + if (!d2xz) { + if (!hc && !d2xy2xz) { + n = (!d3) ? 0 : 1; + } else if (hc == 1) { + n = (!d2xy2xz) ? 2 : 3; + } else { //if >= 2 + n = 4; + } + } else if ( d2xz>=1 && !hc ) { + n = 5; + } else if ( hc>=1 ) { + n = (d2xz==1) ? 6 : 7; + } + } else if (v == 1) { + if (!d2xz) { + n = (!hc) ? 8 : 9; + } else if (d2xz == 1) { + n = (!hc) ? 10 : 11; + } else if (d2xz == 2) { + n = (!hc) ? 12 : 13; + } else { // if (d2xz >= 3) { + n = 14; + } + } else if (v == 2) { + n = 15; + } + break; + } + + return (T1_3D_CTXNO_ZC + n); +} + +static int t1_3d_init_ctxno_sc(unsigned int f) { + int hc, vc, cc; + int n = 0; + + hc = int_min( ( (f & (T1_3D_SIG_E | T1_3D_SGN_E)) == T1_3D_SIG_E ) + + ( (f & (T1_3D_SIG_W | T1_3D_SGN_W)) == T1_3D_SIG_W ) , 1) + - int_min( ( (f & (T1_3D_SIG_E | T1_3D_SGN_E)) == (T1_3D_SIG_E | T1_3D_SGN_E) ) + + ( (f & (T1_3D_SIG_W | T1_3D_SGN_W) ) == (T1_3D_SIG_W | T1_3D_SGN_W)), 1); + + vc = int_min(((f & (T1_3D_SIG_N | T1_3D_SGN_N)) == T1_3D_SIG_N) + + ((f & (T1_3D_SIG_S | T1_3D_SGN_S)) == T1_3D_SIG_S), 1) + - int_min(((f & (T1_3D_SIG_N | T1_3D_SGN_N)) == (T1_3D_SIG_N | T1_3D_SGN_N)) + + ((f & (T1_3D_SIG_S | T1_3D_SGN_S)) == (T1_3D_SIG_S | T1_3D_SGN_S)), 1); + + cc = int_min(((f & (T1_3D_SIG_FC | T1_3D_SGN_F)) == T1_3D_SIG_FC) + + ((f & (T1_3D_SIG_BC | T1_3D_SGN_B)) == T1_3D_SIG_BC), 1) + - int_min(((f & (T1_3D_SIG_FC | T1_3D_SGN_F)) == (T1_3D_SIG_FC | T1_3D_SGN_F)) + + ((f & (T1_3D_SIG_BC | T1_3D_SGN_B)) == (T1_3D_SIG_BC | T1_3D_SGN_B)), 1); + if (hc < 0) { + hc = -hc; + vc = -vc; + cc = -cc; + } + + if (!hc) { + if (!vc) + n = (!cc) ? 0 : 1; + else if (vc == -1) + n = (!cc) ? 1 : ( (cc>0) ? 2 : 4); + else if (vc == 1) + n = (!cc) ? 1 : ( (cc<0) ? 2 : 4); + } else if (hc == 1) { + if (!vc) + n = (!cc) ? 1 : ( (cc<0) ? 2 : 4); + else if (vc == 1) + n = (!cc) ? 4 : ( (cc>0) ? 5 : 3); + else if (vc == -1) + n = (!cc) ? 2 : 3; + } else if (hc == -1) { + if (!vc) + n = (!cc) ? 1 : ( (cc>0) ? 2 : 4); + else if (vc == 1) + n = (!cc) ? 2 : 3; + else if (vc == -1) + n = (!cc) ? 4 : ( (cc<0) ? 5 : 3); + } + + return (T1_3D_CTXNO_SC + n); +} + +static int t1_3d_init_ctxno_mag(unsigned int f, int f2) { + int n; + if (!(f2 & T1_3D_REFINE)) //First refinement for this coefficient (no previous refinement) + n = (f & (T1_3D_SIG_PRIM)) ? 1 : 0; + else + n = 2; + + return (T1_3D_CTXNO_MAG + n); +} + +static int t1_3d_init_spb(unsigned int f) { + int hc, vc, cc; + int n = 0; + + hc = int_min( ( (f & (T1_3D_SIG_E | T1_3D_SGN_E)) == T1_3D_SIG_E ) + + ( (f & (T1_3D_SIG_W | T1_3D_SGN_W)) == T1_3D_SIG_W ) , 1) + - int_min( ( (f & (T1_3D_SIG_E | T1_3D_SGN_E)) == (T1_3D_SIG_E | T1_3D_SGN_E) ) + + ( (f & (T1_3D_SIG_W | T1_3D_SGN_W) ) == (T1_3D_SIG_W | T1_3D_SGN_W)), 1); + + vc = int_min(((f & (T1_3D_SIG_N | T1_3D_SGN_N)) == T1_3D_SIG_N) + + ((f & (T1_3D_SIG_S | T1_3D_SGN_S)) == T1_3D_SIG_S), 1) + - int_min(((f & (T1_3D_SIG_N | T1_3D_SGN_N)) == (T1_3D_SIG_N | T1_3D_SGN_N)) + + ((f & (T1_3D_SIG_S | T1_3D_SGN_S)) == (T1_3D_SIG_S | T1_3D_SGN_S)), 1); + + cc = int_min(((f & (T1_3D_SIG_FC | T1_3D_SGN_F)) == T1_3D_SIG_FC) + + ((f & (T1_3D_SIG_BC | T1_3D_SGN_B)) == T1_3D_SIG_BC), 1) + - int_min(((f & (T1_3D_SIG_FC | T1_3D_SGN_F)) == (T1_3D_SIG_FC | T1_3D_SGN_F)) + + ((f & (T1_3D_SIG_BC | T1_3D_SGN_B)) == (T1_3D_SIG_BC | T1_3D_SGN_B)), 1); + + n = ((hc + vc + cc) < 0); + + return n; +} + +static void t1_3d_init_luts(opj_t1_3d_t *t1) { + int i; + double u, v, t; + /*for (j = 0; j < 4; j++) { + for (i = 0; i < 256; ++i) { + t1->lut_ctxno_zc[(j << 8) | i] = t1_3d_init_ctxno_zc(i, j); + } + } + for (i = 0; i < 4096; i++) { + t1->lut_ctxno_sc[i] = t1_3d_init_ctxno_sc(i << 4); + } + for (j = 0; j < 2; j++) { + for (i = 0; i < 2048; ++i) { + t1->lut_ctxno_mag[(j << 11) + i] = t1_3d_init_ctxno_mag((j ? T1_3D_REFINE : 0) | i); + } + } + for (i = 0; i < 4096; ++i) { + t1->lut_spb[i] = t1_3d_init_spb(i << 4); + }*/ + /* FIXME FIXME FIXME */ + for (i = 0; i < (1 << T1_NMSEDEC_BITS); i++) { + t = i / pow(2, T1_NMSEDEC_FRACBITS); + u = t; + v = t - 1.5; + t1->lut_nmsedec_sig[i] = + int_max(0, + (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + t1->lut_nmsedec_sig0[i] = + 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; + } + t1->lut_nmsedec_ref[i] = + int_max(0, + (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + t1->lut_nmsedec_ref0[i] = + int_max(0, + (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0)); + } +} + +/* ----------------------------------------------------------------------- */ + +opj_t1_3d_t* t1_3d_create(opj_common_ptr cinfo) { + opj_t1_3d_t *t1 = (opj_t1_3d_t*)opj_malloc(sizeof(opj_t1_3d_t)); + if(t1) { + t1->cinfo = cinfo; + /* create MQC and RAW handles */ + t1->mqc = mqc_create(); + t1->raw = raw_create(); + /* initialize the look-up tables of the Tier-1 coder/decoder */ + t1_3d_init_luts(t1); + } + return t1; +} + +void t1_3d_destroy(opj_t1_3d_t *t1) { + if(t1) { + /* destroy MQC and RAW handles */ + mqc_destroy(t1->mqc); + raw_destroy(t1->raw); + opj_free(t1); + } +} + +void t1_3d_encode_cblks(opj_t1_3d_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp) { + int compno, resno, bandno, precno, cblkno; + int x, y, z, i, j, k, orient; + int level[3]; + tile->distotile = 0; /* fixed_quality */ + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + + for (resno = 0; resno < tilec->numresolution[0]; 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->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + + if (band->bandno == 0) { + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 1) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 2) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 3) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 4) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 5) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 6) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 7) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } + + if (tcp->tccps[compno].reversible == 1) { + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + t1->data[k][j][i] = + tilec->data[(x + i) + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)] << T1_NMSEDEC_FRACBITS; + } + } + } + } else if (tcp->tccps[compno].reversible == 0) { + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + t1->data[k][j][i] = fix_mul( + tilec->data[(x + i) + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)], + 8192 * 8192 / ((int) floor(band->stepsize * 8192))) >> (13 - T1_NMSEDEC_FRACBITS); + } + } + } + } + orient = band->bandno; /* FIXME */ + for (i = 0; i < 3; i++) + level[i] = tilec->numresolution[i] - 1 - resno; + + t1_3d_encode_cblk(t1, cblk, orient, compno, level, tcp->tccps[compno].dwtid, band->stepsize, tcp->tccps[compno].cblksty, tile->numcomps, tile); + + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ +} + +void t1_3d_decode_cblks(opj_t1_3d_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp) { + int compno, resno, bandno, precno, cblkno; + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + + for (resno = 0; resno < tilec->numresolution[0]; 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->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + int x, y, z, i, j, k, orient; + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + + orient = band->bandno; /* FIXME */ + + //fprintf(stdout,"[INFO] t1_3d_decode_cblk(t1, cblk, orient(%d), tcp->tccps[compno].roishift (%d), tcp->tccps[compno].cblksty (%d));\n",orient,tcp->tccps[compno].roishift, tcp->tccps[compno].cblksty); + t1_3d_decode_cblk(t1, cblk, orient, tcp->tccps[compno].roishift, tcp->tccps[compno].cblksty); + + if (band->bandno == 0) { + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 1) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 2) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 3) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = cblk->z0 - band->z0; + } else if (band->bandno == 4) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 5) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 6) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } else if (band->bandno == 7) { + opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1]; + x = pres->x1 - pres->x0 + cblk->x0 - band->x0; + y = pres->y1 - pres->y0 + cblk->y0 - band->y0; + z = pres->z1 - pres->z0 + cblk->z0 - band->z0; + } + + if (tcp->tccps[compno].roishift) { + int thresh, val, mag; + thresh = 1 << tcp->tccps[compno].roishift; + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + val = t1->data[k][j][i]; + mag = int_abs(val); + if (mag >= thresh) { + mag >>= tcp->tccps[compno].roishift; + t1->data[k][j][i] = val < 0 ? -mag : mag; + } + } + } + } + } + + if (tcp->tccps[compno].reversible == 1) { + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + int tmp = t1->data[k][j][i]; + tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)] = tmp/2; + } + } + } + } else { /* if (tcp->tccps[compno].reversible == 0) */ + for (k = 0; k < cblk->z1 - cblk->z0; k++) { + for (j = 0; j < cblk->y1 - cblk->y0; j++) { + for (i = 0; i < cblk->x1 - cblk->x0; i++) { + double tmp = (double)(t1->data[k][j][i] * band->stepsize * 4096.0); + if (t1->data[k][j][i] >> 1 == 0) { + tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)] = 0; + } else { + int tmp2 = ((int) (floor(fabs(tmp)))) + ((int) floor(fabs(tmp*2))%2); + tilec->data[x + i + (y + j) * (tilec->x1 - tilec->x0) + (z + k) * (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0)] = ((tmp<0)?-tmp2:tmp2); + } + } + } + } + } + } /* cblkno */ + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ +} diff --git a/src/lib/openjp3d/t1_3d.h b/src/lib/openjp3d/t1_3d.h new file mode 100755 index 00000000..dd73763d --- /dev/null +++ b/src/lib/openjp3d/t1_3d.h @@ -0,0 +1,173 @@ +/* + * Copyrigth (c) 2006, Mónica Díez, LPI-UVA, Spain + * 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_3D_H +#define __T1_3D_H +/** +@file t1_3d.h +@brief Implementation of the tier-1 coding (coding of code-block coefficients) (T1) + +The functions in T1_3D.C have for goal to realize the tier-1 coding operation of 3D-EBCOT. +The functions in T1_3D.C are used by some function in TCD.C. +*/ + +/** @defgroup T1_3D T1_3D - Implementation of the tier-1 coding */ +/*@{*/ + +/* ----------------------------------------------------------------------- */ + +/* Neighbourhood of 3D EBCOT (Significance context)*/ +#define T1_3D_SIG_NE 0x00000001 /*< Context orientation : North-East direction */ +#define T1_3D_SIG_SE 0x00000002 /*< Context orientation : South-East direction */ +#define T1_3D_SIG_SW 0x00000004 /*< Context orientation : South-West direction */ +#define T1_3D_SIG_NW 0x00000008 /* Context orientation : North-West direction */ +#define T1_3D_SIG_N 0x00000010 /*< Context orientation : North direction */ +#define T1_3D_SIG_E 0x00000020 /*< Context orientation : East direction */ +#define T1_3D_SIG_S 0x00000040 /*< Context orientation : South direction */ +#define T1_3D_SIG_W 0x00000080 /*< Context orientation : West direction */ +#define T1_3D_SIG_FC 0x00000100 /*< Context orientation : Forward Central direction */ +#define T1_3D_SIG_BC 0x00000200 /*< Context orientation : Backward Central direction */ +#define T1_3D_SIG_FNE 0x00000400 /*< Context orientation : Forward North-East direction */ +#define T1_3D_SIG_FSE 0x00000800 /*< Context orientation : Forward South-East direction */ +#define T1_3D_SIG_FSW 0x00001000 /*< Context orientation : Forward South-West direction */ +#define T1_3D_SIG_FNW 0x00002000 /*< Context orientation : Forward North-West direction */ +#define T1_3D_SIG_FN 0x00004000 /*< Context orientation : Forward North direction */ +#define T1_3D_SIG_FE 0x00008000 /*< Context orientation : Forward East direction */ +#define T1_3D_SIG_FS 0x00010000 /*< Context orientation : Forward South direction */ +#define T1_3D_SIG_FW 0x00020000 /*< Context orientation : Forward West direction */ +#define T1_3D_SIG_BNE 0x00040000 /*< Context orientation : Backward North-East direction */ +#define T1_3D_SIG_BSE 0x00080000 /*< Context orientation : Backward South-East direction */ +#define T1_3D_SIG_BSW 0x00100000 /*< Context orientation : Backward South-West direction */ +#define T1_3D_SIG_BNW 0x00200000 /*< Context orientation : Backward North-West direction */ +#define T1_3D_SIG_BN 0x00400000 /*< Context orientation : Backward North direction */ +#define T1_3D_SIG_BE 0x00800000 /*< Context orientation : Backward East direction */ +#define T1_3D_SIG_BS 0x01000000 /*< Context orientation : Backward South direction */ +#define T1_3D_SIG_BW 0x02000000 /*< Context orientation : Backward West direction */ +#define T1_3D_SIG_COTH (T1_3D_SIG_N|T1_3D_SIG_NE|T1_3D_SIG_E|T1_3D_SIG_SE|T1_3D_SIG_S|T1_3D_SIG_SW|T1_3D_SIG_W|T1_3D_SIG_NW) +#define T1_3D_SIG_BOTH (T1_3D_SIG_BN|T1_3D_SIG_BNE|T1_3D_SIG_BE|T1_3D_SIG_BSE|T1_3D_SIG_BS|T1_3D_SIG_BSW|T1_3D_SIG_BW|T1_3D_SIG_BNW|T1_3D_SIG_BC) +#define T1_3D_SIG_FOTH (T1_3D_SIG_FN|T1_3D_SIG_FNE|T1_3D_SIG_FE|T1_3D_SIG_FSE|T1_3D_SIG_FS|T1_3D_SIG_FSW|T1_3D_SIG_FW|T1_3D_SIG_FNW|T1_3D_SIG_FC) +#define T1_3D_SIG_OTH (T1_3D_SIG_FOTH|T1_3D_SIG_BOTH|T1_3D_SIG_COTH) +#define T1_3D_SIG_PRIM (T1_3D_SIG_N|T1_3D_SIG_E|T1_3D_SIG_S|T1_3D_SIG_W|T1_3D_SIG_FC|T1_3D_SIG_BC) + +#define T1_3D_SGN_N 0x0400 +#define T1_3D_SGN_E 0x0800 +#define T1_3D_SGN_S 0x1000 +#define T1_3D_SGN_W 0x2000 +#define T1_3D_SGN_F 0x4000 +#define T1_3D_SGN_B 0x8000 +#define T1_3D_SGN (T1_3D_SGN_N|T1_3D_SGN_E|T1_3D_SGN_S|T1_3D_SGN_W|T1_3D_SGN_F|T1_3D_SGN_B) + +#define T1_3D_SIG 0x0001 //Significance state +#define T1_3D_REFINE 0x0002 //Delayed significance +#define T1_3D_VISIT 0x0004 //First-pass membership + +#define T1_3D_NUMCTXS_AGG 1 +#define T1_3D_NUMCTXS_ZC 16 +#define T1_3D_NUMCTXS_MAG 3 +#define T1_3D_NUMCTXS_SC 6 +#define T1_3D_NUMCTXS_UNI 1 + +#define T1_3D_CTXNO_AGG 0 +#define T1_3D_CTXNO_ZC (T1_3D_CTXNO_AGG+T1_3D_NUMCTXS_AGG) //1 +#define T1_3D_CTXNO_MAG (T1_3D_CTXNO_ZC+T1_3D_NUMCTXS_ZC) //17 +#define T1_3D_CTXNO_SC (T1_3D_CTXNO_MAG+T1_3D_NUMCTXS_MAG) //20 +#define T1_3D_CTXNO_UNI (T1_3D_CTXNO_SC+T1_3D_NUMCTXS_SC) //26 +#define T1_3D_NUMCTXS (T1_3D_CTXNO_UNI+T1_3D_NUMCTXS_UNI) //27 + + +/* ----------------------------------------------------------------------- */ + +/** +Tier-1 coding (coding of code-block coefficients) +*/ +typedef struct opj_t1_3d { + /** Codec context */ + opj_common_ptr cinfo; + /** MQC component */ + opj_mqc_t *mqc; + /** RAW component */ + opj_raw_t *raw; + /** LUTs for decoding normalised MSE */ + 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]; + /** Codeblock data */ + int data[T1_CBLKD][T1_CBLKH][T1_CBLKW]; + /** Context information for each voxel in codeblock */ + unsigned int flags[T1_CBLKD + 2][T1_CBLKH + 2][T1_CBLKH + 2]; + /** Voxel information (significance/visited/refined) */ + int flagSVR[T1_CBLKD + 2][T1_CBLKH + 2][T1_CBLKH + 2]; +} opj_t1_3d_t; + +/** @name Exported functions */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +Create a new T1_3D handle +and initialize the look-up tables of the Tier-1 coder/decoder +@return Returns a new T1 handle if successful, returns NULL otherwise +@see t1_init_luts +*/ +opj_t1_3d_t* t1_3d_create(opj_common_ptr cinfo); +/** +Destroy a previously created T1_3D handle +@param t1 T1_3D handle to destroy +*/ +void t1_3d_destroy(opj_t1_3d_t *t1); +/** +Encode the code-blocks of a tile +@param t1 T1_3D handle +@param tile The tile to encode +@param tcp Tile coding parameters +*/ +void t1_3d_encode_cblks(opj_t1_3d_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp); +/** +Decode the code-blocks of a tile +@param t1 T1_3D handle +@param tile The tile to decode +@param tcp Tile coding parameters +*/ +void t1_3d_decode_cblks(opj_t1_3d_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp); +/** +Get weigths of MSE decoding +@param nmsedec The normalized MSE reduction +@param compno +@param level +@param orient +@param bpno +@param reversible +@param stepsize +@param numcomps +@param dwtid +returns MSE associated to decoding pass +double t1_3d_getwmsedec(int nmsedec, int compno, int levelxy, int levelz, int orient, int bpno, int reversible, double stepsize, int numcomps, int dwtid); +*/ +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __T1_H */ diff --git a/src/lib/openjp3d/t2.c b/src/lib/openjp3d/t2.c new file mode 100755 index 00000000..6638b328 --- /dev/null +++ b/src/lib/openjp3d/t2.c @@ -0,0 +1,675 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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 T2 T2 - Implementation of a tier-2 coding */ +/*@{*/ + +/** @name Local static functions */ +/*@{*/ + +static void t2_putcommacode(opj_bio_t *bio, int n); +static int 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, int n); +static int 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 volume_info Structure to create an index file +@param tileno Number of the tile encoded +@param cp Coding parameters +@return Number of bytes encoded from the packet +*/ +static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi, unsigned char *dest, int len, opj_volume_info_t *volume_info, int tileno, opj_cp_t *cp); +/** +Initialize the segment decoder +@param seg Segment instance +@param cblksty Codeblock style +@param first Is first segment +*/ +static void t2_init_seg(opj_tcd_seg_t *seg, int cblksty, int 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 Number of bytes decoded from the packet +*/ +int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi); + +/*@}*/ + +/*@}*/ + +/* ----------------------------------------------------------------------- */ + +/* #define RESTART 0x04 */ +static void t2_putcommacode(opj_bio_t *bio, int n) { + while (--n >= 0) { + bio_write(bio, 1, 1); + } + bio_write(bio, 0, 1); +} + +static int t2_getcommacode(opj_bio_t *bio) { + int n; + for (n = 0; bio_read(bio, 1); n++) { + ; + } + return n; +} + +static void t2_putnumpasses(opj_bio_t *bio, int 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 int t2_getnumpasses(opj_bio_t *bio) { + int 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 int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_iterator_t *pi, unsigned char *dest, int len, opj_volume_info_t * volume_info, int tileno, opj_cp_t *cp) { + int bandno, cblkno; + unsigned char *sop = 0, *eph = 0; + unsigned char *c = dest; + + int compno = pi->compno; /* component value */ + int resno = pi->resno; /* resolution level value */ + int precno = pi->precno; /* precinct value */ + int layno = pi->layno; /* quality layer value */ + + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + opj_bio_t *bio = NULL; /* BIO component */ + + /* */ + if ((tcp->csty & J3D_CP_CSTY_SOP)) { + sop = (unsigned char *) opj_malloc(6 * sizeof(unsigned char)); + sop[0] = 255; + sop[1] = 145; + sop[2] = 0; + sop[3] = 4; + sop[4] = (volume_info) ? (volume_info->num % 65536) / 256 : (0 % 65536) / 256 ; + sop[5] = (volume_info) ? (volume_info->num % 65536) % 256 : (0 % 65536) % 256 ; + memcpy(c, sop, 6); + opj_free(sop); + c += 6; + } + /* */ + + if (!layno) { + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + tgt_reset(prc->incltree); + tgt_reset(prc->imsbtree); + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + cblk->numpasses = 0; + tgt_setvalue(prc->imsbtree, cblkno, band->numbps - cblk->numbps); + } + } + } + + bio = bio_create(); + bio_init_enc(bio, c, len); + bio_write(bio, 1, 1); /* Empty header bit */ + + /* Writing Packet header */ + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + if (!cblk->numpasses && layer->numpasses) { + tgt_setvalue(prc->incltree, cblkno, layno); + } + } + + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + int increment = 0; + int nump = 0; + int len = 0, passno; + /* 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) { + 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); + + /* computation of the increase of the length indicator and insertion in the header */ + for (passno = cblk->numpasses; passno < cblk->numpasses + layer->numpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->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; + } + } + t2_putcommacode(bio, increment); + + /* computation of the new Length indicator */ + cblk->numlenbits += increment; + + /* insertion of the codeword segment length */ + for (passno = cblk->numpasses; passno < cblk->numpasses + layer->numpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->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; + } + } + + } + } + + + if (bio_flush(bio)) { + return -999; /* modified to eliminate longjmp !! */ + } + + c += bio_numbytes(bio); + + bio_destroy(bio); + + /* */ + if (tcp->csty & J3D_CP_CSTY_EPH) { + eph = (unsigned char *) opj_malloc(2 * sizeof(unsigned char)); + eph[0] = 255; + eph[1] = 146; + memcpy(c, eph, 2); + opj_free(eph); + c += 2; + } + /* */ + + /* Writing the packet body */ + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + if (!layer->numpasses) { + continue; + } + if (c + layer->len > dest + len) { + return -999; + } + + memcpy(c, layer->data, layer->len); + cblk->numpasses += layer->numpasses; + c += layer->len; + /* ADD for index Cfr. Marcela --> delta disto by packet */ + if(volume_info && volume_info->index_write && volume_info->index_on) { + opj_tile_info_t *info_TL = &volume_info->tile[tileno]; + opj_packet_info_t *info_PK = &info_TL->packet[volume_info->num]; + info_PK->disto += layer->disto; + if (volume_info->D_max < info_PK->disto) { + volume_info->D_max = info_PK->disto; + } + } + /* */ + } + } + + return (c - dest); +} + +static void t2_init_seg(opj_tcd_seg_t * seg, int cblksty, int first) { + seg->numpasses = 0; + seg->len = 0; + if (cblksty & J3D_CCP_CBLKSTY_TERMALL) { + seg->maxpasses = 1; + } + else if (cblksty & J3D_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; + } +} + +int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi) { + int bandno, cblkno; + unsigned char *c = src; + + opj_cp_t *cp = t2->cp; + + int compno = pi->compno; /* component value */ + int resno = pi->resno; /* resolution level value */ + int precno = pi->precno; /* precinct value */ + int layno = pi->layno; /* quality layer value */ + + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + + unsigned char *hd = NULL; + int present; + + opj_bio_t *bio = NULL; /* BIO component */ + + if (layno == 0) { + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)||(band->z1-band->z0 == 0)) continue; + + tgt_reset(prc->incltree); + tgt_reset(prc->imsbtree); + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + cblk->numsegs = 0; + } + } + } + + /* SOP markers */ + + if (tcp->csty & J3D_CP_CSTY_SOP) { + if ((*c) != 0xff || (*(c + 1) != 0x91)) { + opj_event_msg(t2->cinfo, EVT_WARNING, "Expected SOP marker\n"); + } else { + c += 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 + */ + + bio = bio_create(); + + if (cp->ppm == 1) { /* PPM */ + hd = cp->ppm_data; + bio_init_dec(bio, hd, cp->ppm_len); + } else if (tcp->ppt == 1) { /* PPT */ + hd = tcp->ppt_data; + bio_init_dec(bio, hd, tcp->ppt_len); + } else { /* Normal Case */ + hd = c; + bio_init_dec(bio, hd, src+len-hd); + } + + present = bio_read(bio, 1); + + if (!present) { + bio_inalign(bio); + hd += bio_numbytes(bio); + bio_destroy(bio); + + /* EPH markers */ + + if (tcp->csty & J3D_CP_CSTY_EPH) { + if ((*hd) != 0xff || (*(hd + 1) != 0x92)) { + printf("Error : expected EPH marker\n"); + } else { + hd += 2; + } + } + + if (cp->ppm == 1) { /* PPM case */ + cp->ppm_len += cp->ppm_data-hd; + cp->ppm_data = hd; + return (c - src); + } + if (tcp->ppt == 1) { /* PPT case */ + tcp->ppt_len+=tcp->ppt_data-hd; + tcp->ppt_data = hd; + return (c - src); + } + + return (hd - src); + } + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)||(band->z1-band->z0 == 0)) continue; + + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + int included, increment, n; + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + opj_tcd_seg_t *seg = NULL; + /* if cblk not yet included before --> inclusion tagtree */ + if (!cblk->numsegs) { + included = tgt_decode(bio, prc->incltree, cblkno, layno + 1); + /* else one bit */ + } else { + included = bio_read(bio, 1); + } + /* if cblk not included */ + if (!included) { + cblk->numnewpasses = 0; + continue; + } + /* if cblk not yet included --> zero-bitplane tagtree */ + if (!cblk->numsegs) { + int i, numimsbs; + for (i = 0; !tgt_decode(bio, prc->imsbtree, cblkno, i); i++); + numimsbs = i - 1; + cblk->numbps = band->numbps - numimsbs; + cblk->numlenbits = 3; + } + /* number of coding passes */ + cblk->numnewpasses = t2_getnumpasses(bio); + increment = t2_getcommacode(bio); + /* length indicator increment */ + cblk->numlenbits += increment; + if (!cblk->numsegs) { + seg = &cblk->segs[0]; + t2_init_seg(seg, tcp->tccps[compno].cblksty, 1); + } else { + seg = &cblk->segs[cblk->numsegs - 1]; + if (seg->numpasses == seg->maxpasses) { + t2_init_seg(++seg, tcp->tccps[compno].cblksty, 0); + } + } + n = cblk->numnewpasses; + + do { + seg->numnewpasses = int_min(seg->maxpasses - seg->numpasses, n); + seg->newlen = bio_read(bio, cblk->numlenbits + int_floorlog2(seg->numnewpasses)); + n -= seg->numnewpasses; + if (n > 0) { + t2_init_seg(++seg, tcp->tccps[compno].cblksty, 0); + } + } while (n > 0); + } + } + + if (bio_inalign(bio)) { + bio_destroy(bio); + return -999; + } + + hd += bio_numbytes(bio); + bio_destroy(bio); + + /* EPH markers */ + if (tcp->csty & J3D_CP_CSTY_EPH) { + if ((*hd) != 0xff || (*(hd + 1) != 0x92)) { + opj_event_msg(t2->cinfo, EVT_ERROR, "Expected EPH marker\n"); + } else { + hd += 2; + } + } + + if (cp->ppm==1) { + cp->ppm_len+=cp->ppm_data-hd; + cp->ppm_data = hd; + } else if (tcp->ppt == 1) { + tcp->ppt_len+=tcp->ppt_data-hd; + tcp->ppt_data = hd; + } else { + c=hd; + } + + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + opj_tcd_precinct_t *prc = &band->precincts[precno]; + + if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)||(band->z1-band->z0 == 0)) continue; + + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + opj_tcd_seg_t *seg = NULL; + if (!cblk->numnewpasses) + continue; + if (!cblk->numsegs) { + seg = &cblk->segs[0]; + cblk->numsegs++; + cblk->len = 0; + } else { + seg = &cblk->segs[cblk->numsegs - 1]; + if (seg->numpasses == seg->maxpasses) { + seg++; + cblk->numsegs++; + } + } + + do { + if (c + seg->newlen > src + len) { + return -999; + } + + memcpy(cblk->data + cblk->len, c, seg->newlen); + if (seg->numpasses == 0) { + seg->data = cblk->data + cblk->len; + } + c += seg->newlen; + cblk->len += seg->newlen; + seg->len += seg->newlen; + seg->numpasses += seg->numnewpasses; + cblk->numnewpasses -= seg->numnewpasses; + if (cblk->numnewpasses > 0) { + seg++; + cblk->numsegs++; + } + } while (cblk->numnewpasses > 0); + } + } + + return (c - src); +} + +/* ----------------------------------------------------------------------- */ + +int t2_encode_packets(opj_t2_t* t2, int tileno, opj_tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len, opj_volume_info_t *volume_info) { + unsigned char *c = dest; + int e = 0; + opj_pi_iterator_t *pi = NULL; + int pino; + + opj_volume_t *volume = t2->volume; + opj_cp_t *cp = t2->cp; + + /* create a packet iterator */ + pi = pi_create(volume, cp, tileno); + if(!pi) { + fprintf(stdout,"[ERROR] Failed to create a pi structure\n"); + return -999; + } + + if(volume_info) { + volume_info->num = 0; + } + + for (pino = 0; pino <= cp->tcps[tileno].numpocs; pino++) { + while (pi_next(&pi[pino])) { + if (pi[pino].layno < maxlayers) { + e = t2_encode_packet(tile, &cp->tcps[tileno], &pi[pino], c, dest + len - c, volume_info, tileno, cp); + //opj_event_msg(t2->cinfo, EVT_INFO, " t2_encode_packet: %d bytes coded\n",e); + if (e == -999) { + break; + } else { + c += e; + } + + /* INDEX >> */ + if(volume_info && volume_info->index_on) { + if(volume_info->index_write) { + opj_tile_info_t *info_TL = &volume_info->tile[tileno]; + opj_packet_info_t *info_PK = &info_TL->packet[volume_info->num]; + if (!volume_info->num) { + info_PK->start_pos = info_TL->end_header + 1; + } else { + info_PK->start_pos = info_TL->packet[volume_info->num - 1].end_pos + 1; + } + info_PK->end_pos = info_PK->start_pos + e - 1; + } + + volume_info->num++; + } + /* << INDEX */ + } + } + } + + /* don't forget to release pi */ + pi_destroy(pi, cp, tileno); + + if (e == -999) { + return e; + } + + return (c - dest); +} + +int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile) { + unsigned char *c = src; + opj_pi_iterator_t *pi; + int pino, e = 0; + int n = 0,i; + + opj_volume_t *volume = t2->volume; + opj_cp_t *cp = t2->cp; + + /* create a packet iterator */ + pi = pi_create(volume, cp, tileno); + if(!pi) { + /* TODO: throw an error */ + return -999; + } + + for (pino = 0; pino <= cp->tcps[tileno].numpocs; pino++) { + while (pi_next(&pi[pino])) { + if ((cp->layer==0) || (cp->layer>=((pi[pino].layno)+1))) { + e = t2_decode_packet(t2, c, src + len - c, tile, &cp->tcps[tileno], &pi[pino]); + } else { + e = 0; + } + + /* progression in resolution */ + for (i = 0; i < 3; i++){ + volume->comps[pi[pino].compno].resno_decoded[i] = (e > 0) ? int_max(pi[pino].resno, volume->comps[pi[pino].compno].resno_decoded[i]) : volume->comps[pi[pino].compno].resno_decoded[i]; + } + n++; + + if (e == -999) { /* ADD */ + break; + } else { + opj_event_msg(t2->cinfo, EVT_INFO, " t2_decode_packet: %d bytes decoded\n",e); + c += e; + } + } + } + + /* don't forget to release pi */ + pi_destroy(pi, cp, tileno); + + if (e == -999) { + return e; + } + + return (c - src); +} + +/* ----------------------------------------------------------------------- */ + +opj_t2_t* t2_create(opj_common_ptr cinfo, opj_volume_t *volume, opj_cp_t *cp) { + /* create the tcd structure */ + opj_t2_t *t2 = (opj_t2_t*)opj_malloc(sizeof(opj_t2_t)); + if(!t2) return NULL; + t2->cinfo = cinfo; + t2->volume = volume; + t2->cp = cp; + + return t2; +} + +void t2_destroy(opj_t2_t *t2) { + if(t2) { + opj_free(t2); + } +} + diff --git a/src/lib/openjp3d/t2.h b/src/lib/openjp3d/t2.h new file mode 100755 index 00000000..b937290b --- /dev/null +++ b/src/lib/openjp3d/t2.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyright (c) 2006, Mónica Díez García, Image Processing Laboratory, University of Valladolid, Spain + * 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) + +*/ + +/** @defgroup T2 T2 - Implementation of a tier-2 coding */ +/*@{*/ + +/** +Tier-2 coding +*/ +typedef struct opj_t2 { +/** Codec context */ + opj_common_ptr cinfo; +/** Encoding: pointer to the src volume. Decoding: pointer to the dst volume. */ + opj_volume_t *volume; +/** Pointer to the volume coding parameters */ + opj_cp_t *cp; +} opj_t2_t; + +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +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 volume_info structure to create an index file +@return Number of bytes written from packets +*/ +int t2_encode_packets(opj_t2_t* t2, int tileno, opj_tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len, opj_volume_info_t *volume_info); + +/** +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 +@return Number of bytes read from packets + */ +int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile); + +/** +Create a T2 handle +@param cinfo Codec context info +@param volume Source or destination volume +@param cp Volume coding parameters +@return Returns a new T2 handle if successful, returns NULL otherwise +*/ +opj_t2_t* t2_create(opj_common_ptr cinfo, opj_volume_t *volume, opj_cp_t *cp); +/** +Destroy a T2 handle +@param t2 T2 handle to destroy +*/ +void t2_destroy(opj_t2_t *t2); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __T2_H */ diff --git a/src/lib/openjp3d/tcd.c b/src/lib/openjp3d/tcd.c new file mode 100755 index 00000000..e5147e29 --- /dev/null +++ b/src/lib/openjp3d/tcd.c @@ -0,0 +1,1738 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyright (c) 2006, Mónica Díez, LPI-UVA, Spain + * 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 tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_volume_t * vol) { + int tileno, compno, resno, bandno, precno, cblkno; + + fprintf(fd, "volume {\n"); + fprintf(fd, " tw=%d, th=%d, tl=%d, x0=%d x1=%d y0=%d y1=%d z0=%d z1=%d\n", + vol->tw, vol->th, vol->tl, tcd->volume->x0, tcd->volume->x1, tcd->volume->y0, tcd->volume->y1, tcd->volume->z0, tcd->volume->z1); + + for (tileno = 0; tileno < vol->th * vol->tw * vol->tl; tileno++) { + opj_tcd_tile_t *tile = &tcd->tcd_volume->tiles[tileno]; + fprintf(fd, " tile {\n"); + fprintf(fd, " x0=%d, y0=%d, z0=%d, x1=%d, y1=%d, z1=%d, numcomps=%d\n", + tile->x0, tile->y0, tile->z0, tile->x1, tile->y1, tile->z1, tile->numcomps); + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + fprintf(fd, " tilecomp %d {\n",compno); + fprintf(fd, " x0=%d, y0=%d, z0=%d, x1=%d, y1=%d, z1=%d, numresx=%d, numresy=%d, numresz=%d\n", + tilec->x0, tilec->y0, tilec->z0, tilec->x1, tilec->y1, tilec->z1, tilec->numresolution[0], tilec->numresolution[1], tilec->numresolution[2]); + for (resno = 0; resno < tilec->numresolution[0]; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + fprintf(fd, " res %d{\n",resno); + fprintf(fd," x0=%d, y0=%d, z0=%d, x1=%d, y1=%d, z1=%d, pw=%d, ph=%d, pl=%d, numbands=%d\n", + res->x0, res->y0, res->z0, res->x1, res->y1, res->z1, res->prctno[0], res->prctno[1], res->prctno[2], res->numbands); + for (bandno = 0; bandno < res->numbands; bandno++) { + opj_tcd_band_t *band = &res->bands[bandno]; + fprintf(fd, " band %d{\n", bandno); + fprintf(fd, " x0=%d, y0=%d, z0=%d, x1=%d, y1=%d, z1=%d, stepsize=%f, numbps=%d\n", + band->x0, band->y0, band->z0, band->x1, band->y1, band->z1, band->stepsize, band->numbps); + for (precno = 0; precno < (res->prctno[0] * res->prctno[1] * res->prctno[2]); precno++) { + opj_tcd_precinct_t *prec = &band->precincts[precno]; + fprintf(fd, " prec %d{\n",precno); + fprintf(fd, " x0=%d, y0=%d, z0=%d, x1=%d, y1=%d, z1=%d, cw=%d, ch=%d, cl=%d,\n", + prec->x0, prec->y0, prec->z0, prec->x1, prec->y1, prec->z1, prec->cblkno[0], prec->cblkno[1], prec->cblkno[2]); + for (cblkno = 0; cblkno < (prec->cblkno[0] * prec->cblkno[1] * prec->cblkno[2]); cblkno++) { + opj_tcd_cblk_t *cblk = &prec->cblks[cblkno]; + fprintf(fd, " cblk %d{\n",cblkno); + fprintf(fd, " x0=%d, y0=%d, z0=%d, x1=%d, y1=%d, z1=%d\n", cblk->x0, cblk->y0, cblk->z0, cblk->x1, cblk->y1, cblk->z1); + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, " }\n"); + } + fprintf(fd, "}\n"); +} + +void tilec_dump(FILE *fd, opj_tcd_tilecomp_t *tilec) { + + int i=0,k; + int datalen; + int *a; + + fprintf(fd, " tilecomp{\n"); + fprintf(fd, " x0=%d, y0=%d, z0=%d, x1=%d, y1=%d, z1=%d, numresx=%d, numresy=%d, numresz=%d\n", + tilec->x0, tilec->y0, tilec->z0, tilec->x1, tilec->y1, tilec->z1, tilec->numresolution[0], tilec->numresolution[1], tilec->numresolution[2]); + fprintf(fd, " data {\n"); + datalen = (tilec->z1 - tilec->z0) * (tilec->y1 - tilec->y0) * (tilec->x1 - tilec->x0); + a = tilec->data; + for (k = 0; k < datalen; k++) { + if (!(k % tilec->x1)){ + fprintf(fd, "\n"); + } + if (!(k % (tilec->y1 * tilec->x1))){ + fprintf(fd, "Slice %d\n",i++); + } + fprintf(fd," %d",a[k]); + + + } + fprintf(fd, " }\n"); + /*i=0; + fprintf(fd, "Slice %d\n"); + if (tilec->prediction->prederr) { + fprintf(fd, " prederror {\n"); + a = tilec->prediction->prederr; + for (k = 0; k < datalen; k++) { + fprintf(fd," %d",*(a++)); + if (!(k % (tilec->y1 - tilec->y0) * (tilec->x1 - tilec->x0))){ + fprintf(fd, "\n");fprintf(fd, "Slice %d\n",i++); + } + if (!(k % (tilec->x1 - tilec->x0))){ + fprintf(fd, "\n"); + } + } + } + fprintf(fd, " }\n");*/ + fprintf(fd, "}\n"); +} + +/* ----------------------------------------------------------------------- */ + +/** +Create a new TCD handle +*/ +opj_tcd_t* tcd_create(opj_common_ptr cinfo) { + /* create the tcd structure */ + opj_tcd_t *tcd = (opj_tcd_t*)opj_malloc(sizeof(opj_tcd_t)); + if(!tcd) return NULL; + tcd->cinfo = cinfo; + tcd->tcd_volume = (opj_tcd_volume_t*)opj_malloc(sizeof(opj_tcd_volume_t)); + if(!tcd->tcd_volume) { + opj_free(tcd); + return NULL; + } + + return tcd; +} + +/** +Destroy a previously created TCD handle +*/ +void tcd_destroy(opj_tcd_t *tcd) { + if(tcd) { + opj_free(tcd->tcd_volume); + opj_free(tcd); + } +} + +/* ----------------------------------------------------------------------- */ +void tcd_malloc_encode(opj_tcd_t *tcd, opj_volume_t * volume, opj_cp_t * cp, int curtileno) { + int compno, resno, bandno, precno, cblkno, i, j;//, k; + + opj_tcd_tile_t *tile = NULL; /* pointer to tcd->tile */ + opj_tcd_tilecomp_t *tilec = NULL; /* pointer to tcd->tilec */ + opj_tcd_resolution_t *res = NULL; /* pointer to tcd->res */ + opj_tcd_band_t *band = NULL; /* pointer to tcd->band */ + opj_tcd_precinct_t *prc = NULL; /* pointer to tcd->prc */ + opj_tcd_cblk_t *cblk = NULL; /* pointer to tcd->cblk */ + opj_tcp_t *tcp = &cp->tcps[curtileno]; + int p,q,r; + + tcd->volume = volume; + tcd->cp = cp; + tcd->tcd_volume->tw = cp->tw; + tcd->tcd_volume->th = cp->th; + tcd->tcd_volume->tl = cp->tl; + tcd->tcd_volume->tiles = (opj_tcd_tile_t *) opj_malloc(sizeof(opj_tcd_tile_t)); + tcd->tile = tcd->tcd_volume->tiles; + tile = tcd->tile; + + + /* p61 ISO/IEC IS15444-1 : 2002 */ + /* curtileno --> raster scanned index of tiles */ + /* p,q,r --> matricial index of tiles */ + p = curtileno % cp->tw; + q = curtileno / cp->tw; + r = curtileno / (cp->tw * cp->th); /* extension to 3-D */ + + /* 4 borders of the tile rescale on the volume if necessary (B.3)*/ + tile->x0 = int_max(cp->tx0 + p * cp->tdx, volume->x0); + tile->y0 = int_max(cp->ty0 + q * cp->tdy, volume->y0); + tile->z0 = int_max(cp->tz0 + r * cp->tdz, volume->z0); + tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, volume->x1); + tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, volume->y1); + tile->z1 = int_min(cp->tz0 + (r + 1) * cp->tdz, volume->z1); + tile->numcomps = volume->numcomps; + + /* Modification of the RATE >> */ + for (j = 0; j < tcp->numlayers; j++) { + if (tcp->rates[j] <= 1) { + tcp->rates[j] = 0; + } else { + float num = (float) (tile->numcomps * (tile->x1 - tile->x0) * (tile->y1 - tile->y0) * (tile->z1 - tile->z0) * volume->comps[0].prec); + float den = (float) (8 * volume->comps[0].dx * volume->comps[0].dy * volume->comps[0].dz); + den = tcp->rates[j] * den; + tcp->rates[j] = (num + den - 1) / den; + } + /*tcp->rates[j] = tcp->rates[j] ? int_ceildiv( + tile->numcomps * (tile->x1 - tile->x0) * (tile->y1 - tile->y0) * (tile->z1 - tile->z0) * volume->comps[0].prec, + (tcp->rates[j] * 8 * volume->comps[0].dx * volume->comps[0].dy * volume->comps[0].dz)) : 0;*/ + if (tcp->rates[j]) { + if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) { + tcp->rates[j] = tcp->rates[j - 1] + 20; + } else if (!j && tcp->rates[j] < 30){ + tcp->rates[j] = 30; + } + } + } + /* << Modification of the RATE */ + + tile->comps = (opj_tcd_tilecomp_t *) opj_malloc(volume->numcomps * sizeof(opj_tcd_tilecomp_t)); + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tccp_t *tccp = &tcp->tccps[compno]; + int res_max; + int prevnumbands = 0; + + /* opj_tcd_tilecomp_t *tilec=&tile->comps[compno]; */ + tcd->tilec = &tile->comps[compno]; + tilec = tcd->tilec; + + /* border of each tile component (global) (B.3) */ + tilec->x0 = int_ceildiv(tile->x0, volume->comps[compno].dx); + tilec->y0 = int_ceildiv(tile->y0, volume->comps[compno].dy); + tilec->z0 = int_ceildiv(tile->z0, volume->comps[compno].dz); + tilec->x1 = int_ceildiv(tile->x1, volume->comps[compno].dx); + tilec->y1 = int_ceildiv(tile->y1, volume->comps[compno].dy); + tilec->z1 = int_ceildiv(tile->z1, volume->comps[compno].dz); + + tilec->data = (int *) opj_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * (tilec->z1 - tilec->z0) * sizeof(int)); + + res_max = 0; + for (i = 0;i < 3; i++){ + tilec->numresolution[i] = tccp->numresolution[i]; + //Greater of 3 resolutions contains all information + res_max = (tilec->numresolution[i] > res_max) ? tilec->numresolution[i] : res_max; + } + + + tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(res_max * sizeof(opj_tcd_resolution_t)); + for (resno = 0; resno < res_max; resno++) { + + int pdx, pdy, pdz; + int tlprcxstart, tlprcystart, tlprczstart; + int brprcxend, brprcyend, brprczend; + int tlcbgxstart, tlcbgystart, tlcbgzstart; + int brcbgxend, brcbgyend, brcbgzend; + int cbgwidthexpn, cbgheightexpn, cbglengthexpn; + int cblkwidthexpn, cblkheightexpn, cblklengthexpn; + + int diff = tccp->numresolution[0] - tccp->numresolution[2]; + int levelnox = tilec->numresolution[0] - 1 - resno; + int levelnoy = tilec->numresolution[1] - 1 - resno; + int levelnoz = tilec->numresolution[2] - 1 - ((resno <= diff) ? 0 : (resno - diff)); + if (levelnoz < 0) levelnoz = 0; + + /* opj_tcd_resolution_t *res=&tilec->resolutions[resno]; */ + tcd->res = &tilec->resolutions[resno]; + res = tcd->res; + + /* border for each resolution level (global) (B.14)*/ + res->x0 = int_ceildivpow2(tilec->x0, levelnox); + res->y0 = int_ceildivpow2(tilec->y0, levelnoy); + res->z0 = int_ceildivpow2(tilec->z0, levelnoz); + res->x1 = int_ceildivpow2(tilec->x1, levelnox); + res->y1 = int_ceildivpow2(tilec->y1, levelnoy); + res->z1 = int_ceildivpow2(tilec->z1, levelnoz); + //if (res->z1 < 0)fprintf(stdout,"Res: %d %d/%d --> %d\n",resno,tilec->z1, levelnoz, int_ceildivpow2(tilec->z1, levelnoz)); + + res->numbands = (resno == 0) ? 1 : (resno <= diff) ? 3 : 7; /* --> 3D */ + + /* p. 30, table A-13, ISO/IEC IS154444-1 : 2002 */ + if (tccp->csty & J3D_CCP_CSTY_PRT) { + pdx = tccp->prctsiz[0][resno]; + pdy = tccp->prctsiz[1][resno]; + pdz = tccp->prctsiz[2][resno]; + } else { + pdx = 15; + pdy = 15; + pdz = 15; + } + + /* p. 66, B.16, ISO/IEC IS15444-1 : 2002 */ + tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx; + tlprcystart = int_floordivpow2(res->y0, pdy) << pdy; + tlprczstart = int_floordivpow2(res->z0, pdz) << pdz; + brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; + brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; + brprczend = int_ceildivpow2(res->z1, pdz) << pdz; + + res->prctno[0] = (brprcxend - tlprcxstart) >> pdx; + res->prctno[1] = (brprcyend - tlprcystart) >> pdy; + res->prctno[2] = (brprczend - tlprczstart) >> pdz; + if (res->prctno[2] == 0) res->prctno[2] = 1; + + /* p. 67, B.17 & B.18, ISO/IEC IS15444-1 : 2002 */ + if (resno == 0) { + tlcbgxstart = tlprcxstart; + tlcbgystart = tlprcystart; + tlcbgzstart = tlprczstart; + brcbgxend = brprcxend; + brcbgyend = brprcyend; + brcbgzend = brprczend; + cbgwidthexpn = pdx; + cbgheightexpn = pdy; + cbglengthexpn = pdz; + } else { + tlcbgxstart = int_ceildivpow2(tlprcxstart, 1); + tlcbgystart = int_ceildivpow2(tlprcystart, 1); + tlcbgzstart = int_ceildivpow2(tlprczstart, 1); + brcbgxend = int_ceildivpow2(brprcxend, 1); + brcbgyend = int_ceildivpow2(brprcyend, 1); + brcbgzend = int_ceildivpow2(brprczend, 1); + cbgwidthexpn = pdx - 1; + cbgheightexpn = pdy - 1; + cbglengthexpn = pdz - 1; + } + + cblkwidthexpn = int_min(tccp->cblk[0], cbgwidthexpn); //6 + cblkheightexpn = int_min(tccp->cblk[1], cbgheightexpn); //6 + cblklengthexpn = int_min(tccp->cblk[2], cbglengthexpn); //6 + + res->bands = (opj_tcd_band_t *) opj_malloc(res->numbands * sizeof(opj_tcd_band_t)); + for (bandno = 0; bandno < res->numbands; bandno++) { + int x0b, y0b, z0b, i; + int gain, numbps; + opj_stepsize_t *ss = NULL; + + tcd->band = &res->bands[bandno]; + band = tcd->band; + + band->bandno = (resno == 0) ? 0 : bandno + 1; + /* Bandno: 0 - LLL 2 - LHL + 1 - HLL 3 - HHL + 4 - LLH 6 - LHH + 5 - HLH 7 - HHH */ + x0b = (band->bandno == 1) || (band->bandno == 3) || (band->bandno == 5 ) || (band->bandno == 7 ) ? 1 : 0; + y0b = (band->bandno == 2) || (band->bandno == 3) || (band->bandno == 6 ) || (band->bandno == 7 ) ? 1 : 0; + z0b = (band->bandno == 4) || (band->bandno == 5) || (band->bandno == 6 ) || (band->bandno == 7 ) ? 1 : 0; + + /* p. 65, B.15, ISO/IEC IS15444-1 : 2002 */ + if (band->bandno == 0) { + /* band border (global) */ + band->x0 = int_ceildivpow2(tilec->x0, levelnox); + band->y0 = int_ceildivpow2(tilec->y0, levelnoy); + band->z0 = int_ceildivpow2(tilec->z0, levelnoz); + band->x1 = int_ceildivpow2(tilec->x1, levelnox); + band->y1 = int_ceildivpow2(tilec->y1, levelnoy); + band->z1 = int_ceildivpow2(tilec->z1, levelnoz); + } else { + band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelnox) * x0b, levelnox + 1); + band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelnoy) * y0b, levelnoy + 1); + band->z0 = int_ceildivpow2(tilec->z0 - (1 << levelnoz) * z0b, (resno <= diff) ? levelnoz : levelnoz + 1); + band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelnox) * x0b, levelnox + 1); + band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelnoy) * y0b, levelnoy + 1); + band->z1 = int_ceildivpow2(tilec->z1 - (1 << levelnoz) * z0b, (resno <= diff) ? levelnoz : levelnoz + 1); + } + + ss = &tccp->stepsizes[(resno == 0) ? 0 : (prevnumbands + bandno + 1)]; + if (bandno == (res->numbands - 1)) + prevnumbands += (resno == 0) ? 0 : res->numbands; + gain = dwt_getgain(band->bandno,tccp->reversible); + numbps = volume->comps[compno].prec + gain; + band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn)); + band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ + + band->precincts = (opj_tcd_precinct_t *) opj_malloc((res->prctno[0] * res->prctno[1] * res->prctno[2]) * sizeof(opj_tcd_precinct_t)); + + for (i = 0; i < (res->prctno[0] * res->prctno[1] * res->prctno[2]); i++) { + band->precincts[i].imsbtree = NULL; + band->precincts[i].incltree = NULL; + } + + for (precno = 0; precno < (res->prctno[0] * res->prctno[1] * res->prctno[2]); precno++) { + int tlcblkxstart, tlcblkystart, tlcblkzstart, brcblkxend, brcblkyend, brcblkzend; + int cbgxstart, cbgystart, cbgzstart, cbgxend, cbgyend, cbgzend; + + cbgxstart = tlcbgxstart + (precno % res->prctno[0]) * (1 << cbgwidthexpn); + cbgystart = tlcbgystart + ((precno % (res->prctno[0] * res->prctno[1])) / res->prctno[0]) * (1 << cbgheightexpn); + cbgzstart = tlcbgzstart + (precno / (res->prctno[0] * res->prctno[1])) * (1 << cbglengthexpn); + cbgxend = cbgxstart + (1 << cbgwidthexpn); + cbgyend = cbgystart + (1 << cbgheightexpn); + cbgzend = cbgzstart + (1 << cbglengthexpn); + + tcd->prc = &band->precincts[precno]; + prc = tcd->prc; + + /* precinct size (global) */ + prc->x0 = int_max(cbgxstart, band->x0); + prc->y0 = int_max(cbgystart, band->y0); + prc->z0 = int_max(cbgzstart, band->z0); + prc->x1 = int_min(cbgxend, band->x1); + prc->y1 = int_min(cbgyend, band->y1); + prc->z1 = int_min(cbgzend, band->z1); + + tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn; + tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn; + tlcblkzstart = int_floordivpow2(prc->z0, cblklengthexpn) << cblklengthexpn; + brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn; + brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn; + brcblkzend = int_ceildivpow2(prc->z1, cblklengthexpn) << cblklengthexpn; + prc->cblkno[0] = (brcblkxend - tlcblkxstart) >> cblkwidthexpn; + prc->cblkno[1] = (brcblkyend - tlcblkystart) >> cblkheightexpn; + prc->cblkno[2] = (brcblkzend - tlcblkzstart) >> cblklengthexpn; + prc->cblkno[2] = (prc->cblkno[2] == 0) ? 1 : prc->cblkno[2]; + + prc->cblks = (opj_tcd_cblk_t *) opj_malloc((prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]) * sizeof(opj_tcd_cblk_t)); + prc->incltree = tgt_create(prc->cblkno[0], prc->cblkno[1], prc->cblkno[2]); + prc->imsbtree = tgt_create(prc->cblkno[0], prc->cblkno[1], prc->cblkno[2]); + //tgt_tree_dump(stdout,prc->incltree); + for (cblkno = 0; cblkno < (prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]); cblkno++) { + int cblkxstart = tlcblkxstart + (cblkno % prc->cblkno[0]) * (1 << cblkwidthexpn); + int cblkystart = tlcblkystart + ((cblkno % (prc->cblkno[0] * prc->cblkno[1])) / prc->cblkno[0]) * (1 << cblkheightexpn); + int cblkzstart = tlcblkzstart + (cblkno / (prc->cblkno[0] * prc->cblkno[1])) * (1 << cblklengthexpn); + int cblkxend = cblkxstart + (1 << cblkwidthexpn); + int cblkyend = cblkystart + (1 << cblkheightexpn); + int cblkzend = cblkzstart + (1 << cblklengthexpn); + int prec = ((tilec->bpp > 16) ? 3 : ((tilec->bpp > 8) ? 2 : 1)); + + tcd->cblk = &prc->cblks[cblkno]; + cblk = tcd->cblk; + + /* code-block size (global) */ + cblk->x0 = int_max(cblkxstart, prc->x0); + cblk->y0 = int_max(cblkystart, prc->y0); + cblk->z0 = int_max(cblkzstart, prc->z0); + cblk->x1 = int_min(cblkxend, prc->x1); + cblk->y1 = int_min(cblkyend, prc->y1); + cblk->z1 = int_min(cblkzend, prc->z1); + } + } + } + } + } + //tcd_dump(stdout, tcd, tcd->tcd_volume); + +} +void tcd_init_encode(opj_tcd_t *tcd, opj_volume_t * volume, opj_cp_t * cp, int curtileno) { + int compno, resno, bandno, precno, cblkno; + int j, p, q, r; + + opj_tcd_tile_t *tile = NULL; /* pointer to tcd->tile */ + opj_tcd_tilecomp_t *tilec = NULL; /* pointer to tcd->tilec */ + opj_tcd_resolution_t *res = NULL; /* pointer to tcd->res */ + opj_tcd_band_t *band = NULL; /* pointer to tcd->band */ + opj_tcd_precinct_t *prc = NULL; /* pointer to tcd->prc */ + opj_tcd_cblk_t *cblk = NULL; /* pointer to tcd->cblk */ + opj_tcp_t *tcp = &cp->tcps[curtileno]; + + tcd->tile = tcd->tcd_volume->tiles; + tile = tcd->tile; + + /* p61 ISO/IEC IS15444-1 : 2002 */ + /* curtileno --> raster scanned index of tiles */ + /* p,q,r --> matricial index of tiles */ + p = curtileno % cp->tw; + q = curtileno / cp->tw; + r = curtileno / (cp->tw * cp->th); /* extension to 3-D */ + + /* 4 borders of the tile rescale on the volume if necessary (B.3)*/ + tile->x0 = int_max(cp->tx0 + p * cp->tdx, volume->x0); + tile->y0 = int_max(cp->ty0 + q * cp->tdy, volume->y0); + tile->z0 = int_max(cp->tz0 + r * cp->tdz, volume->z0); + tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, volume->x1); + tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, volume->y1); + tile->z1 = int_min(cp->tz0 + (r + 1) * cp->tdz, volume->z1); + tile->numcomps = volume->numcomps; + + /* Modification of the RATE >> */ + for (j = 0; j < tcp->numlayers; j++) { + if (tcp->rates[j] <= 1) { + tcp->rates[j] = 0; + } else { + float num = (float) (tile->numcomps * (tile->x1 - tile->x0) * (tile->y1 - tile->y0) * (tile->z1 - tile->z0) * volume->comps[0].prec); + float den = (float) (8 * volume->comps[0].dx * volume->comps[0].dy * volume->comps[0].dz); + den = tcp->rates[j] * den; + tcp->rates[j] = (num + den - 1) / den; + } + /*tcp->rates[j] = tcp->rates[j] ? int_ceildiv( + tile->numcomps * (tile->x1 - tile->x0) * (tile->y1 - tile->y0) * (tile->z1 - tile->z0) * volume->comps[0].prec, + (tcp->rates[j] * 8 * volume->comps[0].dx * volume->comps[0].dy * volume->comps[0].dz)) : 0;*/ + if (tcp->rates[j]) { + if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) { + tcp->rates[j] = tcp->rates[j - 1] + 20; + } else if (!j && tcp->rates[j] < 30){ + tcp->rates[j] = 30; + } + } + } + /* << Modification of the RATE */ + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tccp_t *tccp = &tcp->tccps[compno]; + int res_max, i; + int prevnumbands = 0; + + /* opj_tcd_tilecomp_t *tilec=&tile->comps[compno]; */ + tcd->tilec = &tile->comps[compno]; + tilec = tcd->tilec; + + /* border of each tile component (global) (B.3) */ + tilec->x0 = int_ceildiv(tile->x0, volume->comps[compno].dx); + tilec->y0 = int_ceildiv(tile->y0, volume->comps[compno].dy); + tilec->z0 = int_ceildiv(tile->z0, volume->comps[compno].dz); + tilec->x1 = int_ceildiv(tile->x1, volume->comps[compno].dx); + tilec->y1 = int_ceildiv(tile->y1, volume->comps[compno].dy); + tilec->z1 = int_ceildiv(tile->z1, volume->comps[compno].dz); + + tilec->data = (int *) opj_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * (tilec->z1 - tilec->z0) * sizeof(int)); + + res_max = 0; + for (i = 0;i < 3; i++){ + tilec->numresolution[i] = tccp->numresolution[i]; + //Greater of 3 resolutions contains all information + res_max = (tilec->numresolution[i] > res_max) ? tilec->numresolution[i] : res_max; + } + + tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(res_max * sizeof(opj_tcd_resolution_t)); + for (resno = 0; resno < res_max; resno++) { + int pdx, pdy, pdz; + int tlprcxstart, tlprcystart, tlprczstart, brprcxend, brprcyend, brprczend; + int tlcbgxstart, tlcbgystart, tlcbgzstart, brcbgxend, brcbgyend, brcbgzend; + int cbgwidthexpn, cbgheightexpn, cbglengthexpn; + int cblkwidthexpn, cblkheightexpn, cblklengthexpn; + + int levelnox = tilec->numresolution[0] - 1 - resno; + int levelnoy = tilec->numresolution[1] - 1 - resno; + int diff = tccp->numresolution[0] - tccp->numresolution[2]; + int levelnoz = tilec->numresolution[2] - 1 - ((resno <= diff) ? 0 : (resno - diff)); + if (levelnoz < 0) levelnoz = 0; + + tcd->res = &tilec->resolutions[resno]; + res = tcd->res; + + /* border for each resolution level (global) (B.14)*/ + res->x0 = int_ceildivpow2(tilec->x0, levelnox); + res->y0 = int_ceildivpow2(tilec->y0, levelnoy); + res->z0 = int_ceildivpow2(tilec->z0, levelnoz); + res->x1 = int_ceildivpow2(tilec->x1, levelnox); + res->y1 = int_ceildivpow2(tilec->y1, levelnoy); + res->z1 = int_ceildivpow2(tilec->z1, levelnoz); + + // res->numbands = resno == 0 ? 1 : 3; /* --> 2D */ + res->numbands = (resno == 0) ? 1 : (resno <= diff) ? 3 : 7; /* --> 3D */ + + /* p. 30, table A-13, ISO/IEC IS154444-1 : 2002 */ + if (tccp->csty & J3D_CCP_CSTY_PRT) { + pdx = tccp->prctsiz[0][resno]; + pdy = tccp->prctsiz[1][resno]; + pdz = tccp->prctsiz[2][resno]; + } else { + pdx = 15; + pdy = 15; + pdz = 15; + } + /* p. 66, B.16, ISO/IEC IS15444-1 : 2002 */ + tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx; + tlprcystart = int_floordivpow2(res->y0, pdy) << pdy; + tlprczstart = int_floordivpow2(res->z0, pdz) << pdz; + brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; + brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; + brprczend = int_ceildivpow2(res->z1, pdz) << pdz; + + res->prctno[0] = (brprcxend - tlprcxstart) >> pdx; + res->prctno[1] = (brprcyend - tlprcystart) >> pdy; + res->prctno[2] = (brprczend - tlprczstart) >> pdz; + if (res->prctno[2] == 0) res->prctno[2] = 1; + + /* p. 67, B.17 & B.18, ISO/IEC IS15444-1 : 2002 */ + if (resno == 0) { + tlcbgxstart = tlprcxstart; + tlcbgystart = tlprcystart; + tlcbgzstart = tlprczstart; + brcbgxend = brprcxend; + brcbgyend = brprcyend; + brcbgzend = brprczend; + cbgwidthexpn = pdx; + cbgheightexpn = pdy; + cbglengthexpn = pdz; + } else { + tlcbgxstart = int_ceildivpow2(tlprcxstart, 1); + tlcbgystart = int_ceildivpow2(tlprcystart, 1); + tlcbgzstart = int_ceildivpow2(tlprczstart, 1); + brcbgxend = int_ceildivpow2(brprcxend, 1); + brcbgyend = int_ceildivpow2(brprcyend, 1); + brcbgzend = int_ceildivpow2(brprczend, 1); + cbgwidthexpn = pdx - 1; + cbgheightexpn = pdy - 1; + cbglengthexpn = pdz - 1; + } + + cblkwidthexpn = int_min(tccp->cblk[0], cbgwidthexpn); + cblkheightexpn = int_min(tccp->cblk[1], cbgheightexpn); + cblklengthexpn = int_min(tccp->cblk[2], cbglengthexpn); + + res->bands = (opj_tcd_band_t *) opj_malloc(res->numbands * sizeof(opj_tcd_band_t)); + for (bandno = 0; bandno < res->numbands; bandno++) { + int x0b, y0b, z0b; + int gain, numbps; + opj_stepsize_t *ss = NULL; + + tcd->band = &res->bands[bandno]; + band = tcd->band; + + band->bandno = resno == 0 ? 0 : bandno + 1; + /* Bandno: 0 - LLL 2 - LHL + 1 - HLL 3 - HHL + 4 - LLH 6 - LHH + 5 - HLH 7 - HHH */ + x0b = (band->bandno == 1) || (band->bandno == 3) || (band->bandno == 5 ) || (band->bandno == 7 ) ? 1 : 0; + y0b = (band->bandno == 2) || (band->bandno == 3) || (band->bandno == 6 ) || (band->bandno == 7 ) ? 1 : 0; + z0b = (band->bandno == 4) || (band->bandno == 5) || (band->bandno == 6 ) || (band->bandno == 7 ) ? 1 : 0; + + /* p. 65, B.15, ISO/IEC IS15444-1 : 2002 */ + if (band->bandno == 0) { + /* band border (global) */ + band->x0 = int_ceildivpow2(tilec->x0, levelnox); + band->y0 = int_ceildivpow2(tilec->y0, levelnoy); + band->z0 = int_ceildivpow2(tilec->z0, levelnoz); + band->x1 = int_ceildivpow2(tilec->x1, levelnox); + band->y1 = int_ceildivpow2(tilec->y1, levelnoy); + band->z1 = int_ceildivpow2(tilec->z1, levelnoz); + } else { + band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelnox) * x0b, levelnox + 1); + band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelnoy) * y0b, levelnoy + 1); + band->z0 = int_ceildivpow2(tilec->z0 - (1 << levelnoz) * z0b, (resno <= diff) ? levelnoz : levelnoz + 1); + band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelnox) * x0b, levelnox + 1); + band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelnoy) * y0b, levelnoy + 1); + band->z1 = int_ceildivpow2(tilec->z1 - (1 << levelnoz) * z0b, (resno <= diff) ? levelnoz : levelnoz + 1); + } + + ss = &tccp->stepsizes[(resno == 0) ? 0 : (prevnumbands + bandno + 1)]; + if (bandno == (res->numbands - 1)) + prevnumbands += (resno == 0) ? 0 : res->numbands; + gain = dwt_getgain(band->bandno,tccp->reversible); + numbps = volume->comps[compno].prec + gain; + + band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn)); + band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ + + for (precno = 0; precno < res->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + int tlcblkxstart, tlcblkystart, tlcblkzstart, brcblkxend, brcblkyend, brcblkzend; + + int cbgxstart = tlcbgxstart + (precno % res->prctno[0]) * (1 << cbgwidthexpn); + int cbgystart = tlcbgystart + ((precno / (res->prctno[0] * res->prctno[1])) / res->prctno[0]) * (1 << cbgheightexpn); + int cbgzstart = tlcbgzstart + (precno / (res->prctno[0] * res->prctno[1])) * (1 << cbglengthexpn); + int cbgxend = cbgxstart + (1 << cbgwidthexpn); + int cbgyend = cbgystart + (1 << cbgheightexpn); + int cbgzend = cbgzstart + (1 << cbglengthexpn); + + /* opj_tcd_precinct_t *prc=&band->precincts[precno]; */ + tcd->prc = &band->precincts[precno]; + prc = tcd->prc; + + /* precinct size (global) */ + prc->x0 = int_max(cbgxstart, band->x0); + prc->y0 = int_max(cbgystart, band->y0); + prc->z0 = int_max(cbgzstart, band->z0); + prc->x1 = int_min(cbgxend, band->x1); + prc->y1 = int_min(cbgyend, band->y1); + prc->z1 = int_min(cbgzend, band->z1); + + tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn; + tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn; + tlcblkzstart = int_floordivpow2(prc->z0, cblklengthexpn) << cblklengthexpn; + brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn; + brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn; + brcblkzend = int_ceildivpow2(prc->z1, cblklengthexpn) << cblklengthexpn; + prc->cblkno[0] = (brcblkxend - tlcblkxstart) >> cblkwidthexpn; + prc->cblkno[1] = (brcblkyend - tlcblkystart) >> cblkheightexpn; + prc->cblkno[2] = (brcblkzend - tlcblkzstart) >> cblklengthexpn; + prc->cblkno[2] = (prc->cblkno[2] == 0) ? 1 : prc->cblkno[2]; + + opj_free(prc->cblks); + prc->cblks = (opj_tcd_cblk_t *) opj_malloc((prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]) * sizeof(opj_tcd_cblk_t)); + prc->incltree = tgt_create(prc->cblkno[0], prc->cblkno[1], prc->cblkno[2]); + prc->imsbtree = tgt_create(prc->cblkno[0], prc->cblkno[1], prc->cblkno[2]); + + for (cblkno = 0; cblkno < (prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]); cblkno++) { + int cblkxstart = tlcblkxstart + (cblkno % prc->cblkno[0]) * (1 << cblkwidthexpn); + int cblkystart = tlcblkystart + ((cblkno % (prc->cblkno[0] * prc->cblkno[1])) / prc->cblkno[0]) * (1 << cblkheightexpn); + int cblkzstart = tlcblkzstart + (cblkno / (prc->cblkno[0] * prc->cblkno[1])) * (1 << cblklengthexpn); + int cblkxend = cblkxstart + (1 << cblkwidthexpn); + int cblkyend = cblkystart + (1 << cblkheightexpn); + int cblkzend = cblkzstart + (1 << cblklengthexpn); + int prec = ((tilec->bpp > 16) ? 3 : ((tilec->bpp > 8) ? 2 : 1)); + + tcd->cblk = &prc->cblks[cblkno]; + cblk = tcd->cblk; + + /* code-block size (global) */ + cblk->x0 = int_max(cblkxstart, prc->x0); + cblk->y0 = int_max(cblkystart, prc->y0); + cblk->z0 = int_max(cblkzstart, prc->z0); + cblk->x1 = int_min(cblkxend, prc->x1); + cblk->y1 = int_min(cblkyend, prc->y1); + cblk->z1 = int_min(cblkzend, prc->z1); + } + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ + //tcd_dump(stdout, tcd, tcd->tcd_volume); +} + + +void tcd_free_encode(opj_tcd_t *tcd) { + int tileno, compno, resno, bandno, precno; + + opj_tcd_tile_t *tile = NULL; /* pointer to tcd->tile */ +// opj_tcd_slice_t *slice = NULL; /* pointer to tcd->slice */ + opj_tcd_tilecomp_t *tilec = NULL; /* pointer to tcd->tilec */ + opj_tcd_resolution_t *res = NULL; /* pointer to tcd->res */ + opj_tcd_band_t *band = NULL; /* pointer to tcd->band */ + opj_tcd_precinct_t *prc = NULL; /* pointer to tcd->prc */ + + for (tileno = 0; tileno < 1; tileno++) { + tcd->tile = tcd->tcd_volume->tiles; + tile = tcd->tile; + + for (compno = 0; compno < tile->numcomps; compno++) { + tcd->tilec = &tile->comps[compno]; + tilec = tcd->tilec; + + for (resno = 0; resno < tilec->numresolution[0]; resno++) { + tcd->res = &tilec->resolutions[resno]; + res = tcd->res; + + for (bandno = 0; bandno < res->numbands; bandno++) { + tcd->band = &res->bands[bandno]; + band = tcd->band; + + for (precno = 0; precno < res->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + tcd->prc = &band->precincts[precno]; + prc = tcd->prc; + + if (prc->incltree != NULL) { + tgt_destroy(prc->incltree); + prc->incltree = NULL; + } + if (prc->imsbtree != NULL) { + tgt_destroy(prc->imsbtree); + prc->imsbtree = NULL; + } + opj_free(prc->cblks); + prc->cblks = NULL; + } /* for (precno */ + opj_free(band->precincts); + band->precincts = NULL; + } /* for (bandno */ + } /* for (resno */ + opj_free(tilec->resolutions); + tilec->resolutions = NULL; + } /* for (compno */ + opj_free(tile->comps); + tile->comps = NULL; + } /* for (tileno */ + opj_free(tcd->tcd_volume->tiles); + tcd->tcd_volume->tiles = NULL; +} + +/* ----------------------------------------------------------------------- */ +void tcd_malloc_decode(opj_tcd_t *tcd, opj_volume_t * volume, opj_cp_t * cp) { + int tileno, compno, resno, bandno, precno, cblkno, res_max, + i, j, p, q, r; + unsigned int x0 = 0, y0 = 0, z0 = 0, + x1 = 0, y1 = 0, z1 = 0, + w, h, l; + + tcd->volume = volume; + tcd->cp = cp; + tcd->tcd_volume->tw = cp->tw; + tcd->tcd_volume->th = cp->th; + tcd->tcd_volume->tl = cp->tl; + tcd->tcd_volume->tiles = (opj_tcd_tile_t *) opj_malloc(cp->tw * cp->th * cp->tl * sizeof(opj_tcd_tile_t)); + + for (i = 0; i < cp->tileno_size; i++) { + opj_tcp_t *tcp = &(cp->tcps[cp->tileno[i]]); + opj_tcd_tile_t *tile = &(tcd->tcd_volume->tiles[cp->tileno[i]]); + + /* p61 ISO/IEC IS15444-1 : 2002 */ + /* curtileno --> raster scanned index of tiles */ + /* p,q,r --> matricial index of tiles */ + tileno = cp->tileno[i]; + p = tileno % cp->tw; + q = tileno / cp->tw; + r = tileno / (cp->tw * cp->th); /* extension to 3-D */ + + /* 4 borders of the tile rescale on the volume if necessary (B.3)*/ + tile->x0 = int_max(cp->tx0 + p * cp->tdx, volume->x0); + tile->y0 = int_max(cp->ty0 + q * cp->tdy, volume->y0); + tile->z0 = int_max(cp->tz0 + r * cp->tdz, volume->z0); + tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, volume->x1); + tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, volume->y1); + tile->z1 = int_min(cp->tz0 + (r + 1) * cp->tdz, volume->z1); + tile->numcomps = volume->numcomps; + + tile->comps = (opj_tcd_tilecomp_t *) opj_malloc(volume->numcomps * sizeof(opj_tcd_tilecomp_t)); + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tccp_t *tccp = &tcp->tccps[compno]; + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + int prevnumbands = 0; + + /* border of each tile component (global) */ + tilec->x0 = int_ceildiv(tile->x0, volume->comps[compno].dx); + tilec->y0 = int_ceildiv(tile->y0, volume->comps[compno].dy); + tilec->z0 = int_ceildiv(tile->z0, volume->comps[compno].dz); + tilec->x1 = int_ceildiv(tile->x1, volume->comps[compno].dx); + tilec->y1 = int_ceildiv(tile->y1, volume->comps[compno].dy); + tilec->z1 = int_ceildiv(tile->z1, volume->comps[compno].dz); + + tilec->data = (int *) opj_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * (tilec->z1 - tilec->z0) * sizeof(int)); + + res_max = 0; + for (i = 0;i < 3; i++){ + tilec->numresolution[i] = tccp->numresolution[i]; + //Greater of 3 resolutions contains all information + res_max = (tilec->numresolution[i] > res_max) ? tilec->numresolution[i] : res_max; + } + + tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(res_max * sizeof(opj_tcd_resolution_t)); + + for (resno = 0; resno < res_max; resno++) { + opj_tcd_resolution_t *res = &tilec->resolutions[resno]; + int pdx, pdy, pdz; + int tlprcxstart, tlprcystart, tlprczstart, brprcxend, brprcyend, brprczend; + int tlcbgxstart, tlcbgystart, tlcbgzstart, brcbgxend, brcbgyend, brcbgzend; + int cbgwidthexpn, cbgheightexpn, cbglengthexpn; + int cblkwidthexpn, cblkheightexpn, cblklengthexpn; + int levelnox = tilec->numresolution[0] - 1 - resno; + int levelnoy = tilec->numresolution[1] - 1 - resno; + int diff = tccp->numresolution[0] - tccp->numresolution[2]; + int levelnoz = tilec->numresolution[2] - 1 - ((resno <= diff) ? 0 : (resno - diff)); + if (levelnoz < 0) levelnoz = 0; + + /* border for each resolution level (global) */ + res->x0 = int_ceildivpow2(tilec->x0, levelnox); + res->y0 = int_ceildivpow2(tilec->y0, levelnoy); + res->z0 = int_ceildivpow2(tilec->z0, levelnoz); + res->x1 = int_ceildivpow2(tilec->x1, levelnox); + res->y1 = int_ceildivpow2(tilec->y1, levelnoy); + res->z1 = int_ceildivpow2(tilec->z1, levelnoz); + res->numbands = (resno == 0) ? 1 : (resno <= diff) ? 3 : 7; /* --> 3D */ + + /* p. 30, table A-13, ISO/IEC IS154444-1 : 2002 */ + if (tccp->csty & J3D_CCP_CSTY_PRT) { + pdx = tccp->prctsiz[0][resno]; + pdy = tccp->prctsiz[1][resno]; + pdz = tccp->prctsiz[2][resno]; + } else { + pdx = 15; + pdy = 15; + pdz = 15; + } + + /* p. 66, B.16, ISO/IEC IS15444-1 : 2002 */ + tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx; + tlprcystart = int_floordivpow2(res->y0, pdy) << pdy; + tlprczstart = int_floordivpow2(res->z0, pdz) << pdz; + brprcxend = int_ceildivpow2(res->x1, pdx) << pdx; + brprcyend = int_ceildivpow2(res->y1, pdy) << pdy; + brprczend = int_ceildivpow2(res->z1, pdz) << pdz; + + res->prctno[0] = (brprcxend - tlprcxstart) >> pdx; + res->prctno[1] = (brprcyend - tlprcystart) >> pdy; + res->prctno[2] = (brprczend - tlprczstart) >> pdz; + + /* p. 67, B.17 & B.18, ISO/IEC IS15444-1 : 2002 */ + if (resno == 0) { + tlcbgxstart = tlprcxstart;//0 + tlcbgystart = tlprcystart; + tlcbgzstart = tlprczstart; + brcbgxend = brprcxend;//1 + brcbgyend = brprcyend; + brcbgzend = brprczend; + cbgwidthexpn = pdx; //15 + cbgheightexpn = pdy; + cbglengthexpn = pdz; + } else { + tlcbgxstart = int_ceildivpow2(tlprcxstart, 1); + tlcbgystart = int_ceildivpow2(tlprcystart, 1); + tlcbgzstart = int_ceildivpow2(tlprczstart, 1); + brcbgxend = int_ceildivpow2(brprcxend, 1); + brcbgyend = int_ceildivpow2(brprcyend, 1); + brcbgzend = int_ceildivpow2(brprczend, 1); + cbgwidthexpn = pdx - 1; + cbgheightexpn = pdy - 1; + cbglengthexpn = pdz - 1; + } + + cblkwidthexpn = int_min(tccp->cblk[0], cbgwidthexpn); //6 + cblkheightexpn = int_min(tccp->cblk[1], cbgheightexpn); //6 + cblklengthexpn = int_min(tccp->cblk[2], cbglengthexpn); //6 + + res->bands = (opj_tcd_band_t *) opj_malloc(res->numbands * sizeof(opj_tcd_band_t)); + for (bandno = 0; bandno < res->numbands; bandno++) { + int x0b, y0b, z0b; + int gain, numbps; + opj_stepsize_t *ss = NULL; + + opj_tcd_band_t *band = &res->bands[bandno]; + band->bandno = resno == 0 ? 0 : bandno + 1; + /* Bandno: 0 - LLL 2 - LHL + 1 - HLL 3 - HHL + 4 - LLH 6 - LHH + 5 - HLH 7 - HHH */ + x0b = (band->bandno == 1) || (band->bandno == 3) || (band->bandno == 5 ) || (band->bandno == 7 ) ? 1 : 0; + y0b = (band->bandno == 2) || (band->bandno == 3) || (band->bandno == 6 ) || (band->bandno == 7 ) ? 1 : 0; + z0b = (band->bandno == 4) || (band->bandno == 5) || (band->bandno == 6 ) || (band->bandno == 7 ) ? 1 : 0; + + /* p. 65, B.15, ISO/IEC IS15444-1 : 2002 */ + if (band->bandno == 0) { + /* band border (global) */ + band->x0 = int_ceildivpow2(tilec->x0, levelnox); + band->y0 = int_ceildivpow2(tilec->y0, levelnoy); + band->z0 = int_ceildivpow2(tilec->z0, levelnoz); + band->x1 = int_ceildivpow2(tilec->x1, levelnox); + band->y1 = int_ceildivpow2(tilec->y1, levelnoy); + band->z1 = int_ceildivpow2(tilec->z1, levelnoz); + } else { + band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelnox) * x0b, levelnox + 1); + band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelnoy) * y0b, levelnoy + 1); + band->z0 = int_ceildivpow2(tilec->z0 - (1 << levelnoz) * z0b, (resno <= diff) ? levelnoz : levelnoz + 1); + band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelnox) * x0b, levelnox + 1); + band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelnoy) * y0b, levelnoy + 1); + band->z1 = int_ceildivpow2(tilec->z1 - (1 << levelnoz) * z0b, (resno <= diff) ? levelnoz : levelnoz + 1); + } + + ss = &tccp->stepsizes[(resno == 0) ? 0 : (prevnumbands + bandno + 1)]; + if (bandno == (res->numbands - 1)) + prevnumbands += (resno == 0) ? 0 : res->numbands; + gain = dwt_getgain(band->bandno,tccp->reversible); + numbps = volume->comps[compno].prec + gain; + + band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn)); + band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */ + + band->precincts = (opj_tcd_precinct_t *) opj_malloc(res->prctno[0] * res->prctno[1] * res->prctno[2] * sizeof(opj_tcd_precinct_t)); + + for (precno = 0; precno < res->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + int tlcblkxstart, tlcblkystart, tlcblkzstart, brcblkxend, brcblkyend, brcblkzend; + + int cbgxstart = tlcbgxstart + (precno % res->prctno[0]) * (1 << cbgwidthexpn); + int cbgystart = tlcbgystart + (precno / res->prctno[0]) * (1 << cbgheightexpn); + int cbgzstart = tlcbgzstart + (precno / (res->prctno[0] * res->prctno[1])) * (1 << cbglengthexpn); + int cbgxend = cbgxstart + (1 << cbgwidthexpn); + int cbgyend = cbgystart + (1 << cbgheightexpn); + int cbgzend = cbgzstart + (1 << cbglengthexpn); + + opj_tcd_precinct_t *prc = &band->precincts[precno]; + /* precinct size (global) */ + prc->x0 = int_max(cbgxstart, band->x0); + prc->y0 = int_max(cbgystart, band->y0); + prc->z0 = int_max(cbgzstart, band->z0); + prc->x1 = int_min(cbgxend, band->x1); + prc->y1 = int_min(cbgyend, band->y1); + prc->z1 = int_min(cbgzend, band->z1); + + tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn; + tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn; + tlcblkzstart = int_floordivpow2(prc->z0, cblklengthexpn) << cblklengthexpn; + brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn; + brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn; + brcblkzend = int_ceildivpow2(prc->z1, cblklengthexpn) << cblklengthexpn; + prc->cblkno[0] = (brcblkxend - tlcblkxstart) >> cblkwidthexpn; + prc->cblkno[1] = (brcblkyend - tlcblkystart) >> cblkheightexpn; + prc->cblkno[2] = (brcblkzend - tlcblkzstart) >> cblklengthexpn; + prc->cblkno[2] = (prc->cblkno[2] == 0) ? 1 : prc->cblkno[2]; + + prc->cblks = (opj_tcd_cblk_t *) opj_malloc((prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]) * sizeof(opj_tcd_cblk_t)); + prc->incltree = tgt_create(prc->cblkno[0], prc->cblkno[1], prc->cblkno[2]); + prc->imsbtree = tgt_create(prc->cblkno[0], prc->cblkno[1], prc->cblkno[2]); + + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + int cblkxstart = tlcblkxstart + (cblkno % prc->cblkno[0]) * (1 << cblkwidthexpn); + int cblkystart = tlcblkystart + ((cblkno % (prc->cblkno[0] * prc->cblkno[1])) / prc->cblkno[0]) * (1 << cblkheightexpn); + int cblkzstart = tlcblkzstart + (cblkno / (prc->cblkno[0] * prc->cblkno[1])) * (1 << cblklengthexpn); + int cblkxend = cblkxstart + (1 << cblkwidthexpn); + int cblkyend = cblkystart + (1 << cblkheightexpn); + int cblkzend = cblkzstart + (1 << cblklengthexpn); + int prec = ((tilec->bpp > 16) ? 3 : ((tilec->bpp > 8) ? 2 : 1)); + /* code-block size (global) */ + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + + /* code-block size (global) */ + cblk->x0 = int_max(cblkxstart, prc->x0); + cblk->y0 = int_max(cblkystart, prc->y0); + cblk->z0 = int_max(cblkzstart, prc->z0); + cblk->x1 = int_min(cblkxend, prc->x1); + cblk->y1 = int_min(cblkyend, prc->y1); + cblk->z1 = int_min(cblkzend, prc->z1); + } + } /* precno */ + } /* bandno */ + } /* resno */ + } /* compno */ + } /* i = 0..cp->tileno_size */ + + //tcd_dump(stdout, tcd, tcd->tcd_volume); + + /* + Allocate place to store the decoded data = final volume + Place limited by the tile really present in the codestream + */ + + for (i = 0; i < volume->numcomps; i++) { + for (j = 0; j < cp->tileno_size; j++) { + tileno = cp->tileno[j]; + x0 = (j == 0) ? tcd->tcd_volume->tiles[tileno].comps[i].x0 : int_min(x0,(unsigned int) tcd->tcd_volume->tiles[tileno].comps[i].x0); + y0 = (j == 0) ? tcd->tcd_volume->tiles[tileno].comps[i].y0 : int_min(y0,(unsigned int) tcd->tcd_volume->tiles[tileno].comps[i].y0); + z0 = (j == 0) ? tcd->tcd_volume->tiles[tileno].comps[i].z0 : int_min(z0,(unsigned int) tcd->tcd_volume->tiles[tileno].comps[i].z0); + x1 = (j == 0) ? tcd->tcd_volume->tiles[tileno].comps[i].x1 : int_max(x1,(unsigned int) tcd->tcd_volume->tiles[tileno].comps[i].x1); + y1 = (j == 0) ? tcd->tcd_volume->tiles[tileno].comps[i].y1 : int_max(y1,(unsigned int) tcd->tcd_volume->tiles[tileno].comps[i].y1); + z1 = (j == 0) ? tcd->tcd_volume->tiles[tileno].comps[i].z1 : int_max(z1,(unsigned int) tcd->tcd_volume->tiles[tileno].comps[i].z1); + } + + w = x1 - x0; + h = y1 - y0; + l = z1 - z0; + + volume->comps[i].data = (int *) opj_malloc(w * h * l * sizeof(int)); + volume->comps[i].w = w; + volume->comps[i].h = h; + volume->comps[i].l = l; + volume->comps[i].x0 = x0; + volume->comps[i].y0 = y0; + volume->comps[i].z0 = z0; + volume->comps[i].bigendian = cp->bigendian; + } +} + +void tcd_free_decode(opj_tcd_t *tcd) { + int tileno,compno,resno,bandno,precno; + + opj_tcd_volume_t *tcd_volume = tcd->tcd_volume; + + for (tileno = 0; tileno < tcd_volume->tw * tcd_volume->th * tcd_volume->tl; tileno++) { + opj_tcd_tile_t *tile = &tcd_volume->tiles[tileno]; + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + for (resno = 0; resno < tilec->numresolution[0]; 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->prctno[1] * res->prctno[0] * res->prctno[2]; precno++) { + opj_tcd_precinct_t *prec = &band->precincts[precno]; + if (prec->cblks != NULL) opj_free(prec->cblks); + if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree); + if (prec->incltree != NULL) tgt_destroy(prec->incltree); + /*for (treeno = 0; treeno < prec->numtrees; treeno++){ + if (prec->imsbtree[treeno] != NULL) tgt_destroy(prec->imsbtree[treeno]); + if (prec->incltree[treeno] != NULL) tgt_destroy(prec->incltree[treeno]); + }*/ + } + if (band->precincts != NULL) opj_free(band->precincts); + } + } + if (tilec->resolutions != NULL) opj_free(tilec->resolutions); + } + if (tile->comps != NULL) opj_free(tile->comps); + } + + if (tcd_volume->tiles != NULL) opj_free(tcd_volume->tiles); +} + + + +/* ----------------------------------------------------------------------- */ +void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final) { + int compno, resno, bandno, precno, cblkno; + int value; /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolution[0]][3]; */ + int matrice[10][10][3]; + int i, j, k; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_tile; + opj_tcp_t *tcd_tcp = tcd->tcp; + + /*matrice=(int*)opj_malloc(tcd_tcp->numlayers*tcd_tile->comps[0].numresolution[0]*3*sizeof(int)); */ + + 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->numresolution[0]; j++) { + for (k = 0; k < 3; k++) { + matrice[i][j][k] = + (int) (cp->matrice[i * tilec->numresolution[0] * 3 + j * 3 + k] + * (float) (tcd->volume->comps[compno].prec / 16.0)); + } + } + } + + for (resno = 0; resno < tilec->numresolution[0]; 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->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + int n; + int imsb = tcd->volume->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) { + int layno; + for (layno = 0; layno < tcd->tcp->numlayers; layno++) { + tcd_makelayer_fixed(tcd, layno, 1); + } +} + +void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final) { + int compno, resno, bandno, precno, cblkno, passno; + + opj_tcd_tile_t *tcd_tile = tcd->tcd_tile; + + 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->numresolution[0]; 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->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + opj_tcd_layer_t *layer = &cblk->layers[layno]; + + int n; + if (layno == 0) { + cblk->numpassesinlayers = 0; + } + n = cblk->numpassesinlayers; + for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) { + int dr; + double 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) + 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; + + // fprintf(stdout,"MakeLayer : %d %f %d %d \n",layer->len, layer->disto, layer->numpasses, n); + } + } + } + } + } +} + +bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_volume_info_t * volume_info) { + int compno, resno, bandno, precno, cblkno, passno, layno; + double min, max; + double cumdisto[100]; /* fixed_quality */ + const double K = 1; /* 1.1; // fixed_quality */ + double maxSE = 0; + + opj_cp_t *cp = tcd->cp; + opj_tcd_tile_t *tcd_tile = tcd->tcd_tile; + opj_tcp_t *tcd_tcp = tcd->tcp; + + min = DBL_MAX; + max = 0; + + tcd_tile->nbpix = 0; /* fixed_quality */ + + for (compno = 0; compno < tcd_tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno]; + tilec->nbpix = 0; + for (resno = 0; resno < tilec->numresolution[0]; 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->prctno[0] * res->prctno[1] * res->prctno[2]; precno++) { + opj_tcd_precinct_t *prc = &band->precincts[precno]; + for (cblkno = 0; cblkno < prc->cblkno[0] * prc->cblkno[1] * prc->cblkno[2]; cblkno++) { + opj_tcd_cblk_t *cblk = &prc->cblks[cblkno]; + for (passno = 0; passno < cblk->totalpasses; passno++) { + opj_tcd_pass_t *pass = &cblk->passes[passno]; + int dr; + double 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->nbpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0) * (cblk->z1 - cblk->z0)); + tilec->nbpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0) * (cblk->z1 - cblk->z0)); + } /* cbklno */ + } /* precno */ + } /* bandno */ + } /* resno */ + + maxSE += (((double)(1 << tcd->volume->comps[compno].prec) - 1.0) + * ((double)(1 << tcd->volume->comps[compno].prec) -1.0)) + * ((double)(tilec->nbpix)); + } /* compno */ + + /* add antonin index */ + if(volume_info && volume_info->index_on) { + opj_tile_info_t *info_TL = &volume_info->tile[tcd->tcd_tileno]; + info_TL->nbpix = tcd_tile->nbpix; + info_TL->distotile = tcd_tile->distotile; + info_TL->thresh = (double *) opj_malloc(tcd_tcp->numlayers * sizeof(double)); + } + /* dda */ + + for (layno = 0; layno < tcd_tcp->numlayers; layno++) { + double lo = min; + double hi = max; + int success = 0; + int maxlen = tcd_tcp->rates[layno] ? int_min(((int) tcd_tcp->rates[layno]), len) : len; + double goodthresh; + double distotarget; /* fixed_quality */ + int i = 0; + + /* fixed_quality */ + distotarget = tcd_tile->distotile - ((K * maxSE) / pow((float)10, tcd_tcp->distoratio[layno] / 10)); + + if ((tcd_tcp->rates[layno]) || (cp->disto_alloc==0)) { + opj_t2_t *t2 = t2_create(tcd->cinfo, tcd->volume, cp); + int oldl = 0, oldoldl = 0; + for (i = 0; i < 128; i++) { + double thresh = (lo + hi) / 2; + int l = 0; + double distoachieved = 0; /* fixed_quality -q */ + + tcd_makelayer(tcd, layno, thresh, 0); + + if (cp->fixed_quality) { /* fixed_quality -q */ + distoachieved = (layno == 0) ? tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno]; + if (distoachieved < distotarget) { + hi = thresh; + continue; + } + lo = thresh; + } else { /* disto_alloc -r, fixed_alloc -f */ + l = t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, volume_info); + //fprintf(stdout, "layno %d i %d len=%d max=%d \n",layno,i,l,maxlen); + if (l == -999) { + lo = thresh; + continue; + } else if (l == oldl && oldl == oldoldl && tcd_tile->distolayer[layno] > 0.0 && i>32) + break; + hi = thresh; + oldoldl = oldl; + oldl = l; + } + success = 1; + goodthresh = thresh; + } + t2_destroy(t2); + } else { + success = 1; + goodthresh = min; + } + if (!success) { + return false; + } + + if(volume_info && volume_info->index_on) { /* Threshold for Marcela Index */ + volume_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; +} + +/* ----------------------------------------------------------------------- */ +int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_volume_info_t * volume_info) { + int compno; + int l, i, npck = 0; + double encoding_time; + + opj_tcd_tile_t *tile = NULL; + opj_tcp_t *tcd_tcp = NULL; + opj_cp_t *cp = NULL; + + opj_tcp_t *tcp = &tcd->cp->tcps[0]; + opj_tccp_t *tccp = &tcp->tccps[0]; + opj_volume_t *volume = tcd->volume; + opj_t2_t *t2 = NULL; /* T2 component */ + + tcd->tcd_tileno = tileno; /* current encoded/decoded tile */ + + tcd->tcd_tile = tcd->tcd_volume->tiles; /* tile information */ + tile = tcd->tcd_tile; + + tcd->tcp = &tcd->cp->tcps[tileno]; /* coding/decoding params of tileno */ + tcd_tcp = tcd->tcp; + + cp = tcd->cp; /* coding parameters */ + + /* INDEX >> */ + if(volume_info && volume_info->index_on) { + opj_tcd_tilecomp_t *tilec_idx = &tile->comps[0]; /* based on component 0 */ + for (i = 0; i < tilec_idx->numresolution[0]; i++) { + opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[i]; + + volume_info->tile[tileno].prctno[0][i] = res_idx->prctno[0]; + volume_info->tile[tileno].prctno[1][i] = res_idx->prctno[1]; + volume_info->tile[tileno].prctno[2][i] = res_idx->prctno[2]; + + npck += res_idx->prctno[0] * res_idx->prctno[1] * res_idx->prctno[2]; + + volume_info->tile[tileno].prctsiz[0][i] = tccp->prctsiz[0][i]; + volume_info->tile[tileno].prctsiz[1][i] = tccp->prctsiz[1][i]; + volume_info->tile[tileno].prctsiz[2][i] = tccp->prctsiz[2][i]; + } + volume_info->tile[tileno].packet = (opj_packet_info_t *) opj_malloc(volume_info->comp * volume_info->layer * npck * sizeof(opj_packet_info_t)); + } + /* << INDEX */ + + /*---------------TILE-------------------*/ + encoding_time = opj_clock(); /* time needed to encode a tile */ + + for (compno = 0; compno < tile->numcomps; compno++) { + int x, y, z; + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + + int adjust; + int offset_x = int_ceildiv(volume->x0, volume->comps[compno].dx); //ceil(x0 / subsampling_dx) + int offset_y = int_ceildiv(volume->y0, volume->comps[compno].dy); + int offset_z = int_ceildiv(volume->z0, volume->comps[compno].dz); + + int tw = tilec->x1 - tilec->x0; + int w = int_ceildiv(volume->x1 - volume->x0, volume->comps[compno].dx); + int th = tilec->y1 - tilec->y0; + int h = int_ceildiv(volume->y1 - volume->y0, volume->comps[compno].dy); + int tl = tilec->z1 - tilec->z0; + int l = int_ceildiv(volume->z1 - volume->z0, volume->comps[compno].dz); + + + + /* extract tile data from volume.comps[0].data to tile.comps[0].data */ + //fprintf(stdout,"[INFO] Extract tile data\n"); + if (tcd->cp->transform_format == TRF_3D_RLS || tcd->cp->transform_format == TRF_3D_LSE) { + adjust = 0; + } else { + adjust = volume->comps[compno].sgnd ? 0 : 1 << (volume->comps[compno].prec - 1); //sign=='+' --> 2^(prec-1) + if (volume->comps[compno].dcoffset != 0){ + adjust += volume->comps[compno].dcoffset; + fprintf(stdout,"[INFO] DC Offset applied: DCO = %d -> adjust = %d\n",volume->comps[compno].dcoffset,adjust); + } + } + + if (tcd_tcp->tccps[compno].reversible == 1) { //IF perfect reconstruction (DWT.5-3) + for (z = tilec->z0; z < tilec->z1; z++) { + for (y = tilec->y0; y < tilec->y1; y++) { + /* start of the src tile scanline */ + int *data = &volume->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w + (z - offset_z) * w * h]; + /* start of the dst tile scanline */ + int *tile_data = &tilec->data[(y - tilec->y0) * tw + (z - tilec->z0) * tw * th]; + for (x = tilec->x0; x < tilec->x1; x++) { + *tile_data++ = *data++ - adjust; + } + } + } + } else if (tcd_tcp->tccps[compno].reversible == 0) { //IF not (DWT.9-7) + for (z = tilec->z0; z < tilec->z1; z++) { + for (y = tilec->y0; y < tilec->y1; y++) { + /* start of the src tile scanline */ + int *data = &volume->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w + (z - offset_z) * w * h]; + /* start of the dst tile scanline */ + int *tile_data = &tilec->data[(y - tilec->y0) * tw + (z - tilec->z0) * tw * th]; + for (x = tilec->x0; x < tilec->x1; x++) { + *tile_data++ = (*data++ - adjust) << 13; + } + } + } + } + + } + + /*----------------MCT-------------------*/ + if (tcd_tcp->mct) { + int samples = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0) * (tile->comps[0].z1 - tile->comps[0].z0); + fprintf(stdout,"[INFO] Tcd_encode_tile: mct\n"); + if (tcd_tcp->tccps[0].reversible == 0) { + mct_encode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples); + } else { + mct_encode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples); + } + } + /*----------------TRANSFORM---------------------------------*/ + fprintf(stdout,"[INFO] Tcd_encode_tile: Transform\n"); + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + dwt_encode(tilec, tcd_tcp->tccps[compno].dwtid); + } + + /*-------------------ENTROPY CODING-----------------------------*/ + fprintf(stdout,"[INFO] Tcd_encode_tile: Entropy coding\n"); + if ((cp->encoding_format == ENCOD_2EB)||(cp->encoding_format == ENCOD_3EB)) + { + if (cp->encoding_format == ENCOD_2EB) { + opj_t1_t *t1 = NULL; + t1 = t1_create(tcd->cinfo); + t1_encode_cblks(t1, tile, tcd_tcp); + t1_destroy(t1); + } else if (cp->encoding_format == ENCOD_3EB) { + opj_t1_3d_t *t1 = NULL; + t1 = t1_3d_create(tcd->cinfo); + t1_3d_encode_cblks(t1, tile, tcd_tcp); + t1_3d_destroy(t1); + } + /*-----------RATE-ALLOCATE------------------*/ + /* INDEX */ + if(volume_info) { + volume_info->index_write = 0; + } + if (cp->disto_alloc || cp->fixed_quality) { + fprintf(stdout,"[INFO] Tcd_encode_tile: Rate-allocate\n"); + tcd_rateallocate(tcd, dest, len, volume_info); /* Normal Rate/distortion allocation */ + } else {/* fixed_alloc */ + fprintf(stdout,"[INFO] Tcd_encode_tile: Rate-allocate fixed\n"); + tcd_rateallocate_fixed(tcd); /* Fixed layer allocation */ + } + + /*--------------TIER2------------------*/ + /* INDEX */ + if(volume_info) { + volume_info->index_write = 1; + } + fprintf(stdout,"[INFO] Tcd_encode_tile: Tier - 2\n"); + t2 = t2_create(tcd->cinfo, volume, cp); + l = t2_encode_packets(t2, tileno, tile, tcd_tcp->numlayers, dest, len, volume_info); + t2_destroy(t2); + } else if ((cp->encoding_format == ENCOD_2GR)||(cp->encoding_format == ENCOD_3GR)) { + /*if(volume_info) { + volume_info->index_write = 1; + } + gr = golomb_create(tcd->cinfo, volume, cp); + l = golomb_encode(gr, tileno, tile, dest, len, volume_info); + golomb_destroy(gr);*/ + } + + + /*---------------CLEAN-------------------*/ + fprintf(stdout,"[INFO] Tcd_encode_tile: %d bytes coded\n",l); + encoding_time = opj_clock() - encoding_time; + opj_event_msg(tcd->cinfo, EVT_INFO, "- tile encoded in %f s\n", encoding_time); + + /* cleaning memory */ + for (compno = 0; compno < tile->numcomps; compno++) { + tcd->tilec = &tile->comps[compno]; + opj_free(tcd->tilec->data); + } + + if (l == -999){ + fprintf(stdout,"[ERROR] Unable to perform T2 tier. Return -999.\n"); + return 0; + } + + return l; +} + + +bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno) { + int l, i; + int compno, eof = 0; + double tile_time, t1_time, dwt_time; + + opj_tcd_tile_t *tile = NULL; + opj_t2_t *t2 = NULL; /* T2 component */ + + tcd->tcd_tileno = tileno; + tcd->tcd_tile = &(tcd->tcd_volume->tiles[tileno]); + tcd->tcp = &(tcd->cp->tcps[tileno]); + tile = tcd->tcd_tile; + + tile_time = opj_clock(); /* time needed to decode a tile */ + opj_event_msg(tcd->cinfo, EVT_INFO, "tile %d / %d\n", tileno + 1, tcd->cp->tw * tcd->cp->th * tcd->cp->tl); + + if ((tcd->cp->encoding_format == ENCOD_2EB) || (tcd->cp->encoding_format == ENCOD_3EB)) { + /*--------------TIER2------------------*/ + t2 = t2_create(tcd->cinfo, tcd->volume, tcd->cp); + l = t2_decode_packets(t2, src, len, tileno, tile); + t2_destroy(t2); + opj_event_msg(tcd->cinfo, EVT_INFO, "Tcd_decode_tile: %d bytes decoded\n",l); + + if (l == -999) { + eof = 1; + opj_event_msg(tcd->cinfo, EVT_ERROR, "Tcd_decode_tile: incomplete bistream\n"); + } + + /*------------------TIER1-----------------*/ + opj_event_msg(tcd->cinfo, EVT_INFO, "Tcd_decode_tile: Entropy decoding %d \n",tcd->cp->encoding_format); + t1_time = opj_clock(); /* time needed to decode a tile */ + if (tcd->cp->encoding_format == ENCOD_2EB) { + opj_t1_t *t1 = NULL; /* T1 component */ + t1 = t1_create(tcd->cinfo); + t1_decode_cblks(t1, tile, tcd->tcp); + t1_destroy(t1); + }else if (tcd->cp->encoding_format == ENCOD_3EB) { + opj_t1_3d_t *t1 = NULL; /* T1 component */ + t1 = t1_3d_create(tcd->cinfo); + t1_3d_decode_cblks(t1, tile, tcd->tcp); + t1_3d_destroy(t1); + } + + t1_time = opj_clock() - t1_time; + #ifdef VERBOSE + opj_event_msg(tcd->cinfo, EVT_INFO, "- tier-1 took %f s\n", t1_time); + #endif + } else if ((tcd->cp->encoding_format == ENCOD_2GR)||(tcd->cp->encoding_format == ENCOD_3GR)) { + opj_event_msg(tcd->cinfo, EVT_INFO, "Tcd_decode_tile: Entropy decoding -- Does nothing :-D\n"); + /* + gr = golomb_create(tcd->cinfo, tcd->volume, tcd->cp); + l = golomb_decode(gr, tileno, tile, src, len); + golomb_destroy(gr); + if (l == -999) { + eof = 1; + opj_event_msg(tcd->cinfo, EVT_ERROR, "Tcd_decode_tile: incomplete bistream\n"); + } + */ + } + + /*----------------DWT---------------------*/ + fprintf(stdout,"[INFO] Tcd_decode_tile: Inverse DWT\n"); + dwt_time = opj_clock(); /* time needed to decode a tile */ + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + int stops[3], dwtid[3]; + + for (i = 0; i < 3; i++) { + if (tcd->cp->reduce[i] != 0) + tcd->volume->comps[compno].resno_decoded[i] = tile->comps[compno].numresolution[i] - tcd->cp->reduce[i] - 1; + stops[i] = tilec->numresolution[i] - 1 - tcd->volume->comps[compno].resno_decoded[i]; + if (stops[i] < 0) stops[i]=0; + dwtid[i] = tcd->cp->tcps->tccps[compno].dwtid[i]; + } + + dwt_decode(tilec, stops, dwtid); + + for (i = 0; i < 3; i++) { + if (tile->comps[compno].numresolution[i] > 0) { + tcd->volume->comps[compno].factor[i] = tile->comps[compno].numresolution[i] - (tcd->volume->comps[compno].resno_decoded[i] + 1); + if ( (tcd->volume->comps[compno].factor[i]) < 0 ) + tcd->volume->comps[compno].factor[i] = 0; + } + } + } + dwt_time = opj_clock() - dwt_time; + #ifdef VERBOSE + opj_event_msg(tcd->cinfo, EVT_INFO, "- dwt took %f s\n", dwt_time); + #endif + + /*----------------MCT-------------------*/ + + if (tcd->tcp->mct) { + if (tcd->tcp->tccps[0].reversible == 1) { + mct_decode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, + (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0) * (tile->comps[0].z1 - tile->comps[0].z0)); + } else { + mct_decode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, + (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0)* (tile->comps[0].z1 - tile->comps[0].z0)); + } + } + + /*---------------TILE-------------------*/ + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; + opj_tcd_resolution_t *res = &tilec->resolutions[tcd->volume->comps[compno].resno_decoded[0]]; + int adjust; + int minval = tcd->volume->comps[compno].sgnd ? -(1 << (tcd->volume->comps[compno].prec - 1)) : 0; + int maxval = tcd->volume->comps[compno].sgnd ? (1 << (tcd->volume->comps[compno].prec - 1)) - 1 : (1 << tcd->volume->comps[compno].prec) - 1; + + int tw = tilec->x1 - tilec->x0; + int w = tcd->volume->comps[compno].w; + int th = tilec->y1 - tilec->y0; + int h = tcd->volume->comps[compno].h; + + int i, j, k; + int offset_x = int_ceildivpow2(tcd->volume->comps[compno].x0, tcd->volume->comps[compno].factor[0]); + int offset_y = int_ceildivpow2(tcd->volume->comps[compno].y0, tcd->volume->comps[compno].factor[1]); + int offset_z = int_ceildivpow2(tcd->volume->comps[compno].z0, tcd->volume->comps[compno].factor[2]); + + if (tcd->cp->transform_format == TRF_3D_RLS || tcd->cp->transform_format == TRF_3D_LSE) { + adjust = 0; + } else { + adjust = tcd->volume->comps[compno].sgnd ? 0 : 1 << (tcd->volume->comps[compno].prec - 1); //sign=='+' --> 2^(prec-1) + if (tcd->volume->comps[compno].dcoffset != 0){ + adjust += tcd->volume->comps[compno].dcoffset; + fprintf(stdout,"[INFO] DC Offset applied: DCO = %d -> adjust = %d\n",tcd->volume->comps[compno].dcoffset,adjust); + } + } + + for (k = res->z0; k < res->z1; k++) { + for (j = res->y0; j < res->y1; j++) { + for (i = res->x0; i < res->x1; i++) { + int v; + float tmp = (float)((tilec->data[i - res->x0 + (j - res->y0) * tw + (k - res->z0) * tw * th]) / 8192.0); + + if (tcd->tcp->tccps[compno].reversible == 1) { + v = tilec->data[i - res->x0 + (j - res->y0) * tw + (k - res->z0) * tw * th]; + } else { + int tmp2 = ((int) (floor(fabs(tmp)))) + ((int) floor(fabs(tmp*2))%2); + v = ((tmp < 0) ? -tmp2:tmp2); + } + v += adjust; + + tcd->volume->comps[compno].data[(i - offset_x) + (j - offset_y) * w + (k - offset_z) * w * h] = int_clamp(v, minval, maxval); + } + } + } + } + + tile_time = opj_clock() - tile_time; /* time needed to decode a tile */ + opj_event_msg(tcd->cinfo, EVT_INFO, "- tile decoded in %f s\n", tile_time); + + for (compno = 0; compno < tile->numcomps; compno++) { + opj_free(tcd->tcd_volume->tiles[tileno].comps[compno].data); + tcd->tcd_volume->tiles[tileno].comps[compno].data = NULL; + } + + if (eof) { + return false; + } + + return true; +} + diff --git a/src/lib/openjp3d/tcd.h b/src/lib/openjp3d/tcd.h new file mode 100755 index 00000000..52504d10 --- /dev/null +++ b/src/lib/openjp3d/tcd.h @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * Copyright (c) 2006, Mónica Díez García, Image Processing Laboratory, University of Valladolid, Spain + * 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 JP3D.C. +*/ + +/** @defgroup TCD TCD - Implementation of a tile coder/decoder */ +/*@{*/ + +/** +Tile coder/decoder: segment instance +*/ +typedef struct opj_tcd_seg { +/** Number of passes in the segment */ + int numpasses; +/** Length of information */ + int len; +/** Data */ + unsigned char *data; +/** Number of passes posible for the segment */ + int maxpasses; +/** Number of passes added to the segment */ + int numnewpasses; +/** New length after inclusion of segments */ + int newlen; +} opj_tcd_seg_t; + +/** +Tile coder/decoder: pass instance +*/ +typedef struct opj_tcd_pass { +/** Rate obtained in the pass*/ + int rate; +/** Distorsion obtained in the pass*/ + double distortiondec; + int term; +/** Length of information */ + int len; +} opj_tcd_pass_t; + +/** +Tile coder/decoder: layer instance +*/ +typedef struct opj_tcd_layer { +/** Number of passes in the layer */ + int numpasses; +/** Length of information */ + int len; +/** Distortion within layer */ + double disto; /* add for index (Cfr. Marcela) */ + unsigned char *data; /* data */ +} opj_tcd_layer_t; + +/** +Tile coder/decoder: codeblock instance +*/ +typedef struct opj_tcd_cblk { +/** Dimension of the code-blocks : left upper corner (x0, y0, z0) */ + int x0, y0, z0; +/** Dimension of the code-blocks : right low corner (x1,y1,z1) */ + int x1, y1, z1; +/** Number of bits per simbol in codeblock */ + int numbps; + int numlenbits; + int len; /* length */ +/** Number of pass already done for the code-blocks */ + int numpasses; +/** number of pass added to the code-blocks */ + int numnewpasses; +/** Number of segments */ + int numsegs; +/** Segments informations */ + opj_tcd_seg_t segs[100]; +/** Number of passes in the layer */ + int numpassesinlayers; +/** Layer information */ + opj_tcd_layer_t layers[100]; +/** Total number of passes */ + int totalpasses; +/** Information about the passes */ + opj_tcd_pass_t passes[100]; +/* Data */ + unsigned char data[524288]; + //unsigned char *data; +} opj_tcd_cblk_t; + +/** +Tile coder/decoder: precint instance +*/ +typedef struct opj_tcd_precinct { +/** Dimension of the precint : left upper corner (x0, y0, z0) */ + int x0, y0, z0; +/** Dimension of the precint : right low corner (x1,y1,z1) */ + int x1, y1, z1; +/** Number of codeblocks in precinct in width and heigth and length*/ + int cblkno[3]; +/** Information about the codeblocks */ + opj_tcd_cblk_t *cblks; +/** Inclusion tree */ + opj_tgt_tree_t *incltree; +/** Missing MSBs tree */ + opj_tgt_tree_t *imsbtree; +} opj_tcd_precinct_t; + +/** +Tile coder/decoder: subband instance +*/ +typedef struct opj_tcd_band { +/** Dimension of the subband : left upper corner (x0, y0, z0) */ + int x0, y0, z0; +/** Dimension of the subband : right low corner (x1,y1,z1) */ + int x1, y1, z1; +/** Information about the precints */ + opj_tcd_precinct_t *precincts; /* precinct information */ +/** Number of bits per symbol in band */ + int numbps; +/** Quantization stepsize associated */ + float stepsize; +/** Band orientation (O->LLL,...,7->HHH) */ + int bandno; +} opj_tcd_band_t; + +/** +Tile coder/decoder: resolution instance +*/ +typedef struct opj_tcd_resolution { +/** Dimension of the resolution level : left upper corner (x0, y0, z0) */ + int x0, y0, z0; +/** Dimension of the resolution level : right low corner (x1,y1,z1) */ + int x1, y1, z1; +/** Number of precints in each dimension for the resolution level */ + int prctno[3]; +/** Number of subbands for the resolution level */ + int numbands; +/** Subband information */ + opj_tcd_band_t *bands; +} opj_tcd_resolution_t; + +/** +Tile coder/decoder: component instance +*/ +typedef struct opj_tcd_tilecomp { +/** Dimension of the component : left upper corner (x0, y0, z0) */ + int x0, y0, z0; +/** Dimension of the component : right low corner (x1,y1,z1) */ + int x1, y1, z1; +/** Number of resolutions level if DWT transform*/ + int numresolution[3]; +/** Resolution information */ + opj_tcd_resolution_t *resolutions; +/** Data of the component */ + int *data; +/** Fixed_quality related */ + int nbpix; +/** Number of bits per voxel in component */ + int bpp; +} opj_tcd_tilecomp_t; + +/** +Tile coder/decoder: tile instance +*/ +typedef struct opj_tcd_tile { +/** Dimension of the tile : left upper corner (x0, y0, z0) */ + int x0, y0, z0; +/** Dimension of the tile : right low corner (x1,y1,z1) */ + int x1, y1, z1; +/** Number of components in tile */ + int numcomps; +/** Components information */ + opj_tcd_tilecomp_t *comps; +/** Fixed_quality related : no of bytes of data*/ + int nbpix; +/** Fixed_quality related : distortion achieved in tile */ + double distotile; +/** Fixed_quality related : distortion achieved in each layer */ + double distolayer[100]; +} opj_tcd_tile_t; + +/** +Tile coder/decoder: volume instance +*/ +typedef struct opj_tcd_volume { +/** Number of tiles in width and heigth and length */ + int tw, th, tl; +/** Tiles information */ + opj_tcd_tile_t *tiles; +} opj_tcd_volume_t; + +/** +Tile coder/decoder +*/ +typedef struct opj_tcd { +/** Codec context */ + opj_common_ptr cinfo; +/** Volume information */ + opj_volume_t *volume; +/** Coding parameters */ + opj_cp_t *cp; +/** Coding/decoding parameters common to all tiles */ + opj_tcp_t *tcp; +/** Info on each volume tile */ + opj_tcd_volume_t *tcd_volume; +/** Pointer to the current encoded/decoded tile */ + opj_tcd_tile_t *tcd_tile; +/** Current encoded/decoded tile */ + int tcd_tileno; + + /**@name working variables */ + /*@{*/ + opj_tcd_tile_t *tile; + opj_tcd_tilecomp_t *tilec; + opj_tcd_resolution_t *res; + opj_tcd_band_t *band; + opj_tcd_precinct_t *prc; + opj_tcd_cblk_t *cblk; + /*@}*/ +} opj_tcd_t; + +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ + +/** +Dump the content of a tcd structure +*/ +void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_volume_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(opj_common_ptr cinfo); +/** +Destroy a previously created TCD handle +@param tcd TCD handle to destroy +*/ +void tcd_destroy(opj_tcd_t *tcd); +/** +Initialize the tile coder (allocate the memory) +@param tcd TCD handle +@param volume Raw volume +@param cp Coding parameters +@param curtileno Number that identifies the tile that will be encoded +*/ +void tcd_malloc_encode(opj_tcd_t *tcd, opj_volume_t * volume, opj_cp_t * cp, int curtileno); +/** +Initialize the tile coder (reuses the memory allocated by tcd_malloc_encode)(for 3D-DWT) +@param tcd TCD handle +@param volume Raw volume +@param cp Coding parameters +@param curtileno Number that identifies the tile that will be encoded +*/ +void tcd_init_encode(opj_tcd_t *tcd, opj_volume_t * volume, opj_cp_t * cp, int curtileno); +/** +Free the memory allocated for encoding +@param tcd TCD handle +*/ +void tcd_free_encode(opj_tcd_t *tcd); +/** +Initialize the tile decoder +@param tcd TCD handle +@param volume Raw volume +@param cp Coding parameters +*/ +void tcd_malloc_decode(opj_tcd_t *tcd, opj_volume_t * volume, opj_cp_t * cp); + +void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final); +void tcd_rateallocate_fixed(opj_tcd_t *tcd); +void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final); +bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_volume_info_t * volume_info); +/** +Encode a tile from the raw volume into a buffer +@param tcd TCD handle +@param tileno Number that identifies one of the tiles to be encoded +@param dest Destination buffer +@param len Length of destination buffer +@param volume_info Creation of index file +@return +*/ +int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_volume_info_t * volume_info); +/** +Decode a tile from a buffer into a raw volume +@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, unsigned char *src, int len, int tileno); +/** +Free the memory allocated for decoding +@param tcd TCD handle +*/ +void tcd_free_decode(opj_tcd_t *tcd); + +/* ----------------------------------------------------------------------- */ +/*@}*/ + +/*@}*/ + +#endif /* __TCD_H */ diff --git a/src/lib/openjp3d/tgt.c b/src/lib/openjp3d/tgt.c new file mode 100755 index 00000000..1772afac --- /dev/null +++ b/src/lib/openjp3d/tgt.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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 +========================================================== +*/ +void tgt_tree_dump (FILE *fd, opj_tgt_tree_t * tree){ + int nodesno; + + fprintf(fd, "TGT_TREE {\n"); + fprintf(fd, " numnodes: %d \n", tree->numnodes); + fprintf(fd, " numleafsh: %d, numleafsv: %d, numleafsz: %d,\n", tree->numleafsh, tree->numleafsv, tree->numleafsz); + + for (nodesno = 0; nodesno < tree->numnodes; nodesno++) { + fprintf(fd, "tgt_node %d {\n", nodesno); + fprintf(fd, " value: %d \n", tree->nodes[nodesno].value); + fprintf(fd, " low: %d \n", tree->nodes[nodesno].low); + fprintf(fd, " known: %d \n", tree->nodes[nodesno].known); + if (tree->nodes[nodesno].parent) { + fprintf(fd, " parent.value: %d \n", tree->nodes[nodesno].parent->value); + fprintf(fd, " parent.low: %d \n", tree->nodes[nodesno].parent->low); + fprintf(fd, " parent.known: %d \n", tree->nodes[nodesno].parent->known); + } + fprintf(fd, "}\n"); + + } + fprintf(fd, "}\n"); + +} + + +opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv, int numleafsz) { + + int nplh[32]; + int nplv[32]; + int nplz[32]; + opj_tgt_node_t *node = NULL; + opj_tgt_node_t *parentnode = NULL; + opj_tgt_node_t *parentnode0 = NULL; + opj_tgt_tree_t *tree = NULL; + int i, j, k, p, p0; + int numlvls; + int n, z = 0; + + tree = (opj_tgt_tree_t *) opj_malloc(sizeof(opj_tgt_tree_t)); + if(!tree) + return NULL; + tree->numleafsh = numleafsh; + tree->numleafsv = numleafsv; + tree->numleafsz = numleafsz; + + numlvls = 0; + nplh[0] = numleafsh; + nplv[0] = numleafsv; + nplz[0] = numleafsz; + tree->numnodes = 0; + do { + n = nplh[numlvls] * nplv[numlvls] * nplz[numlvls]; + nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2; + nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2; + nplz[numlvls + 1] = (nplz[numlvls] + 1) / 2; + tree->numnodes += n; + ++numlvls; + } while (n > 1); + + if (tree->numnodes == 0) { + opj_free(tree); + return NULL; + } + + tree->nodes = (opj_tgt_node_t *) opj_malloc(tree->numnodes * sizeof(opj_tgt_node_t)); + if(!tree->nodes) { + opj_free(tree); + return NULL; + } + + node = tree->nodes; + parentnode = &tree->nodes[tree->numleafsh * tree->numleafsv * tree->numleafsz]; + parentnode0 = parentnode; + + p = tree->numleafsh * tree->numleafsv * tree->numleafsz; + p0 = p; + n = 0; + //fprintf(stdout,"\nH %d V %d Z %d numlvls %d nodes %d\n",tree->numleafsh,tree->numleafsv,tree->numleafsz,numlvls,tree->numnodes); + for (i = 0; i < numlvls - 1; ++i) { + for (j = 0; j < nplv[i]; ++j) { + k = nplh[i]*nplz[i]; + while (--k >= 0) { + node->parent = parentnode; //fprintf(stdout,"node[%d].parent = node[%d]\n",n,p); + ++node; ++n; + if (--k >= 0 && n < p) { + node->parent = parentnode; //fprintf(stdout,"node[%d].parent = node[%d]\n",n,p); + ++node; ++n; + } + if (nplz[i] != 1){ //2D operation vs 3D operation + if (--k >= 0 && n < p) { + node->parent = parentnode; //fprintf(stdout,"node[%d].parent = node[%d]\n",n,p); + ++node; ++n; + } + if (--k >= 0 && n < p) { + node->parent = parentnode; //fprintf(stdout,"node[%d].parent = node[%d]\n",n,p); + ++node; ++n; + } + } + ++parentnode; ++p; + } + if ((j & 1) || j == nplv[i] - 1) { + parentnode0 = parentnode; p0 = p; //fprintf(stdout,"parent = node[%d] \n",p); + } else { + parentnode = parentnode0; p = p0; //fprintf(stdout,"parent = node[%d] \n",p); + parentnode0 += nplh[i]*nplz[i]; p0 += nplh[i]*nplz[i]; + } + } + } + node->parent = 0; + + + tgt_reset(tree); + + return tree; +} + +void tgt_destroy(opj_tgt_tree_t *tree) { + opj_free(tree->nodes); + opj_free(tree); +} + +void tgt_reset(opj_tgt_tree_t *tree) { + int i; + + if (NULL == tree) + return; + + for (i = 0; i < tree->numnodes; i++) { + tree->nodes[i].value = 999; + tree->nodes[i].low = 0; + tree->nodes[i].known = 0; + } +} + +void tgt_setvalue(opj_tgt_tree_t *tree, int leafno, int 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, int leafno, int threshold) { + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + int 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; + } +} + +int tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold) { + opj_tgt_node_t *stk[31]; + opj_tgt_node_t **stkptr; + opj_tgt_node_t *node; + int 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/src/lib/openjp3d/tgt.h b/src/lib/openjp3d/tgt.h new file mode 100755 index 00000000..ad8e88d8 --- /dev/null +++ b/src/lib/openjp3d/tgt.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium + * 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. +*/ + +/** @defgroup TGT TGT - Implementation of a tag-tree coder */ +/*@{*/ + +/** +Tag node +*/ +typedef struct opj_tgt_node { +/** Node parent reference */ + struct opj_tgt_node *parent; +/** */ + int value; +/** */ + int low; +/** */ + int known; +} opj_tgt_node_t; + +/** +Tag tree +*/ +typedef struct opj_tgt_tree { +/** Number of leaves from horizontal axis */ + int numleafsh; +/** Number of leaves from vertical axis */ + int numleafsv; +/** Number of leaves from axial axis */ + int numleafsz; +/** Number of nodes */ + int numnodes; +/** Reference to each node instance */ + opj_tgt_node_t *nodes; +} opj_tgt_tree_t; + +/** @name Funciones generales */ +/*@{*/ +/* ----------------------------------------------------------------------- */ +/** +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 numleafsz Depth 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(int numleafsh, int numleafsv, int numleafsz); +/** +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, int leafno, int 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(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int 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 +*/ +int tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold); + +/*@}*/ +/* ----------------------------------------------------------------------- */ +void tgt_tree_dump (FILE *fd, opj_tgt_tree_t * tree); + +#endif /* __TGT_H */ diff --git a/src/lib/openjp3d/volume.c b/src/lib/openjp3d/volume.c new file mode 100755 index 00000000..35728daf --- /dev/null +++ b/src/lib/openjp3d/volume.c @@ -0,0 +1,89 @@ +/* + * 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_volume_t* OPJ_CALLCONV opj_volume_create(int numcmpts, opj_volume_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) { + int compno; + opj_volume_t *volume = NULL; + + volume = (opj_volume_t*)opj_malloc(sizeof(opj_volume_t)); + if(volume) { + volume->color_space = clrspc; + volume->numcomps = numcmpts; + /* allocate memory for the per-component information */ + volume->comps = (opj_volume_comp_t*)opj_malloc(volume->numcomps * sizeof(opj_volume_comp_t)); + if(!volume->comps) { + opj_volume_destroy(volume); + return NULL; + } + /* create the individual volume components */ + for(compno = 0; compno < numcmpts; compno++) { + opj_volume_comp_t *comp = &volume->comps[compno]; + comp->dx = cmptparms[compno].dx; + comp->dy = cmptparms[compno].dy; + comp->dz = cmptparms[compno].dz; + comp->w = cmptparms[compno].w; + comp->h = cmptparms[compno].h; + comp->l = cmptparms[compno].l; + comp->x0 = cmptparms[compno].x0; + comp->y0 = cmptparms[compno].y0; + comp->z0 = cmptparms[compno].z0; + comp->prec = cmptparms[compno].prec; + comp->bpp = cmptparms[compno].bpp; + comp->sgnd = cmptparms[compno].sgnd; + comp->bigendian = cmptparms[compno].bigendian; + comp->dcoffset = cmptparms[compno].dcoffset; + comp->data = (int*)opj_malloc(comp->w * comp->h * comp->l * sizeof(int)); + if(!comp->data) { + fprintf(stdout,"Unable to malloc comp->data (%d x %d x %d x bytes)",comp->w,comp->h,comp->l); + opj_volume_destroy(volume); + return NULL; + } + //fprintf(stdout,"%d %d %d %d %d %d %d %d %d", comp->w,comp->h, comp->l, comp->dx, comp->dy, comp->dz, comp->prec, comp->bpp, comp->sgnd); + } + } + + return volume; +} + +void OPJ_CALLCONV opj_volume_destroy(opj_volume_t *volume) { + int i; + if(volume) { + if(volume->comps) { + /* volume components */ + for(i = 0; i < volume->numcomps; i++) { + opj_volume_comp_t *volume_comp = &volume->comps[i]; + if(volume_comp->data) { + opj_free(volume_comp->data); + } + } + opj_free(volume->comps); + } + opj_free(volume); + } +} + diff --git a/src/lib/openjp3d/volume.h b/src/lib/openjp3d/volume.h new file mode 100755 index 00000000..02f28d2a --- /dev/null +++ b/src/lib/openjp3d/volume.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2006, Mónica Díez García, Image Processing Laboratory, University of Valladolid, Spain + * 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 __VOLUME_H +#define __VOLUME_H +/** +@file volume.h +@brief Implementation of operations on volumes (VOLUME) + +The functions in VOLUME.C have for goal to realize operations on volumes. +*/ + +/** @defgroup VOLUME VOLUME - Implementation of operations on volumes */ +/*@{*/ + + +/*@}*/ + +#endif /* __VOLUME_H */ + -- cgit v1.2.3