- - PR -
大きいjpegの色調調整
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-08-29 00:01
お世話になります。
画像の扱い方について質問させてください。 現在、画像ファイルを一つ読み込み、 明るさ・コントラストを変更し表示するアプリケーションを作っています。 ひととおり完成し、とりあえず動く状態にはなったのですが、 1MB程のjpegを読み込むと、java.lang.OutOfMemoryError が発生します。 PixelGrabber で int配列に取り込んでから変更をかけていたのですが、 この取り込み先の配列を宣言する部分で上記エラーが起こっています。 PixelGrabber では無理なのかと思い、BufferedImageでやろうとしたのですが、 やはり宣言部分で OutOfMemoryError が出ます。 1ファイルめから起きるので、GCが原因とは思えないのですが・・・ 実行時に -Xmx128mを指定しても変わらずでした。 うまいメモリの使い方をご存知の方 またPixelGrabber、BufferedImage以外のやり方をご存知の方いらっしゃいましたら ご教授おねがいします。 ------- public void paint(Graphics g){ int[] pixels; image = Toolkit.getDefaultToolkit().getImage(filepath); pixels = new int[image.getWidth(this)*image.getHeight(this)];←←ここでエラー | ||||||||
|
投稿日時: 2003-08-29 00:45
こんにちは。
Toolkit#getImage()は非同期なので、すぐに読み込みが完了するとは限りません。その場合、Image#getWidth()は-1を返します。 幅を得る前に、MediaTrackerで読み込み完了を待つ必要があると思います。 #追記 的外れだったみたいです。すみません。 [ メッセージ編集済み 編集者: ocean 編集日時 2003-08-29 10:36 ] | ||||||||
|
投稿日時: 2003-08-29 01:23
unibon です。こんにちわ。
もし JPEG ファイルの容量が 1MB だとすれば、 それを展開したイメージが使うメモリ量は、数十MBのはずです。 すでに getImage でメモリを消費している上に、 PixelGrabber 用に新たに同程度のメモリを確保しようとしていて、 実際にメモリが足りないだけなのではないでしょうか。
の中の、 image.getWidth(this)*image.getHeight(this) の値が実際にいくつなのかを確認されてはどうでしょうか。 また、エラーになる直前の時点でのメモリ使用量を、調べてみてはどうでしょか。 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=3772&forum=12 などのやりかたで Runtime.totalMemory や Runtime.freeMemory の値を見ます。 もしメモリが本当に足りないようならば、 PixelGrabber はイメージ全体ではなくイメージの一部を対象にできるので、 分割して使うことで対処できるかもしれません。 #あるいは、他のイメージ処理用の API などを使う手もあるのかもしれません(良くは知らないですが)。 | ||||||||
|
投稿日時: 2003-08-29 05:01
こんにちは。さくらばです。
この手の処理を PixelGrabber でやるのが間違いの元だったりします どうすればいいかというと、Java2D でイメージ処理のクラスが提供されているのでそれを使えばいいと思います。 Java2D のイメージ処理は基本的にはフィルタ処理になり、BufferedImageOp というインタフェースをインプリ メントしたクラスを使用します。 明るさ、コントラストを変更したいのであれば RescaleOp が使用できます。 サンプルを添付したので、試してみてください。Image IO を使っているので J2SE 1.4 以上でお願いします。 引数として ファイル名、スケーリングファクタ、オフセット の順になっています。 いちおう、200 万画素 1MB の JPEG ではデフォルトで OK でした。また、Canon EOS-1Ds のサンプルを Canon のサイトからダウンロードしてやって見ましたが、-Xmx96m をつければ OK でした。ちなみに 1110 万画素、 ファイルサイズは 4.6 MB でした。 参考 http://java.sun.com/j2se/1.4/ja/docs/ja/guide/2d/spec/j2d-image.fm8.html
| ||||||||
|
投稿日時: 2003-08-29 12:48
unibon です。こんにちわ。
推測になりますが、128MB もあれば、 たいていの JPEG ファイルは扱えそうな気もします。 もしかしたら、たとえば、 java MyImageConverter MyBigFile.jpg -Xmx128m のような感じでcapさんのオプションの指定が誤っている可能性もわずかにあるかも、 と思いました。 (ただしくはつぎのような感じです。) java -Xmx128m MyImageConverter MyBigFile.jpg #あるいはもともとそれに見合った物理メモリがないなど。 | ||||||||
|
投稿日時: 2003-08-30 01:17
oceanさん、unibonさん、さくらばさん ご回答ありがとうございます。
返信遅れまして申し訳ありません oceanさん、ご指摘ありがとうございます。 原文の方ではgetImageの直後にMediaTracker.addImageと.waitForAllをつけています ソース提示を省いてしまいスイマセン unibonさん、ご忠告ありがとうございます。 エラー直前の状況をしらべたところ、 totalMemory :66650112 freememory :41546328 画像幅 :7680 画像高 :1920 幅*高 :14745600 (テスト環境 WIN2K メモリ192M 982KBのイメージ) でした。 確かにこの幅*高のint配列っていったら持ち切れなさそうですね・・・ PixelGrabberをImage分割で行う方法も試してみようと思います。 さくらばさん、サンプル提示ありがとうございます。 RescaleOpですか・・・知らなかった・・・ 勉強してからこの方法も試してみようと思います。 追記:スイマセンRescaleOpでも解決せずです 単純にサンプルでかすぎるんでしょうか 5Mのjpgでも3000*2000ぐらいのものなら表示できるんですが・・・ [ メッセージ編集済み 編集者: cap 編集日時 2003-09-05 18:23 ] | ||||||||
|
投稿日時: 2003-09-08 17:42
こんにちは、さくらばです。
試しに Image I/O と com.sun.image.codec.jpeg.JPEGImageDecoder を使ってどのくらい メモリが使われているか調べてみました。基本的には前に示したサンプルですが、GUI の 部分は削ってあり純粋に画像のロード (RescapeOp を使用していない場合) と画像変換 (RescapeOp を使用している場合) を調べてみました。 測定にはプロファイラの JProbe を使用しました。単位は KB です。
JPEGImageDecoder で RescapeOp を使うとメモリが倍になるのは、Image I/O とカラー モデルが違うからのようです。 ともあれ、大体のメモリ使用量がはっきりすれば、読み込む画像のサイズによって -Xmx で調節できそうです。 もっと自動的に行いたい場合は Image I/O を使えば画像をロードする前に、画像の 大きさを取得することができる & 分割ロードができるので、大きさを見て OutOfMemory になりそうな場合は分割ロードをするなどの対処法が考えられれます。 |
1