package Algorithms;
// Modified snippet from ij.process.ByteProcessor
// Using "a = Math.min(a, b)" is faster than "if (b<a) a = b"
// See FiltersBenchmark.java for details
public class Filters
{
public static void filterMin(byte[] outputPixels, byte[] inputPixels, int width, int height)
{
if (width == 1) {
filterEdgeMin(outputPixels, inputPixels, width, height, height, 0, 0, 0, 1);
return;
}
int p1, p2, p3, p4, p5, p6, p7, p8, p9;
int min = 0;
for (int y = 1; y < height-1; y++) {
int offset = 1 + width * y;
p2 = inputPixels[offset-width-1] & 0xff;
p3 = inputPixels[offset-width] & 0xff;
p5 = inputPixels[offset-1] & 0xff;
p6 = inputPixels[offset] & 0xff;
p8 = inputPixels[offset+width-1] & 0xff;
p9 = inputPixels[offset+width] & 0xff;
for (int x = 0; x < width-2; x++) {
p1 = p2; p2 = p3;
p3 = inputPixels[offset-width+x+1] & 0xff;
p4 = p5; p5 = p6;
p6 = inputPixels[offset+x+1] & 0xff;
p7 = p8; p8 = p9;
p9 = inputPixels[offset+width+x+1] & 0xff;
min = p5;
min = Math.min(min, p1);
min = Math.min(min, p2);
min = Math.min(min, p3);
min = Math.min(min, p4);
min = Math.min(min, p6);
min = Math.min(min, p7);
min = Math.min(min, p8);
min = Math.min(min, p9);
outputPixels[offset+x] = (byte)min;
}
}
filterEdgeMin(outputPixels, inputPixels, width, height, height, 0, 0, 0, 1);
filterEdgeMin(outputPixels, inputPixels, width, height, width, 0, 0, 1, 0);
filterEdgeMin(outputPixels, inputPixels, width, height, height, width-1, 0, 0, 1);
filterEdgeMin(outputPixels, inputPixels, width, height, width, 0, height-1, 1, 0);
}
static void filterEdgeMin(byte[] outputPixels, byte[] inputPixels, int width, int height, int n, int x, int y, int xinc, int yinc)
{
int p1, p2, p3, p4, p5, p6, p7, p8, p9;
int min = 0;
int count;
for (int i=0; i<n; i++) {
int left = x > 0 ? x-1 : 0;
int right = x < width-1 ? x+1 : width-1;
int top = y > 0 ? y-1 : 0;
int bottom = y < height-1 ? y+1 : height-1;
p1 = inputPixels[left + width * top] & 0xff;
p2 = inputPixels[x + width * top] & 0xff;
p3 = inputPixels[right + width * top] & 0xff;
p4 = inputPixels[left + width * y] & 0xff;
p5 = inputPixels[x + width * y] & 0xff;
p6 = inputPixels[right + width * y] & 0xff;
p7 = inputPixels[left + width * bottom] & 0xff;
p8 = inputPixels[x + width * bottom] & 0xff;
p9 = inputPixels[right + width * bottom] & 0xff;
min = p5;
min = Math.min(min, p1);
min = Math.min(min, p2);
min = Math.min(min, p3);
min = Math.min(min, p4);
min = Math.min(min, p6);
min = Math.min(min, p7);
min = Math.min(min, p8);
min = Math.min(min, p9);
outputPixels[x+y*width] = (byte)min;
x += xinc;
y += yinc;
}
}
public static void filterMax(byte[] outputPixels, byte[] inputPixels, int width, int height)
{
if (width == 1) {
filterEdgeMax(outputPixels, inputPixels, width, height, height, 0, 0, 0, 1);
return;
}
int p1, p2, p3, p4, p5, p6, p7, p8, p9;
int max = 0;
for (int y = 1; y < height-1; y++) {
int offset = 1 + width * y;
p2 = inputPixels[offset-width-1] & 0xff;
p3 = inputPixels[offset-width] & 0xff;
p5 = inputPixels[offset-1] & 0xff;
p6 = inputPixels[offset] & 0xff;
p8 = inputPixels[offset+width-1] & 0xff;
p9 = inputPixels[offset+width] & 0xff;
for (int x = 0; x < width-2; x++) {
p1 = p2; p2 = p3;
p3 = inputPixels[offset-width+x+1] & 0xff;
p4 = p5; p5 = p6;
p6 = inputPixels[offset+x+1] & 0xff;
p7 = p8; p8 = p9;
p9 = inputPixels[offset+width+x+1] & 0xff;
max = p5;
max = Math.max(max, p1);
max = Math.max(max, p2);
max = Math.max(max, p3);
max = Math.max(max, p4);
max = Math.max(max, p6);
max = Math.max(max, p7);
max = Math.max(max, p8);
max = Math.max(max, p9);
outputPixels[offset+x] = (byte)max;
}
}
filterEdgeMax(outputPixels, inputPixels, width, height, height, 0, 0, 0, 1);
filterEdgeMax(outputPixels, inputPixels, width, height, width, 0, 0, 1, 0);
filterEdgeMax(outputPixels, inputPixels, width, height, height, width-1, 0, 0, 1);
filterEdgeMax(outputPixels, inputPixels, width, height, width, 0, height-1, 1, 0);
}
static void filterEdgeMax(byte[] outputPixels, byte[] inputPixels, int width, int height, int n, int x, int y, int xinc, int yinc)
{
int p1, p2, p3, p4, p5, p6, p7, p8, p9;
int max = 0;
int count;
for (int i=0; i<n; i++) {
int left = x > 0 ? x-1 : 0;
int right = x < width-1 ? x+1 : width-1;
int top = y > 0 ? y-1 : 0;
int bottom = y < height-1 ? y+1 : height-1;
p1 = inputPixels[left + width * top] & 0xff;
p2 = inputPixels[x + width * top] & 0xff;
p3 = inputPixels[right + width * top] & 0xff;
p4 = inputPixels[left + width * y] & 0xff;
p5 = inputPixels[x + width * y] & 0xff;
p6 = inputPixels[right + width * y] & 0xff;
p7 = inputPixels[left + width * bottom] & 0xff;
p8 = inputPixels[x + width * bottom] & 0xff;
p9 = inputPixels[right + width * bottom] & 0xff;
max = p5;
max = Math.max(max, p1);
max = Math.max(max, p2);
max = Math.max(max, p3);
max = Math.max(max, p4);
max = Math.max(max, p6);
max = Math.max(max, p7);
max = Math.max(max, p8);
max = Math.max(max, p9);
outputPixels[x+y*width] = (byte)max;
x += xinc;
y += yinc;
}
}
public static void removeInsulatedBrightPixels(byte[] outputPixels, byte[] inputPixels, int width, int height, int depth)
{
depth = Math.min(Math.max(depth, 1), 8);
if (width == 1) {
removeEdgeInsulatedBrightPixels(outputPixels, inputPixels, width, height, depth, height, 0, 0, 0, 1);
return;
}
int p1, p2, p3, p4, p5, p6, p7, p8, p9;
for (int z = 0; z < depth; z++) {
for (int y = 1; y < height-1; y++) {
// No AND with 0xff
int offset = 1 + width * y;
p2 = inputPixels[offset-width-1];
p3 = inputPixels[offset-width];
p5 = inputPixels[offset-1];
p6 = inputPixels[offset];
p8 = inputPixels[offset+width-1];
p9 = inputPixels[offset+width];
for (int x = 0; x < width-2; x++) {
p1 = p2; p2 = p3;
p3 = inputPixels[offset-width+x+1];
p4 = p5; p5 = p6;
p6 = inputPixels[offset+x+1];
p7 = p8; p8 = p9;
p9 = inputPixels[offset+width+x+1];
int sum =
((p1 >> z) & 1) +
((p2 >> z) & 1) +
((p3 >> z) & 1) +
((p4 >> z) & 1) +
((p5 >> z) & 1) +
((p6 >> z) & 1) +
((p7 >> z) & 1) +
((p8 >> z) & 1) +
((p9 >> z) & 1);
outputPixels[offset+x] = (byte)(p5 ^ (((8 - sum) >> 31) & (1 << z)));
}
}
}
removeEdgeInsulatedBrightPixels(outputPixels, inputPixels, width, height, depth, height, 0, 0, 0, 1);
removeEdgeInsulatedBrightPixels(outputPixels, inputPixels, width, height, depth, width, 0, 0, 1, 0);
removeEdgeInsulatedBrightPixels(outputPixels, inputPixels, width, height, depth, height, width-1, 0, 0, 1);
removeEdgeInsulatedBrightPixels(outputPixels, inputPixels, width, height, depth, width, 0, height-1, 1, 0);
}
static void removeEdgeInsulatedBrightPixels(
byte[] outputPixels,
byte[] inputPixels,
int width,
int height,
int depth,
int n,
int x,
int y,
int xinc,
int yinc
) {
int p1, p2, p3, p4, p5, p6, p7, p8, p9;
int max = 0;
int count;
for (int z = 0; z < depth; z++) {
for (int i = 0; i < n; i++) {
int left = x > 0 ? x-1 : 0;
int right = x < width-1 ? x+1 : width-1;
int top = y > 0 ? y-1 : 0;
int bottom = y < height-1 ? y+1 : height-1;
p1 = inputPixels[left + width * top];
p2 = inputPixels[x + width * top];
p3 = inputPixels[right + width * top];
p4 = inputPixels[left + width * y];
p5 = inputPixels[x + width * y];
p6 = inputPixels[right + width * y];
p7 = inputPixels[left + width * bottom];
p8 = inputPixels[x + width * bottom];
p9 = inputPixels[right + width * bottom];
int sum =
((p1 >> z) & 1) +
((p2 >> z) & 1) +
((p3 >> z) & 1) +
((p4 >> z) & 1) +
((p5 >> z) & 1) +
((p6 >> z) & 1) +
((p7 >> z) & 1) +
((p8 >> z) & 1) +
((p9 >> z) & 1);
outputPixels[x+y*width] = (byte)(p5 ^ (((8 - sum) >> 31) & (1 << z)));
x += xinc;
y += yinc;
}
}
}
}