summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAntonin Descampe <antonin@gmail.com>2014-11-03 14:12:01 +0000
committerAntonin Descampe <antonin@gmail.com>2014-11-03 14:12:01 +0000
commitcf5153c518045027f286e08af36809237a76a7df (patch)
treeb099fbd31bf15f254addb20036e78c3e0bdd12bd /src
parent3b7dced8e66418ab90c1f7398fc36453e834f4dc (diff)
[trunk] add a cdef box when alpha component is present (fixes issue 416)
Diffstat (limited to 'src')
-rw-r--r--src/bin/jp2/convert.c5
-rw-r--r--src/lib/openjp2/jp2.c143
2 files changed, 144 insertions, 4 deletions
diff --git a/src/bin/jp2/convert.c b/src/bin/jp2/convert.c
index 606238d1..6af7b7ab 100644
--- a/src/bin/jp2/convert.c
+++ b/src/bin/jp2/convert.c
@@ -3364,7 +3364,10 @@ opj_image_t *pngtoimage(const char *read_idf, opj_cparameters_t * params)
r = image->comps[0].data;
g = image->comps[1].data;
b = image->comps[2].data;
- if(has_alpha) a = image->comps[3].data;
+ if(has_alpha) {
+ a = image->comps[3].data;
+ image->comps[3].alpha = 1;
+ }
for(i = 0; i < height; ++i)
{
diff --git a/src/lib/openjp2/jp2.c b/src/lib/openjp2/jp2.c
index bce8813c..219278fe 100644
--- a/src/lib/openjp2/jp2.c
+++ b/src/lib/openjp2/jp2.c
@@ -109,6 +109,17 @@ static OPJ_BOOL opj_jp2_read_cdef( opj_jp2_t * jp2,
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.
*
* @param jp2 jpeg2000 file codec.
@@ -680,6 +691,55 @@ OPJ_BOOL opj_jp2_read_bpcc( opj_jp2_t *jp2,
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
@@ -688,7 +748,7 @@ OPJ_BYTE * opj_jp2_write_colr( opj_jp2_t *jp2,
/* 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);
@@ -1385,7 +1445,7 @@ OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
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;
@@ -1415,6 +1475,11 @@ OPJ_BOOL opj_jp2_write_jp2h(opj_jp2_t *jp2,
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);
@@ -1614,9 +1679,13 @@ OPJ_BOOL opj_jp2_setup_encoder( opj_jp2_t *jp2,
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;
@@ -1697,6 +1766,74 @@ OPJ_BOOL opj_jp2_setup_encoder( opj_jp2_t *jp2,
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 */