Merge pull request #1001 from rouault/subtile_decoding_stage2
Subtile decoding: only apply IDWT on areas that participate to the window of interest
This commit is contained in:
commit
e9bbc6d3dd
|
@ -133,7 +133,12 @@ OPJ_FLOAT64 opj_clock(void)
|
|||
int main(int argc, char** argv)
|
||||
{
|
||||
int num_threads = 0;
|
||||
opj_tcd_t tcd;
|
||||
opj_tcd_image_t tcd_image;
|
||||
opj_tcd_tile_t tcd_tile;
|
||||
opj_tcd_tilecomp_t tilec;
|
||||
opj_image_t image;
|
||||
opj_image_comp_t image_comp;
|
||||
opj_thread_pool_t* tp;
|
||||
OPJ_INT32 i, j, k;
|
||||
OPJ_BOOL display = OPJ_FALSE;
|
||||
|
@ -191,8 +196,32 @@ int main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
memset(&tcd, 0, sizeof(tcd));
|
||||
tcd.thread_pool = tp;
|
||||
tcd.decoded_x0 = (OPJ_UINT32)tilec.x0;
|
||||
tcd.decoded_y0 = (OPJ_UINT32)tilec.y0;
|
||||
tcd.decoded_x1 = (OPJ_UINT32)tilec.x1;
|
||||
tcd.decoded_y1 = (OPJ_UINT32)tilec.y1;
|
||||
tcd.tcd_image = &tcd_image;
|
||||
memset(&tcd_image, 0, sizeof(tcd_image));
|
||||
tcd_image.tiles = &tcd_tile;
|
||||
memset(&tcd_tile, 0, sizeof(tcd_tile));
|
||||
tcd_tile.x0 = tilec.x0;
|
||||
tcd_tile.y0 = tilec.y0;
|
||||
tcd_tile.x1 = tilec.x1;
|
||||
tcd_tile.y1 = tilec.y1;
|
||||
tcd_tile.numcomps = 1;
|
||||
tcd_tile.comps = &tilec;
|
||||
tcd.image = ℑ
|
||||
memset(&image, 0, sizeof(image));
|
||||
image.numcomps = 1;
|
||||
image.comps = &image_comp;
|
||||
memset(&image_comp, 0, sizeof(image_comp));
|
||||
image_comp.dx = 1;
|
||||
image_comp.dy = 1;
|
||||
|
||||
start = opj_clock();
|
||||
opj_dwt_decode(tp, &tilec, tilec.numresolutions);
|
||||
opj_dwt_decode(&tcd, &tilec, tilec.numresolutions);
|
||||
stop = opj_clock();
|
||||
printf("time for dwt_decode: %.03f s\n", stop - start);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -63,11 +63,12 @@ OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec);
|
|||
/**
|
||||
Inverse 5-3 wavelet transform in 2-D.
|
||||
Apply a reversible inverse DWT transform to a component of an image.
|
||||
@param tp Thread pool
|
||||
@param tcd TCD handle
|
||||
@param tilec Tile component information (current tile)
|
||||
@param numres Number of resolution levels to decode
|
||||
*/
|
||||
OPJ_BOOL opj_dwt_decode(opj_thread_pool_t* tp, opj_tcd_tilecomp_t* tilec,
|
||||
OPJ_BOOL opj_dwt_decode(opj_tcd_t *p_tcd,
|
||||
opj_tcd_tilecomp_t* tilec,
|
||||
OPJ_UINT32 numres);
|
||||
|
||||
/**
|
||||
|
@ -92,10 +93,12 @@ OPJ_BOOL opj_dwt_encode_real(opj_tcd_tilecomp_t * tilec);
|
|||
/**
|
||||
Inverse 9-7 wavelet transform in 2-D.
|
||||
Apply an irreversible inverse DWT transform to a component of an image.
|
||||
@param tcd TCD handle
|
||||
@param tilec Tile component information (current tile)
|
||||
@param numres Number of resolution levels to decode
|
||||
*/
|
||||
OPJ_BOOL opj_dwt_decode_real(opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
|
||||
OPJ_BOOL opj_dwt_decode_real(opj_tcd_t *p_tcd,
|
||||
opj_tcd_tilecomp_t* OPJ_RESTRICT tilec,
|
||||
OPJ_UINT32 numres);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
|
|
@ -95,6 +95,15 @@ static INLINE OPJ_UINT32 opj_uint_adds(OPJ_UINT32 a, OPJ_UINT32 b)
|
|||
return (OPJ_UINT32)(-(OPJ_INT32)(sum >> 32)) | (OPJ_UINT32)sum;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the saturated difference of two unsigned integers
|
||||
@return Returns saturated sum of a-b
|
||||
*/
|
||||
static INLINE OPJ_UINT32 opj_uint_subs(OPJ_UINT32 a, OPJ_UINT32 b)
|
||||
{
|
||||
return (a >= b) ? a - b : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Clamp an integer inside an interval
|
||||
@return
|
||||
|
|
|
@ -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) {
|
||||
|
@ -1770,11 +1771,63 @@ 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;
|
||||
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) {
|
||||
memset(tiledp + j * tile_w, 0, cblk_w * sizeof(OPJ_INT32));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
job = (opj_t1_cblk_decode_processing_job_t*) opj_calloc(1,
|
||||
sizeof(opj_t1_cblk_decode_processing_job_t));
|
||||
if (!job) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <
|
||||
/* 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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
@ -1767,12 +1778,13 @@ static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd)
|
|||
*/
|
||||
|
||||
if (l_tccp->qmfbid == 1) {
|
||||
if (! opj_dwt_decode(p_tcd->thread_pool, l_tile_comp,
|
||||
if (! opj_dwt_decode(p_tcd, l_tile_comp,
|
||||
l_img_comp->resno_decoded + 1)) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
} else {
|
||||
if (! opj_dwt_decode_real(l_tile_comp, l_img_comp->resno_decoded + 1)) {
|
||||
if (! opj_dwt_decode_real(p_tcd, l_tile_comp,
|
||||
l_img_comp->resno_decoded + 1)) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
}
|
||||
|
@ -2359,3 +2371,80 @@ 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)
|
||||
{
|
||||
/* Note: those values for filter_margin are in part the result of */
|
||||
/* experimentation. The value 2 for QMFBID=1 (5x3 filter) can be linked */
|
||||
/* to the maximum left/right extension given in tables F.2 and F.3 of the */
|
||||
/* standard. The value 3 for QMFBID=0 (9x7 filter) is more suspicious, */
|
||||
/* since F.2 and F.3 would lead to 4 instead, so the current 3 might be */
|
||||
/* needed to be bumped to 4, in case inconsistencies are found while */
|
||||
/* decoding parts of irreversible coded images. */
|
||||
/* See opj_dwt_decode_partial_53 and opj_dwt_decode_partial_97 as well */
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/*@}*/
|
||||
|
||||
|
|
|
@ -45,6 +45,9 @@ add_executable(compare_raw_files ${compare_raw_files_SRCS})
|
|||
add_executable(test_tile_encoder test_tile_encoder.c)
|
||||
target_link_libraries(test_tile_encoder ${OPENJPEG_LIBRARY_NAME})
|
||||
|
||||
add_executable(test_decode_area test_decode_area.c)
|
||||
target_link_libraries(test_decode_area ${OPENJPEG_LIBRARY_NAME})
|
||||
|
||||
# Let's try a couple of possibilities:
|
||||
add_test(NAME tte0 COMMAND test_tile_encoder)
|
||||
add_test(NAME tte1 COMMAND test_tile_encoder 3 2048 2048 1024 1024 8 1 tte1.j2k)
|
||||
|
@ -80,6 +83,26 @@ set_property(TEST rta4 APPEND PROPERTY DEPENDS tte4)
|
|||
add_test(NAME rta5 COMMAND j2k_random_tile_access tte5.j2k)
|
||||
set_property(TEST rta5 APPEND PROPERTY DEPENDS tte5)
|
||||
|
||||
add_test(NAME tda_prep_reversible_no_precinct COMMAND test_tile_encoder 1 256 256 32 32 8 0 reversible_no_precinct.j2k 4 4 3 0 0 1)
|
||||
add_test(NAME tda_reversible_no_precinct COMMAND test_decode_area -q reversible_no_precinct.j2k)
|
||||
set_property(TEST tda_reversible_no_precinct APPEND PROPERTY DEPENDS tda_prep_reversible_no_precinct)
|
||||
|
||||
add_test(NAME tda_prep_reversible_203_201_17_19_no_precinct COMMAND test_tile_encoder 1 203 201 17 19 8 0 reversible_203_201_17_19_no_precinct.j2k 4 4 3 0 0 1)
|
||||
add_test(NAME tda_reversible_203_201_17_19_no_precinct COMMAND test_decode_area -q reversible_203_201_17_19_no_precinct.j2k)
|
||||
set_property(TEST tda_reversible_203_201_17_19_no_precinct APPEND PROPERTY DEPENDS tda_prep_reversible_203_201_17_19_no_precinct)
|
||||
|
||||
add_test(NAME tda_prep_reversible_with_precinct COMMAND test_tile_encoder 1 256 256 32 32 8 0 reversible_with_precinct.j2k 4 4 3 0 0 1 16 16)
|
||||
add_test(NAME tda_reversible_with_precinct COMMAND test_decode_area -q reversible_with_precinct.j2k)
|
||||
set_property(TEST tda_reversible_with_precinct APPEND PROPERTY DEPENDS tda_prep_reversible_with_precinct)
|
||||
|
||||
add_test(NAME tda_prep_irreversible_no_precinct COMMAND test_tile_encoder 1 256 256 32 32 8 1 irreversible_no_precinct.j2k 4 4 3 0 0 1)
|
||||
add_test(NAME tda_irreversible_no_precinct COMMAND test_decode_area -q irreversible_no_precinct.j2k)
|
||||
set_property(TEST tda_irreversible_no_precinct APPEND PROPERTY DEPENDS tda_prep_irreversible_no_precinct)
|
||||
|
||||
add_test(NAME tda_prep_irreversible_203_201_17_19_no_precinct COMMAND test_tile_encoder 1 203 201 17 19 8 1 irreversible_203_201_17_19_no_precinct.j2k 4 4 3 0 0 1)
|
||||
add_test(NAME tda_irreversible_203_201_17_19_no_precinct COMMAND test_decode_area -q irreversible_203_201_17_19_no_precinct.j2k)
|
||||
set_property(TEST tda_irreversible_203_201_17_19_no_precinct APPEND PROPERTY DEPENDS tda_prep_irreversible_203_201_17_19_no_precinct)
|
||||
|
||||
add_executable(include_openjpeg include_openjpeg.c)
|
||||
|
||||
# No image send to the dashboard if lib PNG is not available.
|
||||
|
|
|
@ -0,0 +1,396 @@
|
|||
/*
|
||||
* 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) 2017, IntoPix SA <contact@intopix.com>
|
||||
* 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 <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "openjpeg.h"
|
||||
#include "format_defs.h"
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
#define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
|
||||
#define JP2_MAGIC "\x0d\x0a\x87\x0a"
|
||||
/* position 45: "\xff\x52" */
|
||||
#define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
|
||||
|
||||
static int infile_format(const char *fname)
|
||||
{
|
||||
FILE *reader;
|
||||
unsigned char buf[12];
|
||||
unsigned int l_nb_read;
|
||||
|
||||
reader = fopen(fname, "rb");
|
||||
|
||||
if (reader == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buf, 0, 12);
|
||||
l_nb_read = (unsigned int)fread(buf, 1, 12, reader);
|
||||
fclose(reader);
|
||||
if (l_nb_read != 12) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(buf, JP2_RFC3745_MAGIC, 12) == 0 || memcmp(buf, JP2_MAGIC, 4) == 0) {
|
||||
return JP2_CFMT;
|
||||
} else if (memcmp(buf, J2K_CODESTREAM_MAGIC, 4) == 0) {
|
||||
return J2K_CFMT;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
sample error debug callback expecting no client object
|
||||
*/
|
||||
static void error_callback(const char *msg, void *client_data)
|
||||
{
|
||||
(void)client_data;
|
||||
fprintf(stdout, "[ERROR] %s", msg);
|
||||
}
|
||||
/**
|
||||
sample warning debug callback expecting no client object
|
||||
*/
|
||||
static void warning_callback(const char *msg, void *client_data)
|
||||
{
|
||||
(void)client_data;
|
||||
fprintf(stdout, "[WARNING] %s", msg);
|
||||
}
|
||||
/**
|
||||
sample debug callback expecting no client object
|
||||
*/
|
||||
static void info_callback(const char *msg, void *client_data)
|
||||
{
|
||||
(void)client_data;
|
||||
(void)msg;
|
||||
/*fprintf(stdout, "[INFO] %s", msg);*/
|
||||
}
|
||||
|
||||
opj_image_t* decode(
|
||||
OPJ_BOOL quiet,
|
||||
const char* input_file,
|
||||
OPJ_INT32 x0,
|
||||
OPJ_INT32 y0,
|
||||
OPJ_INT32 x1,
|
||||
OPJ_INT32 y1,
|
||||
OPJ_UINT32* ptilew,
|
||||
OPJ_UINT32* ptileh,
|
||||
OPJ_UINT32* pcblkw,
|
||||
OPJ_UINT32* pcblkh)
|
||||
{
|
||||
opj_dparameters_t l_param;
|
||||
opj_codec_t * l_codec = NULL;
|
||||
opj_image_t * l_image = NULL;
|
||||
opj_stream_t * l_stream = NULL;
|
||||
|
||||
if (!quiet) {
|
||||
if (x0 != 0 || x1 != 0 || y0 != 0 || y1 != 0) {
|
||||
printf("Decoding %d,%d,%d,%d\n", x0, y0, x1, y1);
|
||||
} else {
|
||||
printf("Decoding full image\n");
|
||||
}
|
||||
}
|
||||
|
||||
l_stream = opj_stream_create_default_file_stream(input_file, OPJ_TRUE);
|
||||
if (!l_stream) {
|
||||
fprintf(stderr, "ERROR -> failed to create the stream from the file\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set the default decoding parameters */
|
||||
opj_set_default_decoder_parameters(&l_param);
|
||||
|
||||
/* */
|
||||
l_param.decod_format = infile_format(input_file);
|
||||
|
||||
|
||||
switch (l_param.decod_format) {
|
||||
case J2K_CFMT: { /* JPEG-2000 codestream */
|
||||
/* Get a decoder handle */
|
||||
l_codec = opj_create_decompress(OPJ_CODEC_J2K);
|
||||
break;
|
||||
}
|
||||
case JP2_CFMT: { /* JPEG 2000 compressed image data */
|
||||
/* Get a decoder handle */
|
||||
l_codec = opj_create_decompress(OPJ_CODEC_JP2);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
fprintf(stderr, "ERROR -> Not a valid JPEG2000 file!\n");
|
||||
opj_stream_destroy(l_stream);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* catch events using our callbacks and give a local context */
|
||||
opj_set_info_handler(l_codec, info_callback, 00);
|
||||
opj_set_warning_handler(l_codec, warning_callback, 00);
|
||||
opj_set_error_handler(l_codec, error_callback, 00);
|
||||
|
||||
/* Setup the decoder decoding parameters using user parameters */
|
||||
if (! opj_setup_decoder(l_codec, &l_param)) {
|
||||
fprintf(stderr, "ERROR ->failed to setup the decoder\n");
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_destroy_codec(l_codec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read the main header of the codestream and if necessary the JP2 boxes*/
|
||||
if (! opj_read_header(l_stream, l_codec, &l_image)) {
|
||||
fprintf(stderr, "ERROR -> failed to read the header\n");
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_destroy_codec(l_codec);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
opj_codestream_info_v2_t* pCodeStreamInfo = opj_get_cstr_info(l_codec);
|
||||
if (ptilew) {
|
||||
*ptilew = pCodeStreamInfo->tdx;
|
||||
}
|
||||
if (ptileh) {
|
||||
*ptilew = pCodeStreamInfo->tdy;
|
||||
}
|
||||
//int numResolutions = pCodeStreamInfo->m_default_tile_info.tccp_info[0].numresolutions;
|
||||
if (pcblkw) {
|
||||
*pcblkw = 1U << pCodeStreamInfo->m_default_tile_info.tccp_info[0].cblkw;
|
||||
}
|
||||
if (pcblkh) {
|
||||
*pcblkh = 1U << pCodeStreamInfo->m_default_tile_info.tccp_info[0].cblkh;
|
||||
}
|
||||
opj_destroy_cstr_info(&pCodeStreamInfo);
|
||||
}
|
||||
|
||||
if (x0 != 0 || x1 != 0 || y0 != 0 || y1 != 0) {
|
||||
if (!opj_set_decode_area(l_codec, l_image, x0, y0, x1, y1)) {
|
||||
fprintf(stderr, "ERROR -> failed to set the decoded area\n");
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_destroy_codec(l_codec);
|
||||
opj_image_destroy(l_image);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the decoded image */
|
||||
if (!(opj_decode(l_codec, l_stream, l_image))) {
|
||||
fprintf(stderr, "ERROR -> failed to decode image!\n");
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_destroy_codec(l_codec);
|
||||
opj_image_destroy(l_image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (! opj_end_decompress(l_codec, l_stream)) {
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_destroy_codec(l_codec);
|
||||
opj_image_destroy(l_image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_destroy_codec(l_codec);
|
||||
return l_image;
|
||||
}
|
||||
|
||||
OPJ_BOOL check_consistency(opj_image_t* p_image, opj_image_t* p_sub_image)
|
||||
{
|
||||
OPJ_UINT32 compno;
|
||||
for (compno = 0; compno < p_image->numcomps; compno ++) {
|
||||
OPJ_UINT32 y;
|
||||
OPJ_UINT32 shift_y = p_sub_image->comps[compno].y0 - p_image->comps[compno].y0;
|
||||
OPJ_UINT32 shift_x = p_sub_image->comps[compno].x0 - p_image->comps[compno].x0;
|
||||
OPJ_UINT32 image_w = p_image->comps[compno].w;
|
||||
OPJ_UINT32 sub_image_w = p_sub_image->comps[compno].w;
|
||||
for (y = 0; y < p_sub_image->comps[compno].h; y++) {
|
||||
OPJ_UINT32 x;
|
||||
|
||||
for (x = 0; x < sub_image_w; x++) {
|
||||
OPJ_INT32 sub_image_val =
|
||||
p_sub_image->comps[compno].data[y * sub_image_w + x];
|
||||
OPJ_INT32 image_val =
|
||||
p_image->comps[compno].data[(y + shift_y) * image_w + x + shift_x];
|
||||
if (sub_image_val != image_val) {
|
||||
fprintf(stderr,
|
||||
"Difference found at subimage pixel (%u,%u) "
|
||||
"of compno=%u: got %d, expected %d\n",
|
||||
x, y, compno, sub_image_val, image_val);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
static INLINE OPJ_UINT32 opj_uint_min(OPJ_UINT32 a, OPJ_UINT32 b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
opj_image_t * l_image = NULL;
|
||||
opj_image_t * l_sub_image = NULL;
|
||||
OPJ_INT32 da_x0 = 0, da_y0 = 0, da_x1 = 0, da_y1 = 0;
|
||||
const char* input_file = NULL;
|
||||
OPJ_UINT32 tilew, tileh, cblkw, cblkh;
|
||||
OPJ_UINT32 w, h;
|
||||
OPJ_UINT32 x, y;
|
||||
OPJ_UINT32 step_x, step_y;
|
||||
OPJ_BOOL quiet = OPJ_FALSE;
|
||||
OPJ_UINT32 nsteps = 100;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr,
|
||||
"Usage: test_decode_area [-q] [-steps n] input_file_jp2_or_jk2 [x0 y0 x1 y1]\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
int iarg;
|
||||
for (iarg = 1; iarg < argc; iarg++) {
|
||||
if (strcmp(argv[iarg], "-q") == 0) {
|
||||
quiet = OPJ_TRUE;
|
||||
} else if (strcmp(argv[iarg], "-steps") == 0 && iarg + 1 < argc) {
|
||||
nsteps = (OPJ_UINT32)atoi(argv[iarg + 1]);
|
||||
iarg ++;
|
||||
} else if (input_file == NULL) {
|
||||
input_file = argv[iarg];
|
||||
} else if (iarg + 3 < argc) {
|
||||
da_x0 = atoi(argv[iarg]);
|
||||
da_y0 = atoi(argv[iarg + 1]);
|
||||
da_x1 = atoi(argv[iarg + 2]);
|
||||
da_y1 = atoi(argv[iarg + 3]);
|
||||
iarg += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
l_image = decode(quiet, input_file, 0, 0, 0, 0,
|
||||
&tilew, &tileh, &cblkw, &cblkh);
|
||||
if (!l_image) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (da_x0 != 0 || da_x1 != 0 || da_y0 != 0 || da_y1 != 0) {
|
||||
l_sub_image = decode(quiet, input_file, da_x0, da_y0, da_x1, da_y1,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (!l_sub_image) {
|
||||
fprintf(stderr, "decode failed for %d,%d,%d,%d\n",
|
||||
da_x0, da_y0, da_x1, da_y1);
|
||||
opj_image_destroy(l_sub_image);
|
||||
opj_image_destroy(l_image);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!check_consistency(l_image, l_sub_image)) {
|
||||
fprintf(stderr, "Consistency checked failed for %d,%d,%d,%d\n",
|
||||
da_x0, da_y0, da_x1, da_y1);
|
||||
opj_image_destroy(l_sub_image);
|
||||
opj_image_destroy(l_image);
|
||||
return 1;
|
||||
}
|
||||
opj_image_destroy(l_sub_image);
|
||||
opj_image_destroy(l_image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
w = l_image->x1 - l_image->x0;
|
||||
h = l_image->y1 - l_image->y0;
|
||||
step_x = w > nsteps ? w / nsteps : 1;
|
||||
step_y = h > nsteps ? h / nsteps : 1;
|
||||
for (y = 0; y < h; y += step_y) {
|
||||
for (x = 0; x < w; x += step_x) {
|
||||
da_x0 = (OPJ_INT32)(l_image->x0 + x);
|
||||
da_y0 = (OPJ_INT32)(l_image->y0 + y);
|
||||
da_x1 = (OPJ_INT32)opj_uint_min(l_image->x1, l_image->x0 + x + 1);
|
||||
da_y1 = (OPJ_INT32)opj_uint_min(l_image->y1, l_image->y0 + y + 1);
|
||||
l_sub_image = decode(quiet, input_file, da_x0, da_y0, da_x1, da_y1,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (!l_sub_image) {
|
||||
fprintf(stderr, "decode failed for %d,%d,%d,%d\n",
|
||||
da_x0, da_y0, da_x1, da_y1);
|
||||
opj_image_destroy(l_sub_image);
|
||||
opj_image_destroy(l_image);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!check_consistency(l_image, l_sub_image)) {
|
||||
fprintf(stderr, "Consistency checked failed for %d,%d,%d,%d\n",
|
||||
da_x0, da_y0, da_x1, da_y1);
|
||||
opj_image_destroy(l_sub_image);
|
||||
opj_image_destroy(l_image);
|
||||
return 1;
|
||||
}
|
||||
opj_image_destroy(l_sub_image);
|
||||
|
||||
if (step_x > 1 || step_y > 1) {
|
||||
if (step_x > 1) {
|
||||
da_x0 = (OPJ_INT32)opj_uint_min(l_image->x1, (OPJ_UINT32)da_x0 + 1);
|
||||
da_x1 = (OPJ_INT32)opj_uint_min(l_image->x1, (OPJ_UINT32)da_x1 + 1);
|
||||
}
|
||||
if (step_y > 1) {
|
||||
da_y0 = (OPJ_INT32)opj_uint_min(l_image->y1, (OPJ_UINT32)da_y0 + 1);
|
||||
da_y1 = (OPJ_INT32)opj_uint_min(l_image->y1, (OPJ_UINT32)da_y1 + 1);
|
||||
}
|
||||
if (da_x0 < (OPJ_INT32)l_image->x1 && da_y0 < (OPJ_INT32)l_image->y1) {
|
||||
l_sub_image = decode(quiet, input_file, da_x0, da_y0, da_x1, da_y1,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (!l_sub_image) {
|
||||
fprintf(stderr, "decode failed for %d,%d,%d,%d\n",
|
||||
da_x0, da_y0, da_x1, da_y1);
|
||||
opj_image_destroy(l_sub_image);
|
||||
opj_image_destroy(l_image);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!check_consistency(l_image, l_sub_image)) {
|
||||
fprintf(stderr, "Consistency checked failed for %d,%d,%d,%d\n",
|
||||
da_x0, da_y0, da_x1, da_y1);
|
||||
opj_image_destroy(l_sub_image);
|
||||
opj_image_destroy(l_image);
|
||||
return 1;
|
||||
}
|
||||
opj_image_destroy(l_sub_image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opj_image_destroy(l_image);
|
||||
return 0;
|
||||
}
|
|
@ -60,6 +60,16 @@ static void info_callback(const char *msg, void *client_data)
|
|||
fprintf(stdout, "[INFO] %s", msg);
|
||||
}
|
||||
|
||||
static INLINE OPJ_UINT32 opj_uint_max(OPJ_UINT32 a, OPJ_UINT32 b)
|
||||
{
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
static INLINE OPJ_UINT32 opj_uint_min(OPJ_UINT32 a, OPJ_UINT32 b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define NUM_COMPS_MAX 4
|
||||
|
@ -70,7 +80,7 @@ int main(int argc, char *argv[])
|
|||
opj_image_t * l_image;
|
||||
opj_image_cmptparm_t l_params [NUM_COMPS_MAX];
|
||||
opj_stream_t * l_stream;
|
||||
OPJ_UINT32 l_nb_tiles;
|
||||
OPJ_UINT32 l_nb_tiles_width, l_nb_tiles_height, l_nb_tiles;
|
||||
OPJ_UINT32 l_data_size;
|
||||
size_t len;
|
||||
|
||||
|
@ -98,9 +108,18 @@ int main(int argc, char *argv[])
|
|||
int comp_prec;
|
||||
int irreversible;
|
||||
const char *output_file;
|
||||
int cblockw_init = 64;
|
||||
int cblockh_init = 64;
|
||||
int numresolution = 6;
|
||||
OPJ_UINT32 offsetx = 0;
|
||||
OPJ_UINT32 offsety = 0;
|
||||
int quality_loss = 1;
|
||||
int is_rand = 0;
|
||||
|
||||
/* should be test_tile_encoder 3 2000 2000 1000 1000 8 tte1.j2k */
|
||||
if (argc == 9) {
|
||||
opj_set_default_encoder_parameters(&l_param);
|
||||
|
||||
/* should be test_tile_encoder 3 2000 2000 1000 1000 8 tte1.j2k [64 64] [6] [0 0] [0] [256 256] */
|
||||
if (argc >= 9) {
|
||||
num_comps = (OPJ_UINT32)atoi(argv[1]);
|
||||
image_width = atoi(argv[2]);
|
||||
image_height = atoi(argv[3]);
|
||||
|
@ -109,6 +128,28 @@ int main(int argc, char *argv[])
|
|||
comp_prec = atoi(argv[6]);
|
||||
irreversible = atoi(argv[7]);
|
||||
output_file = argv[8];
|
||||
if (argc >= 12) {
|
||||
quality_loss = 0;
|
||||
cblockw_init = atoi(argv[9]);
|
||||
cblockh_init = atoi(argv[10]);
|
||||
}
|
||||
if (argc >= 13) {
|
||||
numresolution = atoi(argv[11]);
|
||||
}
|
||||
if (argc >= 14) {
|
||||
offsetx = (OPJ_UINT32)atoi(argv[12]);
|
||||
offsety = (OPJ_UINT32)atoi(argv[13]);
|
||||
}
|
||||
if (argc >= 15) {
|
||||
is_rand = atoi(argv[14]);
|
||||
}
|
||||
for (i = 15; i + 1 < (OPJ_UINT32)argc &&
|
||||
l_param.res_spec < OPJ_J2K_MAXRLVLS; i += 2) {
|
||||
l_param.csty |= 0x01;
|
||||
l_param.prcw_init[l_param.res_spec] = atoi(argv[i]);
|
||||
l_param.prch_init[l_param.res_spec] = atoi(argv[i + 1]);
|
||||
l_param.res_spec ++;
|
||||
}
|
||||
} else {
|
||||
num_comps = 3;
|
||||
image_width = 2000;
|
||||
|
@ -122,8 +163,11 @@ int main(int argc, char *argv[])
|
|||
if (num_comps > NUM_COMPS_MAX) {
|
||||
return 1;
|
||||
}
|
||||
l_nb_tiles = (OPJ_UINT32)(image_width / tile_width) * (OPJ_UINT32)(
|
||||
image_height / tile_height);
|
||||
l_nb_tiles_width = (offsetx + (OPJ_UINT32)image_width +
|
||||
(OPJ_UINT32)tile_width - 1) / (OPJ_UINT32)tile_width;
|
||||
l_nb_tiles_height = (offsety + (OPJ_UINT32)image_height +
|
||||
(OPJ_UINT32)tile_height - 1) / (OPJ_UINT32)tile_height;
|
||||
l_nb_tiles = l_nb_tiles_width * l_nb_tiles_height;
|
||||
l_data_size = (OPJ_UINT32)tile_width * (OPJ_UINT32)tile_height *
|
||||
(OPJ_UINT32)num_comps * (OPJ_UINT32)(comp_prec / 8);
|
||||
|
||||
|
@ -134,16 +178,21 @@ int main(int argc, char *argv[])
|
|||
fprintf(stdout,
|
||||
"Encoding random values -> keep in mind that this is very hard to compress\n");
|
||||
for (i = 0; i < l_data_size; ++i) {
|
||||
l_data[i] = (OPJ_BYTE)i; /*rand();*/
|
||||
if (is_rand) {
|
||||
l_data[i] = (OPJ_BYTE)rand();
|
||||
} else {
|
||||
l_data[i] = (OPJ_BYTE)i;
|
||||
}
|
||||
}
|
||||
|
||||
opj_set_default_encoder_parameters(&l_param);
|
||||
/** you may here add custom encoding parameters */
|
||||
/* rate specifications */
|
||||
/** number of quality layers in the stream */
|
||||
if (quality_loss) {
|
||||
l_param.tcp_numlayers = 1;
|
||||
l_param.cp_fixed_quality = 1;
|
||||
l_param.tcp_distoratio[0] = 20;
|
||||
}
|
||||
/* is using others way of calculation */
|
||||
/* l_param.cp_disto_alloc = 1 or l_param.cp_fixed_alloc = 1 */
|
||||
/* l_param.tcp_rates[0] = ... */
|
||||
|
@ -158,6 +207,10 @@ int main(int argc, char *argv[])
|
|||
l_param.cp_tdx = tile_width;
|
||||
l_param.cp_tdy = tile_height;
|
||||
|
||||
/* code block size */
|
||||
l_param.cblockw_init = cblockw_init;
|
||||
l_param.cblockh_init = cblockh_init;
|
||||
|
||||
/* use irreversible encoding ?*/
|
||||
l_param.irreversible = irreversible;
|
||||
|
||||
|
@ -187,7 +240,7 @@ int main(int argc, char *argv[])
|
|||
/* l_param.mode = 0;*/
|
||||
|
||||
/** number of resolutions */
|
||||
l_param.numresolution = 6;
|
||||
l_param.numresolution = numresolution;
|
||||
|
||||
/** progression order to use*/
|
||||
/** OPJ_LRCP, OPJ_RLCP, OPJ_RPCL, PCRL, CPRL */
|
||||
|
@ -221,8 +274,8 @@ int main(int argc, char *argv[])
|
|||
l_current_param_ptr->sgnd = 0;
|
||||
l_current_param_ptr->prec = (OPJ_UINT32)comp_prec;
|
||||
|
||||
l_current_param_ptr->x0 = 0;
|
||||
l_current_param_ptr->y0 = 0;
|
||||
l_current_param_ptr->x0 = offsetx;
|
||||
l_current_param_ptr->y0 = offsety;
|
||||
|
||||
++l_current_param_ptr;
|
||||
}
|
||||
|
@ -251,10 +304,10 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
l_image->x0 = 0;
|
||||
l_image->y0 = 0;
|
||||
l_image->x1 = (OPJ_UINT32)image_width;
|
||||
l_image->y1 = (OPJ_UINT32)image_height;
|
||||
l_image->x0 = offsetx;
|
||||
l_image->y0 = offsety;
|
||||
l_image->x1 = offsetx + (OPJ_UINT32)image_width;
|
||||
l_image->y1 = offsety + (OPJ_UINT32)image_height;
|
||||
l_image->color_space = OPJ_CLRSPC_SRGB;
|
||||
|
||||
if (! opj_setup_encoder(l_codec, &l_param, l_image)) {
|
||||
|
@ -286,7 +339,18 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
for (i = 0; i < l_nb_tiles; ++i) {
|
||||
if (! opj_write_tile(l_codec, i, l_data, l_data_size, l_stream)) {
|
||||
OPJ_UINT32 tile_y = i / l_nb_tiles_width;
|
||||
OPJ_UINT32 tile_x = i % l_nb_tiles_width;
|
||||
OPJ_UINT32 tile_x0 = opj_uint_max(l_image->x0, tile_x * (OPJ_UINT32)tile_width);
|
||||
OPJ_UINT32 tile_y0 = opj_uint_max(l_image->y0,
|
||||
tile_y * (OPJ_UINT32)tile_height);
|
||||
OPJ_UINT32 tile_x1 = opj_uint_min(l_image->x1,
|
||||
(tile_x + 1) * (OPJ_UINT32)tile_width);
|
||||
OPJ_UINT32 tile_y1 = opj_uint_min(l_image->y1,
|
||||
(tile_y + 1) * (OPJ_UINT32)tile_height);
|
||||
OPJ_UINT32 tilesize = (tile_x1 - tile_x0) * (tile_y1 - tile_y0) *
|
||||
(OPJ_UINT32)num_comps * (OPJ_UINT32)(comp_prec / 8);
|
||||
if (! opj_write_tile(l_codec, i, l_data, tilesize, l_stream)) {
|
||||
fprintf(stderr, "ERROR -> test_tile_encoder: failed to write the tile %d!\n",
|
||||
i);
|
||||
opj_stream_destroy(l_stream);
|
||||
|
|
Loading…
Reference in New Issue