Skip to content

Commit

Permalink
Fixed bug where fragments following an attribute modified by the utf8…
Browse files Browse the repository at this point in the history
… flow would have all its data filtered out
  • Loading branch information
karl-exini committed Mar 24, 2021
1 parent b2e0abe commit ca63cb2
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
8 changes: 5 additions & 3 deletions src/main/scala/com/exini/dicom/streams/DicomFlows.scala
Expand Up @@ -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
Expand Down
28 changes: 26 additions & 2 deletions 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
Expand All @@ -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 }

Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit ca63cb2

Please sign in to comment.