korge
korge copied to clipboard
Trying to implement BitmapSRGB so that it can take in bytes from Webcam without needing to convert to TYPE_INT_ARGB_PRE
The image looks all wrong:
Can you please take a look at my implementation and see if I'm missing anything?
import korlibs.image.bitmap.Bitmap
import korlibs.image.color.RGBA
import kotlin.math.pow
class BitmapSRGB(
width: Int,
height: Int,
val data: ByteArray = ByteArray(width * height * 3),
): Bitmap(width, height, 8, true, data) {
override fun getInt(x: Int, y: Int): Int {
val idxStart = (x * 3) + (y * width * 3)
val r = data[idxStart].toInt()
val g = data[idxStart + 1].toInt()
val b = data[idxStart + 2].toInt()
val linearRgb = doubleArrayOf(r / 255.0, g / 255.0, b / 255.0)
// Linearization
for (i in 0..2) {
linearRgb[i] = if (linearRgb[i] <= 0.04045) {
linearRgb[i] / 12.92
} else {
((linearRgb[i] + 0.055) / 1.055).pow(2.4)
}
}
// sRGB to XYZ matrix transformation
val srgbToXyzMatrix = arrayOf(
doubleArrayOf(0.4124564, 0.3575761, 0.1804375),
doubleArrayOf(0.2126729, 0.7151522, 0.0721750),
doubleArrayOf(0.0193339, 0.1191920, 0.9503041)
)
val xyz = DoubleArray(3)
for (i in 0..2) {
for (j in 0..2) {
xyz[i] += srgbToXyzMatrix[i][j] * linearRgb[j]
}
}
// XYZ to Adobe RGB matrix transformation
val xyzToAdobeRgbMatrix = arrayOf(
doubleArrayOf(2.0413690, -0.5649464, -0.3446944),
doubleArrayOf(-0.9692660, 1.8760108, 0.0415560),
doubleArrayOf(0.0134474, -0.1183897, 1.0154096)
)
val linearAdobeRgb = DoubleArray(3)
for (i in 0..2) {
for (j in 0..2) {
linearAdobeRgb[i] += xyzToAdobeRgbMatrix[i][j] * xyz[j]
}
}
// Gamma correction
for (i in 0..2) {
linearAdobeRgb[i] = if (linearAdobeRgb[i] <= 0.0) {
0.0
} else {
linearAdobeRgb[i].pow(1 / 2.19921875)
}
}
// Convert back to integer bytes (0-255)
val adobeRgb = IntArray(3)
for (i in 0..2) {
adobeRgb[i] = (linearAdobeRgb[i] * 255.0).toInt()
}
// return RGBA(adobeRgb[0], adobeRgb[1], adobeRgb[2]).value
return (adobeRgb[0] shl 0) or (adobeRgb[1] shl 8) or (adobeRgb[2] shl 16) or (0xFF shl 24)
}
override fun setInt(x: Int, y: Int, color: Int) = TODO()
override fun getRgbaRaw(x: Int, y: Int): RGBA = RGBA(getInt(x, y))
}
For context: The webcam image is in terms of sRGB:
https://github.com/Kietyo/webcam-capture-kotlin/blob/master/src/main/kotlin/com/github/sarxos/webcam/ds/buildin/WebcamDefaultDevice.kt#L394
Resources I followed for my implementation:
- https://en.wikipedia.org/wiki/SRGB
- https://en.wikipedia.org/wiki/Adobe_RGB_color_space