2012-02-29 37 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); 
} 
相关问题