Unfortunately I cant Modify old posts?...so heres an update.
As requested it now allows you to pick the colours used for the gradient.
Code
Configuration
var options = ["Linear", "Circle Up", "Circle Down", "Smooth"];
Configuration.Add1ofNPicker("type", "Type", "Choose the stepping type", options, 3);
Configuration.AddCheckBox("alpha", "Use Alpha", "", true);
Configuration.AddCheckBox("invert", "Invert", "", false);
Configuration.AddCheckBox("merge", "Merge", "", false);
Configuration.AddColorButton("startColour", "Starting Colour", "", 0x000000);
Configuration.AddColorButton("endColour", "End Colour", "", 0xffffff);
Execution
var image = Document.RasterImage;
var w = image.sizeX;
var width = w;
var h = image.sizeY;
var height = h;
var map = [];
var LINEAR = 0;
var CIRCLE_UP = 1;
var CIRCLE_DOWN = 2;
var SMOOTH = 3;
var factor = 1.0;
var gradient=[];
var gradientSize=512;
var colormap = true;
var useAlpha = Configuration.alpha;
var invert = Configuration.invert;
var merge = Configuration.merge;
var type = Configuration.type;
var one = 41;
var sqrt2 = /*(int)*/ (41 * Math.sqrt(2));
var sqrt5 = /*(int)*/ (41 * Math.sqrt(5));
var lerp = function( a, b, percent ) {
return a + percent * ( b - a );
};
var ImageMath = {
clamp: function(x, a, b) {
return (x < a) ? a : (x > b) ? b : x;
},
smoothStep: function(a, b, x) {
if (x < a)
return 0;
if (x >= b)
return 1;
x = (x - a) / (b - a);
return x * x * (3 - 2 * x);
},
circleUp: function(x) {
x = 1 - x;
return /*(float)*/ Math.sqrt(1 - x * x);
},
circleDown: function(x) {
return 1.0 - /*(float)*/ Math.sqrt(1 - x * x);
}
};
// Do ya thing.....
makeColourMap(Configuration.startColour,Configuration.endColour);
makeMap(image, map, width, height);
var max = distanceMap(map, width, height);
applyMap(map, image, width, height, max);
function makeColourMap(start,end){
var sb = (start >> 16) & 0xFF;
var sg = (start >> 8) & 0xFF;
var sr = (start) & 0xFF;
var db = (end >> 16) & 0xFF;
var dg = (end >> 8) & 0xFF;
var dr = (end) & 0xFF;
var r,g,b,c,pos;
for (var i=0,end=gradientSize;i<end;i++){
pos=i/(gradientSize-1);
r=lerp(sr,dr,pos);
g=lerp(sg,dg,pos);
b=lerp(sb,db,pos);
c=(r << 16) | (g << 8)| b;
gradient.push(c);
}
}
function makeMap(pixels, map, width, height) {
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var offset = x + y * width;
var b = useAlpha ? pixels.getPixelAlpha(x, y, 0, 0) : pixels.getPixelL(x, y, 0, 0);
// map[offset] = b * one;
map[offset] = b * one / 10; // This may be needed to converted to an int
}
}
}
function distanceMap(map, width, height) {
var xmax = width - 3;
var ymax = height - 3;
var max = 0;
var v, x, y, offset;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
offset = x + y * width;
if (map[offset] > 0) {
if (x < 2 || x > xmax || y < 2 || y > ymax)
v = setEdgeValue(x, y, map, width, offset, xmax, ymax);
else
v = setValue(map, width, offset);
if (v > max)
max = v;
}
}
}
for (y = height - 1; y >= 0; y--) {
for (x = width - 1; x >= 0; x--) {
offset = x + y * width;
if (map[offset] > 0) {
if (x < 2 || x > xmax || y < 2 || y > ymax)
v = setEdgeValue(x, y, map, width, offset, xmax, ymax);
else
v = setValue(map, width, offset);
if (v > max)
max = v;
}
}
}
return max;
}
function applyMap(map, pixels, width, height, max) {
var x, y, offset, n, v, sa, sr, sg, sb, c, transp, col, a, r, g, b;
if (max === 0)
max = 1;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
offset = x + y * width;
m = map[offset];
v = 0;
sa = 0, sr = 0, sg = 0, sb = 0;
if (m === 0) {
// default color
sa = sr = sg = sb = 0;
sa = pixels.getPixelAlpha(x, y, 0, 0);
} else {
// get V from map
v = ImageMath.clamp(factor * m / max, 0, 1);
switch (type) {
case CIRCLE_UP:
v = (ImageMath.circleUp(v));
break;
case CIRCLE_DOWN:
v = (ImageMath.circleDown(v));
break;
case SMOOTH:
v = (ImageMath.smoothStep(0, 1, v));
break;
}
if (colormap === false) {
sr = sg = sb = /*(int)*/ (v * 255);
} else {
c = (gradient[Math.round(v*gradientSize-1)]);
sr = (c >> 16) & 0xFF;
sg = (c >> 8) & 0xFF;
sb = (c) & 0xFF;
}
sa = useAlpha ? pixels.getPixelAlpha(x, y, 0, 0) : pixels.getPixelL(x, y, 0, 0);
// invert v if necessary
if (invert) {
sr = 255 - sr;
sg = 255 - sg;
sb = 255 - sb;
}
}
// write results
if (merge) {
// merge with source
transp = 255;
//col = pixels[offset];
col = pixels.getPixel(x, y, 0, 0);
a = (col & 0xFF000000) >> 24;
r = (col & 0xFF0000) >> 16;
g = (col & 0xFF00) >> 8;
b = (col & 0xFF);
r = /*(int)*/ ((sr * r / transp));
g = /*(int)*/ ((sg * g / transp));
b = /*(int)*/ ((sb * b / transp));
// clip colors
if (r < 0)
r = 0;
if (r > 255)
r = 255;
if (g < 0)
g = 0;
if (g > 255)
g = 255;
if (b < 0)
b = 0;
if (b > 255)
b = 255;
//pixels[offset] = (a << 24) | (r << 16) | (g << 8) | b;
pixels.setPixel(x, y, 0, 0, (a << 24) | (r << 16) | (g << 8) | b);
} else {
// write gray shades
//pixels[offset] = (sa << 24) | (sr << 16) | (sg << 8) | sb;
pixels.setPixel(x, y, 0, 0, (sa << 24) | (sr << 16) | (sg << 8) | sb);
}
}
}
}
function setEdgeValue(x, y, map, width, offset, xmax, ymax) {
var min, v;
var r1, r2, r3, r4, r5;
r1 = offset - width - width - 2;
r2 = r1 + width;
r3 = r2 + width;
r4 = r3 + width;
r5 = r4 + width;
if (y === 0 || x === 0 || y == ymax + 2 || x == xmax + 2)
return map[offset] = one;
v = map[r2 + 2] + one;
min = v;
v = map[r3 + 1] + one;
if (v < min)
min = v;
v = map[r3 + 3] + one;
if (v < min)
min = v;
v = map[r4 + 2] + one;
if (v < min)
min = v;
v = map[r2 + 1] + sqrt2;
if (v < min)
min = v;
v = map[r2 + 3] + sqrt2;
if (v < min)
min = v;
v = map[r4 + 1] + sqrt2;
if (v < min)
min = v;
v = map[r4 + 3] + sqrt2;
if (v < min)
min = v;
if (y == 1 || x == 1 || y == ymax + 1 || x == xmax + 1)
return map[offset] = min;
v = map[r1 + 1] + sqrt5;
if (v < min)
min = v;
v = map[r1 + 3] + sqrt5;
if (v < min)
min = v;
v = map[r2 + 4] + sqrt5;
if (v < min)
min = v;
v = map[r4 + 4] + sqrt5;
if (v < min)
min = v;
v = map[r5 + 3] + sqrt5;
if (v < min)
min = v;
v = map[r5 + 1] + sqrt5;
if (v < min)
min = v;
v = map[r4] + sqrt5;
if (v < min)
min = v;
v = map[r2] + sqrt5;
if (v < min)
min = v;
return map[offset] = min;
}
function setValue(map, width, offset) {
var min, v;
var r1, r2, r3, r4, r5;
r1 = offset - width - width - 2;
r2 = r1 + width;
r3 = r2 + width;
r4 = r3 + width;
r5 = r4 + width;
v = map[r2 + 2] + one;
min = v;
v = map[r3 + 1] + one;
if (v < min)
min = v;
v = map[r3 + 3] + one;
if (v < min)
min = v;
v = map[r4 + 2] + one;
if (v < min)
min = v;
v = map[r2 + 1] + sqrt2;
if (v < min)
min = v;
v = map[r2 + 3] + sqrt2;
if (v < min)
min = v;
v = map[r4 + 1] + sqrt2;
if (v < min)
min = v;
v = map[r4 + 3] + sqrt2;
if (v < min)
min = v;
v = map[r1 + 1] + sqrt5;
if (v < min)
min = v;
v = map[r1 + 3] + sqrt5;
if (v < min)
min = v;
v = map[r2 + 4] + sqrt5;
if (v < min)
min = v;
v = map[r4 + 4] + sqrt5;
if (v < min)
min = v;
v = map[r5 + 3] + sqrt5;
if (v < min)
min = v;
v = map[r5 + 1] + sqrt5;
if (v < min)
min = v;
v = map[r4] + sqrt5;
if (v < min)
min = v;
v = map[r2] + sqrt5;
if (v < min)
min = v;
return map[offset] = min;
}