[英]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.