Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support parsing NativePixelData when it appears multiple times in a DICOM #79

Merged
merged 3 commits into from
Jun 8, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 25 additions & 9 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ type parser struct {
parsedElements *element.DataSet
op ParseOptions
frameChannel chan *frame.Frame
file *os.File // may be populated if coming from file
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
}

// NewParser initializes and returns a new Parser
Expand Down Expand Up @@ -161,11 +164,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)

if tag == dicomtag.PixelData && options.DropPixelData {
return element.EndOfData
}
Expand Down Expand Up @@ -252,9 +259,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.
Expand All @@ -264,7 +269,13 @@ 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 && len(p.currentSequenceDataset.Elements) > 0 {
datasetToUse = p.currentSequenceDataset
}

image, _, err := readNativeFrames(p.decoder, datasetToUse, p.frameChannel)

if err != nil {
p.decoder.SetError(err)
Expand All @@ -278,6 +289,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
Expand Down Expand Up @@ -314,9 +329,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
Expand All @@ -330,6 +348,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.
Expand All @@ -341,6 +360,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()
}
Expand Down Expand Up @@ -588,10 +608,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
Expand Down