[trunk] WIP: update output filename of conformance dump test to be compatible with...
[openjpeg.git] / libopenjpeg / jp2.c
index 84da39e994abfbf330660d7a73c6ad02e9635517..840b3b867da8426d14b263b3b94e9c7c281be193 100644 (file)
@@ -191,7 +191,7 @@ Apply collected palette data
 @param color Collector for profile, cdef and pclr data
 @param image 
 */
-static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image);
+static void jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color);
 /**
 Collect palette data
 @param jp2 JP2 handle
@@ -763,16 +763,17 @@ static void free_color_data(opj_jp2_color_t *color)
        if(color->icc_profile_buf) opj_free(color->icc_profile_buf);
 }
 
-static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image)
+
+static void jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color)
 {
        opj_image_comp_t *old_comps, *new_comps;
-       unsigned char *channel_size, *channel_sign;
-       unsigned int *entries;
+       OPJ_BYTE *channel_size, *channel_sign;
+       OPJ_UINT32 *entries;
        opj_jp2_cmap_comp_t *cmap;
-       int *src, *dst;
-       unsigned int j, max;
-       unsigned short i, nr_channels, cmp, pcol;
-       int k, top_k;
+       OPJ_INT32 *src, *dst;
+       OPJ_UINT32 j, max;
+       OPJ_UINT16 i, nr_channels, cmp, pcol;
+       OPJ_INT32 k, top_k;
 
        channel_size = color->jp2_pclr->channel_size;
        channel_sign = color->jp2_pclr->channel_sign;
@@ -782,50 +783,52 @@ static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image)
 
        old_comps = image->comps;
        new_comps = (opj_image_comp_t*)
-        opj_malloc(nr_channels * sizeof(opj_image_comp_t));
+                       opj_malloc(nr_channels * sizeof(opj_image_comp_t));
 
-       for(i = 0; i < nr_channels; ++i)
-   {
-       pcol = cmap[i].pcol; cmp = cmap[i].cmp;
+       for(i = 0; i < nr_channels; ++i) {
+               pcol = cmap[i].pcol; cmp = cmap[i].cmp;
 
-       new_comps[pcol] = old_comps[cmp];
+               new_comps[pcol] = old_comps[cmp];
+
+               /* Direct use */
+               if(cmap[i].mtyp == 0){
+                       old_comps[cmp].data = NULL; continue;
+               }
+
+               /* Palette mapping: */
+               new_comps[pcol].data = (int*)
+                               opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int));
+               new_comps[pcol].prec = channel_size[i];
+               new_comps[pcol].sgnd = channel_sign[i];
+       }
 
-       if(cmap[i].mtyp == 0) /* Direct use */
-  {
-       old_comps[cmp].data = NULL; continue;
-  }
-/* Palette mapping: */
-       new_comps[pcol].data = (int*)
-        opj_malloc(old_comps[cmp].w * old_comps[cmp].h * sizeof(int));
-       new_comps[pcol].prec = channel_size[i];
-       new_comps[pcol].sgnd = channel_sign[i];
-   }
        top_k = color->jp2_pclr->nr_entries - 1;
 
-       for(i = 0; i < nr_channels; ++i)
-   {
-/* Direct use: */
-       if(cmap[i].mtyp == 0) continue;
+       for(i = 0; i < nr_channels; ++i) {
+               /* Direct use: */
+               if(cmap[i].mtyp == 0) continue;
 
-/* Palette mapping: */
-       cmp = cmap[i].cmp; pcol = cmap[i].pcol;
-       src = old_comps[cmp].data; 
-       dst = new_comps[pcol].data;
-       max = new_comps[pcol].w * new_comps[pcol].h;
+               /* Palette mapping: */
+               cmp = cmap[i].cmp; pcol = cmap[i].pcol;
+               src = old_comps[cmp].data;
+               dst = new_comps[pcol].data;
+               max = new_comps[pcol].w * new_comps[pcol].h;
+
+               for(j = 0; j < max; ++j)
+               {
+                       /* The index */
+                       if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k;
+
+                       /* The colour */
+                       dst[j] = entries[k * nr_channels + pcol];
+               }
+       }
 
-       for(j = 0; j < max; ++j)
-  {
-/* The index */
-       if((k = src[j]) < 0) k = 0; else if(k > top_k) k = top_k;
-/* The colour */
-       dst[j] = entries[k * nr_channels + pcol];
-  }
-   }
        max = image->numcomps;
