@param color Collector for profile, cdef and pclr data
@param image
*/
-static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image);
+static void jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color);
/**
Collect palette data
@param jp2 JP2 handle
/**
* Reads a IHDR box - Image Header box
*
- * @param p_image_header_data pointer to actual data (already read from file)
* @param jp2 the jpeg2000 file codec.
+ * @param p_image_header_data pointer to actual data (already read from file)
* @param p_image_header_size the size of the image header
- * @param p_image_header_max_size maximum size of the header, any size bigger than this value should result the function to output false.
* @param p_manager the user event manager.
*
* @return true if the image header is valid, fale else.
/**
* Reads a Bit per Component box.
*
- * @param p_bpc_header_data pointer to actual data (already read from file)
* @param jp2 the jpeg2000 file codec.
+ * @param p_bpc_header_data pointer to actual data (already read from file)
* @param p_bpc_header_size pointer that will hold the size of the bpc header
- * @param p_bpc_header_max_size maximum size of the header, any size bigger than this value should result the function to output false.
* @param p_manager the user event manager.
*
- * @return true if the bpc header is valid, fale else.
+ * @return true if the bpc header is valid, false otherwise.
*/
opj_bool jp2_read_bpcc_v2( opj_jp2_v2_t *jp2,
unsigned char * p_bpc_header_data,
if(color->icc_profile_buf) opj_free(color->icc_profile_buf);
}
-static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image)
+
+static void jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color)
{
opj_image_comp_t *old_comps, *new_comps;
- unsigned char *channel_size, *channel_sign;
- unsigned int *entries;
+ OPJ_BYTE *channel_size, *channel_sign;
+ OPJ_UINT32 *entries;
opj_jp2_cmap_comp_t *cmap;
- int *src, *dst;
- unsigned int j, max;
- unsigned short i, nr_channels, cmp, pcol;
- int k, top_k;
+ OPJ_INT32 *src, *dst;
+ OPJ_UINT32 j, max;
+ OPJ_UINT16 i, nr_channels, cmp, pcol;
+ OPJ_INT32 k, top_k;
channel_size = color->jp2_pclr->channel_size;
channel_sign = color->jp2_pclr->channel_sign;
old_comps = image->comps;
new_comps = (opj_image_comp_t*)
- opj_malloc(nr_channels * sizeof(opj_image_comp_t));
+ opj_malloc(nr_channels * sizeof(opj_image_comp_t));
- for(i = 0; i < nr_channels; ++i)
- {
- pcol = cmap[i].pcol; cmp = cmap[i].cmp;
+ for(i = 0; i < nr_channels; ++i) {
+ pcol = cmap[i].pcol; cmp = cmap[i].cmp;
- new_comps[pcol] = old_comps[cmp];
+ new_comps[pcol] = old_comps[cmp];
+
+ /* Direct use */
+ if(cmap[i].mtyp == 0){
+ old_comps[cmp].data = NULL; continue;
+ }
+
+ /* Palette mapping: */
+ new_comps[pcol].data = (int*)
+ opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int));
+ new_comps[pcol].prec = channel_size[i];
+ new_comps[pcol].sgnd = channel_sign[i];
+ }
- if(cmap[i].mtyp == 0) /* Direct use */
- {
- old_comps[cmp].data = NULL; continue;
- }
-/* Palette mapping: */
- new_comps[pcol].data = (int*)
- opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int));
- new_comps[pcol].prec = channel_size[i];
- new_comps[pcol].sgnd = channel_sign[i];
- }
top_k = color->jp2_pclr->nr_entries - 1;
- for(i = 0; i < nr_channels; ++i)
- {
-/* Direct use: */
- if(cmap[i].mtyp == 0) continue;
+ for(i = 0; i < nr_channels; ++i) {
+ /* Direct use: */
+ if(cmap[i].mtyp == 0) continue;
-/* Palette mapping: */
- cmp = cmap[i].cmp; pcol = cmap[i].pcol;
- src = old_comps[cmp].data;
- dst = new_comps[pcol].data;
- max = new_comps[pcol].w * new_comps[pcol].h;
+ /* Palette mapping: */
+ cmp = cmap[i].cmp; pcol = cmap[i].pcol;
+ src = old_comps[cmp].data;
+ dst = new_comps[pcol].data;
+ max = new_comps[pcol].w * new_comps[pcol].h;
+
+ for(j = 0; j < max; ++j)
+ {
+ /* The index */
+ if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k;
+
+ /* The colour */
+ dst[j] = entries[k * nr_channels + pcol];
+ }
+ }
- for(j = 0; j < max; ++j)
- {
-/* The index */
- if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k;
-/* The colour */
- dst[j] = entries[k * nr_channels + pcol];
- }
- }
max = image->numcomps;
- for(i = 0; i < max; ++i)
- {
- if(old_comps[i].data) opj_free(old_comps[i].data);
- }
+ for(i = 0; i < max; ++i) {
+ if(old_comps[i].data) opj_free(old_comps[i].data);
+ }
+
opj_free(old_comps);
image->comps = new_comps;
image->numcomps = nr_channels;
}/* apply_pclr() */
+
static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio,
opj_jp2_box_t *box, opj_jp2_color_t *color)
{
/**
* Reads a palette box.
*
- * @param p_bpc_header_data pointer to actual data (already read from file)
* @param jp2 the jpeg2000 file codec.
- * @param p_bpc_header_size pointer that will hold the size of the bpc header
- * @param p_bpc_header_max_size maximum size of the header, any size bigger than this value should result the function to output false.
+ * @param p_pclr_header_data pointer to actual data (already read from file)
+ * @param p_pclr_header_size pointer that will hold the size of the PCLR header
* @param p_manager the user event manager.
*
* @return true if the bpc header is valid, fale else.
static void jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
{
opj_jp2_cdef_info_t *info;
- int color_space;
- unsigned short i, n, cn, typ, asoc, acn;
+ OPJ_INT32 color_space;
+ OPJ_UINT16 i, n, cn, typ, asoc, acn;
color_space = image->color_space;
info = color->jp2_cdef->info;
n = color->jp2_cdef->n;
for(i = 0; i < n; ++i)
- {
-/* WATCH: acn = asoc - 1 ! */
- if((asoc = info[i].asoc) == 0) continue;
+ {
+ /* WATCH: acn = asoc - 1 ! */
+ if((asoc = info[i].asoc) == 0) continue;
- cn = info[i].cn; typ = info[i].typ; acn = asoc - 1;
+ cn = info[i].cn; typ = info[i].typ; acn = asoc - 1;
- if(cn != acn)
- {
- opj_image_comp_t saved;
+ if(cn != acn)
+ {
+ opj_image_comp_t saved;
- memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t));
- memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t));
- memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t));
+ memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t));
+ memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t));
+ memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t));
+
+ info[i].asoc = cn + 1;
+ info[acn].asoc = info[acn].cn + 1;
+ }
+ }
- info[i].asoc = cn + 1;
- info[acn].asoc = info[acn].cn + 1;
- }
- }
if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info);
opj_free(color->jp2_cdef); color->jp2_cdef = NULL;
jp2_read_boxhdr(cinfo, cio, &box);
continue;
}
- if(box.type == JP2_CDEF)
+ if(box.type == JP2_CDEF && !jp2->ignore_pclr_cmap_cdef)
{
if( !jp2_read_cdef(jp2, cio, &box, color))
{
jp2_read_boxhdr(cinfo, cio, &box);
continue;
}
- if(box.type == JP2_PCLR)
+ if(box.type == JP2_PCLR && !jp2->ignore_pclr_cmap_cdef)
{
if( !jp2_read_pclr(jp2, cio, &box, color))
{
jp2_read_boxhdr(cinfo, cio, &box);
continue;
}
- if(box.type == JP2_CMAP)
+ if(box.type == JP2_CMAP && !jp2->ignore_pclr_cmap_cdef)
{
if( !jp2_read_cmap(jp2, cio, &box, color))
{
opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n");
return NULL;
}
+
+ if (!jp2->ignore_pclr_cmap_cdef){
-/* Set Image Color Space */
+ /* Set Image Color Space */
if (jp2->enumcs == 16)
image->color_space = CLRSPC_SRGB;
else if (jp2->enumcs == 17)
if( !color.jp2_pclr->cmap)
jp2_free_pclr(&color);
else
- jp2_apply_pclr(&color, image);
+ jp2_apply_pclr(image, &color);
}
if(color.icc_profile_buf)
{
color.icc_profile_buf = NULL;
image->icc_profile_len = color.icc_profile_len;
}
+ }
+
return image;
}/* opj_jp2_decode() */
+opj_bool jp2_decode_v2( opj_jp2_v2_t *jp2,
+ struct opj_stream_private *cio,
+ opj_image_t* p_image,
+ struct opj_event_mgr * p_manager)
+{
+ if (!p_image)
+ return OPJ_FALSE;
+
+ /* J2K decoding */
+ if( ! j2k_decode_v2(jp2->j2k, cio, p_image, p_manager) ) {
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to decode the codestream in the JP2 file\n");
+ return OPJ_FALSE;
+ }
+
+ /* Set Image Color Space */
+ if (jp2->enumcs == 16)
+ p_image->color_space = CLRSPC_SRGB;
+ else if (jp2->enumcs == 17)
+ p_image->color_space = CLRSPC_GRAY;
+ else if (jp2->enumcs == 18)
+ p_image->color_space = CLRSPC_SYCC;
+ else
+ p_image->color_space = CLRSPC_UNKNOWN;
+
+ /* Apply the color space if needed */
+ if(jp2->color.jp2_cdef) {
+ jp2_apply_cdef(p_image, &(jp2->color));
+ }
+
+ if(jp2->color.jp2_pclr) {
+ /* Part 1, I.5.3.4: Either both or none : */
+ if( !jp2->color.jp2_pclr->cmap)
+ jp2_free_pclr(&(jp2->color));
+ else
+ jp2_apply_pclr(p_image, &(jp2->color));
+ }
+
+ if(jp2->color.icc_profile_buf) {
+ p_image->icc_profile_buf = jp2->color.icc_profile_buf;
+ p_image->icc_profile_len = jp2->color.icc_profile_len;
+ jp2->color.icc_profile_buf = NULL;
+ }
+
+ return OPJ_TRUE;
+}
+
void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
opj_jp2_box_t box;
cio_skip( cio, 4); /* L [at the end] */
cio_write( cio, JPIP_FIDX, 4); /* IPTR */
- write_prxy( offset_jp2c, length_jp2c, offset_idx, offset_jp2c, cio);
+ write_prxy( offset_jp2c, length_jp2c, offset_idx, length_idx, cio);
len = cio_tell( cio)-lenp;
cio_seek( cio, lenp);
/* setup the J2K codec */
j2k_setup_decoder(jp2->j2k, parameters);
/* further JP2 initializations go here */
+ jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
}
void jp2_setup_decoder_v2(opj_jp2_v2_t *jp2, opj_dparameters_t *parameters)
opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
- int pos_iptr, pos_cidx, pos_jp2c, len_jp2c, end_pos, pos_fidx, len_fidx;
+ int pos_iptr, pos_cidx, pos_jp2c, len_jp2c, len_cidx, end_pos, pos_fidx, len_fidx;
/* JP2 encoding */
if( jp2->jpip_on){
pos_cidx = cio_tell( cio);
- write_cidx( pos_jp2c+8, cio, image, *cstr_info, len_jp2c-8);
+ len_cidx = write_cidx( pos_jp2c+8, cio, image, *cstr_info, len_jp2c-8);
pos_fidx = cio_tell( cio);
- len_fidx = write_fidx( pos_jp2c, len_jp2c, pos_cidx, cio_tell(cio), cio);
+ len_fidx = write_fidx( pos_jp2c, len_jp2c, pos_cidx, len_cidx, cio);
end_pos = cio_tell( cio);
if (l_current_handler != 00) {
if (l_current_data_size > l_last_data_size) {
l_current_data = (unsigned char*)opj_realloc(l_current_data,l_current_data_size);
+ if (!l_current_data){
+ opj_free(l_current_data);
+ return OPJ_FALSE;
+ }
l_last_data_size = l_current_data_size;
}
*/
opj_bool jp2_read_header( struct opj_stream_private *p_stream,
opj_jp2_v2_t *jp2,
- opj_file_info_t * p_file_info,
+ opj_image_t** p_image,
struct opj_event_mgr * p_manager
)
{
- // preconditions
+ /* preconditions */
assert(jp2 != 00);
assert(p_stream != 00);
assert(p_manager != 00);
return j2k_read_header( p_stream,
jp2->j2k,
- p_file_info,
+ p_image,
p_manager);
}
* @param p_stream the stream to write data to.
* @param p_manager the user event manager.
*/
-opj_bool opj_jp2_decode_tile (
+opj_bool jp2_decode_tile (
opj_jp2_v2_t * p_jp2,
OPJ_UINT32 p_tile_index,
OPJ_BYTE * p_data,
}
if (jp2->color.jp2_cdef) {
+ if (jp2->color.jp2_cdef->info) {
+ opj_free(jp2->color.jp2_cdef->info);
+ jp2->color.jp2_cdef->info = NULL;
+ }
+
opj_free(jp2->color.jp2_cdef);
jp2->color.jp2_cdef = 00;
}
if (jp2->color.jp2_pclr) {
+ if (jp2->color.jp2_pclr->cmap) {
+ opj_free(jp2->color.jp2_pclr->cmap);
+ jp2->color.jp2_pclr->cmap = NULL;
+ }
+ if (jp2->color.jp2_pclr->channel_sign) {
+ opj_free(jp2->color.jp2_pclr->channel_sign);
+ jp2->color.jp2_pclr->channel_sign = NULL;
+ }
+ if (jp2->color.jp2_pclr->channel_size) {
+ opj_free(jp2->color.jp2_pclr->channel_size);
+ jp2->color.jp2_pclr->channel_size = NULL;
+ }
+ if (jp2->color.jp2_pclr->entries) {
+ opj_free(jp2->color.jp2_pclr->entries);
+ jp2->color.jp2_pclr->entries = NULL;
+ }
+
opj_free(jp2->color.jp2_pclr);
jp2->color.jp2_pclr = 00;
}
* @return true if the area could be set.
*/
opj_bool jp2_set_decode_area( opj_jp2_v2_t *p_jp2,
+ opj_image_t* p_image,
OPJ_INT32 p_start_x, OPJ_INT32 p_start_y,
OPJ_INT32 p_end_x, OPJ_INT32 p_end_y,
struct opj_event_mgr * p_manager )
{
- return j2k_set_decode_area(p_jp2->j2k, p_start_x, p_start_y, p_end_x, p_end_y, p_manager);
+ return j2k_set_decode_area(p_jp2->j2k, p_image, p_start_x, p_start_y, p_end_x, p_end_y, p_manager);
}
+/**
+ * Get the decoded tile.
+ *
+ * @param jp2 the jpeg2000 codec.
+ * @param p_stream input_stream
+ * @param p_image output image. .
+ * @param p_manager the user event manager
+ * @param tile_index index of the tile we want decode
+ *
+ * @return true if succeed.
+ */
+opj_bool jp2_get_tile( opj_jp2_v2_t *jp2,
+ opj_stream_private_t *p_stream,
+ opj_image_t* p_image,
+ struct opj_event_mgr * p_manager,
+ OPJ_UINT32 tile_index )
+{
+ if (!p_image)
+ return OPJ_FALSE;
+
+ opj_event_msg_v2(p_manager, EVT_WARNING, "JP2 box which are after the codestream will not be read by this function.\n");
+
+ if (! j2k_get_tile(jp2->j2k, p_stream, p_image, p_manager, tile_index) ){
+ opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to decode the codestream in the JP2 file\n");
+ return OPJ_FALSE;
+ }
+
+ /* Set Image Color Space */
+ if (jp2->enumcs == 16)
+ p_image->color_space = CLRSPC_SRGB;
+ else if (jp2->enumcs == 17)
+ p_image->color_space = CLRSPC_GRAY;
+ else if (jp2->enumcs == 18)
+ p_image->color_space = CLRSPC_SYCC;
+ else
+ p_image->color_space = CLRSPC_UNKNOWN;
+
+ /* Apply the color space if needed */
+ if(jp2->color.jp2_cdef) {
+ jp2_apply_cdef(p_image, &(jp2->color));
+ }
+
+ if(jp2->color.jp2_pclr) {
+ /* Part 1, I.5.3.4: Either both or none : */
+ if( !jp2->color.jp2_pclr->cmap)
+ jp2_free_pclr(&(jp2->color));
+ else
+ jp2_apply_pclr(p_image, &(jp2->color));
+ }
+
+ if(jp2->color.icc_profile_buf) {
+ p_image->icc_profile_buf = jp2->color.icc_profile_buf;
+ p_image->icc_profile_len = jp2->color.icc_profile_len;
+ jp2->color.icc_profile_buf = NULL;
+ }
+
+ return OPJ_TRUE;
+}
+
+
+
/* ----------------------------------------------------------------------- */
/* JP2 encoder interface */
/* ----------------------------------------------------------------------- */
return 00;
}
+ /* Color structure */
+ jp2->color.icc_profile_buf = NULL;
+ jp2->color.icc_profile_len = 0;
+ jp2->color.jp2_cdef = NULL;
+ jp2->color.jp2_pclr = NULL;
+ jp2->color.jp2_has_colr = 0;
+
// validation list creation
jp2->m_validation_list = opj_procedure_list_create();
if (! jp2->m_validation_list) {
return jp2;
}
+
+void jp2_dump(opj_jp2_v2_t* p_jp2, OPJ_INT32 flag, FILE* out_stream)
+{
+ /* preconditions */
+ assert(p_jp2 != 00);
+
+ j2k_dump(p_jp2->j2k,
+ flag,
+ out_stream);
+}
+
+opj_codestream_index_t* jp2_get_cstr_index(opj_jp2_v2_t* p_jp2)
+{
+ return j2k_get_cstr_index(p_jp2->j2k);
+}
+
+opj_codestream_info_v2_t* jp2_get_cstr_info(opj_jp2_v2_t* p_jp2)
+{
+ return j2k_get_cstr_info(p_jp2->j2k);
+}
+
+opj_bool jp2_set_decoded_resolution_factor(opj_jp2_v2_t *p_jp2, OPJ_UINT32 res_factor, opj_event_mgr_t * p_manager)
+{
+ return j2k_set_decoded_resolution_factor(p_jp2->j2k, res_factor, p_manager);
+}
+