開発環境 J2SE v 1.4.1_03
RGBImageFilter クラスを使って オフスクリーン hosi[i]の画像の黒の部分を透明に
しようとしています
呼び出し方は
hosi[i]=createImage(20,20);
ura[i]=hosi[i].getGraphics();
ura[i].drawImage(背景画像,0,0,this);
ura[i].drawImage(透過gif画像,0,0,this);
hosi[i]= createImage(new FilteredImageSource(hosi[i].getSource(),new
kuro_toumei())); //重ね合わせた画像の内、黒の部分だけを透明にする
です
その後 MediaTracker を使って画像表示前にフィルター処理を実行させようとしてい
るのですが、
MediaTrackerがうまく動作しない為か、
フィルター処理がうまく動作しない、もしくは終わったと判定されない為に、
描画時に「再びフィルター処理が行われ」、ちらつきがおこります。
色々試した結果、getImage() メソッドで直接読み込んだ画像ならうまく動作するので、
フィルター処理をする前に hosi[i] の画像を Graphicsオブジェクトを使わずに 別の
Image変数にコピーして、その画像をフィルター処理しようと思うのですが、方法がわか
りません
それ以外の解決方法として、MediaTrackerの代わりに、hosi[i] の画像を別のオフスク
リーン等にコピーすることにより、フィルター処理を実行させる事も出来るのですが、
この方法だと、大きなサイズの画像を扱う場合に問題が発生する為使いたくありません
あぅ(汗)
誰もわかんないのかな?
それとも私の質問の仕方が悪かったのかしら?
どなたかヒントだけでもお願いしますぅ
質問の仕方は悪くないと思いますが、
同じ問題で悩んだ人がいないと言うことでしょうか…。
コピペするだけで現象を確認できるコードがあるといいかも。
dairygoods様 お返事ありがとうです
http://www.geocities.co.jp/SiliconValley-Oakland/9570/hosi/nagarebosi.html
に実行結果のアプレットをアップしてみました
ソースも出来る限り短縮してみました
import java.awt.*;
import java.applet.*;
import java.awt.image.*;
public class nagarebosi extends java.applet.Applet implements Runnable {
Thread th = null;
Image hosinokata , hosinomoto ;
Image ura1;
Graphics gc,gc1;
Image ura_hosi[]= new Image[10];
Graphics gc_hosi[]= new Graphics[10];
MediaTracker mt=new MediaTracker(this);
public void init(){
ura1=createImage(300,250);
gc1=ura1.getGraphics();
gc=getGraphics();
hosinokata=getImage(getCodeBase(),hosinokata.gif);
hosinomoto=getImage(getCodeBase(),hosinomoto.jpg);
mt.addImage(hosinokata,0);
mt.addImage(hosinomoto,0);
try{mt.waitForID(0);}
catch (InterruptedException e){ }
}
public void start() {
th=new Thread(this);
th.start();
}
public void run() {
/** <星作成> */
for (int i=0;i<10;i++){
ura_hosi[i]=createImage(20,20);
gc_hosi[i]=ura_hosi[i].getGraphics();
gc_hosi[i].drawImage(hosinomoto,-i,-i,this);
gc_hosi[i].drawImage(hosinokata,0,0,this);
ura_hosi[i]= createImage(new FilteredImageSource
(ura_hosi[i].getSource(),new kuro_toumei()));
mt.addImage (ura_hosi[i],0);
// gc1.drawImage(ura_hosi[i],0,0,this); //MediaTracker
の代わりの処理
}
try{mt.waitForID(0);} //フィルタ処理
の終了を待つ・・・つもり
catch (InterruptedException e){ }
/** <星の表示> */
gc1.setColor(new Color(50,0,0));
System.out.println();
for (int i=0;i<50;i+=1){
System.out.print(★);
gc1.fillRect(0,0,200,200);
gc1.drawImage(ura_hosi[i%10],0,0,this);
paint(gc);
try{Thread.sleep(200);}
catch(Exception e){System.err.println(e);}
}
}
public void stop() {
th=null;
}
public void paint(Graphics gc){
gc.drawImage(ura1, 0, 0, this);
System.out.print(■);
}
public void update(Graphics gc) {
paint(gc);
}
}
class kuro_toumei extends RGBImageFilter {
public kuro_toumei(){
System.out.print(▲);
// canFilterIndexColorModel = true;
}
public int filterRGB (int x,int y,int argb){
if (argb==0xff000000)argb=0x00000000;
if(y==0) System.out.print(△);
return argb;
}
}
それから System.out.print はappletviewer でみた時に処理の流れがわかりやすいよ
うに付け加えたものです
どうか助けて下さい お願いします
確かにdrawImageによって再度フィルタリングされているようですね。
これ自身は、そういうものなのか、制御できるのか分かりません。
> gc1.drawImage(ura_hosi[i%10],0,0,this);
drawImageに渡すImageObserverオブジェクトには、
Imageの読み込み通知が送られます。
(読み込み完了だけでなく、途中経過も通知されます)
thisを渡しているのでApplet自身に通知が来ます。
通知を受け取ったAppletは、その時点まで読み込まれた画像を
表示させるために再描画を行います。
そのため、裏画面を書いている最中に、
表画面の再描画が発生することになります。
これを防ぐため第四引数はnullとします。
gc1.drawImage(ura_hosi[i%10],0,0,null);
あと、フィルタ処理は非同期で動作するものではないようなので、
> try{mt.waitForID(0);} //フィルタ処理の終了を待つ・・・つもり
は、なくてもよさそうです。
dairygoods様 ありがとうございます
thisの代わりにnullが使えるなんて夢にも思いませんでした
だけど以前に書いた別のアプレットのソースでは確かに非同期だったんです(多分)
もっと大きなサイズの画像を連続してフィルタリングすると、途中の画像が欠けてしま
ってたんです。
ただし、そのときは
ura_hosi[i]= createImage(new FilteredImageSource
(hosinomoto.getSource(),new kuro_toumei()));
のような感じになっていたうえに、
裏画面であるhosinomotoに対して
g.drawImage・・・のような事は出来ないようなソースになってました。
もうちょっと色々試してからまた結果報告します
ありがとうでした
遅くなりましたが結果報告です
今回のケースでは画像のサイズが変わっても問題がなかったです。
それから
Image ura_hosi[]
に対して
ura_hosi[i]=createImage(20,20);
gc_hosi[i]=ura_hosi[i].getGraphics();
のような処理をしなかった場合は今回教えて頂いた方法を適用させることは出来ません
でした
この場合はMediaTrackerを使わなければフィルタリングを先にすますことは出来ません
でした
説明が変でごめんなさい
とりあえず解決はしました
ありがとうございました