概要

JavaのBufferedImageを使って画像をモノクロ化してみましょう!画像の読み込みはImageIOで行えます。ImageIOのreadメソッドにFileオブジェクトを渡すとBufferedImageが返ってきます。この処理は以下のように書けます。(ここではあえて型推論を使わず型を明示的に書いています。)

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

画像のモノクロ化

画像をモノクロ化する方法はいくつかありますが、今回は各ピクセルの光りの三原色である赤、緑、青の値を足して3で割ったものを赤、緑、青にそれぞれを割り当てる方法をとります、

ソースコード

import javax.swing.JFrame;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JFileChooser;

import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;

import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

import java.awt.Graphics;
import java.awt.Dimension;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;

import java.io.File;
import javax.imageio.ImageIO;

import java.util.Optional;

import java.io.IOException;

public class MonoImageSample extends JComponent{
    private Optional<BufferedImage> monoImage;

    public static void main(String... args){
        SwingUtilities.invokeLater(MonoImageSample::start);
    }

    private static void start(){
        var frame = new JFrame();
        var sample = new MonoImageSample();
        var scroll = new JScrollPane(sample);

        var menubar = new JMenuBar();
        var fileMenu = menubar.add(new JMenu("ファイル(F)"));
        fileMenu.setMnemonic('F');

        var openItem = fileMenu.add(new JMenuItem("開く(O)", 'O'));
        openItem.setAccelerator(KeyStroke.getKeyStroke('O', InputEvent.CTRL_DOWN_MASK));

        openItem.addActionListener(e -> {
            var fileChooser = new JFileChooser();

            if(fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION){
                try{
                    sample.load(fileChooser.getSelectedFile());
                }catch(IOException ex){
                    JOptionPane.showMessageDialog(frame, "ファイルの読み込みに失敗しました", "エラー", JOptionPane.ERROR_MESSAGE);
                    ex.printStackTrace();
                }
            }
        });

        scroll.setPreferredSize(new Dimension(600, 500));

        frame.add(scroll);
        frame.setJMenuBar(menubar);

        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
    }

    public MonoImageSample(){
        monoImage = Optional.empty();
    }

    public void load(File file) throws IOException{
        //画像ファイルを読み込みモノクロ画像用のBufferedImaageを用意する
        var image = ImageIO.read(file);
        var dstImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
        monoImage = Optional.of(dstImage);

        for(int y = 0; y < image.getHeight(); y++){
            for(int x = 0; x < image.getWidth(); x++){
                int rgb = image.getRGB(x, y);
                
                //RGBをそれぞれ取り出す
                int r = (rgb >> 16) & 0xFF;
                int g = (rgb >> 8) & 0xFF;
                int b = rgb & 0xFF;
                
                //RGBの和を3で割ったものをRGBのそれぞれの値とする
                int mono = (r + g + b) / 3;
                dstImage.setRGB(x, y, 0xFF000000 | (mono << 16) | (mono << 8) | mono);
            }
        }

        setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
        repaint();
    }

    @Override
    public void paintComponent(Graphics g){
        monoImage.ifPresent(image -> g.drawImage(image, 0, 0, this));
    }
}

実行結果

実行した時点では何も表示されないのでメニューバーのファイルメニューから開くを選んで画像を選んでみてください。そうすると以下のようにモノクロ画像が表示されます