2009-07-27 56 views
6

我試圖支持從ASP.NET MVC(以90度遞增)旋轉JPEG圖像。我試圖使用System.Drawing(GDI +),但是我遇到了問題。在.NET中旋轉JPEG,質量損失最小

我試過使用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(); 
    } 
} 

我在transforming a JPEG without loss of information找到一篇文章。使用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(); 
    } 
} 

多有誰知道如何使用上述方法或其他方法,以90度遞增的方式成功地在.NET中旋轉JPEG,並且質量損失最小或沒有損失?謝謝。

而且,這裏是我的執行GetEncoder

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

編輯:

我更新了上面的代碼,以更好地滿足我的實際代碼。該缺陷是以下行:

if (sourceFormat == ImageFormat.Jpeg) { 

它應該是:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) { 
+2

您的代碼適用於我..你確定爲你的數據返回一個ImageCodecInfo? – 2009-07-27 06:49:42

回答

1

感謝確認我的發佈代碼工作。這幫助我隔離了我的問題。我現在感到很蠢。我的實際代碼已經爲圖像格式的核對設定encoderParams之前 - 但它有一個缺陷:

if (sourceFormat == ImageFormat.Jpeg) { 
    // set encoderParams here 

我發現上面的條件總是false,所以encoderParams沒有被設置。修復很簡單:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) { 
2

使用任何解壓縮圖像的方法,旋轉它並壓縮它,將會導致質量損失。

JPEG格式通過獲取平均顏色來表示所有四個像素來壓縮顏色信息,所以如果您的圖像寬度和高度可以被兩個整除,那麼您將失去較少的質量,因爲大多數信息在壓縮是在解壓縮中插入的信息。

同樣,亮度信息以8x8像素的正方形進行壓縮,因此如果您的寬度和高度可以按8進行分割,網格將在旋轉圖像後對齊,並且您將丟失較少的實際信息。

要進行無損旋轉,您必須使用完全不同的方法,讀取JPEG文件並重新排列和旋轉每個方塊的信息,以便形成旋轉後的圖像而不需要解壓縮並重新壓縮它。