Documentation ¶
Overview ¶
Package dicom provides a set of tools to read, write, and generally work with DICOM (http://dicom.nema.org/) medical image files in Go.
dicom.Parse and dicom.Write provide the core functionality to read and write DICOM Datasets. This package provides Go data structures that represent DICOM concepts (for example, dicom.Dataset and dicom.Element). These structures will pretty-print by default and are JSON serializable out of the box.
This package provides some advanced functionality as well, including: streaming image frames to an output channel, reading elements one-by-one (like an iterator pattern), flat iteration over nested elements in a Dataset, and more.
General usage is simple. Check out the package examples below and some function specific examples.
It may also be helpful to take a look at the example cmd/dicomutil program, which is a CLI built around this library to save out image frames from DICOMs and print out metadata to STDOUT.
Example (GetImageFrames) ¶
package main import ( "fmt" "image/jpeg" "os" "github.com/ginuerzh/dicom" "github.com/ginuerzh/dicom/pkg/tag" ) func main() { dataset, _ := dicom.ParseFile("testfiles/1.dcm", nil) pixelDataElement, _ := dataset.FindElementByTag(tag.PixelData) pixelDataInfo := dicom.MustGetPixelDataInfo(pixelDataElement.Value) for i, fr := range pixelDataInfo.Frames { img, _ := fr.GetImage() // The Go image.Image for this frame f, _ := os.Create(fmt.Sprintf("image_%d.jpg", i)) _ = jpeg.Encode(f, img, &jpeg.Options{Quality: 100}) _ = f.Close() } }
Output:
Example (ReadFile) ¶
package main import ( "encoding/json" "fmt" "github.com/ginuerzh/dicom" ) func main() { // See also: dicom.Parse, which uses a more generic io.Reader API. dataset, _ := dicom.ParseFile("testfiles/1.dcm", nil) // Dataset will nicely print the DICOM dataset data out of the box. fmt.Println(dataset) // Dataset is also JSON serializable out of the box. j, _ := json.Marshal(dataset) fmt.Println(j) }
Output:
Example (StreamingFrames) ¶
package main import ( "fmt" "github.com/ginuerzh/dicom" "github.com/ginuerzh/dicom/pkg/frame" ) func main() { frameChan := make(chan *frame.Frame) // Go routine to handle streaming frames as they are parsed. This may be // useful when parsing a large DICOM with many frames from a network source, // where image frames can start to be processed before the entire DICOM // is parsed (or even read from storage). go func() { for fr := range frameChan { fmt.Println(fr) } }() dataset, _ := dicom.ParseFile("testfiles/1.dcm", frameChan) fmt.Println(dataset) // The full dataset }
Output:
Index ¶
- Variables
- func MustGetBytes(v Value) []byte
- func MustGetFloats(v Value) []float64
- func MustGetInts(v Value) []int64
- func MustGetStrings(v Value) []string
- func MustGetUInts(v Value) []uint64
- func Write(out io.Writer, ds Dataset, opts ...WriteOption) error
- type Dataset
- type Element
- type Parser
- type PixelDataInfo
- type SequenceItemValue
- type Value
- type ValueType
- type WriteOption
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrorMagicWord indicates that the magic word was not found in the correct // location in the DICOM. ErrorMagicWord = errors.New("error, DICM magic word not found in correct location") // ErrorMetaElementGroupLength indicates that the MetaElementGroupLength // was not found where expected in the metadata. ErrorMetaElementGroupLength = errors.New("MetaElementGroupLength tag not found where expected") // ErrorEndOfDICOM indicates to the callers of Parser.Next() that the DICOM // has been fully parsed. Users using one of the other Parse APIs should not // need to use this. ErrorEndOfDICOM = errors.New("this indicates to the caller of Next() that the DICOM has been fully parsed") )
var ( // ErrorOWRequiresEvenVL indicates that an element with VR=OW had a not even // value length which is not allowed. ErrorOWRequiresEvenVL = errors.New("vr of OW requires even value length") // ErrorUnsupportedVR indicates that this VR is not supported. ErrorUnsupportedVR = errors.New("unsupported VR") )
var ( // ErrorUnimplemented is for not yet finished things. ErrorUnimplemented = errors.New("this functionality is not yet implemented") // ErrorMismatchValueTypeAndVR is for when there's a discrepency betweeen the ValueType and what the VR specifies. ErrorMismatchValueTypeAndVR = errors.New("ValueType does not match the VR required") // ErrorUnexpectedValueType indicates an unexpected value type was seen. ErrorUnexpectedValueType = errors.New("Unexpected ValueType") // ErrorUnsupportedBitsPerSample indicates that the BitsPerSample in this // Dataset is not supported when unpacking native PixelData. ErrorUnsupportedBitsPerSample = errors.New("unsupported BitsPerSample value") )
var ErrorElementNotFound = errors.New("element not found")
ErrorElementNotFound indicates that the requested element was not found in the Dataset.
var ErrorUnexpectedDataType = errors.New("the type of the data was unexpected or not allowed")
ErrorUnexpectedDataType indicates that an unexpected (not allowed) data type was sent to NewValue.
Functions ¶
func MustGetBytes ¶ added in v1.0.0
MustGetBytes attempts to get a Bytes value out of the provided Value, and will panic if it is unable to do so.
func MustGetFloats ¶ added in v1.0.0
MustGetFloats attempts to get a Floats value out of the provided Value, and will panic if it is unable to do so.
func MustGetInts ¶ added in v1.0.0
MustGetInts attempts to get an Ints value out of the provided value, and will panic if it is unable to do so.
func MustGetStrings ¶ added in v1.0.0
MustGetStrings attempts to get a Strings value out of the provided Value, and will panic if it is unable to do so.
func MustGetUInts ¶ added in v1.0.0
MustGetUInts attempts to get an UInts value out of the provided value, and will panic if it is unable to do so.
Types ¶
type Dataset ¶ added in v1.0.0
Dataset represents a DICOM dataset, see http://dicom.nema.org/medical/dicom/current/output/html/part05.html#chapter_7.
This Dataset representation is JSON serializable out of the box (implements json.Marshaler) and will also pretty print as a string nicely (see String example). This Dataset includes several helper methods to find Elements within this dataset or iterate over every Element within this Dataset (including Elements nested within Sequences).
func Parse ¶ added in v1.0.0
Parse parses the entire DICOM at the input io.Reader into a Dataset of DICOM Elements. Use this if you are looking to parse the DICOM all at once, instead of element-by-element.
func ParseFile ¶ added in v1.0.0
ParseFile parses the entire DICOM at the given filepath. See dicom.Parse as well for a more generic io.Reader based API.
func (*Dataset) FindElementByTag ¶ added in v1.0.0
FindElementByTag searches through the dataset and returns a pointer to the matching element. It DOES NOT search within Sequences as well.
func (*Dataset) FindElementByTagNested ¶ added in v1.0.0
FindElementByTagNested searches through the dataset and returns a pointer to the matching element. This call searches through a flat representation of the dataset, including within sequences.
func (*Dataset) FlatIterator ¶ added in v1.0.0
FlatIterator returns a channel upon which every element in this Dataset will be sent, including elements nested inside sequences. Note that the sequence element itself is sent on the channel in addition to the child elements in the sequence. TODO(suyashkumar): decide if the sequence element itself should be sent or not
Example ¶
nestedData := [][]*Element{ { { Tag: tag.ComponentName, ValueRepresentation: tag.VRString, Value: &stringsValue{ value: []string{"Bob"}, }, }, }, } data := Dataset{ Elements: []*Element{ { Tag: tag.Rows, ValueRepresentation: tag.VRInt32List, Value: &intsValue{ value: []int64{100}, }, }, { Tag: tag.Columns, ValueRepresentation: tag.VRInt32List, Value: &intsValue{ value: []int64{200}, }, }, makeSequenceElement(tag.AddOtherSequence, nestedData), }, } for elem := range data.FlatIterator() { fmt.Println(elem.Tag) } // Note the output below includes all three leaf elements __as well as__ the sequence element's tag
Output: (0028,0010) (0028,0011) (0010,0010) (0046,0102)
func (*Dataset) String ¶ added in v1.0.0
String returns a printable representation of this dataset as a string, including printing out elements nested inside sequence elements.
Example ¶
d := Dataset{ Elements: []*Element{ { Tag: tag.Rows, ValueRepresentation: tag.VRInt32List, RawValueRepresentation: "UL", Value: &intsValue{ value: []int64{100}, }, }, { Tag: tag.Columns, ValueRepresentation: tag.VRInt32List, RawValueRepresentation: "UL", Value: &intsValue{ value: []int64{200}, }, }, }, } fmt.Println(d.String())
Output: [ Tag: (0028,0010) Tag Name: Rows VR: VRInt32List VR Raw: UL VL: 0 Value: &{[100]} ] [ Tag: (0028,0011) Tag Name: Columns VR: VRInt32List VR Raw: UL VL: 0 Value: &{[200]} ]
type Element ¶
type Element struct { Tag tag.Tag `json:"tag"` ValueRepresentation tag.VRKind `json:"VR"` RawValueRepresentation string `json:"rawVR"` ValueLength uint32 `json:"valueLength"` Value Value `json:"value"` }
Element represents a standard DICOM data element (see the DICOM standard: http://dicom.nema.org/medical/dicom/current/output/html/part05.html#sect_7.1 ). This Element can be serialized to JSON out of the box and pretty printed as a string via the String() method.
func NewElement ¶
NewElement creates a new DICOM Element with the supplied tag and with a value built from the provided data. The data can be one of the types that is acceptable to NewValue.
type Parser ¶
type Parser struct {
// contains filtered or unexported fields
}
Parser is a struct that allows a user to parse Elements from a DICOM element-by-element using Next(), which may be useful for some streaming processing applications. If you instead just want to parse the whole input DICOM at once, just use the dicom.Parse(...) method.
func NewParser ¶
NewParser returns a new Parser that points to the provided io.Reader, with bytesToRead bytes left to read. NewParser will read the DICOM header and metadata as part of initialization.
frameChannel is an optional channel (can be nil) upon which DICOM image frames will be sent as they are parsed (if provided).
func (*Parser) GetMetadata ¶ added in v1.0.0
GetMetadata returns just the set of metadata elements that have been parsed so far.
type PixelDataInfo ¶
type PixelDataInfo struct { Frames []frame.Frame IsEncapsulated bool `json:"isEncapsulated"` Offsets []uint32 }
PixelDataInfo is a representation of DICOM PixelData.
func MustGetPixelDataInfo ¶ added in v1.0.0
func MustGetPixelDataInfo(v Value) PixelDataInfo
MustGetPixelDataInfo attempts to get a PixelDataInfo value out of the provided Value, and will panic if it is unable to do so.
type SequenceItemValue ¶ added in v1.0.0
type SequenceItemValue struct {
// contains filtered or unexported fields
}
SequenceItemValue is a Value that represents a single Sequence Item. Learn more about Sequences at http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.5.html.
func (*SequenceItemValue) GetValue ¶ added in v1.0.0
func (s *SequenceItemValue) GetValue() interface{}
func (*SequenceItemValue) MarshalJSON ¶ added in v1.0.0
func (s *SequenceItemValue) MarshalJSON() ([]byte, error)
func (*SequenceItemValue) String ¶ added in v1.0.0
func (s *SequenceItemValue) String() string
func (*SequenceItemValue) ValueType ¶ added in v1.0.0
func (s *SequenceItemValue) ValueType() ValueType
type Value ¶ added in v1.0.0
type Value interface { // ValueType returns the underlying ValueType of this Value. This can be used to unpack the underlying data in this // Value. ValueType() ValueType // GetValue returns the underlying value that this Value holds. What type is returned here can be determined exactly // from the ValueType() of this Value (see the ValueType godoc). GetValue() interface{} // TODO: rename to Get to read cleaner String() string MarshalJSON() ([]byte, error) // contains filtered or unexported methods }
Value represents a DICOM value. The underlying data that a Value stores can be determined by inspecting its ValueType. DICOM values typically can be one of many types (ints, strings, bytes, sequences of other elements, etc), so this Value interface attempts to represent this as canoically as possible in Golang (since generics do not exist yet).
Value is JSON serializable out of the box (implements json.Marshaler).
If necessary, a Value's data can be efficiently unpacked by inspecting its underlying ValueType and either using a Golang type assertion or using the helper functions provided (like MustGetStrings). Because for each ValueType there is exactly one underlying Golang type, this should be safe, efficient, and straightforward.
switch(myvalue.ValueType()) { case dicom.Strings: // We know the underlying Golang type is []string fmt.Println(dicom.MustGetStrings(myvalue)[0]) // or s := myvalue.GetValue().([]string) break; case dicom.Bytes: // ... }
Unpacking the data like above is only necessary if something specific needs to be done with the underlying data. See the Element and Dataset examples as well to see how to work with this kind of data, and common patterns for doing so.
func NewValue ¶ added in v1.0.0
NewValue creates a new DICOM value for the supplied data. Likely most useful if creating an Element in testing or write scenarios.
Data must be one of the following types, otherwise and error will be returned (ErrorUnexpectedDataType).
Acceptable types: int, []int64, uint, []uint64, string, []string, []byte, []float64, PixelDataInfo, [][]*Element (represents a sequence, which contains several items which each contain several elements).
type ValueType ¶ added in v1.0.0
type ValueType int
ValueType is a type that represents the type of a Value. It is an enumerated set, and the set of values can be found below.
const ( // Strings represents an underlying value of []string Strings ValueType = iota // Bytes represents an underlying value of []byte Bytes // Ints represents an underlying value of []int64 Ints // UInts represents an underlying value of []uint64 UInts // PixelData represents an underlying value of PixelDataInfo PixelData // SequenceItem represents an underlying value of []*Element SequenceItem // Sequences represents an underlying value of []SequenceItem Sequences // Floats represents an underlying value of []float64 Floats )
Possible ValueTypes that represent the different value types for information parsed into DICOM element values. Each ValueType corresponds to exactly one underlying Golang type.
type WriteOption ¶ added in v1.0.0
type WriteOption func(*writeOptSet)
WriteOption represents an option that can be passed to WriteDataset. Later options will override previous options if applicable.
func DefaultMissingTransferSyntax ¶ added in v1.0.0
func DefaultMissingTransferSyntax() WriteOption
DefaultMissingTransferSyntax returns a WriteOption indicating that a missing transferSyntax should not raise an error, and instead the default LittleEndian Implicit transfer syntax should be used and written out as a Metadata element in the Dataset.
func SkipVRVerification ¶ added in v1.0.0
func SkipVRVerification() WriteOption
SkipVRVerification returns a WriteOption that skips VR verification.
func SkipValueTypeVerification ¶ added in v1.0.0
func SkipValueTypeVerification() WriteOption
SkipValueTypeVerification returns WriteOption function that skips checking ValueType for concurrency with VR and casting
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
cmd
|
|
dicomutil
Really basic sanity check program
|
Really basic sanity check program |
mocks
|
|
pkg/dicomio
Package mock_dicomio is a generated GoMock package.
|
Package mock_dicomio is a generated GoMock package. |
pkg
|
|
tag
Package dicomtag enumerates element tags defined in the DICOM standard.
|
Package dicomtag enumerates element tags defined in the DICOM standard. |