5

呼び出されるたびに画像のサイズを 50% 縮小するメソッドを作成しようとしていますが、問題が見つかりました。画像が実際には半分になっているのに、ファイルサイズが大きくなってしまうことがあります。DPI と PixelFormat を担当しています。他に何が欠けていますか?

お時間をいただきありがとうございます。

public Bitmap ResizeBitmap(Bitmap origBitmap, int nWidth, int nHeight)
{
    Bitmap newBitmap = new Bitmap(nWidth, nHeight, origBitmap.PixelFormat);

    newBitmap.SetResolution(
       origBitmap.HorizontalResolution, 
       origBitmap.VerticalResolution);

    using (Graphics g = Graphics.FromImage((Image)newBitmap))
    {
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;

        g.DrawImage(origBitmap, 0, 0, nWidth, nHeight);
    }

    return newBitmap;
}

http://imgur.com/lY9BN.png

http://imgur.com/KSka0.png

編集: 不足しているコードは次のとおりです。

int width = (int)(bitmap.Width * 0.5f);
int height = (int)(bitmap.Height * 0.5f);
Bitmap resizedBitmap = ResizeBitmap(bitmap, width, height);
resizedBitmap.Save(newFilename);

編集2: あなたのコメントに基づいて、これが私が見つけた解決策です:

private void saveAsJPEG(string savingPath, Bitmap bitmap, long quality)
{
    EncoderParameter parameter = new EncoderParameter(Encoder.Compression, quality);
    ImageCodecInfo encoder = getEncoder(ImageFormat.Jpeg);
    if (encoder != null)
    {
        EncoderParameters encoderParams = new EncoderParameters(1);
        encoderParams.Param[0] = parameter;
        bitmap.Save(savingPath, encoder, encoderParams);
    }
}

private ImageCodecInfo getEncoder(ImageFormat format)
{

    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
    foreach (ImageCodecInfo codec in codecs)
        if (codec.FormatID == format.Guid)
            return codec;

    return null;
}
4

7 に答える 7

6

ほとんどの場合、低い圧縮率 (高品質) で jpeg 画像を保存しています。

于 2010-03-24T13:12:54.587 に答える
4

JPEG 画像の再圧縮は避けるべきものです。しかし、ここでの本当の問題は InterpolationMode です。高品質のものは、微妙に陰影のあるピクセルを多数生成し、画像の圧縮を難しくします。InterpolationMode.NearestNeighbor を使用すると、これを回避できますが、画質が低下します。

于 2010-03-24T13:28:04.733 に答える
2

問題は投稿したコードではなく、JPEG を保存する場所にあります。どの圧縮比を使用していますか?

于 2010-03-24T13:14:42.447 に答える
1

このコードを試して、持っている JPEG を保存してください。圧縮品質を設定できます。実験して、サイズの問題に役立つかどうかを確認してください。

private void saveJpeg(string path, Bitmap img, long quality)
{
    EncoderParameter parameter = new EncoderParameter(Encoder.Quality, quality);
    ImageCodecInfo encoder = this.getEncoderInfo("image/jpeg");
    if (encoder != null)
    {
        EncoderParameters encoderParams = new EncoderParameters(1);
        encoderParams.Param[0] = parameter;
        img.Save(path, encoder, encoderParams);
    }
}

private ImageCodecInfo getEncoderInfo(string mimeType)
{
    ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders();
    for (int i = 0; i < imageEncoders.Length; i++)
    {
        if (imageEncoders[i].MimeType == mimeType)
        {
            return imageEncoders[i];
        }
    }
    return null;
}
于 2010-03-24T13:58:03.623 に答える
1

オリジナルはデジタルカメラからの出力のようです。カメラのメーカーは独自の超最適化圧縮アルゴリズムを使用していると思いますが、一般的なライブラリの実装はあまり効果的ではない可能性があります。(そしてもちろん、カメラと同じ圧縮レベルを使用していない可能性があります。)

さらに、カメラはセンサーからの生データ (最初に「魔法の」前処理を行う可能性があります) を入力として使用します。再圧縮すると、入力に圧縮と再スケーリングのアーティファクトが含まれるため、圧縮の効果が低下する可能性があります。

実際、同じレベルで同じjpgアルゴリズムを使用して画像を数回圧縮すると、以前の圧縮によるアーティファクトが「詳細」を追加して圧縮が難しくなるため、サイズが大きくなる可能性があると思います(また、醜くなります)。

(カメラ圧縮アルゴリズムは、入力が常に写真であるという事実に合わせて最適化される場合もありますが、汎用アルゴリズムは、写真と、写真と生成されたグラフィック要素の両方を含む線画混合画像両方で適度にうまく機能するために、あまり効果的でないことを行う場合があります。 .)

于 2010-03-24T14:11:51.160 に答える
1

高品質のjpegとして保存していると思います(圧縮が少ない==スペースが多い)

于 2010-03-24T13:14:25.437 に答える
1

ビットマップが実際に jpeg として保存されているように見え、c# がどのように処理を行うのが好きかを知っていると、おそらくかなり低いデフォルトの圧縮レベルで保存されます。元の jpeg には適切な圧縮レベルが必要です。圧縮レベルが同じ場合でも、jpeg 形式の動作により、解像度が低いと肥大化するフルーク画像が見つかった可能性があります。

ビットマップは正確なサイズですが、幅が 10 ピクセル、高さが 10 ピクセルの場合、100 ピクセル、たとえば 16 ビット (2 バイト) の色で 200 バイトと、ヘッダーのビットです。

解像度を 5 x 5 に下げると、50 バイトに少しのヘッダーが追加されますが、同じ量のヘッダーになるはずです。

于 2010-03-24T13:25:16.567 に答える