------ #### RaUIV4 V4.0.2311.0701 - *.[全新]整合了MyDb、ryControls、MyDb_MySQL等dll文件到RaUI一个项目。 - *.[新增]新增ApkOp类,可以轻松获取APK信息。 - *.[新增]新增JsonExt扩展类,让Json操作更简单。 - *.[新增]新增WebP类,可以支持webp格式的图片。 - *.[改进]ryQuickSQL中的AddField方法改为自动替换已存在的同名值。 - *.[修复]ryQuickSQL中的AddFieldCalc方法无法正常计算的BUG。
976 lines
42 KiB
C#
976 lines
42 KiB
C#
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的颜色数最少是256,byte不够表示)
|
||
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,
|
||
}
|
||
}
|