- If you are using your algorithm in real-time, call it less often, maybe every ~20 frames instead of every frame.
- Do more work per iteration, 800x400 in your algorithm is 318,398 iterations. Each iteration is pulling from the input array in a (to the processor) random way which causes issues with caching. Try pulling ay, ay2, by, by2, cy, cy2 and do twice the calculations per loop, you'll notice that the variables in the next iteration will relate to the previous. ay is now ay2 etc...
Here's a rewrite of your algo, doing twice the work per iteration. It saves a bit in redundant memory access, and ignores square root mentioned in another answer.
public void process() { progress=0; index = 0; // calculate size // pixel index size = width*(height-2) - 2; // do FIRST iteration outside of loop // grab input avoid redundant memory accesses ay = ax = input[index]; by = ay2 = ax2 = input[index+1]; cy = by2 = cx = input[index+2]; cy2 = cx2 = input[index+3]; gy = gx = input[index+doubleWidth]; hy = gy2 = gx2 = input[index+doubleWidth+1]; iy = hy2 = ix = input[index+doubleWidth+2]; iy2 = ix2 = input[index+doubleWidth+3]; dx = input[index+width]; dx2 = input[index+width+1]; fx = input[index+width+2]; fx2 = input[index+width+3]; // sumy = ay + (by*2) + cy - gy - (2*hy) - iy; sumy2 = ay2 + (by2*2) + cy2 - gy2 - (2*hy2) - iy2; sumx = -ax + cx -(2*dx) + (2*fx) - gx + ix; sumx2 = -ax2 + cx2 -(2*dx2) + (2*fx2) - gx2 + ix2; // ignore the square root total[index] = fastSqrt(sumx*sumx+sumy*sumy); total[index+1] = fastSqrt(sumx2*sumx2+sumy2*sumy2); max = Math.max(max, Math.max(total[index], total[index+1])); // skip the test for negative value it can never happen if(total[index] > 255) total[index] = 0; if(total[index+1] > 255) total[index+1] = 0; sum = (int) (total[index]); sum2 = (int) (total[index+1]); output[index] = 0xff000000 | (sum << 16) | (sum << 8) | sum; output[index+1] = 0xff000000 | (sum2 << 16) | (sum2 << 8) | sum2; size -= 2; index += 2; while (size>0) { // grab input avoid redundant memory accesses ay = ax = cy; by = ay2 = ax2 = cy2; cy = by2 = cs = input[index+2]; cy2 = cx2 = input[index+3]; gy = gx = iy; hy = gy2 = gx2 = iy2; iy = hy2 = ix = input[index+doubleWidth+2]; iy2 = ix2 = input[index+doubleWidth+3]; dx = fx; dx2 = fx2; fx = input[index+width+2]; fx2 = input[index+width+3]; // sumy = ay + (by*2) + cy - gy - (2*hy) - iy; sumy2 = ay2 + (by2*2) + cy2 - gy2 - (2*hy2) - iy2; sumx = -ax + cx -(2*dx) + (2*fx) - gx + ix; sumx2 = -ax2 + cx2 -(2*dx2) + (2*fx2) - gx2 + ix2; // ignore the square root total[index] = fastSqrt(sumx*sumx+sumy*sumy); total[index+1] = fastSqrt(sumx2*sumx2+sumy2*sumy2); max = Math.max(max, Math.max(total[index], total[index+1])); // skip the test for negative value it can never happen if(total[index] >= 65536) total[index] = 0; if(total[index+1] >= 65536) total[index+1] = 0; sum = (int) (total[index]); sum2 = (int) (total[index+1]); output[index] = 0xff000000 | (sum << 16) | (sum << 8) | sum; output[index+1] = 0xff000000 | (sum2 << 16) | (sum2 << 8) | sum2; size -= 2; index += 2; } } // some faster integer only implementation of square root. public static int fastSqrt(int x) { }
Please note, the above code was not tested, it was written inside the browser window and may contain syntax errors.
EDIT You could try using a fast integer only square root function to avoid the Math.sqrt. http://atoms.alife.co.uk/sqrt/index.html