korlibs / korlibs/korlibs-image

Trying to implement BitmapSRGB so that it can take in bytes from Webcam without needing to convert to TYPE_INT_ARGB_PRE

Open
#17 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Kotlin
Stars
2
Forks
1
PR merge metrics
No merged PRs in 30d

Description

The image looks all wrong:

image

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

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reviewing the BitmapSRGB implementation in the issue, especially its byte indexing, color conversion, channel packing, and unimplemented setInt method. Compare its assumptions with Bitmap and the webcam sRGB byte source linked in the report. Done means webcam bytes can be used directly and the resulting image displays with correct colors without conversion to TYPE_INT_ARGB_PRE.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
computer-graphics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.