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:
Even Rouault 2017-08-21 13:02:07 +02:00 committed by GitHub
commit e9bbc6d3dd
14 changed files with 1576 additions and 189 deletions

View File

@ -133,7 +133,12 @@ OPJ_FLOAT64 opj_clock(void)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
int num_threads = 0; 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_tcd_tilecomp_t tilec;
opj_image_t image;
opj_image_comp_t image_comp;
opj_thread_pool_t* tp; opj_thread_pool_t* tp;
OPJ_INT32 i, j, k; OPJ_INT32 i, j, k;
OPJ_BOOL display = OPJ_FALSE; 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(); start = opj_clock();
opj_dwt_decode(tp, &tilec, tilec.numresolutions); opj_dwt_decode(&tcd, &tilec, tilec.numresolutions);
stop = opj_clock(); stop = opj_clock();
printf("time for dwt_decode: %.03f s\n", stop - start); printf("time for dwt_decode: %.03f s\n", stop - start);

File diff suppressed because it is too large Load Diff

View File

@ -63,11 +63,12 @@ OPJ_BOOL opj_dwt_encode(opj_tcd_tilecomp_t * tilec);
/** /**
Inverse 5-3 wavelet transform in 2-D. Inverse 5-3 wavelet transform in 2-D.
Apply a reversible inverse DWT transform to a component of an image. 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 tilec Tile component information (current tile)
@param numres Number of resolution levels to decode @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); 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. Inverse 9-7 wavelet transform in 2-D.
Apply an irreversible inverse DWT transform to a component of an image. Apply an irreversible inverse DWT transform to a component of an image.
@param tcd TCD handle
@param tilec Tile component information (current tile) @param tilec Tile component information (current tile)
@param numres Number of resolution levels to decode @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); OPJ_UINT32 numres);
/** /**

View File

@ -16,6 +16,7 @@
* Copyright (c) 2010-2011, Kaori Hagihara * Copyright (c) 2010-2011, Kaori Hagihara
* Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France
* Copyright (c) 2012, CS Systemes d'Information, France * Copyright (c) 2012, CS Systemes d'Information, France
* Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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_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); 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_UINT32 l_current_marker;
OPJ_BYTE l_data [2]; OPJ_BYTE l_data [2];
opj_tcp_t * l_tcp; opj_tcp_t * l_tcp;
opj_image_t* l_image_for_bounds;
/* preconditions */ /* preconditions */
assert(p_stream != 00); assert(p_stream != 00);
@ -8787,7 +8799,18 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
return OPJ_FALSE; 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, 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,
l_tcp->m_data_size, l_tcp->m_data_size,
p_tile_index, p_tile_index,

View File

@ -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; 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 Clamp an integer inside an interval
@return @return

View File

