アップロードされた画像を特定の高さに揃える、みたいな作業をすることになった。
サムネイル画像など、表示用であればCloudinaryやimgixのような、リサイズ機能付きCDNサービスを使えばいいが、サーバー側で別途画像処理する必要があったので使えず。
Javaで実装しているので、ImageMagickをインストールして ProcessBuilder
で動かそうとも思ったが、 ImageIO
使えばPure Javaで実装できるかと思ったが、縦横比を自前で計算する必要がありそうだった。
自動でリサイズする方法はないかと調べてみると、ライブラリがあったのでメモ。
縦横比を維持してリサイズするライブラリ
imgscalrというライブラリがあった。Mavenリポジトリにも登録済み。
ライブラリといっても、含まれるのはstaticメソッドを持つ2クラスだけ、うち1クラスは非同期処理用なので実質1クラス。
実装内容もJava標準の画像処理系クラスのラッパーで、縦横比を維持してリサイズ後の幅と高さを自動で計算し、 java.awt.image.BufferedImage
経由でリサイズしている。
最新バージョンは4.2だが、リリースが2012年1月なので枯れている。ライセンスもApache License 2.0で使いやすいので、こちらを利用することとした。
使い方
ImageIO.read
などで変換したい画像を BufferedImage
として読み込み、 Scalr.resize
メソッドを実行する。
引数違いで同名メソッドが複数オーバーロードされているが、 Scalr.Mode
を指定することで、リサイズ方法を変更できる。
モード | 概要 |
---|---|
FIT_EXACT |
指定された幅・高さにリサイズ |
FIT_TO_WIDTH |
指定された幅にリサイズ |
FIT_TO_HEIGHT |
指定された高さにリサイズ |
今回のように高さを固定したい場合、 FIT_TO_HEIGHT
してやれば、縦横比を保ったままリサイズされる。
File originalImageFile = Path.of(...).toFile(); int newHeight = 120; BufferedImage originalImage = ImageIO.read(originalImageFile); BufferedImage resizedImage = Scalr.resize( originalImage, Scalr.Method.QUALITY, Scalr.Mode.FIT_TO_HEIGHT, newHeight ); File tempFile = Files.createTempFile("resized-", ".png").toFile(); ImageIO.write(resizedImage, "png", tempFile);
と書いてやると、画像の高さを120pxに変換できる。
Modeを FIT_EXACT
にすると縦横120px、FIT_TO_WIDTH
にすると幅120pxになる。
この例では数値を1つしか渡していないが、 width
と height
の2つを渡すメソッドもある。幅と高さをそれぞれ指定し、Modeで FIT_EXACT
を使用すると、指定した幅と高さに変換できる模様。
振り返り
地味に面倒な縦横比計算を任せられたので助かった。
余談
当初はImageMagickを使おうかなと思ったが、JavaからImageMagickを使うライブラリもある模様。
JNIを使ってAPIを実行するJMagickと、ProcessBuilder
を使うim4javaの2つ。
両方ともライセンスがLGPLなので、Javaで依存性管理ツール経由で利用するならアプリケーション側をLGPLにする必要はなさそう。
LGPLとJava - GNUプロジェクト - フリーソフトウェアファウンデーション
使うならim4javaのほうかと思う。最終リリースが2012年12月なので、最新のバージョンで使用できるかわからなかったが、こちらの記事を見ると、ImageMagick 7系でも動く模様。