⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdcmpixelwriteconvert.cxx

📁 DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.
💻 CXX
字号:
/*=========================================================================
                                                                                
  Program:   gdcm
  Module:    $RCSfile: gdcmPixelWriteConvert.cxx,v $
  Language:  C++
  Date:      $Date: 2008-05-14 12:25:32 $
  Version:   $Revision: 1.9 $
                                                                                
  Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
  l'Image). All rights reserved. See Doc/License.txt or
  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
                                                                                
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.
                                                                                
=========================================================================*/
#if defined(__BORLANDC__)
#pragma warn -8057 /* parameter is never used */
#endif

#include "gdcmDebug.h"
#include "gdcmPixelWriteConvert.h"
#include "gdcmFile.h"
#include "gdcmUtil.h"

#include <vector>
#include <stdlib.h>

#define WITHOFFSETTABLE 1

namespace gdcm
{
//-----------------------------------------------------------------------------
// Constructor / Destructor
/**
 * \brief Constructor
 */
PixelWriteConvert::PixelWriteConvert() 
{
   ReadData     = 0;
   ReadDataSize = 0;

   UserData     = 0;
   UserDataSize = 0;
   Compressed   = false;
}

/**
 * \brief Destructor
 */
PixelWriteConvert::~PixelWriteConvert() 
{
   if( Compressed )
     {
     delete[] UserData;
     }
}

//-----------------------------------------------------------------------------
// Public
/**
 * \brief   sets Read Data (and size)
 * @param   data data (uint8_t is for prototyping. if your data is not uint8_t
 *                     just cast the pointer for calling the method)
 * @param   size data size, in bytes
 */
void PixelWriteConvert::SetReadData(uint8_t *data, size_t size)
{
   ReadData = data;
   ReadDataSize = size;
}

/**
 * \brief   Sets the internal pointer to the caller's inData
 *          image representation, BUT WITHOUT COPYING THE DATA.
 *          - 'image' Pixels are presented as C-like 2D arrays : line per line.
 *          - 'volume'Pixels are presented as C-like 3D arrays : plane per plane 
 * \warning Since the pixels are not copied, it is the caller's responsability
 *          not to deallocate its data before gdcm uses them (e.g. with
 *          the Write() method )
 * @param   data data (uint8_t is for prototyping. if your data is not uint8_t
 *                     just cast the pointer for calling the method)
 * @param   size size, in bytes.
 */
void PixelWriteConvert::SetUserData(uint8_t *data, size_t size)
{
   UserData = data;
   UserDataSize = size;
}

/**
 * \brief   Get Data (UserData or ReadData)
 * @return  data (uint8_t is for prototyping. if your data is 
 *                    *not* uint8_t, just cast the returned pointer)
 */
uint8_t *PixelWriteConvert::GetData()
{
   if ( UserData )
   {
      return UserData;
   }
   else
   {
      return ReadData;
   }
}

/**
 * \brief   Get Data Size (UserData or ReadData)
 * @return  size, in bytes.
 */
size_t PixelWriteConvert::GetDataSize()
{
   if ( UserData )
   {
      return UserDataSize;
   }
   else
   {
      return ReadDataSize;
   }
}


typedef std::pair<size_t, uint32_t> JpegPair; //offset, jpeg size
typedef std::vector<JpegPair> JpegVector;

bool gdcm_write_JPEG2000_file (std::ostream *of, char *inputdata, size_t inputlength, 
  int image_width, int image_height, int numZ, int sample_pixel, int bitsallocated,
  int sign, int quality);


void WriteDICOMItems(std::ostream *fp, JpegVector &v)
{
  // Item tag:
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe000;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);
  // Item Length
  uint32_t dummy = 0x12345678;
  size_t offset = fp->tellp();
  JpegPair jp;
  jp.first = offset;
  v.push_back(jp);
  gdcm::binary_write(*fp, dummy);
}

// PS 3.5, page 66
#ifdef NDEBUG
void EncodeWithoutBasicOffsetTable(std::ostream *fp, int)// JpegVector& v) //, uint32_t length)
{
#else
void EncodeWithoutBasicOffsetTable(std::ostream *fp, int numFrag)// JpegVector& v) //, uint32_t length)
{
  assert( numFrag == 1);
#endif
  // Item tag:
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe000;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);
  // Item Length
  uint32_t item_length = 0x0000;
  gdcm::binary_write(*fp, item_length);

}