@ -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, volatile OPJ_BOOL* pret,
opj_tcd_tilecomp_t* tilec, opj_tcd_tilecomp_t* tilec,
opj_tccp_t* tccp, opj_tccp_t* tccp,
@ -1760,6 +1760,7 @@ void opj_t1_decode_cblks(opj_thread_pool_t* tp,
OPJ_BOOL check_pterm OPJ_BOOL check_pterm
) )
{ {
opj_thread_pool_t* tp = tcd->thread_pool;
OPJ_UINT32 resno, bandno, precno, cblkno; OPJ_UINT32 resno, bandno, precno, cblkno;
for (resno = 0; resno < tilec->minimum_num_resolutions; ++resno) { 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) { for (precno = 0; precno < res->pw * res->ph; ++precno) {
opj_tcd_precinct_t* precinct = &band->precincts[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) { for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) {
opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno]; opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno];
opj_t1_cblk_decode_processing_job_t* job; 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, job = (opj_t1_cblk_decode_processing_job_t*) opj_calloc(1,
sizeof(opj_t1_cblk_decode_processing_job_t)); sizeof(opj_t1_cblk_decode_processing_job_t));
if (!job) { if (!job) {

View File

@ -230,7 +230,7 @@ OPJ_BOOL opj_t1_encode_cblks(opj_t1_t *t1,
/** /**
Decode the code-blocks of a tile Decode the code-blocks of a tile
@param tp Thread pool @param tcd TCD handle
@param pret Pointer to return value @param pret Pointer to return value
@param tilec The tile to decode @param tilec The tile to decode
@param tccp Tile coding parameters @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 p_manager_mutex mutex for the event manager
@param check_pterm whether PTERM correct termination should be checked @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, volatile OPJ_BOOL* pret,
opj_tcd_tilecomp_t* tilec, opj_tcd_tilecomp_t* tilec,
opj_tccp_t* tccp, opj_tccp_t* tccp,

View File

@ -13,6 +13,7 @@
* Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France * Copyright (c) 2012, CS Systemes d'Information, France
* Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 #define JAS_FPRINTF opj_null_jas_fprintf
#endif #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_UINT32 p_tile_no,
opj_tcd_tile_t *p_tile, opj_tcd_tile_t *p_tile,
OPJ_BYTE *p_src, 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)); memset(first_pass_failed, OPJ_TRUE, l_image->numcomps * sizeof(OPJ_BOOL));
while (opj_pi_next(l_current_pi)) { while (opj_pi_next(l_current_pi)) {
OPJ_BOOL skip_packet = OPJ_FALSE;
JAS_FPRINTF(stderr, JAS_FPRINTF(stderr,
"packet offset=00000166 prg=%d cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d\n\n", "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->poc.prg1, l_current_pi->compno, l_current_pi->resno,
l_current_pi->precno, l_current_pi->layno); l_current_pi->precno, l_current_pi->layno);
if (l_tcp->num_layers_to_decode > l_current_pi->layno /* If the packet layer is greater or equal than the maximum */
&& l_current_pi->resno < /* 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) { 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; l_nb_bytes_read = 0;
first_pass_failed[l_current_pi->compno] = OPJ_FALSE; first_pass_failed[l_current_pi->compno] = OPJ_FALSE;

View File

@ -13,6 +13,7 @@
* Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France * Copyright (c) 2012, CS Systemes d'Information, France
* Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 Decode the packets of a tile from a source buffer
@param tcd TCD handle
@param t2 T2 handle @param t2 T2 handle
@param tileno number that identifies the tile for which to decode the packets @param tileno number that identifies the tile for which to decode the packets
@param tile 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 @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_UINT32 tileno,
opj_tcd_tile_t *tile, opj_tcd_tile_t *tile,
OPJ_BYTE *src, OPJ_BYTE *src,

View File

@ -14,6 +14,7 @@
* Copyright (c) 2006-2007, Parvatha Elangovan * Copyright (c) 2006-2007, Parvatha Elangovan
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France * Copyright (c) 2012, CS Systemes d'Information, France
* Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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->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->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->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);*/ /*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 */ /* 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_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_BYTE *p_src,
OPJ_UINT32 p_max_length, OPJ_UINT32 p_max_length,
OPJ_UINT32 p_tile_no, 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; OPJ_UINT32 l_data_read;
p_tcd->tcd_tileno = p_tile_no; p_tcd->tcd_tileno = p_tile_no;
p_tcd->tcp = &(p_tcd->cp->tcps[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 */ #ifdef TODO_MSD /* FIXME */
/* INDEX >> */ /* INDEX >> */
@ -1690,6 +1700,7 @@ static OPJ_BOOL opj_tcd_t2_decode(opj_tcd_t *p_tcd,
} }
if (! opj_t2_decode_packets( if (! opj_t2_decode_packets(
p_tcd,
l_t2, l_t2,
p_tcd->tcd_tileno, p_tcd->tcd_tileno,
p_tcd->tcd_image->tiles, 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) { 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); p_manager, p_manager_mutex, check_pterm);
if (!ret) { if (!ret) {
break; break;
@ -1767,12 +1778,13 @@ static OPJ_BOOL opj_tcd_dwt_decode(opj_tcd_t *p_tcd)
*/ */
if (l_tccp->qmfbid == 1) { 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)) { l_img_comp->resno_decoded + 1)) {
return OPJ_FALSE; return OPJ_FALSE;
} }
} else { } 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; 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); 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;
}

View File

@ -13,6 +13,7 @@
* Copyright (c) 2005, Herve Drolon, FreeImage Team * Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France * Copyright (c) 2012, CS Systemes d'Information, France
* Copyright (c) 2017, IntoPIX SA <support@intopix.com>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 { typedef struct opj_tcd_tilecomp {
/* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */ /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */
OPJ_INT32 x0, y0, x1, y1; OPJ_INT32 x0, y0, x1, y1;
/* component number */
OPJ_UINT32 compno;
/* number of resolutions level */ /* number of resolutions level */
OPJ_UINT32 numresolutions; OPJ_UINT32 numresolutions;
/* number of resolutions level to decode (at max)*/ /* number of resolutions level to decode (at max)*/
@ -252,6 +255,10 @@ typedef struct opj_tcd {
OPJ_BITFIELD m_is_decoder : 1; OPJ_BITFIELD m_is_decoder : 1;
/** Thread pool */ /** Thread pool */
opj_thread_pool_t* 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; } opj_tcd_t;
/** @name Exported functions */ /** @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 Decode a tile from a buffer into a raw image
@param tcd TCD handle @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 src Source buffer
@param len Length of source buffer @param len Length of source buffer
@param tileno Number that identifies one of the tiles to be decoded @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. @param manager the event manager.
*/ */
OPJ_BOOL opj_tcd_decode_tile(opj_tcd_t *tcd, 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_BYTE *src,
OPJ_UINT32 len, OPJ_UINT32 len,
OPJ_UINT32 tileno, OPJ_UINT32 tileno,
@ -409,6 +424,31 @@ OPJ_BOOL opj_tcd_is_band_empty(opj_tcd_band_t* band);
/** Reinitialize a segment */ /** Reinitialize a segment */
void opj_tcd_reinit_segment(opj_tcd_seg_t* seg); 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);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/*@}*/ /*@}*/

View File

@ -45,6 +45,9 @@ add_executable(compare_raw_files ${compare_raw_files_SRCS})
add_executable(test_tile_encoder test_tile_encoder.c) add_executable(test_tile_encoder test_tile_encoder.c)
target_link_libraries(test_tile_encoder ${OPENJPEG_LIBRARY_NAME}) 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: # Let's try a couple of possibilities:
add_test(NAME tte0 COMMAND test_tile_encoder) 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) 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) add_test(NAME rta5 COMMAND j2k_random_tile_access tte5.j2k)
set_property(TEST rta5 APPEND PROPERTY DEPENDS tte5) 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) add_executable(include_openjpeg include_openjpeg.c)
# No image send to the dashboard if lib PNG is not available. # No image send to the dashboard if lib PNG is not available.

396
tests/test_decode_area.c Normal file
View File

@ -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;
}

