summaryrefslogtreecommitdiff
path: root/src/lib/openjp2/tcd.c
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@mines-paris.org>2017-09-05 22:18:58 +0200
committerGitHub <noreply@github.com>2017-09-05 22:18:58 +0200
commit968e36bbd989fdf789c6a02c80c747346bb851c5 (patch)
tree6773f7cdc63663119105f031c2c5499cc9c5ffd7 /src/lib/openjp2/tcd.c
parent3a382d312306f45853b3ad78b770754d4bc7e440 (diff)
parent579b8937eae7e6b6868b8b5c6286a742c10a5130 (diff)
Merge pull request #1010 from rouault/subtile_decoding_stage3
Subtile decoding: memory use reduction and perf improvements
Diffstat (limited to 'src/lib/openjp2/tcd.c')
-rw-r--r--src/lib/openjp2/tcd.c452
1 files changed, 352 insertions, 100 deletions
diff --git a/src/lib/openjp2/tcd.c b/src/lib/openjp2/tcd.c
index 13d6692b..d577f024 100644
--- a/src/lib/openjp2/tcd.c
+++ b/src/lib/openjp2/tcd.c
@@ -190,6 +190,10 @@ static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd,
opj_codestream_info_t *p_cstr_info,
opj_event_mgr_t *p_manager);
+
+static OPJ_BOOL opj_tcd_is_whole_tilecomp_decoding(opj_tcd_t *tcd,
+ OPJ_UINT32 compno);
+
/* ----------------------------------------------------------------------- */
/**
@@ -685,7 +689,7 @@ OPJ_BOOL opj_alloc_tile_component_data(opj_tcd_tilecomp_t *l_tilec)
((l_tilec->data_size_needed > l_tilec->data_size) &&
(l_tilec->ownsData == OPJ_FALSE))) {
l_tilec->data = (OPJ_INT32 *) opj_image_data_alloc(l_tilec->data_size_needed);
- if (! l_tilec->data) {
+ if (!l_tilec->data && l_tilec->data_size_needed != 0) {
return OPJ_FALSE;
}
/*fprintf(stderr, "tAllocate data of tilec (int): %d x OPJ_UINT32n",l_data_size);*/
@@ -800,22 +804,6 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
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 */
- l_data_size = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0);
- /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */
- if ((l_data_size > 0U) &&
- ((((OPJ_UINT32) - 1) / l_data_size) < (OPJ_UINT32)(l_tilec->y1 -
- l_tilec->y0))) {
- opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
- return OPJ_FALSE;
- }
- l_data_size = l_data_size * (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0);
-
- if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof(OPJ_UINT32)) < l_data_size) {
- opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
- return OPJ_FALSE;
- }
- l_data_size = l_data_size * (OPJ_UINT32)sizeof(OPJ_UINT32);
l_tilec->numresolutions = l_tccp->numresolutions;
if (l_tccp->numresolutions < l_cp->m_specific_param.m_dec.m_reduce) {
l_tilec->minimum_num_resolutions = 1;
@@ -824,15 +812,39 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
l_cp->m_specific_param.m_dec.m_reduce;
}
- l_tilec->data_size_needed = l_data_size;
- if (p_tcd->m_is_decoder && !opj_alloc_tile_component_data(l_tilec)) {
- opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
- return OPJ_FALSE;
+ if (isEncoder) {
+ OPJ_SIZE_T l_tile_data_size;
+
+ /* compute l_data_size with overflow check */
+ OPJ_SIZE_T w = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0);
+ OPJ_SIZE_T h = (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0);
+
+ /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */
+ if (h > 0 && w > SIZE_MAX / h) {
+ opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n");
+ return OPJ_FALSE;
+ }
+ l_tile_data_size = w * h;
+
+ if (SIZE_MAX / sizeof(OPJ_UINT32) < l_tile_data_size) {
+ opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n");
+ return OPJ_FALSE;
+ }
+ l_tile_data_size = l_tile_data_size * sizeof(OPJ_UINT32);
+
+ l_tilec->data_size_needed = l_tile_data_size;
}
l_data_size = l_tilec->numresolutions * (OPJ_UINT32)sizeof(
opj_tcd_resolution_t);
+ opj_image_data_free(l_tilec->data_win);
+ l_tilec->data_win = NULL;
+ l_tilec->win_x0 = 0;
+ l_tilec->win_y0 = 0;
+ l_tilec->win_x1 = 0;
+ l_tilec->win_y1 = 0;
+
if (l_tilec->resolutions == 00) {
l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size);
if (! l_tilec->resolutions) {
@@ -881,6 +893,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no);
l_res->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no);
l_res->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no);
+
/*fprintf(stderr, "\t\t\tres_x0= %d, res_y0 =%d, res_x1=%d, res_y1=%d\n", l_res->x0, l_res->y0, l_res->x1, l_res->y1);*/
/* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */
l_pdx = l_tccp->prcw[resno];
@@ -900,14 +913,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
/*fprintf(stderr, "\t\t\tres_pw=%d, res_ph=%d\n", l_res->pw, l_res->ph );*/
if ((l_res->pw != 0U) && ((((OPJ_UINT32) - 1) / l_res->pw) < l_res->ph)) {
- opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
+ opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n");
return OPJ_FALSE;
}
l_nb_precincts = l_res->pw * l_res->ph;
if ((((OPJ_UINT32) - 1) / (OPJ_UINT32)sizeof(opj_tcd_precinct_t)) <
l_nb_precincts) {
- opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
+ opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n");
return OPJ_FALSE;
}
l_nb_precinct_size = l_nb_precincts * (OPJ_UINT32)sizeof(opj_tcd_precinct_t);
@@ -1255,6 +1268,9 @@ static OPJ_BOOL opj_tcd_code_block_dec_allocate(opj_tcd_cblk_dec_t *
OPJ_UINT32 l_numchunksalloc = p_code_block->numchunksalloc;
OPJ_UINT32 i;
+ opj_aligned_free(p_code_block->decoded_data);
+ p_code_block->decoded_data = 00;
+
memset(p_code_block, 0, sizeof(opj_tcd_cblk_dec_t));
p_code_block->segs = l_segs;
p_code_block->m_current_max_segs = l_current_max_segs;
@@ -1268,7 +1284,8 @@ static OPJ_BOOL opj_tcd_code_block_dec_allocate(opj_tcd_cblk_dec_t *
return OPJ_TRUE;
}
-OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd)
+OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd,
+ OPJ_BOOL take_into_account_partial_decoding)
{
OPJ_UINT32 i;
OPJ_UINT32 l_data_size = 0;
@@ -1282,6 +1299,7 @@ OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd)
l_img_comp = p_tcd->image->comps;
for (i = 0; i < p_tcd->image->numcomps; ++i) {
+ OPJ_UINT32 w, h;
l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
l_remaining = l_img_comp->prec & 7; /* (%8) */
@@ -1294,8 +1312,17 @@ OPJ_UINT32 opj_tcd_get_decoded_tile_size(opj_tcd_t *p_tcd)
}
l_res = l_tile_comp->resolutions + l_tile_comp->minimum_num_resolutions - 1;
- l_temp = (OPJ_UINT32)((l_res->x1 - l_res->x0) * (l_res->y1 -
- l_res->y0)); /* x1*y1 can't overflow */
+ if (take_into_account_partial_decoding && !p_tcd->whole_tile_decoding) {
+ w = l_res->win_x1 - l_res->win_x0;
+ h = l_res->win_y1 - l_res->win_y0;
+ } else {
+ w = (OPJ_UINT32)(l_res->x1 - l_res->x0);
+ h = (OPJ_UINT32)(l_res->y1 - l_res->y0);
+ }
+ if (h > 0 && UINT_MAX / w < h) {
+ return UINT_MAX;
+ }
+ l_temp = w * h;
if (l_size_comp && UINT_MAX / l_size_comp < l_temp) {
return UINT_MAX;
}
@@ -1345,7 +1372,8 @@ OPJ_BOOL opj_tcd_encode_tile(opj_tcd_t *p_tcd,
p_cstr_info->tile[p_tile_no].pdy[i] = (int)l_tccp->prch[i];
}
p_cstr_info->tile[p_tile_no].packet = (opj_packet_info_t*) opj_calloc((
- size_t)p_cstr_info->numcomps * (size_t)p_cstr_info->numlayers * l_num_packs,
+ OPJ_SIZE_T)p_cstr_info->numcomps * (OPJ_SIZE_T)p_cstr_info->numlayers *
+ l_num_packs,
sizeof(opj_packet_info_t));
if (!p_cstr_info->tile[p_tile_no].packet) {
/* FIXME event manager error callback */
@@ -1407,10 +1435,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_UINT32 win_x0,
+ OPJ_UINT32 win_y0,
+ OPJ_UINT32 win_x1,
+ OPJ_UINT32 win_y1,
OPJ_BYTE *p_src,
OPJ_UINT32 p_max_length,
OPJ_UINT32 p_tile_no,
@@ -1419,12 +1447,93 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
)
{
OPJ_UINT32 l_data_read;
+ OPJ_UINT32 compno;
+
p_tcd->tcd_tileno = p_tile_no;
p_tcd->tcp = &(p_tcd->cp->tcps[p_tile_no]);
- p_tcd->decoded_x0 = decoded_x0;
- p_tcd->decoded_y0 = decoded_y0;
- p_tcd->decoded_x1 = decoded_x1;
- p_tcd->decoded_y1 = decoded_y1;
+ p_tcd->win_x0 = win_x0;
+ p_tcd->win_y0 = win_y0;
+ p_tcd->win_x1 = win_x1;
+ p_tcd->win_y1 = win_y1;
+ p_tcd->whole_tile_decoding = OPJ_TRUE;
+
+ for (compno = 0; compno < p_tcd->image->numcomps; compno++) {
+ if (!opj_tcd_is_whole_tilecomp_decoding(p_tcd, compno)) {
+ p_tcd->whole_tile_decoding = OPJ_FALSE;
+ break;
+ }
+ }
+
+ if (p_tcd->whole_tile_decoding) {
+ for (compno = 0; compno < p_tcd->image->numcomps; compno++) {
+ opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]);
+ opj_tcd_resolution_t *l_res = &
+ (tilec->resolutions[tilec->minimum_num_resolutions - 1]);
+ OPJ_SIZE_T l_data_size;
+
+ /* compute l_data_size with overflow check */
+ OPJ_SIZE_T res_w = (OPJ_SIZE_T)(l_res->x1 - l_res->x0);
+ OPJ_SIZE_T res_h = (OPJ_SIZE_T)(l_res->y1 - l_res->y0);
+
+ /* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */
+ if (res_h > 0 && res_w > SIZE_MAX / res_h) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Size of tile data exceeds system limits\n");
+ return OPJ_FALSE;
+ }
+ l_data_size = res_w * res_h;
+
+ if (SIZE_MAX / sizeof(OPJ_UINT32) < l_data_size) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Size of tile data exceeds system limits\n");
+ return OPJ_FALSE;
+ }
+ l_data_size *= sizeof(OPJ_UINT32);
+
+ tilec->data_size_needed = l_data_size;
+
+ if (!opj_alloc_tile_component_data(tilec)) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Size of tile data exceeds system limits\n");
+ return OPJ_FALSE;
+ }
+ }
+ } else {
+ /* Compute restricted tile-component and tile-resolution coordinates */
+ /* of the window of interest, but defer the memory allocation until */
+ /* we know the resno_decoded */
+ for (compno = 0; compno < p_tcd->image->numcomps; compno++) {
+ OPJ_UINT32 resno;
+ opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]);
+ opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]);
+ /* Compute the intersection of the area of interest, expressed in tile coordinates */
+ /* with the tile coordinates */
+ tilec->win_x0 = opj_uint_max(
+ (OPJ_UINT32)tilec->x0,
+ opj_uint_ceildiv(p_tcd->win_x0, image_comp->dx));
+ tilec->win_y0 = opj_uint_max(
+ (OPJ_UINT32)tilec->y0,
+ opj_uint_ceildiv(p_tcd->win_y0, image_comp->dy));
+ tilec->win_x1 = opj_uint_min(
+ (OPJ_UINT32)tilec->x1,
+ opj_uint_ceildiv(p_tcd->win_x1, image_comp->dx));
+ tilec->win_y1 = opj_uint_min(
+ (OPJ_UINT32)tilec->y1,
+ opj_uint_ceildiv(p_tcd->win_y1, image_comp->dy));
+
+ for (resno = 0; resno < tilec->numresolutions; ++resno) {
+ opj_tcd_resolution_t *res = tilec->resolutions + resno;
+ res->win_x0 = opj_uint_ceildivpow2(tilec->win_x0,
+ tilec->numresolutions - 1 - resno);
+ res->win_y0 = opj_uint_ceildivpow2(tilec->win_y0,
+ tilec->numresolutions - 1 - resno);
+ res->win_x1 = opj_uint_ceildivpow2(tilec->win_x1,
+ tilec->numresolutions - 1 - resno);
+ res->win_y1 = opj_uint_ceildivpow2(tilec->win_y1,
+ tilec->numresolutions - 1 - resno);
+ }
+ }
+ }
#ifdef TODO_MSD /* FIXME */
/* INDEX >> */
@@ -1467,6 +1576,45 @@ OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *p_tcd,
}
/* FIXME _ProfStop(PGROUP_T1); */
+
+ /* For subtile decoding, now we know the resno_decoded, we can allocate */
+ /* the tile data buffer */
+ if (!p_tcd->whole_tile_decoding) {
+ for (compno = 0; compno < p_tcd->image->numcomps; compno++) {
+ opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]);
+ opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]);
+ opj_tcd_resolution_t *res = tilec->resolutions + image_comp->resno_decoded;
+ OPJ_SIZE_T w = res->win_x1 - res->win_x0;
+ OPJ_SIZE_T h = res->win_y1 - res->win_y0;
+ OPJ_SIZE_T l_data_size;
+
+ opj_image_data_free(tilec->data_win);
+ tilec->data_win = NULL;
+
+ if (w > 0 && h > 0) {
+ if (w > SIZE_MAX / h) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Size of tile data exceeds system limits\n");
+ return OPJ_FALSE;
+ }
+ l_data_size = w * h;
+ if (l_data_size > SIZE_MAX / sizeof(OPJ_INT32)) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Size of tile data exceeds system limits\n");
+ return OPJ_FALSE;
+ }
+ l_data_size *= sizeof(OPJ_INT32);
+
+ tilec->data_win = opj_image_data_alloc(l_data_size);
+ if (tilec->data_win == NULL) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Size of tile data exceeds system limits\n");
+ return OPJ_FALSE;
+ }
+ }
+ }
+ }
+
/*----------------DWT---------------------*/
/* FIXME _ProfStart(PGROUP_DWT); */
@@ -1508,7 +1656,7 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd,
OPJ_UINT32 l_size_comp, l_remaining;
OPJ_UINT32 l_stride, l_width, l_height;
- l_data_size = opj_tcd_get_decoded_tile_size(p_tcd);
+ l_data_size = opj_tcd_get_decoded_tile_size(p_tcd, OPJ_TRUE);
if (l_data_size == UINT_MAX || l_data_size > p_dest_length) {
return OPJ_FALSE;
}
@@ -1517,12 +1665,23 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd,
l_img_comp = p_tcd->image->comps;
for (i = 0; i < p_tcd->image->numcomps; ++i) {
+ const OPJ_INT32* l_src_data;
l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
l_remaining = l_img_comp->prec & 7; /* (%8) */
l_res = l_tilec->resolutions + l_img_comp->resno_decoded;
- l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0);
- l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0);
- l_stride = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0) - l_width;
+ if (p_tcd->whole_tile_decoding) {
+ l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0);
+ l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0);
+ l_stride = (OPJ_UINT32)(l_tilec->resolutions[l_tilec->minimum_num_resolutions -
+ 1].x1 -
+ l_tilec->resolutions[l_tilec->minimum_num_resolutions - 1].x0) - l_width;
+ l_src_data = l_tilec->data;
+ } else {
+ l_width = l_res->win_x1 - l_res->win_x0;
+ l_height = l_res->win_y1 - l_res->win_y0;
+ l_stride = 0;
+ l_src_data = l_tilec->data_win;
+ }
if (l_remaining) {
++l_size_comp;
@@ -1535,7 +1694,7 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd,
switch (l_size_comp) {
case 1: {
OPJ_CHAR * l_dest_ptr = (OPJ_CHAR *) p_dest;
- const OPJ_INT32 * l_src_ptr = l_tilec->data;
+ const OPJ_INT32 * l_src_ptr = l_src_data;
if (l_img_comp->sgnd) {
for (j = 0; j < l_height; ++j) {
@@ -1557,7 +1716,7 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd,
}
break;
case 2: {
- const OPJ_INT32 * l_src_ptr = l_tilec->data;
+ const OPJ_INT32 * l_src_ptr = l_src_data;
OPJ_INT16 * l_dest_ptr = (OPJ_INT16 *) p_dest;
if (l_img_comp->sgnd) {
@@ -1585,7 +1744,7 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd,
break;
case 4: {
OPJ_INT32 * l_dest_ptr = (OPJ_INT32 *) p_dest;
- OPJ_INT32 * l_src_ptr = l_tilec->data;
+ const OPJ_INT32 * l_src_ptr = l_src_data;
for (j = 0; j < l_height; ++j) {
memcpy(l_dest_ptr, l_src_ptr, l_width * sizeof(OPJ_INT32));
@@ -1680,6 +1839,9 @@ static void opj_tcd_free_tile(opj_tcd_t *p_tcd)
l_tile_comp->data_size = 0;
l_tile_comp->data_size_needed = 0;
}
+
+ opj_image_data_free(l_tile_comp->data_win);
+
++l_tile_comp;
}
@@ -1770,18 +1932,6 @@ static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd)
opj_image_comp_t * l_img_comp = p_tcd->image->comps;
for (compno = 0; compno < l_tile->numcomps; compno++) {
- /*
- if (tcd->cp->reduce != 0) {
- tcd->image->comps[compno].resno_decoded =
- tile->comps[compno].numresolutions - tcd->cp->reduce - 1;
- if (tcd->image->comps[compno].resno_decoded < 0)
- {
- return false;
- }
- }
- numres2decode = tcd->image->comps[compno].resno_decoded + 1;
- if(numres2decode > 0){
- */
if (l_tccp->qmfbid == 1) {
if (! opj_dwt_decode(p_tcd, l_tile_comp,
@@ -1802,6 +1952,7 @@ static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd)
return OPJ_TRUE;
}
+
static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager)
{
opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
@@ -1813,17 +1964,40 @@ static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager)
return OPJ_TRUE;
}
- l_samples = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) *
- (l_tile_comp->y1 - l_tile_comp->y0));
+ if (p_tcd->whole_tile_decoding) {
+ /* A bit inefficient: we process more data than needed if */
+ /* resno_decoded < l_tile_comp->minimum_num_resolutions-1, */
+ /* but we would need to take into account a stride then */
+ l_samples = (OPJ_UINT32)((
+ l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x1 -
+ l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x0) *
+ (l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].y1 -
+ l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].y0));
+ } else {
+ opj_tcd_resolution_t* l_res;
+ l_res = l_tile_comp->resolutions + p_tcd->image->comps[0].resno_decoded;
+ l_samples = (l_res->win_x1 - l_res->win_x0) *
+ (l_res->win_y1 - l_res->win_y0);
+ }
if (l_tile->numcomps >= 3) {
+ opj_tcd_resolution_t* res_comp0 = l_tile->comps[0].resolutions +
+ p_tcd->image->comps[0].resno_decoded;
+ opj_tcd_resolution_t* res_comp1 = l_tile->comps[1].resolutions +
+ p_tcd->image->comps[1].resno_decoded;
+ opj_tcd_resolution_t* res_comp2 = l_tile->comps[2].resolutions +
+ p_tcd->image->comps[2].resno_decoded;
+ OPJ_SIZE_T l_res_samples = (OPJ_SIZE_T)(res_comp0->x1 - res_comp0->x0) *
+ (OPJ_SIZE_T)(res_comp0->y1 - res_comp0->y0);
/* testcase 1336.pdf.asan.47.376 */
- if ((l_tile->comps[0].x1 - l_tile->comps[0].x0) * (l_tile->comps[0].y1 -
- l_tile->comps[0].y0) < (OPJ_INT32)l_samples ||
- (l_tile->comps[1].x1 - l_tile->comps[1].x0) * (l_tile->comps[1].y1 -
- l_tile->comps[1].y0) < (OPJ_INT32)l_samples ||
- (l_tile->comps[2].x1 - l_tile->comps[2].x0) * (l_tile->comps[2].y1 -
- l_tile->comps[2].y0) < (OPJ_INT32)l_samples) {
+ if (p_tcd->image->comps[0].resno_decoded !=
+ p_tcd->image->comps[1].resno_decoded ||
+ p_tcd->image->comps[0].resno_decoded !=
+ p_tcd->image->comps[2].resno_decoded ||
+ (OPJ_SIZE_T)(res_comp1->x1 - res_comp1->x0) *
+ (OPJ_SIZE_T)(res_comp1->y1 - res_comp1->y0) != l_res_samples ||
+ (OPJ_SIZE_T)(res_comp2->x1 - res_comp2->x0) *
+ (OPJ_SIZE_T)(res_comp2->y1 - res_comp2->y0) != l_res_samples) {
opj_event_msg(p_manager, EVT_ERROR,
"Tiles don't all have the same dimension. Skip the MCT step.\n");
return OPJ_FALSE;
@@ -1840,7 +2014,11 @@ static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager)
}
for (i = 0; i < l_tile->numcomps; ++i) {
- l_data[i] = (OPJ_BYTE*) l_tile_comp->data;
+ if (p_tcd->whole_tile_decoding) {
+ l_data[i] = (OPJ_BYTE*) l_tile_comp->data;
+ } else {
+ l_data[i] = (OPJ_BYTE*) l_tile_comp->data_win;
+ }
++l_tile_comp;
}
@@ -1861,15 +2039,29 @@ static OPJ_BOOL opj_tcd_mct_decode(opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager)
opj_free(l_data);
} else {
if (l_tcp->tccps->qmfbid == 1) {
- opj_mct_decode(l_tile->comps[0].data,
- l_tile->comps[1].data,
- l_tile->comps[2].data,
- l_samples);
+ if (p_tcd->whole_tile_decoding) {
+ opj_mct_decode(l_tile->comps[0].data,
+ l_tile->comps[1].data,
+ l_tile->comps[2].data,
+ l_samples);
+ } else {
+ opj_mct_decode(l_tile->comps[0].data_win,
+ l_tile->comps[1].data_win,
+ l_tile->comps[2].data_win,
+ l_samples);
+ }
} else {
- opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data,
- (OPJ_FLOAT32*)l_tile->comps[1].data,
- (OPJ_FLOAT32*)l_tile->comps[2].data,
- l_samples);
+ if (p_tcd->whole_tile_decoding) {
+ opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data,
+ (OPJ_FLOAT32*)l_tile->comps[1].data,
+ (OPJ_FLOAT32*)l_tile->comps[2].data,
+ l_samples);
+ } else {
+ opj_mct_decode_real((OPJ_FLOAT32*)l_tile->comps[0].data_win,
+ (OPJ_FLOAT32*)l_tile->comps[1].data_win,
+ (OPJ_FLOAT32*)l_tile->comps[2].data_win,
+ l_samples);
+ }
}
}
} else {
@@ -1902,12 +2094,24 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd)
for (compno = 0; compno < l_tile->numcomps; compno++) {
l_res = l_tile_comp->resolutions + l_img_comp->resno_decoded;
- l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0);
- l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0);
- l_stride = (OPJ_UINT32)(l_tile_comp->x1 - l_tile_comp->x0) - l_width;
- assert(l_height == 0 ||
- l_width + l_stride <= l_tile_comp->data_size / l_height); /*MUPDF*/
+ if (!p_tcd->whole_tile_decoding) {
+ l_width = l_res->win_x1 - l_res->win_x0;
+ l_height = l_res->win_y1 - l_res->win_y0;
+ l_stride = 0;
+ l_current_ptr = l_tile_comp->data_win;
+ } else {
+ l_width = (OPJ_UINT32)(l_res->x1 - l_res->x0);
+ l_height = (OPJ_UINT32)(l_res->y1 - l_res->y0);
+ l_stride = (OPJ_UINT32)(
+ l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x1 -
+ l_tile_comp->resolutions[l_tile_comp->minimum_num_resolutions - 1].x0)
+ - l_width;
+ l_current_ptr = l_tile_comp->data;
+
+ assert(l_height == 0 ||
+ l_width + l_stride <= l_tile_comp->data_size / l_height); /*MUPDF*/
+ }
if (l_img_comp->sgnd) {
l_min = -(1 << (l_img_comp->prec - 1));
@@ -1917,11 +2121,11 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd)
l_max = (OPJ_INT32)((1U << l_img_comp->prec) - 1);
}
- l_current_ptr = l_tile_comp->data;
if (l_tccp->qmfbid == 1) {
for (j = 0; j < l_height; ++j) {
for (i = 0; i < l_width; ++i) {
+ /* TODO: do addition on int64 ? */
*l_current_ptr = opj_int_clamp(*l_current_ptr + l_tccp->m_dc_level_shift, l_min,
l_max);
++l_current_ptr;
@@ -1932,13 +2136,14 @@ static OPJ_BOOL opj_tcd_dc_level_shift_decode(opj_tcd_t *p_tcd)
for (j = 0; j < l_height; ++j) {
for (i = 0; i < l_width; ++i) {
OPJ_FLOAT32 l_value = *((OPJ_FLOAT32 *) l_current_ptr);
- OPJ_INT32 l_value_int = (OPJ_INT32)opj_lrintf(l_value);
- if (l_value > INT_MAX ||
- (l_value_int > 0 && l_tccp->m_dc_level_shift > 0 &&
- l_value_int > INT_MAX - l_tccp->m_dc_level_shift)) {
+ if (l_value > INT_MAX) {
*l_current_ptr = l_max;
+ } else if (l_value < INT_MIN) {
+ *l_current_ptr = l_min;
} else {
- *l_current_ptr = opj_int_clamp(
+ /* Do addition on int64 to avoid overflows */
+ OPJ_INT64 l_value_int = (OPJ_INT64)opj_lrintf(l_value);
+ *l_current_ptr = (OPJ_INT32)opj_int64_clamp(
l_value_int + l_tccp->m_dc_level_shift, l_min, l_max);
}
++l_current_ptr;
@@ -1987,6 +2192,9 @@ static void opj_tcd_code_block_dec_deallocate(opj_tcd_precinct_t * p_precinct)
l_code_block->chunks = 00;
}
+ opj_aligned_free(l_code_block->decoded_data);
+ l_code_block->decoded_data = NULL;
+
++l_code_block;
}
@@ -2032,9 +2240,10 @@ static void opj_tcd_code_block_enc_deallocate(opj_tcd_precinct_t * p_precinct)
}
}
-OPJ_UINT32 opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd)
+OPJ_SIZE_T opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd)
{
- OPJ_UINT32 i, l_data_size = 0;
+ OPJ_UINT32 i;
+ OPJ_SIZE_T l_data_size = 0;
opj_image_comp_t * l_img_comp = 00;
opj_tcd_tilecomp_t * l_tilec = 00;
OPJ_UINT32 l_size_comp, l_remaining;
@@ -2053,8 +2262,8 @@ OPJ_UINT32 opj_tcd_get_encoded_tile_size(opj_tcd_t *p_tcd)
l_size_comp = 4;
}
- l_data_size += l_size_comp * (OPJ_UINT32)((l_tilec->x1 - l_tilec->x0) *
- (l_tilec->y1 - l_tilec->y0));
+ l_data_size += l_size_comp * ((OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) *
+ (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0));
++l_img_comp;
++l_tilec;
}
@@ -2069,7 +2278,7 @@ static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd)
opj_tccp_t * l_tccp = 00;
opj_image_comp_t * l_img_comp = 00;
opj_tcd_tile_t * l_tile;
- OPJ_UINT32 l_nb_elem, i;
+ OPJ_SIZE_T l_nb_elem, i;
OPJ_INT32 * l_current_ptr;
l_tile = p_tcd->tcd_image->tiles;
@@ -2079,8 +2288,8 @@ static OPJ_BOOL opj_tcd_dc_level_shift_encode(opj_tcd_t *p_tcd)
for (compno = 0; compno < l_tile->numcomps; compno++) {
l_current_ptr = l_tile_comp->data;
- l_nb_elem = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) *
- (l_tile_comp->y1 - l_tile_comp->y0));
+ l_nb_elem = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) *
+ (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0);
if (l_tccp->qmfbid == 1) {
for (i = 0; i < l_nb_elem; ++i) {
@@ -2106,8 +2315,8 @@ static OPJ_BOOL opj_tcd_mct_encode(opj_tcd_t *p_tcd)
{
opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
opj_tcd_tilecomp_t * l_tile_comp = p_tcd->tcd_image->tiles->comps;
- OPJ_UINT32 samples = (OPJ_UINT32)((l_tile_comp->x1 - l_tile_comp->x0) *
- (l_tile_comp->y1 - l_tile_comp->y0));
+ OPJ_SIZE_T samples = (OPJ_SIZE_T)(l_tile_comp->x1 - l_tile_comp->x0) *
+ (OPJ_SIZE_T)(l_tile_comp->y1 - l_tile_comp->y0);
OPJ_UINT32 i;
OPJ_BYTE ** l_data = 00;
opj_tcp_t * l_tcp = p_tcd->tcp;
@@ -2289,13 +2498,15 @@ static OPJ_BOOL opj_tcd_rate_allocate_encode(opj_tcd_t *p_tcd,
OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd,
OPJ_BYTE * p_src,
- OPJ_UINT32 p_src_length)
+ OPJ_SIZE_T p_src_length)
{
- OPJ_UINT32 i, j, l_data_size = 0;
+ OPJ_UINT32 i;
+ OPJ_SIZE_T j;
+ OPJ_SIZE_T l_data_size = 0;
opj_image_comp_t * l_img_comp = 00;
opj_tcd_tilecomp_t * l_tilec = 00;
OPJ_UINT32 l_size_comp, l_remaining;
- OPJ_UINT32 l_nb_elem;
+ OPJ_SIZE_T l_nb_elem;
l_data_size = opj_tcd_get_encoded_tile_size(p_tcd);
if (l_data_size != p_src_length) {
@@ -2307,8 +2518,8 @@ OPJ_BOOL opj_tcd_copy_tile_data(opj_tcd_t *p_tcd,
for (i = 0; i < p_tcd->image->numcomps; ++i) {
l_size_comp = l_img_comp->prec >> 3; /*(/ 8)*/
l_remaining = l_img_comp->prec & 7; /* (%8) */
- l_nb_elem = (OPJ_UINT32)((l_tilec->x1 - l_tilec->x0) * (l_tilec->y1 -
- l_tilec->y0));
+ l_nb_elem = (OPJ_SIZE_T)(l_tilec->x1 - l_tilec->x0) *
+ (OPJ_SIZE_T)(l_tilec->y1 - l_tilec->y0);
if (l_remaining) {
++l_size_comp;
@@ -2402,16 +2613,16 @@ OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd,
/* with the tile coordinates */
OPJ_UINT32 tcx0 = opj_uint_max(
(OPJ_UINT32)tilec->x0,
- opj_uint_ceildiv(tcd->decoded_x0, image_comp->dx));
+ opj_uint_ceildiv(tcd->win_x0, image_comp->dx));
OPJ_UINT32 tcy0 = opj_uint_max(
(OPJ_UINT32)tilec->y0,
- opj_uint_ceildiv(tcd->decoded_y0, image_comp->dy));
+ opj_uint_ceildiv(tcd->win_y0, image_comp->dy));
OPJ_UINT32 tcx1 = opj_uint_min(
(OPJ_UINT32)tilec->x1,
- opj_uint_ceildiv(tcd->decoded_x1, image_comp->dx));
+ opj_uint_ceildiv(tcd->win_x1, image_comp->dx));
OPJ_UINT32 tcy1 = opj_uint_min(
(OPJ_UINT32)tilec->y1,
- opj_uint_ceildiv(tcd->decoded_y1, image_comp->dy));
+ opj_uint_ceildiv(tcd->win_y1, image_comp->dy));
/* Compute number of decomposition for this band. See table F-1 */
OPJ_UINT32 nb = (resno == 0) ?
tilec->numresolutions - 1 :
@@ -2458,3 +2669,44 @@ OPJ_BOOL opj_tcd_is_subband_area_of_interest(opj_tcd_t *tcd,
#endif
return intersects;
}
+
+/** Returns whether a tile componenent is fully decoded, taking into account
+ * p_tcd->win_* members.
+ *
+ * @param p_tcd TCD handle.
+ * @param compno Component number
+ * @return OPJ_TRUE whether the tile componenent is fully decoded
+ */
+static OPJ_BOOL opj_tcd_is_whole_tilecomp_decoding(opj_tcd_t *p_tcd,
+ OPJ_UINT32 compno)
+{
+ opj_tcd_tilecomp_t* tilec = &(p_tcd->tcd_image->tiles->comps[compno]);
+ opj_image_comp_t* image_comp = &(p_tcd->image->comps[compno]);
+ /* Compute the intersection of the area of interest, expressed in tile coordinates */
+ /* with the tile coordinates */
+ OPJ_UINT32 tcx0 = opj_uint_max(
+ (OPJ_UINT32)tilec->x0,
+ opj_uint_ceildiv(p_tcd->win_x0, image_comp->dx));
+ OPJ_UINT32 tcy0 = opj_uint_max(
+ (OPJ_UINT32)tilec->y0,
+ opj_uint_ceildiv(p_tcd->win_y0, image_comp->dy));
+ OPJ_UINT32 tcx1 = opj_uint_min(
+ (OPJ_UINT32)tilec->x1,
+ opj_uint_ceildiv(p_tcd->win_x1, image_comp->dx));
+ OPJ_UINT32 tcy1 = opj_uint_min(
+ (OPJ_UINT32)tilec->y1,
+ opj_uint_ceildiv(p_tcd->win_y1, image_comp->dy));
+
+ OPJ_UINT32 shift = tilec->numresolutions - tilec->minimum_num_resolutions;
+ /* Tolerate small margin within the reduced resolution factor to consider if */
+ /* the whole tile path must be taken */
+ return (tcx0 >= (OPJ_UINT32)tilec->x0 &&
+ tcy0 >= (OPJ_UINT32)tilec->y0 &&
+ tcx1 <= (OPJ_UINT32)tilec->x1 &&
+ tcy1 <= (OPJ_UINT32)tilec->y1 &&
+ (shift >= 32 ||
+ (((tcx0 - (OPJ_UINT32)tilec->x0) >> shift) == 0 &&
+ ((tcy0 - (OPJ_UINT32)tilec->y0) >> shift) == 0 &&
+ (((OPJ_UINT32)tilec->x1 - tcx1) >> shift) == 0 &&
+ (((OPJ_UINT32)tilec->y1 - tcy1) >> shift) == 0)));
+}