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