2
votes

I have an AsyncTask that loads a bitmap from url and uses a Palette to change the background of my Floating Action Button. With most images it works fine but on some it makes the button transparent. Screenshot 1 shows the button color working with the blue color from the image but in Screenshot 2 the color of the button is transparent (even though the image doesnt contain any transparent pixels as it's a jpeg).

    public class ColoredFabTask extends AsyncTask<String , String , String> {
    Context mContext;
    View view;
    private View rootView;
    URL myFileUrl;
    Bitmap imageBitmap = null;

    public ColoredFabTask(Context context, View view) {
        this.mContext = context;
        this.view = view;
    }

    @Override
    protected void onPreExecute() {
    }

    @Override
    protected String doInBackground(String... args) {
        try {
            myFileUrl = new URL(args[0]);
            HttpURLConnection conn = (HttpURLConnection) 
            myFileUrl.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            imageBitmap = BitmapFactory.decodeStream(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(String args) {
        Palette palette  = Palette.from(imageBitmap).generate();
        int vibrant = palette.getVibrantColor(0);
        FloatingActionButton applyButton = (FloatingActionButton) view.findViewById(R.id.applyButton);
        applyButton.setBackgroundTintList(ColorStateList.valueOf(vibrant));
        applyButton.setVisibility(View.VISIBLE);
    }
}

Screenshots:

enter image description here

enter image description here

2

2 Answers

2
votes

Fixed the problem for myself if anyone wants to know how. Just check if the swatch is null.

        Palette palette = Palette.from(imageBitmap).generate();
        int fallbackColor = palette.getDominantColor(0);
        Palette.Swatch vibrantColorSwatch = palette.getVibrantSwatch();
        if (vibrantColorSwatch != null) {
            int vibrantColor = vibrantColorSwatch.getRgb();
            FloatingActionButton applyButton = (FloatingActionButton) view.findViewById(R.id.applyButton);
            applyButton.setBackgroundTintList(ColorStateList.valueOf(vibrantColor));

        }
        else {
            FloatingActionButton applyButton = (FloatingActionButton) view.findViewById(R.id.applyButton);
            applyButton.setBackgroundTintList(ColorStateList.valueOf(fallbackColor));
        }
1
votes

Paletter ignores some colors by default inside of it. Here is it's implementation from Palette sources:

static final Palette.Filter DEFAULT_FILTER = new Palette.Filter() {
    private static final float BLACK_MAX_LIGHTNESS = 0.05F;
    private static final float WHITE_MIN_LIGHTNESS = 0.95F;

    public boolean isAllowed(int rgb, float[] hsl) {
        return !this.isWhite(hsl) && !this.isBlack(hsl) && !this.isNearRedILine(hsl);
    }

    private boolean isBlack(float[] hslColor) {
        return hslColor[2] <= 0.05F;
    }

    private boolean isWhite(float[] hslColor) {
        return hslColor[2] >= 0.95F;
    }

    private boolean isNearRedILine(float[] hslColor) {
        return hslColor[0] >= 10.0F && hslColor[0] <= 37.0F && hslColor[1] <= 0.82F;
    }
};

As you can see, it forces Palette to ignore some colors. So, you need to try setting custom filer to allow processing all colors