rename j2k_setup_decoder_v2 to opj_j2k_setup_decoder
[openjpeg.git] / libopenjpeg / jp2.c
index 58faac56ce7cb4a0de6d972f07f431c64e1007f0..73596295282c482fadb6a030d42ae005d32cbf4c 100644 (file)
@@ -64,14 +64,12 @@ static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio);
  * @param      p_image_header_size                     the size of the image header
  * @param      p_manager                                       the user event manager.
  *
- * @return     true if the image header is valid, fale else.
+ * @return     true if the image header is valid, false else.
  */
-static opj_bool jp2_read_ihdr_v2(
-                                                       opj_jp2_v2_t *jp2,
-                                                       unsigned char * p_image_header_data,
-                                                       unsigned int p_image_header_size,
-                                                       struct opj_event_mgr * p_manager
-                                                 );
+static opj_bool jp2_read_ihdr_v2(   opj_jp2_v2_t *jp2,
+                                    OPJ_BYTE *p_image_header_data,
+                                    OPJ_INT32 p_image_header_size,
+                                    opj_event_mgr_t * p_manager );
 
 static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio);
 
@@ -210,6 +208,21 @@ static opj_bool jp2_read_jp2h_v2(
                                        );
 
 static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
+
+
+/**
+ * Writes the Jpeg2000 codestream Header box - JP2C Header box. This function must be called AFTER the coding has been done.
+ *
+ * @param      cio                     the stream to write data to.
+ * @param      jp2                     the jpeg2000 file codec.
+ * @param      p_manager       user event manager.
+ *
+ * @return true if writting was successful.
+*/
+static opj_bool jp2_write_jp2c_v2(     opj_jp2_v2_t *jp2,
+                                                               struct opj_stream_private *cio,
+                                                               struct opj_event_mgr * p_manager );
+
 static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset);
 static void jp2_write_jp(opj_cio_t *cio);
 /**
@@ -641,11 +654,10 @@ static opj_bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) {
  *
  * @return     true if the image header is valid, fale else.
  */
