DotNetcr.com
Si deseas hacer un intercambio de links con DotNetcr, escríbenos aquí
Recibe las actualizaciones vía RSS
Te invitamos a unirte en nuestras redes
   http://www.facebook.com/DotNetcr
   http://www.twitter.com/dotnetcr

Como comprimir imagenes JPG en VB.NET

Por aconsult | 1/12/2006 | Visitas 31,460 | Voto 5.00
Durante el desarrollo de una aplicación tuve oportunidad de investigar y desarrollar de qué forma se pueden manipular imágenes de una manera optimizada e intentar que no generen sobrecarga de memoria ni de espacio de almacenamiento.
Categorías : VB.NET
Descargar ejemplo JPG_Compresor.zip

La iniciativa surgió en base a la necesidad de agregar imágenes de determinados artículos a una base de datos. Asimismo, estas imágenes se deberían poder visualizar en una aplicación. Las imágenes estaban adquiridas mediante una cámara de fotos digital en un tamaño original de 2048 x 1536 Pixels (3.15 MPixels), arrojando valores de almacenamiento en disco de aproximadamente 1.5 Mb, cada una.

Investigando el Espacio de Nombres System.Drawing.Imaging encontré que existe una variada cantidad de Clases que brindan funcionalidad avanzada GDI+ (Graphics Device Interface / Interfase de Dispositivo Gráfico). La solución que comparto con Uds. es sencilla y generé una pequeña aplicación (fácilmente ampliable) que muestra como implementar métodos de compresión de datos (en este caso, imágenes JPG).

El resultado fue más que satisfactorio: por un lado se redujo la visualización "física" de las imágenes a los requerimientos de la aplicación (un espacio de 200 x 150 pixels). Por el otro, en muchos casos, se redujo el peso de las imágenes a menos del 1 % (uno porciento) de su peso original, ajustando el porcentaje de compresión al 70%, sin perder calidad visual apreciable.

Comencemos viendo la sentencia de llamada:

