-
Notifications
You must be signed in to change notification settings - Fork 128
CodeString.writeBytes() throws on valid multivalued CS tag when individual value exceeds maxLength of 16 #487
Description
CodeString.writeBytes() throws on valid multivalued CS tag when individual value exceeds maxLength of 16
Environment
- dcmjs version: 0.50.1
Description
When writing a DICOM dictionary to a file, dcmjs throws an error on a multivalued CS (CodeString) tag. The validation in writeBytes checks the length of each value (after splitting by \) against the CS max length of 16, but the private tag contains values that exceed this limit (e.g. GE_TAG_TRIGGER_TIME is 19 characters).
Steps to Reproduce
- Load a DICOM file containing the following private tag:
| (Group,Element) | TAG Description | VR | VM | Length | Value |
|---|---|---|---|---|---|
| (07A5,1042) | Unknown Tag & Data | CS | 5 | 98 | GE_TAG_TRIGGER_TIME\GE_TAG_MID_SCAN_TIME\GE_TAG_ATTRIBUTE_MODIFICATION_DATETIME\GE_TAG\GE_TAG_ACQ |
- Attempt to write the DICOM dictionary back to a file (e.g. via
DicomDict.write()).
Expected Behaviour
The tag values should be copied as-is from the original file without validation errors, since the data was already present in the source DICOM file.
Actual Behavior
An error is thrown:
Value exceeds max length, vr: CS, value: GE_TAG_TRIGGER_TIME, length: 19
Error: Value exceeds max length, vr: CS, value: GE_TAG_TRIGGER_TIME, length: 19
at CodeString2.writeBytes (dcmjs.js:6800:22)
at CodeString2.writeBytes (dcmjs.js:6890:94)
at Tag2.write (dcmjs.js:8603:26)
at dcmjs.js:8867:24
at Array.forEach (<anonymous>)
at DicomMessage2.write (dcmjs.js:8864:18)
at DicomDict2.write (dcmjs.js:8115:22)
Analysis
The CS VR has a max length of 16 per value.
dcmjs/src/ValueRepresentation.js
Line 658 in 4427728
| this.maxLength = 16; |
The writeBytes method validates each value in a multivalued tag against this limit. GE_TAG_TRIGGER_TIME is 19 characters, which triggers the error.
dcmjs/src/ValueRepresentation.js
Lines 292 to 322 in 4427728
| for (var i = 0; i < valarr.length; i++) { | |
| var checkValue = valarr[i], | |
| checklen = lengths[i], | |
| isString = false, | |
| displaylen = checklen; | |
| if (checkValue === null || allowInvalidVRLength) { | |
| valid = true; | |
| } else if (this.checkLength) { | |
| valid = this.checkLength(checkValue); | |
| } else if (this.maxCharLength) { | |
| var check = this.maxCharLength; //, checklen = checkValue.length; | |
| valid = checkValue.length <= check; | |
| displaylen = checkValue.length; | |
| isString = true; | |
| } else if (this.maxLength) { | |
| valid = checklen <= this.maxLength; | |
| } | |
| if (!valid) { | |
| var errmsg = | |
| "Value exceeds max length, vr: " + | |
| this.type + | |
| ", value: " + | |
| checkValue + | |
| ", length: " + | |
| displaylen; | |
| if (isString) log.info(errmsg); | |
| else throw new Error(errmsg); | |
| } | |
| total += checklen; | |
| } |
This is a private/vendor-specific tag (07A5,1042) from GE. While the values technically violate the DICOM standard's CS length constraint, they are present in real-world DICOM files. dcmjs should arguably be more lenient when writing back data that was successfully read, or at least provide an option to skip validation on writing.
Hex Dump of the Original Tag
Hex View 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
000020D0 07 42 10 43 53 62 00 47 45 5F 54 41 47 .B.CSb.GE_TAG
000020E0 5F 54 52 49 47 47 45 52 5F 54 49 4D 45 5C 47 45 _TRIGGER_TIME\GE
000020F0 5F 54 41 47 5F 4D 49 44 5F 53 43 41 4E 5F 54 49 _TAG_MID_SCAN_TI
00002100 4D 45 5C 47 45 5F 54 41 47 5F 41 54 54 52 49 42 ME\GE_TAG_ATTRIB
00002110 55 54 45 5F 4D 4F 44 49 46 49 43 41 54 49 4F 4E UTE_MODIFICATION
00002120 5F 44 41 54 45 54 49 4D 45 5C 47 45 5F 54 41 47 _DATETIME\GE_TAG
00002130 5C 47 45 5F 54 41 47 5F 41 43 51 \GE_TAG_ACQ