简体   繁体   English

最有效的水印图像C#On the Fly?

[英]Most Efficient Way To Watermark Image C# On The Fly?

I have an ecommerce store built in asp.net c# (Webforms) and a lot of the new product images are very hard to source, so I'd like to watermark them with our logo or domain name. 我有一个用asp.net c#(Webforms)构建的电子商务商店,很多新产品图片很难找到,所以我想用我们的徽标或域名给它们添加水印。

There are too many products to just download the images and add the watermark, and users with limited image editing experience will be uploading new ones (So they won't have a clue how to add the watermark). 有太多的产品只能下载图像并添加水印,具有有限图像编辑经验的用户将上传新的(因此他们将不知道如何添加水印)。

So I guess this just leaves me with using a HttpHandler? 所以我想这只是让我使用HttpHandler? Yes / No? 是/否? If so can you provide some insight (Preferably code samples in C#) into the most efficient way of adding the watermark, considering some pages will have around 20 images (Jpegs) on (All of which need to be watermarked) 如果是这样,你可以提供一些洞察力(最好是C#中的代码样本)到最有效的添加水印的方法,考虑到一些页面将有大约20个图像 (Jpegs)(所有这些都需要加水印)

I would obtain the Graphics object to the jpeg, and then draw the watermark on top of that item, and save it again with the watermark: 我将获取Graphics对象到jpeg,然后在该项目的顶部绘制水印,并使用水印再次保存:

using (Image image = Image.FromFile("myImage.jpg"))
using(Graphics g = Graphics.FromImage( image)){
  g.DrawImage( myWaterMarkImage, myPosition);
  image.Save(myFilename);
}

This looks like it could be helpful: 看起来它可能会有所帮助:

http://www.switchonthecode.com/tutorials/csharp-snippet-tutorial-how-to-draw-text-on-an-image http://www.switchonthecode.com/tutorials/csharp-snippet-tutorial-how-to-draw-text-on-an-image

While it focus's on text, I am sure with a little modification you could add a graphic in also. 虽然它专注于文本,但我确信只需稍加修改即可添加图形。

Once you have an implementation you could either call it once per view or when adding prior to saving the file. 实现后,您可以在每个视图中调用一次,也可以在保存文件之前添加。

Here is a sample HttpHandler 这是一个示例HttpHandler

/// <summary>
/// Summary description for $codebehindclassname$
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class ImageHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        string imageName = string.Empty;
        string physicalPath = string.Empty;
        Image image = null;
        Image thumbnailImage = null;
        Bitmap bitmap = null;
        using (MemoryStream memoryStream = new MemoryStream())
        {
            string actionName = context.Request.QueryString["Image"];
            string opacity = context.Request.QueryString["Opacity"];
            int opacityPercent = int.Parse(opacity);
            Color waterMarkColor = Color.Gray;
            switch (actionName)
            {
                case "BlueHills":
                    string myCompany = "My Company Name";
                    Font font = new Font("Times New Roman", 8f);

                    context.Response.ContentType = "image/png";
                    bitmap = Resources.Resources.BlueHills;
                    Graphics g = Graphics.FromImage(bitmap);
                    Brush myBrush = new SolidBrush(Color.FromArgb(opacityPercent, waterMarkColor));
                    SizeF sz = g.MeasureString(myCompany, font);
                    int X = (int)(bitmap.Width - sz.Width) / 2;
                    int Y = (int)(sz.Height) / 2;
                    g.DrawString(myCompany, font, myBrush, new Point(X, Y));
                    bitmap.Save(memoryStream, ImageFormat.Png);
                    break;
                default:
                    string test = actionName;
                    break;
            }

            context.Response.BinaryWrite(memoryStream.GetBuffer());
            memoryStream.Close();
            if (image != null) { image.Dispose(); }
            if (thumbnailImage != null) { thumbnailImage.Dispose(); }
            if (bitmap != null) { bitmap.Dispose(); }
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

and can be called like such: 并可以像这样调用:

<asp:Image ID="Image1" runat="server" ImageUrl="~/ImageHandler.ashx?Image=BlueHills&Opacity=50" />

I suggest you to take a look to WPF classes to do this job (GDI+ are deprecated in a web context). 我建议你看看WPF类来完成这项工作(GDI +在Web上下文中已被弃用)。

The way (I don't know if is THE BEST way, but I've already done this and works pretty fine) is something similar to: 方式(我不知道是不是最好的方式,但我已经完成了这个并且工作得非常好)类似于:

// Load the original image
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(physical_imagepath);
image.EndInit();

// Create a final render image
RenderTargetBitmap final = new RenderTargetBitmap(yourNeededWidth, yourNeededHeight, yourDpiDefault, yourDpiDefault, PixelFormats.Default);

DrawingVisual dv = new DrawingVisual();

using (DrawingContext dc = dv.RenderOpen())
{
    Rect rectImage = new Rect(0, 0, (double)image.PixelWidth, (double)image.PixelHeight);
    dc.DrawImage(image, rectImage);

    // Load the bitmap of the watermark
    BitmapImage watermark = new BitmapImage();
    watermark.BeginInit();
    watermark.CacheOption = BitmapCacheOption.OnLoad;
    watermark.UriSource = new Uri(physical_logopath);
    watermark.EndInit();

    // Defines the watermark box
    Rect rectWatermark = new Rect(0, 0, (double)watermark.PixelWidth, (double)watermark.PixelHeight);

    /* use rectWatermark.X and rectWatermark.Y to move your watermark box around on the final image */

    dc.DrawImage(watermark, rectWatermark);
}

final.Render(dv);

// And then serve the final Bitmap to the client

Of course all written as HttpHandler. 当然全都写成HttpHandler。 The code above is not tested. 上面的代码未经过测试。

(little ads: I've published a CodeCanyon Item that do a similar job). (小广告:我发布了一个类似工作的CodeCanyon项目 )。

This isn't an answer so much as a few tips: 这不是一个答案,而是一些提示:

  1. Jpeg doesn't support transparency, the best you can probably do is add the watermark image and make it a very light grey color. Jpeg不支持透明度,你可以做的最好的事情是添加水印图像并使其成为浅灰色。
  2. Use the generic handler (.ashx), it's very lightweight and prevents you from having to add anything to your web.config file. 使用通用处理程序(.ashx),它非常轻量级,可以防止您向web.config文件添加任何内容。
  3. If there are going to be upwards of 20 images per page, then I would recommend adding the watermark as you get the images. 如果每页最多有20张图像,那么我会建议您在获取图像时添加水印。 This is a one-time cost per image and will make loading pages with the images faster. 这是每张图像的一次性成本,并且可以使加载页面的图像更快。

I can't vouch for the most efficient way of adding a watermark, but if you go with tip #3, it becomes less important as you will only be performing the operation once ever per image. 我不能保证添加水印的最有效方法,但如果你使用#3提示,它就变得不那么重要了,因为你只会对每个图像执行一次操作。 I would probably just use the System.Drawing namespace to do this; 我可能只是使用System.Drawing命名空间来执行此操作; just be sure to dispose of the resources you use (Image, Graphics, etc), though I'm sure there are libraries out there that would work much better. 请务必处理您使用的资源(图像,图形等),但我确信有些库可以更好地工作。

The obvious optimization to any 'on the fly image wartermarking' is to cache the 'watermarked' image if you can afford the storage cost. 任何“即时图像标记”的明显优化是,如果您能负担得起存储成本,则缓存“水印”图像。 So, the efficiency of the wartermarking operation itself do not matters much. 因此,wartermarking操作本身的效率并不重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM