这是一个非常好的问题。如果您查看
源代码,您可以看到不同的样本是从分析图像上的像素的HSL颜色配置文件中选择的,基于亮度、饱和度和种群(图像中由样本表示的像素数目)的目标范围。它使用加权平均计算,首选
亮度,然后是
饱和度,最后是
种群。
一般来说,鲜艳的颜色比柔和的颜色更饱和,深色更暗,而浅色更浅。您使用哪一种取决于您想要的整体效果。
克里斯·班恩斯
在他的博客中写道“ Vibrant和Dark Vibrant是开发人员主要使用的样式”,但实际上并不像那么简单。
我找到的一个例子是Google IO 2014中Romain Guy的示例应用中的applyPalette
方法,但代码假定各种色板已经被找到(可能是因为他在处理已知的图像)。
根据图像的不同,有些调色板类型可能无法被找到,因此务必在代码中考虑到这种可能性。
例如,您可以尝试按特定顺序从调色板中获取调色板,例如对于暗色主题,您可以尝试获取Vibrant Dark,然后是Muted Dark,最后回退到某个默认颜色。
如果您想要更可预测的东西,也可以像这样抓取最常出现的颜色:
public static Palette.Swatch getDominantSwatch(Palette palette) {
return Collections.max(palette.getSwatches(), new Comparator<Palette.Swatch>() {
@Override
public int compare(Palette.Swatch sw1, Palette.Swatch sw2) {
return Integer.compare(sw1.getPopulation(), sw2.getPopulation());
}
});
}
每个样本的HSL值也是可访问的,因此您可以编写类似的例程来选择最饱和的样本,例如不是主色的那个。
使用自定义目标
除了 Palette.Target
定义的 6 个目标外,我发现定义一些自定义目标也很有用,这些目标具有不同的权重、目标亮度和饱和度值,以增加找到有用颜色的几率。
例如,您可以要求 Palette 的量化器包含一个符合当前筛选条件的最主要颜色样本,其目标如下:
public static final Target DOMINANT;
static {
DOMINANT = new Target.Builder().setPopulationWeight(1f)
.setSaturationWeight(0f)
.setLightnessWeight(0f)
.setExclusive(false)
.build();
}
你可以获取一些有用的色块,它们将亮度放在比原始标准更高的优先级上,就像这样:
public static final Target DARK;
public static final Target LIGHT;
public static final Target NEUTRAL;
static {
DARK = new Target.Builder().setMinimumLightness(0f)
.setTargetLightness(0.26f)
.setMaximumLightness(0.5f)
.setMinimumSaturation(0.1f)
.setTargetSaturation(0.6f)
.setMaximumSaturation(1f)
.setPopulationWeight(0.18f)
.setSaturationWeight(0.22f)
.setLightnessWeight(0.60f)
.setExclusive(false)
.build();
LIGHT = new Target.Builder().setMinimumLightness(0.50f)
.setTargetLightness(0.74f)
.setMaximumLightness(1.0f)
.setMinimumSaturation(0.1f)
.setTargetSaturation(0.7f)
.setMaximumSaturation(1f)
.setPopulationWeight(0.18f)
.setSaturationWeight(0.22f)
.setLightnessWeight(0.60f)
.setExclusive(false)
.build();
NEUTRAL = new Target.Builder().setMinimumLightness(0.20f)
.setTargetLightness(0.5f)
.setMaximumLightness(0.8f)
.setMinimumSaturation(0.1f)
.setTargetSaturation(0.6f)
.setMaximumSaturation(1f)
.setPopulationWeight(0.18f)
.setSaturationWeight(0.22f)
.setLightnessWeight(0.60f)
.setExclusive(false)
.build();
}
当定制的目标生成后,您可以使用Palette.getSwatchForTarget访问找到的调色板,例如:
Palette.Swatch neutral = Palette.getSwatchForTarget(NEUTRAL);
请注意默认过滤器
默认情况下,
调色板
具有一个
Palette.Filter
,它拒绝非常接近黑色或白色的颜色,以及非常接近红色I线的颜色,我认为这是指对于红色色盲的人来说很难辨别的等时线颜色。
我的理论是,它拒绝接近白色和接近黑色的颜色,以帮助防止它们在饱和度高的情况下被选择为“饱和”颜色。
然而,该过滤器的结果是,如果图像完全由几乎白色和/或几乎黑色的像素组成,则找不到任何样本,并且倾向于避免选择具有粉红色调的颜色。
但是,可以使用
Palette.Builder.clearFilters()
删除此过滤器,并使用
Palette.Builder.addFilter()
添加自己的过滤器。
在我的代码中,如果第一次尝试没有返回任何样本,则选择进行第二次生成调色板。
Palette palette = new Palette.Builder(bitmap).addTarget(DOMINANT)
.addTarget(DARK)
.addTarget(LIGHT)
.addTarget(NEUTRAL)
.generate();
if(palette.getSwatches().isEmpty()) {
Log.v(TAG, "Getting alternate (UNFILTERED) palette.");
palette = new Palette.Builder(bitmap).addTarget(DOMINANT)
.addTarget(DARK)
.addTarget(LIGHT)
.addTarget(NEUTRAL)
.clearFilters() /// allow isBlack(), isWhite(), isNearRedILine()
.generate();
}
链接多个尝试可以在大多数情况下保留默认过滤器的有用性,但仍允许您查找默认完全拒绝的图像的色板。