SaveJPGWithCompressionSetting(DestTmpImage, Application.StartupPath & "\" & "temp.jpg", TrackBar1.Value)


Los parámetros que recibe esta sentencia son:

  • El nombre de un Bitmap que contiene la imagen a comprimir (DestTmpImage), ya ajustado según un factor de escala

  • Una ubicación de almacenamiento en disco junto con un nombre de archivo

  • Un valor numérico que indica el porcentaje de compresión


  • La subrutina que recibe los datos es la siguiente:

    Public Shared Sub SaveJPGWithCompressionSetting(ByVal image As Image, ByVal szFileName As String, ByVal lCompression As Long)

    Dim eps As EncoderParameters = New EncoderParameters(1)
    eps.Param(0) = New EncoderParameter(Encoder.Quality, lCompression)
    Dim ici As ImageCodecInfo = GetEncoderInfo("image/jpeg")

    Try
    image.Save(szFileName, ici, eps)
    Catch exc As Exception
    MessageBox.Show(exc, " Atención !", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try

    End Sub


    Se comienza dimensionando un objeto de tipo EncoderParameters, llamado "eps", que encapsulará una matriz de objetos tipo EncoderParameter. Los objetos EncoderParameter se utilizan para pasar una matriz de valores a un codificador de imágenes. También se pueden utilizar para recibir una lista de posibles valores que estén soportados por una parámetro particular de un codificador de imágenes particular. En este caso inicializamos un nueva instancia de la clase EncoderParameters para que contenga 1 (un) objeto EncoderParameter, mediante la llamada al constructor adecuado.

    A continuación se asigna a la propiedad Param, del objeto declarado anteriormente, una nueva instancia de un objeto EncoderParameter, especificando un objeto Encoder y un valor de tipo Long (32-bit). El objeto tipo Encoder encapsula un identificador global único (GUID) que identifica la categoría de un parámetro de codificación de una imagen. En este caso, la categoría refiere al campo Quality (Calidad). El valor de tipo Long refiere al nivel de compresión deseado (lCompression).

    Paso siguiente se dimensiona un objeto de tipo ImageCodecInfo, llamado "ici". Esta Clase proporciona los miembros y métodos de almacenamiento necesarios para recuperar toda información pertinente acerca de los codecs de imagen que estén instalados. Recordemos que codec hace referencia al término Coder-decoder, es decir, un filtro que comprime o descomprime un flujo de datos. En este momento se llama a la función GetEncoderInfo, pasando como parámetro una cadena que contiene el tipo mimeType asignado como image/jpeg. (MIME = Multipurpose Internet Mail Extensions)

    Veamos como se compone la función:

    Public Shared Function GetEncoderInfo(ByVal mimeType As String) As ImageCodecInfo
    Dim j As Integer
    Dim encoders As ImageCodecInfo()
    encoders = ImageCodecInfo.GetImageEncoders()
    For j = 0 To encoders.Length
    If encoders(j).MimeType = mimeType Then
    Return encoders(j)
    End If
    Next j
    Return Nothing
    End Function


    Dimensionamos una variable de tipo entero llamada "j" para iterar en el loop que figura más abajo.

    Dimensionamos una variable de tipo ImageCodecInfo llamada "encoders". Asignamos a esta variable el resultado de llamar al método GetImageEncoders que en este caso tendrá una longitud de 5 ya que refiere a los codecs de imagen que están instalados por defecto. Si revisamos los elementos de esta matriz se puede constatar que los codecs de imagen son:

    CodecNameFilenameExtensionFormatDescriptionMimeType
    Built-in BMP Codec.BMP;*.DIB;*.RLEBMPimage/bmp
    Built-in JPEG Codec.JPG;*.JPEG;*.JPE;*.JFIFJPEGimage/jpeg
    Built-in GIF Codec*.GIFGIFimage/gif
    Built-in TIFF Codec*.TIF;*.TIFFTIFFimage/tiff
    Built-in PNG Codec*.PNGPNGimage/png


    Iteramos en el loop buscando un encoder que sea similar al tipo de imagen que se está procesando (en este caso image/jpeg) y obtenemos la inforción referente a ese encoder específico, retornando a la subrutina anterior.

    A fines de monitorear el resultado del paso que se ejecutará acontinuación (almacenar la imagen comprimida en disco) y manejar en forma robusta el manejo de excepciones en caso que se produzca un error, utilizaremos una sentencia Try...Catch. En el bloque Try llamaremos el método Save, pasando 3 parámetros: el nombre del archivo ("szFileName"), la información del encoder ("ici") y los parámetros del encoder ("eps"). Si se produce algún error lo podremos manejar a través de un MessageBox para alertar al usuario, que mostrará una descripción de la excepción ocurrida.

    Acerca de la aplicación de ejemplo



    La imagen de la aplicación que se muestra (que se puede obtener en forma completa en el link que aparece en esta página) consta de:

  • Un botón llamado "Cargar Imagen" que permitirá, mediante un Caja de Diálogo, seleccionar y cargar la imagen de tipo JPG a comprimir, que aparecerá en el cuadro llamado "Origen"

  • Un objeto tipo TrackBar para poder setear el Porcentaje de Compresión

  • Un botón llamado "Obtener Resultado" que dimensiona, genera, y muestra la imagen comprimida en el cuadro llamado"Resultado"

  • Un botón llamado "Guardar Imagen" que permitirá, mediante una Caja de Diálogo, almacenar el archivo comprimido resultante


  • Debajo de la imagen original y de la imagen resultante aparecen sus dimensiones reales expresadas en pixels (Ancho-Alto), como así también el espacio en bytes que ocupa y ocupará en disco luego de la compresión. Es decir, con estos datos, se puede experimentar la relación calidad visual / peso en bytes, para así poder seleccionar lo que nos parezca el mejor resultado previo al momento de almacenar.

    El cuadro "Ajustes", que no está habilitado, se muestra como posibilidad de ampliación de la aplicación propuesta a fines de dimensionar la imagen resultante a otros valores que no sean los sugeridos en este ejemplo (200 px de ancho por 150 px de alto).

    Conclusión

    Esta Nota expone algunos aspectos del Espacio de Nombres System.Drawing.Imaging y detalla aspectos de algunas de sus Clases que trabajan sobre GDI+. Describe como poder comprimir imágenes en formato JPG, pero resulta sencillo ahora extender el manejo a otros tipos de formatos, como GIF o PNG. Inclusive se exponen las herramientas básicas para poder convertir entre formatos. La aplicación ejemplo muestra como trabajar con estas herramientas de forma clara e intuitiva. Espero que les sea de utilidad.

    Descargar ejemplo JPG_Compresor.zip
    Area de Comentarios
    Por chekohm - Fecha: 2006/03/30 05:36 PM
    lo puedo utilizar para una aplicacion web en vb.net ????
    Por Anónimo - Fecha: 2006/09/22 12:41 PM
    excelente codigo, un poco enredado, pero muy funcional, en mi caso gracias, me sirvio mucho.
    Por Anónimo - Fecha: 2006/11/30 09:57 AM
    Usas algún algorítmo de compresión propio? o utilizas lo que ya viene con el .net
    Por Anónimo - Fecha: 2007/05/15 09:25 AM
    No me da lo que necesito. Mueranse no puedo hacr la tarea
    quiero ,saber si bmp comprime o no eee,
    Cony y Maru

    Por Anónimo - Fecha: 2007/05/15 09:27 AM
    les dejo mi mail por si quieren agregarme.. milagros_ferda@hotmail.com
    me llamo mili!!
    gracias esta pag es una mierdaaaaaa

    bsoooooo
    Por Anónimo - Fecha: 2007/05/23 07:37 PM
    que pagina tan interesante!
    y que gentuza tan maleducada e poco agradecida con quien comparte su experiencia y conocimiento con ellos.
    Por Anónimo - Fecha: 2007/06/21 06:28 AM
    Por desgracia, en todos lados hay gentuza, y que de seguro se aprovechan de los demás, y su forma de "no reconocerlo" es la que vemos. Gracias por compartir tus horas de investigación que a todos nos cuesta tanto. A mí me ha ido de perlas encontrar este trabajo en este momento.
    Por Anónimo - Fecha: 2007/07/26 05:20 PM
    Hola buen dia, tu codigo me ha servido bastante muchas gracias por haberlo compartido, pero tego el siguiente problema, cuendo quiero comprimir una imagen, aveces si la carga, aveces no y cuando no lo comprime me manda el siguiente error:
    No se puede convertir un objeto de tipo ''System.InvalidCastException'' al tipo ''System.Windows.Forms.IWin32Window''

    Te agradeceria si me pudieras ayudar en lo que puedas, de antemano muchas gracias.
    Te dejo mi correo para ver si me puedes ayudar: tranen_angst@hotmail.com
    Por Anónimo - Fecha: 2007/08/21 12:03 PM
    excelente ejemplo de compresion de imagenes, estaba buscando algo parecido y me ayudo mucho tu ejemplo, feliciones te dejo mi correo para estar en contacto amorales_585@hotmail.com
    Por Anónimo - Fecha: 2007/08/22 07:30 PM
    !Que buen código, para mi ha sido muy provechoso y encontré la solución a mi problema de compresión, ya que las imágenes que antes tenía eran de 400KB y ahora solo pesan 60KB, ¡Excelente!, te doy las gracias, sobre todo por que no hay mucha info disponible sobre el tema, y además la ayuda de microsoft no entra en detalles.
    Solo una pregunta, de donde sacas que la variable lCompression debe ser un porcentaje??, quiero saber como llegas a esa conclusión pues me interesan los detalles técnicos, yo definí lCompression como Integer y funciona, pero no estoy seguro por que debe ser long. Porfa, me puedes explicar, te dejo mi email: cjnmdpnp@hotmail.com
    Vuelo a repetir muchas gracias y esperamos que pronto escribas más códigos interesantes como este.
    Por Anónimo - Fecha: 2007/09/05 11:40 AM
    gracias, lo voy a checar por q necesito agregar imagenes a los registros q me voy a utilizar
    Por Anónimo - Fecha: 2007/11/01 03:38 PM
    holas necesito que alguien me ayude con un compresor rle que necesito implementar en c#...el problema es que no se como acceder a la secuencia de bytes del fichero ejemplo si es una imagen, acceder al arreglo de bytes de la imagen... en fin cuaquier ayuda sera bienvenida les dejo mi mail por si alguno se interesa

    ibrael.avalanch@gmail.com

    saludos a todos y espero que tengan lindo dia
    Por Anónimo - Fecha: 2007/11/04 02:07 PM
    Me has salvado la vida!!!
    Por Anónimo - Fecha: 2008/07/04 07:42 AM
    Muchas gracias, me ha sido de gran utilidad
    Por Anónimo - Fecha: 2008/10/02 02:41 AM
    Aconsult, muchísimas grácias por compartir este codigo con todos nosotros. Particularmente me ha sido de mucha utilidad. Excelente explicación al detalle. Saludos.
    Por Anónimo - Fecha: 2010/02/25 08:06 PM
    Muy buena rutina tio, me ha servido mucho. he implementado una aplicacion que toma fotos desde la webcam y registra los nombres de las archivos en una base de datos y tambien sube las fotos a una carpeta del servidor. mi problema era que al cargar las imagenes en el datagridview, tardaba mucho por que jalaba las imagenes desde el servidor, pero ahora demora menos pues las imagenes que se guardan en mi carpeta del servidor ya estan comprimidas. Gracias por tomarte tu tiempo. Aunque es un post antiguo, igual queria agradecer. omar diaz > www.mejorfinal.blogspot.com
    Por Anónimo - Fecha: 2010/09/10 01:29 AM
    Muchas gracias por las funciones que has publicado, todavia no las he probado pero leí todos los comentarios.
    Por Anónimo - Fecha: 2011/10/02 08:08 AM
    ME DA RISA LA GENTE QUE LO QUIERE TODO FACILITO SI NO SABEN COMO IMPLEMENTAR LOS ARCHIVOS QUE GENTILMENTE SUBEN AQUI MEJOR DEDIQUENSE A OTRA COSA!!!
    Por Anónimo - Fecha: 2012/02/02 10:17 AM
    Muy buen ejemplo funcionó todo ok, cambie las escalas de 200 a 400 y de 150 a 300 para una mejor resolución.
    Muchas gracias!!!!!
    Por Anónimo - Fecha: 2012/06/02 04:45 PM
    a mi no me sale.. porque me tira un error en el OpenFile.. no me lo toma :(
    estoy extremadamente consternado por la situación... ya me tome 6 fernet y no surgen las ideas..
    estoy triste...
    te dejo mi mail..

    malditovb.net@putamadre.com

    chau...
    gracias por el codigo pero soy muy inepto..

    felices pascuas!!
    Por Anónimo - Fecha: 2012/07/18 07:42 PM
    Ole1 Nepf4 tudo bem,Bom quero sim aprofundar eu estou com utpmojero para iniciae7e3o cientedfica ainda estou me graduando em filosofia 2ba peredodo ainda e sou graduado em sistemas de informae7e3o, ente3o para ne3o perder a computae7e3o je1 que estou mudando de e1rea resolvi estudar a filosfia da informae7e3o, e tive um plim interessante, com toda essa modernidade e todo mundo pensando em um des-humanizae7e3o das relae7f5es atrave9s da tecnologia, porque ne3o pensar de forma contre1ria?? Ente3o passei a estudar o que realmente era o virtual na filosofia, com Pierre Levy, Luciano Floridi e mais um que ainda ne3o me lembro o nome, ente3o pensei se he1 o virtual e o real separados eles se3o subjetivos mas, o que e9 subjetivo tem um esseancia, ente3o a teoria das formas de plate3o poderia me ajudar a rever o conceito de virtual e real pensando na informe1tica. Ente3o fae7o comparae7f5es como: Prae7as e centro de conviveancias X Redes Sociais; Quadros X Imagens digitais (Fotomontagens, layouts de sites e etc, aqui uso um pouco da fenomenologia de Merleau-Ponty); Comunicae7f5es diversas X Comunicae7e3o inste2ntanea e afins. Quando eu falo de empedrico eu chamo de empedrico o que os olhos, ou seja, o sentido da vise3o ilhe de1 como real e, quando eu digo que ela sempre sere1 A INTERNET digo que independentemente de como as pessoas pensem a internet em toda a sua subjetividade ela tere1 sempre algo que a fae7a o que ela e9, tere1 sempre sua via de acesso e seus cf3digos espalhados pela rede a disposie7e3o de ve1rias pessoas.Gostaria sim de aprofundar no caso ate9 pedir umas indicae7f5es de leitura sobre ontologia e antropologia que eu consiga associar no meu estudo pois ainda ne3o achei muita coisa interessante nestes aspectos. Fiquei curioso, pois he1 uma linha na filosofia que acredita que he1 algo fora do ser humano e outra que acredita que esse fora por ser intoce1vel sempre sere1 subjetivo. > bom existem as duas pore9m seguindo os filf3sofos que estou estudando a subjetividade ainda e9 um pouco prejorativa, como plate3o e sf3crates que atacam amargamente os sofistas e, entre outros a subjetividade e9 vaga. Pode sim ser subjetivo dependendo da forma de pensar de cada um pore9m ela tem um conceito e este conceito na mais e9 do que a imagem que vocea tem de algo vinculada ao seu uso e este e9 o mesmo para todos, eu penso em uma cadeira assim como vc pensa, pode ne3o ser a mesma cadeira azeul e acolchoada que pensei agora mas a cadeira laranja e de ple1stico continua sendo cadeira e tenhoo mesmo conceito da citada anteriormente, sendo assim, a subjetividade ne3o completa a coisa. Essa linha de reflexe3o e9 que eu tenho quando penso em A INTERNET .Ainda escrevo um pouco de forma confusa mas espero que entenda o que quero dizer, sere1 de grande valia as discussf5es e as trocas de e-mail se possedvel com vc Nepf4, achei que nem fosse obeter resposta hahahah abrae7os e paz .
    Por Anónimo - Fecha: 2012/07/19 10:51 AM
    rNRyi6 , [url=http://ozojutdeohnp.com/]ozojutdeohnp[/url], [link=http://wjiiytgcueoo.com/]wjiiytgcueoo[/link], http://pbxvebyyajdy.com/
    Por Anónimo - Fecha: 2012/07/20 09:44 PM
    fMUnlA , [url=http://dxbxrrnjwfcu.com/]dxbxrrnjwfcu[/url], [link=http://txhgbgqxqiah.com/]txhgbgqxqiah[/link], http://semowktocgqt.com/
    Por Anónimo - Fecha: 2012/09/20 02:33 PM
    muy buen codigo, me aclaro muchas dudas, gracias
    Por Anónimo - Fecha: 2015/07/18 08:11 AM
    Hey, that's a clever way of thniknig about it.
    Por Anónimo - Fecha: 2015/07/21 01:31 PM
    Your cranium must be prtencoitg some very valuable brains. http://tyszejjv.com [url=http://uravjxbzolm.com]uravjxbzolm[/url] [link=http://pvapfucw.com]pvapfucw[/link]
    Por Anónimo - Fecha: 2016/02/02 03:15 PM
    I rekcon you are quite dead on with that.
    Por Anónimo - Fecha: 2016/02/10 09:34 AM
    It's like you're on a miisosn to save me time and money! http://lqqxil.com [url=http://mmxlxxfy.com]mmxlxxfy[/url] [link=http://ltuqqobufu.com]ltuqqobufu[/link]
    Por Anónimo - Fecha: 2017/07/01 07:27 AM
    IDOLO,gracias por el codigo, ya le puse like,, me funciono,, lo adapte a mi sistema,,, era una locura reducir las dimensiones de una imagen y que su peso en bytes aumente,,, con lo tuyo solucione ese problema,, graciasss,,, no se que mas puedo hacer para agradecerteee idolloooooooooo
    Ingrese su Comentario
    Comentario
    Para poder votar debe estar registrado en DotNetcr.com
    Solo queda registrado el primer voto enviado
    Voto


    Últimos Recursos
    ricardo leppe t
    pedrojavier
    CALIN
    willipinru
    richard
    ragomez
    PER 238
    MEX 236
    CRI 188
    COL 118
    ESP 105
    ARG 88