summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2017-08-14 13:23:57 +0200
committerEven Rouault <even.rouault@spatialys.com>2017-08-17 19:05:54 +0200
commitfe338a057c39797bf61939471ebaef09e44464c7 (patch)
treec468abed56c47f7a1fd8d40f0ebbb44c2a404383 /src/lib
parent17ea17f487a777d14bd322ac06c4e6cb9124a226 (diff)
Sub-tile decoding: only decode precincts and codeblocks that intersect the window specified in opj_set_decode_area()
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/openjp2/j2k.c21
-rw-r--r--src/lib/openjp2/t1.c14
-rw-r--r--src/lib/openjp2/t1.h4
-rw-r--r--src/lib/openjp2/t2.c50
-rw-r--r--src/lib/openjp2/t2.h5
-rw-r--r--src/lib/openjp2/tcd.c82
-rw-r--r--src/lib/openjp2/tcd.h40
7 files changed, 206 insertions, 10 deletions
diff --git a/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c
index 6c1f55f4..fe40e29f 100644
--- a/src/lib/openjp2/j2k.c
+++ b/src/lib/openjp2/j2k.c
@@ -16,6 +16,7 @@
* Copyright (c) 2010-2011, Kaori Hagihara
* Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -5162,7 +5163,13 @@ static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k,
++l_img_comp;
}
- l_tile_size = (OPJ_UINT32)(l_tile_size * 0.1625); /* 1.3/8 = 0.1625 */
+ /* TODO: where does this magic value come from ? */
+ /* This used to be 1.3 / 8, but with random data and very small code */
+ /* block sizes, this is not enough. For example with */
+ /* bin/test_tile_encoder 1 256 256 32 32 8 0 reversible_with_precinct.j2k 4 4 3 0 0 1 16 16 */
+ /* TODO revise this to take into account the overhead linked to the */
+ /* number of packets and number of code blocks in packets */
+ l_tile_size = (OPJ_UINT32)(l_tile_size * 1.4 / 8);
l_tile_size += opj_j2k_get_specific_header_sizes(p_j2k);
@@ -8770,6 +8777,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
OPJ_UINT32 l_current_marker;
OPJ_BYTE l_data [2];
opj_tcp_t * l_tcp;
+ opj_image_t* l_image_for_bounds;
/* preconditions */
assert(p_stream != 00);
@@ -8787,7 +8795,18 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
return OPJ_FALSE;
}
+ /* When using the opj_read_tile_header / opj_decode_tile_data API */
+ /* such as in test_tile_decoder, m_output_image is NULL, so fall back */
+ /* to the full image dimension. This is a bit surprising that */
+ /* opj_set_decode_area() is only used to determinte intersecting tiles, */
+ /* but full tile decoding is done */
+ l_image_for_bounds = p_j2k->m_output_image ? p_j2k->m_output_image :
+ p_j2k->m_private_image;
if (! opj_tcd_decode_tile(p_j2k->m_tcd,
+ l_image_for_bounds->x0,
+ l_image_for_bounds->y0,
+ l_image_for_bounds->x1,
+ l_image_for_bounds->y1,
l_tcp->m_data,
l_tcp->m_data_size,
p_tile_index,
diff --git a/src/lib/openjp2/t1.c b/src/lib/openjp2/t1.c
index eb5d6e0e..af6732b3 100644
--- a/src/lib/openjp2/t1.c
+++ b/src/lib/openjp2/t1.c
@@ -1751,7 +1751,7 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls)
}
-void opj_t1_decode_cblks(opj_thread_pool_t* tp,
+void opj_t1_decode_cblks(opj_tcd_t* tcd,
volatile OPJ_BOOL* pret,
opj_tcd_tilecomp_t* tilec,
opj_tccp_t* tccp,
@@ -1760,6 +1760,7 @@ void opj_t1_decode_cblks(opj_thread_pool_t* tp,
OPJ_BOOL check_pterm
)
{
+ opj_thread_pool_t* tp = tcd->thread_pool;
OPJ_UINT32 resno, bandno, precno, cblkno;
for (resno = 0; resno < tilec->minimum_num_resolutions; ++resno) {
@@ -1775,6 +1776,17 @@ void opj_t1_decode_cblks(opj_thread_pool_t* tp,
opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno];
opj_t1_cblk_decode_processing_job_t* job;
+ if (!opj_tcd_is_subband_area_of_interest(tcd,
+ tilec->compno,
+ resno,
+ band->bandno,
+ (OPJ_UINT32)cblk->x0,
+ (OPJ_UINT32)cblk->y0,
+ (OPJ_UINT32)cblk->x1,
+ (OPJ_UINT32)cblk->y1)) {
+ continue;
+ }
+
job = (opj_t1_cblk_decode_processing_job_t*) opj_calloc(1,
sizeof(opj_t1_cblk_decode_processing_job_t));
if (!job) {
diff --git a/src/lib/openjp2/t1.h b/src/lib/openjp2/t1.h
index 5aa6a07b..171dfb0a 100644
--- a/src/lib/openjp2/t1.h
+++ b/src/lib/openjp2/t1.h
@@ -230,7 +230,7 @@ OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1,
/**
Decode the code-blocks of a tile
-@param tp Thread pool
+@param tcd TCD handle
@param pret Pointer to return value
@param tilec The tile to decode
@param tccp Tile coding parameters
@@ -238,7 +238,7 @@ Decode the code-blocks of a tile
@param p_manager_mutex mutex for the event manager
@param check_pterm whether PTERM correct termination should be checked
*/
-void opj_t1_decode_cblks(opj_thread_pool_t* tp,
+void opj_t1_decode_cblks(opj_tcd_t* tcd,
volatile OPJ_BOOL* pret,
opj_tcd_tilecomp_t* tilec,
opj_tccp_t* tccp,
diff --git a/src/lib/openjp2/t2.c b/src/lib/openjp2/t2.c
index 0fd5300c..6f956d1c 100644
--- a/src/lib/openjp2/t2.c
+++ b/src/lib/openjp2/t2.c
@@ -13,6 +13,7 @@
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -369,7 +370,8 @@ static void opj_null_jas_fprintf(FILE* file, const char * format, ...)
#define JAS_FPRINTF opj_null_jas_fprintf
#endif
-OPJ_BOOL opj_t2_decode_packets(opj_t2_t *p_t2,
+OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd,
+ opj_t2_t *p_t2,
OPJ_UINT32 p_tile_no,
opj_tcd_tile_t *p_tile,
OPJ_BYTE *p_src,
@@ -434,14 +436,54 @@ OPJ_BOOL opj_t2_decode_packets(opj_t2_t *p_t2,
memset(first_pass_failed, OPJ_TRUE, l_image->numcomps * sizeof(OPJ_BOOL));
while (opj_pi_next(l_current_pi)) {
+ OPJ_BOOL skip_packet = OPJ_FALSE;
JAS_FPRINTF(stderr,
"packet offset=00000166 prg=%d cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d\n\n",
l_current_pi->poc.prg1, l_current_pi->compno, l_current_pi->resno,
l_current_pi->precno, l_current_pi->layno);
- if (l_tcp->num_layers_to_decode > l_current_pi->layno
- && l_current_pi->resno <
- p_tile->comps[l_current_pi->compno].minimum_num_resolutions) {
+ /* If the packet layer is greater or equal than the maximum */
+ /* number of layers, skip the packet */
+ if (l_current_pi->layno >= l_tcp->num_layers_to_decode) {
+ skip_packet = OPJ_TRUE;
+ }
+ /* If the packet resolution number is greater than the minimum */
+ /* number of resolution allowed, skip the packet */
+ else if (l_current_pi->resno >=
+ p_tile->comps[l_current_pi->compno].minimum_num_resolutions) {
+ skip_packet = OPJ_TRUE;
+ } else {
+ /* If no precincts of any band intersects the area of interest, */
+ /* skip the packet */
+ OPJ_UINT32 bandno;
+ opj_tcd_tilecomp_t *tilec = &p_tile->comps[l_current_pi->compno];
+ opj_tcd_resolution_t *res = &tilec->resolutions[l_current_pi->resno];
+
+ skip_packet = OPJ_TRUE;
+ for (bandno = 0; bandno < res->numbands; ++bandno) {
+ opj_tcd_band_t* band = &res->bands[bandno];
+ opj_tcd_precinct_t* prec = &band->precincts[l_current_pi->precno];
+
+ if (opj_tcd_is_subband_area_of_interest(tcd,
+ l_current_pi->compno,
+ l_current_pi->resno,
+ band->bandno,
+ (OPJ_UINT32)prec->x0,
+ (OPJ_UINT32)prec->y0,
+ (OPJ_UINT32)prec->x1,
+ (OPJ_UINT32)prec->y1)) {
+ skip_packet = OPJ_FALSE;
+ break;
+ }
+ }
+ /*
+ printf("packet cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d -> %s\n",
+ l_current_pi->compno, l_current_pi->resno,
+ l_current_pi->precno, l_current_pi->layno, skip_packet ? "skipped" : "kept");
+ */
+ }
+
+ if (!skip_packet) {
l_nb_bytes_read = 0;
first_pass_failed[l_current_pi->compno] = OPJ_FALSE;
diff --git a/src/lib/openjp2/t2.h b/src/lib/openjp2/t2.h
index 111aa2de..66500b16 100644
--- a/src/lib/openjp2/t2.h
+++ b/src/lib/openjp2/t2.h
@@ -13,6 +13,7 @@
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -94,6 +95,7 @@ OPJ_BOOL opj_t2_encode_packets(opj_t2_t* t2,
/**
Decode the packets of a tile from a source buffer
+@param tcd TCD handle
@param t2 T2 handle
@param tileno number that identifies the tile for which to decode the packets
@param tile tile for which to decode the packets
@@ -105,7 +107,8 @@ Decode the packets of a tile from a source buffer
@return FIXME DOC
*/
-OPJ_BOOL opj_t2_decode_packets(opj_t2_t *t2,
+OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd,
+ opj_t2_t *t2,
OPJ_UINT32 tileno,
opj_tcd_tile_t *tile,
OPJ_BYTE *src,
diff --git a/src/lib/openjp2/tcd.c b/src/lib/openjp2/tcd.c
index 53cdcf64..f90816fc 100644
--- a/src/lib/openjp2/tcd.c
+++ b/src/lib/openjp2/tcd.c
@@ -14,6 +14,7 @@
* Copyright (c) 2006-2007, Parvatha Elangovan
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -790,6 +791,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
l_tilec->y0 = opj_int_ceildiv(l_tile->y0, (OPJ_INT32)l_image_comp->dy);
l_tilec->x1 = opj_int_ceildiv(l_tile->x1, (OPJ_INT32)l_image_comp->dx);
l_tilec->y1 = opj_int_ceildiv(l_tile->y1, (OPJ_INT32)l_image_comp->dy);
+ l_tilec->compno = compno;
/*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/
/* compute l_data_size with overflow check */
@@ -1399,6 +1401,10 @@ OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd,
}
OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
+ OPJ_UINT32 decoded_x0,
+ OPJ_UINT32 decoded_y0,
+ OPJ_UINT32 decoded_x1,
+ OPJ_UINT32 decoded_y1,
OPJ_BYTE *p_src,
OPJ_UINT32 p_max_length,
OPJ_UINT32 p_tile_no,
@@ -1409,6 +1415,10 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
OPJ_UINT32 l_data_read;
p_tcd->tcd_tileno = p_tile_no;
p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]);
+ p_tcd->decoded_x0 = decoded_x0;
+ p_tcd->decoded_y0 = decoded_y0;
+ p_tcd->decoded_x1 = decoded_x1;
+ p_tcd->decoded_y1 = decoded_y1;
#ifdef TODO_MSD /* FIXME */
/* INDEX >> */
@@ -1690,6 +1700,7 @@ static OPJ_BOOL opj_tcd_t2_decode(opj_tcd_t *p_tcd,
}
if (! opj_t2_decode_packets(
+ p_tcd,
l_t2,
p_tcd->tcd_tileno,
p_tcd->tcd_image->tiles,
@@ -1727,7 +1738,7 @@ static OPJ_BOOL opj_tcd_t1_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager)
}
for (compno = 0; compno < l_tile->numcomps; ++compno) {
- opj_t1_decode_cblks(p_tcd->thread_pool, &ret, l_tile_comp, l_tccp,
+ opj_t1_decode_cblks(p_tcd, &ret, l_tile_comp, l_tccp,
p_manager, p_manager_mutex, check_pterm);
if (!ret) {
break;
@@ -2359,3 +2370,72 @@ OPJ_BOOL opj_tcd_is_band_empty(opj_tcd_band_t* band)
{
return (band->x1 - band->x0 == 0) || (band->y1 - band->y0 == 0);
}
+
+OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd,
+ OPJ_UINT32 compno,
+ OPJ_UINT32 resno,
+ OPJ_UINT32 bandno,
+ OPJ_UINT32 band_x0,
+ OPJ_UINT32 band_y0,
+ OPJ_UINT32 band_x1,
+ OPJ_UINT32 band_y1)
+{
+ OPJ_UINT32 filter_margin = (tcd->tcp->tccps[compno].qmfbid == 1) ? 2 : 3;
+ opj_tcd_tilecomp_t *tilec = &(tcd->tcd_image->tiles->comps[compno]);
+ opj_image_comp_t* image_comp = &(tcd->image->comps[compno]);
+ /* Compute the intersection of the area of interest, expressed in tile coordinates */
+ /* with the tile coordinates */
+ OPJ_UINT32 tcx0 = opj_uint_max(
+ (OPJ_UINT32)tilec->x0,
+ opj_uint_ceildiv(tcd->decoded_x0, image_comp->dx));
+ OPJ_UINT32 tcy0 = opj_uint_max(
+ (OPJ_UINT32)tilec->y0,
+ opj_uint_ceildiv(tcd->decoded_y0, image_comp->dy));
+ OPJ_UINT32 tcx1 = opj_uint_min(
+ (OPJ_UINT32)tilec->x1,
+ opj_uint_ceildiv(tcd->decoded_x1, image_comp->dx));
+ OPJ_UINT32 tcy1 = opj_uint_min(
+ (OPJ_UINT32)tilec->y1,
+ opj_uint_ceildiv(tcd->decoded_y1, image_comp->dy));
+ /* Compute number of decomposition for this band. See table F-1 */
+ OPJ_UINT32 nb = (resno == 0) ?
+ tilec->numresolutions - 1 :
+ tilec->numresolutions - resno;
+ /* Map above tile-based coordinates to sub-band-based coordinates per */
+ /* equation B-15 of the standard */
+ OPJ_UINT32 x0b = bandno & 1;
+ OPJ_UINT32 y0b = bandno >> 1;
+ OPJ_UINT32 tbx0 = (nb == 0) ? tcx0 : opj_uint_ceildiv(tcx0 - (1U <<
+ (nb - 1)) * x0b, 1U << nb);
+ OPJ_UINT32 tby0 = (nb == 0) ? tcy0 : opj_uint_ceildiv(tcy0 - (1U <<
+ (nb - 1)) * y0b, 1U << nb);
+ OPJ_UINT32 tbx1 = (nb == 0) ? tcx1 : opj_uint_ceildiv(tcx1 - (1U <<
+ (nb - 1)) * x0b, 1U << nb);
+ OPJ_UINT32 tby1 = (nb == 0) ? tcy1 : opj_uint_ceildiv(tcy1 - (1U <<
+ (nb - 1)) * y0b, 1U << nb);
+ OPJ_BOOL intersects;
+
+ if (tbx0 < filter_margin) {
+ tbx0 = 0;
+ } else {
+ tbx0 -= filter_margin;
+ }
+ if (tby0 < filter_margin) {
+ tby0 = 0;
+ } else {
+ tby0 -= filter_margin;
+ }
+ tbx1 = opj_uint_adds(tbx1, filter_margin);
+ tby1 = opj_uint_adds(tby1, filter_margin);
+
+ intersects = band_x0 < tbx1 && band_y0 < tby1 && band_x1 > tbx0 &&
+ band_y1 > tby0;
+
+#ifdef DEBUG_VERBOSE
+ printf("compno=%u resno=%u nb=%u bandno=%u x0b=%u y0b=%u band=%u,%u,%u,%u tb=%u,%u,%u,%u -> %u\n",
+ compno, resno, nb, bandno, x0b, y0b,
+ band_x0, band_y0, band_x1, band_y1,
+ tbx0, tby0, tbx1, tby1, intersects);
+#endif
+ return intersects;
+}
diff --git a/src/lib/openjp2/tcd.h b/src/lib/openjp2/tcd.h
index ff3f042c..bf645639 100644
--- a/src/lib/openjp2/tcd.h
+++ b/src/lib/openjp2/tcd.h
@@ -13,6 +13,7 @@
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France
+ * Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -180,6 +181,8 @@ typedef struct opj_tcd_resolution {
typedef struct opj_tcd_tilecomp {
/* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */
OPJ_INT32 x0, y0, x1, y1;
+ /* component number */
+ OPJ_UINT32 compno;
/* number of resolutions level */
OPJ_UINT32 numresolutions;
/* number of resolutions level to decode (at max)*/
@@ -252,6 +255,10 @@ typedef struct opj_tcd {
OPJ_BITFIELD m_is_decoder : 1;
/** Thread pool */
opj_thread_pool_t* thread_pool;
+ OPJ_UINT32 decoded_x0;
+ OPJ_UINT32 decoded_y0;
+ OPJ_UINT32 decoded_x1;
+ OPJ_UINT32 decoded_y1;
} opj_tcd_t;
/** @name Exported functions */
@@ -348,6 +355,10 @@ OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd,
/**
Decode a tile from a buffer into a raw image
@param tcd TCD handle
+@param decoded_x0 Upper left x of region to decode (in grid coordinates)
+@param decoded_y0 Upper left y of region to decode (in grid coordinates)
+@param decoded_x1 Lower right x of region to decode (in grid coordinates)
+@param decoded_y1 Lower right y of region to decode (in grid coordinates)
@param src Source buffer
@param len Length of source buffer
@param tileno Number that identifies one of the tiles to be decoded
@@ -355,6 +366,10 @@ Decode a tile from a buffer into a raw image
@param manager the event manager.
*/
OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *tcd,
+ OPJ_UINT32 decoded_x0,
+ OPJ_UINT32 decoded_y0,
+ OPJ_UINT32 decoded_x1,
+ OPJ_UINT32 decoded_y1,
OPJ_BYTE *src,
OPJ_UINT32 len,
OPJ_UINT32 tileno,
@@ -409,6 +424,31 @@ OPJ_BOOL opj_tcd_is_band_empty(opj_tcd_band_t* band);
/** Reinitialize a segment */
void opj_tcd_reinit_segment(opj_tcd_seg_t* seg);
+
+/** Returns whether a sub-band region contributes to the area of interest
+ * tcd->decoded_x0,tcd->decoded_y0,tcd->decoded_x1,tcd->decoded_y1.
+ *
+ * @param tcd TCD handle.
+ * @param compno Component number
+ * @param resno Resolution number
+ * @param bandno Band number (*not* band index, ie 0, 1, 2 or 3)
+ * @param x0 Upper left x in subband coordinates
+ * @param y0 Upper left y in subband coordinates
+ * @param x1 Lower right x in subband coordinates
+ * @param y1 Lower right y in subband coordinates
+ * @return OPJ_TRUE whether the sub-band region contributs to the area of
+ * interest.
+ */
+OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd,
+ OPJ_UINT32 compno,
+ OPJ_UINT32 resno,
+ OPJ_UINT32 bandno,
+ OPJ_UINT32 x0,
+ OPJ_UINT32 y0,
+ OPJ_UINT32 x1,
+ OPJ_UINT32 y1);
+
+
/* ----------------------------------------------------------------------- */
/*@}*/