web-dev-qa-db-ja.com

JavaでJPEGからサムネイル画像を作成するにはどうすればよいですか?

JavaでJPEGのサムネイルを作成するためのコードを誰か助けてください。

私はこれが初めてなので、段階的な説明をお願いします。

37
mmmmr
Image img = ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, BufferedImage.SCALE_SMOOTH);

これにより、100x100ピクセルのサムネイルがImageオブジェクトとして作成されます。ディスクに書き戻す場合は、コードを次のように変換するだけです。

BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
img.createGraphics().drawImage(ImageIO.read(new File("test.jpg")).getScaledInstance(100, 100, Image.SCALE_SMOOTH),0,0,null);
ImageIO.write(img, "jpg", new File("test_thumb.jpg"));

また、速度の問題が心配な場合(多くの画像をスケーリングしたい場合、上記の方法はかなり遅い)、これらの方法と次の宣言を使用します。

private BufferedImage scale(BufferedImage source,double ratio) {
  int w = (int) (source.getWidth() * ratio);
  int h = (int) (source.getHeight() * ratio);
  BufferedImage bi = getCompatibleImage(w, h);
  Graphics2D g2d = bi.createGraphics();
  double xScale = (double) w / source.getWidth();
  double yScale = (double) h / source.getHeight();
  AffineTransform at = AffineTransform.getScaleInstance(xScale,yScale);
  g2d.drawRenderedImage(source, at);
  g2d.dispose();
  return bi;
}

private BufferedImage getCompatibleImage(int w, int h) {
  GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
  GraphicsDevice Gd = ge.getDefaultScreenDevice();
  GraphicsConfiguration gc = Gd.getDefaultConfiguration();
  BufferedImage image = gc.createCompatibleImage(w, h);
  return image;
}

そして、呼び出します:

BufferedImage scaled = scale(img,0.5);

ここで、0.5はスケール比で、imgは通常サイズの画像を含むBufferedImageです。

69

「簡単」と「見栄えの良い結果」は、2つの非常に異なるものであることがわかりました。これらの両方の要件を非常に単純な Javaイメージスケーリングライブラリ (Apache 2ライセンス)にカプセル化しました。

サムネイルを作成するコード例は次のようになります。

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 150);

画像の比率が尊重され、ライブラリはスケーリングによる画像の変化量(最速、バランス、または品質)に基づいて、使用すべき方法で最善の推測を行い、サポートされる最高のJava2D画像タイプが常に使用されます「黒」の結果や本当にひどい見た目の出力の問題を回避するためのスケーリング(例:過度にディザリングされたGIF画像)。

また、Javaで可能な限り最高の外観のサムネイルを出力するように強制する場合、API呼び出しは次のようになります。

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
                                       150, 100, Scalr.OP_ANTIALIAS);

ライブラリは、最良の結果を得るためにJava2D推奨のインクリメンタルスケーリングを使用するだけでなく、オプションのアンチエイリアス効果をサムネイルに適用し(非常に微調整されたカーネルを備えたConvolveOp)、ピクセル値間の遷移により、非常に大きな画像から非常に小さな画像に移動したときに見られるような、サムネイルがより均一になり、シャープまたはポピーではなく見えるようになります。

ライブラリ内のすべてのコメントを読んで(コード自体は頻繁にドキュメント化されています)、回避されているさまざまなJDKバグや、パフォーマンスやメモリ使用量を改善するために行われた最適化を確認できます。私はこの実装の調整に多くの時間を費やし、Webアプリや他のJavaプロジェクトで展開している人々から多くの良いフィードバックを得ました。

31
Riyad Kalla

これは、画像を伸縮させずに100 X 100のサムネイルを作成する簡単な方法です。

