Picasso 加载位图后,如何为它获取调色板?

How do I get a Palette for my bitmap once Picasso Loads it?

2014 年 10 月,杰克沃顿写道 Coercing Picasso to Play With Palette。里面有2个方法在琢磨:

  1. 使用生成调色板的转换。这样做的好处是调色板是在 Picasso 的工作线程上生成的,并且在加载图像时 ready。然而,缺点似乎是我得到的调色板与图片不匹配。目前我一次只 运行 这些转换中的一个。

  2. 使用 CallbackonSuccessImageView 获取位图并生成调色板。我忍不住关注 Jake 放在这一行末尾的 // Ew!,我非常同意。

上面提到的post写于2014年10月。现在我们已经讨论了几个月,我想知道推荐的方法是什么? 还有关于将 meta data 与位图相关联的讨论。那是实施了吗?我将如何使用它?

我的 Transformation 代码(不是最终的,我刚刚开始研究这个):

public final class PaletteGenerator
  implements Transformation {

    private final int numColors;
    @Getter private Palette palette;

    @Override public Bitmap transform (final Bitmap source) {
        palette = null;
        final Palette palette = numColors > 0
                                ? Palette.generate (source, numColors)
                                : Palette.generate (source);
        return source;
    }

    @Override public String key () {
        return String.format (Locale.ENGLISH, "%s:%d", getClass ().getCanonicalName (), numColors);
    }

    public PaletteGenerator () {
        this (0);
    }

    public PaletteGenerator (final int c) {
        numColors = c;
    }
}
Target target = new Target() {
        @Override
        public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            viewHolder.mItemImage.setImageBitmap(bitmap);
            Drawable image = viewHolder.mItemImage.getDrawable();
        }

        @Override
        public void onPrepareLoad(Drawable placeHolderDrawable) {

        }

        @Override
        public void onBitmapFailed(Drawable errorDrawable) {

        }
    };
    Picasso.with(viewHolder.mItemImage.getContext()).load("url").into(viewHolder.mItemImage);

根据 Jake Wharton 的说法目前还没有好的方法

我最终做的是采用转换方法,将丑陋的代码封装并隐藏在阁楼中。

public final class PaletteGeneratorTransformation
  implements Transformation {

    private static final Map<Bitmap, Palette> CACHE = new WeakHashMap<> ();
    private final int    numColors;

    @Override public Bitmap transform (final Bitmap source) {
        if (!CACHE.containsKey (source)) {
            final Palette palette = numColors > 0
                      ? Palette.generate (source, numColors)
                      : Palette.generate (source);
            CACHE.put (source, palette);
        }

        return source;
    }

    @Override public String key () {
        return getClass ().getCanonicalName () + ":" + numColors;
    }

    public PaletteGeneratorTransformation () {
        this (0);
    }

    public PaletteGeneratorTransformation (final int c) {
        numColors = c;
    }

    public static abstract class Callback
      implements com.squareup.picasso.Callback {
        private final ImageView target;

        public Callback (final ImageView t) {
            target = t;
        }

        @Override public void onSuccess () {
            onPalette (CACHE.get (((BitmapDrawable) target.getDrawable ()).getBitmap ()));
        }

        @Override public void onError () {
            onPalette (null);
        }

        public abstract void onPalette (final Palette palette);
    }
}

在我的 Activity 中,我做了一些事情:

Picasso.with(context)
    .load (getPhotoUri())
    .transform (new PaletteGeneratorTransformation (DEFAULT_NUM_COLORS))
    .into (photo, new PaletteGeneratorTransformation.Callback (photo) {
                        @Override public void onPalette (final Palette palette) {
                            themeWithPalette (palette);
                        }
                    });

剩下的唯一问题是我知道阁楼里藏着丑陋的东西,现在必须保留我肮脏的小秘密。