Java Grayscale and Sepia Version Image Using BufferedImage

I want to read the image and convert and output the original image, the grayscale version and the sepia version. I am having problems converting, not very familiar with BufferedImage, and especially having problems with the getRGB and setRGB methods. I still have it

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream;

public class ChangeColor{
  static BufferedImage readImage( String Pic ) throws Exception {

    BufferedImage image = ImageIO.read( new File("Pic.jpg") );
    return( image );
  }

  public static void saveImage( BufferedImage img, File file ) throws IOException {

        ImageWriter      writer = null;
        java.util.Iterator iter = ImageIO.getImageWritersByFormatName("jpg");

        if( iter.hasNext() ){
            writer = (ImageWriter)iter.next();
        }

        ImageOutputStream ios = ImageIO.createImageOutputStream( file );
        writer.setOutput(ios);

        ImageWriteParam param = new JPEGImageWriteParam( java.util.Locale.getDefault() );
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT) ;
        param.setCompressionQuality(0.98f);

        writer.write(null, new IIOImage( img, null, null ), param);

    }

  public static BufferedImage color2gray( BufferedImage inImage ) {

    int            width    = inImage.getWidth();
    int            height   = inImage.getHeight();
    BufferedImage  outImage = new BufferedImage( width, height, BufferedImage.TYPE_3BYTE_BGR );

    for(int i=0; i<height; i++){
        for(int j=0; j<width; j++){
           Color c = new Color(image.getRGB(j, i));
           int red = (int)(c.getRed() * 0.2126);
           int green = (int)(c.getGreen() * 0.7152);
           int blue = (int)(c.getBlue() *0.0722);
           Color newColor = new Color(red+green+blue,
           red+green+blue,red+green+blue);
           image.setRGB(j,i,newColor.getRGB());
           }
    }

    return( outImage );
  }

  public static BufferedImage color2sepia( BufferedImage inImage ) {

    int            width    = inImage.getWidth();
    int            height   = inImage.getHeight();
    BufferedImage  outImage = new BufferedImage( width, height, BufferedImage.TYPE_3BYTE_BGR );
    for(int i=0; i<height; i++){
        for(int j=0; j<width; j++){
           Color c = new Color(image.getRGB(j, i));
           int red = (int)(c.getRed());
           int green = (int)(c.getGreen());
           int blue = (int)(c.getBlue());
           Color newColor = new Color(red* .393)+(green*.769)+(blue* .189),
           (red* .349)+(green*.686)+(blue* .168),(red* .272)+(green*.534)+(blue* .131);
           image.setRGB(j,i,newColor.getRGB());
           }
    }
    return( outImage );
  }



  public static void main(String[] args) throws Exception {

    BufferedImage colorImage, grayImage, sepiaImage;

    if (args.length != 1)
        System.out.println( "" );
    else
    {
        colorImage = readImage  ( args[0] );
    grayImage  = color2gray ( colorImage );
    sepiaImage = color2sepia( colorImage );

    saveImage( grayImage,  new File( "greyPic.jpg" + args[0] ) );
    saveImage( sepiaImage, new File( "sepiaPic.jpg"+ args[0] ) );
    }
  }

}

This is an image of what the output should look like:

enter image description here Thank.

+2
source share
3 answers

Gray scaling is quite simple, sepia is not so much. I stole a network algorithm ...

Convert

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ColorAlteration {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
                try {
                    BufferedImage master = ImageIO.read(new File("C:\\hold\\thumbnails\\_cg_836___Tilting_Windmills___by_Serena_Clearwater.png"));
                    BufferedImage gray = toGrayScale(master);
                    BufferedImage sepia = toSepia(master, 80);

                    JPanel panel = new JPanel(new GridBagLayout());
                    panel.add(new JLabel(new ImageIcon(master)));
                    panel.add(new JLabel(new ImageIcon(gray)));
                    panel.add(new JLabel(new ImageIcon(sepia)));

                    JOptionPane.showMessageDialog(null, panel);

                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        });
    }

    public static BufferedImage toGrayScale(BufferedImage master) {
        BufferedImage gray = new BufferedImage(master.getWidth(), master.getHeight(), BufferedImage.TYPE_INT_ARGB);

        // Automatic converstion....
        ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
        op.filter(master, gray);

        return gray;
    }

    public static BufferedImage toSepia(BufferedImage img, int sepiaIntensity) {

        BufferedImage sepia = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
        // 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();

        WritableRaster raster = sepia.getRaster();

        // 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);

        //  Process 3 ints at a time for each pixel.  Each pixel has 3 RGB
        //    colors in array
        for (int i = 0; i < pixels.length; i += 3) {
            int r = pixels[i];
            int g = pixels[i + 1];
            int b = pixels[i + 2];

            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 -= sepiaIntensity;

            // normalize if out of bounds
            if (b < 0) {
                b = 0;
            }
            if (b > 255) {
                b = 255;
            }

            pixels[i] = r;
            pixels[i + 1] = g;
            pixels[i + 2] = b;
        }
        raster.setPixels(0, 0, w, h, pixels);

        return sepia;
    }
}

You can find the original message for the sepia algorithm here

And because I'm stubborn ... I changed the sepia algorithm for working with alpha-based images ...

public static BufferedImage toSepia(BufferedImage img, int sepiaIntensity) {

    BufferedImage sepia = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
    // 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();

    WritableRaster raster = sepia.getRaster();

    // 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 -= sepiaIntensity;

            // normalize if out of bounds
            if (b < 0) {
                b = 0;
            }
            if (b > 255) {
                b = 255;
            }

            color = new Color(r, g, b, color.getAlpha());
            sepia.setRGB(x, y, color.getRGB());

        }
    }

    return sepia;
}
+7

@@MadProgrammer, . , .

  • . , , .

  • getRGB + getWidth() + getHeight() + getRed(), getGreen() + getBlue().

  • , , , setRGB, . ( -, .)

  • Color getRGB().

, , , , , . , .

, , @MadProgrammer.

public static BufferedImage toSepia(BufferedImage image, int sepiaIntensity) {

    int width = image.getWidth();
    int height = image.getHeight();
    int sepiaDepth = 20;

    int[] imagePixels = image.getRGB(0, 0, width, height, null, 0, width);

    for (int i = 0; i < imagePixels.length; i++) {
        int color = imagePixels[i];

        int r = (color >> 16) & 0xff;
        int g = (color >> 8) & 0xff;
        int b = (color) & 0xff;
        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 -= sepiaIntensity;

        // normalize if out of bounds
        if (b < 0) {
            b = 0;
        }
        if (b > 255) {
            b = 255;
        }

        imagePixels[i] = (color & 0xff000000) + (r << 16) + (g << 8) + b;
    }

    BufferedImage res = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    res.setRGB(0, 0, width, height, imagePixels, 0, width);
    return res;
}
+2

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);
}

Greyscale filter

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

Image source

enter image description here

Generated images

enter image description here enter image description here enter image description here

0
source

Source: https://habr.com/ru/post/1795021/


All Articles