有时,缩小位图会生成更大的文件。为什么?

时间:2010-03-24 13:10:36

标签: c# .net bitmap resize-image

我正在尝试编写一种方法,每次调用时减少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;
}

7 个答案:

答案 0 :(得分:6)

您最有可能以低压缩比(高质量)保存jpeg图像。

答案 1 :(得分:4)

重新压缩JPEG图像是您应该避免的。但这里真正的问题是InterpolationMode,高质量的产生很多细微阴影的像素,使得压缩图像变得更加困难。使用InterpolationMode.NearestNeighbor应该避免这种情况,但代价是获得质量较低的图像。

答案 2 :(得分:2)

问题不在于您发布的代码中,而在于您保存JPEG的位置。你使用什么压缩率?

答案 3 :(得分:1)

我会说你将它保存为高质量的jpeg(压缩程度更低==更多空间)

答案 4 :(得分:1)

看起来你的位图实际上被保存为jpeg,并且知道c#喜欢为你做什么,它可能会保存一个相当低的默认压缩级别。原始jpeg必须具有适当的压缩级别。即使它是相同的压缩级别,jpeg格式的工作方式也可能意味着你发现了一个在较低分辨率下膨胀的侥幸图像。

虽然位图是一个确切的大小,如果它是十个像素宽和十个高,它是100个像素,比如16位(2字节)颜色,即200个字节,再加上一些标题。

将分辨率降低到5乘5,你有50个字节加上一些标题,但应该是相同数量的标题。

答案 5 :(得分: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;
}

答案 6 :(得分:1)

原件似乎是数码相机的输出。我认为相机制造商使用专有的超级优化压缩算法,而公共库的实现可能效率较低。 (当然,你可能没有使用与相机相同的压缩等级。)

此外,相机使用原始数据(可能首先在其上进行“魔术”预处理)作为输入。当您重新压缩它时,输入中会有压缩和重新缩放的工件,这可能会导致压缩效率降低。

实际上我认为如果你使用相同 jpg算法在相同的级别压缩图像几次,它的大小可能会增加,因为先前压缩的工件增加了“细节”更难压缩(而且变得更加丑陋)。

(相机压缩算法也可以针对输入始终照片的事实进行优化,而通用算法可能会做一些效率较低的工作,以便合理地完成照片和< strike> line art 包含照片和生成的图形元素的混合图像。)