diff --git a/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt b/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt index 2658b9470..d758c147c 100644 --- a/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt +++ b/app/src/main/java/io/legado/app/ui/config/ThemeConfigFragment.kt @@ -80,12 +80,38 @@ class ThemeConfigFragment : BasePreferenceFragment(), } findPreference(PreferKey.cAccent)?.let { it.onSaveColor = { color -> - false + val background = + getPrefInt(PreferKey.cBackground, getCompatColor(R.color.md_grey_100)) + val textColor = getCompatColor(R.color.tv_text_default) + when { + ColorUtils.getColorDifference(color, background) <= 60 -> { + toast("强调色不能和背景颜色相似") + true + } + ColorUtils.getColorDifference(color, textColor) <= 60 -> { + toast("强调色不能和文字颜色相似") + true + } + else -> false + } } } findPreference(PreferKey.cNAccent)?.let { it.onSaveColor = { color -> - false + val background = + getPrefInt(PreferKey.cNBackground, getCompatColor(R.color.md_grey_900)) + val textColor = getCompatColor(R.color.tv_text_default) + when { + ColorUtils.getColorDifference(color, background) <= 60 -> { + toast("强调色不能和背景颜色相似") + true + } + ColorUtils.getColorDifference(color, textColor) <= 60 -> { + toast("强调色不能和文字颜色相似") + true + } + else -> false + } } } } diff --git a/app/src/main/java/io/legado/app/utils/ColorUtils.kt b/app/src/main/java/io/legado/app/utils/ColorUtils.kt index d256f879f..8a9a35052 100644 --- a/app/src/main/java/io/legado/app/utils/ColorUtils.kt +++ b/app/src/main/java/io/legado/app/utils/ColorUtils.kt @@ -5,9 +5,7 @@ import android.graphics.Color import androidx.annotation.ColorInt import androidx.annotation.FloatRange import java.util.* -import kotlin.math.max -import kotlin.math.min -import kotlin.math.roundToInt +import kotlin.math.* @Suppress("unused") object ColorUtils { @@ -83,7 +81,6 @@ object ColorUtils { return Color.argb(a.toInt(), r.toInt(), g.toInt(), b.toInt()) } - /** * 按条件的到随机颜色 * @@ -161,4 +158,95 @@ object ColorUtils { } } + fun argb(R: Int, G: Int, B: Int): Int { + return argb(Byte.MAX_VALUE.toInt(), R, G, B) + } + + fun argb(A: Int, R: Int, G: Int, B: Int): Int { + val colorByteArr = + byteArrayOf(A.toByte(), R.toByte(), G.toByte(), B.toByte()) + return byteArrToInt(colorByteArr) + } + + fun rgb(argb: Int): IntArray? { + return intArrayOf(argb shr 16 and 0xFF, argb shr 8 and 0xFF, argb and 0xFF) + } + + fun byteArrToInt(colorByteArr: ByteArray): Int { + return ((colorByteArr[0].toInt() shl 24) + (colorByteArr[1].toInt() and 0xFF shl 16) + + (colorByteArr[2].toInt() and 0xFF shl 8) + (colorByteArr[3].toInt() and 0xFF)) + } + + fun rgb2lab(R: Int, G: Int, B: Int): IntArray { + val x: Float + val y: Float + val z: Float + val fx: Float + val fy: Float + val fz: Float + val xr: Float + val yr: Float + val zr: Float + val ls: Float + val `as`: Float + val bs: Float + val eps = 216f / 24389f + val k = 24389f / 27f + val xr1 = 0.964221f // reference white D50 + val yr1 = 1.0f + val zr1 = 0.825211f + + // RGB to XYZ + var r: Float = R / 255f //R 0..1 + var g: Float = G / 255f //G 0..1 + var b: Float = B / 255f //B 0..1 + + // assuming sRGB (D65) + r = if (r <= 0.04045) r / 12 else ((r + 0.055) / 1.055).pow(2.4).toFloat() + g = if (g <= 0.04045) g / 12 else ((g + 0.055) / 1.055).pow(2.4).toFloat() + b = if (b <= 0.04045) b / 12 else ((b + 0.055) / 1.055).pow(2.4).toFloat() + x = 0.436052025f * r + 0.385081593f * g + 0.143087414f * b + y = 0.222491598f * r + 0.71688606f * g + 0.060621486f * b + z = 0.013929122f * r + 0.097097002f * g + 0.71418547f * b + + // XYZ to Lab + xr = x / xr1 + yr = y / yr1 + zr = z / zr1 + fx = if (xr > eps) xr.toDouble().pow(1 / 3.0) + .toFloat() else ((k * xr + 16.0) / 116.0).toFloat() + fy = if (yr > eps) yr.toDouble().pow(1 / 3.0) + .toFloat() else ((k * yr + 16.0) / 116.0).toFloat() + fz = if (zr > eps) zr.toDouble().pow(1 / 3.0) + .toFloat() else ((k * zr + 16.0) / 116).toFloat() + ls = 116 * fy - 16 + `as` = 500 * (fx - fy) + bs = 200 * (fy - fz) + val lab = IntArray(3) + lab[0] = (2.55 * ls + .5).toInt() + lab[1] = (`as` + .5).toInt() + lab[2] = (bs + .5).toInt() + return lab + } + + /** + * Computes the difference between two RGB colors by converting them to the L*a*b scale and + * comparing them using the CIE76 algorithm { http://en.wikipedia.org/wiki/Color_difference#CIE76} + */ + fun getColorDifference(a: Int, b: Int): Double { + val r1: Int = Color.red(a) + val g1: Int = Color.green(a) + val b1: Int = Color.blue(a) + val r2: Int = Color.red(b) + val g2: Int = Color.green(b) + val b2: Int = Color.blue(b) + val lab1 = rgb2lab(r1, g1, b1) + val lab2 = rgb2lab(r2, g2, b2) + return sqrt( + (lab2[0] - lab1[0].toDouble()) + .pow(2.0) + (lab2[1] - lab1[1].toDouble()) + .pow(2.0) + (lab2[2] - lab1[2].toDouble()) + .pow(2.0) + ) + } }