none
Loading Big Images

    Question

  • Hi all. I have a problem loading a collection of images on an WPF Image tag, the problem is related with the performance of the rendering of a single image (about 40MB) using a BitmapImage.

    The question is: Is there a way of loading the image on an Image tag, without reducing its original size (DecodePixelWidth, DecodePixelHeight) on a fast way?, for example reducing it's quality.

    Please, put some sample code.

    Thanks.
    Tuesday, November 18, 2008 8:32 AM

Answers

  • Hi Jim.

    It's true that your code solves the problem when loading thumbnails (I'm doing the same for the thumbnail load in a ListView).

    But the current problem is to speed up the performance of showing a big image, with it's original size. Finally, I've solved the problem using a region concept and the CroppedImage object. The idea is to show only a region of the image by user demand, in this case I've divided the image in four regions (TopLeft, TopRight, BottomLeft, BottomRight).

    In this case the load performance increases 4 times, without loosing quality.

    That's the object I use. I hope this post would be useful to others.

       
    /// <summary> 
        /// Objeto para la optimización y filtrado de imágenes 
        /// </summary> 
        public class ImageProcessor 
        { 
            /// <summary> 
            /// Representa las distintas regiones visualizables de la imágen 
            /// </summary> 
            public enum ImageRegion { TopLeft, TopRight, BottomLeft, BottomRight, All }; 
            #region Propiedades 
     
            /// <summary> 
            /// Multiplicador para cálculo del ancho de recorte 
            /// </summary> 
            private float cropWidth = 0.5F; 
            /// <summary> 
            /// Multiplicador para cálculo del alto de recorte 
            /// </summary> 
            private float cropHeight = 0.5F; 
            /// <summary> 
            /// Región de la imágen a mostrar 
            /// </summary> 
            private ImageRegion region = ImageRegion.All; 
            /// <summary> 
            /// Ángulo de rotación 
            /// </summary> 
            private double rotationAngle = 0.0; 
            /// <summary> 
            /// Grado en % para el escalado en el Eje X 
            /// </summary> 
            private double scaleX = 1.0; 
            /// <summary> 
            /// Grado en % para el escalado en el Eje Y 
            /// </summary> 
            private double scaleY = 1.0; 
            /// <summary> 
            /// Ruta de la imagen a procesar 
            /// </summary> 
            private string ruta = ""
            /// <summary> 
            /// Ruta de la imagen a procesar 
            /// </summary> 
            private Uri url = null
            /// <summary> 
            /// Imagen original a procesar 
            /// </summary> 
            private BitmapSource source = null
            #endregion 
            #region Atributos 
     
            /// <summary> 
            /// Multiplicador para cálculo del ancho de recorte 
            /// </summary> 
            public float CropWidth 
            { 
                get { return cropWidth; } 
                set  
                { 
                    if (value >= 0) 
                        cropWidth = value; 
                    else 
                        throw new Exception("El ancho de recorte debe ser >= 0."); 
                } 
            } 
     
            /// <summary> 
            /// Multiplicador para cálculo del alto de recorte 
            /// </summary> 
            public float CropHeight 
            { 
                get { return cropHeight; } 
                set 
                { 
                    if (value >= 0) 
                        cropHeight = value; 
                    else 
                        throw new Exception("El alto de recorte debe ser >= 0."); 
                } 
            } 
     
            /// <summary> 
            /// Región de la imágen a mostrar en recortes 
            /// </summary> 
            public ImageRegion Region 
            { 
                get { return region; } 
                set { region = value; } 
            } 
     
            /// <summary> 
            /// Ángulo de rotación 
            /// </summary> 
            public double RotationAngle 
            { 
                get { return rotationAngle; } 
                set { rotationAngle = value; } 
            } 
     
            /// <summary> 
            /// Grado en % para el escalado en el Eje X 
            /// </summary> 
            public double ScaleX 
            { 
                get { return scaleX; } 
                set  
                { 
                    if (value >= 0.0) 
                        scaleX = value; 
                    else 
                        throw new Exception("El grado de escalado debe ser >= 0."); 
                } 
            } 
     
            /// <summary> 
            /// Grado en % para el escalado en el Eje Y 
            /// </summary> 
            public double ScaleY 
            { 
                get { return scaleY; } 
                set 
                { 
                    if (value >= 0.0) 
                        scaleY = value; 
                    else 
                        throw new Exception("El grado de escalado debe ser >= 0."); 
                } 
            } 
            #endregion 
            #region Constructores 
     
            /// <summary> 
            /// Crea un procesador de imágenes para transformaciones/optimizaciones 
            /// </summary> 
            /// <param name="ruta">Ruta completa a la imagen</param> 
            public ImageProcessor(string ruta) 
            { 
                FileStream stream; 
     
                if (ruta != "" && ruta != null && System.IO.File.Exists(ruta)) 
                { 
                    this.ruta = ruta; 
     
                    //Obtener los datos de la imágen 
                    stream = new FileStream(ruta, FileMode.Open, FileAccess.Read, FileShare.Read); 
                    source = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); 
     
                } 
                else 
                    throw new System.IO.FileNotFoundException("No se encuentra el fichero '" + ruta + "'"); 
            } 
     
            /// <summary> 
            /// Crea un procesador de imágenes para transformaciones/optimizaciones 
            /// </summary> 
            /// <param name="ruta">Ruta completa a la imagen</param> 
            public ImageProcessor(Uri ruta) 
            { 
                if (ruta != null && ruta.OriginalString != "" && System.IO.File.Exists(ruta.OriginalString)) 
                { 
                    this.ruta = ruta.OriginalString; 
                    this.url = ruta; 
     
                    //Obtener los datos de la imágen 
                    source = BitmapFrame.Create(ruta); 
     
                } 
                else 
                    throw new System.IO.FileNotFoundException("No se encuentra el fichero '" + ruta + "'"); 
            } 
            #endregion 
            #region Métodos 
     
            /// <summary> 
            /// Reestablece el valor de las transformaciones a su estado original 
            /// </summary> 
            public void Reset() 
            { 
                cropWidth = 0.5F; 
                cropHeight = 0.5F; 
                region = ImageRegion.All; 
                rotationAngle = 0.0; 
                scaleX = 1.0; 
                scaleY = 1.0; 
            } 
     
            /// <summary> 
            /// Obtiene una región de la imagen 
            /// </summary> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public CroppedBitmap CropRegion() 
            { 
                return CropRegion(this.ruta, this.region, this.cropWidth, this.cropHeight); 
            } 
     
            /// <summary> 
            /// Obtiene una región de la imagen 
            /// </summary> 
            /// <param name="region">Región a obtener</param> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public CroppedBitmap CropRegion(ImageRegion region) 
            { 
                return CropRegion(region, this.cropWidth, this.cropHeight); 
            } 
     
            /// <summary> 
            /// Obtiene una región de una imagen 
            /// </summary> 
            /// <param name="url">Ruta completa a la imágen</param> 
            /// <param name="region">Región a obtener</param> 
            /// <param name="cropWidth">Multiplicador para cálculo del ancho de recorte</param> 
            /// <param name="cropHeight">Multiplicador para cálculo del alto de recorte</param> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public CroppedBitmap CropRegion(ImageRegion region, float cropWidth, float cropHeight) 
            { 
                CroppedBitmap res = null
                int width = 0, height = 0, left = 0, top = 0; 
     
                if (source != null
                { 
                    //Calcular el tamaño de recorte 
                    width = Convert.ToInt32(Math.Floor(source.PixelWidth * cropWidth)); 
                    height = Convert.ToInt32(Math.Floor(source.PixelHeight * cropHeight)); 
     
                    //Calcular el inicio de recorte 
                    switch (region) 
                    { 
                        case ImageRegion.TopLeft: 
                            left = top = 0; 
                            break
                        case ImageRegion.TopRight: 
                            left = Convert.ToInt32(source.PixelWidth * (1 - cropWidth)); 
                            top = 0; 
                            break
                        case ImageRegion.BottomLeft: 
                            left = 0; 
                            top = Convert.ToInt32(source.PixelHeight * (1 - cropHeight)); 
                            break
                        case ImageRegion.BottomRight: 
                            left = Convert.ToInt32(source.PixelWidth * (1 - cropWidth)); 
                            top = Convert.ToInt32(source.PixelHeight * (1 - cropHeight)); 
                            break
                        default//No se hace ningún recorte 
                            left = top = 0; 
                            width = Convert.ToInt32(source.PixelWidth); 
                            height = Convert.ToInt32(source.PixelHeight); 
                            break
                    } 
     
                    //Crear la imágen recortada 
                    res = new CroppedBitmap(source, new System.Windows.Int32Rect(left, top, width, height)); 
     
                } 
     
                return res; 
            } 
     
            /// <summary> 
            /// Rota una imagen un cierto angulo 
            /// </summary> 
            /// <param name="angulo">Ángulo a rotar en grados</param> 
            /// <returns>Imagen rotada</returns> 
            public TransformedBitmap Rotate(double angulo) 
            { 
                return Rotate(source, angulo); 
            } 
     
            /// <summary> 
            /// Escala una imagen una determinada cantidad 
            /// </summary> 
            /// <param name="grado">Cantidad que se va a escalar la imágen en %</param> 
            /// <returns>Imagen rotada</returns> 
            public TransformedBitmap Scale(double grado) 
            { 
                return Scale(source, grado, grado); 
            } 
     
            /// <summary> 
            /// Escala una imagen una determinada cantidad 
            /// </summary> 
            /// <param name="gradoX">Cantidad que se va a escalar la imágen en el eje X en %</param> 
            /// <param name="gradoY">Cantidad que se va a escalar la imágen en el eje Y en %</param> 
            /// <returns>Imagen rotada</returns> 
            public TransformedBitmap Scale(double gradoX, double gradoY) 
            { 
                return Scale(source, gradoX, gradoY); 
            } 
     
            /// <summary> 
            /// Aplica las transformaciones en base a los datos de transformación 
            /// </summary> 
            /// <returns></returns> 
            public BitmapSource ApplyTransformations() 
            { 
                return Scale(Rotate(CropRegion(),this.rotationAngle),this.scaleX, this.scaleY); 
            } 
            #endregion 
            #region Static 
     
            /// <summary> 
            /// Obtiene una región de una imagen 
            /// </summary> 
            /// <param name="url">Ruta completa a la imágen</param> 
            /// <param name="region">Región a obtener</param> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public static CroppedBitmap CropRegion(string url, ImageRegion region) 
            { 
                return CropRegion(url, region, 0.5F, 0.5F); 
            } 
     
            /// <summary> 
            /// Obtiene una región de una imagen 
            /// </summary> 
            /// <param name="url">Ruta completa a la imágen</param> 
            /// <param name="region">Región a obtener</param> 
            /// <param name="cropWidth">Multiplicador para cálculo del ancho de recorte</param> 
            /// <param name="cropHeight">Multiplicador para cálculo del alto de recorte</param> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public static CroppedBitmap CropRegion(string url, ImageRegion region, float cropWidth, float cropHeight) 
            { 
                CroppedBitmap res = null
                BitmapSource src = null
                FileStream stream; 
                int width = 0, height = 0, left = 0, top = 0; 
     
                if (url != null && url != "" && File.Exists(url) && cropWidth >= 0.0F && cropWidth <= 1.0F && cropHeight >= 0.0F && cropHeight <= 1.0F) 
                { 
                    //Obtener los datos de la imágen 
                    stream = new FileStream(url, FileMode.Open, FileAccess.Read, FileShare.Read); 
                    src = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); 
     
                    //Calcular el tamaño de recorte 
                    width = Convert.ToInt32(Math.Floor(src.PixelWidth * cropWidth)); 
                    height = Convert.ToInt32(Math.Floor(src.PixelHeight * cropHeight)); 
     
                    //Calcular el inicio de recorte 
                    switch (region) 
                    { 
                        case ImageRegion.TopLeft: 
                            left = top = 0; 
                            break
                        case ImageRegion.TopRight: 
                            left = Convert.ToInt32(src.PixelWidth * (1 - cropWidth)); 
                            top = 0; 
                            break
                        case ImageRegion.BottomLeft: 
                            left = 0; 
                            top = Convert.ToInt32(src.PixelHeight * (1 - cropHeight)); 
                            break
                        case ImageRegion.BottomRight: 
                            left = Convert.ToInt32(src.PixelWidth * (1 - cropWidth)); 
                            top = Convert.ToInt32(src.PixelHeight * (1 - cropHeight)); 
                            break
                        default//No se hace ningún recorte 
                            left = top = 0; 
                            width = Convert.ToInt32(src.PixelWidth); 
                            height = Convert.ToInt32(src.PixelHeight); 
                            break
                    } 
     
                    //Crear la imágen recortada 
                    res = new CroppedBitmap(src, new System.Windows.Int32Rect(left, top, width, height)); 
     
                } 
     
                return res; 
            } 
     
            /// <summary> 
            /// Rota una imagen un cierto angulo 
            /// </summary> 
            /// <param name="imagen">Imagen a la que aplicar la rotación</param> 
            /// <param name="angulo">Ángulo a rotar en grados</param> 
            /// <returns>Imagen rotada</returns> 
            public static TransformedBitmap Rotate(BitmapSource imagen, double angulo) 
            { 
                TransformedBitmap res = null
                 
                if (imagen != null && Math.Abs(angulo) >= 0 && Math.Abs(angulo) <= 360) 
                    res = new TransformedBitmap(imagen, new RotateTransform(angulo)); 
     
                return res; 
            } 
     
            /// <summary> 
            /// Escala una imagen una determinada cantidad 
            /// </summary> 
            /// <param name="imagen">Imagen a la que aplicar el escalado</param> 
            /// <param name="grado">Cantidad que se va a escalar la imágen en %</param> 
            /// <returns>Imagen rotada</returns> 
            private static TransformedBitmap Scale(BitmapSource imagen, double grado) 
            { 
                return Scale(imagen, grado, grado); 
            } 
     
            /// <summary> 
            /// Escala una imagen una determinada cantidad 
            /// </summary> 
            /// <param name="imagen">Imagen a la que aplicar el escalado</param> 
            /// <param name="gradoX">Cantidad que se va a escalar la imágen en el eje X en %</param> 
            /// <param name="gradoY">Cantidad que se va a escalar la imágen en el eje Y en %</param> 
            /// <returns>Imagen rotada</returns> 
            private static TransformedBitmap Scale(BitmapSource imagen, double gradoX, double gradoY) 
            { 
                TransformedBitmap res = null
                if (imagen != null && gradoX >= 0.0 && gradoY >= 0.0) 
                    res = new TransformedBitmap(imagen, new ScaleTransform(gradoX, gradoY)); 
     
                return res; 
            } 
            #endregion 
        } 



    Thursday, November 20, 2008 2:50 PM

