- // Fixed using : HandleOutOfGroup0002()
- // (first hereafter strategy ...)
-
- // We can tell the current file is encoded in big endian (like
- // Data/US-RGB-8-epicard) when we find the "Transfer Syntax" tag
- // and it's value is the one of the encoding of a big endian file.
- // In order to deal with such big endian encoded files, we have
- // (at least) two strategies:
- // * when we load the "Transfer Syntax" tag with value of big endian
- // encoding, we raise the proper flags. Then we wait for the end
- // of the META group (0x0002) among which is "Transfer Syntax",
- // before switching the swap code to big endian. We have to postpone
- // the switching of the swap code since the META group is fully encoded
- // in little endian, and big endian coding only starts at the next
- // group. The corresponding code can be hard to analyse and adds
- // many additional unnecessary tests for regular tags.
- // * the second strategy consists in waiting for trouble, that shall
- // appear when we find the first group with big endian encoding. This
- // is easy to detect since the length of a "Group Length" tag (the
- // ones with zero as element number) has to be of 4 (0x0004). When we
- // encounter 1024 (0x0400) chances are the encoding changed and we
- // found a group with big endian encoding.
- //---> Unfortunately, element 0000 is optional.
- //---> This will not work when missing!
- // We shall use this second strategy. In order to make sure that we
- // can interpret the presence of an apparently big endian encoded
- // length of a "Group Length" without committing a big mistake, we
- // add an additional check: we look in the already parsed elements
- // for the presence of a "Transfer Syntax" whose value has to be "big
- // endian encoding". When this is the case, chances are we have got our
- // hands on a big endian encoded file: we switch the swap code to
- // big endian and proceed...
-
- //
- // if ( element == 0x0000 && length16 == 0x0400 )
- // {
- // std::string ts = GetTransferSyntax();
- // if ( Global::GetTS()->GetSpecialTransferSyntax(ts)
- // != TS::ExplicitVRBigEndian )
- // {
- // throw FormatError( "Document::FindDocEntryLength()",
- // " not explicit VR." );
- // return;
- // }
- // length16 = 4;
- // SwitchByteSwapCode();
-
- // Restore the unproperly loaded values i.e. the group, the element
- // and the dictionary entry depending on them.
-// uint16_t correctGroup = SwapShort( entry->GetGroup() );
-// uint16_t correctElem = SwapShort( entry->GetElement() );
-// DictEntry *newTag = GetDictEntry( correctGroup, correctElem ); if ( !newTag )
-// {
- // This correct tag is not in the dictionary. Create a new one.
-// newTag = NewVirtualDictEntry(correctGroup, correctElem);
-// }
- // FIXME this can create a memory leaks on the old entry that be
- // left unreferenced.
-// entry->SetDictEntry( newTag );
-// }
-
-
- // 0xffff means that we deal with 'No Length' Sequence
- // or 'No Length' SQItem
- if ( length16 == 0xffff)
- {
- length16 = 0;
- }
- FixDocEntryFoundLength( entry, (uint32_t)length16 );
- return;
- }
- else
- {
- // Either implicit VR or a non DICOM conformal (see note below) explicit
- // VR that ommited the VR of (at least) this element. Farts happen.
- // [Note: according to the part 5, PS 3.5-2001, section 7.1 p25
- // on Data elements "Implicit and Explicit VR Data Elements shall
- // not coexist in a Data Set and Data Sets nested within it".]
- // Length is on 4 bytes.
-
- // Well ... group 0002 is always coded in 'Explicit VR Litle Endian'
- // even if Transfer Syntax is 'Implicit VR ...'
-
- FixDocEntryFoundLength( entry, ReadInt32() );
- return;
- }
-}
-
-/**
- * \brief Find the Value Representation of the current Dicom Element.
- * @return Value Representation of the current Entry
- */
-std::string Document::FindDocEntryVR()
-{
- if ( Filetype != ExplicitVR )
- return GDCM_UNKNOWN;
-
- long positionOnEntry = Fp->tellg();
- // Warning: we believe this is explicit VR (Value Representation) because
- // we used a heuristic that found "UL" in the first tag. Alas this
- // doesn't guarantee that all the tags will be in explicit VR. In some
- // cases (see e-film filtered files) one finds implicit VR tags mixed
- // within an explicit VR file. Hence we make sure the present tag
- // is in explicit VR and try to fix things if it happens not to be
- // the case.
-
- char vr[3];
- Fp->read (vr, (size_t)2);
- vr[2] = 0;
-
- if( !CheckDocEntryVR(vr) )
- {
- Fp->seekg(positionOnEntry, std::ios::beg);
- return GDCM_UNKNOWN;
- }
- return vr;
-}
-
-/**
- * \brief Check the correspondance between the VR of the header entry
- * and the taken VR. If they are different, the header entry is
- * updated with the new VR.
- * @param vr Dicom Value Representation
- * @return false if the VR is incorrect of if the VR isn't referenced
- * otherwise, it returns true
-*/
-bool Document::CheckDocEntryVR(VRKey vr)
-{
- // CLEANME searching the dicom_vr at each occurence is expensive.
- // PostPone this test in an optional integrity check at the end
- // of parsing or only in debug mode.
- if ( !Global::GetVR()->IsValidVR(vr) )
- return false;
-
- return true;
-}
-
-/**
- * \brief Get the transformed value of the header entry. The VR value
- * is used to define the transformation to operate on the value
- * \warning NOT end user intended method !
- * @param entry entry to tranform
- * @return Transformed entry value
- */
-std::string Document::GetDocEntryValue(DocEntry *entry)
-{
- if ( IsDocEntryAnInteger(entry) && entry->IsImplicitVR() )
- {
- std::string val = ((ValEntry *)entry)->GetValue();
- std::string vr = entry->GetVR();
- uint32_t length = entry->GetLength();
- std::ostringstream s;
- int nbInt;
-
- // When short integer(s) are expected, read and convert the following
- // n * 2 bytes properly i.e. as a multivaluated strings
- // (each single value is separated fromthe next one by '\'
- // as usual for standard multivaluated filels
- // Elements with Value Multiplicity > 1
- // contain a set of short integers (not a single one)
-
- if( vr == "US" || vr == "SS" )
- {
- uint16_t newInt16;
-
- nbInt = length / 2;
- for (int i=0; i < nbInt; i++)
- {
- if( i != 0 )
- {
- s << '\\';
- }
- newInt16 = ( val[2*i+0] & 0xFF ) + ( ( val[2*i+1] & 0xFF ) << 8);
- newInt16 = SwapShort( newInt16 );
- s << newInt16;
- }
- }
-
- // When integer(s) are expected, read and convert the following
- // n * 4 bytes properly i.e. as a multivaluated strings
- // (each single value is separated fromthe next one by '\'
- // as usual for standard multivaluated filels
- // Elements with Value Multiplicity > 1
- // contain a set of integers (not a single one)
- else if( vr == "UL" || vr == "SL" )
- {
- uint32_t newInt32;
-
- nbInt = length / 4;
- for (int i=0; i < nbInt; i++)
- {
- if( i != 0)
- {
- s << '\\';
- }
- newInt32 = ( val[4*i+0] & 0xFF )
- + (( val[4*i+1] & 0xFF ) << 8 )
- + (( val[4*i+2] & 0xFF ) << 16 )
- + (( val[4*i+3] & 0xFF ) << 24 );
- newInt32 = SwapLong( newInt32 );
- s << newInt32;
- }
- }
-#ifdef GDCM_NO_ANSI_STRING_STREAM
- s << std::ends; // to avoid oddities on Solaris
-#endif //GDCM_NO_ANSI_STRING_STREAM
- return s.str();
- }
-
- return ((ValEntry *)entry)->GetValue();
-}
-
-/**
- * \brief Get the reverse transformed value of the header entry. The VR
- * value is used to define the reverse transformation to operate on
- * the value
- * \warning NOT end user intended method !
- * @param entry Entry to reverse transform
- * @return Reverse transformed entry value
- */
-std::string Document::GetDocEntryUnvalue(DocEntry *entry)
-{
- if ( IsDocEntryAnInteger(entry) && entry->IsImplicitVR() )
- {
- std::string vr = entry->GetVR();
- std::vector<std::string> tokens;
- std::ostringstream s;
-
- if ( vr == "US" || vr == "SS" )
- {
- uint16_t newInt16;
-
- tokens.erase( tokens.begin(), tokens.end()); // clean any previous value
- Util::Tokenize (((ValEntry *)entry)->GetValue(), tokens, "\\");
- for (unsigned int i=0; i<tokens.size(); i++)
- {
- newInt16 = atoi(tokens[i].c_str());
- s << ( newInt16 & 0xFF )
- << (( newInt16 >> 8 ) & 0xFF );
- }
- tokens.clear();
- }
- if ( vr == "UL" || vr == "SL")
- {
- uint32_t newInt32;
-
- tokens.erase(tokens.begin(),tokens.end()); // clean any previous value
- Util::Tokenize (((ValEntry *)entry)->GetValue(), tokens, "\\");
- for (unsigned int i=0; i<tokens.size();i++)
- {
- newInt32 = atoi(tokens[i].c_str());
- s << (char)( newInt32 & 0xFF )
- << (char)(( newInt32 >> 8 ) & 0xFF )
- << (char)(( newInt32 >> 16 ) & 0xFF )
- << (char)(( newInt32 >> 24 ) & 0xFF );
- }
- tokens.clear();
- }
-
-#ifdef GDCM_NO_ANSI_STRING_STREAM
- s << std::ends; // to avoid oddities on Solaris
-#endif //GDCM_NO_ANSI_STRING_STREAM
- return s.str();
- }
-
- return ((ValEntry *)entry)->GetValue();
-}
-
-/**
- * \brief Skip a given Header Entry
- * \warning NOT end user intended method !
- * @param entry entry to skip
- */
-void Document::SkipDocEntry(DocEntry *entry)
-{
- SkipBytes(entry->GetLength());
-}
-
-/**
- * \brief Skips to the begining of the next Header Entry
- * \warning NOT end user intended method !
- * @param currentDocEntry entry to skip
- */
-void Document::SkipToNextDocEntry(DocEntry *currentDocEntry)
-{
- Fp->seekg((long)(currentDocEntry->GetOffset()), std::ios::beg);
- if (currentDocEntry->GetGroup() != 0xfffe) // for fffe pb
- Fp->seekg( (long)(currentDocEntry->GetReadLength()),std::ios::cur);