19

JavaとScalr3.2を使用して、この画像の高品質のサムネイルを作成しようとしています。

フルスケール画像

THUMB_WIDTH = 77これは関連するソースコードです。THUMB_HEIGHT = 57

BufferedImage srcImg = ImageIO.read(new File(sourceFile)); 
BufferedImage dstImg = Scalr.resize(srcImg, Scalr.Method.QUALITY, 
    THUMB_WIDTH, THUMB_HEIGHT); 
ImageIO.write(dstImg, format, new File(destFile));

を使用format = "png"すると、結果は次のようになります。

pngサムネイル

を使用format = "jpg"すると、結果は次のようになります。

jpgサムネイル

imagemagickidentifyを使用すると、JPEGが75の品質で保存されていることがわかりました。これは、見栄えの良いサムネイルを作成するにはまったく不十分です。PNGは私にも似合いません。

元のファイルと2つのサムネイルのIDの出力は次のとおりです。

$ identify 42486_1.jpg 42486_s1.jpg 42486_s1.png 
42486_1.jpg JPEG 580x435 580x435+0+0 8-bit DirectClass 50.6KB 0.000u 0:00.000
42486_s1.jpg[1] JPEG 77x58 77x58+0+0 8-bit DirectClass 2.22KB 0.000u 0:00.000
42486_s1.png[2] PNG 77x58 77x58+0+0 8-bit DirectClass 12.2KB 0.000u 0:00.000

質問

  • 生成されたサムネイルの品質を向上させる方法は?
  • JPEGをより高品質で保存するにはどうすればよいですか?より高い品質で試して、結果を比較したいと思います。JavaDocforImageIO.writeに何も見つかりませんでした。
  • 最大サイズが77x57で、77x58の画像を出力することをScalrに伝えるのはなぜですか?それはプロポーションを維持するためだと思いますが、それが私の最大幅と最大高さです。幅または高さはこれより小さくすることはできますが、それ以上にすることはできません。

更新:Web検索で、 JPEG画像の圧縮品質を調整する方法に関する記事を見つけました。品質を設定するBufferedImageを保存する独自のメソッドを作成しました。

/**
 * Write a JPEG file setting the compression quality.
 * 
 * @param image
 *                a BufferedImage to be saved
 * @param destFile
 *                destination file (absolute or relative path)
 * @param quality
 *                a float between 0 and 1, where 1 means uncompressed.
 * @throws IOException
 *                 in case of problems writing the file
 */
private void writeJpeg(BufferedImage image, String destFile, float quality) 
throws IOException {
    ImageWriter writer = null;
    FileImageOutputStream output = null;
    try {
        writer = ImageIO.getImageWritersByFormatName("jpeg").next();
        ImageWriteParam param = writer.getDefaultWriteParam();
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(quality);
        output = new FileImageOutputStream(new File(destFile));
        writer.setOutput(output);
        IIOImage iioImage = new IIOImage(image, null, null);
        writer.write(null, iioImage, param);
    } catch (IOException ex) {
        throw ex;
    } finally {
        if (writer != null) writer.dispose();
        if (output != null) output.close();
    }
}

結果は次のとおりです。PNG:

pngサムネイル

JPEG品質75:

jpgサムネイル

JPEG品質90(stackoverflowのGravatarはJPEG品質90として保存されます):

jpgサムネイル品質90

およびファイルサイズ:

thumb90.jpg JPEG 77x58 77x58+0+0 8-bit DirectClass 6.89KB 0.000u 0:00.000

更新2:Scalrをjava-image-scalingと比較するためのテスト。

private void scaleAndSaveImageWithScalr(String sourceFile, String destFile, int width, int height)
    throws IOException {
    BufferedImage sourceImage = ImageIO.read(new File(sourceFile));
    BufferedImage destImage = Scalr.resize(sourceImage, Scalr.Method.QUALITY, width, height);
    writeJpeg(destImage, destFile, JPEG_QUALITY);
}

