<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Palette即調色盤這個功能其實很早就釋出了,Jetpack同樣將這個功能也納入其中,想要使用這個功能,需要先依賴庫
implementation 'androidx.palette:palette:1.0.0'
本篇文章就來講解一下如何使用Palette在圖片中提取顏色。
建立Palette其實很簡單,如下
var builder = Palette.from(bitmap) var palette = builder.generate()
這樣,我們就通過一個Bitmap建立一個Pallete物件。
注意:直接使用Palette.generate(bitmap)
也可以,但是這個方法已經不推薦使用了,網上很多老文章中依然使用這種方式。建議還是使用Palette.Builder這種方式。
generate()
這個函數是同步的,當然考慮圖片處理可能比較耗時,Android同時提供了非同步函數
public AsyncTask<Bitmap, Void, Palette> generate( @NonNull final PaletteAsyncListener listener) {
通過一個PaletteAsyncListener來獲取Palette範例,這個介面如下:
public interface PaletteAsyncListener { /** * Called when the {@link Palette} has been generated. {@code null} will be passed when an * error occurred during generation. */ void onGenerated(@Nullable Palette palette); }
有了Palette範例,就可以通過Palette物件的相應函數就可以獲取圖片中的顏色,而且不只一種顏色,下面一一列舉:
這些函數都需要提供一個預設顏色,如果這個顏色Swatch無效則使用這個預設顏色。光這麼說不直觀,我們來測試一下,程式碼如下:
var bitmap = BitmapFactory.decodeResource(resources, R.mipmap.a) var builder = Palette.from(bitmap) var palette = builder.generate() color0.setBackgroundColor(palette.getDominantColor(Color.WHITE)) color1.setBackgroundColor(palette.getMutedColor(Color.WHITE)) color2.setBackgroundColor(palette.getDarkMutedColor(Color.WHITE)) color3.setBackgroundColor(palette.getLightMutedColor(Color.WHITE)) color4.setBackgroundColor(palette.getVibrantColor(Color.WHITE)) color5.setBackgroundColor(palette.getDarkVibrantColor(Color.WHITE)) color6.setBackgroundColor(palette.getLightVibrantColor(Color.WHITE))
執行後結果如下:
這樣各個顏色的差別就一目瞭然。除了上面的函數,還可以使用getColorForTarget
這個函數,如下:
@ColorInt public int getColorForTarget(@NonNull final Target target, @ColorInt final int defaultColor) {
這個函數需要一個Target,提供了6個靜態欄位,如下:
/** * A target which has the characteristics of a vibrant color which is light in luminance. */ public static final Target LIGHT_VIBRANT; /** * A target which has the characteristics of a vibrant color which is neither light or dark. */ public static final Target VIBRANT; /** * A target which has the characteristics of a vibrant color which is dark in luminance. */ public static final Target DARK_VIBRANT; /** * A target which has the characteristics of a muted color which is light in luminance. */ public static final Target LIGHT_MUTED; /** * A target which has the characteristics of a muted color which is neither light or dark. */ public static final Target MUTED; /** * A target which has the characteristics of a muted color which is dark in luminance. */ public static final Target DARK_MUTED;
其實就是對應著上面除了主色調之外的六種顏色。
在上面的執行結果中可以看到,每個顏色上面的文字都很清楚的顯示,而且它們並不是同一種顏色。其實這也是Palette提供的功能。
通過下面的函數,我們可以得到各種色調所對應的Swatch物件:
注意:同上面一樣,也可以通過getSwatchForTarget(@NonNull final Target target)
來獲取
Swatch類提供了以下函數:
所以我們通過getBodyTextColor()
和getTitleTextColor()
可以很容易得到在這個顏色上可以很好現實的標題和主體文字顏色。所以上面的測試程式碼完整如下:
var bitmap = BitmapFactory.decodeResource(resources, R.mipmap.a) var builder = Palette.from(bitmap) var palette = builder.generate() color0.setBackgroundColor(palette.getDominantColor(Color.WHITE)) color0.setTextColor(palette.dominantSwatch?.bodyTextColor ?: Color.WHITE) color1.setBackgroundColor(palette.getMutedColor(Color.WHITE)) color1.setTextColor(palette.mutedSwatch?.bodyTextColor ?: Color.WHITE) color2.setBackgroundColor(palette.getDarkMutedColor(Color.WHITE)) color2.setTextColor(palette.darkMutedSwatch?.bodyTextColor ?: Color.WHITE) color3.setBackgroundColor(palette.getLightMutedColor(Color.WHITE)) color3.setTextColor(palette.lightMutedSwatch?.bodyTextColor ?: Color.WHITE) color4.setBackgroundColor(palette.getVibrantColor(Color.WHITE)) color4.setTextColor(palette.vibrantSwatch?.bodyTextColor ?: Color.WHITE) color5.setBackgroundColor(palette.getDarkVibrantColor(Color.WHITE)) color5.setTextColor(palette.darkVibrantSwatch?.bodyTextColor ?: Color.WHITE) color6.setBackgroundColor(palette.getLightVibrantColor(Color.WHITE)) color6.setTextColor(palette.lightVibrantSwatch?.bodyTextColor ?: Color.WHITE)
這樣每個顏色上的文字都可以清晰的顯示。
那麼這個標題和主體文字顏色有什麼差別,他們又是如何的到的?我們來看看原始碼:
/** * Returns an appropriate color to use for any 'title' text which is displayed over this * {@link Swatch}'s color. This color is guaranteed to have sufficient contrast. */ @ColorInt public int getTitleTextColor() { ensureTextColorsGenerated(); return mTitleTextColor; } /** * Returns an appropriate color to use for any 'body' text which is displayed over this * {@link Swatch}'s color. This color is guaranteed to have sufficient contrast. */ @ColorInt public int getBodyTextColor() { ensureTextColorsGenerated(); return mBodyTextColor; }
可以看到都會先執行ensureTextColorsGenerated()
,它的原始碼如下:
private void ensureTextColorsGenerated() { if (!mGeneratedTextColors) { // First check white, as most colors will be dark final int lightBodyAlpha = ColorUtils.calculateMinimumAlpha( Color.WHITE, mRgb, MIN_CONTRAST_BODY_TEXT); final int lightTitleAlpha = ColorUtils.calculateMinimumAlpha( Color.WHITE, mRgb, MIN_CONTRAST_TITLE_TEXT); if (lightBodyAlpha != -1 && lightTitleAlpha != -1) { // If we found valid light values, use them and return mBodyTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha); mTitleTextColor = ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha); mGeneratedTextColors = true; return; } final int darkBodyAlpha = ColorUtils.calculateMinimumAlpha( Color.BLACK, mRgb, MIN_CONTRAST_BODY_TEXT); final int darkTitleAlpha = ColorUtils.calculateMinimumAlpha( Color.BLACK, mRgb, MIN_CONTRAST_TITLE_TEXT); if (darkBodyAlpha != -1 && darkTitleAlpha != -1) { // If we found valid dark values, use them and return mBodyTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha); mTitleTextColor = ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha); mGeneratedTextColors = true; return; } // If we reach here then we can not find title and body values which use the same // lightness, we need to use mismatched values mBodyTextColor = lightBodyAlpha != -1 ? ColorUtils.setAlphaComponent(Color.WHITE, lightBodyAlpha) : ColorUtils.setAlphaComponent(Color.BLACK, darkBodyAlpha); mTitleTextColor = lightTitleAlpha != -1 ? ColorUtils.setAlphaComponent(Color.WHITE, lightTitleAlpha) : ColorUtils.setAlphaComponent(Color.BLACK, darkTitleAlpha); mGeneratedTextColors = true; } }
通過程式碼可以看到,這兩種文字顏色實際上要麼是白色要麼是黑色,只是透明度Alpha不同。
這裡面有一個關鍵函數,即ColorUtils.calculateMinimumAlpha()
:
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)); } // First lets check that a fully opaque foreground has sufficient contrast int testForeground = setAlphaComponent(foreground, 255); double testRatio = calculateContrast(testForeground, background); if (testRatio < minContrastRatio) { // Fully opaque foreground does not have sufficient contrast, return error return -1; } // Binary search to find a value with the minimum value which provides sufficient contrast 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++; } // Conservatively return the max of the range of possible alphas, which is known to pass. return maxAlpha; }
它根據背景色和前景色計算前景色最合適的Alpha。這期間如果小於minContrastRatio則返回-1,說明這個前景色不合適。而標題和主體文字的差別就是這個minContrastRatio不同而已。
回到ensureTextColorsGenerated
程式碼可以看到,先根據當前色調,計算出白色前景色的Alpha,如果兩個Alpha都不是-1,就返回對應顏色;否則計算黑色前景色的Alpha,如果都不是-1,返回對應顏色;否則標題和主體文字一個用白色一個用黑色,返回對應顏色即可。
上面我們建立Palette時先通過Palette.from(bitmap)
的到了一個Palette.Builder物件,通過這個builder可以實現更多功能,比如:
等等
通過上面我們看到,Palette的功能很強大,但是它使用起來非常簡單,可以讓我們很方便的提取圖片中的顏色,並且適配合適的文字顏色。同時注意因為ColorUtils是public的,所以當我們需要文字自動適配顏色的情況時,也可以通過ColorUtils的幾個函數自己實現計算動態顏色的方案。
以上就是Android利用Palette實現提取圖片顏色的詳細內容,更多關於Android Palette提取顏色的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45