在GDI +中调整大小时的Ghost-border('振铃')

mck*_*mey 18 .net c# gdi+ resize

发生的事情(仅在某些图像上会引人注目)是我会看到1像素的白色边框插入一个像素.它似乎发生在轻而不是白色的区域(例如天空).它类似于某些东西过度锐化并且在高对比度边缘旁边可以看到鬼影边框.

这是完美再现它的repro代码.我正在使用所有最高质量的设置进行缩放.

ImageCodecInfo encoder = null;
EncoderParameters encoderParams = null;

foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders())
{
    if (codec.MimeType == "image/jpeg")
    {
        encoder = codec;

        // use highest quality compression settings
        encoderParams = new EncoderParameters(1);
        encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
        break;
    }
}

using (Bitmap input = (Bitmap)Bitmap.FromFile(inputPath, true))
{
    // shrink by multiple of 2
    Rectangle rect = new Rectangle(0, 0, input.Width/32, input.Height/32);

    using (Bitmap output = new Bitmap(rect.Width, rect.Height))
    {
        using (Graphics g = Graphics.FromImage(output))
        {
            // use highest quality settings (updated per Mark Ransom's answer)
            g.CompositingMode = CompositingMode.SourceCopy;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;

            g.DrawImage(input, rect);
        }

        output.Save(outputPath, encoder, encoderParams);
    }
}
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?我完全不知所措.我已经阅读了大量的问题/答案,但似乎没有一个问题影响我的情况.


编辑:

这是图像之前的一个例子:http://img14.imageshack.us/img14/4174/mg1647.jpg

这是一张图片的例子:http://img64.imageshack.us/img64/3156/afterringing.jpg

原始文件(在托管服务"优化"它们之前)更明显,但你可以在天空中看到较小图像上的一个像素的较亮波段.

mck*_*mey 40

我终于找到了一篇谈论这个问题的文章.

Libor Tinka在继续展示他的广泛过滤器之前随便提到了这一点,这些过滤器的性能优于GDI +缩放:

根据他的建议,听起来它完全符合我们的怀疑:它正在从图像边缘以外的周围像素中提取平均细节.这对我来说似乎是算法中的一个缺陷,但这是有争议的.要解决这个问题,有一个ImageAttributes类,您可以在其中指定超出的像素只是其中像素的镜像.设置此似乎完全消除了振铃:

using (ImageAttributes wrapMode = new ImageAttributes())
{
    wrapMode.SetWrapMode(WrapMode.TileFlipXY);
    g.DrawImage(input, rect, 0, 0, input.Width, input.Height, GraphicsUnit.Pixel, wrapMode);
}
Run Code Online (Sandbox Code Playgroud)

非常感谢Libor Tinka提供的解决方案,以及Mark Ransom帮助我思考这个问题并给予我"振铃"一词,这使得Libor Tinka的解决方案甚至出现在我的搜索中.