private  void saveScaledImage(String filePath,String outputFile){
    try {

        BufferedImage sourceImage = ImageIO.read(new File(filePath));
        int width = sourceImage.getWidth();
        int height = sourceImage.getHeight();

        if(width>height){
            float extraSize=    height-100;
            float percentHight = (extraSize/height)*100;
            float percentWidth = width - ((width/100)*percentHight);
            BufferedImage img = new BufferedImage((int)percentWidth, 100, BufferedImage.TYPE_INT_RGB);
            Image scaledImage = sourceImage.getScaledInstance((int)percentWidth, 100, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);
            BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB);
            img2 = img.getSubimage((int)((percentWidth-100)/2), 0, 100, 100);

            ImageIO.write(img2, "jpg", new File(outputFile));    
        }else{
            float extraSize=    width-100;
            float percentWidth = (extraSize/width)*100;
            float  percentHight = height - ((height/100)*percentWidth);
            BufferedImage img = new BufferedImage(100, (int)percentHight, BufferedImage.TYPE_INT_RGB);
            Image scaledImage = sourceImage.getScaledInstance(100,(int)percentHight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);
            BufferedImage img2 = new BufferedImage(100, 100 ,BufferedImage.TYPE_INT_RGB);
            img2 = img.getSubimage(0, (int)((percentHight-100)/2), 100, 100);

            ImageIO.write(img2, "jpg", new File(outputFile));
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
12
Ali Imran

JMagick ライブラリ(およびJavaで ImageMagick の実装)に必要なものがあります。

4
mfloryan

Java上記のコード(scale/getCompatibleImageメソッドを使用))はうまく機能しましたが、サーバーにデプロイすると、サーバーに関連付けられたディスプレイがなかったため、動作しなくなりました-誰でもそれ以外の場合、この問題を解決するには、BufferedImage bi = new BufferedImage(w、h、BufferedImage.TYPE_INT_RGB);

bufferedImageの代わりにbi = getCompatibleImage(w、h);

およびgetCompatibleImageメソッドの削除

(後で注意してください-これはほとんどの画像でうまく機能することがわかりましたが、32ビットの色深度のjpeg画像である会社のマーケティング部門からたくさんを得て、ライブラリはそれらすべてに対してサポートされていない画像形式の例外をスローします:(- -imagemagick/jmagickはより魅力的に見え始めています)

3
Kem Mason

私はこれがかなり古い記事であることを知っています。私はサムネイルを生成するソリューションを探していたので、これを使用することになります

Thumbnails.of(originalImage).scale(0.25).asBufferedImage();

モバイルに使用している場合は、スケールを0.45に設定することをお勧めします

Thumbnails.of(originalImage).scale(0.45).asBufferedImage();

https://github.com/coobird/thumbnailator

両方のオプションをテストしたので、これは確かにGraphics2Dを使用してはるかに高速です。

2
Athar

私はThumbnailatorを使用しました! 2行のコードで問題を解決しました。

https://github.com/coobird/thumbnailator

2
martins.tuga

ストレッチやライブラリなしでサムネイルを作成する簡単な方法。 PNGの透明度でも機能します。

public File createThumbnail(String imageUrl, String targetPath) {
    final int imageSize = 100;
    File thumbnail = new File(targetPath);

    try {
        thumbnail.getParentFile().mkdirs();
        thumbnail.createNewFile();
        BufferedImage sourceImage = ImageIO.read(new File(imageUrl));
        float width = sourceImage.getWidth();
        float height = sourceImage.getHeight();

        BufferedImage img2;
        if (width > height) {
            float scaledWidth = (width / height) * (float) imageSize;
            float scaledHeight = imageSize;

            BufferedImage img = new BufferedImage((int) scaledWidth, (int) scaledHeight, sourceImage.getType());
            Image scaledImage = sourceImage.getScaledInstance((int) scaledWidth, (int) scaledHeight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);

            int offset = (int) ((scaledWidth - scaledHeight) / 2f);
            img2 = img.getSubimage(offset, 0, imageSize, imageSize);
        }
        else if (width < height) {
            float scaledWidth = imageSize;
            float scaledHeight = (height / width) * (float) imageSize;

            BufferedImage img = new BufferedImage((int) scaledWidth, (int) scaledHeight, sourceImage.getType());
            Image scaledImage = sourceImage.getScaledInstance((int) scaledWidth, (int) scaledHeight, Image.SCALE_SMOOTH);
            img.createGraphics().drawImage(scaledImage, 0, 0, null);

            int offset = (int) ((scaledHeight - scaledWidth) / 2f);
            img2 = img.getSubimage(0, offset, imageSize, imageSize);
        }
        else {
            img2 = new BufferedImage(imageSize, imageSize, sourceImage.getType());
            Image scaledImage = sourceImage.getScaledInstance(imageSize, imageSize, Image.SCALE_SMOOTH);
            img2.createGraphics().drawImage(scaledImage, 0, 0, null);
        }
        ImageIO.write(img2, "png", thumbnail);
    }
    catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return thumbnail;
}
1
Johannes J

数行でこれを実行できる多くの画像処理フレームワークが利用可能です。次の例では、 Marvin Framework を使用して、さまざまな解像度でサムネイルを生成します(参照として幅を指定)。 3つのサムネイルは92 msで生成されました。

input:

enter image description here

output:

enter image description here

enter image description here

enter image description here

import static marvin.MarvinPluginCollection.*;

MarvinImage image = MarvinImageIO.loadImage("./res/input.jpg");
MarvinImage scaledImage = new MarvinImage(1,1);

scale(image, scaledImage, 250);
MarvinImageIO.saveImage(scaledImage, "./res/output_x250.jpg");

scale(image, scaledImage, 150);
MarvinImageIO.saveImage(scaledImage, "./res/output_x150.jpg");

scale(image, scaledImage, 50);
MarvinImageIO.saveImage(scaledImage, "./res/output_x50.jpg");

私はfotovault(sourceforge.net)と呼ばれるアプリケーションを作成しました。これは、imagej apiを使用して、Javaで画像をアップロードし、サムネイルを作成できます。

以下の私のブログを読んでください

http://www.gingercart.com/Home/Java-snippets/create-image-thumbnail-in-Java-using-imagej-api

1
Mouli

私はあなたが次のオプションを持っていることに応じてブログを経験しました-

  1. 単純なRGBファイルにはImageScalrを使用します。 ImageIOクラスはファイルの読み取りに使用され、ImageScalrはサムネイルを作成します
  2. RGB + CYMKをサポートするには、ImageIOおよびJAI(Java Advanced Imaging)APIを使用してファイルを読み取り、ImageScalrを使用してサムネイルを作成します。
  3. どのファイル形式、処理するカラーモードがわからない場合、最も安全なオプションはImageMagickを使用することです。

link は、コードスニペットで完全な回答を提供します。

1
Gagan

私は何年も前にJAIを使用して静的メソッドでutilクラスを作成しました。 Java Advanced Imaging APIは、Javaで画像を処理するのに最も信頼できるAPIです。ベクトル補間はPhotoshopに最も近いものですJava world。ここにそのうちの1つがあります。

public static ByteArrayOutputStream resize(InputStream inputStream , int IMG_WIDTH,
        int IMG_HEIGHT) throws Exception {
    BufferedImage originalImage = ImageIO.read(inputStream);
    int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB
            : originalImage.getType();
    BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT,
            type);
    {
        Graphics2D g = resizedImage.createGraphics();
        g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
        g.dispose();
        g.setComposite(AlphaComposite.Src);

        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
    }
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ImageIO.write(resizedImage, "png", bos);
    return bos;

} 
1
mike oganyan