Created
October 21, 2020 09:37
-
-
Save nadar71/626a9261b904b5a99285277d3d74e24d to your computer and use it in GitHub Desktop.
From Argb to CIE XY and viceversa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.graphics.Color | |
import android.os.Build | |
import android.util.Log | |
import androidx.annotation.ColorInt | |
import it.diceworld.dicehome.utility.common.extensions.round | |
import kotlin.math.pow | |
class ColorConverter { | |
companion object { | |
val TAG = ColorConverter::class.java.simpleName | |
// --------------------------------------------------------------------------------------------- | |
// From Argb to hex | |
// Convert from ARGB to color rgb lamp format 0x1234#0xabdf# for cloud | |
fun fromARGBtoCloud(@ColorInt color: Int):String{ | |
return fromCIEXYtoHexString(fromArgbToCIEXY(color)) | |
} | |
// convert from argb to CIE XY 1931 (bidimensional version for CIE XYZ 1931) | |
// specific for hue philips, works with good aproximation for ours lamp too : | |
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d | |
// https://github.com/johnciech/PhilipsHueSDK/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md | |
fun fromArgbToCIEXY(@ColorInt color: Int): DoubleArray{ | |
// val resultArray = DoubleArray(3) | |
// get r,g,b component | |
val red = Color.red(color) | |
val green = Color.green(color) | |
val blue = Color.blue(color) | |
val redN = if (red > 0.04045) ((red + 0.055) / (1.0 + 0.055)).pow(2.4) else red / 12.92 | |
val greenN = if (green > 0.04045) ((green + 0.055) / (1.0 + 0.055)).pow(2.4) else green / 12.92 | |
val blueN = if (blue > 0.04045) ((blue + 0.055) / (1.0 + 0.055)).pow(2.4) else blue / 12.92 | |
val xAxis = (0.649926 * redN) + (0.103455 * greenN) + (0.197109 * blueN) | |
val yAxis = (0.234327 * redN) + (0.743075 * greenN) + (0.022598 * blueN) | |
val zAxis = (0.0000000 * redN) + (0.053077 * greenN) + (1.035763 * blueN) | |
val xValue = (xAxis / (xAxis + yAxis + zAxis)).round(4) | |
val yValue = (yAxis / (xAxis + yAxis + zAxis)).round(4) | |
return doubleArrayOf(xValue,yValue) | |
} | |
// convert from CIE XY 1931 (bidimensional version for CIE XYZ 1931) to hex string format | |
// 0x1234#0xabdf# suitable for cloud to changing rgb lamp color | |
fun fromCIEXYtoHexString(input: DoubleArray):String{ | |
val result = StringBuilder() | |
for(number in input){ | |
// convert to int | |
val toBeHexConverted = (Math.floor(number * 65536)).toInt() | |
result.append("0x${toBeHexConverted.toString(16)}#") | |
} | |
return result.toString() | |
} | |
// --------------------------------------------------------------------------------------------- | |
// From hex to Argb | |
// Convert from color rgb lamp format 0x1234, 0xabdf for command to ARGB | |
fun fromCloudtoARGB(colorCloud: String, brightness: Double ): Int { | |
return fromCIEXYToArgb(fromHexStringToCIEXY(colorCloud),brightness) | |
} | |
// convert from hex string format 0x1234, 0xabdf suitable for cloud | |
// to CIE XY 1931 (bidimensional version for CIE XYZ 1931) | |
fun fromHexStringToCIEXY(colorCloud: String):DoubleArray{ | |
val resDouble = DoubleArray(2) | |
val colorSeq = colorCloud.replace("0x", "") | |
.replace("\\s".toRegex(), "") | |
.split("#") | |
.filterNot { it.isEmpty() } | |
for( i in colorSeq.indices){ | |
resDouble[i] = colorSeq[i].toInt(16).toDouble() | |
resDouble[i] = (Math.floor(resDouble[i]/65536)) | |
resDouble[i].round(4) | |
} | |
return resDouble | |
} | |
// convert from CIE XY 1931 (bidimensional version for CIE XYZ 1931) to argb | |
// specific for hue philips, works with good aproximation for ours lamp too : | |
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d | |
// https://github.com/johnciech/PhilipsHueSDK/blob/master/ApplicationDesignNotes/RGB%20to%20xy%20Color%20conversion.md | |
fun fromCIEXYToArgb(cieXY :DoubleArray, brightness: Double) : Int { | |
var resultArgb: Int | |
val normalizedBrightness = brightness/100 | |
val xValue = cieXY[0] | |
val yValue = cieXY[1] | |
val zValue = 1.0 - xValue - yValue | |
val yAxis = normalizedBrightness | |
val xAxis = (yAxis / yValue) * xValue | |
val zAxis = (yAxis / yValue) * zValue | |
// sRGB D65 conversion | |
var red = (xAxis * 1.612) - (yAxis * 0.203) - (zAxis * 0.302) | |
var green = (-xAxis * 0.509) + (yAxis * 1.412) + (zAxis * 0.066) | |
var blue = (xAxis * 0.026) - (yAxis * 0.072) + (zAxis * 0.962) | |
if (red > blue && red > green && red > 1.0) { | |
// red is too big | |
green /= red | |
blue /= red | |
red = 1.0 | |
} else if (green > blue && green > red && green > 1.0) { | |
// green is too big | |
red /= green | |
blue /= green | |
green = 1.0 | |
} else if (blue > red && blue > green && blue > 1.0) { | |
// blue is too big | |
red /= blue | |
green /= blue | |
blue = 1.0 | |
} | |
// Apply gamma correction | |
red = if (red <= 0.0031308) 12.92 * red else (1.0 + 0.055) * red.pow((1.0 / 2.4)) - 0.055 | |
green = if (green <= 0.0031308) 12.92 * green else (1.0 + 0.055) * green.pow((1.0 / 2.4)) - 0.055 | |
blue = if (blue <= 0.0031308) 12.92 * blue else (1.0 + 0.055) * blue.pow((1.0 / 2.4)) - 0.055 | |
if (red > blue && red > green) { | |
// red is biggest | |
if (red > 1.0) { | |
green /= red | |
blue /= red | |
red = 1.0 | |
} | |
} else if (green > blue && green > red) { | |
// green is biggest | |
if (green > 1.0) { | |
red /= green | |
blue /= green | |
green = 1.0 | |
} | |
} else if (blue > red && blue > green) { | |
// blue is biggest | |
if (blue > 1.0) { | |
red /= blue | |
green /= blue | |
blue = 1.0 | |
} | |
} | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |
resultArgb = Color.argb(1.0f, red.toFloat(), green.toFloat(), blue.toFloat()) | |
} else { | |
resultArgb = ((1.0.toInt() and 0xff) shl 24) or | |
((red.toInt() and 0xff) shl 16) or | |
((green.toInt() and 0xff) shl 8) or | |
((blue.toInt() and 0xff)) | |
} | |
Log.i(Utility.TAG, "red: $red, green: $green, blue: $blue") | |
Log.i(Utility.TAG, "CIE1931 to RGB converted color: $resultArgb") | |
return resultArgb | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment