Nivel avanzado

Redimensión dinámica de imágenes


Siguiendo con la manipulación de imágenes en .NET, imaginemos que disponemos de una imagen de un tamaño considerable, bien en disco, bien en base de datos, y queremos enviarle al usuario un thumbnail de dicha imagen. ¡Ojo! No queremos mostrar la imagen completa con un estilo que modifique su alto y ancho, ya que con esto estaríamos enviando la imagen completa y luego modificaríamos su visualización en cliente, perdiendo el correspondiente (y valioso) ancho de banda.

En lugar de esto, sacrificaremos unos cuantos ciclos de CPU en pos de limitar el tráfico y realizaremos la operación de redimensionar la imagen en servidor para posteriormente enviarsela (más pequeñita o más grande) al cliente.
Para ello, nos crearemos una función llamada RedimensionarImagen que reciba tres parámetros: la imagen que queremos redimensionar, la nueva altura y la nueva anchura:


private System.Drawing.Bitmap RedimensionarImagen(System.Drawing.Image imagenOriginal, int alto, int ancho)
{

Lo primero que haremos será guardar el alto y el ancho de la imagen original.


int anchoOriginal = imagenOriginal.Width;
int altoOriginal = imagenOriginal.Height;

A continuación declaramos dos variables de tipo float que almacenaran el porcentaje de escalado al que se va a ver sometida la imagen.


float porcentajeEscaladoX = (float)ancho / (float)anchoOriginal;
float porcentajeEscaladoY = (float)alto / (float)altoOriginal;

El siguiente paso será definir una nueva altura para la imagen, multiplicando los valores originales por los factores que hemos obtenido en el paso anterior.


int nuevoAncho = (int)(anchoOriginal * porcentajeEscaladoX);
int nuevoAlto = (int)(altoOriginal * porcentajeEscaladoY);

Ya tenemos las dimensiones de nuestra nueva imagen, ahora necesitaremos crear una instancia.


System.Drawing.Bitmap nuevaImagen = new System.Drawing.Bitmap(nuevoAncho, nuevoAlto);

Ahora instanciamos una superficie de dibujo de GDI+ a partir de la imagen para tratar el tamaño.


System.Drawing.Graphics superficieGDI = System.Drawing.Graphics.FromImage((System.Drawing.Image)nuevaImagen);

Indicamos el modo de interpolación (en nuestro caso, Bicúbico Alta Calidad) y dibujamos la imagen con los nuevos valores de ancho y alto.


superficieGDI.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
superficieGDI.DrawImage(imagenOriginal, 0, 0, nuevoAncho, nuevoAlto);

Finalmente, liberamos el objeto GDI+ y devolvemos la imagen.


superficieGDI.Dispose();

return nuevaImagen;
}

Et voilà!, hecho esto, obtendremos una imagen con el alto y ancho deseados.

Transacciones en ADO.NET (II): Activando las Transacciones Distribuidas mediante MSDTC


Anteriormente hemos aprendido a utilizar entornos transaccionales o Transaction Scopes. El ejemplo anterior mostraba lo que se conoce como una ‘transacción ligera’ que afecta a varias tablas de una misma fuente de datos. Sin embargo, en numerosas ocasiones se nos presentará la dificultad añadida de trabajar con múltiples fuentes de datos localizadas incluso en puntos geográficos diversos.

Para solventar esta dificultad, el propio Windows nos ofrece la posibilidad de utilizar las llamadas Transacciones distribuidas. Por defecto aparecen deshabilitadas, por lo que a continuación, mostraremos cómo activarlas. Una vez activadas, utilizaremos la clase TransactionScope como si se tratara de una transacción ligera, dejando en manos del sistema operativoel control de la propia transacción.

(más…)

Introducción a Reflection (III): Ejecutando métodos de un objeto a partir de su tipo


Ayer veíamos cómo obtener información de un objeto mediante el espacio de nombres Reflection. Ahora veremos que no solo es posible obtener información de los metadatos, sino que también es posible acceder a sus miembros.

Vimos previamente que nuestra clase  ClasePrueba tenía una función llamada sumarUno(). Vamos a intentar, mediante Reflection, invocar a la función sin necesidad de “conocer” el objeto. En realidad, y para simplificar el ejemplo, utilizaremos el nombre del método directamente, pero sería posible, a partir de una estructura MethodInfo, obtener nombre y parámetros de cada uno de los métodos y ejecutarlos de forma dinámica.

Partiendo del código del artículo anterior, añadiríamos lo siguiente para invocar el método:

 // Ejecutamos un método mediante Reflection. En primer lugar obtenemos una referencia al método
 MethodInfo Metodo = tipoObjeto.GetMethod("sumarUno");

 // A continuación, llamamos al método Invoke del tipo, pasándole como primer parámetro
 //el objeto cuyo método queremos ejecutar, y como segundo parámetro, un array de objetos con
 //los parámetros que espera el método o función.
 int dato;
 object[] parametros = new object[1] { 2 };
 dato = (int)Metodo.Invoke(objeto, parametros);

 Console.WriteLine("El resultado de la invocación ha sido: " + dato.ToString());

Recordemos que el objeto ‘objeto‘ era una instancia de ClasePrueba.

Como puntilla mostraremos otra forma de invocar un método mediante Reflection: utilizando Activator para obtener una instancia de la clase ClasePrueba y ejecutando el método Type.InvokeMember().


 // Utilizamos la clase Activator para ejecutar el método de otro objeto
 object objeto2 = Activator.CreateInstance(tipoObjeto);
 dato = (int)tipoObjeto.InvokeMember("sumarUno", BindingFlags.InvokeMethod, null, objeto2, parametros);

 Console.WriteLine("El resultado de la invocación (mediante Activator) ha sido: " + dato.ToString());

El resultado sería el siguiente:

090502Resul

Introducción a Reflection (II): Obteniendo metadatos de una clase


En artículos anteriores hemos visto la potencia de las clases contenidas en el espacio de nombres Reflection. Hoy vamos a intentar profundizar un poco más en la potencia que podemos obtener utilizando estos recursos.
Como hemos visto, Reflection proporciona clases que permiten leer los metadatos de una clase. Bien… habrá quien se pregunte… ¿qué es un metadato? Un metadato no es más que un dato que describe a otro dato. Por ejemplo, en el ámbito que vamos a ver a continuación, el nombre de la clase es en sí un metadato. De hecho, la propia clase en sí es un metadato, ya que describe un “patrón” o estructura de los objetos que derivan de ella.
Reflection nos proporciona una serie de clases que se encargan de encapsular ensamblados, módulos y tipos. Esto nos permite realizar acciones como conocer el nombre de una clase o invocar un método de un objeto -a priori- desconocido en tiempo real.

(más…)