忍者ブログ

軽Lab

 Javaを中心とした、プログラミング関係のナレッジベース

Home > JavaFX入門 > JavaFX 画像表示・画像処理(ピクセル操作)

JavaFX 画像表示・画像処理(ピクセル操作)

これまでも画像表示については取り扱ってきたが、今回は主に画像処理(ピクセル処理)方法についてみていく。

■ 画像出力

JavaFXでは、以下の画像ファイル形式に対応している。GIFアニメーションや、透過Gif/Pngにも対応している。

  • BMP
  • GIF
  • JPEG
  • PNG

画像の出力には、ImageViewクラスを利用する。利用方法については、サンプルコードを参照のこと。

■ 画像エフェクト、画像の重ね合わせ、クリッピング

他のシーングラフ・クラスと同様、ImageViewクラスに対してエフェクトや重ね合わせ、クリッピングなどが設定できる。詳しくは以下の記事を参照のこと。


■ ピクセル操作

画像解析を行う場合や、新しい画像エフェクトを表現したい場合、ピクセルに対して直接操作することができる。ピクセルの読書には、PixelReaderおよびPixelWriterクラスを利用する。利用方法については、サンプルコードを参照のこと。

■ サンプルコード

画像を単純に出力する方法と、ピクセル操作を行うサンプルコードを以下に示す。サンプルでは、本webサイトのヘッダー画像を

  1. 単純に出力
  2. RGB値をずらして出力(1ピクセル毎に処理)
  3. RGB値を反転(全ピクセルを一括処理)

の3種類の方法で出力している。

◇サンプルコード
package application_fx;

import java.nio.IntBuffer;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.image.WritablePixelFormat;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TestImage extends Application {

    public static void main(String[] args)
    {
        launch( args );
    }

    @Override
    public void start(Stage primaryStage) throws Exception
    {
        // シーングラフの作成
        VBox        root        = new VBox();
        
        // 単純に画像を読み込んで表示。ファイルの場合はnew File( "ファイル名" ).toURI().toString()でパスを指定する
        Image       img         = new Image( "http://file.krr.blog.shinobi.jp/header2.jpg" );
        ImageView   imgView     = new ImageView( img );
        root.getChildren().add( imgView );
        
        // ピクセル処理(RGB値をずらした)画像を作成
        WritableImage   wImg1       = createRGBMoveImage( img );
        ImageView       wImg1View   = new ImageView( wImg1 );
        root.getChildren().add( wImg1View );
        
        // ピクセル値を反転した画像を作成
        WritableImage   wImg2       = createInversionImage( img );
        ImageView       wImg2View   = new ImageView( wImg2 );
        root.getChildren().add( wImg2View );
        
        // シーンの作成
        Scene   scene       = new Scene( root );
        
        // ウィンドウ表示
        primaryStage.setScene( scene );
        primaryStage.show();
    }
    
    /**
     * RGB値をずらした画像を作成
     * 赤成分を右下に、緑成分を左上に、青成分を左下に移動させている
     * ピクセル毎にgetPixel,setPixel関数を呼びだす(内部でピクセル走査が発生する)ため、低速な処理となる
     * @param img
     * @return
     */
    public WritableImage createRGBMoveImage( Image img )
    {
        // 白紙イメージを作成
        WritableImage   wImg        = new WritableImage( (int) img.getWidth() , (int) img.getHeight() );

        // ピクセル処理
        PixelReader     reader      = img.getPixelReader();
        PixelWriter     writer      = wImg.getPixelWriter();
        for( int y = 0 ; y < wImg.getHeight() ; y++ )
            for( int x = 0 ; x < wImg.getWidth() ; x++  )
            {
                // ずれ幅の設定
                int gap     = 5;
                
                // ピクセル値を作成
                int argb    = 0x000000;
                
                // α成分を作成
                int a       = ( reader.getArgb( x , y ) >> 24 ) & 0xFF ;
            
                // 赤成分を作成
                int r_x     = ( x + gap ) % (int) img.getWidth();
                int r_y     = ( y + gap ) % (int) img.getHeight();
                int r       = ( reader.getArgb( r_x , r_y ) >> 16 ) & 0xFF ;
            
                // 緑成分を作成
                int g_x     = ( x - gap + (int) img.getWidth() ) % (int) img.getWidth();
                int g_y     = ( y - gap + (int) img.getHeight() ) % (int) img.getHeight();
                int g       = ( reader.getArgb( g_x , g_y ) >> 8 ) & 0x0FF;
                
                // 青成分を作成
                int b_x     = ( x + gap ) % (int) img.getWidth();
                int b_y     = ( y - gap + (int) img.getHeight() ) % (int) img.getHeight();
                int b       = ( reader.getArgb( b_x , b_y ) & 0xFF );
                argb        = ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
                
                // ピクセル値を設定
                writer.setArgb( x , y, argb);
            }
        
        return wImg;
        
    }
    
    /**
     * 色を反転した画像を作成する
     * ピクセル処理を一括して行うため、比較的高速な処理
     * @param img
     * @return
     */
    public WritableImage createInversionImage( Image img )
    {
        // 画像サイズを取得
        int     width   = (int) img.getWidth();
        int     height  = (int) img.getHeight();
        
        // 複製したイメージを作成
        WritableImage   wImg        = new WritableImage( width , height );
        PixelWriter     writer      = wImg.getPixelWriter();
        
        // ピクセル配列(フォーマットはARGBの順)を取得
        WritablePixelFormat<IntBuffer>  format  = WritablePixelFormat.getIntArgbInstance();
        int[]                           pixels  = new int[ width * height ]; 
        img.getPixelReader().getPixels( 0 , 0 , width , height ,
                                        format, pixels, 0 , width );
        
        // ピクセル操作
        for( int y = 0 ; y < height ; y++ )
            for( int x = 0 ; x < width ; x++ )
            {
                // ピクセルを取得
                int index   = ( y * width ) + x;
                int pixel   = pixels[ index ];
                
                // ピクセルを反転
                // α成分を作成
                int a       = ( pixel >> 24 ) & 0xFF;
            
                // 赤成分を作成
                int r       = 0xFF - ( ( pixel >> 16 ) & 0xFF );
            
                // 緑成分を作成
                int g       = 0xFF - ( ( pixel >> 8  ) & 0xFF );
                
                // 青成分を作成
                int b       = 0xFF - ( pixel & 0xFF );
                
                // ピクセルを設定
                pixel           = ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | b;
                pixels[ index ] = pixel;
            }
        
        // ピクセル配列を設定
        writer.setPixels(0 , 0 , width , height , format, pixels, 0 , width);
        
        return wImg;
    }

}
◇実行結果

