martes, 6 de abril de 2010

GetThumbnailImage

Ejemplo en visual basic.Net 2005 del método GetThumbnailImage de la clase DraWing.Image para poder hacer un Thumbnail a un gráfico en un control picturebox

Este ejemplo consta de dos funciones. Una llamada buscar , para poder cargar archivos de imagen en un control Listbox y la otra función es la que usa el método GetThumbnailImage para poder obtener la miniatura de la imagen . También se usa la propiedad sizeMode del control Picturebox para que el gráfico quede centrado dentro del PicBox
Nota: al seleccionar el directorio, este buscará en todos los subdirectorios, por lo tanto puede demorar un poco

Colocar un control Button, un control Listbox y un control PictureBox

Código fuente
Option Explicit On
Option Strict On

' para usar el método Image.FromFile y el método GetThumbnailImage
Imports System.Drawing.Image
Imports System.IO ' para el método GetDirectories de la clase Directoy
' Para la colección de archivos devueltos por FileSystem.GetFiles
Imports System.Collections.ObjectModel

Public Class Form1
' Delegado para el método GetThumbnailImage
Dim CallBack As New GetThumbnailImageAbort(AddressOf MycallBack)
Dim petterns() As String = {"*.png", "*.jpg", "*.bmp", "*.gif", "*.ico"}

Function MycallBack() As Boolean
Return False
End Function

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click

' Crear un FolderBrowserDialog para seleccionar una carpeta
Dim folder_Browser As New FolderBrowserDialog

With folder_Browser
If .ShowDialog <> Windows.Forms.DialogResult.OK Then
Exit Sub
End If
End With

ListBox1.Items.Clear()
Me.Cursor = Cursors.WaitCursor
Application.DoEvents()
'Buscar y listar los archivos de imagen en el control ListBox

If Directory.GetDirectories(folder_Browser.SelectedPath).Length = 0 Then
listar_archivos(folder_Browser.SelectedPath, ListBox1)
Else
buscar(folder_Browser.SelectedPath)
End If

Me.Cursor = Cursors.Default

End Sub

' función recursiva para los directorios
Private Sub buscar(ByVal sPath As String)

' obtener todos los subdirectorios en una matriz de string
Dim carpetas() As String = Directory.GetDirectories(sPath)

' recorrer el array
For Each dir As String In carpetas
Try
' buscar de nuevo
buscar(dir)
' listar los archivos del directorio corriente
listar_archivos(dir, ListBox1)

' errores
Catch ex As UnauthorizedAccessException
Debug.Print(ex.Message.ToString)
Catch ex1 As Exception
Debug.Print(ex1.Message.ToString)
End Try
Next
End Sub

Private Sub listar_archivos(ByVal sPath As String,ByVal lbox As ListBox)

' colección para GetFiles
Dim Collections_Files As ReadOnlyCollection(Of String)

Try
' Obtener todos ficheros ( un solo nivel de dir.)
Collections_Files = My.Computer.FileSystem.GetFiles(sPath, _
FileIO.SearchOption.SearchTopLevelOnly,petterns)

' agegar a la lista las rutas
For Each archivo As String In Collections_Files
lbox.Items.Add(archivo)
Next
' errores
Catch ex As Exception
Debug.Print(ex.Message.ToString)
End Try

End Sub

' devuelve un objeto Drawing.Image con la imagen para el picturebox
Private Function get_Thumbnail_Image(ByVal sPath As String, _
ByVal Ancho As Integer,ByVal Alto As Integer) As System.Drawing.Image

Try
Dim Imagen As Image = Image.FromFile(sPath.ToString)

' Para calcular la escala
Dim HScale As Double = Ancho / Imagen.Width
Dim VScale As Double = Alto / Imagen.Height

Dim escala As Double

If (VScale >= HScale) Then
escala = HScale
Else
escala = VScale
End If

' si la imagen es mas chica (ancho y alto ) que el picture .. se deja del tamaño real
If (Imagen.Width < Ancho) And (Imagen.Height < Alto) Then
escala = 1
End If

' retornar la imagen
Return Imagen.GetThumbnailImage((CInt(Imagen.Width * escala)), _
(CInt(Imagen.Height * escala)),CallBack,IntPtr.Zero)

Catch ex As OutOfMemoryException
Debug.Print(ex.Message)
End Try
Return Nothing
End Function

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

With Picturebox1
.BackColor = Color.Black
' Establecer el SizeMode para centrar la imagen
.SizeMode = PictureBoxSizeMode.CenterImage
End With

Button1.Text = "Seleccionar directorio"
End Sub

Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs)Handles ListBox1.SelectedIndexChanged
Try
' Height y Width del control picture
Dim Ancho As Integer = Picturebox1.Width
Dim Alto As Integer = Picturebox1.Height

With Picturebox1
' recupera el Thumbnail y lo asigna
.Image = get_Thumbnail_Image(ListBox1.SelectedItem.ToString,Ancho,Alto)


End With
' errores
Catch ex As Exception
Debug.Print(ex.Message)
End Try
End Sub
End Class

Nota: el código para buscar los gráficos , parece un poco rebuscado, ya que se podria hacer con tres o cuatro líneas de código nada mas, usando un For each y el método getFiles con el parámetro SearchOption.AllDirectories .
El problema es que me daba error cuando intantaba leer algunas carpetas, como por ejemplo "system Volumen Information" : El error que me daba es UnauthorizedAccessException .. error de acceso no autorizado.
Busqué mucha información sobre este tema , pero no encontré la forma de poder obviar el error y que prosiga con el resto de directorios normalmente, y tube que hacerlo mediante dos funciones y busque recursivamente . Por eso cualquier noticia sobre el tema o una solución mejor, es bienvenida.

No hay comentarios:

Publicar un comentario