From f63b40858c110f671ae0867a10ac2ce7624f1b82 Mon Sep 17 00:00:00 2001 From: chafey Date: Mon, 3 Aug 2015 23:32:22 -0500 Subject: [PATCH] fixes for parsing undefined length sequences with zero items --- bower.json | 2 +- dist/dicomParser.js | 58 ++++++++++++---------- examples/dumpWithDataDictionary/index.html | 14 +++++- package.json | 2 +- src/findItemDelimitationItem.js | 2 +- src/readDicomElementImplicit.js | 7 +++ src/readSequenceElementExplicit.js | 23 ++++----- src/readSequenceElementImplicit.js | 24 ++++----- 8 files changed, 78 insertions(+), 54 deletions(-) diff --git a/bower.json b/bower.json index 7c2dca2..b04e254 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "dicomParser", - "version": "1.1.0", + "version": "1.1.1", "description": "Javascript parser for DICOM Part 10 data", "main" : "dist/dicomParser.js", "ignore": [ diff --git a/dist/dicomParser.js b/dist/dicomParser.js index a2a5287..31df691 100644 --- a/dist/dicomParser.js +++ b/dist/dicomParser.js @@ -1,4 +1,4 @@ -/*! dicom-parser - v1.1.0 - 2015-08-03 | (c) 2014 Chris Hafey | https://github.com/chafey/dicomParser */ +/*! dicom-parser - v1.1.1 - 2015-08-03 | (c) 2014 Chris Hafey | https://github.com/chafey/dicomParser */ (function (root, factory) { // node.js @@ -1373,7 +1373,7 @@ var dicomParser = (function (dicomParser) if(groupNumber === 0xfffe) { var elementNumber = byteStream.readUint16(); - if(elementNumber === 0xe00d || elementNumber === 0xe0dd) + if(elementNumber === 0xe00d) { // NOTE: It would be better to also check for the length to be 0 as part of the check above // but we will just log a warning for now @@ -1782,6 +1782,13 @@ var dicomParser = (function (dicomParser) var nextTag = dicomParser.readTag(byteStream); byteStream.seek(-4); + // zero length sequence + if (element.hadUndefinedLength && nextTag === 'xfffee0dd') { + element.length = 0; + byteStream.seek(8); + return element; + } + if (nextTag === 'xfffee000') { // parse the sequence dicomParser.readSequenceItemsImplicit(byteStream, element); @@ -1864,21 +1871,20 @@ var dicomParser = (function (dicomParser) { while(byteStream.position < byteStream.byteArray.length) { + // end reading this sequence if the next tag is the sequence delimitation item + var nextTag = dicomParser.readTag(byteStream); + byteStream.seek(-4); + if (nextTag === 'xfffee0dd') { + // set the correct length + element.length = byteStream.position - element.dataOffset; + byteStream.seek(8); + return element; + } + var item = readSequenceItemExplicit(byteStream, warnings); element.items.push(item); - - // If this is the sequence delimitation item, return the offset of the next element - if(item.tag === 'xfffee0dd') - { - // sequence delimitation item, update attr data length and return - element.length = byteStream.position - element.dataOffset; - return; - } } - - // eof encountered - log a warning and set the length of the element based on the buffer size - byteStream.warnings.push('eof encountered before finding sequence delimitation item in sequence element of undefined length with tag ' + element.tag); - element.length = byteStream.byteArray.length - element.dataOffset; + element.length = byteStream.position - element.dataOffset; } function readSQElementKnownLengthExplicit(byteStream, element, warnings) @@ -1943,6 +1949,7 @@ var dicomParser = (function (dicomParser) // the end of this sequence item if(element.tag === 'xfffee00d') { + console.log('end of sequence item'); return new dicomParser.DataSet(byteStream.byteArrayParser, byteStream.byteArray, elements); } } @@ -1973,20 +1980,19 @@ var dicomParser = (function (dicomParser) { while(byteStream.position < byteStream.byteArray.length) { - var item = readSequenceItemImplicit(byteStream); - element.items.push(item); + // end reading this sequence if the next tag is the sequence delimitation item + var nextTag = dicomParser.readTag(byteStream); + byteStream.seek(-4); + if (nextTag === 'xfffee0dd') { + // set the correct length + element.length = byteStream.position - element.dataOffset; + byteStream.seek(8); + return element; + } - // If this is the sequence delimitation item, return the offset of the next element - if(item.tag === 'xfffee0dd') - { - // sequence delimitation item, update attr data length and return - element.length = byteStream.position - element.dataOffset; - return; - } + var item = readSequenceItemImplicit(byteStream); + element.items.push(item); } - - // eof encountered - log a warning and set the length of the element based on the buffer size - byteStream.warnings.push('eof encountered before finding sequence delimitation item in sequence of undefined length'); element.length = byteStream.byteArray.length - element.dataOffset; } diff --git a/examples/dumpWithDataDictionary/index.html b/examples/dumpWithDataDictionary/index.html index 469c6de..ed336e4 100644 --- a/examples/dumpWithDataDictionary/index.html +++ b/examples/dumpWithDataDictionary/index.html @@ -230,7 +230,17 @@

DICOM Dump with Data Dictionary

// and recursively call this function var itemNumber = 0; element.items.forEach(function (item) { - output.push('
  • Item #' + itemNumber++ + ' ' + item.tag + '
  • ') + output.push('
  • Item #' + itemNumber++ + ' ' + item.tag); + var lengthText = " length=" + item.length; + if (item.hadUndefinedLength) { + lengthText += " (-1)"; + } + + if(showLength === true) { + text += lengthText + "; "; + output.push(lengthText); + } + output.push('
  • '); output.push(''); @@ -382,6 +392,8 @@

    DICOM Dump with Data Dictionary

    var elementHexStr = ("0000" + element.toString(16)).substr(-4); text += "x" + groupHexStr + elementHexStr; } + else if(vr === 'SQ') { + } else { // If it is some other length and we have no string text += "no display code for VR " + vr + " yet, sorry!"; diff --git a/package.json b/package.json index 9b7a582..1f44cd7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dicom-parser", - "version": "1.1.0", + "version": "1.1.1", "description": "Javascript parser for DICOM Part 10 data", "keywords": [ "DICOM", diff --git a/src/findItemDelimitationItem.js b/src/findItemDelimitationItem.js index 4bbf1df..5193d4c 100644 --- a/src/findItemDelimitationItem.js +++ b/src/findItemDelimitationItem.js @@ -32,7 +32,7 @@ var dicomParser = (function (dicomParser) if(groupNumber === 0xfffe) { var elementNumber = byteStream.readUint16(); - if(elementNumber === 0xe00d || elementNumber === 0xe0dd) + if(elementNumber === 0xe00d) { // NOTE: It would be better to also check for the length to be 0 as part of the check above // but we will just log a warning for now diff --git a/src/readDicomElementImplicit.js b/src/readDicomElementImplicit.js index f031164..f5df0a2 100644 --- a/src/readDicomElementImplicit.js +++ b/src/readDicomElementImplicit.js @@ -40,6 +40,13 @@ var dicomParser = (function (dicomParser) var nextTag = dicomParser.readTag(byteStream); byteStream.seek(-4); + // zero length sequence + if (element.hadUndefinedLength && nextTag === 'xfffee0dd') { + element.length = 0; + byteStream.seek(8); + return element; + } + if (nextTag === 'xfffee000') { // parse the sequence dicomParser.readSequenceItemsImplicit(byteStream, element); diff --git a/src/readSequenceElementExplicit.js b/src/readSequenceElementExplicit.js index f55318e..53e90b3 100644 --- a/src/readSequenceElementExplicit.js +++ b/src/readSequenceElementExplicit.js @@ -56,21 +56,20 @@ var dicomParser = (function (dicomParser) { while(byteStream.position < byteStream.byteArray.length) { + // end reading this sequence if the next tag is the sequence delimitation item + var nextTag = dicomParser.readTag(byteStream); + byteStream.seek(-4); + if (nextTag === 'xfffee0dd') { + // set the correct length + element.length = byteStream.position - element.dataOffset; + byteStream.seek(8); + return element; + } + var item = readSequenceItemExplicit(byteStream, warnings); element.items.push(item); - - // If this is the sequence delimitation item, return the offset of the next element - if(item.tag === 'xfffee0dd') - { - // sequence delimitation item, update attr data length and return - element.length = byteStream.position - element.dataOffset; - return; - } } - - // eof encountered - log a warning and set the length of the element based on the buffer size - byteStream.warnings.push('eof encountered before finding sequence delimitation item in sequence element of undefined length with tag ' + element.tag); - element.length = byteStream.byteArray.length - element.dataOffset; + element.length = byteStream.position - element.dataOffset; } function readSQElementKnownLengthExplicit(byteStream, element, warnings) diff --git a/src/readSequenceElementImplicit.js b/src/readSequenceElementImplicit.js index e05cd9e..4d81407 100644 --- a/src/readSequenceElementImplicit.js +++ b/src/readSequenceElementImplicit.js @@ -24,6 +24,7 @@ var dicomParser = (function (dicomParser) // the end of this sequence item if(element.tag === 'xfffee00d') { + console.log('end of sequence item'); return new dicomParser.DataSet(byteStream.byteArrayParser, byteStream.byteArray, elements); } } @@ -54,20 +55,19 @@ var dicomParser = (function (dicomParser) { while(byteStream.position < byteStream.byteArray.length) { - var item = readSequenceItemImplicit(byteStream); - element.items.push(item); + // end reading this sequence if the next tag is the sequence delimitation item + var nextTag = dicomParser.readTag(byteStream); + byteStream.seek(-4); + if (nextTag === 'xfffee0dd') { + // set the correct length + element.length = byteStream.position - element.dataOffset; + byteStream.seek(8); + return element; + } - // If this is the sequence delimitation item, return the offset of the next element - if(item.tag === 'xfffee0dd') - { - // sequence delimitation item, update attr data length and return - element.length = byteStream.position - element.dataOffset; - return; - } + var item = readSequenceItemImplicit(byteStream); + element.items.push(item); } - - // eof encountered - log a warning and set the length of the element based on the buffer size - byteStream.warnings.push('eof encountered before finding sequence delimitation item in sequence of undefined length'); element.length = byteStream.byteArray.length - element.dataOffset; }