Change CMakeLists.txt to build examples by default (image_to_j2k and j2k_to_image).
[openjpeg.git] / libopenjpeg / jp2.c
index 14e572f208b9f2ef1c3da6fc1414732313e3b2de..b2831cfb0b5940d9b4594bb4d90a53aca528e0dd 100644 (file)
@@ -1,7 +1,10 @@
 /*
- * Copyright (c) 2004, Yannick Verschueren
- * Copyright (c) 2005, Herv� Drolon, FreeImage Team
- * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,7 +45,7 @@ Read box headers
 @return Returns true if successful, returns false otherwise
 */
 static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box);
-static void jp2_write_url(opj_cio_t *cio, char *Idx_file);
+/*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/
 /**
 Read the IHDR box - Image Header box
 @param jp2 JP2 handle
@@ -56,19 +59,6 @@ static bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio);
 static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio);
 static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio);
 /**
-Write the JP2H box - JP2 Header box
-@param jp2 JP2 handle
-@param cio Output buffer stream
-*/
-static void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio);
-/**
-Read the JP2H box - JP2 Header box
-@param jp2 JP2 handle
-@param cio Input buffer stream
-@return Returns true if successful, returns false otherwise
-*/
-static bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio);
-/**
 Write the FTYP box - File type box
 @param jp2 JP2 handle
 @param cio Output buffer stream
@@ -81,7 +71,7 @@ Read the FTYP box - File type box
 @return Returns true if successful, returns false otherwise
 */
 static bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio);
-static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, char *index);
+static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
 static 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);
 /**
@@ -125,6 +115,7 @@ static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t
        return true;
 }
 
+#if 0
 static void jp2_write_url(opj_cio_t *cio, char *Idx_file) {
        unsigned int i;
        opj_jp2_box_t box;
@@ -146,6 +137,7 @@ static void jp2_write_url(opj_cio_t *cio, char *Idx_file) {
        cio_write(cio, box.length, 4);  /* L */
        cio_seek(cio, box.init_pos + box.length);
 }
+#endif
 
 static bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) {
        opj_jp2_box_t box;
@@ -161,6 +153,7 @@ static bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) {
        jp2->h = cio_read(cio, 4);                      /* HEIGHT */
        jp2->w = cio_read(cio, 4);                      /* WIDTH */
        jp2->numcomps = cio_read(cio, 2);       /* NC */
+       jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t));
 
        jp2->bpc = cio_read(cio, 1);            /* BPC */
 
@@ -302,7 +295,7 @@ static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio) {
        return true;
 }
 
-static void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
+void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
        opj_jp2_box_t box;
 
        box.init_pos = cio_tell(cio);
@@ -322,7 +315,7 @@ static void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
        cio_seek(cio, box.init_pos + box.length);
 }
 
-static bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
+bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
        opj_jp2_box_t box;
        int skip_len;
 
@@ -411,12 +404,11 @@ static bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) {
        return true;
 }
 
-static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, char *index) {
+static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
        unsigned int j2k_codestream_offset, j2k_codestream_length;
        opj_jp2_box_t box;
 
        opj_j2k_t *j2k = jp2->j2k;
-       opj_image_t *image = jp2->image;
 
        box.init_pos = cio_tell(cio);
        cio_skip(cio, 4);
@@ -424,7 +416,7 @@ static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, char *index) {
 
        /* J2K encoding */
        j2k_codestream_offset = cio_tell(cio);
-       if(!j2k_encode(j2k, cio, image, index)) {
+       if(!j2k_encode(j2k, cio, image, cstr_info)) {
                opj_event_msg(j2k->cinfo, EVT_ERROR, "Failed to encode image\n");
                return 0;
        }
@@ -515,7 +507,7 @@ static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio) {
 /* ----------------------------------------------------------------------- */
 
 opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo) {
-       opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t));
+       opj_jp2_t *jp2 = (opj_jp2_t*) opj_calloc(1, sizeof(opj_jp2_t));
        if(jp2) {
                jp2->cinfo = cinfo;
                /* create the J2K codec */
@@ -549,7 +541,7 @@ void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) {
        /* further JP2 initializations go here */
 }
 
-opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio) {
+opj_image_t* 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;
 
@@ -566,11 +558,22 @@ opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio) {
        }
 
        /* J2K decoding */
-       image = j2k_decode(jp2->j2k, cio);
+       image = j2k_decode(jp2->j2k, cio, cstr_info);
        if(!image) {
                opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n");
+               return NULL;
        }
 
+       /* 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;
+
        return image;
 }
 
@@ -617,6 +620,12 @@ void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_
        /* setup the J2K codec */
        /* ------------------- */
 
+       /* Check if number of components respects standard */
+       if (image->numcomps < 1 || image->numcomps > 16384) {
+               opj_event_msg(jp2->cinfo, EVT_ERROR, "Invalid number of components specified while setting up JP2 encoder\n");
+               return;
+       }
+
        j2k_setup_encoder(jp2->j2k, parameters, image);
 
        /* setup the JP2 codec */
@@ -632,8 +641,6 @@ void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_
 
        /* Image Header box */
 
-       jp2->image = image;
-
        jp2->numcomps = image->numcomps;        /* NC */
        jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t));
        jp2->h = image->y1 - image->y0;         /* HEIGHT */
@@ -680,7 +687,7 @@ void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_
 
 }
 
-bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, char *index) {
+bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
 
        /* JP2 encoding */
 
@@ -693,7 +700,7 @@ bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, char *index)
 
        /* J2K encoding */
 
-       if(!jp2_write_jp2c(jp2, cio, index)) {
+       if(!jp2_write_jp2c(jp2, cio, image, cstr_info)) {
                opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n");
                return false;
        }