Skip to content

Commit 8510596

Browse files
Material Design Teampaulfthomas
authored andcommitted
[M3][Color] Added the rest of the library for content color support.
PiperOrigin-RevId: 482801156
1 parent 4364c4f commit 8510596

File tree

12 files changed

+2084
-0
lines changed

12 files changed

+2084
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.color.utilities;
18+
19+
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20+
import static java.lang.Math.max;
21+
import static java.lang.Math.min;
22+
23+
import androidx.annotation.RestrictTo;
24+
25+
// TODO(b/254603377): Use copybara to release material color utilities library directly to github.
26+
/**
27+
* An intermediate concept between the key color for a UI theme, and a full color scheme. 5 sets of
28+
* tones are generated, all except one use the same hue as the key color, and all vary in chroma.
29+
*
30+
* @hide
31+
*/
32+
@RestrictTo(LIBRARY_GROUP)
33+
public final class CorePalette {
34+
public TonalPalette a1;
35+
public TonalPalette a2;
36+
public TonalPalette a3;
37+
public TonalPalette n1;
38+
public TonalPalette n2;
39+
public TonalPalette error;
40+
41+
/**
42+
* Create key tones from a color.
43+
*
44+
* @param argb ARGB representation of a color
45+
*/
46+
public static CorePalette of(int argb) {
47+
return new CorePalette(argb, false);
48+
}
49+
50+
/**
51+
* Create content key tones from a color.
52+
*
53+
* @param argb ARGB representation of a color
54+
*/
55+
public static CorePalette contentOf(int argb) {
56+
return new CorePalette(argb, true);
57+
}
58+
59+
private CorePalette(int argb, boolean isContent) {
60+
Hct hct = Hct.fromInt(argb);
61+
double hue = hct.getHue();
62+
double chroma = hct.getChroma();
63+
if (isContent) {
64+
this.a1 = TonalPalette.fromHueAndChroma(hue, chroma);
65+
this.a2 = TonalPalette.fromHueAndChroma(hue, chroma / 3.);
66+
this.a3 = TonalPalette.fromHueAndChroma(hue + 60., chroma / 2.);
67+
this.n1 = TonalPalette.fromHueAndChroma(hue, min(chroma / 12., 4.));
68+
this.n2 = TonalPalette.fromHueAndChroma(hue, min(chroma / 6., 8.));
69+
} else {
70+
this.a1 = TonalPalette.fromHueAndChroma(hue, max(48., chroma));
71+
this.a2 = TonalPalette.fromHueAndChroma(hue, 16.);
72+
this.a3 = TonalPalette.fromHueAndChroma(hue + 60., 24.);
73+
this.n1 = TonalPalette.fromHueAndChroma(hue, 4.);
74+
this.n2 = TonalPalette.fromHueAndChroma(hue, 8.);
75+
}
76+
this.error = TonalPalette.fromHueAndChroma(25, 84.);
77+
}
78+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.color.utilities;
18+
19+
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20+
21+
import androidx.annotation.RestrictTo;
22+
23+
// TODO(b/254603377): Use copybara to release material color utilities library directly to github.
24+
/**
25+
* An interface to allow use of different color spaces by quantizers.
26+
*
27+
* @hide
28+
*/
29+
@RestrictTo(LIBRARY_GROUP)
30+
public interface PointProvider {
31+
public double[] fromInt(int argb);
32+
33+
public int toInt(double[] point);
34+
35+
public double distance(double[] a, double[] b);
36+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.color.utilities;
18+
19+
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20+
21+
import androidx.annotation.RestrictTo;
22+
23+
// TODO(b/254603377): Use copybara to release material color utilities library directly to github.
24+
/**
25+
* Provides conversions needed for K-Means quantization. Converting input to points, and converting
26+
* the final state of the K-Means algorithm to colors.
27+
*
28+
* @hide
29+
*/
30+
@RestrictTo(LIBRARY_GROUP)
31+
public final class PointProviderLab implements PointProvider {
32+
/**
33+
* Convert a color represented in ARGB to a 3-element array of L*a*b* coordinates of the color.
34+
*/
35+
@Override
36+
public double[] fromInt(int argb) {
37+
double[] lab = ColorUtils.labFromArgb(argb);
38+
return new double[] {lab[0], lab[1], lab[2]};
39+
}
40+
41+
/** Convert a 3-element array to a color represented in ARGB. */
42+
@Override
43+
public int toInt(double[] lab) {
44+
return ColorUtils.argbFromLab(lab[0], lab[1], lab[2]);
45+
}
46+
47+
/**
48+
* Standard CIE 1976 delta E formula also takes the square root, unneeded here. This method is
49+
* used by quantization algorithms to compare distance, and the relative ordering is the same,
50+
* with or without a square root.
51+
*
52+
* <p>This relatively minor optimization is helpful because this method is called at least once
53+
* for each pixel in an image.
54+
*/
55+
@Override
56+
public double distance(double[] one, double[] two) {
57+
double dL = (one[0] - two[0]);
58+
double dA = (one[1] - two[1]);
59+
double dB = (one[2] - two[2]);
60+
return (dL * dL + dA * dA + dB * dB);
61+
}
62+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.color.utilities;
18+
19+
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20+
21+
import androidx.annotation.RestrictTo;
22+
23+
// TODO(b/254603377): Use copybara to release material color utilities library directly to github.
24+
/** @hide */
25+
@RestrictTo(LIBRARY_GROUP)
26+
interface Quantizer {
27+
public QuantizerResult quantize(int[] pixels, int maxColors);
28+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.color.utilities;
18+
19+
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20+
21+
import androidx.annotation.RestrictTo;
22+
import java.util.Map;
23+
import java.util.Set;
24+
25+
// TODO(b/254603377): Use copybara to release material color utilities library directly to github.
26+
/**
27+
* An image quantizer that improves on the quality of a standard K-Means algorithm by setting the
28+
* K-Means initial state to the output of a Wu quantizer, instead of random centroids. Improves on
29+
* speed by several optimizations, as implemented in Wsmeans, or Weighted Square Means, K-Means with
30+
* those optimizations.
31+
*
32+
* <p>This algorithm was designed by M. Emre Celebi, and was found in their 2011 paper, Improving
33+
* the Performance of K-Means for Color Quantization. https://arxiv.org/abs/1101.0395
34+
*
35+
* @hide
36+
*/
37+
@RestrictTo(LIBRARY_GROUP)
38+
public final class QuantizerCelebi {
39+
private QuantizerCelebi() {}
40+
41+
/**
42+
* Reduce the number of colors needed to represented the input, minimizing the difference between
43+
* the original image and the recolored image.
44+
*
45+
* @param pixels Colors in ARGB format.
46+
* @param maxColors The number of colors to divide the image into. A lower number of colors may be
47+
* returned.
48+
* @return Map with keys of colors in ARGB format, and values of number of pixels in the original
49+
* image that correspond to the color in the quantized image.
50+
*/
51+
public static Map<Integer, Integer> quantize(int[] pixels, int maxColors) {
52+
QuantizerWu wu = new QuantizerWu();
53+
QuantizerResult wuResult = wu.quantize(pixels, maxColors);
54+
55+
Set<Integer> wuClustersAsObjects = wuResult.colorToCount.keySet();
56+
int index = 0;
57+
int[] wuClusters = new int[wuClustersAsObjects.size()];
58+
for (Integer argb : wuClustersAsObjects) {
59+
wuClusters[index++] = argb;
60+
}
61+
62+
return QuantizerWsmeans.quantize(pixels, wuClusters, maxColors);
63+
}
64+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.color.utilities;
18+
19+
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20+
21+
import androidx.annotation.RestrictTo;
22+
import java.util.HashMap;
23+
import java.util.Map;
24+
25+
// TODO(b/254603377): Use copybara to release material color utilities library directly to github.
26+
/**
27+
* Creates a dictionary with keys of colors, and values of count of the color
28+
*
29+
* @hide
30+
*/
31+
@RestrictTo(LIBRARY_GROUP)
32+
public final class QuantizerMap implements Quantizer {
33+
Map<Integer, Integer> colorToCount;
34+
35+
@Override
36+
public QuantizerResult quantize(int[] pixels, int colorCount) {
37+
final HashMap<Integer, Integer> pixelByCount = new HashMap<>();
38+
for (int pixel : pixels) {
39+
final Integer currentPixelCount = pixelByCount.get(pixel);
40+
final int newPixelCount = currentPixelCount == null ? 1 : currentPixelCount + 1;
41+
pixelByCount.put(pixel, newPixelCount);
42+
}
43+
colorToCount = pixelByCount;
44+
return new QuantizerResult(pixelByCount);
45+
}
46+
47+
public Map<Integer, Integer> getColorToCount() {
48+
return colorToCount;
49+
}
50+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (C) 2022 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.material.color.utilities;
18+
19+
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
20+
21+
import androidx.annotation.RestrictTo;
22+
import java.util.Map;
23+
24+
// TODO(b/254603377): Use copybara to release material color utilities library directly to github.
25+
/**
26+
* Represents result of a quantizer run
27+
*
28+
* @hide
29+
*/
30+
@RestrictTo(LIBRARY_GROUP)
31+
public final class QuantizerResult {
32+
public final Map<Integer, Integer> colorToCount;
33+
34+
QuantizerResult(Map<Integer, Integer> colorToCount) {
35+
this.colorToCount = colorToCount;
36+
}
37+
}

0 commit comments

Comments
 (0)