Самый эффективный способ водяных знаков C # на лету? - PullRequest
10 голосов
/ 02 декабря 2010

У меня есть интернет-магазин, встроенный в asp.net c # (Webforms), и многие изображения новых продуктов очень трудно найти, поэтому я бы хотел добавить к ним водяные знаки с нашим логотипом или доменным именем.

Существует слишком много продуктов, чтобы просто загрузить изображения и добавить водяной знак, и пользователи с ограниченным опытом редактирования изображений будут загружать новые (поэтому они не будут иметь понятия, как добавить водяной знак).

Так что я думаю, что это просто оставляет меня с использованием HttpHandler?Да нет?Если да, то можете ли вы дать некоторое представление (желательно примеры кода на C #) о наиболее эффективном способе добавления водяного знака, учитывая, что на некоторых страницах будет около 20 изображений (JPEG) на (Всеиз которых должны быть водяные знаки)

Ответы [ 6 ]

5 голосов
/ 02 декабря 2010

Я бы получил объект Graphics в формате jpeg, а затем нарисовал водяной знак поверх этого элемента и снова сохранил его с водяным знаком:

using (Image image = Image.FromFile("myImage.jpg"))
using(Graphics g = Graphics.FromImage( image)){
  g.DrawImage( myWaterMarkImage, myPosition);
  image.Save(myFilename);
}
3 голосов
/ 02 декабря 2010

Вот пример 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;
        }
    }
}

и можно назвать так:

<asp:Image ID="Image1" runat="server" ImageUrl="~/ImageHandler.ashx?Image=BlueHills&Opacity=50" />
3 голосов
/ 02 декабря 2010

Похоже, это может быть полезно:

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

Несмотря на то, что он фокусируется на тексте, я уверен, что с небольшой модификацией вы также можете добавить графическое изображение.

Если у вас есть реализация, вы можете вызывать ее один раз для каждого представления или при добавлении до сохранения файла.

2 голосов
/ 02 декабря 2010

Я предлагаю вам взглянуть на классы WPF, чтобы выполнить эту работу (GDI + устарели в веб-контексте).

Способ (я не знаю, ЛУЧШИЙ ли это, но я 'мы уже сделали это и работаем довольно хорошо) что-то похожее на:

// 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

Конечно, все написано как HttpHandler.Код выше не проверен.

(небольшие объявления: я опубликовал элемент CodeCanyon , который выполняет аналогичную работу).

1 голос
/ 02 декабря 2010

Это не столько ответ, сколько несколько советов:

  1. Jpeg не поддерживает прозрачность, лучшее, что вы можете сделать, это добавить изображение водяного знака и сделать его светло-серымcolor.
  2. Используйте универсальный обработчик (.ashx), он очень легкий и не позволяет вам добавлять что-либо в ваш файл web.config.
  3. Если их будет более 20изображений на странице, то я бы порекомендовал добавить водяной знак, как вы получаете изображения.Это единовременная плата за изображение, которая ускорит загрузку страниц с изображениями.

Я не могу поручиться за наиболее эффективный способ добавления водяного знака, но если вы воспользуетесь подсказкой #3, это становится менее важным, так как вы будете выполнять операцию только один раз для каждого изображения.Я бы, вероятно, просто использовал пространство имен System.Drawing для этого;Обязательно распоряжайтесь ресурсами, которые вы используете (изображения, графика и т. д.), хотя я уверен, что есть библиотеки, которые будут работать намного лучше.

0 голосов
/ 02 декабря 2010

Очевидная оптимизация для любого «предупреждения на изображении на лету» - это кэширование изображения с водяным знаком, если вы можете позволить себе стоимость хранения.Таким образом, эффективность самой торговой операции не имеет большого значения.

...