Algorithm is this:
1. Extract pixel's relative distance [0..1] from the start of gradient.
2. Update this distance by feeding it to gradient transfer function.
3. Blend source color with target color using updated distance as blend ratio.
4. Set calculated color to pixel.
We will use such gradient transfer function:
where x is pixel's relative distance from the start and a,b are some adjustable parameters.
Below is Javascript implementation of this method (your browser must support HTML5 canvas element). You can try to change a,b parameters of transfer function and see what happens to gradient.
a 0.5
b 5.00
And here is Javascript code which does that (plot is generated with FLOT library):
function showValue(newValue,el) { document.getElementById(el).innerHTML=parseFloat(newValue).toFixed(2); GeneratePlot(); } function Clamp(x,a,b) { return Math.min(Math.max(x, a), b); }; function NonLinearTransfer(x,a,b) { return (1-a)*x + a*Math.pow(1+Math.exp(b-2*b*x),-1); }; function GeneratePlot() { var data = []; var a = document.getElementById("rngNonlinearity").value; var b = document.getElementById("rngAbruptness").value; for (var i = 0; i <= 1; i += 0.01) data.push([i, Clamp(NonLinearTransfer(i,a,b),0,1)]); $.plot($("#placeholder"), [{ data: data, label: "Transfer function"}], { xaxes: [ { min: 0, max: 1 }], yaxes: [ { min: 0, max: 1 }], legend: { position: 'nw' } } ); GenerateGrad(); }; function Blend(k,x,y) { return (1-k)*x + k*y; } function setPixel(imageData, x, y, r, g, b, a) { index = (x + y * imageData.width) * 4; imageData.data[index+0] = r; imageData.data[index+1] = g; imageData.data[index+2] = b; imageData.data[index+3] = a; } function GenerateGrad() { element = document.getElementById("canvasGrad"); c = element.getContext("2d"); width = parseInt(element.getAttribute("width")); height = parseInt(element.getAttribute("height")); imageData = c.createImageData(width, height); scolor = [0,255,0]; tcolor = [0,0,255]; c1 = document.getElementById("rngNonlinearity").value; c2 = document.getElementById("rngAbruptness").value; // draw gradient for (x = 0; x < width; x++) { k = x/width; k = NonLinearTransfer(k,c1,c2); r = Blend(k,scolor[0],tcolor[0]); g = Blend(k,scolor[1],tcolor[1]); b = Blend(k,scolor[2],tcolor[2]); for (y = 0; y < height; y++) { setPixel(imageData, x, y, r, g, b, 0xff); } } c.putImageData(imageData, 0, 0); }
Have fun!
No comments:
Post a Comment
Comment will be posted after comment moderation.
Thank you for your appreciation.