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(压缩较少 == 更多空间)

于 2010-03-24T13:14:25.437 回答
1

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

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

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

于 2010-03-24T13:25:16.567 回答
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 回答