C# 以JPG文件为中心覆盖水印PNG
我有一种方法,可以获取图像并调整其大小,然后保存它,同时保留exif信息。我现在要做的是在图像顶部覆盖一个透明的PNG图像作为水印。png的大小将始终大于我要放置它的任何图像。我想把它放在图像的中心,保持水印的纵横比。以下是我目前掌握的代码:C# 以JPG文件为中心覆盖水印PNG,c#,system.drawing,C#,System.drawing,我有一种方法,可以获取图像并调整其大小,然后保存它,同时保留exif信息。我现在要做的是在图像顶部覆盖一个透明的PNG图像作为水印。png的大小将始终大于我要放置它的任何图像。我想把它放在图像的中心,保持水印的纵横比。以下是我目前掌握的代码: private static void ResizeImage(Image theImage, int newSize, string savePath, IEnumerable<PropertyItem> propertyItems) {
private static void ResizeImage(Image theImage, int newSize, string savePath, IEnumerable<PropertyItem> propertyItems)
{
int width;
int height;
CalculateNewRatio(theImage.Width, theImage.Height, newSize, out width, out height);
using (var b = new Bitmap(width, height))
{
using (var g = Graphics.FromImage(b))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
using(var a = Image.FromFile("Watermark.png"))
{
g.DrawImage(); //What to do here?
}
g.DrawImage(theImage, new Rectangle(0, 0, width, height));
var qualityParam = new EncoderParameter(Encoder.Quality, 80L);
var codecs = ImageCodecInfo.GetImageEncoders();
var jpegCodec = codecs.FirstOrDefault(t => t.MimeType == "image/jpeg");
var encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;
foreach(var item in propertyItems)
{
b.SetPropertyItem(item);
}
b.Save(savePath, jpegCodec, encoderParams);
}
}
}
private static void ResizeImage(图像、整型新闻大小、字符串保存路径、IEnumerable属性项)
{
整数宽度;
内部高度;
计算范围(图像宽度、图像高度、新闻大小、外宽、外高);
使用(var b=新位图(宽度、高度))
{
使用(var g=Graphics.FromImage(b))
{
g、 SmoothingMode=SmoothingMode.AntiAlias;
g、 插值模式=插值模式。高质量双三次;
g、 PixelOffsetMode=PixelOffsetMode.HighQuality;
使用(var a=Image.FromFile(“Watermark.png”))
{
g、 DrawImage();//在这里做什么?
}
g、 DrawImage(图像,新矩形(0,0,宽度,高度));
var qualityParam=新编码器参数(编码器质量,80L);
var codecs=ImageCodecInfo.GetImageEncoders();
var jpegCodec=codecs.FirstOrDefault(t=>t.MimeType==“image/jpeg”);
var encoderParams=新的EncoderParameters(1);
encoderParams.Param[0]=qualityParam;
foreach(propertyItems中的var项)
{
b、 SetPropertyItem(项目);
}
b、 保存(保存路径、JPEG编解码器、编码器参数);
}
}
}
要在画布上缩放图像以获得最佳匹配,同时保留纵横比,过程相当简单:
double widthFactor = b.Width / a.Width;
double heightFactor = b.Height / a.Height;
double scaleFactor = Math.Min(widthFactor, heightFactor);
int newWidth = a.Width * scaleFactor;
int newHeight = a.Width * scaleFactor;
要计算图像居中的位置,只需再进行一些数学运算:
int left = (b.Width - newWidth) / 2;
int top = (b.Height - newHeight) / 2;
然后使用Graphics.DrawImage方法的适当形式。我找到了解决方案,代码如下。可能不是最理想的代码,但它速度很快,并且做了我需要它做的事情,即在一个目录中获取所有JPG图像,并将它们重新调整为照片库的完整图像和拇指图像,同时在图像上覆盖水印
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace ImageResize
{
internal class Program
{
private static readonly string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
private static void Main()
{
var strFiles = Directory.GetFiles(directory, "*.jpg");
//Using parallel processing for performance
Parallel.ForEach(strFiles, strFile =>
{
using (var image = Image.FromFile(strFile, true))
{
var exif = image.PropertyItems;
var b = directory + "\\" + Path.GetFileNameWithoutExtension(strFile);
ResizeImage(image, 800, b + "_FULL.jpg", exif);
ResizeImage(image, 200, b + "_THUMB.jpg", exif);
}
File.Delete(strFile);
});
}
private static void ResizeImage(Image theImage, int newSize, string savePath, IEnumerable<PropertyItem> propertyItems)
{
try
{
int width;
int height;
CalculateNewRatio(theImage.Width, theImage.Height, newSize, out width, out height);
using (var b = new Bitmap(width, height))
{
using (var g = Graphics.FromImage(b))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(theImage, new Rectangle(0, 0, width, height));
//Using FileStream to avoid lock issues because of the parallel processing
using (var stream = new FileStream(directory + "\\Watermark.png", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var overLay = Image.FromStream(stream))
{
stream.Close();
int newWidth;
int newHeight;
CalculateNewRatio(overLay.Width, overLay.Height, height > width ? width : newSize, out newWidth, out newHeight);
var x = (b.Width - newWidth) / 2;
var y = (b.Height - newHeight) / 2;
g.DrawImage(overLay, new Rectangle(x, y, newWidth, newHeight));
}
}
var qualityParam = new EncoderParameter(Encoder.Quality, 80L);
var codecs = ImageCodecInfo.GetImageEncoders();
var jpegCodec = codecs.FirstOrDefault(t => t.MimeType == "image/jpeg");
var encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = qualityParam;
foreach (var item in propertyItems)
{
b.SetPropertyItem(item);
}
b.Save(savePath, jpegCodec, encoderParams);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
private static void CalculateNewRatio(int width, int height, int desiredSize, out int newWidth, out int newHeight)
{
if ((width >= height && width > desiredSize) || (width <= height && height > desiredSize))
{
if (width > height)
{
newWidth = desiredSize;
newHeight = height*newWidth/width;
}
else if (width < height)
{
newHeight = desiredSize;
newWidth = width*newHeight/height;
}
else
{
newWidth = desiredSize;
newHeight = desiredSize;
}
}
else
{
newWidth = width;
newHeight = height;
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统图;
使用System.Drawing.Drawing2D;
使用系统、绘图、成像;
使用System.IO;
使用System.Linq;
运用系统反思;
使用System.Threading.Tasks;
命名空间ImageResize
{
内部课程计划
{
私有静态只读字符串目录=Path.GetDirectoryName(Assembly.getExecutionGassembly().Location);
私有静态void Main()
{
var strFiles=Directory.GetFiles(Directory,*.jpg”);
//使用并行处理提高性能
Parallel.ForEach(strFile,strFile=>
{
使用(var image=image.FromFile(strFile,true))
{
var exif=image.PropertyItems;
var b=directory+“\\”+Path.GetFileNameWithoutExtension(strFile);
调整图像大小(图像,800,b+“_FULL.jpg”,exif);
调整图像大小(图像,200,b+“_THUMB.jpg”,exif);
}
文件。删除(strFile);
});
}
私有静态void ResizeImage(图像、整型新闻大小、字符串保存路径、IEnumerable属性项)
{
尝试
{
整数宽度;
内部高度;
计算范围(图像宽度、图像高度、新闻大小、外宽、外高);
使用(var b=新位图(宽度、高度))
{
使用(var g=Graphics.FromImage(b))
{
g、 SmoothingMode=SmoothingMode.AntiAlias;
g、 插值模式=插值模式。高质量双三次;
g、 PixelOffsetMode=PixelOffsetMode.HighQuality;
g、 DrawImage(图像,新矩形(0,0,宽度,高度));
//使用FileStream避免由于并行处理而导致的锁问题
使用(var stream=newfilestream(目录+“\\Watermark.png”、FileMode.Open、FileAccess.Read、FileShare.ReadWrite))
{
使用(var overLay=Image.FromStream(stream))
{
stream.Close();
int newWidth;
int newHeight;
计算覆盖(overLay.Width,overLay.Height,Height>Width?Width:newSize,out-newWidth,out-newHeight);
var x=(b.Width-newWidth)/2;
变量y=(b.高度-新高度)/2;
g、 DrawImage(叠加,新矩形(x,y,newWidth,newHeight));
}
}
var qualityParam=新编码器参数(编码器质量,80L);
var codecs=ImageCodecInfo.GetImageEncoders();
var jpegCodec=codecs.FirstOrDefault(t=>t.MimeType==“image/jpeg”);
var encoderParams=新的EncoderParameters(1);
encoderParams.Param[0]=qualityParam;
foreach(propertyItems中的var项)
{
b、 SetPropertyItem(项目);
}
b、 保存(保存路径、JPEG编解码器、编码器参数);