diff --git a/src/lib/openjp2/CMakeLists.txt b/src/lib/openjp2/CMakeLists.txt
index dc411128..3005985c 100644
--- a/src/lib/openjp2/CMakeLists.txt
+++ b/src/lib/openjp2/CMakeLists.txt
@@ -25,6 +25,8 @@ set(OPENJPEG_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/cio.h
${CMAKE_CURRENT_SOURCE_DIR}/dwt.c
${CMAKE_CURRENT_SOURCE_DIR}/dwt.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/dwt_region.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/dwt_region.h
${CMAKE_CURRENT_SOURCE_DIR}/event.c
${CMAKE_CURRENT_SOURCE_DIR}/event.h
${CMAKE_CURRENT_SOURCE_DIR}/image.c
diff --git a/src/lib/openjp2/dwt.c b/src/lib/openjp2/dwt.c
index 97cced10..0b12d166 100644
--- a/src/lib/openjp2/dwt.c
+++ b/src/lib/openjp2/dwt.c
@@ -129,7 +129,6 @@ static OPJ_BOOL opj_dwt_decode_tile(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 i, DWT
static OPJ_BOOL opj_dwt_encode_procedure( opj_tcd_tilecomp_t * tilec,
void (*p_function)(OPJ_INT32 *, OPJ_INT32,OPJ_INT32,OPJ_INT32) );
-static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i);
/* */
/* Inverse 9-7 wavelet transform in 1-D. */
@@ -474,6 +473,8 @@ OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec)
/* Inverse 5-3 wavelet transform in 2-D. */
/* */
OPJ_BOOL opj_dwt_decode(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) {
+ if (opj_tile_buf_is_decode_region(tilec->buf))
+ return opj_dwt_region_decode53(tilec, numres);
return opj_dwt_decode_tile(tilec, numres, &opj_dwt_decode_1);
}
@@ -543,7 +544,7 @@ void opj_dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, OPJ_UINT32 prec) {
/* */
/* Determine maximum computed resolution level for inverse wavelet transform */
/* */
-static OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i) {
+OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i) {
OPJ_UINT32 mr = 0;
OPJ_UINT32 w;
while( --i ) {
@@ -846,6 +847,9 @@ OPJ_BOOL opj_dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, OPJ_UINT32 numr
OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
+ if (opj_tile_buf_is_decode_region(tilec->buf))
+ return opj_dwt_region_decode97(tilec, numres);
+
h.wavelet = (opj_v4_t*) opj_aligned_malloc((opj_dwt_max_resolution(res, numres)+5) * sizeof(opj_v4_t));
if (!h.wavelet) {
/* FIXME event manager error callback */
diff --git a/src/lib/openjp2/dwt.h b/src/lib/openjp2/dwt.h
index 21fe942a..f210d521 100644
--- a/src/lib/openjp2/dwt.h
+++ b/src/lib/openjp2/dwt.h
@@ -114,6 +114,12 @@ Explicit calculation of the Quantization Stepsizes
@param prec Precint analyzed
*/
void opj_dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, OPJ_UINT32 prec);
+
+/* */
+/* Determine maximum computed resolution level for inverse wavelet transform */
+/*
+*/
+OPJ_UINT32 opj_dwt_max_resolution(opj_tcd_resolution_t* restrict r, OPJ_UINT32 i);
/* ----------------------------------------------------------------------- */
/*@}*/
diff --git a/src/lib/openjp2/dwt_region.c b/src/lib/openjp2/dwt_region.c
new file mode 100644
index 00000000..c5f91de5
--- /dev/null
+++ b/src/lib/openjp2/dwt_region.c
@@ -0,0 +1,573 @@
+/*
+ * The copyright in this software is being made available under the 2-clauses
+ * BSD License, included below. This software may be subject to other third
+ * party and contributor rights, including patent rights, and no such rights
+ * are granted under this license.
+ *
+ * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2014, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux
+ * Copyright (c) 2003-2014, Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2007, Jonathan Ballard
+ * Copyright (c) 2007, Callum Lerwick
+ * 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 DWT DWT - Implementation of a discrete wavelet transform */
+/*@{*/
+
+
+/** @name Local data structures */
+/*@{*/
+
+/*
+Note: the letter s is used to denote even locations in a given dimension, while the letter
+d is used to denote odd locations.
+
+*/
+
+typedef struct opj_dwt53 {
+ OPJ_INT32* data;
+ OPJ_INT32 d_dim;
+ OPJ_INT32 s_dim;
+
+ /* if dimension is odd, then number of even locations equals one more than number of
+ odd locations. So, odd_dimension == 1 in case of odd dimension */
+ OPJ_INT32 odd_dimension;
+} opj_dwt53_t;
+
+/* process four coefficients at a time*/
+typedef union {
+ OPJ_FLOAT32 f[4];
+} opj_coeff97_t;
+
+typedef struct opj_dwt97 {
+ opj_coeff97_t* data ;
+ OPJ_INT32 d_dim ;
+ OPJ_INT32 s_dim ;
+ OPJ_INT32 odd_dimension ;
+} opj_dwt97_t ;
+
+static const OPJ_FLOAT32 opj_dwt_alpha = 1.586134342f; /* 12994 */
+static const OPJ_FLOAT32 opj_dwt_beta = 0.052980118f; /* 434 */
+static const OPJ_FLOAT32 opj_dwt_gamma = -0.882911075f; /* -7233 */
+static const OPJ_FLOAT32 opj_dwt_delta = -0.443506852f; /* -3633 */
+
+static const OPJ_FLOAT32 opj_K = 1.230174105f; /* 10078 */
+static const OPJ_FLOAT32 opj_c13318 = 1.625732422f;
+
+/*@}*/
+
+
+/** @name Local static functions */
+/*@{*/
+/**
+Inverse lazy transform (horizontal)
+*/
+static void opj_dwt_region_interleave53_h(opj_dwt53_t* buffer_h,
+ OPJ_INT32 *tile_data);
+/**
+Inverse lazy transform (vertical)
+*/
+static void opj_dwt_region_interleave53_v(opj_dwt53_t* buffer_v,
+ OPJ_INT32 *tile_data,
+ OPJ_INT32 stride);
+/**
+Inverse 5-3 data transform in 1-D
+*/
+static void opj_dwt_region_decode53_1d(opj_dwt53_t *buffer_v);
+
+
+
+/* */
+/* Inverse 9-7 data transform in 1-D. */
+/* */
+static void opj_region_decode97(opj_dwt97_t* restrict dwt);
+
+static void opj_region_interleave97_h(opj_dwt97_t* restrict w,
+ OPJ_FLOAT32* restrict tile_data,
+ OPJ_INT32 stride,
+ OPJ_INT32 size);
+
+static void opj_region_interleave97_v(opj_dwt97_t* restrict buffer_v ,
+ OPJ_FLOAT32* restrict tile_data ,
+ OPJ_INT32 stride,
+ OPJ_INT32 nb_elts_read);
+
+static void opj_region_decode97_scale(opj_coeff97_t* w,
+ OPJ_INT32 count,
+ const OPJ_FLOAT32 c);
+
+static void opj_region_decode97_lift(opj_coeff97_t* l,
+ opj_coeff97_t* w,
+ OPJ_INT32 k,
+ OPJ_INT32 m,
+ OPJ_FLOAT32 c);
+
+
+
+/*@}*/
+
+/*@}*/
+
+#define OPJ_S(i) a[(i)<<1]
+#define OPJ_D(i) a[(1+((i)<<1))]
+#define OPJ_S_(i) ((i)<0?OPJ_S(0):((i)>=s_dim?OPJ_S(s_dim-1):OPJ_S(i)))
+#define OPJ_D_(i) ((i)<0?OPJ_D(0):((i)>=d_dim?OPJ_D(d_dim-1):OPJ_D(i)))
+
+
+#define OPJ_SS_(i) ((i)<0?OPJ_S(0):((i)>=d_dim?OPJ_S(d_dim-1):OPJ_S(i)))
+#define OPJ_DD_(i) ((i)<0?OPJ_D(0):((i)>=s_dim?OPJ_D(s_dim-1):OPJ_D(i)))
+
+/*
+==========================================================
+ local functions
+==========================================================
+*/
+
+/* */
+/* Inverse lazy transform (horizontal). */
+/* */
+static void opj_dwt_region_interleave53_h(opj_dwt53_t* buffer_h, OPJ_INT32 *tile_data) {
+ OPJ_INT32 *tile_data_ptr = tile_data;
+ OPJ_INT32 *buffer_data_ptr = buffer_h->data + buffer_h->odd_dimension;
+ OPJ_INT32 i = buffer_h->s_dim;
+ while (i--) {
+ *buffer_data_ptr = *(tile_data_ptr++);
+ buffer_data_ptr += 2;
+ }
+ tile_data_ptr = tile_data + buffer_h->s_dim;
+ buffer_data_ptr = buffer_h->data + 1 - buffer_h->odd_dimension;
+ i = buffer_h->d_dim;
+ while (i--) {
+ *buffer_data_ptr = *(tile_data_ptr++);
+ buffer_data_ptr += 2;
+ }
+}
+
+/* */
+/* Inverse lazy transform (vertical). */
+/* */
+static void opj_dwt_region_interleave53_v(opj_dwt53_t* buffer_v, OPJ_INT32 *tile_data, OPJ_INT32 stride) {
+ OPJ_INT32 *tile_data_ptr = tile_data;
+ OPJ_INT32 *buffer_data_ptr = buffer_v->data + buffer_v->odd_dimension;
+ OPJ_INT32 i = buffer_v->s_dim;
+ while (i--) {
+ *buffer_data_ptr = *tile_data_ptr;
+ buffer_data_ptr += 2;
+ tile_data_ptr += stride;
+ }
+ tile_data_ptr = tile_data + (buffer_v->s_dim * stride);
+ buffer_data_ptr = buffer_v->data + 1 - buffer_v->odd_dimension;
+ i = buffer_v->d_dim;
+ while (i--) {
+ *buffer_data_ptr = *tile_data_ptr;
+ buffer_data_ptr += 2;
+ tile_data_ptr += stride;
+ }
+}
+
+
+/* */
+/* Inverse 5-3 data transform in 1-D. */
+/* */
+static void opj_dwt_region_decode53_1d(opj_dwt53_t *buffer_v) {
+ OPJ_INT32 *a = buffer_v->data;
+ OPJ_INT32 d_dim = buffer_v->d_dim;
+ OPJ_INT32 s_dim = buffer_v->s_dim;
+ OPJ_INT32 odd_dimension = buffer_v->odd_dimension;
+
+ OPJ_INT32 i;
+
+ if (!odd_dimension) {
+ if ((d_dim > 0) || (s_dim > 1)) {
+ for (i = 0; i < s_dim; i++)
+ OPJ_S(i) -= (OPJ_D_(i - 1) + OPJ_D_(i) + 2) >> 2;
+ for (i = 0; i < d_dim; i++)
+ OPJ_D(i) += (OPJ_S_(i) + OPJ_S_(i + 1)) >> 1;
+ }
+ }
+ else {
+ if (!s_dim && d_dim == 1)
+ OPJ_S(0) >>=1;
+ else {
+ for (i = 0; i < s_dim; i++)
+ OPJ_D(i) -= (OPJ_SS_(i) + OPJ_SS_(i + 1) + 2) >> 2;
+ for (i = 0; i < d_dim; i++)
+ OPJ_S(i) += (OPJ_DD_(i) + OPJ_DD_(i - 1)) >> 1;
+ }
+ }
+}
+
+/*
+==========================================================
+ DWT interface
+==========================================================
+*/
+
+
+/* */
+/* Inverse 5-3 data transform in 2-D. */
+/* */
+OPJ_BOOL opj_dwt_region_decode53(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres) {
+ opj_dwt53_t buffer_h;
+ opj_dwt53_t buffer_v;
+
+ opj_tcd_resolution_t* tr = tilec->resolutions;
+
+ OPJ_UINT32 rw = (OPJ_UINT32)(tr->x1 - tr->x0); /* width of the resolution level computed */
+ OPJ_UINT32 rh = (OPJ_UINT32)(tr->y1 - tr->y0); /* height of the resolution level computed */
+
+ OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
+
+ if (numres == 1U) {
+ return OPJ_TRUE;
+ }
+ buffer_h.data = (OPJ_INT32*)opj_aligned_malloc(opj_dwt_max_resolution(tr, numres) * sizeof(OPJ_INT32));
+ if (!buffer_h.data) {
+ /* FIXME event manager error callback */
+ return OPJ_FALSE;
+ }
+
+ buffer_v.data = buffer_h.data;
+
+ while (--numres) {
+ OPJ_INT32 * restrict tiledp = tilec->buf->data;
+ OPJ_UINT32 j;
+
+ ++tr;
+ buffer_h.s_dim = (OPJ_INT32)rw;
+ buffer_v.s_dim = (OPJ_INT32)rh;
+
+ rw = (OPJ_UINT32)(tr->x1 - tr->x0);
+ rh = (OPJ_UINT32)(tr->y1 - tr->y0);
+
+ buffer_h.d_dim = (OPJ_INT32)(rw - (OPJ_UINT32)buffer_h.s_dim);
+ buffer_h.odd_dimension = tr->x0 &1;
+
+ for (j = 0; j < rh; ++j) {
+ opj_dwt_region_interleave53_h(&buffer_h, tiledp + j*w);
+ opj_dwt_region_decode53_1d(&buffer_h);
+ memcpy(tiledp + j*w, buffer_h.data, rw * sizeof(OPJ_INT32));
+ }
+
+ buffer_v.d_dim = (OPJ_INT32)(rh - (OPJ_UINT32)buffer_v.s_dim);
+ buffer_v.odd_dimension = tr->y0 &1;
+
+ for (j = 0; j < rw; ++j) {
+ OPJ_UINT32 k;
+ opj_dwt_region_interleave53_v(&buffer_v, tiledp + j, (OPJ_INT32)w);
+ opj_dwt_region_decode53_1d(&buffer_v);
+ for (k = 0; k < rh; ++k) {
+ tiledp[k * w + j] = buffer_v.data[k];
+ }
+ }
+ }
+ opj_aligned_free(buffer_h.data);
+ return OPJ_TRUE;
+}
+
+static void opj_region_interleave97_h(opj_dwt97_t* restrict buffer,
+ OPJ_FLOAT32* restrict tile_data,
+ OPJ_INT32 stride,
+ OPJ_INT32 size){
+
+ OPJ_FLOAT32* restrict buffer_data_ptr = (OPJ_FLOAT32*) (buffer->data + buffer->odd_dimension);
+ OPJ_INT32 count = buffer->s_dim;
+ OPJ_INT32 i, k;
+
+ for(k = 0; k < 2; ++k){
+ if ( count + 3 * stride < size &&
+ ((size_t) tile_data & 0x0f) == 0 &&
+ ((size_t) buffer_data_ptr & 0x0f) == 0 &&
+ (stride & 0x0f) == 0 ) {
+ /* Fast code path */
+ for(i = 0; i < count; ++i){
+ OPJ_INT32 j = i;
+ buffer_data_ptr[i<<3 ] = tile_data[j];
+ j += stride;
+
+ buffer_data_ptr[(i<<3) + 1] = tile_data[j];
+ j += stride;
+
+ buffer_data_ptr[(i<<3) + 2] = tile_data[j];
+ j += stride;
+
+ buffer_data_ptr[(i<<3) + 3] = tile_data[j];
+ }
+ }
+ else {
+ /* Slow code path */
+ for(i = 0; i < count; ++i){
+ OPJ_INT32 j = i;
+
+ buffer_data_ptr[i<<3 ] = tile_data[j];
+ j += stride;
+ if(j >= size)
+ continue;
+
+ buffer_data_ptr[(i<<3) + 1] = tile_data[j];
+ j += stride;
+ if(j >= size)
+ continue;
+
+ buffer_data_ptr[(i<<3) + 2] = tile_data[j];
+ j += stride;
+ if(j >= size)
+ continue;
+
+ buffer_data_ptr[(i<<3) + 3] = tile_data[j];
+ }
+ }
+
+ buffer_data_ptr = (OPJ_FLOAT32*) (buffer->data + 1 - buffer->odd_dimension);
+ tile_data += buffer->s_dim;
+ size -= buffer->s_dim;
+ count = buffer->d_dim;
+ }
+}
+
+static void opj_region_interleave97_v(opj_dwt97_t* restrict buffer_v ,
+ OPJ_FLOAT32* restrict tile_data ,
+ OPJ_INT32 stride,
+ OPJ_INT32 nb_elts_read){
+ opj_coeff97_t* restrict buffer_data_ptr = buffer_v->data + buffer_v->odd_dimension;
+ OPJ_INT32 i;
+
+ for(i = 0; i < buffer_v->s_dim; ++i){
+ memcpy(buffer_data_ptr + (i<<1),
+ tile_data + i*stride,
+ (size_t)nb_elts_read * sizeof(OPJ_FLOAT32));
+ }
+
+ tile_data += buffer_v->s_dim * stride;
+ buffer_data_ptr = buffer_v->data + 1 - buffer_v->odd_dimension;
+
+ for(i = 0; i < buffer_v->d_dim; ++i){
+ memcpy(buffer_data_ptr + (i<<1),
+ tile_data + i*stride,
+ (size_t)nb_elts_read * sizeof(OPJ_FLOAT32));
+ }
+}
+
+static void opj_region_decode97_scale(opj_coeff97_t* buffer,
+ OPJ_INT32 count,
+ const OPJ_FLOAT32 scale)
+{
+ OPJ_FLOAT32* restrict fw = (OPJ_FLOAT32*) buffer;
+ OPJ_INT32 i;
+ for(i = 0; i < count; ++i){
+ fw[(i<<3) ] *= scale;
+ fw[(i<<3) + 1] *= scale;
+ fw[(i<<3) + 2] *= scale;
+ fw[(i<<3) + 3] *= scale;
+ }
+}
+
+static void opj_region_decode97_lift(opj_coeff97_t* l,
+ opj_coeff97_t* w,
+ OPJ_INT32 k,
+ OPJ_INT32 m,
+ OPJ_FLOAT32 c)
+{
+ OPJ_FLOAT32* fl = (OPJ_FLOAT32*) l;
+ OPJ_FLOAT32* fw = (OPJ_FLOAT32*) w;
+ OPJ_INT32 i;
+ for(i = 0; i < m; ++i){
+ OPJ_FLOAT32 tmp1_1 = fl[0];
+ OPJ_FLOAT32 tmp1_2 = fl[1];
+ OPJ_FLOAT32 tmp1_3 = fl[2];
+ OPJ_FLOAT32 tmp1_4 = fl[3];
+ OPJ_FLOAT32 tmp2_1 = fw[-4];
+ OPJ_FLOAT32 tmp2_2 = fw[-3];
+ OPJ_FLOAT32 tmp2_3 = fw[-2];
+ OPJ_FLOAT32 tmp2_4 = fw[-1];
+ OPJ_FLOAT32 tmp3_1 = fw[0];
+ OPJ_FLOAT32 tmp3_2 = fw[1];
+ OPJ_FLOAT32 tmp3_3 = fw[2];
+ OPJ_FLOAT32 tmp3_4 = fw[3];
+ fw[-4] = tmp2_1 + ((tmp1_1 + tmp3_1) * c);
+ fw[-3] = tmp2_2 + ((tmp1_2 + tmp3_2) * c);
+ fw[-2] = tmp2_3 + ((tmp1_3 + tmp3_3) * c);
+ fw[-1] = tmp2_4 + ((tmp1_4 + tmp3_4) * c);
+ fl = fw;
+ fw += 8;
+ }
+ if(m < k){
+ OPJ_FLOAT32 c1;
+ OPJ_FLOAT32 c2;
+ OPJ_FLOAT32 c3;
+ OPJ_FLOAT32 c4;
+ c += c;
+ c1 = fl[0] * c;
+ c2 = fl[1] * c;
+ c3 = fl[2] * c;
+ c4 = fl[3] * c;
+ for(; m < k; ++m){
+ OPJ_FLOAT32 tmp1 = fw[-4];
+ OPJ_FLOAT32 tmp2 = fw[-3];
+ OPJ_FLOAT32 tmp3 = fw[-2];
+ OPJ_FLOAT32 tmp4 = fw[-1];
+ fw[-4] = tmp1 + c1;
+ fw[-3] = tmp2 + c2;
+ fw[-2] = tmp3 + c3;
+ fw[-1] = tmp4 + c4;
+ fw += 8;
+ }
+ }
+}
+
+
+/* */
+/* Inverse 9-7 data transform in 1-D. */
+/* */
+static void opj_region_decode97(opj_dwt97_t* restrict dwt)
+{
+ /* a,b are either 0 or 1 */
+ OPJ_INT32 a = dwt->odd_dimension != 0;
+ OPJ_INT32 b = dwt->odd_dimension == 0;
+
+ if (!((dwt->d_dim > a) || (dwt->s_dim > b))) {
+ return;
+ }
+
+ opj_region_decode97_scale(dwt->data+a, dwt->s_dim, opj_K);
+ opj_region_decode97_scale(dwt->data+b, dwt->d_dim, opj_c13318);
+ opj_region_decode97_lift(dwt->data+b, dwt->data+a+1, dwt->s_dim, opj_int_min(dwt->s_dim, dwt->d_dim-a), opj_dwt_delta);
+ opj_region_decode97_lift(dwt->data+a, dwt->data+b+1, dwt->d_dim, opj_int_min(dwt->d_dim, dwt->s_dim-b), opj_dwt_gamma);
+ opj_region_decode97_lift(dwt->data+b, dwt->data+a+1, dwt->s_dim, opj_int_min(dwt->s_dim, dwt->d_dim-a), opj_dwt_beta);
+ opj_region_decode97_lift(dwt->data+a, dwt->data+b+1, dwt->d_dim, opj_int_min(dwt->d_dim, dwt->s_dim-b), opj_dwt_alpha);
+
+}
+
+
+/* */
+/* Inverse 9-7 data transform in 2-D. */
+/* */
+OPJ_BOOL opj_dwt_region_decode97(opj_tcd_tilecomp_t* restrict tilec, OPJ_UINT32 numres)
+{
+ opj_dwt97_t buffer_h;
+ opj_dwt97_t buffer_v;
+
+ opj_tcd_resolution_t* res = tilec->resolutions;
+
+ /* start with lowest resolution */
+ OPJ_UINT32 rw = (OPJ_UINT32)(res->x1 - res->x0); /* width of the resolution level computed */
+ OPJ_UINT32 rh = (OPJ_UINT32)(res->y1 - res->y0); /* height of the resolution level computed */
+
+ OPJ_UINT32 w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
+
+ buffer_h.data = (opj_coeff97_t*) opj_aligned_malloc((opj_dwt_max_resolution(res, numres)) * sizeof(opj_coeff97_t));
+ if (!buffer_h.data) {
+ /* FIXME event manager error callback */
+ return OPJ_FALSE;
+ }
+ /* share data buffer between vertical and horizontal lifting steps*/
+ buffer_v.data = buffer_h.data;
+
+ while( --numres) {
+ OPJ_FLOAT32 * restrict tile_data = (OPJ_FLOAT32*) tilec->buf->data;
+ OPJ_UINT32 bufsize = (OPJ_UINT32)((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0));
+ OPJ_INT32 j;
+
+ buffer_h.s_dim = (OPJ_INT32)rw;
+ buffer_v.s_dim = (OPJ_INT32)rh;
+
+ ++res;
+
+ /* next higher resolution */
+ rw = (OPJ_UINT32)(res->x1 - res->x0); /* width of the resolution level computed */
+ rh = (OPJ_UINT32)(res->y1 - res->y0); /* height of the resolution level computed */
+
+ buffer_h.d_dim = (OPJ_INT32)(rw - (OPJ_UINT32)buffer_h.s_dim);
+ buffer_h.odd_dimension = res->x0 &1;
+
+ for(j = (OPJ_INT32)rh; j > 3; j -= 4) {
+ OPJ_INT32 k;
+ opj_region_interleave97_h(&buffer_h, tile_data, (OPJ_INT32)w, (OPJ_INT32)bufsize);
+ opj_region_decode97(&buffer_h);
+
+ for(k = (OPJ_INT32)rw; --k >= 0;){
+ tile_data[k ] = buffer_h.data[k].f[0];
+ tile_data[k+(OPJ_INT32)w ] = buffer_h.data[k].f[1];
+ tile_data[k+((OPJ_INT32)w<<1)] = buffer_h.data[k].f[2];
+ tile_data[k+(OPJ_INT32)w*3] = buffer_h.data[k].f[3];
+ }
+
+ tile_data += w<<2;
+ bufsize -= w<<2;
+ }
+
+ if (j > 0) {
+ OPJ_INT32 k;
+ opj_region_interleave97_h(&buffer_h, tile_data, (OPJ_INT32)w, (OPJ_INT32)bufsize);
+ opj_region_decode97(&buffer_h);
+ for(k = (OPJ_INT32)rw; --k >= 0;){
+ switch(j) {
+ case 3:
+ tile_data[k+((OPJ_INT32)w<<1)] = buffer_h.data[k].f[2];
+ case 2:
+ tile_data[k+(OPJ_INT32)w ] = buffer_h.data[k].f[1];
+ case 1:
+ tile_data[k ] = buffer_h.data[k].f[0];
+ }
+ }
+ }
+
+ buffer_v.d_dim = (OPJ_INT32)(rh - (OPJ_UINT32)buffer_v.s_dim);
+ buffer_v.odd_dimension = res->y0 &1;
+
+ tile_data = (OPJ_FLOAT32*) tilec->buf->data;
+ for(j = (OPJ_INT32)rw; j > 3; j -= 4){
+ OPJ_UINT32 k;
+
+ opj_region_interleave97_v(&buffer_v, tile_data, (OPJ_INT32)w, 4);
+ opj_region_decode97(&buffer_v);
+
+ for(k = 0; k < rh; ++k){
+ memcpy(tile_data +k*w, buffer_v.data+k, 4 * sizeof(OPJ_FLOAT32));
+ }
+ tile_data += 4;
+ }
+
+ if (j > 0){
+ OPJ_UINT32 k;
+ opj_region_interleave97_v(&buffer_v, tile_data, (OPJ_INT32)w, j);
+ opj_region_decode97(&buffer_v);
+
+ for(k = 0; k < rh; ++k){
+ memcpy(tile_data + k*w, buffer_v.data+k, (size_t)j * sizeof(OPJ_FLOAT32));
+ }
+ }
+ }
+
+ opj_aligned_free(buffer_h.data);
+ return OPJ_TRUE;
+}
diff --git a/src/lib/openjp2/dwt_region.h b/src/lib/openjp2/dwt_region.h
new file mode 100644
index 00000000..c2775b20
--- /dev/null
+++ b/src/lib/openjp2/dwt_region.h
@@ -0,0 +1,60 @@
+/*
+ * The copyright in this software is being made available under the 2-clauses
+ * BSD License, included below. This software may be subject to other third
+ * party and contributor rights, including patent rights, and no such rights
+ * are granted under this license.
+ *
+ * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2014, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux
+ * Copyright (c) 2003-2014, Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DWT_REGION_H
+#define __DWT_REGION_H
+
+ /**
+ Inverse 5-3 wavelet transform in 2-D.
+ Apply a reversible inverse DWT transform to a component of an image.
+ @param tilec Tile component information (current tile)
+ @param numres Number of resolution levels to decode
+ */
+OPJ_BOOL opj_dwt_region_decode53(opj_tcd_tilecomp_t* tilec, OPJ_UINT32 numres);
+
+
+
+/**
+Inverse 9-7 wavelet transform in 2-D.
+Apply an irreversible inverse DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+@param numres Number of resolution levels to decode
+*/
+OPJ_BOOL opj_dwt_region_decode97(opj_tcd_tilecomp_t* restrict tilec, OPJ_UINT32 numres);
+
+
+#endif /* __DWT_REGION_H */
diff --git a/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c
index 80b64022..87c7b8ac 100644
--- a/src/lib/openjp2/j2k.c
+++ b/src/lib/openjp2/j2k.c
@@ -10255,7 +10255,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
l_tilec->buf->data = l_img_comp->data;
l_tilec->buf->owns_data = OPJ_FALSE;
} else {
- if(! opj_tile_buf_alloc_component_data(l_tilec->buf)) {
+ if(! opj_tile_buf_alloc_component_data_encode(l_tilec->buf)) {
opj_event_msg(p_manager, EVT_ERROR, "Error allocating tile component data." );
if (l_current_data) {
opj_free(l_current_data);
@@ -11066,7 +11066,7 @@ OPJ_BOOL opj_j2k_write_tile (opj_j2k_t * p_j2k,
for (j=0;jm_tcd->image->numcomps;++j) {
opj_tcd_tilecomp_t* l_tilec = p_j2k->m_tcd->current_tile->comps + j;
- if(!opj_tile_buf_alloc_component_data(l_tilec->buf)) {
+ if(!opj_tile_buf_alloc_component_data_encode(l_tilec->buf)) {
opj_event_msg(p_manager, EVT_ERROR, "Error allocating tile component data." );
return OPJ_FALSE;
}
diff --git a/src/lib/openjp2/opj_includes.h b/src/lib/openjp2/opj_includes.h
index 9100985b..21d1997a 100644
--- a/src/lib/openjp2/opj_includes.h
+++ b/src/lib/openjp2/opj_includes.h
@@ -198,6 +198,7 @@ static INLINE long opj_lrintf(float f) {
#include "t1.h"
#include "t1_opt.h"
#include "dwt.h"
+#include "dwt_region.h"
#include "t2.h"
#include "mct.h"
#include "opj_intmath.h"
diff --git a/src/lib/openjp2/t1.c b/src/lib/openjp2/t1.c
index 44861d40..7913f875 100644
--- a/src/lib/openjp2/t1.c
+++ b/src/lib/openjp2/t1.c
@@ -1325,7 +1325,7 @@ OPJ_BOOL opj_t1_decode_cblks( opj_tcd_tilecomp_t* tilec,
OPJ_UINT32 tile_w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
OPJ_BOOL rc = OPJ_TRUE;
- if (!opj_tile_buf_alloc_component_data(tilec->buf)) {
+ if (!opj_tile_buf_alloc_component_data_decode(tilec->buf)) {
opj_event_msg(p_manager, EVT_ERROR, "Not enough memory for tile data\n");
return OPJ_FALSE;
}
diff --git a/src/lib/openjp2/tile_buf.c b/src/lib/openjp2/tile_buf.c
index 433ab6b6..be74964e 100644
--- a/src/lib/openjp2/tile_buf.c
+++ b/src/lib/openjp2/tile_buf.c
@@ -60,7 +60,7 @@ OPJ_BOOL opj_tile_buf_create_component(opj_tcd_tilecomp_t* tilec,
tile_offset.x = -tilec->x0;
tile_offset.y = -tilec->y0;
opj_rect_pan(&comp->dim, &tile_offset);
-
+ opj_rect_pan(&comp->tile_dim, &tile_offset);
/* for encode, we don't need to allocate resolutions */
if (!output_image) {
@@ -143,8 +143,17 @@ OPJ_BOOL opj_tile_buf_create_component(opj_tcd_tilecomp_t* tilec,
return OPJ_TRUE;
}
-OPJ_BOOL opj_tile_buf_alloc_component_data(opj_tile_buf_component_t* buf)
+OPJ_BOOL opj_tile_buf_is_decode_region(opj_tile_buf_component_t* buf) {
+ if (!buf)
+ return OPJ_FALSE;
+ return !opj_rect_are_equal(&buf->dim, &buf->tile_dim);
+}
+
+OPJ_BOOL opj_tile_buf_alloc_component_data_encode(opj_tile_buf_component_t* buf)
{
+ if (!buf)
+ return OPJ_FALSE;
+
if ((buf->data == 00) || ((buf->data_size_needed > buf->data_size) && (buf->owns_data == OPJ_FALSE))) {
buf->data = (OPJ_INT32 *)opj_aligned_malloc(buf->data_size_needed);
if (!buf->data) {
@@ -171,6 +180,30 @@ OPJ_BOOL opj_tile_buf_alloc_component_data(opj_tile_buf_component_t* buf)
return OPJ_TRUE;
}
+
+OPJ_BOOL opj_tile_buf_alloc_component_data_decode(opj_tile_buf_component_t* buf)
+{
+ if (!buf)
+ return OPJ_FALSE;
+
+ if (!buf->data ){
+ OPJ_INT32 area = opj_rect_get_area(&buf->tile_dim);
+ if (!area)
+ return OPJ_FALSE;
+ buf->data = (OPJ_INT32 *)opj_aligned_malloc( area * sizeof(OPJ_INT32));
+ if (!buf->data) {
+ return OPJ_FALSE;
+ }
+ /*fprintf(stderr, "tAllocate data of tilec (int): %d x OPJ_UINT32n",l_data_size);*/
+ buf->data_size = area * sizeof(OPJ_INT32);
+ buf->data_size_needed = buf->data_size;
+ buf->owns_data = OPJ_TRUE;
+ }
+
+ return OPJ_TRUE;
+}
+
+
void opj_tile_buf_destroy_component(opj_tile_buf_component_t* comp) {
if (!comp)
return;
diff --git a/src/lib/openjp2/tile_buf.h b/src/lib/openjp2/tile_buf.h
index e7d9ac08..31aa72eb 100644
--- a/src/lib/openjp2/tile_buf.h
+++ b/src/lib/openjp2/tile_buf.h
@@ -33,8 +33,11 @@ typedef struct opj_tile_buf_component {
} opj_tile_buf_component_t;
+OPJ_BOOL opj_tile_buf_alloc_component_data_decode(opj_tile_buf_component_t* buf);
-OPJ_BOOL opj_tile_buf_alloc_component_data(opj_tile_buf_component_t* buf);
+OPJ_BOOL opj_tile_buf_alloc_component_data_encode(opj_tile_buf_component_t* buf);
+
+OPJ_BOOL opj_tile_buf_is_decode_region(opj_tile_buf_component_t* buf);
void opj_tile_buf_destroy_component(opj_tile_buf_component_t* comp);
diff --git a/src/lib/openjp2/util.c b/src/lib/openjp2/util.c
index c777afb2..52782eca 100644
--- a/src/lib/openjp2/util.c
+++ b/src/lib/openjp2/util.c
@@ -43,6 +43,12 @@ OPJ_BOOL opj_rect_is_non_degenerate(opj_rect_t* rect) {
}
OPJ_BOOL opj_rect_are_equal(opj_rect_t* r1, opj_rect_t* r2) {
+ if (!r1 && !r2)
+ return OPJ_TRUE;
+
+ if (!r1 || !r2)
+ return OPJ_FALSE;
+
return r1->x0 == r2->x0 &&
r1->y0 == r2->y0 &&
r1->x1 == r2->x1 &&
@@ -84,6 +90,12 @@ void opj_rect_zoom(opj_rect_t* r, OPJ_FLOAT32 factor) {
}
+OPJ_INT32 opj_rect_get_area(opj_rect_t* r) {
+ if (!r)
+ return 0;
+ return (r->x1 - r->x0) * (r->y1 - r->y0);
+}
+
void opj_rect_pan(opj_rect_t* r, opj_pt_t* shift) {
if (!r)
return;
diff --git a/src/lib/openjp2/util.h b/src/lib/openjp2/util.h
index 2f81ec1e..96b0d681 100644
--- a/src/lib/openjp2/util.h
+++ b/src/lib/openjp2/util.h
@@ -29,6 +29,8 @@ void opj_rect_init(opj_rect_t* r, OPJ_INT32 x0, OPJ_INT32 y0, OPJ_INT32 x1, OPJ_
/* valid if x0 <= x1 && y0 <= y1. Can included degenerate rectangles: line and point*/
OPJ_BOOL opj_rect_is_valid(opj_rect_t* rect);
+OPJ_INT32 opj_rect_get_area(opj_rect_t* r);
+
OPJ_BOOL opj_rect_is_non_degenerate(opj_rect_t* rect);
OPJ_BOOL opj_rect_is_valid(opj_rect_t* rect);