// from https://codepen.io/tculda/pen/pogwpOw sclass MultiPointGradient is MakesBufferedImage { LPair gradientPoints; int w, h; int[] pixels; double[] gradientPointArray; Color[] colors; bool hasRun; *(LPair *gradientPoints, int *w, int *h) {} *(WidthAndHeight size, LPair *gradientPoints) { w = size.getWidth(); h = size.getHeight(); } *(int *w, int *h, LPair *gradientPoints) {} public int getWidth() { ret w; } public int getHeight() { ret h; } public BufferedImage getBufferedImage() { run(); ret intArrayToBufferedImageWithoutAlpha(pixels, w, h); } void init { if (pixels == null) pixels = new int[w*h]; if (gradientPointArray == null) gradientPointArray = iDoublePtsToDoubleArray(pairsA(gradientPoints)); if (colors == null) colors = toArray Color(pairsB(gradientPoints)); } run { if (hasRun) ret; set hasRun; init(); int n = l(colors); double[] colorRatios = new[n]; int iPixel = 0; for y to h: for x to w: { fillArray(colorRatios, 1); for i to n: for j to n: if (i != j) { var d = getProjectionDistance2( gradientPointArray[i*2], gradientPointArray[i*2+1], gradientPointArray[j*2], gradientPointArray[j*2+1], x, y); colorRatios[i] *= clampZeroToOne(d); } pixels[iPixel++] = blendMultipleColorsToInt(colors, colorRatios); } } }