@toe_head2001, thanks for pointing out older sources of PaintNET. After digging it i found that the actual algorithm of posterization uses some kind of pre-generated palette. So the whole process done in two steps: first there should be formed palettes for each level (Red, Green, Blue), depending on input values of the filter:
redLevels = CalcLevels( posterizeValRed );
greenLevels = CalcLevels( posterizeValGreen );
blueLevels = CalcLevels( posterizeValBlue );
function CalcLevels( inputVal ){ // inputVal is int[2..64]
var t1 = new Array( inputVal ); // array of byte
var i; // byte
for (i = 0; i < inputVal; i++){
t1[i] = IntToByte( Round( (255 * i) / (inputVal - 1) ) );
}
var levels = new Array( 256 ); // array of byte
var j = 0; // byte
var k = 0; // int16
for(i = 0; i <= 255; i++){
levels[i] = t1[j];
k += inputVal;
if( k > 255 ){
k -= 255;
j++;
}
}
return levels;
}
and in the second step we should perform next operation on each pixel of image:
function PixelOperation( srcColor ){
var byteRed = getRvalue( srcColor ); // byte
var byteGreen = getGvalue( srcColor ); // byte
var byteBlue = getBvalue( srcColor ); // byte
var byteAlpha = getAvalue( srcColor ); // byte
byteRed = redLevels[byteRed];
byteGreen = greenLevels[byteGreen];
byteBlue = blueLevels[byteBlue];
//byteAlpha = alphaLevels[byteAlpha]; // we can do the same for alpha if we need to
return RGBA( byteRed, byteGreen, byteBlue, byteAlpha );
}
By the way, if we will implement this algorithm in some compiling language (i used JavaScript just to demonstrate the approach) - it will be much faster than standard approach, cuz with this method there will be only 3 (4 with alpha) writing instructions for each pixel. So the overall posterization-application time will be like 2-3 times faster (or even more, depending on image-size) comparing to standard posterization algorithm, which has floating-point calculations for each color-byte of each pixel.