Init
This commit is contained in:
366
Compressor/JPGCompressor.cs
Normal file
366
Compressor/JPGCompressor.cs
Normal file
@@ -0,0 +1,366 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ImageCompressor
|
||||
{
|
||||
/// <summary>
|
||||
/// 单张JPG的压缩运算
|
||||
/// </summary>
|
||||
class JPGCompressor
|
||||
{
|
||||
int compressLevel;
|
||||
int MaxWidth;
|
||||
int MaxHeight;
|
||||
long Quality;
|
||||
|
||||
ImageCodecInfo jpegEncoder;
|
||||
EncoderParameters jpeParameters;
|
||||
|
||||
public JPGCompressor(int compressLevel, int maxWidth,int maxHeight)
|
||||
{
|
||||
CompressLevel= compressLevel;
|
||||
MaxWidth = maxWidth;
|
||||
MaxHeight = maxHeight;
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 设定压缩质量
|
||||
/// </summary>
|
||||
public int CompressLevel
|
||||
{
|
||||
get { return compressLevel; }
|
||||
private set
|
||||
{
|
||||
compressLevel = value;
|
||||
Quality = compressLevel * 5 + 50; //(50-100)
|
||||
if (!SetJpegCompressor()) throw new Exception("Cannot Create JPG Comporessor");
|
||||
}
|
||||
}
|
||||
|
||||
public static int CompressionLevelToMaxWidth(int level)
|
||||
{
|
||||
return Math.Max((int)(1920 * (level * 0.2)), 480);//480-3840
|
||||
}
|
||||
public static int CompressionLevelToMaxHeight(int level)
|
||||
{
|
||||
return Math.Max((int)(1080 * (level * 0.2)), 360);//360-2160
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#region CompressBytes
|
||||
|
||||
/// <summary>
|
||||
/// 储存Bitmap到JPG文件。
|
||||
/// 之后释放 writeBitmap
|
||||
/// </summary>
|
||||
public bool SaveCompressBytes(byte[] saveBytes, FileInfo saveFile, out string errorMessage)
|
||||
{
|
||||
errorMessage = null;
|
||||
if (saveFile.Exists)
|
||||
{
|
||||
if (saveFile.IsReadOnly)
|
||||
{
|
||||
errorMessage = Localize.Get("Save file is ReadOnly. ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DirectoryInfo directory = saveFile.Directory;
|
||||
if (!directory.Exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
directory.Create();
|
||||
}
|
||||
catch
|
||||
{
|
||||
errorMessage = Localize.Get("Cannot create save folder. ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
File.WriteAllBytes(saveFile.FullName, saveBytes);
|
||||
return true;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is IOException)
|
||||
{
|
||||
errorMessage = Localize.Get("Save file is occupied. ");
|
||||
return false;
|
||||
}
|
||||
errorMessage = Localize.Get("Save file error at ")+$"{ex.Message}";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开一个Image文件,返回Bytes
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public byte[] ReadFileToBytes(FileInfo readFile, out string errorMessage)
|
||||
{
|
||||
errorMessage = null;
|
||||
if (!readFile.Exists)
|
||||
{
|
||||
errorMessage = Localize.Get("Read file not exist. ");
|
||||
return null;
|
||||
}
|
||||
if(readFile.Length > 1024 * 1024 * 256)
|
||||
{
|
||||
errorMessage = Localize.Get("Read image larger than 256 MB");
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
return File.ReadAllBytes(readFile.FullName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = Localize.Get("Read file error at ") + $"{ex.Message}";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte[] CompressBytes(byte[] readBytes, out string errorMessage)
|
||||
{
|
||||
MemoryStream memoryStream = null;
|
||||
MemoryStream saveMemoryStream = null;
|
||||
Bitmap rawBit = null;
|
||||
Graphics graphics = null;
|
||||
Bitmap newBit = null;
|
||||
|
||||
errorMessage = null;
|
||||
try
|
||||
{
|
||||
memoryStream = new MemoryStream(readBytes, false);
|
||||
saveMemoryStream = new MemoryStream();
|
||||
rawBit = new Bitmap(memoryStream);
|
||||
memoryStream.Close();
|
||||
memoryStream.Dispose();
|
||||
double percentW = (double)MaxWidth / rawBit.Width;
|
||||
double percentH = (double)MaxHeight / rawBit.Height;
|
||||
double percent = Math.Min(percentW, percentH);
|
||||
percent = Math.Min(1, percent);
|
||||
if (percent < 1 || compressLevel < 10)
|
||||
{
|
||||
int newW = (int)(percent * rawBit.Width);
|
||||
int newH = (int)(percent * rawBit.Height);
|
||||
newBit = new Bitmap(newW, newH);
|
||||
graphics = Graphics.FromImage(newBit);
|
||||
|
||||
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
|
||||
graphics.DrawImage(rawBit, 0, 0, newW, newH);
|
||||
graphics.Dispose();
|
||||
rawBit.Dispose();
|
||||
newBit.Save(saveMemoryStream, jpegEncoder, jpeParameters);
|
||||
newBit.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Level为10则直接储存JPG
|
||||
rawBit.Save(saveMemoryStream, jpegEncoder, jpeParameters);
|
||||
}
|
||||
int length = (int)saveMemoryStream.Length;
|
||||
saveMemoryStream.Position = 0;
|
||||
byte[] savedBytes = new byte[length];
|
||||
saveMemoryStream.Read(savedBytes, 0, length);
|
||||
saveMemoryStream.Close();
|
||||
saveMemoryStream.Dispose();
|
||||
return savedBytes;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = Localize.Get("Save file error at ")+$"{ex.Message}";
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
memoryStream?.Close();
|
||||
memoryStream?.Dispose();
|
||||
saveMemoryStream?.Close();
|
||||
saveMemoryStream?.Dispose();
|
||||
rawBit?.Dispose();
|
||||
newBit?.Dispose();
|
||||
graphics?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region CompressBitmap
|
||||
/// <summary>
|
||||
/// 储存Bitmap到JPG文件。
|
||||
/// </summary>
|
||||
/// <param name="bitmap"></param>
|
||||
/// <param name="savePath"></param>
|
||||
/// <param name="savedSizeInKB"></param>
|
||||
public bool SaveCompressBitmap(Bitmap bitmap, FileInfo saveFile, out long savedSizeInKB, out string errorMessage)
|
||||
{
|
||||
|
||||
savedSizeInKB = 0;
|
||||
errorMessage = null;
|
||||
if (saveFile.Exists)
|
||||
{
|
||||
if (saveFile.IsReadOnly)
|
||||
{
|
||||
errorMessage = Localize.Get("Save file is ReadOnly. ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DirectoryInfo directory = saveFile.Directory;
|
||||
if (!directory.Exists)
|
||||
{
|
||||
try
|
||||
{
|
||||
directory.Create();
|
||||
}
|
||||
catch
|
||||
{
|
||||
errorMessage = Localize.Get("Cannot create save folder. ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FileStream stream = null;
|
||||
try
|
||||
{
|
||||
stream = saveFile.Open(FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
|
||||
bitmap.Save(stream, jpegEncoder, jpeParameters);
|
||||
savedSizeInKB = stream.Length / 1024;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex is IOException)
|
||||
{
|
||||
errorMessage = Localize.Get("Save file is occupied. ");
|
||||
return false;
|
||||
}
|
||||
errorMessage = Localize.Get("Save file error at ") + $"{ex.Message}";
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
stream?.Close();
|
||||
stream?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开一个Image文件
|
||||
/// </summary>
|
||||
/// <param name="readFile"></param>
|
||||
/// <param name="image"></param>
|
||||
/// <param name="readSizeInKB"></param>
|
||||
/// <param name="errorMessage"></param>
|
||||
/// <returns></returns>
|
||||
public bool ReadFileToImage(FileInfo readFile, out Bitmap image, out long readSizeInKB, out string errorMessage)
|
||||
{
|
||||
image = null;
|
||||
readSizeInKB = 0;
|
||||
errorMessage = null;
|
||||
|
||||
if (!readFile.Exists)
|
||||
{
|
||||
errorMessage = Localize.Get("Read file not exist. ");
|
||||
return false;
|
||||
}
|
||||
FileStream stream = null;
|
||||
try
|
||||
{
|
||||
stream = readFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
|
||||
Image im = Image.FromStream(stream);
|
||||
image = new Bitmap(im);
|
||||
im.Dispose();
|
||||
readSizeInKB = stream.Length / 1024;
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
readSizeInKB = readFile.Length / 1024;
|
||||
errorMessage = Localize.Get("Save file error at ") + $"{ex.Message}";
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
stream?.Close();
|
||||
stream?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 将图片压缩,不释放Image
|
||||
/// </summary>
|
||||
/// <param name="raw"></param>
|
||||
/// <returns></returns>
|
||||
public Bitmap CompressImgToBitmap(Bitmap raw)
|
||||
{
|
||||
|
||||
double percentW = (double)MaxWidth / raw.Width;
|
||||
double percentH = (double)MaxHeight / raw.Height;
|
||||
double percent = Math.Min(percentW, percentH);
|
||||
percent = Math.Min(1, percent);
|
||||
if (percent < 1 || compressLevel < 10)
|
||||
{
|
||||
int newW = (int)(percent * raw.Width);
|
||||
int newH = (int)(percent * raw.Height);
|
||||
Bitmap newBit = new Bitmap(newW, newH);
|
||||
using (Graphics g = Graphics.FromImage(newBit))
|
||||
{
|
||||
|
||||
//g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
|
||||
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
|
||||
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
|
||||
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.Half;
|
||||
g.DrawImage(raw, 0, 0, newW, newH);
|
||||
return newBit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Bitmap bitmap = new Bitmap(raw);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
bool SetJpegCompressor()
|
||||
{
|
||||
var temp = ImageCodecInfo.GetImageDecoders();
|
||||
jpegEncoder = temp.FirstOrDefault(x => x.MimeType == "image/jpeg");
|
||||
if (jpegEncoder == null) return false;
|
||||
|
||||
System.Drawing.Imaging.Encoder encoder = System.Drawing.Imaging.Encoder.Quality;
|
||||
jpeParameters = new EncoderParameters(1);
|
||||
EncoderParameter parameter = new EncoderParameter(encoder, Quality);
|
||||
jpeParameters.Param[0] = parameter;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user