Skip to content

Commit

Permalink
GDCM 2020-12-10 (b380cbac)
Browse files Browse the repository at this point in the history
Code extracted from:

    https://github.com/malaterre/GDCM.git

at commit b380cbace6df3deb6700a2a47a4bbb37218a1dba (release).

Change-Id: I1b727d9a7718d5e0abab4419b470db2a8f07a77e
  • Loading branch information
GDCM Upstream authored and thewtex committed Jan 5, 2021
1 parent 7b73de1 commit e161cd5
Show file tree
Hide file tree
Showing 19 changed files with 183 additions and 66 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ endif()
#----------------------------------------------------------------------------

project(GDCM
VERSION 3.0.7
VERSION 3.0.8
LANGUAGES CXX C
)
## NOTE: the "DESCRIPTION" feature of project() was introduced in cmake 3.10.0
Expand Down
8 changes: 4 additions & 4 deletions Source/Common/gdcmEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ inline std::ostream& operator<<(std::ostream& os, Event &e)
typedef classname Self; \
typedef super Superclass; \
classname() {} \
virtual ~classname() {} \
virtual const char * GetEventName() const { return #classname; } \
virtual bool CheckEvent(const ::gdcm::Event* e) const \
virtual ~classname() override = default; \
virtual const char * GetEventName() const override { return #classname; } \
virtual bool CheckEvent(const ::gdcm::Event* e) const override \
{ return dynamic_cast<const Self*>(e) ? true : false; } \
virtual ::gdcm::Event* MakeObject() const \
virtual ::gdcm::Event* MakeObject() const override \
{ return new Self; } \
classname(const Self&s) : super(s){}; \
private: \
Expand Down
10 changes: 5 additions & 5 deletions Source/Common/gdcmSystem.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -766,11 +766,11 @@ bool System::ParseDateTime(time_t &timep, long &milliseconds, const char date[22
{
switch (n)
{
case 1: mon = 1;
case 2: day = 1;
case 3: hour = 0;
case 4: min = 0;
case 5: sec = 0;
case 1: mon = 1; /* Falls through. */
case 2: day = 1; /* Falls through. */
case 3: hour = 0; /* Falls through. */
case 4: min = 0; /* Falls through. */
case 5: sec = 0; /* Falls through. */
break; // http://security.coverity.com/blog/2013/Sep/gimme-a-break.html
}
ptm.tm_year = year - 1900;
Expand Down
23 changes: 23 additions & 0 deletions Source/DataDictionary/gdcmPrivateDefaultDicts.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,29 @@ typedef struct
} DICT_ENTRY;

static const DICT_ENTRY DICOMV3DataDict [] = {
{0x2013,0x0010,"BioDICOMizer",VR::LO,VM::VM1,"Custom Storage Version",false},
{0x2013,0x0011,"BioDICOMizer",VR::ST,VM::VM1,"Custom Storage Former Filename",false},
{0x2013,0x0012,"BioDICOMizer",VR::LO,VM::VM1,"Custom Storage Mime-Type",false},
{0x2013,0x0013,"BioDICOMizer",VR::UL,VM::VM1,"Custom Storage File Length",false},
{0x2013,0x0016,"BioDICOMizer",VR::ST,VM::VM1,"Custom Storage Information Description",false},
{0x2013,0x0017,"BioDICOMizer",VR::UL,VM::VM1,"Custom Storage Number Of Segments",false},
{0x2013,0x0018,"BioDICOMizer",VR::IS,VM::VM1,"Custom Storage Last Byte Padded",false},
{0x2013,0x0010,"BioClinicaImaging",VR::LO,VM::VM1,"Custom Storage Version",false},
{0x2013,0x0011,"BioClinicaImaging",VR::ST,VM::VM1,"Custom Storage Former Filename",false},
{0x2013,0x0012,"BioClinicaImaging",VR::LO,VM::VM1,"Custom Storage Mime-Type",false},
{0x2013,0x0013,"BioClinicaImaging",VR::UL,VM::VM1,"Custom Storage File Length",false},
{0x2013,0x0016,"BioClinicaImaging",VR::ST,VM::VM1,"Custom Storage Information Description",false},
{0x2013,0x0017,"BioClinicaImaging",VR::UL,VM::VM1,"Custom Storage Number Of Segments",false},
{0x2013,0x0018,"BioClinicaImaging",VR::IS,VM::VM1,"Custom Storage Last Byte Padded",false},
{0x2013,0x0001,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #1",false},
{0x2013,0x0002,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #2",false},
{0x2013,0x0003,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #3",false},
{0x2013,0x0004,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #4",false},
{0x2013,0x0005,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #5",false},
{0x2013,0x0006,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #6",false},
{0x2013,0x0007,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #7",false},
{0x2013,0x0008,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #8",false},
{0x2013,0x0009,"BioClinicaImagingSegmentGroup",VR::OB,VM::VM1,"Custom Storage Segment Blob #9",false},
{0x7fe1,0x0001,"Bioclinica",VR::UT,VM::VM1,"??",false},
{0x7fe1,0x0002,"Bioclinica",VR::LO,VM::VM1,"??",false},
{0x7fe1,0x0003,"Bioclinica",VR::LO,VM::VM1,"??",false},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ class GDCM_EXPORT FileMetaInformation : public DataSet
MetaInformationTS = fmi.MetaInformationTS;
DataSetMS = fmi.DataSetMS;
}
FileMetaInformation& operator=(const FileMetaInformation& fmi)
{
DataSetTS = fmi.DataSetTS;
MetaInformationTS = fmi.MetaInformationTS;
DataSetMS = fmi.DataSetMS;
return *this;
}

VL GetFullLength() const {
return P.GetLength() + DataSet::GetLength<ExplicitDataElement>();
Expand Down
46 changes: 16 additions & 30 deletions Source/DataStructureAndEncodingDefinition/gdcmMediaStorage.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ static const char *MSStrings[] = {
"1.2.840.10008.5.1.4.1.1.4.3", // EnhancedMRColorImageStorage
"1.2.392.200036.9125.1.1.4", // FujiPrivateMammoCRImageStorage (aka FUJI MAMMO CR Storage)
"1.2.840.10008.5.1.4.1.1.77.1.5.2", // Ophthalmic Photography 16 Bit Image Storage
"1.2.840.10008.5.1.4.1.1.77.1.2.1", // VideoMicroscopicImageStorage

nullptr
};
Expand Down Expand Up @@ -341,6 +342,7 @@ static const MSModalityType MSModalityTypes[] = {
{"MR", 3, false},// EnhancedMRColorImageStorage
{"MG", 2, false},// FujiPrivateMammoCRImageStorage
{"OP", 3, false},// OphthalmicPhotography16BitImageStorage
{"GM", 3, false},// VideoMicroscopicImageStorage
{nullptr, 0, false} //MS_END
};

Expand Down Expand Up @@ -401,15 +403,14 @@ void MediaStorage::GuessFromModality(const char *modality, unsigned int dim )
}
}

const char* MediaStorage::GetFromDataSetOrHeader(DataSet const &ds, const Tag & tag)
std::string MediaStorage::GetFromDataSetOrHeader(DataSet const &ds, const Tag & tag)
{
static std::string ret;
if( ds.FindDataElement( tag ) )
{
const ByteValue *sopclassuid = ds.GetDataElement( tag ).GetByteValue();
// Empty SOP Class UID:
// lifetechmed/A0038329.DCM
if( !sopclassuid || !sopclassuid->GetPointer() ) return nullptr;
if( !sopclassuid || !sopclassuid->GetPointer() ) return std::string();
std::string sopclassuid_str(
sopclassuid->GetPointer(),
sopclassuid->GetLength() );
Expand All @@ -419,18 +420,17 @@ const char* MediaStorage::GetFromDataSetOrHeader(DataSet const &ds, const Tag &
std::string::size_type pos = sopclassuid_str.find_last_of(' ');
sopclassuid_str = sopclassuid_str.substr(0,pos);
}
ret = sopclassuid_str.c_str();
return ret.c_str();
return sopclassuid_str;
}
return nullptr;
return std::string();
}

bool MediaStorage::SetFromDataSetOrHeader(DataSet const &ds, const Tag & tag)
{
const char * ms_str = GetFromDataSetOrHeader(ds,tag);
if( ms_str )
std::string ms_str = GetFromDataSetOrHeader(ds,tag);
if( !ms_str.empty() )
{
MediaStorage ms = MediaStorage::GetMSType(ms_str);
MediaStorage ms = MediaStorage::GetMSType(ms_str.c_str());
MSField = ms;
if( ms == MS_END )
{
Expand All @@ -442,7 +442,7 @@ bool MediaStorage::SetFromDataSetOrHeader(DataSet const &ds, const Tag & tag)
return false;
}

const char* MediaStorage::GetFromHeader(FileMetaInformation const &fmi)
std::string MediaStorage::GetFromHeader(FileMetaInformation const &fmi)
{
const Tag tmediastoragesopclassuid(0x0002, 0x0002);
return GetFromDataSetOrHeader(fmi, tmediastoragesopclassuid);
Expand All @@ -454,7 +454,7 @@ bool MediaStorage::SetFromHeader(FileMetaInformation const &fmi)
return SetFromDataSetOrHeader(fmi, tmediastoragesopclassuid);
}

const char* MediaStorage::GetFromDataSet(DataSet const &ds)
std::string MediaStorage::GetFromDataSet(DataSet const &ds)
{
const Tag tsopclassuid(0x0008, 0x0016);
return GetFromDataSetOrHeader(ds, tsopclassuid);
Expand Down Expand Up @@ -555,38 +555,24 @@ bool MediaStorage::SetFromFile(File const &file)
* are a pain to handle ...
*/
const FileMetaInformation &header = file.GetHeader();
const char* header_ms_ptr = GetFromHeader(header);
std::string copy1;
const char *header_ms_str = nullptr;
if( header_ms_ptr )
{
copy1 = header_ms_ptr;
header_ms_str = copy1.c_str();
}
std::string header_ms_str = GetFromHeader(header);
const DataSet &ds = file.GetDataSet();
const char* ds_ms_ptr = GetFromDataSet(ds);
std::string copy2;
const char *ds_ms_str = nullptr;
if( ds_ms_ptr )
{
copy2 = ds_ms_ptr;
ds_ms_str = copy2.c_str();
}
std::string ds_ms_str = GetFromDataSet(ds);

// Easy case:
if( header_ms_str && ds_ms_str && strcmp(header_ms_str, ds_ms_str) == 0 )
if( !header_ms_str.empty() && !ds_ms_str.empty() && (header_ms_str == ds_ms_str) )
{
return SetFromHeader( header );
}

if( ds_ms_str )
if( !ds_ms_str.empty() )
{
// means either no header ms or different, take from dataset just in case
return SetFromDataSet( ds );
}

// Looks suspicious or DICOMDIR...
if( header_ms_str )
if( !header_ms_str.empty() )
{
return SetFromHeader( header );
}
Expand Down
11 changes: 5 additions & 6 deletions Source/DataStructureAndEncodingDefinition/gdcmMediaStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class GDCM_EXPORT MediaStorage
EnhancedMRColorImageStorage,
FujiPrivateMammoCRImageStorage,
OphthalmicPhotography16BitImageStorage,
VideoMicroscopicImageStorage,
MS_END
} MSType; // Media Storage Type

Expand Down Expand Up @@ -201,12 +202,10 @@ typedef enum {

private:
bool SetFromDataSetOrHeader(DataSet const &ds, const Tag & tag);
/// NOT THREAD SAFE
const char* GetFromDataSetOrHeader(DataSet const &ds, const Tag & tag);
/// NOT THREAD SAFE
const char* GetFromHeader(FileMetaInformation const &fmi);
/// NOT THREAD SAFE
const char* GetFromDataSet(DataSet const &ds);

std::string GetFromDataSetOrHeader(DataSet const &ds, const Tag & tag);
std::string GetFromHeader(FileMetaInformation const &fmi);
std::string GetFromDataSet(DataSet const &ds);

private:
MSType MSField;
Expand Down
10 changes: 6 additions & 4 deletions Source/DataStructureAndEncodingDefinition/gdcmParseException.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,19 @@ namespace gdcm_ns
class ParseException : public Exception
{
public:
ParseException()
= default;
ParseException() = default;
~ParseException() throw() override {};

/** Assignment operator. */
ParseException &operator= ( const ParseException &orig )
{
(void)orig;
//TODO
LastElement = orig.LastElement;
return *this;
}
ParseException(const ParseException& orig):Exception(orig)
{
LastElement = orig.LastElement;
}

/** Equivalence operator. */
/* virtual bool operator==( const ParseException &orig )
Expand Down
2 changes: 2 additions & 0 deletions Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static bool prepare_file( FILE * pFile, const off64_t offset, const off64_t insl
char buffer[BUFFERSIZE];
struct stat sb;

assert( pFile );
int fd = fileno( pFile );
if (fstat(fd, &sb) == 0)
{
Expand Down Expand Up @@ -366,6 +367,7 @@ class FileStreamerInternals
}
else
{
assert( pFile );
const off64_t curpos = FTello(pFile);
assert( curpos == thepos );
if( ReservedDataLength >= (off64_t)len )
Expand Down
1 change: 1 addition & 0 deletions Source/MediaStorageAndFileFormat/gdcmFileStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class GDCM_EXPORT FileStreamer : public Subject
/// startoffset can be used to specify the very first element you want to
/// start with (instead of the first possible). Value should be in [0x0, 0xff]
/// This will find the first available private creator.
/// \bug maxsizede should be a value lower than the actual total size of the buffer to be copied
bool StartGroupDataElement( const PrivateTag & pt, size_t maxsizede = 0, uint8_t startoffset = 0 );
/// Append to previously started private creator
bool AppendToGroupDataElement( const PrivateTag & pt, const char *array, size_t len );
Expand Down
18 changes: 15 additions & 3 deletions Source/MediaStorageAndFileFormat/gdcmJPEG2000Codec.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,10 @@ std::pair<char *, size_t> JPEG2000Codec::DecodeByStreamsCommon(char *dummy_buffe
file_length--;
}
// what if 0xd9 is never found ?
assert( file_length > 0 && src[file_length-1] == 0xd9 );
if( !( file_length > 0 && src[file_length-1] == 0xd9 ) )
{
return std::make_pair( nullptr, 0 );
}

/* set decoding parameters to default values */
opj_set_default_decoder_parameters(&parameters);
Expand Down Expand Up @@ -1269,7 +1272,7 @@ bool JPEG2000Codec::CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t &

myfile mysrc;
myfile *fsrc = &mysrc;
char *buffer_j2k = new char[inputlength]; // overallocated
char *buffer_j2k = new char[inputlength * 2]; // overallocated for weird case
fsrc->mem = fsrc->cur = buffer_j2k;
fsrc->len = 0; //inputlength;

Expand Down Expand Up @@ -1687,6 +1690,8 @@ bool JPEG2000Codec::DecodeExtent(
{
size_t fraglen = frag.GetVL();
size_t oldlen = vdummybuffer.size();
if( fraglen == 0 && oldlen == 0 )
break;
// update
buf_size = fraglen + oldlen;
vdummybuffer.resize( buf_size );
Expand Down Expand Up @@ -1771,7 +1776,14 @@ bool JPEG2000Codec::DecodeExtent(
if( !raw_len.first || !raw_len.second ) return false;
// check pixel format *after* DecodeByStreamsCommon !
const PixelFormat & pf2 = this->GetPixelFormat();
if( pf != pf2 ) return false;
if( pf.GetSamplesPerPixel() != pf2.GetSamplesPerPixel()
|| pf.GetBitsAllocated() != pf2.GetBitsAllocated()
)
{
gdcmErrorMacro( "Invalid PixelFormat found (mismatch DICOM vs J2K)" );
return false;
}


char *raw = raw_len.first;
const unsigned int rowsize = xmax - xmin + 1;
Expand Down
50 changes: 48 additions & 2 deletions Source/MediaStorageAndFileFormat/gdcmOverlay.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ void Overlay::Update(const DataElement & de)
// if OverlayBitsAllocated is 16 it imply Overlay in unused pixel bits
if( at.GetValue() != 1 )
{
gdcmWarningMacro( "Unsuported OverlayBitsAllocated: " << at.GetValue() );
gdcmDebugMacro( "Unsuported OverlayBitsAllocated: " << at.GetValue() );
}
SetBitsAllocated( at.GetValue() );
}
Expand Down Expand Up @@ -257,7 +257,53 @@ bool Overlay::GrabOverlayFromPixelData(DataSet const &ds)
{
const unsigned int ovlength = Internal->Rows * Internal->Columns / 8;
Internal->Data.resize( ovlength ); // set to 0
if( Internal->BitsAllocated == 16 )
if( Internal->BitsAllocated == 8 )
{
if( !ds.FindDataElement( Tag(0x7fe0,0x0010) ) )
{
gdcmWarningMacro("Could not find Pixel Data. Cannot extract Overlay." );
return false;
}
const DataElement &pixeldata = ds.GetDataElement( Tag(0x7fe0,0x0010) );
const ByteValue *bv = pixeldata.GetByteValue();
if( !bv )
{
gdcmWarningMacro("Could not extract overlay from encapsulated stream." );
return false;
}
const char *array = bv->GetPointer();
const unsigned int length = ovlength * 8 * 1; //bv->GetLength();
const uint8_t *p = (const uint8_t*)(const void*)array;
const uint8_t *end = (const uint8_t*)(const void*)(array + length);
assert( 8 * ovlength == (unsigned int)Internal->Rows * Internal->Columns );
if( Internal->Data.empty() )
{
gdcmWarningMacro("Internal Data is empty." );
return false;
}
unsigned char * overlay = (unsigned char*)&Internal->Data[0];
int c = 0;
uint8_t pmask = (uint8_t)(1 << Internal->BitPosition);
assert( length / 1 == ovlength * 8 );
while( p != end )
{
const uint8_t val = *p & pmask;
assert( val == 0x0 || val == pmask );
// 128 -> 0x80
if( val )
{
overlay[ c / 8 ] |= (unsigned char)(0x1 << c%8);
}
else
{
// else overlay[ c / 8 ] is already 0
}
++p;
++c;
}
assert( (unsigned)c / 8 == ovlength );
}
else if( Internal->BitsAllocated == 16 )
{
//assert( Internal->BitPosition >= 12 );
if( !ds.FindDataElement( Tag(0x7fe0,0x0010) ) )
Expand Down
Loading

0 comments on commit e161cd5

Please sign in to comment.