opj_event_mgr_t * p_manager);
static OPJ_BOOL opj_jp2_skip_jp2c(opj_jp2_t *jp2,
- opj_stream_private_t *cio,
+ opj_stream_private_t *stream,
opj_event_mgr_t * p_manager);
/**
/**
Apply collected palette data
-@param color Collector for profile, cdef and pclr data
-@param image
+@param image Image.
+@param color Collector for profile, cdef and pclr data.
+@param p_manager the user event manager.
+@return true in case of success
*/
-static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color);
+static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
+ opj_jp2_color_t *color,
+ opj_event_mgr_t * p_manager);
static void opj_jp2_free_pclr(opj_jp2_color_t *color);
/**
* Sets up the procedures to do on writing header after the codestream.
- * Developpers wanting to extend the library can add their own writing procedures.
+ * Developers wanting to extend the library can add their own writing procedures.
*/
static OPJ_BOOL opj_jp2_setup_end_header_writing(opj_jp2_t *jp2,
opj_event_mgr_t * p_manager);
/**
* Sets up the procedures to do on reading header after the codestream.
- * Developpers wanting to extend the library can add their own writing procedures.
+ * Developers wanting to extend the library can add their own writing procedures.
*/
static OPJ_BOOL opj_jp2_setup_end_header_reading(opj_jp2_t *jp2,
opj_event_mgr_t * p_manager);
opj_event_mgr_t * p_manager);
/**
- * Excutes the given procedures on the given codec.
+ * Executes the given procedures on the given codec.
*
* @param p_procedure_list the list of procedures to execute
* @param jp2 the jpeg2000 file codec to execute the procedures on.
opj_event_mgr_t * p_manager);
/**
- * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
- * are valid. Developpers wanting to extend the library can add their own validation procedures.
+ * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters
+ * are valid. Developers wanting to extend the library can add their own validation procedures.
*/
static OPJ_BOOL opj_jp2_setup_encoding_validation(opj_jp2_t *jp2,
opj_event_mgr_t * p_manager);
/**
- * Sets up the procedures to do on writing header. Developpers wanting to extend the library can add their own writing procedures.
+ * Sets up the procedures to do on writing header. Developers wanting to extend the library can add their own writing procedures.
*/
static OPJ_BOOL opj_jp2_setup_header_writing(opj_jp2_t *jp2,
opj_event_mgr_t * p_manager);
opj_event_mgr_t * p_manager);
/**
- * Sets up the validation ,i.e. adds the procedures to lauch to make sure the codec parameters
- * are valid. Developpers wanting to extend the library can add their own validation procedures.
+ * Sets up the validation ,i.e. adds the procedures to launch to make sure the codec parameters
+ * are valid. Developers wanting to extend the library can add their own validation procedures.
*/
static OPJ_BOOL opj_jp2_setup_decoding_validation(opj_jp2_t *jp2,
opj_event_mgr_t * p_manager);
/**
* Sets up the procedures to do on reading header.
- * Developpers wanting to extend the library can add their own writing procedures.
+ * Developers wanting to extend the library can add their own writing procedures.
*/
static OPJ_BOOL opj_jp2_setup_header_reading(opj_jp2_t *jp2,
opj_event_mgr_t * p_manager);
opj_read_bytes(p_image_header_data, &(jp2->numcomps), 2); /* NC */
p_image_header_data += 2;
+ if (jp2->h < 1 || jp2->w < 1 || jp2->numcomps < 1) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Wrong values for: w(%d) h(%d) numcomps(%d) (ihdr)\n",
+ jp2->w, jp2->h, jp2->numcomps);
+ return OPJ_FALSE;
+ }
if ((jp2->numcomps - 1U) >=
16384U) { /* unsigned underflow is well defined: 1U <= jp2->numcomps <= 16384U */
opj_event_msg(p_manager, EVT_ERROR, "Invalid number of components (ihdr)\n");
opj_read_bytes(p_image_header_data, &(jp2->IPR), 1); /* IPR */
++ p_image_header_data;
+ jp2->j2k->m_cp.allow_different_bit_depth_sign = (jp2->bpc == 255);
+ jp2->j2k->ihdr_w = jp2->w;
+ jp2->j2k->ihdr_h = jp2->h;
+ jp2->has_ihdr = 1;
+
return OPJ_TRUE;
}
}
/* verify that no component is targeted more than once */
for (i = 0; i < nr_channels; i++) {
- OPJ_UINT16 pcol = cmap[i].pcol;
- assert(cmap[i].mtyp == 0 || cmap[i].mtyp == 1);
- if (pcol >= nr_channels) {
+ OPJ_BYTE mtyp = cmap[i].mtyp;
+ OPJ_BYTE pcol = cmap[i].pcol;
+ /* See ISO 15444-1 Table I.14 – MTYPi field values */
+ if (mtyp != 0 && mtyp != 1) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Invalid value for cmap[%d].mtyp = %d.\n", i,
+ mtyp);
+ is_sane = OPJ_FALSE;
+ } else if (pcol >= nr_channels) {
opj_event_msg(p_manager, EVT_ERROR,
"Invalid component/palette index for direct mapping %d.\n", pcol);
is_sane = OPJ_FALSE;
- } else if (pcol_usage[pcol] && cmap[i].mtyp == 1) {
+ } else if (pcol_usage[pcol] && mtyp == 1) {
opj_event_msg(p_manager, EVT_ERROR, "Component %d is mapped twice.\n", pcol);
is_sane = OPJ_FALSE;
- } else if (cmap[i].mtyp == 0 && cmap[i].pcol != 0) {
+ } else if (mtyp == 0 && pcol != 0) {
/* I.5.3.5 PCOL: If the value of the MTYP field for this channel is 0, then
* the value of this field shall be 0. */
opj_event_msg(p_manager, EVT_ERROR, "Direct use at #%d however pcol=%d.\n", i,
pcol);
is_sane = OPJ_FALSE;
+ } else if (mtyp == 1 && pcol != i) {
+ /* OpenJPEG implementation limitation. See assert(i == pcol); */
+ /* in opj_jp2_apply_pclr() */
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Implementation limitation: for palette mapping, "
+ "pcol[%d] should be equal to %d, but is equal "
+ "to %d.\n", i, i, pcol);
+ is_sane = OPJ_FALSE;
} else {
pcol_usage[pcol] = OPJ_TRUE;
}
if (!pcol_usage[i]) {
is_sane = 0U;
opj_event_msg(p_manager, EVT_WARNING,
- "Component mapping seems wrong. Trying to correct.\n", i);
+ "Component mapping seems wrong. Trying to correct.\n");
break;
}
}
}
/* file9.jp2 */
-static void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color)
+static OPJ_BOOL opj_jp2_apply_pclr(opj_image_t *image,
+ opj_jp2_color_t *color,
+ opj_event_mgr_t * p_manager)
{
opj_image_comp_t *old_comps, *new_comps;
OPJ_BYTE *channel_size, *channel_sign;
cmap = color->jp2_pclr->cmap;
nr_channels = color->jp2_pclr->nr_channels;
+ for (i = 0; i < nr_channels; ++i) {
+ /* Palette mapping: */
+ cmp = cmap[i].cmp;
+ if (image->comps[cmp].data == NULL) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "image->comps[%d].data == NULL in opj_jp2_apply_pclr().\n", i);
+ return OPJ_FALSE;
+ }
+ }
+
old_comps = image->comps;
new_comps = (opj_image_comp_t*)
opj_malloc(nr_channels * sizeof(opj_image_comp_t));
if (!new_comps) {
- /* FIXME no error code for opj_jp2_apply_pclr */
- /* FIXME event manager error callback */
- return;
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Memory allocation failure in opj_jp2_apply_pclr().\n");
+ return OPJ_FALSE;
}
for (i = 0; i < nr_channels; ++i) {
pcol = cmap[i].pcol;
/* Palette mapping: */
new_comps[i].data = (OPJ_INT32*)
- opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(OPJ_INT32));
+ opj_image_data_alloc(sizeof(OPJ_INT32) * old_comps[cmp].w * old_comps[cmp].h);
if (!new_comps[i].data) {
+ while (i > 0) {
+ -- i;
+ opj_image_data_free(new_comps[i].data);
+ }
opj_free(new_comps);
- new_comps = NULL;
- /* FIXME no error code for opj_jp2_apply_pclr */
- /* FIXME event manager error callback */
- return;
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Memory allocation failure in opj_jp2_apply_pclr().\n");
+ return OPJ_FALSE;
}
new_comps[i].prec = channel_size[i];
new_comps[i].sgnd = channel_sign[i];
cmp = cmap[i].cmp;
pcol = cmap[i].pcol;
src = old_comps[cmp].data;
- assert(src);
- max = new_comps[pcol].w * new_comps[pcol].h;
+ assert(src); /* verified above */
+ max = new_comps[i].w * new_comps[i].h;
/* Direct use: */
if (cmap[i].mtyp == 0) {
- assert(cmp == 0);
dst = new_comps[i].data;
assert(dst);
for (j = 0; j < max; ++j) {
}
max = image->numcomps;
- for (i = 0; i < max; ++i) {
- if (old_comps[i].data) {
- opj_free(old_comps[i].data);
+ for (j = 0; j < max; ++j) {
+ if (old_comps[j].data) {
+ opj_image_data_free(old_comps[j].data);
}
}
image->comps = new_comps;
image->numcomps = nr_channels;
- opj_jp2_free_pclr(color);
-
+ return OPJ_TRUE;
}/* apply_pclr() */
static OPJ_BOOL opj_jp2_read_pclr(opj_jp2_t *jp2,
return OPJ_FALSE;
}
- entries = (OPJ_UINT32*) opj_malloc((size_t)nr_channels * nr_entries * sizeof(
- OPJ_UINT32));
+ entries = (OPJ_UINT32*) opj_malloc(sizeof(OPJ_UINT32) * nr_channels *
+ nr_entries);
if (!entries) {
return OPJ_FALSE;
}
"COLR BOX meth value is not a regular value (%d), "
"so we will ignore the entire Colour Specification box. \n", jp2->meth);
}
+
return OPJ_TRUE;
}
-OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
- opj_stream_private_t *p_stream,
- opj_image_t* p_image,
- opj_event_mgr_t * p_manager)
+static OPJ_BOOL opj_jp2_apply_color_postprocessing(opj_jp2_t *jp2,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager)
{
- if (!p_image) {
- return OPJ_FALSE;
- }
-
- /* J2K decoding */
- if (! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager)) {
- opj_event_msg(p_manager, EVT_ERROR,
- "Failed to decode the codestream in the JP2 file\n");
- return OPJ_FALSE;
+ if (jp2->j2k->m_specific_param.m_decoder.m_numcomps_to_decode) {
+ /* Bypass all JP2 component transforms */
+ return OPJ_TRUE;
}
if (!jp2->ignore_pclr_cmap_cdef) {
return OPJ_FALSE;
}
- /* Set Image Color Space */
- if (jp2->enumcs == 16) {
- p_image->color_space = OPJ_CLRSPC_SRGB;
- } else if (jp2->enumcs == 17) {
- p_image->color_space = OPJ_CLRSPC_GRAY;
- } else if (jp2->enumcs == 18) {
- p_image->color_space = OPJ_CLRSPC_SYCC;
- } else if (jp2->enumcs == 24) {
- p_image->color_space = OPJ_CLRSPC_EYCC;
- } else if (jp2->enumcs == 12) {
- p_image->color_space = OPJ_CLRSPC_CMYK;
- } else {
- p_image->color_space = OPJ_CLRSPC_UNKNOWN;
- }
-
if (jp2->color.jp2_pclr) {
/* Part 1, I.5.3.4: Either both or none : */
if (!jp2->color.jp2_pclr->cmap) {
opj_jp2_free_pclr(&(jp2->color));
} else {
- opj_jp2_apply_pclr(p_image, &(jp2->color));
+ if (!opj_jp2_apply_pclr(p_image, &(jp2->color), p_manager)) {
+ return OPJ_FALSE;
+ }
}
}
return OPJ_TRUE;
}
+OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ opj_event_mgr_t * p_manager)
+{
+ if (!p_image) {
+ return OPJ_FALSE;
+ }
+
+ /* J2K decoding */
+ if (! opj_j2k_decode(jp2->j2k, p_stream, p_image, p_manager)) {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Failed to decode the codestream in the JP2 file\n");
+ return OPJ_FALSE;
+ }
+
+ return opj_jp2_apply_color_postprocessing(jp2, p_image, p_manager);
+}
+
static OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
opj_stream_private_t *stream,
opj_event_mgr_t * p_manager
OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
}
+void opj_jp2_decoder_set_strict_mode(opj_jp2_t *jp2, OPJ_BOOL strict)
+{
+ opj_j2k_decoder_set_strict_mode(jp2->j2k, strict);
+}
+
OPJ_BOOL opj_jp2_set_threads(opj_jp2_t *jp2, OPJ_UINT32 num_threads)
{
return opj_j2k_set_threads(jp2->j2k, num_threads);
jp2->jp2_state |= JP2_STATE_UNKNOWN;
if (opj_stream_skip(stream, l_current_data_size,
p_manager) != l_current_data_size) {
- opj_event_msg(p_manager, EVT_ERROR,
- "Problem with skipping JPEG2000 box, stream error\n");
- opj_free(l_current_data);
- return OPJ_FALSE;
+ if (jp2->jp2_state & JP2_STATE_CODESTREAM) {
+ /* If we already read the codestream, do not error out */
+ /* Needed for data/input/nonregression/issue254.jp2 */
+ opj_event_msg(p_manager, EVT_WARNING,
+ "Problem with skipping JPEG2000 box, stream error\n");
+ opj_free(l_current_data);
+ return OPJ_TRUE;
+ } else {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Problem with skipping JPEG2000 box, stream error\n");
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
}
}
}
}
/**
- * Excutes the given procedures on the given codec.
+ * Executes the given procedures on the given codec.
*
* @param p_procedure_list the list of procedures to execute
* @param jp2 the jpeg2000 file codec to execute the procedures on.
}
jp2->jp2_state |= JP2_STATE_HEADER;
+ jp2->has_jp2h = 1;
return OPJ_TRUE;
}
opj_event_mgr_t * p_manager
)
{
+ int ret;
+
/* preconditions */
assert(jp2 != 00);
assert(p_stream != 00);
if (! opj_jp2_exec(jp2, jp2->m_procedure_list, p_stream, p_manager)) {
return OPJ_FALSE;
}
+ if (jp2->has_jp2h == 0) {
+ opj_event_msg(p_manager, EVT_ERROR, "JP2H box missing. Required.\n");
+ return OPJ_FALSE;
+ }
+ if (jp2->has_ihdr == 0) {
+ opj_event_msg(p_manager, EVT_ERROR, "IHDR box_missing. Required.\n");
+ return OPJ_FALSE;
+ }
+
+ ret = opj_j2k_read_header(p_stream,
+ jp2->j2k,
+ p_image,
+ p_manager);
- return opj_j2k_read_header(p_stream,
- jp2->j2k,
- p_image,
- p_manager);
+ if (p_image && *p_image) {
+ /* Set Image Color Space */
+ if (jp2->enumcs == 16) {
+ (*p_image)->color_space = OPJ_CLRSPC_SRGB;
+ } else if (jp2->enumcs == 17) {
+ (*p_image)->color_space = OPJ_CLRSPC_GRAY;
+ } else if (jp2->enumcs == 18) {
+ (*p_image)->color_space = OPJ_CLRSPC_SYCC;
+ } else if (jp2->enumcs == 24) {
+ (*p_image)->color_space = OPJ_CLRSPC_EYCC;
+ } else if (jp2->enumcs == 12) {
+ (*p_image)->color_space = OPJ_CLRSPC_CMYK;
+ } else {
+ (*p_image)->color_space = OPJ_CLRSPC_UNKNOWN;
+ }
+ }
+ return ret;
}
static OPJ_BOOL opj_jp2_setup_encoding_validation(opj_jp2_t *jp2,
}
}
+OPJ_BOOL opj_jp2_set_decoded_components(opj_jp2_t *p_jp2,
+ OPJ_UINT32 numcomps,
+ const OPJ_UINT32* comps_indices,
+ opj_event_mgr_t * p_manager)
+{
+ return opj_j2k_set_decoded_components(p_jp2->j2k,
+ numcomps, comps_indices,
+ p_manager);
+}
+
OPJ_BOOL opj_jp2_set_decode_area(opj_jp2_t *p_jp2,
opj_image_t* p_image,
OPJ_INT32 p_start_x, OPJ_INT32 p_start_y,
return OPJ_FALSE;
}
- if (!opj_jp2_check_color(p_image, &(p_jp2->color), p_manager)) {
- return OPJ_FALSE;
- }
-
- /* Set Image Color Space */
- if (p_jp2->enumcs == 16) {
- p_image->color_space = OPJ_CLRSPC_SRGB;
- } else if (p_jp2->enumcs == 17) {
- p_image->color_space = OPJ_CLRSPC_GRAY;
- } else if (p_jp2->enumcs == 18) {
- p_image->color_space = OPJ_CLRSPC_SYCC;
- } else if (p_jp2->enumcs == 24) {
- p_image->color_space = OPJ_CLRSPC_EYCC;
- } else if (p_jp2->enumcs == 12) {
- p_image->color_space = OPJ_CLRSPC_CMYK;
- } else {
- p_image->color_space = OPJ_CLRSPC_UNKNOWN;
- }
-
- if (p_jp2->color.jp2_pclr) {
- /* Part 1, I.5.3.4: Either both or none : */
- if (!p_jp2->color.jp2_pclr->cmap) {
- opj_jp2_free_pclr(&(p_jp2->color));
- } else {
- opj_jp2_apply_pclr(p_image, &(p_jp2->color));
- }
- }
-
- /* Apply the color space if needed */
- if (p_jp2->color.jp2_cdef) {
- opj_jp2_apply_cdef(p_image, &(p_jp2->color), p_manager);
- }
-
- if (p_jp2->color.icc_profile_buf) {
- p_image->icc_profile_buf = p_jp2->color.icc_profile_buf;
- p_image->icc_profile_len = p_jp2->color.icc_profile_len;
- p_jp2->color.icc_profile_buf = NULL;
- }
-
- return OPJ_TRUE;
+ return opj_jp2_apply_color_postprocessing(p_jp2, p_image, p_manager);
}
/* ----------------------------------------------------------------------- */
return opj_j2k_set_decoded_resolution_factor(p_jp2->j2k, res_factor, p_manager);
}
+/* ----------------------------------------------------------------------- */
+
+OPJ_BOOL opj_jp2_encoder_set_extra_options(
+ opj_jp2_t *p_jp2,
+ const char* const* p_options,
+ opj_event_mgr_t * p_manager)
+{
+ return opj_j2k_encoder_set_extra_options(p_jp2->j2k, p_options, p_manager);
+}
+
+/* ----------------------------------------------------------------------- */
+
/* JPIP specific */
#ifdef USE_JPIP
OPJ_OFF_T j2k_codestream_exit;
OPJ_BYTE l_data_header [24];
+ OPJ_UNUSED(jp2);
+
/* preconditions */
assert(jp2 != 00);
assert(cio != 00);
OPJ_OFF_T j2k_codestream_exit;
OPJ_BYTE l_data_header [24];
+ OPJ_UNUSED(jp2);
+
/* preconditions */
assert(jp2 != 00);
assert(cio != 00);