[trunk] add a cdef box when alpha component is present (fixes issue 416)
This commit is contained in:
parent
3b7dced8e6
commit
cf5153c518
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -108,6 +108,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.
|
||||
*
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -1617,6 +1682,10 @@ OPJ_BOOL opj_jp2_setup_encoder( opj_jp2_t *jp2,
|
|||
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 */
|
||||
|
|
Loading…
Reference in New Issue