using System; using System.Collections.Generic; using System.Drawing.Imaging; using System.Drawing; using System.IO; using System.Linq; using System.Diagnostics; namespace ImageCompressor { /// /// 单张JPG的压缩运算 /// 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; } /// /// 设定压缩质量 /// 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 /// /// 储存Bitmap到JPG文件。 /// 之后释放 writeBitmap /// 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; } } /// /// 打开一个Image文件,返回Bytes /// /// 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 /// /// 储存Bitmap到JPG文件。 /// /// /// /// 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(); } } /// /// 打开一个Image文件 /// /// /// /// /// /// 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(); } } /// /// 将图片压缩,不释放Image /// /// /// 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; } } }