Java Convert a greyscale and sepia version of an image with BufferedImage

前端 未结 3 1655
时光说笑
时光说笑 2020-12-21 13:42

I want to read an image and convert and output the original image, a greyscale version, and a sepia version. I am having trouble with the conversion, not very familiar with

3条回答
  •  Happy的楠姐
    2020-12-21 14:30

    You can create a filter interface for code reuse.

    FilterApp

    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    
    public class FilterApp {
        public static ClassLoader loader = FilterApp.class.getClassLoader();
        public static String outputDir = "build";
    
        public static void main(String[] args) {
            try {
                BufferedImage srcImage = loadImage("lobster.jpg");
                File dir = new File(outputDir);
    
                if (!dir.exists()) {
                    dir.mkdirs();
                }
    
                for (FilterType filter : FilterType.values()) {
                    BufferedImage filteredImage = filter.applyFilter(srcImage);
                    String filename = String.format("%s/lobster_%s", outputDir, filter.name().toLowerCase());
                    writeImage(filteredImage, filename, "jpg");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private static BufferedImage loadImage(String filename) throws IOException {
            return ImageIO.read(loader.getResourceAsStream("resources/" + filename));
        }
    
        private static void writeImage(BufferedImage image, String filename, String ext) throws IOException {
            ImageIO.write(image, ext, new File(filename + '.' + ext));
        }
    }
    

    FilterType

    import java.awt.image.BufferedImage;
    
    import filter.GreyscaleFilter;
    import filter.ImageFilter;
    import filter.InvertFilter;
    import filter.SepiaFilter;
    
    public enum FilterType {
        GREYSCALE(new GreyscaleFilter()),
        INVERT(new InvertFilter()),
        SEPIA_10(new SepiaFilter(10));
    
        private ImageFilter filter;
    
        public ImageFilter getFilter() { return filter; }
    
        public BufferedImage applyFilter(BufferedImage img) {
            return this.filter.apply(img);
        }
    
        private FilterType(ImageFilter filter) {
            this.filter = filter;
        }
    }
    

    ImageFilter

    package filter;
    
    import java.awt.image.BufferedImage;
    
    /** Common Interface for different filters. */ 
    public interface ImageFilter {
        public BufferedImage apply(BufferedImage img);
    }
    

    GreyscaleFilter

    package filter;
    
    import java.awt.color.ColorSpace;
    import java.awt.image.BufferedImage;
    import java.awt.image.ColorConvertOp;
    
    public class GreyscaleFilter implements ImageFilter {
        @Override
        public BufferedImage apply(BufferedImage img) {
            BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), img.getType());
            ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
    
            op.filter(img, result);
    
            return result;
        }
    }
    

    InvertFilter

    package filter;
    
    import java.awt.Color;
    import java.awt.image.BufferedImage;
    
    public class InvertFilter implements ImageFilter {
        @Override
        public BufferedImage apply(BufferedImage img) {
            BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), img.getType());
    
            for (int x = 0; x < img.getWidth(); x++) {
                for (int y = 0; y < img.getHeight(); y++) {
                    int rgb = img.getRGB(x, y);
                    Color color = new Color(rgb, true);
                    int r = 255 - color.getRed();
                    int g = 255 - color.getGreen();
                    int b = 255 - color.getBlue();
    
                    color = new Color(r, g, b, color.getAlpha());
                    result.setRGB(x, y, color.getRGB());
                }
            }
    
            return result;
        }
    }
    

    SepiaFilter

    package filter;
    
    import java.awt.Color;
    import java.awt.image.BufferedImage;
    
    // Algorithm obtained from http://stackoverflow.com/questions/21899824
    public class SepiaFilter implements ImageFilter {
        private int intensity;
    
        public void setIntensity(int intensity) { this.intensity = intensity; }
        public int getIntensity() { return intensity; }
    
        public SepiaFilter(int intensity) {
            this.intensity = intensity;
        }
    
        @Override
        public BufferedImage apply(BufferedImage img) {
            BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), img.getType());
            // Play around with this.
            // 20 works well and was recommended by another developer.
            // 0 produces black/white image
            int sepiaDepth = 20;
    
            int w = img.getWidth();
            int h = img.getHeight();
    
            // We need 3 integers (for R,G,B color values) per pixel.
            int[] pixels = new int[w * h * 3];
            img.getRaster().getPixels(0, 0, w, h, pixels);
    
            for (int x = 0; x < img.getWidth(); x++) {
                for (int y = 0; y < img.getHeight(); y++) {
                    int rgb = img.getRGB(x, y);
                    Color color = new Color(rgb, true);
                    int r = color.getRed();
                    int g = color.getGreen();
                    int b = color.getBlue();
                    int gry = (r + g + b) / 3;
    
                    r = g = b = gry;
                    r = r + (sepiaDepth * 2);
                    g = g + sepiaDepth;
    
                    if (r > 255) { r = 255; }
                    if (g > 255) { g = 255; }
                    if (b > 255) { b = 255; }
    
                    // Darken blue color to increase sepia effect
                    b -= this.intensity;
    
                    // normalize if out of bounds
                    if (b < 0)   { b = 0; }
                    if (b > 255) { b = 255; }
    
                    color = new Color(r, g, b, color.getAlpha());
                    result.setRGB(x, y, color.getRGB());
                }
            }
    
            return result;
        }
    }
    

    Output

    Source Image

    Generated Images

提交回复
热议问题