web-dev-qa-db-ja.com

ピクセルの配列をJavaのImageIOでImageオブジェクトに変換しますか?

現在、次のコードを使用して、ピクセル値の配列(元はJava.awt.image.PixelGrabberオブジェクトで作成されたもの)をImageオブジェクトに変換しています。

public Image getImageFromArray(int[] pixels, int width, int height) {
    MemoryImageSource mis = new MemoryImageSource(width, height, pixels, 0, width);
    Toolkit tk = Toolkit.getDefaultToolkit();
    return tk.createImage(mis);
}

ImageIOパッケージのクラスを使用して同じ結果を達成できるので、AWTツールキットを使用する必要はありませんか?

Toolkit.getDefaultToolkit()は100%信頼できるようには見えず、AWTErrorがスローされる場合がありますが、ImageIOクラスは常に使用可能である必要があるため、メソッドの変更に興味があります。

27

ImageIOを使用せずにイメージを作成できます。ピクセル配列の内容と一致する画像タイプを使用して、BufferedImageを作成するだけです。

public static Image getImageFromArray(int[] pixels, int width, int height) {
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            WritableRaster raster = (WritableRaster) image.getData();
            raster.setPixels(0,0,width,height,pixels);
            return image;
        }

PixelGrabberを使用する場合は、getImageFromArrayを呼び出す前に、ピクセル配列からRGBA情報を抽出することを忘れないでください。この例は、PixelGrabber javadocの handlepixelmethod にあります。それを行ったら、BufferedImageコンストラクタの画像タイプがBufferedImage.TYPE_INT_ARGBであることを確認してください。

27
Brendan Cashman

ArrayIndexOutOfBoundsExceptionを_TYPE_INT_ARGB_で作成した場合でも、ラスターを使用してBufferedImageを取得しました。ただし、BufferedImagesetRGB(...)メソッドを使用するとうまくいきました。

7
mdm

BufferedImage.getData()のJavaDocは、「画像データのcopyであるラスター」と言います。

このコードは私にとってはうまくいきますが、私はそれが効率的であることを疑っています:

        // Получаем картинку из массива.
        int[] pixels = new int[width*height];
            // Рисуем диагональ.
            for (int j = 0; j < height; j++) {
                for (int i = 0; i < width; i++) {
                    if (i == j) {
                        pixels[j*width + i] = Color.RED.getRGB();
                    }
                    else {
                        pixels[j*width + i] = Color.BLUE.getRGB();
                        //pixels[j*width + i] = 0x00000000;
                    }
                }
            }

BufferedImage pixelImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);    
    pixelImage.setRGB(0, 0, width, height, pixels, 0, width);
3
beemaster

私はJava.awt.Robotを使用してスクリーンショット(または画面のセグメント)を取得することに成功しましたが、ImageIOを使用するには、メモリイメージソースの代わりにBufferedImageに保存する必要があります。次に、ImageIOの静的メソッドを1つ呼び出し、ファイルを保存できます。次のようなものを試してください:

// Capture whole screen
Rectangle region = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
BufferedImage capturedImage = new Robot().createScreenCapture(region);

// Save as PNG
File imageFile = new File("capturedImage.png");
ImageIO.write(capturedImage, "png", imageFile);
2
Steve Moyer

これはImageIO on SOでタグ付けされた最も投票数の多い質問の1つであるため、質問が古い場合でも、より良い解決策の余地はまだあると思います。 :-)

GitHubにあるオープンソースのimageioプロジェクトの BufferedImageFactory.Java クラスをご覧ください。

それを使うと、あなたは単に書くことができます:

BufferedImage image = new BufferedImageFactory(image).getBufferedImage();

もう1つの良い点は、このアプローチは、最悪の場合、このスレッドにすでにあるPixelGrabberベースの例とほぼ同じパフォーマンス(時間)であることです。一般的なほとんどの場合(通常はJPEG)、速度は約2倍です。いずれにせよ、それはより少ないメモリを使用します。

副次的なボーナスとして、デフォルトのカラーモデルでint ARGBに変換される代わりに、元の画像のカラーモデルとピクセルレイアウトが保持されます。これにより、メモリを節約できます。

(追記:ファクトリは、サブサンプリング、関心領域、および進行状況リスナーもサポートしています。

0
haraldK