// PS 3.5, page 67
void EncodeWithBasicOffsetTable(std::ostream *fp, int numFrag, size_t &start)
{
  // Item tag:
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe000;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);
  // Item Length
  uint32_t item_length = numFrag*4; // sizeof(uint32_t)
  gdcm::binary_write(*fp, item_length);

  // Just prepare the space
  start = fp->tellp(); //to be able to rewind
  for(int i=0; i<numFrag;++i)
    {
    uint32_t dummy = 0x0000;
    gdcm::binary_write(*fp, dummy);
    }
}

void UpdateBasicOffsetTable(std::ostream *fp, JpegVector const &v, size_t pos)
{
  JpegVector::const_iterator i;
  fp->seekp( pos );
  const JpegPair &first = v[0];
  for(i=v.begin(); i!=v.end(); ++i)
    {
    const JpegPair &jp = *i;
    if(i == v.begin() ){ assert( jp.first - first.first == 0); }
    uint32_t offset = (uint32_t)(jp.first - first.first);
    gdcm::binary_write(*fp, offset);
    //std::cerr << "Updating Table:" << jp.first - first.first << std::endl;
    }
}

void UpdateJpegFragmentSize(std::ostream *fp, JpegVector const &v)
{
  JpegVector::const_iterator i;
  for(i= v.begin(); i!=v.end(); ++i)
    {
    const JpegPair &jp = *i;
    fp->seekp( jp.first );
    uint32_t length = jp.second;
    gdcm::binary_write(*fp, length);
    //std::cerr << "Updating:" << jp.first << "," << jp.second << std::endl;
    }
}

void CloseJpeg(std::ostream *fp, JpegVector &v)
{
  // sequence terminator
  uint16_t group = 0xfffe;
  uint16_t elem  = 0xe0dd;
  gdcm::binary_write(*fp, group);
  gdcm::binary_write(*fp, elem);

  uint32_t length = 0x0;
  gdcm::binary_write(*fp, length);

  // Jpeg is done, now update the frag length
  UpdateJpegFragmentSize(fp, v);
}

// I need to pass the File*. I do not understand how PixelWriteConvert is supposed
// to access this information otherwise
// size can now be computer from File attributes (what an API...)
void PixelWriteConvert::SetCompressJPEG2000UserData(uint8_t *data, size_t size, File *image)
{
  Compressed = true;
  //char * userData = reinterpret_cast<char*>(UserData);

   itksys_ios::ostringstream *of = new itksys_ios::ostringstream();
    int xsize = image->GetXSize();
   int ysize = image->GetYSize();
  int zsize =  image->GetZSize();
    int samplesPerPixel = image->GetSamplesPerPixel();
   //std::cout << "X: " << xsize << std::endl;
   //std::cout << "Y: " << ysize << std::endl;
   //std::cout << "Sample: " << samplesPerPixel << std::endl;
    int bitsallocated = image->GetBitsAllocated();
    int sign = image->IsSignedPixelData();
   unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
    assert( fragment_size*zsize == size );

   JpegVector JpegFragmentSize;
#if WITHOFFSETTABLE
   size_t bots; //basic offset table start
   EncodeWithBasicOffsetTable(of, zsize, bots);
#else
   EncodeWithoutBasicOffsetTable(of, 1);
#endif
   uint8_t *pImageData = data;
   for(int i=0; i<zsize;i++)
     {
     WriteDICOMItems(of, JpegFragmentSize);
     size_t beg = of->tellp();
     gdcm_write_JPEG2000_file(of, (char*)pImageData,size, 
       image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
       image->GetBitsAllocated(), sign, 100);
     //userData, UserDataSize);
     //     CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize, 
     //       samplesPerPixel, quality, JpegFragmentSize);
     //assert( !(fragment_size % 2) );
     // Update the JpegVector with offset
     size_t end = of->tellp();
     //static int i = 0;
     JpegPair &jp = JpegFragmentSize[i];
     jp.second = (uint32_t)(end-beg);
     if( ((end-beg) % 2) )
       {
       of->put( '\0' );
       jp.second += 1;
       }
     assert( !(jp.second % 2) );
     //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
     //++i;
     pImageData += fragment_size;
     }
   CloseJpeg(of, JpegFragmentSize);
#if WITHOFFSETTABLE
   UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
#endif


   size_t of_size = of->str().size();
   UserData = new uint8_t[of_size];
   memcpy(UserData, of->str().c_str(), of_size);
   UserDataSize = of_size;
   delete of;   
}

