Skip to content

Commit

Permalink
Fix reading CompressedSegmentation with uint32 data (#7757)
Browse files Browse the repository at this point in the history
* Fix reading CompressedSegmentation with uint32 data

* changelog
  • Loading branch information
fm3 committed Apr 16, 2024
1 parent c47cd65 commit 0644162
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Fixed a bug where users that have no team memberships were omitted from the user list. [#7721](https://github.com/scalableminds/webknossos/pull/7721)
- Added an appropriate placeholder to be rendered in case the timetracking overview is otherwise empty. [#7736](https://github.com/scalableminds/webknossos/pull/7736)
- The overflow menu in the layer settings tab for layers with long names can now be opened comfortably. [#7747](https://github.com/scalableminds/webknossos/pull/7747)
- Fixed a bug where segmentation data looked scrambled when reading uint32 segmentation layers with CompressedSegmentation codec. [#7757](https://github.com/scalableminds/webknossos/pull/7757)

### Removed

Expand Down
15 changes: 15 additions & 0 deletions util/src/main/scala/com/scalableminds/util/tools/ByteUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,19 @@ trait ByteUtils {
}
result.reverse
}

/**
*
* @param i a 32 bit number
* @return i as array of 8 bytes, little endian
*/
def intToBytes(i: Int): Array[Byte] = {
var w = i
val result = new Array[Byte](4)
for (i <- 3 to 0 by -1) {
result(i) = (w & 0xFF).toByte
w >>= 4
}
result.reverse
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ trait CompressedSegmentation[T <: AnyVal] extends ByteUtils {
val bitmask = (1 << encodedBits) - 1
for (z <- zmin until zmax) {
for (y <- ymin until ymax) {
var outindex = (z * (volumeSize(1)) + y) * volumeSize(0) + xmin
var bitpos = blockSize.x * ((z - zmin) * (blockSize.y) + (y - ymin)) * encodedBits
for (x <- xmin until xmax) {
var outindex = (z * volumeSize(1) + y) * volumeSize(0) + xmin
var bitpos = blockSize.x * ((z - zmin) * blockSize.y + (y - ymin)) * encodedBits
for (_ <- xmin until xmax) {
val bitshift = bitpos % 32
val arraypos = bitpos / (32)
val arraypos = bitpos / 32
var bitval = 0
if (encodedBits > 0) {
bitval = (input(encodedValueStart + arraypos) >> bitshift) & bitmask
Expand All @@ -76,7 +76,7 @@ trait CompressedSegmentation[T <: AnyVal] extends ByteUtils {
.flatMap(channel => decompressChannel(input.drop(input(channel)), volumeSize, blockSize))
.toArray

def valueAsLong(v: T): Long
def valueToBytes(v: T): Array[Byte]

def decompress(encodedBytes: Array[Byte], volumeSize: Array[Int], blockSize: Vec3Int)(
implicit c: ClassTag[T]): Array[Byte] = {
Expand All @@ -87,8 +87,8 @@ trait CompressedSegmentation[T <: AnyVal] extends ByteUtils {
}
val input32 = new Array[Int](encodedBytes.length / 4)
ByteBuffer.wrap(encodedBytes).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().get(input32)
val values = decompressChannels(input32, vs, blockSize)
values.flatMap(v => longToBytes(valueAsLong(v)))
val values: Array[T] = decompressChannels(input32, vs, blockSize)
values.flatMap(v => valueToBytes(v))
}
}

Expand All @@ -101,7 +101,7 @@ object CompressedSegmentation32 extends CompressedSegmentation[Int] {
override def readValue(input: Array[Int], position: Int): Int =
input(position)

override def valueAsLong(v: Int): Long = v.toLong
def valueToBytes(v: Int): Array[Byte] = intToBytes(v)
}

object CompressedSegmentation64 extends CompressedSegmentation[Long] {
Expand All @@ -113,5 +113,5 @@ object CompressedSegmentation64 extends CompressedSegmentation[Long] {
override def readValue(input: Array[Int], position: Int): Long =
ByteBuffer.wrap(ByteBuffer.allocate(8).putInt(input(position + 1)).putInt(input(position)).array()).getLong

override def valueAsLong(v: Long): Long = v
def valueToBytes(v: Long): Array[Byte] = longToBytes(v)
}

0 comments on commit 0644162

Please sign in to comment.