[trunk] WIP: add get_decoded_tile functionality
authorMickael Savinaud <savmickael@users.noreply.github.com>
Tue, 8 Nov 2011 13:21:17 +0000 (13:21 +0000)
committerMickael Savinaud <savmickael@users.noreply.github.com>
Tue, 8 Nov 2011 13:21:17 +0000 (13:21 +0000)
CHANGES
applications/codec/j2k_dump.c
libopenjpeg/cio.c
libopenjpeg/j2k.c
libopenjpeg/j2k.h
libopenjpeg/jp2.c
libopenjpeg/jp2.h
libopenjpeg/openjpeg.c
libopenjpeg/openjpeg.h

diff --git a/CHANGES b/CHANGES
index 166911c362a89efe65d139ed026237d34d232621..75927c2396fb009d59d540ba0d51a7cc580de2c0 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,7 @@ What's New for OpenJPEG
 + : added
 
 November 8, 2011
++ [mickael] WIP: add get_decoded_tile functionality
 + [mickael] WIP: clean and enhance j2K file
 + [mickael] WIP: clean and enhance openjpeg.c
 + [mickael] WIP: clean and enhance openjpeg.h and add deprecated macro
index 9b5475edd9c0bcf3ffd5347d8c410e907047c0ab..6d13bb1111da28d3e64662057bde8b794b230eb9 100644 (file)
@@ -525,77 +525,6 @@ int main(int argc, char *argv[])
 
                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 */
                opj_stream_destroy(cio);
                fclose(fsrc);
