Textos Universitarios / Serie Docencia ________________________________________________________________________ Capítulo 2 Su primera aplicación GDI+ para Web En el capítulo anterior revisamos el sistema de coordenadas de GDI+, las estructuras definidas en el espacio de nombres System.Drawing y lo que entendemos por superficies de dibujo. En este capítulo comenzaremos a integrar esos conceptos y otros que cubriremos aquí relacionados con la clase Image, finalizaremos el capítulo escribiendo código en formularios Web que utilizando GDI+ del Framework.NET puedan generar imágenes en línea. 2.1 Imágenes, mapas de bits y metarchivos La clase Image es una clase base abstracta que proporciona métodos para trabajar con imágenes de trama (mapas de bits) e imágenes vectoriales (metarchivos). Tanto la clase Bitmap como la clase Metafile se heredan de la clase Image. La clase Bitmap expande las capacidades de la clase Image ya que proporciona métodos adicionales para cargar, guardar y manipular imágenes de trama. La clase Metafile expande las capacidades de la clase Image ya que proporciona métodos adicionales para registrar y examinar imágenes vectoriales. Figura 2.1. Espacio de nombres System.Drawing.Image 2.1.1 Clase Image9 Requisitos Espacio de nombres: System.Drawing Como se acaba de mencionar ésta es una Clase base abstracta que proporciona funcionalidad para las clases descendientes Bitmap y Metafile. 2.1.1.1 Propiedades públicas Flags 9 Obtiene indicadores de atributo para este http://msdn2.microsoft.com/en-us/library/k7e7b2kd(d=ide).aspx junio 3 de 2006 47 Jenaro C. Paz ________________________________________________________________________ objeto Image. Obtiene una matriz de GUID que representa las dimensiones de los marcos de este objeto Image. Obtiene el alto de este objeto Image. Obtiene la resolución horizontal, en pixeles por pulgada, de este objeto Image. Obtiene o establece la paleta de colores de este objeto Image. Obtiene el ancho y el alto de esta imagen. Obtiene el formato de pixeles de este objeto Image. Obtiene los identificadores de los elementos de propiedad almacenados en este objeto Image. Obtiene todos los elementos de propiedad (fragmentos de metadatos) almacenados en este objeto Image. Obtiene el formato de este objeto Image. Obtiene el ancho y el alto de esta imagen, expresado en pixeles. Obtiene la resolución vertical, en pixeles por pulgada, de este objeto Image Obtiene el ancho de este objeto Image. FrameDimensionsList Height HorizontalResolution Palette PhysicalDimension PixelFormat PropertyIdList PropertyItems RawFormat Size VerticalResolution Width Tabla 2.1. Miembros de la clase Image 2.1.1.2 Métodos públicos Clone CreateObjRef (se hereda de MarshalByRefObject) Dispose Equals (se hereda de Object) FromFile FromHbitmap 48 Crea una copia exacta de este objeto Image. Crea un objeto que contiene toda la información relevante necesaria para generar un proxy utilizado para comunicarse con un objeto remoto. Sobrecargado. Sobrecargado. Determina si dos instancias de Object son iguales. Sobrecargado. Crea un objeto Image a partir del archivo especificado. Sobrecargado. Crea un objeto Bitmap a partir de un identificador de Windows. Textos Universitarios / Serie Docencia ________________________________________________________________________ FromStream GetBounds GetEncoderParameterList GetFrameCount GetHashCode (se hereda de Object) GetLifetimeService (se hereda de MarshalByRefObject) GetPixelFormatSize GetPropertyItem GetThumbnailImage GetType (se hereda de Object) InitializeLifetimeService (se hereda de MarshalByRefObject) IsAlphaPixelFormat IsCanonicalPixelFormat IsExtendedPixelFormat RemovePropertyItem RotateFlip Save Sobrecargado. Crea un objeto Image a partir de la secuencia de datos especificada. Obtiene un rectángulo delimitador para este objeto Image, en las unidades especificadas. Devuelve información sobre los parámetros que admite el codificador de imágenes especificado. Devuelve el número de marcos de la dimensión especificada. Sirve como función hash para un tipo concreto, apropiado para su utilización en algoritmos de hash y estructuras de datos como las tablas hash. Recupera el objeto de servicio de duración actual que controla la directiva de duración de esta instancia. Devuelve la profundidad de color (número de bits por pixel) del formato de pixel especificado. Obtiene el elemento de propiedad especificado de este objeto Image. Devuelve una vista en miniatura de este objeto Image. Obtiene el objeto Type de la instancia actual. Obtiene un objeto de servicio de duración para controlar la directiva de duración de esta instancia. Devuelve un valor que indica si el formato de pixel de este objeto Image contiene información alfa. Devuelve un valor que indica si el formato de pixel es canónico. Devuelve un valor que indica si el formato de pixel es extendido. Quita el elemento de propiedad especificado de este objeto Image. Este método gira, voltea o gira y voltea el objeto Image. Sobrecargado. Guarda esta imagen en la secuencia especificada con el formato especificado. 49 Jenaro C. Paz ________________________________________________________________________ SaveAdd SelectActiveFrame SetPropertyItem ToString (se hereda de Object) Sobrecargado. Agrega la información del objeto Image especificado a este objeto Image. El objeto EncoderParameters especificado determina cómo se incorpora la nueva información a la imagen existente. Selecciona el marco que especifican la dimensión y el índice. Almacena un elemento de propiedad (fragmento de metadatos) en este objeto Image. Devuelve un objeto String que representa al objeto Object actual. 2.1.1.3 Métodos protegidos Reemplazado. Vea Object.Finalize. Finalize En C# y C++, los finalizadores se expresan mediante la sintaxis del destructor. MemberwiseClone (se hereda de Object) Crea una copia superficial del objeto Object actual. 2.1.2 Imágenes de Trama (bitmaps) Encapsula un mapa de bits (imagen de trama) de GDI+, formado por los datos pixel de una imagen gráfica y sus atributos. Un objeto Bitmap es un objeto utilizado para trabajar con imágenes definidas por datos pixel. 2.1.2.1 Clase Bitmap10 Requisitos Espacio de nombres: System.Drawing 2.1.2.1.1 Constructores públicos Bitmap (Constructor) Sobrecargado. Inicializa una nueva instancia de la clase Bitmap. Tabla 2.2. Miembros de la clase Bitmap 10 http://msdn2.microsoft.com/en-us/library/system.drawing.bitmap(d=ide).aspx Junio 3 de 2006 50 Textos Universitarios / Serie Docencia ________________________________________________________________________ 2.1.2.1.2 Propiedades públicas Obtiene indicadores de atributo para este objeto Image. Obtiene una matriz de GUID que representa FrameDimensionsList (se hereda de las dimensiones de los marcos de este objeto Image) Image. Obtiene el alto de este objeto Image. Height (se hereda de Image) Obtiene la resolución horizontal, en pixeles HorizontalResolution (se hereda de por pulgada, de este objeto Image. Image) Obtiene o establece la paleta de colores de Palette (se hereda de Image) este objeto Image. PhysicalDimension (se hereda de Image) Obtiene el ancho y el alto de esta imagen. Obtiene el formato de pixeles de este objeto PixelFormat (se hereda de Image) Image. Obtiene los identificadores de los elementos PropertyIdList (se hereda de Image) de propiedad almacenados en este objeto Image. Obtiene todos los elementos de propiedad PropertyItems (se hereda de Image) (fragmentos de metadatos) almacenados en este objeto Image. Obtiene el formato de este objeto Image. RawFormat (se hereda de Image) Obtiene el ancho y el alto de esta imagen, Size (se hereda de Image) expresado en pixeles. VerticalResolution (se hereda de Image) Obtiene la resolución vertical, en pixeles por pulgada, de este objeto Image Obtiene el ancho de este objeto Image. Width (se hereda de Image) Flags (se hereda de Image) 2.1.2.1.3 Métodos públicos Clone CreateObjRef (se hereda de MarshalByRefObject) Dispose (se hereda de Image) Equals (se hereda de Object) FromHicon FromResource Sobrecargado. Crea una copia de la sección de este Bitmap definida con un PixelFormat especificado. Crea un objeto que contiene toda la información relevante necesaria para generar un proxy utilizado para comunicarse con un objeto remoto. Sobrecargado. Sobrecargado. Determina si dos instancias de Object son iguales. Crea un Bitmap a partir de un identificador de Windows de un icono. Crea un objeto Bitmap a partir del recurso de Windows especificado. 51 Jenaro C. Paz ________________________________________________________________________ GetBounds (se hereda de Image) GetEncoderParameterList (se hereda de Image) GetFrameCount (se hereda de Image) GetHashCode (se hereda de Object) GetHbitmap GetHicon GetLifetimeService (se hereda de MarshalByRefObject) GetPixel GetPropertyItem (se hereda de Image) GetThumbnailImage (se hereda de Image) GetType (se hereda de Object) InitializeLifetimeService (se hereda de MarshalByRefObject) LockBits MakeTransparent RemovePropertyItem (se hereda de Image) RotateFlip (se hereda de Image) Save (se hereda de Image) SaveAdd (se hereda de Image) 52 Obtiene un rectángulo delimitador para este objeto Image, en las unidades especificadas. Devuelve información sobre los parámetros que admite el codificador de imágenes especificado. Devuelve el número de marcos de la dimensión especificada. Sirve como función hash para un tipo concreto, apropiado para su utilización en algoritmos de hash y estructuras de datos como las tablas hash. Sobrecargado. Crea un objeto de mapa de bits de GDI a partir de un objeto Bitmap GDI+. Devuelve el identificador de un icono. Recupera el objeto de servicio de duración actual que controla la directiva de duración de esta instancia. Obtiene el color del pixel especificado de este Bitmap. Obtiene el elemento de propiedad especificado de este objeto Image. Devuelve una vista en miniatura de este objeto Image. Obtiene el objeto Type de la instancia actual. Obtiene un objeto de servicio de duración para controlar la directiva de duración de esta instancia. Bloquea un objeto Bitmap en la memoria del sistema. Sobrecargado. Hace el color transparente predeterminado transparente para este Bitmap. Quita el elemento de propiedad especificado de este objeto Image. Este método gira, voltea o gira y voltea el objeto Image. Sobrecargado. Guarda esta imagen en la secuencia especificada con el formato especificado. Sobrecargado. Agrega la información del objeto Image especificado a este objeto Textos Universitarios / Serie Docencia ________________________________________________________________________ Image. El objeto EncoderParameters especificado determina cómo se incorpora la nueva información a la imagen existente. SelectActiveFrame (se hereda de Image) Selecciona el marco que especifican la dimensión y el índice. Establece el color del pixel especificado de SetPixel este Bitmap. Almacena un elemento de propiedad SetPropertyItem (se hereda de Image) (fragmento de metadatos) en este objeto Image. Establece la resolución de este objeto SetResolution Bitmap. Devuelve un objeto String que representa al ToString (se hereda de Object) objeto Object actual. Desbloquea este Bitmap de la memoria del UnlockBits sistema. 2.1.2.1.4 Métodos protegidos Reemplazado. Permite que un objeto Object intente liberar recursos y realizar otras operaciones de limpieza antes de que el objeto Object sea reclamado por el recolector de elementos no utilizados. En C# y C++, los finalizadores se expresan mediante la sintaxis del destructor. MemberwiseClone (se hereda de Object) Crea una copia superficial del objeto Object actual. Finalize (se hereda de Object) 2.1.2.2 Tipos de mapas de bits Un mapa de bits es una matriz de bits que especifica el color de cada pixel de una matriz rectangular de pixeles. El número de bits asignado a un pixel individual determina el número de colores que se pueden asignar a dicho pixel. Por ejemplo, si cada pixel se representa con 4 bits, a un pixel determinado se le podrá asignar uno entre los 16 colores distintos (2^4 = 16). En la siguiente tabla se muestran unos cuantos ejemplos del número de colores que se le pueden asignar a un pixel que se representa con un número de bits determinado. Bits por pixel 1 2 4 Número de colores que se le pueden asignar a un pixel 2^1 = 2 2^2 = 4 2^4 = 16 53 Jenaro C. Paz ________________________________________________________________________ 8 16 24 32 2^8 = 256 2^16 = 65536 2^24 = 16, 777, 216 2^32 = 4,294,967,296 Tabla 2.3. Calidad de Color Los archivos de disco que almacenan mapas de bits contienen, por lo general, uno o varios bloques de información que almacenan datos como, por ejemplo, el número de bits por pixel, número de pixeles de cada fila y número de filas de la matriz. Un archivo de este tipo podría contener también una tabla de colores (a veces se denomina paleta de colores). Una tabla de colores asigna números a colores específicos en el mapa de bits. En la siguiente ilustración se muestra una imagen ampliada junto con el mapa de bits y la tabla de colores correspondientes. Cada pixel se representa con un número de 4 bits y, por lo tanto, hay 2^4 = 16 colores en la tabla de colores. Cada color de la tabla se representa con un número de 24 bits: 8 bits para el rojo, 8 bits para el verde y 8 bits para el azul. Los números se muestran en formato hexadecimal (base 16): A = 10, B = 11, C = 12, D = 13, E = 14, F = 15. Figura 2.2. Mapa de bits y tabla de colores correspondiente Observe el pixel de la fila 3, columna 5 de la imagen. El número que le corresponde en el mapa de bits es el 1. La tabla de colores indica que el 1 representa el color rojo y, por ello, el pixel es rojo. Todas las entradas de la fila inferior del mapa de bits son el número 2. La tabla de colores indica que el 2 representa el verde, así que todos los pixeles de la fila inferior de la imagen son verdes. Nota.- Algunos mapas de bits se almacenan en formato ascendente; los números de la primera fila del mapa de bits corresponden a los pixeles de la fila inferior de la imagen. Un mapa de bits que almacena índices en una tabla de colores se denomina mapa de bits de paleta indexada. Algunos mapas de bits no necesitan una tabla de colores. Por 54 Textos Universitarios / Serie Docencia ________________________________________________________________________ ejemplo, si un mapa de bits utiliza 24 bits por pixel, el propio mapa de bits puede almacenar los colores en lugar de los índices de una tabla de colores. En la siguiente ilustración se muestra un mapa de bits que almacena colores directamente (24 bits por pixel) en lugar de utilizar una tabla de colores. En la ilustración se muestra también una vista amplificada de la imagen correspondiente. En el mapa de bits, FFFFFF representa el blanco, FF0000 representa el rojo, 00FF00 representa el verde y 0000FF representa el azul. Figura 2.3. Mapa de bits que almacena colores directamente 2.1.2.3 Formatos de archivos de gráficos Existen muchos formatos estándar para guardar mapas de bits en archivos de disco. GDI+ es compatible con los formatos de archivos de gráficos que se describen a continuación. 2.1.2.3.1 BMP (Bit MaP, mapa de bits) BMP es un formato estándar que Windows utiliza para almacenar imágenes independientes del dispositivo e independientes de la aplicación. El número de bits por pixel (1, 4, 8, 15, 24, 32 o 64) de un archivo BMP determinado se especifica en un encabezado de archivo. Los archivos BMP con 24 bits por pixel son muy comunes. Los archivos BMP no suelen comprimirse y, por lo tanto, no son muy apropiados para que se transfieran a través de Internet. 2.1.2.3.2 GIF (Graphics Interchange Format, formato de intercambio de gráficos) GIF es un formato común de las imágenes que aparecen en páginas Web. Los archivos GIF funcionan bien para dibujar líneas, imágenes con bloques de color sólido e imágenes con límites definidos entre colores. Los archivos GIF se comprimen, sin que se pierda información durante el proceso de compresión; una imagen descomprimida es exactamente igual que la imagen original. En un archivo GIF se puede especificar un color como transparente, de forma que la imagen tenga el color de fondo de cualquier página Web en la que se muestre. Una secuencia de imágenes GIF puede almacenarse en un único archivo para formar un GIF animado. Los archivos GIF almacenan como máximo 8 bits por pixel, por lo que se limitan a 256 colores. 55 Jenaro C. Paz ________________________________________________________________________ 2.1.2.3.3 JPEG (Joint Photographic Experts Group, grupo conjunto de expertos en fotografía) JPEG es un esquema de compresión que funciona muy bien para escenas naturales como fotografías escaneadas. Durante el proceso de compresión se pierde algo de información, pero la pérdida suele ser imperceptible para el ojo humano. Los archivos JPEG almacenan 24 bits por pixel, por lo que son capaces de mostrar más de 16 millones de colores. Los archivos JPEG no admiten transparencia ni animación. El nivel de compresión de las imágenes JPEG puede configurarse, pero cuanto mayor sea el nivel de compresión (archivos más pequeños), mayor será la pérdida de información. Una razón de compresión de 20:1 suele generar una imagen que el ojo humano apenas distingue de la imagen original. En la siguiente ilustración se muestra una imagen BMP y dos imágenes JPEG que se han comprimido a partir de dicha imagen BMP. La primera imagen JPEG tiene una razón de compresión de 4:1 y la segunda imagen JPEG tiene una razón de compresión en torno a 8:1. Figura 2.4. Comparación de BMP y JPG con diferente compresión La compresión de archivos JPEG no es apropiada para el dibujo de líneas, bloques de color sólido o límites definidos. En la siguiente ilustración se muestra un archivo BMP junto con dos archivos JPEG y un archivo GIF. Los archivos JPEG y el archivo GIF se han comprimido a partir del archivo BMP. La razón de compresión es de 4:1 para el archivo GIF, de 4:1 para el archivo JPEG más pequeño y de 8:3 para el archivo JPEG más grande. Tenga en cuenta que el archivo GIF mantiene los límites de las líneas nítidos, mientras que los archivos JPEG tienden a difuminar los límites. Figura 2.5. Comparación de BMP y JPG con diferente compresión 56 Textos Universitarios / Serie Docencia ________________________________________________________________________ JPEG es un esquema de compresión, no un formato de archivo. El formato de intercambio de archivos JPEG (JFIF) es un formato de archivos comúnmente utilizado para almacenar y transferir imágenes que se han comprimido conforme al esquema JPEG. Los archivos JFIF que muestran los exploradores Web utilizan la extensión .jpg. 2.1.2.3.4 EXIF (Exchangeable Image File, archivo de imagen intercambiable) EXIF es un formato de archivo utilizado para las fotografías que se capturan con cámaras digitales. Un archivo EXIF contiene una imagen comprimida conforme a la especificación JPEG. Un archivo EXIF contiene también información acerca de la fotografía (fecha de toma, velocidad de obturación, tiempo de exposición, etcétera) e información acerca de la cámara (fabricante, modelo, etcétera). 2.1.2.3.5 PNG (Portable Network Graphics, gráficos de red portátiles) El formato PNG conserva muchas de las ventajas del formato GIF pero también aporta más funciones que las del formato GIF. Al igual que los archivos GIF, los archivos PNG se comprimen sin que se pierda información. Los archivos PNG pueden almacenar colores con 8, 24 o 48 bits por pixel y escalas de grises con 1, 2, 4, 8 o 16 bits por pixel, mientras que los archivos GIF sólo pueden utilizar 1, 2, 4 u 8 bits por pixel. Un archivo PNG puede almacenar también un valor alfa para cada pixel, que especifica el grado de mezcla de ese pixel con el color de fondo. El formato PNG supone una mejora con respecto al formato GIF por su capacidad para mostrar una imagen progresivamente; es decir, para mostrar aproximaciones cada vez mejores de la imagen a medida que ésta llega a través de una conexión de red. Los archivos PNG pueden contener información sobre la corrección de gamma y la corrección de color para que las imágenes puedan mostrarse con precisión en varios dispositivos de presentación. 2.1.2.3.6 TIFF (Tag Image File Format, formato de archivo de imágenes con etiquetas) TIFF es un formato flexible y extensible, compatible con una amplia variedad de plataformas y aplicaciones de procesamiento de imágenes. Los archivos TIFF pueden almacenar imágenes con un número arbitrario de bits por pixel y pueden emplear varios algoritmos de compresión. Se pueden almacenar diversas imágenes en un único archivo TIFF de varias páginas. La información relacionada con la imagen (marca del escáner, equipo host, tipo de compresión, orientación, muestras por pixel, etcétera) puede almacenarse en el archivo y organizarse mediante el uso de etiquetas. El formato TIFF puede extenderse cuando se precise con la aprobación y adición de nuevas etiquetas. 57 Jenaro C. Paz ________________________________________________________________________ 2.1.3 Clase Metafile11 Requisitos Espacio de nombres: System.Drawing.Imaging Define un metarchivo gráfico. Un metarchivo contiene registros que describen una secuencia de gráficos que pueden grabarse (construirse) y reproducirse (mostrarse). No puede heredarse. 2.1.3.1 Constructores públicos Sobrecargado. Inicializa una nueva instancia de la clase Metafile. Metafile (Constructor) Tabla 2.4. Miembros de la clase Metafile 2.1.3.2 Propiedades públicas Obtiene indicadores de atributo para este objeto Image. Obtiene una matriz de GUID que representa FrameDimensionsList (se hereda de las dimensiones de los marcos de este objeto Image) Image. Obtiene el alto de este objeto Image. Height (se hereda de Image) Obtiene la resolución horizontal, en pixeles HorizontalResolution (se hereda de por pulgada, de este objeto Image. Image) Obtiene o establece la paleta de colores de Palette (se hereda de Image) este objeto Image. PhysicalDimension (se hereda de Image) Obtiene el ancho y el alto de esta imagen. Obtiene el formato de pixeles de este objeto PixelFormat (se hereda de Image) Image. Obtiene los identificadores de los elementos PropertyIdList (se hereda de Image) de propiedad almacenados en este objeto Image. Obtiene todos los elementos de propiedad PropertyItems (se hereda de Image) (fragmentos de metadatos) almacenados en este objeto Image. Obtiene el formato de este objeto Image. RawFormat (se hereda de Image) Obtiene el ancho y el alto de esta imagen, Size (se hereda de Image) expresado en pixeles. VerticalResolution (se hereda de Image) Obtiene la resolución vertical, en pixeles por pulgada, de este objeto Image Flags (se hereda de Image) 11 http://msdn2.microsoft.com/en-us/library/system.drawing.imaging.metafile(d=ide).aspx Junio 3 de 2006 58 Textos Universitarios / Serie Docencia ________________________________________________________________________ Width (se hereda de Image) Obtiene el ancho de este objeto Image. 2.1.3.3 Métodos públicos Clone (se hereda de Image) CreateObjRef (se hereda de MarshalByRefObject) Dispose (se hereda de Image) Equals (se hereda de Object) GetBounds (se hereda de Image) GetEncoderParameterList (se hereda de Image) GetFrameCount (se hereda de Image) GetHashCode (se hereda de Object) GetHenhmetafile GetLifetimeService (se hereda de MarshalByRefObject) GetMetafileHeader GetPropertyItem (se hereda de Image) GetThumbnailImage (se hereda de Image) GetType (se hereda de Object) InitializeLifetimeService (se hereda de MarshalByRefObject) PlayRecord RemovePropertyItem (se hereda de Image) Crea una copia exacta de este objeto Image. Crea un objeto que contiene toda la información relevante necesaria para generar un proxy utilizado para comunicarse con un objeto remoto. Sobrecargado. Sobrecargado. Determina si dos instancias de Object son iguales. Obtiene un rectángulo delimitador para este objeto Image, en las unidades especificadas. Devuelve información sobre los parámetros que admite el codificador de imágenes especificado. Devuelve el número de marcos de la dimensión especificada. Sirve como función hash para un tipo concreto, apropiado para su utilización en algoritmos de hash y estructuras de datos como las tablas hash. Devuelve un identificador de Windows de un objeto Metafile mejorado. Recupera el objeto de servicio de duración actual que controla la directiva de duración de esta instancia. Sobrecargado. Devuelve el objeto MetafileHeader asociado a este objeto Metafile. Obtiene el elemento de propiedad especificado de este objeto Image. Devuelve una vista en miniatura de este objeto Image. Obtiene el objeto Type de la instancia actual. Obtiene un objeto de servicio de duración para controlar la directiva de duración de esta instancia. Reproduce un registro de metarchivo individual. Quita el elemento de propiedad especificado de este objeto Image. 59 Jenaro C. Paz ________________________________________________________________________ Este método gira, voltea o gira y voltea el objeto Image. Sobrecargado. Guarda esta imagen en la Save (se hereda de Image) secuencia especificada con el formato especificado. Sobrecargado. Agrega la información del SaveAdd (se hereda de Image) objeto Image especificado a este objeto Image. El objeto EncoderParameters especificado determina cómo se incorpora la nueva información a la imagen existente. SelectActiveFrame (se hereda de Image) Selecciona el marco que especifican la dimensión y el índice. Almacena un elemento de propiedad SetPropertyItem (se hereda de Image) (fragmento de metadatos) en este objeto Image. Devuelve un objeto String que representa al ToString (se hereda de Object) objeto Object actual. RotateFlip (se hereda de Image) 2.1.3.4 Métodos protegidos Finalize (se hereda de Object) Reemplazado. Permite que un objeto Object intente liberar recursos y realizar otras operaciones de limpieza antes de que el objeto Object sea reclamado por el recolector de elementos no utilizados. En C# y C++, los finalizadores se expresan mediante la sintaxis del destructor. MemberwiseClone (se hereda de Object) Crea una copia superficial del objeto Object actual. 2.1.3.5 Información general acerca de gráficos vectoriales GDI+ proporciona la clase Metafile para que puedan registrarse y mostrarse metarchivos. Un metarchivo, también denominado imagen vectorial, es una imagen que se almacena como una secuencia de comandos y valores de dibujo. Los comandos y valores registrados en un objeto Metafile pueden almacenarse en memoria o pueden guardarse en un archivo o secuencia. GDI+ puede mostrar metarchivos que se hayan almacenado en los siguientes formatos: • • • 60 WMF (Metarchivo de Windows) EMF (Metarchivo mejorado) EMF+ Textos Universitarios / Serie Docencia ________________________________________________________________________ GDI+ puede registrar metarchivos en formato EMF y EMF+, pero no en formato WMF. EMF+ es una extensión de EMF que permite que los registros de GDI+ se almacenen. Hay dos variaciones del formato EMF+: EMF+ Only y EMF+ Dual. Los metarchivos EMF+ Only sólo contienen registros GDI+. GDI+ puede mostrar los metarchivos de este tipo, pero GDI no puede hacerlo. Los metarchivos EMF+ Dual contienen registros GDI+ y GDI. Cada registro GDI+ de un metarchivo EMF+ Dual está emparejado con un registro GDI alternativo. GDI+ o GDI pueden mostrar este tipo de metarchivos. En el siguiente ejemplo se muestra un metarchivo que se guardó previamente como un archivo. El metarchivo se muestra con la esquina superior izquierda en (100, 100). [C#] public void Example_DisplayMetafile(PaintEventArgs e) { Graphics myGraphics = e.Graphics; Metafile myMetafile = new Metafile("SampleMetafile.emf"); myGraphics.DrawImage(myMetafile, 100, 100); } 2.2 Técnica para la generación de gráficos en línea en aplicaciones Web Como se mencionó en la sección 1.1.2 (Sistema de Coordenadas), GDI+ dibuja líneas, rectángulos y otras formas en un sistema de coordenadas. Se puede elegir entre varios sistemas de coordenadas, pero el sistema de coordenadas predeterminado tiene el origen en la esquina superior izquierda, con el eje x apuntando hacia la derecha y el eje y apuntando hacia abajo. La unidad de medida del sistema de coordenadas predeterminado es el pixel. Figura 2.6. Sistema de Coordenadas predeterminado Un monitor del sistema crea su pantalla en una matriz rectangular de puntos a los que se denomina elementos de imagen o pixeles. El número de pixeles que aparece en la pantalla varía de un monitor a otro, y el número de pixeles que aparece en un monitor individual suele poder configurarlo, hasta cierto punto, el usuario. 61 Jenaro C. Paz ________________________________________________________________________ Figura 2.7. Matriz de pixeles en un monitor Cuando se utiliza GDI+ para dibujar una línea, un rectángulo o una curva, se proporciona cierta información clave sobre el elemento que se va a dibujar. Por ejemplo, se puede especificar una línea proporcionando dos puntos, y se puede especificar un rectángulo proporcionando un punto, un alto y un ancho. GDI+ trabaja en combinación con el software del controlador de pantalla para determinar los pixeles que deben activarse para mostrar la línea, el rectángulo o la curva. En la siguiente ilustración se muestra la forma en que se activan los pixeles para mostrar una línea del punto (4, 2) al punto (12, 8). Figura 2.8. Activación de pixeles para generar una línea Con el tiempo, determinadas unidades de creación han resultado ser las más útiles para crear imágenes bidimensionales. Estas unidades de creación, todas ellas compatibles con GDI+, se indican en la lista siguiente: • • • • • • • Líneas Rectángulos Elipses Arcos Polígonos Curvas spline cardinales Curvas spline de Bézier En GDI+, la clase Graphics, proporciona los siguientes métodos para dibujar los elementos de la lista anterior: DrawLine, DrawRectangle, DrawEllipse, DrawPolygon, DrawArc, DrawCurve (para curvas spline cardinales) y DrawBezier. Cada uno de estos métodos está sobrecargado, es decir, cada método admite varias listas distintas de parámetros. Por ejemplo, una variación del método DrawLine recibe un objeto Pen y 62 Textos Universitarios / Serie Docencia ________________________________________________________________________ cuatro enteros, mientras que otra variación del método DrawLine recibe un objeto Pen y dos objetos Point. Los métodos que existen para dibujar líneas, rectángulos y curvas spline de Bézier tienen varios métodos asociados que dibujan varios elementos en una única llamada: DrawLines, DrawRectangles y DrawBeziers. Además, el método DrawCurve tiene un método asociado, DrawClosedCurve, que cierra una curva conectando el punto final con el punto inicial de la curva. Todos los métodos de dibujo de la clase Graphics funcionan junto con un objeto Pen. Para dibujar cualquier cosa, deben crearse como mínimo dos objetos: un objeto Graphics y un objeto Pen. El objeto Pen almacena atributos, como el color y el ancho de línea, del elemento que se va a dibujar. El objeto Pen se pasa como uno de los argumentos del método de dibujo. Por ejemplo, una variación del método DrawRectangle recibe un objeto Pen y cuatro enteros, tal y como se muestra en el siguiente ejemplo, en el que se dibuja un rectángulo con un ancho de 100, una altura de 50 y la esquina superior izquierda en (20, 10): [C#] myGraphics.DrawRectangle(myPen, 20, 10, 100, 50); Se puede utilizar GDI+ con formularios de Windows y con formularios Web12. Por ejemplo, un formulario Web puede generar un archivo .png de forma dinámica, utilizando ciertos datos introducidos por el usuario en él y luego hacer referencia a esta imagen desde este mismo formulario para desplegarla. A continuación se detalla esta tecnología no ampliamente documentada y utilizada por algunas compañías de software que se dedican a la comercialización de herramientas de desarrollo para programadores de aplicaciones Web. En la figura 2.9, se muestra un formulario Web con codificación en lenguaje C# que haciendo uso de algunas bibliotecas de GDI+, lleva a cabo lo siguiente cuando la página se carga en la memoria del servidor IIS, para ser enviada al navegador: • • • • • • • • Define un rectángulo de 200 X 160 pixeles Crea un bitmap para trabajar con imágenes definidas por pixeles Crea un objeto (superficie gráfica) g para dibujar a partir del bitmap anterior Crea una pluma de 2 pixeles para dibujar líneas y curvas de color azul violeta Limpia la superficie gráfica usando el color naranja Dibuja una elipse con la pluma definida Se le indica al IIS que el contenido de la respuesta al navegador es “image/gif” Se envía la imagen en forma binaria al navegador 12 Simple GDI+ Graphics, Philip Quinn http://authors.aspalliance.com/wisemonk/view.aspx?id=AG041602 Junio3 de 2006 63 Jenaro C. Paz ________________________________________________________________________ Figura 2.9. Forma Web básica que mediante un Script genera gráficas e línea La información que llega al navegador de Internet se muestra en la Figura 2.10. Figura 2.10. Imagen generada en línea. La interacción entre el cliente y el servidor se esquematiza a continuación. 64 Textos Universitarios / Serie Docencia ________________________________________________________________________ Figura 2.11. Mecanismo de generación de gráficos GDI+ en línea La imagen que se desea generar, en la mayoría de las aplicaciones Web, es con la información de una base de datos o con aquella enviada por un formulario, ejemplificaremos este segundo caso. La técnica consiste en pasar, mediante el QueryString del método Post de un formulario Web, la información relevante para que otro formulario de la aplicación Web la procese generando la imagen que posteriormente se le devuelve al primer formulario quien a continuación la despliega. Figura 2.11. Figura 2.12. Paso de parámetros para la generación de gráficos GDI+ en línea El formulario Web puede ser tan sencillo como el que se muestra en la Figura 2.13. 65 Jenaro C. Paz ________________________________________________________________________ Figura 2.13. Formulario para la alimentación de parámetros En donde el botón está programado con el código siguiente: Response.Write("<img border='0' src='GDI_Server.aspx?valueH=" + recHeight + "&valueW=" + recWidth + "&valueC=" + theColor + "'>"); Listado 2.1. Código asociado con el botón para generar la imagen Donde valueH , valueW y valueC son las cadenas de caracteres almacenadas en las cajas de texto (TextBox) y en la lista desplegable (DropDownList). La página GDI_Server.aspx al ser solicitada debe leer los parámetros del QueryString que el método Post de la forma le manda y utilizarlos para generar la imagen haciendo uso del siguiente código: private void Page_Load(object sender, System.EventArgs e) { // Define a Rectangle to be the BG rectangle int w1,h1; Color myColor; w1 = UInt16.Parse(Request.QueryString["valueW"]); h1 = UInt16.Parse(Request.QueryString["valueH"]); myColor=Color.FromName(Request.QueryString["valueC"]); Rectangle bgRect = new Rectangle(0,0,w1,h1); // The bitmap Object used to work with images defined by // pixel data Bitmap pixelImage = new Bitmap(w1,h1); // 1) Will be used to build the new Graphics object // 2) Whatever you do with the Graphics object you affect // the image object! Graphics g = Graphics.FromImage(pixelImage); // Fill the interior of the bg rectangle g.FillRectangle(myColor), bgRect); 66 Textos Universitarios / Serie Docencia ________________________________________________________________________ // Create a Stream in memory to save the image MemoryStream memStream = new MemoryStream(); pixelImage.Save(memStream, ImageFormat.Png); // Bmp, Jpeg, Png, Gif Response.Clear(); //Clear the buffer // Send the memory image to Browser in binary mode memStream.WriteTo(Response.OutputStream); } Listado 2.2. Código en el servidor GDI_Server.aspx para generar la imagen En resultado en este mismo formulario se muestra en la Figura 2.14 Figura 2.14. Imagen png generada mediante GDI+ En el Listado 2.2, la clase Graphics representa una superficie de dibujo de GDI+. Para utilizar GDI+, primero es necesaria una referencia a un objeto Graphics, que en nuestro caso es g y que debe crearse de cualquier clase derivada de la clase Image. Bitmap pixelImage = new Bitmap(w1,h1); Graphics g = Graphics.FromImage(pixelImage); Listado 2.3. Referencia a un objeto Graphics Tras crear el objeto g, se puede utilizar entre otras cosas, para dibujar líneas, rellenar formas y dibujar texto. Los objetos que suelen usarse junto con el objeto Graphics son los siguientes: • • Color Se utiliza con el fin de describir el color que se usa para procesar un objeto determinado. En GDI+, el color puede tener una mezcla alfa. (véase sección 1.2.4) Brush. Se utiliza para rellenar superficies delimitadas con esquemas, colores o mapas de bits. 67 Jenaro C. Paz ________________________________________________________________________ • • Pen Se utiliza para dibujar líneas y polígonos, junto con rectángulos, arcos y gráficos. Font Se utiliza para describir la fuente que se usa para procesar textos. En los siguientes Capítulos abordaremos en detalle cada una de las Clases que constituyen GDI+ y veremos las diferentes técnicas que se utilizan para generar diferentes tipos de graficas en línea. 68