JSFiddle - React, Tailwind, and code Playground

HTML

<input type="file" id="upload_input" name="upload" />
<canvas id="palette_canvas"></canvas>
<canvas id="mixed_palette_canvas"></canvas>
<pre id="shader_code_pre"></pre>

CSS

canvas
{
  image-rendering: optimizeSpeed;
  image-rendering: optimize-contrast;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
  image-rendering: -moz-crisp-edges;
  image-rendering: -o-crisp-edges;
  image-rendering: pixelated;
  -ms-interpolation-mode: nearest-neighbor;
}

JavaScript

var PaletteCanvasWidth = 8;
var PaletteCheckerSize = 32;
var MaxLuminanceDelta = 28;

var UploadInput = document.getElementById("upload_input");

UploadInput.onchange = function(Event)
	{
		var ImageFileReader = new FileReader();
			
		ImageFileReader.onload = function(FileReaderEvent)
			{
        LoadImage(FileReaderEvent.target.result);
			};
      
    ImageFileReader.readAsDataURL(Event.target.files[0]);
	};

function LoadImage(ImageSource)
{
	var Image = document.createElement("img");

	Image.onload = function () { ProcessImage(Image); };
	Image.src = ImageSource;
}

function SrgbToRgb(ColorChannel)
{
	return Math.pow(ColorChannel / 255, 2.2) * 255;
}

function RgbToSrgb(ColorChannel)
{
	return Math.pow(ColorChannel / 255, 1.0 / 2.2) * 255;
}

function ProcessImage(Image)
{
	var ImageCanvas = document.createElement("canvas");
	
	ImageCanvas.width = Image.width;
	ImageCanvas.height = Image.height;
	ImageCanvas.getContext("2d").drawImage(Image, 0, 0, Image.width, Image.height);		

	// Count colors.

	var Colors = {};
  
	var ImageContext = ImageCanvas.getContext("2d");
	var ImageData = ImageContext.getImageData(0, 0, ImageCanvas.width, ImageCanvas.height);

	for(var Y = 0; Y < ImageCanvas.height; Y++)
	{
		for(var X = 0; X < ImageCanvas.width; X++)
		{
			var PixelIndex = (X + Y * ImageCanvas.width) * 4;
      
      var Color = 
      	ImageData.data[PixelIndex] + "_" +
	      ImageData.data[PixelIndex + 1] + "_" +
	      ImageData.data[PixelIndex + 2];
        
      Colors[Color] = 
      	{ 
        	Red: ImageData.data[PixelIndex], 
        	Green: ImageData.data[PixelIndex + 1], 
        	Blue: ImageData.data[PixelIndex + 2]
        };
		}
	}

	// Extract palette.

	var Palette = [];

	for(var Color in Colors)
  	Palette.push(Colors[Color]);

	var NumberOfColors = Palette.length;

	Palette.sort(function (Color1, Color2) { return (SrgbToRgb(Color1.Red) * 0.21 + SrgbToRgb(Color1.Green) * 0.72 + SrgbToRgb(Color1.Blue) * 0.07) - (SrgbToRgb(Color2.Red) *...