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