C# 将水印图像写入上载的图像(在MVC控制器中)
我想接受用户上传的图像文件,在角落里写一个16x16的小图标,然后将图像保存到我的Azure云存储中 我已经找到了一些关于这个话题的好帖子,但我不太明白。我以为我差点就拥有了它,但在TextureBrush行中,我摆脱了内存异常 请让我知道,如果有任何其他信息,我需要添加,并感谢任何帮助 以下是我迄今为止的工作(AddWaterMark是最糟糕的部分): -------------------工作方案如下------- 最初,我想在将上传的图像发送到azure存储之前,在中流媒体上添加水印。我想我真的很接近,但是我不能把它和其他的东西结合起来。我上传的图片一次一张,并且<2M,所以我决定采用一种解决方案,保存图片,贴上邮票,然后继续。以下是工作解决方案,欢迎评论: 注意:我已经将公司水印作为base64字符串放置在应用程序设置中,所以前几行只是将其拉出。返回后,调用方法仅获取克隆,上载并删除克隆。显然,有一些更优雅的方法来处理图像,但为了演示标记,这是可以接受的C# 将水印图像写入上载的图像(在MVC控制器中),c#,.net,asp.net-mvc,image-processing,watermark,C#,.net,Asp.net Mvc,Image Processing,Watermark,我想接受用户上传的图像文件,在角落里写一个16x16的小图标,然后将图像保存到我的Azure云存储中 我已经找到了一些关于这个话题的好帖子,但我不太明白。我以为我差点就拥有了它,但在TextureBrush行中,我摆脱了内存异常 请让我知道,如果有任何其他信息,我需要添加,并感谢任何帮助 以下是我迄今为止的工作(AddWaterMark是最糟糕的部分): -------------------工作方案如下------- 最初,我想在将上传的图像发送到azure存储之前,在中流媒体上添加水印。我想
public void AddWaterMark(string filepath)
{
//var outStream = new MemoryStream();
var watermarkImageBase64 = Settings.Default.CompanyWatermark;
var data = Convert.FromBase64String(watermarkImageBase64);
using (var streamWatermark = new MemoryStream(data, 0, data.Length))
using (var watermark = Image.FromStream(streamWatermark))
using (var targetImage = Image.FromFile(filepath))
using (var g = Graphics.FromImage(targetImage))
{
var destX = (targetImage.Width - watermark.Width) - 10;
var destY = 10;
g.DrawImage(watermark, new Rectangle(destX, destY, watermark.Width, watermark.Height));
using (var cloneImage = (Image) targetImage.Clone())
{
cloneImage.Save(Server.MapPath("~/User_Data/cloneImage.png"));
}
}
这种方法有一点我不喜欢……传入的图像在水印点已经转换为png,但水印是16x16,并且根据目标图像的尺寸看起来更小或更大。无论目标图像的分辨率如何,都希望它“显示”在相同的大小。应该很容易 通过将图像绘制到目标,可以更简单地为图像添加水印。
TextureBrush
可以在整个目标上平铺图像
这是使用较大的水印图像(125x125),但这并不重要,因为您可以将其缩略到所需的大小:
// show before
pbWM.Image = Image.FromFile(@"C:\Temp\horus_w.png");
using (Image watermark = Image.FromFile(@"C:\Temp\horus_w.png"))
using (Image TargetImg = Image.FromFile(@"C:\Temp\BigHead.jpg"))
using (Graphics g = Graphics.FromImage(TargetImg))
{
var destX = (TargetImg.Width - watermark.Width) - 10;
var destY = (TargetImg.Height - watermark.Height) - 10;
g.DrawImage(watermark, new Rectangle(destX,
destY,
watermark.Width,
watermark.Height));
// display a clone for demo purposes
pb2.Image = (Image)TargetImg.Clone();
}
玫瑰色图像是裸露的水印图像,另一个是最终的结果。使用TexturedBrush
你可以做一些事情,比如使用平铺的、有角度的、不透明度低的文本作为水印:
创建TextureBrush
时,有时会出现此错误,我通过指定大小来避免此错误:
using (TextureBrush br = new TextureBrush(wmImg,
new Rectangle(0, 0, wmImg.Width - 1, wmImg.Height - 1)))
{
g.FillRectangle(br, 0, 0, Marked.Width, Marked.Height);
}
另外,如果水印图像/徽标相同,我会将其存储在一个变量中,并反复使用相同的图像。问题中的代码每次都创建一个新的
水印图像
,而不是处理它。通过将图像绘制到目标,可以更简单地为图像添加水印。TextureBrush
可以在整个目标上平铺图像
这是使用较大的水印图像(125x125),但这并不重要,因为您可以将其缩略到所需的大小:
// show before
pbWM.Image = Image.FromFile(@"C:\Temp\horus_w.png");
using (Image watermark = Image.FromFile(@"C:\Temp\horus_w.png"))
using (Image TargetImg = Image.FromFile(@"C:\Temp\BigHead.jpg"))
using (Graphics g = Graphics.FromImage(TargetImg))
{
var destX = (TargetImg.Width - watermark.Width) - 10;
var destY = (TargetImg.Height - watermark.Height) - 10;
g.DrawImage(watermark, new Rectangle(destX,
destY,
watermark.Width,
watermark.Height));
// display a clone for demo purposes
pb2.Image = (Image)TargetImg.Clone();
}
玫瑰色图像是裸露的水印图像,另一个是最终的结果。使用TexturedBrush
你可以做一些事情,比如使用平铺的、有角度的、不透明度低的文本作为水印:
创建TextureBrush
时,有时会出现此错误,我通过指定大小来避免此错误:
using (TextureBrush br = new TextureBrush(wmImg,
new Rectangle(0, 0, wmImg.Width - 1, wmImg.Height - 1)))
{
g.FillRectangle(br, 0, 0, Marked.Width, Marked.Height);
}
另外,如果水印图像/徽标相同,我会将其存储在一个变量中,并反复使用相同的图像。问题中的代码是每次都创建一个新的
水印图像
,而不是处理它。你不需要使用纹理刷,如果水印图像是PNG,就把它画到角落。我认为这个例外是误导性的,因为内存充足。我已经了解到,如果过早处理或试图在图像加载之前使用图像,可能会发生这种情况……我目前正在将FromStream替换为FromFile,以防base64字符串不正确或损坏。我将研究你的建议。我不经常使用这些类,所以这有点困难。对于不完整的代码,我深表歉意。目标是:当我的最终用户将图像资产上传到我的应用程序时,它们将存储在azure中。我只想在图像资产的右上角放置一个16x16 png的品牌徽标。当我调用blob.UploadFromStream方法时,需要绘制它并准备将其流式传输到存储容器。我认为问题完全与图形方面有关,而不是Azure(假设您在流中实际获得了有效的图像)。您可以通过这些参数将结果大小控制为g.DrawImage()
。但16x16无法很好地扩展。如果从64x64或128x128开始,可以根据需要根据要标记的图像的大小将其缩小。正如我所说的,我会创建一次水印图像,并将其保留,而不是每次使用都重新创建。它不会改变,是吗?你不需要一个纹理刷,如果水印图像是PNG,就把它画到角落。我认为这个例外是误导性的,因为它有足够的内存。我已经了解到,如果过早处理或试图在图像加载之前使用图像,可能会发生这种情况……我目前正在将FromStream替换为FromFile,以防base64字符串不正确或损坏。我将研究你的建议。我不经常使用这些类,所以这有点困难。对于不完整的代码,我深表歉意。目标是:当我的最终用户将图像资产上传到我的应用程序时,它们将存储在azure中。我只想在图像资产的右上角放置一个16x16 png的品牌徽标。当我调用blob.UploadFromStream方法时,需要绘制它并准备将其流式传输到存储容器。我认为问题完全与图形方面有关,而不是Azure(假设您在流中实际获得了有效的图像)。您可以通过这些参数将结果大小控制为g.DrawImage()
。但16x16无法很好地扩展。如果您从64x64或128x128开始,可以根据需要根据尺寸缩小