1 /*=========================================================================
4 Module: $RCSfile: gdcmJpeg2000.cxx,v $
6 Date: $Date: 2007/08/22 16:14:04 $
7 Version: $Revision: 1.45 $
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
32 sample error callback expecting a FILE* client object
34 void error_callback(const char *msg, void *) {
35 std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
38 sample warning callback expecting a FILE* client object
40 void warning_callback(const char *msg, void *) {
41 std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
44 sample debug callback expecting no client object
46 void info_callback(const char *msg, void *) {
47 std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
51 namespace GDCM_NAME_SPACE
53 //-----------------------------------------------------------------------------
55 * \brief routine for JPEG decompression
57 * @param inputdata inputdata
58 * @param inputlength inputlength
59 * @return 1 on success, 0 on error
63 sample error callback expecting a FILE* client object
65 void error_callback(const char *msg, void *) {
66 std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
69 sample warning callback expecting a FILE* client object
71 void warning_callback(const char *msg, void *) {
72 std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
75 sample debug callback expecting no client object
77 void info_callback(const char *msg, void *) {
78 std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
91 * Divide an integer by a power of 2 and round upwards.
95 inline int int_ceildivpow2(int a, int b) {
96 return (a + (1 << b) - 1) >> b;
100 * The following function was copy paste from j2k_to_image.c with part from convert.c
102 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
104 opj_dparameters_t parameters; /* decompression parameters */
105 opj_event_mgr_t event_mgr; /* event manager */
107 opj_dinfo_t* dinfo; /* handle to a decompressor */
109 unsigned char *src = (unsigned char*)inputdata;
110 int file_length = static_cast< int >( inputlength );
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;
118 /* set decoding parameters to default values */
119 opj_set_default_decoder_parameters(¶meters);
121 // default blindly copied
122 parameters.cp_layer=0;
123 parameters.cp_reduce=0;
124 // parameters.decod_format=-1;
125 // parameters.cod_format=-1;
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);
133 /* get a decoder handle */
134 dinfo = opj_create_decompress(CODEC_J2K);
136 /* catch events using our callbacks and give a local context */
137 opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);
139 /* setup the decoder decoding parameters using user parameters */
140 opj_setup_decoder(dinfo, ¶meters);
142 /* open a byte stream */
143 cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
145 /* decode the stream and fill the image structure */
146 image = opj_decode(dinfo, cio);
148 opj_destroy_decompress(dinfo);
153 /* close the byte stream */
156 /* free the memory containing the code-stream */
157 delete[] src; //FIXME
160 for (int compno = 0; compno < image->numcomps; compno++)
162 opj_image_comp_t *comp = &image->comps[compno];
164 int w = image->comps[compno].w;
165 int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor);
167 //int h = image.comps[compno].h;
168 int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor);
172 uint8_t *data8 = (uint8_t*)raw + compno;
173 for (int i = 0; i < wr * hr; i++)
175 int v = image->comps[compno].data[i / wr * w + i % wr];
177 data8 += image->numcomps;
180 else if (comp->prec <= 16)
182 uint16_t *data16 = (uint16_t*)raw + compno;
183 for (int i = 0; i < wr * hr; i++)
185 int v = image->comps[compno].data[i / wr * w + i % wr];
186 *data16 = (uint16_t)v;
187 data16 += image->numcomps;
192 uint32_t *data32 = (uint32_t*)raw + compno;
193 for (int i = 0; i < wr * hr; i++)
195 int v = image->comps[compno].data[i / wr * w + i % wr];
196 *data32 = (uint32_t)v;
197 data32 += image->numcomps;
200 //free(image.comps[compno].data);
204 /* free remaining structures */
206 opj_destroy_decompress(dinfo);
209 /* free image data structure */
210 opj_image_destroy(image);
216 void rawtoimage_fill(T *inputbuffer, int w, int h, int numcomps, opj_image_t *image)
219 for (int i = 0; i < w * h; i++)
221 for(int compno = 0; compno < numcomps; compno++)
223 /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */
224 image->comps[compno].data[i] = *p;
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)
238 OPJ_COLOR_SPACE color_space;
239 opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */
240 opj_image_t * image = NULL;
242 assert( sample_pixel == 1 || sample_pixel == 3 );
243 if( sample_pixel == 1 )
246 color_space = CLRSPC_GRAY;
248 else // sample_pixel == 3
251 color_space = CLRSPC_SRGB;
253 int subsampling_dx = parameters->subsampling_dx;
254 int subsampling_dy = parameters->subsampling_dy;
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;
273 /* create the image */
274 image = opj_image_create(numcomps, &cmptparm[0], color_space);
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;
286 //assert( fragment_size == numcomps*w*h*(bitsallocated/8) );
287 if (bitsallocated <= 8)
291 rawtoimage_fill<int8_t>((int8_t*)inputbuffer,w,h,numcomps,image);
295 rawtoimage_fill<uint8_t>((uint8_t*)inputbuffer,w,h,numcomps,image);
298 else if (bitsallocated <= 16)
302 rawtoimage_fill<int16_t>((int16_t*)inputbuffer,w,h,numcomps,image);
306 rawtoimage_fill<uint16_t>((uint16_t*)inputbuffer,w,h,numcomps,image);
309 else if (bitsallocated <= 32)
313 rawtoimage_fill<int32_t>((int32_t*)inputbuffer,w,h,numcomps,image);
317 rawtoimage_fill<uint32_t>((uint32_t*)inputbuffer,w,h,numcomps,image);
329 * The following function was copy paste from image_to_j2k.c with part from convert.c
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)
335 //// input_buffer is ONE image
336 //// fragment_size is the size of this image (fragment)
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;
346 configure the event callbacks (not required)
347 setting of each callback is optionnal
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;
354 /* set encoding parameters to default values */
355 memset(¶meters, 0, sizeof(parameters));
356 opj_set_default_encoder_parameters(¶meters);
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;
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;
372 /* decode the source image */
373 /* ----------------------- */
375 image = rawtoimage((char*)inputdata, ¶meters,
376 static_cast<int>( inputlength ),
377 image_width, image_height,
378 sample_pixel, bitsallocated, sign, quality);
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;
390 /* get a J2K compressor handle */
391 opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
393 /* catch events using our callbacks and give a local context */
394 opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
396 /* setup the encoder parameters using the current image and using user parameters */
397 opj_setup_encoder(cinfo, ¶meters, image);
399 /* open a byte stream for writing */
400 /* allocate memory for all tiles */
401 cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
403 /* encode the image */
404 bSuccess = opj_encode(cinfo, cio, image, parameters.index);
407 fprintf(stderr, "failed to encode image\n");
410 codestream_length = cio_tell(cio);
412 /* write the buffer to disk */
413 //f = fopen(parameters.outfile, "wb");
415 // fprintf(stderr, "failed to open %s for writing\n", parameters.outfile);
418 //fwrite(cio->buffer, 1, codestream_length, f);
422 std::ostringstream os;
427 std::ofstream debug(os.str().c_str());
428 debug.write((char*)(cio->buffer), codestream_length);
431 fp->write((char*)(cio->buffer), codestream_length);
434 /* close and free the byte stream */
437 /* free remaining compression structures */
438 opj_destroy_compress(cinfo);
441 /* free user parameters structure */
442 //if(delete_comment) {
443 if(parameters.cp_comment) free(parameters.cp_comment);
445 if(parameters.cp_matrice) free(parameters.cp_matrice);
447 /* free image data */
448 opj_image_destroy(image);
458 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
463 // default blindly copied
469 cp.cod_format=J2K_CFMT;
470 cp.decod_format = PGX_DFMT;
471 int len = inputlength;
472 unsigned char *src = (unsigned char*)inputdata;
475 if (!j2k_decode(src, len, &img, &cp))
477 gdcmStaticErrorMacro( "ERROR -> j2k_to_image: failed to decode image!" );
482 for (int compno = 0; compno < img.numcomps; compno++)
484 j2k_comp_t *comp = &img.comps[compno];
486 int w = img.comps[compno].w;
487 int wr = int_ceildivpow2(img.comps[compno].w, img.comps[compno].factor);
489 //int h = img.comps[compno].h;
490 int hr = int_ceildivpow2(img.comps[compno].h, img.comps[compno].factor);
494 uint8_t *data8 = (uint8_t*)raw;
495 for (int i = 0; i < wr * hr; i++)
497 int v = img.comps[compno].data[i / wr * w + i % wr];
498 *data8++ = (uint8_t)v;
501 else if (comp->prec <= 16)
503 uint16_t *data16 = (uint16_t*)raw;
504 for (int i = 0; i < wr * hr; i++)
506 int v = img.comps[compno].data[i / wr * w + i % wr];
507 *data16++ = (uint16_t)v;
512 uint32_t *data32 = (uint32_t*)raw;
513 for (int i = 0; i < wr * hr; i++)
515 int v = img.comps[compno].data[i / wr * w + i % wr];
516 *data32++ = (uint32_t)v;
519 free(img.comps[compno].data);
522 // Free remaining structures
532 bool gdcm_read_JASPER_file (void* raw, char *inputdata, size_t inputlength)
535 std::cerr << "Inputlenght=" << inputlength << std::endl;
536 std::ofstream out("/tmp/jpeg2000.jpc", std::ios::binary);
537 out.write((char*)inputdata,inputlength);
540 jas_init(); //important...
541 jas_stream_t *jasStream =
542 jas_stream_memopen((char *)inputdata, inputlength);
545 if ((fmtid = jas_image_getfmt(jasStream)) < 0)
547 gdcmErrorMacro("unknown image format");
552 jas_image_t *jasImage /* = NULL*/; // Useless assignation
553 if (!(jasImage = jas_image_decode(jasStream, fmtid, 0)))
555 gdcmErrorMacro("cannot decode image");
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);
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
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 ));
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 ));
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 ));
595 jas_image_destroy(jasImage);
596 jas_image_clearfmts();
599 //delete the jpeg temp buffer
601 std::ofstream rawout("/tmp/jpeg2000.raw");
602 rawout.write((char*)raw,height*width*numcmpts*((prec+4)/8));
611 //-----------------------------------------------------------------------------
612 } // end namespace gdcm