代码:
方法1:方法较简单,相对于其他方法来说不安全,Size参数也不太合适,换成尺寸大小更好一点
public static Bitmap GetImageThumb(Bitmap mg, Size newSize)
{
double ratio = 0d;
double myThumbWidth = 0d;
double myThumbHeight = 0d;
int x = 0;
int y = 0;
Bitmap bp;
if ((mg.Width / Convert.ToDouble(newSize.Width)) > (mg.Height /
Convert.ToDouble(newSize.Height)))
ratio = Convert.ToDouble(mg.Width) / Convert.ToDouble(newSize.Width);
else
ratio = Convert.ToDouble(mg.Height) / Convert.ToDouble(newSize.Height);
myThumbHeight = Math.Ceiling(mg.Height / ratio);
myThumbWidth = Math.Ceiling(mg.Width / ratio);
Size thumbSize = new Size((int)newSize.Width, (int)newSize.Height);
bp = new Bitmap(newSize.Width, newSize.Height);
x = (newSize.Width - thumbSize.Width) / 2;
y = (newSize.Height - thumbSize.Height);
System.Drawing.Graphics g = Graphics.FromImage(bp);
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
Rectangle rect = new Rectangle(x, y, thumbSize.Width, thumbSize.Height);
g.DrawImage(mg, rect, 0, 0, mg.Width, mg.Height, GraphicsUnit.Pixel);
return bp;
}
方法二:结构及使用非托管资源的处理相比第一个要好一些,但压缩后文件大小和第一个差不多
protected static Size CalculateDimensions(Size originalSize, int targetSize)
{
var newSize = new Size();
if (originalSize.Height > originalSize.Width) // portrait
{
newSize.Width = (int)(originalSize.Width * (float)(targetSize / (float)originalSize.Height));
newSize.Height = targetSize;
}
else // landscape or square
{
newSize.Height = (int)(originalSize.Height * (float)(targetSize / (float)originalSize.Width));
newSize.Width = targetSize;
}
return newSize;
}
public static byte[] ValidatePicture(byte[] pictureBinary, string mimeType, ImageFormat rawFormat)
{
using (var stream1 = new MemoryStream(pictureBinary))
{
using (var b = new Bitmap(stream1))
{
var maxSize = 720;
if ((b.Height <= maxSize) && (b.Width <= maxSize))
return pictureBinary;
var newSize = CalculateDimensions(b.Size, maxSize);
using (var newBitMap = new Bitmap(newSize.Width, newSize.Height))
{
using (var g = Graphics.FromImage(newBitMap))
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(b, 0, 0, newSize.Width, newSize.Height);
using (var stream2 = new MemoryStream())
{
var ep = new EncoderParameters();
ep.Param[0] = new EncoderParameter(Encoder.Quality, 80L);
ImageCodecInfo ici = GetImageCodecInfoFromMimeType(mimeType);
if (ici == null)
ici = GetImageCodecInfoFromMimeType("image/jpeg");
newBitMap.Save(stream2, ici, ep);
newBitMap.Save(@"C:\Users\Administrator\Desktop\照片\name91.jpg", ici, ep);
newBitMap.Save(@"C:\Users\Administrator\Desktop\照片\name9.jpg",rawFormat);
return stream2.GetBuffer();
}
}
}
}
}
}
protected static ImageCodecInfo GetImageCodecInfoFromMimeType(string mimeType)
{
var info = ImageCodecInfo.GetImageEncoders();
foreach (var ici in info)
if (ici.MimeType.Equals(mimeType, StringComparison.OrdinalIgnoreCase))
return ici;
return null;
}
方法三:相对于其他两个方法,这个是循环压缩的,一直到满足条件为止,同时还把文件给保存下来了
/// <summary>
/// 无损压缩图片
/// </summary>
/// <param name="sFile">原图片地址</param>
/// <param name="dFile">压缩后保存图片地址</param>
/// <param name="flag">压缩质量(数字越小压缩率越高)1-100</param>
/// <param name="size">压缩后图片的最大大小</param>
/// <param name="sfsc">是否是第一次调用</param>
/// <returns></returns>
public static bool CompressImage(string sFile, string dFile, int flag = 90, int size = 300, bool sfsc = true)
{
//如果是第一次调用,原始图像的大小小于要压缩的大小,则直接复制文件,并且返回true
FileInfo firstFileInfo = new FileInfo(sFile);
if (sfsc == true && firstFileInfo.Length < size * 1024)
{
firstFileInfo.CopyTo(dFile);
return true;
}
Image iSource = Image.FromFile(sFile);
ImageFormat tFormat = iSource.RawFormat;
int dHeight = iSource.Height / 2;
int dWidth = iSource.Width / 2;
int sW = 0, sH = 0;
//按比例缩放
Size tem_size = new Size(iSource.Width, iSource.Height);
if (tem_size.Width > dHeight || tem_size.Width > dWidth)
{
if ((tem_size.Width * dHeight) > (tem_size.Width * dWidth))
{
sW = dWidth;
sH = (dWidth * tem_size.Height) / tem_size.Width;
}
else
{
sH = dHeight;
sW = (tem_size.Width * dHeight) / tem_size.Height;
}
}
else
{
sW = tem_size.Width;
sH = tem_size.Height;
}
Bitmap ob = new Bitmap(dWidth, dHeight);
Graphics g = Graphics.FromImage(ob);
g.Clear(Color.WhiteSmoke);
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);
g.Dispose();
//以下代码为保存图片时,设置压缩质量
EncoderParameters ep = new EncoderParameters();
long[] qy = new long[1];
qy[0] = flag;//设置压缩的比例1-100
EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
ep.Param[0] = eParam;
try
{
ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo jpegICIinfo = null;
for (int x = 0; x < arrayICI.Length; x++)
{
if (arrayICI[x].FormatDescription.Equals("JPEG"))
{
jpegICIinfo = arrayICI[x];
break;
}
}
if (jpegICIinfo != null)
{
ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径
FileInfo fi = new FileInfo(dFile);
if (fi.Length > 1024 * size)
{
flag = flag - 10;
CompressImage(sFile, dFile, flag, size, false);
}
}
else
{
ob.Save(dFile, tFormat);
}
return true;
}
catch
{
return false;
}
finally
{
iSource.Dispose();
ob.Dispose();
}
}
中间遇到的问题:
压缩完之后保存的时候,刚开始用这种方法newBitMap.Save(@"C:\Users\Administrator\Desktop\照片\name9.jpg"),保存的图片比原本的还大,以为没有压缩成功,后来用newBitMap.Save(@"C:\Users\Administrator\Desktop\照片\name9.jpg",rawFormat);保存后,图片变小了,第三种方法newBitMap.Save(@"C:\Users\Administrator\Desktop\照片\name91.jpg", ici, ep);图片的尺寸更小,和压缩效果一致。
最后根据实际业务情况选择合适的方法:
while (arr.Length > 10 * 1024)
{
arr = ValidatePicture(arr, "jpg");
}
public static byte[] ValidatePicture(byte[] pictureBinary, string mimeType)
{
using (var stream1 = new MemoryStream(pictureBinary))
{
using (var b = new Bitmap(stream1))
{
//var maxSize = 720;
//if ((b.Height <= maxSize) && (b.Width <= maxSize))
// return pictureBinary;
//var newSize = CalculateDimensions(b.Size, maxSize);
int dHeight = b.Height / 2;
int dWidth = b.Width / 2;
int sW = 0, sH = 0;
//按比例缩放
Size tem_size = new Size(b.Width, b.Height);
if (tem_size.Width > dHeight || tem_size.Width > dWidth)
{
if ((tem_size.Width * dHeight) > (tem_size.Width * dWidth))
{
sW = dWidth;
sH = (dWidth * tem_size.Height) / tem_size.Width;
}
else
{
sH = dHeight;
sW = (tem_size.Width * dHeight) / tem_size.Height;
}
}
else
{
sW = tem_size.Width;
sH = tem_size.Height;
}
var newSize = new Size(sW, sH);
using (var newBitMap = new Bitmap(newSize.Width, newSize.Height))
{
using (var g = Graphics.FromImage(newBitMap))
{
g.SmoothingMode = SmoothingMode.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(b, 0, 0, newSize.Width, newSize.Height);
using (var stream2 = new MemoryStream())
{
var ep = new EncoderParameters();
ep.Param[0] = new EncoderParameter(Encoder.Quality, 50L);
ImageCodecInfo ici = GetImageCodecInfoFromMimeType(mimeType);
if (ici == null)
ici = GetImageCodecInfoFromMimeType("image/jpeg");
newBitMap.Save(stream2, ici, ep);
newBitMap.Save(@"C:\Users\Administrator\Desktop\照片\name911.jpg", ici, ep);
return stream2.GetBuffer();
}
}
}
}
}
}
附上 image和bitmap相互转换方法
Image img = this.pictureBox1.Image;
Bitmap map = new Bitmap(img);
Bitmap map = new Bitmap(img);
Image img=map;