opj_event_mgr_t * p_manager);
/**
- * Creates a tile-coder decoder.
+ * Creates a tile-coder encoder.
*
* @param p_stream the stream to write data to.
* @param p_j2k J2K codec.
parameters->tcp_rates[0] = 0;
}
+ if (parameters->cp_disto_alloc) {
+ /* Emit warnings if tcp_rates are not decreasing */
+ for (i = 1; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) {
+ OPJ_FLOAT32 rate_i_corr = parameters->tcp_rates[i];
+ OPJ_FLOAT32 rate_i_m_1_corr = parameters->tcp_rates[i - 1];
+ if (rate_i_corr <= 1.0) {
+ rate_i_corr = 1.0;
+ }
+ if (rate_i_m_1_corr <= 1.0) {
+ rate_i_m_1_corr = 1.0;
+ }
+ if (rate_i_corr >= rate_i_m_1_corr) {
+ if (rate_i_corr != parameters->tcp_rates[i] &&
+ rate_i_m_1_corr != parameters->tcp_rates[i - 1]) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "tcp_rates[%d]=%f (corrected as %f) should be strictly lesser "
+ "than tcp_rates[%d]=%f (corrected as %f)\n",
+ i, parameters->tcp_rates[i], rate_i_corr,
+ i - 1, parameters->tcp_rates[i - 1], rate_i_m_1_corr);
+ } else if (rate_i_corr != parameters->tcp_rates[i]) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "tcp_rates[%d]=%f (corrected as %f) should be strictly lesser "
+ "than tcp_rates[%d]=%f\n",
+ i, parameters->tcp_rates[i], rate_i_corr,
+ i - 1, parameters->tcp_rates[i - 1]);
+ } else if (rate_i_m_1_corr != parameters->tcp_rates[i - 1]) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "tcp_rates[%d]=%f should be strictly lesser "
+ "than tcp_rates[%d]=%f (corrected as %f)\n",
+ i, parameters->tcp_rates[i],
+ i - 1, parameters->tcp_rates[i - 1], rate_i_m_1_corr);
+ } else {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "tcp_rates[%d]=%f should be strictly lesser "
+ "than tcp_rates[%d]=%f\n",
+ i, parameters->tcp_rates[i],
+ i - 1, parameters->tcp_rates[i - 1]);
+ }
+ }
+ }
+ } else if (parameters->cp_fixed_quality) {
+ /* Emit warnings if tcp_distoratio are not increasing */
+ for (i = 1; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) {
+ if (parameters->tcp_distoratio[i] < parameters->tcp_distoratio[i - 1] &&
+ !(i == (OPJ_UINT32)parameters->tcp_numlayers - 1 &&
+ parameters->tcp_distoratio[i] == 0)) {
+ opj_event_msg(p_manager, EVT_WARNING,
+ "tcp_distoratio[%d]=%f should be strictly greater "
+ "than tcp_distoratio[%d]=%f\n",
+ i, parameters->tcp_distoratio[i], i - 1,
+ parameters->tcp_distoratio[i - 1]);
+ }
+ }
+ }
+
/* see if max_codestream_size does limit input rate */
if (parameters->max_cs_size <= 0) {
if (parameters->tcp_rates[parameters->tcp_numlayers - 1] > 0) {
OPJ_FLOAT32 temp_size;
- temp_size = (OPJ_FLOAT32)(image->numcomps * image->comps[0].w *
- image->comps[0].h * image->comps[0].prec) /
- (parameters->tcp_rates[parameters->tcp_numlayers - 1] * 8 *
- (OPJ_FLOAT32)image->comps[0].dx * (OPJ_FLOAT32)image->comps[0].dy);
- parameters->max_cs_size = (int) floor(temp_size);
+ temp_size = (OPJ_FLOAT32)(((double)image->numcomps * image->comps[0].w *
+ image->comps[0].h * image->comps[0].prec) /
+ ((double)parameters->tcp_rates[parameters->tcp_numlayers - 1] * 8 *
+ image->comps[0].dx * image->comps[0].dy));
+ if (temp_size > INT_MAX) {
+ parameters->max_cs_size = INT_MAX;
+ } else {
+ parameters->max_cs_size = (int) floor(temp_size);
+ }
} else {
parameters->max_cs_size = 0;
}
} else {
OPJ_FLOAT32 temp_rate;
OPJ_BOOL cap = OPJ_FALSE;
- temp_rate = (OPJ_FLOAT32)(image->numcomps * image->comps[0].w *
- image->comps[0].h * image->comps[0].prec) /
- (OPJ_FLOAT32)(((OPJ_UINT32)parameters->max_cs_size) * 8 * image->comps[0].dx *
- image->comps[0].dy);
+ temp_rate = (OPJ_FLOAT32)(((double)image->numcomps * image->comps[0].w *
+ image->comps[0].h * image->comps[0].prec) /
+ (((double)parameters->max_cs_size) * 8 * image->comps[0].dx *
+ image->comps[0].dy));
for (i = 0; i < (OPJ_UINT32) parameters->tcp_numlayers; i++) {
if (parameters->tcp_rates[i] < temp_rate) {
parameters->tcp_rates[i] = temp_rate;
tcp->rates[j] = parameters->tcp_rates[j];
}
}
+ if (!cp->m_specific_param.m_enc.m_fixed_quality &&
+ tcp->rates[j] <= 1.0) {
+ tcp->rates[j] = 0.0; /* force lossless */
+ }
}
tcp->csty = (OPJ_UINT32)parameters->csty;
}
/* Create the current tile decoder*/
- p_j2k->m_tcd = (opj_tcd_t*)opj_tcd_create(OPJ_TRUE); /* FIXME why a cast ? */
+ p_j2k->m_tcd = opj_tcd_create(OPJ_TRUE);
if (! p_j2k->m_tcd) {
return OPJ_FALSE;
}
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,
{
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) {
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");
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);
}
/* ----- */
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;
-
- 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);
+ ret = opj_j2k_update_image_dimensions(p_image, p_manager);
- 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)
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;
}
/**
- * Creates a tile-coder decoder.
+ * Creates a tile-coder encoder.
*
* @param p_stream the stream to write data to.
* @param p_j2k J2K codec.