web-dev-qa-db-ja.com

Java:BufferedImageを透明なピクセルで埋める

タイプBufferedImage.TYPE_INT_ARGBで構築されたオフスクリーンのBufferedImageがあります。何でも含めることができ、画像を透明なピクセルで(かなり効率的に)完全に上書きして、「見えない」画像にする方法を探しています。

このようなものを使用する:

    (bufimg.getGraphics()).setColor(new Color(10, 10, 100, 0));   
    (bufimg.getGraphics()).fillRect (0, 0, x, y);

効果はありません。考えられる方法の1つは、BufferedImageのすべてのピクセルを上書きすることですが、これが最善の解決策かどうかはわかりません。どうしますか?

[編集]
グラフィックスのドキュメントでは、オフスクリーン画像にclearRectを使用しないようにアドバイスされていますが、上記と同じ結果で試してみました。

[編集2]
MeBigFatGuyのコードを試した後(ありがとう!)、画像がクリアされます。ただし、そのイメージへのそれ以上のペイントも停止します(または表示されます)。このコードの例:

    BufferedImage img = new BufferedImage (600, 600, BufferedImage.TYPE_INT_ARGB);
    Graphics g = img.createGraphics ()    
    g.drawLine (100, 100, 500, 500);
    AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
    g.setComposite(composite);
    g.setColor(new Color(0, 0, 0, 0));
    g.fillRect(0, 0, 600, 600);
    graphicsAI.setColor(new Color (10, 10, 10, 255));
    graphicsAI.drawLine (100, 100, 500, 500);

画像には何も表示されません(画像をJPanelに描画しています)。これはアルファ値の追加と関係がありますか?

19
JBenson

BufferedImageの基になるint[]配列を取得できます(互換性のある形式、つまりint[]に裏打ちされた形式を使用してください)。

次に、int[]にアルファ値が0のintを入力します(0で十分です;)

System.arraycopy非常に高速になります。

int[]に直接書き込むことは、setRGBを使用するよりもlot高速であることを知っておく必要があります。

現在、BufferedImageはJavaのちょっとした黒魔術です。何をしているのか、どのプラットフォーム/ JVMで行っているのかに応じて、mayハードウェアアクセラレーションを失います(mayは、そもそもそこになかった可能性があります)。それに加えて、たとえば、60以上のFPSをプレイ可能にする必要があるゲームなどに取り組んでいない可能性があるため、ハードウェアアクセラレーションについてはまったく気にしないかもしれません。

これは非常に複雑なトピックであり、BufferedImage猫の皮を剥ぐ方法は複数あります。私に関する限り、ピクセルレベルで混乱しなければならないときは、int[]で直接作業します。これは、高レベルの描画プリミティブを使用するよりもはるかに理にかなっていると思うからです。 本当にハードウェアアクセラレーションが失われる可能性については気にしないでください。

9
SyntaxT3rr0r

CLEARコンポジットで背景をクリアした後、通常どおりに描画するには、SRC_OVERに戻す必要があります。例:

//clear
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
g2.fillRect(0,0,256,256);

//reset composite
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
//draw
g2.setPaint(Color.RED);
g2.fillOval(50,50,100,100);
24
Josh Marinacci

GraphicsオブジェクトをGraphics2Dオブジェクトにキャストする場合、Compositeオブジェクトを介して設定できます。

AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setComposite(composite);
g2d.setColor(new Color(0, 0, 0, 0));
g2d.fillRect(0, 0, 10, 10);
5
MeBigFatGuy

グラフィックオブジェクトの背景を設定することは仕事をしているようです:

g.setBackground(new Color(0, 0, 0, 0));

(少なくともスケーリングの目的で画像を描画する場合)

0
Brad Mace

うまくいかないとおっしゃっていましたが、私はclearRectをうまく使いました。

現在の描画面の背景色で塗りつぶして、指定した長方形をクリアします。この操作では、現在のペイントモードは使用されません。

Java 1.1から、オフスクリーン画像の背景色はシステムに依存する場合があります。アプリケーションでは、setColorの後にfillRectを使用して、オフスクリーン画像が特定の色にクリアされるようにする必要があります。


指定された長方形を塗りつぶします。長方形の左端と右端はxとx +幅-1にあります。上端と下端はyとy +高さ-1にあります。結果の長方形は幅ピクセル幅×高さピクセル高さの領域をカバーします。長方形は、グラフィックスコンテキストの現在の色を使用して塗りつぶされます。

ここでは、一方がset長方形を背景色に、もう一方がPaint現在の色の上に前景色を表示することは明確に述べられていませんが、それがそうです。

これは純粋な推測ですが、オフスクリーン画像に関する注記は、ネイティブであるため、オフスクリーンAWTコンポーネントから取得されたGraphicsオブジェクトに関連していると思います。 BufferedImageの背景色がシステムにどのように依存するかは想像もつきません。 APIドキュメントはGraphics用であるため、これはBufferedImageの場合には適用されない一般化である可能性があります。

私のテストコード:

JFrame jf = new JFrame();
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

BufferedImage img = new BufferedImage(200, 300, BufferedImage.TYPE_INT_ARGB);

Graphics2D g = img.createGraphics();

//fill right half with opaque white
g.setColor(Color.WHITE);
g.fillRect(100, 0, 100, 300);

//leave top third as it is

//fill middle third with transparent color
g.setColor(new Color(0, true));
g.fillRect(0, 100, 200, 100);

//clear bottom third with transparent color
g.setBackground(new Color(0, true));
g.clearRect(0, 200, 200, 100);

g.dispose();

jf.add(new JLabel(new ImageIcon(img)));

jf.pack();
jf.setVisible(true);

結果は、右上の2つの白い正方形になります。白がペイントされていない場合、またはclearRectを使用して白を上書きした場合、結果はフレームのデフォルトの背景色であるライトグレーになります。

パフォーマンス面では、通常の描画です。 arraycopyの方が速いかもしれませんが、私にはわかりませんが、少なくともこれは、他の描画操作と同じようにハードウェアアクセラレーションである可能性があります。

アレイソリューションに対するプラスポイントは、a)追加のメモリがなく、b)カラーモデルからの独立性です。これは、イメージがどのように設定されていても機能するはずです。

コンポジットソリューションと比較した場合のマイナス点は、長方形のクリアのみが許可されることです。コンポジットを設定すると、あらゆる種類の形状をクリアできます。

0
Silly Freak

彼は前景のピクセルを透明に設定したいと思っていますが、あなたの答えは間違いなく正しい答えです。

private Color transparent = new Color(0, true);

((Graphics2D) g).setBackground(transparent);

g.clearRect(0, 0, w, h);

背景を透明に設定します。

ところで:他の答えはほとんどがゴミか単にFUDです。技術フォーラムで「バッファリングされた画像がブラックアートである」という回答は受け入れないでください。

0
user1135940