suyashkumar/dicom

dicom.Write() fails on nested dataset where 'ItemDelimitationItem' has a blank VR when dicom.SkipVRVerification() is used.

bpeake-illuscio opened this issue · 0 comments

Hello!

I'm having an issue writing a dicom that I've read in.

Here is some example code, where I make no changes at all to the file:

package main

import (
	"bytes"
	"fmt"
	"github.com/illuscio-dev/edesia-go/service/internal/edesiatest"
	"github.com/suyashkumar/dicom"
)


func main() {
	source := bytes.NewBuffer(edesiatest.DicomFileBasicMR1Data)
	dataset, err := dicom.Parse(source, int64(len(edesiatest.DicomFileBasicMR1Data)), nil)
	if err != nil {
		panic(err)
	}

	writeBuffer := new(bytes.Buffer)
	err = dicom.Write(writeBuffer, dataset, dicom.SkipValueTypeVerification(), dicom.SkipVRVerification())
	fmt.Println("ERROR:", err)
}

I get the following error:

ERROR: ERROR dicomio.writeVRVL: Value Representation must be of length 2, e.g. 'UN'. For tag=(fffe,e00d)[ItemDelimitationItem], it was RawValueRepresentation=

The weird thing is that when I do this:

func main() {
	source := bytes.NewBuffer(edesiatest.DicomFileBasicMR1Data)
	dataset, err := dicom.Parse(source, int64(len(edesiatest.DicomFileBasicMR1Data)), nil)
	if err != nil {
		panic(err)
	}

	_, err = dataset.FindElementByTagNested(tag.ItemDelimitationItem)
	if err != nil {
		panic(err)
	}
}

It doesn't get find that item. From the Dicom Spec it looks like this is a special element that signals the end of a nested dataset. I am guessing your code is inserting this, but failing it's own VR checks since the DICOM spec does not seem to define a VR for this element type.

According to my debugger the error is coming from write.go, line 309:

if len(vr) != 2 && vl != tag.VLUndefinedLength && t != tag.SequenceDelimitationItem {
	return fmt.Errorf("ERROR dicomio.writeVRVL: Value Representation must be of length 2, e.g. 'UN'. For tag=%v, it was RawValueRepresentation=%v",
		tag.DebugString(t), vr)
}

I think we need to add && t != tag.ItemDelimitationItem to this bit of logic.

Digging a bit deeper, it seems that this specifically triggers when dicom.SkipVRVerification() is used because this option ALSO causes the writer to skip over setting a default VR if none is set, here (write.go, line 185):

if !opts.skipVRVerification {
	var err error
	vr, err = verifyVROrDefault(elem.Tag, elem.RawValueRepresentation)
	if err != nil {
		return err
	}
}

So if skipVRVerification, ItemDelimitationItem never gets a default VR and is not caught when checking VR length.

I'll make a PR shortly for this.