56 lines
1.7 KiB
Kotlin
56 lines
1.7 KiB
Kotlin
import java.io.File
|
|
import java.io.OutputStream
|
|
|
|
const val BYTES_PER_PIXEL = 4
|
|
|
|
data class Color(val r: UByte, val g: UByte, val b: UByte, val alpha: UByte = UByte.MAX_VALUE)
|
|
|
|
@OptIn(ExperimentalUnsignedTypes::class)
|
|
class Bitmap(val width: Int, val height: Int) {
|
|
val data = UByteArray(width * height * BYTES_PER_PIXEL)
|
|
|
|
fun setPixel(x: Int, y: Int, color: Color) {
|
|
val offset = (y * width + x) * BYTES_PER_PIXEL
|
|
data[offset + 1] = color.g
|
|
data[offset + 0] = color.b
|
|
data[offset + 2] = color.r
|
|
data[offset + 3] = color.alpha
|
|
}
|
|
|
|
fun getPixel(x: Int, y: Int): Color {
|
|
val offset = (y * width + x) * BYTES_PER_PIXEL
|
|
return Color(
|
|
r = data[offset + 2],
|
|
g = data[offset + 1],
|
|
b = data[offset + 0],
|
|
alpha = data[offset + 3]
|
|
)
|
|
}
|
|
}
|
|
|
|
@OptIn(ExperimentalUnsignedTypes::class)
|
|
fun File.writeBitmap(bitmap: Bitmap) {
|
|
outputStream().use { stream ->
|
|
stream.write(0) // ID length
|
|
stream.write(0) // No color map
|
|
stream.write(2) // Uncompressed true color image
|
|
|
|
stream.writeWord(0) // Color map starts at index 0
|
|
stream.writeWord(0) // No color map entries
|
|
stream.write(0) // 0 bits per color map entry
|
|
|
|
stream.writeWord(0) // X origin
|
|
stream.writeWord(0) // Y origin
|
|
stream.writeWord(bitmap.width.toShort())
|
|
stream.writeWord(bitmap.height.toShort())
|
|
stream.write(BYTES_PER_PIXEL * 8)
|
|
stream.write(8)
|
|
stream.write(bitmap.data.toByteArray())
|
|
}
|
|
}
|
|
|
|
fun OutputStream.writeWord(word: Short) {
|
|
write(word.toInt() and 0xFF)
|
|
write((word.toInt() shr 8) and 0xFF)
|
|
}
|
|
|