Project

General

Profile

Bug #463 » useDictForLengthField2.patch

Working(?) patch + tests for this feature - Uli Schlachter, 2012-12-04 16:55

View differences:

dcmdata/include/dcmtk/dcmdata/dcobject.h
*/
extern DCMTK_DCMDATA_EXPORT OFGlobal<OFBool> dcmPreferVRFromDataDictionary; /* default OFFalse */
/** This flag defines how the element's length field is interpreted when reading
* from a dataset with explicit VR encoding and the data dictionary doesn't
* agree with the VR from the dataset. By default, the length field is assumed
* to match the size of the VR in the dataset. If this flag is enabled and the
* tag is defined in the data dictionary, the parser will use the size for the
* VR from the data dictionary (and ignore the one from the dataset). This flag
* is, therefore, useful for reading incorrectly encoded DICOM datasets.
*/
extern DCMTK_DCMDATA_EXPORT OFGlobal<OFBool> dcmPreferLengthFieldSizeFromDataDictionary; /* default OFFalse */
/** This flag indicates, whether private attributes with implicit transfer
* syntax having a maximum length should be handled as sequences (ignoring
* any dictionary entries for that tag). This can happen, if for example
dcmdata/libsrc/dcitem.cc
newTag.setVR(vr);
}
/* determine VR read from dataset, because this VR specifies the number of bytes for the length-field */
newEVR = vr.getEVR();
if (!dcmPreferLengthFieldSizeFromDataDictionary.get() || newEVR == EVR_UNKNOWN || newEVR == EVR_UNKNOWN2B) {
/* determine VR read from dataset, because this VR specifies the number of bytes for the length-field */
newEVR = vr.getEVR();
} else {
/* use the VR from the dictionary for deciding the length of the length field */
}
/* increase counter by 2 */
bytesRead += 2;
dcmdata/libsrc/dcobject.cc
OFGlobal<OFBool> dcmAutoDetectDatasetXfer(OFFalse);
OFGlobal<OFBool> dcmAcceptUnexpectedImplicitEncoding(OFFalse);
OFGlobal<OFBool> dcmPreferVRFromDataDictionary(OFFalse);
OFGlobal<OFBool> dcmPreferLengthFieldSizeFromDataDictionary(OFFalse);
OFGlobal<OFBool> dcmReadImplPrivAttribMaxLengthAsSQ(OFFalse);
OFGlobal<OFBool> dcmIgnoreParsingErrors(OFFalse);
OFGlobal<DcmTagKey> dcmStopParsingAfterElement(DCM_UndefinedTagKey); // (0xffff,0xffff)
dcmdata/tests/tparser.cc
testOddLengthPartialValue(data, sizeof(data));
}
static const DcmTagKey wrongExplicitVRinDataset_unknownTag(0x0006, 0x0006);
static const Uint8 wrongExplicitVRinDataset_testData[] = {
/* This non-standard tag cannot be corrected (not in data dictionary) */
TAG_AND_LENGTH_SHORT(wrongExplicitVRinDataset_unknownTag, 'P', 'N', 4),
'A', 'B', 'C', 'D',
/* This standard tag has a wrong VR ("ST" instead of "PN") */
TAG_AND_LENGTH_SHORT(DCM_PatientName, 'S', 'T', 4),
'A', 'B', 'C', 'D',
/* This standard tag has a wrong VR ("UN") and uses a 4-byte length field */
TAG_AND_LENGTH(DCM_PatientID, 'U', 'N', 4),
'0', '8', '1', '5',
/* This standard tag has a correct VR, no modification required */
TAG_AND_LENGTH_SHORT(DCM_PatientSex, 'C', 'S', 2),
static const DcmTagKey wrongExplicitVRinDataset_unknownTag1(0x0006, 0x0006);
static const DcmTagKey wrongExplicitVRinDataset_unknownTag2(0x0006, 0x0008);
#define WRONG_EXPLICIT_VR_COMMON \
/* This non-standard tag cannot be corrected (not in data dictionary, short length field) */ \
TAG_AND_LENGTH_SHORT(wrongExplicitVRinDataset_unknownTag1, 'P', 'N', 4), \
'A', 'B', 'C', 'D', \
/* This non-standard tag cannot be corrected (not in data dictionary, long length field) */ \
TAG_AND_LENGTH(wrongExplicitVRinDataset_unknownTag2, 'U', 'T', 4), \
'E', 'F', 'G', 'H', \
/* This standard tag has a wrong VR ("ST" instead of "PN") */ \
TAG_AND_LENGTH_SHORT(DCM_PatientName, 'S', 'T', 4), \
'I', 'J', 'K', 'L', \
/* This standard tag has a correct VR, no modification required */ \
TAG_AND_LENGTH_SHORT(DCM_PatientSex, 'C', 'S', 2), \
'O', ' '
static const Uint8 wrongExplicitVRwithDatasetLen_testData[] = {
WRONG_EXPLICIT_VR_COMMON,
/* This standard tag has a wrong VR ("UN") and does not use the "PN" length field size */
TAG_AND_LENGTH(DCM_PatientBirthName, 'U', 'N', 4),
'0', '8', '1', '5',
/* This standard tag has a wrong VR ("LO") and does not use the "UT" length field size */
TAG_AND_LENGTH_SHORT(DCM_PixelDataProviderURL, 'L', 'O', 4),
'4', '2', '4', '2',
};
static const Uint8 wrongExplicitVRwithDictLen_testData[] = {
WRONG_EXPLICIT_VR_COMMON,
/* This standard tag has a wrong VR ("UN") and uses the "PN" length field size */
TAG_AND_LENGTH_SHORT(DCM_PatientBirthName, 'U', 'N', 4),
'0', '8', '1', '5',
/* This standard tag has a wrong VR ("LO") and uses the "UT" length field size */
TAG_AND_LENGTH(DCM_PixelDataProviderURL, 'L', 'O', 4),
'4', '2', '4', '2',
};
#undef WRONG_EXPLICIT_VR_COMMON
static void testForExpectedVR(DcmDataset &dset, const DcmTagKey &tag, const DcmEVR vr)
{
......
}
}
OFTEST(dcmdata_parser_wrongExplicitVRinDataset_default)
static void expectReadError(const Uint8* buffer, size_t length, E_TransferSyntax ts)
{
DcmDataset dset;
OFCondition cond = readDataset(dset, buffer, length, TRANSFER_SYNTAX);
if (cond != EC_InvalidStream)
{
OFCHECK_FAIL("Dataset should fail with invalid stream, but got: " << cond.text());
if (cond.good())
OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset));
}
}
static void testExplicitVRinDataset(OFBool useDictionaryVR, OFBool useDictionaryVRLen)
{
DcmDataset dset;
OFCondition cond;
const Uint8 *broken, *working;
size_t brokenLength, workingLength;
if (useDictionaryVRLen) {
broken = wrongExplicitVRwithDatasetLen_testData;
brokenLength = sizeof(wrongExplicitVRwithDatasetLen_testData);
working = wrongExplicitVRwithDictLen_testData;
workingLength = sizeof(wrongExplicitVRwithDictLen_testData);
} else {
working = wrongExplicitVRwithDatasetLen_testData;
workingLength = sizeof(wrongExplicitVRwithDatasetLen_testData);
broken = wrongExplicitVRwithDictLen_testData;
brokenLength = sizeof(wrongExplicitVRwithDictLen_testData);
}
dcmPreferLengthFieldSizeFromDataDictionary.set(useDictionaryVRLen);
dcmPreferVRFromDataDictionary.set(useDictionaryVR);
// This should use the VR from the dataset (default)
expectReadError(broken, brokenLength, TRANSFER_SYNTAX);
cond = readDataset(dset, working, workingLength, TRANSFER_SYNTAX);
// Reset to the default values
dcmPreferLengthFieldSizeFromDataDictionary.set(OFFalse);
dcmPreferVRFromDataDictionary.set(OFFalse);
cond = readDataset(dset, wrongExplicitVRinDataset_testData, sizeof(wrongExplicitVRinDataset_testData), TRANSFER_SYNTAX);
if (cond.good())
{
OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset));
testForExpectedVR(dset, wrongExplicitVRinDataset_unknownTag, EVR_PN);
testForExpectedVR(dset, DCM_PatientName, EVR_ST);
testForExpectedVR(dset, DCM_PatientID, EVR_UN);
testForExpectedVR(dset, DCM_PatientSex, EVR_CS);
} else {
if (cond.bad()) {
OFCHECK_FAIL(cond.text());
return;
}
OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset));
testForExpectedVR(dset, wrongExplicitVRinDataset_unknownTag1, EVR_PN);
testForExpectedVR(dset, wrongExplicitVRinDataset_unknownTag2, EVR_UT);
testForExpectedVR(dset, DCM_PatientName, useDictionaryVR ? EVR_PN : EVR_ST);
testForExpectedVR(dset, DCM_PatientBirthName, useDictionaryVR ? EVR_PN : EVR_UN);
testForExpectedVR(dset, DCM_PixelDataProviderURL, useDictionaryVR ? EVR_UT : EVR_LO);
}
// TODO make test name and testData-name match
OFTEST(dcmdata_parser_wrongExplicitVRinDataset_default)
{
DcmDataset dset;
OFCondition cond;
// TODO: Split this up into multiple tests
testExplicitVRinDataset(OFFalse, OFFalse);
testExplicitVRinDataset(OFFalse, OFTrue);
testExplicitVRinDataset(OFTrue, OFFalse);
testExplicitVRinDataset(OFTrue, OFTrue);
}
OFTEST(dcmdata_parser_wrongExplicitVRinDataset_preferDataDict)
......
DcmDataset dset;
OFCondition cond;
// This should use the VR from the data dictionary
dcmPreferVRFromDataDictionary.set(OFTrue);
cond = readDataset(dset, wrongExplicitVRinDataset_testData, sizeof(wrongExplicitVRinDataset_testData), TRANSFER_SYNTAX);
if (cond.good())
{
OFLOG_DEBUG(tparserLogger, DcmObject::PrintHelper(dset));
testForExpectedVR(dset, wrongExplicitVRinDataset_unknownTag, EVR_PN);
testForExpectedVR(dset, DCM_PatientName, EVR_PN);
testForExpectedVR(dset, DCM_PatientID, EVR_LO);
testForExpectedVR(dset, DCM_PatientSex, EVR_CS);
} else {
OFCHECK_FAIL(cond.text());
}
// Reset to the default value
dcmPreferVRFromDataDictionary.set(OFFalse);
}
OFTEST(dcmdata_parser_undefinedLengthUNSequence)
(2-2/2)