[trunk] WIP: add a read MCO marker function (JPEG2000 part 2)

This commit is contained in:
Mickael Savinaud 2011-10-12 14:34:17 +00:00
parent f62201ba9d
commit aeabfaf417
2 changed files with 421 additions and 5 deletions

View File

@ -6,8 +6,9 @@ What's New for OpenJPEG
+ : added + : added
October 12, 2011 October 12, 2011
+ [mickael] WIP: add a read MCC marker function (part 2) + [mickael] WIP: add a read MCO marker function (JPEG2000 part 2)
+ [mickael] WIP: add a read MCT marker function (part 2) + [mickael] WIP: add a read MCC marker function (JPEG2000 part 2)
+ [mickael] WIP: add a read MCT marker function (JPEG2000 part 2)
October 11, 2011 October 11, 2011
* [mickael] WIP: correct a segfault inside j2k_dump output * [mickael] WIP: correct a segfault inside j2k_dump output

View File

@ -725,6 +725,38 @@ static opj_bool j2k_read_mcc ( opj_j2k_v2_t *p_j2k,
OPJ_UINT32 p_header_size, OPJ_UINT32 p_header_size,
struct opj_event_mgr * p_manager ); struct opj_event_mgr * p_manager );
/**
* Reads a MCO marker (Multiple Component Transform Ordering)
*
* @param p_header_data the data contained in the MCO box.
* @param p_j2k the jpeg2000 codec.
* @param p_header_size the size of the data contained in the MCO marker.
* @param p_manager the user event manager.
*/
static opj_bool j2k_read_mco ( opj_j2k_v2_t *p_j2k,
OPJ_BYTE * p_header_data,
OPJ_UINT32 p_header_size,
struct opj_event_mgr * p_manager );
static opj_bool j2k_add_mct(opj_tcp_v2_t * p_tcp, opj_image_t * p_image, OPJ_UINT32 p_index);
static void j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_read_int32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_read_float32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_read_float64_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_read_int16_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_read_int32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_read_float32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_read_float64_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
static void j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
/** /**
* Copy the image header from the jpeg2000 codec into an external image_header * Copy the image header from the jpeg2000 codec into an external image_header
* *
@ -772,6 +804,32 @@ const OPJ_UINT32 MCT_ELEMENT_SIZE [] =
8 8
}; };
typedef void (* j2k_mct_function) (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem);
const j2k_mct_function j2k_mct_read_functions_to_float [] =
{
j2k_read_int16_to_float,
j2k_read_int32_to_float,
j2k_read_float32_to_float,
j2k_read_float64_to_float
};
const j2k_mct_function j2k_mct_read_functions_to_int32 [] =
{
j2k_read_int16_to_int32,
j2k_read_int32_to_int32,
j2k_read_float32_to_int32,
j2k_read_float64_to_int32
};
const j2k_mct_function j2k_mct_write_functions_from_float [] =
{
j2k_write_float_to_int16,
j2k_write_float_to_int32,
j2k_write_float_to_float,
j2k_write_float_to_float64
};
typedef struct opj_dec_memory_marker_handler typedef struct opj_dec_memory_marker_handler
{ {
/** marker value */ /** marker value */
@ -830,8 +888,8 @@ const opj_dec_memory_marker_handler_t j2k_memory_marker_handler_tab [] =
{J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_com_v2}, {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_com_v2},
{J2K_MS_MCT, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_mct}, {J2K_MS_MCT, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_mct},
/*FIXME MSD {J2K_MS_CBD, J2K_STATE_MH , j2k_read_cbd}, /*FIXME MSD {J2K_MS_CBD, J2K_STATE_MH , j2k_read_cbd},
*/{J2K_MS_MCC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_mcc},/* */{J2K_MS_MCC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_mcc},
{J2K_MS_MCO, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_mco}, */ {J2K_MS_MCO, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_mco},
#ifdef USE_JPWL #ifdef USE_JPWL
#ifdef TODO_MS /* FIXME */ #ifdef TODO_MS /* FIXME */
{J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc}, {J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc},
@ -849,11 +907,211 @@ const opj_dec_memory_marker_handler_t j2k_memory_marker_handler_tab [] =
void j2k_read_int16_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data;
OPJ_UINT32 i;
OPJ_UINT32 l_temp;
for (i=0;i<p_nb_elem;++i) {
opj_read_bytes(l_src_data,&l_temp,2);
l_src_data+=sizeof(OPJ_INT16);
*(l_dest_data++) = (OPJ_FLOAT32) l_temp;
}
}
void j2k_read_int32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data;
OPJ_UINT32 i;
OPJ_UINT32 l_temp;
for (i=0;i<p_nb_elem;++i) {
opj_read_bytes(l_src_data,&l_temp,4);
l_src_data+=sizeof(OPJ_INT32);
*(l_dest_data++) = (OPJ_FLOAT32) l_temp;
}
}
void j2k_read_float32_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data;
OPJ_UINT32 i;
OPJ_FLOAT32 l_temp;
for (i=0;i<p_nb_elem;++i) {
opj_read_float(l_src_data,&l_temp);
l_src_data+=sizeof(OPJ_FLOAT32);
*(l_dest_data++) = l_temp;
}
}
void j2k_read_float64_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
OPJ_FLOAT32 * l_dest_data = (OPJ_FLOAT32 *) p_dest_data;
OPJ_UINT32 i;
OPJ_FLOAT64 l_temp;
for (i=0;i<p_nb_elem;++i) {
opj_read_double(l_src_data,&l_temp);
l_src_data+=sizeof(OPJ_FLOAT64);
*(l_dest_data++) = (OPJ_FLOAT32) l_temp;
}
}
void j2k_read_int16_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
OPJ_UINT32 i;
OPJ_UINT32 l_temp;
for (i=0;i<p_nb_elem;++i) {
opj_read_bytes(l_src_data,&l_temp,2);
l_src_data+=sizeof(OPJ_INT16);
*(l_dest_data++) = (OPJ_INT32) l_temp;
}
}
void j2k_read_int32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
OPJ_UINT32 i;
OPJ_UINT32 l_temp;
for (i=0;i<p_nb_elem;++i) {
opj_read_bytes(l_src_data,&l_temp,4);
l_src_data+=sizeof(OPJ_INT32);
*(l_dest_data++) = (OPJ_INT32) l_temp;
}
}
void j2k_read_float32_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
OPJ_UINT32 i;
OPJ_FLOAT32 l_temp;
for (i=0;i<p_nb_elem;++i) {
opj_read_float(l_src_data,&l_temp);
l_src_data+=sizeof(OPJ_FLOAT32);
*(l_dest_data++) = (OPJ_INT32) l_temp;
}
}
void j2k_read_float64_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_src_data = (OPJ_BYTE *) p_src_data;
OPJ_INT32 * l_dest_data = (OPJ_INT32 *) p_dest_data;
OPJ_UINT32 i;
OPJ_FLOAT64 l_temp;
for (i=0;i<p_nb_elem;++i) {
opj_read_double(l_src_data,&l_temp);
l_src_data+=sizeof(OPJ_FLOAT64);
*(l_dest_data++) = (OPJ_INT32) l_temp;
}
}
void j2k_write_float_to_int16 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
OPJ_UINT32 i;
OPJ_UINT32 l_temp;
for (i=0;i<p_nb_elem;++i) {
l_temp = (OPJ_UINT32) *(l_src_data++);
opj_write_bytes(l_dest_data,l_temp,sizeof(OPJ_INT16));
l_dest_data+=sizeof(OPJ_INT16);
}
}
void j2k_write_float_to_int32 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
OPJ_UINT32 i;
OPJ_UINT32 l_temp;
for (i=0;i<p_nb_elem;++i) {
l_temp = (OPJ_UINT32) *(l_src_data++);
opj_write_bytes(l_dest_data,l_temp,sizeof(OPJ_INT32));
l_dest_data+=sizeof(OPJ_INT32);
}
}
void j2k_write_float_to_float (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
OPJ_UINT32 i;
OPJ_FLOAT32 l_temp;
for (i=0;i<p_nb_elem;++i) {
l_temp = (OPJ_FLOAT32) *(l_src_data++);
opj_write_float(l_dest_data,l_temp);
l_dest_data+=sizeof(OPJ_FLOAT32);
}
}
void j2k_write_float_to_float64 (const void * p_src_data, void * p_dest_data, OPJ_UINT32 p_nb_elem)
{
OPJ_BYTE * l_dest_data = (OPJ_BYTE *) p_dest_data;
OPJ_FLOAT32 * l_src_data = (OPJ_FLOAT32 *) p_src_data;
OPJ_UINT32 i;
OPJ_FLOAT64 l_temp;
for (i=0;i<p_nb_elem;++i) {
l_temp = (OPJ_FLOAT64) *(l_src_data++);
opj_write_double(l_dest_data,l_temp);
l_dest_data+=sizeof(OPJ_FLOAT64);
}
}
/**
* Converts an enum type progression order to string type.
*
* @param prg_order the progression order to get.
*
* @return the string representation of the given progression order.
*/
char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order){ char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order){
j2k_prog_order_t *po; j2k_prog_order_t *po;
for(po = j2k_prog_order_list; po->enum_prog != -1; po++ ){ for(po = j2k_prog_order_list; po->enum_prog != -1; po++ ){
if(po->enum_prog == prg_order){ if(po->enum_prog == prg_order){
break; return po->str_prog;
} }
} }
return po->str_prog; return po->str_prog;
@ -4394,6 +4652,163 @@ opj_bool j2k_read_mcc ( opj_j2k_v2_t *p_j2k,
return OPJ_TRUE; return OPJ_TRUE;
} }
/**
* Reads a MCO marker (Multiple Component Transform Ordering)
*
* @param p_header_data the data contained in the MCO box.
* @param p_j2k the jpeg2000 codec.
* @param p_header_size the size of the data contained in the MCO marker.
* @param p_manager the user event manager.
*/
opj_bool j2k_read_mco ( opj_j2k_v2_t *p_j2k,
OPJ_BYTE * p_header_data,
OPJ_UINT32 p_header_size,
struct opj_event_mgr * p_manager )
{
OPJ_UINT32 l_tmp, i;
OPJ_UINT32 l_nb_stages;
opj_tcp_v2_t * l_tcp;
opj_tccp_t * l_tccp;
opj_image_t * l_image;
opj_image_comp_t * l_img_comp;
/* preconditions */
assert(p_header_data != 00);
assert(p_j2k != 00);
assert(p_manager != 00);
l_image = p_j2k->m_image;
l_tcp = p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH ?
&p_j2k->m_cp.tcps[p_j2k->m_current_tile_number] :
p_j2k->m_specific_param.m_decoder.m_default_tcp;
if (p_header_size < 1) {
opj_event_msg_v2(p_manager, EVT_ERROR, "Error reading MCO marker\n");
return OPJ_FALSE;
}
opj_read_bytes(p_header_data,&l_nb_stages,1); /* Nmco : only one tranform stage*/
++p_header_data;
if (l_nb_stages > 1) {
opj_event_msg_v2(p_manager, EVT_WARNING, "Cannot take in charge multiple transformation stages.\n");
return OPJ_TRUE;
}
if (p_header_size != l_nb_stages + 1) {
opj_event_msg_v2(p_manager, EVT_WARNING, "Error reading MCO marker\n");
return OPJ_FALSE;
}
l_tccp = l_tcp->tccps;
l_img_comp = l_image->comps;
for (i=0;i<l_image->numcomps;++i) {
l_tccp->m_dc_level_shift = 0;
++l_tccp;
}
if (l_tcp->m_mct_decoding_matrix) {
opj_free(l_tcp->m_mct_decoding_matrix);
l_tcp->m_mct_decoding_matrix = 00;
}
for (i=0;i<l_nb_stages;++i) {
opj_read_bytes(p_header_data,&l_tmp,1);
++p_header_data;
if (! j2k_add_mct(l_tcp,p_j2k->m_image,l_tmp)) {
return OPJ_FALSE;
}
}
return OPJ_TRUE;
}
opj_bool j2k_add_mct(opj_tcp_v2_t * p_tcp, opj_image_t * p_image, OPJ_UINT32 p_index)
{
OPJ_UINT32 i;
opj_simple_mcc_decorrelation_data_t * l_mcc_record;
opj_mct_data_t * l_deco_array, * l_offset_array;
OPJ_UINT32 l_data_size,l_mct_size, l_offset_size;
OPJ_UINT32 l_nb_elem;
OPJ_UINT32 * l_offset_data, * l_current_offset_data;
opj_tccp_t * l_tccp;
/* preconditions */
assert(p_tcp != 00);
l_mcc_record = p_tcp->m_mcc_records;
for (i=0;i<p_tcp->m_nb_mcc_records;++i) {
if (l_mcc_record->m_index == p_index) {
break;
}
}
if (i==p_tcp->m_nb_mcc_records) {
/** element discarded **/
return OPJ_TRUE;
}
if (l_mcc_record->m_nb_comps != p_image->numcomps) {
/** do not support number of comps != image */
return OPJ_TRUE;
}
l_deco_array = l_mcc_record->m_decorrelation_array;
if (l_deco_array) {
l_data_size = MCT_ELEMENT_SIZE[l_deco_array->m_element_type] * p_image->numcomps * p_image->numcomps;
if (l_deco_array->m_data_size != l_data_size) {
return OPJ_FALSE;
}
l_nb_elem = p_image->numcomps * p_image->numcomps;
l_mct_size = l_nb_elem * sizeof(OPJ_FLOAT32);
p_tcp->m_mct_decoding_matrix = (OPJ_FLOAT32*)opj_malloc(l_mct_size);
if (! p_tcp->m_mct_decoding_matrix ) {
return OPJ_FALSE;
}
j2k_mct_read_functions_to_float[l_deco_array->m_element_type](l_deco_array->m_data,p_tcp->m_mct_decoding_matrix,l_nb_elem);
}
l_offset_array = l_mcc_record->m_offset_array;
if (l_offset_array) {
l_data_size = MCT_ELEMENT_SIZE[l_offset_array->m_element_type] * p_image->numcomps;
if (l_offset_array->m_data_size != l_data_size) {
return OPJ_FALSE;
}
l_nb_elem = p_image->numcomps;
l_offset_size = l_nb_elem * sizeof(OPJ_UINT32);
l_offset_data = (OPJ_UINT32*)opj_malloc(l_offset_size);
if (! l_offset_data ) {
return OPJ_FALSE;
}
j2k_mct_read_functions_to_int32[l_offset_array->m_element_type](l_offset_array->m_data,l_offset_data,l_nb_elem);
l_tccp = p_tcp->tccps;
l_current_offset_data = l_offset_data;
for (i=0;i<p_image->numcomps;++i) {
l_tccp->m_dc_level_shift = *(l_current_offset_data++);
++l_tccp;
}
opj_free(l_offset_data);
}
return OPJ_TRUE;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* J2K / JPT decoder interface */ /* J2K / JPT decoder interface */
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */