00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "gdcmDebug.h"
00020 #include "gdcmFile.h"
00021 #include "gdcmGlobal.h"
00022 #include "gdcmTS.h"
00023 #include "gdcmPixelReadConvert.h"
00024 #include "gdcmDocEntry.h"
00025 #include "gdcmRLEFramesInfo.h"
00026 #include "gdcmJPEGFragmentsInfo.h"
00027
00028 #include <fstream>
00029 #include <stdio.h>
00030
00031 namespace gdcm
00032 {
00033
00034 #define str2num(str, typeNum) *((typeNum *)(str))
00035
00036
00037
00039 PixelReadConvert::PixelReadConvert()
00040 {
00041 RGB = 0;
00042 RGBSize = 0;
00043 Raw = 0;
00044 RawSize = 0;
00045 LutRGBA = 0;
00046 LutRedData = 0;
00047 LutGreenData = 0;
00048 LutBlueData = 0;
00049 }
00050
00052 PixelReadConvert::~PixelReadConvert()
00053 {
00054 Squeeze();
00055 }
00056
00057
00058
00063 bool PixelReadConvert::IsRawRGB()
00064 {
00065 if ( IsMonochrome
00066 || PlanarConfiguration == 2
00067 || IsPaletteColor )
00068 {
00069 return false;
00070 }
00071 return true;
00072 }
00077 void PixelReadConvert::GrabInformationsFromFile( File *file )
00078 {
00079
00080
00081 BitsAllocated = file->GetBitsAllocated();
00082 if ( BitsAllocated == 0 )
00083 {
00084 BitsAllocated = 16;
00085 }
00086
00087
00088
00089 BitsStored = file->GetBitsStored();
00090 if ( BitsStored == 0 )
00091 {
00092 BitsStored = BitsAllocated;
00093 }
00094
00095
00096 HighBitPosition = file->GetHighBitPosition();
00097 if ( HighBitPosition == 0 )
00098 {
00099 HighBitPosition = BitsAllocated - 1;
00100 }
00101
00102 XSize = file->GetXSize();
00103 YSize = file->GetYSize();
00104 ZSize = file->GetZSize();
00105 SamplesPerPixel = file->GetSamplesPerPixel();
00106 PixelSize = file->GetPixelSize();
00107 PixelSign = file->IsSignedPixelData();
00108 SwapCode = file->GetSwapCode();
00109 std::string ts = file->GetTransferSyntax();
00110 IsRaw =
00111 ( ! file->IsDicomV3() )
00112 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian
00113 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndianDLXGE
00114 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRLittleEndian
00115 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian
00116 || Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::DeflatedExplicitVRLittleEndian;
00117
00118 IsJPEG2000 = Global::GetTS()->IsJPEG2000(ts);
00119 IsJPEGLS = Global::GetTS()->IsJPEGLS(ts);
00120 IsJPEGLossy = Global::GetTS()->IsJPEGLossy(ts);
00121 IsJPEGLossless = Global::GetTS()->IsJPEGLossless(ts);
00122 IsRLELossless = Global::GetTS()->IsRLELossless(ts);
00123
00124 PixelOffset = file->GetPixelOffset();
00125 PixelDataLength = file->GetPixelAreaLength();
00126 RLEInfo = file->GetRLEInfo();
00127 JPEGInfo = file->GetJPEGInfo();
00128
00129 PlanarConfiguration = file->GetPlanarConfiguration();
00130 IsMonochrome = file->IsMonochrome();
00131 IsPaletteColor = file->IsPaletteColor();
00132 IsYBRFull = file->IsYBRFull();
00133
00135
00136 HasLUT = file->HasLUT();
00137 if ( HasLUT )
00138 {
00139
00140 LutRedDescriptor = file->GetEntryValue( 0x0028, 0x1101 );
00141 LutGreenDescriptor = file->GetEntryValue( 0x0028, 0x1102 );
00142 LutBlueDescriptor = file->GetEntryValue( 0x0028, 0x1103 );
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 file->LoadEntryBinArea(0x0028, 0x1201);
00160 LutRedData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1201 );
00161 if ( ! LutRedData )
00162 {
00163 gdcmWarningMacro( "Unable to read Red LUT data" );
00164 }
00165
00166
00167 file->LoadEntryBinArea(0x0028, 0x1202);
00168 LutGreenData = (uint8_t*)file->GetEntryBinArea(0x0028, 0x1202 );
00169 if ( ! LutGreenData)
00170 {
00171 gdcmWarningMacro( "Unable to read Green LUT data" );
00172 }
00173
00174
00175 file->LoadEntryBinArea(0x0028, 0x1203);
00176 LutBlueData = (uint8_t*)file->GetEntryBinArea( 0x0028, 0x1203 );
00177 if ( ! LutBlueData )
00178 {
00179 gdcmWarningMacro( "Unable to read Blue LUT data" );
00180 }
00181 }
00182
00183 ComputeRawAndRGBSizes();
00184 }
00185
00187 bool PixelReadConvert::ReadAndDecompressPixelData( std::ifstream *fp )
00188 {
00189
00190
00191
00192 Squeeze();
00193
00196 if ( !fp )
00197 {
00198 gdcmWarningMacro( "Unavailable file pointer." );
00199 return false;
00200 }
00201
00202 fp->seekg( PixelOffset, std::ios::beg );
00203 if( fp->fail() || fp->eof())
00204 {
00205 gdcmWarningMacro( "Unable to find PixelOffset in file." );
00206 return false;
00207 }
00208
00209 AllocateRaw();
00210
00213 if ( BitsAllocated == 12 )
00214 {
00215 ReadAndDecompress12BitsTo16Bits( fp);
00216 }
00217 else if ( IsRaw )
00218 {
00219
00220
00221
00222
00223 if( PixelDataLength != RawSize)
00224 {
00225 gdcmWarningMacro( "Mismatch between PixelReadConvert : "
00226 << PixelDataLength << " and RawSize : " << RawSize );
00227 }
00228 if( PixelDataLength > RawSize)
00229 {
00230 fp->read( (char*)Raw, RawSize);
00231 }
00232 else
00233 {
00234 fp->read( (char*)Raw, PixelDataLength);
00235 }
00236
00237 if ( fp->fail() || fp->eof())
00238 {
00239 gdcmWarningMacro( "Reading of Raw pixel data failed." );
00240 return false;
00241 }
00242 }
00243 else if ( IsRLELossless )
00244 {
00245 if ( ! RLEInfo->DecompressRLEFile( fp, Raw, XSize, YSize, ZSize, BitsAllocated ) )
00246 {
00247 gdcmWarningMacro( "RLE decompressor failed." );
00248 return false;
00249 }
00250 }
00251 else
00252 {
00253
00254 if ( ! ReadAndDecompressJPEGFile( fp ) )
00255 {
00256 gdcmWarningMacro( "JPEG decompressor failed." );
00257 return false;
00258 }
00259 }
00260
00263 ConvertReorderEndianity();
00264 ConvertReArrangeBits();
00265 ConvertHandleColor();
00266
00267 return true;
00268 }
00269
00271 void PixelReadConvert::Squeeze()
00272 {
00273 if ( RGB )
00274 delete [] RGB;
00275 RGB = 0;
00276
00277 if ( Raw )
00278 delete [] Raw;
00279 Raw = 0;
00280
00281 if ( LutRGBA )
00282 delete [] LutRGBA;
00283 LutRGBA = 0;
00284 }
00285
00289 bool PixelReadConvert::BuildRGBImage()
00290 {
00291 if ( RGB )
00292 {
00293
00294 return true;
00295 }
00296
00297 if ( ! Raw )
00298 {
00299
00300 return false;
00301 }
00302
00303 BuildLUTRGBA();
00304 if ( ! LutRGBA )
00305 {
00306
00307 return false;
00308 }
00309
00310
00311 AllocateRGB();
00312 uint8_t *localRGB = RGB;
00313 for (size_t i = 0; i < RawSize; ++i )
00314 {
00315 int j = Raw[i] * 4;
00316 *localRGB++ = LutRGBA[j];
00317 *localRGB++ = LutRGBA[j+1];
00318 *localRGB++ = LutRGBA[j+2];
00319 }
00320 return true;
00321 }
00322
00323
00324
00325
00326
00327
00332 void PixelReadConvert::ReadAndDecompress12BitsTo16Bits( std::ifstream *fp )
00333 throw ( FormatError )
00334 {
00335 int nbPixels = XSize * YSize;
00336 uint16_t *localDecompres = (uint16_t*)Raw;
00337
00338 for( int p = 0; p < nbPixels; p += 2 )
00339 {
00340 uint8_t b0, b1, b2;
00341
00342 fp->read( (char*)&b0, 1);
00343 if ( fp->fail() || fp->eof() )
00344 {
00345 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
00346 "Unfound first block" );
00347 }
00348
00349 fp->read( (char*)&b1, 1 );
00350 if ( fp->fail() || fp->eof())
00351 {
00352 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
00353 "Unfound second block" );
00354 }
00355
00356 fp->read( (char*)&b2, 1 );
00357 if ( fp->fail() || fp->eof())
00358 {
00359 throw FormatError( "PixelReadConvert::ReadAndDecompress12BitsTo16Bits()",
00360 "Unfound second block" );
00361 }
00362
00363
00364
00365
00366
00367
00368 *localDecompres++ = ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
00369
00370 *localDecompres++ = ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
00371
00373 }
00374 }
00375
00382 bool PixelReadConvert::ReadAndDecompressJPEGFile( std::ifstream *fp )
00383 {
00384 if ( IsJPEG2000 )
00385 {
00386 gdcmWarningMacro( "Sorry, JPEG2000 not yet taken into account" );
00387 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
00388
00389 return false;
00390 }
00391
00392 if ( IsJPEGLS )
00393 {
00394 gdcmWarningMacro( "Sorry, JPEG-LS not yet taken into account" );
00395 fp->seekg( JPEGInfo->GetFirstFragment()->GetOffset(), std::ios::beg);
00396
00397 return false;
00398 }
00399
00400
00401
00402 int length = XSize * YSize * SamplesPerPixel;
00403 int numberBytes = BitsAllocated / 8;
00404
00405 JPEGInfo->DecompressFromFile(fp, Raw, BitsStored, numberBytes, length );
00406 return true;
00407 }
00408
00424 void PixelReadConvert::BuildLUTRGBA()
00425 {
00426 if ( LutRGBA )
00427 {
00428 return;
00429 }
00430
00431
00432
00433 if ( ! IsPaletteColor )
00434 {
00435 return;
00436 }
00437
00438 if ( LutRedDescriptor == GDCM_UNFOUND
00439 || LutGreenDescriptor == GDCM_UNFOUND
00440 || LutBlueDescriptor == GDCM_UNFOUND )
00441 {
00442 return;
00443 }
00444
00446
00447 int lengthR;
00448 int debR;
00449 int nbitsR;
00450 int nbRead = sscanf( LutRedDescriptor.c_str(),
00451 "%d\\%d\\%d",
00452 &lengthR, &debR, &nbitsR );
00453 if( nbRead != 3 )
00454 {
00455 gdcmWarningMacro( "Wrong Red LUT descriptor" );
00456 }
00457
00458 int lengthG;
00459 int debG;
00460 int nbitsG;
00461 nbRead = sscanf( LutGreenDescriptor.c_str(),
00462 "%d\\%d\\%d",
00463 &lengthG, &debG, &nbitsG );
00464 if( nbRead != 3 )
00465 {
00466 gdcmWarningMacro( "Wrong Green LUT descriptor" );
00467 }
00468
00469 int lengthB;
00470 int debB;
00471 int nbitsB;
00472 nbRead = sscanf( LutRedDescriptor.c_str(),
00473 "%d\\%d\\%d",
00474 &lengthB, &debB, &nbitsB );
00475 if( nbRead != 3 )
00476 {
00477 gdcmWarningMacro( "Wrong Blue LUT descriptor" );
00478 }
00479
00481 if ( ( ! LutRedData ) || ( ! LutGreenData ) || ( ! LutBlueData ) )
00482 {
00483 return;
00484 }
00485
00487
00488 LutRGBA = new uint8_t[ 1024 ];
00489 if ( !LutRGBA )
00490 return;
00491
00492 memset( LutRGBA, 0, 1024 );
00493
00494 int mult;
00495 if ( ( nbitsR == 16 ) && ( BitsAllocated == 8 ) )
00496 {
00497
00498 mult = 2;
00499 }
00500 else
00501 {
00502
00503 mult = 1;
00504 }
00505
00506
00507
00508
00509
00510
00511
00512
00513 int i;
00514 uint8_t *a = LutRGBA + 0;
00515 for( i=0; i < lengthR; ++i )
00516 {
00517 *a = LutRedData[i*mult+1];
00518 a += 4;
00519 }
00520
00521 a = LutRGBA + 1;
00522 for( i=0; i < lengthG; ++i)
00523 {
00524 *a = LutGreenData[i*mult+1];
00525 a += 4;
00526 }
00527
00528 a = LutRGBA + 2;
00529 for(i=0; i < lengthB; ++i)
00530 {
00531 *a = LutBlueData[i*mult+1];
00532 a += 4;
00533 }
00534
00535 a = LutRGBA + 3;
00536 for(i=0; i < 256; ++i)
00537 {
00538 *a = 1;
00539 a += 4;
00540 }
00541 }
00542
00546 void PixelReadConvert::ConvertSwapZone()
00547 {
00548 unsigned int i;
00549
00550 if( BitsAllocated == 16 )
00551 {
00552 uint16_t *im16 = (uint16_t*)Raw;
00553 switch( SwapCode )
00554 {
00555 case 1234:
00556 break;
00557 case 3412:
00558 case 2143:
00559 case 4321:
00560 for( i = 0; i < RawSize / 2; i++ )
00561 {
00562 im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
00563 }
00564 break;
00565 default:
00566 gdcmWarningMacro("SwapCode value (16 bits) not allowed.");
00567 }
00568 }
00569 else if( BitsAllocated == 32 )
00570 {
00571 uint32_t s32;
00572 uint16_t high;
00573 uint16_t low;
00574 uint32_t *im32 = (uint32_t*)Raw;
00575 switch ( SwapCode )
00576 {
00577 case 1234:
00578 break;
00579 case 4321:
00580 for( i = 0; i < RawSize / 4; i++ )
00581 {
00582 low = im32[i] & 0x0000ffff;
00583 high = im32[i] >> 16;
00584 high = ( high >> 8 ) | ( high << 8 );
00585 low = ( low >> 8 ) | ( low << 8 );
00586 s32 = low;
00587 im32[i] = ( s32 << 16 ) | high;
00588 }
00589 break;
00590 case 2143:
00591 for( i = 0; i < RawSize / 4; i++ )
00592 {
00593 low = im32[i] & 0x0000ffff;
00594 high = im32[i] >> 16;
00595 high = ( high >> 8 ) | ( high << 8 );
00596 low = ( low >> 8 ) | ( low << 8 );
00597 s32 = high;
00598 im32[i] = ( s32 << 16 ) | low;
00599 }
00600 break;
00601 case 3412:
00602 for( i = 0; i < RawSize / 4; i++ )
00603 {
00604 low = im32[i] & 0x0000ffff;
00605 high = im32[i] >> 16;
00606 s32 = low;
00607 im32[i] = ( s32 << 16 ) | high;
00608 }
00609 break;
00610 default:
00611 gdcmWarningMacro("SwapCode value (32 bits) not allowed." );
00612 }
00613 }
00614 }
00615
00619 void PixelReadConvert::ConvertReorderEndianity()
00620 {
00621 if ( BitsAllocated != 8 )
00622 {
00623 ConvertSwapZone();
00624 }
00625
00626
00627 if ( BitsAllocated == 16
00628 && BitsStored < BitsAllocated
00629 && !PixelSign )
00630 {
00631 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
00632 uint16_t *deb = (uint16_t *)Raw;
00633 for(int i = 0; i<l; i++)
00634 {
00635 if( *deb == 0xffff )
00636 {
00637 *deb = 0;
00638 }
00639 deb++;
00640 }
00641 }
00642 }
00643
00648 bool PixelReadConvert::ConvertReArrangeBits() throw ( FormatError )
00649 {
00650 if ( BitsStored != BitsAllocated )
00651 {
00652 int l = (int)( RawSize / ( BitsAllocated / 8 ) );
00653 if ( BitsAllocated == 16 )
00654 {
00655 uint16_t mask = 0xffff;
00656 mask = mask >> ( BitsAllocated - BitsStored );
00657 uint16_t *deb = (uint16_t*)Raw;
00658 for(int i = 0; i<l; i++)
00659 {
00660 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & mask;
00661 deb++;
00662 }
00663 }
00664 else if ( BitsAllocated == 32 )
00665 {
00666 uint32_t mask = 0xffffffff;
00667 mask = mask >> ( BitsAllocated - BitsStored );
00668 uint32_t *deb = (uint32_t*)Raw;
00669 for(int i = 0; i<l; i++)
00670 {
00671 *deb = (*deb >> (BitsStored - HighBitPosition - 1)) & mask;
00672 deb++;
00673 }
00674 }
00675 else
00676 {
00677 gdcmWarningMacro("Weird image");
00678 throw FormatError( "Weird image !?" );
00679 }
00680 }
00681 return true;
00682 }
00683
00688 void PixelReadConvert::ConvertRGBPlanesToRGBPixels()
00689 {
00690 uint8_t *localRaw = Raw;
00691 uint8_t *copyRaw = new uint8_t[ RawSize ];
00692 memmove( copyRaw, localRaw, RawSize );
00693
00694 int l = XSize * YSize * ZSize;
00695
00696 uint8_t *a = copyRaw;
00697 uint8_t *b = copyRaw + l;
00698 uint8_t *c = copyRaw + l + l;
00699
00700 for (int j = 0; j < l; j++)
00701 {
00702 *(localRaw++) = *(a++);
00703 *(localRaw++) = *(b++);
00704 *(localRaw++) = *(c++);
00705 }
00706 delete[] copyRaw;
00707 }
00708
00713 void PixelReadConvert::ConvertYcBcRPlanesToRGBPixels()
00714 {
00715 uint8_t *localRaw = Raw;
00716 uint8_t *copyRaw = new uint8_t[ RawSize ];
00717 memmove( copyRaw, localRaw, RawSize );
00718
00719
00720
00721
00722
00723
00724 int l = XSize * YSize;
00725 int nbFrames = ZSize;
00726
00727 uint8_t *a = copyRaw;
00728 uint8_t *b = copyRaw + l;
00729 uint8_t *c = copyRaw + l + l;
00730 double R, G, B;
00731
00736
00737 for ( int i = 0; i < nbFrames; i++ )
00738 {
00739 for ( int j = 0; j < l; j++ )
00740 {
00741 R = 1.164 *(*a-16) + 1.596 *(*c -128) + 0.5;
00742 G = 1.164 *(*a-16) - 0.813 *(*c -128) - 0.392 *(*b -128) + 0.5;
00743 B = 1.164 *(*a-16) + 2.017 *(*b -128) + 0.5;
00744
00745 if (R < 0.0) R = 0.0;
00746 if (G < 0.0) G = 0.0;
00747 if (B < 0.0) B = 0.0;
00748 if (R > 255.0) R = 255.0;
00749 if (G > 255.0) G = 255.0;
00750 if (B > 255.0) B = 255.0;
00751
00752 *(localRaw++) = (uint8_t)R;
00753 *(localRaw++) = (uint8_t)G;
00754 *(localRaw++) = (uint8_t)B;
00755 a++;
00756 b++;
00757 c++;
00758 }
00759 }
00760 delete[] copyRaw;
00761 }
00762
00767
00768 void PixelReadConvert::ConvertHandleColor()
00769 {
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 if ( ! IsRawRGB() )
00809 {
00810
00811 return;
00812 }
00813
00814 if ( PlanarConfiguration == 1 )
00815 {
00816 if ( IsYBRFull )
00817 {
00818
00819 ConvertYcBcRPlanesToRGBPixels();
00820 }
00821 else
00822 {
00823
00824 ConvertRGBPlanesToRGBPixels();
00825 }
00826 return;
00827 }
00828
00829
00830
00831 if (IsRLELossless)
00832 {
00833 ConvertRGBPlanesToRGBPixels();
00834 }
00835
00836 }
00837
00839 void PixelReadConvert::ComputeRawAndRGBSizes()
00840 {
00841 int bitsAllocated = BitsAllocated;
00842
00843
00844
00845 if ( BitsAllocated == 12 )
00846 {
00847 bitsAllocated = 16;
00848 }
00849
00850 RawSize = XSize * YSize * ZSize
00851 * ( bitsAllocated / 8 )
00852 * SamplesPerPixel;
00853 if ( HasLUT )
00854 {
00855 RGBSize = 3 * RawSize;
00856 }
00857 else
00858 {
00859 RGBSize = RawSize;
00860 }
00861 }
00862
00864 void PixelReadConvert::AllocateRGB()
00865 {
00866 if ( RGB )
00867 delete [] RGB;
00868 RGB = new uint8_t[RGBSize];
00869 }
00870
00872 void PixelReadConvert::AllocateRaw()
00873 {
00874 if ( Raw )
00875 delete [] Raw;
00876 Raw = new uint8_t[RawSize];
00877 }
00878
00879
00880
00886 void PixelReadConvert::Print( std::ostream &os, std::string const &indent )
00887 {
00888 os << indent
00889 << "--- Pixel information -------------------------"
00890 << std::endl;
00891 os << indent
00892 << "Pixel Data: offset " << PixelOffset
00893 << " x(" << std::hex << PixelOffset << std::dec
00894 << ") length " << PixelDataLength
00895 << " x(" << std::hex << PixelDataLength << std::dec
00896 << ")" << std::endl;
00897
00898 if ( IsRLELossless )
00899 {
00900 if ( RLEInfo )
00901 {
00902 RLEInfo->Print( os, indent );
00903 }
00904 else
00905 {
00906 gdcmWarningMacro("Set as RLE file but NO RLEinfo present.");
00907 }
00908 }
00909
00910 if ( IsJPEG2000 || IsJPEGLossless || IsJPEGLossy || IsJPEGLS )
00911 {
00912 if ( JPEGInfo )
00913 {
00914 JPEGInfo->Print( os, indent );
00915 }
00916 else
00917 {
00918 gdcmWarningMacro("Set as JPEG file but NO JPEGinfo present.");
00919 }
00920 }
00921 }
00922
00923
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935