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