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