Javaを使用して画像のサイズを変更するにはどうすればよいですか?
質問
PNG、JPEG、GIFファイルのサイズを変更する必要があります。 Javaを使用してこれを行うにはどうすればよいですか?
解決
画像を読み込んだ後、次を試すことができます:
BufferedImage createResizedCopy(Image originalImage,
int scaledWidth, int scaledHeight,
boolean preserveAlpha)
{
System.out.println("resizing...");
int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
Graphics2D g = scaledBI.createGraphics();
if (preserveAlpha) {
g.setComposite(AlphaComposite.Src);
}
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose();
return scaledBI;
}
他のヒント
FWIW imgscalr と呼ばれるJava用のシンプルな画像スケーリングライブラリをリリースしました(GitHubでホストされるApache 2)。 a>( Maven central で入手可能)。
ライブラリは、画像スケーリングに対していくつかの異なるアプローチを実装し(Chris Campbellのインクリメンタルアプローチといくつかのマイナーな機能強化)、必要に応じて最適なアプローチを選択するか、最速または最高の外観を提供します(それを要求した場合)。
使用法は非常に単純で、単なる静的メソッドの集まりです。最も単純なユースケースは次のとおりです。
BufferedImage scaledImage = Scalr.resize(myImage, 200);
すべての操作は画像の元の比率を維持するため、この場合はimgscalrに幅200ピクセル、高さ200ピクセルの範囲内で画像のサイズを変更するように要求します。指定されなかったため。
私は最初はこれが自己宣伝のように見えることを認識していますが、まったく同じテーマをグーグルで探し、さまざまな結果/アプローチ/思考/提案を考え出し、座ることに決めましたそして、画像があり、おそらくサムネイルを必要とする80-85%のユースケースに対処する簡単な実装を作成します-できるだけ速く、または見栄えの良いもの(試した人には、十分に小さい画像にBICUBIC補間を行ってもGraphics.drawImageを行うことに気付くでしょう、それはまだゴミのように見えます。)
Thumbnailator は、流aなインターフェースを備えたJava用のオープンソースの画像サイズ変更ライブラリで、 MITライセンス。
このライブラリを作成したのは、Javaで高品質のサムネイルを作成するのは驚くほど難しく、結果として得られるコードはかなり複雑になるからです。 Thumbnailatorでは、シンプルで流APIなAPIを使用して、かなり複雑なタスクを表現することができます。
簡単な例
簡単な例として、画像を取得して100 x 100にサイズ変更し(元の画像の縦横比を保持)、ファイルに保存することは1つのステートメントで実現できます:
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
高度な例
Thumbnailatorの流れるようなインターフェイスにより、複雑なサイズ変更タスクの実行が簡素化されます。
次のことをしたいとします:
- 画像をディレクトリに保存し、
- 元の画像のアスペクト比を使用して、サイズを100 x 100に変更します
- それらをすべて
0.85
の品質設定でJPEGに保存します - ファイル名は、
thumbnail。
が先頭に追加されたオリジナルから取得されます
Thumbnailatorに変換すると、上記を次のように実行できるようになります。
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
画質と速度に関するメモ
このライブラリは、 = "http://filthyrichclients.org/"> Filthy Rich Clients でハイライトされているプログレッシブ双線形スケーリングメソッドも使用しています。許容可能な実行時パフォーマンスを確保しながら、高品質のサムネイルを生成するため。
これを行うためにライブラリは必要ありません。 Java自体で実行できます。
Chris Campbellには、画像のスケーリングに関する優れた詳細な記事があります-この記事。
Chet HaaseとRomain Guyの本には、 Filthy Rich Clients の画像スケーリングに関する詳細かつ非常に有益な記事もあります。
Java Advanced Imaging は現在オープンソースです、必要な操作を提供します。
大きな画像を扱う場合や見栄えの良い結果が必要な場合は、Javaでの簡単な作業ではありません。 Graphics2Dを介したスケール変更操作を介して単純に実行しても、高品質のサムネイルは作成されません。 JAIを使用してそれを行うことができますが、見栄えの良いものを得るために想像するよりも多くの作業が必要であり、JAIにはOutOfMemoryエラーでJVMを吹き飛ばすという厄介な習慣があります。
ImageMagickを使用できる場合は、ImageMagickを外部実行可能ファイルとして使用することをお勧めします。使い方は簡単で、適切に機能するため、必要はありません。
マシンにimagemagickをインストールするオプションがある場合、 im4java をお勧めします。これは、コマンドラインインターフェイス上の非常に薄い抽象化レイヤーですが、非常にうまく機能します。
Java APIは、画像の標準スケーリング機能および画像品質のダウングレードを提供しません。
このため、JavaCVのcvResizeを使用しようとしましたが、問題が発生するようです。
画像のスケーリングに適したライブラリが見つかりました。単に「java-image-scaling」の依存関係を追加してください。 pom.xmlで。
<dependency>
<groupId>com.mortennobel</groupId>
<artifactId>java-image-scaling</artifactId>
<version>0.8.6</version>
</dependency>
mavenリポジトリで、これの最新バージョンを取得します。
例Javaプログラムで
ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
GraphicsMagick Image Processing System を im4java をJavaのコマンドラインインターフェイスとして使用します。
GraphicsMagickには多くの利点がありますが、すべての利点があります:
- GMは何十億もの処理に使用されます 世界最大の写真のファイル サイト(FlickrやEtsyなど)。
Image Magickが言及されました。 JMagickと呼ばれるJNIフロントエンドプロジェクトがあります。これは特に安定したプロジェクトではありません(Image Magick自体は大きく変化し、互換性を壊すことでも知られています)。とはいえ、JMagickとImage Magickの互換性のあるバージョンを運用環境で使用して、高スループット、低レイテンシレートでスケーリングを実行した良い経験がありました。以前に試したすべてのJavaグラフィックライブラリを使用した場合よりも、速度が大幅に向上しました。
単にBurkhardの答えを使用しますが、グラフィックの作成後に次の行を追加します。
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
値をBICUBICに設定することもできます。これにより、より高品質の画像が生成されますが、より高価な操作です。設定できるレンダリングヒントは他にもありますが、補間が最も顕著な効果をもたらすことがわかりました。 ズームインしたい場合は、Javaコードが非常に遅くなる可能性が高いことに留意してください。すべてのレンダリングヒントが速度よりも品質を最適化するように設定されている場合でも、より大きな画像では300%のズームでラグが発生し始めます。
この種の操作には、Marvin(純粋なJava画像処理フレームワーク)を使用できます。 http://marvinproject.sourceforge.net
Scaleプラグイン: http://marvinproject.sourceforge.net/en/plugins/scale.html
パフォーマンススケーラーの作成は簡単ではないことがわかりました。私は一度オープンソースプロジェクトのためにそれをやった: ImageScaler 。
原則として「java.awt.Image#getScaledInstance(int、int、int)」も同様に機能しますが、これには厄介なバグがあります-詳細についてはリンクを参照してください。
私は、GIFアニメーションを処理するために自由に利用できるクラス(AnimatedGifEncoder、GifDecoder、およびLWZEncoder)を使用できるソリューションを開発しました。
jgifcode jarをダウンロードして、GifImageUtilクラスを実行できます。
リンク: http://www.jgifcode.com
次の人気製品を使用できます: thumbnailator
imgScalr をインポートしたくない場合は、上記でテストした@Riyad Kallaの回答も問題なく動作します、 あなたはこれを行うことができます ピーターウォルザーの回答しかし、別の問題に関する@Peter Walser:
/**
* utility method to get an icon from the resources of this class
* @param name the name of the icon
* @return the icon, or null if the icon wasn't found.
*/
public Icon getIcon(String name) {
Icon icon = null;
URL url = null;
ImageIcon imgicon = null;
BufferedImage scaledImage = null;
try {
url = getClass().getResource(name);
icon = new ImageIcon(url);
if (icon == null) {
System.out.println("Couldn't find " + url);
}
BufferedImage bi = new BufferedImage(
icon.getIconWidth(),
icon.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
// paint the Icon to the BufferedImage.
icon.paintIcon(null, g, 0,0);
g.dispose();
bi = resizeImage(bi,30,30);
scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
imgicon = new ImageIcon(scaledImage);
} catch (Exception e) {
System.out.println("Couldn't find " + getClass().getName() + "/" + name);
e.printStackTrace();
}
return imgicon;
}
public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
float scaleX = (float) areaWidth / image.getWidth();
float scaleY = (float) areaHeight / image.getHeight();
float scale = Math.min(scaleX, scaleY);
int w = Math.round(image.getWidth() * scale);
int h = Math.round(image.getHeight() * scale);
int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
boolean scaleDown = scale < 1;
if (scaleDown) {
// multi-pass bilinear div 2
int currentW = image.getWidth();
int currentH = image.getHeight();
BufferedImage resized = image;
while (currentW > w || currentH > h) {
currentW = Math.max(w, currentW / 2);
currentH = Math.max(h, currentH / 2);
BufferedImage temp = new BufferedImage(currentW, currentH, type);
Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(resized, 0, 0, currentW, currentH, null);
g2.dispose();
resized = temp;
}
return resized;
} else {
Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;
BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = resized.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(image, 0, 0, w, h, null);
g2.dispose();
return resized;
}
}