-opj_bool jp2_read_ihdr_v2(
-                                                       opj_jp2_v2_t *jp2,
-                                                       unsigned char * p_image_header_data,
-                                                       unsigned int p_image_header_size,
-                                                       opj_event_mgr_t * p_manager
+opj_bool jp2_read_ihdr_v2(  opj_jp2_v2_t *jp2,
+                            OPJ_BYTE *p_image_header_data,
+                            OPJ_INT32 p_image_header_size,
+                            opj_event_mgr_t * p_manager
                                                  )
 {
        /* preconditions */
@@ -662,7 +674,7 @@ opj_bool jp2_read_ihdr_v2(
        p_image_header_data += 4;
        opj_read_bytes(p_image_header_data,&(jp2->w),4);                        /* WIDTH */
        p_image_header_data += 4;
-       opj_read_bytes(p_image_header_data,&(jp2->numcomps),2);                 /* NC */
+       opj_read_bytes(p_image_header_data,&(jp2->numcomps),2);         /* NC */
        p_image_header_data += 2;
 
        /* allocate memory for components */
@@ -1145,7 +1157,7 @@ static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio,
        for(i = 0; i < nr_channels; ++i)
   {
 /* Cji */
-       *entries++ = cio_read(cio, channel_size[i]>>3);
+       *entries++ = cio_read(cio, (channel_size[i]+7)>>3);
   }
    }
 
@@ -1178,6 +1190,7 @@ opj_bool jp2_read_pclr_v2(        opj_jp2_v2_t *jp2,
        assert(p_pclr_header_data != 00);
        assert(jp2 != 00);
        assert(p_manager != 00);
+  (void)p_pclr_header_size;
 
        if(jp2->color.jp2_pclr)
                return OPJ_FALSE;
@@ -1214,9 +1227,10 @@ opj_bool jp2_read_pclr_v2(       opj_jp2_v2_t *jp2,
 
        for(j = 0; j < nr_entries; ++j) {
                for(i = 0; i < nr_channels; ++i) {
-                       /**entries++ = cio_read(cio, channel_size[i]>>3); */
-                       opj_read_bytes(p_pclr_header_data, &l_value , channel_size[i]>>3);      /* Cji */
-                       p_pclr_header_data += channel_size[i]>>3;
+                       int bytes_to_read = (channel_size[i]+7)>>3;
+
+                       opj_read_bytes(p_pclr_header_data, &l_value , bytes_to_read);   /* Cji */
+                       p_pclr_header_data += bytes_to_read;
                        *entries = (OPJ_UINT32) l_value;
                        entries++;
                }
@@ -1284,6 +1298,7 @@ static opj_bool jp2_read_cmap_v2( opj_jp2_v2_t * jp2,
        assert(jp2 != 00);
        assert(p_cmap_header_data != 00);
        assert(p_manager != 00);
+  (void)p_cmap_header_size;
 
        /* Need nr_channels: */
        if(jp2->color.jp2_pclr == NULL) {
@@ -1414,6 +1429,7 @@ static opj_bool jp2_read_cdef_v2( opj_jp2_v2_t * jp2,
        assert(jp2 != 00);
        assert(p_cdef_header_data != 00);
        assert(p_manager != 00);
+  (void)p_cdef_header_size;
 
        /* Part 1, I.5.3.6: 'The shall be at most one Channel Definition box
         * inside a JP2 Header box.'*/
@@ -1678,116 +1694,53 @@ opj_bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio, opj_jp2_color_t *color)
 
 }/* jp2_read_jp2h() */
 
-opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, 
-       opj_codestream_info_t *cstr_info) 
-{
-       opj_common_ptr cinfo;
-       opj_image_t *image = NULL;
-       opj_jp2_color_t color;
-
-       if(!jp2 || !cio) 
-   {
-       return NULL;
-   }
-       memset(&color, 0, sizeof(opj_jp2_color_t));
-       cinfo = jp2->cinfo;
-
-/* JP2 decoding */
-       if(!jp2_read_struct(jp2, cio, &color)) 
-   {
-       free_color_data(&color);
-       opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n");
-       return NULL;
-   }
-
-/* J2K decoding */
-       image = j2k_decode(jp2->j2k, cio, cstr_info);
-
-       if(!image) 
-   {
-       free_color_data(&color);
-       opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n");
-       return NULL;
-   }
-   
-    if (!jp2->ignore_pclr_cmap_cdef){
 
-    /* Set Image Color Space */
-       if (jp2->enumcs == 16)
-               image->color_space = CLRSPC_SRGB;
-       else if (jp2->enumcs == 17)
-               image->color_space = CLRSPC_GRAY;
-       else if (jp2->enumcs == 18)
-               image->color_space = CLRSPC_SYCC;
-       else
-               image->color_space = CLRSPC_UNKNOWN;
 
-       if(color.jp2_cdef)
-   {
-       jp2_apply_cdef(image, &color);
-   }
-       if(color.jp2_pclr)
-   {
-/* Part 1, I.5.3.4: Either both or none : */
-       if( !color.jp2_pclr->cmap) 
-        jp2_free_pclr(&color);
-       else
-        jp2_apply_pclr(image, &color);
-   }
-       if(color.icc_profile_buf)
-   {
-       image->icc_profile_buf = color.icc_profile_buf;
-       color.icc_profile_buf = NULL;
-       image->icc_profile_len = color.icc_profile_len;
-   }
-   }
-   
-       return image;
-
-}/* opj_jp2_decode() */
-
-opj_bool jp2_decode_v2(        opj_jp2_v2_t *jp2,
-                                               struct opj_stream_private *cio,
-                                               opj_image_t* p_image,
-                                               struct opj_event_mgr * p_manager)
+opj_bool opj_jp2_decode(opj_jp2_v2_t *jp2,
+                        opj_stream_private_t *p_stream,
+                        opj_image_t* p_image,
+                        opj_event_mgr_t * p_manager)
 {
        if (!p_image)
                return OPJ_FALSE;
 
        /* J2K decoding */
-       if( ! j2k_decode_v2(jp2->j2k, cio, p_image, p_manager) ) {
+       if( ! j2k_decode_v2(jp2->j2k, p_stream, p_image, p_manager) ) {
                opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to decode the codestream in the JP2 file\n");
                return OPJ_FALSE;
        }
+    
+    if (!jp2->ignore_pclr_cmap_cdef){
 
-       /* 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;
-       }
+           /* 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;
 }
@@ -1890,7 +1843,7 @@ opj_bool jp2_write_jp2h_v2(       opj_jp2_v2_t *jp2,
        
        /* write super box data on stream */
        if (opj_stream_write_data(cio,l_jp2h_data,8,p_manager) != 8) {
-               opj_event_msg(p_manager, EVT_ERROR, "Stream error while writting JP2 Header box\n");
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Stream error while writing JP2 Header box\n");
                l_result = OPJ_FALSE;
        }
        
@@ -1898,7 +1851,7 @@ opj_bool jp2_write_jp2h_v2(       opj_jp2_v2_t *jp2,
                l_current_writer = l_writers;
                for (i=0;i<l_nb_pass;++i) {
                        if (opj_stream_write_data(cio,l_current_writer->m_data,l_current_writer->m_size,p_manager) != l_current_writer->m_size) {
-                               opj_event_msg(p_manager, EVT_ERROR, "Stream error while writting JP2 Header box\n");
+                               opj_event_msg_v2(p_manager, EVT_ERROR, "Stream error while writting JP2 Header box\n");
                                l_result = OPJ_FALSE;
                                break;
                        }
@@ -1993,7 +1946,7 @@ opj_bool jp2_write_ftyp_v2(       opj_jp2_v2_t *jp2,
        l_result = (opj_stream_write_data(cio,l_ftyp_data,l_ftyp_size,p_manager) == l_ftyp_size);
        if (! l_result)
        {
-               opj_event_msg(p_manager, EVT_ERROR, "Error while writting ftyp data to stream\n");
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Error while writting ftyp data to stream\n");
        }
 
        opj_free(l_ftyp_data);
@@ -2060,6 +2013,50 @@ static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, op
        return box.length;
 }
 
+/**
+ * Writes the Jpeg2000 codestream Header box - JP2C Header box.
+ *
+ * @param      cio                     the stream to write data to.
+ * @param      jp2                     the jpeg2000 file codec.
+ * @param      p_manager       user event manager.
+ *
+ * @return true if writting was successful.
+*/
+opj_bool jp2_write_jp2c_v2(    opj_jp2_v2_t *jp2,
+                                                       opj_stream_private_t *cio,
+                                                       opj_event_mgr_t * p_manager ) 
+{
+       unsigned int j2k_codestream_exit;
+       unsigned char l_data_header [8];
+       
+       // preconditions
+       assert(jp2 != 00);
+       assert(cio != 00);
+       assert(p_manager != 00);
+       assert(opj_stream_has_seek(cio));
+       
+       j2k_codestream_exit = opj_stream_tell(cio);
+       opj_write_bytes(l_data_header,j2k_codestream_exit - jp2->j2k_codestream_offset,4); /* size of codestream */
+       opj_write_bytes(l_data_header + 4,JP2_JP2C,4);                                                                     /* JP2C */
+
+       if (! opj_stream_seek(cio,jp2->j2k_codestream_offset,p_manager)) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to seek in the stream.\n");
+               return OPJ_FALSE;
+       }
+       
+       if (opj_stream_write_data(cio,l_data_header,8,p_manager) != 8) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to seek in the stream.\n");
+               return OPJ_FALSE;
+       }
+
+       if (! opj_stream_seek(cio,j2k_codestream_exit,p_manager)) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to seek in the stream.\n");
+               return OPJ_FALSE;
+       }
+
+       return OPJ_TRUE;
+}
+
 static opj_bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset) {
        opj_jp2_box_t box;
 
@@ -2230,20 +2227,6 @@ static void write_iptr( int offset, int length, opj_cio_t *cio)
 /* JP2 decoder interface                                             */
 /* ----------------------------------------------------------------------- */
 
-opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo) {
-       opj_jp2_t *jp2 = (opj_jp2_t*) opj_calloc(1, sizeof(opj_jp2_t));
-       if(jp2) {
-               jp2->cinfo = cinfo;
-               /* create the J2K codec */
-               jp2->j2k = j2k_create_decompress(cinfo);
-               if(jp2->j2k == NULL) {
-                       jp2_destroy_decompress(jp2);
-                       return NULL;
-               }
-       }
-       return jp2;
-}
-
 void jp2_destroy_decompress(opj_jp2_t *jp2) {
        if(jp2) {
                /* destroy the J2K codec */
@@ -2259,20 +2242,15 @@ void jp2_destroy_decompress(opj_jp2_t *jp2) {
        }
 }
 
-void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) {
-       /* setup the J2K codec */
-       j2k_setup_decoder(jp2->j2k, parameters);
-       /* further JP2 initializations go here */
-       jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
-}
 
-void jp2_setup_decoder_v2(opj_jp2_v2_t *jp2, opj_dparameters_t *parameters)
+void opj_jp2_setup_decoder(opj_jp2_v2_t *jp2, opj_dparameters_t *parameters)
 {
        /* setup the J2K codec */
-       j2k_setup_decoder_v2(jp2->j2k, parameters);
+       opj_j2k_setup_decoder(jp2->j2k, parameters);
 
        /* further JP2 initializations go here */
        jp2->color.jp2_has_colr = 0;
+    jp2->ignore_pclr_cmap_cdef = parameters->flags & OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
 }
 
 
@@ -2497,7 +2475,7 @@ void jp2_setup_end_header_writting (opj_jp2_v2_t *jp2)
        /* preconditions */
        assert(jp2 != 00);
 
-       opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)jp2_write_jp2c );
+       opj_procedure_list_add_procedure(jp2->m_procedure_list,(opj_procedure)jp2_write_jp2c_v2 );
        /* DEVELOPER CORNER, add your custom procedures */
 }
 
@@ -3410,7 +3388,7 @@ opj_jp2_v2_t* jp2_create(opj_bool p_is_decoder)
                        jp2->j2k = j2k_create_compress_v2();
                }
                else {
-                       jp2->j2k = j2k_create_decompress_v2();
+                       jp2->j2k = opj_j2k_create_decompress();
                }
 
                if (jp2->j2k == 00) {