◇解説
  1. プログラムの流れを見ると、3種類の画像の登録をstart関数で行っている(23行目~50行目)。
  2. 『単純に画像を出力する』場合には、Imageクラスにファイル名(URL)を指定し、ImageViewクラスに登録することで表示される。(29行目~32行目)
  3. 『RGB値をずらして出力(1ピクセル毎に処理)』する処理は、createRGBMoveImage関数内で行っている(59行目~101行目)。書込可能な画像はWritableImageクラスで作成(62行目)し、PixelReader.getArgb関数でピクセルのRGBA値を取得、PixelReader.setArgb関数でRGBA値を設定している。ピクセル値はアルファ値(8ビット)、赤成分値(8ビット)、緑成分値(8ビット)、青成分値(8ビット)の合計32ビット値のInt型に格納されているため、ビット操作により各成分値を分離して処理している。
  4. 『RGB値を反転(全ピクセルを一括処理)』する処理は、createInversionImage関数内で行っている(109行目~155行目)。一括処理する場合は、画像全体のピクセル値を持った配列をPixelReader.getPixels関数で取得し、ピクセル操作の後、PixelWriter.setPixels関数で設定している。ピクセル値はARGBの形で取得・設定するように設定している(120行目)。色の反転は、各成分の最大値0xFFから、実際の成分値を引くことで実現している。

■ 参照

  1. JavaDoc - Class Image
  2. JavaFX in the Box
Home > JavaFX入門 > JavaFX 画像表示・画像処理(ピクセル操作)

- ランダム記事 -
- PR -

コメント

プロフィール

管理者:
 連絡はContactよりお願いします。

PR