* Copyright (c) 2002-2003, Yannick Verschueren
* Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
* Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2010-2011, Kaori Hagihara
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@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_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo);
/**
Collect palette data
@param jp2 JP2 handle
*/
static opj_bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio,
opj_jp2_box_t *box, opj_jp2_color_t *color);
+/**
+Write file Index (superbox)
+@param[in] offset_jp2c offset of jp2c box
+@param[in] length_jp2c length of jp2c box
+@param[in] offset_idx offset of cidx box
+@param[in] length_idx length of cidx box
+@param[in] cio file output handle
+@return length of fidx box
+*/
+static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio);
+/**
+Write index Finder box
+@param[in] offset offset of fidx box
+@param[in] length length of fidx box
+@param[in] cio file output handle
+*/
+static void write_iptr( int offset, int length, opj_cio_t *cio);
+/**
+Write proxy box
+@param[in] offset_jp2c offset of jp2c box
+@param[in] length_jp2c length of jp2c box
+@param[in] offset_idx offset of cidx box
+@param[in] length_idx length of cidx box
+@param[in] cio file output handle
+*/
+static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio);
/*@}*/
/*@}*/
opj_common_ptr cinfo = jp2->cinfo;
- jp2_read_boxhdr(cinfo, cio, &box);
+ if(jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+ opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+ return OPJ_FALSE;
+ }
if (JP2_IHDR != box.type) {
opj_event_msg(cinfo, EVT_ERROR, "Expected IHDR Marker\n");
return OPJ_FALSE;
opj_common_ptr cinfo = jp2->cinfo;
- jp2_read_boxhdr(cinfo, cio, &box);
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+ opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+ return OPJ_FALSE;
+ }
if (JP2_BPCC != box.type) {
opj_event_msg(cinfo, EVT_ERROR, "Expected BPCC Marker\n");
return OPJ_FALSE;
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_jp2_color_t *color, opj_image_t *image, opj_common_ptr cinfo)
{
opj_image_comp_t *old_comps, *new_comps;
unsigned char *channel_size, *channel_sign;
{
pcol = cmap[i].pcol; cmp = cmap[i].cmp;
- new_comps[pcol] = old_comps[cmp];
+ if( pcol < nr_channels )
+ new_comps[pcol] = old_comps[cmp];
+ else
+ {
+ opj_event_msg(cinfo, EVT_ERROR, "Error with pcol value %d (max: %d). skipping\n", pcol, nr_channels);
+ continue;
+ }
if(cmap[i].mtyp == 0) /* Direct use */
{
for(i = 0; i < nr_channels; ++i)
{
/* Cji */
- *entries++ = cio_read(cio, channel_size[i]>>3);
+ *entries++ = cio_read(cio, (channel_size[i]+7)>>3);
}
}
opj_common_ptr cinfo = jp2->cinfo;
- jp2_read_boxhdr(cinfo, cio, &box);
- do
- {
- if (JP2_JP2H != box.type)
- {
- if (box.type == JP2_JP2C)
- {
- opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n");
- return OPJ_FALSE;
- }
- cio_skip(cio, box.length - 8);
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+ do {
+ if (JP2_JP2H != box.type)
+ {
+ if (box.type == JP2_JP2C)
+ {
+ opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n");
+ return OPJ_FALSE;
+ }
+ cio_skip(cio, box.length - 8);
- if(cio->bp >= cio->end) return OPJ_FALSE;
+ if(cio->bp >= cio->end) return OPJ_FALSE;
- jp2_read_boxhdr(cinfo, cio, &box);
- }
- } while(JP2_JP2H != box.type);
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+ }
+ } while(JP2_JP2H != box.type);
if (!jp2_read_ihdr(jp2, cio))
return OPJ_FALSE;
jp2h_end = box.init_pos + box.length;
- if (jp2->bpc == 255)
- {
- if (!jp2_read_bpcc(jp2, cio))
- return OPJ_FALSE;
- }
- jp2_read_boxhdr(cinfo, cio, &box);
-
- while(cio_tell(cio) < jp2h_end)
- {
- if(box.type == JP2_COLR)
- {
- if( !jp2_read_colr(jp2, cio, &box, color))
- {
- cio_seek(cio, box.init_pos + 8);
- cio_skip(cio, box.length - 8);
- }
- jp2_read_boxhdr(cinfo, cio, &box);
- continue;
- }
- if(box.type == JP2_CDEF)
- {
- if( !jp2_read_cdef(jp2, cio, &box, color))
- {
- cio_seek(cio, box.init_pos + 8);
- cio_skip(cio, box.length - 8);
- }
- jp2_read_boxhdr(cinfo, cio, &box);
- continue;
- }
- if(box.type == JP2_PCLR)
- {
- if( !jp2_read_pclr(jp2, cio, &box, color))
- {
- cio_seek(cio, box.init_pos + 8);
- cio_skip(cio, box.length - 8);
- }
- jp2_read_boxhdr(cinfo, cio, &box);
- continue;
- }
- if(box.type == JP2_CMAP)
- {
- if( !jp2_read_cmap(jp2, cio, &box, color))
- {
+ if (jp2->bpc == 255)
+ {
+ if (!jp2_read_bpcc(jp2, cio))
+ return OPJ_FALSE;
+ }
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+
+ while(cio_tell(cio) < jp2h_end)
+ {
+ if(box.type == JP2_COLR)
+ {
+ if( !jp2_read_colr(jp2, cio, &box, color))
+ {
+ cio_seek(cio, box.init_pos + 8);
+ cio_skip(cio, box.length - 8);
+ }
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+ continue;
+ }
+ if(box.type == JP2_CDEF && !jp2->ignore_pclr_cmap_cdef)
+ {
+ if( !jp2_read_cdef(jp2, cio, &box, color))
+ {
+ cio_seek(cio, box.init_pos + 8);
+ cio_skip(cio, box.length - 8);
+ }
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+ continue;
+ }
+ if(box.type == JP2_PCLR && !jp2->ignore_pclr_cmap_cdef)
+ {
+ if( !jp2_read_pclr(jp2, cio, &box, color))
+ {
+ cio_seek(cio, box.init_pos + 8);
+ cio_skip(cio, box.length - 8);
+ }
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+ continue;
+ }
+ if(box.type == JP2_CMAP && !jp2->ignore_pclr_cmap_cdef)
+ {
+ if( !jp2_read_cmap(jp2, cio, &box, color))
+ {
+ cio_seek(cio, box.init_pos + 8);
+ cio_skip(cio, box.length - 8);
+ }
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
+ continue;
+ }
cio_seek(cio, box.init_pos + 8);
cio_skip(cio, box.length - 8);
- }
- jp2_read_boxhdr(cinfo, cio, &box);
- continue;
- }
- cio_seek(cio, box.init_pos + 8);
- cio_skip(cio, box.length - 8);
- jp2_read_boxhdr(cinfo, cio, &box);
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
- }/* while(cio_tell(cio) < box_end) */
+ }/* while(cio_tell(cio) < box_end) */
- cio_seek(cio, jp2h_end);
+ cio_seek(cio, jp2h_end);
-/* Part 1, I.5.3.3 : 'must contain at least one' */
- return (color->jp2_has_colr == 1);
+ /* Part 1, I.5.3.3 : 'must contain at least one' */
+ return (color->jp2_has_colr == 1);
}/* jp2_read_jp2h() */
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(&color, image, cinfo);
}
if(color.icc_profile_buf)
{
color.icc_profile_buf = NULL;
image->icc_profile_len = color.icc_profile_len;
}
+ }
+
return image;
}/* opj_jp2_decode() */
opj_common_ptr cinfo = jp2->cinfo;
- jp2_read_boxhdr(cinfo, cio, &box);
-
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+ opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+ return OPJ_FALSE;
+ }
if (JP2_FTYP != box.type) {
opj_event_msg(cinfo, EVT_ERROR, "Expected FTYP Marker\n");
return OPJ_FALSE;
opj_common_ptr cinfo = jp2->cinfo;
- jp2_read_boxhdr(cinfo, cio, &box);
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+ opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+ return OPJ_FALSE;
+ }
do {
if(JP2_JP2C != box.type) {
cio_skip(cio, box.length - 8);
- jp2_read_boxhdr(cinfo, cio, &box);
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) return OPJ_FALSE;
}
} while(JP2_JP2C != box.type);
opj_common_ptr cinfo = jp2->cinfo;
- jp2_read_boxhdr(cinfo, cio, &box);
+ if( jp2_read_boxhdr(cinfo, cio, &box) == OPJ_FALSE ) {
+ opj_event_msg(cinfo, EVT_ERROR, "Failed to read boxhdr\n");
+ return OPJ_FALSE;
+ }
if (JP2_JP != box.type) {
opj_event_msg(cinfo, EVT_ERROR, "Expected JP Marker\n");
return OPJ_FALSE;
return OPJ_TRUE;
}
+
+static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio)
+{
+ int len, lenp;
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_FIDX, 4); /* IPTR */
+
+ write_prxy( offset_jp2c, length_jp2c, offset_idx, length_idx, cio);
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+
+ return len;
+}
+
+static void write_prxy( int offset_jp2c, int length_jp2c, int offset_idx, int length_idx, opj_cio_t *cio)
+{
+ int len, lenp;
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_PRXY, 4); /* IPTR */
+
+ cio_write( cio, offset_jp2c, 8); /* OOFF */
+ cio_write( cio, length_jp2c, 4); /* OBH part 1 */
+ cio_write( cio, JP2_JP2C, 4); /* OBH part 2 */
+
+ cio_write( cio, 1,1); /* NI */
+
+ cio_write( cio, offset_idx, 8); /* IOFF */
+ cio_write( cio, length_idx, 4); /* IBH part 1 */
+ cio_write( cio, JPIP_CIDX, 4); /* IBH part 2 */
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+}
+
+static void write_iptr( int offset, int length, opj_cio_t *cio)
+{
+ int len, lenp;
+
+ lenp = cio_tell( cio);
+ cio_skip( cio, 4); /* L [at the end] */
+ cio_write( cio, JPIP_IPTR, 4); /* IPTR */
+
+ cio_write( cio, offset, 8);
+ cio_write( cio, length, 8);
+
+ len = cio_tell( cio)-lenp;
+ cio_seek( cio, lenp);
+ cio_write( cio, len, 4); /* L */
+ cio_seek( cio, lenp+len);
+}
+
+
/* ----------------------------------------------------------------------- */
/* JP2 decoder interface */
/* ----------------------------------------------------------------------- */
/* 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;
}
/* ----------------------------------------------------------------------- */
jp2->enumcs = 18; /* YUV */
jp2->precedence = 0; /* PRECEDENCE */
jp2->approx = 0; /* APPROX */
-
+
+ jp2->jpip_on = parameters->jpip_on;
}
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, len_cidx, end_pos, pos_fidx, len_fidx;
+ pos_jp2c = pos_iptr = -1; /* remove a warning */
+
/* JP2 encoding */
/* JPEG 2000 Signature box */
/* JP2 Header box */
jp2_write_jp2h(jp2, cio);
+ if( jp2->jpip_on){
+ pos_iptr = cio_tell( cio);
+ cio_skip( cio, 24); /* IPTR further ! */
+
+ pos_jp2c = cio_tell( cio);
+ }
+
/* J2K encoding */
+ if(!(len_jp2c = jp2_write_jp2c( jp2, cio, image, cstr_info))){
+ opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n");
+ return OPJ_FALSE;
+ }
- if(!jp2_write_jp2c(jp2, cio, image, cstr_info)) {
- opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n");
- return OPJ_FALSE;
+ if( jp2->jpip_on){
+ pos_cidx = cio_tell( cio);
+
+ 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, len_cidx, cio);
+
+ end_pos = cio_tell( cio);
+
+ cio_seek( cio, pos_iptr);
+ write_iptr( pos_fidx, len_fidx, cio);
+
+ cio_seek( cio, end_pos);
}
return OPJ_TRUE;
}
-
-