]> Creatis software - gdcm.git/blob - src/gdcmJpeg2000.cxx
Forgot to blacklist :
[gdcm.git] / src / gdcmJpeg2000.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmJpeg2000.cxx,v $
5   Language:  C++
6   Date:      $Date: 2006/02/07 16:05:13 $
7   Version:   $Revision: 1.41 $
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;
88   opj_dinfo_t* dinfo;  /* handle to a decompressor */
89   opj_cio_t *cio;
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
140    // Copy buffer
141    for (int compno = 0; compno < image->numcomps; compno++)
142    {
143       opj_image_comp_t *comp = &image->comps[compno];
144   
145       int w = image->comps[compno].w;
146       int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor);
147   
148       //int h = image.comps[compno].h;
149       int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor);
150   
151       if (comp->prec <= 8)
152       {
153          uint8_t *data8 = (uint8_t*)raw;
154          for (int i = 0; i < wr * hr; i++) 
155          {
156             int v = image->comps[compno].data[i / wr * w + i % wr];
157             *data8++ = (uint8_t)v;
158          }
159       }
160       else if (comp->prec <= 16)
161       {
162          uint16_t *data16 = (uint16_t*)raw;
163          for (int i = 0; i < wr * hr; i++) 
164          {
165             int v = image->comps[compno].data[i / wr * w + i % wr];
166             *data16++ = (uint16_t)v;
167          }
168       }
169       else
170       {
171          uint32_t *data32 = (uint32_t*)raw;
172          for (int i = 0; i < wr * hr; i++) 
173          {
174             int v = image->comps[compno].data[i / wr * w + i % wr];
175             *data32++ = (uint32_t)v;
176          }
177       }
178       //free(image.comps[compno].data);
179    }
180  
181
182   /* free remaining structures */
183   if(dinfo) {
184     opj_destroy_decompress(dinfo);
185   }
186
187   /* free image data structure */
188   opj_image_destroy(image);
189
190   return true;
191 }
192
193 #if 0
194 // For openjpeg 0.97
195 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
196 {
197    j2k_image_t img;
198    j2k_cp_t cp;
199  
200    // default blindly copied
201    cp.layer=0;
202    cp.reduce=0;
203    cp.decod_format=-1;
204    cp.cod_format=-1;
205  
206    cp.cod_format=J2K_CFMT;
207    cp.decod_format = PGX_DFMT;
208    int len = inputlength;
209    unsigned char *src = (unsigned char*)inputdata;
210  
211    // Decompression
212    if (!j2k_decode(src, len, &img, &cp))
213    {
214       gdcmStaticErrorMacro( "ERROR -> j2k_to_image: failed to decode image!" );
215       return false;
216    }
217  
218    // Copy buffer
219    for (int compno = 0; compno < img.numcomps; compno++)
220    {
221       j2k_comp_t *comp = &img.comps[compno];
222   
223       int w = img.comps[compno].w;
224       int wr = int_ceildivpow2(img.comps[compno].w, img.comps[compno].factor);
225   
226       //int h = img.comps[compno].h;
227       int hr = int_ceildivpow2(img.comps[compno].h, img.comps[compno].factor);
228   
229       if (comp->prec <= 8)
230       {
231          uint8_t *data8 = (uint8_t*)raw;
232          for (int i = 0; i < wr * hr; i++) 
233          {
234             int v = img.comps[compno].data[i / wr * w + i % wr];
235             *data8++ = (uint8_t)v;
236          }
237       }
238       else if (comp->prec <= 16)
239       {
240          uint16_t *data16 = (uint16_t*)raw;
241          for (int i = 0; i < wr * hr; i++) 
242          {
243             int v = img.comps[compno].data[i / wr * w + i % wr];
244             *data16++ = (uint16_t)v;
245          }
246       }
247       else
248       {
249          uint32_t *data32 = (uint32_t*)raw;
250          for (int i = 0; i < wr * hr; i++) 
251          {
252             int v = img.comps[compno].data[i / wr * w + i % wr];
253             *data32++ = (uint32_t)v;
254          }
255       }
256       free(img.comps[compno].data);
257    }
258  
259    // Free remaining structures
260    j2k_dec_release();
261    // FIXME
262    delete[] inputdata;
263  
264    return true;
265 }
266 #endif
267
268 #if 0
269 bool gdcm_read_JASPER_file (void* raw, char *inputdata, size_t inputlength)
270 {
271 #if 0
272   std::cerr << "Inputlenght=" << inputlength << std::endl;
273   std::ofstream out("/tmp/jpeg2000.jpc", std::ios::binary);
274   out.write((char*)inputdata,inputlength);
275   out.close();
276 #endif
277   jas_init(); //important...
278   jas_stream_t *jasStream = 
279     jas_stream_memopen((char *)inputdata, inputlength);
280     
281   int fmtid;
282   if ((fmtid = jas_image_getfmt(jasStream)) < 0) 
283     {
284     gdcmErrorMacro("unknown image format");
285     return false;
286     }
287
288   // Decode the image. 
289   jas_image_t *jasImage /* = NULL*/; // Useless assignation
290   if (!(jasImage = jas_image_decode(jasStream, fmtid, 0))) 
291     {
292     gdcmErrorMacro("cannot decode image");
293     return false;
294     }
295
296   // close the stream. 
297   jas_stream_close(jasStream);
298   int numcmpts = jas_image_numcmpts(jasImage);
299   int width = jas_image_cmptwidth(jasImage, 0);
300   int height = jas_image_cmptheight(jasImage, 0);
301   int prec = jas_image_cmptprec(jasImage, 0);
302   int i, j, k;
303
304   // The following should serioulsy be rewritten I cannot believe we need to
305   // do a per pixel decompression, there should be a way to read a full
306   // scanline...
307   if (prec == 8)
308     {
309     uint8_t *data8 = (uint8_t*)raw;
310     for ( i = 0; i < height; i++)
311       for ( j = 0; j < width; j++)
312         for ( k= 0; k < numcmpts; k++)
313           *data8++ = (uint8_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
314     }
315   else if (prec <= 16)
316     {
317     uint16_t *data16 = (uint16_t*)raw;
318     for ( i = 0; i < height; i++) 
319       for ( j = 0; j < width; j++) 
320         for ( k= 0; k < numcmpts; k++)
321           *data16++ = (uint16_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
322     }
323   else if (prec <= 32)
324     {
325     uint32_t *data32 = (uint32_t*)raw;
326     for ( i = 0; i < height; i++) 
327       for ( j = 0; j < width; j++) 
328         for ( k= 0; k < numcmpts; k++)
329           *data32++ = (uint32_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
330     }
331
332   jas_image_destroy(jasImage);
333   jas_image_clearfmts();
334
335   //FIXME
336   //delete the jpeg temp buffer
337 #if 0
338   std::ofstream rawout("/tmp/jpeg2000.raw");
339   rawout.write((char*)raw,height*width*numcmpts*((prec+4)/8));
340   rawout.close();
341 #endif
342   delete[] inputdata;
343
344   return true;
345 }
346 #endif
347
348 //-----------------------------------------------------------------------------
349 } // end namespace gdcm
350