Skip to content

Commit

Permalink
Add more expansive write native PixelData tests, cleanup internals. (s…
Browse files Browse the repository at this point in the history
…uyashkumar#170)

This change cleans up some of the internals of the Native PixelData write code, along with adding more expansive tests for this.
  • Loading branch information
suyashkumar committed Dec 31, 2020
1 parent 5accaa2 commit c22fd68
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 9 deletions.
21 changes: 12 additions & 9 deletions write.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,26 +509,29 @@ func writePixelData(w dicomio.Writer, t tag.Tag, value Value, vr string, vl uint
numFrames := len(image.Frames)
numPixels := len(image.Frames[0].NativeData.Data)
numValues := len(image.Frames[0].NativeData.Data[0])
length := numFrames * numPixels * numValues * image.Frames[0].NativeData.BitsPerSample / 8 // length in bytes
// Total required buffer length in bytes:
length := numFrames * numPixels * numValues * image.Frames[0].NativeData.BitsPerSample / 8

buf := new(bytes.Buffer)
buf := &bytes.Buffer{}
buf.Grow(length)
for frame := 0; frame < numFrames; frame++ {
for pixel := 0; pixel < numPixels; pixel++ {
for value := 0; value < numValues; value++ {
if image.Frames[frame].NativeData.BitsPerSample == 8 {
if err := binary.Write(buf, binary.LittleEndian, uint8(image.Frames[frame].NativeData.Data[pixel][value])); err != nil {
pixelValue := image.Frames[frame].NativeData.Data[pixel][value]
switch image.Frames[frame].NativeData.BitsPerSample {
case 8:
if err := binary.Write(buf, binary.LittleEndian, uint8(pixelValue)); err != nil {
return err
}
} else if image.Frames[frame].NativeData.BitsPerSample == 16 {
if err := binary.Write(buf, binary.LittleEndian, uint16(image.Frames[frame].NativeData.Data[pixel][value])); err != nil {
case 16:
if err := binary.Write(buf, binary.LittleEndian, uint16(pixelValue)); err != nil {
return err
}
} else if image.Frames[frame].NativeData.BitsPerSample == 32 {
if err := binary.Write(buf, binary.LittleEndian, uint32(image.Frames[frame].NativeData.Data[pixel][value])); err != nil {
case 32:
if err := binary.Write(buf, binary.LittleEndian, uint32(pixelValue)); err != nil {
return err
}
} else {
default:
return ErrorUnsupportedBitsPerSample
}
}
Expand Down
125 changes: 125 additions & 0 deletions write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"os"
"testing"

"github.com/suyashkumar/dicom/pkg/frame"

"github.com/google/go-cmp/cmp/cmpopts"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -156,6 +158,129 @@ func TestWrite(t *testing.T) {
expectedError: nil,
opts: []WriteOption{DefaultMissingTransferSyntax()},
},
{
name: "native PixelData: 8bit",
dataset: Dataset{Elements: []*Element{
mustNewElement(tag.MediaStorageSOPClassUID, []string{"1.2.840.10008.5.1.4.1.1.1.2"}),
mustNewElement(tag.MediaStorageSOPInstanceUID, []string{"1.2.3.4.5.6.7"}),
mustNewElement(tag.TransferSyntaxUID, []string{uid.ImplicitVRLittleEndian}),
mustNewElement(tag.Rows, []int{2}),
mustNewElement(tag.Columns, []int{2}),
mustNewElement(tag.BitsAllocated, []int{8}),
mustNewElement(tag.NumberOfFrames, []string{"1"}),
mustNewElement(tag.SamplesPerPixel, []int{1}),
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}},
},
},
},
}),
mustNewElement(tag.FloatingPointValue, []float64{128.10}),
mustNewElement(tag.DimensionIndexPointer, []int{32, 36950}),
}},
expectedError: nil,
},
{
name: "native PixelData: 16bit",
dataset: Dataset{Elements: []*Element{
mustNewElement(tag.MediaStorageSOPClassUID, []string{"1.2.840.10008.5.1.4.1.1.1.2"}),
mustNewElement(tag.MediaStorageSOPInstanceUID, []string{"1.2.3.4.5.6.7"}),
mustNewElement(tag.TransferSyntaxUID, []string{uid.ImplicitVRLittleEndian}),
mustNewElement(tag.Rows, []int{2}),
mustNewElement(tag.Columns, []int{2}),
mustNewElement(tag.BitsAllocated, []int{16}),
mustNewElement(tag.NumberOfFrames, []string{"1"}),
mustNewElement(tag.SamplesPerPixel, []int{1}),
mustNewElement(tag.PixelData, PixelDataInfo{
IsEncapsulated: false,
Frames: []frame.Frame{
{
Encapsulated: false,
NativeData: frame.NativeFrame{
BitsPerSample: 16,
Rows: 2,
Cols: 2,
Data: [][]int{{1}, {2}, {3}, {4}},
},
},
},
}),
}},
expectedError: nil,
},
{
name: "native PixelData: 32bit",
dataset: Dataset{Elements: []*Element{
mustNewElement(tag.MediaStorageSOPClassUID, []string{"1.2.840.10008.5.1.4.1.1.1.2"}),
mustNewElement(tag.MediaStorageSOPInstanceUID, []string{"1.2.3.4.5.6.7"}),
mustNewElement(tag.TransferSyntaxUID, []string{uid.ImplicitVRLittleEndian}),
mustNewElement(tag.Rows, []int{2}),
mustNewElement(tag.Columns, []int{2}),
mustNewElement(tag.BitsAllocated, []int{32}),
mustNewElement(tag.NumberOfFrames, []string{"1"}),
mustNewElement(tag.SamplesPerPixel, []int{1}),
mustNewElement(tag.PixelData, PixelDataInfo{
IsEncapsulated: false,
Frames: []frame.Frame{
{
Encapsulated: false,
NativeData: frame.NativeFrame{
BitsPerSample: 32,
Rows: 2,
Cols: 2,
Data: [][]int{{1}, {2}, {3}, {4}},
},
},
},
}),
}},
expectedError: nil,
},
{
name: "native PixelData: 2 SamplesPerPixel, 2 frames",
dataset: Dataset{Elements: []*Element{
mustNewElement(tag.MediaStorageSOPClassUID, []string{"1.2.840.10008.5.1.4.1.1.1.2"}),
mustNewElement(tag.MediaStorageSOPInstanceUID, []string{"1.2.3.4.5.6.7"}),
mustNewElement(tag.TransferSyntaxUID, []string{uid.ImplicitVRLittleEndian}),
mustNewElement(tag.Rows, []int{2}),
mustNewElement(tag.Columns, []int{2}),
mustNewElement(tag.BitsAllocated, []int{32}),
mustNewElement(tag.NumberOfFrames, []string{"2"}),
mustNewElement(tag.SamplesPerPixel, []int{2}),
mustNewElement(tag.PixelData, PixelDataInfo{
IsEncapsulated: false,
Frames: []frame.Frame{
{
Encapsulated: false,
NativeData: frame.NativeFrame{
BitsPerSample: 32,
Rows: 2,
Cols: 2,
Data: [][]int{{1, 1}, {2, 2}, {3, 3}, {4, 4}},
},
},
{
Encapsulated: false,
NativeData: frame.NativeFrame{
BitsPerSample: 32,
Rows: 2,
Cols: 2,
Data: [][]int{{5, 1}, {2, 2}, {3, 3}, {4, 5}},
},
},
},
}),
}},
expectedError: nil,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
Expand Down

0 comments on commit c22fd68

Please sign in to comment.