opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n");
return OPJ_FALSE;
}
+#ifdef DEBUG_VERBOSE
+ fprintf(stderr, "SOT %d %d %d %d\n",
+ p_j2k->m_current_tile_number, l_tot_len, l_current_part, l_num_parts);
+#endif
l_cp = &(p_j2k->m_cp);
l_tile_x = p_j2k->m_current_tile_number % l_cp->tw;
l_tile_y = p_j2k->m_current_tile_number / l_cp->tw;
- /* Fixes issue with id_000020,sig_06,src_001958,op_flip4,pos_149 */
- /* of https://github.com/uclouvain/openjpeg/issues/939 */
- /* We must avoid reading twice the same tile part number for a given tile */
- /* so as to avoid various issues, like opj_j2k_merge_ppt being called */
- /* several times. */
- /* ISO 15444-1 A.4.2 Start of tile-part (SOT) mandates that tile parts */
- /* should appear in increasing order. */
- if (l_tcp->m_current_tile_part_number + 1 != (OPJ_INT32)l_current_part) {
- opj_event_msg(p_manager, EVT_ERROR,
- "Invalid tile part index for tile number %d. "
- "Got %d, expected %d\n",
- p_j2k->m_current_tile_number,
- l_current_part,
- l_tcp->m_current_tile_part_number + 1);
- return OPJ_FALSE;
+ if (p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec < 0 ||
+ p_j2k->m_current_tile_number == (OPJ_UINT32)
+ p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec) {
+ /* Do only this check if we decode all tile part headers, or if */
+ /* we decode one precise tile. Otherwise the m_current_tile_part_number */
+ /* might not be valid */
+ /* Fixes issue with id_000020,sig_06,src_001958,op_flip4,pos_149 */
+ /* of https://github.com/uclouvain/openjpeg/issues/939 */
+ /* We must avoid reading twice the same tile part number for a given tile */
+ /* so as to avoid various issues, like opj_j2k_merge_ppt being called */
+ /* several times. */
+ /* ISO 15444-1 A.4.2 Start of tile-part (SOT) mandates that tile parts */
+ /* should appear in increasing order. */
+ if (l_tcp->m_current_tile_part_number + 1 != (OPJ_INT32)l_current_part) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Invalid tile part index for tile number %d. "
+ "Got %d, expected %d\n",
+ p_j2k->m_current_tile_number,
+ l_current_part,
+ l_tcp->m_current_tile_part_number + 1);
+ return OPJ_FALSE;
+ }
}
- ++ l_tcp->m_current_tile_part_number;
+
+ l_tcp->m_current_tile_part_number = (OPJ_INT32) l_current_part;
#ifdef USE_JPWL
if (l_cp->correct) {
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;
l_img_comp_dest = p_output_image->comps;
- for (i = 0; i < l_image_src->numcomps; i++) {
+ for (i = 0; i < l_image_src->numcomps;
+ i++, ++l_img_comp_dest, ++l_img_comp_src, ++l_tilec) {
OPJ_INT32 res_x0, res_x1, res_y0, res_y1;
OPJ_UINT32 src_data_stride;
const OPJ_INT32* p_src_data;
- /* Allocate output component buffer if necessary */
- if (!l_img_comp_dest->data) {
- OPJ_SIZE_T l_width = l_img_comp_dest->w;
- OPJ_SIZE_T l_height = l_img_comp_dest->h;
-
- if ((l_height == 0U) || (l_width > (SIZE_MAX / l_height)) ||
- l_width * l_height > SIZE_MAX / sizeof(OPJ_INT32)) {
- /* would overflow */
- return OPJ_FALSE;
- }
- l_img_comp_dest->data = (OPJ_INT32*) opj_image_data_alloc(l_width * l_height *
- sizeof(OPJ_INT32));
- if (! l_img_comp_dest->data) {
- return OPJ_FALSE;
- }
- /* Do we really need this memset ? */
- memset(l_img_comp_dest->data, 0, l_width * l_height * sizeof(OPJ_INT32));
- }
-
/* Copy info from decoded comp image to output image */
l_img_comp_dest->resno_decoded = l_img_comp_src->resno_decoded;
l_start_offset_dest = (OPJ_SIZE_T)l_start_x_dest + (OPJ_SIZE_T)l_start_y_dest
* (OPJ_SIZE_T)l_img_comp_dest->w;
+ /* Allocate output component buffer if necessary */
+ if (l_img_comp_dest->data == NULL &&
+ l_start_offset_src == 0 && l_start_offset_dest == 0 &&
+ src_data_stride == l_img_comp_dest->w &&
+ l_width_dest == l_img_comp_dest->w &&
+ l_height_dest == l_img_comp_dest->h) {
+ /* If the final image matches the tile buffer, then borrow it */
+ /* directly to save a copy */
+ if (p_tcd->whole_tile_decoding) {
+ l_img_comp_dest->data = l_tilec->data;
+ l_tilec->data = NULL;
+ } else {
+ l_img_comp_dest->data = l_tilec->data_win;
+ l_tilec->data_win = NULL;
+ }
+ continue;
+ } else if (l_img_comp_dest->data == NULL) {
+ OPJ_SIZE_T l_width = l_img_comp_dest->w;
+ OPJ_SIZE_T l_height = l_img_comp_dest->h;
+
+ if ((l_height == 0U) || (l_width > (SIZE_MAX / l_height)) ||
+ l_width * l_height > SIZE_MAX / sizeof(OPJ_INT32)) {
+ /* would overflow */
+ return OPJ_FALSE;
+ }
+ l_img_comp_dest->data = (OPJ_INT32*) opj_image_data_alloc(l_width * l_height *
+ sizeof(OPJ_INT32));
+ if (! l_img_comp_dest->data) {
+ return OPJ_FALSE;
+ }
+
+ if (l_img_comp_dest->w != l_width_dest ||
+ l_img_comp_dest->h != l_height_dest) {
+ memset(l_img_comp_dest->data, 0,
+ (OPJ_SIZE_T)l_img_comp_dest->w * l_img_comp_dest->h * sizeof(OPJ_INT32));
+ }
+ }
+
/* Move the output buffer to the first place where we will write*/
l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest;
}
}
- ++l_img_comp_dest;
- ++l_img_comp_src;
- ++l_tilec;
+
}
return OPJ_TRUE;
OPJ_UINT32 it_comp;
if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 &&
- &p_j2k->m_cp.tcps[0].m_data != NULL) {
+ p_j2k->m_cp.tcps[0].m_data != NULL) {
/* In the case of a single-tiled image whose codestream we have already */
/* ingested, go on */
}
/* If user wants to remove more resolutions than the codestream contains, return error */
if (l_cp->m_specific_param.m_dec.m_reduce >= l_tccp->numresolutions) {
opj_event_msg(p_manager, EVT_ERROR,
- "Error decoding component %d.\nThe number of resolutions to remove is higher than the number "
- "of resolutions of this component\nModify the cp_reduce parameter.\n\n",
- compno);
+ "Error decoding component %d.\nThe number of resolutions "
+ "to remove (%d) is greater or equal than the number "
+ "of resolutions of this component (%d)\nModify the cp_reduce parameter.\n\n",
+ compno, l_cp->m_specific_param.m_dec.m_reduce, l_tccp->numresolutions);
p_j2k->m_specific_param.m_decoder.m_state |=
0x8000;/* FIXME J2K_DEC_STATE_ERR;*/
return OPJ_FALSE;
return OPJ_FALSE;
}
+ if (p_image->numcomps < p_j2k->m_private_image->numcomps) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Image has less components than codestream.\n");
+ return OPJ_FALSE;
+ }
+
if (/*(tile_index < 0) &&*/ (tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th)) {
opj_event_msg(p_manager, EVT_ERROR,
"Tile index provided by the user is incorrect %d (max = %d) \n", tile_index,
}
l_img_comp = p_image->comps;
- for (compno = 0; compno < p_image->numcomps; ++compno) {
+ for (compno = 0; compno < p_j2k->m_private_image->numcomps; ++compno) {
OPJ_INT32 l_comp_x1, l_comp_y1;
l_img_comp->factor = p_j2k->m_private_image->comps[compno].factor;
l_img_comp++;
}
+ if (p_image->numcomps > p_j2k->m_private_image->numcomps) {
+ /* Can happen when calling repeatdly opj_get_decoded_tile() on an
+ * image with a color palette, where color palette expansion is done
+ * later in jp2.c */
+ for (compno = p_j2k->m_private_image->numcomps; compno < p_image->numcomps;
+ ++compno) {
+ opj_image_data_free(p_image->comps[compno].data);
+ p_image->comps[compno].data = NULL;
+ }
+ p_image->numcomps = p_j2k->m_private_image->numcomps;
+ }
+
/* Destroy the previous output image*/
if (p_j2k->m_output_image) {
opj_image_destroy(p_j2k->m_output_image);