PNG、JPEG、GIF ファイルのサイズを変更する必要があります。Javaを使用してこれを行うにはどうすればよいですか?
17 に答える
FWIW私はちょうどimgscalr(Maven Centralで利用可能)と呼ばれるJava用の単純な画像スケーリングライブラリをリリースしました(Apache 2、GitHubでホストされています)。
ライブラリは、画像スケーリングへのいくつかの異なるアプローチを実装し(Chris Campbellのインクリメンタルアプローチといくつかのマイナーな機能強化を含む)、要求された場合に最適なアプローチを選択するか、最速または最も見栄えの良いものを提供します(それを求めてください)。
使用法は非常に単純で、静的メソッドの集まりにすぎません。最も単純なユースケースは次のとおりです。
BufferedImage scaledImage = Scalr.resize(myImage, 200);
すべての操作で画像の元の比率が維持されるため、この場合、画像のサイズを幅200ピクセル、高さ200ピクセルの範囲内で変更するようにimgscalrに要求します。デフォルトでは、画像がなかったため、最も見栄えがよく、最速のアプローチが自動的に選択されます。指定されていません。
最初はこれが自己宣伝のように見えることに気づきましたが(そうです)、私はかなりの時間をこのまったく同じ主題をグーグルで調べ、さまざまな結果/アプローチ/考え/提案を考え出し続け、座って書くことにしました画像があり、おそらくその画像のサムネイルが必要な80〜85%のユースケースに対処する単純な実装-可能な限り高速または見栄えの良いもの(試した人は気付くでしょう)十分に小さい画像へのBICUBIC補間を使用してもGraphics.drawImageを実行すると、それでもゴミのように見えます)。
画像を読み込んだ後、次を試すことができます:
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;
}
Thumbnailatorは、流暢なインターフェースを備えた Java 用のオープンソースの画像サイズ変更ライブラリで、MIT ライセンスの下で配布されています。
私がこのライブラリを作成したのは、Java で高品質のサムネイルを作成するのは驚くほど難しく、結果のコードがかなり面倒になる可能性があるためです。Thumbnailator を使用すると、シンプルで流暢な API を使用して、かなり複雑なタスクを表現できます。
簡単な例
簡単な例として、画像を取得して 100 x 100 にサイズ変更し (元の画像の縦横比を維持)、ファイルに保存することは、次の 1 つのステートメントで実現できます。
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
高度な例
複雑なサイズ変更タスクの実行は、Thumbnailator の流暢なインターフェイスで簡素化されます。
次のことをしたいとしましょう。
- ディレクトリ内の画像を取得し、
- 元の画像の縦横比で 100 x 100 にサイズ変更し、
- それらすべてを の品質設定で JPEG に保存します
0.85
。 - ファイル名は元のファイル名
thumbnail.
の先頭に追加されたものです
Thumbnailator に変換すると、次のようにして上記を実行できます。
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
画質と速度に関する注意
このライブラリは、 Chet Haase と Romain Guy によるFilthy Rich Clientsで強調されているプログレッシブ バイリニア スケーリングメソッドも使用して、許容可能なランタイム パフォーマンスを確保しながら高品質のサムネイルを生成します。
Java Advanced Imagingがオープン ソースになり、必要な操作が提供されます。
大きな画像を扱っている場合や見栄えの良い結果が必要な場合、Java では簡単な作業ではありません。Graphics2D を介して再スケーリング操作を行うだけでは、高品質のサムネイルは作成されません。JAI を使用してそれを行うことはできますが、見栄えの良いものを得るには想像以上の作業が必要であり、JAI には OutOfMemory エラーで JVM を吹き飛ばすという厄介な癖があります。
ImageMagick を使いこなせる場合は、外部実行可能ファイルとして使用することをお勧めします。使い方は簡単で、仕事を正しく行うので、そうする必要はありません。
マシンに imagemagick をインストールするオプションがある場合は、 im4java をお勧めします。これは、コマンド ライン インターフェイス上の非常に薄い抽象化レイヤーですが、その機能は非常に優れています。
Java のコマンドライン インターフェイスとして、im4javaでGraphicsMagick Image Processing Systemを使用することができます。
GraphicsMagick には多くの利点がありますが、すべてに 1 つ:
- GM は、世界最大の写真サイト (Flickr や Etsy など) で何十億ものファイルを処理するために使用されています。
ImageMagickが言及されています。JMagickと呼ばれるJNIフロントエンドプロジェクトがあります。これは特に安定したプロジェクトではありません(そしてImage Magick自体が大きく変化し、互換性を損なうことさえあることが知られています)。とはいえ、本番環境でJMagickと互換性のあるバージョンのImage Magickを使用して、高スループット、低遅延率でスケーリングを実行した経験は豊富です。以前に試したすべてのJavaグラフィックライブラリを使用した場合よりも、速度が大幅に向上しました。
この種の操作には、Marvin(純粋なJava画像処理フレームワーク)を使用できます:http: //marvinproject.sourceforge.net
スケールプラグイン:http: //marvinproject.sourceforge.net/en/plugins/scale.html
Burkhard's answer を使用するだけですが、グラフィックを作成した後に次の行を追加します。
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
値を BICUBIC に設定することもできます。これにより、より高品質の画像が生成されますが、操作のコストが高くなります。設定できるレンダリングのヒントは他にもありますが、補間が最も顕著な効果を生み出すことがわかりました。多くの場合、Java コードは非常に遅くなる可能性が高いことに注意してください。すべてのレンダリングヒントが品質よりも速度を最適化するように設定されていても、大きな画像では 300% ズーム前後で遅延が発生し始めることがわかりました。
パフォーマンスの高いスケーラーを作成するのは簡単ではないことがわかりました。私はオープンソースプロジェクトのために一度それをしました: ImageScaler .
原則として、「java.awt.Image#getScaledInstance(int, int, int)」でも同じように機能しますが、これには厄介なバグがあります。詳細については、私のリンクを参照してください。
上記でテストした@Riyad Kallaの回答のようにimgScalrをインポートしたくない場合は、別の問題でPeter Walserの回答@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;
}
}
私は、GIF アニメーションの処理に使用できる無料のクラス (AnimatedGifEncoder、GifDecoder、および LWZEncoder) を使用したソリューションを開発しました。
jgifcode jar をダウンロードして、GifImageUtil クラスを実行できます。リンク: http://www.jgifcode.com