问题
I got this code for scaling image by bilinear interpolation.I know this works but i can't figure out one thing what if the approximated pixel value is an edge(by edge i mean it is in the last row or last column) pixel in the input image then i can i gt a pixel of coordinate (x+1,y+1) ,this should lead to a array index out of range error but no such error occurs why? The code is:
public int[] resizeBilinearGray(int[] pixels, int w, int h, int w2, int h2) {
int[] temp = new int[w2*h2] ;
int A, B, C, D, x, y, index, gray ;
float x_ratio = ((float)(w-1))/w2 ;
float y_ratio = ((float)(h-1))/h2 ;
float x_diff, y_diff, ya, yb ;
int offset = 0 ;
for (int i=0;i<h2;i++) {
for (int j=0;j<w2;j++) {
x = (int)(x_ratio * j) ;
y = (int)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = y*w+x ;
// range is 0 to 255 thus bitwise AND with 0xff
A = pixels[index] & 0xff ;
B = pixels[index+1] & 0xff ;
C = pixels[index+w] & 0xff ;
D = pixels[index+w+1] & 0xff ;
// Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
gray = (int)(
A*(1-x_diff)*(1-y_diff) + B*(x_diff)*(1-y_diff) +
C*(y_diff)*(1-x_diff) + D*(x_diff*y_diff)
) ;
temp[offset++] = gray ;
}
}
return temp ;
}
回答1:
The reason is that x_ratio
and y_ratio
are computed incorrectly.
Consider the last pixel of the last row:
i=h2, j=w2
then:
x = x_ratio * j = (w-1)/w2 * (w2-1) = (w-1) * (w2-1)/w2 <= w-1
y = y_ratio * i = (h-1)/h2 * (h2-1) = (h-1) * (h2-1)/h2 <= h-1
index = y*w+x <= (h-1)*w + (w-1) < w*h
so the index is always less than the size of the pixels
array.
Note however, that this is a very dirty hack, which will result in inaccurate results, especially for small images.
You should calculate width/height ratio as follows:
float x_ratio = ((float)w)/w2;
float y_ratio = ((float)h)/h2;
and create a function which converts coordinates to array index - let's name it coord2index
. This function takes out-of range coordinates into account and implements a so-called boundary option, which simulates that there are pixels outside the image boundary.
Common options for boundary are:
symmetric - pixels outside the image bounds are computed by mirror-reflecting the image at the border. This is probably the best possibility in this case.
replicate - pixels outside the image bounds are assumed to be equal to the nearest pixel at the border. This is the simplest way.
circular - the image is virtually repeated periodically in all directions. Used for some advanced image processing algorithms; not good for image resizing.
回答2:
I guess the trick is in x_ratio = (float)(w-1))/w2
, which computes the ratio as if the original image were one pixel smaller than it's really is. But I'm not sure if this is foolproof and correct (I'd be it isn't - think for example the case w=w2 h=h2 which should give exactly the same image). I really don't like this approach.
来源:https://stackoverflow.com/questions/16341167/bilinear-interpolation