geotrellis.raster.io.geotiff.compression.HorizontalPredictor.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of geotrellis-raster_2.11 Show documentation
Show all versions of geotrellis-raster_2.11 Show documentation
GeoTrellis is an open source geographic data processing engine for high performance applications.
The newest version!
package geotrellis.raster.io.geotiff.compression
import geotrellis.raster.io.geotiff._
import geotrellis.raster.io.geotiff.tags._
import geotrellis.raster.io.geotiff.reader.MalformedGeoTiffException
import monocle.syntax._
import java.nio.ByteBuffer
import spire.syntax.cfor._
object HorizontalPredictor {
def apply(tiffTags: TiffTags): Predictor = {
val colsPerRow = tiffTags.rowSize
val rowsInSegment: (Int => Int) = { i => tiffTags.rowsInSegment(i) }
val bandType = tiffTags.bandType
val predictor =
if(tiffTags.hasPixelInterleave) {
new HorizontalPredictor(colsPerRow, rowsInSegment, tiffTags.bandCount)
} else {
new HorizontalPredictor(colsPerRow, rowsInSegment, 1)
}
predictor.forBandType(bandType)
}
}
class HorizontalPredictor(cols: Int, rowsInSegment: Int => Int, bandCount: Int) {
def forBandType(bandType: BandType): Predictor = {
val applyFunc: (Array[Byte], Int) => Array[Byte] =
bandType.bitsPerSample match {
case 8 => apply8 _
case 16 => apply16 _
case 32 => apply32 _
case _ =>
throw new MalformedGeoTiffException(s"""Horizontal differencing "Predictor" not supported with ${bandType.bitsPerSample} bits per sample""")
}
new Predictor {
val checkEndian = true
def apply(bytes: Array[Byte], segmentIndex: Int): Array[Byte] =
applyFunc(bytes, segmentIndex)
}
}
def apply8(bytes: Array[Byte], segmentIndex: Int): Array[Byte] = {
val rows = rowsInSegment(segmentIndex)
cfor(0)(_ < rows, _ + 1) { row =>
var count = bandCount * (row * cols + 1)
cfor(bandCount)({ k => k < cols * bandCount && k < bytes.length }, _ + 1) { k =>
bytes(count) = (bytes(count) + bytes(count - bandCount)).toByte
count += 1
}
}
bytes
}
def apply16(bytes: Array[Byte], segmentIndex: Int): Array[Byte] = {
val buffer = ByteBuffer.wrap(bytes).asShortBuffer
val rows = rowsInSegment(segmentIndex)
cfor(0)(_ < rows, _ + 1) { row =>
var count = bandCount * (row * cols + 1)
cfor(bandCount)(_ < cols * bandCount, _ + 1) { k =>
buffer.put(count, (buffer.get(count) + buffer.get(count - bandCount)).toShort)
count += 1
}
}
bytes
}
def apply32(bytes: Array[Byte], segmentIndex: Int): Array[Byte] = {
val buffer = ByteBuffer.wrap(bytes).asIntBuffer
val rows = rowsInSegment(segmentIndex)
cfor(0)(_ < rows, _ + 1) { row =>
var count = bandCount * (row * cols + 1)
cfor(bandCount)(_ < cols * bandCount, _ + 1) { k =>
buffer.put(count, buffer.get(count) + buffer.get(count - bandCount))
count += 1
}
}
bytes
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy