]> Creatis software - gdcm.git/blob - src/gdcmJpeg2000.cxx
Add #include for BCC
[gdcm.git] / src / gdcmJpeg2000.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmJpeg2000.cxx,v $
5   Language:  C++
6   Date:      $Date: 2006/01/27 10:01:34 $
7   Version:   $Revision: 1.40 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 #include "gdcmFileHelper.h"
19 #include "gdcmDebug.h"
20
21 #include <iostream>
22 #include <fstream>
23
24 #if defined(__BORLANDC__)
25    #include <mem.h> // for memset
26 #endif 
27
28 extern "C" {
29   #include <openjpeg.h>
30 }
31
32 namespace gdcm 
33 {
34 //-----------------------------------------------------------------------------
35  /**
36  * \brief   routine for JPEG decompression 
37  * @param raw raw
38  * @param inputdata inputdata
39  * @param inputlength inputlength 
40  * @return 1 on success, 0 on error
41  */
42
43 /**
44 sample error callback expecting a FILE* client object
45 */
46 void error_callback(const char *msg, void *) {
47   std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
48 }
49 /**
50 sample warning callback expecting a FILE* client object
51 */
52 void warning_callback(const char *msg, void *) {
53   std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
54 }
55 /**
56 sample debug callback expecting no client object
57 */
58 void info_callback(const char *msg, void *) {
59   std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
60 }
61
62 #define J2K_CFMT 0
63 #define JP2_CFMT 1
64 #define JPT_CFMT 2
65 #define MJ2_CFMT 3
66 #define PXM_DFMT 0
67 #define PGX_DFMT 1
68 #define BMP_DFMT 2
69 #define YUV_DFMT 3
70
71 /*
72  * Divide an integer by a power of 2 and round upwards.
73  *
74  * a divided by 2^b
75  */
76 inline int int_ceildivpow2(int a, int b) {
77   return (a + (1 << b) - 1) >> b;
78 }
79
80 /*
81  * The following function was copy paste from j2k_to_image.c with part from convert.c
82  */
83 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
84 {
85   opj_dparameters_t parameters;  /* decompression parameters */
86   opj_event_mgr_t event_mgr;    /* event manager */
87   opj_image_t *image = NULL;
88   opj_dinfo_t* dinfo = NULL;  /* handle to a decompressor */
89   opj_cio_t *cio = NULL;
90   unsigned char *src = (unsigned char*)inputdata; 
91   int file_length = inputlength;
92
93   /* configure the event callbacks (not required) */
94   memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
95   event_mgr.error_handler = error_callback;
96   event_mgr.warning_handler = warning_callback;
97   event_mgr.info_handler = info_callback;
98
99   /* set decoding parameters to default values */
100   opj_set_default_decoder_parameters(&parameters);
101  
102    // default blindly copied
103    parameters.cp_layer=0;
104    parameters.cp_reduce=0;
105 //   parameters.decod_format=-1;
106 //   parameters.cod_format=-1;
107
108       /* JPEG-2000 codestream */
109     parameters.decod_format = J2K_CFMT;
110     assert(parameters.decod_format == J2K_CFMT);
111   parameters.cod_format = PGX_DFMT;
112   assert(parameters.cod_format == PGX_DFMT);
113
114       /* get a decoder handle */
115       dinfo = opj_create_decompress(CODEC_J2K);
116       
117       /* catch events using our callbacks and give a local context */
118       opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);      
119
120       /* setup the decoder decoding parameters using user parameters */
121       opj_setup_decoder(dinfo, &parameters);
122
123       /* open a byte stream */
124       cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
125
126       /* decode the stream and fill the image structure */
127       image = opj_decode(dinfo, cio);
128       if(!image) {
129         opj_destroy_decompress(dinfo);
130         opj_cio_close(cio);
131         return 1;
132       }
133       
134       /* close the byte stream */
135       opj_cio_close(cio);
136
137   /* free the memory containing the code-stream */
138   delete[] src;  //FIXME
139   src = NULL;
140
141
142    // Copy buffer
143    for (int compno = 0; compno < image->numcomps; compno++)
144    {
145       opj_image_comp_t *comp = &image->comps[compno];
146   
147       int w = image->comps[compno].w;
148       int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor);
149   
150       //int h = image.comps[compno].h;
151       int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor);
152   
153       if (comp->prec <= 8)
154       {
155          uint8_t *data8 = (uint8_t*)raw;
156          for (int i = 0; i < wr * hr; i++) 
157          {
158             int v = image->comps[compno].data[i / wr * w + i % wr];
159             *data8++ = (uint8_t)v;
160          }
161       }
162       else if (comp->prec <= 16)
163       {
164          uint16_t *data16 = (uint16_t*)raw;
165          for (int i = 0; i < wr * hr; i++) 
166          {
167             int v = image->comps[compno].data[i / wr * w + i % wr];
168             *data16++ = (uint16_t)v;
169          }
170       }
171       else
172       {
173          uint32_t *data32 = (uint32_t*)raw;
174          for (int i = 0; i < wr * hr; i++) 
175          {
176             int v = image->comps[compno].data[i / wr * w + i % wr];
177             *data32++ = (uint32_t)v;
178          }
179       }
180       //free(image.comps[compno].data);
181    }
182  
183
184   /* free remaining structures */
185   if(dinfo) {
186     opj_destroy_decompress(dinfo);
187   }
188
189   /* free image data structure */
190   opj_image_destroy(image);
191
192   return true;
193 }
194
195 #if 0
196 // For openjpeg 0.97
197 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
198 {
199    j2k_image_t img;
200    j2k_cp_t cp;
201  
202    // default blindly copied
203    cp.layer=0;
204    cp.reduce=0;
205    cp.decod_format=-1;
206    cp.cod_format=-1;
207  
208    cp.cod_format=J2K_CFMT;
209    cp.decod_format = PGX_DFMT;
210    int len = inputlength;
211    unsigned char *src = (unsigned char*)inputdata;
212  
213    // Decompression
214    if (!j2k_decode(src, len, &img, &cp))
215    {
216       gdcmStaticErrorMacro( "ERROR -> j2k_to_image: failed to decode image!" );
217       return false;
218    }
219  
220    // Copy buffer
221    for (int compno = 0; compno < img.numcomps; compno++)
222    {
223       j2k_comp_t *comp = &img.comps[compno];
224   
225       int w = img.comps[compno].w;
226       int wr = int_ceildivpow2(img.comps[compno].w, img.comps[compno].factor);
227   
228       //int h = img.comps[compno].h;
229       int hr = int_ceildivpow2(img.comps[compno].h, img.comps[compno].factor);
230   
231       if (comp->prec <= 8)
232       {
233          uint8_t *data8 = (uint8_t*)raw;
234          for (int i = 0; i < wr * hr; i++) 
235          {
236             int v = img.comps[compno].data[i / wr * w + i % wr];
237             *data8++ = (uint8_t)v;
238          }
239       }
240       else if (comp->prec <= 16)
241       {
242          uint16_t *data16 = (uint16_t*)raw;
243          for (int i = 0; i < wr * hr; i++) 
244          {
245             int v = img.comps[compno].data[i / wr * w + i % wr];
246             *data16++ = (uint16_t)v;
247          }
248       }
249       else
250       {
251          uint32_t *data32 = (uint32_t*)raw;
252          for (int i = 0; i < wr * hr; i++) 
253          {
254             int v = img.comps[compno].data[i / wr * w + i % wr];
255             *data32++ = (uint32_t)v;
256          }
257       }
258       free(img.comps[compno].data);
259    }
260  
261    // Free remaining structures
262    j2k_dec_release();
263    // FIXME
264    delete[] inputdata;
265  
266    return true;
267 }
268 #endif
269
270 #if 0
271 bool gdcm_read_JASPER_file (void* raw, char *inputdata, size_t inputlength)
272 {
273 #if 0
274   std::cerr << "Inputlenght=" << inputlength << std::endl;
275   std::ofstream out("/tmp/jpeg2000.jpc", std::ios::binary);
276   out.write((char*)inputdata,inputlength);
277   out.close();
278 #endif
279   jas_init(); //important...
280   jas_stream_t *jasStream = 
281     jas_stream_memopen((char *)inputdata, inputlength);
282     
283   int fmtid;
284   if ((fmtid = jas_image_getfmt(jasStream)) < 0) 
285     {
286     gdcmErrorMacro("unknown image format");
287     return false;
288     }
289
290   // Decode the image. 
291   jas_image_t *jasImage /* = NULL*/; // Useless assignation
292   if (!(jasImage = jas_image_decode(jasStream, fmtid, 0))) 
293     {
294     gdcmErrorMacro("cannot decode image");
295     return false;
296     }
297
298   // close the stream. 
299   jas_stream_close(jasStream);
300   int numcmpts = jas_image_numcmpts(jasImage);
301   int width = jas_image_cmptwidth(jasImage, 0);
302   int height = jas_image_cmptheight(jasImage, 0);
303   int prec = jas_image_cmptprec(jasImage, 0);
304   int i, j, k;
305
306   // The following should serioulsy be rewritten I cannot believe we need to
307   // do a per pixel decompression, there should be a way to read a full
308   // scanline...
309   if (prec == 8)
310     {
311     uint8_t *data8 = (uint8_t*)raw;
312     for ( i = 0; i < height; i++)
313       for ( j = 0; j < width; j++)
314         for ( k= 0; k < numcmpts; k++)
315           *data8++ = (uint8_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
316     }
317   else if (prec <= 16)
318     {
319     uint16_t *data16 = (uint16_t*)raw;
320     for ( i = 0; i < height; i++) 
321       for ( j = 0; j < width; j++) 
322         for ( k= 0; k < numcmpts; k++)
323           *data16++ = (uint16_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
324     }
325   else if (prec <= 32)
326     {
327     uint32_t *data32 = (uint32_t*)raw;
328     for ( i = 0; i < height; i++) 
329       for ( j = 0; j < width; j++) 
330         for ( k= 0; k < numcmpts; k++)
331           *data32++ = (uint32_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
332     }
333
334   jas_image_destroy(jasImage);
335   jas_image_clearfmts();
336
337   //FIXME
338   //delete the jpeg temp buffer
339 #if 0
340   std::ofstream rawout("/tmp/jpeg2000.raw");
341   rawout.write((char*)raw,height*width*numcmpts*((prec+4)/8));
342   rawout.close();
343 #endif
344   delete[] inputdata;
345
346   return true;
347 }
348 #endif
349
350 //-----------------------------------------------------------------------------
351 } // end namespace gdcm
352