View File

@ -60,6 +60,16 @@ static void info_callback(const char *msg, void *client_data)
fprintf(stdout, "[INFO] %s", msg); 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 #define NUM_COMPS_MAX 4
@ -70,7 +80,7 @@ int main(int argc, char *argv[])
opj_image_t * l_image; opj_image_t * l_image;
opj_image_cmptparm_t l_params [NUM_COMPS_MAX]; opj_image_cmptparm_t l_params [NUM_COMPS_MAX];
opj_stream_t * l_stream; 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; OPJ_UINT32 l_data_size;
size_t len; size_t len;
@ -98,9 +108,18 @@ int main(int argc, char *argv[])
int comp_prec; int comp_prec;
int irreversible; int irreversible;
const char *output_file; 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 */ opj_set_default_encoder_parameters(&l_param);
if (argc == 9) {
/* 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]); num_comps = (OPJ_UINT32)atoi(argv[1]);
image_width = atoi(argv[2]); image_width = atoi(argv[2]);
image_height = atoi(argv[3]); image_height = atoi(argv[3]);
@ -109,6 +128,28 @@ int main(int argc, char *argv[])
comp_prec = atoi(argv[6]); comp_prec = atoi(argv[6]);
irreversible = atoi(argv[7]); irreversible = atoi(argv[7]);
output_file = argv[8]; 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 { } else {
num_comps = 3; num_comps = 3;
image_width = 2000; image_width = 2000;
@ -122,8 +163,11 @@ int main(int argc, char *argv[])
if (num_comps > NUM_COMPS_MAX) { if (num_comps > NUM_COMPS_MAX) {
return 1; return 1;
} }
l_nb_tiles = (OPJ_UINT32)(image_width / tile_width) * (OPJ_UINT32)( l_nb_tiles_width = (offsetx + (OPJ_UINT32)image_width +
image_height / tile_height); (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 * l_data_size = (OPJ_UINT32)tile_width * (OPJ_UINT32)tile_height *
(OPJ_UINT32)num_comps * (OPJ_UINT32)(comp_prec / 8); (OPJ_UINT32)num_comps * (OPJ_UINT32)(comp_prec / 8);
@ -134,16 +178,21 @@ int main(int argc, char *argv[])
fprintf(stdout, fprintf(stdout,
"Encoding random values -> keep in mind that this is very hard to compress\n"); "Encoding random values -> keep in mind that this is very hard to compress\n");
for (i = 0; i < l_data_size; ++i) { 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 */ /** you may here add custom encoding parameters */
/* rate specifications */ /* rate specifications */
/** number of quality layers in the stream */ /** number of quality layers in the stream */
if (quality_loss) {
l_param.tcp_numlayers = 1; l_param.tcp_numlayers = 1;
l_param.cp_fixed_quality = 1; l_param.cp_fixed_quality = 1;
l_param.tcp_distoratio[0] = 20; l_param.tcp_distoratio[0] = 20;
}
/* is using others way of calculation */ /* is using others way of calculation */
/* l_param.cp_disto_alloc = 1 or l_param.cp_fixed_alloc = 1 */ /* l_param.cp_disto_alloc = 1 or l_param.cp_fixed_alloc = 1 */
/* l_param.tcp_rates[0] = ... */ /* l_param.tcp_rates[0] = ... */
@ -158,6 +207,10 @@ int main(int argc, char *argv[])
l_param.cp_tdx = tile_width; l_param.cp_tdx = tile_width;
l_param.cp_tdy = tile_height; l_param.cp_tdy = tile_height;
/* code block size */
l_param.cblockw_init = cblockw_init;
l_param.cblockh_init = cblockh_init;
/* use irreversible encoding ?*/ /* use irreversible encoding ?*/
l_param.irreversible = irreversible; l_param.irreversible = irreversible;
@ -187,7 +240,7 @@ int main(int argc, char *argv[])
/* l_param.mode = 0;*/ /* l_param.mode = 0;*/
/** number of resolutions */ /** number of resolutions */
l_param.numresolution = 6; l_param.numresolution = numresolution;
/** progression order to use*/ /** progression order to use*/
/** OPJ_LRCP, OPJ_RLCP, OPJ_RPCL, PCRL, CPRL */ /** 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->sgnd = 0;
l_current_param_ptr->prec = (OPJ_UINT32)comp_prec; l_current_param_ptr->prec = (OPJ_UINT32)comp_prec;
l_current_param_ptr->x0 = 0; l_current_param_ptr->x0 = offsetx;
l_current_param_ptr->y0 = 0; l_current_param_ptr->y0 = offsety;
++l_current_param_ptr; ++l_current_param_ptr;
} }
@ -251,10 +304,10 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
l_image->x0 = 0; l_image->x0 = offsetx;
l_image->y0 = 0; l_image->y0 = offsety;
l_image->x1 = (OPJ_UINT32)image_width; l_image->x1 = offsetx + (OPJ_UINT32)image_width;
l_image->y1 = (OPJ_UINT32)image_height; l_image->y1 = offsety + (OPJ_UINT32)image_height;
l_image->color_space = OPJ_CLRSPC_SRGB; l_image->color_space = OPJ_CLRSPC_SRGB;
if (! opj_setup_encoder(l_codec, &l_param, l_image)) { 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) { 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", fprintf(stderr, "ERROR -> test_tile_encoder: failed to write the tile %d!\n",
i); i);
opj_stream_destroy(l_stream); opj_stream_destroy(l_stream);