Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将水印图像写入上载的图像(在MVC控制器中)_C#_.net_Asp.net Mvc_Image Processing_Watermark - Fatal编程技术网

C# 将水印图像写入上载的图像(在MVC控制器中)

C# 将水印图像写入上载的图像(在MVC控制器中),c#,.net,asp.net-mvc,image-processing,watermark,C#,.net,Asp.net Mvc,Image Processing,Watermark,我想接受用户上传的图像文件,在角落里写一个16x16的小图标,然后将图像保存到我的Azure云存储中 我已经找到了一些关于这个话题的好帖子,但我不太明白。我以为我差点就拥有了它,但在TextureBrush行中,我摆脱了内存异常 请让我知道,如果有任何其他信息,我需要添加,并感谢任何帮助 以下是我迄今为止的工作(AddWaterMark是最糟糕的部分): -------------------工作方案如下------- 最初,我想在将上传的图像发送到azure存储之前,在中流媒体上添加水印。我想

我想接受用户上传的图像文件,在角落里写一个16x16的小图标,然后将图像保存到我的Azure云存储中

我已经找到了一些关于这个话题的好帖子,但我不太明白。我以为我差点就拥有了它,但在TextureBrush行中,我摆脱了内存异常

请让我知道,如果有任何其他信息,我需要添加,并感谢任何帮助

以下是我迄今为止的工作(AddWaterMark是最糟糕的部分):

-------------------工作方案如下-------

最初,我想在将上传的图像发送到azure存储之前,在中流媒体上添加水印。我想我真的很接近,但是我不能把它和其他的东西结合起来。我上传的图片一次一张,并且<2M,所以我决定采用一种解决方案,保存图片,贴上邮票,然后继续。以下是工作解决方案,欢迎评论:

注意:我已经将公司水印作为base64字符串放置在应用程序设置中,所以前几行只是将其拉出。返回后,调用方法仅获取克隆,上载并删除克隆。显然,有一些更优雅的方法来处理图像,但为了演示标记,这是可以接受的

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开始,可以根据需要根据尺寸缩小