From 2834c48caa29df626d9a88b2a2d7e69dc73d3c56 Mon Sep 17 00:00:00 2001 From: Suyash Kumar Date: Fri, 22 May 2020 12:55:37 -0700 Subject: [PATCH 1/3] Read native pixel metadata from current sequence, if any --- parse.go | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/parse.go b/parse.go index 494dce67..3e0e576d 100755 --- a/parse.go +++ b/parse.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io" + "log" "os" "strconv" "strings" @@ -32,11 +33,12 @@ type Parser interface { // parser implements Parser type parser struct { - decoder *dicomio.Decoder - parsedElements *element.DataSet - op ParseOptions - frameChannel chan *frame.Frame - file *os.File // may be populated if coming from file + decoder *dicomio.Decoder + parsedElements *element.DataSet + op ParseOptions + frameChannel chan *frame.Frame + file *os.File // may be populated if coming from file + currentSequenceDataset *element.DataSet } // NewParser initializes and returns a new Parser @@ -166,6 +168,8 @@ func (p *parser) Parse(options ParseOptions) (*element.DataSet, error) { func (p *parser) ParseNext(options ParseOptions) *element.Element { tag := readTag(p.decoder) + log.Println("Len remaining", p.decoder.Len()) + log.Println("Reading Tag ", tag) if tag == dicomtag.PixelData && options.DropPixelData { return element.EndOfData } @@ -189,6 +193,7 @@ func (p *parser) ParseNext(options ParseOptions) *element.Element { vr, vl = readExplicit(p.decoder, tag) } var data []interface{} + log.Println("VR", vr, "VL", vl) elem := &element.Element{ Tag: tag, @@ -264,7 +269,15 @@ func (p *parser) ParseNext(options ParseOptions) *element.Element { return nil // TODO(suyash) investigate error handling in this library } - image, _, err := readNativeFrames(p.decoder, p.parsedElements, p.frameChannel) + datasetToUse := p.parsedElements + + if p.currentSequenceDataset != nil { + datasetToUse = p.currentSequenceDataset + log.Println("Using item dataset") + log.Println(datasetToUse) + } + + image, _, err := readNativeFrames(p.decoder, datasetToUse, p.frameChannel) if err != nil { p.decoder.SetError(err) @@ -278,6 +291,10 @@ func (p *parser) ParseNext(options ParseOptions) *element.Element { // Note: when reading subitems inside sequence or item, we ignore // DropPixelData and other shortcircuiting options. If we honored them, we'decoder // be unable to read the rest of the file. + + // TODO: refactor to avoid temporarily storing two copies + oldDataset := p.currentSequenceDataset + p.currentSequenceDataset = &element.DataSet{} if vl == element.VLUndefinedLength { // Format: // Sequence := ItemSet* SequenceDelimitationItem @@ -314,9 +331,12 @@ func (p *parser) ParseNext(options ParseOptions) *element.Element { break } data = append(data, item) + p.currentSequenceDataset.Elements = append(p.currentSequenceDataset.Elements, item) } p.decoder.PopLimit() } + // Restore oldDataset if any: + p.currentSequenceDataset = oldDataset } else if tag == dicomtag.Item { // Item (component of SQ) if vl == element.VLUndefinedLength { // Format: Item Any* ItemDelimitationItem @@ -330,6 +350,7 @@ func (p *parser) ParseNext(options ParseOptions) *element.Element { break } data = append(data, subelem) + p.currentSequenceDataset.Elements = append(p.currentSequenceDataset.Elements, subelem) } } else { // Sequence of arbitary elements, for the total of "vl" bytes. @@ -341,6 +362,7 @@ func (p *parser) ParseNext(options ParseOptions) *element.Element { break } data = append(data, subelem) + p.currentSequenceDataset.Elements = append(p.currentSequenceDataset.Elements, subelem) } p.decoder.PopLimit() } From 77289c6191a1ecb2ab400ac3a2499453f4df4f41 Mon Sep 17 00:00:00 2001 From: Suyash Kumar Date: Fri, 22 May 2020 13:43:57 -0700 Subject: [PATCH 2/3] Cleanup --- parse.go | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/parse.go b/parse.go index 3e0e576d..bbc72a7f 100755 --- a/parse.go +++ b/parse.go @@ -7,7 +7,6 @@ import ( "errors" "fmt" "io" - "log" "os" "strconv" "strings" @@ -163,13 +162,15 @@ func (p *parser) Parse(options ParseOptions) (*element.DataSet, error) { } } + if p.frameChannel != nil { + close(p.frameChannel) + } return p.parsedElements, p.decoder.Error() } func (p *parser) ParseNext(options ParseOptions) *element.Element { tag := readTag(p.decoder) - log.Println("Len remaining", p.decoder.Len()) - log.Println("Reading Tag ", tag) + if tag == dicomtag.PixelData && options.DropPixelData { return element.EndOfData } @@ -193,7 +194,6 @@ func (p *parser) ParseNext(options ParseOptions) *element.Element { vr, vl = readExplicit(p.decoder, tag) } var data []interface{} - log.Println("VR", vr, "VL", vl) elem := &element.Element{ Tag: tag, @@ -257,9 +257,7 @@ func (p *parser) ParseNext(options ParseOptions) *element.Element { p.frameChannel <- &f // write frame to channel } } - if p.frameChannel != nil { - close(p.frameChannel) - } + data = append(data, image) } else { // Assume we're reading NativeData data since we have a defined value length as per Part 5 Sec A.4 of DICOM spec. @@ -271,10 +269,8 @@ func (p *parser) ParseNext(options ParseOptions) *element.Element { datasetToUse := p.parsedElements - if p.currentSequenceDataset != nil { + if p.currentSequenceDataset != nil && len(p.currentSequenceDataset.Elements) > 0 { datasetToUse = p.currentSequenceDataset - log.Println("Using item dataset") - log.Println(datasetToUse) } image, _, err := readNativeFrames(p.decoder, datasetToUse, p.frameChannel) @@ -610,10 +606,6 @@ func readNativeFrames(d *dicomio.Decoder, parsedData *element.DataSet, frameChan } } - if frameChan != nil { - close(frameChan) // close frameChan if it exists - } - bytesRead = (bitsAllocated / 8) * samplesPerPixel * pixelsPerFrame * nFrames return &image, bytesRead, nil From 4d46e0dd6bf0c8a3887014a79f05334fd1ab6add Mon Sep 17 00:00:00 2001 From: Suyash Kumar Date: Sun, 7 Jun 2020 19:02:58 -0700 Subject: [PATCH 3/3] add comment --- parse.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/parse.go b/parse.go index bbc72a7f..9aaeb443 100755 --- a/parse.go +++ b/parse.go @@ -32,11 +32,13 @@ type Parser interface { // parser implements Parser type parser struct { - decoder *dicomio.Decoder - parsedElements *element.DataSet - op ParseOptions - frameChannel chan *frame.Frame - file *os.File // may be populated if coming from file + decoder *dicomio.Decoder + parsedElements *element.DataSet + op ParseOptions + frameChannel chan *frame.Frame + file *os.File // may be populated if this parser is coming from a file + // currentSequenceDataset is populated with Elements read so far in a SQ DICOM sequence (or is nil if not currently + // reading a sequence). currentSequenceDataset *element.DataSet }