static void opj_jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color);
+/**
+ * Writes the Channel Definition box.
+ *
+ * @param jp2 jpeg2000 file codec.
+ * @param p_nb_bytes_written pointer to store the nb of bytes written by the function.
+ *
+ * @return the data being copied.
+ */
+static OPJ_BYTE * opj_jp2_write_cdef( opj_jp2_t *jp2,
+ OPJ_UINT32 * p_nb_bytes_written );
+
/**
* Writes the Colour Specification box.
*
return OPJ_TRUE;
}
+static OPJ_BYTE * opj_jp2_write_cdef(opj_jp2_t *jp2, OPJ_UINT32 * p_nb_bytes_written)
+{
+ /* room for 8 bytes for box, 2 for n */
+ OPJ_UINT32 l_cdef_size = 10;
+ OPJ_BYTE * l_cdef_data,* l_current_cdef_ptr;
+ OPJ_UINT32 l_value;
+ OPJ_UINT16 i;
+
+ /* preconditions */
+ assert(jp2 != 00);
+ assert(p_nb_bytes_written != 00);
+ assert(jp2->color.jp2_cdef != 00);
+ assert(jp2->color.jp2_cdef->info != 00);
+ assert(jp2->color.jp2_cdef->n > 0U);
+
+ l_cdef_size += 6 * jp2->color.jp2_cdef->n;
+
+ l_cdef_data = (OPJ_BYTE *) opj_malloc(l_cdef_size);
+ if (l_cdef_data == 00) {
+ return 00;
+ }
+
+ l_current_cdef_ptr = l_cdef_data;
+
+ opj_write_bytes(l_current_cdef_ptr,l_cdef_size,4); /* write box size */
+ l_current_cdef_ptr += 4;
+
+ opj_write_bytes(l_current_cdef_ptr,JP2_CDEF,4); /* BPCC */
+ l_current_cdef_ptr += 4;
+
+ l_value = jp2->color.jp2_cdef->n;
+ opj_write_bytes(l_current_cdef_ptr,l_value,2); /* N */
+ l_current_cdef_ptr += 2;
+
+ for (i = 0U; i < jp2->color.jp2_cdef->n; ++i) {
+ l_value = jp2->color.jp2_cdef->info[i].cn;
+ opj_write_bytes(l_current_cdef_ptr,l_value,2); /* Cni */
+ l_current_cdef_ptr += 2;
+ l_value = jp2->color.jp2_cdef->info[i].typ;
+ opj_write_bytes(l_current_cdef_ptr,l_value,2); /* Typi */
+ l_current_cdef_ptr += 2;
+ l_value = jp2->color.jp2_cdef->info[i].asoc;
+ opj_write_bytes(l_current_cdef_ptr,l_value,2); /* Asoci */
+ l_current_cdef_ptr += 2;
+ }
+ *p_nb_bytes_written = l_cdef_size;
+
+ return l_cdef_data;
+}
OPJ_BYTE * opj_jp2_write_colr( opj_jp2_t *jp2,
OPJ_UINT32 * p_nb_bytes_written
/* room for 8 bytes for box 3 for common data and variable upon profile*/
OPJ_UINT32 l_colr_size = 11;
OPJ_BYTE * l_colr_data,* l_current_colr_ptr;
-
+
/* preconditions */
assert(jp2 != 00);
assert(p_nb_bytes_written != 00);
opj_event_mgr_t * p_manager
)
{
- opj_jp2_img_header_writer_handler_t l_writers [3];
+ opj_jp2_img_header_writer_handler_t l_writers [4];
opj_jp2_img_header_writer_handler_t * l_current_writer;
OPJ_INT32 i, l_nb_pass;
l_writers[1].handler = opj_jp2_write_colr;
}
+ if (jp2->color.jp2_cdef != NULL) {
+ l_writers[l_nb_pass].handler = opj_jp2_write_cdef;
+ l_nb_pass++;
+ }
+
/* write box header */
/* write JP2H type */
opj_write_bytes(l_jp2h_data+4,JP2_JP2H,4);
opj_image_t *image,
opj_event_mgr_t * p_manager)
{
- OPJ_UINT32 i;
+ OPJ_UINT32 i;
OPJ_UINT32 depth_0;
OPJ_UINT32 sign;
+ OPJ_UINT32 alpha_count;
+ OPJ_UINT32 color_channels;
+ OPJ_UINT32 alpha_channel;
+
if(!jp2 || !parameters || !image)
return OPJ_FALSE;
jp2->enumcs = 18; /* YUV */
}
+ /* Channel Definition box */
+ /* FIXME not provided by parameters */
+ /* We try to do what we can... */
+ alpha_count = 0U;
+ for (i = 0; i < image->numcomps; i++) {
+ if (image->comps[i].alpha != 0) {
+ alpha_count++;
+ alpha_channel = i;
+ }
+ }
+ if (alpha_count == 1U) { /* no way to deal with more than 1 alpha channel */
+ switch (jp2->enumcs) {
+ case 16:
+ case 18:
+ color_channels = 3;
+ break;
+ case 17:
+ color_channels = 1;
+ break;
+ default:
+ alpha_count = 0U;
+ break;
+ }
+ if (alpha_count == 0U) {
+ opj_event_msg(p_manager, EVT_WARNING, "Alpha channel specified but unknown enumcs. No cdef box will be created.\n");
+ } else if (image->numcomps < (color_channels+1)) {
+ opj_event_msg(p_manager, EVT_WARNING, "Alpha channel specified but not enough image components for an automatic cdef box creation.\n");
+ alpha_count = 0U;
+ } else if ((OPJ_UINT32)alpha_channel < color_channels) {
+ opj_event_msg(p_manager, EVT_WARNING, "Alpha channel position conflicts with color channel. No cdef box will be created.\n");
+ alpha_count = 0U;
+ }
+ } else if (alpha_count > 1) {
+ opj_event_msg(p_manager, EVT_WARNING, "Multiple alpha channels specified. No cdef box will be created.\n");
+ }
+ if (alpha_count == 1U) { /* if here, we know what we can do */
+ jp2->color.jp2_cdef = (opj_jp2_cdef_t*)opj_malloc(sizeof(opj_jp2_cdef_t));
+ if(!jp2->color.jp2_cdef) {
+ opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup the JP2 encoder\n");
+ return OPJ_FALSE;
+ }
+ /* no memset needed, all values will be overwritten except if jp2->color.jp2_cdef->info allocation fails, */
+ /* in which case jp2->color.jp2_cdef->info will be NULL => valid for destruction */
+ jp2->color.jp2_cdef->info = (opj_jp2_cdef_info_t*) opj_malloc(image->numcomps * sizeof(opj_jp2_cdef_info_t));
+ if (!jp2->color.jp2_cdef->info) {
+ /* memory will be freed by opj_jp2_destroy */
+ opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to setup the JP2 encoder\n");
+ return OPJ_FALSE;
+ }
+ jp2->color.jp2_cdef->n = (OPJ_UINT16) image->numcomps; /* cast is valid : image->numcomps [1,16384] */
+ for (i = 0U; i < color_channels; i++) {
+ jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16)i; /* cast is valid : image->numcomps [1,16384] */
+ jp2->color.jp2_cdef->info[i].typ = 0U;
+ jp2->color.jp2_cdef->info[i].asoc = (OPJ_UINT16)(i+1U); /* No overflow + cast is valid : image->numcomps [1,16384] */
+ }
+ for (; i < image->numcomps; i++) {
+ if (image->comps[i].alpha != 0) { /* we'll be here exactly once */
+ jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16)i; /* cast is valid : image->numcomps [1,16384] */
+ jp2->color.jp2_cdef->info[i].typ = 1U; /* Opacity channel */
+ jp2->color.jp2_cdef->info[i].asoc = 0U; /* Apply alpha channel to the whole image */
+ } else {
+ /* Unknown channel */
+ jp2->color.jp2_cdef->info[i].cn = (OPJ_UINT16)i; /* cast is valid : image->numcomps [1,16384] */
+ jp2->color.jp2_cdef->info[i].typ = 65535U;
+ jp2->color.jp2_cdef->info[i].asoc = 65535U;
+ }
+ }
+ }
jp2->precedence = 0; /* PRECEDENCE */
jp2->approx = 0; /* APPROX */