forked from pool/dcmtk
Compare commits
17 Commits
| Author | SHA256 | Date | |
|---|---|---|---|
| d4fb3533e4 | |||
|
|
6a17e471db | ||
|
|
7c5ae0880b | ||
|
|
3316ef937a | ||
| 712786f580 | |||
|
|
12934b1da2 | ||
| 7b378e4339 | |||
|
|
3fee1869be | ||
| 46d5457a5c | |||
|
|
f7094eee3f | ||
|
|
1d655fa6db | ||
|
|
f1d25f7a15 | ||
| 44f5842d6f | |||
|
|
eb3b79e18d | ||
| a229ea85f3 | |||
|
|
d46ae2f526 | ||
|
|
a3512f14ef |
@@ -1,69 +0,0 @@
|
||||
From 66c317feae446deda1a389226aa24c95a0eeac4c Mon Sep 17 00:00:00 2001
|
||||
From: Marco Eichelberg <dicom@offis.de>
|
||||
Date: Wed, 13 Mar 2024 23:03:40 +0100
|
||||
Subject: [PATCH] Fixed DcmDecimalString unit tests.
|
||||
|
||||
---
|
||||
dcmdata/tests/tvrds.cc | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dcmdata/tests/tvrds.cc b/dcmdata/tests/tvrds.cc
|
||||
index a9132a341..0e929304d 100644
|
||||
--- a/dcmdata/tests/tvrds.cc
|
||||
+++ b/dcmdata/tests/tvrds.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 2011-2020, OFFIS e.V.
|
||||
+ * Copyright (C) 2011-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
OFTEST(dcmdata_decimalString_1)
|
||||
{
|
||||
- DcmDecimalString decStr(DCM_ContourData, EVR_DS);
|
||||
+ DcmDecimalString decStr(DCM_ContourData);
|
||||
OFVector<Float64> doubleVals;
|
||||
OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\+500.005\\6.66E-01").good());
|
||||
OFCHECK(decStr.getFloat64Vector(doubleVals).good());
|
||||
@@ -45,7 +45,7 @@ OFTEST(dcmdata_decimalString_1)
|
||||
|
||||
OFTEST(dcmdata_decimalString_2)
|
||||
{
|
||||
- DcmDecimalString decStr(DCM_ContourData, EVR_DS);
|
||||
+ DcmDecimalString decStr(DCM_ContourData);
|
||||
OFVector<Float64> doubleVals;
|
||||
/* insert a NULL byte into the string */
|
||||
OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\0\\+500.005\\6.66E-01", 34).good());
|
||||
@@ -61,7 +61,7 @@ OFTEST(dcmdata_decimalString_2)
|
||||
|
||||
OFTEST(dcmdata_decimalString_3)
|
||||
{
|
||||
- DcmDecimalString decStr(DCM_ContourData, EVR_DS);
|
||||
+ DcmDecimalString decStr(DCM_ContourData);
|
||||
OFVector<Float64> doubleVals;
|
||||
/* insert a NULL byte into the string */
|
||||
OFCHECK(decStr.putOFStringArray(OFString("1\\2.0\\3.5\\-4.99\0\\+500.005\\6.66E-01", 34)).good());
|
||||
@@ -77,7 +77,7 @@ OFTEST(dcmdata_decimalString_3)
|
||||
|
||||
OFTEST(dcmdata_decimalString_4)
|
||||
{
|
||||
- DcmDecimalString decStr(DCM_ContourData, EVR_DS);
|
||||
+ DcmDecimalString decStr(DCM_ContourData);
|
||||
OFVector<Float64> doubleVals;
|
||||
OFCHECK(decStr.putString("1\\2.0\\3.5\\-4.99\\+500.005\\6.66E-01\\").good());
|
||||
OFCHECK_EQUAL(decStr.getVM(), 7);
|
||||
@@ -96,7 +96,7 @@ OFTEST(dcmdata_decimalString_putFloat64)
|
||||
{
|
||||
// Test insertion in the beginning
|
||||
OFString testStr;
|
||||
- DcmDecimalString decStr(DCM_ContourData, EVR_DS);
|
||||
+ DcmDecimalString decStr(DCM_ContourData);
|
||||
OFCHECK(decStr.putFloat64(0, 0).good());
|
||||
decStr.getOFStringArray(testStr);
|
||||
OFCHECK(testStr == "0");
|
||||
--
|
||||
2.44.0
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
From 31ff413f97839c61752875569862a94a6cce06dd Mon Sep 17 00:00:00 2001
|
||||
From: Marco Eichelberg <dicom@offis.de>
|
||||
Date: Thu, 28 Dec 2023 17:32:42 +0100
|
||||
Subject: [PATCH] Fixed buffer overflow in decompression codecs.
|
||||
|
||||
Fixed the computation of the element size for the decompressed PixelData
|
||||
element in all decompression codecs. In the case of datasets that cannot
|
||||
be decoded to an unencapsulated transfer syntax, since the resulting
|
||||
pixel data would be larger than 4 GByte, an overflow of the size
|
||||
variable remained undetected and could lead to a segmentation fault due
|
||||
to a buffer overrun.
|
||||
|
||||
This closes DCMTK issue #1099.
|
||||
---
|
||||
dcmdata/libsrc/dcrleccd.cc | 39 ++++++++++++++++++++++++++++++--------
|
||||
dcmjpeg/libsrc/djcodecd.cc | 36 ++++++++++++++++++++++++++++++-----
|
||||
dcmjpls/libsrc/djcodecd.cc | 17 ++++++++++++++++-
|
||||
3 files changed, 78 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/dcmdata/libsrc/dcrleccd.cc b/dcmdata/libsrc/dcrleccd.cc
|
||||
index ffdd14116..5ddc8f6be 100644
|
||||
--- a/dcmdata/libsrc/dcrleccd.cc
|
||||
+++ b/dcmdata/libsrc/dcrleccd.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 2002-2020, OFFIS e.V.
|
||||
+ * Copyright (C) 2002-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -129,9 +129,25 @@ OFCondition DcmRLECodecDecoder::decode(
|
||||
if (rledecoder.fail()) result = EC_MemoryExhausted; // RLE decoder failed to initialize
|
||||
else
|
||||
{
|
||||
- const size_t frameSize = OFstatic_cast(size_t, imageBytesAllocated) * OFstatic_cast(size_t, imageRows)
|
||||
- * OFstatic_cast(size_t, imageColumns) * OFstatic_cast(size_t, imageSamplesPerPixel);
|
||||
- size_t totalSize = frameSize * imageFrames;
|
||||
+ // compute size of uncompressed frame, in bytes
|
||||
+ Uint32 frameSize = imageBytesAllocated * imageRows * imageColumns * imageSamplesPerPixel;
|
||||
+
|
||||
+ // check for overflow
|
||||
+ if (imageRows != 0 && frameSize / imageRows != (imageBytesAllocated * imageColumns * imageSamplesPerPixel))
|
||||
+ {
|
||||
+ DCMDATA_WARN("Cannot decompress image because uncompressed representation would exceed maximum possible size of PixelData attribute.");
|
||||
+ return EC_ElemLengthExceeds32BitField;
|
||||
+ }
|
||||
+
|
||||
+ Uint32 totalSize = frameSize * imageFrames;
|
||||
+
|
||||
+ // check for overflow
|
||||
+ if (totalSize == 0xFFFFFFFF || (frameSize != 0 && totalSize / frameSize != OFstatic_cast(Uint32, imageFrames)))
|
||||
+ {
|
||||
+ DCMDATA_WARN("Cannot decompress image because uncompressed representation would exceed maximum possible size of PixelData attribute.");
|
||||
+ return EC_ElemLengthExceeds32BitField;
|
||||
+ }
|
||||
+
|
||||
if (totalSize & 1) totalSize++; // align on 16-bit word boundary
|
||||
Uint16 *imageData16 = NULL;
|
||||
Sint32 currentFrame = 0;
|
||||
@@ -139,7 +155,7 @@ OFCondition DcmRLECodecDecoder::decode(
|
||||
Uint32 numberOfStripes = 0;
|
||||
Uint32 fragmentLength = 0;
|
||||
|
||||
- result = uncompressedPixelData.createUint16Array(OFstatic_cast(Uint32, totalSize/sizeof(Uint16)), imageData16);
|
||||
+ result = uncompressedPixelData.createUint16Array(totalSize/sizeof(Uint16), imageData16);
|
||||
if (result.good())
|
||||
{
|
||||
Uint8 *imageData8 = OFreinterpret_cast(Uint8 *, imageData16);
|
||||
@@ -463,7 +479,7 @@ OFCondition DcmRLECodecDecoder::decodeFrame(
|
||||
Uint16 imageColumns = 0;
|
||||
Sint32 imageFrames = 1;
|
||||
Uint16 imageBitsAllocated = 0;
|
||||
- Uint16 imageBytesAllocated = 0;
|
||||
+ Uint32 imageBytesAllocated = 0;
|
||||
Uint16 imagePlanarConfiguration = 0;
|
||||
Uint32 rleHeader[16];
|
||||
OFString photometricInterpretation;
|
||||
@@ -476,7 +492,7 @@ OFCondition DcmRLECodecDecoder::decodeFrame(
|
||||
if (result.good()) result = dataset->findAndGetOFString(DCM_PhotometricInterpretation, photometricInterpretation);
|
||||
if (result.good())
|
||||
{
|
||||
- imageBytesAllocated = OFstatic_cast(Uint16, imageBitsAllocated / 8);
|
||||
+ imageBytesAllocated = OFstatic_cast(Uint32, imageBitsAllocated / 8);
|
||||
if ((imageBitsAllocated < 8)||(imageBitsAllocated % 8 != 0))
|
||||
{
|
||||
DCMDATA_ERROR("The RLE decoder only supports images where BitsAllocated is a multiple of 8.");
|
||||
@@ -500,9 +516,16 @@ OFCondition DcmRLECodecDecoder::decodeFrame(
|
||||
const size_t bytesPerStripe = OFstatic_cast(size_t, imageColumns) * OFstatic_cast(size_t, imageRows);
|
||||
Uint32 numberOfStripes = 0;
|
||||
Uint32 fragmentLength = 0;
|
||||
- Uint32 frameSize = OFstatic_cast(Uint32, imageBytesAllocated) * OFstatic_cast(Uint32, imageRows)
|
||||
+ Uint32 frameSize = imageBytesAllocated * OFstatic_cast(Uint32, imageRows)
|
||||
* OFstatic_cast(Uint32, imageColumns) * OFstatic_cast(Uint32, imageSamplesPerPixel);
|
||||
|
||||
+ // check for overflow
|
||||
+ if (imageRows != 0 && frameSize / imageRows != (imageBytesAllocated * imageColumns * imageSamplesPerPixel))
|
||||
+ {
|
||||
+ DCMDATA_WARN("Cannot decompress image because uncompressed representation would exceed maximum possible size of PixelData attribute.");
|
||||
+ return EC_ElemLengthExceeds32BitField;
|
||||
+ }
|
||||
+
|
||||
if (frameSize > bufSize) return EC_IllegalCall;
|
||||
|
||||
DcmRLEDecoder rledecoder(bytesPerStripe);
|
||||
diff --git a/dcmjpeg/libsrc/djcodecd.cc b/dcmjpeg/libsrc/djcodecd.cc
|
||||
index 364b75533..a93a8104b 100644
|
||||
--- a/dcmjpeg/libsrc/djcodecd.cc
|
||||
+++ b/dcmjpeg/libsrc/djcodecd.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 2001-2022, OFFIS e.V.
|
||||
+ * Copyright (C) 2001-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -150,8 +150,25 @@ OFCondition DJCodecDecoder::decode(
|
||||
if (jpeg == NULL) result = EC_MemoryExhausted;
|
||||
else
|
||||
{
|
||||
- size_t frameSize = ((precision > 8) ? sizeof(Uint16) : sizeof(Uint8)) * imageRows * imageColumns * imageSamplesPerPixel;
|
||||
- size_t totalSize = frameSize * imageFrames;
|
||||
+ Uint32 imageBytesAllocated = (precision > 8) ? sizeof(Uint16) : sizeof(Uint8);
|
||||
+ Uint32 frameSize = imageBytesAllocated * imageRows * imageColumns * imageSamplesPerPixel;
|
||||
+
|
||||
+ // check for overflow
|
||||
+ if (imageRows != 0 && frameSize / imageRows != (imageBytesAllocated * imageColumns * imageSamplesPerPixel))
|
||||
+ {
|
||||
+ DCMJPEG_WARN("Cannot decompress image because uncompressed representation would exceed maximum possible size of PixelData attribute.");
|
||||
+ return EC_ElemLengthExceeds32BitField;
|
||||
+ }
|
||||
+
|
||||
+ Uint32 totalSize = frameSize * imageFrames;
|
||||
+
|
||||
+ // check for overflow
|
||||
+ if (totalSize == 0xFFFFFFFF || (frameSize != 0 && totalSize / frameSize != OFstatic_cast(Uint32, imageFrames)))
|
||||
+ {
|
||||
+ DCMJPEG_WARN("Cannot decompress image because uncompressed representation would exceed maximum possible size of PixelData attribute.");
|
||||
+ return EC_ElemLengthExceeds32BitField;
|
||||
+ }
|
||||
+
|
||||
if (totalSize & 1) totalSize++; // align on 16-bit word boundary
|
||||
Uint16 *imageData16 = NULL;
|
||||
Sint32 currentFrame = 0;
|
||||
@@ -166,7 +183,7 @@ OFCondition DJCodecDecoder::decode(
|
||||
}
|
||||
}
|
||||
|
||||
- result = uncompressedPixelData.createUint16Array(OFstatic_cast(Uint32, totalSize / sizeof(Uint16)), imageData16);
|
||||
+ result = uncompressedPixelData.createUint16Array(totalSize / sizeof(Uint16), imageData16);
|
||||
if (result.good())
|
||||
{
|
||||
Uint8 *imageData8 = OFreinterpret_cast(Uint8*, imageData16);
|
||||
@@ -492,7 +509,16 @@ OFCondition DJCodecDecoder::decodeFrame(
|
||||
if (precision == 0) result = EC_CannotChangeRepresentation; // something has gone wrong, bail out
|
||||
else
|
||||
{
|
||||
- size_t frameSize = ((precision > 8) ? sizeof(Uint16) : sizeof(Uint8)) * imageRows * imageColumns * imageSamplesPerPixel;
|
||||
+ Uint32 imageBytesAllocated = (precision > 8) ? sizeof(Uint16) : sizeof(Uint8);
|
||||
+ Uint32 frameSize = imageBytesAllocated * imageRows * imageColumns * imageSamplesPerPixel;
|
||||
+
|
||||
+ // check for overflow
|
||||
+ if (imageRows != 0 && frameSize / imageRows != (imageBytesAllocated * imageColumns * imageSamplesPerPixel))
|
||||
+ {
|
||||
+ DCMJPEG_WARN("Cannot decompress image because uncompressed representation would exceed maximum possible size of PixelData attribute.");
|
||||
+ return EC_ElemLengthExceeds32BitField;
|
||||
+ }
|
||||
+
|
||||
if (frameSize > bufSize) return EC_IllegalCall;
|
||||
|
||||
DJDecoder *jpeg = createDecoderInstance(fromParam, djcp, precision, isYBR);
|
||||
diff --git a/dcmjpls/libsrc/djcodecd.cc b/dcmjpls/libsrc/djcodecd.cc
|
||||
index e04a21e0d..45e6fec56 100644
|
||||
--- a/dcmjpls/libsrc/djcodecd.cc
|
||||
+++ b/dcmjpls/libsrc/djcodecd.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 2007-2022, OFFIS e.V.
|
||||
+ * Copyright (C) 2007-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -143,8 +143,23 @@ OFCondition DJLSDecoderBase::decode(
|
||||
// compute size of uncompressed frame, in bytes
|
||||
Uint32 frameSize = bytesPerSample * imageRows * imageColumns * imageSamplesPerPixel;
|
||||
|
||||
+ // check for overflow
|
||||
+ if (imageRows != 0 && frameSize / imageRows != (bytesPerSample * imageColumns * imageSamplesPerPixel))
|
||||
+ {
|
||||
+ DCMJPLS_WARN("Cannot decompress image because uncompressed representation would exceed maximum possible size of PixelData attribute.");
|
||||
+ return EC_ElemLengthExceeds32BitField;
|
||||
+ }
|
||||
+
|
||||
// compute size of pixel data attribute, in bytes
|
||||
Uint32 totalSize = frameSize * imageFrames;
|
||||
+
|
||||
+ // check for overflow
|
||||
+ if (totalSize == 0xFFFFFFFF || (frameSize != 0 && totalSize / frameSize != OFstatic_cast(Uint32, imageFrames)))
|
||||
+ {
|
||||
+ DCMJPLS_WARN("Cannot decompress image because uncompressed representation would exceed maximum possible size of PixelData attribute.");
|
||||
+ return EC_ElemLengthExceeds32BitField;
|
||||
+ }
|
||||
+
|
||||
if (totalSize & 1) totalSize++; // align on 16-bit word boundary
|
||||
|
||||
// assume we can cast the codec parameter to what we need
|
||||
--
|
||||
2.44.0
|
||||
|
||||
@@ -1,611 +0,0 @@
|
||||
From c5d8818f68c991cb580c7d52cc2ed99391259ce9 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Onken <onken@open-connections.de>
|
||||
Date: Tue, 20 Feb 2024 10:50:28 +0100
|
||||
Subject: [PATCH] Fixed possible overflows when allocating memory.
|
||||
|
||||
Thanks to GitHub user "bananabr" (Daniel Berredo) for the report and
|
||||
suggested patch.
|
||||
---
|
||||
dcmect/libsrc/enhanced_ct.cc | 14 +-
|
||||
dcmect/tests/CMakeLists.txt | 1 +
|
||||
dcmect/tests/Makefile.dep | 151 +++++++++++++++
|
||||
dcmect/tests/t_overflow.cc | 360 +++++++++++++++++++++++++++++++++++
|
||||
dcmect/tests/tests.cc | 3 +-
|
||||
5 files changed, 527 insertions(+), 2 deletions(-)
|
||||
create mode 100644 dcmect/tests/t_overflow.cc
|
||||
|
||||
diff --git a/dcmect/libsrc/enhanced_ct.cc b/dcmect/libsrc/enhanced_ct.cc
|
||||
index 6193742..47d6335 100644
|
||||
--- a/dcmect/libsrc/enhanced_ct.cc
|
||||
+++ b/dcmect/libsrc/enhanced_ct.cc
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "dcmtk/dcmect/types.h"
|
||||
#include "dcmtk/dcmfg/concatenationcreator.h"
|
||||
#include "dcmtk/dcmfg/concatenationloader.h"
|
||||
+#include "dcmtk/dcmfg/fgtypes.h"
|
||||
#include "dcmtk/dcmiod/iodutil.h"
|
||||
#include "dcmtk/dcmiod/modimagepixel.h"
|
||||
|
||||
@@ -100,8 +101,19 @@ struct EctEnhancedCT::WriteVisitor
|
||||
m_CT.getRows(rows);
|
||||
m_CT.getColumns(cols);
|
||||
const size_t numFrames = m_CT.m_Frames.size();
|
||||
+ if (numFrames > 2147483647)
|
||||
+ {
|
||||
+ DCMECT_ERROR("More than 2147483647 frames provided");
|
||||
+ return FG_EC_PixelDataTooLarge;
|
||||
+ }
|
||||
+ const size_t numPixelsFrame = OFstatic_cast(size_t, rows) * OFstatic_cast(size_t, cols);
|
||||
const size_t numBytesFrame = m_CT.m_Frames[0]->length;
|
||||
- const size_t numPixelsFrame = rows * cols;
|
||||
+ if (numBytesFrame != numPixelsFrame * 2)
|
||||
+ {
|
||||
+ DCMECT_ERROR("Invalid number of bytes per frame: Expected " << numPixelsFrame * 2 << " but got "
|
||||
+ << numBytesFrame << " frame pixel data");
|
||||
+ return ECT_InvalidPixelInfo;
|
||||
+ }
|
||||
// Creates the correct pixel data element, based on the image pixel module used.
|
||||
DcmPixelData* pixData = new DcmPixelData(DCM_PixelData);
|
||||
OFCondition result;
|
||||
diff --git a/dcmect/tests/CMakeLists.txt b/dcmect/tests/CMakeLists.txt
|
||||
index 5d66b11..0325534 100644
|
||||
--- a/dcmect/tests/CMakeLists.txt
|
||||
+++ b/dcmect/tests/CMakeLists.txt
|
||||
@@ -2,6 +2,7 @@
|
||||
DCMTK_ADD_EXECUTABLE(dcmect_tests
|
||||
tests.cc
|
||||
t_huge_concat.cc
|
||||
+ t_overflow.cc
|
||||
t_roundtrip.cc
|
||||
)
|
||||
|
||||
diff --git a/dcmect/tests/Makefile.dep b/dcmect/tests/Makefile.dep
|
||||
index 9d26f58..dfb50b8 100644
|
||||
--- a/dcmect/tests/Makefile.dep
|
||||
+++ b/dcmect/tests/Makefile.dep
|
||||
@@ -192,6 +192,157 @@ t_huge_concat.o: t_huge_concat.cc \
|
||||
../../dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h \
|
||||
../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h \
|
||||
../../dcmfg/include/dcmtk/dcmfg/fgtemporalposition.h
|
||||
+t_overflow.o: t_overflow.cc ../../config/include/dcmtk/config/osconfig.h \
|
||||
+ ../include/dcmtk/dcmect/enhanced_ct.h ../include/dcmtk/dcmect/def.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofexport.h \
|
||||
+ ../include/dcmtk/dcmect/types.h ../../oflog/include/dcmtk/oflog/oflog.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/logger.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/config.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofdefine.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofcast.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofstdinc.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/config/defines.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/helpers/threadcf.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/loglevel.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofvector.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/oftypes.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofstream.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/tstring.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofstring.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/tchar.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/spi/apndatch.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/appender.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofmem.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofutil.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/oftraits.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/variadic/tuplefwd.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/layout.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/streams.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/helpers/pointer.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/thread/syncprim.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/spi/filter.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/helpers/lockfile.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/spi/logfact.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/logmacro.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/helpers/snprintf.h \
|
||||
+ ../../oflog/include/dcmtk/oflog/tracelog.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofcond.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofdiag.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/diag/push.def \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/diag/useafree.def \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/diag/pop.def \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fginterface.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fg.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgbase.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcitem.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/offile.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofstd.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/oflist.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/oflimits.h \
|
||||
+ ../../config/include/dcmtk/config/arith.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/oferror.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dctypes.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcdefine.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcobject.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofglobal.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofthread.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcerror.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcxfer.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvr.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dctag.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dctagkey.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/diag/ignrattr.def \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcstack.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dclist.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcpcache.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgtypes.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgdefine.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofmap.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/iodimage.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/iodcommn.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/iodrules.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/iodtypes.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/ioddef.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modcommoninstanceref.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/iodmacro.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcdeftag.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlo.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcchrstr.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcbytstr.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcelem.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvris.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrus.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrlt.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrcs.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrpn.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modbase.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/iodreferences.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modequipment.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modfor.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralseries.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralstudy.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modpatient.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modpatientstudy.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modsopcommon.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modgeneralimage.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelvariant.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixelbase.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofvriant.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/variadic/variant.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/variadic/helpers.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofalign.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/diag/cnvrsn.def \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/diag/vsprfw.def \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/diag/arrybnds.def \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/diag/unrefprm.def \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modacquisitioncontext.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modenhequipment.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modimagepixel.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modmultiframedimension.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modmultiframefg.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/modsynchronisation.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrdt.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofdatime.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofdate.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/oftime.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrds.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrfd.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/oftempf.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/oftest.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofconapp.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofcmdln.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofexbl.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofconsol.h \
|
||||
+ ../../ofstd/include/dcmtk/ofstd/ofexit.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcuid.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcdict.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dchashdi.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcfilefo.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcsequen.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcdatset.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgctacquisitiondetails.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgctacquisitiontype.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgctadditionalxraysource.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrfl.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrsh.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgctexposure.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgctgeometry.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgctimageframetype.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgctposition.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgctreconstruction.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgcttabledynamics.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgctxraydetails.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgfracon.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrul.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgframeanatomy.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgirradiationeventid.h \
|
||||
+ ../../dcmdata/include/dcmtk/dcmdata/dcvrui.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgpixeltransform.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgpixmsr.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgplanor.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgplanpo.h \
|
||||
+ ../../dcmfg/include/dcmtk/dcmfg/fgrealworldvaluemapping.h \
|
||||
+ ../../dcmiod/include/dcmtk/dcmiod/iodcontentitemmacro.h
|
||||
t_roundtrip.o: t_roundtrip.cc \
|
||||
../../config/include/dcmtk/config/osconfig.h \
|
||||
../../ofstd/include/dcmtk/ofstd/ofmem.h \
|
||||
diff --git a/dcmect/tests/t_overflow.cc b/dcmect/tests/t_overflow.cc
|
||||
new file mode 100644
|
||||
index 0000000..4e9ac8b
|
||||
--- /dev/null
|
||||
+++ b/dcmect/tests/t_overflow.cc
|
||||
@@ -0,0 +1,360 @@
|
||||
+/*
|
||||
+ *
|
||||
+ * Copyright (C) 2024, OFFIS e.V.
|
||||
+ * All rights reserved. See COPYRIGHT file for details.
|
||||
+ *
|
||||
+ * This software and supporting documentation were developed by
|
||||
+ *
|
||||
+ * OFFIS e.V.
|
||||
+ * R&D Division Health
|
||||
+ * Escherweg 2
|
||||
+ * D-26121 Oldenburg, Germany
|
||||
+ *
|
||||
+ *
|
||||
+ * Module: dcmect
|
||||
+ *
|
||||
+ * Author: Daniel Berredo / Michael Onken
|
||||
+ *
|
||||
+ * Purpose: Tests that check for pixel data overflow conditions
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+
|
||||
+#include <dcmtk/config/osconfig.h> /* make sure OS specific configuration is included first */
|
||||
+
|
||||
+#include <dcmtk/dcmect/enhanced_ct.h>
|
||||
+
|
||||
+#include <dcmtk/ofstd/oftempf.h>
|
||||
+#include <dcmtk/ofstd/oftest.h>
|
||||
+
|
||||
+#include <dcmtk/dcmdata/dcdict.h>
|
||||
+#include <dcmtk/dcmdata/dcfilefo.h>
|
||||
+
|
||||
+#include <dcmtk/dcmfg/fgctacquisitiondetails.h>
|
||||
+#include <dcmtk/dcmfg/fgctacquisitiontype.h>
|
||||
+#include <dcmtk/dcmfg/fgctadditionalxraysource.h>
|
||||
+#include <dcmtk/dcmfg/fgctexposure.h>
|
||||
+#include <dcmtk/dcmfg/fgctgeometry.h>
|
||||
+#include <dcmtk/dcmfg/fgctimageframetype.h>
|
||||
+#include <dcmtk/dcmfg/fgctposition.h>
|
||||
+#include <dcmtk/dcmfg/fgctreconstruction.h>
|
||||
+#include <dcmtk/dcmfg/fgcttabledynamics.h>
|
||||
+#include <dcmtk/dcmfg/fgctxraydetails.h>
|
||||
+#include <dcmtk/dcmfg/fgfracon.h>
|
||||
+#include <dcmtk/dcmfg/fgframeanatomy.h>
|
||||
+#include <dcmtk/dcmfg/fgirradiationeventid.h>
|
||||
+#include <dcmtk/dcmfg/fgpixeltransform.h>
|
||||
+#include <dcmtk/dcmfg/fgpixmsr.h>
|
||||
+#include <dcmtk/dcmfg/fgplanor.h>
|
||||
+#include <dcmtk/dcmfg/fgplanpo.h>
|
||||
+#include <dcmtk/dcmfg/fgrealworldvaluemapping.h>
|
||||
+
|
||||
+static const Uint16 NUM_ROWS = 1024;
|
||||
+static const Uint16 NUM_COLS = 1;
|
||||
+static const Uint16 NUM_FRAMES = 2;
|
||||
+static const size_t NUM_PIXELS_PER_FRAME = 1;
|
||||
+
|
||||
+static OFString EXPECTED_DUMP;
|
||||
+
|
||||
+static EctEnhancedCT *create();
|
||||
+static void configureIOD(EctEnhancedCT *ct);
|
||||
+static void setGenericValues(EctEnhancedCT *ct);
|
||||
+static void addSharedFGs(EctEnhancedCT *ct);
|
||||
+static void addFrames(EctEnhancedCT *ct);
|
||||
+static void addDimensions(EctEnhancedCT *ct);
|
||||
+
|
||||
+
|
||||
+OFTEST(dcmect_overflow)
|
||||
+{
|
||||
+ /* make sure data dictionary is loaded */
|
||||
+ if (!dcmDataDict.isDictionaryLoaded())
|
||||
+ {
|
||||
+ OFCHECK(dcmDataDict.isDictionaryLoaded());
|
||||
+ }
|
||||
+
|
||||
+ // Creation
|
||||
+ EctEnhancedCT *ct = create();
|
||||
+ configureIOD(ct);
|
||||
+ setGenericValues(ct);
|
||||
+ addSharedFGs(ct);
|
||||
+ addFrames(ct);
|
||||
+ addDimensions(ct);
|
||||
+
|
||||
+ // Write to dataset and compare its dump with expected result
|
||||
+ DcmFileFormat dcmff;
|
||||
+
|
||||
+ OFTempFile tf(O_RDWR, "", "t_overflow", ".dcm");
|
||||
+ OFCondition result;
|
||||
+ result = ct->saveFile("output.dcm", EXS_LittleEndianExplicit);
|
||||
+ OFCHECK_MSG(result == ECT_InvalidPixelInfo, result.text());
|
||||
+}
|
||||
+
|
||||
+static EctEnhancedCT *create()
|
||||
+{
|
||||
+ IODEnhGeneralEquipmentModule::EquipmentInfo eq("Open Connections", "OC CT", "4711", "0.1");
|
||||
+ EctEnhancedCT *ct = NULL;
|
||||
+ OFCondition result;
|
||||
+ result = EctEnhancedCT::create(ct,
|
||||
+ NUM_ROWS,
|
||||
+ NUM_COLS,
|
||||
+ OFFalse,
|
||||
+ EctTypes::E_ImageType1_Original,
|
||||
+ EctTypes::DT_ImageType3_Volume,
|
||||
+ EctTypes::DT_ImageType4_Maximum,
|
||||
+ "1" /* instance number */,
|
||||
+ EctTypes::E_ContQuali_Research,
|
||||
+ EctTypes::E_PixelPres_Monochrome,
|
||||
+ EctTypes::E_VolProps_Volume,
|
||||
+ EctTypes::DT_VolBasedCalcTechnique_VolumeRender,
|
||||
+ eq,
|
||||
+ "20190801120000" /* acquisition date */,
|
||||
+ 2.0 /* acquisition duration */);
|
||||
+
|
||||
+ OFCHECK(result.good());
|
||||
+ OFCHECK(ct != OFnullptr);
|
||||
+ return ct;
|
||||
+}
|
||||
+
|
||||
+static void configureIOD(EctEnhancedCT *ct)
|
||||
+{
|
||||
+ if (!ct)
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void setGenericValues(EctEnhancedCT *ct)
|
||||
+{
|
||||
+ if (!ct)
|
||||
+ return;
|
||||
+ OFCHECK(ct->getPatient().setPatientName("Bond^James").good());
|
||||
+ OFCHECK(ct->getPatient().setPatientID("007").good());
|
||||
+ OFCHECK(ct->getPatient().setPatientBirthDate("19771007").good());
|
||||
+ OFCHECK(ct->getStudy().setStudyDate("20190801").good());
|
||||
+ OFCHECK(ct->getStudy().setStudyTime("120000").good());
|
||||
+ OFCHECK(ct->getStudy().setStudyID("1").good());
|
||||
+ OFCHECK(ct->getPatientStudy().setPatientAge("040Y").good());
|
||||
+ OFCHECK(ct->getSeries().setSeriesDescription("Test Description").good());
|
||||
+ OFCHECK(ct->getSeries().setSeriesNumber("1").good());
|
||||
+ OFCHECK(ct->getSeries().setPatientPosition("HFS").good());
|
||||
+
|
||||
+ // Those values are usually computed automatically. UIDS are generated and date/times are set to current values.
|
||||
+ // But in order to compare the "old" dump with the freshly created image attributes, we set some values manually,
|
||||
+ // so that they are not overwritten with new, automatically created values later.
|
||||
+ OFCHECK(ct->getStudy().setStudyInstanceUID("1.2.276.0.7230010.3.1.2.8323329.14863.1565940357.864811").good());
|
||||
+ OFCHECK(ct->getFrameOfReference().setFrameOfReferenceUID("2.25.30853397773651184949181049330553108086").good());
|
||||
+ OFCHECK(ct->getSeries().setSeriesInstanceUID("1.2.276.0.7230010.3.1.3.8323329.14863.1565940357.864812").good());
|
||||
+ OFCHECK(ct->getSOPCommon().setSOPInstanceUID("1.2.276.0.7230010.3.1.4.8323329.14863.1565940357.864813").good());
|
||||
+
|
||||
+ OFCHECK(ct->getIODMultiFrameFGModule().setContentTime("092557").good());
|
||||
+ OFCHECK(ct->getIODMultiFrameFGModule().setContentDate("20190816").good());
|
||||
+}
|
||||
+
|
||||
+static void addSharedFGs(EctEnhancedCT *ct)
|
||||
+{
|
||||
+ if (!ct)
|
||||
+ return;
|
||||
+
|
||||
+ FGPixelMeasures meas;
|
||||
+ OFCHECK(meas.setPixelSpacing("0.1\\0.1").good());
|
||||
+ OFCHECK(meas.setSliceThickness("1.0").good());
|
||||
+ OFCHECK(meas.setSpacingBetweenSlices("0.05").good());
|
||||
+
|
||||
+ FGPlanePosPatient planpo;
|
||||
+ OFCHECK(planpo.setImagePositionPatient("0.0", "0.0", "0.0").good());
|
||||
+
|
||||
+ FGPlaneOrientationPatient planor;
|
||||
+ OFCHECK(planor.setImageOrientationPatient("1.0", "0.0", "0.0", "0.0", "1.0", "0.0").good());
|
||||
+
|
||||
+ FGFrameAnatomy ana;
|
||||
+ OFCHECK(ana.setLaterality(FGFrameAnatomy::LATERALITY_BOTH).good());
|
||||
+ OFCHECK(ana.getAnatomy().getAnatomicRegion().set("12738006", "SCT", "Brain").good());
|
||||
+
|
||||
+ FGIrradiationEventIdentification irr;
|
||||
+ OFCHECK(irr.setIrradiationEventUID("2.25.30853892236613436472911970638347155062").good());
|
||||
+
|
||||
+ FGCTImageFrameType itype;
|
||||
+ OFCHECK(itype.setFrameType("ORIGINAL\\PRIMARY\\VOLUME\\MAXIMUM").good());
|
||||
+ OFCHECK(itype.setPixelPresentation(FGCTImageFrameType::E_PixelPres_Monochrome).good());
|
||||
+ OFCHECK(itype.setVolumetricProperties(FGCTImageFrameType::E_VolProp_Volume).good());
|
||||
+ OFCHECK(itype.setVolumeBasedCalculationTechnique(FGCTImageFrameType::DT_VolBasedCalcTechnique_VolumeRender).good());
|
||||
+
|
||||
+ FGCTAcquisitionType atype;
|
||||
+ OFCHECK(atype.setAcquisitionType(FGCTAcquisitionType::DT_AcquisitionType_ConstantAngle).good());
|
||||
+ OFCHECK(atype.setTubeAngle(0.1).good());
|
||||
+ OFCHECK(atype.setConstantVolumeFlag(FGCTAcquisitionType::E_ConstVol_Yes).good());
|
||||
+ OFCHECK(atype.setFluoroscopyFlag(FGCTAcquisitionType::E_Fluoroscopy_No).good());
|
||||
+
|
||||
+ FGCTAcquisitionDetails adetails;
|
||||
+ FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem *item = new FGCTAcquisitionDetails::FGCTAcquisitionDetailsItem();
|
||||
+ OFCHECK(item->setRotationDirection(FGCTAcquisitionDetails::E_RotationDirection_CW).good());
|
||||
+ OFCHECK(item->setRevolutionTime(5).good());
|
||||
+ OFCHECK(item->setSingleCollimationWidth(1).good());
|
||||
+ OFCHECK(item->setTotalCollimationWidth(10).good());
|
||||
+ OFCHECK(item->setTableHeight(50).good());
|
||||
+ OFCHECK(item->setGantryDetectorTilt(5).good());
|
||||
+ OFCHECK(item->setDataCollectionDiameter(20).good());
|
||||
+ adetails.getCTAcquisitionDetailsItems().push_back(item);
|
||||
+
|
||||
+ FGCTTableDynamics dyn;
|
||||
+ FGCTTableDynamics::FGCTTableDynamicsItem *dyn_item = new FGCTTableDynamics::FGCTTableDynamicsItem;
|
||||
+ OFCHECK(dyn_item);
|
||||
+ if (dyn_item)
|
||||
+ {
|
||||
+ OFCHECK(dyn_item->setTableSpeed(1.0).good());
|
||||
+ OFCHECK(dyn_item->setTableFeedPerRotation(0.1).good());
|
||||
+ OFCHECK(dyn_item->setSpiralPitchFactor(0.2).good());
|
||||
+ dyn.getCTTableDynamicsItems().push_back(dyn_item);
|
||||
+ }
|
||||
+
|
||||
+ FGCTPosition pos;
|
||||
+ OFCHECK(pos.setTablePosition(100.0).good());
|
||||
+ OFCHECK(pos.setReconstructionTargetCenterPatient(OFVector<Float64>(3, 1.0)).good());
|
||||
+ OFCHECK(pos.setDataCollectionCenterPatient(OFVector<Float64>(3, 2.0)).good());
|
||||
+
|
||||
+ FGCTGeometry geo;
|
||||
+ FGCTGeometry::FGCTGeometryItem *geo_item = new FGCTGeometry::FGCTGeometryItem;
|
||||
+ if (geo_item)
|
||||
+ {
|
||||
+ OFCHECK(geo_item->setDistanceSourceToDataCollectionCenter(5.0).good());
|
||||
+ OFCHECK(geo_item->setDistanceSourceToDetector(0.5).good());
|
||||
+ geo.getCTGeometryItems().push_back(geo_item);
|
||||
+ }
|
||||
+
|
||||
+ FGCTReconstruction rec;
|
||||
+ OFCHECK(rec.setConvolutionKernel("DUMMY").good());
|
||||
+ OFCHECK(rec.setConvolutionKernelGroup("DUMMYGROUP").good());
|
||||
+ OFCHECK(rec.setImageFilter("FILTER").good());
|
||||
+ OFCHECK(rec.setReconstructionAlgorithm("ALGO").good());
|
||||
+ OFCHECK(rec.setReconstructionAngle(90.0).good());
|
||||
+ OFCHECK(rec.setReconstructionDiameter(100.0).good());
|
||||
+ // Not permitted if Reconstruction Diameter is provided instead
|
||||
+ // OFCHECK(rec.setReconstructionFieldOfView(100.0, 100.0).good());
|
||||
+ OFCHECK(rec.setReconstructionPixelSpacing(0.1, 0.1).good());
|
||||
+
|
||||
+ FGCTExposure exp;
|
||||
+ FGCTExposure::FGCTExposureItem *exp_item = new FGCTExposure::FGCTExposureItem;
|
||||
+ if (exp_item)
|
||||
+ {
|
||||
+ OFCHECK(exp_item->setCTDIVol(0.1).good());
|
||||
+ CodeSequenceMacro *phantom_item = new CodeSequenceMacro("113682", "DCM", "ACR Accreditation Phantom - CT");
|
||||
+ exp_item->getCTDIPhantomTypeCodeSequence().push_back(phantom_item);
|
||||
+ OFCHECK(exp_item->setExposureInMas(0.3).good());
|
||||
+ OFCHECK(exp_item->setExposureModulationType("WEIRD").good());
|
||||
+ OFCHECK(exp_item->setExposureTimeInMs(0.4).good());
|
||||
+ OFCHECK(exp_item->setImageAndFluoroscopyAreaDoseProduct(0.5).good());
|
||||
+ OFCHECK(exp_item->setWaterEquivalentDiameter(0.6).good());
|
||||
+ CodeSequenceMacro *water_code = new CodeSequenceMacro("113987", "DCM", "AAPM 220");
|
||||
+ exp_item->getWaterEquivalentDiameterCalculationMethodCodeSequence().push_back(water_code);
|
||||
+ OFCHECK(exp_item->setXRayTubeCurrentInMa(0.7).good());
|
||||
+ exp.getCTExposureItems().push_back(exp_item);
|
||||
+ }
|
||||
+
|
||||
+ FGCTXRayDetails det;
|
||||
+ FGCTXRayDetails::FGCTXRayDetailsItem *det_item = new FGCTXRayDetails::FGCTXRayDetailsItem;
|
||||
+ if (det_item)
|
||||
+ {
|
||||
+ OFCHECK(det_item->setCalciumScoringMassFactorDevice(OFVector<Float32>(3, 1)).good());
|
||||
+ OFCHECK(det_item->setCalciumScoringMassFactorPatient(2).good());
|
||||
+ OFCHECK(det_item->setEnergyWeightingFactor(3).good());
|
||||
+ OFCHECK(det_item->setFilterMaterial("FILTER_MATERIAL").good());
|
||||
+ OFCHECK(det_item->setFilterType("FILTER_TYPE").good());
|
||||
+ OFCHECK(det_item->setFocalSpots(OFVector<Float64>(4, 4.4)).good());
|
||||
+ OFCHECK(det_item->setKVP(5.0).good());
|
||||
+ det.getCTXRayDetailsItems().push_back(det_item);
|
||||
+ }
|
||||
+
|
||||
+ FGPixelValueTransformation trans;
|
||||
+ trans.setFGType(FGPixelValueTransformation::E_PixelValTrans_CT);
|
||||
+ trans.setRescaleIntercept("0");
|
||||
+ trans.setRescaleSlope("1");
|
||||
+ trans.setRescaleType("HU");
|
||||
+
|
||||
+ FGCTAdditionalXRaySource asrc;
|
||||
+ FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem *asrc_item = new FGCTAdditionalXRaySource::FGCTAdditionalXRaySourceItem;
|
||||
+ if (asrc_item)
|
||||
+ {
|
||||
+ OFCHECK(asrc_item->setDataCollectionDiameter(1.0).good());
|
||||
+ OFCHECK(asrc_item->setEnergyWeightingFactor(2.0).good());
|
||||
+ OFCHECK(asrc_item->setExposureInmAs(3.0).good());
|
||||
+ OFCHECK(asrc_item->setFilterMaterial("FILTER_MATERIAL").good());
|
||||
+ OFCHECK(asrc_item->setFilterType("FILTER_TYPE").good());
|
||||
+ OFCHECK(asrc_item->setFocalSpots(OFVector<Float64>(4, 4.4)).good());
|
||||
+ OFCHECK(asrc_item->setKVP(5).good());
|
||||
+ OFCHECK(asrc_item->setXRayTubeCurrentInmA(6).good());
|
||||
+ asrc.getCTAdditionalXRaySourceItems().push_back(asrc_item);
|
||||
+ }
|
||||
+
|
||||
+ OFCHECK(ct->addForAllFrames(meas).good());
|
||||
+ OFCHECK(ct->addForAllFrames(planpo).good());
|
||||
+ OFCHECK(ct->addForAllFrames(planor).good());
|
||||
+ OFCHECK(ct->addForAllFrames(ana).good());
|
||||
+ OFCHECK(ct->addForAllFrames(irr).good());
|
||||
+ OFCHECK(ct->addForAllFrames(itype).good());
|
||||
+ OFCHECK(ct->addForAllFrames(atype).good());
|
||||
+ OFCHECK(ct->addForAllFrames(adetails).good());
|
||||
+ OFCHECK(ct->addForAllFrames(dyn).good());
|
||||
+ OFCHECK(ct->addForAllFrames(pos).good());
|
||||
+ OFCHECK(ct->addForAllFrames(geo).good());
|
||||
+ OFCHECK(ct->addForAllFrames(rec).good());
|
||||
+ OFCHECK(ct->addForAllFrames(exp).good());
|
||||
+ OFCHECK(ct->addForAllFrames(det).good());
|
||||
+ OFCHECK(ct->addForAllFrames(trans).good());
|
||||
+ OFCHECK(ct->addForAllFrames(asrc).good());
|
||||
+}
|
||||
+
|
||||
+static void addFrames(EctEnhancedCT *ct)
|
||||
+{
|
||||
+ if (!ct)
|
||||
+ return;
|
||||
+
|
||||
+ FGFrameContent *fg = new FGFrameContent();
|
||||
+ fg->setStackID("1");
|
||||
+ OFCHECK(fg);
|
||||
+ if (fg)
|
||||
+ {
|
||||
+ EctEnhancedCT::FramesType frames = ct->getFrames();
|
||||
+ for (Uint16 frameNo = 1; frameNo <= NUM_FRAMES; frameNo++)
|
||||
+ {
|
||||
+ OFCHECK(fg->setFrameAcquisitionNumber(frameNo).good());
|
||||
+ OFCHECK(fg->setFrameReferenceDateTime("20190816092557").good());
|
||||
+ OFCHECK(fg->setFrameAcquisitionDateTime("20190816092557").good());
|
||||
+ OFCHECK(fg->setFrameAcquisitionDuration(0.001).good());
|
||||
+ OFCHECK(fg->setInStackPositionNumber(frameNo).good());
|
||||
+ OFCHECK(fg->setDimensionIndexValues(1, 0).good());
|
||||
+ OFCHECK(fg->setDimensionIndexValues(frameNo, 1).good());
|
||||
+ OFVector<FGBase *> groups;
|
||||
+ groups.push_back(fg);
|
||||
+
|
||||
+ Uint16 *data = new Uint16[NUM_PIXELS_PER_FRAME];
|
||||
+ for (size_t i = 0; i < NUM_PIXELS_PER_FRAME; ++i)
|
||||
+ {
|
||||
+ data[i] = 0x4141;
|
||||
+ }
|
||||
+ OFCHECK(
|
||||
+ OFget<EctEnhancedCT::Frames<Uint16>>(&frames)->addFrame(data, NUM_PIXELS_PER_FRAME, groups).good());
|
||||
+ delete[] data;
|
||||
+ }
|
||||
+ }
|
||||
+ delete fg;
|
||||
+}
|
||||
+
|
||||
+static void addDimensions(EctEnhancedCT *ct)
|
||||
+{
|
||||
+ if (!ct)
|
||||
+ return;
|
||||
+ IODMultiframeDimensionModule &dims = ct->getDimensions();
|
||||
+ OFCHECK(dims.addDimensionIndex(
|
||||
+ DCM_StackID, "2.25.30855560781715986879861690673941231222", DCM_FrameContentSequence, "STACK_DIM")
|
||||
+ .good());
|
||||
+ OFCHECK(dims.addDimensionIndex(DCM_InStackPositionNumber,
|
||||
+ "2.25.30855560781715986879861690673941231222",
|
||||
+ DCM_FrameContentSequence,
|
||||
+ "STACK_DIM")
|
||||
+ .good());
|
||||
+ OFunique_ptr<IODMultiframeDimensionModule::DimensionOrganizationItem> org(
|
||||
+ new IODMultiframeDimensionModule::DimensionOrganizationItem);
|
||||
+ if (org)
|
||||
+ {
|
||||
+ org->setDimensionOrganizationUID("2.25.30855560781715986879861690673941231222");
|
||||
+ dims.getDimensionOrganizationSequence().push_back(org.release());
|
||||
+ }
|
||||
+}
|
||||
diff --git a/dcmect/tests/tests.cc b/dcmect/tests/tests.cc
|
||||
index 54a6ca0..8639dc1 100644
|
||||
--- a/dcmect/tests/tests.cc
|
||||
+++ b/dcmect/tests/tests.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 2019, OFFIS e.V.
|
||||
+ * Copyright (C) 2019-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -23,5 +23,6 @@
|
||||
#include "dcmtk/ofstd/oftest.h"
|
||||
|
||||
OFTEST_REGISTER(dcmect_huge_concat);
|
||||
+OFTEST_REGISTER(dcmect_overflow);
|
||||
OFTEST_REGISTER(dcmect_roundtrip);
|
||||
OFTEST_MAIN("dcmect")
|
||||
--
|
||||
2.44.0
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
From c78e434c0c5f9d932874f0b17a8b4ce305ca01f5 Mon Sep 17 00:00:00 2001
|
||||
From: Marco Eichelberg <dicom@offis.de>
|
||||
Date: Wed, 13 Mar 2024 17:15:58 +0100
|
||||
Subject: [PATCH] Fixed two segmentation faults.
|
||||
|
||||
Fixed two segmentations faults that could occur while processing an
|
||||
invalid incoming DIMSE message due to insufficient error handling
|
||||
causing a de-referenced NULL pointer.
|
||||
|
||||
Thanks to Nils Bars <nils.bars@rub.de> for the bug report and sample files.
|
||||
|
||||
This closes DCMTK issue #1114.
|
||||
---
|
||||
dcmdata/libsrc/dcelem.cc | 9 ++++++++-
|
||||
dcmnet/libsrc/dimcmd.cc | 33 ++++++++++++++++++---------------
|
||||
2 files changed, 26 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/dcmdata/libsrc/dcelem.cc b/dcmdata/libsrc/dcelem.cc
|
||||
index 1524904be..3b9cc2bf7 100644
|
||||
--- a/dcmdata/libsrc/dcelem.cc
|
||||
+++ b/dcmdata/libsrc/dcelem.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 1994-2023, OFFIS e.V.
|
||||
+ * Copyright (C) 1994-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -717,6 +717,13 @@ OFCondition DcmElement::loadValue(DcmInputStream *inStream)
|
||||
if (isStreamNew)
|
||||
delete readStream;
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ errorFlag = EC_InvalidStream; // incomplete dataset read from stream
|
||||
+ DCMDATA_ERROR("DcmElement: " << getTagName() << " " << getTag()
|
||||
+ << " larger (" << getLengthField() << ") than remaining bytes ("
|
||||
+ << getTransferredBytes() << ") in file, premature end of stream");
|
||||
+ }
|
||||
}
|
||||
/* return result value */
|
||||
return errorFlag;
|
||||
diff --git a/dcmnet/libsrc/dimcmd.cc b/dcmnet/libsrc/dimcmd.cc
|
||||
index 6dca39546..ffd225f4b 100644
|
||||
--- a/dcmnet/libsrc/dimcmd.cc
|
||||
+++ b/dcmnet/libsrc/dimcmd.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 1994-2022, OFFIS e.V.
|
||||
+ * Copyright (C) 1994-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were partly developed by
|
||||
@@ -205,22 +205,25 @@ getString(DcmDataset *obj, DcmTagKey t, char *s, int maxlen, OFBool *spacePadded
|
||||
return parseErrorWithMsg("dimcmd:getString: string too small", t);
|
||||
} else {
|
||||
ec = elem->getString(aString);
|
||||
- strncpy(s, aString, maxlen);
|
||||
- if (spacePadded)
|
||||
+ if (ec.good())
|
||||
{
|
||||
- /* before we remove leading and tailing spaces we want to know
|
||||
- * whether the string is actually space padded. Required to communicate
|
||||
- * with dumb peers which send space padded UIDs and fail if they
|
||||
- * receive correct UIDs back.
|
||||
- *
|
||||
- * This test can only detect space padded strings if
|
||||
- * dcmEnableAutomaticInputDataCorrection is false; otherwise the padding
|
||||
- * has already been removed by dcmdata at this stage.
|
||||
- */
|
||||
- size_t s_len = strlen(s);
|
||||
- if ((s_len > 0)&&(s[s_len-1] == ' ')) *spacePadded = OFTrue; else *spacePadded = OFFalse;
|
||||
+ strncpy(s, aString, maxlen);
|
||||
+ if (spacePadded)
|
||||
+ {
|
||||
+ /* before we remove leading and tailing spaces we want to know
|
||||
+ * whether the string is actually space padded. Required to communicate
|
||||
+ * with dumb peers which send space padded UIDs and fail if they
|
||||
+ * receive correct UIDs back.
|
||||
+ *
|
||||
+ * This test can only detect space padded strings if
|
||||
+ * dcmEnableAutomaticInputDataCorrection is false; otherwise the padding
|
||||
+ * has already been removed by dcmdata at this stage.
|
||||
+ */
|
||||
+ size_t s_len = strlen(s);
|
||||
+ if ((s_len > 0)&&(s[s_len-1] == ' ')) *spacePadded = OFTrue; else *spacePadded = OFFalse;
|
||||
+ }
|
||||
+ DU_stripLeadingAndTrailingSpaces(s);
|
||||
}
|
||||
- DU_stripLeadingAndTrailingSpaces(s);
|
||||
}
|
||||
}
|
||||
return (ec.good())? ec : DIMSE_PARSEFAILED;
|
||||
--
|
||||
2.44.0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
25
0001-dcmimage-Link-privately-to-libtiff-and-libpng.patch
Normal file
25
0001-dcmimage-Link-privately-to-libtiff-and-libpng.patch
Normal file
@@ -0,0 +1,25 @@
|
||||
From 2f51702b80a72eaba041bfef19cd93c009bc1fc8 Mon Sep 17 00:00:00 2001
|
||||
From: Fabian Vogt <fvogt@suse.de>
|
||||
Date: Wed, 26 Nov 2025 15:36:29 +0100
|
||||
Subject: [PATCH] dcmimage: Link privately to libtiff and libpng
|
||||
|
||||
Those are not used by the interface.
|
||||
---
|
||||
dcmimage/libsrc/CMakeLists.txt | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dcmimage/libsrc/CMakeLists.txt b/dcmimage/libsrc/CMakeLists.txt
|
||||
index 8f2c76cc9441..44e866a07579 100644
|
||||
--- a/dcmimage/libsrc/CMakeLists.txt
|
||||
+++ b/dcmimage/libsrc/CMakeLists.txt
|
||||
@@ -24,5 +24,5 @@ DCMTK_ADD_LIBRARY(dcmimage
|
||||
diyp2img.cc
|
||||
)
|
||||
|
||||
-DCMTK_TARGET_LINK_MODULES(dcmimage oflog dcmdata dcmimgle)
|
||||
-DCMTK_TARGET_LINK_LIBRARIES(dcmimage ${LIBTIFF_LIBS} ${LIBPNG_LIBS})
|
||||
+DCMTK_TARGET_LINK_MODULES(dcmimage PUBLIC oflog dcmdata dcmimgle)
|
||||
+DCMTK_TARGET_LINK_LIBRARIES(dcmimage PRIVATE ${LIBTIFF_LIBS} ${LIBPNG_LIBS})
|
||||
--
|
||||
2.51.1
|
||||
|
||||
@@ -1,506 +0,0 @@
|
||||
From 601b227eecaab33a3a3a11dc256d84b1a62f63af Mon Sep 17 00:00:00 2001
|
||||
From: Marco Eichelberg <dicom@offis.de>
|
||||
Date: Mon, 15 Apr 2024 12:19:33 +0200
|
||||
Subject: [PATCH 2/3] Fixed unchecked typecasts and fixed LUT handling.
|
||||
|
||||
This commit adds further fixes for unchecked typecasts of DcmItem::search()
|
||||
results (see description of previous commit). Furthermore, this commit
|
||||
specifically addresses the handling of look-up tables (LUTs) in module
|
||||
dcmpstat, where attribute (0028,3006) LUTData may use either US or OW
|
||||
value representation, and (0028,3002) LUTDescriptor may be either US or SS.
|
||||
The code should now properly handle all permitted value representations.
|
||||
LUTData is now always written as OW in order to avoid the 64k size limit
|
||||
for US in explicit VR encoding.
|
||||
|
||||
Thanks to Martin Zeiser from the Cisco Talos team
|
||||
<vulndiscovery@external.cisco.com> for the bug report (TALOS-2024-1957).
|
||||
|
||||
Together with the previous commit, this closes DCMTK issue #1120.
|
||||
---
|
||||
dcmpstat/libsrc/dcmpstat.cc | 40 ++++++++++++++++-------
|
||||
dcmpstat/libsrc/dvpspl.cc | 34 +++++++++++++------
|
||||
dcmpstat/libsrc/dvpssv.cc | 34 +++++++++++++------
|
||||
dcmpstat/libsrc/dvpssvl.cc | 25 +++++++++-----
|
||||
dcmpstat/libsrc/dvpstat.cc | 65 +++++++++++++++++--------------------
|
||||
dcmpstat/libsrc/dvpsvl.cc | 19 +++++++++--
|
||||
6 files changed, 139 insertions(+), 78 deletions(-)
|
||||
|
||||
diff --git a/dcmpstat/libsrc/dcmpstat.cc b/dcmpstat/libsrc/dcmpstat.cc
|
||||
index 4a8e5af6c..a7d11abac 100644
|
||||
--- a/dcmpstat/libsrc/dcmpstat.cc
|
||||
+++ b/dcmpstat/libsrc/dcmpstat.cc
|
||||
@@ -384,12 +384,16 @@ OFCondition DcmPresentationState::read(DcmItem &dset)
|
||||
{
|
||||
item = seq->getItem(0);
|
||||
stack.clear();
|
||||
- // LUTDescriptor can be US or SS. For now we only handle US.
|
||||
+
|
||||
+ // LUTDescriptor can be US or SS
|
||||
if ((EC_Normal == item->search((DcmTagKey &)modalityLUTDescriptor.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US))
|
||||
+ stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_SS))
|
||||
{
|
||||
- modalityLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // We explicitly use DcmElement::operator=(), which works for US and SS
|
||||
+ DcmElement *mLUTDescriptor = &modalityLUTDescriptor;
|
||||
+ mLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, stack.top()));
|
||||
}
|
||||
+
|
||||
stack.clear();
|
||||
if ((EC_Normal == item->search((DcmTagKey &)modalityLUTExplanation.getTag(),
|
||||
stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_LO))
|
||||
@@ -400,9 +404,11 @@ OFCondition DcmPresentationState::read(DcmItem &dset)
|
||||
|
||||
// LUTData can be OW, US or SS. For now we only handle US.
|
||||
if ((EC_Normal == item->search((DcmTagKey &)modalityLUTData.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US))
|
||||
+ stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_OW))
|
||||
{
|
||||
- modalityLUTData = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // we deliberately call DcmElement::operator=() here, which will work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
|
||||
+ DcmElement *mdata = &modalityLUTData;
|
||||
+ mdata->operator=(*(DcmElement *)(stack.top()));
|
||||
}
|
||||
stack.clear();
|
||||
if ((EC_Normal == item->search((DcmTagKey &)modalityLUTType.getTag(),
|
||||
@@ -879,11 +885,13 @@ OFCondition DcmPresentationState::createFromImage(
|
||||
{
|
||||
item = seq->getItem(0);
|
||||
stack.clear();
|
||||
- // LUTDescriptor can be US or SS. For now we only handle US.
|
||||
+ // LUTDescriptor can be US or SS
|
||||
if ((EC_Normal == item->search((DcmTagKey &)modalityLUTDescriptor.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US))
|
||||
+ stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_SS))
|
||||
{
|
||||
- modalityLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // We explicitly use DcmElement::operator=(), which works for US and SS
|
||||
+ DcmElement *mLUTDescriptor = &modalityLUTDescriptor;
|
||||
+ mLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, stack.top()));
|
||||
}
|
||||
stack.clear();
|
||||
if ((EC_Normal == item->search((DcmTagKey &)modalityLUTExplanation.getTag(),
|
||||
@@ -895,9 +903,11 @@ OFCondition DcmPresentationState::createFromImage(
|
||||
|
||||
// LUTData can be OW, US or SS. For now we only handle US.
|
||||
if ((EC_Normal == item->search((DcmTagKey &)modalityLUTData.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US))
|
||||
+ stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_OW))
|
||||
{
|
||||
- modalityLUTData = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // we deliberately call DcmElement::operator=() here, which will work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
|
||||
+ DcmElement *mdata = &modalityLUTData;
|
||||
+ mdata->operator=(*(DcmElement *)(stack.top()));
|
||||
}
|
||||
stack.clear();
|
||||
if ((EC_Normal == item->search((DcmTagKey &)modalityLUTType.getTag(),
|
||||
@@ -1247,10 +1257,16 @@ OFCondition DcmPresentationState::write(DcmItem &dset, OFBool replaceSOPInstance
|
||||
dseq = new DcmSequenceOfItems(DCM_ModalityLUTSequence);
|
||||
if (dseq)
|
||||
{
|
||||
- delem = new DcmUnsignedShort(modalityLUTDescriptor);
|
||||
+ // we clone modalityLUTDescriptor in order to retain the VR (US or SS)
|
||||
+ delem = OFstatic_cast(DcmElement *, modalityLUTDescriptor.clone());
|
||||
if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted;
|
||||
- delem = new DcmUnsignedShort(modalityLUTData);
|
||||
+
|
||||
+ // we write LUTData as OW in order to avoid the 64 kByte limit for US
|
||||
+ delem = new DcmOtherByteOtherWord(DCM_LUTData);
|
||||
+ delem->operator=(modalityLUTData);
|
||||
+ OFstatic_cast(DcmOtherByteOtherWord *, delem)->setVR(EVR_OW);
|
||||
if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted;
|
||||
+
|
||||
delem = new DcmLongString(modalityLUTType);
|
||||
if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted;
|
||||
if (modalityLUTExplanation.getLength() >0)
|
||||
diff --git a/dcmpstat/libsrc/dvpspl.cc b/dcmpstat/libsrc/dvpspl.cc
|
||||
index ec4cccf97..f5574ab33 100644
|
||||
--- a/dcmpstat/libsrc/dvpspl.cc
|
||||
+++ b/dcmpstat/libsrc/dvpspl.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 1999-2018, OFFIS e.V.
|
||||
+ * Copyright (C) 1999-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "dcmtk/dcmdata/dcdeftag.h"
|
||||
#include "dcmtk/dcmdata/dcsequen.h"
|
||||
#include "dcmtk/dcmdata/dcvrcs.h"
|
||||
+#include "dcmtk/dcmdata/dcvrobow.h"
|
||||
#include "dcmtk/dcmpstat/dvpspl.h"
|
||||
#include "dcmtk/dcmpstat/dvpsdef.h" /* for constants and macros */
|
||||
#include "dcmtk/dcmnet/dimse.h"
|
||||
@@ -79,29 +80,36 @@ OFCondition DVPSPresentationLUT::read(DcmItem &dset, OFBool withSOPInstance)
|
||||
if (result==EC_Normal)
|
||||
{
|
||||
stack.clear();
|
||||
- if (EC_Normal == dset.search(DCM_PresentationLUTSequence, stack, ESM_fromHere, OFFalse))
|
||||
+ if (EC_Normal == dset.search(DCM_PresentationLUTSequence, stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_SQ))
|
||||
{
|
||||
seq=(DcmSequenceOfItems *)stack.top();
|
||||
if (seq->card() ==1)
|
||||
{
|
||||
item = seq->getItem(0);
|
||||
stack.clear();
|
||||
- if (EC_Normal == item->search((DcmTagKey &)presentationLUTDescriptor.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse))
|
||||
+
|
||||
+ // LUTDescriptor can be US or SS
|
||||
+ if ((EC_Normal == item->search((DcmTagKey &)presentationLUTDescriptor.getTag(),
|
||||
+ stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_SS))
|
||||
{
|
||||
- presentationLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // We explicitly use DcmElement::operator=(), which works for US and SS
|
||||
+ DcmElement *pLUTDescriptor = &presentationLUTDescriptor;
|
||||
+ pLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, stack.top()));
|
||||
}
|
||||
+
|
||||
stack.clear();
|
||||
if (EC_Normal == item->search((DcmTagKey &)presentationLUTExplanation.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse))
|
||||
+ stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_LO))
|
||||
{
|
||||
presentationLUTExplanation = *((DcmLongString *)(stack.top()));
|
||||
}
|
||||
stack.clear();
|
||||
if (EC_Normal == item->search((DcmTagKey &)presentationLUTData.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse))
|
||||
+ stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_OW))
|
||||
{
|
||||
- presentationLUTData = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // we deliberately call DcmElement::operator=() here, which will work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
|
||||
+ DcmElement *pldata = &presentationLUTData;
|
||||
+ pldata->operator=(*(DcmElement *)(stack.top()));
|
||||
}
|
||||
} else {
|
||||
result=EC_TagNotFound;
|
||||
@@ -187,10 +195,16 @@ OFCondition DVPSPresentationLUT::write(DcmItem &dset, OFBool withSOPInstance)
|
||||
dseq = new DcmSequenceOfItems(DCM_PresentationLUTSequence);
|
||||
if (dseq)
|
||||
{
|
||||
- delem = new DcmUnsignedShort(presentationLUTDescriptor);
|
||||
+ // we clone presentationLUTDescriptor in order to retain the VR (US or SS)
|
||||
+ delem = OFstatic_cast(DcmElement *, presentationLUTDescriptor.clone());
|
||||
if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted;
|
||||
- delem = new DcmUnsignedShort(presentationLUTData);
|
||||
+
|
||||
+ // we write LUTData as OW in order to avoid the 64 kByte limit for US
|
||||
+ delem = new DcmOtherByteOtherWord(DCM_LUTData);
|
||||
+ delem->operator=(presentationLUTData);
|
||||
+ OFstatic_cast(DcmOtherByteOtherWord *, delem)->setVR(EVR_OW);
|
||||
if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted;
|
||||
+
|
||||
if (presentationLUTExplanation.getLength() >0)
|
||||
{
|
||||
delem = new DcmLongString(presentationLUTExplanation);
|
||||
diff --git a/dcmpstat/libsrc/dvpssv.cc b/dcmpstat/libsrc/dvpssv.cc
|
||||
index 8e3d49bd4..4a7fd0e30 100644
|
||||
--- a/dcmpstat/libsrc/dvpssv.cc
|
||||
+++ b/dcmpstat/libsrc/dvpssv.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 1998-2018, OFFIS e.V.
|
||||
+ * Copyright (C) 1998-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
|
||||
#include "dcmtk/dcmdata/dcdeftag.h"
|
||||
#include "dcmtk/dcmdata/dcsequen.h"
|
||||
+#include "dcmtk/dcmdata/dcvrobow.h"
|
||||
#include "dcmtk/dcmpstat/dvpssv.h"
|
||||
#include "dcmtk/dcmpstat/dvpsri.h" /* for DVPSReferencedImage */
|
||||
#include "dcmtk/dcmpstat/dvpsrsl.h" /* DVPSReferencedSeries_PList */
|
||||
@@ -75,29 +76,36 @@ OFCondition DVPSSoftcopyVOI::read(DcmItem &dset)
|
||||
if (result==EC_Normal)
|
||||
{
|
||||
stack.clear();
|
||||
- if (EC_Normal == dset.search(DCM_VOILUTSequence, stack, ESM_fromHere, OFFalse))
|
||||
+ if (EC_Normal == dset.search(DCM_VOILUTSequence, stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_SQ))
|
||||
{
|
||||
seq=(DcmSequenceOfItems *)stack.top();
|
||||
if (seq->card() ==1)
|
||||
{
|
||||
item = seq->getItem(0);
|
||||
stack.clear();
|
||||
- if (EC_Normal == item->search((DcmTagKey &)voiLUTDescriptor.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse))
|
||||
+
|
||||
+ // LUTDescriptor can be US or SS
|
||||
+ if ((EC_Normal == item->search((DcmTagKey &)voiLUTDescriptor.getTag(),
|
||||
+ stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_SS))
|
||||
{
|
||||
- voiLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // We explicitly use DcmElement::operator=(), which works for US and SS
|
||||
+ DcmElement *vLUTDescriptor = &voiLUTDescriptor;
|
||||
+ vLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, stack.top()));
|
||||
}
|
||||
+
|
||||
stack.clear();
|
||||
if (EC_Normal == item->search((DcmTagKey &)voiLUTExplanation.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse))
|
||||
+ stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_LO))
|
||||
{
|
||||
voiLUTExplanation = *((DcmLongString *)(stack.top()));
|
||||
}
|
||||
stack.clear();
|
||||
if (EC_Normal == item->search((DcmTagKey &)voiLUTData.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse))
|
||||
+ stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_OW))
|
||||
{
|
||||
- voiLUTData = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // we deliberately call DcmElement::operator=() here, which will work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
|
||||
+ DcmElement *vldata = &voiLUTData;
|
||||
+ vldata->operator=(*(DcmElement *)(stack.top()));
|
||||
}
|
||||
} else {
|
||||
result=EC_TagNotFound;
|
||||
@@ -177,10 +185,16 @@ OFCondition DVPSSoftcopyVOI::write(DcmItem &dset)
|
||||
dseq = new DcmSequenceOfItems(DCM_VOILUTSequence);
|
||||
if (dseq)
|
||||
{
|
||||
- delem = new DcmUnsignedShort(voiLUTDescriptor);
|
||||
+ // we clone voiLUTDescriptor in order to retain the VR (US or SS)
|
||||
+ delem = OFstatic_cast(DcmElement *, voiLUTDescriptor.clone());
|
||||
if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted;
|
||||
- delem = new DcmUnsignedShort(voiLUTData);
|
||||
+
|
||||
+ // we write LUTData as OW in order to avoid the 64 kByte limit for US
|
||||
+ delem = new DcmOtherByteOtherWord(DCM_LUTData);
|
||||
+ delem->operator=(voiLUTData);
|
||||
+ OFstatic_cast(DcmOtherByteOtherWord *, delem)->setVR(EVR_OW);
|
||||
if (delem) ditem->insert(delem, OFTrue /*replaceOld*/); else result=EC_MemoryExhausted;
|
||||
+
|
||||
if (voiLUTExplanation.getLength() >0)
|
||||
{
|
||||
delem = new DcmLongString(voiLUTExplanation);
|
||||
diff --git a/dcmpstat/libsrc/dvpssvl.cc b/dcmpstat/libsrc/dvpssvl.cc
|
||||
index d1532db5c..efcb6a26b 100644
|
||||
--- a/dcmpstat/libsrc/dvpssvl.cc
|
||||
+++ b/dcmpstat/libsrc/dvpssvl.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 1999-2023, OFFIS e.V.
|
||||
+ * Copyright (C) 1999-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -72,7 +72,7 @@ OFCondition DVPSSoftcopyVOI_PList::read(DcmItem &dset)
|
||||
DcmSequenceOfItems *dseq=NULL;
|
||||
DcmItem *ditem=NULL;
|
||||
|
||||
- if (EC_Normal == dset.search(DCM_SoftcopyVOILUTSequence, stack, ESM_fromHere, OFFalse))
|
||||
+ if (EC_Normal == dset.search(DCM_SoftcopyVOILUTSequence, stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_SQ))
|
||||
{
|
||||
dseq=(DcmSequenceOfItems *)stack.top();
|
||||
if (dseq)
|
||||
@@ -249,29 +249,36 @@ OFCondition DVPSSoftcopyVOI_PList::createFromImage(
|
||||
if (result==EC_Normal)
|
||||
{
|
||||
stack.clear();
|
||||
- if (EC_Normal == dset.search(DCM_VOILUTSequence, stack, ESM_fromHere, OFFalse))
|
||||
+ if (EC_Normal == dset.search(DCM_VOILUTSequence, stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_SQ))
|
||||
{
|
||||
seq=(DcmSequenceOfItems *)stack.top();
|
||||
if (seq->card() > 0)
|
||||
{
|
||||
item = seq->getItem(0);
|
||||
stack.clear();
|
||||
- if (EC_Normal == item->search((DcmTagKey &)voiLUTDescriptor.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse))
|
||||
+
|
||||
+ // LUTDescriptor can be US or SS
|
||||
+ if ((EC_Normal == item->search((DcmTagKey &)voiLUTDescriptor.getTag(),
|
||||
+ stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_SS))
|
||||
{
|
||||
- voiLUTDescriptor = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // We explicitly use DcmElement::operator=(), which works for US and SS
|
||||
+ DcmElement *vLUTDescriptor = &voiLUTDescriptor;
|
||||
+ vLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, stack.top()));
|
||||
}
|
||||
+
|
||||
stack.clear();
|
||||
if (EC_Normal == item->search((DcmTagKey &)voiLUTExplanation.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse))
|
||||
+ stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_LO))
|
||||
{
|
||||
voiLUTExplanation = *((DcmLongString *)(stack.top()));
|
||||
}
|
||||
stack.clear();
|
||||
if (EC_Normal == item->search((DcmTagKey &)voiLUTData.getTag(),
|
||||
- stack, ESM_fromHere, OFFalse))
|
||||
+ stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_OW))
|
||||
{
|
||||
- voiLUTData = *((DcmUnsignedShort *)(stack.top()));
|
||||
+ // we deliberately call DcmElement::operator=() here, which will work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
|
||||
+ DcmElement *vldata = &voiLUTData;
|
||||
+ vldata->operator=(*(DcmElement *)(stack.top()));
|
||||
}
|
||||
} else result=EC_TagNotFound;
|
||||
}
|
||||
diff --git a/dcmpstat/libsrc/dvpstat.cc b/dcmpstat/libsrc/dvpstat.cc
|
||||
index ce2f5ad5f..4bfe8f9cb 100644
|
||||
--- a/dcmpstat/libsrc/dvpstat.cc
|
||||
+++ b/dcmpstat/libsrc/dvpstat.cc
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
- * Copyright (C) 1998-2021, OFFIS e.V.
|
||||
+ * Copyright (C) 1998-2024, OFFIS e.V.
|
||||
* All rights reserved. See COPYRIGHT file for details.
|
||||
*
|
||||
* This software and supporting documentation were developed by
|
||||
@@ -578,14 +578,14 @@ OFCondition DVPresentationState::attachImage(DcmDataset *dataset, OFBool transfe
|
||||
currentImageSelectedFrame = 1; // default: first frame
|
||||
|
||||
// get Modality
|
||||
- if (EC_Normal == dataset->search(DCM_Modality, stack, ESM_fromHere, OFFalse))
|
||||
+ if (EC_Normal == dataset->search(DCM_Modality, stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_CS))
|
||||
{
|
||||
currentImageModality = *((DcmCodeString *)(stack.top()));
|
||||
}
|
||||
stack.clear();
|
||||
|
||||
// determine default Presentation LUT Shape
|
||||
- if (EC_Normal == dataset->search(DCM_PhotometricInterpretation, stack, ESM_fromHere, OFFalse))
|
||||
+ if (EC_Normal == dataset->search(DCM_PhotometricInterpretation, stack, ESM_fromHere, OFFalse) && (stack.top()->ident() == EVR_CS))
|
||||
{
|
||||
DcmCodeString *photometricInterpretation = (DcmCodeString *)(stack.top());
|
||||
if (photometricInterpretation->getVM() == 1)
|
||||
@@ -598,12 +598,12 @@ OFCondition DVPresentationState::attachImage(DcmDataset *dataset, OFBool transfe
|
||||
stack.clear();
|
||||
|
||||
// get SOP class UID and SOP instance UID.
|
||||
- if ((EC_Normal == result)&&(EC_Normal == dataset->search(DCM_SOPClassUID, stack, ESM_fromHere, OFFalse)))
|
||||
+ if ((EC_Normal == result)&&(EC_Normal == dataset->search(DCM_SOPClassUID, stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_UI))
|
||||
{
|
||||
result = ((DcmUniqueIdentifier *)(stack.top()))->getString(currentImageSOPClassUID);
|
||||
}
|
||||
stack.clear();
|
||||
- if ((EC_Normal == result)&&(EC_Normal == dataset->search(DCM_SOPInstanceUID, stack, ESM_fromHere, OFFalse)))
|
||||
+ if ((EC_Normal == result)&&(EC_Normal == dataset->search(DCM_SOPInstanceUID, stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_UI))
|
||||
{
|
||||
result = ((DcmUniqueIdentifier *)(stack.top()))->getString(currentImageSOPInstanceUID);
|
||||
}
|
||||
@@ -1124,40 +1124,36 @@ OFCondition DVPresentationState::setGammaVOILUT(double gammaValue, DVPSObjectApp
|
||||
numEntries16 = (Uint16)numberOfEntries;
|
||||
|
||||
/* LUT Descriptor */
|
||||
- DcmElement *lutDescriptor = NULL;
|
||||
- if (firstMapped < 0)
|
||||
+ DcmUnsignedShort *lutDescriptor = new DcmUnsignedShort(DcmTag(DCM_LUTDescriptor, EVR_US));
|
||||
+ if (lutDescriptor == NULL) status = EC_MemoryExhausted;
|
||||
+ else
|
||||
{
|
||||
- // LUT Descriptor is SS
|
||||
- lutDescriptor = new DcmSignedShort(DcmTag(DCM_LUTDescriptor, EVR_SS));
|
||||
- if (lutDescriptor != NULL)
|
||||
+ if (firstMapped < 0)
|
||||
{
|
||||
- status = lutDescriptor->putSint16((Sint16)numEntries16, 0);
|
||||
- if (EC_Normal == status)
|
||||
- status = lutDescriptor->putSint16((Sint16)firstMapped, 1);
|
||||
- if (EC_Normal == status)
|
||||
- status = lutDescriptor->putSint16((Sint16)numberOfBits, 2);
|
||||
- } else
|
||||
- status = EC_MemoryExhausted;
|
||||
- } else {
|
||||
- // LUT Descriptor is US
|
||||
- lutDescriptor = new DcmUnsignedShort(DcmTag(DCM_LUTDescriptor, EVR_US));
|
||||
- if (lutDescriptor != NULL)
|
||||
- {
|
||||
- status = lutDescriptor->putUint16(numEntries16, 0);
|
||||
- if (EC_Normal == status)
|
||||
- status = lutDescriptor->putUint16((Uint16)firstMapped, 1);
|
||||
- if (EC_Normal == status)
|
||||
- status = lutDescriptor->putUint16((Uint16)numberOfBits, 2);
|
||||
- } else
|
||||
- status = EC_MemoryExhausted;
|
||||
+ // LUT Descriptor is SS
|
||||
+ DcmSignedShort ldesc(DcmTag(DCM_LUTDescriptor, EVR_SS));
|
||||
+ status = ldesc.putSint16((Sint16)numEntries16, 0);
|
||||
+ if (EC_Normal == status) status = ldesc.putSint16((Sint16)firstMapped, 1);
|
||||
+ if (EC_Normal == status) status = ldesc.putSint16((Sint16)numberOfBits, 2);
|
||||
+ if (EC_Normal == status)
|
||||
+ {
|
||||
+ // copy content of SS element into DcmUnsignedShort using DcmElement::operator=
|
||||
+ DcmElement *ld = lutDescriptor;
|
||||
+ ld->operator=(ldesc);
|
||||
+ }
|
||||
+ } else {
|
||||
+ // LUT Descriptor is US
|
||||
+ status = lutDescriptor->putUint16(numEntries16, 0);
|
||||
+ if (EC_Normal == status) status = lutDescriptor->putUint16((Uint16)firstMapped, 1);
|
||||
+ if (EC_Normal == status) status = lutDescriptor->putUint16((Uint16)numberOfBits, 2);
|
||||
+ }
|
||||
}
|
||||
|
||||
/* LUT Data */
|
||||
- DcmElement *lutData = NULL;
|
||||
+ DcmUnsignedShort *lutData = NULL;
|
||||
if (status == EC_Normal)
|
||||
{
|
||||
- // LUT Data as OW, because of max size = 64K
|
||||
- lutData = new DcmOtherByteOtherWord(DcmTag(DCM_LUTData, EVR_OW));
|
||||
+ lutData = new DcmUnsignedShort(DcmTag(DCM_LUTData, EVR_US));
|
||||
if (lutData != NULL)
|
||||
status = lutData->putUint16Array(data, numberOfEntries);
|
||||
else
|
||||
@@ -1186,15 +1182,14 @@ OFCondition DVPresentationState::setGammaVOILUT(double gammaValue, DVPSObjectApp
|
||||
if (status == EC_Normal)
|
||||
{
|
||||
if ((lutDescriptor != NULL) && (lutData != NULL) && (lutExplanation != NULL))
|
||||
- status = setVOILUT(*(DcmUnsignedShort *)lutDescriptor, *(DcmUnsignedShort *)lutData, *lutExplanation, applicability);
|
||||
+ status = setVOILUT(*lutDescriptor, *lutData, *lutExplanation, applicability);
|
||||
}
|
||||
|
||||
/* delete temporary dcmtk structures */
|
||||
delete lutDescriptor;
|
||||
delete lutData;
|
||||
delete lutExplanation;
|
||||
- } else
|
||||
- status = EC_MemoryExhausted;
|
||||
+ } else status = EC_MemoryExhausted;
|
||||
delete[] data;
|
||||
}
|
||||
return status;
|
||||
diff --git a/dcmpstat/libsrc/dvpsvl.cc b/dcmpstat/libsrc/dvpsvl.cc
|
||||
index b10b83f20..fdba0a0e0 100644
|
||||
--- a/dcmpstat/libsrc/dvpsvl.cc
|
||||
+++ b/dcmpstat/libsrc/dvpsvl.cc
|
||||
@@ -59,9 +59,24 @@ OFCondition DVPSVOILUT::read(DcmItem &dset)
|
||||
OFCondition result = EC_Normal;
|
||||
DcmStack stack;
|
||||
|
||||
- READ_FROM_DATASET(DcmUnsignedShort, EVR_US, voiLUTDescriptor)
|
||||
+ // LUTDescriptor can be US or SS
|
||||
+ if ((EC_Normal == dset.search((DcmTagKey &)voiLUTDescriptor.getTag(),
|
||||
+ stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_SS))
|
||||
+ {
|
||||
+ // We explicitly use DcmElement::operator=(), which works for US and SS
|
||||
+ DcmElement *vLUTDescriptor = &voiLUTDescriptor;
|
||||
+ vLUTDescriptor->operator=(* OFstatic_cast(DcmElement *, stack.top()));
|
||||
+ }
|
||||
+
|
||||
READ_FROM_DATASET(DcmLongString, EVR_LO, voiLUTExplanation)
|
||||
- READ_FROM_DATASET(DcmUnsignedShort, EVR_US, voiLUTData)
|
||||
+
|
||||
+ stack.clear();
|
||||
+ if ((EC_Normal == dset.search((DcmTagKey &)voiLUTData.getTag(), stack, ESM_fromHere, OFFalse)) && (stack.top()->ident() == EVR_US || stack.top()->ident() == EVR_OW))
|
||||
+ {
|
||||
+ // we deliberately call DcmElement::operator=() here, which will work for both DcmUnsignedShort and DcmOtherByteOtherWord parameters
|
||||
+ DcmElement *vldata = &voiLUTData;
|
||||
+ vldata->operator=(*(DcmElement *)(stack.top()));
|
||||
+ }
|
||||
|
||||
if (EC_Normal == result)
|
||||
{
|
||||
--
|
||||
2.44.0
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
From 7d54f8efec995e5601d089fa17b0625c2b41af23 Mon Sep 17 00:00:00 2001
|
||||
From: Joerg Riesmeier <dicom@jriesmeier.com>
|
||||
Date: Mon, 22 Apr 2024 12:11:11 +0200
|
||||
Subject: [PATCH 3/3] Fixed wrong error handling (previous commit).
|
||||
|
||||
Fixed wrong error handling introduced with the previous commit.
|
||||
---
|
||||
dcmrt/libsrc/drttypes.cc | 6 +++---
|
||||
dcmsr/libsrc/dsrtypes.cc | 32 ++++++++++++++++++++------------
|
||||
2 files changed, 23 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/dcmrt/libsrc/drttypes.cc b/dcmrt/libsrc/drttypes.cc
|
||||
index 77ff1674c..097ab9727 100644
|
||||
--- a/dcmrt/libsrc/drttypes.cc
|
||||
+++ b/dcmrt/libsrc/drttypes.cc
|
||||
@@ -210,11 +210,11 @@ OFCondition DRTTypes::getAndCheckStringValueFromDataset(DcmItem &dataset,
|
||||
{
|
||||
DcmStack stack;
|
||||
OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/);
|
||||
- if (result.good() && stack.top()->isElement())
|
||||
+ if (result.good())
|
||||
{
|
||||
- DcmElement *element = OFstatic_cast(DcmElement *, stack.top());
|
||||
- if (element != NULL)
|
||||
+ if (stack.top()->isElement())
|
||||
{
|
||||
+ DcmElement *element = OFstatic_cast(DcmElement *, stack.top());
|
||||
if (checkElementValue(*element, vm, type, result, moduleName))
|
||||
result = element->getOFString(stringValue, 0);
|
||||
else
|
||||
diff --git a/dcmsr/libsrc/dsrtypes.cc b/dcmsr/libsrc/dsrtypes.cc
|
||||
index a9d621859..166bfabff 100644
|
||||
--- a/dcmsr/libsrc/dsrtypes.cc
|
||||
+++ b/dcmsr/libsrc/dsrtypes.cc
|
||||
@@ -1178,13 +1178,17 @@ OFCondition DSRTypes::getAndCheckElementFromDataset(DcmItem &dataset,
|
||||
DcmStack stack;
|
||||
const DcmTagKey tagKey = delem.getTag();
|
||||
OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/);
|
||||
- if (result.good() && stack.top()->isElement())
|
||||
+ if (result.good())
|
||||
{
|
||||
- /* copy object from search stack */
|
||||
- result = delem.copyFrom(*stack.top());
|
||||
- /* we need a reference to the original element in order to determine the SpecificCharacterSet */
|
||||
- if (!checkElementValue(OFstatic_cast(DcmElement *, stack.top()), tagKey, vm, type, result, moduleName, acceptViolation))
|
||||
- result = SR_EC_InvalidValue;
|
||||
+ if (stack.top()->isElement())
|
||||
+ {
|
||||
+ /* copy object from search stack */
|
||||
+ result = delem.copyFrom(*stack.top());
|
||||
+ /* we need a reference to the original element in order to determine the SpecificCharacterSet */
|
||||
+ if (!checkElementValue(OFstatic_cast(DcmElement *, stack.top()), tagKey, vm, type, result, moduleName, acceptViolation))
|
||||
+ result = SR_EC_InvalidValue;
|
||||
+ } else
|
||||
+ result = EC_CorruptedData;
|
||||
}
|
||||
/* the element could not be found in the dataset */
|
||||
else if (!checkElementValue(delem, vm, type, result, moduleName, acceptViolation))
|
||||
@@ -1203,13 +1207,17 @@ OFCondition DSRTypes::getAndCheckStringValueFromDataset(DcmItem &dataset,
|
||||
{
|
||||
DcmStack stack;
|
||||
OFCondition result = dataset.search(tagKey, stack, ESM_fromHere, OFFalse /*searchIntoSub*/);
|
||||
- if (result.good() && stack.top()->isElement())
|
||||
+ if (result.good())
|
||||
{
|
||||
- DcmElement *delem = OFstatic_cast(DcmElement *, stack.top());
|
||||
- /* we need a reference to the original element in order to determine the SpecificCharacterSet */
|
||||
- if (!checkElementValue(delem, tagKey, vm, type, result, moduleName, acceptViolation))
|
||||
- result = SR_EC_InvalidValue;
|
||||
- delem->getOFString(stringValue, 0);
|
||||
+ if (stack.top()->isElement())
|
||||
+ {
|
||||
+ DcmElement *delem = OFstatic_cast(DcmElement *, stack.top());
|
||||
+ /* we need a reference to the original element in order to determine the SpecificCharacterSet */
|
||||
+ if (!checkElementValue(delem, tagKey, vm, type, result, moduleName, acceptViolation))
|
||||
+ result = SR_EC_InvalidValue;
|
||||
+ delem->getOFString(stringValue, 0);
|
||||
+ } else
|
||||
+ result = EC_CorruptedData;
|
||||
} else {
|
||||
if ((type == "1") || (type == "2"))
|
||||
{
|
||||
--
|
||||
2.44.0
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:232076655503138debf2f624109f1799e539354f186ce4e04b27cf82a9d8720f
|
||||
size 9628364
|
||||
3
dcmtk-3.7.0.tar.gz
Normal file
3
dcmtk-3.7.0.tar.gz
Normal file
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f103df876040a4f904f01d2464f7868b4feb659d8cd3f46a5f1f61aa440be415
|
||||
size 9735627
|
||||
@@ -1,4 +1,4 @@
|
||||
From 6bb5b2b2865b4b57a80d5f801a43453918666d99 Mon Sep 17 00:00:00 2001
|
||||
From 67419b8bd14ad1f559312d8b3cf5827185a91554 Mon Sep 17 00:00:00 2001
|
||||
From: Christophe Giboudeaux <christophe@krop.fr>
|
||||
Date: Sat, 23 Jul 2022 09:21:38 +0200
|
||||
Subject: [PATCH] Don't add executables to exported CMake targets
|
||||
@@ -10,7 +10,7 @@ This prevents installing the devel package without requiring the dcmtk utilities
|
||||
2 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/CMake/GenerateCMakeExports.cmake b/CMake/GenerateCMakeExports.cmake
|
||||
index 4512624..11205e3 100644
|
||||
index b4f44e4..0e3cc3c 100644
|
||||
--- a/CMake/GenerateCMakeExports.cmake
|
||||
+++ b/CMake/GenerateCMakeExports.cmake
|
||||
@@ -18,8 +18,8 @@
|
||||
@@ -25,10 +25,10 @@ index 4512624..11205e3 100644
|
||||
# Get and store libraries to DCMTKTargets.cmake within the build's main dir
|
||||
get_property(DCMTK_LIBRARY_TARGETS GLOBAL PROPERTY DCMTK_LIBRARY_TARGETS)
|
||||
diff --git a/CMake/dcmtkMacros.cmake b/CMake/dcmtkMacros.cmake
|
||||
index 6cbce0a..0844e58 100644
|
||||
index 4ba6845..c669d63 100644
|
||||
--- a/CMake/dcmtkMacros.cmake
|
||||
+++ b/CMake/dcmtkMacros.cmake
|
||||
@@ -64,7 +64,7 @@ macro(DCMTK_ADD_EXECUTABLE PROGRAM)
|
||||
@@ -66,7 +66,7 @@ macro(DCMTK_ADD_EXECUTABLE PROGRAM)
|
||||
|
||||
# declare installation files, also export DCMTKTargets.cmake
|
||||
install(TARGETS ${PROGRAM}
|
||||
@@ -38,5 +38,5 @@ index 6cbce0a..0844e58 100644
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
--
|
||||
2.37.1
|
||||
2.52.0
|
||||
|
||||
|
||||
@@ -1,10 +1,85 @@
|
||||
-------------------------------------------------------------------
|
||||
Sun Jan 4 10:12:31 UTC 2026 - Christophe Marin <christophe@krop.fr>
|
||||
|
||||
- Update to 3.7.0. See docs/CHANGES.370 for the full list of changes
|
||||
* Fixes CVE-2025-14841 / boo#1255292
|
||||
* Fixes CVE-2025-14607 / boo#1255464
|
||||
- Drop patches, merged upstream:
|
||||
* 0001-Added-check-to-make-sure-HighBit-BitsAllocated.patch
|
||||
* 0001-Fixed-issue-rendering-invalid-monochrome-image.patch
|
||||
* 0001-Fixed-another-issue-with-invalid-mono-images.patch
|
||||
* 0001-Replaced-call-of-delete-by-delete.patch
|
||||
* 0001-Fixed-another-issue-with-invalid-DICOM-images.patch
|
||||
* 0001-Fixed-issue-with-invalid-RLE-compressed-DICOM-images.patch
|
||||
* CVE-2025-2357.patch
|
||||
* CVE-2025-9732.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Nov 26 14:38:25 UTC 2025 - Fabian Vogt <fvogt@suse.com>
|
||||
|
||||
- Add patch to avoid unnecessary dependencies (boo#1254123):
|
||||
* 0001-dcmimage-Link-privately-to-libtiff-and-libpng.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Sep 1 08:22:33 UTC 2025 - Christophe Marin <christophe@krop.fr>
|
||||
|
||||
- Add upstream change (CVE-2025-9732, boo#1248995)
|
||||
* CVE-2025-9732.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Mar 17 10:31:13 UTC 2025 - Christophe Marin <christophe@krop.fr>
|
||||
|
||||
- Add upstream change (CVE-2025-2357, boo#1239679)
|
||||
* CVE-2025-2357.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Feb 19 14:09:24 UTC 2025 - Christophe Marin <christophe@krop.fr>
|
||||
|
||||
- Add patches:
|
||||
* 0001-Fixed-another-issue-with-invalid-mono-images.patch
|
||||
(CVE-2025-25472, boo#1237369)
|
||||
* 0001-Fixed-another-issue-with-invalid-DICOM-images.patch
|
||||
(CVE-2025-25474, boo#1237365)
|
||||
* 0001-Fixed-issue-with-invalid-RLE-compressed-DICOM-images.patch
|
||||
(CVE-2025-25475, boo#1237355)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jan 13 18:43:39 UTC 2025 - Christophe Marin <christophe@krop.fr>
|
||||
|
||||
- Update to 3.6.9. See DOCS/CHANGES.368 for the full list of changes
|
||||
- Drop patches, merged upstream:
|
||||
* 0001-Fixed-buffer-overflow-in-decompression-codecs.patch
|
||||
* 0001-Fixed-possible-overflows-when-allocating-memory.patch
|
||||
* 0001-Fixed-two-segmentation-faults.patch
|
||||
* 0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch
|
||||
* 0002-Fixed-unchecked-typecasts-and-fixed-LUT-handling.patch
|
||||
* 0003-Fixed-wrong-error-handling-previous-commit.patch
|
||||
* 0001-Fixed-DcmDecimalString-unit-tests.patch
|
||||
* 0001-Fixed-link-instructions-for-libtiff.patch
|
||||
* 0001-Fix-find_package-library-variables-for-libtiff.patch
|
||||
- Add patches:
|
||||
* 0001-Added-check-to-make-sure-HighBit-BitsAllocated.patch
|
||||
(CVE-2024-52333, boo#1235811)
|
||||
* 0001-Replaced-call-of-delete-by-delete.patch
|
||||
* 0001-Fixed-issue-rendering-invalid-monochrome-image.patch
|
||||
(CVE-2024-47796, boo#1235810)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Nov 20 16:59:26 UTC 2024 - Christophe Marin <christophe@krop.fr>
|
||||
|
||||
- Add patches:
|
||||
* 0001-Fixed-link-instructions-for-libtiff.patch
|
||||
* 0001-Fix-find_package-library-variables-for-libtiff.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Apr 24 07:45:23 UTC 2024 - Christophe Marin <christophe@krop.fr>
|
||||
|
||||
- Add upstream changes:
|
||||
* 0001-Fixed-buffer-overflow-in-decompression-codecs.patch
|
||||
* 0001-Fixed-possible-overflows-when-allocating-memory.patch
|
||||
(boo#1227235, CVE-2024-27628)
|
||||
* 0001-Fixed-two-segmentation-faults.patch
|
||||
(boo#1223949, CVE-2024-34509, boo#1223925, CVE-2024-34508)
|
||||
* 0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch
|
||||
* 0002-Fixed-unchecked-typecasts-and-fixed-LUT-handling.patch
|
||||
(boo#1223324, CVE-2024-28130)
|
||||
|
||||
28
dcmtk.spec
28
dcmtk.spec
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# spec file for package dcmtk
|
||||
#
|
||||
# Copyright (c) 2024 SUSE LLC
|
||||
# Copyright (c) 2025 SUSE LLC and contributors
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
@@ -16,24 +16,18 @@
|
||||
#
|
||||
|
||||
|
||||
%define abiversion 18
|
||||
%define abiversion 20
|
||||
Name: dcmtk
|
||||
Version: 3.6.8
|
||||
Version: 3.7.0
|
||||
Release: 0
|
||||
Summary: DICOM Toolkit
|
||||
License: Apache-2.0 AND BSD-3-Clause
|
||||
URL: https://dicom.offis.de/dcmtk.php.en
|
||||
Source0: ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/release/%{name}-%{version}.tar.gz
|
||||
Source0: https://dicom.offis.de/download/dcmtk/dcmtk370/%{name}-%{version}.tar.gz
|
||||
# PATCH-FIX-OPENSUSE dcmtk-fix-DCMTKTargets.cmake.patch -- Do not track executables to be able to use dcmtk-devel without dcmtk package
|
||||
Patch0: dcmtk-fix-DCMTKTargets.cmake.patch
|
||||
# PATCH-FIX-UPSTREAM
|
||||
Patch1: 0001-Fixed-buffer-overflow-in-decompression-codecs.patch
|
||||
Patch2: 0001-Fixed-possible-overflows-when-allocating-memory.patch
|
||||
Patch3: 0001-Fixed-two-segmentation-faults.patch
|
||||
Patch4: 0001-Fixed-unchecked-typecasts-of-DcmItem-search-results.patch
|
||||
Patch5: 0002-Fixed-unchecked-typecasts-and-fixed-LUT-handling.patch
|
||||
Patch6: 0003-Fixed-wrong-error-handling-previous-commit.patch
|
||||
Patch7: 0001-Fixed-DcmDecimalString-unit-tests.patch
|
||||
Patch1: 0001-dcmimage-Link-privately-to-libtiff-and-libpng.patch
|
||||
BuildRequires: cmake
|
||||
BuildRequires: doxygen
|
||||
BuildRequires: fdupes
|
||||
@@ -61,7 +55,6 @@ Requires: libdcmtk%{abiversion} = %{version}
|
||||
Requires: tcpd-devel
|
||||
Requires: pkgconfig(libjpeg)
|
||||
Requires: pkgconfig(libopenjp2)
|
||||
Requires: pkgconfig(libpng)
|
||||
Requires: pkgconfig(libxml-2.0)
|
||||
|
||||
%description devel
|
||||
@@ -70,8 +63,6 @@ software using dcmtk.
|
||||
|
||||
%package -n libdcmtk%{abiversion}
|
||||
Summary: DICOM Toolkit
|
||||
Provides: libdcmtk3_6 = %{version}
|
||||
Obsoletes: libdcmtk3_6 < %{version}
|
||||
|
||||
%description -n libdcmtk%{abiversion}
|
||||
DCMTK is a collection of libraries and applications implementing large
|
||||
@@ -86,7 +77,8 @@ parts the DICOM standard.
|
||||
-DDCMTK_WITH_XML=ON \
|
||||
-DDCMTK_WITH_OPENSSL=ON \
|
||||
-DDCMTK_WITH_SNDFILE=ON \
|
||||
-DDCMTK_WITH_ZLIB=ON}
|
||||
-DDCMTK_WITH_ZLIB=ON \
|
||||
-DCMAKE_INSTALL_SYSCONFDIR=%{_sysconfdir}}
|
||||
|
||||
%cmake_build
|
||||
|
||||
@@ -106,7 +98,8 @@ install -pm 0644 README %{buildroot}%{_docdir}/dcmtk/
|
||||
%fdupes %{buildroot}
|
||||
|
||||
%check
|
||||
%ctest
|
||||
# dcmect_roundtrip fails on s390x
|
||||
%ctest --exclude-regex 'dcmect_roundtrip'
|
||||
|
||||
%ldconfig_scriptlets -n libdcmtk%{abiversion}
|
||||
|
||||
@@ -121,7 +114,6 @@ install -pm 0644 README %{buildroot}%{_docdir}/dcmtk/
|
||||
%{_mandir}/man1/*
|
||||
|
||||
%files devel
|
||||
%license COPYRIGHT
|
||||
%{_includedir}/dcmtk/
|
||||
%{_libdir}/*.so
|
||||
%{_libdir}/cmake/dcmtk/
|
||||
@@ -130,6 +122,6 @@ install -pm 0644 README %{buildroot}%{_docdir}/dcmtk/
|
||||
%files -n libdcmtk%{abiversion}
|
||||
%license COPYRIGHT
|
||||
%{_libdir}/*.so.%{abiversion}
|
||||
%{_libdir}/*.so.%{abiversion}.3.6*
|
||||
%{_libdir}/*.so.%{abiversion}.3.7*
|
||||
|
||||
%changelog
|
||||
|
||||
Reference in New Issue
Block a user