@Test public void testMinAlphas() { for (TestEntry entry : sEntryList) { verifyMinAlpha("Black title", entry.rgb, entry.blackMinAlpha30, ColorUtils.calculateMinimumAlpha(Color.BLACK, entry.rgb, 3.0f)); verifyMinAlpha("Black body", entry.rgb, entry.blackMinAlpha45, ColorUtils.calculateMinimumAlpha(Color.BLACK, entry.rgb, 4.5f)); verifyMinAlpha("White title", entry.rgb, entry.whiteMinAlpha30, ColorUtils.calculateMinimumAlpha(Color.WHITE, entry.rgb, 3.0f)); verifyMinAlpha("White body", entry.rgb, entry.whiteMinAlpha45, ColorUtils.calculateMinimumAlpha(Color.WHITE, entry.rgb, 4.5f)); } }
public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background, float minContrastRatio) { if (Color.alpha(background) != 255) { throw new IllegalArgumentException("background can not be translucent: #" + Integer.toHexString(background)); } int testForeground = setAlphaComponent(foreground, 255); double testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { return -1; } int numIterations = 0; int minAlpha = 0; int maxAlpha = 255; while (numIterations <= MIN_ALPHA_SEARCH_MAX_ITERATIONS && (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) { final int testAlpha = (minAlpha + maxAlpha) / 2; testForeground = setAlphaComponent(foreground, testAlpha); testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { minAlpha = testAlpha; } else { maxAlpha = testAlpha; } numIterations++; } return maxAlpha; }
ColorUtils { public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background, float minContrastRatio) { if (Color.alpha(background) != 255) { throw new IllegalArgumentException("background can not be translucent: #" + Integer.toHexString(background)); } int testForeground = setAlphaComponent(foreground, 255); double testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { return -1; } int numIterations = 0; int minAlpha = 0; int maxAlpha = 255; while (numIterations <= MIN_ALPHA_SEARCH_MAX_ITERATIONS && (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) { final int testAlpha = (minAlpha + maxAlpha) / 2; testForeground = setAlphaComponent(foreground, testAlpha); testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { minAlpha = testAlpha; } else { maxAlpha = testAlpha; } numIterations++; } return maxAlpha; } }
ColorUtils { public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background, float minContrastRatio) { if (Color.alpha(background) != 255) { throw new IllegalArgumentException("background can not be translucent: #" + Integer.toHexString(background)); } int testForeground = setAlphaComponent(foreground, 255); double testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { return -1; } int numIterations = 0; int minAlpha = 0; int maxAlpha = 255; while (numIterations <= MIN_ALPHA_SEARCH_MAX_ITERATIONS && (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) { final int testAlpha = (minAlpha + maxAlpha) / 2; testForeground = setAlphaComponent(foreground, testAlpha); testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { minAlpha = testAlpha; } else { maxAlpha = testAlpha; } numIterations++; } return maxAlpha; } private  ColorUtils(); }
ColorUtils { public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background, float minContrastRatio) { if (Color.alpha(background) != 255) { throw new IllegalArgumentException("background can not be translucent: #" + Integer.toHexString(background)); } int testForeground = setAlphaComponent(foreground, 255); double testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { return -1; } int numIterations = 0; int minAlpha = 0; int maxAlpha = 255; while (numIterations <= MIN_ALPHA_SEARCH_MAX_ITERATIONS && (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) { final int testAlpha = (minAlpha + maxAlpha) / 2; testForeground = setAlphaComponent(foreground, testAlpha); testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { minAlpha = testAlpha; } else { maxAlpha = testAlpha; } numIterations++; } return maxAlpha; } private  ColorUtils(); static int compositeColors(@ColorInt int foreground, @ColorInt int background); @RequiresApi(26) @NonNull static Color compositeColors(@NonNull Color foreground, @NonNull Color background); @FloatRange(from = 0.0, to = 1.0) static double calculateLuminance(@ColorInt int color); static double calculateContrast(@ColorInt int foreground, @ColorInt int background); static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background,
            float minContrastRatio); static void RGBToHSL(@IntRange(from = 0x0, to = 0xFF) int r,
            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
            @NonNull float[] outHsl); static void colorToHSL(@ColorInt int color, @NonNull float[] outHsl); @ColorInt static int HSLToColor(@NonNull float[] hsl); @ColorInt static int setAlphaComponent(@ColorInt int color,
            @IntRange(from = 0x0, to = 0xFF) int alpha); static void colorToLAB(@ColorInt int color, @NonNull double[] outLab); static void RGBToLAB(@IntRange(from = 0x0, to = 0xFF) int r,
            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
            @NonNull double[] outLab); static void colorToXYZ(@ColorInt int color, @NonNull double[] outXyz); static void RGBToXYZ(@IntRange(from = 0x0, to = 0xFF) int r,
            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
            @NonNull double[] outXyz); static void XYZToLAB(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z,
            @NonNull double[] outLab); static void LABToXYZ(@FloatRange(from = 0f, to = 100) final double l,
            @FloatRange(from = -128, to = 127) final double a,
            @FloatRange(from = -128, to = 127) final double b,
            @NonNull double[] outXyz); @ColorInt static int XYZToColor(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z); @ColorInt static int LABToColor(@FloatRange(from = 0f, to = 100) final double l,
            @FloatRange(from = -128, to = 127) final double a,
            @FloatRange(from = -128, to = 127) final double b); static double distanceEuclidean(@NonNull double[] labX, @NonNull double[] labY); @ColorInt static int blendARGB(@ColorInt int color1, @ColorInt int color2,
            @FloatRange(from = 0.0, to = 1.0) float ratio); static void blendHSL(@NonNull float[] hsl1, @NonNull float[] hsl2,
            @FloatRange(from = 0.0, to = 1.0) float ratio, @NonNull float[] outResult); static void blendLAB(@NonNull double[] lab1, @NonNull double[] lab2,
            @FloatRange(from = 0.0, to = 1.0) double ratio, @NonNull double[] outResult); }
