- - PR -
画像のjpeg変換
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-07-07 15:33
こんにちは。
今あるサイトから画像のjpeg変換を行っています。 ソースはこんな感じなのですが、8MB近いサイズの画像だと ヒープオブメモリとエラーになってしまいます。 path = "c:/test"; filename = "upimage.bmp"; fis = new FileInputStream(path + "/" + filename); image = ImageIO.read(fis); int height = 1024; int width = 1024; fis.close(); BufferedImage shrinkImage = new BufferedImage(width,height, image.getType()); Graphics2D g2d = shrinkImage.createGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); g2d.drawImage(image, 0, 0, width, height, null); String newfilename = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()) + ".jpg"; //JPEG変換ファイル名 ImageIO.write(shrinkImage, "jpg", new File(path + "/" + newfilename)); この対処法として、適切なやり方はあるのでしょうか? やっぱり、ハードのメモリ増設を行わないとだめでしょうか? | ||||||||
|
投稿日時: 2008-07-07 16:41
まずはVMの起動引数でVMの使用するメモリの上限を増やしてみましょう。
javaコマンドのドキュメントに書かれていますが、-Xmx引数で設定できます。 | ||||||||
|
投稿日時: 2008-07-07 19:22
ありがとうございます。
おっしゃる通り、256M - 512Mで試してみましたが、処理は重いままでした。 5MB近い画像ファイルではそれほど重く感じられないのですが、元画像ファイルが ある一定サイズ以上は途端に重くなってしまいます。 パレメータで設定できそうなのもVALUE_COLOR_RENDER_SPEEDぐらいしかありませんし・・。 | ||||||||
|
投稿日時: 2008-07-08 08:43
ん?問題は処理が重いことじゃなくて、ヒープエラーじゃなかったの??
それを指定しても速度は全く変わらないのですか? 次の値も有効だと思いますが、影響ないんですか? VALUE_ALPHA_INTERPOLATION_SPEED VALUE_RENDER_SPEED VALUE_ANTIALIAS_OFF VALUE_DITHER_DISABLE _________________ 「ご教授」はできません | ||||||||
|
投稿日時: 2008-07-08 12:33
Xmxなんかいじらず、ブラウザとかメーラーとかいろいろ動いている環境(古いマシンなので搭載メモリは384M + 仮想記憶)で、正常かつ短時間で動作します(vmstatを見ると、(たぶん他のプロセスが)仮想記憶を相当使っていることが分かります)。
------------------------------------------------------------- import javax.imageio.*; import java.awt.image.*; import java.io.*; import java.awt.*; import java.text.*; import java.util.*; public class Bmp2Jpg{ static BufferedImage image; public static void main(String[] args){ try{ image = ImageIO.read(new File("big.bmp")); // 12 mega byte } catch (Exception e){ e.printStackTrace(); } int width = image.getWidth(); int height = image.getHeight(); long start = System.currentTimeMillis(); BufferedImage shrinkImage = new BufferedImage(width, height, image.getType()); Graphics2D g2d = shrinkImage.createGraphics(); g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE); g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); g2d.drawImage(image, 0, 0, width, height, null); long intm = System.currentTimeMillis(); String newfilename = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date()) + ".jpg"; try{ ImageIO.write(shrinkImage, "jpg", new File(newfilename)); } catch (Exception e){ e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("until draw : " + (intm - start)); System.out.println("until write: " + (end - intm)); System.out.println("total : " + (end - start)); } } ------------------------------------------------------------ [出力] until draw : 2944 until write: 1504 total : 4448 | ||||||||
|
投稿日時: 2008-07-08 15:15
ありがとうございます。
私もたくさんのサンプルで試しているわけではないのですが、デジカメでとった下記サイズの画像変換にとても時間がかかっております。 以前、メモリヒープの問題を起こしてましたが、環境を変えることでそれは退避できています。 環境は CPU 3.2Ghz メモリ 1GB OS Windows2003 Server TomcatのJavaのメモリ使用量は256M 〜 512MBです。 で、タスクマネージャーを見る限りCPU,メモリ共に100%まで達していません。 7.91MB (3575 * 4984) JPEG オーバフローして止まっているわけではないのですが、この一枚の画像を変換するのに15分以上かかってしまいます。 画像の質によってこのような問題が出てくるということなのでしょうか? よろしくお願いします。 | ||||||||
|
投稿日時: 2008-07-08 19:28
VMの上限メモリ内で処理が行われるため、タスクマネージャで見てもVMのメモリ上限+αよりメモリ使用量が増えることはありません。 jconsoleでも使ってVMの中でのメモリ使用率やGC発生率を見てください。 推測ですが、メモリを多量に使うことでFullGCが頻発している状況にあるのではないでしょうか。 | ||||||||
|
投稿日時: 2008-07-08 19:50
> 7.91MB (3575 * 4984) JPEG
BMP -> JPGでなくて、JPG -> JPGなら、もっと単純にスケーリングできるけど…。 |