From 0ffe9434840c30ee1e307bb4d0153b3a4351768e Mon Sep 17 00:00:00 2001 From: GDCM Upstream Date: Fri, 15 Mar 2024 15:53:35 -0400 Subject: [PATCH] GDCM 2024-03-15 (092db794) Code extracted from: https://github.com/InsightSoftwareConsortium/GDCM.git at commit 092db7949144f86ab8c58fc7c3170c9f982d1d72 (20240315_GDCM_PATCHES_FOR_ITK). --- .codespellrc | 3 - CMakeLists.txt | 2 +- .../gdcmCSAHeader.cxx | 10 +- .../MediaStorageAndFileFormat/gdcmCleaner.cxx | 33 +- .../MediaStorageAndFileFormat/gdcmCleaner.h | 3 + .../gdcmDirectionCosines.cxx | 13 +- .../gdcmDirectionCosines.h | 3 + .../gdcmFileStreamer.cxx | 2 +- .../gdcmImageCodec.cxx | 6 +- .../gdcmImageHelper.cxx | 37 +- .../gdcmImageHelper.h | 7 + .../gdcmSplitMosaicFilter.cxx | 121 +++++-- .../gdcmSplitMosaicFilter.h | 9 + Utilities/gdcmext/csa.c | 23 +- Utilities/gdcmutfcpp/README.GDCM.txt | 17 - Utilities/gdcmutfcpp/utf8.h | 34 -- Utilities/gdcmutfcpp/utf8/checked.h | 327 ----------------- Utilities/gdcmutfcpp/utf8/core.h | 329 ------------------ Utilities/gdcmutfcpp/utf8/unchecked.h | 228 ------------ 19 files changed, 224 insertions(+), 983 deletions(-) delete mode 100644 .codespellrc delete mode 100644 Utilities/gdcmutfcpp/README.GDCM.txt delete mode 100644 Utilities/gdcmutfcpp/utf8.h delete mode 100644 Utilities/gdcmutfcpp/utf8/checked.h delete mode 100644 Utilities/gdcmutfcpp/utf8/core.h delete mode 100644 Utilities/gdcmutfcpp/utf8/unchecked.h diff --git a/.codespellrc b/.codespellrc deleted file mode 100644 index 6771ed04bbc4..000000000000 --- a/.codespellrc +++ /dev/null @@ -1,3 +0,0 @@ -[codespell] -skip = ./Utilities/gdcmcharls,./Utilities/gdcmopenjpeg,./Utilities/gdcmrle,./Utilities/gdcmexpat,./Utilities/gdcmjpeg,./Utilities/gdcmzlib,./Utilities/pvrg,./Utilities/socketxx -ignore-words-list = convertor,possibile,iif,comando,oly,ofthe,didi,promis,alue,tutoriels,som,tabl,psot,cna,varian,pres,comparaison,serie,ore,ect,mor,setts,unknow,inout,te,nd,te,pinter,fo,ot,siz,ist,shs,invers,studi,wallthickness,vas,fith diff --git a/CMakeLists.txt b/CMakeLists.txt index 44531b695ef2..345f29732081 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ endif() #---------------------------------------------------------------------------- project(GDCM - VERSION 3.0.22 + VERSION 3.0.23 LANGUAGES CXX C ) ## NOTE: the "DESCRIPTION" feature of project() was introduced in cmake 3.10.0 diff --git a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx index ad944ac64628..3fe9075c03b3 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx @@ -910,7 +910,8 @@ bool check_mapping(uint32_t syngodt, const char *vr) { static const unsigned int max = sizeof(mapping) / sizeof(equ); const equ *p = mapping; - assert( syngodt <= mapping[max-1].syngodt ); (void)max; + if( syngodt > mapping[max-1].syngodt ) return false; + assert( syngodt <= mapping[max-1].syngodt ); while(p->syngodt < syngodt ) { //std::cout << "mapping:" << p->vr << std::endl; @@ -1098,6 +1099,11 @@ bool CSAHeader::LoadFromDataElement(DataElement const &de) char vr[4]; ss.read(vr, 4); // In dataset without magic signature (OLD FORMAT) vr[3] is garbage... + if( vr[2] != 0 ) + { + gdcmErrorMacro( "Garbage data. Stopping CSA parsing." ); + return false; + } assert( /*vr[3] == 0 &&*/ vr[2] == 0 ); csael.SetVR( VR::GetVRTypeFromFile(vr) ); //std::cout << "VR " << vr << ", "; @@ -1131,8 +1137,10 @@ bool CSAHeader::LoadFromDataElement(DataElement const &de) uint32_t item_xx[4]; ss.read((char*)&item_xx, 4*sizeof(uint32_t)); SwapperNoOp::SwapArray(item_xx,4); + if( item_xx[2] != 77 && item_xx[2] != 205 ) return false; assert( item_xx[2] == 77 || item_xx[2] == 205 ); uint32_t len = item_xx[1]; // 2nd element + if( item_xx[0] != item_xx[1] || item_xx[1] != item_xx[3] ) return false; assert( item_xx[0] == item_xx[1] && item_xx[1] == item_xx[3] ); if( len ) { diff --git a/Source/MediaStorageAndFileFormat/gdcmCleaner.cxx b/Source/MediaStorageAndFileFormat/gdcmCleaner.cxx index e1600152608b..0d0ffe28b097 100644 --- a/Source/MediaStorageAndFileFormat/gdcmCleaner.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmCleaner.cxx @@ -538,10 +538,12 @@ struct Cleaner::impl { bool AllMissingPrivateCreator; bool AllGroupLength; bool AllIllegal; + bool WhenScrubFails; impl() : AllMissingPrivateCreator(true), AllGroupLength(true), - AllIllegal(true) {} + AllIllegal(true), + WhenScrubFails(false) {} enum ACTION { NONE, EMPTY, REMOVE, SCRUB }; enum ACTION ComputeAction(File const &file, DataSet &ds, @@ -668,6 +670,10 @@ struct Cleaner::impl { bool RemoveMissingPrivateCreator(Tag const & /*t*/) { return false; } void RemoveAllGroupLength(bool remove) { AllGroupLength = remove; } void RemoveAllIllegal(bool remove) { AllIllegal = remove; } + void EmptyWhenScrubFails(bool empty) { WhenScrubFails = empty; } + + bool CleanCSAImage(DataSet &ds, const DataElement &de); + bool CleanCSASeries(DataSet &ds, const DataElement &de); }; static VR ComputeDictVR(File &file, DataSet &ds, DataElement const &de) { @@ -840,7 +846,7 @@ static inline bool bs_is_signature(const ByteValue *bv, const char *str) { return false; } -static bool CleanCSAImage(DataSet &ds, const DataElement &de) { +bool Cleaner::impl::CleanCSAImage(DataSet &ds, const DataElement &de) { const ByteValue *bv = de.GetByteValue(); // fast path: if (!bv) return true; @@ -888,6 +894,13 @@ static bool CleanCSAImage(DataSet &ds, const DataElement &de) { gdcmDebugMacro("Zero-out CSA header"); return true; } + // fallback logic: + if (WhenScrubFails && is_signature(bv, sv10)) { + // so SV10 header has been identified, but we failed to 'scrub', let's + // empty it: + ds.Replace(clean); + return true; + } gdcmErrorMacro("Failure to call CleanCSAImage"); return false; } @@ -900,7 +913,7 @@ static bool CleanCSAImage(DataSet &ds, const DataElement &de) { return true; } -static bool CleanCSASeries(DataSet &ds, const DataElement &de) { +bool Cleaner::impl::CleanCSASeries(DataSet &ds, const DataElement &de) { const ByteValue *bv = de.GetByteValue(); // fast path: if (!bv) return true; @@ -944,6 +957,13 @@ static bool CleanCSASeries(DataSet &ds, const DataElement &de) { gdcmDebugMacro("Zero-out CSA header"); return true; } + // fallback logic: + if (WhenScrubFails && is_signature(bv, sv10)) { + // so SV10 header has been identified, but we failed to 'scrub', let's + // empty it: + ds.Replace(clean); + return true; + } gdcmErrorMacro("Failure to call CleanCSASeries"); return false; } @@ -1065,8 +1085,8 @@ static bool IsDPathInSet(std::set const &aset, DPath const dpath) { } Cleaner::impl::ACTION Cleaner::impl::ComputeAction( - File const & /*file*/, DataSet &ds, const DataElement &de, VR const &ref_dict_vr, - const std::string &tag_path) { + File const & /*file*/, DataSet &ds, const DataElement &de, + VR const &ref_dict_vr, const std::string &tag_path) { const Tag &tag = de.GetTag(); // Group Length & Illegal cannot be preserved so it is safe to do them now: if (tag.IsGroupLength()) { @@ -1302,6 +1322,9 @@ void Cleaner::RemoveAllGroupLength(bool remove) { pimpl->RemoveAllGroupLength(remove); } void Cleaner::RemoveAllIllegal(bool remove) { pimpl->RemoveAllIllegal(remove); } +void Cleaner::EmptyWhenScrubFails(bool empty) { + pimpl->EmptyWhenScrubFails(empty); +} bool Cleaner::Clean() { DataSet &ds = F->GetDataSet(); diff --git a/Source/MediaStorageAndFileFormat/gdcmCleaner.h b/Source/MediaStorageAndFileFormat/gdcmCleaner.h index 4d8c351abe7f..bf2ad54430ba 100644 --- a/Source/MediaStorageAndFileFormat/gdcmCleaner.h +++ b/Source/MediaStorageAndFileFormat/gdcmCleaner.h @@ -65,6 +65,9 @@ class GDCM_EXPORT Cleaner : public Subject { /// Should I remove all illegal attribute. Default: true void RemoveAllIllegal(bool remove); + /// Should I empty instead of scrub upon failure + void EmptyWhenScrubFails(bool empty); + /// main loop bool Clean(); diff --git a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx index 275d74855a60..119a7b4a8392 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx @@ -98,15 +98,20 @@ double DirectionCosines::Dot() const } // static function is within gdcm:: namespace, so should not pollute too much on UNIX -static inline double Norm(const double x[3]) +static inline double NormImpl(const double x[3]) { return sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]); } +double DirectionCosines::Norm(const double v[3]) +{ + return NormImpl(v); +} + void DirectionCosines::Normalize(double v[3]) { double den; - if ( (den = Norm(v)) != 0.0 ) + if ( (den = NormImpl(v)) != 0.0 ) { for (int i=0; i < 3; i++) { @@ -119,7 +124,7 @@ void DirectionCosines::Normalize() { double *x = Values; double den; - if ( (den = Norm(x)) != 0.0 ) + if ( (den = NormImpl(x)) != 0.0 ) { for (int i=0; i < 3; i++) { @@ -127,7 +132,7 @@ void DirectionCosines::Normalize() } } x = Values+3; - if ( (den = Norm(x)) != 0.0 ) + if ( (den = NormImpl(x)) != 0.0 ) { for (int i=0; i < 3; i++) { diff --git a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h index 73717fdc0cad..1313146cf083 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h +++ b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h @@ -49,6 +49,9 @@ class GDCM_EXPORT DirectionCosines /// Normalize in-place static void Normalize(double v[3]); + /// Return norm of the vector + static double Norm(const double v[3]); + /// Make the class behave like a const double * operator const double* () const { return Values; } diff --git a/Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx b/Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx index 7723b0a83f92..c35cc716dbab 100644 --- a/Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx @@ -35,7 +35,7 @@ #include typedef int64_t off64_t; #else -#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__EMSCRIPTEN__) # define off64_t off_t #endif #include // ftruncate diff --git a/Source/MediaStorageAndFileFormat/gdcmImageCodec.cxx b/Source/MediaStorageAndFileFormat/gdcmImageCodec.cxx index deba8ab004cc..c2030c0a89f2 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageCodec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImageCodec.cxx @@ -460,7 +460,8 @@ bool ImageCodec::CleanupUnusedBits(char * data8, size_t datalen) smask = (uint16_t)( smask << ( 16 - (PF.GetBitsAllocated() - PF.GetBitsStored() + 1) )); // nmask : to propagate sign bit on negative values - int16_t nmask = (int16_t)(0x8000U >> ( PF.GetBitsAllocated() - PF.GetBitsStored() - 1 )); + int16_t nmask = (int16_t)0x8000; + nmask = (int16_t)(nmask >> ( PF.GetBitsAllocated() - PF.GetBitsStored() - 1 )); uint16_t *start = (uint16_t*)data; for( uint16_t *p = start ; p != start + datalen / 2; ++p ) @@ -515,7 +516,8 @@ bool ImageCodec::DoOverlayCleanup(std::istream &is, std::ostream &os) smask = (uint16_t)( smask << ( 16 - (PF.GetBitsAllocated() - PF.GetBitsStored() + 1) )); // nmask : to propagate sign bit on negative values - int16_t nmask = (int16_t)(0x8000U >> ( PF.GetBitsAllocated() - PF.GetBitsStored() - 1 )); + int16_t nmask = (int16_t)0x8000; + nmask = (int16_t)(nmask >> ( PF.GetBitsAllocated() - PF.GetBitsStored() - 1 )); uint16_t c; while( is.read((char*)&c,2) ) diff --git a/Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx b/Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx index d8973f413047..552a437f01ba 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx @@ -48,6 +48,7 @@ namespace gdcm bool ImageHelper::ForceRescaleInterceptSlope = false; bool ImageHelper::PMSRescaleInterceptSlope = true; bool ImageHelper::ForcePixelSpacing = false; +bool ImageHelper::SecondaryCaptureImagePlaneModule = false; static bool GetOriginValueFromSequence(const DataSet& ds, const Tag& tfgs, std::vector &ori) { @@ -205,6 +206,7 @@ static bool ComputeZSpacingFromIPP(const DataSet &ds, double &zspacing) double normal[3]; DirectionCosines dc( cosines.data() ); dc.Cross( normal ); + DirectionCosines::Normalize(normal); // For each item SequenceOfItems::SizeType nitems = sqi->GetNumberOfItems(); @@ -577,7 +579,7 @@ std::vector ImageHelper::GetOriginValue(File const & f) // else const Tag timagepositionpatient(0x0020, 0x0032); - if( ms != MediaStorage::SecondaryCaptureImageStorage && ds.FindDataElement( timagepositionpatient ) ) + if( (ms != MediaStorage::SecondaryCaptureImageStorage || SecondaryCaptureImagePlaneModule) && ds.FindDataElement( timagepositionpatient ) ) { const DataElement& de = ds.GetDataElement( timagepositionpatient ); Attribute<0x0020,0x0032> at = {{0,0,0}}; // default value if empty @@ -729,7 +731,7 @@ std::vector ImageHelper::GetDirectionCosinesValue(File const & f) } dircos.resize( 6 ); - if( ms == MediaStorage::SecondaryCaptureImageStorage || !GetDirectionCosinesFromDataSet(ds, dircos) ) + if( (ms != MediaStorage::SecondaryCaptureImageStorage || SecondaryCaptureImagePlaneModule) && !GetDirectionCosinesFromDataSet(ds, dircos) ) { dircos[0] = 1; dircos[1] = 0; @@ -773,6 +775,16 @@ bool ImageHelper::GetForcePixelSpacing() return ForcePixelSpacing; } +void ImageHelper::SetSecondaryCaptureImagePlaneModule(bool b) +{ + SecondaryCaptureImagePlaneModule = b; +} + +bool ImageHelper::GetSecondaryCaptureImagePlaneModule() +{ + return SecondaryCaptureImagePlaneModule; +} + bool GetRescaleInterceptSlopeValueFromDataSet(const DataSet& ds, std::vector & interceptslope) { Attribute<0x0028,0x1052> at1; @@ -1388,6 +1400,7 @@ std::vector ImageHelper::GetSpacingValue(File const & f) MediaStorage ms; ms.SetFromFile(f); const DataSet& ds = f.GetDataSet(); + Tag spacingtag(0xffff,0xffff); if( ms == MediaStorage::EnhancedCTImageStorage || ms == MediaStorage::EnhancedMRImageStorage @@ -1450,8 +1463,24 @@ std::vector ImageHelper::GetSpacingValue(File const & f) return sp; } } + else if( ms == MediaStorage::SecondaryCaptureImageStorage ) + { + if( ds.FindDataElement( Tag(0x0028,0x0030) ) ) + { + // Type 1C in 'SC Image' (for calibrated images) + spacingtag = Tag(0x0028,0x0030); + } + else if( ds.FindDataElement( Tag(0x0018,0x2010) ) ) + { + // Type 3 in 'SC Image' + spacingtag = Tag(0x0018,0x2010); + } + } + else + { + spacingtag = GetSpacingTagFromMediaStorage(ms); + } - Tag spacingtag = GetSpacingTagFromMediaStorage(ms); if( spacingtag != Tag(0xffff,0xffff) && ds.FindDataElement( spacingtag ) && !ds.GetDataElement( spacingtag ).IsEmpty() ) { const DataElement& de = ds.GetDataElement( spacingtag ); @@ -2027,6 +2056,7 @@ void ImageHelper::SetOriginValue(DataSet & ds, const Image & image) double normal[3]; dc.Cross( normal ); + DirectionCosines::Normalize(normal); for(unsigned int i = 0; i < dimz; ++i ) { @@ -2896,6 +2926,7 @@ MediaStorage ImageHelper::ComputeMediaStorageFromModality(const char *modality, || pi == PhotometricInterpretation::YBR_RCT || pi == PhotometricInterpretation::YBR_ICT || pi == PhotometricInterpretation::YBR_PARTIAL_420 + || pi == PhotometricInterpretation::YBR_FULL /* PI when coming from other gdcm filter */ || pi == PhotometricInterpretation::YBR_FULL_422 ) && pixeltype.GetBitsAllocated() == 8 && pixeltype.GetBitsStored() == 8 && diff --git a/Source/MediaStorageAndFileFormat/gdcmImageHelper.h b/Source/MediaStorageAndFileFormat/gdcmImageHelper.h index 2f70231d4b73..05f5aab1bad3 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageHelper.h +++ b/Source/MediaStorageAndFileFormat/gdcmImageHelper.h @@ -85,6 +85,12 @@ class GDCM_EXPORT ImageHelper static void SetForcePixelSpacing(bool); static bool GetForcePixelSpacing(); + /// Opt into Image Plane Module for Secondary Capture Image Storage + /// Enable reading Image Position Patient (IPP) and Image Orientation Patient (IOP) + /// for Secondary Capture Image Storage. + static void SetSecondaryCaptureImagePlaneModule(bool); + static bool GetSecondaryCaptureImagePlaneModule(); + /// This function checks tags (0x0028, 0x0010) and (0x0028, 0x0011) for the /// rows and columns of the image in pixels (as opposed to actual distances). /// The output is {col , row} @@ -156,6 +162,7 @@ class GDCM_EXPORT ImageHelper static bool ForceRescaleInterceptSlope; static bool PMSRescaleInterceptSlope; static bool ForcePixelSpacing; + static bool SecondaryCaptureImagePlaneModule; }; } // end namespace gdcm diff --git a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx index d3c43ebf8725..6f368e0c51a6 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx @@ -287,6 +287,96 @@ bool SplitMosaicFilter::ComputeMOSAICSliceNormal( double slicenormalvector[3], b return snvfound; } +bool SplitMosaicFilter::ComputeMOSAICImagePositionPatient( double ret[3], + const double ipp[6], + const double dircos[6], + const double pixelspacing[3], + const unsigned int image_dims[3] , + const unsigned int mosaic_dims[3] , bool inverted) +{ + CSAHeader csa; + DataSet& ds = GetFile().GetDataSet(); + DirectionCosines dc( dircos ); + dc.Normalize(); + const double *dircos_normalized = dc; + const double *x = dircos_normalized; + const double *y = dircos_normalized + 3; + + double ipp_csa[3] = {}; + bool hasIppCsa = false; + MrProtocol mrprot; + // https://www.nmr.mgh.harvard.edu/~greve/dicom-unpack + if( csa.GetMrProtocol(ds, mrprot) ) + { + MrProtocol::SliceArray sa; + bool b = mrprot.GetSliceArray(sa); + if( b ) { + size_t size = sa.Slices.size(); + if( size ) { + // two cases: + if( size == mosaic_dims[2] ) { + // all mosaic have there own slice position, simply need to pick the right one + // Handle inverted case: + size_t index = inverted ? size - 1 : 0; + MrProtocol::Slice & slice = sa.Slices[index]; + MrProtocol::Vector3 & p = slice.Position; + double pos[3]; + pos[0] = p.dSag; + pos[1] = p.dCor; + pos[2] = p.dTra; + for(int i = 0; i < 3; ++i ) { + ipp_csa[i] = pos[i] - mosaic_dims[0] / 2. * pixelspacing[0] * x[i] - mosaic_dims[1] / 2. * pixelspacing[1] * y[i]; + } + hasIppCsa = true; + } else if( size == 1 /*&& mosaic_dims[2] % 2 == 0*/) { + // there is a single SliceArray but multiple mosaics, assume this is exactly the center one + double z[3]={}; + dc.Cross(z); + DirectionCosines::Normalize(z); + size_t index = 0; + MrProtocol::Slice & slice = sa.Slices[index]; + MrProtocol::Vector3 & p = slice.Position; + double pos[3]; + pos[0] = p.dSag; + pos[1] = p.dCor; + pos[2] = p.dTra; + for(int i = 0; i < 3; ++i ) { + ipp_csa[i] = pos[i] - mosaic_dims[0] / 2. * pixelspacing[0] * x[i] - mosaic_dims[1] / 2. * pixelspacing[1] * y[i] + - (mosaic_dims[2] - 1) / 2. * pixelspacing[2] * z[i]; + } + hasIppCsa = true; + } else { + gdcmWarningMacro( "Inconsistent SliceArray: " << size << " vs expected: " << mosaic_dims[2] ); + } + } + } + } + + // https://nipy.org/nibabel/dicom/dicom_mosaic.html#dicom-mosaic + double ipp_dcm[3] = {}; + { + for(int i = 0; i < 3; ++i ) { + ipp_dcm[i] = ipp[i] + (image_dims[0] - mosaic_dims[0]) / 2. * pixelspacing[0] * x[i] + + (image_dims[1] - mosaic_dims[1]) / 2. * pixelspacing[1] * y[i] ; + } + } + if(hasIppCsa ) { + double diff[3]; + for(int i = 0; i < 3; ++i ) { + diff[i] = ipp_dcm[i] - ipp_csa[i]; + } + double n = DirectionCosines::Norm(diff); + if( n > 1e-4 ) { + gdcmWarningMacro( "Inconsistent values for IPP/CSA: (" << ipp_dcm[0] << "," << ipp_dcm[1] << "," << ipp_dcm[2] << ") vs (" << ipp_csa[0] << "," << ipp_csa[1] << "," << ipp_csa[2] << ")" ); + } + } + // no error set origin: + for(int i = 0; i < 3; ++i ) + ret[i] = ipp_dcm[i]; + + return true; +} + bool SplitMosaicFilter::ComputeMOSAICSlicePosition( double pos[3], bool ) { CSAHeader csa; @@ -301,25 +391,6 @@ bool SplitMosaicFilter::ComputeMOSAICSlicePosition( double pos[3], bool ) size_t size = sa.Slices.size(); if( !size ) return false; -#if 0 - { - double z[3]; - for( int i = 0; i < size; ++i ) - { - MrProtocol::Slice & slice = sa.Slices[i]; - MrProtocol::Vector3 & p = slice.Position; - z[0] = p.dSag; - z[1] = p.dCor; - z[2] = p.dTra; - const double snv_dot = DirectionCosines::Dot( slicenormalvector, z ); - if( (1. - snv_dot) < 1e-6 ) - { - gdcmErrorMacro("Invalid direction found"); - return false; - } - } - } -#endif size_t index = 0; MrProtocol::Slice & slice = sa.Slices[index]; @@ -342,7 +413,7 @@ bool SplitMosaicFilter::Split() return false; } const unsigned int div = (unsigned int )ceil(sqrt( (double)dims[2]) ); - bool inverted; + bool inverted = false; double normal[3]; bool hasOriginCSA = true; bool hasNormalCSA = true; @@ -353,13 +424,21 @@ bool SplitMosaicFilter::Split() } (void)hasNormalCSA; double origin[3]; + const Image &inputimage = GetImage(); +#if 0 if( !ComputeMOSAICSlicePosition( origin, inverted ) ) { gdcmWarningMacro( "Origin will not be accurate" ); hasOriginCSA = false; } +#else + if(!ComputeMOSAICImagePositionPatient( origin, inputimage.GetOrigin(), inputimage.GetDirectionCosines(), inputimage.GetSpacing(), inputimage.GetDimensions(), dims, inverted )) + { + gdcmWarningMacro( "Origin will not be accurate" ); + hasOriginCSA = false; + } +#endif - const Image &inputimage = GetImage(); if( inputimage.GetPixelFormat() != PixelFormat::UINT16 ) { gdcmErrorMacro( "Expecting UINT16 PixelFormat" ); diff --git a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.h b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.h index 7f30b0a25de9..06f281a3dbd7 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.h +++ b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.h @@ -57,8 +57,17 @@ class GDCM_EXPORT SplitMosaicFilter bool ComputeMOSAICSliceNormal( double dims[3], bool & inverted ); /// Extract the value for ImagePositionPatient (requires inverted flag) + /// Deprecated bool ComputeMOSAICSlicePosition( double pos[3], bool inverted ); + /// Extract the value for ImagePositionPatient + bool ComputeMOSAICImagePositionPatient( double pos[3], + const double ipp[6], + const double dircos[6], + const double pixelspacing[3], + const unsigned int image_dims[3] , + const unsigned int mosaic_dims[3], bool inverted ); + void SetImage(const Image& image); const Image &GetImage() const { return *I; } Image &GetImage() { return *I; } diff --git a/Utilities/gdcmext/csa.c b/Utilities/gdcmext/csa.c index bbab6b3914d3..517de950e356 100644 --- a/Utilities/gdcmext/csa.c +++ b/Utilities/gdcmext/csa.c @@ -89,8 +89,15 @@ static void setup_buffer(struct app *self, void *output, const void *input, self->out->write = stream_write; } +//#define CSA_DEBUG + +#ifdef CSA_DEBUG +#define ERROR_RETURN(X, Y) \ + if ((X) != (Y)) assert(0); +#else #define ERROR_RETURN(X, Y) \ if ((X) != (Y)) return false +#endif static size_t fread_mirror(void *ptr, size_t size, size_t nmemb, struct app *self) { @@ -214,16 +221,18 @@ static bool read_info(struct app *self, struct csa_info *i) { s = fread_mirror(&i->vm, sizeof i->vm, 1, self); ERROR_RETURN(s, 1); // vm == 115301884 seems to be ok... - assert(i->vm < 0x6df5dfd); + ERROR_RETURN(i->vm < 0x6df5dfd, true); // vr s = fread_mirror(i->vr, sizeof *i->vr, sizeof i->vr / sizeof *i->vr, self); ERROR_RETURN(s, 4); { const char *s = i->vr; - assert(s[0] >= 'A' && s[0] <= 'Z'); - assert(s[1] >= 'A' && s[1] <= 'Z'); - assert(s[2] == 0); - if (self->csa_type == SV10) assert(s[3] == 0); + ERROR_RETURN(s[0] >= 'A' && s[0] <= 'Z', true); + ERROR_RETURN(s[1] >= 'A' && s[1] <= 'Z', true); + ERROR_RETURN(s[2], 0); + if (self->csa_type == SV10) { + ERROR_RETURN(s[3], 0); + } } // syngodt (signed) s = fread_mirror(&i->syngodt, sizeof i->syngodt, 1, self); @@ -250,15 +259,15 @@ static bool read_data(struct app *self, struct csa_item_data *d) { uint32_t unused; s = fread_mirror(&unused, sizeof unused, 1, self); ERROR_RETURN(s, 1); - assert(unused == d->len || unused == 0x4d || unused == 0xcd); + ERROR_RETURN(unused == d->len || unused == 0x4d || unused == 0xcd, true); } if (d->len != 0) { const uint32_t padding_len = (4 - d->len % 4) % 4; const uint32_t padded_len = ((d->len + 3u) / 4u) * 4u; // (len + 3) & ~0x03 assert(padded_len == d->len + padding_len); // programmer error - d->buffer = (char *)realloc(d->buffer, padded_len); assert(padded_len != 0); + d->buffer = (char *)realloc(d->buffer, padded_len); ERROR_RETURN(d->buffer != NULL, true); s = fread_mirror(d->buffer, sizeof *d->buffer, padded_len, self); ERROR_RETURN(s, padded_len); diff --git a/Utilities/gdcmutfcpp/README.GDCM.txt b/Utilities/gdcmutfcpp/README.GDCM.txt deleted file mode 100644 index 36d9195bf0bc..000000000000 --- a/Utilities/gdcmutfcpp/README.GDCM.txt +++ /dev/null @@ -1,17 +0,0 @@ -I was looking for a UTF-8 lightweight library with a license compatible with GDCM. - -I (Mathieu Malaterre) decided to pick utfcpp: -http://sourceforge.net/projects/utfcpp/ - -Version 2.3.4 is included here, with no changes. - -Source: -http://sourceforge.net/projects/utfcpp/files/utf8cpp_2x/Release%202.3.4/utf8_v2_3_4.zip/download - -SHA 256 checksum: -3373cebb25d88c662a2b960c4d585daf9ae7b396031ecd786e7bb31b15d010ef - - -New location is: - -* https://github.com/nemtrif/utfcpp diff --git a/Utilities/gdcmutfcpp/utf8.h b/Utilities/gdcmutfcpp/utf8.h deleted file mode 100644 index 82b13f59f983..000000000000 --- a/Utilities/gdcmutfcpp/utf8.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "utf8/checked.h" -#include "utf8/unchecked.h" - -#endif // header guard diff --git a/Utilities/gdcmutfcpp/utf8/checked.h b/Utilities/gdcmutfcpp/utf8/checked.h deleted file mode 100644 index 133115513814..000000000000 --- a/Utilities/gdcmutfcpp/utf8/checked.h +++ /dev/null @@ -1,327 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "core.h" -#include - -namespace utf8 -{ - // Base for the exceptions that may be thrown from the library - class exception : public ::std::exception { - }; - - // Exceptions that may be thrown from the library functions. - class invalid_code_point : public exception { - uint32_t cp; - public: - invalid_code_point(uint32_t cp) : cp(cp) {} - virtual const char* what() const throw() { return "Invalid code point"; } - uint32_t code_point() const {return cp;} - }; - - class invalid_utf8 : public exception { - uint8_t u8; - public: - invalid_utf8 (uint8_t u) : u8(u) {} - virtual const char* what() const throw() { return "Invalid UTF-8"; } - uint8_t utf8_octet() const {return u8;} - }; - - class invalid_utf16 : public exception { - uint16_t u16; - public: - invalid_utf16 (uint16_t u) : u16(u) {} - virtual const char* what() const throw() { return "Invalid UTF-16"; } - uint16_t utf16_word() const {return u16;} - }; - - class not_enough_room : public exception { - public: - virtual const char* what() const throw() { return "Not enough space"; } - }; - - /// The library API - functions intended to be called by the users - - template - octet_iterator append(uint32_t cp, octet_iterator result) - { - if (!utf8::internal::is_code_point_valid(cp)) - throw invalid_code_point(cp); - - if (cp < 0x80) // one octet - *(result++) = static_cast(cp); - else if (cp < 0x800) { // two octets - *(result++) = static_cast((cp >> 6) | 0xc0); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else if (cp < 0x10000) { // three octets - *(result++) = static_cast((cp >> 12) | 0xe0); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else { // four octets - *(result++) = static_cast((cp >> 18) | 0xf0); - *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - return result; - } - - template - output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) - { - while (start != end) { - octet_iterator sequence_start = start; - internal::utf_error err_code = utf8::internal::validate_next(start, end); - switch (err_code) { - case internal::UTF8_OK : - for (octet_iterator it = sequence_start; it != start; ++it) - *out++ = *it; - break; - case internal::NOT_ENOUGH_ROOM: - throw not_enough_room(); - case internal::INVALID_LEAD: - out = utf8::append (replacement, out); - ++start; - break; - case internal::INCOMPLETE_SEQUENCE: - case internal::OVERLONG_SEQUENCE: - case internal::INVALID_CODE_POINT: - out = utf8::append (replacement, out); - ++start; - // just one replacement mark for the sequence - while (start != end && utf8::internal::is_trail(*start)) - ++start; - break; - } - } - return out; - } - - template - inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) - { - static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); - return utf8::replace_invalid(start, end, out, replacement_marker); - } - - template - uint32_t next(octet_iterator& it, octet_iterator end) - { - uint32_t cp = 0; - internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); - switch (err_code) { - case internal::UTF8_OK : - break; - case internal::NOT_ENOUGH_ROOM : - throw not_enough_room(); - case internal::INVALID_LEAD : - case internal::INCOMPLETE_SEQUENCE : - case internal::OVERLONG_SEQUENCE : - throw invalid_utf8(*it); - case internal::INVALID_CODE_POINT : - throw invalid_code_point(cp); - } - return cp; - } - - template - uint32_t peek_next(octet_iterator it, octet_iterator end) - { - return utf8::next(it, end); - } - - template - uint32_t prior(octet_iterator& it, octet_iterator start) - { - // can't do much if it == start - if (it == start) - throw not_enough_room(); - - octet_iterator end = it; - // Go back until we hit either a lead octet or start - while (utf8::internal::is_trail(*(--it))) - if (it == start) - throw invalid_utf8(*it); // error - no lead byte in the sequence - return utf8::peek_next(it, end); - } - - /// Deprecated in versions that include "prior" - template - uint32_t previous(octet_iterator& it, octet_iterator pass_start) - { - octet_iterator end = it; - while (utf8::internal::is_trail(*(--it))) - if (it == pass_start) - throw invalid_utf8(*it); // error - no lead byte in the sequence - octet_iterator temp = it; - return utf8::next(temp, end); - } - - template - void advance (octet_iterator& it, distance_type n, octet_iterator end) - { - for (distance_type i = 0; i < n; ++i) - utf8::next(it, end); - } - - template - typename std::iterator_traits::difference_type - distance (octet_iterator first, octet_iterator last) - { - typename std::iterator_traits::difference_type dist; - for (dist = 0; first < last; ++dist) - utf8::next(first, last); - return dist; - } - - template - octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) - { - while (start != end) { - uint32_t cp = utf8::internal::mask16(*start++); - // Take care of surrogate pairs first - if (utf8::internal::is_lead_surrogate(cp)) { - if (start != end) { - uint32_t trail_surrogate = utf8::internal::mask16(*start++); - if (utf8::internal::is_trail_surrogate(trail_surrogate)) - cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; - else - throw invalid_utf16(static_cast(trail_surrogate)); - } - else - throw invalid_utf16(static_cast(cp)); - - } - // Lone trail surrogate - else if (utf8::internal::is_trail_surrogate(cp)) - throw invalid_utf16(static_cast(cp)); - - result = utf8::append(cp, result); - } - return result; - } - - template - u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) - { - while (start != end) { - uint32_t cp = utf8::next(start, end); - if (cp > 0xffff) { //make a surrogate pair - *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); - *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); - } - else - *result++ = static_cast(cp); - } - return result; - } - - template - octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) - { - while (start != end) - result = utf8::append(*(start++), result); - - return result; - } - - template - u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) - { - while (start != end) - (*result++) = utf8::next(start, end); - - return result; - } - - // The iterator class - template - class iterator : public std::iterator { - octet_iterator it; - octet_iterator range_start; - octet_iterator range_end; - public: - iterator () {} - explicit iterator (const octet_iterator& octet_it, - const octet_iterator& range_start, - const octet_iterator& range_end) : - it(octet_it), range_start(range_start), range_end(range_end) - { - if (it < range_start || it > range_end) - throw std::out_of_range("Invalid utf-8 iterator position"); - } - // the default "big three" are OK - octet_iterator base () const { return it; } - uint32_t operator * () const - { - octet_iterator temp = it; - return utf8::next(temp, range_end); - } - bool operator == (const iterator& rhs) const - { - if (range_start != rhs.range_start || range_end != rhs.range_end) - throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); - return (it == rhs.it); - } - bool operator != (const iterator& rhs) const - { - return !(operator == (rhs)); - } - iterator& operator ++ () - { - utf8::next(it, range_end); - return *this; - } - iterator operator ++ (int) - { - iterator temp = *this; - utf8::next(it, range_end); - return temp; - } - iterator& operator -- () - { - utf8::prior(it, range_start); - return *this; - } - iterator operator -- (int) - { - iterator temp = *this; - utf8::prior(it, range_start); - return temp; - } - }; // class iterator - -} // namespace utf8 - -#endif //header guard - - diff --git a/Utilities/gdcmutfcpp/utf8/core.h b/Utilities/gdcmutfcpp/utf8/core.h deleted file mode 100644 index 693d388c078d..000000000000 --- a/Utilities/gdcmutfcpp/utf8/core.h +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include - -namespace utf8 -{ - // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers - // You may need to change them to match your system. - // These typedefs have the same names as ones from cstdint, or boost/cstdint - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - -// Helper code - not intended to be directly called by the library users. May be changed at any time -namespace internal -{ - // Unicode constants - // Leading (high) surrogates: 0xd800 - 0xdbff - // Trailing (low) surrogates: 0xdc00 - 0xdfff - const uint16_t LEAD_SURROGATE_MIN = 0xd800u; - const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; - const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; - const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; - const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); - const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; - - // Maximum valid value for a Unicode code point - const uint32_t CODE_POINT_MAX = 0x0010ffffu; - - template - inline uint8_t mask8(octet_type oc) - { - return static_cast(0xff & oc); - } - template - inline uint16_t mask16(u16_type oc) - { - return static_cast(0xffff & oc); - } - template - inline bool is_trail(octet_type oc) - { - return ((utf8::internal::mask8(oc) >> 6) == 0x2); - } - - template - inline bool is_lead_surrogate(u16 cp) - { - return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); - } - - template - inline bool is_trail_surrogate(u16 cp) - { - return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); - } - - template - inline bool is_surrogate(u16 cp) - { - return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); - } - - template - inline bool is_code_point_valid(u32 cp) - { - return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); - } - - template - inline typename std::iterator_traits::difference_type - sequence_length(octet_iterator lead_it) - { - uint8_t lead = utf8::internal::mask8(*lead_it); - if (lead < 0x80) - return 1; - else if ((lead >> 5) == 0x6) - return 2; - else if ((lead >> 4) == 0xe) - return 3; - else if ((lead >> 3) == 0x1e) - return 4; - else - return 0; - } - - template - inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) - { - if (cp < 0x80) { - if (length != 1) - return true; - } - else if (cp < 0x800) { - if (length != 2) - return true; - } - else if (cp < 0x10000) { - if (length != 3) - return true; - } - - return false; - } - - enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; - - /// Helper for get_sequence_x - template - utf_error increase_safely(octet_iterator& it, octet_iterator end) - { - if (++it == end) - return NOT_ENOUGH_ROOM; - - if (!utf8::internal::is_trail(*it)) - return INCOMPLETE_SEQUENCE; - - return UTF8_OK; - } - - #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} - - /// get_sequence_x functions decode utf-8 sequences of the length x - template - utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - return UTF8_OK; - } - - template - utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); - - return UTF8_OK; - } - - template - utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point += (*it) & 0x3f; - - return UTF8_OK; - } - - template - utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - if (it == end) - return NOT_ENOUGH_ROOM; - - code_point = utf8::internal::mask8(*it); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; - - UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) - - code_point += (*it) & 0x3f; - - return UTF8_OK; - } - - #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR - - template - utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) - { - // Save the original value of it so we can go back in case of failure - // Of course, it does not make much sense with i.e. stream iterators - octet_iterator original_it = it; - - uint32_t cp = 0; - // Determine the sequence length based on the lead octet - typedef typename std::iterator_traits::difference_type octet_difference_type; - const octet_difference_type length = utf8::internal::sequence_length(it); - - // Get trail octets and calculate the code point - utf_error err = UTF8_OK; - switch (length) { - case 0: - return INVALID_LEAD; - case 1: - err = utf8::internal::get_sequence_1(it, end, cp); - break; - case 2: - err = utf8::internal::get_sequence_2(it, end, cp); - break; - case 3: - err = utf8::internal::get_sequence_3(it, end, cp); - break; - case 4: - err = utf8::internal::get_sequence_4(it, end, cp); - break; - } - - if (err == UTF8_OK) { - // Decoding succeeded. Now, security checks... - if (utf8::internal::is_code_point_valid(cp)) { - if (!utf8::internal::is_overlong_sequence(cp, length)){ - // Passed! Return here. - code_point = cp; - ++it; - return UTF8_OK; - } - else - err = OVERLONG_SEQUENCE; - } - else - err = INVALID_CODE_POINT; - } - - // Failure branch - restore the original value of the iterator - it = original_it; - return err; - } - - template - inline utf_error validate_next(octet_iterator& it, octet_iterator end) { - uint32_t ignored; - return utf8::internal::validate_next(it, end, ignored); - } - -} // namespace internal - - /// The library API - functions intended to be called by the users - - // Byte order mark - const uint8_t bom[] = {0xef, 0xbb, 0xbf}; - - template - octet_iterator find_invalid(octet_iterator start, octet_iterator end) - { - octet_iterator result = start; - while (result != end) { - utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); - if (err_code != internal::UTF8_OK) - return result; - } - return result; - } - - template - inline bool is_valid(octet_iterator start, octet_iterator end) - { - return (utf8::find_invalid(start, end) == end); - } - - template - inline bool starts_with_bom (octet_iterator it, octet_iterator end) - { - return ( - ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && - ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && - ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) - ); - } - - //Deprecated in release 2.3 - template - inline bool is_bom (octet_iterator it) - { - return ( - (utf8::internal::mask8(*it++)) == bom[0] && - (utf8::internal::mask8(*it++)) == bom[1] && - (utf8::internal::mask8(*it)) == bom[2] - ); - } -} // namespace utf8 - -#endif // header guard - - diff --git a/Utilities/gdcmutfcpp/utf8/unchecked.h b/Utilities/gdcmutfcpp/utf8/unchecked.h deleted file mode 100644 index cb2427166b19..000000000000 --- a/Utilities/gdcmutfcpp/utf8/unchecked.h +++ /dev/null @@ -1,228 +0,0 @@ -// Copyright 2006 Nemanja Trifunovic - -/* -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - - -#ifndef UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 -#define UTF8_FOR_CPP_UNCHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 - -#include "core.h" - -namespace utf8 -{ - namespace unchecked - { - template - octet_iterator append(uint32_t cp, octet_iterator result) - { - if (cp < 0x80) // one octet - *(result++) = static_cast(cp); - else if (cp < 0x800) { // two octets - *(result++) = static_cast((cp >> 6) | 0xc0); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else if (cp < 0x10000) { // three octets - *(result++) = static_cast((cp >> 12) | 0xe0); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - else { // four octets - *(result++) = static_cast((cp >> 18) | 0xf0); - *(result++) = static_cast(((cp >> 12) & 0x3f)| 0x80); - *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); - *(result++) = static_cast((cp & 0x3f) | 0x80); - } - return result; - } - - template - uint32_t next(octet_iterator& it) - { - uint32_t cp = utf8::internal::mask8(*it); - typename std::iterator_traits::difference_type length = utf8::internal::sequence_length(it); - switch (length) { - case 1: - break; - case 2: - it++; - cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); - break; - case 3: - ++it; - cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); - ++it; - cp += (*it) & 0x3f; - break; - case 4: - ++it; - cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); - ++it; - cp += (utf8::internal::mask8(*it) << 6) & 0xfff; - ++it; - cp += (*it) & 0x3f; - break; - } - ++it; - return cp; - } - - template - uint32_t peek_next(octet_iterator it) - { - return utf8::unchecked::next(it); - } - - template - uint32_t prior(octet_iterator& it) - { - while (utf8::internal::is_trail(*(--it))) ; - octet_iterator temp = it; - return utf8::unchecked::next(temp); - } - - // Deprecated in versions that include prior, but only for the sake of consistency (see utf8::previous) - template - inline uint32_t previous(octet_iterator& it) - { - return utf8::unchecked::prior(it); - } - - template - void advance (octet_iterator& it, distance_type n) - { - for (distance_type i = 0; i < n; ++i) - utf8::unchecked::next(it); - } - - template - typename std::iterator_traits::difference_type - distance (octet_iterator first, octet_iterator last) - { - typename std::iterator_traits::difference_type dist; - for (dist = 0; first < last; ++dist) - utf8::unchecked::next(first); - return dist; - } - - template - octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) - { - while (start != end) { - uint32_t cp = utf8::internal::mask16(*start++); - // Take care of surrogate pairs first - if (utf8::internal::is_lead_surrogate(cp)) { - uint32_t trail_surrogate = utf8::internal::mask16(*start++); - cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; - } - result = utf8::unchecked::append(cp, result); - } - return result; - } - - template - u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) - { - while (start < end) { - uint32_t cp = utf8::unchecked::next(start); - if (cp > 0xffff) { //make a surrogate pair - *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); - *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); - } - else - *result++ = static_cast(cp); - } - return result; - } - - template - octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) - { - while (start != end) - result = utf8::unchecked::append(*(start++), result); - - return result; - } - - template - u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) - { - while (start < end) - (*result++) = utf8::unchecked::next(start); - - return result; - } - - // The iterator class - template - class iterator : public std::iterator { - octet_iterator it; - public: - iterator () {} - explicit iterator (const octet_iterator& octet_it): it(octet_it) {} - // the default "big three" are OK - octet_iterator base () const { return it; } - uint32_t operator * () const - { - octet_iterator temp = it; - return utf8::unchecked::next(temp); - } - bool operator == (const iterator& rhs) const - { - return (it == rhs.it); - } - bool operator != (const iterator& rhs) const - { - return !(operator == (rhs)); - } - iterator& operator ++ () - { - ::std::advance(it, utf8::internal::sequence_length(it)); - return *this; - } - iterator operator ++ (int) - { - iterator temp = *this; - ::std::advance(it, utf8::internal::sequence_length(it)); - return temp; - } - iterator& operator -- () - { - utf8::unchecked::prior(it); - return *this; - } - iterator operator -- (int) - { - iterator temp = *this; - utf8::unchecked::prior(it); - return temp; - } - }; // class iterator - - } // namespace utf8::unchecked -} // namespace utf8 - - -#endif // header guard -