gdcmJpeg2000.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002                                                                                 
00003   Program:   gdcm
00004   Module:    $RCSfile: gdcmJpeg2000.cxx,v $
00005   Language:  C++
00006   Date:      $Date: 2007/08/22 16:14:04 $
00007   Version:   $Revision: 1.45 $
00008                                                                                 
00009   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
00010   l'Image). All rights reserved. See Doc/License.txt or
00011   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
00012                                                                                 
00013      This software is distributed WITHOUT ANY WARRANTY; without even
00014      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00015      PURPOSE.  See the above copyright notices for more information.
00016                                                                                 
00017 =========================================================================*/
00018 #include "gdcmFileHelper.h"
00019 #include "gdcmDebug.h"
00020 
00021 #include <iostream>
00022 #include <fstream>
00023 
00024 #if defined(__BORLANDC__)
00025    #include <mem.h> // for memset
00026 #endif
00027 
00028 extern "C" {
00029   #include <openjpeg.h>
00030 
00034 void error_callback(const char *msg, void *) {
00035   std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
00036 }
00040 void warning_callback(const char *msg, void *) {
00041   std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
00042 }
00046 void info_callback(const char *msg, void *) {
00047   std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
00048 }
00049 }
00050 
00051 namespace GDCM_NAME_SPACE 
00052 {
00053 //-----------------------------------------------------------------------------
00065 void error_callback(const char *msg, void *) {
00066   std::cerr << "Error in gdcmopenjpeg" << msg << std::endl;
00067 }
00071 void warning_callback(const char *msg, void *) {
00072   std::cerr << "Warning in gdcmopenjpeg" << msg << std::endl;
00073 }
00077 void info_callback(const char *msg, void *) {
00078   std::cerr << "Info in gdcmopenjpeg" << msg << std::endl;
00079 }
00080 
00081 #define J2K_CFMT 0
00082 #define JP2_CFMT 1
00083 #define JPT_CFMT 2
00084 #define MJ2_CFMT 3
00085 #define PXM_DFMT 0
00086 #define PGX_DFMT 1
00087 #define BMP_DFMT 2
00088 #define YUV_DFMT 3
00089 
00090 /*
00091  * Divide an integer by a power of 2 and round upwards.
00092  *
00093  * a divided by 2^b
00094  */
00095 inline int int_ceildivpow2(int a, int b) {
00096   return (a + (1 << b) - 1) >> b;
00097 }
00098 
00099 /*
00100  * The following function was copy paste from j2k_to_image.c with part from convert.c
00101  */
00102 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
00103 {
00104   opj_dparameters_t parameters;  /* decompression parameters */
00105   opj_event_mgr_t event_mgr;    /* event manager */
00106   opj_image_t *image;
00107   opj_dinfo_t* dinfo;  /* handle to a decompressor */
00108   opj_cio_t *cio;
00109   unsigned char *src = (unsigned char*)inputdata; 
00110   int file_length = static_cast< int >( inputlength );
00111 
00112   /* configure the event callbacks (not required) */
00113   memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
00114   event_mgr.error_handler = error_callback;
00115   event_mgr.warning_handler = warning_callback;
00116   event_mgr.info_handler = info_callback;
00117 
00118   /* set decoding parameters to default values */
00119   opj_set_default_decoder_parameters(&parameters);
00120  
00121    // default blindly copied
00122    parameters.cp_layer=0;
00123    parameters.cp_reduce=0;
00124 //   parameters.decod_format=-1;
00125 //   parameters.cod_format=-1;
00126 
00127       /* JPEG-2000 codestream */
00128     parameters.decod_format = J2K_CFMT;
00129     assert(parameters.decod_format == J2K_CFMT);
00130   parameters.cod_format = PGX_DFMT;
00131   assert(parameters.cod_format == PGX_DFMT);
00132 
00133       /* get a decoder handle */
00134       dinfo = opj_create_decompress(CODEC_J2K);
00135 
00136       /* catch events using our callbacks and give a local context */
00137       opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);
00138 
00139       /* setup the decoder decoding parameters using user parameters */
00140       opj_setup_decoder(dinfo, &parameters);
00141 
00142       /* open a byte stream */
00143       cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
00144 
00145       /* decode the stream and fill the image structure */
00146       image = opj_decode(dinfo, cio);
00147       if(!image) {
00148         opj_destroy_decompress(dinfo);
00149         opj_cio_close(cio);
00150         return 1;
00151       }
00152       
00153       /* close the byte stream */
00154       opj_cio_close(cio);
00155 
00156   /* free the memory containing the code-stream */
00157   delete[] src;  //FIXME
00158 
00159    // Copy buffer
00160    for (int compno = 0; compno < image->numcomps; compno++)
00161    {
00162       opj_image_comp_t *comp = &image->comps[compno];
00163 
00164       int w = image->comps[compno].w;
00165       int wr = int_ceildivpow2(image->comps[compno].w, image->comps[compno].factor);
00166 
00167       //int h = image.comps[compno].h;
00168       int hr = int_ceildivpow2(image->comps[compno].h, image->comps[compno].factor);
00169 
00170       if (comp->prec <= 8)
00171       {
00172          uint8_t *data8 = (uint8_t*)raw + compno;
00173          for (int i = 0; i < wr * hr; i++)
00174          {
00175             int v = image->comps[compno].data[i / wr * w + i % wr];
00176             *data8 = (uint8_t)v;
00177             data8 += image->numcomps;
00178          }
00179       }
00180       else if (comp->prec <= 16)
00181       {
00182          uint16_t *data16 = (uint16_t*)raw + compno;
00183          for (int i = 0; i < wr * hr; i++)
00184          {
00185             int v = image->comps[compno].data[i / wr * w + i % wr];
00186             *data16 = (uint16_t)v;
00187             data16 += image->numcomps;
00188          }
00189       }
00190       else
00191       {
00192          uint32_t *data32 = (uint32_t*)raw + compno;
00193          for (int i = 0; i < wr * hr; i++)
00194          {
00195             int v = image->comps[compno].data[i / wr * w + i % wr];
00196             *data32 = (uint32_t)v;
00197             data32 += image->numcomps;
00198          }
00199       }
00200       //free(image.comps[compno].data);
00201    }
00202 
00203 
00204   /* free remaining structures */
00205   if(dinfo) {
00206     opj_destroy_decompress(dinfo);
00207   }
00208 
00209   /* free image data structure */
00210   opj_image_destroy(image);
00211 
00212   return true;
00213 }
00214 
00215 template<typename T>
00216 void rawtoimage_fill(T *inputbuffer, int w, int h, int numcomps, opj_image_t *image)
00217 {
00218   T *p = inputbuffer;
00219   for (int i = 0; i < w * h; i++)
00220     {
00221     for(int compno = 0; compno < numcomps; compno++)
00222       {
00223       /* compno : 0 = GREY, (0, 1, 2) = (R, G, B) */
00224       image->comps[compno].data[i] = *p;
00225       ++p;
00226       }
00227     }
00228 }
00229 
00230 opj_image_t* rawtoimage(char *inputbuffer, opj_cparameters_t *parameters,
00231   int fragment_size, int image_width, int image_height, int sample_pixel,
00232   int bitsallocated, int sign, int quality)
00233 {
00234   (void)quality;
00235   (void)fragment_size;
00236   int w, h;
00237   int numcomps;
00238   OPJ_COLOR_SPACE color_space;
00239   opj_image_cmptparm_t cmptparm[3]; /* maximum of 3 components */
00240   opj_image_t * image = NULL;
00241 
00242   assert( sample_pixel == 1 || sample_pixel == 3 );
00243   if( sample_pixel == 1 )
00244     {
00245     numcomps = 1;
00246     color_space = CLRSPC_GRAY;
00247     }
00248   else // sample_pixel == 3
00249     {
00250     numcomps = 3;
00251     color_space = CLRSPC_SRGB;
00252     }
00253   int subsampling_dx = parameters->subsampling_dx;
00254   int subsampling_dy = parameters->subsampling_dy;
00255 
00256   // FIXME
00257   w = image_width;
00258   h = image_height;
00259 
00260   /* initialize image components */
00261   memset(&cmptparm[0], 0, 3 * sizeof(opj_image_cmptparm_t));
00262   //assert( bitsallocated == 8 );
00263   for(int i = 0; i < numcomps; i++) {
00264     cmptparm[i].prec = bitsallocated;
00265     cmptparm[i].bpp = bitsallocated;
00266     cmptparm[i].sgnd = sign;
00267     cmptparm[i].dx = subsampling_dx;
00268     cmptparm[i].dy = subsampling_dy;
00269     cmptparm[i].w = w;
00270     cmptparm[i].h = h;
00271   }
00272 
00273   /* create the image */
00274   image = opj_image_create(numcomps, &cmptparm[0], color_space);
00275   if(!image) {
00276     return NULL;
00277   }
00278   /* set image offset and reference grid */
00279   image->x0 = parameters->image_offset_x0;
00280   image->y0 = parameters->image_offset_y0;
00281   image->x1 = parameters->image_offset_x0 + (w - 1) * subsampling_dx + 1;
00282   image->y1 = parameters->image_offset_y0 + (h - 1) * subsampling_dy + 1;
00283 
00284   /* set image data */
00285 
00286   //assert( fragment_size == numcomps*w*h*(bitsallocated/8) );
00287   if (bitsallocated <= 8)
00288     {
00289     if( sign )
00290       {
00291       rawtoimage_fill<int8_t>((int8_t*)inputbuffer,w,h,numcomps,image);
00292       }
00293     else
00294       {
00295       rawtoimage_fill<uint8_t>((uint8_t*)inputbuffer,w,h,numcomps,image);
00296       }
00297     }
00298   else if (bitsallocated <= 16)
00299     {
00300     if( sign )
00301       {
00302       rawtoimage_fill<int16_t>((int16_t*)inputbuffer,w,h,numcomps,image);
00303       }
00304     else
00305       {
00306       rawtoimage_fill<uint16_t>((uint16_t*)inputbuffer,w,h,numcomps,image);
00307       }
00308     }
00309   else if (bitsallocated <= 32)
00310     {
00311     if( sign )
00312       {
00313       rawtoimage_fill<int32_t>((int32_t*)inputbuffer,w,h,numcomps,image);
00314       }
00315     else
00316       {
00317       rawtoimage_fill<uint32_t>((uint32_t*)inputbuffer,w,h,numcomps,image);
00318       }
00319     }
00320   else
00321     {
00322     abort();
00323     }
00324 
00325   return image;
00326 }
00327 
00328 /*
00329  * The following function was copy paste from image_to_j2k.c with part from convert.c
00330  */
00331 bool gdcm_write_JPEG2000_file (std::ostream *fp, char *inputdata, size_t inputlength, 
00332   int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated,
00333   int sign, int quality)
00334 {
00337   (void)numZ;
00338   bool bSuccess;
00339   //bool delete_comment = true;
00340   opj_cparameters_t parameters;  /* compression parameters */
00341   opj_event_mgr_t event_mgr;    /* event manager */
00342   opj_image_t *image = NULL;
00343   //quality = 100;
00344 
00345   /*
00346   configure the event callbacks (not required)
00347   setting of each callback is optionnal
00348   */
00349   memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
00350   event_mgr.error_handler = error_callback;
00351   event_mgr.warning_handler = warning_callback;
00352   event_mgr.info_handler = info_callback;
00353 
00354   /* set encoding parameters to default values */
00355   memset(&parameters, 0, sizeof(parameters));
00356   opj_set_default_encoder_parameters(&parameters);
00357 
00358   /* if no rate entered, lossless by default */
00359   parameters.tcp_rates[0] = 0;
00360   parameters.tcp_numlayers = 1;
00361   parameters.cp_disto_alloc = 1;
00362 
00363   if(parameters.cp_comment == NULL) {
00364     const char comment[] = "Created by GDCM/OpenJPEG version 1.0";
00365     parameters.cp_comment = (char*)malloc(strlen(comment) + 1);
00366     strcpy(parameters.cp_comment, comment);
00367     /* no need to delete parameters.cp_comment on exit */
00368     //delete_comment = false;
00369   }
00370 
00371   
00372   /* decode the source image */
00373   /* ----------------------- */
00374 
00375   image = rawtoimage((char*)inputdata, &parameters, 
00376     static_cast<int>( inputlength ), 
00377     image_width, image_height,
00378     sample_pixel, bitsallocated, sign, quality);
00379   if (!image) {
00380     return 1;
00381   }
00382 
00383     /* encode the destination image */
00384   /* ---------------------------- */
00385    parameters.cod_format = J2K_CFMT; /* J2K format output */
00386     int codestream_length;
00387     opj_cio_t *cio = NULL;
00388     //FILE *f = NULL;
00389 
00390     /* get a J2K compressor handle */
00391     opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K);
00392 
00393     /* catch events using our callbacks and give a local context */
00394     opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
00395 
00396     /* setup the encoder parameters using the current image and using user parameters */
00397     opj_setup_encoder(cinfo, &parameters, image);
00398 
00399     /* open a byte stream for writing */
00400     /* allocate memory for all tiles */
00401     cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
00402 
00403     /* encode the image */
00404     bSuccess = opj_encode(cinfo, cio, image, parameters.index);
00405     if (!bSuccess) {
00406       opj_cio_close(cio);
00407       fprintf(stderr, "failed to encode image\n");
00408       return 1;
00409     }
00410     codestream_length = cio_tell(cio);
00411 
00412     /* write the buffer to disk */
00413     //f = fopen(parameters.outfile, "wb");
00414     //if (!f) {
00415     //  fprintf(stderr, "failed to open %s for writing\n", parameters.outfile);
00416     //  return 1;
00417     //}
00418     //fwrite(cio->buffer, 1, codestream_length, f);
00419 //#define MDEBUG
00420 #ifdef MDEBUG
00421     static int c = 0;
00422     std::ostringstream os;
00423     os << "/tmp/debug";
00424     os << c;
00425     c++;
00426     os << ".j2k";
00427     std::ofstream debug(os.str().c_str());
00428     debug.write((char*)(cio->buffer), codestream_length);
00429     debug.close();
00430 #endif
00431     fp->write((char*)(cio->buffer), codestream_length);
00432     //fclose(f);
00433 
00434     /* close and free the byte stream */
00435     opj_cio_close(cio);
00436 
00437     /* free remaining compression structures */
00438     opj_destroy_compress(cinfo);
00439 
00440 
00441       /* free user parameters structure */
00442   //if(delete_comment) {
00443     if(parameters.cp_comment) free(parameters.cp_comment);
00444   //}
00445   if(parameters.cp_matrice) free(parameters.cp_matrice);
00446 
00447   /* free image data */
00448   opj_image_destroy(image);
00449 
00450 
00451 
00452 
00453   return true;
00454 }
00455 
00456 #if 0
00457 // For openjpeg 0.97
00458 bool gdcm_read_JPEG2000_file (void* raw, char *inputdata, size_t inputlength)
00459 {
00460    j2k_image_t img;
00461    j2k_cp_t cp;
00462  
00463    // default blindly copied
00464    cp.layer=0;
00465    cp.reduce=0;
00466    cp.decod_format=-1;
00467    cp.cod_format=-1;
00468  
00469    cp.cod_format=J2K_CFMT;
00470    cp.decod_format = PGX_DFMT;
00471    int len = inputlength;
00472    unsigned char *src = (unsigned char*)inputdata;
00473  
00474    // Decompression
00475    if (!j2k_decode(src, len, &img, &cp))
00476    {
00477       gdcmStaticErrorMacro( "ERROR -> j2k_to_image: failed to decode image!" );
00478       return false;
00479    }
00480  
00481    // Copy buffer
00482    for (int compno = 0; compno < img.numcomps; compno++)
00483    {
00484       j2k_comp_t *comp = &img.comps[compno];
00485   
00486       int w = img.comps[compno].w;
00487       int wr = int_ceildivpow2(img.comps[compno].w, img.comps[compno].factor);
00488   
00489       //int h = img.comps[compno].h;
00490       int hr = int_ceildivpow2(img.comps[compno].h, img.comps[compno].factor);
00491   
00492       if (comp->prec <= 8)
00493       {
00494          uint8_t *data8 = (uint8_t*)raw;
00495          for (int i = 0; i < wr * hr; i++) 
00496          {
00497             int v = img.comps[compno].data[i / wr * w + i % wr];
00498             *data8++ = (uint8_t)v;
00499          }
00500       }
00501       else if (comp->prec <= 16)
00502       {
00503          uint16_t *data16 = (uint16_t*)raw;
00504          for (int i = 0; i < wr * hr; i++) 
00505          {
00506             int v = img.comps[compno].data[i / wr * w + i % wr];
00507             *data16++ = (uint16_t)v;
00508          }
00509       }
00510       else
00511       {
00512          uint32_t *data32 = (uint32_t*)raw;
00513          for (int i = 0; i < wr * hr; i++) 
00514          {
00515             int v = img.comps[compno].data[i / wr * w + i % wr];
00516             *data32++ = (uint32_t)v;
00517          }
00518       }
00519       free(img.comps[compno].data);
00520    }
00521  
00522    // Free remaining structures
00523    j2k_dec_release();
00524    // FIXME
00525    delete[] inputdata;
00526  
00527    return true;
00528 }
00529 #endif
00530 
00531 #if 0
00532 bool gdcm_read_JASPER_file (void* raw, char *inputdata, size_t inputlength)
00533 {
00534 #if 0
00535   std::cerr << "Inputlenght=" << inputlength << std::endl;
00536   std::ofstream out("/tmp/jpeg2000.jpc", std::ios::binary);
00537   out.write((char*)inputdata,inputlength);
00538   out.close();
00539 #endif
00540   jas_init(); //important...
00541   jas_stream_t *jasStream = 
00542     jas_stream_memopen((char *)inputdata, inputlength);
00543     
00544   int fmtid;
00545   if ((fmtid = jas_image_getfmt(jasStream)) < 0) 
00546     {
00547     gdcmErrorMacro("unknown image format");
00548     return false;
00549     }
00550 
00551   // Decode the image. 
00552   jas_image_t *jasImage /* = NULL*/; // Useless assignation
00553   if (!(jasImage = jas_image_decode(jasStream, fmtid, 0))) 
00554     {
00555     gdcmErrorMacro("cannot decode image");
00556     return false;
00557     }
00558 
00559   // close the stream. 
00560   jas_stream_close(jasStream);
00561   int numcmpts = jas_image_numcmpts(jasImage);
00562   int width = jas_image_cmptwidth(jasImage, 0);
00563   int height = jas_image_cmptheight(jasImage, 0);
00564   int prec = jas_image_cmptprec(jasImage, 0);
00565   int i, j, k;
00566 
00567   // The following should serioulsy be rewritten I cannot believe we need to
00568   // do a per pixel decompression, there should be a way to read a full
00569   // scanline...
00570   if (prec == 8)
00571     {
00572     uint8_t *data8 = (uint8_t*)raw;
00573     for ( i = 0; i < height; i++)
00574       for ( j = 0; j < width; j++)
00575         for ( k= 0; k < numcmpts; k++)
00576           *data8++ = (uint8_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
00577     }
00578   else if (prec <= 16)
00579     {
00580     uint16_t *data16 = (uint16_t*)raw;
00581     for ( i = 0; i < height; i++) 
00582       for ( j = 0; j < width; j++) 
00583         for ( k= 0; k < numcmpts; k++)
00584           *data16++ = (uint16_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
00585     }
00586   else if (prec <= 32)
00587     {
00588     uint32_t *data32 = (uint32_t*)raw;
00589     for ( i = 0; i < height; i++) 
00590       for ( j = 0; j < width; j++) 
00591         for ( k= 0; k < numcmpts; k++)
00592           *data32++ = (uint32_t)(jas_image_readcmptsample(jasImage, k, j ,i ));
00593     }
00594 
00595   jas_image_destroy(jasImage);
00596   jas_image_clearfmts();
00597 
00598   //FIXME
00599   //delete the jpeg temp buffer
00600 #if 0
00601   std::ofstream rawout("/tmp/jpeg2000.raw");
00602   rawout.write((char*)raw,height*width*numcmpts*((prec+4)/8));
00603   rawout.close();
00604 #endif
00605   delete[] inputdata;
00606 
00607   return true;
00608 }
00609 #endif
00610 
00611 //-----------------------------------------------------------------------------
00612 } // end namespace gdcm
00613 

Generated on Fri Aug 24 12:59:31 2007 for gdcm by  doxygen 1.4.6