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