Program: gdcm
Module: $RCSfile: gdcmPixelConvert.cxx,v $
Language: C++
- Date: $Date: 2004/10/18 12:49:22 $
- Version: $Revision: 1.15 $
+ Date: $Date: 2004/10/28 22:21:57 $
+ Version: $Revision: 1.22 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
#include "gdcmDebug.h"
#include "gdcmPixelConvert.h"
+#include <fstream>
namespace gdcm
{
-
#define str2num(str, typeNum) *((typeNum *)(str))
// For JPEG 2000, body in file gdcmJpeg2000.cxx
-bool gdcm_read_JPEG2000_file (FILE* fp, void* image_buffer);
+bool gdcm_read_JPEG2000_file (std::ifstream* fp, void* image_buffer);
// For JPEG 8 Bits, body in file gdcmJpeg8.cxx
-bool gdcm_read_JPEG_file8 (FILE* fp, void* image_buffer);
+bool gdcm_read_JPEG_file8 (std::ifstream* fp, void* image_buffer);
// For JPEG 12 Bits, body in file gdcmJpeg12.cxx
-bool gdcm_read_JPEG_file12 (FILE* fp, void* image_buffer);
+bool gdcm_read_JPEG_file12 (std::ifstream* fp, void* image_buffer);
// For JPEG 16 Bits, body in file gdcmJpeg16.cxx
// Beware this is misleading there is no 16bits DCT algorithm, only
// jpeg lossless compression exist in 16bits.
-bool gdcm_read_JPEG_file16 (FILE* fp, void* image_buffer);
+bool gdcm_read_JPEG_file16 (std::ifstream* fp, void* image_buffer);
//-----------------------------------------------------------------------------
* \brief Read from file a 12 bits per pixel image and decompress it
* into a 16 bits per pixel image.
*/
-void PixelConvert::ReadAndDecompress12BitsTo16Bits( FILE* fp )
+void PixelConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream* fp )
throw ( FormatError )
{
int nbPixels = XSize * YSize;
uint16_t* localDecompres = (uint16_t*)Decompressed;
-
+
for( int p = 0; p < nbPixels; p += 2 )
{
uint8_t b0, b1, b2;
- size_t ItemRead;
-
- ItemRead = fread( &b0, 1, 1, fp );
- if ( ItemRead != 1 )
+
+ fp->read( (char*)&b0, 1);
+ if ( fp->fail() || fp->eof() )//Fp->gcount() == 1
{
throw FormatError( "PixelConvert::ReadAndDecompress12BitsTo16Bits()",
"Unfound first block" );
}
-
- ItemRead = fread( &b1, 1, 1, fp );
- if ( ItemRead != 1 )
+
+ fp->read( (char*)&b1, 1 );
+ if ( fp->fail() || fp->eof())//Fp->gcount() == 1
{
throw FormatError( "PixelConvert::ReadAndDecompress12BitsTo16Bits()",
"Unfound second block" );
}
-
- ItemRead = fread( &b2, 1, 1, fp );
- if ( ItemRead != 1 )
+
+ fp->read( (char*)&b2, 1 );
+ if ( fp->fail() || fp->eof())//Fp->gcount() == 1
{
throw FormatError( "PixelConvert::ReadAndDecompress12BitsTo16Bits()",
"Unfound second block" );
}
-
+
// Two steps are necessary to please VC++
//
// 2 pixels 12bit = [0xABCDEF]
*localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
// F C E
*localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
-
+
/// \todo JPR Troubles expected on Big-Endian processors ?
}
}
bool PixelConvert::ReadAndDecompressRLEFragment( uint8_t* subDecompressed,
long fragmentSize,
long decompressedSegmentSize,
- FILE* fp )
+ std::ifstream* fp )
{
int8_t count;
long numberOfOutputBytes = 0;
long numberOfReadBytes = 0;
-
+
while( numberOfOutputBytes < decompressedSegmentSize )
{
- fread( &count, 1, 1, fp );
+ fp->read( (char*)&count, 1 );
numberOfReadBytes += 1;
if ( count >= 0 )
// Note: count <= 127 comparison is always true due to limited range
// signed integer of width N is 2^(N-1) - 1, which for int8_t
// is 127].
{
- fread( subDecompressed, count + 1, 1, fp);
+ fp->read( (char*)subDecompressed, count + 1);
numberOfReadBytes += count + 1;
subDecompressed += count + 1;
numberOfOutputBytes += count + 1;
if ( ( count <= -1 ) && ( count >= -127 ) )
{
int8_t newByte;
- fread( &newByte, 1, 1, fp);
+ fp->read( (char*)&newByte, 1);
numberOfReadBytes += 1;
for( int i = 0; i < -count + 1; i++ )
{
* at which the pixel data should be copied
* @return Boolean
*/
-bool PixelConvert::ReadAndDecompressRLEFile( FILE* fp )
+bool PixelConvert::ReadAndDecompressRLEFile( std::ifstream* fp )
{
uint8_t* subDecompressed = Decompressed;
long decompressedSegmentSize = XSize * YSize;
++it )
{
// Loop on the fragments
- for( int k = 1; k <= (*it)->NumberFragments; k++ )
+ for( unsigned int k = 1; k <= (*it)->NumberFragments; k++ )
{
- fseek( fp, (*it)->Offset[k] ,SEEK_SET );
+ fp->seekg( (*it)->Offset[k] , std::ios_base::beg );
(void)ReadAndDecompressRLEFragment( subDecompressed,
(*it)->Length[k],
decompressedSegmentSize,
subDecompressed += decompressedSegmentSize;
}
}
-
+
if ( BitsAllocated == 16 )
{
// Try to deal with RLE 16 Bits
(void)DecompressRLE16BitsFromRLE8Bits( ZSize );
}
-
+
return true;
}
void PixelConvert::ConvertSwapZone()
{
unsigned int i;
-
+
if( BitsAllocated == 16 )
{
uint16_t* im16 = (uint16_t*)Decompressed;
* @param fp File Pointer
* @return Boolean
*/
-bool PixelConvert::ReadAndDecompressJPEGFile( FILE* fp )
+bool PixelConvert::ReadAndDecompressJPEGFile( std::ifstream* fp )
{
uint8_t* localDecompressed = Decompressed;
// Loop on the fragment[s]
it != JPEGInfo->Fragments.end();
++it )
{
- fseek( fp, (*it)->Offset, SEEK_SET );
+ fp->seekg( (*it)->Offset, std::ios_base::beg);
if ( IsJPEG2000 )
{
"jpeg lossy compression ");
return false;
}
-
+
// Advance to next free location in Decompressed
// for next fragment decompression (if any)
int length = XSize * YSize * SamplesPerPixel;
int numberBytes = BitsAllocated / 8;
-
+
localDecompressed += length * numberBytes;
}
return true;
uint8_t* localDecompressed = Decompressed;
uint8_t* copyDecompressed = new uint8_t[ DecompressedSize ];
memmove( copyDecompressed, localDecompressed, DecompressedSize );
-
+
// to see the tricks about YBR_FULL, YBR_FULL_422,
// YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
// ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
//
int l = XSize * YSize;
int nbFrames = ZSize;
-
+
uint8_t* a = copyDecompressed;
uint8_t* b = copyDecompressed + l;
uint8_t* c = copyDecompressed + l + l;
double R, G, B;
-
+
/// \todo : Replace by the 'well known' integer computation
/// counterpart. Refer to
/// http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
/// for code optimisation.
-
+
for ( int i = 0; i < nbFrames; i++ )
{
for ( int j = 0; j < l; j++ )
R = 1.164 *(*a-16) + 1.596 *(*c -128) + 0.5;
G = 1.164 *(*a-16) - 0.813 *(*c -128) - 0.392 *(*b -128) + 0.5;
B = 1.164 *(*a-16) + 2.017 *(*b -128) + 0.5;
-
+
if (R < 0.0) R = 0.0;
if (G < 0.0) G = 0.0;
if (B < 0.0) B = 0.0;
if (R > 255.0) R = 255.0;
if (G > 255.0) G = 255.0;
if (B > 255.0) B = 255.0;
-
+
*(localDecompressed++) = (uint8_t)R;
*(localDecompressed++) = (uint8_t)G;
*(localDecompressed++) = (uint8_t)B;
uint8_t* localDecompressed = Decompressed;
uint8_t* copyDecompressed = new uint8_t[ DecompressedSize ];
memmove( copyDecompressed, localDecompressed, DecompressedSize );
-
+
int l = XSize * YSize * ZSize;
-
+
uint8_t* a = copyDecompressed;
uint8_t* b = copyDecompressed + l;
uint8_t* c = copyDecompressed + l + l;
-
+
for (int j = 0; j < l; j++)
{
*(localDecompressed++) = *(a++);
delete[] copyDecompressed;
}
-bool PixelConvert::ReadAndDecompressPixelData( FILE* fp )
+bool PixelConvert::ReadAndDecompressPixelData( std::ifstream* fp )
{
ComputeDecompressedAndRGBSizes();
AllocateDecompressed();
"unavailable file pointer." );
return false;
}
-
- if ( fseek( fp, PixelOffset, SEEK_SET ) == -1 )
+
+ fp->seekg( PixelOffset, std::ios_base::beg );
+ if( fp->fail() || fp->eof()) //Fp->gcount() == 1
{
dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: "
"unable to find PixelOffset in file." );
return false;
}
-
+
//////////////////////////////////////////////////
//// Second stage: read from disk dans decompress.
if ( BitsAllocated == 12 )
}
else if ( IsDecompressed )
{
- size_t ItemRead = fread( Decompressed, PixelDataLength, 1, fp );
- if ( ItemRead != 1 )
+ fp->read( (char*)Decompressed, PixelDataLength);
+ if ( fp->fail() || fp->eof())//Fp->gcount() == 1
{
dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: "
"reading of decompressed pixel data failed." );
// [Planar 1] AND [Photo C]
ConvertRGBPlanesToRGBPixels();
}
+ return;
}
- // When planarConf is 0, pixels are allready in RGB
+ // When planarConf is 0, and RLELossless (forbidden by Dicom norm)
+ // pixels need to be RGB-fied anyway
+ if (IsRLELossless)
+ {
+ ConvertRGBPlanesToRGBPixels();
+ }
+ // In *normal *case, when planarConf is 0, pixels are already in RGB
}
/**
* \brief Predicate to know wether the image[s] (once decompressed) is RGB.
- * \note See comments of \ref HandleColor
+ * \note See comments of \ref ConvertHandleColor
*/
bool PixelConvert::IsDecompressedRGB()
{
if ( IsMonochrome
- || ( PlanarConfiguration == 2 )
+ || PlanarConfiguration == 2
|| IsPaletteColor )
{
return false;
{
// Just in case some access to a Header element requires disk access.
// Note: gdcmDocument::Fp is leaved open after OpenFile.
- FILE* fp = header->OpenFile();
+ std::ifstream* fp = header->OpenFile();
// Number of Bits Allocated for storing a Pixel is defaulted to 16
// when absent from the header.
BitsAllocated = header->GetBitsAllocated();
PixelSize = header->GetPixelSize();
PixelSign = header->IsSignedPixelData();
SwapCode = header->GetSwapCode();
+ TransferSyntaxType ts = header->GetTransferSyntax();
IsDecompressed =
( ! header->IsDicomV3() )
- || header->IsImplicitVRLittleEndianTransferSyntax()
- || header->IsExplicitVRLittleEndianTransferSyntax()
- || header->IsExplicitVRBigEndianTransferSyntax()
- || header->IsDeflatedExplicitVRLittleEndianTransferSyntax();
+ || ts == ImplicitVRLittleEndian
+ || ts == ExplicitVRLittleEndian
+ || ts == ExplicitVRBigEndian
+ || ts == DeflatedExplicitVRLittleEndian;
IsJPEG2000 = header->IsJPEG2000();
IsJPEGLossless = header->IsJPEGLossless();
- IsRLELossless = header->IsRLELossLessTransferSyntax();
+ IsRLELossless = ( ts == RLELossless );
PixelOffset = header->GetPixelOffset();
PixelDataLength = header->GetPixelAreaLength();
RLEInfo = header->GetRLEInfo();
DocEntry* lutRedDataEntry = header->GetDocEntryByNumber( 0x0028,
0x1201 );
LutRedData = new uint8_t[ lutRedDataEntry->GetLength() ];
- fseek( fp, lutRedDataEntry->GetOffset() ,SEEK_SET );
- int numberItem = fread( LutRedData,
- (size_t)lutRedDataEntry->GetLength(),
- 1, fp );
- if ( numberItem != 1 )
+ fp->seekg( lutRedDataEntry->GetOffset() ,std::ios_base::beg );
+ fp->read( (char*)LutRedData, (size_t)lutRedDataEntry->GetLength());
+ if ( fp->fail() || fp->eof())//Fp->gcount() == 1
{
dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: "
"unable to read red LUT data" );
DocEntry* lutGreenDataEntry = header->GetDocEntryByNumber( 0x0028,
0x1202 );
LutGreenData = new uint8_t[ lutGreenDataEntry->GetLength() ];
- fseek( fp, lutGreenDataEntry->GetOffset() ,SEEK_SET );
- int numberItem = fread( LutGreenData,
- (size_t)lutGreenDataEntry->GetLength(),
- 1, fp );
- if ( numberItem != 1 )
+ fp->seekg( lutGreenDataEntry->GetOffset() , std::ios_base::beg );
+ fp->read( (char*)LutGreenData, (size_t)lutGreenDataEntry->GetLength() );
+ if ( fp->fail() || fp->eof())//Fp->gcount() == 1
{
dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: "
"unable to read green LUT data" );
DocEntry* lutBlueDataEntry = header->GetDocEntryByNumber( 0x0028,
0x1203 );
LutBlueData = new uint8_t[ lutBlueDataEntry->GetLength() ];
- fseek( fp, lutBlueDataEntry->GetOffset() ,SEEK_SET );
- int numberItem = fread( LutBlueData,
- (size_t)lutBlueDataEntry->GetLength(),
- 1, fp );
- if ( numberItem != 1 )
+ fp->seekg( lutBlueDataEntry->GetOffset() , std::ios_base::beg );
+ fp->read( (char*)LutBlueData, (size_t)lutBlueDataEntry->GetLength() );
+ if ( fp->fail() || fp->eof())//Fp->gcount() == 1
{
dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: "
"unable to read blue LUT data" );
* no known Dicom reader deals with them :-(
* @return a RGBA Lookup Table
*/
-void PixelConvert::BuildLUTRGBA( FILE* fp )
+void PixelConvert::BuildLUTRGBA()
{
if ( LutRGBA )
{
return;
}
- if ( ( LutRedDescriptor == GDCM_UNFOUND )
- || ( LutGreenDescriptor == GDCM_UNFOUND )
- || ( LutBlueDescriptor == GDCM_UNFOUND ) )
+ if ( LutRedDescriptor == GDCM_UNFOUND
+ || LutGreenDescriptor == GDCM_UNFOUND
+ || LutBlueDescriptor == GDCM_UNFOUND )
{
return;
}
/**
* \brief Build the RGB image from the Decompressed imagage and the LUTs.
*/
-bool PixelConvert::BuildRGBImage( FILE* fp )
+bool PixelConvert::BuildRGBImage()
{
- BuildLUTRGBA( fp );
+ if ( RGB )
+ {
+ // The job is already done.
+ return true;
+ }
+
+ if ( ! Decompressed )
+ {
+ // The job can't be done
+ return false;
+ }
+
+ BuildLUTRGBA();
if ( ! LutRGBA )
{
- return false;
+ // The job can't be done
+ return false;
}
// Build RGB Pixels
uint8_t* localRGB = RGB;
for (size_t i = 0; i < DecompressedSize; ++i )
{
- int j = Decompressed[i] * 4; // \todo I don't get this 4 coefficient !
+ int j = Decompressed[i] * 4;
*localRGB++ = LutRGBA[j];
*localRGB++ = LutRGBA[j+1];
*localRGB++ = LutRGBA[j+2];
return true;
}
+/**
+ * \brief Print self.
+ * @param indent Indentation string to be prepended during printing.
+ * @param os Stream to print to.
+ */
+void PixelConvert::Print( std::string indent, std::ostream &os )
+{
+ os << indent
+ << "--- Pixel information -------------------------"
+ << std::endl;
+ os << indent
+ << "Pixel Data: offset " << PixelOffset
+ << " x" << std::hex << PixelOffset << std::dec
+ << " length " << PixelDataLength
+ << " x" << std::hex << PixelDataLength << std::dec
+ << std::endl;
+
+ if ( IsRLELossless )
+ {
+ if ( RLEInfo )
+ {
+ RLEInfo->Print( indent, os );
+ }
+ else
+ {
+ dbg.Verbose(0, "PixelConvert::Print: set as RLE file "
+ "but NO RLEinfo present.");
+ }
+ }
+
+ if ( IsJPEG2000 || IsJPEGLossless )
+ {
+ if ( JPEGInfo )
+ {
+ JPEGInfo->Print( indent, os );
+ }
+ else
+ {
+ dbg.Verbose(0, "PixelConvert::Print: set as JPEG file "
+ "but NO JPEGinfo present.");
+ }
+ }
+}
} // end namespace gdcm