1 /*=========================================================================
4 Module: $RCSfile: gdcmJpeg2000.cxx,v $
6 Date: $Date: 2008/05/24 12:24:04 $
7 Version: $Revision: 1.48 $
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
27 #include <stdio.h> // for fprintf
28 #include <stdlib.h> // for abort
34 namespace GDCM_NAME_SPACE
36 //-----------------------------------------------------------------------------
38 * \brief routine for JPEG decompression
40 * @param inputdata inputdata
41 * @param inputlength inputlength
42 * @return 1 on success, 0 on error
46 sample error callback expecting a FILE* client object
49 void error_callback(const char *msg, void *) {
50 std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
53 sample warning callback expecting a FILE* client object
55 void warning_callback(const char *msg, void *) {
56 std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
59 sample debug callback expecting no client object
61 void info_callback(const char *msg, void *) {
62 std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
76 * Divide an integer by a power of 2 and round upwards.
80 inline int int_ceildivpow2(int a, int b) {
81 return (a + (1 << b) - 1) >> b;
85 * The following function was copy paste from j2k_to_image.c with part from convert.c
87 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
89 opj_dparameters_t parameters; /* decompression parameters */
90 opj_event_mgr_t event_mgr; /* event manager */
92 opj_dinfo_t* dinfo; /* handle to a decompressor */
94 unsigned char *src = (unsigned char*)inputdata;
95 int file_length = static_cast< int >( inputlength );
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;
103 /* set decoding parameters to default values */
104 opj_set_default_decoder_parameters(¶meters);
106 // default blindly copied
107 parameters.cp_layer=0;
108 parameters.cp_reduce=0;
109 // parameters.decod_format=-1;
110 // parameters.cod_format=-1;
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);
118 /* get a decoder handle */
119 dinfo = opj_create_decompress(CODEC_J2K);
121 /* catch events using our callbacks and give a local context */
122 opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);
124 /* setup the decoder decoding parameters using user parameters */
125 opj_setup_decoder(dinfo, ¶meters);
127 /* open a byte stream */
128 cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
130 /* decode the stream and fill the image structure */
131 image = opj_decode(dinfo, cio);
133 opj_destroy_decompress(dinfo);
138 /* close the byte stream */
141 /* free the memory containing the code-stream */
142 delete[] src; //FIXME
145 for (int compno = 0; compno < image->numcomps; compno++)
147 opj_image_comp_t *comp = &image->comps[compno];
149 int w = image->comps[compno].w;
150 int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor);
152 //int h = image.comps[compno].h;
153 int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor);
157 uint8_t *data8 = (uint8_t*)raw + compno;
158 for (int i = 0; i < wr * hr; i++)
160 int v = image->comps[compno].data[i / wr * w + i % wr];
162 data8 += image->numcomps;
165 else if (comp->prec <= 16)
167 uint16_t *data16 = (uint16_t*)raw + compno;
168 for (int i = 0; i < wr * hr; i++)
170 int v = image->comps[compno].data[i / wr * w + i % wr];
171 *data16 = (uint16_t)v;
172 data16 += image->numcomps;
177 uint32_t *data32 = (uint32_t*)raw + compno;
178 for (int i = 0; i < wr * hr; i++)
180 int v = image->comps[compno].data[i / wr * w + i % wr];
181 *data32 = (uint32_t)v;
182 data32 += image->numcomps;
185 //free(image.comps[compno].data);
189 /* free remaining structures */
191 opj_destroy_decompress(dinfo);
194 /* free image data structure */
195 opj_image_destroy(image);
201 void rawtoimage_fill(T *inputbuffer, int w, int h, int numcomps, opj_image_t *image)
204 for (int i = 0; i < w * h; i++)
206 for(int compno = 0; compno < numcomps; compno++)
208 /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */
209 image->comps[compno].data[i] = *p;
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)
223 OPJ_COLOR_SPACE color_space;
224 opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */
225 opj_image_t * image = NULL;
227 assert( sample_pixel == 1 || sample_pixel == 3 );
228 if( sample_pixel == 1 )
231 color_space = CLRSPC_GRAY;
233 else // sample_pixel == 3
236 color_space = CLRSPC_SRGB;
238 int subsampling_dx = parameters->subsampling_dx;
239 int subsampling_dy = parameters->subsampling_dy;
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;
258 /* create the image */
259 image = opj_image_create(numcomps, &cmptparm[0], color_space);
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;
271 //assert( fragment_size == numcomps*w*h*(bitsallocated/8) );
272 if (bitsallocated <= 8)
276 rawtoimage_fill<int8_t>((int8_t*)inputbuffer,w,h,numcomps,image);
280 rawtoimage_fill<uint8_t>((uint8_t*)inputbuffer,w,h,numcomps,image);
283 else if (bitsallocated <= 16)
287 rawtoimage_fill<int16_t>((int16_t*)inputbuffer,w,h,numcomps,image);
291 rawtoimage_fill<uint16_t>((uint16_t*)inputbuffer,w,h,numcomps,image);
294 else if (bitsallocated <= 32)
298 rawtoimage_fill<int32_t>((int32_t*)inputbuffer,w,h,numcomps,image);
302 rawtoimage_fill<uint32_t>((uint32_t*)inputbuffer,w,h,numcomps,image);
314 * The following function was copy paste from image_to_j2k.c with part from convert.c
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)
320 //// input_buffer is ONE image
321 //// fragment_size is the size of this image (fragment)
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;
331 configure the event callbacks (not required)
332 setting of each callback is optionnal
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;
339 /* set encoding parameters to default values */
340 memset(¶meters, 0, sizeof(parameters));
341 opj_set_default_encoder_parameters(¶meters);
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;
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;
357 /* decode the source image */
358 /* ----------------------- */
360 image = rawtoimage((char*)inputdata, ¶meters,
361 static_cast<int>( inputlength ),
362 image_width, image_height,
363 sample_pixel, bitsallocated, sign, quality);
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;
375 /* get a J2K compressor handle */
376 opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
378 /* catch events using our callbacks and give a local context */
379 opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
381 /* setup the encoder parameters using the current image and using user parameters */
382 opj_setup_encoder(cinfo, ¶meters, image);
384 /* open a byte stream for writing */
385 /* allocate memory for all tiles */
386 cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
388 /* encode the image */
389 bSuccess = opj_encode(cinfo, cio, image, parameters.index);
392 fprintf(stderr, "failed to encode image\n");
395 codestream_length = cio_tell(cio);
397 /* write the buffer to disk */
398 //f = fopen(parameters.outfile, "wb");
400 // fprintf(stderr, "failed to open %s for writing\n", parameters.outfile);
403 //fwrite(cio->buffer, 1, codestream_length, f);
407 std::ostringstream os;
412 std::ofstream debug(os.str().c_str());
413 debug.write((char*)(cio->buffer), codestream_length);
416 fp->write((char*)(cio->buffer), codestream_length);
419 /* close and free the byte stream */
422 /* free remaining compression structures */
423 opj_destroy_compress(cinfo);
426 /* free user parameters structure */
427 //if(delete_comment) {
428 if(parameters.cp_comment) free(parameters.cp_comment);
430 if(parameters.cp_matrice) free(parameters.cp_matrice);
432 /* free image data */
433 opj_image_destroy(image);
443 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
448 // default blindly copied
454 cp.cod_format=J2K_CFMT;
455 cp.decod_format = PGX_DFMT;
456 int len = inputlength;
457 unsigned char *src = (unsigned char*)inputdata;
460 if (!j2k_decode(src, len, &img, &cp))
462 gdcmStaticErrorMacro( "ERROR -> j2k_to_image: failed to decode image!" );
467 for (int compno = 0; compno < img.numcomps; compno++)
469 j2k_comp_t *comp = &img.comps[compno];
471 int w = img.comps[compno].w;
472 int wr = int_ceildivpow2(img.comps[compno].w, img.comps[compno].factor);
474 //int h = img.comps[compno].h;
475 int hr = int_ceildivpow2(img.comps[compno].h, img.comps[compno].factor);
479 uint8_t *data8 = (uint8_t*)raw;
480 for (int i = 0; i < wr * hr; i++)
482 int v = img.comps[compno].data[i / wr * w + i % wr];
483 *data8++ = (uint8_t)v;
486 else if (comp->prec <= 16)
488 uint16_t *data16 = (uint16_t*)raw;
489 for (int i = 0; i < wr * hr; i++)
491 int v = img.comps[compno].data[i / wr * w + i % wr];
492 *data16++ = (uint16_t)v;
497 uint32_t *data32 = (uint32_t*)raw;
498 for (int i = 0; i < wr * hr; i++)
500 int v = img.comps[compno].data[i / wr * w + i % wr];
501 *data32++ = (uint32_t)v;
504 free(img.comps[compno].data);
507 // Free remaining structures
517 bool gdcm_read_JASPER_file (void* raw, char *inputdata, size_t inputlength)
520 std::cerr << "Inputlenght=" << inputlength << std::endl;
521 std::ofstream out("/tmp/jpeg2000.jpc", std::ios::binary);
522 out.write((char*)inputdata,inputlength);
525 jas_init(); //important...
526 jas_stream_t *jasStream =
527 jas_stream_memopen((char *)inputdata, inputlength);
530 if ((fmtid = jas_image_getfmt(jasStream)) < 0)
532 gdcmErrorMacro("unknown image format");
537 jas_image_t *jasImage /* = NULL*/; // Useless assignation
538 if (!(jasImage = jas_image_decode(jasStream, fmtid, 0)))
540 gdcmErrorMacro("cannot decode image");
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);
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
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 ));
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 ));
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 ));
580 jas_image_destroy(jasImage);
581 jas_image_clearfmts();
584 //delete the jpeg temp buffer
586 std::ofstream rawout("/tmp/jpeg2000.raw");
587 rawout.write((char*)raw,height*width*numcmpts*((prec+4)/8));
596 //-----------------------------------------------------------------------------
597 } // end namespace gdcm