gdcmPixelWriteConvert.cxx

Go to the documentation of this file.
00001 /*=========================================================================
00002                                                                                 
00003   Program:   gdcm
00004   Module:    $RCSfile: gdcmPixelWriteConvert.cxx,v $
00005   Language:  C++
00006   Date:      $Date: 2007/08/24 10:45:18 $
00007   Version:   $Revision: 1.17 $
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 
00019 #include "gdcmDebug.h"
00020 #include "gdcmPixelWriteConvert.h"
00021 #include "gdcmFile.h"
00022 #include "gdcmUtil.h"
00023 
00024 #include <vector>
00025 
00026 #define WITHOFFSETTABLE 1
00027 
00028 namespace GDCM_NAME_SPACE
00029 {
00030 //-----------------------------------------------------------------------------
00031 // Public
00032 
00033 //-----------------------------------------------------------------------------
00034 // Protected
00035 
00036 //-----------------------------------------------------------------------------
00037 // Private
00038 
00039 // Constructor / Destructor
00043 PixelWriteConvert::PixelWriteConvert() 
00044 {
00045    ReadData     = 0;
00046    ReadDataSize = 0;
00047 
00048    UserData     = 0;
00049    UserDataSize = 0;
00050    Compressed   = false;
00051 }
00052 
00056 PixelWriteConvert::~PixelWriteConvert() 
00057 {
00058    gdcmDebugMacro("PixelWriteConvert::~PixelWriteConvert()" );
00059    if( Compressed )
00060      {
00061      delete[] UserData;
00062      }
00063 }
00064 
00071 void PixelWriteConvert::SetReadData(uint8_t *data, size_t size)
00072 {
00073    ReadData = data;
00074    ReadDataSize = size;
00075 }
00076 
00089 void PixelWriteConvert::SetUserData(uint8_t *data, size_t size)
00090 {
00091    UserData = data;
00092    UserDataSize = size;
00093 }
00094 
00100 uint8_t *PixelWriteConvert::GetData()
00101 {
00102    if ( UserData )
00103    {
00104       return UserData;
00105    }
00106    else
00107    {
00108       return ReadData;
00109    }
00110 }
00111 
00116 size_t PixelWriteConvert::GetDataSize()
00117 {
00118    if ( UserData )
00119    {
00120       return UserDataSize;
00121    }
00122    else
00123    {
00124       return ReadDataSize;
00125    }
00126 }
00127 
00128 
00129 typedef std::pair<size_t, uint32_t> JpegPair; //offset, jpeg size
00130 typedef std::vector<JpegPair> JpegVector;
00131 
00132 bool gdcm_write_JPEG2000_file (std::ostream *of, char *inputdata, size_t inputlength, 
00133   int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated,
00134   int sign, int quality);
00135 
00136 
00137 void WriteDICOMItems(std::ostream *fp, JpegVector &v)
00138 {
00139   // Item tag:
00140   uint16_t group = 0xfffe;
00141   uint16_t elem  = 0xe000;
00142   GDCM_NAME_SPACE::binary_write(*fp, group);
00143   GDCM_NAME_SPACE::binary_write(*fp, elem);
00144   // Item Length
00145   uint32_t dummy = 0x12345678;
00146   size_t offset = fp->tellp();
00147   JpegPair jp;
00148   jp.first = offset;
00149   v.push_back(jp);
00150   GDCM_NAME_SPACE::binary_write(*fp, dummy);
00151 }
00152 
00153 // PS 3.5, page 66
00154 void EncodeWithoutBasicOffsetTable(std::ostream *fp, int numFrag)// JpegVector& v) //, uint32_t length)
00155 {
00156   assert( numFrag == 1);
00157 
00158   // Item tag:
00159   uint16_t group = 0xfffe;
00160   uint16_t elem  = 0xe000;
00161   GDCM_NAME_SPACE::binary_write(*fp, group);
00162   GDCM_NAME_SPACE::binary_write(*fp, elem);
00163   // Item Length
00164   uint32_t item_length = 0x0000;
00165   GDCM_NAME_SPACE::binary_write(*fp, item_length);
00166 
00167 }
00168 
00169 // PS 3.5, page 67
00170 void EncodeWithBasicOffsetTable(std::ostream *fp, int numFrag, size_t &start)
00171 {
00172   // Item tag:
00173   uint16_t group = 0xfffe;
00174   uint16_t elem  = 0xe000;
00175   GDCM_NAME_SPACE::binary_write(*fp, group);
00176   GDCM_NAME_SPACE::binary_write(*fp, elem);
00177   // Item Length
00178   uint32_t item_length = numFrag*4; // sizeof(uint32_t)
00179   GDCM_NAME_SPACE::binary_write(*fp, item_length);
00180 
00181   // Just prepare the space
00182   start = fp->tellp(); //to be able to rewind
00183   for(int i=0; i<numFrag;++i)
00184     {
00185     uint32_t dummy = 0x0000;
00186     GDCM_NAME_SPACE::binary_write(*fp, dummy);
00187     }
00188 }
00189 
00190 void UpdateBasicOffsetTable(std::ostream *fp, JpegVector const &v, size_t pos)
00191 {
00192   JpegVector::const_iterator i;
00193   fp->seekp( pos );
00194   const JpegPair &first = v[0];
00195   for(i=v.begin(); i!=v.end(); ++i)
00196     {
00197     const JpegPair &jp = *i;
00198     if(i == v.begin() ){ assert( jp.first - first.first == 0); }
00199     uint32_t offset = (uint32_t)(jp.first - first.first);
00200     GDCM_NAME_SPACE::binary_write(*fp, offset);
00201     //std::cerr << "Updating Table:" << jp.first - first.first << std::endl;
00202     }
00203 }
00204 
00205 void UpdateJpegFragmentSize(std::ostream *fp, JpegVector const &v)
00206 {
00207   JpegVector::const_iterator i;
00208   for(i= v.begin(); i!=v.end(); ++i)
00209     {
00210     const JpegPair &jp = *i;
00211     fp->seekp( jp.first );
00212     uint32_t length = jp.second;
00213     GDCM_NAME_SPACE::binary_write(*fp, length);
00214     //std::cerr << "Updating:" << jp.first << "," << jp.second << std::endl;
00215     }
00216 }
00217 
00218 void CloseJpeg(std::ostream *fp, JpegVector &v)
00219 {
00220   // sequence terminator
00221   uint16_t group = 0xfffe;
00222   uint16_t elem  = 0xe0dd;
00223   GDCM_NAME_SPACE::binary_write(*fp, group);
00224   GDCM_NAME_SPACE::binary_write(*fp, elem);
00225 
00226   uint32_t length = 0x0;
00227   GDCM_NAME_SPACE::binary_write(*fp, length);
00228 
00229   // Jpeg is done, now update the frag length
00230   UpdateJpegFragmentSize(fp, v);
00231 }
00232 
00233 // I need to pass the File*. I do not understand how PixelWriteConvert is supposed
00234 // to access this information otherwise
00235 // size can now be computed from File attributes (what an API...)
00236 void PixelWriteConvert::SetCompressJPEG2000UserData(uint8_t *data, size_t size, File *image)
00237 {
00238   Compressed = true;
00239   //char * userData = reinterpret_cast<char*>(UserData);
00240 
00241    std::ostringstream *of = new std::ostringstream();
00242     int xsize = image->GetXSize();
00243    int ysize = image->GetYSize();
00244   int zsize =  image->GetZSize();
00245     int samplesPerPixel = image->GetSamplesPerPixel();
00246    //std::cout << "X: " << xsize << std::endl;
00247    //std::cout << "Y: " << ysize << std::endl;
00248    //std::cout << "Sample: " << samplesPerPixel << std::endl;
00249     int bitsallocated = image->GetBitsAllocated();
00250     int sign = image->IsSignedPixelData();
00251    unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
00252     assert( fragment_size*zsize == size );
00253 
00254    JpegVector JpegFragmentSize;
00255 #if WITHOFFSETTABLE
00256    size_t bots; //basic offset table start
00257    EncodeWithBasicOffsetTable(of, zsize, bots);
00258 #else
00259    EncodeWithoutBasicOffsetTable(of, 1);
00260 #endif
00261    uint8_t *pImageData = data;
00262    for(int i=0; i<zsize;i++)
00263      {
00264      WriteDICOMItems(of, JpegFragmentSize);
00265      size_t beg = of->tellp();
00266      gdcm_write_JPEG2000_file(of, (char*)pImageData,size, 
00267        image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
00268        image->GetBitsAllocated(), sign, 100);
00269      //userData, UserDataSize);
00270      //     CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize, 
00271      //       samplesPerPixel, quality, JpegFragmentSize);
00272      //assert( !(fragment_size % 2) );
00273      // Update the JpegVector with offset
00274      size_t end = of->tellp();
00275      //static int i = 0;
00276      JpegPair &jp = JpegFragmentSize[i];
00277      jp.second = (uint32_t)(end-beg);
00278      if( ((end-beg) % 2) )
00279        {
00280        of->put( '\0' );
00281        jp.second += 1;
00282        }
00283      assert( !(jp.second % 2) );
00284      //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
00285      //++i;
00286      pImageData += fragment_size;
00287      }
00288    CloseJpeg(of, JpegFragmentSize);
00289 #if WITHOFFSETTABLE
00290    UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
00291 #endif
00292 
00293 
00294    size_t of_size = of->str().size();
00295    UserData = new uint8_t[of_size];
00296    memcpy(UserData, of->str().c_str(), of_size);
00297    UserDataSize = of_size;
00298    delete of;   
00299 }
00300 
00301 bool gdcm_write_JPEG_file8 (std::ostream *fp, char *inputdata, size_t inputlength,
00302                            int image_width, int image_height, int numZ,
00303                            int sample_pixel, int bitsallocated, int quality);
00304 bool gdcm_write_JPEG_file12 (std::ostream *fp, char *inputdata, size_t inputlength,
00305                            int image_width, int image_height, int numZ,
00306                            int sample_pixel, int bitsallocated, int quality);
00307 bool gdcm_write_JPEG_file16 (std::ostream *fp, char *inputdata, size_t inputlength,
00308                            int image_width, int image_height, int numZ,
00309                            int sample_pixel, int bitsallocated, int quality);
00310 
00311 void PixelWriteConvert::SetCompressJPEGUserData(uint8_t *data, size_t size, File *image)
00312 {
00313   (void)data;
00314   (void)size;
00315   (void)image;
00316   Compressed = true;
00317   //char * userData = reinterpret_cast<char*>(UserData);
00318 
00319    std::ostringstream *of = new std::ostringstream();
00320     int xsize = image->GetXSize();
00321     int ysize = image->GetYSize();
00322     int zsize = image->GetZSize();
00323     int samplesPerPixel = image->GetSamplesPerPixel();
00324    //std::cout << "X: " << xsize << std::endl;
00325    //std::cout << "Y: " << ysize << std::endl;
00326    //std::cout << "Sample: " << samplesPerPixel << std::endl;
00327     int bitsallocated = image->GetBitsAllocated();
00328    unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
00329     assert( fragment_size*zsize == size );
00330 
00331    JpegVector JpegFragmentSize;
00332 #if WITHOFFSETTABLE
00333    size_t bots; //basic offset table start
00334    EncodeWithBasicOffsetTable(of, zsize, bots);
00335 #else
00336    EncodeWithoutBasicOffsetTable(of, 1);
00337 #endif
00338    uint8_t *pImageData = data;
00339    for(int i=0; i<zsize;i++)
00340      {
00341      WriteDICOMItems(of, JpegFragmentSize);
00342   size_t beg = of->tellp();
00343      if( bitsallocated == 8 )
00344        {
00345        gdcm_write_JPEG_file8(of, (char*)pImageData,size, 
00346          image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
00347          image->GetBitsAllocated(), 100 );
00348        }
00349      else if (bitsallocated <= 12)
00350        {
00351        assert( bitsallocated >= 8 );
00352        gdcm_write_JPEG_file12(of, (char*)pImageData,size, 
00353          image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
00354          image->GetBitsAllocated(), 100);
00355        }
00356      else if (bitsallocated <= 16)
00357        {
00358        assert( bitsallocated >= 12 );
00359        gdcm_write_JPEG_file16(of, (char*)pImageData,size, 
00360          image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
00361          image->GetBitsAllocated(), 100);
00362        }
00363      else
00364        {
00365        abort();
00366        }
00367     size_t end = of->tellp();
00368     //static int i = 0;
00369     JpegPair &jp = JpegFragmentSize[i];
00370       jp.second = (uint32_t)(end-beg);
00371     if( ((end-beg) % 2) )
00372       {
00373       of->put( '\0' );
00374       jp.second += 1;
00375       }
00376     assert( !(jp.second % 2) );
00377     //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
00378     //++i;
00379 
00380   //JpegPair &jp = v[0];
00381   //jp.second = 15328;
00382 
00383 
00384      //userData, UserDataSize);
00385      //     CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize, 
00386      //       samplesPerPixel, quality, JpegFragmentSize);
00387      //assert( !(fragment_size % 2) );
00388      pImageData += fragment_size;
00389      }
00390    CloseJpeg(of, JpegFragmentSize);
00391 #if WITHOFFSETTABLE
00392    UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
00393 #endif
00394 
00395 
00396    size_t of_size = of->str().size();
00397    UserData = new uint8_t[of_size];
00398    memcpy(UserData, of->str().c_str(), of_size);
00399    UserDataSize = of_size;
00400    delete of;
00401 }
00402 
00403 
00404 //-----------------------------------------------------------------------------
00405 // Protected
00406 //bool PixelWriteConvert::CompressJPEG2000(uint8_t *data, size_t size)
00407 //{
00408 //}
00409 
00410 //-----------------------------------------------------------------------------
00411 // Private
00412 
00413 //-----------------------------------------------------------------------------
00414 // Print
00415 
00416 //-----------------------------------------------------------------------------
00417 } // end namespace gdcm

Generated on Fri Aug 24 12:53:18 2007 for gdcm by  doxygen 1.4.6