[trunk] WIP: add get_decoded_tile functionality

This commit is contained in:
Mickael Savinaud 2011-11-08 13:21:17 +00:00
parent 9110aa09a4
commit bd8bca87b2
9 changed files with 427 additions and 134 deletions

View File

@ -6,6 +6,7 @@ What's New for OpenJPEG
+ : added + : added
November 8, 2011 November 8, 2011
+ [mickael] WIP: add get_decoded_tile functionality
+ [mickael] WIP: clean and enhance j2K file + [mickael] WIP: clean and enhance j2K file
+ [mickael] WIP: clean and enhance openjpeg.c + [mickael] WIP: clean and enhance openjpeg.c
+ [mickael] WIP: clean and enhance openjpeg.h and add deprecated macro + [mickael] WIP: clean and enhance openjpeg.h and add deprecated macro

View File

@ -525,77 +525,6 @@ int main(int argc, char *argv[])
cstr_index = opj_get_cstr_index(dinfo); cstr_index = opj_get_cstr_index(dinfo);
#ifdef MSD
fprintf(stdout,"Setting decoding area to %d,%d,%d,%d\n",
parameters.DA_x0, parameters.DA_y0, parameters.DA_x1, parameters.DA_y1);
/* FIXME WIP_MSD <*/
if (! opj_set_decode_area( dinfo,
parameters.DA_x0, parameters.DA_y0,
parameters.DA_x1, parameters.DA_y1)){
fprintf(stderr, "ERROR -> j2k_dump: failed to set the decoded area\n");
opj_stream_destroy(cio);
opj_destroy_codec(dinfo);
fclose(fsrc);
fclose(fout);
return EXIT_FAILURE;
}
while (l_go_on) {
OPJ_INT32 l_current_tile_x0,l_current_tile_y0,l_current_tile_x1,l_current_tile_y1;
OPJ_UINT32 l_nb_comps, l_tile_index, l_data_size;
if (! opj_read_tile_header( dinfo,
cio,
&l_tile_index,
&l_data_size,
&l_current_tile_x0,
&l_current_tile_y0,
&l_current_tile_x1,
&l_current_tile_y1,
&l_nb_comps,
&l_go_on
)) {
fprintf(stderr, "ERROR -> j2k_dump: failed read the tile header\n");
opj_stream_destroy(cio);
fclose(fsrc);
opj_destroy_codec(dinfo);
return EXIT_FAILURE;
}
if (l_go_on) {
if (l_data_size > l_max_data_size) {
l_data = (OPJ_BYTE *) realloc(l_data,l_data_size);
if (! l_data) {
opj_stream_destroy(cio);
opj_destroy_codec(dinfo);
fclose(fsrc);
fclose(fout);
return EXIT_FAILURE;
}
l_max_data_size = l_data_size;
}
if (! opj_decode_tile_data(dinfo,l_tile_index,l_data,l_data_size,cio))
{
free(l_data);
opj_stream_destroy(cio);
opj_destroy_codec(dinfo);
fclose(fsrc);
fclose(fout);
return EXIT_FAILURE;
}
/** now should inspect image to know the reduction factor and then how to behave with data */
}
}
/* FIXME WIP_MSD >*/
#endif
/* close the byte stream */ /* close the byte stream */
opj_stream_destroy(cio); opj_stream_destroy(cio);
fclose(fsrc); fclose(fsrc);

View File

