Javaで画像縮小
Javaで画像をリサイズすることになったので、試した結果を纏めてみます。
Javaで画像処理した人なら、ImageMagickを使えるJMagickやOpenCVを使えるJavaCVを使うかなと思います。
今回はサーバ等にインストールしないで使えるLibrary等を使って軽く検証。
画像ファイルの読み込み書き込みは共通の以下のコード
public static BufferedImage readImageFile(File file) { return ImageIO.read(file); } public static void writeImageFile(BufferedImage image) { try { ImageIO.write(image, "JPG", new File("hoge.JPG")); } catch (IOException e) { e.printStackTrace(); } }
リサイズ処理は以下の5パターン。
- BufferedImage#getScaledInstance()
public static BufferedImage reSize1(BufferedImage image, int width, int height) { BufferedImage thumb = new BufferedImage(width, height, image.getType()); thumb.getGraphics().drawImage(image.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING), 0, 0, width, height, null); return thumb; }
- Graphics2D#drawImage()
public static BufferedImage reSize2(BufferedImage img, int width, int height) { BufferedImage thmb = new BufferedImage(width, height, img.getType()); Graphics2D g2d = thmb.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(img, 0, 0, width, height, null); return thmb; }
- java-image-scaling-0.8.5.jar
public static BufferedImage reSize3(BufferedImage img, int width, int height) { ResampleOp resampleOp = new ResampleOp(width, height); resampleOp.setFilter(ResampleFilters.getLanczos3Filter()); resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.VerySharp); BufferedImage rescaled = resampleOp.filter(img, null); return rescaled; }
- img-scalr-lib-4.2.jar
public static BufferedImage reSize4(BufferedImage img, int width, int height) { BufferedImage thmb = Scalr.resize(img, Scalr.Method.ULTRA_QUALITY, Scalr.Mode.FIT_EXACT, width, height, Scalr.OP_ANTIALIAS); return thmb; }
- thumbnailator-0.4.6.jar
public static BufferedImage reSize5(BufferedImage img, int width, int height) { BufferedImage thmb = null; try { thmb = Thumbnails.of(img) .size(width, height) .outputQuality(1.0f) .rotate(90) // 画像のローテートも可能 .asBufferedImage(); } catch (IOException e) { e.printStackTrace(); } return thmb; }
上の5パターンで試した結果java-image-scalingが一番綺麗にリサイズされる。
ただjpgとかだとExifのOrientationからrotateしたいなって時に出来ないのが難点。。。
img-scalr-libはjava-image-scalingには劣るけど、大差はないかな。
また別メソッドでrotate出来るので使い勝手は良さそう!
private static BufferedImage rotate1(BufferedImage img) { BufferedImage thmb = Scalr.rotate(img, Scalr.Rotation.CW_90, Scalr.OP_ANTIALIAS); return thmb; }
品質もかなり良い感じ。
thumbnailator-0.4.6.jarは上のコードでも書いてる通りリサイズと同時にrotate出来るのでコード自体は少なくて綺麗に書けます。
他にもOrientationが分かれば簡単にrotateしてくれるメソッドも用意されてる!
private static BufferedImage rotate2(BufferedImage img) { BufferedImage thmb = ExifFilterUtils.getFilterForOrientation(Orientation.LEFT_BOTTOM).apply(img); return thmb; }
意外とどのLibraryも簡単!!