]> Creatis software - gdcm.git/blob - src/gdcmJpeg2000.cxx
#include <algorithm>
[gdcm.git] / src / gdcmJpeg2000.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmJpeg2000.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/08/22 16:14:04 $
7   Version:   $Revision: 1.45 $
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 sample error callback expecting a FILE* client object
64 */
65 void error_callback(const char *msg, void *) {
66   std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
67 }
68 /**
69 sample warning callback expecting a FILE* client object
70 */
71 void warning_callback(const char *msg, void *) {
72   std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
73 }
74 /**
75 sample debug callback expecting no client object
76 */
77 void info_callback(const char *msg, void *) {
78   std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
79 }
80
81 #define J2K_CFMT 0
82 #define JP2_CFMT 1
83 #define JPT_CFMT 2
84 #define MJ2_CFMT 3
85 #define PXM_DFMT 0
86 #define PGX_DFMT 1
87 #define BMP_DFMT 2
88 #define YUV_DFMT 3
89
90 /*
91  * Divide an integer by a power of 2 and round upwards.
92  *
93  * a divided by 2^b
94  */
95 inline int int_ceildivpow2(int a, int b) {
96   return (a + (1 << b) - 1) >> b;
97 }
98
99 /*
100  * The following function was copy paste from j2k_to_image.c with part from convert.c
101  */
102 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
103 {
104   opj_dparameters_t parameters;  /* decompression parameters */
105   opj_event_mgr_t event_mgr;    /* event manager */
106   opj_image_t *image;
107   opj_dinfo_t* dinfo;  /* handle to a decompressor */
108   opj_cio_t *cio;
109   unsigned char *src = (unsigned char*)inputdata; 
110   int file_length = static_cast< int >( inputlength );
111
112   /* configure the event callbacks (not required) */
113   memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
114   event_mgr.error_handler = error_callback;
115   event_mgr.warning_handler = warning_callback;
116   event_mgr.info_handler = info_callback;
117
118   /* set decoding parameters to default values */
119   opj_set_default_decoder_parameters(&parameters);
120  
121    // default blindly copied
122    parameters.cp_layer=0;
123    parameters.cp_reduce=0;
124 //   parameters.decod_format=-1;
125 //   parameters.cod_format=-1;
126
127       /* JPEG-2000 codestream */
128     parameters.decod_format = J2K_CFMT;
129     assert(parameters.decod_format == J2K_CFMT);
130   parameters.cod_format = PGX_DFMT;
131   assert(parameters.cod_format == PGX_DFMT);
132
133       /* get a decoder handle */
134       dinfo = opj_create_decompress(CODEC_J2K);
135
136       /* catch events using our callbacks and give a local context */
137       opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);
138
139       /* setup the decoder decoding parameters using user parameters */
140       opj_setup_decoder(dinfo, &parameters);
141
142       /* open a byte stream */
143       cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
144
145       /* decode the stream and fill the image structure */
146       image = opj_decode(dinfo, cio);
147       if(!image) {
148         opj_destroy_decompress(dinfo);
149         opj_cio_close(cio);
150         return 1;
151       }
152       
153       /* close the byte stream */
154       opj_cio_close(cio);
155
156   /* free the memory containing the code-stream */
157   delete[] src;  //FIXME
158
159    // Copy buffer
160    for (int compno = 0; compno < image->numcomps; compno++)
161    {
162       opj_image_comp_t *comp = &image->comps[compno];
163
164       int w = image->comps[compno].w;
165       int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor);
166
167       //int h = image.comps[compno].h;
168       int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor);
169
170       if (comp->prec <= 8)
171       {
172          uint8_t *data8 = (uint8_t*)raw + compno;
173          for (int i = 0; i < wr * hr; i++)
174          {
175             int v = image->comps[compno].data[i / wr * w + i % wr];
176             *data8 = (uint8_t)v;
177             data8 += image->numcomps;
178          }
179       }
180       else if (comp->prec <= 16)
181       {
182          uint16_t *data16 = (uint16_t*)raw + compno;
183          for (int i = 0; i < wr * hr; i++)
184          {
185             int v = image->comps[compno].data[i / wr * w + i % wr];
186             *data16 = (uint16_t)v;
187             data16 += image->numcomps;
188          }
189       }
190       else
191       {
192          uint32_t *data32 = (uint32_t*)raw + compno;
193          for (int i = 0; i < wr * hr; i++)
194          {
195             int v = image->comps[compno].data[i / wr * w + i % wr];
196             *data32 = (uint32_t)v;
197             data32 += image->numcomps;
198          }
199       }
200       //free(image.comps[compno].data);
201    }
202
203
204   /* free remaining structures */
205   if(dinfo) {
206     opj_destroy_decompress(dinfo);
207   }
208
209   /* free image data structure */
210   opj_image_destroy(image);
211
212   return true;
213 }
214
215 template<typename T>
216 void rawtoimage_fill(T *inputbuffer, int w, int h, int numcomps, opj_image_t *image)
217 {
218   T *p = inputbuffer;
219   for (int i = 0; i < w * h; i++)
220     {
221     for(int compno = 0; compno < numcomps; compno++)
222       {
223       /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */
224       image->comps[compno].data[i] = *p;
225       ++p;
226       }
227     }
228 }
229
230 opj_image_t* rawtoimage(char *inputbuffer, opj_cparameters_t *parameters,
231   int fragment_size, int image_width, int image_height, int sample_pixel,
232   int bitsallocated, int sign, int quality)
233 {
234   (void)quality;
235   (void)fragment_size;
236   int w, h;
237   int numcomps;
238   OPJ_COLOR_SPACE color_space;
239   opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */
240   opj_image_t * image = NULL;
241
242   assert( sample_pixel == 1 || sample_pixel == 3 );
243   if( sample_pixel == 1 )
244     {
245     numcomps = 1;
246     color_space = CLRSPC_GRAY;
247     }
248   else // sample_pixel == 3
249     {
250     numcomps = 3;
251     color_space = CLRSPC_SRGB;
252     }
253   int subsampling_dx = parameters->subsampling_dx;
254   int subsampling_dy = parameters->subsampling_dy;
255
256   // FIXME
257   w = image_width;
258   h = image_height;
259
260   /* initialize image components */
261   memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));
262   //assert( bitsallocated == 8 );
263   for(int i = 0; i < numcomps; i++) {
264     cmptparm[i].prec = bitsallocated;
265     cmptparm[i].bpp = bitsallocated;
266     cmptparm[i].sgnd = sign;
267     cmptparm[i].dx = subsampling_dx;
268     cmptparm[i].dy = subsampling_dy;
269     cmptparm[i].w = w;
270     cmptparm[i].h = h;
271   }
272
273   /* create the image */
274   image = opj_image_create(numcomps, &cmptparm[0], color_space);
275   if(!image) {
276     return NULL;
277   }
278   /* set image offset and reference grid */
279   image->x0 = parameters->image_offset_x0;
280   image->y0 = parameters->image_offset_y0;
281   image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1;
282   image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1;
283
284   /* set image data */
285
286   //assert( fragment_size == numcomps*w*h*(bitsallocated/8) );
287   if (bitsallocated <= 8)
288     {
289     if( sign )
290       {
291       rawtoimage_fill<int8_t>((int8_t*)inputbuffer,w,h,numcomps,image);
292       }
293     else
294       {
295       rawtoimage_fill<uint8_t>((uint8_t*)inputbuffer,w,h,numcomps,image);
296       }
297     }
298   else if (bitsallocated <= 16)
299     {
300     if( sign )
301       {
302       rawtoimage_fill<int16_t>((int16_t*)inputbuffer,w,h,numcomps,image);
303       }
304     else
305       {
306       rawtoimage_fill<uint16_t>((uint16_t*)inputbuffer,w,h,numcomps,image);
307       }
308     }
309   else if (bitsallocated <= 32)
310     {
311     if( sign )
312       {
313       rawtoimage_fill<int32_t>((int32_t*)inputbuffer,w,h,numcomps,image);
314       }
315     else
316       {
317       rawtoimage_fill<uint32_t>((uint32_t*)inputbuffer,w,h,numcomps,image);
318       }
319     }
320   else
321     {
322     abort();
323     }
324
325   return image;
326 }
327
328 /*
329  * The following function was copy paste from image_to_j2k.c with part from convert.c
330  */
331 bool gdcm_write_JPEG2000_file (std::ostream *fp, char *inputdata, size_t inputlength, 
332   int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated,
333   int sign, int quality)
334 {
335 //// input_buffer is ONE image
336 //// fragment_size is the size of this image (fragment)
337   (void)numZ;
338   bool bSuccess;
339   //bool delete_comment = true;
340   opj_cparameters_t parameters;  /* compression parameters */
341   opj_event_mgr_t event_mgr;    /* event manager */
342   opj_image_t *image = NULL;
343   //quality = 100;
344
345   /*
346   configure the event callbacks (not required)
347   setting of each callback is optionnal
348   */
349   memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
350   event_mgr.error_handler = error_callback;
351   event_mgr.warning_handler = warning_callback;
352   event_mgr.info_handler = info_callback;
353
354   /* set encoding parameters to default values */
355   memset(&parameters, 0, sizeof(parameters));
356   opj_set_default_encoder_parameters(&parameters);
357
358   /* if no rate entered, lossless by default */
359   parameters.tcp_rates[0] = 0;
360   parameters.tcp_numlayers = 1;
361   parameters.cp_disto_alloc = 1;
362
363   if(parameters.cp_comment == NULL) {
364     const char comment[] = "Created by GDCM/OpenJPEG version 1.0";
365     parameters.cp_comment = (char*)malloc(strlen(comment) + 1);
366     strcpy(parameters.cp_comment, comment);
367     /* no need to delete parameters.cp_comment on exit */
368     //delete_comment = false;
369   }
370
371   
372   /* decode the source image */
373   /* ----------------------- */
374
375   image = rawtoimage((char*)inputdata, &parameters, 
376     static_cast<int>( inputlength ), 
377     image_width, image_height,
378     sample_pixel, bitsallocated, sign, quality);
379   if (!image) {
380     return 1;
381   }
382
383     /* encode the destination image */
384   /* ---------------------------- */
385    parameters.cod_format = J2K_CFMT; /* J2K format output */
386     int codestream_length;
387     opj_cio_t *cio = NULL;
388     //FILE *f = NULL;
389
390     /* get a J2K compressor handle */
391     opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
392
393     /* catch events using our callbacks and give a local context */
394     opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
395
396     /* setup the encoder parameters using the current image and using user parameters */
397     opj_setup_encoder(cinfo, &parameters, image);
398
399     /* open a byte stream for writing */
400     /* allocate memory for all tiles */
401     cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
402
403     /* encode the image */
404     bSuccess = opj_encode(cinfo, cio, image, parameters.index);
405     if (!bSuccess) {
406       opj_cio_close(cio);
407       fprintf(stderr, "failed to encode image\n");
408       return 1;
409     }
410     codestream_length = cio_tell(cio);
411
412     /* write the buffer to disk */
413     //f = fopen(parameters.outfile, "wb");
414     //if (!f) {
415     //  fprintf(stderr, "failed to open %s for writing\n", parameters.outfile);
416     //  return 1;
417     //}
418     //fwrite(cio->buffer, 1, codestream_length, f);
419 //#define MDEBUG
420 #ifdef MDEBUG
421     static int c = 0;
422     std::ostringstream os;
423     os << "/tmp/debug";
424     os << c;
425     c++;
426     os << ".j2k";
427     std::ofstream debug(os.str().c_str());
428     debug.write((char*)(cio->buffer), codestream_length);
429     debug.close();
430 #endif
431     fp->write((char*)(cio->buffer), codestream_length);
432     //fclose(f);
433
434     /* close and free the byte stream */
435     opj_cio_close(cio);
436
437     /* free remaining compression structures */
438     opj_destroy_compress(cinfo);
439
440
441       /* free user parameters structure */
442   //if(delete_comment) {
443     if(parameters.cp_comment) free(parameters.cp_comment);
444   //}
445   if(parameters.cp_matrice) free(parameters.cp_matrice);
446
447   /* free image data */
448   opj_image_destroy(image);
449
450
451
452
453   return true;
454 }
455
456 #if 0
457 // For openjpeg 0.97
458 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
459 {
460    j2k_image_t img;
461    j2k_cp_t cp;
462  
463    // default blindly copied
464    cp.layer=0;
465    cp.reduce=0;
466    cp.decod_format=-1;
467    cp.cod_format=-1;
468  
469    cp.cod_format=J2K_CFMT;
470    cp.decod_format = PGX_DFMT;
471    int len = inputlength;
472    unsigned char *src = (unsigned char*)inputdata;
473  
474    // Decompression
475    if (!j2k_decode(src, len, &img, &cp))
476    {
477       gdcmStaticErrorMacro( "ERROR -> j2k_to_image: failed to decode image!" );
478       return false;
479    }
480  
481    // Copy buffer
482    for (int compno = 0; compno < img.numcomps; compno++)
483    {
484       j2k_comp_t *comp = &img.comps[compno];
485   
486       int w = img.comps[compno].w;
487       int wr = int_ceildivpow2(img.comps[compno].w, img.comps[compno].factor);
488   
489       //int h = img.comps[compno].h;
490       int hr = int_ceildivpow2(img.comps[compno].h, img.comps[compno].factor);
491   
492       if (comp->prec <= 8)
493       {
494          uint8_t *data8 = (uint8_t*)raw;
495          for (int i = 0; i < wr * hr; i++) 
496          {
497             int v = img.comps[compno].data[i / wr * w + i % wr];
498             *data8++ = (uint8_t)v;
499          }
500       }
501       else if (comp->prec <= 16)
502       {
503          uint16_t *data16 = (uint16_t*)raw;
504          for (int i = 0; i < wr * hr; i++) 
505          {
506             int v = img.comps[compno].data[i / wr * w + i % wr];
507             *data16++ = (uint16_t)v;
508          }
509       }
510       else
511       {
512          uint32_t *data32 = (uint32_t*)raw;
513          for (int i = 0; i < wr * hr; i++) 
514          {
515             int v = img.comps[compno].data[i / wr * w + i % wr];
516             *data32++ = (uint32_t)v;
517          }
518       }
519       free(img.comps[compno].data);
520    }
521  
522    // Free remaining structures
523    j2k_dec_release();
524    // FIXME
525    delete[] inputdata;
526  
527    return true;
528 }
529 #endif
530
531 #if 0
532 bool gdcm_read_JASPER_file (void* raw, char *inputdata, size_t inputlength)
533 {
534 #if 0
535   std::cerr << "Inputlenght=" << inputlength << std::endl;
536   std::ofstream out("/tmp/jpeg2000.jpc", std::ios::binary);
537   out.write((char*)inputdata,inputlength);
538   out.close();
539 #endif
540   jas_init(); //important...
541   jas_stream_t *jasStream = 
542     jas_stream_memopen((char *)inputdata, inputlength);
543     
544   int fmtid;
545   if ((fmtid = jas_image_getfmt(jasStream)) < 0) 
546     {
547     gdcmErrorMacro("unknown image format");
548     return false;
549     }
550
551   // Decode the image. 
552   jas_image_t *jasImage /* = NULL*/; // Useless assignation
553   if (!(jasImage = jas_image_decode(jasStream, fmtid, 0))) 
554     {
555     gdcmErrorMacro("cannot decode image");
556     return false;
557     }
558
559   // close the stream. 
560   jas_stream_close(jasStream);
561   int numcmpts = jas_image_numcmpts(jasImage);
562   int width = jas_image_cmptwidth(jasImage, 0);
563   int height = jas_image_cmptheight(jasImage, 0);
564   int prec = jas_image_cmptprec(jasImage, 0);
565   int i, j, k;
566
567   // The following should serioulsy be rewritten I cannot believe we need to
568   // do a per pixel decompression, there should be a way to read a full
569   // scanline...
570   if (prec == 8)
571     {
572     uint8_t *data8 = (uint8_t*)raw;
573     for ( i = 0; i < height; i++)
574       for ( j = 0; j < width; j++)
575         for ( k= 0; k < numcmpts; k++)
576           *data8++ = (uint8_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
577     }
578   else if (prec <= 16)
579     {
580     uint16_t *data16 = (uint16_t*)raw;
581     for ( i = 0; i < height; i++) 
582       for ( j = 0; j < width; j++) 
583         for ( k= 0; k < numcmpts; k++)
584           *data16++ = (uint16_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
585     }
586   else if (prec <= 32)
587     {
588     uint32_t *data32 = (uint32_t*)raw;
589     for ( i = 0; i < height; i++) 
590       for ( j = 0; j < width; j++) 
591         for ( k= 0; k < numcmpts; k++)
592           *data32++ = (uint32_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
593     }
594
595   jas_image_destroy(jasImage);
596   jas_image_clearfmts();
597
598   //FIXME
599   //delete the jpeg temp buffer
600 #if 0
601   std::ofstream rawout("/tmp/jpeg2000.raw");
602   rawout.write((char*)raw,height*width*numcmpts*((prec+4)/8));
603   rawout.close();
604 #endif
605   delete[] inputdata;
606
607   return true;
608 }
609 #endif
610
611 //-----------------------------------------------------------------------------
612 } // end namespace gdcm
613