Color science studies of color preference indicate universal distaste for dark yellow-greens, 25 | * and also show this is correlated to distate for biological waste and rotting food. 26 | * 27 | *
See Palmer and Schloss, 2010 or Schloss and Palmer's Chapter 21 in Handbook of Color 28 | * Psychology (2015). 29 | */ 30 | public final class DislikeAnalyzer { 31 | 32 | private DislikeAnalyzer() { 33 | throw new UnsupportedOperationException(); 34 | } 35 | 36 | /** 37 | * Returns true if color is disliked. 38 | * 39 | *
Disliked is defined as a dark yellow-green that is not neutral. 40 | */ 41 | public static boolean isDisliked(Hct hct) { 42 | final boolean huePasses = Math.round(hct.getHue()) >= 90.0 && Math.round(hct.getHue()) <= 111.0; 43 | final boolean chromaPasses = Math.round(hct.getChroma()) > 16.0; 44 | final boolean tonePasses = Math.round(hct.getTone()) < 65.0; 45 | 46 | return huePasses && chromaPasses && tonePasses; 47 | } 48 | 49 | /** If color is disliked, lighten it to make it likable. */ 50 | public static Hct fixIfDisliked(Hct hct) { 51 | if (isDisliked(hct)) { 52 | return Hct.from(hct.getHue(), hct.getChroma(), 70.0); 53 | } 54 | 55 | return hct; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /m3utils/src/main/java/dynamiccolor/TonePolarity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 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 dynamiccolor; 18 | 19 | /** 20 | * Describes the relationship in lightness between two colors. 21 | * 22 | *
'nearer' and 'farther' describes closeness to the surface roles. For instance, 23 | * ToneDeltaPair(A, B, 10, 'nearer', stayTogether) states that A should be 10 lighter than B in 24 | * light mode, and 10 darker than B in dark mode. 25 | * 26 | *
See `ToneDeltaPair` for details. 27 | */ 28 | public enum TonePolarity { 29 | DARKER, 30 | LIGHTER, 31 | NEARER, 32 | FARTHER; 33 | } 34 | -------------------------------------------------------------------------------- /m3utils/src/main/java/palettes/CorePalette.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 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 palettes; 18 | 19 | import static java.lang.Math.max; 20 | import static java.lang.Math.min; 21 | 22 | import hct.Hct; 23 | 24 | /** 25 | * An intermediate concept between the key color for a UI theme, and a full color scheme. 5 sets of 26 | * tones are generated, all except one use the same hue as the key color, and all vary in chroma. 27 | */ 28 | public final class CorePalette { 29 | public TonalPalette a1; 30 | public TonalPalette a2; 31 | public TonalPalette a3; 32 | public TonalPalette n1; 33 | public TonalPalette n2; 34 | public TonalPalette error; 35 | 36 | /** 37 | * Create key tones from a color. 38 | * 39 | * @param argb ARGB representation of a color 40 | */ 41 | public static CorePalette of(int argb) { 42 | return new CorePalette(argb, false); 43 | } 44 | 45 | /** 46 | * Create content key tones from a color. 47 | * 48 | * @param argb ARGB representation of a color 49 | */ 50 | public static CorePalette contentOf(int argb) { 51 | return new CorePalette(argb, true); 52 | } 53 | 54 | private CorePalette(int argb, boolean isContent) { 55 | Hct hct = Hct.fromInt(argb); 56 | double hue = hct.getHue(); 57 | double chroma = hct.getChroma(); 58 | if (isContent) { 59 | this.a1 = TonalPalette.fromHueAndChroma(hue, chroma); 60 | this.a2 = TonalPalette.fromHueAndChroma(hue, chroma / 3.); 61 | this.a3 = TonalPalette.fromHueAndChroma(hue + 60., chroma / 2.); 62 | this.n1 = TonalPalette.fromHueAndChroma(hue, min(chroma / 12., 4.)); 63 | this.n2 = TonalPalette.fromHueAndChroma(hue, min(chroma / 6., 8.)); 64 | } else { 65 | this.a1 = TonalPalette.fromHueAndChroma(hue, max(48., chroma)); 66 | this.a2 = TonalPalette.fromHueAndChroma(hue, 16.); 67 | this.a3 = TonalPalette.fromHueAndChroma(hue + 60., 24.); 68 | this.n1 = TonalPalette.fromHueAndChroma(hue, 4.); 69 | this.n2 = TonalPalette.fromHueAndChroma(hue, 8.); 70 | } 71 | this.error = TonalPalette.fromHueAndChroma(25, 84.); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /m3utils/src/main/java/quantize/PointProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 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 quantize; 18 | 19 | /** An interface to allow use of different color spaces by quantizers. */ 20 | public interface PointProvider { 21 | /** The four components in the color space of an sRGB color. */ 22 | public double[] fromInt(int argb); 23 | 24 | /** The ARGB (i.e. hex code) representation of this color. */ 25 | public int toInt(double[] point); 26 | 27 | /** 28 | * Squared distance between two colors. Distance is defined by scientific color spaces and 29 | * referred to as delta E. 30 | */ 31 | public double distance(double[] a, double[] b); 32 | } 33 | -------------------------------------------------------------------------------- /m3utils/src/main/java/quantize/PointProviderLab.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 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 quantize; 18 | 19 | import utils.ColorUtils; 20 | 21 | /** 22 | * Provides conversions needed for K-Means quantization. Converting input to points, and converting 23 | * the final state of the K-Means algorithm to colors. 24 | */ 25 | public final class PointProviderLab implements PointProvider { 26 | /** 27 | * Convert a color represented in ARGB to a 3-element array of L*a*b* coordinates of the color. 28 | */ 29 | @Override 30 | public double[] fromInt(int argb) { 31 | double[] lab = ColorUtils.labFromArgb(argb); 32 | return new double[] {lab[0], lab[1], lab[2]}; 33 | } 34 | 35 | /** Convert a 3-element array to a color represented in ARGB. */ 36 | @Override 37 | public int toInt(double[] lab) { 38 | return ColorUtils.argbFromLab(lab[0], lab[1], lab[2]); 39 | } 40 | 41 | /** 42 | * Standard CIE 1976 delta E formula also takes the square root, unneeded here. This method is 43 | * used by quantization algorithms to compare distance, and the relative ordering is the same, 44 | * with or without a square root. 45 | * 46 | *
This relatively minor optimization is helpful because this method is called at least once 47 | * for each pixel in an image. 48 | */ 49 | @Override 50 | public double distance(double[] one, double[] two) { 51 | double dL = (one[0] - two[0]); 52 | double dA = (one[1] - two[1]); 53 | double dB = (one[2] - two[2]); 54 | return (dL * dL + dA * dA + dB * dB); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /m3utils/src/main/java/quantize/Quantizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 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 quantize; 18 | 19 | interface Quantizer { 20 | public QuantizerResult quantize(int[] pixels, int maxColors); 21 | } 22 | -------------------------------------------------------------------------------- /m3utils/src/main/java/quantize/QuantizerCelebi.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 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 quantize; 18 | 19 | import java.util.Map; 20 | import java.util.Set; 21 | 22 | /** 23 | * An image quantizer that improves on the quality of a standard K-Means algorithm by setting the 24 | * K-Means initial state to the output of a Wu quantizer, instead of random centroids. Improves on 25 | * speed by several optimizations, as implemented in Wsmeans, or Weighted Square Means, K-Means with 26 | * those optimizations. 27 | * 28 | *
This algorithm was designed by M. Emre Celebi, and was found in their 2011 paper, Improving
29 | * the Performance of K-Means for Color Quantization. https://arxiv.org/abs/1101.0395
30 | */
31 | public final class QuantizerCelebi {
32 | private QuantizerCelebi() {}
33 |
34 | /**
35 | * Reduce the number of colors needed to represented the input, minimizing the difference between
36 | * the original image and the recolored image.
37 | *
38 | * @param pixels Colors in ARGB format.
39 | * @param maxColors The number of colors to divide the image into. A lower number of colors may be
40 | * returned.
41 | * @return Map with keys of colors in ARGB format, and values of number of pixels in the original
42 | * image that correspond to the color in the quantized image.
43 | */
44 | public static Map Primary Container is the source color, adjusted for color relativity. It maintains constant
30 | * appearance in light mode and dark mode. This adds ~5 tone in light mode, and subtracts ~5 tone in
31 | * dark mode.
32 | *
33 | * Tertiary Container is an analogous color, specifically, the analog of a color wheel divided
34 | * into 6, and the precise analog is the one found by increasing hue. This is a scientifically
35 | * grounded equivalent to rotating hue clockwise by 60 degrees. It also maintains constant
36 | * appearance.
37 | */
38 | public class SchemeContent extends DynamicScheme {
39 | public SchemeContent(Hct sourceColorHct, boolean isDark, double contrastLevel) {
40 | super(
41 | sourceColorHct,
42 | Variant.CONTENT,
43 | isDark,
44 | contrastLevel,
45 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), sourceColorHct.getChroma()),
46 | TonalPalette.fromHueAndChroma(
47 | sourceColorHct.getHue(),
48 | max(sourceColorHct.getChroma() - 32.0, sourceColorHct.getChroma() * 0.5)),
49 | TonalPalette.fromHct(
50 | DislikeAnalyzer.fixIfDisliked(
51 | new TemperatureCache(sourceColorHct)
52 | .getAnalogousColors(/* count= */ 3, /* divisions= */ 6)
53 | .get(2))),
54 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), sourceColorHct.getChroma() / 8.0),
55 | TonalPalette.fromHueAndChroma(
56 | sourceColorHct.getHue(), (sourceColorHct.getChroma() / 8.0) + 4.0));
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/m3utils/src/main/java/scheme/SchemeExpressive.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 Google LLC
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 scheme;
18 |
19 | import hct.Hct;
20 | import palettes.TonalPalette;
21 | import utils.MathUtils;
22 |
23 | /** A playful theme - the source color's hue does not appear in the theme. */
24 | public class SchemeExpressive extends DynamicScheme {
25 | // NOMUTANTS--arbitrary increments/decrements, correctly, still passes tests.
26 | private static final double[] HUES = {0, 21, 51, 121, 151, 191, 271, 321, 360};
27 | private static final double[] SECONDARY_ROTATIONS = {45, 95, 45, 20, 45, 90, 45, 45, 45};
28 | private static final double[] TERTIARY_ROTATIONS = {120, 120, 20, 45, 20, 15, 20, 120, 120};
29 |
30 | public SchemeExpressive(Hct sourceColorHct, boolean isDark, double contrastLevel) {
31 | super(
32 | sourceColorHct,
33 | Variant.EXPRESSIVE,
34 | isDark,
35 | contrastLevel,
36 | TonalPalette.fromHueAndChroma(
37 | MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 240.0), 40.0),
38 | TonalPalette.fromHueAndChroma(
39 | DynamicScheme.getRotatedHue(sourceColorHct, HUES, SECONDARY_ROTATIONS), 24.0),
40 | TonalPalette.fromHueAndChroma(
41 | DynamicScheme.getRotatedHue(sourceColorHct, HUES, TERTIARY_ROTATIONS), 32.0),
42 | TonalPalette.fromHueAndChroma(
43 | MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 15.0), 8.0),
44 | TonalPalette.fromHueAndChroma(
45 | MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 15.0), 12.0));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/m3utils/src/main/java/scheme/SchemeFidelity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 Google LLC
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 scheme;
18 |
19 | import dislike.DislikeAnalyzer;
20 | import hct.Hct;
21 | import palettes.TonalPalette;
22 | import temperature.TemperatureCache;
23 |
24 | /**
25 | * A scheme that places the source color in Scheme.primaryContainer.
26 | *
27 | * Primary Container is the source color, adjusted for color relativity. It maintains constant
28 | * appearance in light mode and dark mode. This adds ~5 tone in light mode, and subtracts ~5 tone in
29 | * dark mode.
30 | *
31 | * Tertiary Container is the complement to the source color, using TemperatureCache. It also
32 | * maintains constant appearance.
33 | */
34 | public class SchemeFidelity extends DynamicScheme {
35 | public SchemeFidelity(Hct sourceColorHct, boolean isDark, double contrastLevel) {
36 | super(
37 | sourceColorHct,
38 | Variant.FIDELITY,
39 | isDark,
40 | contrastLevel,
41 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), sourceColorHct.getChroma()),
42 | TonalPalette.fromHueAndChroma(
43 | sourceColorHct.getHue(),
44 | Math.max(sourceColorHct.getChroma() - 32.0, sourceColorHct.getChroma() * 0.5)),
45 | TonalPalette.fromHct(
46 | DislikeAnalyzer.fixIfDisliked(new TemperatureCache(sourceColorHct).getComplement())),
47 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), sourceColorHct.getChroma() / 8.0),
48 | TonalPalette.fromHueAndChroma(
49 | sourceColorHct.getHue(), (sourceColorHct.getChroma() / 8.0) + 4.0));
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/m3utils/src/main/java/scheme/SchemeFruitSalad.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Google LLC
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 | package scheme;
17 |
18 | import hct.Hct;
19 | import palettes.TonalPalette;
20 | import utils.MathUtils;
21 |
22 | /** A playful theme - the source color's hue does not appear in the theme. */
23 | public class SchemeFruitSalad extends DynamicScheme {
24 | public SchemeFruitSalad(Hct sourceColorHct, boolean isDark, double contrastLevel) {
25 | super(
26 | sourceColorHct,
27 | Variant.FRUIT_SALAD,
28 | isDark,
29 | contrastLevel,
30 | TonalPalette.fromHueAndChroma(
31 | MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() - 50.0), 48.0),
32 | TonalPalette.fromHueAndChroma(
33 | MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() - 50.0), 36.0),
34 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 36.0),
35 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 10.0),
36 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 16.0));
37 | }
38 | }
--------------------------------------------------------------------------------
/m3utils/src/main/java/scheme/SchemeMonochrome.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 Google LLC
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 scheme;
18 |
19 | import hct.Hct;
20 | import palettes.TonalPalette;
21 |
22 | /** A monochrome theme, colors are purely black / white / gray. */
23 | public class SchemeMonochrome extends DynamicScheme {
24 | public SchemeMonochrome(Hct sourceColorHct, boolean isDark, double contrastLevel) {
25 | super(
26 | sourceColorHct,
27 | Variant.MONOCHROME,
28 | isDark,
29 | contrastLevel,
30 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
31 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
32 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
33 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
34 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/m3utils/src/main/java/scheme/SchemeNeutral.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 Google LLC
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 | package scheme;
17 |
18 | import hct.Hct;
19 | import palettes.TonalPalette;
20 |
21 | /** A theme that's slightly more chromatic than monochrome, which is purely black / white / gray. */
22 | public class SchemeNeutral extends DynamicScheme {
23 | public SchemeNeutral(Hct sourceColorHct, boolean isDark, double contrastLevel) {
24 | super(
25 | sourceColorHct,
26 | Variant.NEUTRAL,
27 | isDark,
28 | contrastLevel,
29 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 12.0),
30 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 8.0),
31 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 16.0),
32 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 2.0),
33 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 2.0));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/m3utils/src/main/java/scheme/SchemeRainbow.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2023 Google LLC
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 | package scheme;
17 |
18 | import hct.Hct;
19 | import palettes.TonalPalette;
20 | import utils.MathUtils;
21 |
22 | /** A playful theme - the source color's hue does not appear in the theme. */
23 | public class SchemeRainbow extends DynamicScheme {
24 | public SchemeRainbow(Hct sourceColorHct, boolean isDark, double contrastLevel) {
25 | super(
26 | sourceColorHct,
27 | Variant.RAINBOW,
28 | isDark,
29 | contrastLevel,
30 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 48.0),
31 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 16.0),
32 | TonalPalette.fromHueAndChroma(
33 | MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 60.0), 24.0),
34 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0),
35 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 0.0));
36 | }
37 | }
--------------------------------------------------------------------------------
/m3utils/src/main/java/scheme/SchemeTonalSpot.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 Google LLC
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 | package scheme;
17 |
18 | import hct.Hct;
19 | import palettes.TonalPalette;
20 | import utils.MathUtils;
21 |
22 | /** A calm theme, sedated colors that aren't particularly chromatic. */
23 | public class SchemeTonalSpot extends DynamicScheme {
24 | public SchemeTonalSpot(Hct sourceColorHct, boolean isDark, double contrastLevel) {
25 | super(
26 | sourceColorHct,
27 | Variant.TONAL_SPOT,
28 | isDark,
29 | contrastLevel,
30 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 36.0),
31 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 16.0),
32 | TonalPalette.fromHueAndChroma(
33 | MathUtils.sanitizeDegreesDouble(sourceColorHct.getHue() + 60.0), 24.0),
34 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 6.0),
35 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 8.0));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/m3utils/src/main/java/scheme/SchemeVibrant.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 Google LLC
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 | package scheme;
17 |
18 | import hct.Hct;
19 | import palettes.TonalPalette;
20 |
21 | /** A loud theme, colorfulness is maximum for Primary palette, increased for others. */
22 | public class SchemeVibrant extends DynamicScheme {
23 | private static final double[] HUES = {0, 41, 61, 101, 131, 181, 251, 301, 360};
24 | private static final double[] SECONDARY_ROTATIONS = {18, 15, 10, 12, 15, 18, 15, 12, 12};
25 | private static final double[] TERTIARY_ROTATIONS = {35, 30, 20, 25, 30, 35, 30, 25, 25};
26 |
27 | public SchemeVibrant(Hct sourceColorHct, boolean isDark, double contrastLevel) {
28 | super(
29 | sourceColorHct,
30 | Variant.VIBRANT,
31 | isDark,
32 | contrastLevel,
33 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 200.0),
34 | TonalPalette.fromHueAndChroma(
35 | DynamicScheme.getRotatedHue(sourceColorHct, HUES, SECONDARY_ROTATIONS), 24.0),
36 | TonalPalette.fromHueAndChroma(
37 | DynamicScheme.getRotatedHue(sourceColorHct, HUES, TERTIARY_ROTATIONS), 32.0),
38 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 10.0),
39 | TonalPalette.fromHueAndChroma(sourceColorHct.getHue(), 12.0));
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/m3utils/src/main/java/scheme/Variant.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2022 Google LLC
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 | package scheme;
17 |
18 | /** Themes for Dynamic Color. */
19 | public enum Variant {
20 | MONOCHROME,
21 | NEUTRAL,
22 | TONAL_SPOT,
23 | VIBRANT,
24 | EXPRESSIVE,
25 | FIDELITY,
26 | CONTENT,
27 | RAINBOW,
28 | FRUIT_SALAD
29 | }
30 |
--------------------------------------------------------------------------------
/m3utils/src/main/java/utils/StringUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 Google LLC
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 utils;
18 |
19 | /** Utility methods for string representations of colors. */
20 | final class StringUtils {
21 | private StringUtils() {}
22 |
23 | /**
24 | * Hex string representing color, ex. #ff0000 for red.
25 | *
26 | * @param argb ARGB representation of a color.
27 | */
28 | public static String hexFromArgb(int argb) {
29 | int red = ColorUtils.redFromArgb(argb);
30 | int blue = ColorUtils.blueFromArgb(argb);
31 | int green = ColorUtils.greenFromArgb(argb);
32 | return String.format("#%02x%02x%02x", red, green, blue);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/privacy-policy.md:
--------------------------------------------------------------------------------
1 |
2 | # Privacy Policy
3 |
4 | **General**
5 | Zen Music Player is developed and maintained by only one developer.
6 | This Privacy Policy aims to describe how information obtained from users is collected, used and disclosed.
7 | By using Zen, you agree that your personal information will be handled as described in this Policy.
8 |
9 | **Information being collected**
10 | For better user experience, Zen collects log data in cases of error or app crashes and reports them automatically (**Users can opt out of automatic reporting from app's settings**).
11 | Log data may include information such as the brand and model of device used, the operating system version and other statistics.
12 | Zen uses Firebase Crashlytics for enabling the log reporting service. Read about it [here](https://firebase.google.com/support/privacy) and [here](https://firebase.google.com/terms/crashlytics-app-distribution-data-processing-terms).
13 |
14 | **How is the information used**
15 | The reported log data is used to fix bugs or any other technical issues that may occur and improve Zen.
16 |
17 | **Disclosure of your information**
18 | We do not sell, trade, or otherwise transfer your information to outside parties. We may share your information with trusted third-party service providers such as Firebase Crashlytics.
19 |
20 | **Your Choices**
21 | You may opt out of the automatic reporting of crash logs data through Firebase Crashlytics by disabling the feature in the app's settings.
22 | However, please note that this may impact our ability to provide certain features and services.
23 |
24 | **Changes to the Policy**
25 | If the Policy changes, the modification date below will be updated. The Policy may change from time to time, so please be sure to check back periodically.
26 |
27 | **Last modified: 21 March, 2023**
28 |
29 | **Contact**
30 | If you have any questions about the Policy, please contact me via music.zen@outlook.com
--------------------------------------------------------------------------------
/screenshots/Dark/album_collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/album_collection.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/albums.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/albums.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/all_songs_default.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/all_songs_default.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/all_songs_elm.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/all_songs_elm.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/all_songs_jacksonspurple.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/all_songs_jacksonspurple.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/all_songs_magenta.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/all_songs_magenta.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/all_songs_malibu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/all_songs_malibu.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/all_songs_melrose.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/all_songs_melrose.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/artists.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/artists.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/genres.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/genres.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/now_playing_magenta.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/now_playing_magenta.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/now_playing_malibu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/now_playing_malibu.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/now_playing_melrose.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/now_playing_melrose.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/playlists.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/playlists.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/search.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/search.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/storage_access.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/storage_access.jpg
--------------------------------------------------------------------------------
/screenshots/Dark/storage_scan.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Dark/storage_scan.jpg
--------------------------------------------------------------------------------
/screenshots/Light/album_collection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/album_collection.jpg
--------------------------------------------------------------------------------
/screenshots/Light/albums.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/albums.jpg
--------------------------------------------------------------------------------
/screenshots/Light/all_songs_default.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/all_songs_default.jpg
--------------------------------------------------------------------------------
/screenshots/Light/all_songs_elm.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/all_songs_elm.jpg
--------------------------------------------------------------------------------
/screenshots/Light/all_songs_jacksonspurple.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/all_songs_jacksonspurple.jpg
--------------------------------------------------------------------------------
/screenshots/Light/all_songs_magenta.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/all_songs_magenta.jpg
--------------------------------------------------------------------------------
/screenshots/Light/all_songs_malibu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/all_songs_malibu.jpg
--------------------------------------------------------------------------------
/screenshots/Light/all_songs_melrose.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/all_songs_melrose.jpg
--------------------------------------------------------------------------------
/screenshots/Light/artists.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/artists.jpg
--------------------------------------------------------------------------------
/screenshots/Light/genres.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/genres.jpg
--------------------------------------------------------------------------------
/screenshots/Light/now_playing_magenta.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/now_playing_magenta.jpg
--------------------------------------------------------------------------------
/screenshots/Light/now_playing_malibu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/now_playing_malibu.jpg
--------------------------------------------------------------------------------
/screenshots/Light/now_playing_melrose.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/now_playing_melrose.jpg
--------------------------------------------------------------------------------
/screenshots/Light/playlists.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/playlists.jpg
--------------------------------------------------------------------------------
/screenshots/Light/search.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/search.jpg
--------------------------------------------------------------------------------
/screenshots/Light/storage_access.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/storage_access.jpg
--------------------------------------------------------------------------------
/screenshots/Light/storage_scan.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/Light/storage_scan.jpg
--------------------------------------------------------------------------------
/screenshots/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pakka-papad/Zen/3111a3b1db486e80cb11a96a65c8f9ab9b850ecb/screenshots/banner.png
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | }
15 | rootProject.name = "Zen"
16 | include (":app")
17 | include(":m3utils")
18 |
--------------------------------------------------------------------------------