00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "gdcmDocument.h"
00020 #include "gdcmValEntry.h"
00021 #include "gdcmBinEntry.h"
00022 #include "gdcmSeqEntry.h"
00023 #include "gdcmGlobal.h"
00024 #include "gdcmUtil.h"
00025 #include "gdcmDebug.h"
00026 #include "gdcmTS.h"
00027 #include "gdcmDictSet.h"
00028 #include "gdcmDocEntrySet.h"
00029 #include "gdcmSQItem.h"
00030
00031 #include <vector>
00032 #include <iomanip>
00033 #include <fstream>
00034
00035
00036 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MINGW32__)
00037 #include <winsock.h>
00038 #endif
00039
00040 #ifdef CMAKE_HAVE_NETINET_IN_H
00041 #include <netinet/in.h>
00042 #endif
00043
00044 namespace gdcm
00045 {
00046
00047
00048
00049
00050
00051 const unsigned int Document::MAX_SIZE_LOAD_ELEMENT_VALUE = 0xfff;
00052 const unsigned int Document::MAX_SIZE_PRINT_ELEMENT_VALUE = 0x7fffffff;
00053
00054
00055
00056
00061 Document::Document( std::string const &filename )
00062 :ElementSet(-1)
00063 {
00064 SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
00065 Filename = filename;
00066 Initialize();
00067
00068 Fp = 0;
00069 if ( !OpenFile() )
00070 {
00071 return;
00072 }
00073
00074 Group0002Parsed = false;
00075
00076 gdcmWarningMacro( "Starting parsing of file: " << Filename.c_str());
00077
00078 Fp->seekg(0, std::ios::end);
00079 long lgt = Fp->tellg();
00080
00081 Fp->seekg(0, std::ios::beg);
00082
00083 CheckSwap();
00084 long beg = Fp->tellg();
00085 lgt -= beg;
00086
00087 ParseDES( this, beg, lgt, false);
00088
00089 Fp->seekg( 0, std::ios::beg);
00090
00091
00092
00093 std::string PhotometricInterpretation = GetEntryValue(0x0028,0x0004);
00094 if( PhotometricInterpretation == "PALETTE COLOR " )
00095 {
00096 LoadEntryBinArea(0x0028,0x1200);
00112 LoadEntryBinArea(0x0028,0x1201);
00113 LoadEntryBinArea(0x0028,0x1202);
00114 LoadEntryBinArea(0x0028,0x1203);
00115
00116
00117 LoadEntryBinArea(0x0028,0x1221);
00118
00119 LoadEntryBinArea(0x0028,0x1222);
00120
00121 LoadEntryBinArea(0x0028,0x1223);
00122 }
00123
00124 LoadEntryBinArea(0x0028,0x3006);
00125
00126 CloseFile();
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 std::string RecCode;
00139 RecCode = GetEntryValue(0x0008, 0x0010);
00140 if (RecCode == "ACRNEMA_LIBIDO_1.1" ||
00141 RecCode == "CANRME_AILIBOD1_1." )
00142
00143 {
00144 Filetype = ACR_LIBIDO;
00145 std::string rows = GetEntryValue(0x0028, 0x0010);
00146 std::string columns = GetEntryValue(0x0028, 0x0011);
00147 SetValEntry(columns, 0x0028, 0x0010);
00148 SetValEntry(rows , 0x0028, 0x0011);
00149 }
00150
00151 }
00152
00157 Document::Document()
00158 :ElementSet(-1)
00159 {
00160 Fp = 0;
00161
00162 SetMaxSizeLoadEntry(MAX_SIZE_LOAD_ELEMENT_VALUE);
00163 Initialize();
00164 SwapCode = 1234;
00165 Filetype = ExplicitVR;
00166 Group0002Parsed = false;
00167 }
00168
00172 Document::~Document ()
00173 {
00174 RefPubDict = NULL;
00175 RefShaDict = NULL;
00176 }
00177
00178
00179
00183 Dict *Document::GetPubDict()
00184 {
00185 return RefPubDict;
00186 }
00187
00191 Dict *Document::GetShaDict()
00192 {
00193 return RefShaDict;
00194 }
00195
00200 bool Document::SetShaDict(Dict *dict)
00201 {
00202 RefShaDict = dict;
00203 return !RefShaDict;
00204 }
00205
00210 bool Document::SetShaDict(DictKey const &dictName)
00211 {
00212 RefShaDict = Global::GetDicts()->GetDict(dictName);
00213 return !RefShaDict;
00214 }
00215
00224 bool Document::IsReadable()
00225 {
00226 if( Filetype == Unknown)
00227 {
00228 gdcmWarningMacro( "Wrong filetype");
00229 return false;
00230 }
00231
00232 if ( IsEmpty() )
00233 {
00234 gdcmWarningMacro( "No tag in internal hash table.");
00235 return false;
00236 }
00237
00238 return true;
00239 }
00240
00245 bool Document::IsDicomV3()
00246 {
00247
00248
00249
00250
00251 return GetDocEntry(0x0002, 0x0010) != NULL;
00252 }
00253
00259 bool Document::IsPapyrus()
00260 {
00261
00262 DocEntry *e = GetDocEntry(0x0041, 0x1050);
00263 if ( !e )
00264 return false;
00265
00266 if ( !dynamic_cast<SeqEntry*>(e) )
00267 return false;
00268 return true;
00269 }
00270
00276 FileType Document::GetFileType()
00277 {
00278 return Filetype;
00279 }
00280
00287 std::string Document::GetTransferSyntax()
00288 {
00289 DocEntry *entry = GetDocEntry(0x0002, 0x0010);
00290 if ( !entry )
00291 {
00292 return GDCM_UNKNOWN;
00293 }
00294
00295
00296
00297 LoadDocEntrySafe(entry);
00298 if (ValEntry *valEntry = dynamic_cast< ValEntry* >(entry) )
00299 {
00300 std::string transfer = valEntry->GetValue();
00301
00302
00303
00304 if ( transfer.length() == 0 )
00305 {
00306
00307 return GDCM_UNKNOWN;
00308 }
00309 while ( !isdigit((unsigned char)transfer[transfer.length()-1]) )
00310 {
00311 transfer.erase(transfer.length()-1, 1);
00312 }
00313 return transfer;
00314 }
00315 return GDCM_UNKNOWN;
00316 }
00317
00322 std::string Document::GetTransferSyntaxName()
00323 {
00324
00325 std::string transferSyntax = GetEntryValue(0x0002,0x0010);
00326
00327 if ( (transferSyntax.find(GDCM_NOTLOADED) < transferSyntax.length()) )
00328 {
00329 gdcmErrorMacro( "Transfer Syntax not loaded. " << std::endl
00330 << "Better you increase MAX_SIZE_LOAD_ELEMENT_VALUE" );
00331 return "Uncompressed ACR-NEMA";
00332 }
00333 if ( transferSyntax == GDCM_UNFOUND )
00334 {
00335 gdcmWarningMacro( "Unfound Transfer Syntax (0002,0010)");
00336 return "Uncompressed ACR-NEMA";
00337 }
00338
00339
00340 const TSKey &tsName = Global::GetTS()->GetValue( transferSyntax );
00341
00342
00343 return tsName;
00344 }
00345
00346
00351 uint16_t Document::SwapShort(uint16_t a)
00352 {
00353 if ( SwapCode == 4321 || SwapCode == 2143 )
00354 {
00355 a = ((( a << 8 ) & 0xff00 ) | (( a >> 8 ) & 0x00ff ) );
00356 }
00357 return a;
00358 }
00359
00365 uint32_t Document::SwapLong(uint32_t a)
00366 {
00367 switch (SwapCode)
00368 {
00369 case 1234 :
00370 break;
00371 case 4321 :
00372 a=( ((a<<24) & 0xff000000) | ((a<<8) & 0x00ff0000) |
00373 ((a>>8) & 0x0000ff00) | ((a>>24) & 0x000000ff) );
00374 break;
00375 case 3412 :
00376 a=( ((a<<16) & 0xffff0000) | ((a>>16) & 0x0000ffff) );
00377 break;
00378 case 2143 :
00379 a=( ((a<< 8) & 0xff00ff00) | ((a>>8) & 0x00ff00ff) );
00380 break;
00381 default :
00382 gdcmErrorMacro( "Unset swap code:" << SwapCode );
00383 a = 0;
00384 }
00385 return a;
00386 }
00387
00388
00389
00395 std::ifstream *Document::OpenFile()
00396 {
00397 HasDCMPreamble = false;
00398 if (Filename.length() == 0)
00399 {
00400 return 0;
00401 }
00402
00403 if(Fp)
00404 {
00405 gdcmWarningMacro( "File already open: " << Filename.c_str());
00406 CloseFile();
00407 }
00408
00409 Fp = new std::ifstream(Filename.c_str(), std::ios::in | std::ios::binary);
00410 if( ! *Fp )
00411 {
00412 gdcmDebugMacro( "Cannot open file: " << Filename.c_str());
00413 delete Fp;
00414 Fp = 0;
00415 return 0;
00416 }
00417
00418 uint16_t zero = 0;
00419 Fp->read((char*)&zero, (size_t)2);
00420 if( Fp->eof() )
00421 {
00422 CloseFile();
00423 return 0;
00424 }
00425
00426
00427 if(
00428 zero == 0x0001 || zero == 0x0100 || zero == 0x0002 || zero == 0x0200 ||
00429 zero == 0x0003 || zero == 0x0300 || zero == 0x0004 || zero == 0x0400 ||
00430 zero == 0x0005 || zero == 0x0500 || zero == 0x0006 || zero == 0x0600 ||
00431 zero == 0x0007 || zero == 0x0700 || zero == 0x0008 || zero == 0x0800 )
00432 {
00433 std::string msg
00434 = Util::Format("ACR/DICOM with no preamble: (%04x)\n", zero);
00435 gdcmWarningMacro( msg.c_str() );
00436 return Fp;
00437 }
00438
00439
00440 Fp->seekg(126L, std::ios::cur);
00441 char dicm[4] = {' ',' ',' ',' '};
00442 Fp->read(dicm, (size_t)4);
00443 if( Fp->eof() )
00444 {
00445 CloseFile();
00446 return 0;
00447 }
00448 if( memcmp(dicm, "DICM", 4) == 0 )
00449 {
00450 HasDCMPreamble = true;
00451 return Fp;
00452 }
00453
00454 CloseFile();
00455 gdcmWarningMacro( "Not DICOM/ACR (missing preamble)" << Filename.c_str());
00456
00457 return 0;
00458 }
00459
00464 bool Document::CloseFile()
00465 {
00466 if( Fp )
00467 {
00468 Fp->close();
00469 delete Fp;
00470 Fp = 0;
00471 }
00472 return true;
00473 }
00474
00482 void Document::WriteContent(std::ofstream *fp, FileType filetype)
00483 {
00484
00485
00486
00487
00488
00489
00490 if ( filetype == ImplicitVR || filetype == ExplicitVR )
00491 {
00492
00493 char filePreamble[128];
00494 memset(filePreamble, 0, 128);
00495 fp->write(filePreamble, 128);
00496 fp->write("DICM", 4);
00497 }
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 ElementSet::WriteContent(fp, filetype);
00512 }
00513
00514
00515
00522 void Document::LoadEntryBinArea(uint16_t group, uint16_t elem)
00523 {
00524
00525 DocEntry *docElement = GetDocEntry(group, elem);
00526 if ( !docElement )
00527 return;
00528
00529 BinEntry *binElement = dynamic_cast<BinEntry *>(docElement);
00530 if( !binElement )
00531 return;
00532
00533 LoadEntryBinArea(binElement);
00534 }
00535
00541 void Document::LoadEntryBinArea(BinEntry *elem)
00542 {
00543 if(elem->GetBinArea())
00544 return;
00545
00546 bool openFile = !Fp;
00547 if(openFile)
00548 OpenFile();
00549
00550 size_t o =(size_t)elem->GetOffset();
00551 Fp->seekg(o, std::ios::beg);
00552
00553 size_t l = elem->GetLength();
00554 uint8_t *a = new uint8_t[l];
00555 if( !a )
00556 {
00557 gdcmWarningMacro( "Cannot allocate BinEntry content");
00558 return;
00559 }
00560
00562 Fp->read((char*)a, l);
00563 if( Fp->fail() || Fp->eof())
00564 {
00565 delete[] a;
00566 return;
00567 }
00568
00569 elem->SetBinArea(a);
00570
00571 if(openFile)
00572 CloseFile();
00573 }
00574
00581 void Document::LoadDocEntrySafe(DocEntry *entry)
00582 {
00583 if(Fp)
00584 {
00585 long PositionOnEntry = Fp->tellg();
00586 LoadDocEntry(entry);
00587 Fp->seekg(PositionOnEntry, std::ios::beg);
00588 }
00589 }
00590
00598 bool Document::operator<(Document &document)
00599 {
00600
00601 std::string s1 = GetEntryValue(0x0010,0x0010);
00602 std::string s2 = document.GetEntryValue(0x0010,0x0010);
00603 if(s1 < s2)
00604 {
00605 return true;
00606 }
00607 else if( s1 > s2 )
00608 {
00609 return false;
00610 }
00611 else
00612 {
00613
00614 s1 = GetEntryValue(0x0010,0x0020);
00615 s2 = document.GetEntryValue(0x0010,0x0020);
00616 if ( s1 < s2 )
00617 {
00618 return true;
00619 }
00620 else if ( s1 > s2 )
00621 {
00622 return false;
00623 }
00624 else
00625 {
00626
00627 s1 = GetEntryValue(0x0020,0x000d);
00628 s2 = document.GetEntryValue(0x0020,0x000d);
00629 if ( s1 < s2 )
00630 {
00631 return true;
00632 }
00633 else if( s1 > s2 )
00634 {
00635 return false;
00636 }
00637 else
00638 {
00639
00640 s1 = GetEntryValue(0x0020,0x000e);
00641 s2 = document.GetEntryValue(0x0020,0x000e);
00642 if ( s1 < s2 )
00643 {
00644 return true;
00645 }
00646 else if( s1 > s2 )
00647 {
00648 return false;
00649 }
00650 }
00651 }
00652 }
00653 return false;
00654 }
00655
00656
00657
00663 uint16_t Document::ReadInt16()
00664 throw( FormatError )
00665 {
00666 uint16_t g;
00667 Fp->read ((char*)&g, (size_t)2);
00668 if ( Fp->fail() )
00669 {
00670 throw FormatError( "Document::ReadInt16()", " file error." );
00671 }
00672 if( Fp->eof() )
00673 {
00674 throw FormatError( "Document::ReadInt16()", "EOF." );
00675 }
00676 g = SwapShort(g);
00677 return g;
00678 }
00679
00685 uint32_t Document::ReadInt32()
00686 throw( FormatError )
00687 {
00688 uint32_t g;
00689 Fp->read ((char*)&g, (size_t)4);
00690 if ( Fp->fail() )
00691 {
00692 throw FormatError( "Document::ReadInt32()", " file error." );
00693 }
00694 if( Fp->eof() )
00695 {
00696 throw FormatError( "Document::ReadInt32()", "EOF." );
00697 }
00698 g = SwapLong(g);
00699 return g;
00700 }
00701
00707 void Document::SkipBytes(uint32_t nBytes)
00708 {
00709
00710 Fp->seekg((long)nBytes, std::ios::cur);
00711 }
00712
00717 int Document::ComputeGroup0002Length( FileType filetype )
00718 {
00719 uint16_t gr;
00720 std::string vr;
00721
00722 int groupLength = 0;
00723 bool found0002 = false;
00724
00725
00726 DocEntry *entry = GetFirstEntry();
00727 while( entry )
00728 {
00729 gr = entry->GetGroup();
00730
00731 if( gr == 0x0002 )
00732 {
00733 found0002 = true;
00734
00735 if( entry->GetElement() != 0x0000 )
00736 {
00737 vr = entry->GetVR();
00738
00739 if( filetype == ExplicitVR )
00740 {
00741 if ( (vr == "OB") || (vr == "OW") || (vr == "SQ") )
00742 {
00743
00744 groupLength += 4;
00745 }
00746 }
00747 groupLength += 2 + 2 + 4 + entry->GetLength();
00748 }
00749 }
00750 else if (found0002 )
00751 break;
00752
00753 entry = GetNextEntry();
00754 }
00755 return groupLength;
00756 }
00757
00758
00759
00764 void Document::Initialize()
00765 {
00766 RefPubDict = Global::GetDicts()->GetDefaultPubDict();
00767 RefShaDict = NULL;
00768 Filetype = Unknown;
00769 }
00770
00775 void Document::ParseDES(DocEntrySet *set, long offset,
00776 long l_max, bool delim_mode)
00777 {
00778 DocEntry *newDocEntry = 0;
00779 ValEntry *newValEntry;
00780 BinEntry *newBinEntry;
00781 SeqEntry *newSeqEntry;
00782 VRKey vr;
00783 bool used = false;
00784
00785 while (true)
00786 {
00787 if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
00788 {
00789 break;
00790 }
00791
00792 used = true;
00793 newDocEntry = ReadNextDocEntry( );
00794
00795 if ( !newDocEntry )
00796 {
00797 break;
00798 }
00799
00800 vr = newDocEntry->GetVR();
00801 newValEntry = dynamic_cast<ValEntry*>(newDocEntry);
00802 newBinEntry = dynamic_cast<BinEntry*>(newDocEntry);
00803 newSeqEntry = dynamic_cast<SeqEntry*>(newDocEntry);
00804
00805 if ( newValEntry || newBinEntry )
00806 {
00807 if ( newBinEntry )
00808 {
00809 if ( Filetype == ExplicitVR &&
00810 !Global::GetVR()->IsVROfBinaryRepresentable(vr) )
00811 {
00813 gdcmWarningMacro( std::hex << newDocEntry->GetGroup()
00814 << "|" << newDocEntry->GetElement()
00815 << " : Neither Valentry, nor BinEntry."
00816 "Probably unknown VR.");
00817 }
00818
00820
00821
00822 if ( dynamic_cast< Document* > ( set ) )
00823 {
00824 newBinEntry->SetKey( newBinEntry->GetKey() );
00825 }
00826
00827
00828
00829 if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
00830 {
00831 newBinEntry->SetKey( parentSQItem->GetBaseTagKey()
00832 + newBinEntry->GetKey() );
00833 }
00834
00835 LoadDocEntry( newBinEntry );
00836 if( !set->AddEntry( newBinEntry ) )
00837 {
00838
00839
00840 used=false;
00841 }
00842 }
00843 else
00844 {
00846
00847
00848 if ( dynamic_cast< Document* > ( set ) )
00849 {
00850 newValEntry->SetKey( newValEntry->GetKey() );
00851 }
00852
00853
00854
00855 if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
00856 {
00857 newValEntry->SetKey( parentSQItem->GetBaseTagKey()
00858 + newValEntry->GetKey() );
00859 }
00860
00861 LoadDocEntry( newValEntry );
00862 bool delimitor=newValEntry->IsItemDelimitor();
00863 if( !set->AddEntry( newValEntry ) )
00864 {
00865
00866
00867 used=false;
00868 }
00869
00870 if (delimitor)
00871 {
00872 if(!used)
00873 delete newDocEntry;
00874 break;
00875 }
00876 if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
00877 {
00878 if(!used)
00879 delete newDocEntry;
00880 break;
00881 }
00882 }
00883
00884
00885 SkipToNextDocEntry(newDocEntry);
00886 }
00887 else
00888 {
00889
00890 unsigned long l = newDocEntry->GetReadLength();
00891 if ( l != 0 )
00892 {
00893 if ( l == 0xffffffff )
00894 {
00895 delim_mode = true;
00896 }
00897 else
00898 {
00899 delim_mode = false;
00900 }
00901 }
00902
00903 newSeqEntry->SetDelimitorMode( delim_mode );
00904
00905
00906
00907
00908
00909 if ( dynamic_cast< Document* > ( set ) )
00910 {
00911
00912 newSeqEntry->SetDepthLevel( 1 );
00913 newSeqEntry->SetKey( newSeqEntry->GetKey() );
00914 }
00915
00916
00917
00918 if (SQItem *parentSQItem = dynamic_cast< SQItem* > ( set ) )
00919 {
00920 newSeqEntry->SetDepthLevel( parentSQItem->GetDepthLevel() + 1 );
00921 newSeqEntry->SetKey( parentSQItem->GetBaseTagKey()
00922 + newSeqEntry->GetKey() );
00923 }
00924
00925 if ( l != 0 )
00926 {
00927 ParseSQ( newSeqEntry,
00928 newDocEntry->GetOffset(),
00929 l, delim_mode);
00930 }
00931 if( !set->AddEntry( newSeqEntry ) )
00932 {
00933 used = false;
00934 }
00935 if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
00936 {
00937 if( !used )
00938 delete newDocEntry;
00939 break;
00940 }
00941 }
00942
00943 if( !used )
00944 delete newDocEntry;
00945 }
00946 }
00947
00952 void Document::ParseSQ( SeqEntry *seqEntry,
00953 long offset, long l_max, bool delim_mode)
00954 {
00955 int SQItemNumber = 0;
00956 bool dlm_mod;
00957 long offsetStartCurrentSQItem = offset;
00958
00959 while (true)
00960 {
00961
00962 DocEntry *newDocEntry = ReadNextDocEntry();
00963
00964 if ( !newDocEntry )
00965 {
00966
00967 break;
00968 }
00969 if( delim_mode )
00970 {
00971 if ( newDocEntry->IsSequenceDelimitor() )
00972 {
00973 seqEntry->SetDelimitationItem( newDocEntry );
00974 break;
00975 }
00976 }
00977 if ( !delim_mode && ((long)(Fp->tellg())-offset) >= l_max)
00978 {
00979 delete newDocEntry;
00980 break;
00981 }
00982
00983 SQItem *itemSQ = new SQItem( seqEntry->GetDepthLevel() );
00984 std::ostringstream newBase;
00985 newBase << seqEntry->GetKey()
00986 << "/"
00987 << SQItemNumber
00988 << "#";
00989 itemSQ->SetBaseTagKey( newBase.str() );
00990 unsigned int l = newDocEntry->GetReadLength();
00991
00992 if ( l == 0xffffffff )
00993 {
00994 dlm_mod = true;
00995 }
00996 else
00997 {
00998 dlm_mod = false;
00999 }
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 delete newDocEntry;
01010 Fp->seekg(offsetStartCurrentSQItem, std::ios::beg);
01011
01012 ParseDES(itemSQ, offsetStartCurrentSQItem, l+8, dlm_mod);
01013 offsetStartCurrentSQItem = Fp->tellg();
01014
01015
01016 seqEntry->AddSQItem( itemSQ, SQItemNumber );
01017 SQItemNumber++;
01018 if ( !delim_mode && ((long)(Fp->tellg())-offset ) >= l_max )
01019 {
01020 break;
01021 }
01022 }
01023 }
01024
01030 void Document::LoadDocEntry(DocEntry *entry)
01031 {
01032 uint16_t group = entry->GetGroup();
01033 std::string vr = entry->GetVR();
01034 uint32_t length = entry->GetLength();
01035
01036 Fp->seekg((long)entry->GetOffset(), std::ios::beg);
01037
01038
01039
01040
01041
01042 if( group == 0xfffe )
01043 {
01044
01045 return;
01046 }
01047
01048
01049 if ( length == 0 )
01050 {
01051 ((ValEntry *)entry)->SetValue("");
01052 return;
01053 }
01054
01055
01056
01057
01058
01059 std::ostringstream s;
01060 if (length > MaxSizeLoadEntry)
01061 {
01062 if (BinEntry *binEntryPtr = dynamic_cast< BinEntry* >(entry) )
01063 {
01064
01065 s << GDCM_NOTLOADED;
01066 s << " Address:" << (long)entry->GetOffset();
01067 s << " Length:" << entry->GetLength();
01068 s << " x(" << std::hex << entry->GetLength() << ")";
01069 binEntryPtr->SetValue(s.str());
01070 }
01071
01072 else if (ValEntry *valEntryPtr = dynamic_cast< ValEntry* >(entry) )
01073 {
01074
01075 s << GDCM_NOTLOADED;
01076 s << " Address:" << (long)entry->GetOffset();
01077 s << " Length:" << entry->GetLength();
01078 s << " x(" << std::hex << entry->GetLength() << ")";
01079 valEntryPtr->SetValue(s.str());
01080 }
01081 else
01082 {
01083
01084 gdcmErrorMacro( "MaxSizeLoadEntry exceeded, neither a BinEntry "
01085 << "nor a ValEntry ?! Should never print that !" );
01086 }
01087
01088
01089 Fp->seekg((long)entry->GetOffset()+(long)entry->GetLength(),
01090 std::ios::beg);
01091 return;
01092 }
01093
01094
01095 if (BinEntry *binEntryPtr = dynamic_cast< BinEntry* >(entry) )
01096 {
01097 s << GDCM_BINLOADED;
01098 binEntryPtr->SetValue(s.str());
01099 LoadEntryBinArea(binEntryPtr);
01100 return;
01101 }
01102
01104 if ( IsDocEntryAnInteger(entry) )
01105 {
01106 uint32_t NewInt;
01107 int nbInt;
01108
01109
01110
01111
01112
01113 if (vr == "US" || vr == "SS")
01114 {
01115 nbInt = length / 2;
01116 NewInt = ReadInt16();
01117 s << NewInt;
01118 if (nbInt > 1)
01119 {
01120 for (int i=1; i < nbInt; i++)
01121 {
01122 s << '\\';
01123 NewInt = ReadInt16();
01124 s << NewInt;
01125 }
01126 }
01127 }
01128
01129 else if (vr == "UL" || vr == "SL")
01130 {
01131 nbInt = length / 4;
01132 NewInt = ReadInt32();
01133 s << NewInt;
01134 if (nbInt > 1)
01135 {
01136 for (int i=1; i < nbInt; i++)
01137 {
01138 s << '\\';
01139 NewInt = ReadInt32();
01140 s << NewInt;
01141 }
01142 }
01143 }
01144 #ifdef GDCM_NO_ANSI_STRING_STREAM
01145 s << std::ends;
01146 #endif //GDCM_NO_ANSI_STRING_STREAM
01147
01148 ((ValEntry *)entry)->SetValue(s.str());
01149 return;
01150 }
01151
01152
01153 char *str = new char[length+1];
01154 Fp->read(str, (size_t)length);
01155 str[length] = '\0';
01156
01157 std::string newValue;
01158 if( length % 2 )
01159 {
01160 newValue = Util::DicomString(str, length+1);
01161 gdcmWarningMacro("Warning: bad length: " << length <<
01162 ",For string :" << newValue.c_str());
01163
01164
01165 }
01166 else
01167 {
01168 newValue = Util::DicomString(str, length);
01169 }
01170 delete[] str;
01171
01172 if ( ValEntry *valEntry = dynamic_cast<ValEntry* >(entry) )
01173 {
01174 if ( Fp->fail() || Fp->eof())
01175 {
01176 gdcmWarningMacro("Unread element value");
01177 valEntry->SetValue(GDCM_UNREAD);
01178 return;
01179 }
01180
01181 if( vr == "UI" )
01182 {
01183
01184 valEntry->SetValue(newValue);
01185 }
01186 else
01187 {
01188 valEntry->SetValue(newValue);
01189 }
01190 }
01191 else
01192 {
01193 gdcmErrorMacro( "Should have a ValEntry, here !");
01194 }
01195 }
01196
01201 void Document::FindDocEntryLength( DocEntry *entry )
01202 throw ( FormatError )
01203 {
01204 std::string vr = entry->GetVR();
01205 uint16_t length16;
01206
01207 if ( Filetype == ExplicitVR && !entry->IsImplicitVR() )
01208 {
01209 if ( vr == "OB" || vr == "OW" || vr == "SQ" || vr == "UN" )
01210 {
01211
01212
01213
01214 Fp->seekg( 2L, std::ios::cur);
01215 uint32_t length32 = ReadInt32();
01216
01217 if ( (vr == "OB" || vr == "OW") && length32 == 0xffffffff )
01218 {
01219 uint32_t lengthOB;
01220 try
01221 {
01222 lengthOB = FindDocEntryLengthOBOrOW();
01223 }
01224 catch ( FormatUnexpected )
01225 {
01226
01227
01228
01229
01230
01231 long currentPosition = Fp->tellg();
01232 Fp->seekg(0L,std::ios::end);
01233
01234 long lengthUntilEOF = (long)(Fp->tellg())-currentPosition;
01235 Fp->seekg(currentPosition, std::ios::beg);
01236
01237 entry->SetReadLength(lengthUntilEOF);
01238 entry->SetLength(lengthUntilEOF);
01239 return;
01240 }
01241 entry->SetReadLength(lengthOB);
01242 entry->SetLength(lengthOB);
01243 return;
01244 }
01245 FixDocEntryFoundLength(entry, length32);
01246 return;
01247 }
01248
01249
01250 length16 = ReadInt16();
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320 if ( length16 == 0xffff)
01321 {
01322 length16 = 0;
01323 }
01324 FixDocEntryFoundLength( entry, (uint32_t)length16 );
01325 return;
01326 }
01327 else
01328 {
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339 FixDocEntryFoundLength( entry, ReadInt32() );
01340 return;
01341 }
01342 }
01343
01349 uint32_t Document::FindDocEntryLengthOBOrOW()
01350 throw( FormatUnexpected )
01351 {
01352
01353 long positionOnEntry = Fp->tellg();
01354 bool foundSequenceDelimiter = false;
01355 uint32_t totalLength = 0;
01356
01357 while ( !foundSequenceDelimiter )
01358 {
01359 uint16_t group;
01360 uint16_t elem;
01361 try
01362 {
01363 group = ReadInt16();
01364 elem = ReadInt16();
01365 }
01366 catch ( FormatError )
01367 {
01368 throw FormatError("Unexpected end of file encountered during ",
01369 "Document::FindDocEntryLengthOBOrOW()");
01370 }
01371
01372 totalLength += 4;
01373 if ( group != 0xfffe || ( ( elem != 0xe0dd ) && ( elem != 0xe000 ) ) )
01374 {
01375 long filePosition = Fp->tellg();
01376 gdcmWarningMacro( "Neither an Item tag nor a Sequence delimiter tag on :"
01377 << std::hex << group << " , " << elem
01378 << ") -before- position x(" << filePosition << ")" );
01379
01380 Fp->seekg(positionOnEntry, std::ios::beg);
01381 throw FormatUnexpected( "Neither an Item tag nor a Sequence delimiter tag.");
01382 }
01383 if ( elem == 0xe0dd )
01384 {
01385 foundSequenceDelimiter = true;
01386 }
01387 uint32_t itemLength = ReadInt32();
01388
01389 totalLength += itemLength + 4;
01390 SkipBytes(itemLength);
01391
01392 if ( foundSequenceDelimiter )
01393 {
01394 break;
01395 }
01396 }
01397 Fp->seekg( positionOnEntry, std::ios::beg);
01398 return totalLength;
01399 }
01400
01405 std::string Document::FindDocEntryVR()
01406 {
01407 if ( Filetype != ExplicitVR )
01408 return GDCM_UNKNOWN;
01409
01410 long positionOnEntry = Fp->tellg();
01411
01412
01413
01414
01415
01416
01417
01418
01419 char vr[3];
01420 Fp->read (vr, (size_t)2);
01421 vr[2] = 0;
01422
01423 if( !CheckDocEntryVR(vr) )
01424 {
01425 Fp->seekg(positionOnEntry, std::ios::beg);
01426 return GDCM_UNKNOWN;
01427 }
01428 return vr;
01429 }
01430
01439 bool Document::CheckDocEntryVR(VRKey vr)
01440 {
01441 if ( !Global::GetVR()->IsValidVR(vr) )
01442 return false;
01443
01444 return true;
01445 }
01446
01454 std::string Document::GetDocEntryValue(DocEntry *entry)
01455 {
01456 if ( IsDocEntryAnInteger(entry) && entry->IsImplicitVR() )
01457 {
01458 std::string val = ((ValEntry *)entry)->GetValue();
01459 std::string vr = entry->GetVR();
01460 uint32_t length = entry->GetLength();
01461 std::ostringstream s;
01462 int nbInt;
01463
01464
01465
01466
01467
01468
01469
01470
01471 if( vr == "US" || vr == "SS" )
01472 {
01473 uint16_t newInt16;
01474
01475 nbInt = length / 2;
01476 for (int i=0; i < nbInt; i++)
01477 {
01478 if( i != 0 )
01479 {
01480 s << '\\';
01481 }
01482 newInt16 = ( val[2*i+0] & 0xFF ) + ( ( val[2*i+1] & 0xFF ) << 8);
01483 newInt16 = SwapShort( newInt16 );
01484 s << newInt16;
01485 }
01486 }
01487
01488
01489
01490
01491
01492
01493
01494 else if( vr == "UL" || vr == "SL" )
01495 {
01496 uint32_t newInt32;
01497
01498 nbInt = length / 4;
01499 for (int i=0; i < nbInt; i++)
01500 {
01501 if( i != 0)
01502 {
01503 s << '\\';
01504 }
01505 newInt32 = ( val[4*i+0] & 0xFF )
01506 + (( val[4*i+1] & 0xFF ) << 8 )
01507 + (( val[4*i+2] & 0xFF ) << 16 )
01508 + (( val[4*i+3] & 0xFF ) << 24 );
01509 newInt32 = SwapLong( newInt32 );
01510 s << newInt32;
01511 }
01512 }
01513 #ifdef GDCM_NO_ANSI_STRING_STREAM
01514 s << std::ends;
01515 #endif //GDCM_NO_ANSI_STRING_STREAM
01516 return s.str();
01517 }
01518 return ((ValEntry *)entry)->GetValue();
01519 }
01520
01529 std::string Document::GetDocEntryUnvalue(DocEntry *entry)
01530 {
01531 if ( IsDocEntryAnInteger(entry) && entry->IsImplicitVR() )
01532 {
01533 std::string vr = entry->GetVR();
01534 std::vector<std::string> tokens;
01535 std::ostringstream s;
01536
01537 if ( vr == "US" || vr == "SS" )
01538 {
01539 uint16_t newInt16;
01540
01541 tokens.erase( tokens.begin(), tokens.end());
01542 Util::Tokenize (((ValEntry *)entry)->GetValue(), tokens, "\\");
01543 for (unsigned int i=0; i<tokens.size(); i++)
01544 {
01545 newInt16 = atoi(tokens[i].c_str());
01546 s << ( newInt16 & 0xFF )
01547 << (( newInt16 >> 8 ) & 0xFF );
01548 }
01549 tokens.clear();
01550 }
01551 if ( vr == "UL" || vr == "SL")
01552 {
01553 uint32_t newInt32;
01554
01555 tokens.erase(tokens.begin(),tokens.end());
01556 Util::Tokenize (((ValEntry *)entry)->GetValue(), tokens, "\\");
01557 for (unsigned int i=0; i<tokens.size();i++)
01558 {
01559 newInt32 = atoi(tokens[i].c_str());
01560 s << (char)( newInt32 & 0xFF )
01561 << (char)(( newInt32 >> 8 ) & 0xFF )
01562 << (char)(( newInt32 >> 16 ) & 0xFF )
01563 << (char)(( newInt32 >> 24 ) & 0xFF );
01564 }
01565 tokens.clear();
01566 }
01567
01568 #ifdef GDCM_NO_ANSI_STRING_STREAM
01569 s << std::ends;
01570 #endif //GDCM_NO_ANSI_STRING_STREAM
01571 return s.str();
01572 }
01573
01574 return ((ValEntry *)entry)->GetValue();
01575 }
01576
01582 void Document::SkipDocEntry(DocEntry *entry)
01583 {
01584 SkipBytes(entry->GetLength());
01585 }
01586
01592 void Document::SkipToNextDocEntry(DocEntry *currentDocEntry)
01593 {
01594 Fp->seekg((long)(currentDocEntry->GetOffset()), std::ios::beg);
01595 if (currentDocEntry->GetGroup() != 0xfffe)
01596 Fp->seekg( (long)(currentDocEntry->GetReadLength()),std::ios::cur);
01597 }
01598
01606 void Document::FixDocEntryFoundLength(DocEntry *entry,
01607 uint32_t foundLength)
01608 {
01609 entry->SetReadLength( foundLength );
01610 if ( foundLength == 0xffffffff)
01611 {
01612 foundLength = 0;
01613 }
01614
01615 uint16_t gr = entry->GetGroup();
01616 uint16_t elem = entry->GetElement();
01617
01618 if ( foundLength % 2)
01619 {
01620 gdcmWarningMacro( "Warning : Tag with uneven length " << foundLength
01621 << " in x(" << std::hex << gr << "," << elem <<")");
01622 }
01623
01625
01626
01627
01628
01629
01630 if ( foundLength == 13)
01631 {
01632
01633 if ( gr != 0x0008 || ( elem != 0x0070 && elem != 0x0080 ) )
01634 {
01635 foundLength = 10;
01636 entry->SetReadLength(10);
01637 }
01638 }
01639
01641
01642
01643
01644 else if ( gr == 0x0009 && ( elem == 0x1113 || elem == 0x1114 ) )
01645 {
01646 foundLength = 4;
01647 entry->SetReadLength(4);
01648 }
01649
01650 else if ( entry->GetVR() == "SQ" )
01651 {
01652 foundLength = 0;
01653 }
01654
01656
01657
01658 else if( gr == 0xfffe )
01659 {
01660
01661
01662
01663 if( entry->GetElement() != 0x0000 )
01664 {
01665 foundLength = 0;
01666 }
01667 }
01668 entry->SetLength(foundLength);
01669 }
01670
01677 bool Document::IsDocEntryAnInteger(DocEntry *entry)
01678 {
01679 uint16_t elem = entry->GetElement();
01680 uint16_t group = entry->GetGroup();
01681 const std::string &vr = entry->GetVR();
01682 uint32_t length = entry->GetLength();
01683
01684
01685
01686
01687 if ( elem == 0 )
01688 {
01689 if ( length == 4 )
01690 {
01691 return true;
01692 }
01693 else
01694 {
01695
01696
01697
01698
01699
01700
01701
01702 long filePosition = Fp->tellg();
01703 gdcmWarningMacro( "Erroneous Group Length element length on : ("
01704 << std::hex << group << " , " << elem
01705 << ") -before- position x(" << filePosition << ")"
01706 << "lgt : " << length );
01707 }
01708 }
01709
01710 if ( vr == "UL" || vr == "US" || vr == "SL" || vr == "SS" )
01711 {
01712 return true;
01713 }
01714 return false;
01715 }
01716
01725 bool Document::CheckSwap()
01726 {
01727
01728
01729
01730
01731
01732 uint32_t x = 4;
01733 bool net2host;
01734 uint32_t s32;
01735 uint16_t s16;
01736
01737 char deb[256];
01738
01739
01740
01741 if ( x == ntohs(x) )
01742 {
01743 net2host = true;
01744 }
01745 else
01746 {
01747 net2host = false;
01748 }
01749
01750
01751
01752 Fp->read(deb, 256);
01753
01754 char *entCur = deb + 128;
01755 if( memcmp(entCur, "DICM", (size_t)4) == 0 )
01756 {
01757 gdcmWarningMacro( "Looks like DICOM Version3 (preamble + DCM)" );
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773 entCur = deb + 136;
01774
01775
01776
01777
01778
01779 if( memcmp(entCur, "UL", (size_t)2) == 0 ||
01780 memcmp(entCur, "OB", (size_t)2) == 0 ||
01781 memcmp(entCur, "UI", (size_t)2) == 0 ||
01782 memcmp(entCur, "CS", (size_t)2) == 0 )
01783
01784
01785
01786
01787 {
01788 Filetype = ExplicitVR;
01789 gdcmWarningMacro( "Group 0002 : Explicit Value Representation");
01790 }
01791 else
01792 {
01793 Filetype = ImplicitVR;
01794 gdcmWarningMacro( "Group 0002 :Not an explicit Value Representation;"
01795 << "Looks like a bugged Header!");
01796 }
01797
01798 if ( net2host )
01799 {
01800 SwapCode = 4321;
01801 gdcmWarningMacro( "HostByteOrder != NetworkByteOrder");
01802 }
01803 else
01804 {
01805 SwapCode = 1234;
01806 gdcmWarningMacro( "HostByteOrder = NetworkByteOrder");
01807 }
01808
01809
01810
01811 Fp->seekg(0, std::ios::beg);
01812 Fp->seekg ( 132L, std::ios::beg);
01813 return true;
01814 }
01815
01816
01817
01818
01819 gdcmWarningMacro( "Not a DICOM Version3 file");
01820 Fp->seekg(0, std::ios::beg);
01821
01822
01823
01824
01825
01826
01827 entCur = deb + 4;
01828
01829
01830
01831 s32 = *((uint32_t *)(entCur));
01832
01833 switch( s32 )
01834 {
01835 case 0x00040000 :
01836 SwapCode = 3412;
01837 Filetype = ACR;
01838 return true;
01839 case 0x04000000 :
01840 SwapCode = 4321;
01841 Filetype = ACR;
01842 return true;
01843 case 0x00000400 :
01844 SwapCode = 2143;
01845 Filetype = ACR;
01846 return true;
01847 case 0x00000004 :
01848 SwapCode = 1234;
01849 Filetype = ACR;
01850 return true;
01851 default :
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867 s16 = *((uint16_t *)(deb));
01868
01869 switch ( s16 )
01870 {
01871 case 0x0001 :
01872 case 0x0002 :
01873 case 0x0003 :
01874 case 0x0004 :
01875 case 0x0005 :
01876 case 0x0006 :
01877 case 0x0007 :
01878 case 0x0008 :
01879 SwapCode = 1234;
01880 Filetype = ACR;
01881 return true;
01882 case 0x0100 :
01883 case 0x0200 :
01884 case 0x0300 :
01885 case 0x0400 :
01886 case 0x0500 :
01887 case 0x0600 :
01888 case 0x0700 :
01889 case 0x0800 :
01890 SwapCode = 4321;
01891 Filetype = ACR;
01892 return true;
01893 default :
01894 gdcmWarningMacro( "ACR/NEMA unfound swap info (Really hopeless !)");
01895 Filetype = Unknown;
01896 return false;
01897 }
01898 }
01899 }
01900
01904 void Document::SwitchByteSwapCode()
01905 {
01906 gdcmWarningMacro( "Switching Byte Swap code from "<< SwapCode);
01907 if ( SwapCode == 1234 )
01908 {
01909 SwapCode = 4321;
01910 }
01911 else if ( SwapCode == 4321 )
01912 {
01913 SwapCode = 1234;
01914 }
01915 else if ( SwapCode == 3412 )
01916 {
01917 SwapCode = 2143;
01918 }
01919 else if ( SwapCode == 2143 )
01920 {
01921 SwapCode = 3412;
01922 }
01923 }
01924
01929 void Document::SetMaxSizeLoadEntry(long newSize)
01930 {
01931 if ( newSize < 0 )
01932 {
01933 return;
01934 }
01935 if ((uint32_t)newSize >= (uint32_t)0xffffffff )
01936 {
01937 MaxSizeLoadEntry = 0xffffffff;
01938 return;
01939 }
01940 MaxSizeLoadEntry = newSize;
01941 }
01942
01948 void Document::SetMaxSizePrintEntry(long newSize)
01949 {
01950 if ( newSize < 0 )
01951 {
01952 return;
01953 }
01954 if ((uint32_t)newSize >= (uint32_t)0xffffffff )
01955 {
01956 MaxSizePrintEntry = 0xffffffff;
01957 return;
01958 }
01959 MaxSizePrintEntry = newSize;
01960 }
01961
01962
01970 DocEntry *Document::ReadNextDocEntry()
01971 {
01972 uint16_t group;
01973 uint16_t elem;
01974
01975 try
01976 {
01977 group = ReadInt16();
01978 elem = ReadInt16();
01979 }
01980 catch ( FormatError e )
01981 {
01982
01983
01984 return 0;
01985 }
01986
01987
01988 HandleBrokenEndian(group, elem);
01989
01990
01991 if ( HasDCMPreamble )
01992 HandleOutOfGroup0002(group, elem);
01993
01994 std::string vr = FindDocEntryVR();
01995 std::string realVR = vr;
01996
01997 if( vr == GDCM_UNKNOWN)
01998 {
01999 DictEntry *dictEntry = GetDictEntry(group,elem);
02000 if( dictEntry )
02001 realVR = dictEntry->GetVR();
02002 }
02003
02004 DocEntry *newEntry;
02005 if( Global::GetVR()->IsVROfSequence(realVR) )
02006 newEntry = NewSeqEntry(group, elem);
02007 else if( Global::GetVR()->IsVROfStringRepresentable(realVR) )
02008 newEntry = NewValEntry(group, elem,vr);
02009 else
02010 newEntry = NewBinEntry(group, elem,vr);
02011
02012 if( vr == GDCM_UNKNOWN )
02013 {
02014 if( Filetype == ExplicitVR )
02015 {
02016
02017
02018 if ( newEntry->GetGroup() != 0xfffe )
02019 {
02020 std::string msg;
02021 msg = Util::Format("Entry (%04x,%04x) should be Explicit VR\n",
02022 newEntry->GetGroup(), newEntry->GetElement());
02023 gdcmWarningMacro( msg.c_str() );
02024 }
02025 }
02026 newEntry->SetImplicitVR();
02027 }
02028
02029 try
02030 {
02031 FindDocEntryLength(newEntry);
02032 }
02033 catch ( FormatError e )
02034 {
02035
02036
02037 delete newEntry;
02038 return 0;
02039 }
02040
02041 newEntry->SetOffset(Fp->tellg());
02042
02043 return newEntry;
02044 }
02045
02052 void Document::HandleBrokenEndian(uint16_t &group, uint16_t &elem)
02053 {
02054
02055 static int reversedEndian = 0;
02056
02057 if ((group == 0xfeff) && (elem == 0x00e0))
02058 {
02059
02060 reversedEndian++;
02061 SwitchByteSwapCode();
02062
02063 group = 0xfffe;
02064 elem = 0xe000;
02065 }
02066 else if (group == 0xfffe && elem == 0xe00d && reversedEndian)
02067 {
02068
02069 reversedEndian--;
02070 SwitchByteSwapCode();
02071 }
02072 }
02073
02079 void Document::HandleOutOfGroup0002(uint16_t &group, uint16_t &elem)
02080 {
02081
02082 if ( !Group0002Parsed && group != 0x0002)
02083 {
02084 Group0002Parsed = true;
02085
02086
02087
02088 std::string ts = GetTransferSyntax();
02089 if ( !Global::GetTS()->IsTransferSyntax(ts) )
02090 {
02091 gdcmWarningMacro("True DICOM File, with NO Tansfer Syntax: " << ts );
02092 return;
02093 }
02094
02095
02096
02097 if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ImplicitVRLittleEndian )
02098 {
02099 Filetype = ImplicitVR;
02100 }
02101
02102
02103
02104 if ( Global::GetTS()->GetSpecialTransferSyntax(ts) == TS::ExplicitVRBigEndian )
02105 {
02106 gdcmWarningMacro("Transfer Syntax Name = ["
02107 << GetTransferSyntaxName() << "]" );
02108 SwitchByteSwapCode();
02109 group = SwapShort(group);
02110 elem = SwapShort(elem);
02111 }
02112 }
02113 }
02114
02115
02116
02117
02118
02119 }