-       for(i = 0; i < max; ++i)
-   {
-       if(old_comps[i].data) opj_free(old_comps[i].data);
-   }
+       for(i = 0; i < max; ++i) {
+               if(old_comps[i].data) opj_free(old_comps[i].data);
+       }
+
        opj_free(old_comps);
        image->comps = new_comps;
        image->numcomps = nr_channels;
@@ -834,6 +837,7 @@ static void jp2_apply_pclr(opj_jp2_color_t *color, opj_image_t *image)
 
 }/* apply_pclr() */
 
+
 static opj_bool jp2_read_pclr(opj_jp2_t *jp2, opj_cio_t *cio,
        opj_jp2_box_t *box, opj_jp2_color_t *color)
 {
@@ -1062,32 +1066,33 @@ static opj_bool jp2_read_cmap_v2(       opj_jp2_v2_t * jp2,
 static void jp2_apply_cdef(opj_image_t *image, opj_jp2_color_t *color)
 {
        opj_jp2_cdef_info_t *info;
-       int color_space;
-       unsigned short i, n, cn, typ, asoc, acn;
+       OPJ_INT32 color_space;
+       OPJ_UINT16 i, n, cn, typ, asoc, acn;
 
        color_space = image->color_space;
        info = color->jp2_cdef->info;
        n = color->jp2_cdef->n;
 
        for(i = 0; i < n; ++i)
-   {
-/* WATCH: acn = asoc - 1 ! */
-       if((asoc = info[i].asoc) == 0) continue;
+       {
+               /* WATCH: acn = asoc - 1 ! */
+               if((asoc = info[i].asoc) == 0) continue;
 
-       cn = info[i].cn; typ = info[i].typ; acn = asoc - 1;
+               cn = info[i].cn; typ = info[i].typ; acn = asoc - 1;
 
-       if(cn != acn)
-  {
-       opj_image_comp_t saved;
+               if(cn != acn)
+               {
+                       opj_image_comp_t saved;
 
-       memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t));
-       memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t));
-       memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t));
+                       memcpy(&saved, &image->comps[cn], sizeof(opj_image_comp_t));
+                       memcpy(&image->comps[cn], &image->comps[acn], sizeof(opj_image_comp_t));
+                       memcpy(&image->comps[acn], &saved, sizeof(opj_image_comp_t));
+
+                       info[i].asoc = cn + 1;
+                       info[acn].asoc = info[acn].cn + 1;
+               }
+       }
 
-       info[i].asoc = cn + 1;
-       info[acn].asoc = info[acn].cn + 1;
-  }
-   }
        if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info);
 
        opj_free(color->jp2_cdef); color->jp2_cdef = NULL;
@@ -1156,11 +1161,11 @@ static opj_bool jp2_read_cdef_v2(       opj_jp2_v2_t * jp2,
         * inside a JP2 Header box.'*/
        if(jp2->color.jp2_cdef) return OPJ_FALSE;
 
-       opj_read_bytes(p_cdef_header_data,&l_value ,1);                 /* N */
-       ++p_cdef_header_data;
+       opj_read_bytes(p_cdef_header_data,&l_value ,2);                 /* N */
+       p_cdef_header_data+= 2;
 
        if ( (OPJ_UINT16)l_value == 0){ /* szukw000: FIXME */
-               opj_event_msg_v2(p_manager, EVT_ERROR, "Number of component description is equal to zero in CDEF box.\n");
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Number of channel description is equal to zero in CDEF box.\n");
                return OPJ_FALSE;
        }
 
@@ -1317,7 +1322,7 @@ static opj_bool jp2_read_colr_v2( opj_jp2_v2_t * jp2,
 
        }
        else // TODO MSD
-               opj_event_msg_v2(p_manager, EVT_INFO, "COLR BOX meth value is not is not a regular value (%d), so we will skip the fields following approx field.\n", jp2->meth);
+               opj_event_msg_v2(p_manager, EVT_INFO, "COLR BOX meth value is not a regular value (%d), so we will skip the fields following the approx field.\n", jp2->meth);
 
        jp2->color.jp2_has_colr = 1;
 
@@ -1467,7 +1472,7 @@ opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio,
        if( !color.jp2_pclr->cmap) 
         jp2_free_pclr(&color);
        else
-        jp2_apply_pclr(&color, image);
+        jp2_apply_pclr(image, &color);
    }
        if(color.icc_profile_buf)
    {
@@ -1479,6 +1484,48 @@ opj_image_t* opj_jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio,
 
 }/* opj_jp2_decode() */
 
