1 /*=========================================================================
4 Module: $RCSfile: gdcmJpeg2000.cxx,v $
6 Date: $Date: 2007/10/25 07:52:59 $
7 Version: $Revision: 1.46 $
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.
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.
17 =========================================================================*/
18 #include "gdcmFileHelper.h"
19 #include "gdcmDebug.h"
24 #if defined(__BORLANDC__)
25 #include <mem.h> // for memset
33 sample error callback expecting a FILE* client object
35 void error_callback(const char *msg, void *) {
36 std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
39 sample warning callback expecting a FILE* client object
41 void warning_callback(const char *msg, void *) {
42 std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
45 sample debug callback expecting no client object
47 void info_callback(const char *msg, void *) {
48 std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
52 namespace GDCM_NAME_SPACE
54 //-----------------------------------------------------------------------------
56 * \brief routine for JPEG decompression
58 * @param inputdata inputdata
59 * @param inputlength inputlength
60 * @return 1 on success, 0 on error
64 sample error callback expecting a FILE* client object
66 void error_callback(const char *msg, void *) {
67 std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
70 sample warning callback expecting a FILE* client object
72 void warning_callback(const char *msg, void *) {
73 std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
76 sample debug callback expecting no client object
78 void info_callback(const char *msg, void *) {
79 std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
92 * Divide an integer by a power of 2 and round upwards.
96 inline int int_ceildivpow2(int a, int b) {
97 return (a + (1 << b) - 1) >> b;
101 * The following function was copy paste from j2k_to_image.c with part from convert.c
103 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
105 opj_dparameters_t parameters; /* decompression parameters */
106 opj_event_mgr_t event_mgr; /* event manager */
108 opj_dinfo_t* dinfo; /* handle to a decompressor */
110 unsigned char *src = (unsigned char*)inputdata;
111 int file_length = static_cast< int >( inputlength );
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;
119 /* set decoding parameters to default values */
120 opj_set_default_decoder_parameters(¶meters);
122 // default blindly copied
123 parameters.cp_layer=0;
124 parameters.cp_reduce=0;
125 // parameters.decod_format=-1;
126 // parameters.cod_format=-1;
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);
134 /* get a decoder handle */
135 dinfo = opj_create_decompress(CODEC_J2K);
137 /* catch events using our callbacks and give a local context */
138 opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);
140 /* setup the decoder decoding parameters using user parameters */
141 opj_setup_decoder(dinfo, ¶meters);
143 /* open a byte stream */
144 cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
146 /* decode the stream and fill the image structure */
147 image = opj_decode(dinfo, cio);
149 opj_destroy_decompress(dinfo);
154 /* close the byte stream */
157 /* free the memory containing the code-stream */
158 delete[] src; //FIXME
161 for (int compno = 0; compno < image->numcomps; compno++)
163 opj_image_comp_t *comp = &image->comps[compno];
165 int w = image->comps[compno].w;
166 int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor);
168 //int h = image.comps[compno].h;
169 int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor);
173 uint8_t *data8 = (uint8_t*)raw + compno;
174 for (int i = 0; i < wr * hr; i++)
176 int v = image->comps[compno].data[i / wr * w + i % wr];
178 data8 += image->numcomps;
181 else if (comp->prec <= 16)
183 uint16_t *data16 = (uint16_t*)raw + compno;
184 for (int i = 0; i < wr * hr; i++)
186 int v = image->comps[compno].data[i / wr * w + i % wr];
187 *data16 = (uint16_t)v;
188 data16 += image->numcomps;
193 uint32_t *data32 = (uint32_t*)raw + compno;
194 for (int i = 0; i < wr * hr; i++)
196 int v = image->comps[compno].data[i / wr * w + i % wr];
197 *data32 = (uint32_t)v;
198 data32 += image->numcomps;
201 //free(image.comps[compno].data);
205 /* free remaining structures */
207 opj_destroy_decompress(dinfo);
210 /* free image data structure */
211 opj_image_destroy(image);
217 void rawtoimage_fill(T *inputbuffer, int w, int h, int numcomps, opj_image_t *image)
220 for (int i = 0; i < w * h; i++)
222 for(int compno = 0; compno < numcomps; compno++)
224 /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */
225 image->comps[compno].data[i] = *p;
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)
239 OPJ_COLOR_SPACE color_space;
240 opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */
241 opj_image_t * image = NULL;
243 assert( sample_pixel == 1 || sample_pixel == 3 );
244 if( sample_pixel == 1 )
247 color_space = CLRSPC_GRAY;
249 else // sample_pixel == 3
252 color_space = CLRSPC_SRGB;
254 int subsampling_dx = parameters->subsampling_dx;
255 int subsampling_dy = parameters->subsampling_dy;
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;
274 /* create the image */
275 image = opj_image_create(numcomps, &cmptparm[0], color_space);
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;
287 //assert( fragment_size == numcomps*w*h*(bitsallocated/8) );
288 if (bitsallocated <= 8)
292 rawtoimage_fill<int8_t>((int8_t*)inputbuffer,w,h,numcomps,image);
296 rawtoimage_fill<uint8_t>((uint8_t*)inputbuffer,w,h,numcomps,image);
299 else if (bitsallocated <= 16)
303 rawtoimage_fill<int16_t>((int16_t*)inputbuffer,w,h,numcomps,image);
307 rawtoimage_fill<uint16_t>((uint16_t*)inputbuffer,w,h,numcomps,image);
310 else if (bitsallocated <= 32)
314 rawtoimage_fill<int32_t>((int32_t*)inputbuffer,w,h,numcomps,image);
318 rawtoimage_fill<uint32_t>((uint32_t*)inputbuffer,w,h,numcomps,image);
330 * The following function was copy paste from image_to_j2k.c with part from convert.c
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)
336 //// input_buffer is ONE image
337 //// fragment_size is the size of this image (fragment)
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;
347 configure the event callbacks (not required)
348 setting of each callback is optionnal
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;
355 /* set encoding parameters to default values */
356 memset(¶meters, 0, sizeof(parameters));
357 opj_set_default_encoder_parameters(¶meters);
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;
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;
373 /* decode the source image */
374 /* ----------------------- */
376 image = rawtoimage((char*)inputdata, ¶meters,
377 static_cast<int>( inputlength ),
378 image_width, image_height,
379 sample_pixel, bitsallocated, sign, quality);
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;
391 /* get a J2K compressor handle */
392 opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
394 /* catch events using our callbacks and give a local context */
395 opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
397 /* setup the encoder parameters using the current image and using user parameters */
398 opj_setup_encoder(cinfo, ¶meters, image);
400 /* open a byte stream for writing */
401 /* allocate memory for all tiles */
402 cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
404 /* encode the image */
405 bSuccess = opj_encode(cinfo, cio, image, parameters.index);
408 fprintf(stderr, "failed to encode image\n");
411 codestream_length = cio_tell(cio);
413 /* write the buffer to disk */
414 //f = fopen(parameters.outfile, "wb");
416 // fprintf(stderr, "failed to open %s for writing\n", parameters.outfile);
419 //fwrite(cio->buffer, 1, codestream_length, f);
423 std::ostringstream os;
428 std::ofstream debug(os.str().c_str());
429 debug.write((char*)(cio->buffer), codestream_length);
432 fp->write((char*)(cio->buffer), codestream_length);
435 /* close and free the byte stream */
438 /* free remaining compression structures */
439 opj_destroy_compress(cinfo);
442 /* free user parameters structure */
443 //if(delete_comment) {
444 if(parameters.cp_comment) free(parameters.cp_comment);
446 if(parameters.cp_matrice) free(parameters.cp_matrice);
448 /* free image data */
449 opj_image_destroy(image);
459 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
464 // default blindly copied
470 cp.cod_format=J2K_CFMT;
471 cp.decod_format = PGX_DFMT;
472 int len = inputlength;
473 unsigned char *src = (unsigned char*)inputdata;
476 if (!j2k_decode(src, len, &img, &cp))
478 gdcmStaticErrorMacro( "ERROR -> j2k_to_image: failed to decode image!" );
483 for (int compno = 0; compno < img.numcomps; compno++)
485 j2k_comp_t *comp = &img.comps[compno];
487 int w = img.comps[compno].w;
488 int wr = int_ceildivpow2(img.comps[compno].w, img.comps[compno].factor);
490 //int h = img.comps[compno].h;
491 int hr = int_ceildivpow2(img.comps[compno].h, img.comps[compno].factor);
495 uint8_t *data8 = (uint8_t*)raw;
496 for (int i = 0; i < wr * hr; i++)
498 int v = img.comps[compno].data[i / wr * w + i % wr];
499 *data8++ = (uint8_t)v;
502 else if (comp->prec <= 16)
504 uint16_t *data16 = (uint16_t*)raw;
505 for (int i = 0; i < wr * hr; i++)
507 int v = img.comps[compno].data[i / wr * w + i % wr];
508 *data16++ = (uint16_t)v;
513 uint32_t *data32 = (uint32_t*)raw;
514 for (int i = 0; i < wr * hr; i++)
516 int v = img.comps[compno].data[i / wr * w + i % wr];
517 *data32++ = (uint32_t)v;
520 free(img.comps[compno].data);
523 // Free remaining structures
533 bool gdcm_read_JASPER_file (void* raw, char *inputdata, size_t inputlength)
536 std::cerr << "Inputlenght=" << inputlength << std::endl;
537 std::ofstream out("/tmp/jpeg2000.jpc", std::ios::binary);
538 out.write((char*)inputdata,inputlength);
541 jas_init(); //important...
542 jas_stream_t *jasStream =
543 jas_stream_memopen((char *)inputdata, inputlength);
546 if ((fmtid = jas_image_getfmt(jasStream)) < 0)
548 gdcmErrorMacro("unknown image format");
553 jas_image_t *jasImage /* = NULL*/; // Useless assignation
554 if (!(jasImage = jas_image_decode(jasStream, fmtid, 0)))
556 gdcmErrorMacro("cannot decode image");
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);
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
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 ));
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 ));
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 ));
596 jas_image_destroy(jasImage);
597 jas_image_clearfmts();
600 //delete the jpeg temp buffer
602 std::ofstream rawout("/tmp/jpeg2000.raw");
603 rawout.write((char*)raw,height*width*numcmpts*((prec+4)/8));
612 //-----------------------------------------------------------------------------
613 } // end namespace gdcm