2010-12-02 13 views
10

Tengo una tienda de comercio electrónico integrada en asp.net C# (Webforms) y muchas de las nuevas imágenes de productos son muy difíciles de obtener, por lo que me gustaría marcarlas con nuestro logotipo o nombre de dominio.Forma más eficiente de filmar la imagen C# On The Fly?

Hay demasiados productos para descargar las imágenes y agregar la marca de agua, y los usuarios con experiencia limitada en la edición de imágenes cargarán archivos nuevos (para que no tengan ni idea de cómo agregar la marca de agua).

Así que supongo que esto me deja con el uso de HttpHandler? ¿Si no? Si es así, puede proporcionar algunas ideas (Preferiblemente ejemplos de código en C#) en el manera más eficiente de agregar la marca de agua, considerando algunas páginas tendrán alrededor de 20 imágenes (JPEG) activadas (Todas las cuales deben tener marca de agua)

Respuesta

5

Me gustaría obtener el objeto Graphics a la jpeg, y luego dibujar la marca de agua en la parte superior de ese tema, y ​​guardarla de nuevo con la marca de agua:

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

El problema con esto es que probablemente reduce la calidad de la imagen de toda la imagen debido a la re-JPEG compresión en lugar de solo los bloques donde está la marca de agua. Pero no sé si hay una manera fácil de hacerlo mejor. – CodesInChaos

+0

Si bien reducirá la calidad de la imagen, siempre y cuando solo se haga una vez, no debería ser un gran problema, especialmente en el tipo de tamaños/resolución para una imagen web promedio. A menos, por supuesto, que la compresión sea demasiado alta, entonces terminas con el tipo de desastre que produce Paint. – themaninthesuitcase

0

La optimización evidente para cualquier 'la imagen mosca en wartermarking 'es almacenar en caché la imagen' marca de agua 'si puede pagar el costo de almacenamiento. Por lo tanto, la eficiencia de la operación de marcado no importa mucho.

1

Esta no es una respuesta tanto como algunos consejos:

  1. JPEG no es compatible con la transparencia, la mejor es probable que pueda hacer es añadir la imagen de marca de agua y que sea de un color gris muy claro.
  2. Utilice el controlador genérico (.ashx), es muy liviano y le evita tener que agregar nada a su archivo web.config.
  3. Si va a haber más de 20 imágenes por página, le recomiendo que agregue la marca de agua a medida que obtiene las imágenes. Este es un costo por imagen por única vez y hará que cargar páginas con las imágenes sea más rápido.

No puedo responder por la forma más eficiente de agregar una marca de agua, pero si opta por la punta 3, se vuelve menos importante ya que solo realizará la operación una vez por imagen. Probablemente usaría el espacio de nombres System.Drawing para hacer esto; solo asegúrese de deshacerse de los recursos que usa (Imagen, Gráficos, etc.), aunque estoy seguro de que hay bibliotecas que funcionarían mucho mejor.

+2

Las etapas intermedias de agregar la marca de agua no están vinculadas a las restricciones de un archivo JPEG, por lo que podría poner una marca de agua transparente en una imagen sin problemas. –

+0

Tiene razón, aunque he tenido malas experiencias con System.Drawing Library al cargar una imagen de un tipo y guardarla como otro tipo (problemas de calidad de imagen), por lo que no recomendaría hacerlo. Además, si guardara como un formato que permite la transparencia, sería ya sea gif (que no es bueno para imágenes de calidad fotográfica) o png (que no es compatible con algunos navegadores más antiguos). No me considero un experto en imágenes, estas observaciones se basan en mis experiencias pasadas. –

2

Le sugiero que eche un vistazo a las clases de WPF para hacer este trabajo (GDI + están en desuso en un contexto web).

La forma (no sé si es la mejor manera, pero yo ya he hecho esto y funciona bastante bien) es algo similar a:

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

Por supuesto, todos escritos como HttpHandler. El código anterior no está probado.

(anuncios pequeños: he publicado un CodeCanyon Item que hacen un trabajo similar).

+0

Esta es una respuesta anterior, pero espero que veas esto: ¿por qué estás usando 96 para los valores de ppp? – JoseMarmolejos

+0

Es arbitrario. Tuve que elegir un dpi fijo para la salida, y muchos piensan que 96dpi reemplazará el estándar web real (72dpi) ... pero sí, no hay un motivo REAL – tanathos

3

Aquí está una muestra de 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; 
     } 
    } 
} 

y pueden ser llamados como tales:

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