index 85a320c8c549a8953670044e84b8ecf7d52ffa7f..32203a459182b2a27a3245c2b2e8e70915ced346 100644 (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 l_read_nb_bytes = 0;
-       if
-               (p_stream->m_bytes_in_buffer >= p_size)
-       {
+       if (p_stream->m_bytes_in_buffer >= p_size) {
                memcpy(p_buffer,p_stream->m_current_data,p_size);
                p_stream->m_current_data += 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;
        }
 
-       // we are now in the case when the remaining data if not sufficient
-       if
-               (p_stream->m_status & opj_stream_e_end)
-       {
+       /* we are now in the case when the remaining data if not sufficient */
+       if (p_stream->m_status & opj_stream_e_end) {
                l_read_nb_bytes += 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;
@@ -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;
        }
 
-       // the flag is not set, we copy data and then do an actual read on the stream
-       if
-               (p_stream->m_bytes_in_buffer)
-       {
+       /* the flag is not set, we copy data and then do an actual read on the stream */
+       if (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);
                p_stream->m_current_data = p_stream->m_stored_data;
@@ -559,37 +553,31 @@ 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_bytes_in_buffer = 0;
        }
-  else
-  {
+       else {
     /* case where we are already at the end of the buffer
        so reset the m_current_data to point to the start of the
        stored buffer to get ready to read from disk*/
-    p_stream->m_current_data = p_stream->m_stored_data;
-  }
+               p_stream->m_current_data = p_stream->m_stored_data;
+       }
 
 
        while(1){
-               // we should read less than a chunk -> read a chunk
-               if
-                       (p_size < p_stream->m_buffer_size)
-               {
-                       // we should do an actual read on the media
+               /* we should read less than a chunk -> read a chunk */
+               if (p_size < p_stream->m_buffer_size) {
+                       /* 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);
-                       if
-                               (p_stream->m_bytes_in_buffer == -1)
-                       {
-                               // end of stream
+
+                       if (p_stream->m_bytes_in_buffer == -1) {
+                               /* end of stream */
                                opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
 
                                p_stream->m_bytes_in_buffer = 0;
                                p_stream->m_status |= opj_stream_e_end;
-                               // end of stream
+                               /* end of stream */
                                return l_read_nb_bytes ? l_read_nb_bytes : -1;
                        }
-                       else if
-                               (p_stream->m_bytes_in_buffer < p_size)
-                       {
-                               // not enough data
+                       else if (p_stream->m_bytes_in_buffer < p_size) {
+                               /* not enough data */
                                l_read_nb_bytes += 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;
@@ -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_bytes_in_buffer = 0;
                        }
-                       else
-                       {
+                       else {
                                l_read_nb_bytes += p_size;
                                memcpy(p_buffer,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;
                        }
                }
-               else
-               {
-                       // direct read on the dest buffer
+               else {
+                       /* 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);
-                       if
-                               (p_stream->m_bytes_in_buffer == -1)
-                       {
-                               // end of stream
+
+                       if (p_stream->m_bytes_in_buffer == -1) {
+                               /*  end of stream */
                                opj_event_msg_v2(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
 
                                p_stream->m_bytes_in_buffer = 0;
                                p_stream->m_status |= opj_stream_e_end;
-                               // end of stream
+                               /* end of stream */
                                return l_read_nb_bytes ? l_read_nb_bytes : -1;
                        }
-                       else if
-                               (p_stream->m_bytes_in_buffer < p_size)
-                       {
-                               // not enough data
+                       else if (p_stream->m_bytes_in_buffer < p_size) {
+                               /* not enough data */
                                l_read_nb_bytes += p_stream->m_bytes_in_buffer;
                                p_stream->m_current_data = p_stream->m_stored_data;
                                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_bytes_in_buffer = 0;
                        }
-                       else
-                       {
-                               // we have read the exact size
+                       else {
+                               /* we have read the exact size */
                                l_read_nb_bytes += 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;
@@ -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_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;
                return EXIT_FAILURE;
        }
-       else
-       {
+       else {
                // reset stream status
                p_stream->m_status &= (~opj_stream_e_end);
                p_stream->m_byte_offset = p_size;
 
        }
+
        return EXIT_SUCCESS;
 }
 
index 111e8c71d0204595932188f156e0a0c3faeea75e..281b087fc9d7cd677052540d3f0eab6c5d41e6b0 100644 (file)
@@ -3687,12 +3687,17 @@ opj_bool j2k_read_sot_v2 (
 
        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)*/
-       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_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_end_tile_y);
+       /* 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 =
+                               (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_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);
+       }
+       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 */
        if (p_j2k->cstr_index)
@@ -6636,9 +6641,6 @@ opj_bool j2k_read_tile_header(    opj_j2k_v2_t * p_j2k,
                                return OPJ_FALSE;
                        }
 
-/*                     if (l_current_marker == J2K_MS_SOT)
-                               j2k_add_tlmarker();*/
-
                        /* Add the marker to the codestream index*/
                        j2k_add_tlmarker_v2(p_j2k->m_current_tile_number,
                                                                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,
                                                                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) {
                                /* 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) {
@@ -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",
-                       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_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*/
                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, "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"
@@ -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"
                                        "\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);
-               }
+               }*/
 
 
                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_tile_ind_to_dec = -1 ;
+
+       l_j2k->m_specific_param.m_decoder.m_last_sot_read_pos = 0 ;
+
        /* codestream index creation */
        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.
@@ -8200,3 +8343,98 @@ opj_bool j2k_decode_v2(  opj_j2k_v2_t * p_j2k,
 
        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;
+}
index d5fd2bea9fa81a5ffed397984a928548f60ebc1e..04a387b85e5b49a256dcdabe77f930e80afaf8be 100644 (file)
@@ -607,6 +607,12 @@ typedef struct opj_j2k_dec
        OPJ_UINT32 m_DA_y0;
        OPJ_UINT32 m_DA_x1;
        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.
         * 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_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 */
index 322abc75c73638eb68513cfac86fabe17946da82..57f970705b21e7af79bfeec6f5344e41b86f35ba 100644 (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);
 }
 
+/**
+ * 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                                             */
 /* ----------------------------------------------------------------------- */
index 4d44aacbff184e5a90fc5d4722a751092bdb6200..ddd61e41e8f16e5a0a8602e6181e596838e96cd9 100644 (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,
                                                                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 .
index b1795f8f2e7167a0bd74f9d38c09cbe0955ffd12..aa77a5e1a3de38571ac67a1f4966bd790a48f3f0 100644 (file)
@@ -78,6 +78,13 @@ typedef struct opj_decompression
                                                                                OPJ_INT32 p_start_x, OPJ_INT32 p_end_x,
                                                                                OPJ_INT32 p_start_y, OPJ_INT32 p_end_y,
                                                                                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;
 
 /**
@@ -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 =
                                        (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();
 
                        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_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);
 
                        if (! l_info->m_codec) {
@@ -937,6 +956,10 @@ opj_bool OPJ_CALLCONV opj_decode_v2(opj_codec_t *p_info,
        return OPJ_FALSE;
 }
 
+/*
+ *
+ *
+ */
 opj_bool OPJ_CALLCONV opj_end_decompress (opj_codec_t *p_codec,opj_stream_t *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;
 }
+
+/*
+ *
+ *
+ */
+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;
+}
index 0ac208f1d1af3ffbb441bf153c4469b5470a5b18..3c82498c04942b9f815cd8aa410d49633791ce62 100644 (file)
@@ -1270,6 +1270,19 @@ OPJ_API opj_bool OPJ_CALLCONV opj_decode_v2(opj_codec_t *p_decompressor,
                                                                                        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.
@@ -1477,6 +1490,8 @@ OPJ_API opj_jp2_index_t* OPJ_CALLCONV opj_get_jp2_index(opj_codec_t *p_codec);
 
 
 
+
+
 #ifdef __cplusplus
 }
 #endif