import java.awt.color.ColorSpace; import java.awt.image.BufferedImage; import java.awt.image.ColorConvertOp; import java.io.File; import javax.imageio.ImageIO; /** * 生成素描 * @author 老陈 * @version 1.0 * @since 2014-11-12 */ public class sketch { public static void main(String[] args) throws Exception{ String file1 = "D:/100.jpg";//原文件 String file2 = "D:/06.jpg";//素描 File inputFile = new File(file1); BufferedImage old = ImageIO.read(inputFile); //去色 BufferedImage b1 = discolor(old); //反相 b1 = invert(b1); //高斯模糊 float[][] matric = gaussian2DKernel(3, 3f); b1 = convolution(b1, matric); //叠加 b1 = deceaseColorCompound(old, b1); //黑白 ColorSpace cs1 = ColorSpace.getInstance(ColorSpace.CS_GRAY); ColorConvertOp op1 = new ColorConvertOp(cs1, null); BufferedImage b2 = new BufferedImage(old.getWidth(), old.getHeight(), BufferedImage.TYPE_INT_RGB); op1.filter(b1, b2); ImageIO.write(b2, "jpg", new File(file2)); System.out.println("生成素描"); } //去色 public static BufferedImage discolor(final BufferedImage sourceImage) { final int width = sourceImage.getWidth(); final int height = sourceImage.getHeight(); final BufferedImage retImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { final int color1 = sourceImage.getRGB(i, j); final int a1 = (color1 >> 24) & 0xff; final int r1 = (color1 >> 16) & 0xff; final int g1 = (color1 >> 8) & 0xff; final int b1 = color1 & 0xff; double sumA = a1; double sumR = 0; double sumG = 0; double sumB = 0; sumR = sumG = sumB = r1 * 0.299 + g1 * 0.587 + b1 * 0.114; final int result = (((int) sumA)<<24) | (((int) sumR) << 16) | (((int) sumG) << 8) | ((int) sumB); retImage.setRGB(i, j, result); } } return retImage; } //反相 public static BufferedImage invert(final BufferedImage sourceImage) { final int width = sourceImage.getWidth(); final int height = sourceImage.getHeight(); final BufferedImage retImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { final int color1 = sourceImage.getRGB(i, j); final int a1 = (color1 >> 24) & 0xff; final int r1 = (color1 >> 16) & 0xff; final int g1 = (color1 >> 8) & 0xff; final int b1 = color1 & 0xff; int a = a1; int r = 255 - r1; int g = 255 - g1; int b = 255 - b1; int result = (a << 24) | (r << 16) | (g << 8) | b; if(result > 255) result = 255; retImage.setRGB(i, j, result); } } return retImage; } //叠加:两张图片颜色减淡混合 // C =MIN( A +(A×B)/(256-B),255) public static BufferedImage deceaseColorCompound(final BufferedImage sourceImage, final BufferedImage targetImage) { final int width = sourceImage.getWidth() > targetImage.getWidth() ? sourceImage .getWidth() : targetImage.getWidth(); final int height = sourceImage.getHeight() > targetImage.getHeight() ? sourceImage .getHeight() : targetImage.getHeight(); final BufferedImage retImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { if(i>=sourceImage.getWidth() || j>=sourceImage.getHeight()){ if(i>=targetImage.getWidth() || j>=targetImage.getHeight()){ retImage.setRGB(i, j, 0); continue; } retImage.setRGB(i, j, targetImage.getRGB(i, j)); continue; } if(i>=targetImage.getWidth() || j>=targetImage.getHeight()){ retImage.setRGB(i, j, sourceImage.getRGB(i, j)); continue; } final int color1 = sourceImage.getRGB(i, j); final int color2 = targetImage.getRGB(i, j); final int a1 = (color1 >> 24) & 0xff; final int r1 = (color1 >> 16) & 0xff; final int g1 = (color1 >> 8) & 0xff; final int b1 = color1 & 0xff; final int a2 = (color2 >> 24) & 0xff; final int r2 = (color2 >> 16) & 0xff; final int g2 = (color2 >> 8) & 0xff; final int b2 = color2 & 0xff; final int a = deceaseColorChannel(a1, a2); final int r = deceaseColorChannel(r1, r2); final int g = deceaseColorChannel(g1, g2); final int b = deceaseColorChannel(b1, b2); final int result = (a << 24) | (r << 16) | (g << 8) | b; retImage.setRGB(i, j, result); } } return retImage; } // C =MIN( A +(A×B)/(256-B),255) private static int deceaseColorChannel(final int source, final int target) { final int result = source + source * target / (256 - target); return result > 255 ? 255 : result; } //高斯模糊 public static BufferedImage convolution(final BufferedImage image, final float kernel[][]) { final int width = image.getWidth(); final int height = image.getHeight(); final int radius = kernel.length / 2; final BufferedImage retImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { double sumA = 0; double sumR = 0; double sumG = 0; double sumB = 0; for (int x = i - radius; x <= i + radius; x++) { for (int y = j - radius; y <= j + radius; y++) { final int posX = x < 0 ? 0 : x >= width ? width - 1 : x; final int posY = y < 0 ? 0 : y >= height ? height - 1 : y; final int color = image.getRGB(posX, posY); final int a = (color >> 24) & 0xff; final int r = (color >> 16) & 0xff; final int g = (color >> 8) & 0xff; final int b = color & 0xff; final int kelX=x - i + radius; final int kelY=y - j + radius; sumA += kernel[kelX][kelY] * a; sumR += kernel[kelX][kelY] * r; sumG += kernel[kelX][kelY] * g; sumB += kernel[kelX][kelY] * b; } } final int blurColor = (((int) sumA)<<24) | (((int) sumR) << 16) | (((int) sumG) << 8) | ((int) sumB); retImage.setRGB(i, j, blurColor); } } return retImage; } //2D高斯卷积矩阵 // G(x,y)=[1/(2*PI*sigma^2)]*e^[-((x^2+y^2)/(2*sigma^2))] // x,y->[-radius,radius) public static float[][] gaussian2DKernel(final int radius, final float sigma) { final int length = 2 * radius; final float[][] matric = new float[length + 1][length + 1]; final float sigmaSquare2 = 2 * sigma * sigma; float sum = 0; for (int x = -radius; x <= radius; x++) { for (int y = -radius; y <= radius; y++) { matric[radius + x][radius + y] = (float) (Math.pow(Math.E, -(x * x + y * y) / sigmaSquare2) / (Math.PI * sigmaSquare2)); sum += matric[radius + x][radius + y]; } } for (int x = 0; x < length; x++) { for (int y = 0; y < length; y++) { matric[x][y] /= sum; } } return matric; } }