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 #if defined(__BORLANDC__)
00037 #include <mem.h>
00038 #endif
00039
00040 namespace GDCM_NAME_SPACE
00041 {
00042
00043
00044
00045 const unsigned int Document::MAX_SIZE_LOAD_ELEMENT_VALUE = 0xfff;
00046
00047
00048
00049
00050
00056 Document::Document()
00057 :ElementSet()
00058 {
00059 Fp = 0;
00060
00061 SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
00062 Initialize();
00063 SwapCode = 1234;
00064 Filetype = ExplicitVR;
00065 CurrentOffsetPosition = 0;
00066
00067 Group0002Parsed = false;
00068 IsDocumentAlreadyLoaded = false;
00069 IsDocumentModified = true;
00070 LoadMode = LD_ALL;
00071
00072 SetFileName("");
00073 changeFromUN=false;
00074 UnexpectedEOF=false;
00075 }
00076
00080 Document::~Document ()
00081 {
00082 CloseFile();
00083 }
00084
00085
00086
00092 bool Document::Load( )
00093 {
00094 if ( GetFileName() == "" )
00095 {
00096 gdcmWarningMacro( "Use SetFileName, before !" );
00097 return false;
00098 }
00099 return DoTheLoadingDocumentJob( );
00100 }
00101
00102
00103
00110
00111
00112
00113
00114
00115
00116
00117
00118
00124 bool Document::DoTheLoadingDocumentJob( )
00125 {
00126 if ( ! IsDocumentModified )
00127 return true;
00128
00129 ClearEntry();
00130
00131 Fp = 0;
00132 if ( !OpenFile() )
00133 {
00134
00135 Filetype = Unknown;
00136 return false;
00137 }
00138
00139 Group0002Parsed = false;
00140
00141 gdcmDebugMacro( "Starting parsing of file: " << Filename.c_str());
00142
00143
00144 Fp->seekg(0, std::ios::end);
00145 long lgt = Fp->tellg();
00146 Fp->seekg(0, std::ios::beg);
00147
00148
00149
00150 if (! CheckSwap() )
00151 {
00152 gdcmWarningMacro( "Neither a DICOM V3 nor an ACR-NEMA file: "
00153 << Filename.c_str());
00154 CloseFile();
00155 return false;
00156 }
00157
00158 long beg = Fp->tellg();
00159
00160 lgt -= beg;
00161
00162
00163
00164 ParseDES( this, beg, lgt, false);
00165
00166 if ( IsEmpty() )
00167 {
00168 gdcmErrorMacro( "No tag in internal hash table for: "
00169 << Filename.c_str());
00170 CloseFile();
00171 return false;
00172 }
00173 IsDocumentAlreadyLoaded = true;
00174
00175
00176
00177
00178
00179 std::string PhotometricInterpretation = GetEntryString(0x0028,0x0004);
00180 if ( PhotometricInterpretation == "PALETTE COLOR " )
00181 {
00182
00183
00184
00185 LoadEntryBinArea(0x0028,0x1200);
00186
00209
00210
00211
00212
00213
00214
00215 LoadEntryBinArea(0x0028,0x1201);
00216 LoadEntryBinArea(0x0028,0x1202);
00217 LoadEntryBinArea(0x0028,0x1203);
00218
00219
00220 LoadEntryBinArea(0x0028,0x1221);
00221
00222 LoadEntryBinArea(0x0028,0x1222);
00223
00224 LoadEntryBinArea(0x0028,0x1223);
00225 }
00226
00227
00228 SeqEntry *modLutSeq = GetSeqEntry(0x0028,0x3000);
00229 if ( modLutSeq !=0 )
00230 {
00231 SQItem *sqi= modLutSeq->GetFirstSQItem();
00232 if ( sqi != 0 )
00233 {
00234 DataEntry *dataEntry = sqi->GetDataEntry(0x0028,0x3006);
00235 if ( dataEntry != 0 )
00236 {
00237 if ( dataEntry->GetLength() != 0 )
00238 {
00239
00240
00241 LoadEntryBinArea(dataEntry);
00242 }
00243 }
00244 }
00245 }
00246
00247
00248
00249 GDCM_NAME_SPACE::DocEntry *d;
00250 for (ListElements::iterator it = UserForceLoadList.begin();
00251 it != UserForceLoadList.end();
00252 ++it)
00253 {
00254 gdcmDebugMacro( "Force Load " << std::hex
00255 << (*it).Group << "|" <<(*it).Elem );
00256
00257 d = GetDocEntry( (*it).Group, (*it).Elem);
00258
00259 if ( d == NULL)
00260 {
00261 gdcmWarningMacro( "You asked to ForceLoad " << std::hex
00262 << (*it).Group <<"|"<< (*it).Elem
00263 << " that doesn't exist" );
00264 continue;
00265 }
00266
00267 LoadDocEntry(d, true);
00268 }
00269
00270 CloseFile();
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 std::string RecCode;
00283 RecCode = GetEntryString(0x0008, 0x0010);
00284 if (RecCode == "ACRNEMA_LIBIDO_1.1" ||
00285 RecCode == "CANRME_AILIBOD1_1." )
00286
00287 {
00288 Filetype = ACR_LIBIDO;
00289 std::string rows = GetEntryString(0x0028, 0x0010);
00290 std::string columns = GetEntryString(0x0028, 0x0011);
00291 SetEntryString(columns, 0x0028, 0x0010);
00292 SetEntryString(rows , 0x0028, 0x0011);
00293 }
00294
00295 return true;
00296 }
00297
00298
00304 void Document::AddForceLoadElement (uint16_t group, uint16_t elem)
00305 {
00306 DicomElement el;
00307 el.Group = group;
00308 el.Elem = elem;
00309 UserForceLoadList.push_back(el);
00310 }
00314 Dict *Document::GetPubDict()
00315 {
00316 return RefPubDict;
00317 }
00318
00322 Dict *Document::GetShaDict()
00323 {
00324 return RefShaDict;
00325 }
00326
00331 bool Document::SetShaDict(Dict *dict)
00332 {
00333 RefShaDict = dict;
00334 return !RefShaDict;
00335 }
00336
00341 bool Document::SetShaDict(DictKey const &dictName)
00342 {
00343 RefShaDict = Global::GetDicts()->GetDict(dictName);
00344 return !RefShaDict;
00345 }
00346
00354 bool Document::IsParsable()
00355 {
00356 if ( Filetype == Unknown )
00357 {
00358 gdcmWarningMacro( "Wrong filetype for " << GetFileName());
00359 return false;
00360 }
00361
00362 if ( IsEmpty() )
00363 {
00364 gdcmWarningMacro( "No tag in internal hash table.");
00365 return false;
00366 }
00367
00368 return true;
00369 }
00377 bool Document::IsReadable()
00378 {
00379 return IsParsable();
00380 }
00381
00386 bool Document::IsDicomV3()
00387 {
00388
00389
00390
00391
00392 return GetDocEntry(0x0002, 0x0010) != NULL;
00393 }
00394
00400 bool Document::IsPapyrus()
00401 {
00402
00403 DocEntry *e = GetDocEntry(0x0041, 0x1050);
00404 if ( !e )
00405 return false;
00406
00407 if ( !dynamic_cast<SeqEntry*>(e) )
00408 return false;
00409 return true;
00410 }
00411
00417 FileType Document::GetFileType()
00418 {
00419 return Filetype;
00420 }
00421
00429 std::string Document::GetTransferSyntax()
00430 {
00431 DocEntry *entry = GetDocEntry(0x0002, 0x0010);
00432 if ( !entry )
00433 {
00434 return GDCM_UNKNOWN;
00435 }
00436
00437
00438
00439
00440
00441
00442
00443 if (DataEntry *dataEntry = dynamic_cast<DataEntry *>(entry) )
00444 {
00445 std::string transfer = dataEntry->GetString();
00446
00447
00448
00449 if ( transfer.length() == 0 )
00450 {
00451
00452 gdcmWarningMacro( "Transfer Syntax has length = 0.");
00453 return GDCM_UNKNOWN;
00454 }
00455 while ( !isdigit((unsigned char)transfer[transfer.length()-1]) )
00456 {
00457 transfer.erase(transfer.length()-1, 1);
00458 if ( transfer.length() == 0 )
00459 {
00460
00461 gdcmWarningMacro( "Transfer Syntax contains no valid character.");
00462 return GDCM_UNKNOWN;
00463 }
00464 }
00465 return transfer;
00466 }
00467 return GDCM_UNKNOWN;
00468 }
00469
00474 std::string Document::GetTransferSyntaxName()
00475 {
00476
00477 std::string transferSyntax = GetEntryString(0x0002,0x0010);
00478
00479 if ( (transferSyntax.find(GDCM_NOTLOADED) < transferSyntax.length()) )
00480 {
00481 gdcmErrorMacro( "Transfer Syntax not loaded. " << std::endl
00482 << "Better you increase MAX_SIZE_LOAD_ELEMENT_VALUE" );
00483 return "Uncompressed ACR-NEMA";
00484 }
00485 if ( transferSyntax == GDCM_UNFOUND )
00486 {
00487 gdcmDebugMacro( "Unfound Transfer Syntax (0002,0010)");
00488 return "Uncompressed ACR-NEMA";
00489 }
00490
00491
00492 const TSKey &tsName = Global::GetTS()->GetValue( transferSyntax );
00493
00494
00495 return tsName;
00496 }
00497
00498
00503 uint16_t Document::SwapShort(uint16_t a)
00504 {
00505 if ( SwapCode == 4321 || SwapCode == 2143 )
00506 {
00507
00508
00509 a = ( a << 8 ) | ( a >> 8 );
00510 }
00511 return a;
00512 }
00513
00519 uint32_t Document::SwapLong(uint32_t a)
00520 {
00521 switch (SwapCode)
00522 {
00523 case 1234 :
00524 break;
00525 case 4321 :
00526
00527
00528
00529 a=( ( a<<24) | ((a<<8) & 0x00ff0000) |
00530 ((a>>8) & 0x0000ff00) | (a>>24) );
00531 break;
00532 case 3412 :
00533
00534 a=( (a<<16) | (a>>16) );
00535 break;
00536 case 2143 :
00537 a=( ((a<< 8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) );
00538 break;
00539 default :
00540 gdcmErrorMacro( "Unexpected swap code:" << SwapCode );
00541 a = 0;
00542 }
00543 return a;
00544 }
00545
00551 double Document::SwapDouble(double a)
00552 {
00553 switch (SwapCode)
00554 {
00555
00556
00557
00558 case 1234 :
00559 break;
00560 case 4321 :
00561 {
00562 char *beg = (char *)&a;
00563 char *end = beg + 7;
00564 char t;
00565 for (unsigned int i = 0; i<7; i++)
00566 {
00567 t = *beg;
00568 *beg = *end;
00569 *end = t;
00570 beg++,
00571 end--;
00572 }
00573 }
00574 break;
00575 default :
00576 gdcmErrorMacro( "Unexpected swap code:" << SwapCode );
00577 a = 0.;
00578 }
00579 return a;
00580 }
00581
00582
00583
00590 std::ifstream *Document::OpenFile()
00591 {
00592 HasDCMPreamble = false;
00593 if (Filename.length() == 0)
00594 {
00595 return 0;
00596 }
00597
00598 if ( Fp )
00599 {
00600 gdcmDebugMacro( "File already open: " << Filename.c_str());
00601 CloseFile();
00602 }
00603
00604 Fp = new std::ifstream(Filename.c_str(), std::ios::in | std::ios::binary);
00605 if ( ! *Fp )
00606 {
00607
00608
00609
00610
00611
00612
00613
00614
00615 gdcmWarningMacro( "Cannot open file: " << Filename.c_str());
00616 delete Fp;
00617 Fp = 0;
00618 return 0;
00619
00620
00621 }
00622
00623 uint16_t zero = 0;
00624 Fp->read((char*)&zero, (size_t)2);
00625 if ( Fp->eof() )
00626 {
00627 CloseFile();
00628 return 0;
00629 }
00630
00631
00632 Fp->seekg(126L, std::ios::cur);
00633 char dicm[4];
00634 Fp->read(dicm, (size_t)4);
00635 if ( Fp->eof() )
00636 {
00637 CloseFile();
00638 return 0;
00639 }
00640
00641 if ( memcmp(dicm, "DICM", 4) == 0 )
00642 {
00643 HasDCMPreamble = true;
00644 return Fp;
00645 }
00646
00647
00648
00649
00650 if (
00651 zero == 0x0001 || zero == 0x0100 || zero == 0x0002 || zero == 0x0200 ||
00652 zero == 0x0003 || zero == 0x0300 || zero == 0x0004 || zero == 0x0400 ||
00653 zero == 0x0005 || zero == 0x0500 || zero == 0x0006 || zero == 0x0600 ||
00654 zero == 0x0007 || zero == 0x0700 || zero == 0x0008 || zero == 0x0800 ||
00655 zero == 0x0028 || 0x2800
00656
00657 )
00658 {
00659 std::string msg = Util::Format(
00660 "ACR/DICOM starting by 0x(%04x) at the beginning of the file\n", zero);
00661
00662 gdcmWarningMacro( msg.c_str() );
00663 return Fp;
00664 }
00665
00666
00667 CloseFile();
00668
00669
00670 gdcmDebugMacro( "Neither ACR/No Preamble Dicom nor DICOMV3 file: "
00671 << Filename.c_str());
00672 return 0;
00673 }
00674
00679 bool Document::CloseFile()
00680 {
00681 if ( Fp )
00682 {
00683 Fp->close();
00684 delete Fp;
00685 Fp = 0;
00686 }
00687 return true;
00688 }
00689
00696 void Document::WriteContent(std::ofstream *fp, FileType filetype)
00697 {
00698
00699
00700 if ( filetype == ImplicitVR || filetype == ExplicitVR ||
00701 filetype == JPEG || filetype == JPEG2000 )
00702 {
00703
00704 char filePreamble[128];
00705 memset(filePreamble, 0, 128);
00706 fp->write(filePreamble, 128);
00707 fp->write("DICM", 4);
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 ElementSet::WriteContent(fp, filetype, false);
00726 }
00727
00728
00729
00736 void Document::LoadEntryBinArea(uint16_t group, uint16_t elem)
00737 {
00738
00739 DocEntry *docEntry = GetDocEntry(group, elem);
00740 if ( !docEntry )
00741 {
00742 gdcmDebugMacro(std::hex << group << "|" << elem
00743 << " doesn't exist" );
00744 return;
00745 }
00746 DataEntry *dataEntry = dynamic_cast<DataEntry *>(docEntry);
00747 if ( !dataEntry )
00748 {
00749 gdcmWarningMacro(std::hex << group << "|" << elem
00750 << " is NOT a DataEntry");
00751 return;
00752 }
00753 LoadEntryBinArea(dataEntry);
00754 }
00755
00761 void Document::LoadEntryBinArea(DataEntry *entry)
00762 {
00763 if( entry->GetBinArea() )
00764 return;
00765
00766 bool openFile = !Fp;
00767 if ( openFile )
00768 OpenFile();
00769
00770
00771 Fp->seekg((size_t)entry->GetOffset(), std::ios::beg);
00772
00773 size_t l = entry->GetLength();
00774 uint8_t *data = new uint8_t[l];
00775 if ( !data )
00776 {
00777 gdcmWarningMacro( "Cannot allocate DataEntry content for : "
00778 << std::hex << entry->GetGroup()
00779 << "|" << entry->GetElement() );
00780 return;
00781 }
00782
00783
00784 Fp->read((char*)data, l);
00785 if ( Fp->fail() || Fp->eof() )
00786 {
00787 delete[] data;
00788 entry->SetState(DataEntry::STATE_UNREAD);
00789 return;
00790 }
00791
00792
00793 uint32_t i;
00794 unsigned short vrLgth =
00795 Global::GetVR()->GetAtomicElementLength(entry->GetVR());
00796
00797
00798
00799
00800
00801 switch(vrLgth)
00802 {
00803 case 1:
00804 {
00805 break;
00806 }
00807 case 2:
00808 {
00809 uint16_t *data16 = (uint16_t *)data;
00810 for(i=0;i<l/vrLgth;i++)
00811 data16[i] = SwapShort(data16[i]);
00812 break;
00813 }
00814 case 4:
00815 {
00816 uint32_t *data32 = (uint32_t *)data;
00817 for(i=0;i<l/vrLgth;i++)
00818 data32[i] = SwapLong(data32[i]);
00819 break;
00820 }
00821 case 8:
00822 {
00823 double *data64 = (double *)data;
00824 for(i=0;i<l/vrLgth;i++)
00825 data64[i] = SwapDouble(data64[i]);
00826 break;
00827 }
00828 }
00829
00830 entry->SetBinArea(data);
00831
00832 if ( openFile )
00833 CloseFile();
00834 }
00835
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00860 bool Document::operator<(Document &document)
00861 {
00862
00863 std::string s1 = GetEntryString(0x0010,0x0010);
00864 std::string s2 = document.GetEntryString(0x0010,0x0010);
00865 if (s1 < s2)
00866 {
00867 return true;
00868 }
00869 else if ( s1 > s2 )
00870 {
00871 return false;
00872 }
00873 else
00874 {
00875
00876 s1 = GetEntryString(0x0010,0x0020);
00877 s2 = document.GetEntryString(0x0010,0x0020);
00878 if ( s1 < s2 )
00879 {
00880 return true;
00881 }
00882 else if ( s1 > s2 )
00883 {
00884 return false;
00885 }
00886 else
00887 {
00888
00889 s1 = GetEntryString(0x0020,0x000d);
00890 s2 = document.GetEntryString(0x0020,0x000d);
00891 if ( s1 < s2 )
00892 {
00893 return true;
00894 }
00895 else if ( s1 > s2 )
00896 {
00897 return false;
00898 }
00899 else
00900 {
00901
00902 s1 = GetEntryString(0x0020,0x000e);
00903 s2 = document.GetEntryString(0x0020,0x000e);
00904 if ( s1 < s2 )
00905 {
00906 return true;
00907 }
00908 else if ( s1 > s2 )
00909 {
00910 return false;
00911 }
00912 }
00913 }
00914 }
00915 return false;
00916 }
00917
00918
00919
00920
00926 void Document::ReadBegBuffer(size_t l)
00927 throw( FormatError )
00928 {
00929 Fp->read (BegBuffer, (size_t)l);
00930 if ( Fp->fail() )
00931 {
00932 throw FormatError( "Document::ReadBegBuffer()", " file error." );
00933 }
00934 if ( Fp->eof() )
00935 {
00936 throw FormatError( "Document::ReadBegBuffer()", "EOF." );
00937 }
00938 PtrBegBuffer = BegBuffer;
00939 CurrentOffsetPosition+=l;
00940 }
00946 uint16_t Document::ReadInt16()
00947 throw( FormatError )
00948 {
00949 uint16_t g;
00950 Fp->read ((char*)&g, (size_t)2);
00951 if ( Fp->fail() )
00952 {
00953 throw FormatError( "Document::ReadInt16()", " file error." );
00954 }
00955 if ( Fp->eof() )
00956 {
00957 throw FormatError( "Document::ReadInt16()", "EOF." );
00958 }
00959 g = SwapShort(g);
00960 return g;
00961 }
00962
00968 uint16_t Document::GetInt16()
00969 {
00970 uint16_t g = *((uint16_t*)PtrBegBuffer);
00971 g = SwapShort(g);
00972 PtrBegBuffer+=2;
00973 return g;
00974 }
00980 uint32_t Document::ReadInt32()
00981 throw( FormatError )
00982 {
00983 uint32_t g;
00984 Fp->read ((char*)&g, (size_t)4);
00985 if ( Fp->fail() )
00986 {
00987 throw FormatError( "Document::ReadInt32()", " file error." );
00988 }
00989 if ( Fp->eof() )
00990 {
00991 throw FormatError( "Document::ReadInt32()", "EOF." );
00992 }
00993 g = SwapLong(g);
00994 return g;
00995 }
00996
01002 uint32_t Document::GetInt32()
01003 {
01004 uint32_t g = *((uint32_t*)PtrBegBuffer);
01005 g = SwapLong(g);
01006 PtrBegBuffer+=4;
01007 return g;
01008 }
01009
01013 int Document::ComputeGroup0002Length( )
01014 {
01015 uint16_t gr;
01016 VRKey vr;
01017
01018 int groupLength = 0;
01019 bool found0002 = false;
01020
01021
01022 DocEntry *entry = GetFirstEntry();
01023 while( entry )
01024 {
01025 gr = entry->GetGroup();
01026
01027 if ( gr == 0x0002 )
01028 {
01029 found0002 = true;
01030
01031 if ( entry->GetElement() != 0x0000 )
01032 {
01033 vr = entry->GetVR();
01034
01035
01036
01037 if ( vr == "OB" )
01038 {
01039
01040 groupLength += 4;
01041 }
01042 groupLength += 2 + 2 + 4 + entry->GetLength();
01043 }
01044 }
01045 else if (found0002 )
01046 break;
01047
01048 entry = GetNextEntry();
01049 }
01050 return groupLength;
01051 }
01052
01056 void Document::CallStartMethod()
01057 {
01058 Progress = 0.0f;
01059 Abort = false;
01060 CommandManager::ExecuteCommand(this,CMD_STARTPROGRESS);
01061 }
01062
01066 void Document::CallProgressMethod()
01067 {
01068 CommandManager::ExecuteCommand(this,CMD_PROGRESS);
01069 }
01070
01074 void Document::CallEndMethod()
01075 {
01076 Progress = 1.0f;
01077 CommandManager::ExecuteCommand(this,CMD_ENDPROGRESS);
01078 }
01079
01080
01081
01086 void Document::Initialize()
01087 {
01088 RefPubDict = Global::GetDicts()->GetDefaultPubDict();
01089 RefShaDict = NULL;
01090 Filetype = Unknown;
01091 }
01092
01100 void Document::ParseDES(DocEntrySet *set, long offset,
01101 long l_max, bool delim_mode)
01102 {
01103 DocEntry *newDocEntry;
01104 DataEntry *newDataEntry;
01105 SeqEntry *newSeqEntry;
01106
01107 bool used;
01108
01109 bool delim_mode_intern = delim_mode;
01110 bool first = true;
01111 gdcmDebugMacro( "Enter in ParseDES, delim-mode " << delim_mode
01112 << " at offset " << std::hex << "0x(" << offset << ")" );
01113 while (true)
01114 {
01115
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127 if ( !delim_mode )
01128 if ( ((long)(Fp->tellg())-offset) >= l_max)
01129 {
01130 break;
01131 }
01132
01133 newDocEntry = ReadNextDocEntry( );
01134
01135 if ( !newDocEntry )
01136 {
01137 break;
01138 }
01139
01140
01141
01142 if( Debug::GetDebugFlag() )
01143 std::cerr<<newDocEntry->GetKey()<<" "<<newDocEntry->GetVR()<<std::endl;
01144
01145
01146
01147
01148
01149 if ( !first && newDocEntry->IsItemStarter() )
01150 {
01151
01152 newDocEntry = Backtrack(newDocEntry);
01153 }
01154 else
01155 {
01156 PreviousDocEntry = newDocEntry;
01157 }
01158
01159 used = true;
01160 newDataEntry = dynamic_cast<DataEntry*>(newDocEntry);
01161
01162 if ( newDataEntry )
01163 {
01165
01166
01167
01168 if ( !set->AddEntry( newDataEntry ) )
01169 {
01170 gdcmDebugMacro( "in ParseDES : cannot add a DataEntry "
01171 << newDataEntry->GetKey()
01172 << " (at offset : 0x("
01173 << newDataEntry->GetOffset() << ") )" );
01174 used=false;
01175 }
01176 else
01177 {
01178 newDataEntry->Delete();
01179
01180 LoadDocEntry( newDataEntry );
01181 }
01182 if ( newDataEntry->GetElement() == 0x0000 )
01183 {
01184 if ( newDataEntry->GetGroup()%2 != 0 )
01185 {
01186 if ( LoadMode & LD_NOSHADOW )
01187 {
01188 std::string strLgrGroup = newDataEntry->GetString();
01189
01190 int lgrGroup;
01191
01192 {
01193 lgrGroup = atoi(strLgrGroup.c_str());
01194 Fp->seekg(lgrGroup, std::ios::cur);
01195 RemoveEntry( newDocEntry );
01196 continue;
01197 }
01198 }
01199 }
01200 }
01201
01202 bool delimitor = newDataEntry->IsItemDelimitor();
01203 bool outOfBounds = false;
01204 if (!delim_mode )
01205 if ( ((long)(Fp->tellg())-offset) >= l_max )
01206 outOfBounds = true;
01207
01208
01209
01210
01211
01212 if ( delimitor || outOfBounds )
01213 {
01214 if ( !used )
01215 newDocEntry->Delete();
01216 break;
01217 }
01218
01219
01220 SkipToNextDocEntry(newDocEntry);
01221 }
01222 else
01223 {
01225
01226 unsigned long l = newDocEntry->GetReadLength();
01227 if ( l != 0 )
01228 {
01229 if ( l == 0xffffffff )
01230 {
01231 delim_mode_intern = true;
01232 }
01233 else
01234 {
01235 delim_mode_intern = false;
01236 }
01237 }
01238
01239 if ( (LoadMode & LD_NOSHADOWSEQ) && ! delim_mode_intern )
01240 {
01241
01242 if ( newDocEntry->GetGroup()%2 != 0 )
01243 {
01244 Fp->seekg( l, std::ios::cur);
01245 newDocEntry->Delete();
01246 continue;
01247 }
01248 }
01249 if ( (LoadMode & LD_NOSEQ) && ! delim_mode_intern )
01250 {
01251
01252 Fp->seekg( l, std::ios::cur);
01253 newDocEntry->Delete();
01254 continue;
01255 }
01256
01257 newSeqEntry = dynamic_cast<SeqEntry*>(newDocEntry);
01258
01259
01260 newSeqEntry->SetDelimitorMode( delim_mode_intern );
01261
01262
01263
01264
01265
01266 if ( set == this )
01267 {
01268 newSeqEntry->SetDepthLevel( 1 );
01269 }
01270
01271
01272
01273
01274
01275 else if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
01276 {
01277 newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 );
01278 }
01279
01280 if ( l != 0 )
01281 {
01282
01283 gdcmDebugMacro( "Entry in ParseSQ, delim " << delim_mode_intern
01284 << " at offset 0x(" << std::hex
01285 << newDocEntry->GetOffset() << ")");
01286
01287 bool res = ParseSQ( newSeqEntry,
01288 newDocEntry->GetOffset(),
01289 l, delim_mode_intern);
01290
01291 gdcmDebugMacro( "Exit from ParseSQ, delim " << delim_mode_intern << " -->return : " << res);
01292 }
01293 if ( !set->AddEntry( newSeqEntry ) )
01294 {
01295 gdcmWarningMacro( "in ParseDES : cannot add a SeqEntry "
01296 << newSeqEntry->GetKey()
01297 << " (at offset : 0x("
01298 << newSeqEntry->GetOffset() << ") )" );
01299 used = false;
01300 }
01301 else
01302 {
01303 newDocEntry->Delete();
01304 }
01305
01306
01307
01308 if ( !delim_mode )
01309 if ( ((long)(Fp->tellg())-offset) >= l_max)
01310
01311 {
01312 if ( !used )
01313 newDocEntry->Delete();
01314 break;
01315 }
01316 }
01317
01318 if ( !used )
01319 {
01320 newDocEntry->Delete();
01321 }
01322 first = false;
01323
01324 if (UnexpectedEOF)
01325 break;
01326 }
01327 gdcmDebugMacro( "Exit from ParseDES, delim-mode " << delim_mode );
01328 }
01329
01334 bool Document::ParseSQ( SeqEntry *seqEntry,
01335 long offset, long l_max, bool delim_mode)
01336 {
01337 int SQItemNumber = 0;
01338 bool dlm_mod;
01339 long offsetStartCurrentSQItem = offset;
01340
01341 while (true)
01342 {
01343
01344 DocEntry *newDocEntry = ReadNextDocEntry();
01345
01346 if ( !newDocEntry )
01347 {
01348
01349 gdcmWarningMacro("in ParseSQ : should never get here!");
01350 UnexpectedEOF = true;
01351 return false;
01352 }
01353 if ( delim_mode )
01354 {
01355 if ( newDocEntry->IsSequenceDelimitor() )
01356 {
01357 seqEntry->SetDelimitationItem( newDocEntry );
01358 newDocEntry->Delete();
01359 break;
01360 }
01361 }
01362 else
01363 {
01364 if ( ((long)(Fp->tellg())-offset) >= l_max)
01365 {
01366 newDocEntry->Delete();
01367 break;
01368 }
01369 }
01370
01371 SQItem *itemSQ = SQItem::New( seqEntry->GetDepthLevel() );
01372 unsigned int l = newDocEntry->GetReadLength();
01373
01374 if ( l == 0xffffffff )
01375 {
01376 dlm_mod = true;
01377 }
01378 else
01379 {
01380 dlm_mod = false;
01381 }
01382
01383
01384
01385 Fp->seekg(offsetStartCurrentSQItem, std::ios::beg);
01386 ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod);
01387 offsetStartCurrentSQItem = Fp->tellg();
01388
01389 seqEntry->AddSQItem( itemSQ, SQItemNumber );
01390 itemSQ->Delete();
01391 newDocEntry->Delete();
01392 SQItemNumber++;
01393
01394 if ( !delim_mode && (offsetStartCurrentSQItem-offset ) >= l_max )
01395 {
01396 break;
01397 }
01398 }
01399 return true;
01400 }
01401
01408 DocEntry *Document::Backtrack(DocEntry *docEntry)
01409 {
01410
01411
01412 docEntry->Delete();
01413
01414
01415 uint16_t group = PreviousDocEntry->GetGroup();
01416 uint16_t elem = PreviousDocEntry->GetElement();
01417 uint32_t lgt = PreviousDocEntry->GetLength();
01418 long offset = PreviousDocEntry->GetOffset();
01419
01420 gdcmDebugMacro( "Backtrack :" << std::hex << group
01421 << "|" << elem
01422 << " at offset 0x(" <<offset << ")" );
01423 RemoveEntry( PreviousDocEntry );
01424
01425
01426 DocEntry *newEntry = NewSeqEntry(group, elem);
01427 newEntry->SetLength(lgt);
01428 newEntry->SetOffset(offset);
01429
01430
01431
01432 Fp->seekg(offset, std::ios::beg);
01433 return newEntry;
01434 }
01435
01442 void Document::LoadDocEntry(DocEntry *entry, bool forceLoad)
01443 {
01444 uint16_t group = entry->GetGroup();
01445 uint16_t elem = entry->GetElement();
01446 const VRKey &vr = entry->GetVR();
01447 uint32_t length = entry->GetLength();
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458 if ( (group == 0xfffe && elem != 0x0000 ) || vr == "SQ" )
01459 {
01460
01461 return;
01462 }
01463
01464 DataEntry *dataEntryPtr = dynamic_cast< DataEntry* >(entry);
01465 if( !dataEntryPtr )
01466 {
01467 return;
01468 }
01469
01470
01471 if ( length == 0 )
01472 {
01473 dataEntryPtr->SetBinArea(NULL,true);
01474 return;
01475 }
01476
01477
01478
01479
01480 if (!forceLoad)
01481 {
01482 if (length > MaxSizeLoadEntry)
01483 {
01484 dataEntryPtr->SetBinArea(NULL,true);
01485 dataEntryPtr->SetState(DataEntry::STATE_NOTLOADED);
01486
01487
01488
01489
01490 return;
01491 }
01492 }
01493
01500
01501 LoadEntryBinArea(dataEntryPtr);
01502 }
01503
01508 void Document::FindDocEntryLength( DocEntry *entry )
01509 throw ( FormatError )
01510 {
01511 const VRKey &vr = entry->GetVR();
01512 uint16_t length16;
01513 if ( Filetype == ExplicitVR && !entry->IsImplicitVR() )
01514 {
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525 if ( vr == "OB" || vr == "OW" || vr == "SQ" || vr == "UT"
01526 || vr == "UN" || changeFromUN == true)
01527 {
01528 changeFromUN = false;
01529
01530
01531
01532
01533
01534 uint32_t length32 = ReadInt32();
01535 CurrentOffsetPosition+=4;
01536 if ( (vr == "OB" || vr == "OW") && length32 == 0xffffffff )
01537 {
01538 uint32_t lengthOB;
01539 try
01540 {
01541 lengthOB = FindDocEntryLengthOBOrOW();
01542 }
01543 catch ( FormatUnexpected )
01544 {
01545
01546
01547
01548
01549
01550 gdcmWarningMacro( " Computing the length failed for " <<
01551 entry->GetKey() <<" in " <<GetFileName());
01552
01553 long currentPosition = Fp->tellg();
01554 Fp->seekg(0L,std::ios::end);
01555
01556 long lengthUntilEOF = (long)(Fp->tellg())-currentPosition;
01557 Fp->seekg(currentPosition, std::ios::beg);
01558
01559 entry->SetReadLength(lengthUntilEOF);
01560 entry->SetLength(lengthUntilEOF);
01561 return;
01562 }
01563 entry->SetReadLength(lengthOB);
01564 entry->SetLength(lengthOB);
01565 return;
01566 }
01567 FixDocEntryFoundLength(entry, length32);
01568 return;
01569 }
01570
01571
01572 length16 = GetInt16();
01573
01574
01575 if ( length16 == 0xffff)
01576 {
01577 length16 = 0;
01578 }
01579 FixDocEntryFoundLength( entry, (uint32_t)length16 );
01580 return;
01581 }
01582 else
01583 {
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596 FixDocEntryFoundLength( entry, GetInt32() );
01597 return;
01598 }
01599 }
01600
01606 uint32_t Document::FindDocEntryLengthOBOrOW()
01607 throw( FormatUnexpected )
01608 {
01609
01610
01611 long positionOnEntry = Fp->tellg();
01612
01613 bool foundSequenceDelimiter = false;
01614 uint32_t totalLength = 0;
01615
01616 while ( !foundSequenceDelimiter )
01617 {
01618 uint16_t group;
01619 uint16_t elem;
01620
01621 try
01622 {
01623
01624
01625 ReadBegBuffer(4);
01626 }
01627 catch ( FormatError )
01628 {
01629 throw FormatError("Unexpected end of file encountered during ",
01630 "Document::FindDocEntryLengthOBOrOW()");
01631 }
01632 group = GetInt16();
01633 elem = GetInt16();
01634
01635
01636 totalLength += 4;
01637 if ( group != 0xfffe || ( ( elem != 0xe0dd ) && ( elem != 0xe000 ) ) )
01638 {
01639 gdcmWarningMacro(
01640 "Neither an Item tag nor a Sequence delimiter tag on :"
01641 << std::hex << group << " , " << elem
01642 << ")" );
01643
01644 Fp->seekg(positionOnEntry, std::ios::beg);
01645 throw FormatUnexpected(
01646 "Neither an Item tag nor a Sequence delimiter tag.");
01647 }
01648 if ( elem == 0xe0dd )
01649 {
01650 foundSequenceDelimiter = true;
01651 }
01652 uint32_t itemLength = ReadInt32();
01653
01654 totalLength += itemLength + 4;
01655 SkipBytes(itemLength);
01656
01657 if ( foundSequenceDelimiter )
01658 {
01659 break;
01660 }
01661 }
01662 Fp->seekg( positionOnEntry, std::ios::beg);
01663 return totalLength;
01664 }
01665
01670 VRKey Document::FindDocEntryVR()
01671 {
01672 if ( Filetype != ExplicitVR )
01673 {
01674 return GDCM_VRUNKNOWN;
01675 }
01676
01677
01678 if ( CurrentGroup == 0xfffe )
01679 return GDCM_VRUNKNOWN;
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696 VRKey vr;
01697
01698 vr[0] = *PtrBegBuffer++;
01699 vr[1] = *PtrBegBuffer++;
01700
01701
01702 if ( !Global::GetVR()->IsValidVR(vr) )
01703 {
01704
01705
01706
01707
01708
01709
01710
01711
01712 gdcmWarningMacro( "Unknown VR " << std::hex << "0x("
01713 << (unsigned int)vr[0] << "|" << (unsigned int)vr[1]
01714 << ")"
01715 << " at offset : 0x(" << CurrentOffsetPosition-4<< ") for group " << CurrentGroup
01716 );
01717
01718
01719
01720
01721 PtrBegBuffer-=2;
01722 return GDCM_VRUNKNOWN;
01723 }
01724 return vr;
01725 }
01726
01735 bool Document::CheckDocEntryVR(const VRKey &vr)
01736 {
01737 return Global::GetVR()->IsValidVR(vr);
01738 }
01739
01744 void Document::SkipDocEntry(DocEntry *entry)
01745 {
01746 SkipBytes(entry->GetLength());
01747 }
01748
01753 void Document::SkipToNextDocEntry(DocEntry *currentDocEntry)
01754 {
01755 long l = currentDocEntry->GetReadLength();
01756 if ( l == -1 )
01757
01758 return;
01759 Fp->seekg((size_t)(currentDocEntry->GetOffset()), std::ios::beg);
01760 if (currentDocEntry->GetGroup() != 0xfffe)
01761 {
01762 Fp->seekg( l,std::ios::cur);
01763 }
01764 }
01765
01773 void Document::FixDocEntryFoundLength(DocEntry *entry,
01774 uint32_t foundLength)
01775 {
01776 entry->SetReadLength( foundLength );
01777
01778 if ( foundLength == 0xffffffff)
01779 {
01780
01781
01782 entry->SetLength(0);
01783 return;
01784 }
01785
01786 uint16_t gr = entry->GetGroup();
01787 uint16_t elem = entry->GetElement();
01788
01789 if ( foundLength % 2)
01790 {
01791 gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength
01792 << " in x(" << std::hex << gr << "," << elem <<")");
01793 }
01794
01796
01797
01798
01799
01800
01801 if ( foundLength == 13)
01802 {
01803
01804 if ( gr != 0x0008 || ( elem != 0x0070 && elem != 0x0080 ) )
01805 {
01806 foundLength = 10;
01807 entry->SetReadLength(10);
01808 }
01809 }
01810
01812
01813
01814
01815 else if ( gr == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) )
01816 {
01817
01818
01819 if( foundLength == 6 )
01820 {
01821 gdcmWarningMacro( "Replacing Length from 6 into 4" );
01822 foundLength = 4;
01823 entry->SetReadLength(4);
01824 }
01825 else if ( foundLength%4 )
01826 {
01827 gdcmErrorMacro( "This looks like to a buggy Siemens DICOM file."
01828 "The length of this tag seems to be wrong" );
01829 }
01830 }
01831
01832 else if ( entry->GetVR() == "SQ" )
01833 {
01834 foundLength = 0;
01835 }
01836
01838
01839
01840 else if ( gr == 0xfffe )
01841 {
01842
01843
01844
01845 if ( elem != 0x0000 )
01846 {
01847 foundLength = 0;
01848 }
01849 else
01850 {
01851 foundLength=12;
01852 }
01853 }
01854 entry->SetLength(foundLength);
01855 }
01856
01863 bool Document::IsDocEntryAnInteger(DocEntry *entry)
01864 {
01865 uint16_t elem = entry->GetElement();
01866 uint16_t group = entry->GetGroup();
01867 const VRKey &vr = entry->GetVR();
01868 uint32_t length = entry->GetLength();
01869
01870
01871
01872
01873 if ( elem == 0 )
01874 {
01875 if ( length == 4 )
01876 {
01877 return true;
01878 }
01879 else
01880 {
01881
01882
01883
01884
01885
01886
01887
01888 long filePosition = Fp->tellg();
01889 (void)filePosition;
01890 gdcmWarningMacro( "Erroneous Group Length element length on : ("
01891 << std::hex << group << " , " << elem
01892 << ") -before- position x(" << filePosition << ")"
01893 << "lgt : " << length );
01894 }
01895 }
01896
01897 if ( vr == "UL" || vr == "US" || vr == "SL" || vr == "SS" )
01898 {
01899 return true;
01900 }
01901 return false;
01902 }
01903
01912 bool Document::CheckSwap()
01913 {
01914 uint32_t s32;
01915 uint16_t s16;
01916
01917 char deb[256];
01918
01919
01920
01921 bool net2host = Util::IsCurrentProcessorBigEndian();
01922
01923
01924
01925 Fp->read(deb, 256);
01926
01927 char *entCur = deb + 128;
01928 if ( memcmp(entCur, "DICM", (size_t)4) == 0 )
01929 {
01930 gdcmDebugMacro( "Looks like DICOM Version3 (preamble + DCM)" );
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946 entCur = deb + 136;
01947
01948
01949
01950
01951
01952 if ( memcmp(entCur, "UL", (size_t)2) == 0 ||
01953 memcmp(entCur, "OB", (size_t)2) == 0 ||
01954 memcmp(entCur, "UI", (size_t)2) == 0 ||
01955 memcmp(entCur, "CS", (size_t)2) == 0 )
01956
01957
01958
01959
01960 {
01961 Filetype = ExplicitVR;
01962 gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
01963 }
01964 else
01965 {
01966 Filetype = ImplicitVR;
01967 gdcmWarningMacro( "Group 0002 :Not an explicit Value Representation;"
01968 << "Looks like a bugged Header!");
01969 }
01970
01971
01972
01973 if ( net2host )
01974 {
01975 SwapCode = 4321;
01976 gdcmDebugMacro( "HostByteOrder != NetworkByteOrder, SwapCode = 4321");
01977 }
01978 else
01979 {
01980 SwapCode = 1234;
01981 gdcmDebugMacro( "HostByteOrder = NetworkByteOrder, SwapCode = 1234");
01982 }
01983
01984
01985
01986
01987 Fp->seekg ( 132L, std::ios::beg);
01988 CurrentOffsetPosition = 132;
01989 return true;
01990 }
01991
01992
01993
01994
01995
01996 gdcmWarningMacro( "Not a Kosher DICOM Version3 file (no preamble)");
01997
01998 Fp->seekg(0, std::ios::beg);
01999 CurrentOffsetPosition = 0;
02000
02001
02002
02003
02004 s16 = *((uint16_t *)(deb));
02005 SwapCode = 0;
02006 switch ( s16 )
02007 {
02008 case 0x0002 :
02009 SwapCode = 1234;
02010 entCur = deb + 4;
02011 break;
02012 case 0x0200 :
02013 SwapCode = 4321;
02014 entCur = deb + 6;
02015 }
02016
02017 if ( SwapCode != 0 )
02018 {
02019 if ( memcmp(entCur, "UL", (size_t)2) == 0 ||
02020 memcmp(entCur, "OB", (size_t)2) == 0 ||
02021 memcmp(entCur, "UI", (size_t)2) == 0 ||
02022 memcmp(entCur, "SH", (size_t)2) == 0 ||
02023 memcmp(entCur, "AE", (size_t)2) == 0 ||
02024 memcmp(entCur, "OB", (size_t)2) == 0 )
02025 {
02026 Filetype = ExplicitVR;
02027
02028 gdcmDebugMacro( "Group 0002 : Explicit Value Representation");
02029 return true;
02030 }
02031 }
02032
02033
02034
02035
02036
02037
02038
02039 entCur = deb + 4;
02040
02041
02042
02043 s32 = *((uint32_t *)(entCur));
02044 switch( s32 )
02045 {
02046 case 0x00040000 :
02047 SwapCode = 3412;
02048 Filetype = ACR;
02049 return true;
02050 case 0x04000000 :
02051 SwapCode = 4321;
02052 Filetype = ACR;
02053 return true;
02054 case 0x00000400 :
02055 SwapCode = 2143;
02056 Filetype = ACR;
02057 return true;
02058 case 0x00000004 :
02059 SwapCode = 1234;
02060 Filetype = ACR;
02061 return true;
02062 default :
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078 s16 = *((uint16_t *)(deb));
02079
02080 gdcmDebugMacro("not a DicomV3 nor a 'clean' ACR/NEMA;"
02081 << " (->despaired wild guesses !)");
02082 switch ( s16 )
02083 {
02084 case 0x0001 :
02085 case 0x0002 :
02086 case 0x0003 :
02087 case 0x0004 :
02088 case 0x0005 :
02089 case 0x0006 :
02090 case 0x0007 :
02091 case 0x0008 :
02092 case 0x0028 :
02093 SwapCode = 1234;
02094 Filetype = ACR;
02095 return true;
02096 case 0x0100 :
02097 case 0x0200 :
02098 case 0x0300 :
02099 case 0x0400 :
02100 case 0x0500 :
02101 case 0x0600 :
02102 case 0x0700 :
02103 case 0x0800 :
02104 case 0x2800 :
02105 SwapCode = 4321;
02106 Filetype = ACR;
02107 return true;
02108 default :
02109
02110 s16 = *((uint16_t *)(deb));
02111 if (s16 != 0x0000)
02112 return false;
02113 s16 = *((uint16_t *)(deb+2));
02114
02115 Fp->seekg ( 0L, std::ios::beg);
02116 CurrentOffsetPosition = 0;
02117 switch(s16)
02118
02119
02120 {
02121 case 0x0004 :
02122 SwapCode = 1234;
02123 break;
02124 case 0x0400 :
02125 SwapCode = 3412;
02126 break;
02127 default:
02128 gdcmWarningMacro("ACR/NEMA unfound swap info (Hopeless !)");
02129 Filetype = Unknown;
02130 return false;
02131 }
02132
02133
02134 const char VRvalues[] = "AEASCSDADSFLFDISLOLTPNSHSLSSSTTMUIULUSUTOBOWOFATUNSQ";
02135 int nbVal = 26;
02136 const char *pt = VRvalues;
02137 for (int i=0;i<nbVal;i++)
02138 {
02139 if(*(deb+4) == *pt++)
02140 if(*(deb+5) == *pt++) {
02141 Filetype = ExplicitVR;
02142 return true;
02143 }
02144
02145 }
02146 Filetype = ImplicitVR;
02147 return true;
02148 }
02149 }
02150 }
02151
02155 void Document::SwitchByteSwapCode()
02156 {
02157 gdcmDebugMacro( "Switching Byte Swap code from "<< SwapCode
02158 << " at: 0x" << std::hex << Fp->tellg() );
02159 if ( SwapCode == 1234 )
02160 {
02161 SwapCode = 4321;
02162 }
02163 else if ( SwapCode == 4321 )
02164 {
02165 SwapCode = 1234;
02166 }
02167 else if ( SwapCode == 3412 )
02168 {
02169 SwapCode = 2143;
02170 }
02171 else if ( SwapCode == 2143 )
02172 {
02173 SwapCode = 3412;
02174 }
02175 gdcmDebugMacro( " Into: "<< SwapCode );
02176 }
02177
02182 void Document::SetMaxSizeLoadEntry(long newSize)
02183 {
02184 if ( newSize < 0 )
02185 {
02186 return;
02187 }
02188 if ((uint32_t)newSize >= (uint32_t)0xffffffff )
02189 {
02190 MaxSizeLoadEntry = 0xffffffff;
02191 return;
02192 }
02193 MaxSizeLoadEntry = newSize;
02194 }
02195
02203 DocEntry *Document::ReadNextDocEntry()
02204 {
02205 try
02206 {
02207 ReadBegBuffer(8);
02208
02209
02210 }
02211 catch ( FormatError )
02212 {
02213
02214
02215 return 0;
02216 }
02217
02218 changeFromUN = false;
02219 CurrentGroup = GetInt16();
02220 CurrentElem = GetInt16();
02221
02222
02223 if ( HasDCMPreamble )
02224 {
02225 if ( !Group0002Parsed && CurrentGroup != 0x0002)
02226 HandleOutOfGroup0002(CurrentGroup, CurrentElem);
02227 else
02228
02229 HandleBrokenEndian(CurrentGroup, CurrentElem);
02230 }
02231
02232 VRKey vr = FindDocEntryVR();
02233 VRKey realVR = vr;
02234
02235 if ( vr == GDCM_VRUNKNOWN )
02236 {
02237 if ( CurrentElem == 0x0000 )
02238 {
02239 realVR = "UL";
02240 }
02241 else if (CurrentGroup == 0xfffe)
02242 {
02243 realVR = "UL";
02244 }
02245
02246
02247
02248
02249
02250 else if (CurrentGroup%2 == 1 )
02251 {
02252 if (CurrentElem >= 0x0010 && CurrentElem <=0x00ff )
02253
02254
02255
02256 realVR = "LO";
02257
02258
02259
02260
02261
02262 else if ( CurrentElem == 0x0001)
02263 realVR = "UL";
02264 }
02265
02266 else
02267 {
02268 DictEntry *dictEntry = GetDictEntry(CurrentGroup,CurrentElem);
02269 if ( dictEntry )
02270 {
02271 realVR = dictEntry->GetVR();
02272 dictEntry->Unregister();
02273 }
02274 }
02275 }
02276
02277
02278
02279 else if (vr == "UN")
02280 {
02281 DictEntry *dictEntry = GetDictEntry(CurrentGroup,CurrentElem);
02282 if ( dictEntry )
02283 {
02284 realVR = dictEntry->GetVR();
02285 dictEntry->Unregister();
02286
02287
02288 changeFromUN=true;
02293 }
02294 }
02295
02296
02297 DocEntry *newEntry;
02298
02299 if (realVR == "SQ")
02300 {
02301 newEntry = NewSeqEntry(CurrentGroup, CurrentElem);
02302 }
02303 else
02304 {
02305 newEntry = NewDataEntry(CurrentGroup, CurrentElem, realVR);
02306 static_cast<DataEntry *>(newEntry)->SetState(DataEntry::STATE_NOTLOADED);
02307 }
02308
02309 if ( vr == GDCM_VRUNKNOWN )
02310 {
02311 if ( Filetype == ExplicitVR )
02312 {
02313
02314
02315
02316
02317 if (CurrentGroup != 0xfffe)
02318 {
02319 int offset = Fp->tellg();
02320
02321 gdcmWarningMacro("Entry (" << newEntry->GetKey() << ") at x("
02322 << offset << ") should be Explicit VR");
02323 }
02324 }
02325 newEntry->SetImplicitVR();
02326 }
02327
02328 try
02329 {
02330 FindDocEntryLength(newEntry);
02331 }
02332 catch ( FormatError )
02333 {
02334
02335 newEntry->Delete();
02336 return 0;
02337 }
02338
02339 newEntry->SetOffset(Fp->tellg());
02340 return newEntry;
02341 }
02342
02349 void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
02350 {
02351
02352
02353
02354
02355
02356
02357 if ((group == 0x3f3f) && (elem == 0x3f00))
02358 {
02359
02360 gdcmDebugMacro( " delimiter 0x3f3f found." );
02361
02362 group = 0xfffe;
02363 elem = 0xe000;
02364 return;
02365 }
02366
02367
02368
02369
02370 static int reversedEndian = 0;
02371
02372 if ((group == 0xfeff) && (elem == 0x00e0))
02373 {
02374
02375 gdcmDebugMacro( "Start endian swap mark found." );
02376 reversedEndian++;
02377 SwitchByteSwapCode();
02378
02379 group = 0xfffe;
02380 elem = 0xe000;
02381 }
02382 else if (group == 0xfffe && elem == 0xe00d && reversedEndian)
02383 {
02384
02385 gdcmDebugMacro( "End of reversed endian." );
02386 reversedEndian--;
02387 SwitchByteSwapCode();
02388 }
02389 else if (group == 0xfeff && elem == 0xdde0)
02390 {
02391
02392
02393
02394
02395
02396 gdcmWarningMacro( "Should never get here! reversed Sequence Terminator!" );
02397
02398 group = 0xfffe;
02399 elem = 0xe0dd;
02400 }
02401 else if (group == 0xfffe && elem == 0xe0dd)
02402 {
02403 gdcmDebugMacro( "Straight Sequence Terminator." );
02404 }
02405 }
02406
02412 void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
02413 {
02414
02415
02416
02417 Group0002Parsed = true;
02418
02419
02420
02421 std::string ts = GetTransferSyntax();
02422 TS::SpecialType s = Global::GetTS()->GetSpecialTransferSyntax(ts);
02423
02424
02425
02426
02427 if ( s == TS::ImplicitVRLittleEndian
02428 ||
02429 s == TS::ImplicitVRBigEndianPrivateGE
02430 )
02431 {
02432 Filetype = ImplicitVR;
02433 }
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458 if ( !( (group >= 0x0001 && group <= 0x0008) || group == 0x0028 ) )
02459 {
02460
02461 SwitchByteSwapCode();
02462 group = SwapShort(group);
02463 elem = SwapShort(elem);
02464
02465 gdcmDebugMacro("Transfer Syntax Name = ["
02466 << GetTransferSyntaxName() << "]" );
02467 }
02468
02470
02471 if ( s == TS::DeflatedExplicitVRLittleEndian)
02472 {
02473 gdcmWarningMacro("Transfer Syntax ["
02474 << GetTransferSyntaxName() << "] :"
02475 << " not yet dealt with ");
02476 return;
02477 }
02478
02479
02480
02481
02482 if ( ts == GDCM_UNKNOWN )
02483 {
02484 gdcmDebugMacro("True DICOM File, with NO Transfer Syntax (?!) " );
02485 return;
02486 }
02487
02488 if ( !Global::GetTS()->IsTransferSyntax(ts) )
02489 {
02490 gdcmWarningMacro("True DICOM File, with illegal Transfer Syntax: ["
02491 << ts << "]");
02492 return;
02493 }
02494 }
02495
02496
02497
02498
02499
02500 }