Я портирую библиотеку подпрограмм манипулирования изображениями на C из Java и получаю очень небольшие различия при сравнении результатов. Разумно ли, что эти различия связаны с обработкой значений с плавающей запятой в разных языках или у меня все еще есть работа?
Процедура Convolution с ядром 3 x 3, она работает с растровым изображением, представленным линейным массивом пикселей, шириной и глубиной. Вам не нужно понимать этот код именно для того, чтобы ответить на мой вопрос, он здесь только для справки.
Java-код;
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++){
int offset = (y*width)+x;
if(x % (width-1) == 0 || y % (height-1) == 0){
input.setPixel(x, y, 0xFF000000); // Alpha channel only for border
} else {
float r = 0;
float g = 0;
float b = 0;
for(int kx = -1 ; kx <= 1; kx++ ){
for(int ky = -1 ; ky <= 1; ky++ ){
int pixel = pix[offset+(width*ky)+kx];
int t1 = Color.red(pixel);
int t2 = Color.green(pixel);
int t3 = Color.blue(pixel);
float m = kernel[((ky+1)*3)+kx+1];
r += Color.red(pixel) * m;
g += Color.green(pixel) * m;
b += Color.blue(pixel) * m;
}
}
input.setPixel(x, y, Color.rgb(clamp((int)r), clamp((int)g), clamp((int)b)));
}
}
}
return input;
Зажим ограничивает значения полос в диапазоне [0..255], а Color.red эквивалентен (pixel & 0x00FF0000) >> 16.
Код C выглядит следующим образом;
for(x=1;x<width-1;x++){
for(y=1; y<height-1; y++){
offset = x + (y*width);
rAcc=0;
gAcc=0;
bAcc=0;
for(z=0;z<kernelLength;z++){
xk = x + xOffsets[z];
yk = y + yOffsets[z];
kOffset = xk + (yk * width);
rAcc += kernel[z] * ((b1[kOffset] & rMask)>>16);
gAcc += kernel[z] * ((b1[kOffset] & gMask)>>8);
bAcc += kernel[z] * (b1[kOffset] & bMask);
}
// Clamp values
rAcc = rAcc > 255 ? 255 : rAcc < 0 ? 0 : rAcc;
gAcc = gAcc > 255 ? 255 : gAcc < 0 ? 0 : gAcc;
bAcc = bAcc > 255 ? 255 : bAcc < 0 ? 0 : bAcc;
// Round the floats
r = (int)(rAcc + 0.5);
g = (int)(gAcc + 0.5);
b = (int)(bAcc + 0.5);
output[offset] = (a|r<<16|g<<8|b) ;
}
}
Это немного отличается от xOffsets, например, xOffset для элемента ядра.
Суть в том, что мои результаты превышают максимум один бит. Ниже приведены значения пикселей:
FF205448 expected
FF215449 returned
44 wrong
FF56977E expected
FF56977F returned
45 wrong
FF4A9A7D expected
FF4B9B7E returned
54 wrong
FF3F9478 expected
FF3F9578 returned
74 wrong
FF004A12 expected
FF004A13 returned
Считаете ли вы, что это проблема с моим кодом или, скорее, разница в языке?
С уважением,
Гав