00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "gdcmDocument.h"
00020 #include "gdcmSeqEntry.h"
00021 #include "gdcmGlobal.h"
00022 #include "gdcmUtil.h"
00023 #include "gdcmDebug.h"
00024 #include "gdcmTS.h"
00025 #include "gdcmDictSet.h"
00026 #include "gdcmDocEntrySet.h"
00027 #include "gdcmSQItem.h"
00028 #include "gdcmDataEntry.h"
00029
00030 #include <vector>
00031 #include <iomanip>
00032 #include <fstream>
00033 #include <ctype.h>
00034 #include <stdlib.h>
00035
00036 namespace gdcm
00037 {
00038
00039
00040
00041 const unsigned int Document::MAX_SIZE_LOAD_ELEMENT_VALUE = 0xfff;
00042
00043
00044
00045
00046
00052 Document::Document()
00053 :ElementSet()
00054 {
00055 Fp = 0;
00056
00057 SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
00058 Initialize();
00059 SwapCode = 1234;
00060 Filetype = ExplicitVR;
00061
00062 Group0002Parsed = false;
00063 IsDocumentAlreadyLoaded = false;
00064 IsDocumentModified = true;
00065 LoadMode = LD_ALL;
00066 SetFileName("");
00067 }
00068
00072 Document::~Document ()
00073 {
00074 CloseFile();
00075 }
00076
00077
00078
00084 bool Document::Load( )
00085 {
00086 if ( GetFileName() == "" )
00087 {
00088 gdcmWarningMacro( "Use SetFileName, before !" );
00089 return false;
00090 }
00091 return DoTheLoadingDocumentJob( );
00092 }
00093
00099 bool Document::DoTheLoadingDocumentJob( )
00100 {
00101 if ( ! IsDocumentModified )
00102 return true;
00103
00104 ClearEntry();
00105
00106 Fp = 0;
00107 if ( !OpenFile() )
00108 {
00109
00110 Filetype = Unknown;
00111 return false;
00112 }
00113
00114 Group0002Parsed = false;
00115
00116 gdcmDebugMacro( "Starting parsing of file: " << Filename.c_str());
00117
00118 Fp->seekg(0, std::ios::end);
00119 long lgt = Fp->tellg();
00120
00121 Fp->seekg(0, std::ios::beg);
00122
00123
00124
00125 if (! CheckSwap() )
00126 {
00127 gdcmWarningMacro( "Neither a DICOM V3 nor an ACR-NEMA file: "
00128 << Filename.c_str());
00129 CloseFile();
00130 return false;
00131 }
00132
00133 long beg = Fp->tellg();
00134
00135 lgt -= beg;
00136
00137
00138
00139 ParseDES( this, beg, lgt, false);
00140
00141 if ( IsEmpty() )
00142 {
00143 gdcmErrorMacro( "No tag in internal hash table for: "
00144 << Filename.c_str());
00145 CloseFile();
00146 return false;
00147 }
00148 IsDocumentAlreadyLoaded = true;
00149
00150 Fp->seekg( 0, std::ios::beg);
00151
00152
00153
00154 std::string PhotometricInterpretation = GetEntryString(0x0028,0x0004);
00155 if ( PhotometricInterpretation == "PALETTE COLOR " )
00156 {
00157
00158
00159
00160 LoadEntryBinArea(0x0028,0x1200);
00161
00184
00185
00186
00187
00188
00189
00190 LoadEntryBinArea(0x0028,0x1201);
00191 LoadEntryBinArea(0x0028,0x1202);
00192 LoadEntryBinArea(0x0028,0x1203);
00193
00194
00195 LoadEntryBinArea(0x0028,0x1221);
00196
00197 LoadEntryBinArea(0x0028,0x1222);
00198
00199 LoadEntryBinArea(0x0028,0x1223);
00200 }
00201
00202
00203 SeqEntry *modLutSeq = GetSeqEntry(0x0028,0x3000);
00204 if ( modLutSeq !=0 )
00205 {
00206 SQItem *sqi= modLutSeq->GetFirstSQItem();
00207 if ( sqi != 0 )
00208 {
00209 DataEntry *dataEntry = sqi->GetDataEntry(0x0028,0x3006);
00210 if ( dataEntry != 0 )
00211 {
00212 if ( dataEntry->GetLength() != 0 )
00213 {
00214
00215
00216 LoadEntryBinArea(dataEntry);
00217 }
00218 }
00219 }
00220 }
00221
00222
00223
00224 gdcm::DocEntry *d;
00225 for (ListElements::iterator it = UserForceLoadList.begin();
00226 it != UserForceLoadList.end();
00227 ++it)
00228 {
00229 gdcmDebugMacro( "Force Load " << std::hex
00230 << (*it).Group << "|" <<(*it).Elem );
00231
00232 d = GetDocEntry( (*it).Group, (*it).Elem);
00233
00234 if ( d == NULL)
00235 {
00236 gdcmWarningMacro( "You asked toForce Load " << std::hex
00237 << (*it).Group <<"|"<< (*it).Elem
00238 << " that doesn't exist" );
00239 continue;
00240 }
00241
00242 LoadDocEntry(d, true);
00243 }
00244
00245 CloseFile();
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 std::string RecCode;
00258 RecCode = GetEntryString(0x0008, 0x0010);
00259 if (RecCode == "ACRNEMA_LIBIDO_1.1" ||
00260 RecCode == "CANRME_AILIBOD1_1." )
00261
00262 {
00263 Filetype = ACR_LIBIDO;
00264 std::string rows = GetEntryString(0x0028, 0x0010);
00265 std::string columns = GetEntryString(0x0028, 0x0011);
00266 SetEntryString(columns, 0x0028, 0x0010);
00267 SetEntryString(rows , 0x0028, 0x0011);
00268 }
00269
00270 return true;
00271 }
00272
00273
00279 void Document::AddForceLoadElement (uint16_t group, uint16_t elem)
00280 {
00281 DicomElement el;
00282 el.Group = group;
00283 el.Elem = elem;
00284 UserForceLoadList.push_back(el);
00285 }
00289 Dict *Document::GetPubDict()
00290 {
00291 return RefPubDict;
00292 }
00293
00297 Dict *Document::GetShaDict()
00298 {
00299 return RefShaDict;
00300 }
00301
00306 bool Document::SetShaDict(Dict *dict)
00307 {
00308 RefShaDict = dict;
00309 return !RefShaDict;
00310 }
00311
00316 bool Document::SetShaDict(DictKey const &dictName)
00317 {
00318 RefShaDict = Global::GetDicts()->GetDict(dictName);
00319 return !RefShaDict;
00320 }
00321
00329 bool Document::IsParsable()
00330 {
00331 if ( Filetype == Unknown )
00332 {
00333 gdcmWarningMacro( "Wrong filetype for " << GetFileName());
00334 return false;
00335 }
00336
00337 if ( IsEmpty() )
00338 {
00339 gdcmWarningMacro( "No tag in internal hash table.");
00340 return false;
00341 }
00342
00343 return true;
00344 }
00352 bool Document::IsReadable()
00353 {
00354 return IsParsable();
00355 }
00356
00361 bool Document::IsDicomV3()
00362 {
00363
00364
00365
00366
00367 return GetDocEntry(0x0002, 0x0010) != NULL;
00368 }
00369
00375 bool Document::IsPapyrus()
00376 {
00377
00378 DocEntry *e = GetDocEntry(0x0041, 0x1050);
00379 if ( !e )
00380 return false;
00381
00382 if ( !dynamic_cast<SeqEntry*>(e) )
00383 return false;
00384 return true;
00385 }
00386
00392 FileType Document::GetFileType()
00393 {
00394 return Filetype;
00395 }
00396
00404 std::string Document::GetTransferSyntax()
00405 {
00406 DocEntry *entry = GetDocEntry(0x0002, 0x0010);
00407 if ( !entry )
00408 {
00409 return GDCM_UNKNOWN;
00410 }
00411
00412
00413
00414 LoadDocEntrySafe(entry);
00415 if (DataEntry *dataEntry = dynamic_cast<DataEntry *>(entry) )
00416 {
00417 std::string transfer = dataEntry->GetString();
00418
00419
00420
00421 if ( transfer.length() == 0 )
00422 {
00423
00424 gdcmWarningMacro( "Transfer Syntax has length = 0.");
00425 return GDCM_UNKNOWN;
00426 }
00427 while ( !isdigit((unsigned char)transfer[transfer.length()-1]) )
00428 {
00429 transfer.erase(transfer.length()-1, 1);
00430 if ( transfer.length() == 0 )
00431 {
00432
00433 gdcmWarningMacro( "Transfer Syntax contains no valid character.");
00434 return GDCM_UNKNOWN;
00435 }
00436 }
00437 return transfer;
00438 }
00439 return GDCM_UNKNOWN;
00440 }
00441
00446 std::string Document::GetTransferSyntaxName()
00447 {
00448
00449 std::string transferSyntax = GetEntryString(0x0002,0x0010);
00450
00451 if ( (transferSyntax.find(GDCM_NOTLOADED) < transferSyntax.length()) )
00452 {
00453 gdcmErrorMacro( "Transfer Syntax not loaded. " << std::endl
00454 << "Better you increase MAX_SIZE_LOAD_ELEMENT_VALUE" );
00455 return "Uncompressed ACR-NEMA";
00456 }
00457 if ( transferSyntax == GDCM_UNFOUND )
00458 {
00459 gdcmDebugMacro( "Unfound Transfer Syntax (0002,0010)");
00460 return "Uncompressed ACR-NEMA";
00461 }
00462
00463
00464 const TSKey &tsName = Global::GetTS()->GetValue( transferSyntax );
00465
00466
00467 return tsName;
00468 }
00469
00470
00475 uint16_t Document::SwapShort(uint16_t a)
00476 {
00477 if ( SwapCode == 4321 || SwapCode == 2143 )
00478 {
00479
00480
00481 a = ( a << 8 ) | ( a >> 8 );
00482 }
00483 return a;
00484 }
00485
00491 uint32_t Document::SwapLong(uint32_t a)
00492 {
00493 switch (SwapCode)
00494 {
00495 case 1234 :
00496 break;
00497 case 4321 :
00498
00499
00500
00501 a=( ( a<<24) | ((a<<8) & 0x00ff0000) |
00502 ((a>>8) & 0x0000ff00) | (a>>24) );
00503 break;
00504 case 3412 :
00505
00506 a=( (a<<16) | (a>>16) );
00507 break;
00508 case 2143 :
00509 a=( ((a<< 8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) );
00510 break;
00511 default :
00512 gdcmErrorMacro( "Unexpected swap code:" << SwapCode );
00513 a = 0;
00514 }
00515 return a;
00516 }
00517
00523 double Document::SwapDouble(double a)
00524 {
00525 switch (SwapCode)
00526 {
00527
00528
00529
00530 case 1234 :
00531 break;
00532 case 4321 :
00533 {
00534 char *beg = (char *)&a;
00535 char *end = beg + 7;
00536 char t;
00537 for (unsigned int i = 0; i<7; i++)
00538 {
00539 t = *beg;
00540 *beg = *end;
00541 *end = t;
00542 beg++,
00543 end--;
00544 }
00545 }
00546 break;
00547 default :
00548 gdcmErrorMacro( "Unexpected swap code:" << SwapCode );
00549 a = 0.;
00550 }
00551 return a;
00552 }
00553
00554
00555
00561 std::ifstream *Document::OpenFile()
00562 {
00563 HasDCMPreamble = false;
00564 if (Filename.length() == 0)
00565 {
00566 return 0;
00567 }
00568
00569 if ( Fp )
00570 {
00571 gdcmDebugMacro( "File already open: " << Filename.c_str());
00572 CloseFile();
00573 }
00574
00575 Fp = new std::ifstream(Filename.c_str(), std::ios::in | std::ios::binary);
00576 if ( ! *Fp )
00577 {
00578
00579
00580
00581
00582
00583
00584
00585
00586 gdcmWarningMacro( "Cannot open file: " << Filename.c_str());
00587 delete Fp;
00588 Fp = 0;
00589 return 0;
00590
00591
00592 }
00593
00594 uint16_t zero = 0;
00595 Fp->read((char*)&zero, (size_t)2);
00596 if ( Fp->eof() )
00597 {
00598 CloseFile();
00599 return 0;
00600 }
00601
00602
00603
00604
00605
00606 if (
00607 zero == 0x0001 || zero == 0x0100 || zero == 0x0002 || zero == 0x0200 ||
00608 zero == 0x0003 || zero == 0x0300 || zero == 0x0004 || zero == 0x0400 ||
00609 zero == 0x0005 || zero == 0x0500 || zero == 0x0006 || zero == 0x0600 ||
00610 zero == 0x0007 || zero == 0x0700 || zero == 0x0008 || zero == 0x0800 )
00611 {
00612 std::string msg = Util::Format(
00613 "ACR/DICOM starting by 0x(%04x) at the beginning of the file\n", zero);
00614
00615 gdcmWarningMacro( msg.c_str() );
00616 return Fp;
00617 }
00618
00619
00620 Fp->seekg(126L, std::ios::cur);
00621 char dicm[4];
00622 Fp->read(dicm, (size_t)4);
00623 if ( Fp->eof() )
00624 {
00625 CloseFile();
00626 return 0;
00627 }
00628 if ( memcmp(dicm, "DICM", 4) == 0 )
00629 {
00630 HasDCMPreamble = true;
00631 return Fp;
00632 }
00633
00634
00635 CloseFile();
00636
00637
00638 gdcmDebugMacro( "Neither ACR/No Preamble Dicom nor DICOMV3 file: "
00639 << Filename.c_str());
00640 return 0;
00641 }
00642
00647 bool Document::CloseFile()
00648 {
00649 if ( Fp )
00650 {
00651 Fp->close();
00652 delete Fp;
00653 Fp = 0;
00654 }
00655 return true;
00656 }
00657
00664 void Document::WriteContent(std::ofstream *fp, FileType filetype)
00665 {
00666
00667
00668 if ( filetype == ImplicitVR || filetype == ExplicitVR ||
00669 filetype == JPEG )
00670 {
00671
00672 char filePreamble[128];
00673 memset(filePreamble, 0, 128);
00674 fp->write(filePreamble, 128);
00675 fp->write("DICM", 4);
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 ElementSet::WriteContent(fp, filetype);
00695 }
00696
00697
00698
00705 void Document::LoadEntryBinArea(uint16_t group, uint16_t elem)
00706 {
00707
00708 DocEntry *docEntry = GetDocEntry(group, elem);
00709 if ( !docEntry )
00710 {
00711 gdcmDebugMacro(std::hex << group << "|" << elem
00712 << " doesn't exist" );
00713 return;
00714 }
00715 DataEntry *dataEntry = dynamic_cast<DataEntry *>(docEntry);
00716 if ( !dataEntry )
00717 {
00718 gdcmWarningMacro(std::hex << group << "|" << elem
00719 << " is NOT a DataEntry");
00720 return;
00721 }
00722 LoadEntryBinArea(dataEntry);
00723 }
00724
00730 void Document::LoadEntryBinArea(DataEntry *entry)
00731 {
00732 if( entry->GetBinArea() )
00733 return;
00734
00735 bool openFile = !Fp;
00736 if ( openFile )
00737 OpenFile();
00738
00739 size_t o =(size_t)entry->GetOffset();
00740 Fp->seekg(o, std::ios::beg);
00741
00742 size_t l = entry->GetLength();
00743 uint8_t *data = new uint8_t[l];
00744 if ( !data )
00745 {
00746 gdcmWarningMacro( "Cannot allocate DataEntry content for : "
00747 << std::hex << entry->GetGroup()
00748 << "|" << entry->GetElement() );
00749 return;
00750 }
00751
00752
00753 Fp->read((char*)data, l);
00754 if ( Fp->fail() || Fp->eof() )
00755 {
00756 delete[] data;
00757 entry->SetState(DataEntry::STATE_UNREAD);
00758 return;
00759 }
00760
00761
00762 uint32_t i;
00763 unsigned short vrLgth =
00764 Global::GetVR()->GetAtomicElementLength(entry->GetVR());
00765
00766
00767
00768
00769
00770 switch(vrLgth)
00771 {
00772 case 1:
00773 {
00774 break;
00775 }
00776 case 2:
00777 {
00778 uint16_t *data16 = (uint16_t *)data;
00779 for(i=0;i<l/vrLgth;i++)
00780 data16[i] = SwapShort(data16[i]);
00781 break;
00782 }
00783 case 4:
00784 {
00785 uint32_t *data32 = (uint32_t *)data;
00786 for(i=0;i<l/vrLgth;i++)
00787 data32[i] = SwapLong(data32[i]);
00788 break;
00789 }
00790 case 8:
00791 {
00792 double *data64 = (double *)data;
00793 for(i=0;i<l/vrLgth;i++)
00794 data64[i] = SwapDouble(data64[i]);
00795 break;
00796 }
00797 }
00798
00799 entry->SetBinArea(data);
00800
00801 if ( openFile )
00802 CloseFile();
00803 }
00804
00811 void Document::LoadDocEntrySafe(DocEntry *entry)
00812 {
00813 if ( Fp )
00814 {
00815 long PositionOnEntry = Fp->tellg();
00816 LoadDocEntry(entry);
00817 Fp->seekg(PositionOnEntry, std::ios::beg);
00818 }
00819 }
00820
00828 bool Document::operator<(Document &document)
00829 {
00830
00831 std::string s1 = GetEntryString(0x0010,0x0010);
00832 std::string s2 = document.GetEntryString(0x0010,0x0010);
00833 if (s1 < s2)
00834 {
00835 return true;
00836 }
00837 else if ( s1 > s2 )
00838 {
00839 return false;
00840 }
00841 else
00842 {
00843
00844 s1 = GetEntryString(0x0010,0x0020);
00845 s2 = document.GetEntryString(0x0010,0x0020);
00846 if ( s1 < s2 )
00847 {
00848 return true;
00849 }
00850 else if ( s1 > s2 )
00851 {
00852 return false;
00853 }
00854 else
00855 {
00856
00857 s1 = GetEntryString(0x0020,0x000d);
00858 s2 = document.GetEntryString(0x0020,0x000d);
00859 if ( s1 < s2 )
00860 {
00861 return true;
00862 }
00863 else if ( s1 > s2 )
00864 {
00865 return false;
00866 }
00867 else
00868 {
00869
00870 s1 = GetEntryString(0x0020,0x000e);
00871 s2 = document.GetEntryString(0x0020,0x000e);
00872 if ( s1 < s2 )
00873 {
00874 return true;
00875 }
00876 else if ( s1 > s2 )
00877 {
00878 return false;
00879 }
00880 }
00881 }
00882 }
00883 return false;
00884 }
00885
00886
00887
00893 uint16_t Document::ReadInt16()
00894 throw( FormatError )
00895 {
00896 uint16_t g;
00897 Fp->read ((char*)&g, (size_t)2);
00898 if ( Fp->fail() )
00899 {
00900 throw FormatError( "Document::ReadInt16()", " file error." );
00901 }
00902 if ( Fp->eof() )
00903 {
00904 throw FormatError( "Document::ReadInt16()", "EOF." );
00905 }
00906 g = SwapShort(g);
00907 return g;
00908 }
00909
00915 uint32_t Document::ReadInt32()
00916 throw( FormatError )
00917 {
00918 uint32_t g;
00919 Fp->read ((char*)&g, (size_t)4);
00920 if ( Fp->fail() )
00921 {
00922 throw FormatError( "Document::ReadInt32()", " file error." );
00923 }
00924 if ( Fp->eof() )
00925 {
00926 throw FormatError( "Document::ReadInt32()", "EOF." );
00927 }
00928 g = SwapLong(g);
00929 return g;
00930 }
00931
00936 void Document::SkipBytes(uint32_t nBytes)
00937 {
00938
00939 Fp->seekg((long)nBytes, std::ios::cur);
00940 }
00941
00945 int Document::ComputeGroup0002Length( )
00946 {
00947 uint16_t gr;
00948 VRKey vr;
00949
00950 int groupLength = 0;
00951 bool found0002 = false;
00952
00953
00954 DocEntry *entry = GetFirstEntry();
00955 while( entry )
00956 {
00957 gr = entry->GetGroup();
00958
00959 if ( gr == 0x0002 )
00960 {
00961 found0002 = true;
00962
00963 if ( entry->GetElement() != 0x0000 )
00964 {
00965 vr = entry->GetVR();
00966
00967
00968
00969 if ( vr == "OB" )
00970 {
00971
00972 groupLength += 4;
00973 }
00974
00975 groupLength += 2 + 2 + 4 + entry->GetLength();
00976 }
00977 }
00978 else if (found0002 )
00979 break;
00980
00981 entry = GetNextEntry();
00982 }
00983 return groupLength;
00984 }
00985
00989 void Document::CallStartMethod()
00990 {
00991 Progress = 0.0f;
00992 Abort = false;
00993 CommandManager::ExecuteCommand(this,CMD_STARTPROGRESS);
00994 }
00995
00999 void Document::CallProgressMethod()
01000 {
01001 CommandManager::ExecuteCommand(this,CMD_PROGRESS);
01002 }
01003
01007 void Document::CallEndMethod()
01008 {
01009 Progress = 1.0f;
01010 CommandManager::ExecuteCommand(this,CMD_ENDPROGRESS);
01011 }
01012
01013
01014
01018 void Document::Initialize()
01019 {
01020 RefPubDict = Global::GetDicts()->GetDefaultPubDict();
01021 RefShaDict = NULL;
01022 Filetype = Unknown;
01023 }
01024
01032 void Document::ParseDES(DocEntrySet *set, long offset,
01033 long l_max, bool delim_mode)
01034 {
01035 DocEntry *newDocEntry;
01036 DataEntry *newDataEntry;
01037 SeqEntry *newSeqEntry;
01038 VRKey vr;
01039 bool used;
01040
01041 bool delim_mode_intern = delim_mode;
01042 bool first = true;
01043 gdcmDebugMacro( "Enter in ParseDES, delim-mode " << delim_mode
01044 << " at offset " << std::hex << "0x(" << offset << ")" );
01045 while (true)
01046 {
01047 if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
01048 {
01049 break;
01050 }
01051
01052 newDocEntry = ReadNextDocEntry( );
01053
01054
01055
01056 if( Debug::GetDebugFlag() )
01057 std::cerr<<newDocEntry->GetKey()<<" "<<newDocEntry->GetVR()<<std::endl;
01058
01059 if ( !newDocEntry )
01060 {
01061 break;
01062 }
01063
01064
01065
01066
01067
01068 if ( !first && newDocEntry->IsItemStarter() )
01069 {
01070
01071 newDocEntry = Backtrack(newDocEntry);
01072 }
01073 else
01074 {
01075 PreviousDocEntry = newDocEntry;
01076 }
01077
01078 used = true;
01079 newDataEntry = dynamic_cast<DataEntry*>(newDocEntry);
01080
01081 if ( newDataEntry )
01082 {
01084
01085 vr = newDocEntry->GetVR();
01086
01087 if ( !set->AddEntry( newDataEntry ) )
01088 {
01089 gdcmDebugMacro( "in ParseDES : cannot add a DataEntry "
01090 << newDataEntry->GetKey()
01091 << " (at offset : 0x("
01092 << newDataEntry->GetOffset() << ") )" );
01093 used=false;
01094 }
01095 else
01096 {
01097 newDataEntry->Delete();
01098
01099 LoadDocEntry( newDataEntry );
01100 }
01101 if ( newDataEntry->GetElement() == 0x0000 )
01102 {
01103 if ( newDataEntry->GetGroup()%2 != 0 )
01104 {
01105 if ( LoadMode & LD_NOSHADOW )
01106 {
01107 std::string strLgrGroup = newDataEntry->GetString();
01108
01109 int lgrGroup;
01110
01111 {
01112 lgrGroup = atoi(strLgrGroup.c_str());
01113 Fp->seekg(lgrGroup, std::ios::cur);
01114
01115 RemoveEntry( newDocEntry );
01116
01117
01118 continue;
01119 }
01120 }
01121 }
01122 }
01123
01124 bool delimitor = newDataEntry->IsItemDelimitor();
01125
01126 if ( (delimitor) ||
01127 (!delim_mode && ((long)(Fp->tellg())-offset) >= l_max) )
01128 {
01129 if ( !used )
01130 newDocEntry->Delete();
01131 break;
01132 }
01133
01134
01135 SkipToNextDocEntry(newDocEntry);
01136 }
01137 else
01138 {
01140
01141 unsigned long l = newDocEntry->GetReadLength();
01142 if ( l != 0 )
01143 {
01144 if ( l == 0xffffffff )
01145 {
01146 delim_mode_intern = true;
01147 }
01148 else
01149 {
01150 delim_mode_intern = false;
01151 }
01152 }
01153
01154 if ( (LoadMode & LD_NOSHADOWSEQ) && ! delim_mode_intern )
01155 {
01156
01157 if ( newDocEntry->GetGroup()%2 != 0 )
01158 {
01159 Fp->seekg( l, std::ios::cur);
01160 newDocEntry->Delete();
01161 continue;
01162 }
01163 }
01164 if ( (LoadMode & LD_NOSEQ) && ! delim_mode_intern )
01165 {
01166
01167 Fp->seekg( l, std::ios::cur);
01168 newDocEntry->Delete();
01169 continue;
01170 }
01171
01172 newSeqEntry = dynamic_cast<SeqEntry*>(newDocEntry);
01173
01174
01175 newSeqEntry->SetDelimitorMode( delim_mode_intern );
01176
01177
01178
01179
01180
01181 if ( set == this )
01182 {
01183 newSeqEntry->SetDepthLevel( 1 );
01184 }
01185
01186
01187
01188
01189
01190 else if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
01191 {
01192 newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 );
01193 }
01194
01195 if ( l != 0 )
01196 {
01197
01198 gdcmDebugMacro( "Entry in ParseSQ, delim " << delim_mode_intern
01199 << " at offset 0x(" << std::hex
01200 << newDocEntry->GetOffset() << ")");
01201
01202 ParseSQ( newSeqEntry,
01203 newDocEntry->GetOffset(),
01204 l, delim_mode_intern);
01205
01206 gdcmDebugMacro( "Exit from ParseSQ, delim " << delim_mode_intern);
01207
01208 }
01209 if ( !set->AddEntry( newSeqEntry ) )
01210 {
01211 gdcmWarningMacro( "in ParseDES : cannot add a SeqEntry "
01212 << newSeqEntry->GetKey()
01213 << " (at offset : 0x("
01214 << newSeqEntry->GetOffset() << ") )" );
01215 used = false;
01216 }
01217 else
01218 {
01219 newDocEntry->Delete();
01220 }
01221
01222 if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
01223 {
01224 if ( !used )
01225 newDocEntry->Delete();
01226 break;
01227 }
01228 }
01229
01230 if ( !used )
01231 {
01232 newDocEntry->Delete();
01233 }
01234 first = false;
01235 }
01236 gdcmDebugMacro( "Exit from ParseDES, delim-mode " << delim_mode );
01237 }
01238
01243 void Document::ParseSQ( SeqEntry *seqEntry,
01244 long offset, long l_max, bool delim_mode)
01245 {
01246 int SQItemNumber = 0;
01247 bool dlm_mod;
01248 long offsetStartCurrentSQItem = offset;
01249
01250 while (true)
01251 {
01252
01253 DocEntry *newDocEntry = ReadNextDocEntry();
01254
01255 if ( !newDocEntry )
01256 {
01257 gdcmWarningMacro("in ParseSQ : should never get here!");
01258 break;
01259 }
01260 if ( delim_mode )
01261 {
01262 if ( newDocEntry->IsSequenceDelimitor() )
01263 {
01264 seqEntry->SetDelimitationItem( newDocEntry );
01265 newDocEntry->Delete();
01266 break;
01267 }
01268 }
01269 if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
01270 {
01271 newDocEntry->Delete();
01272 break;
01273 }
01274
01275 SQItem *itemSQ = SQItem::New( seqEntry->GetDepthLevel() );
01276 unsigned int l = newDocEntry->GetReadLength();
01277
01278 if ( l == 0xffffffff )
01279 {
01280 dlm_mod = true;
01281 }
01282 else
01283 {
01284 dlm_mod = false;
01285 }
01286
01287
01288 Fp->seekg(offsetStartCurrentSQItem, std::ios::beg);
01289
01290
01291 ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod);
01292
01293 offsetStartCurrentSQItem = Fp->tellg();
01294
01295 seqEntry->AddSQItem( itemSQ, SQItemNumber );
01296 itemSQ->Delete();
01297 newDocEntry->Delete();
01298 SQItemNumber++;
01299 if ( !delim_mode && ((long)(Fp->tellg())-offset ) >= l_max )
01300 {
01301 break;
01302 }
01303 }
01304 }
01305
01312 DocEntry *Document::Backtrack(DocEntry *docEntry)
01313 {
01314
01315
01316 docEntry->Delete();
01317
01318
01319 uint16_t group = PreviousDocEntry->GetGroup();
01320 uint16_t elem = PreviousDocEntry->GetElement();
01321 uint32_t lgt = PreviousDocEntry->GetLength();
01322 long offset = PreviousDocEntry->GetOffset();
01323
01324 gdcmDebugMacro( "Backtrack :" << std::hex << group
01325 << "|" << elem
01326 << " at offset 0x(" <<offset << ")" );
01327 RemoveEntry( PreviousDocEntry );
01328
01329
01330 DocEntry *newEntry = NewSeqEntry(group, elem);
01331 newEntry->SetLength(lgt);
01332 newEntry->SetOffset(offset);
01333
01334
01335 Fp->seekg( 0, std::ios::beg);
01336 Fp->seekg(offset, std::ios::cur);
01337
01338 return newEntry;
01339 }
01340
01347 void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
01348 {
01349 uint16_t group = entry->GetGroup();
01350 uint16_t elem = entry->GetElement();
01351 const VRKey &vr = entry->GetVR();
01352 uint32_t length = entry->GetLength();
01353
01354 Fp->seekg((long)entry->GetOffset(), std::ios::beg);
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364 if ( (group == 0xfffe && elem != 0x0000 ) || vr == "SQ" )
01365 {
01366
01367 return;
01368 }
01369
01370 DataEntry *dataEntryPtr = dynamic_cast< DataEntry* >(entry);
01371 if( !dataEntryPtr )
01372 {
01373 return;
01374 }
01375
01376
01377 if ( length == 0 )
01378 {
01379 dataEntryPtr->SetBinArea(NULL,true);
01380 return;
01381 }
01382
01383
01384
01385
01386 std::ostringstream s;
01387
01388 if (!forceLoad)
01389 {
01390 if (length > MaxSizeLoadEntry)
01391 {
01392 dataEntryPtr->SetBinArea(NULL,true);
01393 dataEntryPtr->SetState(DataEntry::STATE_NOTLOADED);
01394
01395
01396 Fp->seekg((long)entry->GetOffset()+(long)entry->GetLength(),
01397 std::ios::beg);
01398 return;
01399 }
01400 }
01401
01402 LoadEntryBinArea(dataEntryPtr);
01403 }
01404
01409 void Document::FindDocEntryLength( DocEntry *entry )
01410 throw ( FormatError )
01411 {
01412 const VRKey &vr = entry->GetVR();
01413 uint16_t length16;
01414
01415 if ( Filetype == ExplicitVR && !entry->IsImplicitVR() )
01416 {
01417 if ( vr == "OB" || vr == "OW" || vr == "SQ" || vr == "UT"
01418 || vr == "UN" )
01419 {
01420
01421
01422
01423 Fp->seekg( 2L, std::ios::cur);
01424 uint32_t length32 = ReadInt32();
01425
01426 if ( (vr == "OB" || vr == "OW") && length32 == 0xffffffff )
01427 {
01428 uint32_t lengthOB;
01429 try
01430 {
01431 lengthOB = FindDocEntryLengthOBOrOW();
01432 }
01433 catch ( FormatUnexpected )
01434 {
01435
01436
01437
01438
01439
01440 gdcmWarningMacro( " Computing the length failed for " <<
01441 entry->GetKey() <<" in " <<GetFileName());
01442
01443 long currentPosition = Fp->tellg();
01444 Fp->seekg(0L,std::ios::end);
01445
01446 long lengthUntilEOF = (long)(Fp->tellg())-currentPosition;
01447 Fp->seekg(currentPosition, std::ios::beg);
01448
01449 entry->SetReadLength(lengthUntilEOF);
01450 entry->SetLength(lengthUntilEOF);
01451 return;
01452 }
01453 entry->SetReadLength(lengthOB);
01454 entry->SetLength(lengthOB);
01455 return;
01456 }
01457 FixDocEntryFoundLength(entry, length32);
01458 return;
01459 }
01460
01461
01462 length16 = ReadInt16();
01463
01464
01465
01466 if ( length16 == 0xffff)
01467 {
01468 length16 = 0;
01469 }
01470 FixDocEntryFoundLength( entry, (uint32_t)length16 );
01471 return;
01472 }
01473 else
01474 {
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486 FixDocEntryFoundLength( entry, ReadInt32() );
01487 return;
01488 }
01489 }
01490
01495 uint32_t Document::FindDocEntryLengthOBOrOW()
01496 throw( FormatUnexpected )
01497 {
01498
01499 long positionOnEntry = Fp->tellg();
01500 bool foundSequenceDelimiter = false;
01501 uint32_t totalLength = 0;
01502
01503 while ( !foundSequenceDelimiter )
01504 {
01505 uint16_t group;
01506 uint16_t elem;
01507 try
01508 {
01509 group = ReadInt16();
01510 elem = ReadInt16();
01511 }
01512 catch ( FormatError )
01513 {
01514 throw FormatError("Unexpected end of file encountered during ",
01515 "Document::FindDocEntryLengthOBOrOW()");
01516 }
01517
01518 totalLength += 4;
01519 if ( group != 0xfffe || ( ( elem != 0xe0dd ) && ( elem != 0xe000 ) ) )
01520 {
01521 long filePosition = Fp->tellg();
01522 gdcmWarningMacro(
01523 "Neither an Item tag nor a Sequence delimiter tag on :"
01524 << std::hex << group << " , " << elem
01525 << ") -before- position x(" << filePosition << ")" );
01526
01527 Fp->seekg(positionOnEntry, std::ios::beg);
01528 throw FormatUnexpected(
01529 "Neither an Item tag nor a Sequence delimiter tag.");
01530 }
01531 if ( elem == 0xe0dd )
01532 {
01533 foundSequenceDelimiter = true;
01534 }
01535 uint32_t itemLength = ReadInt32();
01536
01537 totalLength += itemLength + 4;
01538 SkipBytes(itemLength);
01539
01540 if ( foundSequenceDelimiter )
01541 {
01542 break;
01543 }
01544 }
01545 Fp->seekg( positionOnEntry, std::ios::beg);
01546 return totalLength;
01547 }
01548
01553 VRKey Document::FindDocEntryVR()
01554 {
01555 if ( Filetype != ExplicitVR )
01556 return GDCM_VRUNKNOWN;
01557
01558 long positionOnEntry = Fp->tellg();
01559
01560
01561
01562
01563
01564
01565
01566
01567 VRKey vr;
01568 Fp->read(&(vr[0]),(size_t)2);
01569
01570 if ( !CheckDocEntryVR(vr) )
01571 {
01572
01573
01574 if ( CurrentGroup != 0xfffe )
01575 gdcmWarningMacro( "Unknown VR " << std::hex << "0x("
01576 << (unsigned int)vr[0] << "|" << (unsigned int)vr[1]
01577 << ") at offset : 0x(" << positionOnEntry<< ")" );
01578 Fp->seekg(positionOnEntry, std::ios::beg);
01579 return GDCM_VRUNKNOWN;
01580 }
01581 return vr;
01582 }
01583
01592 bool Document::CheckDocEntryVR(const VRKey &vr)
01593 {
01594 return Global::GetVR()->IsValidVR(vr);
01595 }
01596
01601 void Document::SkipDocEntry(DocEntry *entry)
01602 {
01603 SkipBytes(entry->GetLength());
01604 }
01605
01610 void Document::SkipToNextDocEntry(DocEntry *currentDocEntry)
01611 {
01612 int l = currentDocEntry->GetReadLength();
01613 if ( l == -1 )
01614
01615 return;
01616 Fp->seekg((long)(currentDocEntry->GetOffset()), std::ios::beg);
01617 if (currentDocEntry->GetGroup() != 0xfffe)
01618 {
01619 Fp->seekg( (long)(currentDocEntry->GetReadLength()),std::ios::cur);
01620 }
01621 }
01622
01630 void Document::FixDocEntryFoundLength(DocEntry *entry,
01631 uint32_t foundLength)
01632 {
01633 entry->SetReadLength( foundLength );
01634 if ( foundLength == 0xffffffff)
01635 {
01636 foundLength = 0;
01637 }
01638
01639 uint16_t gr = entry->GetGroup();
01640 uint16_t elem = entry->GetElement();
01641
01642 if ( foundLength % 2)
01643 {
01644 gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength
01645 << " in x(" << std::hex << gr << "," << elem <<")");
01646 }
01647
01649
01650
01651
01652
01653
01654 if ( foundLength == 13)
01655 {
01656
01657 if ( gr != 0x0008 || ( elem != 0x0070 && elem != 0x0080 ) )
01658 {
01659 foundLength = 10;
01660 entry->SetReadLength(10);
01661 }
01662 }
01663
01665
01666
01667
01668 else if ( gr == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) )
01669 {
01670 foundLength = 4;
01671 entry->SetReadLength(4);
01672 }
01673
01674 else if ( entry->GetVR() == "SQ" )
01675 {
01676 foundLength = 0;
01677 }
01678
01680
01681
01682 else if ( gr == 0xfffe )
01683 {
01684
01685
01686
01687 if ( entry->GetElement() != 0x0000 )
01688 {
01689 foundLength = 0;
01690 }
01691 else
01692 {
01693 foundLength=12;
01694 }
01695 }
01696 entry->SetLength(foundLength);
01697 }
01698
01705 bool Document::IsDocEntryAnInteger(DocEntry *entry)
01706 {
01707 uint16_t elem = entry->GetElement();
01708 uint16_t group = entry->GetGroup();
01709 const VRKey &vr = entry->GetVR();
01710 uint32_t length = entry->GetLength();
01711
01712
01713
01714
01715 if ( elem == 0 )
01716 {
01717 if ( length == 4 )
01718 {
01719 return true;
01720 }
01721 else
01722 {
01723
01724
01725
01726
01727
01728
01729
01730 long filePosition = Fp->tellg();
01731 gdcmWarningMacro( "Erroneous Group Length element length on : ("
01732 << std::hex << group << " , " << elem
01733 << ") -before- position x(" << filePosition << ")"
01734 << "lgt : " << length );
01735 }
01736 }
01737
01738 if ( vr == "UL" || vr == "US" || vr == "SL" || vr == "SS" )
01739 {
01740 return true;
01741 }
01742 return false;
01743 }
01744
01753 bool Document::CheckSwap()
01754 {
01755 uint32_t s32;
01756 uint16_t s16;
01757
01758 char deb[256];
01759
01760
01761
01762 bool net2host = Util::IsCurrentProcessorBigEndian();
01763
01764
01765
01766 Fp->read(deb, 256);
01767
01768 char *entCur = deb + 128;
01769 if ( memcmp(entCur, "DICM", (size_t)4) == 0 )
01770 {
01771 gdcmDebugMacro( "Looks like DICOM Version3 (preamble + DCM)" );
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787 entCur = deb + 136;
01788
01789
01790
01791
01792
01793 if ( memcmp(entCur, "UL", (size_t)2) == 0 ||
01794 memcmp(entCur, "OB", (size_t)2) == 0 ||
01795 memcmp(entCur, "UI", (size_t)2) == 0 ||
01796 memcmp(entCur, "CS", (size_t)2) == 0 )
01797
01798
01799
01800
01801 {
01802 Filetype = ExplicitVR;
01803 gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
01804 }
01805 else
01806 {
01807 Filetype = ImplicitVR;
01808 gdcmWarningMacro( "Group 0002 :Not an explicit Value Representation;"
01809 << "Looks like a bugged Header!");
01810 }
01811
01812 if ( net2host )
01813 {
01814 SwapCode = 4321;
01815 gdcmDebugMacro( "HostByteOrder != NetworkByteOrder, SwapCode = 4321");
01816 }
01817 else
01818 {
01819 SwapCode = 1234;
01820 gdcmDebugMacro( "HostByteOrder = NetworkByteOrder, SwapCode = 1234");
01821 }
01822
01823
01824
01825
01826 Fp->seekg(0, std::ios::beg);
01827
01828 Fp->seekg ( 132L, std::ios::beg);
01829 return true;
01830 }
01831
01832
01833
01834
01835
01836 gdcmWarningMacro( "Not a Kosher DICOM Version3 file (no preamble)");
01837
01838 Fp->seekg(0, std::ios::beg);
01839
01840
01841
01842
01843
01844 s16 = *((uint16_t *)(deb));
01845 SwapCode = 0;
01846 switch ( s16 )
01847 {
01848 case 0x0002 :
01849 SwapCode = 1234;
01850 entCur = deb + 4;
01851 break;
01852 case 0x0200 :
01853 SwapCode = 4321;
01854 entCur = deb + 6;
01855 }
01856
01857 if ( SwapCode != 0 )
01858 {
01859 if ( memcmp(entCur, "UL", (size_t)2) == 0 ||
01860 memcmp(entCur, "OB", (size_t)2) == 0 ||
01861 memcmp(entCur, "UI", (size_t)2) == 0 ||
01862 memcmp(entCur, "SH", (size_t)2) == 0 ||
01863 memcmp(entCur, "AE", (size_t)2) == 0 ||
01864 memcmp(entCur, "OB", (size_t)2) == 0 )
01865 {
01866 Filetype = ExplicitVR;
01867 gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
01868 return true;
01869 }
01870 }
01871
01872
01873
01874
01875
01876
01877
01878 entCur = deb + 4;
01879
01880
01881
01882 s32 = *((uint32_t *)(entCur));
01883 switch( s32 )
01884 {
01885 case 0x00040000 :
01886 SwapCode = 3412;
01887 Filetype = ACR;
01888 return true;
01889 case 0x04000000 :
01890 SwapCode = 4321;
01891 Filetype = ACR;
01892 return true;
01893 case 0x00000400 :
01894 SwapCode = 2143;
01895 Filetype = ACR;
01896 return true;
01897 case 0x00000004 :
01898 SwapCode = 1234;
01899 Filetype = ACR;
01900 return true;
01901 default :
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917 s16 = *((uint16_t *)(deb));
01918
01919 switch ( s16 )
01920 {
01921 case 0x0001 :
01922 case 0x0002 :
01923 case 0x0003 :
01924 case 0x0004 :
01925 case 0x0005 :
01926 case 0x0006 :
01927 case 0x0007 :
01928 case 0x0008 :
01929 SwapCode = 1234;
01930 Filetype = ACR;
01931 return true;
01932 case 0x0100 :
01933 case 0x0200 :
01934 case 0x0300 :
01935 case 0x0400 :
01936 case 0x0500 :
01937 case 0x0600 :
01938 case 0x0700 :
01939 case 0x0800 :
01940 SwapCode = 4321;
01941 Filetype = ACR;
01942 return true;
01943 default :
01944 gdcmWarningMacro("ACR/NEMA unfound swap info (Hopeless !)");
01945 Filetype = Unknown;
01946 return false;
01947 }
01948 }
01949 }
01950
01954 void Document::SwitchByteSwapCode()
01955 {
01956 gdcmDebugMacro( "Switching Byte Swap code from "<< SwapCode
01957 << " at: 0x" << std::hex << Fp->tellg() );
01958 if ( SwapCode == 1234 )
01959 {
01960 SwapCode = 4321;
01961 }
01962 else if ( SwapCode == 4321 )
01963 {
01964 SwapCode = 1234;
01965 }
01966 else if ( SwapCode == 3412 )
01967 {
01968 SwapCode = 2143;
01969 }
01970 else if ( SwapCode == 2143 )
01971 {
01972 SwapCode = 3412;
01973 }
01974 gdcmDebugMacro( " Into: "<< SwapCode );
01975 }
01976
01981 void Document::SetMaxSizeLoadEntry(long newSize)
01982 {
01983 if ( newSize < 0 )
01984 {
01985 return;
01986 }
01987 if ((uint32_t)newSize >= (uint32_t)0xffffffff )
01988 {
01989 MaxSizeLoadEntry = 0xffffffff;
01990 return;
01991 }
01992 MaxSizeLoadEntry = newSize;
01993 }
01994
02002 DocEntry *Document::ReadNextDocEntry()
02003 {
02004 try
02005 {
02006 CurrentGroup = ReadInt16();
02007 CurrentElem = ReadInt16();
02008 }
02009 catch ( FormatError )
02010 {
02011
02012
02013 return 0;
02014 }
02015
02016
02017 HandleBrokenEndian(CurrentGroup, CurrentElem);
02018
02019
02020 if ( HasDCMPreamble )
02021 HandleOutOfGroup0002(CurrentGroup, CurrentElem);
02022
02023 VRKey vr = FindDocEntryVR();
02024
02025 VRKey realVR = vr;
02026
02027 if ( vr == GDCM_VRUNKNOWN )
02028 {
02029 if ( CurrentElem == 0x0000 )
02030 {
02031 realVR = "UL";
02032 }
02033 else if (CurrentGroup%2 == 1 &&
02034 (CurrentElem >= 0x0010 && CurrentElem <=0x00ff ))
02035 {
02036
02037
02038 realVR = "LO";
02039 }
02040 else
02041 {
02042 DictEntry *dictEntry = GetDictEntry(CurrentGroup,CurrentElem);
02043 if ( dictEntry )
02044 {
02045 realVR = dictEntry->GetVR();
02046 dictEntry->Unregister();
02047 }
02048 }
02049 }
02050
02051
02052 DocEntry *newEntry;
02053 if ( Global::GetVR()->IsVROfSequence(realVR) )
02054 newEntry = NewSeqEntry(CurrentGroup, CurrentElem);
02055 else
02056 {
02057 newEntry = NewDataEntry(CurrentGroup, CurrentElem, realVR);
02058 static_cast<DataEntry *>(newEntry)->SetState(DataEntry::STATE_NOTLOADED);
02059 }
02060
02061 if ( vr == GDCM_VRUNKNOWN )
02062 {
02063 if ( Filetype == ExplicitVR )
02064 {
02065
02066
02067 if ( newEntry->GetGroup() != 0xfffe )
02068 {
02069 std::string msg;
02070 int offset = Fp->tellg();
02071 msg = Util::Format(
02072 "Entry (%04x,%04x) at x(%x) should be Explicit VR\n",
02073 newEntry->GetGroup(), newEntry->GetElement(), offset );
02074 gdcmWarningMacro( msg.c_str() );
02075 }
02076 }
02077 newEntry->SetImplicitVR();
02078 }
02079
02080 try
02081 {
02082 FindDocEntryLength(newEntry);
02083 }
02084 catch ( FormatError )
02085 {
02086
02087 newEntry->Delete();
02088 return 0;
02089 }
02090
02091 newEntry->SetOffset(Fp->tellg());
02092
02093 return newEntry;
02094 }
02095
02102 void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
02103 {
02104
02105
02106 static int reversedEndian = 0;
02107
02108 if ((group == 0xfeff) && (elem == 0x00e0))
02109 {
02110
02111 gdcmDebugMacro( "Start endian swap mark found." );
02112 reversedEndian++;
02113 SwitchByteSwapCode();
02114
02115 group = 0xfffe;
02116 elem = 0xe000;
02117 }
02118 else if (group == 0xfffe && elem == 0xe00d && reversedEndian)
02119 {
02120
02121 gdcmDebugMacro( "End of reversed endian." );
02122 reversedEndian--;
02123 SwitchByteSwapCode();
02124 }
02125 else if (group == 0xfeff && elem == 0xdde0)
02126 {
02127
02128
02129
02130
02131
02132 gdcmWarningMacro( "Should never get here! reversed Sequence Terminator!" );
02133
02134 group = 0xfffe;
02135 elem = 0xe0dd;
02136 }
02137 else if (group == 0xfffe && elem == 0xe0dd)
02138 {
02139 gdcmDebugMacro( "Straight Sequence Terminator." );
02140 }
02141 }
02142
02148 void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
02149 {
02150
02151
02152 if ( !Group0002Parsed && group != 0x0002)
02153 {
02154 Group0002Parsed = true;
02155
02156
02157
02158 std::string ts = GetTransferSyntax();
02159 if ( ts == GDCM_UNKNOWN )
02160 {
02161 gdcmDebugMacro("True DICOM File, with NO Transfer Syntax (?!) " );
02162 return;
02163 }
02164 if ( !Global::GetTS()->IsTransferSyntax(ts) )
02165 {
02166 gdcmWarningMacro("True DICOM File, with illegal Transfer Syntax: ["
02167 << ts << "]");
02168 return;
02169 }
02170
02171
02172
02173
02174 if ( Global::GetTS()->GetSpecialTransferSyntax(ts) ==
02175 TS::ImplicitVRLittleEndian )
02176 {
02177 Filetype = ImplicitVR;
02178 }
02179
02180
02181
02182
02183
02184
02185
02186
02187 if ( Global::GetTS()->GetSpecialTransferSyntax(ts) ==
02188 TS::ExplicitVRBigEndian )
02189 {
02190 gdcmDebugMacro("Transfer Syntax Name = ["
02191 << GetTransferSyntaxName() << "]" );
02192 SwitchByteSwapCode();
02193 group = SwapShort(group);
02194 elem = SwapShort(elem);
02195 }
02196 }
02197 }
02198
02199
02200
02201
02202
02203 }