start using API style in openJPIP library
[openjpeg.git] / applications / jpip / libopenjpip / jp2k_decoder.c
1 /*
2  * $Id: jp2k_decoder.c 53 2011-05-09 16:55:39Z kaori $
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 "jp2k_decoder.h"
35 #include "openjpeg.h"
36
37
38 void error_callback(const char *msg, void *client_data);
39 void warning_callback(const char *msg, void *client_data);
40 void info_callback(const char *msg, void *client_data);
41
42 Byte_t * imagetopnm(opj_image_t *image, ihdrbox_param_t **ihdrbox);
43
44 Byte_t * j2k_to_pnm( Byte_t *j2kstream, Byte8_t j2klen, ihdrbox_param_t **ihdrbox)
45 {
46   Byte_t *pnmstream = NULL;
47   opj_dparameters_t parameters; /* decompression parameters */
48   opj_event_mgr_t event_mgr;            /* event manager */
49   opj_image_t *image = NULL;
50   opj_dinfo_t* dinfo = NULL;    /* handle to a decompressor */
51   opj_cio_t *cio = NULL;
52
53   /* configure the event callbacks (not required) */
54   memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
55   event_mgr.error_handler = error_callback;
56   event_mgr.warning_handler = warning_callback;
57   event_mgr.info_handler = info_callback;
58
59   /* set decoding parameters to default values */
60   opj_set_default_decoder_parameters(&parameters);
61
62   /* decode the code-stream */
63   /* ---------------------- */
64
65   /* JPEG-2000 codestream */
66   /* get a decoder handle */
67   dinfo = opj_create_decompress( CODEC_J2K);
68
69   /* catch events using our callbacks and give a local context */
70   opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
71
72   /* setup the decoder decoding parameters using user parameters */
73   opj_setup_decoder(dinfo, &parameters);
74   /* open a byte stream */
75   cio = opj_cio_open((opj_common_ptr)dinfo, j2kstream, j2klen);
76
77   fprintf( stderr, "opj_decode dinfo:%p cio:%p\n", dinfo, cio);
78   /* decode the stream and fill the image structure */
79   image = opj_decode(dinfo, cio);
80
81   fprintf( stderr, "done\n");
82   if(!image) {
83     fprintf(stderr, "ERROR -> jp2_to_image: failed to decode image!\n");
84     opj_destroy_decompress(dinfo);
85     opj_cio_close(cio);
86     return NULL;
87   }
88
89   /* close the byte stream */
90   opj_cio_close(cio);
91   
92   /* create output image */
93   /* ------------------- */
94   if( (pnmstream = imagetopnm( image, ihdrbox))==NULL)
95     fprintf( stderr, "PNM image not generated\n");
96
97   /* free remaining structures */
98   if(dinfo) {
99     opj_destroy_decompress(dinfo);
100   }
101
102   /* free image data structure */
103   opj_image_destroy(image);
104   
105   return pnmstream;
106 }
107
108
109 /**
110    sample error callback expecting a FILE* client object
111 */
112 void error_callback(const char *msg, void *client_data) {
113   FILE *stream = (FILE*)client_data;
114   fprintf(stream, "[ERROR] %s", msg);
115 }
116 /**
117    sample warning callback expecting a FILE* client object
118 */
119 void warning_callback(const char *msg, void *client_data) {
120   FILE *stream = (FILE*)client_data;
121   fprintf(stream, "[WARNING] %s", msg);
122 }
123 /**
124    sample debug callback expecting no client object
125 */
126 void info_callback(const char *msg, void *client_data) {
127   (void)client_data;
128   //  fprintf(stdout, "[INFO] %s", msg);
129 }
130
131
132 Byte_t * imagetopnm(opj_image_t *image, ihdrbox_param_t **ihdrbox)
133 {
134   int adjustR, adjustG=0, adjustB=0;
135   int datasize;
136   Byte_t *pix=NULL, *ptr=NULL;
137   int i;
138   
139   if(*ihdrbox){
140     if( (*ihdrbox)->nc != image->numcomps)
141       fprintf( stderr, "Exception: num of components not identical, codestream: %d, ihdrbox: %d\n", image->numcomps, (*ihdrbox)->nc);
142
143     if( (*ihdrbox)->width != image->comps[0].w)
144       (*ihdrbox)->width = image->comps[0].w;
145     
146     if( (*ihdrbox)->height != image->comps[0].h)
147       (*ihdrbox)->height = image->comps[0].h;
148
149     if( (*ihdrbox)->bpc != image->comps[0].prec)
150       fprintf( stderr, "Exception: bits per component not identical, codestream: %d, ihdrbox: %d\n", image->comps[0].prec, (*ihdrbox)->bpc);
151   }
152   else{
153     *ihdrbox = (ihdrbox_param_t *)malloc( sizeof(ihdrbox_param_t));
154     (*ihdrbox)->width  = image->comps[0].w;
155     (*ihdrbox)->height = image->comps[0].h;
156     (*ihdrbox)->bpc    = image->comps[0].prec;
157     (*ihdrbox)->nc     = image->numcomps;
158   }
159   
160   datasize = (image->numcomps)*(image->comps[0].w)*(image->comps[0].h);
161   
162   if (image->comps[0].prec > 8) {
163     adjustR = image->comps[0].prec - 8;
164     printf("PNM CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec);
165   }
166   else
167     adjustR = 0;
168   
169   if( image->numcomps == 3){
170     if (image->comps[1].prec > 8) {
171       adjustG = image->comps[1].prec - 8;
172       printf("PNM CONVERSION: Truncating component 1 from %d bits to 8 bits\n", image->comps[1].prec);
173     }
174     else 
175       adjustG = 0;
176     
177     if (image->comps[2].prec > 8) {
178       adjustB = image->comps[2].prec - 8;
179       printf("PNM CONVERSION: Truncating component 2 from %d bits to 8 bits\n", image->comps[2].prec);
180     }
181     else 
182       adjustB = 0;
183   }
184
185   pix = (Byte_t *)malloc( datasize);
186   ptr = pix;
187
188   for( i = 0; i < image->comps[0].w * image->comps[0].h; i++){
189     int r, g, b;
190     r = image->comps[0].data[i];
191     r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
192     
193     //    if( adjustR > 0)
194     *(ptr++) = (Byte_t) ((r >> adjustR)+((r >> (adjustR-1))%2));
195
196     if( image->numcomps == 3){
197       g = image->comps[1].data[i];
198       g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
199       *(ptr++) = (Byte_t) ((g >> adjustG)+((g >> (adjustG-1))%2));
200       
201       b = image->comps[2].data[i];
202       b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
203       *(ptr++) = (Byte_t) ((b >> adjustB)+((b >> (adjustB-1))%2));
204     }
205   }
206
207   return pix;
208 }