+opj_bool opj_jp2_decode_v2(    opj_jp2_v2_t *jp2,
+                                                       struct opj_stream_private *cio,
+                                                       opj_image_t* p_image,
+                                                       struct opj_event_mgr * p_manager)
+{
+       /* J2K decoding */
+       if( j2k_decode_v2(jp2->j2k, cio, p_image, p_manager) ) {
+               opj_event_msg_v2(p_manager, EVT_ERROR, "Failed to decode J2K image\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;
+       }
+
+       return OPJ_TRUE;
+}
+
 
 void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
        opj_jp2_box_t box;
@@ -1659,7 +1706,7 @@ static int write_fidx( int offset_jp2c, int length_jp2c, int offset_idx, int len
   cio_skip( cio, 4);              /* L [at the end] */
   cio_write( cio, JPIP_FIDX, 4);  /* IPTR           */
   
-  write_prxy( offset_jp2c, length_jp2c, offset_idx, offset_jp2c, cio);
+  write_prxy( offset_jp2c, length_jp2c, offset_idx, length_idx, cio);
 
   len = cio_tell( cio)-lenp;
   cio_seek( cio, lenp);
@@ -1750,11 +1797,12 @@ void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) {
        /* further JP2 initializations go here */
 }
 
-void jp2_setup_decoder_v2(opj_jp2_v2_t *jp2, opj_dparameters_t *parameters) {
+void jp2_setup_decoder_v2(opj_jp2_v2_t *jp2, opj_dparameters_t *parameters)
+{
        /* setup the J2K codec */
        j2k_setup_decoder_v2(jp2->j2k, parameters);
-       /* further JP2 initializations go here */
 
+       /* further JP2 initializations go here */
        jp2->color.jp2_has_colr = 0;
 }
 
@@ -1861,7 +1909,7 @@ void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_
 
 opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
 
-       int pos_iptr, pos_cidx, pos_jp2c, len_jp2c, end_pos, pos_fidx, len_fidx;
+       int pos_iptr, pos_cidx, pos_jp2c, len_jp2c, len_cidx, end_pos, pos_fidx, len_fidx;
 
        /* JP2 encoding */
 
@@ -1888,10 +1936,10 @@ opj_bool opj_jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_
        if( jp2->jpip_on){
          pos_cidx = cio_tell( cio);
          
-         write_cidx( pos_jp2c+8, cio, image, *cstr_info, len_jp2c-8);
+         len_cidx = write_cidx( pos_jp2c+8, cio, image, *cstr_info, len_jp2c-8);
          
          pos_fidx = cio_tell( cio);
-         len_fidx = write_fidx( pos_jp2c, len_jp2c, pos_cidx, cio_tell(cio), cio);
+         len_fidx = write_fidx( pos_jp2c, len_jp2c, pos_cidx, len_cidx, cio);
          
          end_pos = cio_tell( cio);
          
@@ -2273,7 +2321,7 @@ opj_bool jp2_read_jp2h_v2(
                }
 
                if (box.length > p_header_size) {
-                       opj_event_msg_v2(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box\n");
+                       opj_event_msg_v2(p_manager, EVT_ERROR, "Stream error while reading JP2 Header box: box length is inconsistent.\n");
                        return OPJ_FALSE;
                }
 
@@ -2389,8 +2437,7 @@ static opj_bool jp2_read_boxhdr_char(
  */
 opj_bool jp2_read_header(      struct opj_stream_private *p_stream,
                                                        opj_jp2_v2_t *jp2,
-                                                       opj_image_header_t ** p_image_header,
-                                                       struct opj_codestream_info** p_cstr_info,
+                                                       opj_image_t* p_image,
                                                        struct opj_event_mgr * p_manager
                                                        )
 {
@@ -2417,8 +2464,7 @@ opj_bool jp2_read_header( struct opj_stream_private *p_stream,
 
        return j2k_read_header( p_stream,
                                                        jp2->j2k,
-                                                       p_image_header,
-                                                       p_cstr_info,
+                                                       p_image,
                                                        p_manager);
 }
 
@@ -2453,27 +2499,21 @@ void jp2_setup_header_reading (opj_jp2_v2_t *jp2)
  * @param      p_stream                        the stream to write data to.
  * @param      p_manager       the user event manager.
  */
-opj_bool jp2_read_tile_header (
-                                        opj_jp2_v2_t * p_jp2,
-                                        OPJ_UINT32 * p_tile_index,
-                                        OPJ_UINT32 * p_data_size,
-                                        OPJ_INT32 * p_tile_x0,
-                                        OPJ_INT32 * p_tile_y0,
-                                        OPJ_INT32 * p_tile_x1,
-                                        OPJ_INT32 * p_tile_y1,
-                                        OPJ_UINT32 * p_nb_comps,
-                                        opj_bool * p_go_on,
-                                        opj_stream_private_t *p_stream,
-                                        opj_event_mgr_t * p_manager
-                                       )
+opj_bool jp2_read_tile_header( opj_jp2_v2_t * p_jp2,
+                                                               OPJ_UINT32 * p_tile_index,
+                                                               OPJ_UINT32 * p_data_size,
+                                                               OPJ_INT32 * p_tile_x0, OPJ_INT32 * p_tile_y0,
+                                                               OPJ_INT32 * p_tile_x1, OPJ_INT32 * p_tile_y1,
+                                                               OPJ_UINT32 * p_nb_comps,
+                                                               opj_bool * p_go_on,
+                                                               opj_stream_private_t *p_stream,
+                                                               opj_event_mgr_t * p_manager )
 {
-       return j2k_read_tile_header (p_jp2->j2k,
+       return j2k_read_tile_header(p_jp2->j2k,
                                                                p_tile_index,
                                                                p_data_size,
-                                                               p_tile_x0,
-                                                               p_tile_y0,
-                                                               p_tile_x1,
-                                                               p_tile_y1,
+                                                               p_tile_x0, p_tile_y0,
+                                                               p_tile_x1, p_tile_y1,
                                                                p_nb_comps,
                                                                p_go_on,
                                                                p_stream,
@@ -2560,16 +2600,12 @@ void jp2_destroy(opj_jp2_v2_t *jp2)
  *
  * @return     true                    if the area could be set.
  */
-opj_bool jp2_set_decode_area(
-                       opj_jp2_v2_t *p_jp2,
-                       OPJ_INT32 p_start_x,
-                       OPJ_INT32 p_start_y,
-                       OPJ_INT32 p_end_x,
-                       OPJ_INT32 p_end_y,
-                       struct opj_event_mgr * p_manager
-                       )
+opj_bool jp2_set_decode_area(  opj_jp2_v2_t *p_jp2,
+                                                               OPJ_INT32 p_start_x, OPJ_INT32 p_start_y,
+                                                               OPJ_INT32 p_end_x, OPJ_INT32 p_end_y,
+                                                               struct opj_event_mgr * p_manager )
 {
-       return j2k_set_decode_area(p_jp2->j2k,p_start_x,p_start_y,p_end_x,p_end_y,p_manager);
+       return j2k_set_decode_area(p_jp2->j2k, p_start_x, p_start_y, p_end_x, p_end_y, p_manager);
 }
 
 /* ----------------------------------------------------------------------- */