Program: gdcm
Module: $RCSfile: gdcmPixelConvert.cxx,v $
Language: C++
- Date: $Date: 2004/10/22 04:13:26 $
- Version: $Revision: 1.19 $
+ Date: $Date: 2004/11/24 10:23:47 $
+ Version: $Revision: 1.32 $
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>
+#include <stdio.h>
namespace gdcm
{
-
#define str2num(str, typeNum) *((typeNum *)(str))
// For JPEG 2000, body in file gdcmJpeg2000.cxx
{
delete [] RGB;
}
+ RGB = 0;
+
if ( Decompressed )
{
delete [] Decompressed;
}
+ Decompressed = 0;
+
if ( LutRGBA )
{
delete [] LutRGBA;
}
+ LutRGBA = 0;
}
PixelConvert::~PixelConvert()
{
int nbPixels = XSize * YSize;
uint16_t* localDecompres = (uint16_t*)Decompressed;
-
+
for( int p = 0; p < nbPixels; p += 2 )
{
uint8_t b0, b1, b2;
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 ?
}
}
{
for ( unsigned int j = 0; j < PixelNumber; j++ )
{
- *(x++) = *(a++);
*(x++) = *(b++);
+ *(x++) = *(a++);
}
}
int8_t count;
long numberOfOutputBytes = 0;
long numberOfReadBytes = 0;
-
+
while( numberOfOutputBytes < decompressedSegmentSize )
{
fp->read( (char*)&count, 1 );
++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],
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;
it != JPEGInfo->Fragments.end();
++it )
{
- //fseek( fp, (*it)->Offset, SEEK_SET );
fp->seekg( (*it)->Offset, std::ios_base::beg);
if ( IsJPEG2000 )
return false;
}
}
- else if ( BitsStored == 12)
+ else if ( BitsStored <= 12)
{
// Reading Fragment pixels
if ( ! gdcm_read_JPEG_file12 ( fp, localDecompressed ) )
return false;
}
}
- else if ( BitsStored == 16)
+ else if ( BitsStored <= 16)
{
// Reading Fragment pixels
if ( ! gdcm_read_JPEG_file16 ( fp, localDecompressed ) )
"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++);
//// First stage: get our hands on the Pixel Data.
if ( !fp )
{
- dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: "
- "unavailable file pointer." );
+ dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: "
+ "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." );
+ 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 )
{
- fp->read( (char*)Decompressed, PixelDataLength);
+ // This problem can be found when some obvious informations are found
+ // after the field containing the image datas. In this case, these
+ // bad datas are added to the size of the image (in the PixelDataLength
+ // variable). But DecompressedSize is the right size of the image !
+ if( PixelDataLength != DecompressedSize)
+ {
+ dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: "
+ "Mismatch between PixelConvert and DecompressedSize." );
+ }
+ if( PixelDataLength > DecompressedSize)
+ {
+ fp->read( (char*)Decompressed, DecompressedSize);
+ }
+ else
+ {
+ fp->read( (char*)Decompressed, PixelDataLength);
+ }
+
if ( fp->fail() || fp->eof())//Fp->gcount() == 1
{
dbg.Verbose( 0, "PixelConvert::ReadAndDecompressPixelData: "
// [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
}
/**
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.
- std::ifstream* 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();
IsDecompressed =
( ! header->IsDicomV3() )
|| ts == ImplicitVRLittleEndian
+ || ts == ImplicitVRLittleEndianDLXGE
|| ts == ExplicitVRLittleEndian
|| ts == ExplicitVRBigEndian
|| ts == DeflatedExplicitVRLittleEndian;
DocEntry* lutRedDataEntry = header->GetDocEntryByNumber( 0x0028,
0x1201 );
LutRedData = new uint8_t[ lutRedDataEntry->GetLength() ];
- //fseek( fp, lutRedDataEntry->GetOffset() ,SEEK_SET );
fp->seekg( lutRedDataEntry->GetOffset() ,std::ios_base::beg );
- fp->read( (char*)LutRedData, (size_t)lutRedDataEntry->GetLength());
- //if ( numberItem != 1 )
- if ( fp->fail() || fp->eof())//Fp->gcount() == 1
+ 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" );
return;
}
}
-
+
////// Green round:
LutGreenData = (uint8_t*)header->GetEntryBinAreaByNumber(0x0028, 0x1202 );
if ( ! LutGreenData)
DocEntry* lutGreenDataEntry = header->GetDocEntryByNumber( 0x0028,
0x1202 );
LutGreenData = new uint8_t[ lutGreenDataEntry->GetLength() ];
- //fseek( fp, lutGreenDataEntry->GetOffset() ,SEEK_SET );
fp->seekg( lutGreenDataEntry->GetOffset() , std::ios_base::beg );
- fp->read( (char*)LutGreenData, (size_t)lutGreenDataEntry->GetLength() );
- //if ( numberItem != 1 )
- if ( fp->fail() || fp->eof())//Fp->gcount() == 1
+ 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" );
return;
}
}
-
+
////// Blue round:
LutBlueData = (uint8_t*)header->GetEntryBinAreaByNumber( 0x0028, 0x1203 );
if ( ! LutBlueData )
DocEntry* lutBlueDataEntry = header->GetDocEntryByNumber( 0x0028,
0x1203 );
LutBlueData = new uint8_t[ lutBlueDataEntry->GetLength() ];
- //fseek( fp, lutBlueDataEntry->GetOffset() ,SEEK_SET );
fp->seekg( lutBlueDataEntry->GetOffset() , std::ios_base::beg );
fp->read( (char*)LutBlueData, (size_t)lutBlueDataEntry->GetLength() );
- //if ( numberItem != 1 )
- if ( fp->fail() || fp->eof())//Fp->gcount() == 1
+ if ( fp->fail() || fp->eof())//Fp->gcount() == 1
{
dbg.Verbose(0, "PixelConvert::GrabInformationsFromHeader: "
"unable to read blue LUT data" );
}
}
}
-
- header->CloseFile();
+
+ if(fp) header->CloseFile();
}
/**
return;
}
- if ( ( LutRedDescriptor == GDCM_UNFOUND )
- || ( LutGreenDescriptor == GDCM_UNFOUND )
- || ( LutBlueDescriptor == GDCM_UNFOUND ) )
+ if ( LutRedDescriptor == GDCM_UNFOUND
+ || LutGreenDescriptor == GDCM_UNFOUND
+ || LutBlueDescriptor == GDCM_UNFOUND )
{
return;
}
*/
bool PixelConvert::BuildRGBImage()
{
+ if ( RGB )
+ {
+ // The job is already done.
+ return true;
+ }
+
+ if ( ! Decompressed )
+ {
+ // The job can't be done
+ return false;
+ }
+
BuildLUTRGBA();
- if ( ( ! LutRGBA ) || ( ! Decompressed ) )
+ 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];