Material design color palette

While working on project Cyanea I was interested in programmatically computing a color palette which produced the same color codes as Google’s 2014 Material Design color palettes. I asked for help on StackOverflow.com and was answered that it was impossible. However, I did manage to generate a color palette similar to the material design palette.

Question

Google has designed a color palette. Given a color, I want to dynamically create the palette in Android.

There was a similar question in the Graphic Design site and an open source javascript solution which generates a similar color palette. The factors for each color are found here and the function used to create the color is found in this stackoverflow answer.

I used that answer and project to generate a palette that is similar to Google’s. However, I want an algorithm that would return the exact values which Google has generated (see the first link).

Question: How does Google calculate the palette colors for material design?


What I have tried so far:

Based off the information above, I created this example to show how I generated a similar palette. Again, I want the exact values.

import android.app.Activity;
import android.app.AlertDialog;
import android.graphics.Color;
import android.os.AsyncTask;
import android.view.Gravity;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;

import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;

/**
 * @author Jared Rummler <[email protected]>
 */
public class PaletteTask extends AsyncTask<Integer, Void, List<PaletteTask.Shade>> {

  private static int shadeColor(int color, double percent) {
    return shadeColor(String.format("#%06X", (0xFFFFFF & color)), percent);
  }

  private static int shadeColor(String color, double percent) {
    long f = Long.parseLong(color.substring(1), 16);
    double t = percent < 0 ? 0 : 255;
    double p = percent < 0 ? percent * -1 : percent;
    long R = f >> 16;
    long G = f >> 8 & 0x00FF;
    long B = f & 0x0000FF;
    int red = (int) (Math.round((t - R) * p) + R);
    int green = (int) (Math.round((t - G) * p) + G);
    int blue = (int) (Math.round((t - B) * p) + B);
    return Color.rgb(red, green, blue);
  }

  private final WeakReference<Activity> activityWeakReference;

  private final List<Shade> shades = new LinkedList<>();

  {
    shades.add(new Shade(0.9, "50"));
    shades.add(new Shade(0.7, "100"));
    shades.add(new Shade(0.5, "200"));
    shades.add(new Shade(0.333, "300"));
    shades.add(new Shade(0.166, "400"));
    shades.add(new Shade(0, "500"));
    shades.add(new Shade(-0.125, "600"));
    shades.add(new Shade(-0.25, "700"));
    shades.add(new Shade(-0.375, "800"));
    shades.add(new Shade(-0.5, "900"));
    shades.add(new Shade(0.7, "A100"));
    shades.add(new Shade(0.5, "A200"));
    shades.add(new Shade(0.166, "A400"));
    shades.add(new Shade(-0.25, "A700"));
  }

  public PaletteTask(Activity activity) {
    activityWeakReference = new WeakReference<>(activity);
  }

  @Override protected List<Shade> doInBackground(Integer... colors) {

    for (Shade shade : shades) {
      shade.color = shadeColor(colors[0], shade.percent);
    }

    return shades;
  }

  @Override protected void onPostExecute(List<Shade> shades) {
    Activity activity = activityWeakReference.get();
    if (activity == null || activity.isFinishing()) {
      return;
    }

    // Create a dialog that shows our generated colors:

    ScrollView scrollView = new ScrollView(activity);
    LinearLayout linearLayout = new LinearLayout(activity);
    linearLayout.setOrientation(LinearLayout.VERTICAL);

    int width, height;
    width = LinearLayout.LayoutParams.MATCH_PARENT;
    height = (int) (30/*dp*/ * (activity.getResources().getDisplayMetrics().densityDpi / 160f));

    // add each color
    for (Shade shade : shades) {
      LinearLayout layoutColor = new LinearLayout(activity);
      TextView textView = new TextView(activity);

      layoutColor.setLayoutParams(new LinearLayout.LayoutParams(width, height));
      layoutColor.setBackgroundColor(shade.color);
      layoutColor.setGravity(Gravity.CENTER);

      textView.setText(shade.name + "    " + String.format("#%06X", (0xFFFFFF & shade.color)));

      layoutColor.addView(textView);
      linearLayout.addView(layoutColor);
    }

    scrollView.addView(linearLayout);

    new AlertDialog.Builder(activity).setView(scrollView).show();
  }

  public static class Shade {

    final double percent;
    final String name;
    int color;

    public Shade(double percent, String name) {
      this.percent = percent;
      this.name = name;
    }
  }

}

Invoking the AsynTask:

int materialRed500 = 0xFFF44336;
new PaletteTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, materialRed500);

Dialog created from the above code:

color palette dialog

Answer

Mikel Bitson gave the answer that it was impossible.

