-void PixelReadConvert::GrabInformationsFromHeader( Header *header )
-{
- // Number of Bits Allocated for storing a Pixel is defaulted to 16
- // when absent from the header.
- BitsAllocated = header->GetBitsAllocated();
- if ( BitsAllocated == 0 )
- {
- BitsAllocated = 16;
- }
-
- // Number of "Bits Stored" defaulted to number of "Bits Allocated"
- // when absent from the header.
- BitsStored = header->GetBitsStored();
- if ( BitsStored == 0 )
- {
- BitsStored = BitsAllocated;
- }
-
- // High Bit Position
- HighBitPosition = header->GetHighBitPosition();
- if ( HighBitPosition == 0 )
- {
- HighBitPosition = BitsAllocated - 1;
- }
-
- XSize = header->GetXSize();
- YSize = header->GetYSize();
- ZSize = header->GetZSize();
- SamplesPerPixel = header->GetSamplesPerPixel();
- PixelSize = header->GetPixelSize();
- PixelSign = header->IsSignedPixelData();
- SwapCode = header->GetSwapCode();
- std::string ts = header->GetTransferSyntax();
- IsRaw =
- ( ! header->IsDicomV3() )
- || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian
- || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndianDLXGE
- || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian
- || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian
- || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian;
- IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts);
- IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts);
- IsRLELossless = Global::GetTS()->IsRLELossless(ts);
- PixelOffset = header->GetPixelOffset();
- PixelDataLength = header->GetPixelAreaLength();
- RLEInfo = header->GetRLEInfo();
- JPEGInfo = header->GetJPEGInfo();
-
- PlanarConfiguration = header->GetPlanarConfiguration();
- IsMonochrome = header->IsMonochrome();
- IsPaletteColor = header->IsPaletteColor();
- IsYBRFull = header->IsYBRFull();
-
- /////////////////////////////////////////////////////////////////
- // LUT section:
- HasLUT = header->HasLUT();
- if ( HasLUT )
- {
- // Just in case some access to a Header element requires disk access.
- LutRedDescriptor = header->GetEntry( 0x0028, 0x1101 );
- LutGreenDescriptor = header->GetEntry( 0x0028, 0x1102 );
- LutBlueDescriptor = header->GetEntry( 0x0028, 0x1103 );
-
- // 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 header
- // and when this fails we read the LUTs data directely 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
- header->LoadEntryBinArea(0x0028, 0x1201);
- LutRedData = (uint8_t*)header->GetEntryBinArea( 0x0028, 0x1201 );
- if ( ! LutRedData )
- {
- gdcmVerboseMacro( "Unable to read red LUT data" );
- }
-
- ////// Green round:
- header->LoadEntryBinArea(0x0028, 0x1202);
- LutGreenData = (uint8_t*)header->GetEntryBinArea(0x0028, 0x1202 );
- if ( ! LutGreenData)
- {
- gdcmVerboseMacro( "Unable to read green LUT data" );
- }
-
- ////// Blue round:
- header->LoadEntryBinArea(0x0028, 0x1203);
- LutBlueData = (uint8_t*)header->GetEntryBinArea( 0x0028, 0x1203 );
- if ( ! LutBlueData )
- {
- gdcmVerboseMacro( "Unable to read blue LUT data" );
- }
- }
-
- ComputeRawAndRGBSizes();
-}
-
-/**
- * \brief Build Red/Green/Blue/Alpha LUT from Header
- * when (0028,0004),Photometric Interpretation = [PALETTE COLOR ]
- * and (0028,1101),(0028,1102),(0028,1102)
- * - xxx Palette Color Lookup Table Descriptor - are found
- * and (0028,1201),(0028,1202),(0028,1202)
- * - xxx Palette Color Lookup Table Data - are found
- * \warning does NOT deal with :
- * 0028 1100 Gray Lookup Table Descriptor (Retired)
- * 0028 1221 Segmented Red Palette Color Lookup Table Data
- * 0028 1222 Segmented Green Palette Color Lookup Table Data
- * 0028 1223 Segmented Blue Palette Color Lookup Table Data
- * no known Dicom reader deals with them :-(
- * @return a RGBA Lookup Table
- */
-void PixelReadConvert::BuildLUTRGBA()
-{
- if ( LutRGBA )
- {
- return;
- }
- // Not so easy : see
- // http://www.barre.nom.fr/medical/dicom2/limitations.html#Color%20Lookup%20Tables
-
- if ( ! IsPaletteColor )
- {
- return;
- }
-
- if ( LutRedDescriptor == GDCM_UNFOUND
- || LutGreenDescriptor == GDCM_UNFOUND
- || LutBlueDescriptor == GDCM_UNFOUND )
- {
- return;
- }
-
- ////////////////////////////////////////////
- // Extract the info from the LUT descriptors
- int lengthR; // Red LUT length in Bytes
- int debR; // Subscript of the first Lut Value
- int nbitsR; // Lut item size (in Bits)
- int nbRead = sscanf( LutRedDescriptor.c_str(),
- "%d\\%d\\%d",
- &lengthR, &debR, &nbitsR );
- if( nbRead != 3 )
- {
- gdcmVerboseMacro( "Wrong red LUT descriptor" );
- }
-
- int lengthG; // Green LUT length in Bytes
- int debG; // Subscript of the first Lut Value
- int nbitsG; // Lut item size (in Bits)
- nbRead = sscanf( LutGreenDescriptor.c_str(),
- "%d\\%d\\%d",
- &lengthG, &debG, &nbitsG );
- if( nbRead != 3 )
- {
- gdcmVerboseMacro( "Wrong green LUT descriptor" );
- }
-
- int lengthB; // Blue LUT length in Bytes
- int debB; // Subscript of the first Lut Value
- int nbitsB; // Lut item size (in Bits)
- nbRead = sscanf( LutRedDescriptor.c_str(),
- "%d\\%d\\%d",
- &lengthB, &debB, &nbitsB );
- if( nbRead != 3 )
- {
- gdcmVerboseMacro( "Wrong blue LUT descriptor" );
- }
-
- ////////////////////////////////////////////////////////
- if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
- {
- return;
- }
-
- ////////////////////////////////////////////////
- // forge the 4 * 8 Bits Red/Green/Blue/Alpha LUT
- LutRGBA = new uint8_t[ 1024 ]; // 256 * 4 (R, G, B, Alpha)
- if ( !LutRGBA )
- {
- return;
- }
- memset( LutRGBA, 0, 1024 );
-
- int mult;
- if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
- {
- // when LUT item size is different than pixel size
- mult = 2; // high byte must be = low byte
- }
- else
- {
- // See PS 3.3-2003 C.11.1.1.2 p 619
- mult = 1;
- }
-
- // if we get a black image, let's just remove the '+1'
- // from 'i*mult+1' and check again
- // if it works, we shall have to check the 3 Palettes
- // to see which byte is ==0 (first one, or second one)
- // and fix the code
- // We give up the checking to avoid some (useless ?)overhead
- // (optimistic asumption)
- int i;
- uint8_t* a = LutRGBA + 0;
- for( i=0; i < lengthR; ++i )
- {
- *a = LutRedData[i*mult+1];
- a += 4;
- }
-
- a = LutRGBA + 1;
- for( i=0; i < lengthG; ++i)
- {
- *a = LutGreenData[i*mult+1];
- a += 4;
- }
-
- a = LutRGBA + 2;
- for(i=0; i < lengthB; ++i)
- {
- *a = LutBlueData[i*mult+1];
- a += 4;
- }
-
- a = LutRGBA + 3;
- for(i=0; i < 256; ++i)
- {
- *a = 1; // Alpha component
- a += 4;
- }
-}
-
-/**
- * \brief Build the RGB image from the Raw imagage and the LUTs.
- */
-bool PixelReadConvert::BuildRGBImage()