<dependency>
<groupId>com.jhlabs</groupId>
<artifactId>filters</artifactId>
<version>2.0.235</version>
</dependency>
package net.nasacj.javalearn.ImageGradient;
import com.jhlabs.image.AbstractBufferedImageOp;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
/**
* prewitt operator
* X-direction
* -1, 0, 1
* -1, 0, 1
* -1, 0, 1
* <p>
* Y-direction
* -1, -1, -1
* 0, 0, 0
* 1, 1, 1
* <p>
* sobel operator
* X-direction
* -1, 0, 1
* -2, 0, 2
* -1, 0, 1
* <p>
* Y-direction
* -1, -2, -1
* 0, 0, 0
* 1, 2, 1
*/
public class GradientFilter extends AbstractBufferedImageOp {
// prewitt operator
public final static int[][] PREWITT_X = new int[][]{{-1, 0, 1}, {-1, 0, 1}, {-1, 0, 1}};
public final static int[][] PREWITT_Y = new int[][]{{-1, -1, -1}, {0, 0, 0}, {1, 1, 1}};
// sobel operator
public final static int[][] SOBEL_X = new int[][]{{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
public final static int[][] SOBEL_Y = new int[][]{{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
// direction parameter
public final static int X_DIRECTION = 0;
public final static int Y_DIRECTION = 2;
public final static int XY_DIRECTION = 4;
private int direction;
private boolean isSobel;
public GradientFilter() {
direction = XY_DIRECTION;
isSobel = true;
}
public static int clamp(int value) {
return value < 0 ? 0 : (value > 255 ? 255 : value);
}
public static int getGray(Color pixel) {
return (pixel.getRed() * 30 + pixel.getGreen() * 60 + pixel.getBlue() * 10) / 100;
}
public static void main(String[] args) throws IOException, InterruptedException {
new Thread(new Runnable() {
public void run() {
}
}).start();
BufferedImage img = null;
try {
img = ImageIO.read(new File("/Users/nasacj/Downloads/testImage.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
int w = img.getWidth(null);
int h = img.getHeight(null);
BufferedImage bi = new
BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.getGraphics();
g.drawImage(img, 0, 0, null);
BufferedImage destImg = null;
GradientFilter gradientFilter = new GradientFilter();
long timeinit = System.currentTimeMillis();
destImg = gradientFilter.filter(img, destImg);
System.out.println("Time cost: " + (System.currentTimeMillis() - timeinit) + " millis seconds");
ImageIO.write(destImg, "jpeg", new File("/Users/nasacj/Downloads/testImageOut.jpg"));
System.out.println();
}
public void setSoble(boolean sobel) {
this.isSobel = sobel;
}
public int getDirection() {
return direction;
}
public void setDirection(int direction) {
this.direction = direction;
}
public BufferedImage filter(BufferedImage src, BufferedImage dest) {
int width = src.getWidth();
int height = src.getHeight();
if (dest == null)
dest = createCompatibleDestImage(src, null);
int[] inPixels = new int[width * height];
int[] outPixels = new int[width * height];
getRGB(src, 0, 0, width, height, inPixels);
int index = 0, index2 = 0;
double xred = 0, xgreen = 0, xblue = 0;
double yred = 0, ygreen = 0, yblue = 0;
int newRow, newCol;
for (int row = 0; row < height; row++) {
int ta = 255, tr = 0, tg = 0, tb = 0;
for (int col = 0; col < width; col++) {
index = row * width + col;
for (int subrow = -1; subrow <= 1; subrow++) {
for (int subcol = -1; subcol <= 1; subcol++) {
newRow = row + subrow;
newCol = col + subcol;
if (newRow < 0 || newRow >= height) {
newRow = row;
}
if (newCol < 0 || newCol >= width) {
newCol = col;
}
index2 = newRow * width + newCol;
int originPixel = inPixels[index2];
Color color = new Color(originPixel);
int gray = getGray(color);
int newPixel = new Color(gray, gray, gray).getRGB();
// tr = (inPixels[index2] >> 16) & 0xff;
// tg = (inPixels[index2] >> 8) & 0xff;
// tb = inPixels[index2] & 0xff;
tr = (newPixel >> 16) & 0xff;
tg = (newPixel >> 8) & 0xff;
tb = newPixel & 0xff;
if (isSobel) {
xred += (SOBEL_X[subrow + 1][subcol + 1] * tr);
xgreen += (SOBEL_X[subrow + 1][subcol + 1] * tg);
xblue += (SOBEL_X[subrow + 1][subcol + 1] * tb);
yred += (SOBEL_Y[subrow + 1][subcol + 1] * tr);
ygreen += (SOBEL_Y[subrow + 1][subcol + 1] * tg);
yblue += (SOBEL_Y[subrow + 1][subcol + 1] * tb);
} else {
xred += (PREWITT_X[subrow + 1][subcol + 1] * tr);
xgreen += (PREWITT_X[subrow + 1][subcol + 1] * tg);
xblue += (PREWITT_X[subrow + 1][subcol + 1] * tb);
yred += (PREWITT_Y[subrow + 1][subcol + 1] * tr);
ygreen += (PREWITT_Y[subrow + 1][subcol + 1] * tg);
yblue += (PREWITT_Y[subrow + 1][subcol + 1] * tb);
}
}
}
double mred = Math.sqrt(xred * xred + yred * yred);
double mgreen = Math.sqrt(xgreen * xgreen + ygreen * ygreen);
double mblue = Math.sqrt(xblue * xblue + yblue * yblue);
if (XY_DIRECTION == direction) {
outPixels[index] = (ta << 24) | (clamp((int) mred) << 16) | (clamp((int) mgreen) << 8) | clamp((int) mblue);
} else if (X_DIRECTION == direction) {
outPixels[index] = (ta << 24) | (clamp((int) yred) << 16) | (clamp((int) ygreen) << 8) | clamp((int) yblue);
} else if (Y_DIRECTION == direction) {
outPixels[index] = (ta << 24) | (clamp((int) xred) << 16) | (clamp((int) xgreen) << 8) | clamp((int) xblue);
} else {
// as default, always XY gradient
outPixels[index] = (ta << 24) | (clamp((int) mred) << 16) | (clamp((int) mgreen) << 8) | clamp((int) mblue);
}
// cleanup for next loop
newRow = newCol = 0;
xred = xgreen = xblue = 0;
yred = ygreen = yblue = 0;
}
}
setRGB(dest, 0, 0, width, height, outPixels);
return dest;
}
}