Sped up targa bitmap loading significantly

This commit is contained in:
Josh Larson
2022-07-18 15:45:07 -05:00
parent 1bbd38e3cd
commit 9d5334e5d8
2 changed files with 60 additions and 76 deletions
@@ -2,6 +2,7 @@ package com.projectswg.common.data.swgiff.parsers.terrain.bitmap
import java.io.FileInputStream
import java.io.InputStream
import kotlin.math.min
class TargaBitmap {
@@ -9,62 +10,19 @@ class TargaBitmap {
private var colorMapType: Byte = 0
private var dataTypeCode: Byte = 0
private var colorMapDepth: Byte = 0
private var bitsPerPixel: Byte = 0
private var bitsPerPixel: Int = 0
private var imageDescriptor: Byte = 0
private var colorMapOrigin: Short = 0
private var colorMapLength: Short = 0
private var originX: Short = 0
private var originY: Short = 0
var width: Short = 0
var width: Int = 0
private set
var height: Short = 0
var height: Int = 0
private set
private lateinit var pixelData: Array<TargaPixel?>
private lateinit var pixelData: ByteArray
var fileName: String? = null
inner class TargaColorPixel : TargaPixel() {
var r = 0.toChar()
var g = 0.toChar()
var b = 0.toChar()
var a = 0.toChar()
override fun read(buffer: InputStream, bytes: Int) {
when (bytes) {
4 -> {
r = Char(buffer.read().toUShort())
g = Char(buffer.read().toUShort())
b = Char(buffer.read().toUShort())
a = Char(buffer.read().toUShort())
}
3 -> {
r = Char(buffer.read().toUShort())
g = Char(buffer.read().toUShort())
b = Char(buffer.read().toUShort())
a = 0.toChar()
}
2 -> {
val first = Char(buffer.read().toUShort())
val second = Char(buffer.read().toUShort())
r = (first.code and 0x7c shl 1).toChar()
g = (first.code and 0x03 shl 6 or (second.code and 0xe0 shl 2)).toChar()
b = (second.code and 0x1f shl 3).toChar()
a = (first.code and 0x80).toChar()
}
}
}
}
inner class TargaBlackPixel : TargaPixel() {
var `val` = 0.toChar()
override fun read(buffer: InputStream, bytes: Int) {
`val` = Char(buffer.readByte().toUShort())
}
}
abstract inner class TargaPixel {
abstract fun read(buffer: InputStream, bytes: Int)
}
fun readFile(filePath: String) {
fileName = filePath
FileInputStream("clientdata/$filePath").use { inputStream ->
@@ -76,9 +34,9 @@ class TargaBitmap {
colorMapDepth = inputStream.readByte()
originX = inputStream.readShort()
originY = inputStream.readShort()
width = inputStream.readShort()
height = inputStream.readShort()
bitsPerPixel = inputStream.readByte()
width = inputStream.readShort().toInt()
height = inputStream.readShort().toInt()
bitsPerPixel = inputStream.readByte().toInt()
imageDescriptor = inputStream.readByte()
var length = 0
@@ -89,37 +47,35 @@ class TargaBitmap {
else if (height > width)
length = height * height
pixelData = arrayOfNulls(length)
for (i in 0 until length) {
var pixel: TargaPixel? = null
when (dataTypeCode.toInt()) {
3 -> pixel = TargaBlackPixel()
2, 10 -> pixel = TargaColorPixel()
}
pixelData[i] = pixel
}
inputStream.skip((idLength + colorMapType * colorMapLength).toLong())
val bytes = bitsPerPixel / 8
if (width <= height) {
for (i in width - 1 downTo 0) {
for (j in 0 until height) {
pixelData[i * width + j]!!.read(inputStream, bytes)
}
}
if (bitsPerPixel == 8) {
pixelData = inputStream.readNBytes(length)
} else {
for (i in height - 1 downTo 0) {
for (j in 0 until width) {
pixelData[i * height + j]!!.read(inputStream, bytes)
}
assert(dataTypeCode == 2.toByte() || dataTypeCode == 10.toByte())
pixelData = ByteArray(length * 4)
val pixelLoaderFunction = when (bitsPerPixel) {
16 -> ::read2ByteColorPixel
24 -> ::read3ByteColorPixel
32 -> ::read4ByteColorPixel
else -> throw NotImplementedError("unsupported bits per pixel: $bitsPerPixel")
}
val bytesPerPixel = bitsPerPixel / 8
var index = 0
for (i in 0 until length) {
pixelLoaderFunction(inputStream, pixelData, index)
index += bytesPerPixel
}
}
}
}
fun getData(offset: Int): Char {
fun getData(offset: Int): Byte {
if (offset < 0 || offset >= width * height)
throw ArrayIndexOutOfBoundsException(offset)
return (pixelData[offset] as TargaBlackPixel?)!!.`val`
val smaller = min(width, height)
val y = offset / smaller
val x = offset % smaller
return pixelData[(smaller - y - 1) * smaller + x]
}
private fun InputStream.readByte(): Byte {
@@ -130,4 +86,32 @@ class TargaBitmap {
return ((read() or (read() shl 8)) and 0xFFFF).toShort()
}
companion object {
private fun read4ByteColorPixel(src: InputStream, dst: ByteArray, indexIn: Int) {
var index: Int = indexIn
dst[index++] = src.read().toByte()
dst[index++] = src.read().toByte()
dst[index++] = src.read().toByte()
dst[index] = src.read().toByte()
}
private fun read3ByteColorPixel(src: InputStream, dst: ByteArray, indexIn: Int) {
var index: Int = indexIn
dst[index++] = src.read().toByte()
dst[index++] = src.read().toByte()
dst[index++] = src.read().toByte()
dst[index] = 0
}
private fun read2ByteColorPixel(src: InputStream, dst: ByteArray, indexIn: Int) {
var index: Int = indexIn
val first = src.read()
val second = src.read()
dst[index++] = (first and 0x7c shl 1).toByte()
dst[index++] = (first and 0x03 shl 6 or (second and 0xe0 shl 2)).toByte()
dst[index++] = (second and 0x1f shl 3).toByte()
dst[index] = (first and 0x80).toByte()
}
}
}
@@ -40,12 +40,12 @@ class FilterBitmap : FilterLayer() {
var v25 = (v44 * (height - v41 - 1)).toInt()
val v26 = (v39 * v44 / arg6).toInt()
var v27 = (v43 * v44 / arg6).toInt()
val v28 = (bitmap.getData(v27 + v25).code and 0xFF).toFloat()
val v28 = (bitmap.getData(v27 + v25).toInt() and 0xFF).toFloat()
//byte mapValue = v28;
var arg2 = (bitmap.getData(v26 + v25).code and 0xFF).toFloat()
var arg2 = (bitmap.getData(v26 + v25).toInt() and 0xFF).toFloat()
val v29 = (v44 * (height - arg1 - 1)).toInt()
v25 = bitmap.getData(v29 + v27).code and 0xFF
v27 = bitmap.getData(v26 + v29).code and 0xFF
v25 = bitmap.getData(v29 + v27).toInt() and 0xFF
v27 = bitmap.getData(v26 + v29).toInt() and 0xFF
arg6 = v25.toFloat()
arg1 = v27.toFloat()
val v30 = v42 - v43.toDouble()