Make opj_set_decode_area() and opj_decode() take into account opj_set_decoded_resolution_factor() (#1006, affect API use)
* Better document usage of opj_set_decode_area(), ie expecting coordinates in full resolution/reference grid even if requesting at a lower resolution factor * Make sure that image->comps[].factor is set by opj_set_decode_area() and opj_decode() from the value specified in opj_set_decoded_resolution_factor() * opj_decompress: add 2 environmenet variables to test alternate ways of using the API, namely USE_OPJ_SET_DECODED_RESOLUTION_FACTOR=YES to use opj_set_decoded_resolution_factor() instead of parameters.cp_reduce, and SKIP_OPJ_SET_DECODE_AREA=YES to not call opj_set_decode_area() if -d is not specified.
This commit is contained in:
parent
5a4a10120a
commit
8f92fc9791
|
@ -1297,6 +1297,7 @@ int main(int argc, char **argv)
|
|||
int failed = 0;
|
||||
OPJ_FLOAT64 t, tCumulative = 0;
|
||||
OPJ_UINT32 numDecompressedImages = 0;
|
||||
OPJ_UINT32 cp_reduce;
|
||||
|
||||
/* set decoding parameters to default values */
|
||||
set_default_parameters(¶meters);
|
||||
|
@ -1310,6 +1311,14 @@ int main(int argc, char **argv)
|
|||
goto fin;
|
||||
}
|
||||
|
||||
cp_reduce = parameters.core.cp_reduce;
|
||||
if (getenv("USE_OPJ_SET_DECODED_RESOLUTION_FACTOR") != NULL) {
|
||||
/* For debugging/testing purposes, do not set the cp_reduce member */
|
||||
/* if USE_OPJ_SET_DECODED_RESOLUTION_FACTOR is defined, but used */
|
||||
/* the opj_set_decoded_resolution_factor() API instead */
|
||||
parameters.core.cp_reduce = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize reading of directory */
|
||||
if (img_fol.set_imgdir == 1) {
|
||||
|
@ -1446,11 +1455,35 @@ int main(int argc, char **argv)
|
|||
goto fin;
|
||||
}
|
||||
|
||||
if (getenv("USE_OPJ_SET_DECODED_RESOLUTION_FACTOR") != NULL) {
|
||||
/* For debugging/testing purposes, and also an illustration on how to */
|
||||
/* use the alternative API opj_set_decoded_resolution_factor() instead */
|
||||
/* of setting parameters.cp_reduce */
|
||||
if (! opj_set_decoded_resolution_factor(l_codec, cp_reduce)) {
|
||||
fprintf(stderr,
|
||||
"ERROR -> opj_decompress: failed to set the resolution factor tile!\n");
|
||||
opj_destroy_codec(l_codec);
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_image_destroy(image);
|
||||
failed = 1;
|
||||
goto fin;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parameters.nb_tile_to_decode) {
|
||||
if (getenv("SKIP_OPJ_SET_DECODE_AREA") != NULL &&
|
||||
parameters.DA_x0 == 0 &&
|
||||
parameters.DA_y0 == 0 &&
|
||||
parameters.DA_x1 == 0 &&
|
||||
parameters.DA_y1 == 0) {
|
||||
/* For debugging/testing purposes, */
|
||||
/* do nothing if SKIP_OPJ_SET_DECODE_AREA env variable */
|
||||
/* is defined and no decoded area has been set */
|
||||
}
|
||||
/* Optional if you want decode the entire image */
|
||||
if (!opj_set_decode_area(l_codec, image, (OPJ_INT32)parameters.DA_x0,
|
||||
(OPJ_INT32)parameters.DA_y0, (OPJ_INT32)parameters.DA_x1,
|
||||
(OPJ_INT32)parameters.DA_y1)) {
|
||||
else if (!opj_set_decode_area(l_codec, image, (OPJ_INT32)parameters.DA_x0,
|
||||
(OPJ_INT32)parameters.DA_y0, (OPJ_INT32)parameters.DA_x1,
|
||||
(OPJ_INT32)parameters.DA_y1)) {
|
||||
fprintf(stderr, "ERROR -> opj_decompress: failed to set the decoded area\n");
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_destroy_codec(l_codec);
|
||||
|
@ -1471,15 +1504,6 @@ int main(int argc, char **argv)
|
|||
}
|
||||
} else {
|
||||
|
||||
/* It is just here to illustrate how to use the resolution after set parameters */
|
||||
/*if (!opj_set_decoded_resolution_factor(l_codec, 5)) {
|
||||
fprintf(stderr, "ERROR -> opj_decompress: failed to set the resolution factor tile!\n");
|
||||
opj_destroy_codec(l_codec);
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_image_destroy(image);
|
||||
failed = 1; goto fin;
|
||||
}*/
|
||||
|
||||
if (!opj_get_decoded_tile(l_codec, l_stream, image, parameters.tile_index)) {
|
||||
fprintf(stderr, "ERROR -> opj_decompress: failed to decode tile!\n");
|
||||
opj_destroy_codec(l_codec);
|
||||
|
|
|
@ -9143,6 +9143,51 @@ static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, OPJ_BYTE * p_data,
|
|||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
static OPJ_BOOL opj_j2k_update_image_dimensions(opj_image_t* p_image,
|
||||
opj_event_mgr_t * p_manager)
|
||||
{
|
||||
OPJ_UINT32 it_comp;
|
||||
OPJ_INT32 l_comp_x1, l_comp_y1;
|
||||
opj_image_comp_t* l_img_comp = NULL;
|
||||
|
||||
l_img_comp = p_image->comps;
|
||||
for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) {
|
||||
OPJ_INT32 l_h, l_w;
|
||||
|
||||
l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0,
|
||||
(OPJ_INT32)l_img_comp->dx);
|
||||
l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0,
|
||||
(OPJ_INT32)l_img_comp->dy);
|
||||
l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx);
|
||||
l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy);
|
||||
|
||||
l_w = opj_int_ceildivpow2(l_comp_x1, (OPJ_INT32)l_img_comp->factor)
|
||||
- opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, (OPJ_INT32)l_img_comp->factor);
|
||||
if (l_w < 0) {
|
||||
opj_event_msg(p_manager, EVT_ERROR,
|
||||
"Size x of the decoded component image is incorrect (comp[%d].w=%d).\n",
|
||||
it_comp, l_w);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
l_img_comp->w = (OPJ_UINT32)l_w;
|
||||
|
||||
l_h = opj_int_ceildivpow2(l_comp_y1, (OPJ_INT32)l_img_comp->factor)
|
||||
- opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, (OPJ_INT32)l_img_comp->factor);
|
||||
if (l_h < 0) {
|
||||
opj_event_msg(p_manager, EVT_ERROR,
|
||||
"Size y of the decoded component image is incorrect (comp[%d].h=%d).\n",
|
||||
it_comp, l_h);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
l_img_comp->h = (OPJ_UINT32)l_h;
|
||||
|
||||
l_img_comp++;
|
||||
}
|
||||
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
|
||||
OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
|
||||
opj_image_t* p_image,
|
||||
OPJ_INT32 p_start_x, OPJ_INT32 p_start_y,
|
||||
|
@ -9151,10 +9196,8 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
|
|||
{
|
||||
opj_cp_t * l_cp = &(p_j2k->m_cp);
|
||||
opj_image_t * l_image = p_j2k->m_private_image;
|
||||
|
||||
OPJ_BOOL ret;
|
||||
OPJ_UINT32 it_comp;
|
||||
OPJ_INT32 l_comp_x1, l_comp_y1;
|
||||
opj_image_comp_t* l_img_comp = NULL;
|
||||
|
||||
/* Check if we are read the main header */
|
||||
if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) {
|
||||
|
@ -9163,6 +9206,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
|
|||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
/* Update the comps[].factor member of the output image with the one */
|
||||
/* of m_reduce */
|
||||
for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) {
|
||||
p_image->comps[it_comp].factor = p_j2k->m_cp.m_specific_param.m_dec.m_reduce;
|
||||
}
|
||||
|
||||
if (!p_start_x && !p_start_y && !p_end_x && !p_end_y) {
|
||||
opj_event_msg(p_manager, EVT_INFO,
|
||||
"No decoded area parameters, set the decoded area to the whole image\n");
|
||||
|
@ -9172,7 +9221,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
|
|||
p_j2k->m_specific_param.m_decoder.m_end_tile_x = l_cp->tw;
|
||||
p_j2k->m_specific_param.m_decoder.m_end_tile_y = l_cp->th;
|
||||
|
||||
return OPJ_TRUE;
|
||||
p_image->x0 = l_image->x0;
|
||||
p_image->y0 = l_image->y0;
|
||||
p_image->x1 = l_image->x1;
|
||||
p_image->y1 = l_image->y1;
|
||||
|
||||
return opj_j2k_update_image_dimensions(p_image, p_manager);
|
||||
}
|
||||
|
||||
/* ----- */
|
||||
|
@ -9274,44 +9328,14 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
|
|||
|
||||
p_j2k->m_specific_param.m_decoder.m_discard_tiles = 1;
|
||||
|
||||
l_img_comp = p_image->comps;
|
||||
for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) {
|
||||
OPJ_INT32 l_h, l_w;
|
||||
ret = opj_j2k_update_image_dimensions(p_image, p_manager);
|
||||
|
||||
l_img_comp->x0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->x0,
|
||||
(OPJ_INT32)l_img_comp->dx);
|
||||
l_img_comp->y0 = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)p_image->y0,
|
||||
(OPJ_INT32)l_img_comp->dy);
|
||||
l_comp_x1 = opj_int_ceildiv((OPJ_INT32)p_image->x1, (OPJ_INT32)l_img_comp->dx);
|
||||
l_comp_y1 = opj_int_ceildiv((OPJ_INT32)p_image->y1, (OPJ_INT32)l_img_comp->dy);
|
||||
|
||||
l_w = opj_int_ceildivpow2(l_comp_x1, (OPJ_INT32)l_img_comp->factor)
|
||||
- opj_int_ceildivpow2((OPJ_INT32)l_img_comp->x0, (OPJ_INT32)l_img_comp->factor);
|
||||
if (l_w < 0) {
|
||||
opj_event_msg(p_manager, EVT_ERROR,
|
||||
"Size x of the decoded component image is incorrect (comp[%d].w=%d).\n",
|
||||
it_comp, l_w);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
l_img_comp->w = (OPJ_UINT32)l_w;
|
||||
|
||||
l_h = opj_int_ceildivpow2(l_comp_y1, (OPJ_INT32)l_img_comp->factor)
|
||||
- opj_int_ceildivpow2((OPJ_INT32)l_img_comp->y0, (OPJ_INT32)l_img_comp->factor);
|
||||
if (l_h < 0) {
|
||||
opj_event_msg(p_manager, EVT_ERROR,
|
||||
"Size y of the decoded component image is incorrect (comp[%d].h=%d).\n",
|
||||
it_comp, l_h);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
l_img_comp->h = (OPJ_UINT32)l_h;
|
||||
|
||||
l_img_comp++;
|
||||
if (ret) {
|
||||
opj_event_msg(p_manager, EVT_INFO, "Setting decoding area to %d,%d,%d,%d\n",
|
||||
p_image->x0, p_image->y0, p_image->x1, p_image->y1);
|
||||
}
|
||||
|
||||
opj_event_msg(p_manager, EVT_INFO, "Setting decoding area to %d,%d,%d,%d\n",
|
||||
p_image->x0, p_image->y0, p_image->x1, p_image->y1);
|
||||
|
||||
return OPJ_TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
opj_j2k_t* opj_j2k_create_decompress(void)
|
||||
|
@ -10796,6 +10820,31 @@ OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k,
|
|||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
/* Heuristics to detect sequence opj_read_header(), opj_set_decoded_resolution_factor() */
|
||||
/* and finally opj_decode_image() without manual setting of comps[].factor */
|
||||
/* We could potentially always execute it, if we don't allow people to do */
|
||||
/* opj_read_header(), modify x0,y0,x1,y1 of returned image an call opj_decode_image() */
|
||||
if (p_j2k->m_cp.m_specific_param.m_dec.m_reduce > 0 &&
|
||||
p_j2k->m_private_image != NULL &&
|
||||
p_j2k->m_private_image->numcomps > 0 &&
|
||||
p_j2k->m_private_image->comps[0].factor ==
|
||||
p_j2k->m_cp.m_specific_param.m_dec.m_reduce &&
|
||||
p_image->numcomps > 0 &&
|
||||
p_image->comps[0].factor == 0 &&
|
||||
/* Don't mess with image dimension if the user has allocated it */
|
||||
p_image->comps[0].data == NULL) {
|
||||
OPJ_UINT32 it_comp;
|
||||
|
||||
/* Update the comps[].factor member of the output image with the one */
|
||||
/* of m_reduce */
|
||||
for (it_comp = 0; it_comp < p_image->numcomps; ++it_comp) {
|
||||
p_image->comps[it_comp].factor = p_j2k->m_cp.m_specific_param.m_dec.m_reduce;
|
||||
}
|
||||
if (!opj_j2k_update_image_dimensions(p_image, p_manager)) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
p_j2k->m_output_image = opj_image_create0();
|
||||
if (!(p_j2k->m_output_image)) {
|
||||
return OPJ_FALSE;
|
||||
|
|
|
@ -1336,6 +1336,10 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_read_header(opj_stream_t *p_stream,
|
|||
/**
|
||||
* Sets the given area to be decoded. This function should be called right after opj_read_header and before any tile header reading.
|
||||
*
|
||||
* The coordinates passed to this function should be expressed in the reference grid,
|
||||
* that is to say at the highest resolution level, even if requesting the image at lower
|
||||
* resolution levels.
|
||||
*
|
||||
* @param p_codec the jpeg2000 codec.
|
||||
* @param p_image the decoded image previously setted by opj_read_header
|
||||
* @param p_start_x the left position of the rectangle to decode (in image coordinates).
|
||||
|
|
Loading…
Reference in New Issue