ColorUtils { public static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background, float minContrastRatio) { if (Color.alpha(background) != 255) { throw new IllegalArgumentException("background can not be translucent: #" + Integer.toHexString(background)); } int testForeground = setAlphaComponent(foreground, 255); double testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { return -1; } int numIterations = 0; int minAlpha = 0; int maxAlpha = 255; while (numIterations <= MIN_ALPHA_SEARCH_MAX_ITERATIONS && (maxAlpha - minAlpha) > MIN_ALPHA_SEARCH_PRECISION) { final int testAlpha = (minAlpha + maxAlpha) / 2; testForeground = setAlphaComponent(foreground, testAlpha); testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { minAlpha = testAlpha; } else { maxAlpha = testAlpha; } numIterations++; } return maxAlpha; } private  ColorUtils(); static int compositeColors(@ColorInt int foreground, @ColorInt int background); @RequiresApi(26) @NonNull static Color compositeColors(@NonNull Color foreground, @NonNull Color background); @FloatRange(from = 0.0, to = 1.0) static double calculateLuminance(@ColorInt int color); static double calculateContrast(@ColorInt int foreground, @ColorInt int background); static int calculateMinimumAlpha(@ColorInt int foreground, @ColorInt int background,
            float minContrastRatio); static void RGBToHSL(@IntRange(from = 0x0, to = 0xFF) int r,
            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
            @NonNull float[] outHsl); static void colorToHSL(@ColorInt int color, @NonNull float[] outHsl); @ColorInt static int HSLToColor(@NonNull float[] hsl); @ColorInt static int setAlphaComponent(@ColorInt int color,
            @IntRange(from = 0x0, to = 0xFF) int alpha); static void colorToLAB(@ColorInt int color, @NonNull double[] outLab); static void RGBToLAB(@IntRange(from = 0x0, to = 0xFF) int r,
            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
            @NonNull double[] outLab); static void colorToXYZ(@ColorInt int color, @NonNull double[] outXyz); static void RGBToXYZ(@IntRange(from = 0x0, to = 0xFF) int r,
            @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
            @NonNull double[] outXyz); static void XYZToLAB(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z,
            @NonNull double[] outLab); static void LABToXYZ(@FloatRange(from = 0f, to = 100) final double l,
            @FloatRange(from = -128, to = 127) final double a,
            @FloatRange(from = -128, to = 127) final double b,
            @NonNull double[] outXyz); @ColorInt static int XYZToColor(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
            @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z); @ColorInt static int LABToColor(@FloatRange(from = 0f, to = 100) final double l,
            @FloatRange(from = -128, to = 127) final double a,
            @FloatRange(from = -128, to = 127) final double b); static double distanceEuclidean(@NonNull double[] labX, @NonNull double[] labY); @ColorInt static int blendARGB(@ColorInt int color1, @ColorInt int color2,
            @FloatRange(from = 0.0, to = 1.0) float ratio); static void blendHSL(@NonNull float[] hsl1, @NonNull float[] hsl2,
            @FloatRange(from = 0.0, to = 1.0) float ratio, @NonNull float[] outResult); static void blendLAB(@NonNull double[] lab1, @NonNull double[] lab2,
            @FloatRange(from = 0.0, to = 1.0) double ratio, @NonNull double[] outResult);  }