PDF:

Merlin の魔術: Porter-Duff のルール!
Java 2D が残りの 4 つのルールを追加
John Zukowski
President
JZ Ventures, Inc.
2001年 9月 01日
Java 言語による二次元グラフィックス・プログラミングがちょっとした進化を遂げています。
これまでディジタル・イメージ合成に関する 12 の Porter-Duff ルールのうち 8 項目しかサポー
トしていなかった AlphaComposite クラスは、12 項目すべてをサポートするようになりまし
た。Merlin の魔術の今回の記事で、John Zukowski は 12 の全ルールに言及し、インタラクティ
ブ・プログラムを通じてそのはたらきを紹介しています。
このシリーズの他の記事を見る
かつて 1984年に、Thomas Porter と Tom Duff は、「Compositing Digital Images」というテーマの
論文を著し、2 つのイメージを合成する場合の 12 のルールについて論じました。こうした合成の
ルールに対するサポートは、Java 言語のバージョン 1.2 で最初に導入された AlphaComposite クラ
スにみられます。現在ベータ 2 となっているバージョン 1.4 は、12 のルールすべてをサポートし
ます。
合成に対するサポートは、背景イメージやプレーヤー・キャラクター・イメージなどの複数のイ
メージ・タイプを含むゲームのようなアプリケーションで必要になります。常に背景の上にプ
レーヤーを描くことは簡単ですが、プレーヤーが木の向こうにジャンプするような状況では、
キャラクター・イメージが木のイメージの後ろに姿を消すような効果が欲しくなることでしょ
う。こんな時こそ、合成が役立ちます。
Porter と Duff の 12 のルール
AlphaComposite クラスには 12 の定数があり、それぞれが各ルールに対応しています。ルールが
どのように適用されるのかを説明すると、込み入ったことになるおそれもあるので、稼動中の各
ルールを図解して説明します。イメージが不透明でない場合には、実際の組み合わせも異なって
きます。リスト 1 に示されているデモンストレーション・プログラムは、参考文献のセクション
でダウンロードできるので、さまざまな透過レベルで試してみることができます。
注: Merlin リリースで新たに加えられたルールには、アスタリスク (*) を付けてあります。
ルール 1.AlphaComposite.CLEAR: 結合イメージ (combined image) には何も描画されません。
© Copyright IBM Corporation 2001
Merlin の魔術: Porter-Duff のルール!
商標
ページ 1 / 11
developerWorks®
ibm.com/developerWorks/jp/
AlphaComposite.CLEAR
ルール 2.AlphaComposite.SRC: SRC はソースを意味します。ソース・イメージ (source image) だけ
が結合イメージに含まれます。
AlphaComposite.SRC
ルール 3.AlphaComposite.DST*: DST は宛先を意味します。宛先イメージ (destination image) だけ
が、結合イメージに含まれます。
AlphaComposite.DST
ルール 4.AlphaComposite.SRC_OVER: ソース・イメージが宛先イメージの上に描画されます。
Merlin の魔術: Porter-Duff のルール!
ページ 2 / 11
ibm.com/developerWorks/jp/
developerWorks®
AlphaComposite.SRC_OVER
ルール 5.AlphaComposite.DST_OVER: 宛先イメージがソース・イメージの上に描画されます。
AlphaComposite.DST_OVER
ルール 6.AlphaComposite.SRC_IN: ソース・イメージのうちの宛先イメージと重なる部分だけが描
画されます。
AlphaComposite.SRC_IN
ルール 7.AlphaComposite.DST_IN: 宛先イメージのうちのソース・イメージと重なる部分だけが描
画されます。
Merlin の魔術: Porter-Duff のルール!
ページ 3 / 11
developerWorks®
ibm.com/developerWorks/jp/
AlphaComposite.DST_IN
ルール 8.AlphaComposite.SRC_OUT: ソース・イメージのうちの宛先イメージと重ならない部分だけ
が描画されます。
AlphaComposite.SRC_OUT
ルール 9.AlphaComposite.DST_OUT: 宛先イメージのうちのソース・イメージと重ならない部分だけ
が描画されます。
AlphaComposite.DST_OUT
ルール 10.AlphaComposite.SRC_ATOP*: ソース・イメージのうちのソース・イメージと重なる部分
が、宛先イメージのうちのソース・イメージと重ならない部分とともに描画されます。
Merlin の魔術: Porter-Duff のルール!
ページ 4 / 11
ibm.com/developerWorks/jp/
developerWorks®
AlphaComposite.SRC_ATOP
ルール 11.AlphaComposite.DST_ATOP*: 宛先イメージのうちのソース・イメージと重なる部分が、
ソース・イメージのうちの宛先イメージと重ならない部分とともに描画されます。
AlphaComposite.DST_ATOP
ルール 12.AlphaComposite.XOR*: ソース・イメージのうちの宛先イメージと重ならない部分が、宛
先イメージのうちのソース・イメージと重ならない部分とともに描画されます。
AlphaComposite.XOR
Merlin の魔術: Porter-Duff のルール!
ページ 5 / 11
developerWorks®
ibm.com/developerWorks/jp/
完結した例
次に示すプログラムは、アルファ合成ルールのインタラクティブ・デモンストレーションです。
各トライアングルの不透過度を変更し、イメージの合成による効果を確かめるために使うルール
を選んでみてください。
リスト 1. インタラクティブな例
import
import
import
import
import
import
import
import
java.awt.*;
java.awt.event.*;
java.awt.geom.*;
java.awt.image.*;
java.lang.reflect.*;
javax.swing.*;
javax.swing.event.*;
java.util.*;
public class CompositeIt extends JFrame {
JSlider sourcePercentage = new JSlider();
JSlider destinationPercentage = new JSlider();
JComboBox alphaComposites = new JComboBox();
DrawingPanel drawingPanel = new DrawingPanel();
public CompositeIt() {
super("Porter-Duff");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = (JPanel) this.getContentPane();
Dictionary labels = new Hashtable();
labels.put(new Integer(0),
new JLabel("0.0"));
labels.put(new Integer(25), new JLabel("0.25"));
labels.put(new Integer(33), new JLabel("0.33"));
labels.put(new Integer(50), new JLabel("0.50"));
labels.put(new Integer(67), new JLabel("0.67"));
labels.put(new Integer(75), new JLabel("0.75"));
labels.put(new Integer(100), new JLabel("1.00"));
sourcePercentage.setOrientation(JSlider.VERTICAL);
sourcePercentage.setLabelTable(labels);
sourcePercentage.setPaintTicks(true);
sourcePercentage.setPaintLabels(true);
sourcePercentage.setValue(100);
sourcePercentage.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
int sourceValue = sourcePercentage.getValue();
drawingPanel.setSourcePercentage(sourceValue/100.0f);
}
});
destinationPercentage.setOrientation(JSlider.VERTICAL);
destinationPercentage.setLabelTable(labels);
destinationPercentage.setPaintTicks(true);
destinationPercentage.setPaintLabels(true);
destinationPercentage.setValue(100);
destinationPercentage.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
int destinationValue = destinationPercentage.getValue();
drawingPanel.setDestinationPercentage(destinationValue/100.0f);
}
});
String rules[] = {
"CLEAR",
"DST",
"DST_ATOP", "DST_IN",
"DST_OUT", "DST_OVER",
"SRC",
"SRC_ATOP",
"SRC_IN",
"SRC_OUT",
"SRC_OVER", "XOR"};
ComboBoxModel model = new DefaultComboBoxModel(rules);
alphaComposites.setModel(model);
Merlin の魔術: Porter-Duff のルール!
ページ 6 / 11
ibm.com/developerWorks/jp/
developerWorks®
alphaComposites.setSelectedItem("XOR");
alphaComposites.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String alphaValue = alphaComposites.getSelectedItem().toString();
Class alphaClass = AlphaComposite.class;
try {
Field field = alphaClass.getDeclaredField(alphaValue);
int rule = ((Integer)field.get(AlphaComposite.Clear)).intValue();
drawingPanel.setCompositeRule(rule);
} catch (Exception exception) {
System.err.println("Unable to find field");
}
}
});
contentPane.add(sourcePercentage, BorderLayout.WEST);
contentPane.add(destinationPercentage, BorderLayout.EAST);
contentPane.add(alphaComposites, BorderLayout.SOUTH);
contentPane.add(drawingPanel, BorderLayout.CENTER);
pack();
}
public static void main(String args[]) {
new CompositeIt().show();
}
class DrawingPanel extends JPanel {
GeneralPath sourcePath, destPath;
BufferedImage source, dest;
float sourcePercentage = 1, destinationPercentage = 1;
int compositeRule = AlphaComposite.XOR;
Dimension dimension = new Dimension(200, 200);
public DrawingPanel() {
sourcePath = new GeneralPath();
sourcePath.moveTo(0,
0);
sourcePath.lineTo(150, 0);
sourcePath.lineTo(0, 200);
sourcePath.closePath();
source = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
destPath = new GeneralPath();
destPath.moveTo(200, 0);
destPath.lineTo(50, 0);
destPath.lineTo(200, 200);
destPath.closePath();
dest = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
}
public void setSourcePercentage(float value) {
sourcePercentage = value;
repaint();
}
public void setDestinationPercentage(float value) {
destinationPercentage = value;
repaint();
}
public void setCompositeRule(int value) {
compositeRule = value;
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
Graphics2D sourceG = source.createGraphics();
Graphics2D destG = dest.createGraphics();
destG.setComposite(AlphaComposite.Clear);
destG.fillRect(0, 0, 200, 200);
destG.setComposite(AlphaComposite.getInstance(
Merlin の魔術: Porter-Duff のルール!
ページ 7 / 11
developerWorks®
ibm.com/developerWorks/jp/
AlphaComposite.XOR, destinationPercentage));
destG.setPaint(Color.magenta);
destG.fill(destPath);
sourceG.setComposite(AlphaComposite.Clear);
sourceG.fillRect(0, 0, 200, 200);
sourceG.setComposite(AlphaComposite.getInstance(
AlphaComposite.XOR, sourcePercentage));
sourceG.setPaint(Color.green);
sourceG.fill(sourcePath);
destG.setComposite(AlphaComposite.getInstance(compositeRule));
destG.drawImage(source, 0, 0, null);
g2d.drawImage(dest, 0, 0, this);
}
public Dimension getPreferredSize() {
return dimension;
}
}
}
Merlin の魔術: Porter-Duff のルール!
ページ 8 / 11
ibm.com/developerWorks/jp/
developerWorks®
ダウンロード
内容
j-mer0918.zip
Merlin の魔術: Porter-Duff のルール!
ファイル名
j-mer0918.zip
サイズ
ページ 9 / 11
developerWorks®
ibm.com/developerWorks/jp/
参考文献
• シリーズ「Merlin の魔術」のその他の記事もお読み下さい。
• さまざまな Porter-Duff ルールについては、原典の SigGraph paper をお読みください。
• Java 2 SDK, 1.4 の新たな Java 2D features について理解を深めてください。
• 「The Java 2 user interface」(developerWorks、2001年 7月) で Java UI の発展過程についてお読
みください。
• IBM ではグラフィックスとビジュアリゼーションの分野で幅広い研究を行っています。現在
進行中のプロジェクトをご覧ください。
• John Zukowski による、以下の Merlin のヒント集もご一読ください。
• Swing の新たな Spinner コンポーネント: JSpinner を使用して、ユーザーがピック・リス
トから素早く日付、数値および選択肢を選べるようにする
• もう 1 つのシンプルなフレーム: AWT Frame を最大化し、その装飾を取り外す
• 長期の永続性: JavaBean コンポーネントの状態を XML にシリアライズする
• 挿入順序を保持する: 新たにリンクされた HashSet と HashMap の実装を使ってみる
• タブ付きペインのスクロール: 大き過ぎて収まりきらない場合にどうするか
• developerWorks の Java ゾーンで他の Java 参考文献をご覧ください。
Merlin の魔術: Porter-Duff のルール!
ページ 10 / 11
ibm.com/developerWorks/jp/
developerWorks®
著者について
John Zukowski
John Zukowski は、JZ Ventures, Inc. の戦略的 Java コンサルティングを推進し、数多く
の jGuru のコミュニティー主導の Java FAQs で常任指導者として活躍しています。最
新の著書には、Apress から出版された「 Java Collections」および「 Definitive Guide
to Swing for Java 2」 (第 2 版) があります。
© Copyright IBM Corporation 2001
(www.ibm.com/legal/copytrade.shtml)
商標
(www.ibm.com/developerworks/jp/ibm/trademarks/)
Merlin の魔術: Porter-Duff のルール!
ページ 11 / 11
Similar pages
PDF