修改
为了更好地了解Android Palette课程,我决定制作一个简单的应用程序来测试它的一些功能 - 如果您有兴趣,可以在Play商店中找到该应用程序:https://play.google.com/store/apps/details?id=com.tonyw.sampleapps.palettecolorextraction。基本上它只有Palette类提取的图像和颜色(如下所述),您也可以添加自己的图像进行测试。您可以在Github上找到我的源代码:https://github.com/tony-w/PaletteColorExtraction
截图
原帖
有人可以使用Android's Palette class描述可以从位图中提取的颜色之间的差异吗?
只是柔和的色彩比鲜艳的色彩更暗淡吗?黑暗和光明应该分别更好地匹配棒棒糖的黑暗和轻质材料设计主题吗?
答案 0 :(得分:32)
这是一个非常好的问题。如果查看source code,您可以看到根据亮度,饱和度和总体的目标范围(图像中的像素数)分析图像上像素的HSL颜色配置文件,选择不同的样本由样本代表)。它使用加权平均计算,优先选择亮度,然后饱和度,然后人口。
一般来说,鲜艳的色彩比柔和的色彩更饱和,深色的色彩更暗,而浅色的色彩更浅。你使用哪一个取决于你想要的整体效果。
Chris Banes wrote in his blog“充满活力和黑暗的活力是开发人员将主要使用的”但实际上它并不那么简单。
我发现的一个示例是来自Google IO 2014的Romain Guy's sample app中的applyPalette
方法,尽管代码假定会找到各种样本(可能是因为他正在使用已知图像)。
根据图片的不同,可能无法找到某些样本类型,因此请务必在代码中考虑这种可能性。
例如,您可以尝试按特定顺序从调色板中获取色板,例如对于黑暗主题,你可能会尝试获得充满活力的黑暗,然后是柔和的黑暗,然后再回到默认颜色。
如果你想要一些更可预测的东西,也可以抓住最具代表性的颜色,如下所示:
public static Palette.Swatch getDominantSwatch(Palette palette) {
// find most-represented swatch based on population
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
有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();
}
在大多数情况下,链接尝试会保留默认过滤器的有用性,但仍允许您查找默认情况下完全拒绝的图像的样本。