簡體   English   中英

C# 旋轉 JPG 而不會損失太多質量

[英]C# Rotating JPG without losing too much quality

所以我從一個目錄中讀取文件,找出它們需要旋轉的方式。 旋轉然后保存。 那部分有效......問題是,在保存文件后,它會被重新壓縮,我從 1.5meg 圖像變為 250k 圖像。 我需要將文件大小保持在原始文件附近。 我嘗試使用 jhead.exe 並從命令行調用它,但無法正確傳遞我的任何參數。 這是我用於檢測、旋轉和保存的代碼片段。

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;
}

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

請注意,即使您使用 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;
}

簡單的...

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); 
}

參見參考:

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。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM