I am transferring a library of image processing routines in C with Java, and when comparing the results I get very slight differences. Is it reasonable that these differences are related to the handling of float values โโby different languages โโor do I still have work!
A subprogram is a convolution with a 3 x 3 kernel; it works on a raster image represented by a linear array of pixels, width and depth. You do not have to understand this code exactly to answer my question, it is here for reference only.
Java code
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;
Clamp limits the range values โโto the range [0..255], and Color.red is equivalent (pixel and 0x00FF0000) โ 16.
C code is as follows:
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) ; } }
A bit different xOffsets provides xOffset for a kernel element, for example.
The main thing is that my results go no more than one bit. Below are the pixel values:
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
Do you think this is a problem with my code, or rather, a difference in language?
Yours faithfully,
Woof
source share