diff --git a/src/main/scala/com/exini/dicom/streams/DicomFlows.scala b/src/main/scala/com/exini/dicom/streams/DicomFlows.scala index fcfb495..7299fe8 100644 --- a/src/main/scala/com/exini/dicom/streams/DicomFlows.scala +++ b/src/main/scala/com/exini/dicom/streams/DicomFlows.scala @@ -555,15 +555,17 @@ object DicomFlows { currentHeader = None header :: Nil } - case value: ValueChunk if currentHeader.isDefined => + case value: ValueChunk if currentHeader.isDefined && !inFragments => currentValue = currentValue ++ value.bytes if (value.last) { - val newValue = currentHeader + val header = currentHeader + currentHeader = None + val newValue = header .map(h => characterSets.decode(h.vr, currentValue).getBytes(utf8Charset)) .map(ByteString.apply) val newLength = newValue.map(_.length) val newElement = for { - h <- currentHeader + h <- header v <- newValue l <- newLength } yield h.withUpdatedLength(l) :: ValueChunk(h.bigEndian, v, last = true) :: Nil diff --git a/src/test/scala/com/exini/dicom/streams/DicomFlowsTest.scala b/src/test/scala/com/exini/dicom/streams/DicomFlowsTest.scala index 546c7cc..9ce8927 100644 --- a/src/test/scala/com/exini/dicom/streams/DicomFlowsTest.scala +++ b/src/test/scala/com/exini/dicom/streams/DicomFlowsTest.scala @@ -1,7 +1,5 @@ package com.exini.dicom.streams -import java.io.File - import akka.actor.ActorSystem import akka.stream.scaladsl.{ FileIO, Sink, Source } import akka.stream.testkit.scaladsl.TestSink @@ -19,6 +17,7 @@ import org.scalatest.BeforeAndAfterAll import org.scalatest.flatspec.AnyFlatSpecLike import org.scalatest.matchers.should.Matchers +import java.io.File import scala.concurrent.duration.DurationInt import scala.concurrent.{ Await, ExecutionContextExecutor } @@ -1210,6 +1209,31 @@ class DicomFlowsTest .expectDicomComplete() } + it should "should handle fragments appearing just after an updated attribute" in { + val specificCharacterSet = tagToBytesLE(Tag.SpecificCharacterSet) ++ ByteString("CS") ++ + shortToBytesLE(0x001e.toShort) ++ padToEvenLength(ByteString("ISO 2022 IR 13\\ISO 2022 IR 87"), VR.CS) + + val bytes = specificCharacterSet ++ personNameJohnDoe() ++ pixeDataFragments() ++ item(4) ++ + ByteString(1, 2, 3, 4) ++ sequenceDelimitation() + + val source = Source + .single(bytes) + .via(parseFlow) + .via(toUtf8Flow) + + source + .runWith(TestSink.probe[DicomPart]) + .expectHeader(Tag.SpecificCharacterSet) + .expectValueChunk(ByteString("ISO_IR 192")) + .expectHeader(Tag.PatientName) + .expectValueChunk() + .expectFragments() + .expectFragment(4) + .expectValueChunk(ByteString(1, 2, 3, 4)) + .expectFragmentsDelimitation() + .expectDicomComplete() + } + "The explicit VR little endian flow" should "convert explicit VR big endian to explicit VR little endian" in { val bigEndian = true val bytes = preamble ++ fmiGroupLength(transferSyntaxUID(UID.ExplicitVRBigEndianRetired)) ++ transferSyntaxUID(