@ -524,9 +524,7 @@ OPJ_API void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream
OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_UINT32 p_size, opj_event_mgr_t * p_event_mgr) OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_UINT32 p_size, opj_event_mgr_t * p_event_mgr)
{ {
OPJ_UINT32 l_read_nb_bytes = 0; OPJ_UINT32 l_read_nb_bytes = 0;
if if (p_stream->m_bytes_in_buffer >= p_size) {
(p_stream->m_bytes_in_buffer >= p_size)
{
memcpy(p_buffer,p_stream->m_current_data,p_size); memcpy(p_buffer,p_stream->m_current_data,p_size);
p_stream->m_current_data += p_size; p_stream->m_current_data += p_size;
p_stream->m_bytes_in_buffer -= p_size; p_stream->m_bytes_in_buffer -= p_size;
@ -535,10 +533,8 @@ OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_bu
return l_read_nb_bytes; return l_read_nb_bytes;
} }
// we are now in the case when the remaining data if not sufficient /* we are now in the case when the remaining data if not sufficient */
if if (p_stream->m_status & opj_stream_e_end) {
(p_stream->m_status & opj_stream_e_end)
{
l_read_nb_bytes += p_stream->m_bytes_in_buffer; l_read_nb_bytes += p_stream->m_bytes_in_buffer;
memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer); memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
p_stream->m_current_data += p_stream->m_bytes_in_buffer; p_stream->m_current_data += p_stream->m_bytes_in_buffer;
@ -547,10 +543,8 @@ OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_bu
return l_read_nb_bytes ? l_read_nb_bytes : -1; return l_read_nb_bytes ? l_read_nb_bytes : -1;
} }
// the flag is not set, we copy data and then do an actual read on the stream /* the flag is not set, we copy data and then do an actual read on the stream */
if if (p_stream->m_bytes_in_buffer) {
(p_stream->m_bytes_in_buffer)
{
l_read_nb_bytes += p_stream->m_bytes_in_buffer; l_read_nb_bytes += p_stream->m_bytes_in_buffer;
memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer); memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
p_stream->m_current_data = p_stream->m_stored_data; p_stream->m_current_data = p_stream->m_stored_data;
@ -559,8 +553,7 @@ OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_bu
p_stream->m_byte_offset += p_stream->m_bytes_in_buffer; p_stream->m_byte_offset += p_stream->m_bytes_in_buffer;
p_stream->m_bytes_in_buffer = 0; p_stream->m_bytes_in_buffer = 0;
} }
else else {
{
/* case where we are already at the end of the buffer /* case where we are already at the end of the buffer
so reset the m_current_data to point to the start of the so reset the m_current_data to point to the start of the
stored buffer to get ready to read from disk*/ stored buffer to get ready to read from disk*/
@ -569,27 +562,22 @@ OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_bu
while(1){ while(1){
// we should read less than a chunk -> read a chunk /* we should read less than a chunk -> read a chunk */
if if (p_size < p_stream->m_buffer_size) {
(p_size < p_stream->m_buffer_size) /* we should do an actual read on the media */
{
// we should do an actual read on the media
p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_stream->m_stored_data,p_stream->m_buffer_size,p_stream->m_user_data); p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_stream->m_stored_data,p_stream->m_buffer_size,p_stream->m_user_data);
if
(p_stream->m_bytes_in_buffer == -1) if (p_stream->m_bytes_in_buffer == -1) {
{ /* end of stream */
// end of stream
opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
p_stream->m_bytes_in_buffer = 0; p_stream->m_bytes_in_buffer = 0;
p_stream->m_status |= opj_stream_e_end; p_stream->m_status |= opj_stream_e_end;
// end of stream /* end of stream */
return l_read_nb_bytes ? l_read_nb_bytes : -1; return l_read_nb_bytes ? l_read_nb_bytes : -1;
} }
else if else if (p_stream->m_bytes_in_buffer < p_size) {
(p_stream->m_bytes_in_buffer < p_size) /* not enough data */
{
// not enough data
l_read_nb_bytes += p_stream->m_bytes_in_buffer; l_read_nb_bytes += p_stream->m_bytes_in_buffer;
memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer); memcpy(p_buffer,p_stream->m_current_data,p_stream->m_bytes_in_buffer);
p_stream->m_current_data = p_stream->m_stored_data; p_stream->m_current_data = p_stream->m_stored_data;
@ -598,8 +586,7 @@ OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_bu
p_stream->m_byte_offset += p_stream->m_bytes_in_buffer; p_stream->m_byte_offset += p_stream->m_bytes_in_buffer;
p_stream->m_bytes_in_buffer = 0; p_stream->m_bytes_in_buffer = 0;
} }
else else {
{
l_read_nb_bytes += p_size; l_read_nb_bytes += p_size;
memcpy(p_buffer,p_stream->m_current_data,p_size); memcpy(p_buffer,p_stream->m_current_data,p_size);
p_stream->m_current_data += p_size; p_stream->m_current_data += p_size;
@ -608,25 +595,21 @@ OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_bu
return l_read_nb_bytes; return l_read_nb_bytes;
} }
} }
else else {
{ /* direct read on the dest buffer */
// direct read on the dest buffer
p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer,p_size,p_stream->m_user_data); p_stream->m_bytes_in_buffer = p_stream->m_read_fn(p_buffer,p_size,p_stream->m_user_data);
if
(p_stream->m_bytes_in_buffer == -1) if (p_stream->m_bytes_in_buffer == -1) {
{ /* end of stream */
// end of stream
opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
p_stream->m_bytes_in_buffer = 0; p_stream->m_bytes_in_buffer = 0;
p_stream->m_status |= opj_stream_e_end; p_stream->m_status |= opj_stream_e_end;
// end of stream /* end of stream */
return l_read_nb_bytes ? l_read_nb_bytes : -1; return l_read_nb_bytes ? l_read_nb_bytes : -1;
} }
else if else if (p_stream->m_bytes_in_buffer < p_size) {
(p_stream->m_bytes_in_buffer < p_size) /* not enough data */
{
// not enough data
l_read_nb_bytes += p_stream->m_bytes_in_buffer; l_read_nb_bytes += p_stream->m_bytes_in_buffer;
p_stream->m_current_data = p_stream->m_stored_data; p_stream->m_current_data = p_stream->m_stored_data;
p_buffer += p_stream->m_bytes_in_buffer; p_buffer += p_stream->m_bytes_in_buffer;
@ -634,9 +617,8 @@ OPJ_UINT32 opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_bu
p_stream->m_byte_offset += p_stream->m_bytes_in_buffer; p_stream->m_byte_offset += p_stream->m_bytes_in_buffer;
p_stream->m_bytes_in_buffer = 0; p_stream->m_bytes_in_buffer = 0;
} }
else else {
{ /* we have read the exact size */
// we have read the exact size
l_read_nb_bytes += p_stream->m_bytes_in_buffer; l_read_nb_bytes += p_stream->m_bytes_in_buffer;
p_stream->m_byte_offset += p_stream->m_bytes_in_buffer; p_stream->m_byte_offset += p_stream->m_bytes_in_buffer;
p_stream->m_current_data = p_stream->m_stored_data; p_stream->m_current_data = p_stream->m_stored_data;
@ -903,19 +885,18 @@ opj_bool opj_stream_read_seek (opj_stream_private_t * p_stream, OPJ_SIZE_T p_siz
{ {
p_stream->m_current_data = p_stream->m_stored_data; p_stream->m_current_data = p_stream->m_stored_data;
p_stream->m_bytes_in_buffer = 0; p_stream->m_bytes_in_buffer = 0;
if
(! p_stream->m_seek_fn(p_size,p_stream->m_user_data)) if( p_stream->m_seek_fn(p_size,p_stream->m_user_data)) {
{
p_stream->m_status |= opj_stream_e_end; p_stream->m_status |= opj_stream_e_end;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
else else {
{
// reset stream status // reset stream status
p_stream->m_status &= (~opj_stream_e_end); p_stream->m_status &= (~opj_stream_e_end);
p_stream->m_byte_offset = p_size; p_stream->m_byte_offset = p_size;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -3687,12 +3687,17 @@ opj_bool j2k_read_sot_v2 (
p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPH; p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPH;
/* Check if the current tile is outside the area we want decode (in tile index)*/ /* Check if the current tile is outside the area we want decode or not corresponding to the tile index*/
if (p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec == -1) {
p_j2k->m_specific_param.m_decoder.m_skip_data = p_j2k->m_specific_param.m_decoder.m_skip_data =
(l_tile_x < p_j2k->m_specific_param.m_decoder.m_start_tile_x) (l_tile_x < p_j2k->m_specific_param.m_decoder.m_start_tile_x)
|| (l_tile_x >= p_j2k->m_specific_param.m_decoder.m_end_tile_x) || (l_tile_x >= p_j2k->m_specific_param.m_decoder.m_end_tile_x)
|| (l_tile_y < p_j2k->m_specific_param.m_decoder.m_start_tile_y) || (l_tile_y < p_j2k->m_specific_param.m_decoder.m_start_tile_y)
|| (l_tile_y >= p_j2k->m_specific_param.m_decoder.m_end_tile_y); || (l_tile_y >= p_j2k->m_specific_param.m_decoder.m_end_tile_y);
}
else
p_j2k->m_specific_param.m_decoder.m_skip_data =
(p_j2k->m_current_tile_number != p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec);
/* Index */ /* Index */
if (p_j2k->cstr_index) if (p_j2k->cstr_index)
@ -6636,9 +6641,6 @@ opj_bool j2k_read_tile_header( opj_j2k_v2_t * p_j2k,
return OPJ_FALSE; return OPJ_FALSE;
} }
/* if (l_current_marker == J2K_MS_SOT)
j2k_add_tlmarker();*/
/* Add the marker to the codestream index*/ /* Add the marker to the codestream index*/
j2k_add_tlmarker_v2(p_j2k->m_current_tile_number, j2k_add_tlmarker_v2(p_j2k->m_current_tile_number,
p_j2k->cstr_index, p_j2k->cstr_index,
@ -6646,6 +6648,16 @@ opj_bool j2k_read_tile_header( opj_j2k_v2_t * p_j2k,
(OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4, (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4,
l_marker_size + 4 ); l_marker_size + 4 );
/* Keep the position of the last SOT marker read */
if ( l_marker_handler->id == J2K_MS_SOT ) {
OPJ_UINT32 sot_pos = (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4 ;
if (sot_pos > p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos)
{
p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = sot_pos;
}
}
if (p_j2k->m_specific_param.m_decoder.m_skip_data) { if (p_j2k->m_specific_param.m_decoder.m_skip_data) {
/* Skip the rest of the tile part header*/ /* Skip the rest of the tile part header*/
if (opj_stream_skip(p_stream,p_j2k->m_specific_param.m_decoder.m_sot_length,p_manager) != p_j2k->m_specific_param.m_decoder.m_sot_length) { if (opj_stream_skip(p_stream,p_j2k->m_specific_param.m_decoder.m_sot_length,p_manager) != p_j2k->m_specific_param.m_decoder.m_sot_length) {
@ -6733,7 +6745,7 @@ opj_bool j2k_read_tile_header( opj_j2k_v2_t * p_j2k,
} }
opj_event_msg_v2(p_manager, EVT_INFO, "Header of tile %d / %d has been read.\n", opj_event_msg_v2(p_manager, EVT_INFO, "Header of tile %d / %d has been read.\n",
p_j2k->m_current_tile_number +1, p_j2k->m_cp.th * p_j2k->m_cp.tw); p_j2k->m_current_tile_number, (p_j2k->m_cp.th * p_j2k->m_cp.tw) - 1);
*p_tile_index = p_j2k->m_current_tile_number; *p_tile_index = p_j2k->m_current_tile_number;
*p_go_on = OPJ_TRUE; *p_go_on = OPJ_TRUE;
@ -6963,7 +6975,7 @@ opj_bool j2k_update_image_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data, opj_ima
/* Move the output buffer to the first place where we will write*/ /* Move the output buffer to the first place where we will write*/
l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest; l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest;
if (i == 0) { /*if (i == 0) {
fprintf(stdout, "COMPO[%d]:\n",i); fprintf(stdout, "COMPO[%d]:\n",i);
fprintf(stdout, "SRC: l_start_x_src=%d, l_start_y_src=%d, l_width_src=%d, l_height_src=%d\n" fprintf(stdout, "SRC: l_start_x_src=%d, l_start_y_src=%d, l_width_src=%d, l_height_src=%d\n"
"\t tile offset:%d, %d, %d, %d\n" "\t tile offset:%d, %d, %d, %d\n"
@ -6975,7 +6987,7 @@ opj_bool j2k_update_image_data (opj_tcd_v2_t * p_tcd, OPJ_BYTE * p_data, opj_ima
fprintf(stdout, "DEST: l_start_x_dest=%d, l_start_y_dest=%d, l_width_dest=%d, l_height_dest=%d\n" fprintf(stdout, "DEST: l_start_x_dest=%d, l_start_y_dest=%d, l_width_dest=%d, l_height_dest=%d\n"
"\t start offset: %d, line offset= %d\n", "\t start offset: %d, line offset= %d\n",
l_start_x_dest, l_start_y_dest, l_width_dest, l_height_dest, l_start_offset_dest, l_line_offset_dest); l_start_x_dest, l_start_y_dest, l_width_dest, l_height_dest, l_start_offset_dest, l_line_offset_dest);
} }*/
switch (l_size_comp) { switch (l_size_comp) {
@ -7260,6 +7272,10 @@ opj_j2k_v2_t* j2k_create_decompress_v2()
l_j2k->m_specific_param.m_decoder.m_header_data_size = J2K_DEFAULT_HEADER_SIZE; l_j2k->m_specific_param.m_decoder.m_header_data_size = J2K_DEFAULT_HEADER_SIZE;
l_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = -1 ;
l_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = 0 ;
/* codestream index creation */ /* codestream index creation */
l_j2k->cstr_index = j2k_create_cstr_index(); l_j2k->cstr_index = j2k_create_cstr_index();
@ -8161,6 +8177,133 @@ void j2k_setup_decoding (opj_j2k_v2_t *p_j2k)
} }
/*
* Read and decode one tile.
*/
opj_bool j2k_decode_one_tile ( opj_j2k_v2_t *p_j2k,
opj_stream_private_t *p_stream,
opj_event_mgr_t * p_manager)
{
opj_bool l_go_on = OPJ_TRUE;
OPJ_UINT32 l_current_tile_no;
OPJ_UINT32 l_tile_no_to_dec;
OPJ_UINT32 l_data_size,l_max_data_size;
OPJ_INT32 l_tile_x0,l_tile_y0,l_tile_x1,l_tile_y1;
OPJ_UINT32 l_nb_comps;
OPJ_BYTE * l_current_data;
l_current_data = (OPJ_BYTE*)opj_malloc(1000);
if (! l_current_data) {
return OPJ_FALSE;
}
l_max_data_size = 1000;
/*Allocate and initialize some elements of codestrem index if not already done*/
if( !p_j2k->cstr_index->tile_index)
{
if (!j2k_allocate_tile_element_cstr_index(p_j2k))
return OPJ_FALSE;
}
/* Move into the codestream to the first SOT used to decode the desired tile */
l_tile_no_to_dec = p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec;
if (p_j2k->cstr_index->tile_index)
if(p_j2k->cstr_index->tile_index->tp_index)
{
if ( ! p_j2k->cstr_index->tile_index[l_tile_no_to_dec].nb_tps) {
/* not build the index for this tile, so we will move to the last SOT read*/
if ( opj_stream_read_seek(p_stream, p_j2k->m_specific_param.m_decoder.m_last_sot_read_pos+2, p_manager) ){
opj_event_msg_v2(p_manager, EVT_ERROR, "Problem with seek function\n");
return OPJ_FALSE;
}
}
else{
if (opj_stream_read_seek(p_stream, p_j2k->cstr_index->tile_index[l_tile_no_to_dec].tp_index[0].start_pos+2, p_manager)) {
opj_event_msg_v2(p_manager, EVT_ERROR, "Problem with seek function\n");
return OPJ_FALSE;
}
}
/* Special case if we have previously read the EOC marker (if the previous tile getted is the last ) */
if(p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_EOC)
p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT;
}
while (OPJ_TRUE) {
if (! j2k_read_tile_header( p_j2k,
&l_current_tile_no,
&l_data_size,
&l_tile_x0, &l_tile_y0,
&l_tile_x1, &l_tile_y1,
&l_nb_comps,
&l_go_on,
p_stream,
p_manager)) {
opj_free(l_current_data);
return OPJ_FALSE;
}
if (! l_go_on) {
break;
}
if (l_data_size > l_max_data_size) {
l_current_data = (OPJ_BYTE*)opj_realloc(l_current_data,l_data_size);
if (! l_current_data) {
return OPJ_FALSE;
}
l_max_data_size = l_data_size;
}
if (! j2k_decode_tile(p_j2k,l_current_tile_no,l_current_data,l_data_size,p_stream,p_manager)) {
opj_free(l_current_data);
return OPJ_FALSE;
}
opj_event_msg_v2(p_manager, EVT_INFO, "Tile %d/%d has been decode.\n", l_current_tile_no, (p_j2k->m_cp.th * p_j2k->m_cp.tw) - 1);
if (! j2k_update_image_data(p_j2k->m_tcd,l_current_data, p_j2k->m_output_image)) {
opj_free(l_current_data);
return OPJ_FALSE;
}
opj_event_msg_v2(p_manager, EVT_INFO, "Image data has been updated with tile %d.\n\n", l_current_tile_no);
if(l_current_tile_no == l_tile_no_to_dec)
{
/* move into the codestream to the the first SOT (FIXME or not move?)*/
if (opj_stream_read_seek(p_stream, p_j2k->cstr_index->main_head_end + 2, p_manager) ) {
opj_event_msg_v2(p_manager, EVT_ERROR, "Problem with seek function\n");
return OPJ_FALSE;
}
break;
}
else {
opj_event_msg_v2(p_manager, EVT_WARNING, "Tile read, decode and updated is not the desired (%d vs %d).\n", l_current_tile_no, l_tile_no_to_dec);
}
}
opj_free(l_current_data);
return OPJ_TRUE;
}
/**
* Sets up the procedures to do on decoding one tile. Developpers wanting to extend the library can add their own reading procedures.
*/
void j2k_setup_decoding_tile (opj_j2k_v2_t *p_j2k)
{
// preconditions
assert(p_j2k != 00);
opj_procedure_list_add_procedure(p_j2k->m_procedure_list,(void*)j2k_decode_one_tile);
/* DEVELOPER CORNER, add your custom procedures */
}
/** /**
* Decodes the tiles of the stream. * Decodes the tiles of the stream.
@ -8200,3 +8343,98 @@ opj_bool j2k_decode_v2( opj_j2k_v2_t * p_j2k,
return OPJ_TRUE; return OPJ_TRUE;
} }
/**
* Get the decoded tile.
*
* @param p_j2k the jpeg2000 codestream codec.
* @param p_stream input_stream
* @param p_image output image. .
* @param p_manager the user event manager
* @param tile_index index of the tile we want decode
*
* @return true if succeed.
*/
opj_bool j2k_get_tile( opj_j2k_v2_t *p_j2k,
opj_stream_private_t *p_stream,
opj_image_t* p_image,
struct opj_event_mgr * p_manager,
OPJ_UINT32 tile_index )
{
OPJ_UINT32 compno;
OPJ_UINT32 l_tile_x, l_tile_y;
opj_image_comp_t* l_img_comp;
if (!p_image) {
opj_event_msg_v2(p_manager, EVT_ERROR, "We need a image previously created.\n");
return OPJ_FALSE;
}
/* Compute the dimension of the desired tile*/
l_tile_x = tile_index % p_j2k->m_cp.tw;
l_tile_y = tile_index / p_j2k->m_cp.tw;
p_image->x0 = l_tile_x * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0;
p_image->x1 = (l_tile_x + 1) * p_j2k->m_cp.tdx + p_j2k->m_cp.tx0;
p_image->y0 = l_tile_y * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0;
p_image->y1 = (l_tile_y + 1) * p_j2k->m_cp.tdy + p_j2k->m_cp.ty0;
l_img_comp = p_image->comps;
for (compno=0; compno < p_image->numcomps; ++compno)
{
OPJ_INT32 l_comp_x1, l_comp_y1;
l_img_comp->x0 = int_ceildiv(p_image->x0, l_img_comp->dx);
l_img_comp->y0 = int_ceildiv(p_image->y0, l_img_comp->dy);
l_comp_x1 = int_ceildiv(p_image->x1, l_img_comp->dx);
l_comp_y1 = int_ceildiv(p_image->y1, l_img_comp->dy);
l_img_comp->w = int_ceildivpow2(l_comp_x1 - l_img_comp->x0, l_img_comp->factor);
l_img_comp->h = int_ceildivpow2(l_comp_y1 - l_img_comp->y0, l_img_comp->factor);
l_img_comp++;
}
/* Destroy the previous output image*/
if (p_j2k->m_output_image)
opj_image_destroy(p_j2k->m_output_image);
/* Create the ouput image from the information previously computed*/
p_j2k->m_output_image = opj_image_create0();
if (! (p_j2k->m_output_image)) {
return OPJ_FALSE;
}
opj_copy_image_header(p_image, p_j2k->m_output_image);
if ( (tile_index < 0) && (tile_index >= p_j2k->m_cp.tw * p_j2k->m_cp.th) ){
opj_event_msg_v2(p_manager, EVT_ERROR, "Tile index provided by the user is incorrect %d (max = %d) \n", tile_index, (p_j2k->m_cp.tw * p_j2k->m_cp.th) - 1);
return OPJ_FALSE;
}
p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = tile_index;
/* customization of the decoding */
j2k_setup_decoding_tile(p_j2k);
/* Decode the codestream */
if (! j2k_exec (p_j2k,p_j2k->m_procedure_list,p_stream,p_manager)) {
opj_image_destroy(p_j2k->m_private_image);
p_j2k->m_private_image = NULL;
return OPJ_FALSE;
}
/* Move data and copy one information from codec to output image*/
for (compno = 0; compno < p_image->numcomps; compno++) {
p_image->comps[compno].resno_decoded = p_j2k->m_output_image->comps[compno].resno_decoded;
if (p_image->comps[compno].data)
opj_free(p_image->comps[compno].data);
p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data;
p_j2k->m_output_image->comps[compno].data = NULL;
}
return OPJ_TRUE;
}

View File

@ -607,6 +607,12 @@ typedef struct opj_j2k_dec
OPJ_UINT32 m_DA_y0; OPJ_UINT32 m_DA_y0;
OPJ_UINT32 m_DA_x1; OPJ_UINT32 m_DA_x1;
OPJ_UINT32 m_DA_y1; OPJ_UINT32 m_DA_y1;
/** Index of the tile to decode (used in get_tile) */
OPJ_INT32 m_tile_ind_to_dec;
/** Position of the last SOT marker read */
OPJ_UINT32 m_last_sot_read_pos;
/** /**
* Indicate that the current tile-part is assume as the last tile part of the codestream. * Indicate that the current tile-part is assume as the last tile part of the codestream.
* It is useful in the case of PSot is equal to zero. The sot length will be compute in the * It is useful in the case of PSot is equal to zero. The sot length will be compute in the
@ -1009,4 +1015,11 @@ opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_v2_t* p_j2k);
opj_bool j2k_decode_v2(opj_j2k_v2_t *j2k, struct opj_stream_private *cio, opj_image_t* p_image, opj_event_mgr_t * p_manager); opj_bool j2k_decode_v2(opj_j2k_v2_t *j2k, struct opj_stream_private *cio, opj_image_t* p_image, opj_event_mgr_t * p_manager);
opj_bool j2k_get_tile( opj_j2k_v2_t *p_j2k,
opj_stream_private_t *p_stream,
opj_image_t* p_image,
struct opj_event_mgr * p_manager,
OPJ_UINT32 tile_index );
#endif /* __J2K_H */ #endif /* __J2K_H */

View File

@ -2635,6 +2635,67 @@ opj_bool jp2_set_decode_area( opj_jp2_v2_t *p_jp2,
return j2k_set_decode_area(p_jp2->j2k, p_image, p_start_x, p_start_y, p_end_x, p_end_y, p_manager); return j2k_set_decode_area(p_jp2->j2k, p_image, p_start_x, p_start_y, p_end_x, p_end_y, p_manager);
} }
/**
* Get the decoded tile.
*
* @param p_jp2 the jpeg2000 codec.
* @param p_stream input_stream
* @param p_image output image. .
* @param p_manager the user event manager
* @param tile_index index of the tile we want decode
*
* @return true if succeed.
*/
opj_bool jp2_get_tile( opj_jp2_v2_t *jp2,
opj_stream_private_t *p_stream,
opj_image_t* p_image,
struct opj_event_mgr * p_manager,
OPJ_UINT32 tile_index )
{
if (!p_image)
return OPJ_FALSE;
opj_event_msg_v2(p_manager, EVT_WARNING, "JP2 box which are after the codestream will not be read by this function.\n");
if (! j2k_get_tile(jp2->j2k, p_stream, p_image, p_manager, tile_index) ){
opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to decode the codestream in the JP2 file\n");
return OPJ_FALSE;
}
/* Set Image Color Space */
if (jp2->enumcs == 16)
p_image->color_space = CLRSPC_SRGB;
else if (jp2->enumcs == 17)
p_image->color_space = CLRSPC_GRAY;
else if (jp2->enumcs == 18)
p_image->color_space = CLRSPC_SYCC;
else
p_image->color_space = CLRSPC_UNKNOWN;
/* Apply the color space if needed */
if(jp2->color.jp2_cdef) {
jp2_apply_cdef(p_image, &(jp2->color));
}
if(jp2->color.jp2_pclr) {
/* Part 1, I.5.3.4: Either both or none : */
if( !jp2->color.jp2_pclr->cmap)
jp2_free_pclr(&(jp2->color));
else
jp2_apply_pclr(p_image, &(jp2->color));
}
if(jp2->color.icc_profile_buf) {
p_image->icc_profile_buf = jp2->color.icc_profile_buf;
p_image->icc_profile_len = jp2->color.icc_profile_len;
jp2->color.icc_profile_buf = NULL;
}
return OPJ_TRUE;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* JP2 encoder interface */ /* JP2 encoder interface */
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */

View File

@ -418,6 +418,12 @@ opj_bool jp2_set_decode_area( opj_jp2_v2_t *p_jp2,
OPJ_INT32 p_end_x, OPJ_INT32 p_end_y, OPJ_INT32 p_end_x, OPJ_INT32 p_end_y,
struct opj_event_mgr * p_manager ); struct opj_event_mgr * p_manager );
opj_bool jp2_get_tile( opj_jp2_v2_t *p_jp2,
opj_stream_private_t *p_stream,
opj_image_t* p_image,
struct opj_event_mgr * p_manager,
OPJ_UINT32 tile_index );
/** /**
* Dump some elements from the JP2 decompression structure . * Dump some elements from the JP2 decompression structure .

View File

@ -78,6 +78,13 @@ typedef struct opj_decompression
OPJ_INT32 p_start_x, OPJ_INT32 p_end_x, OPJ_INT32 p_start_x, OPJ_INT32 p_end_x,
OPJ_INT32 p_start_y, OPJ_INT32 p_end_y, OPJ_INT32 p_start_y, OPJ_INT32 p_end_y,
struct opj_event_mgr * p_manager); struct opj_event_mgr * p_manager);
/** Get tile function */
opj_bool (*opj_get_decoded_tile) ( void *p_codec,
opj_stream_private_t *p_cio,
opj_image_t *p_image,
struct opj_event_mgr * p_manager,
OPJ_UINT32 tile_index);
}opj_decompression_t; }opj_decompression_t;
/** /**
@ -286,6 +293,12 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress_v2(OPJ_CODEC_FORMAT p_format)
l_info->m_codec_data.m_decompression.opj_set_decode_area = l_info->m_codec_data.m_decompression.opj_set_decode_area =
(opj_bool (*) (void *, opj_image_t*, OPJ_INT32, OPJ_INT32, OPJ_INT32, OPJ_INT32, struct opj_event_mgr *)) j2k_set_decode_area; (opj_bool (*) (void *, opj_image_t*, OPJ_INT32, OPJ_INT32, OPJ_INT32, OPJ_INT32, struct opj_event_mgr *)) j2k_set_decode_area;
l_info->m_codec_data.m_decompression.opj_get_decoded_tile = (opj_bool (*) ( void *p_codec,
opj_stream_private_t *p_cio,
opj_image_t *p_image,
struct opj_event_mgr * p_manager,
OPJ_UINT32 tile_index)) j2k_get_tile;
l_info->m_codec = j2k_create_decompress_v2(); l_info->m_codec = j2k_create_decompress_v2();
if (! l_info->m_codec) { if (! l_info->m_codec) {
@ -338,6 +351,12 @@ opj_codec_t* OPJ_CALLCONV opj_create_decompress_v2(OPJ_CODEC_FORMAT p_format)
l_info->m_codec_data.m_decompression.opj_set_decode_area = (opj_bool (*) (void *,opj_image_t*, OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) jp2_set_decode_area; l_info->m_codec_data.m_decompression.opj_set_decode_area = (opj_bool (*) (void *,opj_image_t*, OPJ_INT32,OPJ_INT32,OPJ_INT32,OPJ_INT32, struct opj_event_mgr * )) jp2_set_decode_area;
l_info->m_codec_data.m_decompression.opj_get_decoded_tile = (opj_bool (*) ( void *p_codec,
opj_stream_private_t *p_cio,
opj_image_t *p_image,
struct opj_event_mgr * p_manager,
OPJ_UINT32 tile_index)) jp2_get_tile;
l_info->m_codec = jp2_create(OPJ_TRUE); l_info->m_codec = jp2_create(OPJ_TRUE);
if (! l_info->m_codec) { if (! l_info->m_codec) {
@ -937,6 +956,10 @@ opj_bool OPJ_CALLCONV opj_decode_v2(opj_codec_t *p_info,
return OPJ_FALSE; return OPJ_FALSE;
} }
/*
*
*
*/
opj_bool OPJ_CALLCONV opj_end_decompress (opj_codec_t *p_codec,opj_stream_t *p_cio) opj_bool OPJ_CALLCONV opj_end_decompress (opj_codec_t *p_codec,opj_stream_t *p_cio)
{ {
if (p_codec && p_cio) { if (p_codec && p_cio) {
@ -953,3 +976,29 @@ opj_bool OPJ_CALLCONV opj_end_decompress (opj_codec_t *p_codec,opj_stream_t *p_c
return OPJ_FALSE; return OPJ_FALSE;
} }
/*
*
*
*/
opj_bool OPJ_CALLCONV opj_get_decoded_tile( opj_codec_t *p_codec,
opj_stream_t *p_cio,
opj_image_t *p_image,
OPJ_UINT32 tile_index)
{
if (p_codec && p_cio) {
opj_codec_private_t * l_codec = (opj_codec_private_t *) p_codec;
opj_stream_private_t * l_stream = (opj_stream_private_t *) p_cio;
if (! l_codec->is_decompressor) {
return OPJ_FALSE;
}
return l_codec->m_codec_data.m_decompression.opj_get_decoded_tile( l_codec->m_codec,
l_stream,
p_image,
l_codec->m_event_mgr,
tile_index);
}
return OPJ_FALSE;
}

View File

@ -1270,6 +1270,19 @@ OPJ_API opj_bool OPJ_CALLCONV opj_decode_v2(opj_codec_t *p_decompressor,
opj_image_t *p_image); opj_image_t *p_image);
/**
* Get the decoded tile from the codec
* @param p_codec the jpeg2000 codec.
* @param p_cio input streamm
* @param p_image output image
* @param tile_index index of the tile which will be decode
*
* @return a pointer to a JP2 index structure.
*/
OPJ_API opj_bool OPJ_CALLCONV opj_get_decoded_tile( opj_codec_t *p_codec,
opj_stream_t *p_cio,
opj_image_t *p_image,
OPJ_UINT32 tile_index);
/** /**
* Reads a tile header. This function is compulsory and allows one to know the size of the tile thta will be decoded. * Reads a tile header. This function is compulsory and allows one to know the size of the tile thta will be decoded.
@ -1477,6 +1490,8 @@ OPJ_API opj_jp2_index_t* OPJ_CALLCONV opj_get_jp2_index(opj_codec_t *p_codec);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif