使用 Palette 提取图片调色板

        使用 Palette 支持包分析图片的像素数据,并为旨在补充此图片的背景和文本产生颜色样本。

        调色板仅作为 Android 支持库中的模块提供,它不是核心框架的一部分。然而,目标平台为 API Level 7或之后版本的任意应用程序都可以通过包含支持库使用调色板。可以把 V7 支持库中的关于 palette 的 jar 包拷贝到应用程序中的 libs 包下。

        效果如下:



item_list.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/root"
    android:padding="16dp">

    <ImageView
        android:id="@+id/image"
        android:scaleType="centerCrop"
        android:layout_width="match_parent"
        android:layout_height="102dp" />

    <TextView
        android:id="@+id/text"
        android:gravity="center"
        android:textAppearance="?android:textAppearanceLarge"
        android:layout_width="match_parent"
        android:layout_height="72dp" />

</LinearLayout>



ColorfulAdapter.java :

package com.crazy.colorfilters;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.AsyncTask;
import android.support.v7.graphics.Palette;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Created by antimage on 2015/12/27.
 */
public class ColorfulAdapter extends ArrayAdapter<String> {

    private static final int[] IMAGES = {
            R.drawable .bricks, R.drawable.flower, R.drawable.grass,
            R.drawable.stones, R.drawable.wood, R.drawable.dog
    };

    private static final String[] NAMES = {"砖", "花", "草", "石", "木", "狗"};

    private SparseArray<Bitmap> mImages;
    private SparseArray<Palette.Swatch> mBackgroundColors;

    public ColorfulAdapter(Context context) {
        super(context, R.layout.item_list, NAMES);
        mImages = new SparseArray<>(IMAGES.length);
        mBackgroundColors = new SparseArray<>(IMAGES.length);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext())
                    .inflate(R.layout.item_list, parent, false);
        }

        View root = convertView.findViewById(R.id.root);
        ImageView image = (ImageView)convertView.findViewById(R.id.image);
        TextView text = (TextView)convertView.findViewById(R.id.text);

        int imageId = IMAGES[position];
        if (mImages.get(imageId) == null) {
            new ImageTask().execute(imageId);
            text.setTextColor(Color.BLACK);
        } else {
            image.setImageBitmap(mImages.get(imageId));
            Palette.Swatch colors = mBackgroundColors.get(imageId);
            if (colors != null) {
                root.setBackgroundColor(colors.getRgb());
                text.setTextColor(colors.getTitleTextColor());
            }
        }
        text.setText(NAMES[position]);
        return convertView;
    }

    private class ImageResult {
        public int imageId;
        public Bitmap image;
        public Palette.Swatch colors;

        public ImageResult(int imageId, Bitmap image, Palette.Swatch colors) {
            this.imageId = imageId;
            this.image = image;
            this.colors = colors;
        }
    }

    private void updateImageItem(ImageResult result) {
        mImages.put(result.imageId, result.image);
        mBackgroundColors.put(result.imageId, result.colors);
    }

    private class ImageTask extends AsyncTask<Integer, Void, ImageResult> {

        @Override
        protected ImageResult doInBackground(Integer... params) {
            int imageId = params[0];
            // 确保图片缩略图不会太大
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = 4;
            Bitmap image = BitmapFactory.decodeResource(
                    getContext().getResources(), imageId, options);
            Palette colors = Palette.generate(image);
            Palette.Swatch selected = colors.getVibrantSwatch();
            if (selected == null) {
                selected = colors.getMutedSwatch();
            }
            return new ImageResult(imageId, image, selected);
        }

        @Override
        protected void onPostExecute(ImageResult result) {
            updateImageItem(result);
            notifyDataSetChanged();
        }
    }
}


        在适配器的 getView() 回调中,可以看到文本颜色和背景容器颜色都从 Palette.Swatch 中读取,Palette.Swatch 可能已经存在,也可能还不存在。

        因为从磁盘加载图片和使用 Palette 分析这些图片的过程会花费一些时间,所以我们要在后台执行此工作以避免阻塞主线程太长时间,所以将工作封装在 AsyncTask 中。

        后台加载的结果存储在一对 SparseArray 实例中。当适配器在没有产生结果的情况下遇到一个图片条目时,它会触发新的后台任务以加载内容。通过 BitmapFactory 解码图片之后,可以使用 Palette.Generate() 收集颜色方案数据,该方法将在分析图片时阻塞。

       如果在生成颜色方案时未准备好后台线程, Palette 的 generateAsync() 方法会接受回调。

       完成上述操作后,可以使用各种 getter 方法访问颜色样本。首先尝试使用 getVibrantSwatch() 获取 Vibrant 样本。如果图片颜色不兼容 Vibrant 颜色方案(即返回 null),我们就降低要求,获取一种颜色减弱的样本。

      

       解码的图片和选择的样本封装在持有者对象(ImageResult)中,这样有助于从 AsyncTask 返回多个条目,AsyncTask 仅支持返回单个类型。




ColorfulListActivity.java :

package com.crazy.colorfilters;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.widget.GridView;


public class ColorfulListActivity extends ActionBarActivity {

    private GridView mGridView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mGridView = new GridView(this);
        mGridView.setNumColumns(2);
        mGridView.setAdapter(new ColorfulAdapter(this));

        setContentView(mGridView);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基于Python和OpenCV库的获取图片调色板的代码示例: ```python import cv2 # 载入图像 img = cv2.imread('image.jpg') # 转换成HSV颜色空间 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 计算直方图 hist = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256]) # 归一化直方图 cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX) # 创建一个空白图像 h, w = img.shape[:2] palette = np.zeros((h, w, 3), dtype=np.uint8) # 遍历每一个像素 for i in range(h): for j in range(w): # 取得当前像素的HSV值 h, s, v = hsv[i, j] # 计算像素在直方图中的位置 bin_h = int(h * 180 / 256) bin_s = int(s * 256 / 256) # 取得直方图中对应位置的值 value = int(hist[bin_h, bin_s]) # 将值作为像素的RGB值 palette[i, j] = (value, value, value) # 显示调色板图像 cv2.imshow('palette', palette) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在代码中,我们首先使用`cv2.imread()`函数加载需要获取调色板的图像。然后,我们将图像转换成HSV颜色空间,方便计算直方图。接下来,我们使用`cv2.calcHist()`函数计算直方图,并使用`cv2.normalize()`函数归一化直方图的值。然后,我们创建一个空白图像`palette`,遍历每一个像素,计算像素在直方图中的位置,并取得直方图中对应位置的值,将值作为像素的RGB值,最后将RGB值赋给`palette`图像中对应位置的像素。最后,使用`cv2.imshow()`函数将调色板图像显示出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值