在.NET中旋转JPEG,质量损失最小

Mik*_*nry 7 .net jpeg image-processing

我试图支持从ASP.NET MVC旋转JPEG图像(以90度为增量).我试图使用System.Drawing(GDI +),但是我遇到了问题.

我尝试使用Image.RotateFlip哪种能够旋转图像,但会导致质量下降.即使编码器质量为100,旋转图像上仍然存在可见的伪像,这些伪像不在原始图像上,也不会在我使用其他程序(Gimp等)旋转时出现.

using (Image image = Image.FromFile("C:\\source.jpg")) {
    ImageFormat sourceFormat = image.RawFormat;
    image.RotateFlip(RotateFlipType.Rotate90FlipNone);
    EncoderParameters encoderParams = null;
    try {
        if (sourceFormat == ImageFormat.Jpeg) {
            encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
        }
        image.Save("C:\\target.jpg", GetEncoder(sourceFormat), encoderParams);
    } finally {
        if (encoderParams != null)
            encoderParams.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现了一篇关于转换JPEG而不会丢失信息的文章.使用Encoder.Transformation似乎是.NET中的一个选项 - 但是我不能让它导致我的任何JPEG测试图像完全旋转,无论尺寸是16的倍数.

using (Image image = Image.FromFile("C:\\source.jpg")) {
    ImageFormat sourceFormat = image.RawFormat;
    EncoderParameters encoderParams = null;
    try {
        if (sourceFormat == ImageFormat.Jpeg) {
            encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = new EncoderParameter(Encoder.Transformation, 
                (long)EncoderValue.TransformRotate90);
        }
        image.Save("C:\\target.jpg", GetEncoder(sourceFormat), encoderParams);
    } finally {
        if (encoderParams != null)
            encoderParams.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有人知道如何使用上述方法或其他方法,以90度为增量成功旋转JPEG,而质量损失最小或没有损失?谢谢.

另外,这是我的实现GetEncoder:

private ImageCodecInfo GetEncoder(ImageFormat format) {
    foreach (var info in ImageCodecInfo.GetImageEncoders())
        if (info.FormatID == format.Guid)
            return info;
    return null;
}
Run Code Online (Sandbox Code Playgroud)

编辑:

我更新了上面的代码以更好地匹配我的实际代码.该错误位于以下行:

if (sourceFormat == ImageFormat.Jpeg) {
Run Code Online (Sandbox Code Playgroud)

应该是:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) {
Run Code Online (Sandbox Code Playgroud)

Mik*_*nry 4

感谢您确认我发布的代码有效。这帮助我隔离了我的问题。我现在觉得自己很蠢。我的实际代码在设置之前检查了图像格式encoderParams- 但它有一个错误:

if (sourceFormat == ImageFormat.Jpeg) {
    // set encoderParams here
Run Code Online (Sandbox Code Playgroud)

我发现上面的条件总是错误的,所以encoderParams没有被设置。修复方法很简单:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) {
Run Code Online (Sandbox Code Playgroud)