11package dicom
22
33import (
4+ "bytes"
45 "encoding/json"
56 "errors"
67 "fmt"
@@ -24,6 +25,24 @@ type Element struct {
2425 Value Value `json:"value"`
2526}
2627
28+ // Equals returns true if this Element equals the provided target Element,
29+ // otherwise false.
30+ func (e * Element ) Equals (target * Element ) bool {
31+ if target == nil || e == nil {
32+ return e == target
33+ }
34+ if ! e .Tag .Equals (target .Tag ) ||
35+ e .RawValueRepresentation != target .RawValueRepresentation ||
36+ e .ValueLength != target .ValueLength ||
37+ e .ValueRepresentation != target .ValueRepresentation {
38+ return false
39+ }
40+ if ! e .Value .Equals (target .Value ) {
41+ return false
42+ }
43+ return true
44+ }
45+
2746func (e * Element ) String () string {
2847 var tagName string
2948 if tagInfo , err := tag .Find (e .Tag ); err == nil {
@@ -75,6 +94,8 @@ type Value interface {
7594 GetValue () interface {} // TODO: rename to Get to read cleaner
7695 String () string
7796 MarshalJSON () ([]byte , error )
97+ // Equals returns true if this value equals the input Value.
98+ Equals (Value ) bool
7899}
79100
80101// NewValue creates a new DICOM value for the supplied data. Likely most useful
@@ -204,6 +225,16 @@ func (b *bytesValue) MarshalJSON() ([]byte, error) {
204225 return json .Marshal (b .value )
205226}
206227
228+ func (b * bytesValue ) Equals (target Value ) bool {
229+ if target .ValueType () != Bytes {
230+ return false
231+ }
232+ if ! bytes .Equal (b .value , target .GetValue ().([]byte )) {
233+ return false
234+ }
235+ return true
236+ }
237+
207238// stringsValue represents a value of []string.
208239type stringsValue struct {
209240 value []string
@@ -219,34 +250,81 @@ func (s *stringsValue) MarshalJSON() ([]byte, error) {
219250 return json .Marshal (s .value )
220251}
221252
253+ func (s * stringsValue ) Equals (target Value ) bool {
254+ if target .ValueType () != Strings {
255+ return false
256+ }
257+ targetVal := target .GetValue ().([]string )
258+ if len (s .value ) != len (targetVal ) {
259+ return false
260+ }
261+ for idx , val := range s .value {
262+ if val != targetVal [idx ] {
263+ return false
264+ }
265+ }
266+ return true
267+ }
268+
222269// intsValue represents a value of []int.
223270type intsValue struct {
224271 value []int
225272}
226273
227- func (s * intsValue ) isElementValue () {}
228- func (s * intsValue ) ValueType () ValueType { return Ints }
229- func (s * intsValue ) GetValue () interface {} { return s .value }
230- func (s * intsValue ) String () string {
231- return fmt .Sprintf ("%v" , s .value )
274+ func (i * intsValue ) isElementValue () {}
275+ func (i * intsValue ) ValueType () ValueType { return Ints }
276+ func (i * intsValue ) GetValue () interface {} { return i .value }
277+ func (i * intsValue ) String () string {
278+ return fmt .Sprintf ("%v" , i .value )
232279}
233- func (s * intsValue ) MarshalJSON () ([]byte , error ) {
234- return json .Marshal (s .value )
280+ func (i * intsValue ) MarshalJSON () ([]byte , error ) {
281+ return json .Marshal (i .value )
282+ }
283+
284+ func (i * intsValue ) Equals (target Value ) bool {
285+ if target .ValueType () != Ints {
286+ return false
287+ }
288+ targetVal := target .GetValue ().([]int )
289+ if len (i .value ) != len (targetVal ) {
290+ return false
291+ }
292+ for idx , val := range i .value {
293+ if val != targetVal [idx ] {
294+ return false
295+ }
296+ }
297+ return true
235298}
236299
237300// floatsValue represents a value of []float64.
238301type floatsValue struct {
239302 value []float64
240303}
241304
242- func (s * floatsValue ) isElementValue () {}
243- func (s * floatsValue ) ValueType () ValueType { return Floats }
244- func (s * floatsValue ) GetValue () interface {} { return s .value }
245- func (s * floatsValue ) String () string {
246- return fmt .Sprintf ("%v" , s .value )
305+ func (f * floatsValue ) isElementValue () {}
306+ func (f * floatsValue ) ValueType () ValueType { return Floats }
307+ func (f * floatsValue ) GetValue () interface {} { return f .value }
308+ func (f * floatsValue ) String () string {
309+ return fmt .Sprintf ("%v" , f .value )
247310}
248- func (s * floatsValue ) MarshalJSON () ([]byte , error ) {
249- return json .Marshal (s .value )
311+ func (f * floatsValue ) MarshalJSON () ([]byte , error ) {
312+ return json .Marshal (f .value )
313+ }
314+ func (f * floatsValue ) Equals (target Value ) bool {
315+ if target .ValueType () != Floats {
316+ return false
317+ }
318+ targetVal := target .GetValue ().([]float64 )
319+ if len (f .value ) != len (targetVal ) {
320+ return false
321+ }
322+ for idx , val := range f .value {
323+ if val != targetVal [idx ] {
324+ return false
325+ }
326+ }
327+ return true
250328}
251329
252330// SequenceItemValue is a Value that represents a single Sequence Item. Learn
@@ -278,6 +356,22 @@ func (s *SequenceItemValue) MarshalJSON() ([]byte, error) {
278356 return json .Marshal (s .elements )
279357}
280358
359+ func (s * SequenceItemValue ) Equals (target Value ) bool {
360+ if target .ValueType () != SequenceItem {
361+ return false
362+ }
363+ targetVal := target .GetValue ().([]* Element )
364+ if len (s .elements ) != len (targetVal ) {
365+ return false
366+ }
367+ for idx , val := range s .elements {
368+ if ! val .Equals (targetVal [idx ]) {
369+ return false
370+ }
371+ }
372+ return true
373+ }
374+
281375// sequencesValue represents a set of items in a DICOM sequence.
282376type sequencesValue struct {
283377 value []* SequenceItemValue
@@ -293,6 +387,21 @@ func (s *sequencesValue) String() string {
293387func (s * sequencesValue ) MarshalJSON () ([]byte , error ) {
294388 return json .Marshal (s .value )
295389}
390+ func (s * sequencesValue ) Equals (target Value ) bool {
391+ if target .ValueType () != Sequences {
392+ return false
393+ }
394+ targetVal := target .GetValue ().([]* SequenceItemValue )
395+ if len (s .value ) != len (targetVal ) {
396+ return false
397+ }
398+ for idx , val := range s .value {
399+ if ! val .Equals (targetVal [idx ]) {
400+ return false
401+ }
402+ }
403+ return true
404+ }
296405
297406// PixelDataInfo is a representation of DICOM PixelData.
298407type PixelDataInfo struct {
@@ -304,7 +413,7 @@ type PixelDataInfo struct {
304413
305414 // Frames hold the processed PixelData frames (either Native or Encapsulated
306415 // PixelData).
307- Frames []frame.Frame
416+ Frames []* frame.Frame
308417
309418 // ParseErr indicates if there was an error when reading this Frame from the DICOM.
310419 // 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 {
329438 PixelDataInfo
330439}
331440
332- func (e * pixelDataValue ) isElementValue () {}
333- func (e * pixelDataValue ) ValueType () ValueType { return PixelData }
334- func (e * pixelDataValue ) GetValue () interface {} { return e .PixelDataInfo }
335- func (e * pixelDataValue ) String () string {
336- if len (e .Frames ) == 0 {
441+ func (p * pixelDataValue ) isElementValue () {}
442+ func (p * pixelDataValue ) ValueType () ValueType { return PixelData }
443+ func (p * pixelDataValue ) GetValue () interface {} { return p .PixelDataInfo }
444+ func (p * pixelDataValue ) String () string {
445+ if len (p .Frames ) == 0 {
337446 return "empty pixel data"
338447 }
339- if e .IsEncapsulated {
340- return fmt .Sprintf ("encapsulated FramesLength=%d Frame[0] size=%d" , len (e .Frames ), len (e .Frames [0 ].EncapsulatedData .Data ))
448+ if p .IsEncapsulated {
449+ return fmt .Sprintf ("encapsulated FramesLength=%d Frame[0] size=%d" , len (p .Frames ), len (p .Frames [0 ].EncapsulatedData .Data ))
341450 }
342- if e .ParseErr != nil {
343- return fmt .Sprintf ("parseErr err=%s FramesLength=%d Frame[0] size=%d" , e .ParseErr .Error (), len (e .Frames ), len (e .Frames [0 ].EncapsulatedData .Data ))
451+ if p .ParseErr != nil {
452+ return fmt .Sprintf ("parseErr err=%s FramesLength=%d Frame[0] size=%d" , p .ParseErr .Error (), len (p .Frames ), len (p .Frames [0 ].EncapsulatedData .Data ))
344453 }
345- return fmt .Sprintf ("FramesLength=%d FrameSize rows=%d cols=%d" , len (e .Frames ), e .Frames [0 ].NativeData .Rows , e .Frames [0 ].NativeData .Cols )
454+ return fmt .Sprintf ("FramesLength=%d FrameSize rows=%d cols=%d" , len (p .Frames ), p .Frames [0 ].NativeData .Rows , p .Frames [0 ].NativeData .Cols )
346455}
347456
348- func (e * pixelDataValue ) MarshalJSON () ([]byte , error ) {
349- return json .Marshal (e .PixelDataInfo )
457+ func (p * pixelDataValue ) MarshalJSON () ([]byte , error ) {
458+ return json .Marshal (p .PixelDataInfo )
459+ }
460+ func (p * pixelDataValue ) Equals (target Value ) bool {
461+ if target .ValueType () != PixelData {
462+ return false
463+ }
464+ targetVal := target .GetValue ().(PixelDataInfo )
465+ if p .IntentionallySkipped != targetVal .IntentionallySkipped ||
466+ p .IntentionallyUnprocessed != targetVal .IntentionallyUnprocessed ||
467+ p .ParseErr != targetVal .ParseErr ||
468+ p .IsEncapsulated != targetVal .IsEncapsulated ||
469+ ! bytes .Equal (p .UnprocessedValueData , targetVal .UnprocessedValueData ) {
470+ return false
471+ }
472+ targetFrameVal := target .GetValue ().(PixelDataInfo ).Frames
473+ if len (p .Frames ) != len (targetFrameVal ) {
474+ return false
475+ }
476+ for idx , val := range p .Frames {
477+ if ! val .Equals (targetFrameVal [idx ]) {
478+ return false
479+ }
480+ }
481+ return true
350482}
351483
352484// MustGetInts attempts to get an Ints value out of the provided value, and will
0 commit comments