private void scaleAndSaveImageWithJImage(String sourceFile, String destFile, int width, int height)
    throws IOException {
    BufferedImage sourceImage = ImageIO.read(new File(sourceFile));
    ResampleOp resampleOp = new ResampleOp(width, height);
    resampleOp.setFilter(ResampleFilters.getLanczos3Filter());
    resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
    BufferedImage destImage = resampleOp.filter(sourceImage, null);
    writeJpeg(destImage, destFile, JPEG_QUALITY);
}

Scalrで生成されたJPEG品質90:

jpgスカルからの親指

java-image-scalingで生成されたJPEG品質90:

java-image-scalingからのjpgサム

それ以上のフィードバックはありませんでした。個人的な結論として、java-image-scalingは優れた品質を提供し、それが私が選択したライブラリです。

4

5 に答える 5

2

@Stivlo、これに返信しなかったことをお詫びします。質問についてSOから通知を受け取ったことはありません。

java-image-scalingには、必要に応じて微調整するのに役立ついくつかの優れたフィルターがあります。とは言うものの、imgscalrのv4.2で、私はあなたが望むものに近づくかもしれない新しいULTRA_QUALITYを追加しました。

それがお役に立てば幸いですが、残念ながら、これは事実からほぼ1年後に返信されていることに気づきます。申し訳ありません。

于 2012-12-30T17:51:51.880 に答える
1

これはあなたの質問に対する完全な答えではありませんが、:

JPEG品質について:

圧縮品質は、ここで説明するImageWriteParamようにを使用して設定できます。彼らは0|1の値を使用することを提案していますが、実際には0.0から1.0の間のfloat値を指定する必要があると思います。int

スケーリングディメンションの問題について:

Scalrのホームページから:

注:画像の比率に違反する幅と高さが指定されている場合(たとえば、800×600の画像を150×150の正方形にサイズ変更しようとする場合)、ライブラリは最初に画像の向き(横向き/正方形または縦向き)を確認し、次に、一次寸法(横向きまたは正方形は幅を使用、縦向きは高さを使用)を選択して、正しい二次寸法を再計算します。 比率に違反していたユーザーから渡されたものを無視します。

あなたの場合、一次寸法は幅77であるため、高さ制限57は無視されます。

于 2011-10-12T15:09:26.053 に答える
0

私は同じテストを実行しましたが、java-image-scalingは、250pxよりも小さいサムネイルに対して間違いなくより良い結果をもたらします。また、シャープなフィルタリングをサポートしているため、結果が向上します。

Scalrの構文は多くの場合、1行だけで簡単なので、両方のライブラリを保持します。

于 2012-03-20T22:31:37.790 に答える
0

画像にアルファチャネルがある場合、両方のライブラリに問題があることに注意してください。私は縮小する画像について話しているだけで、それらを拡大することはテストしていません。

java-image-scalingは、画像によっては透明なエッジの周りに醜い境界線を作成する可能性があり、これは非常に悪いように見えます。これを回避する方法は見つかりませんでした。

Scalrは、(超)品質モードを使用する場合にのみ問題があります。ただし、正常に機能する方法で簡単に使用できます。バイキュービック補間では、透明な画像にアーティファクトが残るため、回避することをお勧めします。これは(超)品質の画像のデフォルトであり、scaleImageIncrementally()が保護されているため、品質が必要な場合は、このためにサブクラス化する必要があります(ただし、2を超える部分は双一次フィルタリングでは非常にぼやけて見えます)。

于 2014-08-07T08:25:49.760 に答える
0

高品質の結果が必要な場合は、[RapidDecoder][1]ライブラリを使用してください。それは次のように簡単です:

インポートrapid.decoder.BitmapDecoder; ...ビットマップビットマップ=BitmapDecoder.from(getResources()、R.drawable.image).scale(width、height).useBuiltInDecoder(true).decode(); 50%未満にスケールダウンしてHQの結果を得る場合は、組み込みのデコーダーを使用することを忘れないでください。

于 2016-08-25T11:49:32.433 に答える