Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the ways to programmatically generate Material Design color sets?

I am trying to create a colour palette of Material Design that changing the lightness / luminosity by percentage with arbitrary color hex. When it comes to the implementation, I have found that there are some color hex I cannot generate and shows Color Unknown Exception. Would you please tell me what are the alternatives or technical precautions to generate this set of colours?

enter image description here The following is my code

package com.example.dino.util;

import android.content.Context;
import android.graphics.Color;

import java.util.ArrayList;

/**
 * Created by larrylo on 18/1/15.
 */

public  class ColorUtils {

    public Context context;

    public static float[]  colorToHsl(String hexColor) {
        int color = Color.parseColor(hexColor);
        float r = ((0x00ff0000 & color) >> 16) / 255.0F;
        float g = ((0x0000ff00 & color) >> 8) / 255.0F;
        float b = ((0x000000ff & color)) / 255.0F;
        float max = Math.max(Math.max(r, g), b);
        float min = Math.min(Math.min(r, g), b);
        float c = max - min;

        float hTemp = 0.0F;
        if (c == 0) {
            hTemp = 0;
        } else if (max == r) {
            hTemp = (float) (g - b) / c;
            if (hTemp < 0)
                hTemp += 6.0F;
        } else if (max == g) {
            hTemp = (float) (b - r) / c + 2.0F;
        } else if (max == b) {
            hTemp = (float) (r - g) / c + 4.0F;
        }
        float h = 60.0F * hTemp;

        float l = (max + min) * 0.5F;

        float s;
        if (c == 0) {
            s = 0.0F;
        } else {
            s = c / (1 - Math.abs(2.0F * l - 1.0F));
        }

        float []  hsl  = {h , s , l } ;
        return hsl;
    }



    public static String hslToColor(int alpha, float hue, float saturation, float lightness) {
        float hh = hue;
        float ss = saturation;
        float ll = lightness;
        float h, s, v;
        h = hh;
        ll *= 2;
        ss *= (ll <= 1) ? Ll : 2 - ll;
        v = (ll + ss) / 2;
        s = ((ll + ss) != 0) ? (2 * ss) / (ll + ss) : 0;
        int resultColorInt =  Color.HSVToColor(alpha, new float[] { h, s, v });
        return Integer.toHexString(resultColorInt).toUpperCase();
    }

    public static ArrayList<String> returnMaterialDesignColorSet (String colorHex){
        ArrayList<String> resultList = new ArrayList<String>();
        float [] baseColorHSL = colorToHsl(colorHex);
        double randomMid = randomWithRange(0.48 , 0.52);
        String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);
        resultList.add(baseColor);
        return resultList;
    }

    public static double randomWithRange(double min, double max)
    {
        double range = Math.abs(max - min);
        return (Math.random() * range) + (min <= max ? Min : max);
    }

    public static int colorInt (String hex){
        return Color.parseColor(hex);
    }
}

Code for testing

 ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
        double max = 0.52;
        double min = 0.48;
        double range = Math.abs(max - min);
        double value =  (Math.random() * range) + (min <= max ? Min : max);
        float result = (float)value;
        System.out.println(result);
        String test  = "#973f5c";
        String test2 = ColorUtils.returnMaterialDesignColorSet(test).get(0);
        int colorInt = ColorUtils.colorInt(test2);

        actionBar .setBackgroundDrawable(new ColorDrawable(colorInt));
like image 857
Raju yourPepe Avatar asked Jan 18 '15 16:01

Raju yourPepe


1 Answers

Original problem

Your code has error working with color format. Replace last line of hslToColor() like shown below and you'll make it run without errors:

public static String hslToColor(int alpha, float hue, float saturation, float lightness) {

    ...

    // !!! ERROR WAS ON THE LAST LINE:
    return String.format("#%08x", resultColorInt).toUpperCase();
}

I've tested it - it works - because it makes 2 additional things:
1) Formats value to have 8 digits
2) Adds "#" prefix

Possible SECOND problem in your code

The alpha value may have values from 0 (transparent) to 255 (opaque). If you want to have opaque image you should pass 255 (0xFF).
Now you pass 1 and I think it's an error - because it's almost transparent.
So to have opaque color replace line

String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);

with

String baseColor = hslToColor(0xFF ,baseColorHSL[0] , baseColorHSL[1] , (float)0.5);

Annex
If one needs to get a set of colors - a bit of creativity should be applied.
To create a tint palette you have to change in a loop a) saturation or b) lightness or c) both of them.
Here is an implementation example that returns palette based on lightness change from 0.4 to 0.6 (non inclusive) in 10 steps.
"Experimental" means that you should find values for yourself.

public static ArrayList<String> returnMaterialDesignColorSet(String baseColorHex, int colorCount) {
    ArrayList<String> resultList = new ArrayList<String>();
     float [] baseColorHSL = colorToHsl(baseColorHex);

    float lght=0.4;// initial lightness value (experimental)
    float lStep=(0.6 - lght) / colorCount; // step to go up to 0.6 lightness (experimental)
    for (int i = 0; i < colorCount; i++) {
         String baseColor = hslToColor(1 ,baseColorHSL[0] , baseColorHSL[1] , lght);
         resultList.add(baseColor);
         lght += lStep;
    }

    return resultList;
}
like image 53
sberezin Avatar answered Oct 23 '22 03:10

sberezin