suyashkumar / dicom

⚡High Performance DICOM Medical Image Parser in Go.
MIT License
920 stars 133 forks source link

Write() fails for encapsulated pixel data unless ValueLength explicitly set to tag.VLUndefinedLength #285

Closed pattersp closed 10 months ago

pattersp commented 10 months ago

I am trying to write a dicom dataset that holds encapsulated pixel data. Example program:

package main

import (
    "log"
    "os"

    "github.com/spf13/pflag"
    "github.com/suyashkumar/dicom"
    "github.com/suyashkumar/dicom/pkg/frame"
    "github.com/suyashkumar/dicom/pkg/tag"
)

var (
    outPath = pflag.String("out_path", "", "out_path")
)

func main() {
    pflag.Parse()

    dataset := dicom.Dataset{}

    transferSyntaxUIDEl, err := dicom.NewElement(tag.TransferSyntaxUID, []string{"1.2.840.10008.1.2.4.50"})
    if err != nil {
        log.Fatalf("transfer syntax el: %v", err)
    }

    myPD := dicom.PixelDataInfo{
        IsEncapsulated: true,
        Frames: []frame.Frame{
            {
                Encapsulated: true,
                EncapsulatedData: frame.EncapsulatedFrame{
                    Data: []byte{}, // put your data here
                },
            },
        },
    }
    pixelData, err := dicom.NewElement(tag.PixelData, myPD)
    if err != nil {
        log.Fatalf("pixel data: %v", err)
    }
    // pixelData.ValueLength = tag.VLUndefinedLength UNCOMMENT TO FIX
    dataset.Elements = append(dataset.Elements, transferSyntaxUIDEl, pixelData)

    f, err := os.Create(*outPath)
    if err != nil {
        log.Fatalf("Create: %v", err)
    }
    if err := dicom.Write(f, dataset); err != nil {
        log.Fatalf("Write: %v", err)
    }

    log.Println("Succcess")
}

When I run this program as-is, I get the following error (unless I uncomment the line that sets VLUndefinedLength):

panic: runtime error: index out of range [0] with length 0

goroutine 1 [running]:
github.com/suyashkumar/dicom.writePixelData({{0x6332b8, 0xc000016600}, {0x6345b8, 0x72d680}, 0x0}, {0x0?, 0x0?}, {0x634170?, 0xc0000d2070?}, {0x5ecfc8, ...}, ...)
    <redacted>/go/pkg/mod/github.com/suyashkumar/dicom@v1.0.6/write.go:577 +0x60f
github.com/suyashkumar/dicom.writeValue({{0x6332b8, 0xc000016600}, {0x6345b8, 0x72d680}, 0x0}, {0x7fe0, 0x10}, {0x634170, 0xc0000d2070}, 0x3, ...)
    <redacted>/go/pkg/mod/github.com/suyashkumar/dicom@v1.0.6/write.go:447 +0x38a
github.com/suyashkumar/dicom.writeElement({{0x633238, 0xc000070050}, {0x6345b8, 0x72d680}, 0x0}, 0xc0000980c0, {0x28?, 0x13?, 0x67?})
    <redacted>/go/pkg/mod/github.com/suyashkumar/dicom@v1.0.6/write.go:232 +0x257
github.com/suyashkumar/dicom.(*Writer).writeDataset(0xc000016540, {{0xc00002e100, 0x2, 0x2}})
    <redacted>/go/pkg/mod/github.com/suyashkumar/dicom@v1.0.6/write.go:80 +0x405
github.com/suyashkumar/dicom.Write({0x633238?, 0xc000070050?}, {{0xc00002e100?, 0x2?, 0x5cdea0?}}, {0x0?, 0x5ed973?, 0x8?})
    <redacted>/go/pkg/mod/github.com/suyashkumar/dicom@v1.0.6/write.go:99 +0x53

Is this working as intended? Is it expected that I need to explicitly set this length field?

Thanks!

suyashkumar commented 10 months ago

Hi thanks for reaching out! I think it is indeed the case that ValueLength needs to be set, in DICOM I think ValueLength needs to be set on all Elements (and even undefined value length is a specific value, as you see here). we can check the spec, but iirc a PixelData with undefined length is one of the main things indicating the DICOM is going to be encapsulated vs. native data.