- PR -

JAI について

1
投稿者投稿内容
なっちゃん
会議室デビュー日: 2004/03/19
投稿数: 7
投稿日時: 2008-12-12 11:38
JAIを使用して画像を圧縮するプログラムを作成したのですが、
圧縮したファイルをJAIがファイルを開放してくれない為、
圧縮ファイルの削除処理に失敗します。

ファイルの削除前にSystem.gc();を実行すると削除は可能になります。

また、TomCatを使用してサーブレット側で同処理を実行しても同じ結果で、
エクスローラ上でもファイルを削除できませんでした。
※TomCatを停止するとエクスプローラ上からファイルを削除できます。

JAIを使用された方やこの問題の原因がお解りの方がおられましたら
ご教授ください。

実際のソースコードは以下の通りです

package image;

import java.awt.image.renderable.ParameterBlock;
import java.io.File;

import javax.media.jai.Interpolation;
import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;

import org.apache.commons.io.IOUtils;

import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.JPEGEncodeParam;

public class Test {

/**
* @param args
*/
public static void main(String[] args) {
for( int i = 0 ; i < 10 ; i++ ){
String outFile = "C:\\testOut" + i + ".jpg";
test("C:\\testIn.jpg",outFile);
System.gc();
if(!new File(outFile).delete()) {
System.out.println("削除失敗:" + outFile);

}
}
}
/**
* 圧縮
* @param inFile
* @param outFile
* @return
*/
private static boolean test(String inFile, String outFile) {
long size = 100; // 縮小するピクセル数
float quality = 0.6f; // 圧縮率
FileSeekableStream stream = null;
RenderedOp op = null;
try {
// 画像ファイルの読み込み
stream = new FileSeekableStream(inFile);
RenderedOp image1 = JAI.create("stream", stream);
// 画像の縮小
Interpolation interp = Interpolation.getInstance(Interpolation.INTERP_BILINEAR);
int width = image1.getWidth(); // 現在の幅
int height = image1.getHeight(); // 現在の高さ
float scaleX = (float)size / (float)width; // 幅の変更倍率
float y = scaleX * (float)height;//(size * height)/width;
float scaleY = y / (float)height;// 高さの変更倍率

ParameterBlock params = new ParameterBlock();
params.addSource(image1);
params.add(scaleX); // 幅変更の倍率
params.add(scaleY); // 高さ変更の倍率
params.add(0.0F);
params.add(0.0F);
params.add(interp);

// 画像の縮小
RenderedOp image2 = JAI.create("scale", params);

// 画像の書き出し
// 圧縮
JPEGEncodeParam encParam = new JPEGEncodeParam();
encParam.setQuality(quality);
op = JAI.create("filestore", image2, outFile, "JPEG", encParam);


image2.dispose();
image2.dispose();
op.dispose();
} catch (Exception e) {
return false;
}


finally{
IOUtils.closeQuietly(stream);
}
return true;
}
}



かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2008-12-12 13:30
引用:

image2.dispose();
image2.dispose();


コード:
image1.dispose();
image2.dispose(); 


じゃなくて?
なっちゃん
会議室デビュー日: 2004/03/19
投稿数: 7
投稿日時: 2008-12-12 13:44
早速の返信ありがとうございます

image1.dispose();
すみません。これは単純な間違いでした。
上記指摘を修正してみたのですが
それでもやはり削除に失敗します。






[ メッセージ編集済み 編集者: なっちゃん 編集日時 2008-12-12 13:48 ]

[ メッセージ編集済み 編集者: なっちゃん 編集日時 2008-12-12 13:49 ]
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2008-12-12 15:41
確実に全てのdisposeが呼ばれているのでしょうか。
例外をキャッチしてfalseを返しているようですが、
例外を出力したら何か出ていたりしていませんか。

これ以上はJAIを使ったことがないので、
アドバイスは難しいです。中途半端なアドバイスですみません。
なっちゃん
会議室デビュー日: 2004/03/19
投稿数: 7
投稿日時: 2008-12-12 16:03
ご返答ありがとうございます

image1.dispose();
image2.dispose();
op.dispose();
System.out.println("処理終了");

} catch (Exception e) {
e.printStackTrace();
return false;
}
上記コードを書いてコンソールに「処理終了」が出力される事を確認しましたので
例外は発生していない事は確認してみました。

また、System.gc();を使用した場合はループで100回実行すると100ファイル中、失敗したのが2〜3ファイルとなりましたがSystem.gc();を使用しないと100ファイルとも失敗しました。


だっちょ
大ベテラン
会議室デビュー日: 2006/12/05
投稿数: 115
投稿日時: 2008-12-12 16:30
 単にfinalize処理が遅延しているせいではないのですか?
下のようにしてもだめですか?

コード:

finally {
if (stream!=null) {
IOUtils.closeQuietly(stream);
stream.close();
}
return false;
}
return true;


(勘違いしてたので、ちょっと修正)


[ メッセージ編集済み 編集者: だっちょ 編集日時 2008-12-15 08:45 ]
なっちゃん
会議室デビュー日: 2004/03/19
投稿数: 7
投稿日時: 2008-12-15 09:23
ご回答ありがとうございます。
下記のコードで試してみたのですが削除に失敗します。
また、デバッグしてみたのですが
IOUtils.closeQuietly(stream);
stream.close();
の両方とも処理は実行されていて例外は発生していない事は確認できています。
1

スキルアップ/キャリアアップ(JOB@IT)