bool gdcm_write_JPEG_file8 (std::ostream *fp, char *inputdata, size_t inputlength,
                           int image_width, int image_height, int numZ,
                           int sample_pixel, int bitsallocated, int quality);
bool gdcm_write_JPEG_file12 (std::ostream *fp, char *inputdata, size_t inputlength,
                           int image_width, int image_height, int numZ,
                           int sample_pixel, int bitsallocated, int quality);
bool gdcm_write_JPEG_file16 (std::ostream *fp, char *inputdata, size_t inputlength,
                           int image_width, int image_height, int numZ,
                           int sample_pixel, int bitsallocated, int quality);

void PixelWriteConvert::SetCompressJPEGUserData(uint8_t *data, size_t size, File *image)
{
  (void)data;
  (void)size;
  (void)image;
  Compressed = true;
  //char * userData = reinterpret_cast<char*>(UserData);

   itksys_ios::ostringstream *of = new itksys_ios::ostringstream();
    int xsize = image->GetXSize();
   int ysize = image->GetYSize();
  int zsize =  image->GetZSize();
    int samplesPerPixel = image->GetSamplesPerPixel();
   //std::cout << "X: " << xsize << std::endl;
   //std::cout << "Y: " << ysize << std::endl;
   //std::cout << "Sample: " << samplesPerPixel << std::endl;
    int bitsallocated = image->GetBitsAllocated();
   unsigned int fragment_size = xsize*ysize*samplesPerPixel * (bitsallocated / 8);
    assert( fragment_size*zsize == size );

   JpegVector JpegFragmentSize;
#if WITHOFFSETTABLE
   size_t bots; //basic offset table start
   EncodeWithBasicOffsetTable(of, zsize, bots);
#else
   EncodeWithoutBasicOffsetTable(of, 1);
#endif
   uint8_t *pImageData = data;
   for(int i=0; i<zsize;i++)
     {
     WriteDICOMItems(of, JpegFragmentSize);
  size_t beg = of->tellp();
     if( bitsallocated == 8 )
       {
       gdcm_write_JPEG_file8(of, (char*)pImageData,size, 
         image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
         image->GetBitsAllocated(), 100 );
       }
     else if (bitsallocated <= 12)
       {
       assert( bitsallocated >= 8 );
       gdcm_write_JPEG_file12(of, (char*)pImageData,size, 
         image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
         image->GetBitsAllocated(), 100);
       }
     else if (bitsallocated <= 16)
       {
       assert( bitsallocated >= 12 );
       gdcm_write_JPEG_file16(of, (char*)pImageData,size, 
         image->GetXSize(), image->GetYSize(), image->GetZSize(), image->GetSamplesPerPixel(),
         image->GetBitsAllocated(), 100);
       }
     else
       {
       abort();
       }
    size_t end = of->tellp();
    //static int i = 0;
    JpegPair &jp = JpegFragmentSize[i];
      jp.second = (uint32_t)(end-beg);
    if( ((end-beg) % 2) )
      {
      of->put( '\0' );
      jp.second += 1;
      }
    assert( !(jp.second % 2) );
    //std::cerr << "DIFF: " << i <<" -> " << jp.second << std::endl;
    //++i;

  //JpegPair &jp = v[0];
  //jp.second = 15328;


     //userData, UserDataSize);
     //     CreateOneFrame(of, pImageData, fragment_size, xsize, ysize, zsize, 
     //       samplesPerPixel, quality, JpegFragmentSize);
     //assert( !(fragment_size % 2) );
     pImageData += fragment_size;
     }
   CloseJpeg(of, JpegFragmentSize);
#if WITHOFFSETTABLE
   UpdateBasicOffsetTable(of, JpegFragmentSize, bots);
#endif


   size_t of_size = of->str().size();
   UserData = new uint8_t[of_size];
   memcpy(UserData, of->str().c_str(), of_size);
   UserDataSize = of_size;
   delete of;
}


//-----------------------------------------------------------------------------
// Protected
//bool PixelWriteConvert::CompressJPEG2000(uint8_t *data, size_t size)
//{
//}

//-----------------------------------------------------------------------------
// Private

//-----------------------------------------------------------------------------
// Print

//-----------------------------------------------------------------------------
} // end namespace gdcm

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -