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

📄 gdcmpixelreadconvert.cxx

📁 DTMK软件开发包,此为开源软件,是一款很好的医学图像开发资源.
💻 CXX
📖 第 1 页 / 共 4 页
字号:
/*=========================================================================
 
  Program:   gdcm
  Module:    $RCSfile: gdcmPixelReadConvert.cxx,v $
  Language:  C++
  Date:      $Date: 2008-05-28 11:26:41 $
  Version:   $Revision: 1.11 $
                                                                                
  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.
                                                                                
=========================================================================*/

#include "gdcmPixelReadConvert.h"
#include "gdcmDebug.h"
#include "gdcmFile.h"
#include "gdcmGlobal.h"
#include "gdcmTS.h"
#include "gdcmDocEntry.h"
#include "gdcmRLEFramesInfo.h"
#include "gdcmJPEGFragmentsInfo.h"

#include <fstream>
#include <stdio.h> //for sscanf

#if defined(__BORLANDC__)
   #include <mem.h> // for memset
#endif 

namespace gdcm
{

//bool ReadMPEGFile (std::ifstream *fp, void *image_buffer, size_t lenght);
bool gdcm_read_JPEG2000_file (void* raw, 
                              char *inputdata, size_t inputlength);
//-----------------------------------------------------------------------------
#define str2num(str, typeNum) *((typeNum *)(str))

//-----------------------------------------------------------------------------
// Constructor / Destructor
/// Constructor
PixelReadConvert::PixelReadConvert()
{
   RGB          = 0;
   RGBSize      = 0;
   Raw          = 0;
   RawSize      = 0;
   LutRGBA      = 0;
   LutRedData   = 0;
   LutGreenData = 0;
   LutBlueData  = 0;
   RLEInfo      = 0;
   JPEGInfo     = 0;
   UserFunction = 0;
   FileInternal = 0;
}

/// Canonical Destructor
PixelReadConvert::~PixelReadConvert() 
{
   Squeeze();
}

//-----------------------------------------------------------------------------
// Public
/**
 * \brief Predicate to know whether the image[s] (once Raw) is RGB.
 * \note See comments of \ref ConvertHandleColor
 */
bool PixelReadConvert::IsRawRGB()
{
   if (   IsMonochrome
       || PlanarConfiguration == 2
       || IsPaletteColor )
   {
      return false;
   }
   return true;
}
/**
 * \brief Gets various usefull informations from the file header
 * @param file gdcm::File pointer
 */
void PixelReadConvert::GrabInformationsFromFile( File *file )
{
   // Number of Bits Allocated for storing a Pixel is defaulted to 16
   // when absent from the file.
   BitsAllocated = file->GetBitsAllocated();
   if ( BitsAllocated == 0 )
   {
      BitsAllocated = 16;
   }
   else if ( BitsAllocated > 8 && BitsAllocated < 16 && BitsAllocated != 12 )
   {
      BitsAllocated = 16;
   }

   // Number of "Bits Stored", defaulted to number of "Bits Allocated"
   // when absent from the file.
   BitsStored = file->GetBitsStored();
   if ( BitsStored == 0 )
   {
      BitsStored = BitsAllocated;
   }

   // High Bit Position, defaulted to "Bits Allocated" - 1
   HighBitPosition = file->GetHighBitPosition();
   if ( HighBitPosition == 0 )
   {
      HighBitPosition = BitsAllocated - 1;
   }

   XSize           = file->GetXSize();
   YSize           = file->GetYSize();
   ZSize           = file->GetZSize();
   SamplesPerPixel = file->GetSamplesPerPixel();
   //PixelSize       = file->GetPixelSize();  Useless
   PixelSign       = file->IsSignedPixelData();
   SwapCode        = file->GetSwapCode();

   IsPrivateGETransferSyntax = IsMPEG
             = IsJPEG2000 = IsJPEGLS = IsJPEGLossy  
             = IsJPEGLossless = IsRLELossless 
             = false;

   std::string ts  = file->GetTransferSyntax();
   IsRaw =
        ( ! file->IsDicomV3() )
     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian
     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE
     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian
     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian
     || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian;

   IsMPEG          = Global::GetTS()->IsMPEG(ts);
   IsJPEG2000      = Global::GetTS()->IsJPEG2000(ts);
   IsJPEGLS        = Global::GetTS()->IsJPEGLS(ts);
   IsJPEGLossy     = Global::GetTS()->IsJPEGLossy(ts);
   IsJPEGLossless  = Global::GetTS()->IsJPEGLossless(ts);
   IsRLELossless   = Global::GetTS()->IsRLELossless(ts);

      IsPrivateGETransferSyntax = 
                ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRBigEndianPrivateGE );



   PixelOffset     = file->GetPixelOffset();
   PixelDataLength = file->GetPixelAreaLength();
   RLEInfo         = file->GetRLEInfo();
   JPEGInfo        = file->GetJPEGInfo();

   IsMonochrome    = file->IsMonochrome();
   IsMonochrome1   = file->IsMonochrome1();
   IsPaletteColor  = file->IsPaletteColor();
   IsYBRFull       = file->IsYBRFull();

   PlanarConfiguration = file->GetPlanarConfiguration();

   /////////////////////////////////////////////////////////////////
   // LUT section:
   HasLUT = file->HasLUT();
   if ( HasLUT )
   {
      // Just in case some access to a File element requires disk access.
      LutRedDescriptor   = file->GetEntryValue( 0x0028, 0x1101 );
      LutGreenDescriptor = file->GetEntryValue( 0x0028, 0x1102 );
      LutBlueDescriptor  = file->GetEntryValue( 0x0028, 0x1103 );
   
      // FIXME : The following comment is probabely meaningless, since LUT are *always*
      // loaded at parsing time, whatever their length is.
         
      // Depending on the value of Document::MAX_SIZE_LOAD_ELEMENT_VALUE
      // [ refer to invocation of Document::SetMaxSizeLoadEntry() in
      // Document::Document() ], the loading of the value (content) of a
      // [Bin|Val]Entry occurence migth have been hindered (read simply NOT
      // loaded). Hence, we first try to obtain the LUTs data from the file
      // and when this fails we read the LUTs data directly from disk.
      // \TODO Reading a [Bin|Val]Entry directly from disk is a kludge.
      //       We should NOT bypass the [Bin|Val]Entry class. Instead
      //       an access to an UNLOADED content of a [Bin|Val]Entry occurence
      //       (e.g. BinEntry::GetBinArea()) should force disk access from
      //       within the [Bin|Val]Entry class itself. The only problem
      //       is that the [Bin|Val]Entry is unaware of the FILE* is was
      //       parsed from. Fix that. FIXME.
   
      // //// Red round
      file->LoadEntryBinArea(0x0028, 0x1201);
      LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
      if ( ! LutRedData )
      {
         gdcmWarningMacro("Unable to read Red Palette Color Lookup Table data");
      }

      // //// Green round:
      file->LoadEntryBinArea(0x0028, 0x1202);
      LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
      if ( ! LutGreenData)
      {
         gdcmWarningMacro("Unable to read Green Palette Color Lookup Table data");
      }

      // //// Blue round:
      file->LoadEntryBinArea(0x0028, 0x1203);
      LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
      if ( ! LutBlueData )
      {
         gdcmWarningMacro("Unable to read Blue Palette Color Lookup Table data");
      }
   }
   FileInternal = file;   

   ComputeRawAndRGBSizes();
}

/// \brief Reads from disk and decompresses Pixels
bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
{
   // ComputeRawAndRGBSizes is already made by 
   // ::GrabInformationsFromfile. So, the structure sizes are
   // correct
   Squeeze();

   //////////////////////////////////////////////////
   //// First stage: get our hands on the Pixel Data.
   if ( !fp )
   {
      gdcmWarningMacro( "Unavailable file pointer." );
      return false;
   }

   fp->seekg( PixelOffset, std::ios::beg );
   if ( fp->fail() || fp->eof() )
   {
      gdcmWarningMacro( "Unable to find PixelOffset in file." );
      return false;
   }

   AllocateRaw();

   //////////////////////////////////////////////////
   //// Second stage: read from disk and decompress.
   if ( BitsAllocated == 12 ) // We suppose 'BitsAllocated' = 12 only exist for uncompressed files
   {
      ReadAndDecompress12BitsTo16Bits( fp);
   }
   else if ( IsRaw )
   {
      // This problem can be found when some obvious informations are found
      // after the field containing the image data. In this case, these
      // bad data are added to the size of the image (in the PixelDataLength
      // variable). But RawSize is the right size of the image !
      if ( PixelDataLength != RawSize )
      {
         gdcmWarningMacro( "Mismatch between PixelReadConvert : "
                            << PixelDataLength << " and RawSize : " << RawSize );
      }
      if ( PixelDataLength > RawSize )
      {
         fp->read( (char*)Raw, RawSize);
      }
      else
      {
         fp->read( (char*)Raw, RawSize);
      }

      if ( fp->fail() || fp->eof())
      {
         gdcmWarningMacro( "Reading of Raw pixel data failed." );
         return false;
      }
   } 
   else if ( IsRLELossless )
   {
      if ( ! RLEInfo->DecompressRLEFile
                               ( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
      {
         gdcmWarningMacro( "RLE decompressor failed." );
         return false;
      }
   }
   else if ( IsMPEG )
   {
      //gdcmWarningMacro( "Sorry, MPEG not yet taken into account" );
      //return false;
      // fp has already been seek to start of mpeg
      //ReadMPEGFile(fp, (char*)Raw, PixelDataLength); 
      return true;
   }
   else
   {
      // Default case concerns JPEG family
      if ( ! ReadAndDecompressJPEGFile( fp ) )
      {
         gdcmWarningMacro( "JPEG decompressor ( ReadAndDecompressJPEGFile()"
                              << " method ) failed." );
         return false;
      }
   }

   ////////////////////////////////////////////
   //// Third stage: twigle the bytes and bits.
   ConvertReorderEndianity();
   ConvertReArrangeBits();
   ConvertFixGreyLevels();
   if (UserFunction) // user is allowed to Mirror, TopDown, Rotate,...the image
      UserFunction( Raw, FileInternal);
   ConvertHandleColor();

   return true;
}

/// Deletes Pixels Area
void PixelReadConvert::Squeeze() 
{
   if ( RGB )
      delete [] RGB;
   RGB = 0;

   if ( Raw )
      delete [] Raw;
   Raw = 0;

   if ( LutRGBA )
      delete [] LutRGBA;
   LutRGBA = 0;
}

/**
 * \brief Build the RGB image from the Raw image and the LUTs.
 */
bool PixelReadConvert::BuildRGBImage()
{
   if ( RGB )
   {
      // The job is already done.
      return true;
   }

   if ( ! Raw )
   {
      // The job can't be done
      return false;
   }

   BuildLUTRGBA();
   if ( ! LutRGBA )
   {
      // The job can't be done
      return false;
   }

   gdcmDebugMacro( "--> BuildRGBImage" );
                                                                                
   // Build RGB Pixels
   AllocateRGB();
   
   int j;
   if ( BitsAllocated <= 8 )
   {
      uint8_t *localRGB = RGB;
      for (size_t i = 0; i < RawSize; ++i )
      {
         j  = Raw[i] * 4;
         *localRGB++ = LutRGBA[j];
         *localRGB++ = LutRGBA[j+1];
         *localRGB++ = LutRGBA[j+2];
      }
    }
 
    else  // deal with 16 bits pixels and 16 bits Palette color
    {
      uint16_t *localRGB = (uint16_t *)RGB;
      for (size_t i = 0; i < RawSize/2; ++i )
      {
         j  = ((uint16_t *)Raw)[i] * 4;
         *localRGB++ = ((uint16_t *)LutRGBA)[j];
         *localRGB++ = ((uint16_t *)LutRGBA)[j+1];
         *localRGB++ = ((uint16_t *)LutRGBA)[j+2];
      } 
    }

⌨️ 快捷键说明

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