生成素描图片

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;
    }
}
原文地址:https://www.cnblogs.com/chrischen662/p/4588610.html