C#旋转JPG而不会损失太多质量

时间:2012-02-29 19:46:39

标签: c# resize drawing jpeg rotation

所以我正在读取目录中的文件,弄清楚它们需要旋转的方式。旋转然后保存。该部分有效...问题是,在保存文件后,它会被重新压缩,我从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;
}

3 个答案:

答案 0 :(得分: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。

答案 1 :(得分:1)

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

答案 2 :(得分: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); 
}