miércoles, 20 de junio de 2012

Marca de Agua

Objetivo

Para esta entrada se marcan dos objetivos diferentes con las marcas de agua:

-    Se desea conseguir, en función a una imagen origen, una imagen destino con una marca de agua que será otra imagen.
  
-    Se desea conseguir, en función de una imagen origen, una imagen destino con una marca de agua al pie que será un texto. Por ejemplo el Copyright.

Marca de Agua con Imagen

Esta marca de agua estará creada por otra imagen. Es decir, se fusionarán 2 imágenes diferentes en 1. Para conseguirlo habrá que aprovechar el GDI de .NET, las librerías gráficas de las que dispone .NET. Con este ejemplo, la marca de agua resultante estará centrada.


Librerías


-     System.Drawing;
-     System.Drawing.Imaging;
-     System.Drawing.Drawing2D;


Clases


-    Image: Funciones y propiedades de imágenes (abrir, guardar, etc)
-    BitMap: Mapa de Bits.
-    Graphics: Se emplea para “pintar”


Procedimiento


-    Inicialmente se cargan las dos imágenes, la imagen origen y la que actuará como marca de agua.
-     A continuación, crear un BitMap que servirá como lienzo en el que “pintar” la nueva imagen.
-    Creamos un objeto Graphic asociado al BitMap.
-    A continuación, pintar la imagen original con la función ‘DrawImage’ del objeto Graphic. Se debe especificar el ancho y alto de la imagen.  Previamente se pueden especificar efectos de suavizado.
-    Después seleccionar las posiciones para la marca de agua.
-    Lo siguiente será pintar la marca de agua con el objeto graphics en la posición calculada. Se puede  (se debe) aplicar transparencia a la imagen con los atributos de la imagen y una matriz de transparencia.
-    Finalmente pasar el Bitmap a un objeto imagen y guardar la imagen con el formato que se desee. Descargamos de memoria los objetos Image y Graphics.


Código


 
        ///  -----------------------------------------------------------------------------
        /// 
        ///  Genera una imagen con una marca de agua que es otra imagen.
        /// 
        /// 


Ruta de la imagen original
        /// 


Ruta de la imagen que servirá de marca de agua
        /// 


Ruta de la imagen final con la marca de agua
        /// 
        ///  [fcortes] 01/06/2012 10:55:10
        /// 
        ///  -----------------------------------------------------------------------------
        public bool marcaAguaImagen(string rutaImgOrig, string rutaMarca, string rutaImgDest, bool transparencia)
        {
            bool exito = true;
            Image imgPhoto = null;
            Image imgWatermark = null;
            try
            {
                // Cargamos la foto original
                imgPhoto = Image.FromFile(rutaImgOrig);
                // Cargamos la imagen de la marca de agua
                imgWatermark = new Bitmap(rutaMarca);
            }
            catch (Exception ex)
            {
                exito = false;
            }
            if (exito)
            {
                // Obtenemos ancho y alto de la foto
                int phWidth = imgPhoto.Width;
                int phHeight = imgPhoto.Height;

                //Creamos un nuevo mapa de bits con el ancho y alto de la imagen origen
                Bitmap bmPhoto = new Bitmap(phWidth, phHeight,
                                     PixelFormat.Format24bppRgb);
                //bmPhoto.SetResolution(72, 72);

                // Obtenemos el objeto graphics del mapa de bits bmPhoto. 
                Graphics grPhoto = Graphics.FromImage(bmPhoto);



                int wmWidth = imgWatermark.Width;
                int wmHeight = imgWatermark.Height;

                // Suavizado de contorno
                grPhoto.SmoothingMode = SmoothingMode.AntiAlias;
                // Pintamos la imagen de origen
                grPhoto.DrawImage(
                    imgPhoto,
                    new Rectangle(0, 0, phWidth, phHeight),
                    0,
                    0,
                    phWidth,
                    phHeight,
                    GraphicsUnit.Pixel);
                // Atributos para la marca de agua (por si deseamos cambiar la transparencia etc)
                ImageAttributes imageAttributes =
                               new ImageAttributes();

                //Si deseamos transparencia
                if (transparencia)
                {
                    float[][] colorMatrixElements = { 
               new float[] {1.0f,  0.0f,  0.0f,  0.0f, 0.0f},
               new float[] {0.0f,  1.0f,  0.0f,  0.0f, 0.0f},
               new float[] {0.0f,  0.0f,  1.0f,  0.0f, 0.0f},
               new float[] {0.0f,  0.0f,  0.0f,  0.3f, 0.0f},
               new float[] {0.0f,  0.0f,  0.0f,  0.0f, 1.0f}
                };

                    ColorMatrix wmColorMatrix = new
                                    ColorMatrix(colorMatrixElements);

                    imageAttributes.SetColorMatrix(wmColorMatrix,
                                           ColorMatrixFlag.Default,
                                             ColorAdjustType.Bitmap);
                }
                // Posicion centrada de la marca de agua
                int xPosOfWm = (phWidth / 2) - (wmWidth / 2);
                int yPosOfWm = (phHeight / 2) - (wmHeight / 2);
                // Pintamos la marca de agua en nuestro mapa de bits.
                grPhoto.DrawImage(imgWatermark,
                    new Rectangle(xPosOfWm, yPosOfWm, wmWidth,
                                                     wmHeight),
                    0,
                    0,
                    wmWidth,
                    wmHeight,
                    GraphicsUnit.Pixel,
                    imageAttributes);
                // Vamos a cambiar la imagen por lo que la sacamos de memoria antes
                imgPhoto.Dispose();
                // Pasamos el bitmap a un Image para aprovecharnos de sus propiedades
                imgPhoto = bmPhoto;
                // Descargamos de memoria el graphics
                grPhoto.Dispose();
                // Guardamos la imagen
                imgPhoto.Save(rutaImgDest,
                    ImageFormat.Jpeg);

                imgPhoto.Dispose();
                imgWatermark.Dispose();
            }

            return exito;
        }

Marca de Agua Texto

Esta marca de agua estará creada por un texto, fusionando 1 imagen con texto. Para conseguirlo habrá que aprovechar el GDI de .NET, las librerías gráficas de las que dispone .NET. La marca de agua resultante estará centrada.


Librerías


-     System.Drawing;
-     System.Drawing.Imaging;
-     System.Drawing.Drawing2D;


Clases


-    Image: Funciones y propiedades de imágenes (abrir, guardar, etc)
-    BitMap: Mapa de Bits.
-    Graphics: Se emplea para “pintar”


Procedimiento


-    Cargar la imagen.
-    A continuación, crear un BitMap que servirá como lienzo en el que “pintar” la nueva imagen.
-    Crear un objeto Graphic asociado al BitMap.
-    Encontrar tamaño de letra que maximiza el ancho.
-    Seleccionar laposición en la que pintar las letras. Usar un align center para facilitar algo las cosas.
-    Pintar dos veces las letras usando el método de Graphics ‘DrawString’. Se deben usar dos Brush diferentes (dos pinceles) y uno de los 'draw' realizarlo un pixel en X e Y más adelantado. Con esto último conseguimos efecto sombreado.
-    Finalmente pasar el Bitmap a un objeto imagen y guardar la imagen con el formato que se desee. Descargar de memoria los objetos Image y Graphics.

Código


 
 ///  -----------------------------------------------------------------------------
        /// 
        ///  Genera una imagen con una marca de agua que es un texto (Copyright)
        /// 
        /// 


Ruta de la imagen original
        /// 


Texto que deseamos escribir
        /// 


Ruta de la imagen de destino
        /// 
        ///  [fcortes] 01/06/2012 11:08:56
        /// 
        ///  -----------------------------------------------------------------------------
        public bool marcaAguaTexto(string rutaImgOrig, string textoMarca, string rutaImgDest)
        {
            bool exito = true;
            // Cargamos la foto original
            Image imgPhoto = Image.FromFile(rutaImgOrig);
            // Obtenemos ancho y alto de la foto
            int phWidth = imgPhoto.Width;
            int phHeight = imgPhoto.Height;

            Bitmap bmPhoto = new Bitmap(phWidth, phHeight,
                                 PixelFormat.Format24bppRgb);
            //bmPhoto.SetResolution(72, 72);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);

            grPhoto.SmoothingMode = SmoothingMode.AntiAlias;
            grPhoto.DrawImage(
                imgPhoto,
                new Rectangle(0, 0, phWidth, phHeight),
                0,
                0,
                phWidth,
                phHeight,
                GraphicsUnit.Pixel);

            //To maximize the size of the Copyright message we will test 7 different Font sizes 
            // to determine the largest possible size we can use for the width of our Photograph.
            int[] sizes = new int[] { 16, 14, 12, 10, 8, 6, 4 };
            Font crFont = null;
            SizeF crSize = new SizeF();
            for (int i = 0; i < 7; i++)
            {
                crFont = new Font("arial", sizes[i],
                                             FontStyle.Bold);
                crSize = grPhoto.MeasureString(textoMarca,
                                                     crFont);

                if ((ushort)crSize.Width < (ushort)phWidth)
                    break;
            }

            // Posición abajo centrada
            int yPixlesFromBottom = (int)(phHeight * .05);
            float yPosFromBottom = ((phHeight -
                       yPixlesFromBottom) - (crSize.Height / 2));
            float xCenterOfImg = (phWidth / 2);


            // Pintamos dos veces con el graphics el texto en la imagen con dos brush diferentes
            // con esto conseguiremos el efecto de sombra.
            StringFormat StrFormat = new StringFormat();
            StrFormat.Alignment = StringAlignment.Center;

            SolidBrush semiTransBrush2 =
                 new SolidBrush(Color.FromArgb(153, 0, 0, 0));

            grPhoto.DrawString(textoMarca,
                crFont,
                semiTransBrush2,
                new PointF(xCenterOfImg + 1, yPosFromBottom + 1),
                StrFormat);

            SolidBrush semiTransBrush = new SolidBrush(
                         Color.FromArgb(153, 255, 255, 255));

            grPhoto.DrawString(textoMarca,
                crFont,
                semiTransBrush,
                new PointF(xCenterOfImg, yPosFromBottom),
                StrFormat);

            // Vamos a cambiar la imagen por lo que la sacamos de memoria antes
            imgPhoto.Dispose();
            // Pasamos el bitmap a un Image para aprovecharnos de sus propiedades
            imgPhoto = bmPhoto;
            // Descargamos de memoria el graphics
            grPhoto.Dispose();
            // Guardamos la imagen
            imgPhoto.Save(rutaImgDest,
                ImageFormat.Jpeg);

            imgPhoto.Dispose();

            return exito;
        }

No hay comentarios:

Publicar un comentario