All replies

  • Hi,

     

    Here is a small example of loading image in WPF with a bit more higher performance.

     

    In the BitmapImage class, you can use some trickly skills, when you want to load  an image, just tell it to only load a thunmbnail. To achieve this, we should create a converter to connnect the equation.

     

    In the converter ,the parameter is the picture file’s fullname,  and then return a BitmapImage instance.

     

    XAML code:

     

            <Window.Resources>

            <local:PictureToBitmapConverter x:Key="converter />

        </Window.Resources>

        <ListView ItemsSource="{Binding}" Name="listview">

            <ListView.ItemTemplate>

                <DataTemplate>

                    <Image Source="{Binding Path=FullName,Converter={StaticResource converter}}" />

                </DataTemplate>

            </ListView.ItemTemplate>

         </ListView>

        </ListView>

    In the code behind:


    namespace
    WpfApplication4

    {

        public partial class Window1 : Window

        {

            public Window1()

            {

                InitializeComponent();

                //set your loaded picture path

                string picturePath = @"C:\Pictures";

                //

                DirectoryInfo dirInfo = new DirectoryInfo(picturePath);

                FileInfo[] fileInfo = dirInfo.GetFiles();

                listview.DataContext = fileInfo;

            }

        }

        // create a converter

        public class PictureToBitmapConverter : IValueConverter

        {

            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

            {

                var path = value as string;

                if (!string.IsNullOrEmpty(path))

                {

                    FileInfo info = new FileInfo(path);

                    if (info.Exists && info.Length > 0)

                    {

                        BitmapImage bi = new BitmapImage();

                        bi.BeginInit();

                        bi.DecodePixelWidth = 100;  //you can set your own size for it

                        bi.CacheOption = BitmapCacheOption.OnLoad;

                        bi.UriSource = new Uri(info.FullName);

                        bi.EndInit();

                        return bi;

                    }

                }

                return null;

            }

            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

            {

                throw new Exception("The method is not implemented.");

     

            }

        }

     }


    If you are still having some questions with this, please feel free to ask.

     

    Thanks.

    </ListView>

    If


    Jim Zhou -MSFT
    Wednesday, November 19, 2008 11:08 AM
  • Hi Jim.

    It's true that your code solves the problem when loading thumbnails (I'm doing the same for the thumbnail load in a ListView).

    But the current problem is to speed up the performance of showing a big image, with it's original size. Finally, I've solved the problem using a region concept and the CroppedImage object. The idea is to show only a region of the image by user demand, in this case I've divided the image in four regions (TopLeft, TopRight, BottomLeft, BottomRight).

    In this case the load performance increases 4 times, without loosing quality.

    That's the object I use. I hope this post would be useful to others.

       
    /// <summary> 
        /// Objeto para la optimización y filtrado de imágenes 
        /// </summary> 
        public class ImageProcessor 
        { 
            /// <summary> 
            /// Representa las distintas regiones visualizables de la imágen 
            /// </summary> 
            public enum ImageRegion { TopLeft, TopRight, BottomLeft, BottomRight, All }; 
            #region Propiedades 
     
            /// <summary> 
            /// Multiplicador para cálculo del ancho de recorte 
            /// </summary> 
            private float cropWidth = 0.5F; 
            /// <summary> 
            /// Multiplicador para cálculo del alto de recorte 
            /// </summary> 
            private float cropHeight = 0.5F; 
            /// <summary> 
            /// Región de la imágen a mostrar 
            /// </summary> 
            private ImageRegion region = ImageRegion.All; 
            /// <summary> 
            /// Ángulo de rotación 
            /// </summary> 
            private double rotationAngle = 0.0; 
            /// <summary> 
            /// Grado en % para el escalado en el Eje X 
            /// </summary> 
            private double scaleX = 1.0; 
            /// <summary> 
            /// Grado en % para el escalado en el Eje Y 
            /// </summary> 
            private double scaleY = 1.0; 
            /// <summary> 
            /// Ruta de la imagen a procesar 
            /// </summary> 
            private string ruta = ""
            /// <summary> 
            /// Ruta de la imagen a procesar 
            /// </summary> 
            private Uri url = null
            /// <summary> 
            /// Imagen original a procesar 
            /// </summary> 
            private BitmapSource source = null
            #endregion 
            #region Atributos 
     
            /// <summary> 
            /// Multiplicador para cálculo del ancho de recorte 
            /// </summary> 
            public float CropWidth 
            { 
                get { return cropWidth; } 
                set  
                { 
                    if (value >= 0) 
                        cropWidth = value; 
                    else 
                        throw new Exception("El ancho de recorte debe ser >= 0."); 
                } 
            } 
     
            /// <summary> 
            /// Multiplicador para cálculo del alto de recorte 
            /// </summary> 
            public float CropHeight 
            { 
                get { return cropHeight; } 
                set 
                { 
                    if (value >= 0) 
                        cropHeight = value; 
                    else 
                        throw new Exception("El alto de recorte debe ser >= 0."); 
                } 
            } 
     
            /// <summary> 
            /// Región de la imágen a mostrar en recortes 
            /// </summary> 
            public ImageRegion Region 
            { 
                get { return region; } 
                set { region = value; } 
            } 
     
            /// <summary> 
            /// Ángulo de rotación 
            /// </summary> 
            public double RotationAngle 
            { 
                get { return rotationAngle; } 
                set { rotationAngle = value; } 
            } 
     
            /// <summary> 
            /// Grado en % para el escalado en el Eje X 
            /// </summary> 
            public double ScaleX 
            { 
                get { return scaleX; } 
                set  
                { 
                    if (value >= 0.0) 
                        scaleX = value; 
                    else 
                        throw new Exception("El grado de escalado debe ser >= 0."); 
                } 
            } 
     
            /// <summary> 
            /// Grado en % para el escalado en el Eje Y 
            /// </summary> 
            public double ScaleY 
            { 
                get { return scaleY; } 
                set 
                { 
                    if (value >= 0.0) 
                        scaleY = value; 
                    else 
                        throw new Exception("El grado de escalado debe ser >= 0."); 
                } 
            } 
            #endregion 
            #region Constructores 
     
            /// <summary> 
            /// Crea un procesador de imágenes para transformaciones/optimizaciones 
            /// </summary> 
            /// <param name="ruta">Ruta completa a la imagen</param> 
            public ImageProcessor(string ruta) 
            { 
                FileStream stream; 
     
                if (ruta != "" && ruta != null && System.IO.File.Exists(ruta)) 
                { 
                    this.ruta = ruta; 
     
                    //Obtener los datos de la imágen 
                    stream = new FileStream(ruta, FileMode.Open, FileAccess.Read, FileShare.Read); 
                    source = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); 
     
                } 
                else 
                    throw new System.IO.FileNotFoundException("No se encuentra el fichero '" + ruta + "'"); 
            } 
     
            /// <summary> 
            /// Crea un procesador de imágenes para transformaciones/optimizaciones 
            /// </summary> 
            /// <param name="ruta">Ruta completa a la imagen</param> 
            public ImageProcessor(Uri ruta) 
            { 
                if (ruta != null && ruta.OriginalString != "" && System.IO.File.Exists(ruta.OriginalString)) 
                { 
                    this.ruta = ruta.OriginalString; 
                    this.url = ruta; 
     
                    //Obtener los datos de la imágen 
                    source = BitmapFrame.Create(ruta); 
     
                } 
                else 
                    throw new System.IO.FileNotFoundException("No se encuentra el fichero '" + ruta + "'"); 
            } 
            #endregion 
            #region Métodos 
     
            /// <summary> 
            /// Reestablece el valor de las transformaciones a su estado original 
            /// </summary> 
            public void Reset() 
            { 
                cropWidth = 0.5F; 
                cropHeight = 0.5F; 
                region = ImageRegion.All; 
                rotationAngle = 0.0; 
                scaleX = 1.0; 
                scaleY = 1.0; 
            } 
     
            /// <summary> 
            /// Obtiene una región de la imagen 
            /// </summary> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public CroppedBitmap CropRegion() 
            { 
                return CropRegion(this.ruta, this.region, this.cropWidth, this.cropHeight); 
            } 
     
            /// <summary> 
            /// Obtiene una región de la imagen 
            /// </summary> 
            /// <param name="region">Región a obtener</param> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public CroppedBitmap CropRegion(ImageRegion region) 
            { 
                return CropRegion(region, this.cropWidth, this.cropHeight); 
            } 
     
            /// <summary> 
            /// Obtiene una región de una imagen 
            /// </summary> 
            /// <param name="url">Ruta completa a la imágen</param> 
            /// <param name="region">Región a obtener</param> 
            /// <param name="cropWidth">Multiplicador para cálculo del ancho de recorte</param> 
            /// <param name="cropHeight">Multiplicador para cálculo del alto de recorte</param> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public CroppedBitmap CropRegion(ImageRegion region, float cropWidth, float cropHeight) 
            { 
                CroppedBitmap res = null
                int width = 0, height = 0, left = 0, top = 0; 
     
                if (source != null
                { 
                    //Calcular el tamaño de recorte 
                    width = Convert.ToInt32(Math.Floor(source.PixelWidth * cropWidth)); 
                    height = Convert.ToInt32(Math.Floor(source.PixelHeight * cropHeight)); 
     
                    //Calcular el inicio de recorte 
                    switch (region) 
                    { 
                        case ImageRegion.TopLeft: 
                            left = top = 0; 
                            break
                        case ImageRegion.TopRight: 
                            left = Convert.ToInt32(source.PixelWidth * (1 - cropWidth)); 
                            top = 0; 
                            break
                        case ImageRegion.BottomLeft: 
                            left = 0; 
                            top = Convert.ToInt32(source.PixelHeight * (1 - cropHeight)); 
                            break
                        case ImageRegion.BottomRight: 
                            left = Convert.ToInt32(source.PixelWidth * (1 - cropWidth)); 
                            top = Convert.ToInt32(source.PixelHeight * (1 - cropHeight)); 
                            break
                        default//No se hace ningún recorte 
                            left = top = 0; 
                            width = Convert.ToInt32(source.PixelWidth); 
                            height = Convert.ToInt32(source.PixelHeight); 
                            break
                    } 
     
                    //Crear la imágen recortada 
                    res = new CroppedBitmap(source, new System.Windows.Int32Rect(left, top, width, height)); 
     
                } 
     
                return res; 
            } 
     
            /// <summary> 
            /// Rota una imagen un cierto angulo 
            /// </summary> 
            /// <param name="angulo">Ángulo a rotar en grados</param> 
            /// <returns>Imagen rotada</returns> 
            public TransformedBitmap Rotate(double angulo) 
            { 
                return Rotate(source, angulo); 
            } 
     
            /// <summary> 
            /// Escala una imagen una determinada cantidad 
            /// </summary> 
            /// <param name="grado">Cantidad que se va a escalar la imágen en %</param> 
            /// <returns>Imagen rotada</returns> 
            public TransformedBitmap Scale(double grado) 
            { 
                return Scale(source, grado, grado); 
            } 
     
            /// <summary> 
            /// Escala una imagen una determinada cantidad 
            /// </summary> 
            /// <param name="gradoX">Cantidad que se va a escalar la imágen en el eje X en %</param> 
            /// <param name="gradoY">Cantidad que se va a escalar la imágen en el eje Y en %</param> 
            /// <returns>Imagen rotada</returns> 
            public TransformedBitmap Scale(double gradoX, double gradoY) 
            { 
                return Scale(source, gradoX, gradoY); 
            } 
     
            /// <summary> 
            /// Aplica las transformaciones en base a los datos de transformación 
            /// </summary> 
            /// <returns></returns> 
            public BitmapSource ApplyTransformations() 
            { 
                return Scale(Rotate(CropRegion(),this.rotationAngle),this.scaleX, this.scaleY); 
            } 
            #endregion 
            #region Static 
     
            /// <summary> 
            /// Obtiene una región de una imagen 
            /// </summary> 
            /// <param name="url">Ruta completa a la imágen</param> 
            /// <param name="region">Región a obtener</param> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public static CroppedBitmap CropRegion(string url, ImageRegion region) 
            { 
                return CropRegion(url, region, 0.5F, 0.5F); 
            } 
     
            /// <summary> 
            /// Obtiene una región de una imagen 
            /// </summary> 
            /// <param name="url">Ruta completa a la imágen</param> 
            /// <param name="region">Región a obtener</param> 
            /// <param name="cropWidth">Multiplicador para cálculo del ancho de recorte</param> 
            /// <param name="cropHeight">Multiplicador para cálculo del alto de recorte</param> 
            /// <returns>Imágen recortada con la región especificada</returns> 
            public static CroppedBitmap CropRegion(string url, ImageRegion region, float cropWidth, float cropHeight) 
            { 
                CroppedBitmap res = null
                BitmapSource src = null
                FileStream stream; 
                int width = 0, height = 0, left = 0, top = 0; 
     
                if (url != null && url != "" && File.Exists(url) && cropWidth >= 0.0F && cropWidth <= 1.0F && cropHeight >= 0.0F && cropHeight <= 1.0F) 
                { 
                    //Obtener los datos de la imágen 
                    stream = new FileStream(url, FileMode.Open, FileAccess.Read, FileShare.Read); 
                    src = BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad); 
     
                    //Calcular el tamaño de recorte 
                    width = Convert.ToInt32(Math.Floor(src.PixelWidth * cropWidth)); 
                    height = Convert.ToInt32(Math.Floor(src.PixelHeight * cropHeight)); 
     
                    //Calcular el inicio de recorte 
                    switch (region) 
                    { 
                        case ImageRegion.TopLeft: 
                            left = top = 0; 
                            break
                        case ImageRegion.TopRight: 
                            left = Convert.ToInt32(src.PixelWidth * (1 - cropWidth)); 
                            top = 0; 
                            break
                        case ImageRegion.BottomLeft: 
                            left = 0; 
                            top = Convert.ToInt32(src.PixelHeight * (1 - cropHeight)); 
                            break
                        case ImageRegion.BottomRight: 
                            left = Convert.ToInt32(src.PixelWidth * (1 - cropWidth)); 
                            top = Convert.ToInt32(src.PixelHeight * (1 - cropHeight)); 
                            break
                        default//No se hace ningún recorte 
                            left = top = 0; 
                            width = Convert.ToInt32(src.PixelWidth); 
                            height = Convert.ToInt32(src.PixelHeight); 
                            break
                    } 
     
                    //Crear la imágen recortada 
                    res = new CroppedBitmap(src, new System.Windows.Int32Rect(left, top, width, height)); 
     
                } 
     
                return res; 
            } 
     
            /// <summary> 
            /// Rota una imagen un cierto angulo 
            /// </summary> 
            /// <param name="imagen">Imagen a la que aplicar la rotación</param> 
            /// <param name="angulo">Ángulo a rotar en grados</param> 
            /// <returns>Imagen rotada</returns> 
            public static TransformedBitmap Rotate(BitmapSource imagen, double angulo) 
            { 
                TransformedBitmap res = null
                 
                if (imagen != null && Math.Abs(angulo) >= 0 && Math.Abs(angulo) <= 360) 
                    res = new TransformedBitmap(imagen, new RotateTransform(angulo)); 
     
                return res; 
            } 
     
            /// <summary> 
            /// Escala una imagen una determinada cantidad 
            /// </summary> 
            /// <param name="imagen">Imagen a la que aplicar el escalado</param> 
            /// <param name="grado">Cantidad que se va a escalar la imágen en %</param> 
            /// <returns>Imagen rotada</returns> 
            private static TransformedBitmap Scale(BitmapSource imagen, double grado) 
            { 
                return Scale(imagen, grado, grado); 
            } 
     
            /// <summary> 
            /// Escala una imagen una determinada cantidad 
            /// </summary> 
            /// <param name="imagen">Imagen a la que aplicar el escalado</param> 
            /// <param name="gradoX">Cantidad que se va a escalar la imágen en el eje X en %</param> 
            /// <param name="gradoY">Cantidad que se va a escalar la imágen en el eje Y en %</param> 
            /// <returns>Imagen rotada</returns> 
            private static TransformedBitmap Scale(BitmapSource imagen, double gradoX, double gradoY) 
            { 
                TransformedBitmap res = null
                if (imagen != null && gradoX >= 0.0 && gradoY >= 0.0) 
                    res = new TransformedBitmap(imagen, new ScaleTransform(gradoX, gradoY)); 
     
                return res; 
            } 
            #endregion 
        } 



    Thursday, November 20, 2008 2:50 PM