图片加水印是网站中使用非常广泛的技术,可以保护网站内容的版权,例如我博客这样的网站。在传统ASP.NET(.NET Framework)中,我们可以使用System.Web.Helpers.WebImage来添加水印,就像这样:
代码语言:javascript复制var image = new WebImage(imageBytes);
image.AddTextWatermark(
Settings.Instance.WatermarkText, "White", Settings.Instance.WatermarkFontSize,
opacity: Settings.Instance.WatermarkTextOpacityPercentage
);
但是在.NET Core中,没有WebImage这个类型了。我们如何给图片加水印呢?
我们从图片上传开始。在ASP.NET Core中,我们用IFormFile来上传文件,也包括图片文件。需要详细了解可以参考微软官方文档:https://docs.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads?view=aspnetcore-2.1
在我的博客系统里,我写了一个Action用来上传图片,将图片文件塞到一个MemoryStream对象里,之后的图片存储服务就可以把它保存到目标位置
代码语言:javascript复制[Route("image/upload")]
public async Task<IActionResult> UploadImageAsync(IFormFile file)
{
...
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
... // call underlying image storage service
}
...
}
要添加水印,我们需要修改图片stream。
但是.NET Core默认情况下没有处理图片的能力,因为System.Drawing命名空间里的API是非常有限的。我们需要引用一个微软官方的NuGet包来引入我们在.NET Framework中曾经熟悉的那些API:
Install-Package System.Drawing.Common -Version 4.5.1
现在我们就可以访问System.Drawing.Image 和 System.Drawing.Graphics等API了。
下面的代码将会使用这些类型在上传的图片的stream上添加文字水印:
代码语言:javascript复制// Add watermark
var watermarkedStream = new MemoryStream();
using (var img = Image.FromStream(stream))
{
using (var graphic = Graphics.FromImage(img))
{
var font = new Font(FontFamily.GenericSansSerif, 20, FontStyle.Bold, GraphicsUnit.Pixel);
var color = Color.FromArgb(128, 255, 255, 255);
var brush = new SolidBrush(color);
var point = new Point(img.Width - 120, img.Height - 30);
graphic.DrawString("edi.wang", font, brush, point);
img.Save(watermarkedStream, ImageFormat.Png);
}
}
结果就是这样的:
其中有一些要注意的地方:
1. 你不能更改原始stream,如果你尝试把图片存储覆盖原始stream的话,是不会有效果的,就像这样:
代码语言:javascript复制img.Save(stream, ImageFormat.Png);
这就是为啥我定义了另一个watermarkedStream对象。
2. 针对水印的位置,也就是point对象。我的计算方式是添加水印到图片右下角,你需要根据自己需要修改这个位置。
3. 我建议字体采用跨平台的字体,因为.NET Core不止能部署在Windows上。
最后,我博客里上传图片加水印的完整样例代码如下:
代码语言:javascript复制[Authorize]
[HttpPost]
[Route("image/upload")]
public async Task<IActionResult> UploadImageAsync(IFormFile file)
{
try
{
if (null == file)
{
Logger.LogError("file is null.");
return BadRequest();
}
if (file.Length > 0)
{
var name = Path.GetFileName(file.FileName);
if (name != null)
{
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
// Add watermark
var watermarkedStream = new MemoryStream();
using (var img = Image.FromStream(stream))
{
using (var graphic = Graphics.FromImage(img))
{
var font = new Font(FontFamily.GenericSansSerif, 20, FontStyle.Bold, GraphicsUnit.Pixel);
var color = Color.FromArgb(128, 255, 255, 255);
var brush = new SolidBrush(color);
var point = new Point(img.Width - 120, img.Height - 30);
graphic.DrawString("edi.wang", font, brush, point);
img.Save(watermarkedStream, ImageFormat.Png);
}
}
var response = await _imageStorageProvider.InsertAsync(name, watermarkedStream.ToArray());
Logger.LogInformation("Image Upload: " JsonConvert.SerializeObject(response));
if (response.IsSuccess)
{
string refPath = "/uploads/" response.Item;
return Json(new { location = refPath });
}
Logger.LogError(response.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}
return BadRequest();
}
catch (Exception e)
{
Logger.LogError(e, $"Error uploading image.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}