function oilPaint(aContext, size, levels, filterSize)
{
levels = levels - 1;
var filterOffset = Math.floor((filterSize - 1) / 2);
var byteOffset = 0;
var calcOffset = 0;
var currentIntensity = 0;
var maxIntensity = 0;
var maxIndex = 0;
var imageData = aContext.getImageData(0, 0, size.width, size.height);
var pixelBuffer = imageData.data;
var resultImageData = aContext.createImageData(imageData);
var resultBuffer = resultImageData.data;
for (var i = 0; i < pixelBuffer.length; ++i)
resultBuffer[i] = pixelBuffer[i];
var toPixel = (x, y) => x * 4 + y * size.width * 4;
for (var offsetY = filterOffset; offsetY < imageData.height - filterOffset; offsetY++)
{
for (var offsetX = filterOffset; offsetX < size.width - filterOffset; offsetX++)
{
var blue = 0;
var green = 0;
var red = 0;
var currentIntensity = 0;
var maxIntensity = 0;
var maxIndex = 0;
var intensityBin = require("ramda").times(() => 0, levels + 1);
var blueBin = require("ramda").times(() => 0, levels + 1);
var greenBin = require("ramda").times(() => 0, levels + 1);
var redBin = require("ramda").times(() => 0, levels + 1);
var byteOffset = toPixel(offsetX, offsetY);
for (var filterY = -filterOffset; filterY <= filterOffset; filterY++)
{
for (var filterX = -filterOffset; filterX <= filterOffset; filterX++)
{
var calcOffset = byteOffset + toPixel(filterX, filterY);
var currentIntensity = Math.round((
(pixelBuffer[calcOffset] +
pixelBuffer[calcOffset + 1] +
pixelBuffer[calcOffset + 2]) / 3.0 *
(levels)) / 255.0);
intensityBin[currentIntensity] += 1;
blueBin[currentIntensity] += pixelBuffer[calcOffset];
greenBin[currentIntensity] += pixelBuffer[calcOffset + 1];
redBin[currentIntensity] += pixelBuffer[calcOffset + 2];
if (intensityBin[currentIntensity] > maxIntensity)
{
maxIntensity = intensityBin[currentIntensity];
maxIndex = currentIntensity;
}
}
}
var blue = blueBin[maxIndex] / maxIntensity;
var green = greenBin[maxIndex] / maxIntensity;
var red = redBin[maxIndex] / maxIntensity;
resultBuffer[byteOffset] = ClipByte(blue);
resultBuffer[byteOffset + 1] = ClipByte(green);
resultBuffer[byteOffset + 2] = ClipByte(red);
resultBuffer[byteOffset + 3] = 255;
}
}
return resultImageData;
}
function ClipByte(byte)
{
return byte > 255 ? 255 : byte < 0 ? 0 : byte;
}