00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 #include "gdcmFile.h"
00091 #include "gdcmGlobal.h"
00092 #include "gdcmUtil.h"
00093 #include "gdcmDebug.h"
00094 #include "gdcmTS.h"
00095 #include "gdcmSeqEntry.h"
00096 #include "gdcmRLEFramesInfo.h"
00097 #include "gdcmJPEGFragmentsInfo.h"
00098 #include "gdcmDataEntry.h"
00099
00100 #include <vector>
00101 #include <stdio.h>
00102 #include <stdlib.h>
00103
00104 namespace gdcm
00105 {
00106
00107
00108
00109
00113 File::File():
00114 Document()
00115 {
00116 RLEInfo = new RLEFramesInfo;
00117 JPEGInfo = new JPEGFragmentsInfo;
00118 GrPixel = 0x7fe0;
00119 NumPixel = 0x0010;
00120 BasicOffsetTableItemValue = 0;
00121 }
00122
00123
00127 File::~File ()
00128 {
00129 if ( RLEInfo )
00130 delete RLEInfo;
00131 if ( JPEGInfo )
00132 delete JPEGInfo;
00133 delete[] BasicOffsetTableItemValue;
00134 }
00135
00136
00137
00143 bool File::Load( )
00144 {
00145 if ( ! this->Document::Load( ) )
00146 return false;
00147
00148 return DoTheLoadingJob( );
00149 }
00150
00156 bool File::DoTheLoadingJob( )
00157 {
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 const std::string &imgLocation = GetEntryString(0x0028, 0x0200);
00170 if ( imgLocation == GDCM_UNFOUND )
00171 {
00172
00173 GrPixel = 0x7fe0;
00174 }
00175 else
00176 {
00177 GrPixel = (uint16_t) atoi( imgLocation.c_str() );
00178 }
00179
00180
00181
00182
00183 if ( GrPixel == 0xe07f )
00184 {
00185 GrPixel = 0x7fe0;
00186 }
00187
00188 if ( GrPixel != 0x7fe0 )
00189 {
00190
00191 NumPixel = 0x1010;
00192 }
00193 else
00194 {
00195 NumPixel = 0x0010;
00196 }
00197
00198
00199
00200
00201 DocEntry *entry = GetDocEntry(GrPixel, NumPixel);
00202 if ( entry != 0 )
00203 {
00204
00205 OpenFile();
00206 const std::string &ts = GetTransferSyntax();
00207 Fp->seekg( entry->GetOffset(), std::ios::beg );
00208 if ( Global::GetTS()->IsRLELossless(ts) )
00209 ComputeRLEInfo();
00210 else if ( Global::GetTS()->IsJPEG(ts) )
00211 ComputeJPEGFragmentInfo();
00212 CloseFile();
00213
00214
00215
00216
00217
00218 DataEntry *oldEntry = dynamic_cast<DataEntry *>(entry);
00219 if (oldEntry)
00220 {
00221 VRKey PixelVR;
00222
00223
00224 if ( GetBitsAllocated() == 8 || GetBitsAllocated() == 24 )
00225 PixelVR = "OB";
00226 else
00227 PixelVR = "OW";
00228
00229
00230 if ( PixelVR != oldEntry->GetVR() )
00231 {
00232 DictEntry* newDict = DictEntry::New(GrPixel,NumPixel,
00233 PixelVR,"1","Pixel Data");
00234
00235 DataEntry *newEntry = DataEntry::New(newDict);
00236 newDict->Delete();
00237 newEntry->Copy(entry);
00238 newEntry->SetBinArea(oldEntry->GetBinArea(),oldEntry->IsSelfArea());
00239 oldEntry->SetSelfArea(false);
00240
00241 RemoveEntry(oldEntry);
00242 AddEntry(newEntry);
00243 newEntry->Delete();
00244 }
00245 }
00246 }
00247 return true;
00248 }
00257 bool File::IsReadable()
00258 {
00259 if ( !Document::IsReadable() )
00260 {
00261 return false;
00262 }
00263
00264 const std::string &res = GetEntryString(0x0028, 0x0005);
00265 if ( res != GDCM_UNFOUND && atoi(res.c_str()) > 4 )
00266 {
00267 gdcmWarningMacro("Wrong Image Dimensions" << res);
00268 return false;
00269 }
00270 bool b0028_0100 = true;
00271 if ( !GetDocEntry(0x0028, 0x0100) )
00272 {
00273 gdcmWarningMacro("Bits Allocated (0028|0100) not found");
00274
00275 b0028_0100 = false;
00276 }
00277 bool b0028_0101 = true;
00278 if ( !GetDocEntry(0x0028, 0x0101) )
00279 {
00280 gdcmWarningMacro("Bits Stored (0028|0101) not found");
00281
00282 b0028_0101 = false;
00283 }
00284 bool b0028_0102 = true;
00285 if ( !GetDocEntry(0x0028, 0x0102) )
00286 {
00287 gdcmWarningMacro("Hight Bit (0028|0102) not found");
00288
00289 b0028_0102 = false;
00290 }
00291 bool b0028_0103 = true;
00292 if ( !GetDocEntry(0x0028, 0x0103) )
00293 {
00294 gdcmWarningMacro("Pixel Representation (0028|0103) not found");
00295
00296 b0028_0103 = false;
00297 }
00298
00299 if ( !b0028_0100 && !b0028_0101 && !b0028_0102 && !b0028_0103)
00300 {
00301 gdcmWarningMacro("Too much mandatory Tags missing !");
00302 return false;
00303 }
00304
00305 if ( !GetDocEntry(GrPixel, NumPixel) )
00306 {
00307 gdcmWarningMacro("Pixel Dicom Element " << std::hex <<
00308 GrPixel << "|" << NumPixel << "not found");
00309 return false;
00310 }
00311 return true;
00312 }
00313
00318 int File::GetImageNumber()
00319 {
00320
00321 std::string strImNumber = GetEntryString(0x0020,0x0013);
00322 if ( strImNumber != GDCM_UNFOUND )
00323 {
00324 return atoi( strImNumber.c_str() );
00325 }
00326 return 0;
00327 }
00328
00333 ModalityType File::GetModality()
00334 {
00335
00336 std::string strModality = GetEntryString(0x0008,0x0060);
00337 if ( strModality != GDCM_UNFOUND )
00338 {
00339 if ( strModality.find("AU") < strModality.length()) return AU;
00340 else if ( strModality.find("AS") < strModality.length()) return AS;
00341 else if ( strModality.find("BI") < strModality.length()) return BI;
00342 else if ( strModality.find("CF") < strModality.length()) return CF;
00343 else if ( strModality.find("CP") < strModality.length()) return CP;
00344 else if ( strModality.find("CR") < strModality.length()) return CR;
00345 else if ( strModality.find("CT") < strModality.length()) return CT;
00346 else if ( strModality.find("CS") < strModality.length()) return CS;
00347 else if ( strModality.find("DD") < strModality.length()) return DD;
00348 else if ( strModality.find("DF") < strModality.length()) return DF;
00349 else if ( strModality.find("DG") < strModality.length()) return DG;
00350 else if ( strModality.find("DM") < strModality.length()) return DM;
00351 else if ( strModality.find("DS") < strModality.length()) return DS;
00352 else if ( strModality.find("DX") < strModality.length()) return DX;
00353 else if ( strModality.find("ECG") < strModality.length()) return ECG;
00354 else if ( strModality.find("EPS") < strModality.length()) return EPS;
00355 else if ( strModality.find("FA") < strModality.length()) return FA;
00356 else if ( strModality.find("FS") < strModality.length()) return FS;
00357 else if ( strModality.find("HC") < strModality.length()) return HC;
00358 else if ( strModality.find("HD") < strModality.length()) return HD;
00359 else if ( strModality.find("LP") < strModality.length()) return LP;
00360 else if ( strModality.find("LS") < strModality.length()) return LS;
00361 else if ( strModality.find("MA") < strModality.length()) return MA;
00362 else if ( strModality.find("MR") < strModality.length()) return MR;
00363 else if ( strModality.find("NM") < strModality.length()) return NM;
00364 else if ( strModality.find("OT") < strModality.length()) return OT;
00365 else if ( strModality.find("PT") < strModality.length()) return PT;
00366 else if ( strModality.find("RF") < strModality.length()) return RF;
00367 else if ( strModality.find("RG") < strModality.length()) return RG;
00368 else if ( strModality.find("RTDOSE")
00369 < strModality.length()) return RTDOSE;
00370 else if ( strModality.find("RTIMAGE")
00371 < strModality.length()) return RTIMAGE;
00372 else if ( strModality.find("RTPLAN")
00373 < strModality.length()) return RTPLAN;
00374 else if ( strModality.find("RTSTRUCT")
00375 < strModality.length()) return RTSTRUCT;
00376 else if ( strModality.find("SM") < strModality.length()) return SM;
00377 else if ( strModality.find("ST") < strModality.length()) return ST;
00378 else if ( strModality.find("TG") < strModality.length()) return TG;
00379 else if ( strModality.find("US") < strModality.length()) return US;
00380 else if ( strModality.find("VF") < strModality.length()) return VF;
00381 else if ( strModality.find("XA") < strModality.length()) return XA;
00382 else if ( strModality.find("XC") < strModality.length()) return XC;
00383
00384 else
00385 {
00388 return Unknow;
00389 }
00390 }
00391 return Unknow;
00392 }
00393
00399 int File::GetXSize()
00400 {
00401 DataEntry *entry = GetDataEntry(0x0028,0x0011);
00402 if( entry )
00403 return (int)entry->GetValue(0);
00404 return 0;
00405 }
00406
00413 int File::GetYSize()
00414 {
00415 DataEntry *entry = GetDataEntry(0x0028,0x0010);
00416 if( entry )
00417 return (int)entry->GetValue(0);
00418
00419 if ( IsDicomV3() )
00420 {
00421 return 0;
00422 }
00423
00424
00425
00426
00427 return 1;
00428 }
00429
00438 int File::GetZSize()
00439 {
00440
00441
00442 DataEntry *entry = GetDataEntry(0x0028,0x0008);
00443 if( entry )
00444 return (int)entry->GetValue(0);
00445
00446
00447 entry = GetDataEntry(0x0028,0x0012);
00448 if( entry )
00449 return (int)entry->GetValue(0);
00450 return 1;
00451 }
00452
00459 float File::GetXSpacing()
00460 {
00461 float xspacing = 1.0;
00462 uint32_t nbValue;
00463
00464
00465
00466 DataEntry *entry = GetDataEntry(0x0018,0x1164);
00467 if( entry )
00468 {
00469 nbValue = entry->GetValueCount();
00470
00471 if( nbValue !=2 )
00472 gdcmWarningMacro("ImagerPixelSpacing (0x0018,0x1164) "
00473 << "has a wrong number of values :" << nbValue);
00474
00475 if( nbValue >= 3 )
00476 xspacing = (float)entry->GetValue(2);
00477 else if( nbValue >= 2 )
00478 xspacing = (float)entry->GetValue(1);
00479 else
00480 xspacing = (float)entry->GetValue(0);
00481
00482 if ( xspacing == 0.0 )
00483 xspacing = 1.0;
00484 return xspacing;
00485 }
00486 else
00487 {
00488 gdcmWarningMacro( "Unfound Imager Pixel Spacing (0018,1164)" );
00489 }
00490
00491 entry = GetDataEntry(0x0028,0x0030);
00492 if( entry )
00493 {
00494 nbValue = entry->GetValueCount();
00495 if( nbValue !=2 )
00496 gdcmWarningMacro("PixelSpacing (0x0018,0x0030) "
00497 << "has a wrong number of values :" << nbValue);
00498
00499 if( nbValue >= 3 )
00500 xspacing = (float)entry->GetValue(2);
00501 else if( nbValue >= 2 )
00502 xspacing = (float)entry->GetValue(1);
00503 else
00504 xspacing = (float)entry->GetValue(0);
00505
00506 if ( xspacing == 0.0 )
00507 xspacing = 1.0;
00508 return xspacing;
00509 }
00510 else
00511 {
00512 gdcmWarningMacro( "Unfound Pixel Spacing (0028,0030)" );
00513 }
00514
00515 return xspacing;
00516 }
00517
00524 float File::GetYSpacing()
00525 {
00526 float yspacing = 1.0;
00527
00528
00529 DataEntry *entry = GetDataEntry(0x0018,0x1164);
00530 if( entry )
00531 {
00532 yspacing = (float)entry->GetValue(0);
00533
00534 if ( yspacing == 0.0 )
00535 yspacing = 1.0;
00536 return yspacing;
00537 }
00538 else
00539 {
00540 gdcmWarningMacro( "Unfound Imager Pixel Spacing (0018,1164)" );
00541 }
00542
00543 entry = GetDataEntry(0x0028,0x0030);
00544 if( entry )
00545 {
00546 yspacing = (float)entry->GetValue(0);
00547
00548 if ( yspacing == 0.0 )
00549 yspacing = 1.0;
00550 return yspacing;
00551 }
00552 else
00553 {
00554 gdcmWarningMacro( "Unfound Pixel Spacing (0028,0030)" );
00555 }
00556
00557 return yspacing;
00558 }
00559
00574 float File::GetZSpacing()
00575 {
00576
00577 float zspacing = 1.0f;
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588 DataEntry *entry = GetDataEntry(0x0018,0x0088);
00589 if( entry )
00590 {
00591 zspacing = (float)entry->GetValue(0);
00592
00593 if ( zspacing == 0.0 )
00594 zspacing = 1.0;
00595 return zspacing;
00596 }
00597 else
00598 gdcmWarningMacro("Unfound Spacing Between Slices (0018,0088)");
00599
00600
00601
00602
00603 entry = GetDataEntry(0x0018,0x0050);
00604 if( entry )
00605 {
00606 zspacing = (float)entry->GetValue(0);
00607
00608 if ( zspacing == 0.0 )
00609 zspacing = 1.0;
00610 return zspacing;
00611 }
00612 else
00613 gdcmWarningMacro("Unfound Slice Thickness (0018,0050)");
00614
00615
00616
00617
00618 entry = GetDataEntry(0x3004,0x000c);
00619 if( entry )
00620 {
00621 float z1 = (float)entry->GetValue(0);
00622 float z2 = (float)entry->GetValue(1);
00623 zspacing = z2 - z1;
00624
00625 if ( zspacing == 0.0 )
00626 zspacing = 1.0;
00627 return zspacing;
00628 }
00629
00630 return zspacing;
00631 }
00632
00639 float File::GetXOrigin()
00640 {
00641 DataEntry *entry = GetDataEntry(0x0020,0x0032);
00642 if( !entry )
00643 {
00644 gdcmWarningMacro( "Unfound Image Position Patient (0020,0032)");
00645 entry = GetDataEntry(0x0020,0x0030);
00646 if( !entry )
00647 {
00648 gdcmWarningMacro( "Unfound Image Position (RET) (0020,0030)");
00649 return 0.0f;
00650 }
00651 }
00652
00653 if( entry->GetValueCount() == 3 )
00654 {
00655 if (!entry->IsValueCountValid() )
00656 {
00657 gdcmErrorMacro( "Invalid Value Count" );
00658 }
00659 return (float)entry->GetValue(0);
00660 }
00661 return 0.0f;
00662 }
00663
00670 float File::GetYOrigin()
00671 {
00672 DataEntry *entry = GetDataEntry(0x0020,0x0032);
00673 if( !entry )
00674 {
00675 gdcmWarningMacro( "Unfound Image Position Patient (0020,0032)");
00676 entry = GetDataEntry(0x0020,0x0030);
00677 if( !entry )
00678 {
00679 gdcmWarningMacro( "Unfound Image Position (RET) (0020,0030)");
00680 return 0.0f;
00681 }
00682 }
00683
00684 if( entry->GetValueCount() == 3 )
00685 {
00686 if (!entry->IsValueCountValid() )
00687 {
00688 gdcmErrorMacro( "Invalid Value Count" );
00689 }
00690 return (float)entry->GetValue(1);
00691 }
00692 return 0.0f;
00693 }
00694
00703 float File::GetZOrigin()
00704 {
00705 DataEntry *entry = GetDataEntry(0x0020,0x0032);
00706 if( entry )
00707 {
00708 if( entry->GetValueCount() == 3 )
00709 {
00710 if (!entry->IsValueCountValid() )
00711 {
00712 gdcmErrorMacro( "Invalid Value Count" );
00713 }
00714 return (float)entry->GetValue(2);
00715 }
00716 gdcmWarningMacro( "Wrong Image Position Patient (0020,0032)");
00717 return 0.0f;
00718 }
00719
00720 entry = GetDataEntry(0x0020,0x0030);
00721 if( entry )
00722 {
00723 if( entry->GetValueCount() == 3 )
00724 {
00725 if (!entry->IsValueCountValid() )
00726 {
00727 gdcmErrorMacro( "Invalid Value Count" );
00728 }
00729 return (float)entry->GetValue(2);
00730 }
00731 gdcmWarningMacro( "Wrong Image Position (RET) (0020,0030)");
00732 return 0.0f;
00733 }
00734
00735
00736 entry = GetDataEntry(0x0020,0x1041);
00737 if( entry )
00738 {
00739 if( entry->GetValueCount() == 1 )
00740 {
00741 if (!entry->IsValueCountValid() )
00742 {
00743 gdcmErrorMacro( "Invalid Value Count" );
00744 }
00745 return (float)entry->GetValue(0);
00746 }
00747 gdcmWarningMacro( "Wrong Slice Location (0020,1041)");
00748 return 0.0f;
00749 }
00750
00751 entry = GetDataEntry(0x0020,0x0050);
00752 if( entry )
00753 {
00754 if( entry->GetValueCount() == 1 )
00755 {
00756 if (!entry->IsValueCountValid() )
00757 {
00758 gdcmErrorMacro( "Invalid Value Count" );
00759 }
00760 return (float)entry->GetValue(0);
00761 }
00762 gdcmWarningMacro( "Wrong Location (0020,0050)");
00763 return 0.0f;
00764 }
00765 return 0.;
00766 }
00767
00780 bool File::GetImageOrientationPatient( float iop[6] )
00781 {
00782 std::string strImOriPat;
00783
00784
00785
00786 if ( (strImOriPat = GetEntryString(0x0020,0x0037)) != GDCM_UNFOUND )
00787 {
00788 if ( sscanf( strImOriPat.c_str(), "%f \\ %f \\%f \\%f \\%f \\%f ",
00789 &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6 )
00790 {
00791 iop[0] = iop[4] = 1.;
00792 iop[1] = iop[2] = iop[3] = iop[5] = 0.;
00793 gdcmWarningMacro( "Wrong Image Orientation Patient (0020,0037)."
00794 << " Less than 6 values were found." );
00795 return false;
00796 }
00797 else
00798 return true;
00799 }
00800
00801
00802 else if ( (strImOriPat = GetEntryString(0x0020,0x0035)) != GDCM_UNFOUND )
00803 {
00804 if ( sscanf( strImOriPat.c_str(), "%f \\ %f \\%f \\%f \\%f \\%f ",
00805 &iop[0], &iop[1], &iop[2], &iop[3], &iop[4], &iop[5]) != 6 )
00806 {
00807 iop[0] = iop[4] = 1.;
00808 iop[1] = iop[2] = iop[3] = iop[5] = 0.;
00809 gdcmWarningMacro( "wrong Image Orientation Patient (0020,0035). "
00810 << "Less than 6 values were found." );
00811 return false;
00812 }
00813 else
00814 return true;
00815 }
00816 return false;
00817 }
00818
00825 int File::GetBitsStored()
00826 {
00827 DataEntry *entry = GetDataEntry(0x0028,0x0101);
00828 if( !entry )
00829 {
00830 gdcmWarningMacro("BitsStored (0028,0101) is supposed to be mandatory");
00831 return 0;
00832 }
00833 return (int)entry->GetValue(0);
00834 }
00835
00842 int File::GetBitsAllocated()
00843 {
00844 DataEntry *entry = GetDataEntry(0x0028,0x0100);
00845 if( !entry )
00846 {
00847 gdcmWarningMacro("BitsAllocated (0028,0100) is supposed to be mandatory");
00848 return 0;
00849 }
00850 return (int)entry->GetValue(0);
00851 }
00852
00859 int File::GetHighBitPosition()
00860 {
00861 DataEntry *entry = GetDataEntry(0x0028,0x0102);
00862 if( !entry )
00863 {
00864 gdcmWarningMacro("HighBitPosition (0028,0102) is supposed to be mandatory");
00865 return 0;
00866 }
00867 return (int)entry->GetValue(0);
00868 }
00869
00876 int File::GetSamplesPerPixel()
00877 {
00878 DataEntry *entry = GetDataEntry(0x0028,0x0002);
00879 if( !entry )
00880 {
00881 gdcmWarningMacro("SamplesPerPixel (0028,0002) is supposed to be mandatory");
00882 return 1;
00883
00884 }
00885 return (int)entry->GetValue(0);
00886 }
00887
00893 int File::GetPlanarConfiguration()
00894 {
00895 DataEntry *entry = GetDataEntry(0x0028,0x0006);
00896 if( !entry )
00897 {
00898 return 0;
00899 }
00900 return (int)entry->GetValue(0);
00901 }
00902
00908 int File::GetPixelSize()
00909 {
00910
00911
00912 assert( !(GetEntryString(0x0028,0x0100) == "24") );
00913
00914 std::string pixelType = GetPixelType();
00915 if ( pixelType == "8U" || pixelType == "8S" )
00916 {
00917 return 1;
00918 }
00919 if ( pixelType == "16U" || pixelType == "16S")
00920 {
00921 return 2;
00922 }
00923 if ( pixelType == "32U" || pixelType == "32S")
00924 {
00925 return 4;
00926 }
00927 if ( pixelType == "FD" )
00928 {
00929 return 8;
00930 }
00931 gdcmWarningMacro( "Unknown pixel type: " << pixelType);
00932 return 0;
00933 }
00934
00950 std::string File::GetPixelType()
00951 {
00952 std::string bitsAlloc = GetEntryString(0x0028, 0x0100);
00953 if ( bitsAlloc == GDCM_UNFOUND )
00954 {
00955 gdcmWarningMacro( "Bits Allocated (0028,0100) supposed to be mandatory");
00956 bitsAlloc = "16";
00957 }
00958
00959 if ( bitsAlloc == "64" )
00960 {
00961 return "FD";
00962 }
00963 else if ( bitsAlloc == "12" )
00964 {
00965
00966 bitsAlloc = "16";
00967 }
00968 else if ( bitsAlloc == "24" )
00969 {
00970
00971 bitsAlloc = "8";
00972 }
00973
00974 std::string sign;
00975 if( IsSignedPixelData() )
00976 {
00977 sign = "S";
00978 }
00979 else
00980 {
00981 sign = "U";
00982 }
00983 return bitsAlloc + sign;
00984 }
00985
00994 bool File::IsSignedPixelData()
00995 {
00996 DataEntry *entry = GetDataEntry(0x0028, 0x0103);
00997 if( !entry )
00998 {
00999 gdcmWarningMacro( "Pixel Representation (0028,0103) supposed to be "
01000 << "mandatory");
01001 return false;
01002 }
01003 return entry->GetValue(0) != 0;
01004 }
01005
01011 bool File::IsMonochrome()
01012 {
01013 const std::string &PhotometricInterp = GetEntryString( 0x0028, 0x0004 );
01014 if ( Util::DicomStringEqual(PhotometricInterp, "MONOCHROME1")
01015 || Util::DicomStringEqual(PhotometricInterp, "MONOCHROME2") )
01016 {
01017 return true;
01018 }
01019 if ( PhotometricInterp == GDCM_UNFOUND )
01020 {
01021 gdcmWarningMacro( "Photometric Interpretation (0028,0004) supposed to be "
01022 << "mandatory");
01023 }
01024 return false;
01025 }
01026
01032 bool File::IsMonochrome1()
01033 {
01034 const std::string &PhotometricInterp = GetEntryString( 0x0028, 0x0004 );
01035 if ( Util::DicomStringEqual(PhotometricInterp, "MONOCHROME1") )
01036 {
01037 return true;
01038 }
01039 if ( PhotometricInterp == GDCM_UNFOUND )
01040 {
01041 gdcmWarningMacro( "Photometric Interpretation (0028,0004) : supposed to"
01042 << " be mandatory! ");
01043 }
01044 return false;
01045 }
01046
01052 bool File::IsPaletteColor()
01053 {
01054 std::string PhotometricInterp = GetEntryString( 0x0028, 0x0004 );
01055 if ( PhotometricInterp == "PALETTE COLOR " )
01056 {
01057 return true;
01058 }
01059 if ( PhotometricInterp == GDCM_UNFOUND )
01060 {
01061 gdcmDebugMacro( "Not found : Palette color (0028,0004)");
01062 }
01063 return false;
01064 }
01065
01071 bool File::IsYBRFull()
01072 {
01073 std::string PhotometricInterp = GetEntryString( 0x0028, 0x0004 );
01074 if ( PhotometricInterp == "YBR_FULL" )
01075 {
01076 return true;
01077 }
01078 if ( PhotometricInterp == GDCM_UNFOUND )
01079 {
01080 gdcmDebugMacro( "Not found : YBR Full (0028,0004)");
01081 }
01082 return false;
01083 }
01084
01093 bool File::HasLUT()
01094 {
01095
01096
01097 if ( !GetDocEntry(0x0028,0x1101) )
01098 {
01099 return false;
01100 }
01101
01102 if ( !GetDocEntry(0x0028,0x1102) )
01103 {
01104 return false;
01105 }
01106
01107 if ( !GetDocEntry(0x0028,0x1103) )
01108 {
01109 return false;
01110 }
01111
01112 if ( !GetDocEntry(0x0028,0x1201) )
01113 {
01114 return false;
01115 }
01116
01117 if ( !GetDocEntry(0x0028,0x1202) )
01118 {
01119 return false;
01120 }
01121
01122 if ( !GetDocEntry(0x0028,0x1203) )
01123 {
01124 return false;
01125 }
01126
01127
01128
01129 return true;
01130 }
01131
01139 int File::GetLUTNbits()
01140 {
01141 std::vector<std::string> tokens;
01142 int lutNbits;
01143
01144
01145
01146
01147 std::string lutDescription = GetEntryString(0x0028,0x1101);
01148 if ( lutDescription == GDCM_UNFOUND )
01149 {
01150 return 0;
01151 }
01152
01153 tokens.clear();
01154 Util::Tokenize ( lutDescription, tokens, "\\" );
01155
01156
01157
01158 lutNbits = atoi( tokens[2].c_str() );
01159 tokens.clear();
01160
01161 return lutNbits;
01162 }
01163
01168 float File::GetRescaleIntercept()
01169 {
01170
01171 DataEntry *entry = GetDataEntry(0x0028, 0x1052);
01172 if( !entry )
01173 {
01174 gdcmWarningMacro( "Missing Rescale Intercept (0028,1052)");
01175 return 0.0f;
01176 }
01177 return (float)entry->GetValue(0);
01178
01179 }
01180
01185 float File::GetRescaleSlope()
01186 {
01187
01188 DataEntry *entry = GetDataEntry(0x0028, 0x1053);
01189 if( !entry )
01190 {
01191 gdcmDebugMacro( "Missing Rescale Slope (0028,1053)");
01192 return 1.0f;
01193 }
01194 return (float)entry->GetValue(0);
01195 }
01196
01204 int File::GetNumberOfScalarComponents()
01205 {
01206 if ( GetSamplesPerPixel() == 3 )
01207 {
01208 return 3;
01209 }
01210
01211
01212
01213 if ( GetEntryString(0x0028,0x0100) == "24" )
01214 {
01215 return 3;
01216 }
01217
01218 std::string strPhotometricInterpretation = GetEntryString(0x0028,0x0004);
01219
01220 if ( ( strPhotometricInterpretation == "PALETTE COLOR ") )
01221 {
01222 if ( HasLUT() )
01223 {
01224 return 3;
01225 }
01226 else
01227 {
01228 return 1;
01229 }
01230 }
01231
01232
01233
01234 if ( strPhotometricInterpretation == GDCM_UNFOUND ||
01235 Util::DicomStringEqual(strPhotometricInterpretation, "MONOCHROME1") ||
01236 Util::DicomStringEqual(strPhotometricInterpretation, "MONOCHROME2") )
01237 {
01238 return 1;
01239 }
01240 else
01241 {
01242
01243 return 3;
01244 }
01245 }
01246
01254 int File::GetNumberOfScalarComponentsRaw()
01255 {
01256
01257
01258 if ( File::GetEntryString(0x0028,0x0100) == "24" )
01259 {
01260 return 3;
01261 }
01262
01263
01264 return GetSamplesPerPixel();
01265 }
01266
01272 size_t File::GetPixelOffset()
01273 {
01274 DocEntry *pxlElement = GetDocEntry(GrPixel, NumPixel);
01275 if ( pxlElement )
01276 {
01277 return pxlElement->GetOffset();
01278 }
01279 else
01280 {
01281 gdcmWarningMacro( "Big trouble : Pixel Element ("
01282 << std::hex << GrPixel<<","<< NumPixel<< ") NOT found" );
01283 return 0;
01284 }
01285 }
01286
01294 size_t File::GetPixelAreaLength()
01295 {
01296 DocEntry *pxlElement = GetDocEntry(GrPixel, NumPixel);
01297 if ( pxlElement )
01298 {
01299 return pxlElement->GetLength();
01300 }
01301 else
01302 {
01303 gdcmWarningMacro( "Big trouble : Pixel Element ("
01304 << std::hex << GrPixel<<","<< NumPixel<< ") NOT found" );
01305 return 0;
01306 }
01307 }
01308
01315 void File::AddAnonymizeElement (uint16_t group, uint16_t elem,
01316 std::string const &value)
01317 {
01318 DicomElement el;
01319 el.Group = group;
01320 el.Elem = elem;
01321 el.Value = value;
01322 UserAnonymizeList.push_back(el);
01323 }
01324
01329 void File::AnonymizeNoLoad()
01330 {
01331 std::fstream *fp = new std::fstream(Filename.c_str(),
01332 std::ios::in | std::ios::out | std::ios::binary);
01333 gdcm::DocEntry *d;
01334 uint32_t offset;
01335 uint32_t lgth;
01336 uint32_t valLgth = 0;
01337 std::string *spaces;
01338 for (ListElements::iterator it = UserAnonymizeList.begin();
01339 it != UserAnonymizeList.end();
01340 ++it)
01341 {
01342 d = GetDocEntry( (*it).Group, (*it).Elem);
01343
01344 if ( d == NULL)
01345 continue;
01346
01347 if ( dynamic_cast<SeqEntry *>(d) )
01348 {
01349 gdcmWarningMacro( "You cannot 'Anonymize' a SeqEntry ");
01350 continue;
01351 }
01352
01353 offset = d->GetOffset();
01354 lgth = d->GetLength();
01355 if (valLgth < lgth)
01356 {
01357 spaces = new std::string( lgth-valLgth, ' ');
01358 (*it).Value = (*it).Value + *spaces;
01359 delete spaces;
01360 }
01361 fp->seekp( offset, std::ios::beg );
01362 fp->write( (*it).Value.c_str(), lgth );
01363
01364 }
01365 fp->close();
01366 delete fp;
01367 }
01368
01374 bool File::AnonymizeFile()
01375 {
01376
01377 if ( UserAnonymizeList.begin() == UserAnonymizeList.end() )
01378 {
01379
01380 SetEntryString(" ",0x0010, 0x2154);
01381 SetEntryString(" ",0x0010, 0x1040);
01382 SetEntryString(" ",0x0010, 0x0020);
01383
01384 DocEntry *patientNameHE = GetDocEntry (0x0010, 0x0010);
01385
01386 if ( patientNameHE )
01387 {
01388 std::string studyInstanceUID = GetEntryString (0x0020, 0x000d);
01389 if ( studyInstanceUID != GDCM_UNFOUND )
01390 {
01391 SetEntryString(studyInstanceUID, 0x0010, 0x0010);
01392 }
01393 else
01394 {
01395 SetEntryString("anonymized", 0x0010, 0x0010);
01396 }
01397 }
01398 }
01399 else
01400 {
01401 gdcm::DocEntry *d;
01402 for (ListElements::iterator it = UserAnonymizeList.begin();
01403 it != UserAnonymizeList.end();
01404 ++it)
01405 {
01406 d = GetDocEntry( (*it).Group, (*it).Elem);
01407
01408 if ( d == NULL)
01409 continue;
01410
01411 if ( dynamic_cast<SeqEntry *>(d) )
01412 {
01413 gdcmWarningMacro( "You cannot 'Anonymize' a SeqEntry ");
01414 continue;
01415 }
01416
01417 if ( dynamic_cast<DataEntry *>(d) )
01418 {
01419 gdcmWarningMacro( "To 'Anonymize' a DataEntry, better use AnonymizeNoLoad (FIXME) ");
01420 continue;
01421 }
01422 else
01423 SetEntryString ((*it).Value, (*it).Group, (*it).Elem);
01424 }
01425 }
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479 return true;
01480 }
01481
01490 bool File::Write(std::string fileName, FileType writetype)
01491 {
01492 std::ofstream *fp = new std::ofstream(fileName.c_str(),
01493 std::ios::out | std::ios::binary);
01494 if (*fp == NULL)
01495 {
01496 gdcmWarningMacro("Failed to open (write) File: " << fileName.c_str());
01497 return false;
01498 }
01499
01500
01501 DataEntry *e0000 = GetDataEntry(0x0002,0x0000);
01502 if ( e0000 )
01503 {
01504 std::ostringstream sLen;
01505 sLen << ComputeGroup0002Length( );
01506 e0000->SetString(sLen.str());
01507 }
01508
01510 if( writetype != JPEG )
01511 {
01512 int i_lgPix = GetEntryLength(GrPixel, NumPixel);
01513 if (i_lgPix != -2)
01514 {
01515
01516 std::string s_lgPix = Util::Format("%d", i_lgPix+12);
01517 s_lgPix = Util::DicomString( s_lgPix.c_str() );
01518 InsertEntryString(s_lgPix,GrPixel, 0x0000);
01519 }
01520 }
01521 Document::WriteContent(fp, writetype);
01522
01523 fp->close();
01524 delete fp;
01525
01526 return true;
01527 }
01528
01529
01530
01531
01532
01533
01534
01535
01541 void File::ComputeRLEInfo()
01542 {
01543 std::string ts = GetTransferSyntax();
01544 if ( !Global::GetTS()->IsRLELossless(ts) )
01545 {
01546 return;
01547 }
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 ReadEncapsulatedBasicOffsetTable();
01563
01564
01565
01566
01567
01568
01569
01570
01571 long frameLength;
01572 int i=0;
01573 uint32_t sum = 0;
01574 while ( (frameLength = ReadTagLength(0xfffe, 0xe000)) != 0 )
01575 {
01576
01577
01578 if ( BasicOffsetTableItemValue )
01579 {
01580
01581 uint32_t individualLength = BasicOffsetTableItemValue[i];
01582 assert( individualLength == sum );
01583 if( individualLength != sum )
01584 {
01585 gdcmWarningMacro( "BasicOffsetTableItemValue differs from the fragment lenght" );
01586 }
01587 sum += frameLength + 8;
01588 i++;
01589 }
01590
01591
01592
01593
01594 long frameOffset = Fp->tellg();
01595
01596 uint32_t nbRleSegments = ReadInt32();
01597 if ( nbRleSegments > 16 )
01598 {
01599
01600 gdcmWarningMacro( "Too many segments.");
01601 }
01602
01603 uint32_t rleSegmentOffsetTable[16];
01604 for( int k = 1; k <= 15; k++ )
01605 {
01606 rleSegmentOffsetTable[k] = ReadInt32();
01607 }
01608
01609
01610
01611
01612 long rleSegmentLength[15];
01613
01614 if ( nbRleSegments > 1)
01615 {
01616 for(unsigned int k = 1; k <= nbRleSegments-1; k++)
01617 {
01618 rleSegmentLength[k] = rleSegmentOffsetTable[k+1]
01619 - rleSegmentOffsetTable[k];
01620 SkipBytes(rleSegmentLength[k]);
01621 }
01622 }
01623
01624 rleSegmentLength[nbRleSegments] = frameLength
01625 - rleSegmentOffsetTable[nbRleSegments];
01626 SkipBytes(rleSegmentLength[nbRleSegments]);
01627
01628
01629 RLEFrame *newFrame = new RLEFrame;
01630 newFrame->SetNumberOfFragments(nbRleSegments);
01631 for( unsigned int uk = 1; uk <= nbRleSegments; uk++ )
01632 {
01633 newFrame->SetOffset(uk,frameOffset + rleSegmentOffsetTable[uk]);
01634 newFrame->SetLength(uk,rleSegmentLength[uk]);
01635 }
01636 RLEInfo->AddFrame(newFrame);
01637 }
01638
01639
01640
01641 if ( !ReadTag(0xfffe, 0xe0dd) )
01642 {
01643 gdcmWarningMacro( "No sequence delimiter item at end of RLE item sequence");
01644 }
01645 }
01646
01653 void File::ComputeJPEGFragmentInfo()
01654 {
01655
01656 std::string ts = GetTransferSyntax();
01657 if ( ! Global::GetTS()->IsJPEG(ts) )
01658 {
01659 return;
01660 }
01661
01662 ReadEncapsulatedBasicOffsetTable();
01663
01664
01665
01666 long fragmentLength;
01667 int i=0;
01668 uint32_t sum = 0;
01669 while ( (fragmentLength = ReadTagLength(0xfffe, 0xe000)) != 0 )
01670 {
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680 if ( BasicOffsetTableItemValue )
01681 {
01682
01683 uint32_t individualLength = BasicOffsetTableItemValue[i];
01684
01685 if( individualLength != sum )
01686 {
01687 gdcmWarningMacro( "BasicOffsetTableItemValue differs from the fragment lenght:" <<
01688 individualLength << " != " << sum );
01689 }
01690 sum += fragmentLength + 8;
01691 i++;
01692 }
01693
01694 long fragmentOffset = Fp->tellg();
01695
01696 JPEGFragment *newFragment = new JPEGFragment;
01697 newFragment->SetOffset(fragmentOffset);
01698 newFragment->SetLength(fragmentLength);
01699 JPEGInfo->AddFragment(newFragment);
01700
01701 SkipBytes(fragmentLength);
01702 }
01703
01704
01705
01706 if ( !ReadTag(0xfffe, 0xe0dd) )
01707 {
01708 gdcmWarningMacro( "No sequence delimiter item at end of JPEG item sequence");
01709 }
01710 }
01711
01725 bool File::ReadTag(uint16_t testGroup, uint16_t testElem)
01726 {
01727 long positionOnEntry = Fp->tellg();
01728 long currentPosition = Fp->tellg();
01729
01730
01731
01732 uint16_t itemTagGroup;
01733 uint16_t itemTagElem;
01734 try
01735 {
01736 itemTagGroup = ReadInt16();
01737 itemTagElem = ReadInt16();
01738 }
01739 catch ( FormatError )
01740 {
01741 gdcmErrorMacro( "Can not read tag for "
01742 << " We should have found tag ("
01743 << DictEntry::TranslateToKey(testGroup,testElem) << ")"
01744 ) ;
01745
01746 return false;
01747 }
01748 if ( itemTagGroup != testGroup || itemTagElem != testElem )
01749 {
01750
01751 if (itemTagGroup != 0xfffe || testGroup != 0xfffe )
01752 gdcmWarningMacro( "Wrong Item Tag found:"
01753 << " We should have found tag ("
01754 << DictEntry::TranslateToKey(testGroup,testElem) << ")" << std::endl
01755 << " but instead we encountered tag ("
01756 << DictEntry::TranslateToKey(itemTagGroup,itemTagElem) << ")"
01757 << " at address: " << " 0x(" << std::hex
01758 << (unsigned int)currentPosition << std::dec << ")"
01759 ) ;
01760 Fp->seekg(positionOnEntry, std::ios::beg);
01761
01762 return false;
01763 }
01764 return true;
01765 }
01766
01781 uint32_t File::ReadTagLength(uint16_t testGroup, uint16_t testElem)
01782 {
01783
01784 if ( !ReadTag(testGroup, testElem) )
01785 {
01786
01787 if ( testGroup != 0xfffe )
01788 gdcmErrorMacro( "ReadTag did not succeed for ("
01789 << DictEntry::TranslateToKey(testGroup,testElem)
01790 << ")..." );
01791 return 0;
01792 }
01793
01795 long currentPosition = Fp->tellg();
01796 uint32_t itemLength = ReadInt32();
01797 gdcmDebugMacro( "Basic Item Length is: " << itemLength
01798 << " at address: " << std::hex << (unsigned int)currentPosition);
01799 return itemLength;
01800 }
01801
01806 void File::ReadEncapsulatedBasicOffsetTable()
01807 {
01809 uint32_t itemLength = ReadTagLength(0xfffe, 0xe000);
01810
01811
01812
01813
01814
01815
01816
01817 if ( itemLength != 0 )
01818 {
01819 char *charBasicOffsetTableItemValue = new char[itemLength];
01820 Fp->read(charBasicOffsetTableItemValue, itemLength);
01821 unsigned int nbEntries = itemLength/4;
01822 assert( nbEntries*4 == itemLength);
01823 BasicOffsetTableItemValue = new uint32_t[nbEntries];
01824
01825 for (unsigned int i=0; i < nbEntries; i++ )
01826 {
01827 BasicOffsetTableItemValue[i] = *((uint32_t*)(&charBasicOffsetTableItemValue[4*i]));
01828 #if defined(GDCM_WORDS_BIGENDIAN) || defined(GDCM_FORCE_BIGENDIAN_EMULATION)
01829 uint32_t val = BasicOffsetTableItemValue[i];
01830 BasicOffsetTableItemValue[i]
01831 = ( (val<<24) | ((val<<8) & 0x00ff0000) |
01832 ( (val>>8) & 0x0000ff00) | (val>>24) );
01833 #endif
01834 gdcmDebugMacro( "Read one length for: " <<
01835 std::hex << BasicOffsetTableItemValue[i] );
01836 }
01837
01838 delete[] charBasicOffsetTableItemValue;
01839 }
01840 }
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870 }