Material Color Palette

50#ffebee
50#fce4ec
50#f3e5f5
100#ffcdd2
100#f8bbd0
100#e1bee7
200#ef9a9a
200#f48fb1
200#ce93d8
300#e57373
300#f06292
300#ba68c8
400#ef5350
400#ec407a
400#ab47bc
500#f44336
500#e91e63
500#9c27b0
600#e53935
600#d81b60
600#8e24aa
700#d32f2f
700#c2185b
700#7b1fa2
800#c62828
800#ad1457
800#6a1b9a
900#b71c1c
900#880e4f
900#4a148c
A100#ff8a80
A100#ff80ab
A100#ea80fc
A200#ff5252
A200#ff4081
A200#e040fb
A400#ff1744
A400#f50057
A400#d500f9
A700#d50000
A700#c51162
A700#aa00ff
50#ede7f6
50#e8eaf6
50#e3f2fd
100#d1c4e9
100#c5cae9
100#bbdefb
200#b39ddb
200#9fa8da
200#90caf9
300#9575cd
300#7986cb
300#64b5f6
400#7e57c2
400#5c6bc0
400#42a5f5
500#673ab7
500#3f51b5
500#2196f3
600#5e35b1
600#3949ab
600#1e88e5
700#512da8
700#303f9f
700#1976d2
800#4527a0
800#283593
800#1565c0
900#311b92
900#1a237e
900#d47a1
A100#b388ff
A100#8c9eff
A100#82b1ff
A200#7c4dff
A200#536dfe
A200#448aff
A400#651fff
A400#3d5afe
A400#2979ff
A700#6200ea
A700#304ffe
A700#2962ff
50#e1f5fe
50#e0f7fa
50#e0f2f1
100#b3e5fc
100#b2ebf2
100#b2dfdb
200#81d4fa
200#80deea
200#80cbc4
300#4fc3f7
300#4dd0e1
300#4db6ac
400#29b6f6
400#26c6da
400#26a69a
500#3a9f4
500#bcd4
500#9688
600#39be5
600#acc1
600#897b
700#288d1
700#97a7
700#796b
800#277bd
800#838f
800#695c
900#1579b
900#6064
900#4d40
A100#80d8ff
A100#84ffff
A100#a7ffeb
A200#40c4ff
A200#18ffff
A200#64ffda
A400#b0ff
A400#e5ff
A400#1de9b6
A700#91ea
A700#b8d4
A700#bfa5
50#e8f5e9
50#f1f8e9
50#f9fbe7
100#c8e6c9
100#dcedc8
100#f0f4c3
200#a5d6a7
200#c5e1a5
200#e6ee9c
300#81c784
300#aed581
300#dce775
400#66bb6a
400#9ccc65
400#d4e157
500#4caf50
500#8bc34a
500#cddc39
600#43a047
600#7cb342
600#c0ca33
700#388e3c
700#689f38
700#afb42b
800#2e7d32
800#558b2f
800#9e9d24
900#1b5e20
900#33691e
900#827717
A100#b9f6ca
A100#ccff90
A100#f4ff81
A200#69f0ae
A200#b2ff59
A200#eeff41
A400#e676
A400#76ff03
A400#c6ff00
A700#c853
A700#64dd17
A700#aeea00
50#fffde7
50#fff8e1
50#fff3e0
100#fff9c4
100#ffecb3
100#ffe0b2
200#fff59d
200#ffe082
200#ffcc80
300#fff176
300#ffd54f
300#ffb74d
400#ffee58
400#ffca28
400#ffa726
500#ffeb3b
500#ffc107
500#ff9800
600#fdd835
600#ffb300
600#fb8c00
700#fbc02d
700#ffa000
700#f57c00
800#f9a825
800#ff8f00
800#ef6c00
900#f57f17
900#ff6f00
900#e65100
A100#ffff8d
A100#ffe57f
A100#ffd180
A200#ffff00
A200#ffd740
A200#ffab40
A400#ffea00
A400#ffc400
A400#ff9100
A700#ffd600
A700#ffab00
A700#ff6d00
50#ede7f6
50#efebe9
50#fafafa
100#d1c4e9
100#d7ccc8
100#f5f5f5
200#b39ddb
200#bcaaa4
200#eeeeee
300#9575cd
300#a1887f
300#e0e0e0
400#7e57c2
400#8d6e63
400#bdbdbd
500#673ab7
500#795548
500#9e9e9e
600#5e35b1
600#6d4c41
600#757575
700#512da8
700#5d4037
700#616161
800#4527a0
800#4e342e
800#424242
900#311b92
900#3e2723
900#212121