Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sub-tile decoding: only decode precincts and codeblocks that intersect the window specified in opj_set_decode_area() #990

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion src/lib/openjp2/j2k.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -5162,7 +5163,17 @@ 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);

/* Arbitrary amount to make the following work: */
/* bin/test_tile_encoder 1 256 256 17 16 8 0 reversible_no_precinct.j2k 4 4 3 0 0 1 */
l_tile_size += 500;

l_tile_size += opj_j2k_get_specific_header_sizes(p_j2k);

Expand Down Expand Up @@ -8770,6 +8781,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);
Expand All @@ -8787,7 +8799,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,
Expand Down
57 changes: 56 additions & 1 deletion src/lib/openjp2/t1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand All @@ -1770,11 +1771,65 @@ void opj_t1_decode_cblks(opj_thread_pool_t* tp,

for (precno = 0; precno < res->pw * res->ph; ++precno) {
opj_tcd_precinct_t* precinct = &band->precincts[precno];
OPJ_BOOL skip_precinct = OPJ_FALSE;

if (!opj_tcd_is_subband_area_of_interest(tcd,
tilec->compno,
resno,
band->bandno,
(OPJ_UINT32)precinct->x0,
(OPJ_UINT32)precinct->y0,
(OPJ_UINT32)precinct->x1,
(OPJ_UINT32)precinct->y1)) {
skip_precinct = OPJ_TRUE;
/* TODO: do a continue here once the below 0 initialization */
/* of tiledp is removed */
}

for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) {
opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno];
opj_t1_cblk_decode_processing_job_t* job;

if (skip_precinct ||
!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)) {

/* TODO: remove this once we don't iterate over */
/* tile pixels that are not in the subwindow of interest */
OPJ_UINT32 j, i;
OPJ_INT32 x = cblk->x0 - band->x0;
OPJ_INT32 y = cblk->y0 - band->y0;
OPJ_INT32* OPJ_RESTRICT tiledp;
OPJ_UINT32 tile_w = (OPJ_UINT32)(tilec->x1 - tilec->x0);
OPJ_UINT32 cblk_w = (OPJ_UINT32)(cblk->x1 - cblk->x0);
OPJ_UINT32 cblk_h = (OPJ_UINT32)(cblk->y1 - cblk->y0);

if (band->bandno & 1) {
opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1];
x += pres->x1 - pres->x0;
}
if (band->bandno & 2) {
opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1];
y += pres->y1 - pres->y0;
}

tiledp = &tilec->data[(OPJ_UINT32)y * tile_w +
(OPJ_UINT32)x];

for (j = 0; j < cblk_h; ++j) {
for (i = 0; i < cblk_w; ++i) {
((OPJ_INT32*)tiledp)[(j * tile_w) + i] = 0;
}
}
continue;
}

job = (opj_t1_cblk_decode_processing_job_t*) opj_calloc(1,
sizeof(opj_t1_cblk_decode_processing_job_t));
if (!job) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/openjp2/t1.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,15 @@ 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
@param p_manager the event manager
@param p_manager_mutex mutex for the event manager
@param check_pterm whether PTERM correct termination should be checked
*/
void opj_t1_decode_cblks(opj_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,
Expand Down
50 changes: 46 additions & 4 deletions src/lib/openjp2/t2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion src/lib/openjp2/t2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down
82 changes: 81 additions & 1 deletion src/lib/openjp2/tcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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,
Expand All @@ -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 >> */
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Loading