2012-02-29 42 views
2

因此,我正在從目錄中讀取文件,確定它們需要旋轉的方式。旋轉然後保存。這部分工作...問題是,它保存文件後,它重新壓縮,我從1.5meg圖像到250k圖像。我需要保持原來的文件大小。我嘗試使用jhead.exe並從命令行調用它,但無法讓我的任何參數正確傳入。這是我的代碼片段來檢測,旋轉和保存。C#在不損失太多質量的情況下旋轉JPG

foreach (FileInfo f in dir.GetFiles("*.jpg")) 
{ 
    try 
    { 
     string ExportName = ""; 

     Bitmap originalImage = new Bitmap(f.FullName.ToString()); 

     Info inf = new Info(originalImage); 

     gma.Drawing.ImageInfo.Orientation orientation = gma.Drawing.ImageInfo.Orientation.TopLeft; 
     try 
     { 
      orientation = inf.Orientation; 
     } 
     catch 
     { 
      orientation = gma.Drawing.ImageInfo.Orientation.TopLeft; 
     } 

     originalImage = CheckRotation(originalImage, orientation); 

     progressBar.Value = progressBar.Value + 1; 
     originalImage.Save(f.FullName.ToString(), ImageFormat.Jpeg); 
     Application.DoEvents(); 


    } 

private Bitmap CheckRotation(Bitmap inputImage, gma.Drawing.ImageInfo.Orientation orientation) 
{ 

    Bitmap rotatedImage = inputImage; 

    switch (orientation) 
    { 
     case gma.Drawing.ImageInfo.Orientation.LeftBottom: 
      rotatedImage.RotateFlip(RotateFlipType.Rotate90FlipXY); 
      break; 
     case gma.Drawing.ImageInfo.Orientation.RightTop: 
      rotatedImage.RotateFlip(RotateFlipType.Rotate90FlipNone); 
      break; 
     default: 
      break; 
    } 
    return rotatedImage; 
} 
+1

我會建議你使用一個開源工具進行無損旋轉(如jhead.exe出現)。你爲什麼不用你用來運行jhead的代碼打開另一個問題? – Douglas 2012-02-29 19:51:11

+0

您需要使用一個'Save'重載,它需要一個'ImageCodecInfo'和'EncoderParameters' - 參數應該包含高質量,以確保圖像不會顯着降級。 – Oded 2012-02-29 19:51:54

+0

@Oded:你的意思是「不會顯着降低」。將圖像編碼爲JPEG時,即使以「100%」質量進行編碼,實際上也總會出現退化。根據定義,格式是有損的。 – Douglas 2012-02-29 19:53:58

回答

2
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); 
ImageCodecInfo ici = null; 

foreach (ImageCodecInfo codec in codecs) 
{ 
    if (codec.MimeType == "image/jpeg") 
    ici = codec; 
} 

EncoderParameters ep = new EncoderParameters(); 
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100); 

originalImage.Save(f.FullName.ToString(), ici, ep); 

這將使用100%的品質 - 但請注意,JPEG文件仍然是有損壓縮 - 嘗試用一個PNG,如果你需要無損質量。

+0

這很好。謝謝。我想我會再次試着讓自己的工作。它似乎有點快。但是這個插入並且工作。 – 2012-03-01 01:56:14

+0

我應該指出 - 你不需要每次都查找jpeg編解碼器 - 你應該確保你的ici變量被緩存在任何循環之外。戴夫(和那個'ep'變量) – 2012-03-01 10:15:58

0

無損jpeg編輯的關鍵是始終使用相同的QualityLevel和BitmapCreateOptions.PreservePixelFormat |帶BitmapCacheOption.None的BitmapCreateOptions.IgnoreColorProfile。

請注意,即使您使用QualityLevel 100,質量也會下降。使用這種方法只是第一次,因爲它從未知的QualityLevel到80,但其他每個jpeg編輯都是無損的。

RotateJpeg(@"d:\!test\TestInTest\20160209_143609.jpg", 80, Rotation.Rotate90); 

public bool RotateJpeg(string filePath, int quality, Rotation rotation) { 
    var original = new FileInfo(filePath); 
    if (!original.Exists) return false; 
    var temp = new FileInfo(original.FullName.Replace(".", "_temp.")); 

    const BitmapCreateOptions createOptions = BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile; 

    try { 
    using (Stream originalFileStream = File.Open(original.FullName, FileMode.Open, FileAccess.Read)) { 
     JpegBitmapEncoder encoder = new JpegBitmapEncoder {QualityLevel = quality, Rotation = rotation}; 

     //BitmapCreateOptions.PreservePixelFormat | BitmapCreateOptions.IgnoreColorProfile and BitmapCacheOption.None 
     //is a KEY to lossless jpeg edit if the QualityLevel is the same 
     encoder.Frames.Add(BitmapFrame.Create(originalFileStream, createOptions, BitmapCacheOption.None)); 

     using (Stream newFileStream = File.Open(temp.FullName, FileMode.Create, FileAccess.ReadWrite)) { 
     encoder.Save(newFileStream); 
     } 
    } 
    } 
    catch (Exception) { 
    return false; 
    } 

    try { 
    temp.CreationTime = original.CreationTime; 
    original.Delete(); 
    temp.MoveTo(original.FullName); 
    } 
    catch (Exception) { 
    return false; 
    } 

    return true; 
} 
0

容易...

public static void Rotate90(string fileName) 
{ 
    Image Pic; 
    string FileNameTemp; 
    Encoder Enc = Encoder.Transformation; 
    EncoderParameters EncParms = new EncoderParameters(1); 
    EncoderParameter EncParm; 
    ImageCodecInfo CodecInfo = GetEncoderInfo("image/jpeg"); 

    // load the image to change 
    Pic = Image.FromFile(fileName); 

    // we cannot store in the same image, so use a temporary image instead 
    FileNameTemp = fileName + ".temp"; 

    // for rewriting without recompression we must rotate the image 90 degrees 
    EncParm = new EncoderParameter(Enc,(long)EncoderValue.TransformRotate90); 
    EncParms.Param[0] = EncParm; 

    // now write the rotated image with new description 
    Pic.Save(FileNameTemp,CodecInfo,EncParms); 
    Pic.Dispose(); 
    Pic = null; 

    // delete the original file, will be replaced later 
    System.IO.File.Delete(fileName); 
    System.IO.File.Move(FileNameTemp, fileName); 
} 
相關問題