[trunk] propagate the new OPJ_ symbol and type to openjpip
[openjpeg.git] / src / lib / openjpip / jp2k_decoder.c
1 /*
2  * $Id$
3  *
4  * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2011, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <assert.h>
35 #include <limits.h>
36 #include "jp2k_decoder.h"
37 #include "openjpeg.h"
38
39
40 static void error_callback(const char *msg, void *client_data);
41 static void warning_callback(const char *msg, void *client_data);
42 static void info_callback(const char *msg, void *client_data);
43
44 static Byte_t * imagetopnm(opj_image_t *image, ihdrbox_param_t **ihdrbox);
45
46 Byte_t * j2k_to_pnm( FILE *fp, ihdrbox_param_t **ihdrbox)
47 {
48   Byte_t *pnmstream = NULL;
49   opj_dparameters_t parameters; /* decompression parameters */
50   opj_image_t *image = NULL;
51   opj_codec_t *l_codec = NULL;  /* handle to a decompressor */
52   opj_stream_t *l_stream = NULL;
53
54
55
56   /* set decoding parameters to default values */
57   opj_set_default_decoder_parameters(&parameters);
58
59   /* set a byte stream */
60   l_stream = opj_stream_create_default_file_stream( fp, 1);
61   if (!l_stream){
62     fprintf(stderr, "ERROR -> failed to create the stream from the file\n");
63     return NULL;
64   }
65
66   /* decode the code-stream */
67   /* ---------------------- */
68
69   /* JPEG-2000 codestream */
70   /* get a decoder handle */
71   l_codec = opj_create_decompress(OPJ_CODEC_J2K);
72
73   /* catch events using our callbacks and give a local context */
74   opj_set_info_handler(l_codec, info_callback,00);
75   opj_set_warning_handler(l_codec, warning_callback,00);
76   opj_set_error_handler(l_codec, error_callback,00);
77
78   /* setup the decoder decoding parameters using user parameters */
79   if ( !opj_setup_decoder(l_codec, &parameters) ){
80     fprintf(stderr, "ERROR -> j2k_dump: failed to setup the decoder\n");
81     return NULL;
82   }
83
84   /* Read the main header of the codestream and if necessary the JP2 boxes*/
85   if(! opj_read_header( l_stream, l_codec, &image)){
86     fprintf(stderr, "ERROR -> j2k_to_image: failed to read the header\n");
87     opj_stream_destroy(l_stream);
88     opj_destroy_codec(l_codec);
89     opj_image_destroy(image);
90     return NULL;
91   }
92
93 #ifdef TODO /*decode area could be set from j2k_to_pnm call, modify the protocol between JPIP viewer and opj_dec_server*/
94   if (! opj_set_decode_area( l_codec, image, parameters.DA_x0, parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)){
95     fprintf(stderr, "ERROR -> j2k_to_image: failed to set the decoded area\n");
96     opj_stream_destroy(l_stream);
97     opj_destroy_codec(l_codec);
98     opj_image_destroy(image);
99     return NULL;
100   }
101 #endif /*TODO*/
102
103   /* Get the decoded image */
104   if ( !( opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec,l_stream) ) ) {
105     fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n");
106     opj_stream_destroy(l_stream);
107     opj_destroy_codec(l_codec);
108     opj_image_destroy(image);
109     return NULL;
110   }
111
112   fprintf(stderr, "image is decoded!\n");
113
114   /* close the byte stream */
115   opj_stream_destroy(l_stream);
116   
117   /* create output image */
118   /* ------------------- */
119   if( (pnmstream = imagetopnm( image, ihdrbox))==NULL)
120     fprintf( stderr, "PNM image not generated\n");
121
122   /* free remaining structures */
123   if(l_codec) {
124     opj_destroy_codec(l_codec);
125   }
126
127   /* free image data structure */
128   opj_image_destroy(image);
129   
130   return pnmstream;
131 }
132
133
134 /**
135    sample error callback expecting a FILE* client object
136 */
137 static void error_callback(const char *msg, void *client_data) {
138   FILE *stream = (FILE*)client_data;
139   fprintf(stream, "[ERROR] %s", msg);
140 }
141 /**
142    sample warning callback expecting a FILE* client object
143 */
144 static void warning_callback(const char *msg, void *client_data) {
145   FILE *stream = (FILE*)client_data;
146   fprintf(stream, "[WARNING] %s", msg);
147 }
148 /**
149    sample debug callback expecting no client object
150 */
151 static void info_callback(const char *msg, void *client_data) {
152   (void)client_data;
153   (void)msg;
154   /*  fprintf(stdout, "[INFO] %s", msg); */
155 }
156
157
158 static Byte_t * imagetopnm(opj_image_t *image, ihdrbox_param_t **ihdrbox)
159 {
160   OPJ_UINT32 adjustR, adjustG=0, adjustB=0;
161   OPJ_SIZE_T datasize;
162   Byte_t *pix=NULL, *ptr=NULL;
163   OPJ_UINT32 i;
164   
165   if(*ihdrbox){
166     if( (*ihdrbox)->nc != image->numcomps)
167       fprintf( stderr, "Exception: num of components not identical, codestream: %d, ihdrbox: %d\n", image->numcomps, (*ihdrbox)->nc);
168
169     if( (*ihdrbox)->width != image->comps[0].w)
170       (*ihdrbox)->width = image->comps[0].w;
171     
172     if( (*ihdrbox)->height != image->comps[0].h)
173       (*ihdrbox)->height = image->comps[0].h;
174
175     if( (*ihdrbox)->bpc != image->comps[0].prec)
176       fprintf( stderr, "Exception: bits per component not identical, codestream: %d, ihdrbox: %d\n", image->comps[0].prec, (*ihdrbox)->bpc);
177   }
178   else{
179     *ihdrbox = (ihdrbox_param_t *)malloc( sizeof(ihdrbox_param_t));
180     (*ihdrbox)->width  = image->comps[0].w;
181     (*ihdrbox)->height = image->comps[0].h;
182     assert( image->comps[0].prec < 256 );
183     (*ihdrbox)->bpc    = (Byte_t)image->comps[0].prec;
184     assert( image->numcomps < USHRT_MAX );
185     (*ihdrbox)->nc     = (Byte2_t)image->numcomps;
186   }
187   
188   datasize = (image->numcomps)*(image->comps[0].w)*(image->comps[0].h);
189   
190   if (image->comps[0].prec > 8) {
191     adjustR = image->comps[0].prec - 8;
192     printf("PNM CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec);
193   }
194   else
195     adjustR = 0;
196   
197   if( image->numcomps == 3){
198     if (image->comps[1].prec > 8) {
199       adjustG = image->comps[1].prec - 8;
200       printf("PNM CONVERSION: Truncating component 1 from %d bits to 8 bits\n", image->comps[1].prec);
201     }
202     else 
203       adjustG = 0;
204     
205     if (image->comps[2].prec > 8) {
206       adjustB = image->comps[2].prec - 8;
207       printf("PNM CONVERSION: Truncating component 2 from %d bits to 8 bits\n", image->comps[2].prec);
208     }
209     else 
210       adjustB = 0;
211   }
212
213   pix = (Byte_t *)malloc( datasize);
214   ptr = pix;
215
216   for( i = 0; i < image->comps[0].w * image->comps[0].h; i++){
217     int r, g, b;
218     r = image->comps[0].data[i];
219     r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
220     
221     /*    if( adjustR > 0) */
222     *(ptr++) = (Byte_t) ((r >> adjustR)+((r >> (adjustR-1))%2));
223
224     if( image->numcomps == 3){
225       g = image->comps[1].data[i];
226       g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
227       *(ptr++) = (Byte_t) ((g >> adjustG)+((g >> (adjustG-1))%2));
228       
229       b = image->comps[2].data[i];
230       b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
231       *(ptr++) = (Byte_t) ((b >> adjustB)+((b >> (adjustB-1))%2));
232     }
233   }
234
235   return pix;
236 }