From 8f1f1517075e03fc3a3ec2463016177dad551ae8 Mon Sep 17 00:00:00 2001 From: Suyash Kumar Date: Sat, 26 Aug 2023 19:41:35 -0400 Subject: [PATCH] Add Dataset & Element equality methods, greatly speeding up tests that rely on dataset comparisons. (#280) This change introduces well-defined equality methods for Dataset, Element, and some other data structures. This greatly speeds up tests that rely on checking equality of datasets (that previously needed reflection). For example, it reduces the total test suite from 1m24s to 10s on GitHub actions (mostly due to one test). These methods may also be of use to library users. However, this does mean that if new fields are added to any of these structs it is important for the Equals method to be updated as well. For now this will be enforced during code review (helped by the fact most of these structs should not fail often), but we should investigate lint rules or some auto-generated reflection based tests that can help catch when this doesn't happen (see #281). This change also makes a change to rely on pointers for []*frame.Frame in the PixelDataInfo. --- cmd/dicomutil/main.go | 2 +- dataset.go | 14 ++ element.go | 186 +++++++++++++++++++++---- element_test.go | 280 ++++++++++++++++++++++++++++++++++++++ parse_internal_test.go | 7 +- pkg/frame/encapsulated.go | 9 ++ pkg/frame/frame.go | 18 +++ pkg/frame/native.go | 21 +++ read.go | 8 +- read_test.go | 18 +-- write_test.go | 12 +- 11 files changed, 524 insertions(+), 51 deletions(-) diff --git a/cmd/dicomutil/main.go b/cmd/dicomutil/main.go index 33aaeac3..5c037dc4 100644 --- a/cmd/dicomutil/main.go +++ b/cmd/dicomutil/main.go @@ -186,6 +186,6 @@ func generateImage(fr *frame.Frame, frameIndex int, frameSuffix string, wg *sync func writePixelDataElement(e *dicom.Element, suffix string) { imageInfo := e.Value.GetValue().(dicom.PixelDataInfo) for idx, f := range imageInfo.Frames { - generateImage(&f, idx, suffix, nil) + generateImage(f, idx, suffix, nil) } } diff --git a/dataset.go b/dataset.go index e5653157..4d8a5cb7 100644 --- a/dataset.go +++ b/dataset.go @@ -190,6 +190,20 @@ func (d *Dataset) String() string { return b.String() } +// Equals returns true if this Dataset equals the provided target Dataset, +// otherwise false. +func (d *Dataset) Equals(target *Dataset) bool { + if target == nil || d == nil { + return d == target + } + for idx, e := range d.Elements { + if !e.Equals(target.Elements[idx]) { + return false + } + } + return true +} + type elementWithLevel struct { e *Element // l represents the nesting level of the Element diff --git a/element.go b/element.go index 3c16be17..2682a311 100644 --- a/element.go +++ b/element.go @@ -1,6 +1,7 @@ package dicom import ( + "bytes" "encoding/json" "errors" "fmt" @@ -24,6 +25,24 @@ type Element struct { Value Value `json:"value"` } +// Equals returns true if this Element equals the provided target Element, +// otherwise false. +func (e *Element) Equals(target *Element) bool { + if target == nil || e == nil { + return e == target + } + if !e.Tag.Equals(target.Tag) || + e.RawValueRepresentation != target.RawValueRepresentation || + e.ValueLength != target.ValueLength || + e.ValueRepresentation != target.ValueRepresentation { + return false + } + if !e.Value.Equals(target.Value) { + return false + } + return true +} + func (e *Element) String() string { var tagName string if tagInfo, err := tag.Find(e.Tag); err == nil { @@ -75,6 +94,8 @@ type Value interface { GetValue() interface{} // TODO: rename to Get to read cleaner String() string MarshalJSON() ([]byte, error) + // Equals returns true if this value equals the input Value. + Equals(Value) bool } // NewValue creates a new DICOM value for the supplied data. Likely most useful @@ -204,6 +225,16 @@ func (b *bytesValue) MarshalJSON() ([]byte, error) { return json.Marshal(b.value) } +func (b *bytesValue) Equals(target Value) bool { + if target.ValueType() != Bytes { + return false + } + if !bytes.Equal(b.value, target.GetValue().([]byte)) { + return false + } + return true +} + // stringsValue represents a value of []string. type stringsValue struct { value []string @@ -219,19 +250,51 @@ func (s *stringsValue) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } +func (s *stringsValue) Equals(target Value) bool { + if target.ValueType() != Strings { + return false + } + targetVal := target.GetValue().([]string) + if len(s.value) != len(targetVal) { + return false + } + for idx, val := range s.value { + if val != targetVal[idx] { + return false + } + } + return true +} + // intsValue represents a value of []int. type intsValue struct { value []int } -func (s *intsValue) isElementValue() {} -func (s *intsValue) ValueType() ValueType { return Ints } -func (s *intsValue) GetValue() interface{} { return s.value } -func (s *intsValue) String() string { - return fmt.Sprintf("%v", s.value) +func (i *intsValue) isElementValue() {} +func (i *intsValue) ValueType() ValueType { return Ints } +func (i *intsValue) GetValue() interface{} { return i.value } +func (i *intsValue) String() string { + return fmt.Sprintf("%v", i.value) } -func (s *intsValue) MarshalJSON() ([]byte, error) { - return json.Marshal(s.value) +func (i *intsValue) MarshalJSON() ([]byte, error) { + return json.Marshal(i.value) +} + +func (i *intsValue) Equals(target Value) bool { + if target.ValueType() != Ints { + return false + } + targetVal := target.GetValue().([]int) + if len(i.value) != len(targetVal) { + return false + } + for idx, val := range i.value { + if val != targetVal[idx] { + return false + } + } + return true } // floatsValue represents a value of []float64. @@ -239,14 +302,29 @@ type floatsValue struct { value []float64 } -func (s *floatsValue) isElementValue() {} -func (s *floatsValue) ValueType() ValueType { return Floats } -func (s *floatsValue) GetValue() interface{} { return s.value } -func (s *floatsValue) String() string { - return fmt.Sprintf("%v", s.value) +func (f *floatsValue) isElementValue() {} +func (f *floatsValue) ValueType() ValueType { return Floats } +func (f *floatsValue) GetValue() interface{} { return f.value } +func (f *floatsValue) String() string { + return fmt.Sprintf("%v", f.value) } -func (s *floatsValue) MarshalJSON() ([]byte, error) { - return json.Marshal(s.value) +func (f *floatsValue) MarshalJSON() ([]byte, error) { + return json.Marshal(f.value) +} +func (f *floatsValue) Equals(target Value) bool { + if target.ValueType() != Floats { + return false + } + targetVal := target.GetValue().([]float64) + if len(f.value) != len(targetVal) { + return false + } + for idx, val := range f.value { + if val != targetVal[idx] { + return false + } + } + return true } // SequenceItemValue is a Value that represents a single Sequence Item. Learn @@ -278,6 +356,22 @@ func (s *SequenceItemValue) MarshalJSON() ([]byte, error) { return json.Marshal(s.elements) } +func (s *SequenceItemValue) Equals(target Value) bool { + if target.ValueType() != SequenceItem { + return false + } + targetVal := target.GetValue().([]*Element) + if len(s.elements) != len(targetVal) { + return false + } + for idx, val := range s.elements { + if !val.Equals(targetVal[idx]) { + return false + } + } + return true +} + // sequencesValue represents a set of items in a DICOM sequence. type sequencesValue struct { value []*SequenceItemValue @@ -293,6 +387,21 @@ func (s *sequencesValue) String() string { func (s *sequencesValue) MarshalJSON() ([]byte, error) { return json.Marshal(s.value) } +func (s *sequencesValue) Equals(target Value) bool { + if target.ValueType() != Sequences { + return false + } + targetVal := target.GetValue().([]*SequenceItemValue) + if len(s.value) != len(targetVal) { + return false + } + for idx, val := range s.value { + if !val.Equals(targetVal[idx]) { + return false + } + } + return true +} // PixelDataInfo is a representation of DICOM PixelData. type PixelDataInfo struct { @@ -304,7 +413,7 @@ type PixelDataInfo struct { // Frames hold the processed PixelData frames (either Native or Encapsulated // PixelData). - Frames []frame.Frame + Frames []*frame.Frame // ParseErr indicates if there was an error when reading this Frame from the DICOM. // If this is set, this means fallback behavior was triggered to blindly write the PixelData bytes to an encapsulated frame. @@ -329,24 +438,47 @@ type pixelDataValue struct { PixelDataInfo } -func (e *pixelDataValue) isElementValue() {} -func (e *pixelDataValue) ValueType() ValueType { return PixelData } -func (e *pixelDataValue) GetValue() interface{} { return e.PixelDataInfo } -func (e *pixelDataValue) String() string { - if len(e.Frames) == 0 { +func (p *pixelDataValue) isElementValue() {} +func (p *pixelDataValue) ValueType() ValueType { return PixelData } +func (p *pixelDataValue) GetValue() interface{} { return p.PixelDataInfo } +func (p *pixelDataValue) String() string { + if len(p.Frames) == 0 { return "empty pixel data" } - if e.IsEncapsulated { - return fmt.Sprintf("encapsulated FramesLength=%d Frame[0] size=%d", len(e.Frames), len(e.Frames[0].EncapsulatedData.Data)) + if p.IsEncapsulated { + return fmt.Sprintf("encapsulated FramesLength=%d Frame[0] size=%d", len(p.Frames), len(p.Frames[0].EncapsulatedData.Data)) } - if e.ParseErr != nil { - return fmt.Sprintf("parseErr err=%s FramesLength=%d Frame[0] size=%d", e.ParseErr.Error(), len(e.Frames), len(e.Frames[0].EncapsulatedData.Data)) + if p.ParseErr != nil { + return fmt.Sprintf("parseErr err=%s FramesLength=%d Frame[0] size=%d", p.ParseErr.Error(), len(p.Frames), len(p.Frames[0].EncapsulatedData.Data)) } - return fmt.Sprintf("FramesLength=%d FrameSize rows=%d cols=%d", len(e.Frames), e.Frames[0].NativeData.Rows, e.Frames[0].NativeData.Cols) + return fmt.Sprintf("FramesLength=%d FrameSize rows=%d cols=%d", len(p.Frames), p.Frames[0].NativeData.Rows, p.Frames[0].NativeData.Cols) } -func (e *pixelDataValue) MarshalJSON() ([]byte, error) { - return json.Marshal(e.PixelDataInfo) +func (p *pixelDataValue) MarshalJSON() ([]byte, error) { + return json.Marshal(p.PixelDataInfo) +} +func (p *pixelDataValue) Equals(target Value) bool { + if target.ValueType() != PixelData { + return false + } + targetVal := target.GetValue().(PixelDataInfo) + if p.IntentionallySkipped != targetVal.IntentionallySkipped || + p.IntentionallyUnprocessed != targetVal.IntentionallyUnprocessed || + p.ParseErr != targetVal.ParseErr || + p.IsEncapsulated != targetVal.IsEncapsulated || + !bytes.Equal(p.UnprocessedValueData, targetVal.UnprocessedValueData) { + return false + } + targetFrameVal := target.GetValue().(PixelDataInfo).Frames + if len(p.Frames) != len(targetFrameVal) { + return false + } + for idx, val := range p.Frames { + if !val.Equals(targetFrameVal[idx]) { + return false + } + } + return true } // MustGetInts attempts to get an Ints value out of the provided value, and will diff --git a/element_test.go b/element_test.go index a5d88a41..3d825a8c 100644 --- a/element_test.go +++ b/element_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/suyashkumar/dicom/pkg/frame" "github.com/suyashkumar/dicom/pkg/tag" ) @@ -144,3 +145,282 @@ func TestNewValue_UnexpectedType(t *testing.T) { t.Errorf("NewValue(%v) expected an error. got: %v, want: %v", data, err, ErrorUnexpectedDataType) } } + +func TestElement_Equals(t *testing.T) { + // Some general sanity checks below, not every possible case is included. + cases := []struct { + name string + a *Element + b *Element + wantEqual bool + }{ + { + name: "EqualNilElements", + a: nil, + b: nil, + wantEqual: true, + }, + { + name: "UnequalNilElement", + a: nil, + b: mustNewElement(tag.FloatingPointValue, []float64{1.23}), + wantEqual: false, + }, + { + name: "EqualFloats", + a: mustNewElement(tag.FloatingPointValue, []float64{1.23, 4.40, 5.50}), + b: mustNewElement(tag.FloatingPointValue, []float64{1.23, 4.40, 5.50}), + wantEqual: true, + }, + { + name: "UnequalLenFloats", + a: mustNewElement(tag.FloatingPointValue, []float64{1.23, 4.40}), + b: mustNewElement(tag.FloatingPointValue, []float64{1.23, 4.40, 5.50}), + wantEqual: false, + }, + { + name: "UnequalFloats", + a: mustNewElement(tag.FloatingPointValue, []float64{1.23, 4.40, 10.1}), + b: mustNewElement(tag.FloatingPointValue, []float64{1.23, 4.40, 5.50}), + wantEqual: false, + }, + { + name: "EqualInts", + a: mustNewElement(tag.Rows, []int{1, 2, 3}), + b: mustNewElement(tag.Rows, []int{1, 2, 3}), + wantEqual: true, + }, + { + name: "UnequalInts", + a: mustNewElement(tag.Rows, []int{1, 2, 6}), + b: mustNewElement(tag.Rows, []int{1, 2, 3}), + wantEqual: false, + }, + { + name: "UnequalLenInts", + a: mustNewElement(tag.Rows, []int{1, 6}), + b: mustNewElement(tag.Rows, []int{1, 2, 3}), + wantEqual: false, + }, + { + name: "EqualBytes", + a: mustNewElement(tag.AirCounts, []byte{1, 2, 3}), + b: mustNewElement(tag.AirCounts, []byte{1, 2, 3}), + wantEqual: true, + }, + { + name: "UnequalBytes", + a: mustNewElement(tag.AirCounts, []byte{1, 2, 4}), + b: mustNewElement(tag.AirCounts, []byte{1, 2, 3}), + wantEqual: false, + }, + { + name: "UnequalLenBytes", + a: mustNewElement(tag.AirCounts, []byte{1, 2, 3}), + b: mustNewElement(tag.AirCounts, []byte{1, 2}), + wantEqual: false, + }, + { + name: "EqualStrings", + a: mustNewElement(tag.PatientName, []string{"John", "Smith"}), + b: mustNewElement(tag.PatientName, []string{"John", "Smith"}), + wantEqual: true, + }, + { + name: "UnequalStrings", + a: mustNewElement(tag.PatientName, []string{"John", "Doe"}), + b: mustNewElement(tag.PatientName, []string{"John", "Smith"}), + wantEqual: false, + }, + { + name: "UnequalLenStrings", + a: mustNewElement(tag.PatientName, []string{"John"}), + b: mustNewElement(tag.PatientName, []string{"John", "Smith"}), + wantEqual: false, + }, + { + name: "EqualNativePixelData", + a: mustNewElement(tag.PixelData, PixelDataInfo{ + IsEncapsulated: false, + Frames: []*frame.Frame{ + { + Encapsulated: false, + NativeData: frame.NativeFrame{ + BitsPerSample: 8, + Rows: 2, + Cols: 2, + Data: [][]int{{1}, {2}, {3}, {4}}, + }, + }, + }, + }), + b: mustNewElement(tag.PixelData, PixelDataInfo{ + IsEncapsulated: false, + Frames: []*frame.Frame{ + { + Encapsulated: false, + NativeData: frame.NativeFrame{ + BitsPerSample: 8, + Rows: 2, + Cols: 2, + Data: [][]int{{1}, {2}, {3}, {4}}, + }, + }, + }, + }), + wantEqual: true, + }, + { + name: "UnequalNativePixelData", + a: mustNewElement(tag.PixelData, PixelDataInfo{ + IsEncapsulated: false, + Frames: []*frame.Frame{ + { + Encapsulated: false, + NativeData: frame.NativeFrame{ + BitsPerSample: 8, + Rows: 2, + Cols: 2, + Data: [][]int{{1}, {2}, {3}, {6}}, + }, + }, + }, + }), + b: mustNewElement(tag.PixelData, PixelDataInfo{ + IsEncapsulated: false, + Frames: []*frame.Frame{ + { + Encapsulated: false, + NativeData: frame.NativeFrame{ + BitsPerSample: 8, + Rows: 2, + Cols: 2, + Data: [][]int{{1}, {2}, {3}, {4}}, + }, + }, + }, + }), + wantEqual: false, + }, + { + name: "EqualSequences", + a: makeSequenceElement(tag.AddOtherSequence, [][]*Element{ + // Item 1. + { + { + Tag: tag.PatientName, + ValueRepresentation: tag.VRStringList, + RawValueRepresentation: "PN", + Value: &stringsValue{value: []string{"Bob", "Jones"}}, + }, + }, + // Item 2. + { + { + Tag: tag.PatientName, + ValueRepresentation: tag.VRStringList, + RawValueRepresentation: "PN", + Value: &stringsValue{value: []string{"Bob", "Jones"}}, + }, + { + Tag: tag.Rows, + ValueRepresentation: tag.VRUInt16List, + RawValueRepresentation: "US", + Value: &intsValue{value: []int{100}}, + }, + }, + }), + b: makeSequenceElement(tag.AddOtherSequence, [][]*Element{ + // Item 1. + { + { + Tag: tag.PatientName, + ValueRepresentation: tag.VRStringList, + RawValueRepresentation: "PN", + Value: &stringsValue{value: []string{"Bob", "Jones"}}, + }, + }, + // Item 2. + { + { + Tag: tag.PatientName, + ValueRepresentation: tag.VRStringList, + RawValueRepresentation: "PN", + Value: &stringsValue{value: []string{"Bob", "Jones"}}, + }, + { + Tag: tag.Rows, + ValueRepresentation: tag.VRUInt16List, + RawValueRepresentation: "US", + Value: &intsValue{value: []int{100}}, + }, + }, + }), + wantEqual: true, + }, + { + name: "UnequalSequences", + a: makeSequenceElement(tag.AddOtherSequence, [][]*Element{ + // Item 1. + { + { + Tag: tag.PatientName, + ValueRepresentation: tag.VRStringList, + RawValueRepresentation: "PN", + // Smith instead of Jones below causes inequality. + Value: &stringsValue{value: []string{"Bob", "Smith"}}, + }, + }, + // Item 2. + { + { + Tag: tag.PatientName, + ValueRepresentation: tag.VRStringList, + RawValueRepresentation: "PN", + Value: &stringsValue{value: []string{"Bob", "Jones"}}, + }, + { + Tag: tag.Rows, + ValueRepresentation: tag.VRUInt16List, + RawValueRepresentation: "US", + Value: &intsValue{value: []int{100}}, + }, + }, + }), + b: makeSequenceElement(tag.AddOtherSequence, [][]*Element{ + // Item 1. + { + { + Tag: tag.PatientName, + ValueRepresentation: tag.VRStringList, + RawValueRepresentation: "PN", + Value: &stringsValue{value: []string{"Bob", "Jones"}}, + }, + }, + // Item 2. + { + { + Tag: tag.PatientName, + ValueRepresentation: tag.VRStringList, + RawValueRepresentation: "PN", + Value: &stringsValue{value: []string{"Bob", "Jones"}}, + }, + { + Tag: tag.Rows, + ValueRepresentation: tag.VRUInt16List, + RawValueRepresentation: "US", + Value: &intsValue{value: []int{100}}, + }, + }, + }), + wantEqual: false, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if tc.a.Equals(tc.b) != tc.wantEqual { + t.Errorf("Element.Equals(%v, %v) != %v", tc.a, tc.b, tc.wantEqual) + } + }) + } +} diff --git a/parse_internal_test.go b/parse_internal_test.go index 61e1101b..6655de9a 100644 --- a/parse_internal_test.go +++ b/parse_internal_test.go @@ -5,8 +5,6 @@ import ( "os" "strings" "testing" - - "github.com/google/go-cmp/cmp" ) // TestParseUntilEOFConformsToParse runs both the dicom.ParseUntilEOF and the dicom.Parse APIs against each @@ -42,9 +40,10 @@ func TestParseUntilEOFConformsToParse(t *testing.T) { } // Ensure dataset read from ParseUntilEOF and Parse are the same. - if diff := cmp.Diff(parse_dataset, parse_eof_dataset, cmp.AllowUnexported(allValues...)); diff != "" { - t.Errorf("dicom.Parse and dicom.ParseUntilEOF do not result in the same dataset. diff: %v", diff) + if !parse_dataset.Equals(&parse_eof_dataset) { + t.Errorf("dicom.Parse and dicom.ParseUntilEOF do not result in the same dataset.\nParse Dataset: %v\n\n\nParse EOF Dataset: %v", parse_dataset, parse_eof_dataset) } + }) } } diff --git a/pkg/frame/encapsulated.go b/pkg/frame/encapsulated.go index a7750e1d..32517740 100644 --- a/pkg/frame/encapsulated.go +++ b/pkg/frame/encapsulated.go @@ -34,3 +34,12 @@ func (e *EncapsulatedFrame) GetImage() (image.Image, error) { // there. return jpeg.Decode(bytes.NewReader(e.Data)) } + +// Equals returns true if this frame equals the provided target frame, otherwise +// false. +func (e *EncapsulatedFrame) Equals(target *EncapsulatedFrame) bool { + if !bytes.Equal(e.Data, target.Data) { + return false + } + return true +} diff --git a/pkg/frame/frame.go b/pkg/frame/frame.go index 8d6eadad..5532de1a 100644 --- a/pkg/frame/frame.go +++ b/pkg/frame/frame.go @@ -71,3 +71,21 @@ func (f *Frame) GetImage() (image.Image, error) { } return f.NativeData.GetImage() } + +// Equals returns true if this frame equals the provided target frame, otherwise +// false. +func (f *Frame) Equals(target *Frame) bool { + if target == nil || f == nil { + return f == target + } + if f.Encapsulated != target.Encapsulated { + return false + } + if f.Encapsulated && !f.EncapsulatedData.Equals(&target.EncapsulatedData) { + return false + } + if !f.Encapsulated && !f.NativeData.Equals(&target.NativeData) { + return false + } + return true +} diff --git a/pkg/frame/native.go b/pkg/frame/native.go index 9d00e459..0c43ada8 100644 --- a/pkg/frame/native.go +++ b/pkg/frame/native.go @@ -39,3 +39,24 @@ func (n *NativeFrame) GetImage() (image.Image, error) { } return i, nil } + +// Equals returns true if this frame equals the provided target frame, otherwise +// false. +func (n *NativeFrame) Equals(target *NativeFrame) bool { + if target == nil || n == nil { + return n == target + } + if n.Rows != target.Rows || + n.Cols != target.Cols || + n.BitsPerSample != n.BitsPerSample { + return false + } + for pixIdx, pix := range n.Data { + for valIdx, val := range pix { + if val != target.Data[pixIdx][valIdx] { + return false + } + } + } + return true +} diff --git a/read.go b/read.go index 3dbdd341..337735f9 100644 --- a/read.go +++ b/read.go @@ -258,7 +258,7 @@ func (r *reader) readPixelData(vl uint32, d *Dataset, fc chan<- *frame.Frame) (V fc <- &f } - image.Frames = append(image.Frames, f) + image.Frames = append(image.Frames, &f) } image.IntentionallySkipped = r.opts.skipPixelData return &pixelDataValue{PixelDataInfo: image}, nil @@ -358,7 +358,7 @@ func makeErrorPixelData(reader io.Reader, vl uint32, fc chan<- *frame.Frame, par } image := PixelDataInfo{ ParseErr: parseErr, - Frames: []frame.Frame{f}, + Frames: []*frame.Frame{&f}, } return &image, nil } @@ -437,7 +437,7 @@ func (r *reader) readNativeFrames(parsedData *Dataset, fc chan<- *frame.Frame, v image := PixelDataInfo{ IsEncapsulated: false, } - image.Frames = make([]frame.Frame, nFrames) + image.Frames = make([]*frame.Frame, nFrames) bo := r.rawReader.ByteOrder() pixelBuf := make([]byte, bytesAllocated) for frameIdx := 0; frameIdx < nFrames; frameIdx++ { @@ -482,7 +482,7 @@ func (r *reader) readNativeFrames(parsedData *Dataset, fc chan<- *frame.Frame, v currentFrame.NativeData.Data[pixel] = buf[pixel*samplesPerPixel : (pixel+1)*samplesPerPixel] } } - image.Frames[frameIdx] = currentFrame + image.Frames[frameIdx] = ¤tFrame if fc != nil { fc <- ¤tFrame // write the current frame to the frame channel } diff --git a/read_test.go b/read_test.go index 859abb86..b8fe8002 100644 --- a/read_test.go +++ b/read_test.go @@ -229,7 +229,7 @@ func TestReadNativeFrames(t *testing.T) { data: []uint16{1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, expectedPixelData: &PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -255,7 +255,7 @@ func TestReadNativeFrames(t *testing.T) { data: []uint16{1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 3, 0}, expectedPixelData: &PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -299,7 +299,7 @@ func TestReadNativeFrames(t *testing.T) { data: []uint16{1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 3, 5}, expectedPixelData: &PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -360,7 +360,7 @@ func TestReadNativeFrames(t *testing.T) { data: []uint16{1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 3, 2, 2}, expectedPixelData: &PixelDataInfo{ ParseErr: ErrorMismatchPixelDataLength, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { EncapsulatedData: frame.EncapsulatedFrame{ Data: []byte{1, 0, 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 3, 0, 2, 0, 1, 0, 2, 0, 3, 0, 2, 0, 2, 0}, @@ -408,7 +408,7 @@ func TestReadNativeFrames(t *testing.T) { dataBytes: []byte{11, 12, 13, 21, 22, 23, 31, 32, 33, 11, 12, 13, 21, 22, 23, 31, 32, 33, 11, 12, 13, 21, 22, 23, 31, 32, 33, 0}, // there is a 28th byte to make total value length even, as required by DICOM spec expectedPixelData: &PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -453,7 +453,7 @@ func TestReadNativeFrames(t *testing.T) { dataBytes: []byte{1, 2, 3, 1, 2, 3, 1, 2, 3, 0}, // 10th byte to make total value length even expectedPixelData: &PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -761,7 +761,7 @@ func makeEncapsulatedSequence(t *testing.T) []byte { buf := &bytes.Buffer{} w := dicomio.NewWriter(buf, binary.LittleEndian, true) - writePixelData(w, tag.PixelData, &pixelDataValue{PixelDataInfo{IsEncapsulated: true, Frames: []frame.Frame{ + writePixelData(w, tag.PixelData, &pixelDataValue{PixelDataInfo{IsEncapsulated: true, Frames: []*frame.Frame{ { Encapsulated: true, EncapsulatedData: frame.EncapsulatedFrame{ @@ -795,7 +795,7 @@ func TestReadNativeFrames_OneBitAllocated(t *testing.T) { data: []byte{0b00010111, 0b10010111}, expectedPixelData: &PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -822,7 +822,7 @@ func TestReadNativeFrames_OneBitAllocated(t *testing.T) { data: []byte{0b00010111, 0b10010111}, expectedPixelData: &PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ diff --git a/write_test.go b/write_test.go index 4e4a2546..5c67fd59 100644 --- a/write_test.go +++ b/write_test.go @@ -286,7 +286,7 @@ func TestWrite(t *testing.T) { mustNewElement(tag.SamplesPerPixel, []int{1}), mustNewElement(tag.PixelData, PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -316,7 +316,7 @@ func TestWrite(t *testing.T) { mustNewElement(tag.SamplesPerPixel, []int{1}), mustNewElement(tag.PixelData, PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -344,7 +344,7 @@ func TestWrite(t *testing.T) { mustNewElement(tag.SamplesPerPixel, []int{1}), mustNewElement(tag.PixelData, PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -372,7 +372,7 @@ func TestWrite(t *testing.T) { mustNewElement(tag.SamplesPerPixel, []int{2}), mustNewElement(tag.PixelData, PixelDataInfo{ IsEncapsulated: false, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: false, NativeData: frame.NativeFrame{ @@ -405,7 +405,7 @@ func TestWrite(t *testing.T) { mustNewElement(tag.BitsAllocated, []int{8}), setUndefinedLength(mustNewElement(tag.PixelData, PixelDataInfo{ IsEncapsulated: true, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: true, EncapsulatedData: frame.EncapsulatedFrame{Data: []byte{1, 2, 3, 4}}, @@ -426,7 +426,7 @@ func TestWrite(t *testing.T) { mustNewElement(tag.BitsAllocated, []int{8}), setUndefinedLength(mustNewElement(tag.PixelData, PixelDataInfo{ IsEncapsulated: true, - Frames: []frame.Frame{ + Frames: []*frame.Frame{ { Encapsulated: true, EncapsulatedData: frame.EncapsulatedFrame{Data: []byte{1, 2, 3, 4}},