RaUI/Source/MyDb/FileFuns/RyImage.cs
zilinsoft 3262955f2f ### 2023-11-07更新
------
#### RaUIV4    V4.0.2311.0701
- *.[全新]整合了MyDb、ryControls、MyDb_MySQL等dll文件到RaUI一个项目。
- *.[新增]新增ApkOp类,可以轻松获取APK信息。
- *.[新增]新增JsonExt扩展类,让Json操作更简单。
- *.[新增]新增WebP类,可以支持webp格式的图片。
- *.[改进]ryQuickSQL中的AddField方法改为自动替换已存在的同名值。
- *.[修复]ryQuickSQL中的AddFieldCalc方法无法正常计算的BUG。
2023-11-07 16:37:53 +08:00

976 lines
42 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrayNotify;
namespace ryCommon
{
/// <summary>
/// 图片相关API
/// </summary>
public static class RyImage
{
#region
private static EncoderParameters GetEncoderParameters()
{
System.Drawing.Imaging.Encoder myEncoder;
EncoderParameter myEncoderParameter;
EncoderParameters myEncoderParameters;
myEncoder = System.Drawing.Imaging.Encoder.Quality;
myEncoderParameters = new EncoderParameters(1);
// Save the bitmap as a JPEG file with quality level 100.
myEncoderParameter = new EncoderParameter(myEncoder, 100L);
myEncoderParameters.Param[0] = myEncoderParameter;
return myEncoderParameters;
}
private static ImageCodecInfo GetEncoderInfo(String mimeType)
{
int j;
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
for (j = 0; j < encoders.Length; ++j)
{
if (encoders[j].MimeType == mimeType)
return encoders[j];
}
return null;
}
private static ImageCodecInfo GetEncoderInfo(ryCommon.sType.ImageType type)
{
#region
ImageCodecInfo myImageCodecInfo;
string type_str = "image/jpeg";
switch (type)
{
case sType.ImageType.Bmp:
type_str = "image/bmp";
break;
case sType.ImageType.Jpeg:
type_str = "image/jpeg";
break;
case sType.ImageType.Gif:
type_str = "image/gif";
break;
case sType.ImageType.Tiff:
type_str = "image/tiff";
break;
case sType.ImageType.Png:
type_str = "image/png";
break;
}
myImageCodecInfo = GetEncoderInfo(type_str);
#endregion
return myImageCodecInfo;
}
#endregion
/// <summary>
/// 从文件或Url中加载图片,使用本方法,不会导致图片文件被占用。
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static Image LoadPic(string url)
{
if (url.IndexOfEx("http") == 0)
{
Image image = null;
try
{
WebRequest webreq = WebRequest.Create(url);
WebResponse webres = webreq.GetResponse();
Stream stream = webres.GetResponseStream();
image = Image.FromStream(stream);
stream.Close();
}
catch { }
return image;
}
else
{
if (!System.IO.File.Exists(url))
{ return null; }
try
{
FileStream fs = new FileStream(url, FileMode.Open, FileAccess.Read);
//把文件读取到字节数组
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
fs.Close();
//实例化一个内存流--->把从文件流中读取的内容[字节数组]放到内存流中去
MemoryStream ms = new MemoryStream(data);
//设置图片框 pictureBox1中的图片
return Image.FromStream(ms);
}
catch { return null; }
}
}
#region SaveHighQualityImage
/// <summary>
/// 保存高质量不失真照片
/// </summary>
/// <param name="m"></param>
/// <param name="path"></param>
/// <param name="type"></param>
public static void SaveHighQualityImage(this Bitmap m, string path, ryCommon.sType.ImageType type)
{
m.Save(path, GetEncoderInfo(type), GetEncoderParameters());
}
/// <summary>
/// 保存高质量不失真照片
/// </summary>
/// <param name="m"></param>
/// <param name="ms"></param>
/// <param name="type"></param>
public static void SaveHighQualityImage(this Bitmap m, MemoryStream ms, ryCommon.sType.ImageType type)
{
m.Save(ms, GetEncoderInfo(type), GetEncoderParameters());
}
/// <summary>
/// 保存高质量不失真照片
/// </summary>
/// <param name="m"></param>
/// <param name="path"></param>
/// <param name="type"></param>
public static void SaveHighQualityImage(this Image m, string path, ryCommon.sType.ImageType type)
{
m.Save(path, GetEncoderInfo(type), GetEncoderParameters());
}
/// <summary>
/// 保存高质量不失真照片
/// </summary>
/// <param name="m"></param>
/// <param name="path"></param>
public static bool SaveHighQualityImage(this Bitmap m, string path)
{
return SaveHighQualityImage((Image)m, path);
}
/// <summary>
/// 保存高质量不失真照片
/// </summary>
/// <param name="m"></param>
/// <param name="path"></param>
public static bool SaveHighQualityImage(this Image m, string path)
{
ryCommon.sType.ImageType type = sType.ImageType.Png;
var ext = System.IO.Path.GetExtension(path).ToLower();
switch (ext)
{
case ".png":
m.Save(path, GetEncoderInfo(type), GetEncoderParameters());
break;
case ".jpg":
type = sType.ImageType.Jpeg;
m.Save(path, GetEncoderInfo(type), GetEncoderParameters());
break;
case ".bmp":
type = sType.ImageType.Bmp;
m.Save(path, GetEncoderInfo(type), GetEncoderParameters());
break;
case ".gif":
type = sType.ImageType.Gif;
m.Save(path, GetEncoderInfo(type), GetEncoderParameters());
break;
case ".tif":
type = sType.ImageType.Tiff;
m.Save(path, GetEncoderInfo(type), GetEncoderParameters());
break;
default:
return false;
}
return true;
}
#region
/// <summary>
/// 以逆时针为方向对图像进行旋转
/// </summary>
/// <param name="b">位图流</param>
/// <param name="angle">旋转角度[0,360](前台给的)</param>
/// <returns></returns>
public static Bitmap Rotate(this Bitmap b, int angle)
{
angle = angle % 360;
//弧度转换
double radian = angle * Math.PI / 180.0;
double cos = Math.Cos(radian);
double sin = Math.Sin(radian);
//原图的宽和高
int w = b.Width;
int h = b.Height;
int W = (int)(Math.Max(Math.Abs(w * cos - h * sin), Math.Abs(w * cos + h * sin)));
int H = (int)(Math.Max(Math.Abs(w * sin - h * cos), Math.Abs(w * sin + h * cos)));
//目标位图
Bitmap dsImage = new Bitmap(W, H);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(dsImage);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//计算偏移量
Point Offset = new Point((W - w) / 2, (H - h) / 2);
//构造图像显示区域:让图像的中心与窗口的中心点一致
Rectangle rect = new Rectangle(Offset.X, Offset.Y, w, h);
Point center = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
g.TranslateTransform(center.X, center.Y);
g.RotateTransform(360 - angle);
//恢复图像在水平和垂直方向的平移
g.TranslateTransform(-center.X, -center.Y);
g.DrawImage(b, rect);
//重至绘图的所有变换
g.ResetTransform();
g.Save();
g.Dispose();
//dsImage.Save("yuancd.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
return dsImage;
}
#endregion
/// <summary>
/// 是否包括透明像素
/// </summary>
/// <param name="i"></param>
/// <returns></returns>
/// <exception cref="Exception">操作失败</exception>
public static bool HasTransparentPixel(this System.Drawing.Image i)
{
using (Bitmap bitmap = new Bitmap(i))
{
for (int x = 0; x < bitmap.Width; x++)
{
for (int y = 0; y < bitmap.Height; y++)
{
if (bitmap.GetPixel(x, y).A < 255)
{
return true;
}
}
}
}
return false;
}
/// <summary>
/// 矩形边界
/// </summary>
/// <param name="bounds"></param>
/// <param name="rect"></param>
/// <returns></returns>
private static Size ScaleRectangleToFitBounds(Size bounds, Size rect)
{
if (rect.Width < bounds.Width && rect.Height < bounds.Height)
{
return rect;
}
if (bounds.Width == 0 || bounds.Height == 0)
{
return new Size(0, 0);
}
double scaleFactorWidth = (double)rect.Width / bounds.Width;
double scaleFactorHeight = (double)rect.Height / bounds.Height;
double scaleFactor = Math.Max(scaleFactorWidth, scaleFactorHeight);
return new Size()
{
Width = (int)(rect.Width / scaleFactor),
Height = (int)(rect.Height / scaleFactor)
};
}
/// <summary>
/// 计算水印位置
/// </summary>
/// <param name="watermarkPosition"></param>
/// <param name="imageSize"></param>
/// <param name="watermarkSize"></param>
/// <returns></returns>
private static Point CalculateWatermarkPosition(WatermarkPosition watermarkPosition, Size imageSize, Size watermarkSize)
{
Point position = new Point();
switch (watermarkPosition)
{
case WatermarkPosition.TopLeftCorner:
position.X = 0;
position.Y = 0;
break;
case WatermarkPosition.TopCenter:
position.X = (imageSize.Width / 2) - (watermarkSize.Width / 2);
position.Y = 0;
break;
case WatermarkPosition.TopRightCorner:
position.X = imageSize.Width - watermarkSize.Width;
position.Y = 0;
break;
case WatermarkPosition.CenterLeft:
position.X = 0;
position.Y = (imageSize.Height / 2) - (watermarkSize.Height / 2);
break;
case WatermarkPosition.Center:
position.X = (imageSize.Width / 2) - (watermarkSize.Width / 2);
position.Y = (imageSize.Height / 2) - (watermarkSize.Height / 2);
break;
case WatermarkPosition.CenterRight:
position.X = imageSize.Width - watermarkSize.Width;
position.Y = (imageSize.Height / 2) - (watermarkSize.Height / 2);
break;
case WatermarkPosition.BottomLeftCorner:
position.X = 0;
position.Y = imageSize.Height - watermarkSize.Height;
break;
case WatermarkPosition.BottomCenter:
position.X = (imageSize.Width / 2) - (watermarkSize.Width / 2);
position.Y = imageSize.Height - watermarkSize.Height;
break;
case WatermarkPosition.BottomRightCorner:
position.X = imageSize.Width - watermarkSize.Width;
position.Y = imageSize.Height - watermarkSize.Height;
break;
}
return position;
}
/// <summary>
/// 写入水印
/// </summary>
/// <param name="image">原图</param>
/// <param name="wmImg">水印图片</param>
/// <param name="Position">水印位置</param>
/// <param name="opacity">不透明度(0~1),越小越透明</param>
/// <returns></returns>
public static Bitmap DrawWatermark(this Image image, Bitmap wmImg, WatermarkPosition Position, float opacity)
{
return DrawWatermark(image, wmImg, new List<WatermarkPosition>() { Position }, 0,0, opacity);
}
/// <summary>
/// 写入水印
/// </summary>
/// <param name="image">原图</param>
/// <param name="wmImg">水印图片</param>
/// <param name="Position">水印位置</param>
/// <param name="offset_x">x坐标偏移</param>
/// <param name="offset_y">y坐标偏移</param>
/// <param name="opacity">不透明度(0~1),越小越透明</param>
/// <returns></returns>
public static Bitmap DrawWatermark(this Image image, Bitmap wmImg, WatermarkPosition Position, int offset_x, int offset_y, float opacity)
{
return DrawWatermark(image, wmImg, new List<WatermarkPosition>() { Position }, offset_x, offset_y, opacity);
}
/// <summary>
/// 写入水印
/// </summary>
/// <param name="image">原图</param>
/// <param name="wmImg">水印图片</param>
/// <param name="PositionList">水印位置</param>
/// <param name="offset_x">x坐标偏移</param>
/// <param name="offset_y">y坐标偏移</param>
/// <param name="opacity">不透明度(0~1),越小越透明</param>
/// <returns></returns>
public static Bitmap DrawWatermark(this Image image, Bitmap wmImg, List<WatermarkPosition> PositionList,int offset_x, int offset_y, float opacity)
{
Bitmap bm1 = new Bitmap(image); //克隆原图,它也是我们的返回值
using (Graphics g = Graphics.FromImage(bm1))
{
Size calculatedWatermarkSize = ScaleRectangleToFitBounds(bm1.Size, wmImg.Size);
if (calculatedWatermarkSize.Width == 0 || calculatedWatermarkSize.Height == 0)
{
return bm1;
}
Bitmap scaledWatermarkBitmap =
new Bitmap(calculatedWatermarkSize.Width, calculatedWatermarkSize.Height);
using (Graphics watermarkGraphics = Graphics.FromImage(scaledWatermarkBitmap))
{
ColorMatrix opacityMatrix = new ColorMatrix
{
Matrix33 = opacity
};
ImageAttributes attrs = new ImageAttributes();
attrs.SetColorMatrix(opacityMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
watermarkGraphics.DrawImage(wmImg,
new Rectangle(0, 0, scaledWatermarkBitmap.Width, scaledWatermarkBitmap.Height),
0, 0, wmImg.Width, wmImg.Height,
GraphicsUnit.Pixel, attrs);
attrs.Dispose();
}
foreach (var position in PositionList)
{
if(position== WatermarkPosition.FullScreenTile)
{
//g.RotateTransform(-45);
//scaledWatermarkBitmap=scaledWatermarkBitmap.Rotate(45);
var space = 100;
var start_y = ((scaledWatermarkBitmap.Width - scaledWatermarkBitmap.Height) / Math.Sqrt(2)) + (Math.Sqrt(2) * scaledWatermarkBitmap.Height)- scaledWatermarkBitmap.Size.Height;
for (int i_y = start_y.ToInt()-50+offset_y; i_y < image.Size.Height*2; i_y += scaledWatermarkBitmap.Height + space)
{
for (int i_x = offset_x; i_x < image.Size.Width; i_x += scaledWatermarkBitmap.Width + space)
{
var bottomleft_x = i_x;
var bottomleft_y = i_y+ scaledWatermarkBitmap.Size.Height;
var bottomright_x = i_x +(scaledWatermarkBitmap.Size.Width / Math.Sqrt(2));//水印右上角x坐标
var bottomright_y = bottomleft_y - (scaledWatermarkBitmap.Size.Width / Math.Sqrt(2));//水印右上角y坐标
if (bottomright_x> image.Size.Width){ continue; }
if (bottomright_y< 0){ continue; }
if(bottomright_y > image.Size.Height) {
continue;
}
if (bottomleft_y > image.Size.Height) {
continue;
}
//if ((xx* Math.Sqrt(2))< scaledWatermarkBitmap.Size.Width) { continue; }
g.TranslateTransform(bottomleft_x, bottomleft_y);
g.RotateTransform(-45);
//if (i_x+ scaledWatermarkBitmap.Width> image.Size.Width) { continue; }
//if (i_y + scaledWatermarkBitmap.Height > image.Size.Height) { continue; }
g.DrawImage(scaledWatermarkBitmap,
new Rectangle(new Point(0,0), scaledWatermarkBitmap.Size),
0, 0, scaledWatermarkBitmap.Width, scaledWatermarkBitmap.Height, GraphicsUnit.Pixel);
g.TranslateTransform(-bottomleft_x, -bottomleft_y);
g.RotateTransform(45);
///////重置绘图平面的所有变换
g.ResetTransform();
}
}
continue;
}
Point watermarkPosition = CalculateWatermarkPosition(position,
image.Size, calculatedWatermarkSize);
watermarkPosition.Offset(offset_x, offset_y);
if(watermarkPosition.X<0 || watermarkPosition.Y < 0) { continue; }
if (watermarkPosition.X > bm1.Width- calculatedWatermarkSize.Width || watermarkPosition.Y>bm1.Height- calculatedWatermarkSize.Height) { continue; }
g.DrawImage(scaledWatermarkBitmap,
new Rectangle(watermarkPosition, calculatedWatermarkSize),
0, 0, calculatedWatermarkSize.Width, calculatedWatermarkSize.Height, GraphicsUnit.Pixel);
}
scaledWatermarkBitmap.Dispose();
}
return bm1;
}
/// <summary>
/// 计算最大字体大小
/// </summary>
/// <param name="text"></param>
/// <param name="angle"></param>
/// <param name="fontName"></param>
/// <param name="maxTextSize"></param>
/// <param name="g"></param>
/// <returns></returns>
private static int ComputeMaxFontSize(string text, int angle, string fontName, Size maxTextSize, Graphics g)
{
for (int fontSize = 2; ; fontSize++)
{
using (Font tmpFont = new Font(fontName, fontSize, FontStyle.Bold))
{
SizeF textSize = g.MeasureString(text, tmpFont);
SizeF rotatedTextSize = CalculateRotatedRectSize(textSize, angle);
if (((int)rotatedTextSize.Width > maxTextSize.Width) ||
((int)rotatedTextSize.Height > maxTextSize.Height))
{
return fontSize - 1;
}
}
}
}
/// <summary>
/// 计算旋转矩形大小
/// </summary>
/// <param name="rectSize"></param>
/// <param name="angleDeg"></param>
/// <returns></returns>
private static SizeF CalculateRotatedRectSize(SizeF rectSize, double angleDeg)
{
double angleRad = angleDeg * Math.PI / 180;
double width = rectSize.Height * Math.Abs(Math.Sin(angleRad)) +
rectSize.Width * Math.Abs(Math.Cos(angleRad));
double height = rectSize.Height * Math.Abs(Math.Cos(angleRad)) +
rectSize.Width * Math.Abs(Math.Sin(angleRad));
return new SizeF((float)width, (float)height);
}
/// <summary>
/// 写入水印文字
/// </summary>
/// <param name="image">图片</param>
/// <param name="wmText">水印文字</param>
/// <param name="WatermarkFont">水印字体名字</param>
/// <param name="TextColor">字体颜色</param>
/// <param name="TextSize">字体大小</param>
/// <param name="TextRotatedDegree">旋转角度</param>
/// <param name="PositionList">水印位置</param>
/// <param name="x">x坐标偏移</param>
/// <param name="y">y坐标偏移</param>
/// <param name="opacity">不透明度(0~1),越小越透明</param>
/// <returns></returns>
public static Bitmap DrawWatermark(this Image image, string wmText,string WatermarkFont,Color TextColor, int TextSize, int TextRotatedDegree, List<WatermarkPosition> PositionList, int x, int y, float opacity)
{
Bitmap bm1 = new Bitmap(image); //克隆原图,它也是我们的返回值
using (Graphics g = Graphics.FromImage(bm1))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
string text = wmText;
int textAngle = TextRotatedDegree;
double sizeFactor = (double)TextSize / 100;
Size maxTextSize = new Size(
(int)(bm1.Width * sizeFactor),
(int)(bm1.Height * sizeFactor));
int fontSize = ComputeMaxFontSize(text, textAngle, WatermarkFont, maxTextSize, g);
Font font = new Font(WatermarkFont, (float)fontSize, FontStyle.Bold);
SizeF originalTextSize = g.MeasureString(text, font);
SizeF rotatedTextSize = CalculateRotatedRectSize(originalTextSize, textAngle);
Bitmap textBitmap = new Bitmap((int)rotatedTextSize.Width, (int)rotatedTextSize.Height,
PixelFormat.Format32bppArgb);
using (Graphics textG = Graphics.FromImage(textBitmap))
{
Color color = Color.FromArgb((int)(opacity * 255), TextColor);
SolidBrush brush = new SolidBrush(color);
textG.TranslateTransform(rotatedTextSize.Width / 2, rotatedTextSize.Height / 2);
textG.RotateTransform((float)textAngle);
textG.DrawString(text, font, brush, -originalTextSize.Width / 2,
-originalTextSize.Height / 2);
textG.ResetTransform();
brush.Dispose();
}
foreach (var position in PositionList)
{
Point textPosition = CalculateWatermarkPosition(position,
bm1.Size, rotatedTextSize.ToSize());
g.DrawImage(textBitmap, textPosition);
}
textBitmap.Dispose();
font.Dispose();
}
return bm1;
}
/// <summary>
/// 写入水印文字
/// </summary>
/// <param name="image">图片</param>
/// <param name="wmText">水印文字</param>
/// <param name="WatermarkFont">水印字体名字</param>
/// <param name="TextColor">字体颜色</param>
/// <param name="TextSize">字体大小</param>
/// <param name="TextRotatedDegree">旋转角度</param>
/// <param name="Position">水印位置</param>
/// <param name="x">x坐标偏移</param>
/// <param name="y">y坐标偏移</param>
/// <param name="opacity">不透明度(0~1),越小越透明</param>
/// <returns></returns>
public static Bitmap DrawWatermark(this Image image, string wmText, string WatermarkFont, Color TextColor, int TextSize, int TextRotatedDegree, WatermarkPosition Position, int x, int y, float opacity)
{
return DrawWatermark(image, wmText, WatermarkFont, TextColor, TextSize, TextRotatedDegree,
new List<WatermarkPosition>() { Position }, x, y, opacity);
}
/// <summary>
/// 写入水印文字
/// </summary>
/// <param name="image">图片</param>
/// <param name="wmText">水印文字</param>
/// <param name="WatermarkFont">水印字体名字</param>
/// <param name="TextColor">字体颜色</param>
/// <param name="TextSize">字体大小</param>
/// <param name="TextRotatedDegree">旋转角度</param>
/// <param name="Position">水印位置</param>
/// <param name="opacity">不透明度(0~1),越小越透明</param>
/// <returns></returns>
public static Bitmap DrawWatermark(this Image image, string wmText, string WatermarkFont, Color TextColor, int TextSize, int TextRotatedDegree, WatermarkPosition Position, float opacity)
{
return DrawWatermark(image, wmText, WatermarkFont, TextColor, TextSize, TextRotatedDegree,
new List<WatermarkPosition>() { Position }, 0,0, opacity);
}
/// <summary>
/// 往图片右下角写入水印文字
/// </summary>
/// <param name="image">图片</param>
/// <param name="wmText">水印文字</param>
/// <param name="WatermarkFont">水印字体名字</param>
/// <param name="TextColor">字体颜色</param>
/// <param name="TextSize">字体大小</param>
/// <param name="opacity">不透明度(0~1),越小越透明</param>
/// <returns></returns>
public static Bitmap DrawWatermark(this Image image, string wmText, string WatermarkFont, Color TextColor, int TextSize, float opacity)
{
return DrawWatermark(image, wmText, WatermarkFont, TextColor, TextSize, 0,
new List<WatermarkPosition>() { WatermarkPosition.BottomRightCorner }, 0, 0, opacity);
}
/// <summary>
/// 往图片右下角写入水印文字
/// </summary>
/// <param name="image">图片</param>
/// <param name="wmText">水印文字</param>
/// <param name="WatermarkFont">水印字体名字</param>
/// <param name="TextColor">字体颜色</param>
/// <param name="TextSize">字体大小</param>
/// <returns></returns>
public static Bitmap DrawWatermark(this Image image, string wmText, string WatermarkFont, Color TextColor, int TextSize)
{
return DrawWatermark(image, wmText, WatermarkFont, TextColor, TextSize, 0,
new List<WatermarkPosition>() { WatermarkPosition.BottomRightCorner }, 0, 0, 0.1f);
}
/// <summary>
/// 缩放
/// </summary>
/// <param name="i"></param>
/// <param name="width">宽</param>
/// <param name="height">高</param>
/// <param name="mode">插值算法</param>
/// <returns>返回缩放后的图片</returns>
/// <exception cref="NullReferenceException">Image 不能为 null</exception>
/// <exception cref="Exception">操作失败</exception>
public static System.Drawing.Image Zoom(this System.Drawing.Image i, int width, int height, InterpolationMode mode)
{
Bitmap bitmap = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.InterpolationMode = mode;
g.Clear(Color.Empty);
g.DrawImage(i, new Rectangle(0, 0, width, height), new Rectangle(0, 0, i.Width, i.Height), GraphicsUnit.Pixel);
}
return bitmap;
}
/// <summary>
/// 缩放
/// </summary>
/// <param name="i"></param>
/// <param name="width">宽</param>
/// <param name="height">高</param>
/// <returns>返回缩放后的图片</returns>
/// <exception cref="NullReferenceException">Image 不能为 null</exception>
/// <exception cref="Exception">操作失败</exception>
public static System.Drawing.Image Zoom(this System.Drawing.Image i, int width, int height)
{
Bitmap bitmap = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.Clear(Color.Empty);
g.DrawImage(i, new Rectangle(0, 0, width, height), new Rectangle(0, 0, i.Width, i.Height), GraphicsUnit.Pixel);
}
return bitmap;
}
#endregion
/// <summary>
/// 根据原边长和新边长计算绘制的起始点坐标
/// </summary>
/// <param name="oldLength"></param>
/// <param name="newLength"></param>
/// <returns></returns>
private static int GetSrc(int oldLength, int newLength)
{
return ((float)(oldLength - newLength) / 2).ToInt();
}
/// <summary>
/// 获取缩放模式
/// </summary>
/// <param name="oldWidth"></param>
/// <param name="oldHeight"></param>
/// <param name="newWidth"></param>
/// <param name="newHeight"></param>
/// <param name="crop">是否裁剪图片</param>
/// <returns></returns>
private static ResizeMode GetMode(int oldWidth, int oldHeight, int newWidth, int newHeight, bool crop)
{
float oldScale = (float)oldWidth / oldHeight;
float newScale = (float)newWidth / newHeight;
if (crop)
{
return oldScale < newScale ? ResizeMode.WidthFirst : ResizeMode.HeightFirst;
}
else
{
return oldScale > newScale ? ResizeMode.WidthFirst : ResizeMode.HeightFirst;
}
}
/// <summary>
/// 裁剪或填充
/// </summary>
/// <param name="image"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="background">背景色</param>
/// <param name="mode">插值算法</param>
/// <returns></returns>
/// <exception cref="NullReferenceException">Image 不能为 null</exception>
/// <exception cref="Exception">操作失败</exception>
private static System.Drawing.Image CropOrFill(this System.Drawing.Image image, int width, int height, Color background, InterpolationMode mode)
{
Bitmap bitmap = new Bitmap(width, height);
using (Graphics g = Graphics.FromImage(bitmap))
{
g.InterpolationMode = mode;
int srcX = GetSrc(image.Width, width);
int srcY = GetSrc(image.Height, height);
g.Clear(background);
g.DrawImage(image, new Rectangle(0, 0, width, height), srcX, srcY, width, height, GraphicsUnit.Pixel);
}
return bitmap;
}
/// <summary>
/// 裁剪
/// </summary>
/// <param name="i"></param>
/// <param name="width">宽度</param>
/// <param name="height">高度</param>
/// <param name="interpolationMode"></param>
/// <returns>返回裁剪后的图片</returns>
/// <exception cref="NullReferenceException">Image 不能为 null</exception>
/// <exception cref="ArgumentOutOfRangeException">新的图片尺寸的宽度和高度必须大于零</exception>
/// <exception cref="Exception">操作失败</exception>
public static System.Drawing.Image Crop(this System.Drawing.Image i, int width, int height, InterpolationMode interpolationMode)
{
return i.ReSize(width, height,Color.Transparent, GetMode(i.Width, i.Height, width, height, true), interpolationMode);
}
/// <summary>
/// 调整宽度
/// </summary>
/// <param name="i"></param>
/// <param name="width"></param>
/// <returns></returns>
public static Image ReSizeW(this Image i, int width)
{
return i.ReSize(width, (((float)width / i.Width) * i.Height).ToInt(), ResizeMode.WidthFirst);
}
/// <summary>
/// 根据最大宽度调整图片尺寸
/// </summary>
/// <param name="i"></param>
/// <param name="maxWidth">最大宽度</param>
/// <returns>返回调整后的图片</returns>
/// <exception cref="NullReferenceException">Image 不能为 null</exception>
/// <exception cref="ArgumentOutOfRangeException">最大宽度必须大于零</exception>
/// <exception cref="Exception">操作失败</exception>
public static System.Drawing.Image ResizeMaxW(this System.Drawing.Image i, int maxWidth)
{
if (i.Width > maxWidth)
{
return i.ReSizeW(maxWidth);
}
else
{
return (System.Drawing.Image)i.Clone();
}
}
/// <summary>
/// 根据最大高度调整图片尺寸
/// </summary>
/// <param name="i"></param>
/// <param name="maxHeight">最大高度</param>
/// <returns>返回调整后的图片</returns>
/// <exception cref="NullReferenceException">Image 不能为 null</exception>
/// <exception cref="ArgumentOutOfRangeException">最大宽度必须大于零</exception>
/// <exception cref="Exception">操作失败</exception>
public static System.Drawing.Image ResizeMaxH(this System.Drawing.Image i, int maxHeight)
{
if (i.Height > maxHeight)
{
return i.ReSizeH(maxHeight);
}
else
{
return (System.Drawing.Image)i.Clone();
}
}
/// <summary>
/// 调整高度
/// </summary>
/// <param name="i"></param>
/// <param name="height"></param>
/// <returns></returns>
public static Image ReSizeH(this Image i, int height)
{
return i.ReSize((((float)height / i.Height) * i.Width).ToInt(), height, ResizeMode.WidthFirst);
}
/// <summary>
/// 调整图片大小
/// </summary>
/// <param name="i"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="resizeMode"></param>
/// <returns></returns>
public static Image ReSize(this Image i, int width, int height, ResizeMode resizeMode)
{
return ReSize(i, width, height, Color.Transparent, resizeMode);
}
/// <summary>
/// 调整图片大小
/// </summary>
/// <param name="i"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="background"></param>
/// <param name="resizeMode"></param>
/// <returns></returns>
public static Image ReSize(this Image i, int width, int height, Color background, ResizeMode resizeMode)
{
return ReSize(i,width,height,background,resizeMode, InterpolationMode.HighQualityBilinear);
}
/// <summary>
/// 调整图片大小
/// </summary>
/// <param name="i"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="background"></param>
/// <param name="resizeMode"></param>
/// <param name="interpolationMode"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static Image ReSize(this Image i,int width,int height, Color background, ResizeMode resizeMode, InterpolationMode interpolationMode)
{
if (width <= 0 || height <= 0)
{
throw new ArgumentOutOfRangeException("新的图片尺寸的宽和高必须大于零");
}
//如果原图片和新图片尺寸一致,克隆对象返回
if (i.Width == width && i.Height == height)
{
return (System.Drawing.Image)i.Clone();
}
if (((float)i.Width / i.Height == (float)width / height))
{
//如果原图片和新图片的比例相同,只缩放
return i.Zoom(width, height);
}
else
{
Size size = new Size();
//新宽高比
float scale = (float)width / height;
if (resizeMode == ResizeMode.WidthFirst)
{
//等宽,计算高
size.Width = i.Width;
size.Height = (i.Width / scale).ToInt();
}
else
{
//等高,计算宽
size.Height = i.Height;
size.Width = (i.Height * scale).ToInt();
}
//如果原图片和新图片的比例不同,先裁剪或填充后,再缩放
using (System.Drawing.Image cropOrFill = i.CropOrFill(size.Width, size.Height, background, interpolationMode))
{
return cropOrFill.Zoom(width, height, interpolationMode);
}
}
}
/// <summary>
/// 转换Image为Icon
/// </summary>
/// <param name="image">要转换为图标的Image对象</param>
/// <param name="nullTonull">当image为null时是否返回null。false则抛空引用异常</param>
/// <exception cref="ArgumentNullException" />
public static Icon ConvertToIcon(Image image, bool nullTonull = false)
{
if (image == null)
{
if (nullTonull) { return null; }
throw new ArgumentNullException("image");
}
using (MemoryStream msImg = new MemoryStream()
, msIco = new MemoryStream())
{
image.Save(msImg, ImageFormat.Png);
using (var bin = new BinaryWriter(msIco))
{
//写图标头部
bin.Write((short)0); //0-1保留
bin.Write((short)1); //2-3文件类型。1=图标, 2=光标
bin.Write((short)1); //4-5图像数量图标可以包含多个图像
bin.Write((byte)image.Width); //6图标宽度
bin.Write((byte)image.Height); //7图标高度
bin.Write((byte)0); //8颜色数若像素位深>=8填0。这是显然的达到8bpp的颜色数最少是256byte不够表示
bin.Write((byte)0); //9保留。必须为0
bin.Write((short)0); //10-11调色板
bin.Write((short)32); //12-13位深
bin.Write((int)msImg.Length); //14-17位图数据大小
bin.Write(22); //18-21位图数据起始字节
//写图像数据
bin.Write(msImg.ToArray());
bin.Flush();
bin.Seek(0, SeekOrigin.Begin);
return new Icon(msIco);
}
}
}
}
/// <summary>
/// 缩放模式
/// </summary>
public enum ResizeMode
{
/// <summary>
/// 宽度优先(不裁剪宽)
/// </summary>
WidthFirst,
/// <summary>
/// 高度优先(不裁剪高)
/// </summary>
HeightFirst
}
/// <summary>
/// 水印位置
/// </summary>
public enum WatermarkPosition
{
/// <summary>
/// 左上角
/// </summary>
TopLeftCorner,
/// <summary>
/// 中上
/// </summary>
TopCenter,
/// <summary>
/// 右上角
/// </summary>
TopRightCorner,
/// <summary>
/// 左中
/// </summary>
CenterLeft,
/// <summary>
/// 居中
/// </summary>
Center,
/// <summary>
/// 右中
/// </summary>
CenterRight,
/// <summary>
/// 左下角
/// </summary>
BottomLeftCorner,
/// <summary>
/// 中下
/// </summary>
BottomCenter,
/// <summary>
/// 右下角
/// </summary>
BottomRightCorner,
/// <summary>
/// 全屏平铺
/// </summary>
FullScreenTile,
}
}