Universidad Central Del Ecuador Facultad De Ingeniería

Preview only show first 6 pages with water mark for full document please download

Transcript

UNIVERSIDAD CENTRAL DEL ECUADOR FACULTAD DE INGENIERÍA CIENCIAS FÍSICAS Y MATEMÁTICA CARRERA DE INGENIERÍA EN COMPUTACIÓN GRÁFICA DESARROLLO DE UNA APLICACIÓN WEB PARA LA COMPRESIÓN DE IMÁGENES TRABAJO DE GRADUACIÓN PREVIO A LA OBTENCIÓN DEL TÍTULO DE INGENIERO EN COMPUTACIÓN GRÁFICA AUTOR: VERÓNICA ELIZABETH VICENTE CUEVA TUTOR: FIS. GONZALO BAYARDO CAMPUZANO NIETO QUITO – 15 JULIO 2016 DEDICATORIA El presente proyecto está dedicado a mis padres: Pedro y Amanda pilares fundamentales en mi vida. Sin ellos, jamás hubiese podido conseguir lo que hasta ahora. Su esfuerzo, humildad y perseverancia han sido fuente de inspiración para superar las adversidades y salir adelante. Sus consejos y disciplina fueron la motivación principal para hacer realidad este sueño. Verónica Vicente ii AGRADECIMIENTO A Dios, por haberme dado la oportunidad de culminar esta etapa de mi vida. A mis padres, por todo el esfuerzo, apoyo y amor incondicional durante esta trayectoria. A mis hermanos, por estar siempre presentes acompañándome en todo momento. A mis profesores, por su tiempo, dedicación y conocimientos brindados a lo largo de toda mi carrera profesional. A mis compañeros, con quiénes año tras año he compartido conocimientos, tristezas y alegrías. Verónica Vicente iii AUTORIZACIÓN DE LA AUTORÍA INTELECTUAL Yo, VERÓNICA ELIZABETH VICENTE CUEVA, en calidad de autora del Trabajo Proyecto Integrador realizado sobre: “DESARROLLO DE UNA APLICACIÓN WEB PARA LA COMPRESIÓN DE IMÁGENES”, por la presente autorizo a la UNIVERSIDAD CENTRAL DEL ECUADOR, hacer uso de todos los contenidos que me pertenecen o parte de los que contiene esta obra, con fines estrictamente académicos o de investigación. Los derechos que como autor me corresponden, con excepción de la presente autorización, seguirán vigentes a mi favor, de conformidad con lo establecido en los artículos 5, 6, 8, 19 y demás pertinentes de la Ley de Propiedad Intelectual y su Reglamento. Asimismo, autorizo a la UNIVERSIDAD CENTRAL DEL ECUADOR para que realice la digitalización y publicación de este trabajo de investigación en el repositorio virtual, de conformidad a lo dispuesto en el Art. 144 de la Ley Orgánica de Educación Superior. Quito, 15 de Julio de 2016. Verónica Elizabeth Vicente Cueva CI: 1718870965 Telf: 0992569910 mail: [email protected] iv CERTIFICACIÓN DEL TUTOR Yo, Gonzalo Bayardo Campuzano Nieto, titulación DESARROLLO DE UNA en calidad de tutor del trabajo de APLICACIÓN WEB PARA LA COMPRESIÓN DE IMÁGENES, elaborado por la estudiante VERÓNICA ELIZABETH VICENTE CUEVA de la Carrera de Computación Gráfica, Facultad de Ingeniería Ciencias Físicas y Matemática de la Universidad Central del Ecuador, considero que el mismo reúne los requisitos y méritos necesarios en el campo metodológico y en el campo epistemológico, para ser sometido a la evaluación por parte del jurado examinador que se designe, por lo que lo APRUEBO, a fin de que trabajo investigativo sea habilitado para continuar con el proceso de titulación determinado por la Universidad Central del Ecuador. En la ciudad de Quito, a los 20 días del mes de Junio de 2016. Fis. Gonzalo Bayardo Campuzano Nieto CC. 1708459118 mail: [email protected] v vi vii CONTENIDO pág. DEDICATORIA .................................................................................................... ii AGRADECIMIENTO ............................................................................................iii AUTORIZACIÓN DE LA AUTORÍA INTELECTUAL ............................................ iv CERTIFICACIÓN DEL TUTOR ............................................................................ v CONTENIDO ..................................................................................................... viii LISTA DE TABLAS .............................................................................................. x LISTA DE FIGURAS ........................................................................................... xi RESUMEN......................................................................................................... xiii ABSTRACT .......................................................................................................xiv INTRODUCCIÓN ................................................................................................. 1 1. DEFINICIÓN DEL PROBLEMA .................................................................... 2 1.1 Antecedentes ............................................................................................. 2 1.2 Planteamiento del problema ....................................................................... 4 1.3 Formulación del problema .......................................................................... 5 1.4 Objetivos .................................................................................................... 5 1.4.1 Objetivo general................................................................................... 5 1.4.2 Objetivos específicos ........................................................................... 5 1.5 Justificación................................................................................................ 5 2. MARCO TEÓRICO ....................................................................................... 7 2.1 Compresión de imágenes........................................................................... 7 2.1.1 Compresión sin pérdida ...................................................................... 7 a) Compresión RLE ................................................................................ 7 b) Compresión LZW ............................................................................... 9 2.1.2 Compresión con pérdida ..................................................................... 9 2.2 a) Compresión Fractal .......................................................................... 10 b) Compresión por Wavelets ................................................................ 10 c) Compresión JPEG ........................................................................... 11 Descompresión.................................................................................... 24 viii 3. METODOLOGÍA ......................................................................................... 27 3.1 Análisis de los requisitos del software ...................................................... 27 3.1.1 Librería de compresión ...................................................................... 29 3.1.2 Aplicación web ................................................................................... 31 3.2 Diseño ...................................................................................................... 35 3.2.1 Diagrama de clases para la Librería desarrollada .............................. 35 3.2.2 Diagrama para la Aplicación Web ...................................................... 37 3.3 Generación de código ............................................................................. 39 3.3.1 Librería de compresión de imágenes ................................................. 39 3.3.2 Aplicación Web .................................................................................. 40 4. PRUEBAS Y RESULTADOS ...................................................................... 42 5. CONCLUSIONES ....................................................................................... 57 6. RECOMENDACIONES ............................................................................... 59 BIBLIOGRAFÍA .................................................................................................. 60 ANEXOS ........................................................................................................... 64 ix LISTA DE TABLAS Tabla 2.1 Matrices de Cuantización: a) Luminancia, b) Crominancia ................. 18 Tabla 2.2 Categorías y bits adicionales para los coeficientes AC ..................... 20 Tabla 2.3 Contenido parcial para la Codificación de Huffman. ........................... 21 Tabla 2.4 Ejemplo Codificación de Huffman para coeficientes AC ..................... 22 Tabla 2.5 Categorías y bits adicionales para los coeficientes DC ...................... 23 Tabla 2.6 Codificación de Huffman de coeficientes DC ..................................... 23 Tabla 2.7 Ejemplo de Codificación de coeficientes DC ...................................... 24 Tabla 4.1 Resultado de compresión de imágenes TIF ....................................... 46 Tabla 4.2 Resultado de compresión de imágenes PNG ..................................... 46 Tabla 4.3 Resultado de compresión de imágenes JPG...................................... 47 Tabla 4.4 Resultado de compresión de imágenes binarias GIF ......................... 48 Tabla 4.5 Resultado de compresión de imágenes a escala de gris TIF ............. 48 Tabla 4.6 Medidas de calidad de cada formato de imagen ................................ 49 Tabla 4.7 Compresión de imágenes utilizando diferentes herramientas ............ 55 x LISTA DE FIGURAS Figura 2.1 Método de compresión RLE................................................................ 8 Figura 2.2 Tipos de recorrido de una matriz a) Recorrido por filas b) Recorrido por columnas ....................................................................................................... 8 Figura 2.3 Esquema de descomposición una imagen por Wavelets. ................ 10 Figura 2.4 a) Imagen Original, b) Descomposición de la imagen en wavelets. ... 11 Figura 2.5 Etapas del proceso de compresión JPEG ......................................... 11 Figura 2.6 Componentes de una imagen a color................................................ 12 Figura 2.7 Descomposición de planos del espacio de color YCBCR.................. 13 Figura 2.8 División de la imagen en bloques de 8x8 píxeles .............................. 15 Figura 2.9 Completar filas y columnas de una imagen ....................................... 15 Figura 2.10 Representación de las frecuencias de una imagen (SlideShare, 2016) ................................................................................................................. 16 Figura 2.11 Compactación de la energía DCT (Wikipedia, 2016) ....................... 17 Figura 2.12 Recorrido de un bloque en zigzag ................................................... 19 Figura 2.13 Vector con pares, luego de aplicar RLE .......................................... 19 Figura 2.14 Codificación DPCM en bloques de imagen. (Martín M. , 2004) ....... 22 Figura 2.15 Código de Huffman de un bloque de imagen. ................................. 24 Figura 3.1 Diagrama de flujo de la aplicación. ................................................... 35 Figura 3.2 Diagrama de clases Librería de compresión de imágenes, método JPEG. ................................................................................................................ 36 Figura 3.3 Relación entre las clases: Imagen y CompresionJPEG .................... 36 Figura 3.4 Diagrama de clases: Bloque y MatrizBloque ..................................... 37 Figura 3.5 Esquema de aplicación web ............................................................. 37 Figura 3.6 Diagrama de clases de la Aplicación Web ........................................ 38 Figura 4.1 Prueba de imágenes formato TIFF ................................................... 45 Figura 4.2 Prueba de imágenes formato PNG ................................................... 46 Figura 4.3 Resultado de compresión de imágenes JPG .................................... 47 Figura 4.4 Prueba de imágenes binarias formato GIF ........................................ 47 Figura 4.5 Prueba de imágenes escala de grises formato TIFF ......................... 48 Figura 4.6 Gráfico comparativo del ratio de compresión. ................................... 49 Figura 4.7 Porcentaje de compresión ................................................................ 50 Figura 4.8 Error Medio Cuadrático ..................................................................... 50 Figura 4.9 Relación señal ruido ......................................................................... 51 Figura 4.10 Medida de calidad estructural ......................................................... 51 Figura 4.11 Compresión de una imagen de formato bmp .................................. 53 xi Figura 4.12 Compresión de una imagen de formato tif ...................................... 53 Figura 4.13 Compresión de una imagen de formato gif...................................... 54 Figura 4.14 Compresión de una imagen de formato png ................................... 54 Figura 4.15 Compresión de una imagen de formato jpg..................................... 55 Figura 4.16 Comparativo de compresión de imágenes ...................................... 55 xii RESUMEN DESARROLLO DE UNA APLICACIÓN WEB PARA LA COMPRESIÓN DE IMÁGENES Autor: Verónica Elizabeth Vicente Cueva Tutor: Fis. Gonzalo Bayardo Campuzano Nieto En el presente proyecto se realizó un estudio de técnicas de compresión de imágenes, el cual sirvió de base para el desarrollo de una librería en C#, apoyada en el método de compresión JPEG; mismo que utiliza algoritmos matemáticos como por ejemplo la Transformada de coseno y la Cuantización que permiten eliminar parte de la información de una imagen considerada imperceptible para el ojo humano. Asimismo se creó una interfaz de usuario tomando en cuenta la metodología para el desarrollo de aplicaciones web, que conjuntamente con la librería desarrollada, realizan el proceso de compresión y descompresión de imágenes. Es decir que esta herramienta permite a los usuarios reducir el tamaño del archivo de imágenes, sin que afecte la calidad de las mismas. Además, estas imágenes estarán en formato JPG, se podrán descargar y visualizar desde cualquier visor de imágenes. PALABRAS CLAVE: /APLICACIÓN WEB /COMPRESIÓN DE IMÁGENES / ALGORITMO JPEG /TRANSFORMADA DE COSENO /CUANTIZACIÓN / DESCOMPRESIÓN DE IMÁGENES/ xiii ABSTRACT DEVELOPMENT OF A WEB APPLICATION FOR IMAGES COMPRESSION Author: Verónica Elizabeth Vicente Cueva Tutor: Fis. Gonzalo Bayardo Campuzano Nieto In the current project, a study of images compression technics was conducted, used as base to develop a library in C#, supported on JPEG compression method, which uses mathematical algorithms, such as cosine Transform and Quantization that allows eliminating a part of the information of an imaged, deemed imperceptible for the naked eye. Likewise, a user interphase was created taking into account methodology for the development of a web applications, which jointly with developed library, conduct compression and decompression process of images. Hence, such a tool allows users reducing the size of images file, without affecting their quality. Additionally, such images shall be in JPG format, can be downloaded and viewed from any images viewer. KEYWORDS: ALGORITHM /WEB APPLICATION /COSINE /IMAGES TRANSFORM COMPRESSION /QUANTIZATION /JPEG /IMAGES DECOMPRESSION I CERTIFY that the above and foregoing is a true and correct translation of the original document in Spanish. ____________ Ernesto Andino Certified Translator IC: 1703852317 xiv INTRODUCCIÓN En la actualidad, la imagen digital juega un papel importante en la transmisión de información, el fácil acceso a los diferentes dispositivos móviles y la rapidez con que se puede tomar fotografías y capturar cada momento vivido hace que subir fotos en línea sea cada vez más habitual. Sin embargo existe cierta limitación en el ancho de banda de los medios de comunicación, así como en el espacio de almacenamiento. Existen múltiples programas que permiten realizar un tratamiento previo a las imágenes con el objetivo de disminuir el peso de las mismas. Algunos de estos programas necesitan ser instalados ocupando mucho espacio en el disco duro del ordenador, incluso en algunos casos (como el de Photoshop1) además de que el programa ocupa espacio en el disco se debe pagar por la licencia. Estos programas utilizan técnicas de compresión que se pueden clasificar en dos tipos: sin pérdidas y con pérdidas. La diferencia principal radica en que la compresión sin pérdida se puede recuperar los datos en forma exacta, mientras que la compresión con pérdida se recupera una aproximación de los datos. Por este motivo surge la necesidad de realizar una aplicación web gratuita que permita a los usuarios reducir el tamaño del archivo de una imagen, mediante el desarrollo de una Librería basada en la técnica de compresión JPEG; la cual emplea algoritmos matemáticos para eliminar parte de la información de una imagen que se considera imperceptible al sistema visual humano. 1 Photoshop, software comercializado por Adobe, utilizado para crear, editar y retocar imágenes. 1 1. DEFINICIÓN DEL PROBLEMA 1.1 Antecedentes En los últimos años, la obtención de imágenes digitales es cada vez más frecuente debido a la facilidad con que se puede digitalizar la información mediante las herramientas que vienen incorporadas en los dispositivos móviles, de igual forma compartir imágenes en las diferentes redes sociales, blogs, sitios web o para uso personal. No obstante, es indispensable comprimir las imágenes con el fin disminuir el peso para su almacenamiento o posterior transmisión mejorando así la velocidad de carga de los sitios web, redes sociales, etc. Actualmente existen programas de compresión de imágenes para PC y programas de compresión en línea que permiten cargar imágenes desde el ordenador o importarlas desde otros de sitios web para luego procesarlas y generar una nueva imagen con menor peso. Tras realizar una revisión de proyectos relacionados con la compresión de imágenes podemos nombrar algunos de ellos que están relacionados con el presente proyecto:  Carlos Giler (2003), en su trabajo de grado titulado “Implementación del Algoritmo RLC (Run Length Code) para compresión y descompresión aplicado a datos provenientes de imágenes telemétricas”, orientado en el área de Electrónica y Telecomunicaciones. Propone un sistema de monitoreo visual de volcanes para el Departamento de Geofísica de la Escuela Politécnica Nacional. El sistema se desarrolló en Visual Basic, está compuesto por una PC con una cámara que permite capturar las imágenes (formato BMP) en determinado tiempo para luego ser transmitidas al receptor (otra PC) mediante equipo especializado. La finalidad de este sistema es acortar el tiempo de transmisión de éstas imágenes, para lo cual implementa el algoritmo de compresión RLE que reduce la longitud de cadena de datos de una imagen para ser transmitida en un menor tiempo.  El trabajo de Mario Sandoval (2008), se denomina “Algoritmo de compresión de imágenes de alta resolución sin pérdidas”, se trata de un proyecto desarrollado en C#, implementa el algoritmo de compresión 2 llamado RSM (Recorridos sobre la imagen). Este método lee una imagen, y obtiene las siguientes características: dimensiones de la imagen, el número de colores de la imagen, número de píxeles, número de bits por píxel. Estos datos son guardados en un vector llamado CADENA y posteriormente este vector se almacena en archivos con extensión .DAT en formato binario. El autor señala que esta técnica no presenta pérdida de información.  Manuel Velásquez (2014), realizó el proyecto “Aplicación gráfica para la compresión de información multimedia”. Es una aplicación de escritorio desarrollada en Java, permite realizar tres técnicas de compresión: RLE, LZW y Huffman, estas técnicas son descritas con mayor detalle en el Capítulo 2. A continuación se presentan algunos proyectos de código abierto de compresores de imágenesg.  jep compresor2: Es un pequeño proyecto desarrollado en C++, utiliza un solo archivo de código jpeg.cpp. Está basado en la compresión JPEG y además realiza la codificación de Huffman en una sola pasada.  Huffman Swing: Es un proyecto educativo desarrollado en java que permite realizar la compresión de archivos basado en el método compresión de Huffman.  Project One - Image Compression3: Es un proyecto desarrollado en Matlab utiliza la transformada de wavelet para la compresión de imágenes. De igual forma, la siguiente lista muestra algunos de los optimizadores de imágenes en línea más destacados de los cuales se tiene una breve descripción de sus funcionalidades y tecnologías utilizadas.  Compressor.io4: Es una aplicación web que dispone de dos alternativas de compresión: la compresión sin pérdida de calidad, que sólo es aplicable a los formatos JPG y PNG, y compresión con pérdida. Permite subir solo una imagen a la vez desde una PC y en pocos segundos se obtiene los resultados, mostrando una vista previa de la imagen original conjuntamente con la imagen comprimida, donde la diferencia entre las dos imágenes es imperceptible a la vista. La nueva imagen se puede descargar directamente a un lugar de almacenamiento de la PC. Las 2 (Google Code , 2016) (Owlnet.rice.edu, 2014) 4 (Quiñónez, 2014) 3 3 tecnologías que utiliza son software libre y de código abierto como: pngquant5, OptiPNG6, JpegOptim7, Gifsicle8 and Scour9.  Kraken.io10: Esta aplicación puede subir 20 imágenes en formato JPG y PNG simultáneamente con un tamaño máximo de 1 MB por imagen. También se pueden comprimir imágenes solo copiando la URL de las mismas. Esta aplicación web se basa en el tipo de compresión con pérdida, para ello elige la mejor calidad de la imagen en relación a su tamaño.  TinyPNG11: Utiliza técnicas de compresión con pérdida para reducir el tamaño de los archivos PNG. Disminuye selectivamente el número de colores de la imagen, de esta forma se requieren menos bytes para almacenar los datos de la imagen. Además permite subir 20 archivos de una vez con un límite de tamaño de 3MB por archivo. 1.2 Planteamiento del problema Hoy en día nos encontramos con la llamada sociedad de la información donde las imágenes se han convertido en uno de los elementos importantes en la comunicación y por ende la mayoría de los mensajes que nos transmiten ya sea en, televisión, sitios web, redes sociales, etc. utilizan fundamentalmente la imagen. Una de las tareas más usuales es el envío de imágenes o fotografías por medio de las redes sociales ya sea para compartir con amigos, para utilizarlas en el perfil de alguna red social on-line así como para personalizar una página web. En la mayoría de los casos esta tarea se complica debido a que las fotos poseen un tamaño excesivo dificultando así el subirlas a la red. Existen varios programas dedicados a disminuir el peso de imágenes con el inconveniente que en algunos casos es necesario instalarlos en la PC ocupando demasiado espacio en el disco duro o en otros casos como ocurre en algunos sitios web se debe crear una cuenta para obtener mejores resultados en la compresión de imágenes. 5 (Pngquant.org) (Optipng.sourceforge.net) 7 (GitHub) 8 (Kornel.ski) 9 (Codedread.com) 10 (Martín J. , 2013) 11 (Quiñónez, 2014) 6 4 Es por esta razón que surge la necesidad de realizar una aplicación web gratuita que permita al usuario subir una imagen, y mediante el uso de una Librería de compresión de imágenes reducir el peso de las mismas. 1.3 Formulación del problema ¿Es posible mejorar la transmisión de una imagen implementando un algoritmo de compresión en la web que permita disminuir su peso? 1.4 Objetivos 1.4.1 Objetivo general Diseñar e implementar una aplicación web de compresión de imágenes para reducir el peso de las mismas. 1.4.2 Objetivos específicos  Analizar el funcionamiento de los algoritmos de compresión más importantes.  Implementar un algoritmo en la web que permita reducir el peso de imágenes.  Diseñar una interfaz de usuario que realice el proceso de compresión de imágenes. 1.5 Justificación En la actualidad, los sitios web y las redes sociales se están volviendo más visuales cada día. Las imágenes estimulan la participación de los usuarios, ya sea porque las comparten, las comentan o lo que es más importante, las recuerdan. En efecto, el uso de imágenes es fundamental. Con el fin de ofrecer un mejor rendimiento en la transmisión y almacenamiento de imágenes en diferentes sitios web o redes sociales, es necesario emplear técnicas de compresión de imágenes cuyo propósito es eliminar la redundancia visual. En otras palabras, la compresión de imágenes trata de disminuir el número de bits necesarios para representar una imagen y hacer que la transmisión sea más rápida. Este proyecto plantea el DESARROLLO DE UNA APLICACIÓN WEB PARA LA COMPRESIÓN DE IMÁGENES, que permita a los usuarios subir sus imágenes e internamente mediante técnicas de compresión se reduce el peso de las mismas 5 para posteriormente retornar una nueva imagen que a la percepción del ojo humano es igual que la imagen original pero con la diferencia que presenta un menor tamaño en el archivo. Es decir que las características de esta imagen serán lo más parecido posible a las de la imagen original. Adicionalmente el presente proyecto es de código abierto, el mismo que puede ser utilizado como una herramienta de consulta para los estudiantes de la carrera de COMPUTACIÓN GRÁFICA. 6 2. MARCO TEÓRICO 2.1 Compresión de imágenes12 La compresión de imágenes es un proceso que consiste en reducir la cantidad de datos necesarios para representar una imagen. Este proceso se realiza empleando algoritmos matemáticos que disminuyen el peso del archivo con la finalidad de que ocupe menos espacio en su almacenamiento y de igual manera se abrevia el tiempo para su posterior transmisión. Existen dos tipos de compresión de imágenes:  Compresión sin pérdida  Compresión con pérdida 2.1.1 Compresión sin pérdida Es una técnica que trata de agrupar los datos de una imagen que sean de igual valor o que tengan alguna característica en común de tal manera que se ocupa un menor espacio para su representación y se puedan recuperar de manera intacta los datos originales de la imagen sin que haya pérdida de información. Algunas de las técnicas que pertenecen a este grupo son:  RLE (Run Length Encoding)  LZW (Lempel Zib Welch) A continuación se describe cada una de las técnicas antes mencionadas: a) Compresión RLE13: Es uno de los métodos más antiguos y simples para compresión de datos, es muy útil en imágenes que contengan grandes áreas del mismo color. Este método disminuye el tamaño de una cadena de datos que se repite. Este algoritmo es de bastante utilidad en imágenes binarias o imágenes satelitales que poseen varias regiones con pocas gamas de color bien definidas. En la figura 2.1 se visualiza un ejemplo de la forma en que trabaja el algoritmo RLE sobre una imagen. 12 13 (Sánchez Menéndez, 2012) (Zanuy, 2000) 7 Recorrido por filas 0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 3 0 0 1 1 1 1 0 0 4 0 1 1 1 1 1 1 0 5 0 1 1 1 1 1 1 0 Contador 6 0 1 1 1 1 1 0 0 7 0 0 0 0 0 0 0 0 ( 8, 0) (4,0) (3,1) (1,0) (3,0) (4,1) (1,0) (2,0) (5,1) (1,0) (3,0) (4,1) (1,0) (3,0) (4,1) (1,0) (4,0) (2,1) (2,0) (8, 0) Elemento repetido Figura 2.1 Método de compresión RLE Para la implementación de la compresión RLE se debe seguir los siguientes pasos: 1) Recorrer la imagen píxel a píxel, para esto existen tres formas de recorrer una imagen: horizontal (por columnas), vertical (por filas) y en zigzag, como se visualiza en la figura 2.3. En el presente proyecto se utilizó el recorrido por columnas, es decir el recorrido horizontal. Figura 2.2 Tipos de recorrido de una matriz a) Recorrido por filas b) Recorrido por columnas d) Recorrido en zigzag (FileFormat.Info, 2015) 8 2) Emplear una estructura de datos (lista o arreglo) que permita almacenar los datos de la imagen. Esta estructura está conformada por dos componentes:  La primera componente se utiliza para contar el número de veces que se repite dicho elemento.  La segunda componente almacena el elemento que se repite de manera consecutiva Estos pasos se realizan en toda la imagen, recorriendo cada uno de los píxeles. Este método también es utilizado como parte del proceso de otros métodos de compresión como es el caso de la compresión JPEG, que se describe posteriormente en el apartado de la compresión con pérdida. b) Compresión LZW: Es un método de compresión sin pérdida, desarrollado por Terry Welch en 1984 y mejorado por Abraham Lempel y Jacob Ziv. Utilizado en formato de imágenes de tipo *.TIFF, *.GIF y *.PNG. “El algoritmo busca patrones repetidos en la imagen y los reemplaza por códigos de una tabla predefinida, asignando los códigos más cortos a los patrones o secuencias más repetidos al igual que el algoritmo de Huffman.“ (Sánchez Menéndez, 2012, p. 62) 2.1.2 Compresión con pérdida Esta técnica de compresión maneja algoritmos que eliminan cierta parte de la información de la imagen que puede ser imperceptible al ojo humano. Aplicando este proceso se consigue un alto grado de compresión pero con la desventaja que se pierden parte de los datos de la imagen y por ende no se puede reconstruir en forma exacta la imagen original. Entre las técnicas de compresión con pérdida tenemos:  Compresión Fractal  Compresión por Wavelets  JPEG(Joint Photographic Experts Group - Grupo Conjunto de Expertos en Fotografía) De las tres técnicas de compresión antes mencionadas, la compresión JPEG se implementó en el presente proyecto. 9 a) Compresión Fractal: Como su nombre lo indica está basado en fractales14. Es una técnica bastante útil en imágenes que contienen texturas. Este método asume que partes de la imagen se parecen a otras partes. Es decir que para aplicar este método se divide a la imagen en pequeños bloques, se toma uno de estos bloques como un patrón y se busca dentro de la imagen otro similar para luego reemplazarlo mediante una ecuación matemática. b) Compresión por Wavelets15: Utiliza la Transformada discreta de Wavelet. Esta transformada descompone a una imagen en un conjunto de imágenes pequeñas mediante la aplicación sucesiva de filtros pasa bajos y pasa altos. Dada una imagen se aplican dos filtros: un filtro pasa bajo y otro pasa alto obteniendo dos imágenes, seguidamente se diezma a cada una de las imágenes verticalmente eliminando la columna de la mitad de la imagen. Seguidamente se vuelve a aplicar los filtros en cada una de las imágenes y por último se diezma cada una de las cuatro imágenes pero horizontalmente. En la figura 2.3 y figura 2.4 se puede observar el proceso de descomposición por Wavelets, donde los cuadros de color rojo representan los filtros pasa alto y los azules representan los filtros pasa bajo. Imagen original Figura 2.3 Esquema de descomposición una imagen por Wavelets. 14 Fractal, es un objeto geométrico cuya estructura básica, fragmentada o irregular, se repite a diferentes escalas. (Mandelbrot) 15 (Fournier, Castro, Russo, & Bria) 10 Figura 2.4 a) Imagen Original, b) Descomposición de la imagen en wavelets. (What-when-how, 2016) c) Compresión JPEG: Es un estándar desarrollado conjuntamente por los comités ISO (International Standarization Organization) y CCITT (Comitte of the International Telephone & Telegraph). Pertenece a los algoritmos de compresión con pérdida, es decir que al descomprimir la imagen esta no tiene exactamente la misma calidad que la imagen original. “El algoritmo de compresión JPEG se basa en dos fenómenos visuales del ojo humano: uno es el hecho de que es mucho más sensible al cambio en la luminancia que en la crominancia; es decir, capta más claramente los cambios de brillo que de color. El otro es que nota con más facilidad pequeños cambios de brillo en zonas homogéneas que en zonas donde la variación es grande; por ejemplo en los bordes de los cuerpos de los objetos.” (Wikipedia, 2006) En la figura 2.5 se observa el proceso de compresión JPEG. Figura 2.5 Etapas del proceso de compresión JPEG 11 El proceso de compresión está dividido en las siguientes etapas: 1) Descomposición de la imagen en planos de color (RGB) Las imágenes digitales están representadas por tres matrices, donde cada una es la matriz correspondiente a cada plano de color (Rojo, Verde o Azul). “Desde el punto de vista del programador una imagen a color RGB es un arreglo de tamaño MxNx3, donde MxN define las dimensiones de los planos, mientras que la dimensión correspondiente a 3 define a cada uno de los ellos R, G y B.” (Cuevas, Zaldivar , & Perez, 2010) El modelo RGB es muy adecuado para representar imágenes en monitores de computadoras, cámaras digitales, escáneres, etc. Es un modelo de color básico, formado por la combinación de colores primarios: Rojo, Verde y Azul. En la figura 2.6 se puede apreciar las componentes de color de una imagen. Normalmente los valores de cada componente de color son enteros positivos que están en el intervalo [0,255] o en valores reales en el intervalo [0,1] Figura 2.6 Componentes de una imagen a color. 2) Cambiar el espacio de color de la imagen al espacio YCbCr16 El ojo humano es menos sensible a los matices de color que a la cantidad de luz percibida. Es por esta razón que es de mucha importancia convertir la imagen al espacio de color YCbCR ya que permite eliminar la información innecesaria de la imagen separando la intensidad de los colores de su tonalidad. En la figura 2.7 se observa la imagen en el espacio de color YCbCr y sus respectivas componentes de color. 16 (Cuevas, Zaldivar , & Perez, 2010) 12 Figura 2.7 Descomposición de planos del espacio de color YCBCR. El parámetro Y indica la Luminancia, es decir la imagen a escala de grises, se encuentra en el intervalo [0,255] y los parámetros Cb y Cr representan la Crominancia es decir la información con respecto al color: la componente Cb, es la diferencia entre la componente azul y un valor de referencia, y la componente Cr, es la diferencia entre la componente roja y un valor de referencia. Estas componentes están en el intervalo de [-128,127] con signo o [0,255] sin signo. Las ecuaciones para pasar del modelo RGB al modelo YCBCR son: ( 2.1 ) 𝑌(𝑥, 𝑦) = 𝑤𝑅 𝑅(𝑥, 𝑦) + (1 − 𝑤𝐵 − 𝑤𝑅 )𝐺(𝑥, 𝑦) + 𝑤𝐵 𝐵(𝑥, 𝑦) 0.5 (𝐵(𝑥, 𝑦) − 𝑌(𝑥, 𝑦)) 1 − 𝑤𝐵 0.5 𝐶𝑟 = (𝑅(𝑥, 𝑦) − 𝑌(𝑥, 𝑦)) 1 − 𝑤𝑅 𝐶𝑏 = Dónde:  𝑅(𝑥, 𝑦) es la componente de color rojo en la posición 𝑥, 𝑦  𝐺(𝑥, 𝑦) es la componente de color verde la posición 𝑥, 𝑦  𝐵(𝑥, 𝑦) es la componente de color azul en la posición 𝑥, 𝑦 En la ecuación 2.2 se describe el proceso inverso para pasar del modelo RGB a YCBCR. ( 2.2 ) 1 − 𝑤𝑅 𝐶𝑟 0.5 𝑤𝑅 (1 − 𝑤𝑏 ) 𝑤𝐺 (1 − 𝑤𝐺 ) 𝐺(𝑥, 𝑦) = 𝑌(𝑥, 𝑦) − 𝐶𝑏 − 𝐶 0.5(1 − 𝑤𝐵 − 𝑤𝑅 ) 0.5(1 − 𝑤𝐵 − 𝑤𝑅 ) 𝑟 𝑅(𝑥, 𝑦) = 𝑌(𝑥, 𝑦) + 𝐵(𝑥, 𝑦) = 𝑌(𝑥, 𝑦) + 1 − 𝑤𝐵 𝐶𝑏 0.5 Dónde:  𝑌(𝑥, 𝑦) es la componente de la luminancia en la posición x, 𝑦  𝐶𝑏 (𝑥, 𝑦) es la componente de color azul la posición 𝑥, 𝑦  𝐶𝑟 (𝑥, 𝑦) es la componente de color rojo en la posición 𝑥, 𝑦 13 Para la transformación de modelos de color la Unión Internacional de Telecomunicaciones (ITU) especifica los siguientes valores: 𝑤𝑅 = 0.299 𝑤𝐵 = 0.114 𝑤𝐺 = 0.587 Con los valores antes mencionados las matrices para la transformación de modelo RGB a YCBCR y YCBCR a RGB respectivamente son las siguientes: ( 2.3 ) 𝑌(𝑥, 𝑦) 0.299 0.587 0.114 𝑅(𝑥, 𝑦) [𝐶𝑏 (𝑥, 𝑦)] = [−0.169 −0.331 −0.500] [𝐺(𝑥, 𝑦)] 𝐶𝑟 (𝑥, 𝑦) 0.500 −0.419 −0.081 𝐵(𝑥, 𝑦) ( 2.4 ) 𝑅(𝑥, 𝑦) 𝑌(𝑥, 𝑦) 1.000 0.000 1.403 [𝐺(𝑥, 𝑦)] = [1.000 −0.344 −0.714] [𝐶𝑏 (𝑥, 𝑦)] 𝐵(𝑥, 𝑦) 1.000 1.773 0.000 𝐶𝑟 (𝑥, 𝑦) Los planos CbCr, de acuerdo a las transformaciones realizadas, pueden contener valores tanto positivos como negativos, por esta razón se añade un offset de 128 a los planos de color antes mencionados. Es decir la ecuación (2.1) quedaría expresada de la siguiente forma: ( 2.5 ) 𝑌(𝑥, 𝑦) = 𝑤𝑅 𝑅(𝑥, 𝑦) + (1 − 𝑤𝐵 − 𝑤𝑅 )𝐺(𝑥, 𝑦) + 𝑤𝐵 𝐵(𝑥, 𝑦) 0.5 (𝐵(𝑥, 𝑦) − 𝑌(𝑥, 𝑦)) + 𝟏𝟐𝟖 1 − 𝑤𝐵 0.5 𝐶𝑟 = (𝑅(𝑥, 𝑦) − 𝑌(𝑥, 𝑦)) + 𝟏𝟐𝟖 1 − 𝑤𝑅 𝐶𝑏 = 3) Generar bloques de 8x8 para el procesamiento. Antes de efectuar cualquier cálculo sobre la imagen, previamente se debe dividir a cada plano de imagen en submatrices de 8x8 píxeles, estas submatrices se denominan bloques. Para realizar este proceso se debe tener en cuenta que las dimensiones de la imagen, deben ser múltiplos de 8 tanto ancho como alto como se muestra en la figura 2.8, caso contrario se debe realizar un proceso adicional para completar la imagen tanto en filas como en columnas. 14 Figura 2.8 División de la imagen en bloques de 8x8 píxeles  Completar una imagen Este proceso se debe aplicar únicamente a las imágenes que no cumplan con el requisito de ser múltiplo de 8, en las dimensiones: ancho y alto. Los pasos a seguir son los siguientes:  En el ancho de la imagen, se debe agregar las columnas necesarias a la derecha de la imagen original hasta que su ancho sea múltiplo de 8. Estas columnas se llenarán con los mismos datos de la última columna.  De igual manera en el alto de la imagen se aumentan filas en la parte inferior de la imagen original, estas filas contendrán los datos de la última fila. En la figura 2.9 se puede observar que la parte sombreada representa una imagen de 10x13 píxeles. Dado que estas medidas no son múltiplos de 8 se procede a aumentar las filas y columnas respectivas. Figura 2.9 Completar filas y columnas de una imagen 15 4) Transformada discreta de Coseno17 (DCT) También llamada Transformada de Coseno es una transformada basada en la transformada discreta de Fourier (DFT) con la diferencia que solo trabaja con la parte real. Esta transformada es muy utilizada en la compresión de imágenes, aplicaciones de video, teleconferencias y televisión digital. La transformada de coseno principalmente se aplica en la compresión de imágenes JPEG, cuyo objetivo consiste en tomar los datos de la imagen (muestras de dominio espacial), procesarlos y convertirlos en una representación de dominio de frecuencias. Esta transformada trabaja con las frecuencias presentes en una imagen, estas son: las frecuencias bajas que representan el área más sensitiva al ojo humano, y las frecuencias altas que son menos sensibles al ojo. En la figura 2.10 se muestra como se distribuyen las frecuencias en una imagen. Altas frecuencias Bajas frecuencias Altas frecuencias Figura 2.10 Representación de las frecuencias de una imagen (SlideShare, 2016) Este proceso se aplica para cada uno de los componentes de la imagen y a su vez cada uno de los bloques 8x8. Para ello se multiplica cada píxel del bloque por términos que representan ondas de coseno, seguidamente se realiza una suma secuencial con el resultado del cálculo antes mencionado, obteniendo una nueva matriz con 64 elementos por cada bloque. Estos elementos se dividen en dos partes: el elemento de la esquina superior izquierda de la imagen esta la frecuencia más baja denominada DC o frecuencia cero y alrededor de este se dispersan los 63 coeficientes restantes que son las frecuencias altas denominadas AC. 17 (Esqueda Elizondo & Palafox Maestre, 2005) 16 En la figura 2.11, se muestra que la concentración de la energía se encuentra en la esquina superior izquierda de la imagen. Figura 2.11 Compactación de la energía DCT (Wikipedia, 2016) El proceso que realiza la DCT es de gran utilidad ya que ordena los coeficientes de la imagen de forma adecuada en frecuencias altas y bajas facilitando la eliminación de las frecuencias bajas que se realiza en el siguiente paso que es la Cuantización. La ecuación 2.6 define la DCT: ( 2.6 ) 𝐷𝐶𝑇(𝑢, 𝑣) = 𝑁−1 𝑁−1 (2𝑥 + 1)𝑢𝜋 (2𝑦 + 1)𝑣𝜋 𝐶𝑢 𝐶𝑣 ∑ ∑ 𝐼(𝑥, 𝑦) cos [ ] cos [ ] 2𝑁 2𝑁 √2𝑁 1 𝑥=0 𝑦=0 Dónde: 1 𝐶𝑢 , 𝐶𝑣 = {√2 1 𝑢, 𝑣 = 0 𝑜𝑡𝑟𝑜𝑠 𝑐𝑎𝑠𝑜𝑠 𝑢, 𝑣 = 0,1, … , 𝑁  𝐼(𝑥, 𝑦) representa los datos de la imagen en la fila (x) y columna (y)  𝑁 es el tamaño del bloque, en este caso N es 8 De igual forma para reconstruir la imagen se cuenta con la Transformada Inversa de Coseno que viene dada por la siguiente expresión matemática: ( 2.7 ) 17 𝐼(𝑥, 𝑦) = 𝑁−1 𝑁−1 (2𝑥 + 1)𝑢𝜋 (2𝑦 + 1)𝑣𝜋 𝐶𝑢 𝐶𝑣 ∑ ∑ 𝐷𝐶𝑇(𝑢, 𝑣) cos [ ] cos [ ] 2𝑁 2𝑁 √2𝑁 1 𝑥=0 𝑦=0 Dónde:  𝐷𝐶𝑇(𝑥, 𝑦) representa los datos de la transformada de coseno  𝑁 es el tamaño del bloque, en este caso de N es 8 5) Cuantización18 Es una técnica que se utiliza en la compresión de imágenes JPEG y se aplica luego de emplear la Transformada Discreta de Coseno. Este proceso también se aplica en matrices (bloques 8x8) resultantes de la DCT y divide cada componente de los bloques para cada componente de la matriz de cuantificación y se redondea a su entero más cercano. Las matrices de cuantificación estandarizadas para los diferentes planos de color se muestran en la tabla 2.1. 16 12 14 14 18 24 49 [72 11 12 13 17 22 35 64 92 10 14 16 22 37 55 78 95 24 40 16 26 58 19 24 40 57 29 51 87 56 68 109 64 81 104 87 103 121 98 112 100 17 51 61 18 60 55 24 69 56 47 80 62 99 103 77 99 113 92 99 120 101 [ ] 99 103 99 a) 18 21 26 66 99 99 99 99 24 26 56 99 99 99 99 99 47 66 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 80 99 99 99 99 b) Tabla 2.1 Matrices de Cuantización: a) Luminancia, b) Crominancia En resultado de este proceso elimina las componentes de altas frecuencias, es decir tienden a igualarse a cero, mientras que las demás componentes se reducen a números pequeños. 6) Recorrido en zigzag En este paso se construye un vector de 64 elementos para cada uno de los bloques anteriormente procesados. En cada bloque se hace un recorrido en forma de zigzag como se visualiza en la figura 2.12 y se obtiene un vector en cada bloque de la imagen. 18 (SlideShare, 2011) 18 99 99 99 99 99 99 99 99] Figura 2.12 Recorrido de un bloque en zigzag 7) Codificación RLE Utilizando el vector obtenido en el paso anterior, se procede a aplicar el método RLE (explicado en la sección compresión sin pérdida), se utiliza las misma lógica pero en vez de contar los elementos repetidos en este caso se cuentan los ceros que anteceden a determinado elemento distinto de cero. Los datos se almacenan de tal manera que se tiene una serie de pares (número de ceros que anteceden, valor distinto de cero). Utilizando el vector de la figura 2.12, se obtienen los pares de elementos mostrados en la siguiente figura. (0,5) (0,2) (0, -21) DC (0,-8) (5,-3) (54,0) AC Figura 2.13 Vector con pares, luego de aplicar RLE 8) Codificación de Huffman19 El objetivo de la Codificación de Huffman es reducir la cantidad de bits necesarios para representar los datos de los bloques anteriormente cuantificados. Para llevar a cabo esta codificación se utilizan las tablas estandarizadas que se detallan más adelante, donde determinado valor de cada uno de los bloques poseen una categoría determinada y una determinada representación en binario. Este proceso se ejecuta en dos partes: 19  Codificación para los coeficientes AC  Codificación para los coeficientes DC (Carrillo, 2002) 19 A continuación se presentan dos tablas que se utilizan para la codificación de coeficientes AC. La tabla 2.2 contiene la categoría y bits que se debe agregar a un determinado par de elementos. Categoría Bits adicionales 1 Valores incluidos en la categoría -1,1 2 -3,-2,2,3 00, 01, 10, 11 3 -7,…,-4,4,…,7 000,…,011,100,…111 4 -15,…,-8,8,…,15 0000,…,0111, 1000,…,1111 5 -31,…,-16,16,…,31 6 -63,…,-32,32,…,63 7 -127,…,-64,64,…,127 8 -255,…,-128,128,…,255 9 -511,…,-256,256,…,511 10 -1024,…,-512,512,… 0,1 Tabla 2.2 Categorías y bits adicionales para los coeficientes AC En la tabla 2.3, se muestra el contenido parcial de la codificación de Huffman. Donde la iniciales R/C, representan R: número de ceros que anteceden a determinado elemento y C: representa la categoría a la que pertenece. R/C EOB 0/1 0/2 0/3 0/4 0/5 … 1/1 1/2 1/3 1/4 1/5 … 2/1 Dimensión código 4 2 2 3 4 5 … 4 5 Código … 5 … 11100 20 1010 00 01 100 1011 11010 … 1100 11011 2/2 2/3 2/4 2/5 … 3/1 3/2 3/3 3/4 3/5 … 4/1 4/2 4/3 4/4 4/5 … 5/1 5/2 5/3 5/4 EOB 0/1 0/2 0/3 0/4 0/5 8 10 11111011 1111110111 … 6 9 12 … 111010 111110111 111111110101 … 6 10 16 … 1111011 1111111000 1111111110010110 … 7 11 16 … 1111010 11111110111 1111111110011110 4 2 2 3 4 5 1010 00 01 100 1011 11010 Tabla 2.3 Contenido parcial para la Codificación de Huffman.  Codificación de los coeficientes AC Teniendo en cuenta el par de elementos que se obtuvo en la compresión RLE, se realiza los siguientes pasos:  Se analiza el primer par AC, del cual se toma el elemento de la segunda componente, este valor se verifica a que intervalo de la segunda columna de la Tabla 2.2 pertenece; además se obtiene de la tercera columna el código que representa al mismo valor que en este caso lo llamaremos código1 y por último se obtienen los valores de R/C, R viene a ser el valor del primer elemento del par evaluado y C, es la categoría correspondiente al segundo elemento del par evaluado.  Utilizando los valores R/C, se verifica en la Tabla 2.3 el código que le corresponde, en este caso lo denominamos código2. 21  Por último se concatenan los códigos (código2 y código1) obtenidos anteriormente para formar una cadena de bits que representa el par evaluado. El proceso antes descrito se realiza en cada uno de los bloques de la imagen. Aplicando este proceso a los datos de la figura 2.13, se obtienen los siguientes resultados. Tabla 2.4 Ejemplo Codificación de Huffman para coeficientes AC  Codificación para los coeficientes DC Dado que los coeficientes DC representan el promedio de intensidad de cada bloque, son valores muy grandes. Por ende se debe realizar un proceso adicional para reducir dichos valores. Este proceso se denomina codificación DPCM20 (Differential Pulse Code Modulation – Codificación modulada de los pulsos diferenciales) que consiste en restar los valores DC de cada bloque, es decir se realiza una resta entre el valor DC del bloque actual y el valor DC del bloque anterior. Únicamente en el caso del primer bloque al valor DC se resta de cero, que nos da como resultado el mismo valor. Los valores obtenidos al realizar estas restas se almacenan en un vector, para posteriormente utilizar estos datos en la Codificación de Huffman de valores DC. Figura 2.14 Codificación DPCM en bloques de imagen. (Martín M. , 2004) 20 (Pap, 2005) 22 A continuación se muestran dos tablas: tabla 2.5 y tabla 2.6 que se utilizan para realizar la codificación de coeficientes DC. Categoría Bit adicionales 0 Valores incluidos en la categoría 0 1 -1,1 0,1 2 -3,-2,2,3 00, 01, 10, 11 3 -7,…,-4,4,…,7 000,…,011,100,…111 4 -15,…,-8,8,…,15 0000,…,0111, 1000,…,1111 5 -31,…,-16,16,…,31 6 -63,…,-32,32,…,63 7 -127,…,-64,64,…,127 8 -255,…,-128,128,…,255 9 -511,…,-256,256,…,511 10 -1024,…,-512,512,… ----- Tabla 2.5 Categorías y bits adicionales para los coeficientes DC Categoría Dimensión del código 0 2 Código 00 1 3 010 2 3 011 3 3 101 4 3 101 5 3 110 6 4 1110 7 5 111110 8 6 1111110 9 7 1111110 10 8 11111110 Tabla 2.6 Codificación de Huffman de coeficientes DC Empleando el vector obtenido al aplicar la codificación DPCM, se procede a calcular los respectivos Códigos de Huffman. Este proceso se realiza en forma similar a la codificación para coeficientes AC, empleando las Tablas 2.5 y 2.6. 23 Utilizando el ejemplo de la Figura 2.13 el valor DC es 5, asumiendo que este dato pertenece al primer bloque de la imagen. Su codificación sería: Segundo Código Código1 Categoría Código2 elemento completo (0,5) 5 101 3 101 101101 Par Tabla 2.7 Ejemplo de Codificación de coeficientes DC Finalmente se unen todos los códigos obtenidos en cada bloque es decir el código de los coeficientes AC con el código del coeficiente DC respectivamente de cada bloque. Del ejemplo antes expuesto y empleando las Tablas 2.4 y 2.7 que tiene la siguiente cadena de bits resultante. 101101 (0,5) 𝐶𝑜𝑒𝑓𝑖𝑐𝑖𝑒𝑛𝑡𝑒 𝐷𝐶 0110 1101001010 10110111 1111111011100 1010 (0, −8) (5, −3) (0,63) (0,2) (0, −21) 𝐶𝑜𝑒𝑓𝑖𝑐𝑖𝑒𝑛𝑡𝑒𝑠 𝐴𝐶 Figura 2.15 Código de Huffman de un bloque de imagen. 2.2 Descompresión El proceso de descompresión se utiliza para reconstruir la imagen. Esto se lleva a cabo empleando el mismo proceso que el de la compresión pero en forma inversa. Se parte desde el último proceso de compresión hasta llegar a obtener la imagen en el espacio de color RGB. 1) Recuperar los coeficientes cuantificados AC y DC Para recuperar estos coeficientes se utilizan las mismas tablas empleadas en la codificación de Huffman.  Se procede a realizar una búsqueda del código y para ello se toman los dos primeros bits de la cadena y se va agregando un bit hasta que la comparación sea exitosa.  Una vez que ya se haya encontrado el primer código, en nuestro caso lo llamamos código2 se determina el valor al que representa. 24  Con este valor se deduce la categoría a la que pertenece y la dimensión que tiene el código1, es decir con este dato ya se sabe cuántos bits se deben tomar en próximo recorrido. Este proceso se realiza hasta finalizar la cadena de bits, obteniendo así un vector con dos elementos. Por último en el caso de la componente DC además de encontrar el valor correspondiente se debe realizar una suma con los coeficientes DC empleado la lógica de la codificación DPCM. Se tiene como resultado un vector que en cada posición almacena un par de elementos. 2) Recorrido inverso en zigzag Utilizando el vector anterior, se procede a colocar cada uno de los datos en cada posición del bloque 8x8, realizando un recorrido en zigzag en cada uno de ellos hasta almacenar el último término. 3) Proceso Inverso de la Cuantificación A pesar de que el proceso de cuantificación es un proceso irreversible se puede recuperar una aproximación de los valores de la DCT. Para esto se realiza una multiplicación entre la matriz (bloque 8x8) obtenida anteriormente y una de las matriz de cuantificación estandarizadas correspondiente al plano de color que se esté procesando. 4) Proceso Inverso DTC Este proceso se realiza empleando la Ecuación 2.7 en cada uno de los bloques de la imagen. De esta forma se obtiene los valores de cada componente del espacio de color YCbCr. 5) Conversión al espacio de color RGB Por último solo resta pasar del espacio de color YCbCr al espacio de color RBG y para ello se utiliza la Ecuación 2.2. Finalmente se obtiene una nueva imagen en formato JPG que a percepción del ojo humano es similar a la imagen original, con la diferencia que esta nueva imagen posee un menor peso. Cabe aclarar que el formato JPEG o JPG es lo mismo, “... la diferencia está en que en algunos sistemas operativos solo aceptan tres letras de 25 extensión.” (García, 2006) . La extensión JPEG generalmente se utiliza en MAC y la extensión JPG se utiliza en Windows. 26 3. METODOLOGÍA El desarrollo de este proyecto se basa en la metodología de Pressman21 que se divide en 5 fases: a) Análisis de los requisitos del software: En esta etapa se define la funcionalidad de la aplicación, además las tecnologías y herramientas que son de utilidad para la implementación de la misma. b) Diseño: Se realizan diferentes tipos de diagramas para representar la navegación, estructura e interfaz de la aplicación. c) Generación de Código: Se refiere tanto a la parte de generación de los ambientes virtuales, como a la parte en la cual se añadirá comportamiento a estos ambientes. d) Prueba: Se evalúa la aplicación mediante pruebas reales tanto en la estructura como en la funcionalidad. e) Mantenimiento: El software indudablemente sufrirá cambios, y habrá que hacer algunas modificaciones a su funcionalidad. De estas fases, se descarta la última etapa debido a que no se ajusta completamente al proyecto planteado. A continuación de describe cada una de las etapas desarrolladas en el presente proyecto: 3.1 Análisis de los requisitos del software La aplicación web está diseñada para cargar una imagen, la cual se someterá al proceso de compresión imágenes, y pocos segundos después se retornará la imagen comprimida, es decir la interfaz mostrará la imagen original y la reconstruida. Las imágenes que se admiten deben tener las siguientes características:  Imágenes pequeñas (256x256) e imágenes medianas (800x500).  Formatos bmp, tiff, png, jpg, gif La aplicación web estará compuesta por tres páginas:  La primera, que contenga una breve introducción de la funcionalidad de la aplicación. 21 (Barrios, León, & Romero, 2016) 27  La segunda, una pantalla que permita cargar imágenes y poco después que retorne la imagen comprimida.  La tercera, que presente información acerca del desarrollo la aplicación. Además se debe tener en cuenta que para el desarrollo del proyecto se empleó una Portátil con las siguientes características:  Procesador 2.20Hz  Memoria RAM 8GB  Disco duro 1TB  Sistema operativo Windos7 En base a los requisitos anteriormente expuestos de utilizó Visual Studio 2013(versión estable), como entorno de desarrollo y ejecución. Visual Studio22: Es un entorno de desarrollo integrado (IDE), proporcionado por la compañía Microsoft. Es una herramienta multilenguaje ya que permite desarrollar en varios lenguajes como: C++, C#, Visual Basic .NET, etc., además de ASP .NET que está orientado al desarrollo web. Dispone de un conjunto de herramientas de programación para la generación de aplicaciones de escritorio, aplicaciones web, Servicios Web XML y aplicaciones móviles. Estas herramientas son las siguientes:  Editor de código fuente: Es un editor de texto que permite editar código fuente en un lenguaje determinado como: C++, C#, HTML, CSS o JavaScript, etc.  Un compilador: Convierte el código fuente en lenguaje de máquina.  Un depurador: Su función es probar y eliminar posibles errores en un programa en desarrollo.  Constructor de interfaz gráfica: Se utiliza para crear, diseñar y especificar la ubicación de los controles y otros elementos que permiten la interacción entre la aplicación y el usuario. El desarrollo del proyecto se dividió en dos partes:  Primero se implementó una librería que efectúa el proceso de compresión de imágenes basado en la técnica de compresión JPEG.  Segundo, se crea una interfaz de usuario que se adapte al proceso de compresión. 22 (Msdn.microsoft.com, 2016) 28 3.1.1 Librería de compresión Se utilizó como lenguaje de desarrollo a C Sharp(C#) junto con algunas librerías que permiten el manejo de imágenes digitales. a) C Sharp23 (C#): Es un lenguaje de programación creado por el danés Anders Hejlsberg y estandarizado por Microsoft como parte de la plataforma .NET. Está diseñado para crear aplicaciones de escritorio, aplicaciones web y móviles. Utiliza sintaxis que se deriva de C/ C++, lo que facilita la migración de código entre estos lenguajes. Posee las siguientes características:  Sencillo: Elimina elementos que otros lenguajes crean y no son necesarios.  Alto nivel: Es independiente de la arquitectura del ordenador. Es un lenguaje muy similar al lenguaje natural, esto quiere decir que para ejecutar un programa un compilador se encarga de convertirlo en lenguaje de máquina.  Orientado a objetos: Permiten estructurar programas de una forma más ordenada, para ello utiliza objetos, compuestos por atributos y métodos propios de cada clase. Además cuenta con características de encapsulación, herencia y polimorfismo.  Administración de memoria: Es muy útil ya que gracias a esta característica los programas pueden liberar memoria de forma automática, es decir que no es necesario crear destructores de objetos.  Compatible: Facilita la migración a otros lenguajes como: C, C++ y Java ya que tienen una sintaxis muy similar. b) System.Drawing24: Permite el manejo de imágenes mediante las clases Bitmap y Color. Es decir se puede acceder a los atributos de una imagen como son: su tamaño y la información que está contenida en cada píxel de la imagen. - Clase Bitmap: Esta clase permite manipular imágenes. Para inicializar un constructor de tipo Bitmap, que se requiere como parámetro de entrada la ruta de la imagen. 23 24 (C Sharp - EcuRed, 2016) (Besteiro & Rodríguez ) 29 Bitmap img = new Bitmap(@"C:\Users\dell\Documents \IMAGENES\img1.jpg"); - Clase Color25: Se utiliza para acceder a la información del color en cada píxel de la imagen. La estructura Color está representada por un color de tipo ARGB (Alpha, Red, Green, Blue), donde:  A representa la componente de la opacidad  R representa la componente de color rojo  G representa la componente de color verde  B representa la componente de color azul Cada uno de los colores anteriores está en el intervalo de 0 a 255. Para manipular los datos de la imagen se tienen los siguientes métodos GetPixel, se utiliza para obtener los datos de la imagen en una determinada posición. Color pixelColor = img.GetPixel(x, y); SetPixel, se utiliza para modificar los datos de la imagen en una determinada posición. Color nuevoColor = Color.FromArgb(30, 0, 0); img.SetPixel(x, y, nuevoColor); c) System.Collections.Generic: Esta librería es usada para trabajar con estructuras de datos, en este proyecto se utilizó la estructura List. - List26: Es una estructura dinámica en la que se puede ir agregando o quitando elementos. Estos elementos pueden ser agregados al principio, al final o en la mitad de una lista. Proporciona métodos para buscar, ordenar y manipular elementos de la lista. El acceso a los elementos de una lista se lo hace mediante el uso de un índice. En el presente proyecto se utilizaron listas para la implementación del método de compresión RLE, a continuación se describe un ejemplo:  Inicializar una estructura de tipo List List elementos = new List(); Tipo de dato 25 26 (Msdn.microsoft, 2016) (Nachocabanes.com, 2010) 30  Agregar elementos a la lista Point datos = new Point(); datos.X = cont; datos.Y = aux1; elementos.Add(datos); 3.1.2 Aplicación web En el desarrollo de la interfaz de la Aplicación web se utilizaron las siguientes herramientas: a) ASP.NET27: Es una tecnología que permite crear páginas web dinámicas que se ejecutan en el servidor. El servidor que utiliza es IIS (Internet Information Service) que viene incorporado en el Sistema operativo de Windows y se comunica con la capa cliente utilizando el protocolo HTTP. Características de Asp.net:  Facilita la realización de tareas comunes como envío de formularios y la autenticación del cliente.  Está conformado por Web Forms que permiten separar la interfaz de usuario de la funcionalidad de la aplicación.  Gestión automática de memoria con recolección de basura.  Es multilenguaje ya que para desarrollar aplicaciones puede emplear cualquier lenguaje de programación admitido por la plataforma .NET.  Para mejorar el rendimiento de las aplicaciones compila el código solo la primera vez que algún cliente lo solicite y así el resto de peticiones del mismo se atenderán de forma más ágil. En el presente proyecto, la interfaz de usuario se diseñó mediante formularios, Web Forms que reemplazan a las páginas de tipo HTML. Además se utilizaron las siguientes librerías:  System.Drawing.Imaging: Se utiliza para para establecer el tipo de formato de una imagen.  System.IO: Esta librería se utiliza para el manejo de archivos, es decir permite crear, mover o almacenar archivos en una ruta determinada. En este caso para almacenar las imágenes que son subidas al servidor. 27 (Guérin, 2014) 31 De igual forma se utilizaron las siguientes tecnologías para la estructura de la Aplicación Web: b) JavaScript28: Es un lenguaje de programación interpretado, multiplataforma y orientado a objetos, utilizado para el desarrollo de aplicaciones web, tanto en la parte del cliente como en la del servidor. Este lenguaje permite dar funcionalidad a los objetos dentro de la aplicación o sitos web. Es dinámico ya que responde a eventos que son producidos por el usuario en tiempo real. Estos eventos pueden ser presionar un botón, validación de formularios, etc. c) CSS29: Se conoce como hojas de estilo en cascada. Es una tecnología que permite controlar el diseño y la estética de un sitio o aplicación web. Permite dar formato a la página web, por ejemplo modificar estilos como: el tipo, tamaño y color de la fuente, establecer márgenes, color de fondo de la página, interlineados de párrafo, etc. Estos estilos se pueden incorporar de la siguiente forma:  CSS in line, es decir insertar el estilo CSS directamente dentro de la etiqueta HTML

párrafo

 Hoja de estilos interna, significa agregar el estilo CSS dentro del mismo archivo HTML, pero empleando etiquetas  Hojas de estilo externas, es decir crear un archivo aparte guardado con la extensión .CSS. Este archivo se debe importar en el encabezado de la página donde se va a utilizar los estilos incorporados en la hoja de estilo. En el presente proyecto se utiliza la última opción, es decir Hojas de estilo externas, esto ayuda a tener por separado el lado estético de la Web y de esta forma la estructura de la aplicación está mejor organizada. 28 29 (Berzal, Cortijo, & Cubero) (Barcia, 2003) 32 d) HTML530: Es una versión de HTML que conjuntamente con las tecnologías CSS y JavaScript permite la creación de sitios y aplicaciones web. Incorpora nuevos elementos multimedia como audio, video que pueden ser incrustados de forma más sencilla, simplemente empleando las etiquetas y respectivamente. Es decir que para visualizar un video ya no es necesario instalar el plugin de adobe flash player, simplemente basta con disponer de un navegador compatible con HTML5. Además otra etiqueta destacada es el que permite crear un área de dibujo rectangular donde se puede dibujar líneas, rectángulos, etc; también manipular imágenes y crear animaciones mediante la programación en JavaScript. En este proyecto de utilizó la etiqueta input de type="file", que permite la entrada y previsualización de archivos como imágenes y texto. Estos archivos pueden ser seleccionados de forma individual o múltiple. En este caso particular se empleó para subir imágenes de forma individual. A continuación se muestra la etiqueta con sus respectivas características: e) AJAX31: Javascript y XML Asíncrono, es una técnica de JavaScript que se emplea para intercambiar información entre un servidor y el cliente sin necesidad de recargar la página. Ajax es bastante útil en páginas que manejan gran cantidad de datos o a su vez que son usadas por un buen número de personas. Utiliza los siguientes parámetros:  type: se especifica el tipo de petición GET o POST  url: se edita el nombre de la página a la que van a ser enviados los datos.  data: se especifica la información que será enviada al servidor en forma de una cadena de texto, es decir un dato de tipo String.  succes: Este evento se ejecuta en caso de que la petición se ha realizado con éxito. Esta técnica se utilizó para subir imágenes del cliente al servidor y a su vez para retornar la imagen comprimida al cliente. 30 31 (Exp3rto, 2014) (LIBROSWEB) 33 Para alojar la aplicación web, se empleó el servidor descrito a continuación: f) IIS32 (Internet Information Server): Es un conjunto de servicios web que hacen que un ordenador se convierta en un servidor web. Este servidor web viene por defecto en el paquete de Windows 7 profesional y se emplea para la creación, hospedaje, configuración y administración de sitios y aplicaciones web. Los principales servicios de IIS son:  FTP: Permite transferir archivos en una arquitectura cliente servidor, es decir que los usuarios pueden subir o a su vez descargar archivos del lado del servidor.  SMTP: Permite intercambiar mensajes de correo electrónico entre los ordenadores.  NNTP: Protocolo de transferencia de noticias en la red, como su nombre lo indica permite la lectura y publicación de noticias.  HTTP: Protocolo de transferencia de hipertexto. Este protocolo permite el intercambio de información hipertextual (enlaces) de las páginas web. 32 (Scribd, 2016) 34 3.2 Diseño En esta etapa se realizaron diferentes diagramas para representar la estructura y el funcionamiento de la Aplicación Web desarrollada. INICIO Leer imagen Mostrar imagen en pantalla Proceso compresión Proceso descompresión Mostrar imagen comprimida FIN Figura 3.1 Diagrama de flujo de la aplicación. 3.2.1 Diagrama de clases para la Librería desarrollada a) En la siguiente figura se puede observar el proceso completo para realizar la compresión JPEG, además como están relacionadas cada una de las clases. 35 Figura 3.2 Diagrama de clases Librería de compresión de imágenes, método JPEG. b) Se parte de una clase Imagen, la cual permite obtener el alto, ancho y los datos de las diferentes componentes de la imagen, mismos que se utiliza en la clase CompresionJPEG. Figura 3.3 Relación entre las clases: Imagen y CompresionJPEG c) Las clases: Bloque y MatrizBloque realizan la mayor parte de los cálculos de la compresión. 36 Figura 3.4 Diagrama de clases: Bloque y MatrizBloque 3.2.2 Diagrama para la Aplicación Web En un principio la aplicación cuenta con una página principal, y tres subpáginas como se visualiza en el siguiente esquema: Página principal Descripción Aplicación Documentación compresión Figura 3.5 Esquema de aplicación web a) Página principal, está conformada por cuatro botones que permiten acceder a los formularios Descripción, Aplicación y Documentación. b) Descripción, esta página contiene información acerca de la Aplicación desarrollada. 37 c) Aplicación, este formulario es el más importante ya que contiene la implementación de la Librería desarrollada. d) Documentación, presenta una breve descripción de las clases más importantes de la Librería y tiene un botón que permite descargar el proyecto completo. Para la implementación de la Aplicación Web se creó en un proyecto en ASP.NET, el cual está conformado por cinco formularios como se visualiza en la figura 3.7. Figura 3.6 Diagrama de clases de la Aplicación Web 38 3.3 Generación de código En esta etapa se desarrollaron diferentes clases y métodos para la creación de la Librería de compresión de imágenes y la Aplicación Web. A continuación se describen los más importantes: 3.3.1 Librería de compresión de imágenes a) Clase Imagen: Esta clase tiene como atributos tres variables de tipo matriz que son los planos de color de la imagen: r (rojo), g (verde), b (azul), adicionalmente ancho y alto que representan las dimensiones de la imagen respectivamente. Esta clase cuenta con los siguientes métodos:  ObtenerPlanos(Bitmap imagen): Recibe como parámetro de entrada un Bitmap. Este método se utiliza para descomponer la imagen sus componentes de color: Rojo, Verde y Azul.  ReconstruirImagen (double [,,]matImg): Permite reconstruir una imagen a partir de uan matriz que tiene tres componetes, es decir los canales de color:rojo, verde y azul.  ConvertiRGBaYCBCR(): Este método permite la conversión del espacio de color RGB al espacio de color YCBCR.  ConvertirYCBCRaRGB(): Realiza el proceso inverso del anterior método. b) Clase Bloque: En esta clase es donde se realiza la mayor parte de los cálculos de la compresión JPEG. Para ello define una matriz de 8x8 denominado bloque y sobre el cual se realizan las siguientes métodos:  TDC(), ITDC(): Se utilizan para calcular la Transformada de Coseno y su inversa en un bloque dado.  Cuantizar(), InvCuantizar(): Permite calcular la cuantificación y su inversa respectivamente de un determinado bloque. Para ello utiliza las matrices estandarizadas que son Luminancia y Crominancia para cada componente de color respectivamente.  RecorrerZigZag(): Recorre los datos de un bloque en forma de zigzag y de vuelta retorna un vector con 64 elementos. 39 c) Clase MatrizBloque: Esta clase hereda la mayoría de los métodos de la clase Bloque y se utiliza para realizar los cálculos sobre toda la imagen. d) Clase CompresionJPEG: Esta clase emplea los métodos de la clase MatrizBloque para realizar el proceso de compresión. Consta de un constructor que recibe como parámetro de entrada un Bitmap.  CompresionJPEG(Bitmap Imagen): Este constructor internamente realiza el procesamiento de la imagen que fue subida al servidor y para ello emplea los siguientes métodos:  CompresionImagen(Imagen img): Permite realizar la compresión de la imagen y requiere como parámetro de entrada un objeto de tipo Imagen, posteriormente retorna una matriz con tres componentes.  DescompresionImagen(double [,,] imgCompress): Recibe los datos de la imagen comprimida y procede a realizar el proceso inverso para poder mostrar la imagen en pantalla. 3.3.2 Aplicación Web La mayor parte del desarrollo de la Aplicación Web se encuentra en el formulario de nombre Aplicación. En este formulario está compuesto por dos botones, uno que permite subir la imagen y otro que se usa para descargar la imagen una vez que se haya realizado el proceso de compresión. Para subir la imagen al servidor, se empleó un Controlador Genérico más conocido como Handler que permite obtener y enviar datos entre cliente y servidor utilizando la tecnología AJAX. En la clase Handler, denominada SubirArchivo, se recibe y envían los datos de la imagen mediante el método ProcessRequest(HttpContext context). Para ello emplea los siguientes objetos:  Request, permite el acceso a toda la información que pasa desde el navegador del cliente al servidor.  Response, permite enviar datos al cliente como respuesta a una petición realizada. A continuación se muestra como se utilizaron los objetos en el presente proyecto. Para obtener los datos de la imagen que sube el cliente al servidor: 40 context.Request["Image"]; De igual forma para enviar los datos de la imagen al cliente se utiliza el siguiente código. context.Response.Write(base64); donde Image representa los datos de la imagen codificados en Base64. Este dato se procede a decodificar con los métodos que se describen a continuación:  Base64ToBitmap(String Base64), este método recibe como parámetro de entrada un String de tipo Base64, y procede a convertirlo en un Bitmap.  BitmapToBase64(Bitmap imagen), realiza el proceso inverso del anterior método, es decir a partir de un Bitmap se retorna un String de tipo Base64. Para enviar la imagen del lado del cliente se utiliza un archivo JavaScript, denominado aplicacion.js, en el que se utilizó la técnica AJAX, de la siguiente forma: Variable que se recibe en el Handler var Img = { Image: datos_img, Nombre: file.name }; $.ajax({ url: 'SubirArchivo.ashx', Nombre de la página a la que se envían los datos type: 'POST', data: Img, Datos a enviar success: function (data) { img_compress.src = 'data:image/jpg;base64,'+data;//ASIGNA LA CADENA BASE64 AL LA IMAGEN_COMPRIMIDA alert("LA IMAGEN HA SIDO CARGADA EXITOSAMENTE"); }, error: function(){alert("ERROR AL INTENTAR SUBIR LA IMAGEN. VUELA A INTENTAR")} }); Evento que se ejecuta luego que la solicitud ha sido satisfactoria 41 4. PRUEBAS Y RESULTADOS En este capítulo se describen las pruebas realizadas para verificar el funcionamiento de la Librería y Aplicación Web desarrollada. En primer lugar se obtuvieron imágenes de diferentes páginas web que publican Bases de datos (Dataset) de imágenes que no presentan ningún preprocesamiento. A continuación se presenta una lista con las fuentes antes mencionadas:  Imágenes .TIFF G. Schaefer and M. Stich (2004) "UCID - An Uncompressed Colour Image Database", Proc. SPIE, Storage and Retrieval Methods and Applications for Multimedia 2004, pp. 472-480, San Jose, USA. Esta página la podemos encontrar en el siguiente link: http://homepages.lboro.ac.uk/~cogs/datasets/ucid/ucid.html  Imágenes .PNG V. Christlein, C. Riess, J. Jordan, C. Riess, E. Angelopoulou: "An Evaluation of Popular Copy-Move Forgery Detection Approaches", IEEE Transactions on Information Forensics and Security, vol. 7, no. 6, pp. 1841-1854, 2012. Se puede tener acceso a las imágenes desde la siguiente dirección web: https://www5.cs.fau.de/research/data/imagemanipulation/  Imágenes .GIF BINARIAS, .TIFF ESCALA DE GRISES ImageProcessingPlace.com, para tener acceso a las imágenes visitar la dirección web: http://www.imageprocessingplace.com/root_files_V3/image_databases.ht m  Imágenes .JPG Herve Jegou, Matthijs Douze and Cordelia Schmid "Hamming Embedding and Weak geometry consistency for large scale image search" Proceedings of the 10th European conference on Computer vision, October, 2008. http://lear.inrialpes.fr/~jegou/data.php 42 Revisar el siguiente link: Por otra parte para determinar el nivel de compresión y calidad de las imágenes se realizó un estudio de métricas de calidad. A continuación se describe cada una de ellas: 1. Ratio de Compresión: Es la relación que existe entre el tamaño de la imagen original y la comprimida, es decir: (4.1) 𝐶𝑟 = 𝑛1 𝑛2 Dónde:  𝑛1 representa el tamaño original de la imagen  𝑛2 representa el tamaño de la imagen comprimida 2. Porcentaje de Compresión: Determina el nivel de redundancia de datos en porcentaje. % = (𝟏 − 1 ) ∗ 𝟏𝟎𝟎 𝐶𝑟 3. Medidas de calidad objetivas33: Se basa en las siguientes métricas:  MSE (Mean Squared Error - Error Medio Cuadrático)  PSNR (Peak Signal-to-Noise Ratio - Relación Señal a Ruido de Pico)  SSIM (Structural Similarity – Índice de Similitud Estructural) a) MSE: Determina la cantidad de error que existe entre la señal de una imagen reconstruida respecto a la señal original, es decir mientras más bajo sea el valor, el error será menor. Se obtiene calculando la diferencia entre los píxeles de la imagen original y los píxeles de la imagen reconstruida de acuerdo a la siguiente expresión matemática. (4.2) 𝑀𝑆𝐸 = ′ 2 ∑𝑚,𝑛 𝑥,𝑦=0(𝐼(𝑥, 𝑦) − 𝐼 (𝑥, 𝑦)) 𝑚𝑥𝑛 Dónde:  𝐼(𝑥, 𝑦) representa los datos de la imagen original en la posición 𝑥, 𝑦  𝐼 ′ (𝑥, 𝑦) representa los datos la imagen reconstruida en la posición 𝑥, 𝑦 33 (Cabezas González, 2012) 43  𝑚 representa la dimensión de ancho de la imagen  𝑛 representa la dimensión de alto de la imagen. En una imagen RGB, el valor del MSE se calcula por cada plano de imagen y posteriormente se realiza un promedio de los tres valores. b) PSNR: Es una medida de estimación de calidad de una imagen, toma en cuenta la imagen reconstruida y su original. Generalmente este valor oscila entre 20 y 40 dB (decibelios). Un valor de PSNR alto puede representar buena calidad aunque no siempre se cumple esta condición. Esta medida se calcula en base al MSE, de acuerdo a la siguiente ecuación:: (4.3) 255 𝑃𝑆𝑁𝑅 = 20 log10 ( ) √𝑀𝑆𝐸 c) SSIM: Nace con la intención de crear una medida que se asemeje al sistema de percepción visual humano, fue creada por Zhou Wang en 2004. Esta medida se calcula solo tomando en cuenta los planos de luminancia, debido a la poca información estructural contenida en los planos de diferencia de color. Además, hay que tener en cuenta que este proceso se lo realiza por bloques de 8x8, y posteriormente se realiza una media aritmética entre los valores obtenidos en cada bloque. De acuerdo a la siguiente ecuación: (4.4) 𝑆𝑆𝐼𝑀(𝑥, 𝑦) = (2𝜇𝑥 𝜇𝑦 + 𝑐1)(2𝜎𝑥𝑦 + 𝑐2) (𝜇𝑥2 + 𝜇𝑦2 + 𝑐1)(𝜎𝑥2 + 𝜎𝑦2 + 𝑐2) Dónde:  x representa la imagen original  y representa la imagen reconstruida  𝜇𝑥 , 𝜇𝑦 son la media aritmética de x e y respectivamente  𝜎𝑥2 , 𝜎𝑦2 son la varianza de x e y respectivamente.  𝜎𝑥𝑦 es la covarianza entre x e y.  𝑐1 = (0.01𝑥𝑀𝐴𝑋)2 y 𝑐2 = (0.03𝑥𝑀𝐴𝑋)2  𝑀𝐴𝑋, es el valor máximo que puede tomar cada píxel, en este caso 255. 44 Los valores de SSIM están en el intervalo [0, 1], es decir cuanto más cercanos estén a 1, habrá menor distorsión estructural entre las dos imágenes (buena calidad). PRUEBA 1 Partiendo de los datos anteriormente expuestos, se procedió a seleccionar 10 imágenes por cada formato de imagen, conformado 5 grupos entre los cuales están:  GRUPO 1. Imágenes a color, formato TIFF  GRUPO 2. Imágenes a color, formato PNG  GRUPO 3. Imágenes a color , formato JPG  GRUPO 4. Imágenes binarias, formato GIF  GRUPO 5. Imágenes escala de grises, formato TIFF De estos grupos se obtuvieron los siguientes datos:  Nombre de la imagen  Tamaño de la imagen original  Dimensiones: Ancho y Alto  Tamaño de la imagen comprimida  Ratio de compresión  Medias de calidad: MSE, PSNR, SSIM A continuación se muestra las pruebas que se realizaron en los distintos grupos de imagen. GRUPO 1. Imágenes a color, formato TIFF Figura 4.1 Prueba de imágenes formato TIFF 45 Las pruebas con imágenes de formato TIFF se realizaron en el navegador Internet Explorer, versión 11. Tabla 4.1 Resultado de compresión de imágenes TIF GRUPO 2. Imágenes a color, formato PNG Figura 4.2 Prueba de imágenes formato PNG Tabla 4.2 Resultado de compresión de imágenes PNG 46 GRUPO 3. Imágenes a color, formato JPG Figura 4.3 Resultado de compresión de imágenes JPG Tabla 4.3 Resultado de compresión de imágenes JPG GRUPO 4. Imágenes binarias, formato GIF Figura 4.4 Prueba de imágenes binarias formato GIF 47 Tabla 4.4 Resultado de compresión de imágenes binarias GIF GRUPO 5. Imágenes a escala de grises, formato TIFF Figura 4.5 Prueba de imágenes escala de grises formato TIFF Tabla 4.5 Resultado de compresión de imágenes a escala de gris TIF Hay que tener en cuenta que las imágenes a prueba presentan dimensiones inferiores a 1600x1200. 48 En la siguiente tabla se muestran los resultados promedio obtenidos al analizar cada grupo de imagen. TIPO_IMG RATIO_COMPRESIÓN COMPRESIÓN (%) MSE PSNR SSIM TIFF 24.23 95.67 106.14 28.42 0.8938 PNG 18.25 94.08 65.76 30.73 0.8803 JPG 5.02 78.46 60.35 31.30 0.8911 GIF 0.31 46.85 62.68 30.94 0.7694 TIFF_GRIS 16.67 92.05 62.36 31.06 0.7637 Tabla 4.6 Medidas de calidad de cada formato de imagen Utilizando la anterior tabla se realizó gráficos estadísticos que facilitaron la presentación de los resultados. 1. Ratio de Compresión: En el gráfico se observa que hay una alta compresión en las imágenes de formato TIFF, seguidas por las de formato PNG. En imágenes de formato JPG también se puede apreciar cierto nivel de compresión, a pesar de que es bajo, pero existe compresión. El inconveniente es en imágenes binarias de formato GIF, en las que el nivel de compresión no supera el 0.5. Es decir que en este caso las imágenes aumentaron de tamaño al realizar la compresión. (Ver Anexo B, Grupo 4.) RATIO_COMPRESIÓN 30,00 25,00 20,00 15,00 10,00 5,00 0,00 TIFF PNG JPG GIF TIFF_GRIS Figura 4.6 Gráfico comparativo del ratio de compresión. 49 2. Porcentaje de Compresión: En el grafico 4.7, se muestra en que las imágenes de formato TIFF, se alcanza una compresión de 95%, mientras que en imágenes JPG, se tiene un porcentaje de 78%. % COMPRESIÓN 120,00 100,00 80,00 60,00 40,00 20,00 0,00 TIFF PNG JPG GIF TIFF_GRIS Figura 4.7 Porcentaje de compresión 3. MSE: Se puede apreciar que hay un alto error medio en imágenes a color de formato TIFF, mientras que en los demás formatos el error medio se encuentra en el intervalo [62, 65]. MSE 120,00 100,00 80,00 60,00 40,00 20,00 0,00 TIFF PNG JPG Figura 4.8 Error Medio Cuadrático 50 GIF TIFF_GRIS 4. PNSR: Si bien esta medida no presenta correlación con el sistema visual humano. Se observa que las imágenes JPG existe alta calidad, los demás grupos de imágenes se encuentran en el intervalo de [30, 31], excepto las imágenes a color TIFF, que son las que más baja calidad presentan. PSNR 32,00 31,50 31,00 30,50 30,00 29,50 29,00 28,50 28,00 27,50 27,00 26,50 TIFF PNG JPG GIF TIFF_GRIS Figura 4.9 Relación señal ruido 5. SSIM: Asumiendo que esta medida se asemeja a la percepción visual humana, se comprueba que al aplicar la compresión JPEG en imágenes a color de formato TIFF, PNG y JPG, existe una alta calidad, ya que los valores obtenidos se asemejan a 0.9. Mientras que en imágenes binarias GIF y escala de grises TIF los valores oscilan entre 0.75 y 0.77 SSIM 0,9500 0,9000 0,8500 0,8000 0,7500 0,7000 0,6500 TIFF PNG JPG GIF Figura 4.10 Medida de calidad estructural 51 TIFF_GRIS Haciendo una síntesis de los resultados obtenidos, se tiene:  Las imágenes que presentan un alto nivel compresión son las imágenes de formato TIFF por lo tanto su nivel de error medio cuadrático también es alto, sin embargo tomando en cuenta el valor del SSIM, se verifica que las imágenes comprimidas tienen una buena calidad.  Las imágenes PNG, presentan alto nivel de compresión, un error medio bajo y en base a medida de calidad SSIM está cercana a 0.9 es decir buena calidad.  En imágenes JPG, hay bajo nivel de compresión, bajo error medio y una calidad buena de acuerdo al SSIM.  En imágenes binarias se aprecia que el ratio de compresión es bastante bajo debido a que en estas imágenes en vez de disminuir el tamaño del archivo, tiende a aumentar, y por el mismo hecho el valor de calidad SSIM está sobre el 0.7.  Por último, en imágenes a escala de grises tienen un alto nivel de compresión y en cuanto a calidad presentan un valor superior a 0.7. PRUEBA 2 Esta prueba consiste en comparar el tamaño de compresión de imágenes que se obtiene en las herramientas: Paint34, Photoshop y la aplicación web desarrollada (FotoCompressApp). Para esto se generó cinco imágenes en Paint que contienen figuras geométricas como: rectángulos, círculos, cuadrados, etc, mismas que son de formato: bmp, tif, gif, png y jpg. A continuación se muestran las pruebas efectuadas en la aplicación FotoCompressApp: 34 Paint, es un programa que permite dibujar, colorear, generar y modificar imágenes. 52 IMAGEN BMP Figura 4.11 Compresión de una imagen de formato BMP IMAGEN TIF Figura 4.12 Compresión de una imagen de formato TIFF 53 IMAGEN GIF Figura 4.13 Compresión de una imagen de formato GIF IMAGEN PNG Figura 4.14 Compresión de una imagen de formato PNG 54 IMAGENJPG Figura 4.15 Compresión de una imagen de formato JPG En la tabla 4.7 se muestran los resultados obtenidos al efectuar la compresión de imágenes en tres herramientas. Tabla 4.7 Compresión de imágenes utilizando diferentes herramientas TAMAÑO DE COMPRESIÓN 35,00 30,00 25,00 20,00 PAINT 15,00 PHOTOSHOP 10,00 FOTOCOMPRESSAPP 5,00 0,00 bmp tif gif png jpg FORMATO DE IMAGEN Figura 4.16 Comparativo de compresión de imágenes 55 De la tabla 4.7, se tiene que la imagen de formato GIF aumenta el tamaño del archivo al comprimirla en herramientas como: Paint y Photoshop, mientras que al utilizar la presente aplicación se reduce el tamaño del archivo de 10.40 KB a 7.20 KB. La imagen de formato TIFF aumenta el tamaño al comprimir el archivo en las tres herramientas, sin embargo en la aplicación FotoCompressApp se incrementa en menor proporción. En la figura 4.16 se observa que la aplicación que reduce en su mayoría el tamaño de archivo de imágenes es FotoCompressApp, seguido de Photoshop y por último Paint. 56 5. CONCLUSIONES  De acuerdo al análisis de las técnicas de compresión, se optó por utilizar el algoritmo de compresión JPEG, ya que permite reducir significativamente el tamaño de archivos de imágenes, con una pérdida de calidad mínima. Esto se puede apreciar en los resultados obtenidos en la métrica de calidad SSIM, donde se tiene valores superiores a 0.7 y dado que el límite es 1, se considera que hay buena calidad en la imagen.  El algoritmo de compresión JPEG implementado en la web alcanza altos niveles de compresión, en imágenes JPG se tiene valores cercanos al 78%, mientras que para otros formatos como TIFF y PNG alcanza un porcentaje cercano al 90%.  La librería desarrollada permite realizar el proceso de compresión de imágenes, a través de una aplicación web sencilla y amigable donde el usuario puede reducir el peso de imágenes de forma interactiva.  La compresión JPEG, no es aplicable para imágenes binarias en formato GIF, puesto que al comprimir este tipo de imágenes el tamaño del archivo aumentó; esto se debe a que una imagen binaria solo está compuesta una matriz de ceros y unos, pero al aplicar el algoritmo JPEG se debe manejar la imagen en sus tres canales de color, es decir que se aumenta información y por ende el tamaño del archivo aumenta.  A pesar de que las imágenes en formato JPG ya presentan un nivel de compresión, también se les puede aplicar la técnica de compresión JPEG, haciendo que esta ocupe menos espacio en el disco. El inconveniente es que cuanto más veces se aplique la compresión, mayor es la perdida de detalle de la imagen original.  Después de realizar una comparación de la compresión de imágenes entre Paint, Photoshop y FotoCompressorApp, se concluye que FotoCompressorApp tiene la ventaja de realizar una mayor reducción en el peso de imágenes.  JPEG es un algoritmo de compresión simétrico ya que emplea el mismo tiempo en comprimir y descomprimir una imagen. 57  La compresión de imágenes JPEG mejora velocidad de transmisión de imágenes debido a la gran reducción en el tamaño de los archivos, permitiendo de esta forma disminuir el tiempo de transmisión.  El presente proyecto sirve como una guía para dar inicio a nuevas líneas de investigación en el campo de la compresión de imágenes en áreas como: la medicina, electrónica, etc. 58 6. RECOMENDACIONES  Se recomienda optimizar la librería de compresión JPEG, de manera que se reduzca el tiempo de procesamiento de las imágenes subidas y a su vez se admita imágenes con un tamaño de archivo superior a 1600x1200.  Se recomienda emplear otro algoritmo de compresión para imágenes binarias.  Para cargar imágenes en formato TIFF, se recomienda utilizar el navegador Internet Explorer a partir de la versión 10, ya que es el único navegador que soporta este tipo de formato de imagen.  Debido a la inmensa información digital que se maneja a diario es recomendable utilizar técnicas de compresión que permitan reducir los archivos ya sea para almacenarlos o enviarlos a otro medio con el fin de mejorar la velocidad de transmisión.  La compresión JPEG es bastante útil en medios digitales, ya que reduce el tiempo de carga de sitios web y redes sociales, pero en medios de impresión no es muy recomendable hacer uso de esta compresión y en el caso de hacerlo, solo efectuarlo una vez, debido a que es una técnica de compresión con pérdida de información y no se garantiza la correcta visualización de las imágenes sobre el papel una vez impresas. 59 BIBLIOGRAFÍA 1. Alejandro, G. E. (2013). Implementación del Algoritmo RLC (Run Length Code) para compresión y descompresión aplicado a datos provenientes de imágenes telemétricas. Escuela Politécnica Nacional, Quito. 2. Barcia, D. (2003). Maestros del Web. Obtenido de http://www.maestrosdelweb.com/introcss/ 3. Barrios, C. E., León, J., & Romero, Y. (2016). METODOLOGÍA DE PRESSMAN - 2DA PARTE. Obtenido de SistemInformacII: http://sisteminformacii.wikispaces.com/METODOLOG%C3%8DA+DE+PR ESSMAN+-+2DA+PARTE 4. Berzal, F., Cortijo, F. J., & Cubero, J. C. (s.f.). Desarrollo Profesional de Aplicaciones Web con ASP.NET. 5. Besteiro, M., & Rodríguez , M. (s.f.). Recuperado el 05 de abril de 2016, de http://www.ehu.eus/mrodriguez/archivos/csharppdf/WinForms/GDI.pdf 6. Cabezas González, J. (Septiembre de 2012). Recuperado el 31 de Mayo de 2016, de http://oa.upm.es/14048/1/PFC_JAVIER_CABEZAS_GONZALEZ.pdf 7. Carrillo, I. M. (19 de febrero de 2002). Recuperado el 16 de noviembre de 2015, de http://clusterfie.epn.edu.ec/ibernal/html/CURSOS/OCTUBRE04/CICC200 4/Jpeg.PDF 8. Codedread.com. (s.f.). Codedread.com. Recuperado el 22 de Mayo de 2016, de http://www.codedread.com/scour/ 9. Cuevas, E., Zaldivar , D., & Perez, M. (2010). Procesamiento digital de imágenes con MATLAB y Simulink (Primera ed.). Madrid, España: RAMA. 10. Ecured.cu. (2016). Recuperado el 01 de Mayo de 2016, de http://www.ecured.cu/C_Sharp 11. Elvex.ugr.es. (01 de Mayo de 2016). Elvex.ugr.es. Obtenido de http://elvex.ugr.es/decsai/csharp/dotnet/index.xml 12. Es.slideshare.net. (2016). Es.slideshare.net. Recuperado el 02 de Mayo de 2016, de http://es.slideshare.net/dixzan/tecnologia-microsoft-net 60 13. Esqueda Elizondo, J. J., & Palafox Maestre, L. E. (2005). Fundamentos para el procesamiento de imágenes. Baja California, México: Universidad Autónoma de Baja California. 14. Exp3rto. (2014). Exp3rto. Recuperado el 15 de Abril de 2016, de http://www.exp3rto.com/introduccion-a-html5-capacidades-caracteristicasy-recursos/ 15. F, M. (28 de Mayo de 2014). GENBETA. Obtenido de http://www.genbeta.com/imagen-digital/compressor-io-servicio-decompresion-y-optimizacion-de-imagenes-gratuito-a-fondo 16. Ferreira Escutia, R. (s.f.). Atributos de aplicaciones basadas en WEB. Obtenido de http://www.xumarhu.net/isw_1_1_atributos_de_aplicaciones_basadas_en _web.pdf 17. FileFormat.Info. (Junio de 2015). Recuperado el 16 de Enero de 2016, de http://www.fileformat.info/mirror/egff/ch09_03.htm 18. Fournier, N., Castro, G., Russo, C., & Bria, O. (s.f.). Recuperado el 23 de Mayo de 2016, de http://sedici.unlp.edu.ar/bitstream/handle/10915/23906/Documento_compl eto.pdf?sequence=1 19. García, N. S. (2006). Aplicación de las TIC a la docencia. Vigo: Ideaspropias Editorial. 20. GitHub. (s.f.). GitHub. Recuperado el 22 de Mayo de 2016, de https://github.com/tjko/jpegoptim 21. Gonzalez, R. C., & Woods, R. E. (2002). Digital Image Processing. Upper Saddle River, New Jersey 07458: Prentice Hall. 22. Google Code . (2016). Google Code . Recuperado el 30 de Enero de 2016, de https://code.google.com/archive/p/jpeg-compressor/ 23. Guérin, B.-A. (2014). ASP.NET en C# con Visual Studio 2013 (Vol. 1 st). Barcelona: Ediciones ENI. 24. Kornel.ski. (s.f.). Kornel.ski. Recuperado el 22 de Mayo de 2016, de https://kornel.ski/lossygif 25. LIBROSWEB. (s.f.). LIBROSWEB. Recuperado el 25 de Mayo de 2016, de http://librosweb.es/libro/fundamentos_jquery/capitulo_7/metodos_ajax_de _jquery.html 26. Luján Mora, S. (2002). Programación de aplicaciones web: historia, principios básicos y . San Vicente (Alicante): Club Universitario. 61 27. Mandelbrot, B. (s.f.). La Geometría Fractal de la Naturaleza. Tusquets. 28. Martín, J. (4 de octubre de 2013). CheckApps. Recuperado el 19 de noviembre de 2015, de http://www.checkapps.net/2013/10/10herramientas-online-optimizar-imagenes-web.html 29. Martín, M. (4 de mayo de 2004). Obtenido de http://lmi.bwh.harvard.edu/papers/pdfs/2003/martinfernandezCOURSE03c.pdf 30. Martínez Giménez, F., Peris Manguillot, A., & Ródenas Escribá, F. (2004). Tratamiento de señales digitales mediante wavelets y su uso con Matlab. Editorial Club Universitario. 31. Menendez, F. J. (2009). Georreferenciación de Cartografia: Datos Raster y Vectoriales (Vol. Volumen 4 de Cartografia Magazine). EOSGIS SL. 32. Msdn.microsoft. (2016). Msdn.microsoft. Recuperado el 19 de Abril de 2016, de https://msdn.microsoft.com/eses/library/system.drawing.color(v=vs.110).aspx 33. Msdn.microsoft.com. (2016). Recuperado el 19 de Abril de 2016, de https://msdn.microsoft.com/eses/library/system.drawing.color(v=vs.110).aspx 34. Msdn.microsoft.com. (2016). Msdn.microsoft.com. Recuperado el 30 de Abril de 2016, de https://msdn.microsoft.com/eses/library/fx6bk1f4(v=vs.100).aspx 35. Nachocabanes.com. (16 de Abril de 2010). Nachocabanes. Recuperado el 05 de Mayo de 2016, de http://www.nachocabanes.com/csharp/curso/csharp08b.php 36. Olivé, M. S. (2008). Algoritmo de compresión de imágenes de alta resolución sin pérdidas. Intituto Politécnico Nacional, México. 37. Optipng.sourceforge.net. (s.f.). Optipng.sourceforge.net. Recuperado el 22 de Mayo de 2016, de http://optipng.sourceforge.net/ 38. Owlnet.rice.edu. (2014). Owlnet.rice.edu. Recuperado el 15 de Diciembre de 2015, de http://www.owlnet.rice.edu/~elec539/Projects99/JAMK/proj1/ 39. Pap, F. M. (01 de Abril de 2005). Recuperado el 20 de Mayo de 2016 40. Pngquant.org. (s.f.). Pngquant.org. Recuperado el 22 de Mayo de 2016, de https://pngquant.org/ 41. Quiñónez, J. D. (26 de mayo de 2014). wwwhat´s new. Recuperado el 19 de noviembre de 2015, de http://wwwhatsnew.com/2014/05/26/reducirpeso-imagen-sin-perder-calidad/ 62 42. Sánchez Menéndez, F. (2012). Georreferenciación de Cartografia (Vol. 1 st). EOSGIS SL. 43. Scribd. (2016). Obtenido de https://es.xdoc.com/doc/27519905/Servidores-Web 44. Sisternas, M. A. (2014). Aplicación gráfica para la compresión de información multimedia. 45. SlideShare. (10 de enero de 2011). SlideShare. Obtenido de http://es.slideshare.net/Amedio/cuantificacin-digital 46. SlideShare. (2016). SlideShare. Recuperado el 23 de Mayo de 2016, de http://es.slideshare.net/ddocampo/tema2-4360428 47. Vilet, J. R. (2005). Procesamiento digital de Imágenes. Área de Computación e Informática UASLP. 48. What-when-how. (2016). What-when-how. Recuperado el 22 de Mayo de 2016, de http://what-when-how.com/embedded-image-processing-on-thetms320c6000-dsp/mathematical-preliminaries-image-processing-part-1/ 49. Wikipedia. (16 de marzo de 2006). Wikipedia. Recuperado el 02 de abril de 2016, de https://es.wikipedia.org/wiki/Joint_Photographic_Experts_Group 50. Wikipedia. (06 de Febrero de 2016). Recuperado el 22 de Marzo de 2016, de https://es.wikipedia.org/wiki/Transformada_de_coseno_discreta 51. Yañez Durán, C., Pro Concepción, L., & La Serna, N. (s.f.). Recuperado el 29 de marzo de 2016, de http://sisbib.unmsm.edu.pe/BibVirtual/publicaciones/risi/2009_n1/v6n1/a0 4v6n1.pdf 52. Zanuy, M. F. (2000). Tratamiento digital de voz e imagen (Vol. 1 st). (M. B. Editores, Ed.) Barcelona. 63 ANEXOS ANEXO A Código fuente ANEXO B Manual de usuario 64 ANEXO A Código Fuente 1. Librería LibImageCompress CLASE IMAGEN using using using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Threading.Tasks; System.Drawing; System.Drawing.Imaging; System.IO; namespace LibImageCompress { public class Imagen { //ATRIBUTOS private int ancho;//DIMENSIÓN DEL ANCHO DE LA IMAGEN private int alto;//DIMENSIÓN DEL ALTO DE LA IMAGEN private double[,] r, g, b;//COMPONENTES DE LA IMAGEN POR SEPARADO RED, GREEN, BLUE //CONSTRUCTOR POR DEFECTO public Imagen() { } //CONSTRUCTOR CON PARÁMETROS public Imagen(Bitmap bitmap) { ancho = bitmap.Width; alto = bitmap.Height; //inicializar las variables r = new double[ancho, alto]; g = new double[ancho, alto]; b = new double[ancho, alto]; ObtenerDatos(bitmap); } //CONSTRUCTOR2 CON PARÁMETROS public Imagen(double[, ,] datosImg) { ancho = datosImg.GetLength(0); alto = datosImg.GetLength(1); r = new double[ancho, alto]; g = new double[ancho, alto]; b = new double[ancho, alto]; for (int i = 0; i < ancho; i++) { for (int j = 0; j < alto; j++) { r[i, j] = datosImg[i, j, 0]; COMPONENTE DE COLOR ROJO I //DATOS DE LA g[i, j] = datosImg[i, j, 1]; COMPONENTE DE COLOR VERDE b[i, j] = datosImg[i, j, 2]; COMPONENTE DE COLOR AZUL //DATOS DE LA //DATOS DE LA } } //**************************** PROPIEDADES **************// public double[,] R { get { return r; } set { r = value; } } public double[,] G { get { return g; } set { g = value; } } public double[,] B { get { return b; } set { b = value; } } public int Ancho { get { return ancho; } set { ancho = value; } } public int Alto { get { return alto; } set { alto = value; } } //**************************** MÉTODOS **********************// private void ObtenerDatos(Bitmap bm) { Color color = new Color(); for (int j = 0; j < bm.Height; j++) { for (int i = 0; i < bm.Width; i++) { color = bm.GetPixel(i, j); r[i, j] = color.R; //DATOS DE LA COMPONENTE DE COLOR ROJO g[i, j] = color.G; //DATOS DE LA COMPONENTE DE COLOR VERDE b[i, j] = color.B; //DATOS DE LA COMPONENTE DE COLOR AZUL } } } //MÉTODO QUE PErMITE rECONSTrUIr UNA IMÁgEN A PArTIr DE UNA MATrIZ DE TrES COMPONENTES DE COLOr public Bitmap ReconstruirImagen(double[, ,] matImg) { Bitmap nuevaIm = new Bitmap(ancho, alto);//CrEA UN bITMAP AUXILIAr PArA AgrEgAr LOS DATOS II Color color = new Color(); int r, g, b; for (int i = 0; i < ancho; i++) { for (int j = 0; j < alto; j++) { r = (int)matImg[i, j, 0]; g = (int)matImg[i, j, 1]; b = (int)matImg[i, j, 2]; r = VerificaValor(r); g = VerificaValor(g); b = VerificaValor(b); color = Color.FromArgb(r, g, b); nuevaIm.SetPixel(i, j, color); } } return nuevaIm; } //VErIFICA QUE LOS DATOS DE UNA IMAgEN ESTEN EN EL INTErVALO [0,255] private int VerificaValor(int dato) { int vaux = 0; if (dato > 255) vaux = 255; else if (dato < 0) vaux = 0; else vaux = dato; return vaux; } //CAMBIA EL ESPACIO DE COLOR DE UNA IMAGEN DE RGB AL ESPACIO YCBCR public double[, ,] ConvertiRGBaYCBCR() { double wr = 0.299, wg = 0.587, wb = 0.114; double[,] red, green, blue; //OBTIENE LOS DATOS DE LOS TRES CANALES DE COLOR(ROJO, VERDE Y AZUL) red = R; green = G; blue = B; double[, ,] ycbcr = new double[ancho, alto, 3];//INICIALIZA LA MATRIZ RESULTANTE double cal1 = 1 - wb - wr; double cal2 = 0.5 / (1 - wb); double cal3 = 0.5 / (1 - wr); for (int i = 0; i < ancho; i++) { for (int j = 0; j < alto; j++) { ycbcr[i, j, 0] = wr * red[i, j] + cal1 * green[i, j] + wb * blue[i, j]; ycbcr[i, j, 1] = cal2 * (blue[i, j] - ycbcr[i, j, 0]) + 128; ycbcr[i, j, 2] = cal3 * (red[i, j] - ycbcr[i, j, 0]) + 128; III } } return ycbcr; } //CONVIErTE UNA public double[, { double[, ,] double wr = double double double double cal1 cal2 cal3 cal4 IMAgEN EN ESPACIO YCbCr EN EL ESPACIO rgb ,] ConvertirYCBCRaRGB() rgb = new double[ancho, alto, 3]; 0.299, wg = 0.587, wb = 0.114; = = = = (1 - wr) / 0.5; 1 - wb; 1 - wb - wr; 1 - wg; for (int i = 0; i < ancho; i++) { for (int j = 0; j < alto; j++) { rgb[i, j, 0] = r[i, j] + cal1 * (b[i, COMPONENETE DE COLOr rOJO rgb[i, j, 2] = r[i, j] + (cal2 / 0.5) 128); // COMPONENTE DE COLOr AZUL rgb[i, j, 1] = r[i, j] - (wb * cal2 * + wg * cal4 * (b[i, j] - 128)) / (0.5 cal3);//COMPONENTE DE COLOr VErDE } } return rgb; j] - 128); // * (g[i, j] (g[i, j] - 128) * } //rESTA 128 A LA MATrIZ DE ESPACIO DE COLOr YCbCr public double[, ,] Resta() { double[, ,] resultado = new double[ancho, alto, 3]; for (int i = 0; i < ancho; i++) { for (int j = 0; j < alto; j++) { resultado[i, j, 0] = r[i, j] - 128; resultado[i, j, 1] = g[i, j] - 128; resultado[i, j, 2] = b[i, j] - 128; } } return resultado; } //rEALIZA LA SUMA ENTrE UNA MATrIZ Y UN ESCALAr(128) public double[, ,] Suma() { double[, ,] resultado = new double[ancho, alto, 3];//MATrIZ rESULTANTE for (int i = 0; i < ancho; i++) { for (int j = 0; j < alto; j++) { IV resultado[i, j, 0] = r[i, j] + 128; resultado[i, j, 1] = g[i, j] + 128; resultado[i, j, 2] = b[i, j] + 128; } } return resultado; } //COMPLETA CON FILAS Y COLUMNAS A UNA MATrIZ PArA QUE SEA MULTIPLO DE 8 public double[, ,] CompletarMatriz(double[, ,] matImagen) { int f = matImagen.GetLength(0); int c = matImagen.GetLength(1); int filas_aum = 0, col_aum = 0; if (Multiplo8(f)) { filas_aum = 8 - (f % 8); } if (Multiplo8(c)) { col_aum = 8 - (c % 8); } double[, ,] nueva = new double[f + filas_aum, c + col_aum, 3]; LLenarMatriz(matImagen, nueva); nueva = CompletarFilas(matImagen, nueva); nueva = CompletarColumnas(matImagen, nueva); return nueva; } //VErIFICA SI SE DEbE AgrEgAr FILAS O COLUMNAS A UNA MATrIZ PArA QUE SEA MULTIPLO DE 8 private int VerificaMultiplo8(int dimension) { return dimension % 8; } // private bool Multiplo8(int dimension) { if (VerificaMultiplo8(dimension) == 0) { return false; } return true; } //LLENA private { int int UNA MATrIZ CON LOS DATOS DE OTrA MATrIZ ANTErIOr void LLenarMatriz(double[, ,] datos, double[, ,] nueva) f = datos.GetLength(0); c = datos.GetLength(1); for (int i = 0; i < { for (int j = 0; { nueva[i, j, nueva[i, j, nueva[i, j, } } f; i++) j < c; j++) 0] = datos[i, j, 0]; 1] = datos[i, j, 1]; 2] = datos[i, j, 2]; } V //COMPLETA LAS FILAS DE UNA MATrIZ QUE NO ES DIVIbLE PArA 8 //public int[,] CompletarFilas(int[,] mat, int num_filas) private double[, ,] CompletarFilas(double[, ,] mat, double[, ,] nueva) { int f = mat.GetLength(0); int fnueva = nueva.GetLength(0);//DIMENSIÓN ANCHO NUEVA MATrIZ int cnueva = nueva.GetLength(1);//DIMENSIÓN ALTO NUEVA MATrIZ //AgrEgA FILAS A UNA MATrIZ PArA QUE EL ANCHO SEA DIVIbLE PArA 8 for (int i = f; i < fnueva; i++) { for (int j = 0; j < cnueva; j++) { nueva[i, j, 0] = nueva[f - 1, j, 0]; nueva[i, j, 1] = nueva[f - 1, j, 1]; nueva[i, j, 2] = nueva[f - 1, j, 2]; } } return nueva; } //COMPLETA LAS COLUMNAS DE UNA MATrIZ QUE NO ES DIVIbLE PArA 8 //public int[,] CompletarColumnas(int[,] mat, int num_col) private double[, ,] CompletarColumnas(double[, ,] mat, double[, ,] nueva) { int c = mat.GetLength(1);//DIMENSIÓN ALTO MATrIZ int fnueva = nueva.GetLength(0);//DIMENSIÓN ANCHO NUEVA MATrIZ int cnueva = nueva.GetLength(1);//DIMENSIÓN ALTO NUEVA MATrIZ for (int i = 0; i < { for (int j = c; { nueva[i, j, nueva[i, j, nueva[i, j, } } return nueva; fnueva; i++) j < cnueva; j++) 0] = nueva[i, c - 1, 0]; 1] = nueva[i, c - 1, 1]; 2] = nueva[i, c - 1, 2]; } } } CLASE BLOQUE using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Threading.Tasks; System.Drawing; namespace LibImageCompress { VI public class Bloque { //VARIABLES DE LA CLASE private double[, ,] datos; //CONSTRUCTOR POR DEFECTO public Bloque() { datos = new double[8, 8, 3]; } //CONSTRUCTOR CREA UN BLOQUE (MATRIZ 8X8) DADO UNA MATRIZ public Bloque(double[, ,] bloque8x8) { int m = bloque8x8.GetLength(0); int n = bloque8x8.GetLength(1); if ((m == 8) && (n == 8)) datos = bloque8x8; else Console.Write("Solo se admite matrices de 8x8"); } //CONSTRUCTOR CON PARÁMETROS //INGRESA UN VALOR EN LA MATRIZ DE DATOS EN LA POSCIÓN I, J public Bloque(double r, double g, double b, int i, int j) { datos[i, j, 0] = r; datos[i, j, 1] = g; datos[i, j, 2] = b; } //PROPIEDADES DE LA CLASE public double[, ,] Datos { get { return datos; } set { datos = value; } } //*********************************MÉTODOS*****************************// //PERMITE VISUALIZAR LOS DATOS DE LA MATRIZ public void ImprimeMatriz() { for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { Console.Write(Datos[i, j, 0] + " "); Console.Write(Datos[i, j, 1] + " "); Console.Write(Datos[i, j, 2] + " "); } Console.WriteLine(); } } //CALCULA LA TRANSFORMADA DISCRETA DE COSENO EN UN BLOQUE 8X8 public Bloque TDC() { double auxR = 0, auxG = 0, auxB = 0; double Cu, Cv; const double PI = Math.PI; const double r = 16; double val_raiz = 1 / (Math.Sqrt(2)); double[, ,] resultado = new double[8, 8, 3];//MATRIZ RESULTANTE for (int u = 0; u < 8; u++) { for (int v = 0; v < 8; v++) VII { auxR = 0; auxG = 0; auxB = 0; if (u == Cu = else Cu = if (v == Cv = else Cv = 0) val_raiz; 1; 0) val_raiz; 1; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { auxR += (Math.Cos(((2 * i + 1) * u * PI) / r)) * (Math.Cos(((2 * j + 1) * v * PI) / r)) * datos[i, j, 0]; auxG += (Math.Cos(((2 * i + 1) * u * PI) / r)) * (Math.Cos(((2 * j + 1) * v * PI) / r)) * datos[i, j, 1]; auxB += (Math.Cos(((2 * i + 1) * u * PI) / r)) * (Math.Cos(((2 * j + 1) * v * PI) / r)) * datos[i, j, 2]; } } auxR *= (1 / Math.Sqrt(r)) * Cu * Cv; auxG *= (1 / Math.Sqrt(r)) * Cu * Cv; auxB *= (1 / Math.Sqrt(r)) * Cu * Cv; resultado[u, v, 0] = auxR; resultado[u, v, 1] = auxG; resultado[u, v, 2] = auxB; } } Bloque tc = new Bloque(resultado); return tc; } //CALCULA LA TRANSFORMADA INVERSA DE COSENO EN UN BLOQUE 8X8 public Bloque ITDC() { double auxR = 0, auxG = 0, auxB = 0; double Cu, Cv; const double PI = Math.PI; const double r = 16; double val_raiz = 1 / (Math.Sqrt(2)); double[, ,] resultado = new double[8, 8, 3];//MATRIZ RESULTANTE for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { auxR = 0; auxG = 0; auxB = 0; for (int u = 0; u < 8; u++) { for (int v = 0; v < 8; v++) { if (u == 0) Cu = val_raiz; else Cu = 1; if (v == 0) Cv = val_raiz; else Cv = 1; VIII auxR += Cu * Cv * datos[u, v, (Math.Cos(((2 * i + 1) * u * PI) / (Math.Cos(((2 * j + 1) * v * PI) / r)); auxG += Cu * Cv * datos[u, v, (Math.Cos(((2 * i + 1) * u * PI) / (Math.Cos(((2 * j + 1) * v * PI) / r)); auxB += Cu * Cv * datos[u, v, (Math.Cos(((2 * i + 1) * u * PI) / (Math.Cos(((2 * j + 1) * v * PI) / r)); 0] * r)) * 1] * r)) * 2] * r)) * } } auxR *= (1 / Math.Sqrt(r)); auxG *= (1 / Math.Sqrt(r)); auxB *= (1 / Math.Sqrt(r)); resultado[i, j, 0] = auxR; resultado[i, j, 1] = auxG; resultado[i, j, 2] = auxB; } } Bloque tc = new Bloque(resultado); return tc; } //REALIZA EL PROCESO DE CUANTIZACIÓN DE UNA MATRIZ LUEGO DE APLICAR LA TDC public Bloque Cuantizar() { double[,] quan = new double[8, 8]; double[,] maqlumi = new double[,]{{16,11 ,10, 16, 24, 40, 51, 61},{12, 12, 14, 19, 26, 58, 60, 55}, {14, 13, 16, 24, 40, 57, 69, 56},{14, 17, 22, 29, 51, 87, 80, 52}, {18, 22, 37, 56, 68, 109, 103, 77},{24, 35, 55, 64, 81, 104, 113, 92}, {49, 64, 78, 87, 103, 121, 120, 101},{72, 92, 95, 98, 112, 100, 103, 99}}; double[,] maqcrom = new double[,]{{17, 18, 24, 47, 99, 99, 99, 99},{18, 21, 26, 66, 99, 99, 99, 99}, {24, 26, 56, 99, 99, 99, 99, 99},{47, 66, 99, 99, 99, 99, 99, 99}, {99, 99, 99, 99, 99, 99, 99 ,99},{99, 99, 99, 99, 99, 99, 99 ,99}, {99, 99, 99, 99, 99, 99, 99 ,99},{99, 99, 99, 99, 99, 99, 99 ,99}}; /*if (tipo == 1) { quan = maqlumi; } else { quan = maqcrom; }*/ Bloque bloq = new Bloque(Division(datos, maqlumi, maqcrom)); return bloq; } //REALIZA EL PROCESO DE INVERSO DE LA CUANTIZACIÓN DE UNA MATRIZ public Bloque InvCuantizar() { double[,] quan = new double[8, 8]; double[,] maqlumi = new double[,]{{16,11 ,10, 16, 24, 40, 51, 61},{12, 12, 14, 19, 26, 58, 60, 55}, {14, 13, 16, 24, 40, 57, 69, 56},{14, 17, 22, 29, 51, 87, 80, 52}, {18, 22, 37, 56, 68, 109, 103, 77},{24, 35, 55, 64, 81, 104, 113, 92}, {49, 64, 78, 87, 103, 121, 120, 101},{72, 92, 95, 98, 112, 100, 103, 99}}; double[,] maqcrom = new double[,]{{17, 18, 24, 47, 99, 99, 99, 99},{18, 21, 26, 66, 99, 99, 99, 99}, {24, 26, 56, 99, 99, 99, 99, 99},{47, 66, 99, 99, 99, 99, 99, 99}, IX {99, 99, 99, 99, 99, 99, 99 ,99},{99, 99, 99, 99, 99, 99, 99 ,99}, {99, 99, 99, 99, 99, 99, 99 ,99},{99, 99, 99, 99, 99, 99, 99 ,99}}; Bloque bloq = new Bloque(Producto(datos, maqlumi, maqcrom)); return bloq; } public double[,] RecorrerZigZag() { int f = 8;//DIMENSIÓN DEL ANCHO DE UNA MATRIZ int c = 8;//DIMENSIÓN DEL ALTO DE UNA MATRIZ double[,] vec = new double[f * c, 3];//ALMACENA LOS DATOS DE UNA MATRIZ EN FORMA DE VECTOR int pos = -1;//RECORRE LAS POSICIONES DE UN VECTOR for (int i = 0; i < f * c; i++) { for (int j = 0; j < f; j++) { for (int k = 0; k < c; k++) { if ((j + k) == i) { pos++; if ((i % 2) == 0) { vec[pos, 0] = datos[k, i vec[pos, 1] = datos[k, i vec[pos, 2] = datos[k, i } else { vec[pos, 0] = datos[i - k, vec[pos, 1] = datos[k, i vec[pos, 2] = datos[k, i } k, 0]; k, 1]; k, 2]; k, 0]; k, 1]; k, 2]; } } } } return vec; } public Bloque InvRecorrerZigZag(double[,] vec) { int f = 8;//DIMENSIÓN DEL ANCHO DE UNA MATRIZ int c = 8;//DIMENSIÓN DEL ALTO DE UNA MATRIZ int pos = -1;//RECORRE LAS POSICIONES DE UN VECTOR for (int i = 0; i < f * c; i++) { for (int j = 0; j < f; j++) { for (int k = 0; k < c; k++) { if ((j + k) == i) { pos++; if ((i % 2) == 0) { datos[k, i - k, 0] = vec[pos, 0]; datos[k, i - k, 1] = vec[pos, 1]; datos[k, i - k, 2] = vec[pos, 2]; } X else { datos[i - k, k, 0] = vec[pos, 0]; datos[k, i - k, 1] = vec[pos, 1]; datos[k, i - k, 2] = vec[pos, 2]; } } } } } Bloque bloq = new Bloque(datos); return bloq; } //REALIZA LA COMPRESIÓN RLE EN UN BLOQUE /* public void CompRLE(double [,] zigzag) { int contR = 0, contG = 0, contB = 0;//CUENTA EL NÚMERO DE CEROS EN SECUENCIA int dimzz = zigzag.GetLength(0);//DIMENSIÓN DEL VECTOR List elementos = new List();//GUARDA LOS DATOS EN UNA LISTA return elementos; }*/ //REALIZA LA COMPRESIÓN RLE INVERSA public void InvCompRLE() { } //CALCULA LA DIVISIÓN DE DOS MATRICES COMPONENTE A COMPONENTE //LAS MATRICES A Y B DEBEN SER DE LA MISMA DIMENSIÓN public double[, ,] Division(double[, ,] A, double[,] double[,] C) { int f = A.GetLength(0);//DIMENSIÓN DEL ANCHO DE LA MATRIZ int c = A.GetLength(1);//DIMENSIÓN DEL ALTO DE LA MATRIZ B, double[, ,] resultado = new double[f, c, 3]; for (int i = 0; i < f; i++) { for (int j = 0; j < c; j++) { //resultado[i, j] = Convert.ToInt32(A[i, j] / B[i, j]); resultado[i, j, 0] = (int)(A[i, j, 0] / B[i, j]); resultado[i, j, 1] = (int)(A[i, j, 1] / C[i, j]); resultado[i, j, 2] = (int)(A[i, j, 2] / C[i, j]); //resultado[i, j] = A[i, j] / B[i, j]; } } return resultado; } //CALCULA EL PRODUCTO DE DOS MATRICES COMPONENTE A COMPONENTE public double[, ,] Producto(double[, ,] A, double[,] B, double[,] C) { int f = A.GetLength(0);//DIMENSIÓN DEL ANCHO DE LA MATRIZ int c = A.GetLength(1);//DIMENSIÓN DEL ALTO DE LA MATRIZ double[, ,] RESULTANTE resultado = XI new double[f, c, 3];//MATRIZ for (int i = 0; i < f; i++) { for (int j = 0; j < c; j++) { resultado[i, j, 0] = A[i, j, 0] * B[i, j]; resultado[i, j, 1] = A[i, j, 1] * C[i, j]; resultado[i, j, 2] = A[i, j, 2] * C[i, j]; } } return resultado; } } } CLASE MATRIZBLOQUE using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Threading.Tasks; namespace LibImageCompress { public class MatrizBloque { //VARIABLES DE LA CLASE private Bloque[,] matbloque8x8; private int m, n; //CONSTRUCTOR POR DEFECTO public MatrizBloque() { } //CONSTRUCTOR CON PARÁMETROS public MatrizBloque(int m, int n) { this.m = m; this.n = n; matbloque8x8 = new Bloque[m, n]; } //CONSTRUCTOR CREA UNA MATRIZ DE BLOQUES CON DATOS DE UNA MATRIZ GRANDE (DATOS IMAGEN) public MatrizBloque(double[, ,] matIm) { m = matIm.GetLength(0) / 8; n = matIm.GetLength(1) / 8; this.matbloque8x8 = new Bloque[m, n]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { this.matbloque8x8[i, j] = bloque8x8(matIm, i, j); } } } //CONVIERTE UNA MATRIZ POR BLOQUES EN UNA MATRIZ SIMPLE public double[, ,] Matriz(MatrizBloque mb) XII { double[, ,] mat_aux = new double[m * 8, n * 8, 3]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { mat_aux[8 * i + x, 8 * j + y, 0] = mb.matbloque8x8[i, j].Datos[x, y, 0]; mat_aux[8 * i + x, 8 * j + y, 1] = mb.matbloque8x8[i, j].Datos[x, y, 1]; mat_aux[8 * i + x, 8 * j + y, 2] = mb.matbloque8x8[i, j].Datos[x, y, 2]; } } } } return mat_aux; } //*********************************** PROPIEDADES ********************// public Bloque[,] Matbloque8x8 { get { return matbloque8x8; } set { matbloque8x8 = value; } } //************************** MÉTODOS *********************************// //RETORNA UN BLOQUE DE 8X8 DENTRO DE UNA IMAGEN DADAS LAS COORDENADAS x,y private Bloque bloque8x8(double[, ,] matI, int x, int y) { Bloque submatriz = new Bloque(); for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { submatriz.Datos[i, j, 0] = matI[8 * x + i, 8 * y + j, 0]; submatriz.Datos[i, j, 1] = matI[8 * x + i, 8 * y + j, 1]; submatriz.Datos[i, j, 2] = matI[8 * x + i, 8 * y + j, 2]; } } return submatriz; } //CALCULA LA TRANSFORMADA DE COSENO EN UNA MATRIZ DE BLOQUES public MatrizBloque TrasformadaCoseno() { MatrizBloque TCD = new MatrizBloque(m, n); for (int i = 0; i < m; i++) XIII { for (int j = 0; j < n; j++) { TCD.Matbloque8x8[i, j] = matbloque8x8[i, j].TDC(); } } return TCD; } //CALCULA LA TRANSFORMADA INVERSA DE COSENO EN UNA MATRIZ DE BLOQUES //public MatrizBloque TrasformadaInversaCoseno(MatrizBloque mb) public MatrizBloque TrasformadaInversaCoseno() { MatrizBloque ITCD = new MatrizBloque(m, n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { ITCD.Matbloque8x8[i, j] = matbloque8x8[i, j].ITDC(); } } return ITCD; } //CALCULA LA TRANSFORMADA DE COSENO EN UNA MATRIZ DE BLOQUES public MatrizBloque Cuantificacion() { MatrizBloque QUANT = new MatrizBloque(m, n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { QUANT.Matbloque8x8[i, j] = matbloque8x8[i, j].Cuantizar(); } } return QUANT; } //CALCULA EL PROCESO INVERSO DE LA CUANTIFICACIÓN EN UNA MATRIZ DE BLOQUES public MatrizBloque Descuantificacion() { MatrizBloque DESQUANT = new MatrizBloque(m, n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { DESQUANT.Matbloque8x8[i, j] = matbloque8x8[i, j].InvCuantizar(); } } return DESQUANT; } XIV //RECORRIDO EN ZIG ZAG MATRIZ DE BLOQUES public List RecorridoZigzag() { List zz = new List(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { zz.Add(matbloque8x8[i, j].RecorrerZigZag()); } } return zz; } public MatrizBloque InvRecorridZigZag(List zz) { MatrizBloque INV_ZZ = new MatrizBloque(m, n); int pos = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { INV_ZZ.matbloque8x8[i, j] = matbloque8x8[i, j].InvRecorrerZigZag(zz[pos]); pos++; } } return INV_ZZ; } //PERMITE VISUALIZAR LOS DATOS DE LOS BLOQUES public void ImprimeMatbloque() { for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { matbloque8x8[i, j].ImprimeMatriz(); } Console.WriteLine(); } } } } CLASE COMPRESIONJPEG using using using using using using using DE UN System; System.Collections.Generic; System.Linq; System.Text; System.Threading.Tasks; System.Drawing;//LIBRERIA PERMITE TRABAJAR CON BITMAPs System.Diagnostics;//LIBRERIA PARA CALCULAR EL TIEMPO DE EJECUCIÓN ALGORITMO namespace LibImageCompress { XV public class CompresionJPEG { public Bitmap ImCompress; public double time; Imagen img_RGB; double[, ,] nuevaIMG; //CONSTRUCTOR POR DEFECTO public CompresionJPEG() { } //CONSTRUCTOR CON PARÁMETROS public CompresionJPEG(Bitmap Imagen) { //DETERMINA EL TIEMPO DE EJECUCIÓN DE UN ALGORITMO Stopwatch tiempo = Stopwatch.StartNew(); img_RGB = new Imagen(Imagen);//DECLARA UN CONSTRUCTOR DE LA CLASE IMAGEN double[, ,] img_Compress = CompresionImagen(img_RGB); //List img_List = CompresionImagen(img_RGB); //double[, ,] img_Descompress = DescompresionImagen(img_List); double[, ,] img_Descompress = DescompresionImagen(img_Compress); ImCompress = img_RGB.ReconstruirImagen(img_Descompress); CodificacionHuffman ch = new CodificacionHuffman(); Point p = new Point(5, -3); time = tiempo.Elapsed.Seconds; } public double[, ,] CompresionImagen(Imagen img) //public List CompresionImagen(Imagen img) { //1. CAMBIAR EL ESPACIO DE COLOR DE LA IMAGEN AL ESPACIO YCBCR double[, ,] YCBCR = img.ConvertiRGBaYCBCR(); Imagen img_YCBCR = new Imagen(YCBCR); //2. RESTAR 128 A CADA PLANO DE IMAGEN double[, ,] resta_YCBCR = img_YCBCR.Resta(); //COMPLETAR LAS FILAS Y COLUMNAS QUE HAGAN FALTA PARA //QUE LA MATRIZ SEA MULTIPLO DE 8 nuevaIMG = img_YCBCR.CompletarMatriz(resta_YCBCR); //3. GENERAR LOS BLOQUES DE 8X8 MatrizBloque calculos = new MatrizBloque(nuevaIMG); //4. APLICAR LA TRANSFORMADA DE COSENO A CADA BLOQUE //MatrizBloque calculos1= calculos.TrasformadaCoseno(); calculos = calculos.TrasformadaCoseno(); //5. REALIZAR LA CUANTIFICACIÓN //MatrizBloque calculos2 = calculos1.Cuantificacion(); calculos = calculos.Cuantificacion(); //List l = calculos.RecorridoZigzag(); double[, ,] imgComprimida = calculos.Matriz(calculos); XVI //cr = l[0][0, 0]; cg = l[0][0, 1]; cb = l[0][0, 2]; //dr = nuevaIMG.GetLength(0); dg = nuevaIMG.GetLength(1); db = resta_YCBCR[0, 0, 2]; return imgComprimida; //return l; } //public double[, ,] DescompresionImagen(List imgCompress) public double[, ,] DescompresionImagen(double[, ,] imgCompress) { /*MatrizBloque reconstruccion = new MatrizBloque(nuevaIMG.GetLength(0), nuevaIMG.GetLength(1)); reconstruccion = reconstruccion.InvRecorridZigZag(imgCompress);*/ MatrizBloque reconstruccion = new MatrizBloque(imgCompress); reconstruccion = reconstruccion.Descuantificacion(); reconstruccion = reconstruccion.TrasformadaInversaCoseno(); double[, ,] img_nueva = reconstruccion.Matriz(reconstruccion); Imagen imagen_aux = new Imagen(img_nueva); double[, ,] img_YCBCR = imagen_aux.Suma(); Imagen imagen_nueva = new Imagen(img_YCBCR); double[, ,] img_RGB = imagen_nueva.ConvertirYCBCRaRGB(); return img_RGB; } } } CLASE CALIDADIMAGEN using using using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.Threading.Tasks; System.Drawing; System.Drawing.Imaging; System.IO; namespace LibImageCompress { public class CalidadImagen { private double mse; private double psnr; private double ssim; private float factor_compresion; //CONSTRUCTOR POR DEFECTO public CalidadImagen() { } XVII //CONTRUCTOR CON PARÁMETROS public CalidadImagen(Imagen img_original, Imagen img_nueva) { mse = Calculo_MSE(img_original, img_nueva); psnr = Calcula_PSNR(mse); ssim = SSIM_IMG(img_original, img_nueva); } /*************************** PROPIEDADES ***********************/ public double MSE { get { return mse; } set { mse = value; } } public double PSNR { get { return psnr; } set { psnr = value; } } public double SSIM { get { return ssim; } set { ssim = value; } } public float Factor_compresion { get { return factor_compresion; } } /**************************** MÉTODOS *************************/ //CÁLCULA LA TASA DE COMPRESIÓN ENTRE EL TAMAÑO DE LA IMAGEN ORIGINAL Y LA IMAGEN COMPRESA public float Calcula_RatioCompresion(float size_img1, float size_img2) { return (size_img1 / size_img2); } //CÁLCULO DEL ERRROR MEDIO CUADRÁTICO private double Calculo_MSE(Imagen img_original, Imagen img_nueva) { int ancho = img_original.Ancho; int alto = img_original.Alto; int nump = ancho * alto; double MSE_R = 0, MSE_G = 0, MSE_B = 0; for (int i = 0; i < ancho; i++) { for (int j = 0; j < alto; j++) { MSE_R += Math.Pow(img_original.R[i, j] img_nueva.R[i, j], 2); MSE_G += Math.Pow(img_original.G[i, j] img_nueva.G[i, j], 2); MSE_B += Math.Pow(img_original.B[i, j] img_nueva.B[i, j], 2); } } MSE_R /= nump; MSE_G /= nump; MSE_B /= nump; double MSE_aux = (MSE_R + MSE_G + MSE_B) / 3; XVIII MSE = Math.Round(MSE_aux, 2); return MSE; } //CÁLCULO LA MEDIDA DE SEÑAL RUIDO private double Calcula_PSNR(double MSE) { double PSNR_aux = 20 * Math.Log10(255 / (Math.Sqrt(MSE))); double PSNR = Math.Round(PSNR_aux, 2); return PSNR; } //CALCULA EL SSIM, INDICE DE CALIDAD ESTRUCTURAL private double SSIM_IMG(Imagen img_original, Imagen img_compress) { double[, ,] aux_img1 = img_original.ConvertiRGBaYCBCR(); double[, ,] aux_img2 = img_compress.ConvertiRGBaYCBCR(); int ancho = img_original.Ancho; int alto = img_original.Alto; int m, n = 0; if (ancho % 8 == 0) { m = ancho; } else { m = ancho - (ancho % 8); } if (alto % 8 == 0) { n = alto; } else { n = alto - (alto % 8); } double[, ,] img1 = new double[m, n, 3]; double[, ,] img2 = new double[m, n, 3]; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { img1[i, j, 0] = aux_img1[i, j, 0]; img1[i, j, 1] = aux_img1[i, j, 1]; img1[i, j, 2] = aux_img1[i, j, 2]; img2[i, j, 0] = aux_img2[i, j, 0]; img2[i, j, 1] = aux_img2[i, j, 1]; img2[i, j, 2] = aux_img2[i, j, 2]; } } MatrizBloque mb_img1 = new MatrizBloque(img1); MatrizBloque mb_img2 = new MatrizBloque(img2); double aux_ssim = 0; for (int i = 0; i < m / 8; i++) { for (int j = 0; j < n / 8; j++) { aux_ssim += Calcula_SSIM(mb_img1.Matbloque8x8[i, j], mb_img2.Matbloque8x8[i, j]); } } aux_ssim /= (m / 8) * (n / 8);//MEDIA ARITMETICA DE LOS BLOQUES CALCULADOS aux_ssim = Math.Round(aux_ssim, 4); XIX return aux_ssim; } //CALCULA LA MEDIDA DE CALIDAD OBJETIVA private double Calcula_SSIM(Bloque bloq1, Bloque bloq2) { int MAX = 255; double c1 = Math.Pow(0.01 * MAX, 2); double c2 = Math.Pow(0.03 * MAX, 2); double SSIM = 0; double Ux, Uy = 0; double Ux2, Uy2 = 0; double Ox2, Oy2, Oxy = 0; Ux = Calcula_Media(bloq1); Uy = Calcula_Media(bloq2); Ux2 = Math.Pow(Ux, 2); Uy2 = Math.Pow(Uy, 2); Ox2 = Calcula_Varianza(bloq1, Ux); Oy2 = Calcula_Varianza(bloq2, Uy); Oxy = Calcula_Covarianza(bloq1, bloq2, Ux, Uy); SSIM = ((2 * Ux * Uy + c1) * (2 * Oxy + c2)) / ((Ux2 + Uy2 + c1) * (Ox2 + Oy2 + c2)); return SSIM; } //CALCULA LA MEDIA DE UN BLOQUE DE DATOS private double Calcula_Media(Bloque bloq) { double aux = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { aux += bloq.Datos[i, j, 0]; } } aux /= 64; return aux; } //CALCULA LA VARIANDA DE UN BLOQUE DE DATOS private double Calcula_Varianza(Bloque bloq, double media) { double aux = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { aux += Math.Pow(bloq.Datos[i, j, 0] - media, 2); } } aux /= 64; return aux; } //CALCULA LA COVARIANZA DE UN BLOQUDE DE DATOS DADO XX private double Calcula_Covarianza(Bloque bloq1, Bloque bloq2, double media1, double media2) { double aux = 0; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { aux += (bloq1.Datos[i, j, 0] - media1) * (bloq2.Datos[i, j, 0] - media2); } } aux /= 64; return aux; } } } 2. Aplicación Web PÁGINA MAESTRA <%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="FotoCompressApp.SiteMaster" %> <%: Page.Title %> - Mi aplicación ASP.NET <%: Scripts.Render("~/bundles/modernizr") %> XXI
<%--To learn more about bundling scripts in ScriptManager see http://go.microsoft.com/fwlink/?LinkID=301884 --%> <%--Framework Scripts--%> <%--Site Scripts--%>
XXII

© <%: DateTime.Now.Year %> - Mi aplicación ASP.NET

PÁGINA PRINCIPAL <%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="FotoCompressApp.Default" %> PÁGINA APLICACIÓN <%@ Page Title="Aplicación" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Aplicacion.aspx.cs" Inherits="FotoCompressApp.Aplicacion" %>

<%: Title %>.


Imagen Original

NOMBRE:

TAMAÑO ORIGINAL:

ANCHO:

ALTO:

XXIV

Imagen Comprimida

TAMAÑO COMPRESIÓN:

PORCENTAJE COMPRESIÓN:

ÍNDICE SSIM:

CONEXIÓN CLIENTE SERVIDOR $(document).ready(function () { //ocultar();//OCULTA LOS BOTONES DE DESCARGA ocultarInfo();//OCULTA EL CUADRO DE LA INFORMACIÓN DE LA IMAGEN /*---------------------------------------------------------------*/ var datos;//VARIABLE QUE ALMACENA LOS DATOS DE UNA IMAGEN var file;//VARIABLE QUE LEE EL ARCHIVO DE IMAGEN var tamano_img;//VARIABLE QUE ALMACENA EL TAMAÑO DE UNA IMAGEN ORIGINAL var img_aux, preview;//VARIABLES DE TIPO IMAGEN var ancho, alto; /*-------------------------------SELECCIONAR IMAGEN----------------*/ $('#Upload').on('change', function () { //OCULTA EL BOTÓN DESCARGA SI SE VUELEVE A SELECCIONAR OTRA IMAGEN ocultar();//OCULTA LOS BOTONES DE DESCARGA ocultarInfo();//OCULTA EL CUADRO DE LA INFORMACIÓN DE LA IMAGEN eliminarImgComprimida(); eliminarImgOriginal(); if (typeof (FileReader) != "undefined") { //OCULTA EL ICONO PARA CARGAR LA IMAGEN $("#icono_img").attr("style", "visibility: hidden"); /*-------------------------------------------------------*/ //OBTIENE LA IMAGEN EN LA POSICIÓN 0 file = document.querySelector('input[type=file]').files[0]; preview = new Image();// IMAGEN PARA VISUALIZAR LA IMAGEN QUE SE CARGA img_aux = new Image();//IMAGEN AUXILIAR PARA VERIFICAR LA DIMENSIÓN DE LA IMAGEN //ASIGNA UN ID A LA IMAGEN preview.id = "imagen_original"; var reader = new FileReader(); //CARGA LA IMAGEN SELECCIONA reader.onload = function () { datos = reader.result;//OBTIENE LA IMAGEN EN CODIFICACIÓN BASE64 img_aux.src = datos; img_aux.onload = function () { if (img_aux.width > 1600 || img_aux.height > 1600) { alert('Las medidas deben ser: inferiores a 1600x1200, intente cargar otra imagen.'); } else { XXV /*-------------------------------------------*/ calcula_tamano(); preview.src = datos;//ASIGNA la CADENA BASE64 A LA IMAGEN ORIGINAL $('i').remove('#icono_img');//OCULTA EL ICONO DE LA IMAGEN document.getElementById('img_o').appendChild(prev iew); $('#imagen_original').addClass("img_style"); ancho = $('#imagen_original').width(); alto = $('#imagen_original').height(); /*-----------------------------------*/ $("#nombre_img").text(file.name); //RETORNA LA DIMENSIÓN DEL ANCHO DE UNA IMAGEN $("#ancho_img").text(preview.naturalWidth + px"); //RETORNA LA DIMENSIÓN DEL ALTO DE UAN IMAGEN " $("#alto_img").text(preview.naturalHeight + " px"); //RETORNA LA DIMENSIÓN DEL ARCHIVO DE UNA IMAGEN $("#tamano_original").text(tamano_img + " KB"); mostrarInfoOrginal();//MUESTRA EL CUADRO CON LA INFORMACIÓN /*---------------------------------------------*/ $("#btn_comprimir").attr("style", "visibility: visible");//MUESTRA EL BOTÓN PARA REALIZAR LA COMPRESIÓN } } }//FIN READER reader.readAsDataURL($(this)[0].files[0]); } }); /*------------------------------------*/ /*--------------------------COMPRIMIR IMAGEN----------------------*/ $('#btn_comprimir').click(function () { //OCULTA EL ICONO PARA CARGAR LA IMAGEN $('i').remove('#icono_imgc'); /*-------------------------------------------------------------*/ show_progressbar(); //MUESTRA LA BARRA DE PROGRESO MIENTRAS SE CARGA LA IMG_COMPRESS /*-------------------------------------------------------------*/ //ANTES DE SER ENVIADOS LOS DATOS SE RETIRA LOS PRIMEROS CARACTERES DE LA CADENA BASE64 datos_img = datos.replace(/^data:image\/(jpeg|png|bmp|tiff|gif);base64,/, ""); //ARMA UN VECTOR CON LOS DATOS QUE VAN A SER ENVIADOS AL SERVIDOR var Img = { Image: datos_img, Nombre: file.name }; //REALIZA LA PETICIÓN DE AJAX //ENVIA DATOS AL SERVIDOR Y DEVUELVE DATOS EN EL CASO DE SER NECESARIO /*-------------------------------*/ $.ajax({ url: 'SubirArchivo.ashx', type: 'POST', data: Img, success: function (data) { //ASIGNA LOS DATOS DE LA IMAGEN COMPRIMIDA XXVI var datos_imgComp = 'data:image/jpg;base64,' data.Image_base64; mostrarImgComprimida(datos_imgComp); + //$('img').remove('#barra_cargando');//ELIMINA LA ETIQUETA DE LA BARRA DE CARGA eliminarDiv(); /*-----------------------------------------------------*/ $("#tamano_compress").text(data.Size_compress + " KB");//RETORNA EL TAMAÑO DE LA IMAGEN COMPRIMIDA $("#porcentaje_comp").text(data.Porcentaje + " %");//RETORNA EL PORCENTAJE DE COMPRESIÓN $("#indice_ssim").text(data.SSim);//RETORNA EL VALOR DE LA CALIDAD DE UNA IMAGEN mostrarInfo();//MUESTRA EL CUADRO CON LA INFORMACIÓN DE LA IMAGEN COMPRIMIDA mostrar();//MOSTRAR EL BOTÓN DE DESCARGA alert("LA IMAGEN SE HA COMPRIMIDO EXITOSAMENTE"); /*-----------------------------------------------------*/ }, error: function () { alert("ERROR AL INTENTAR COMPRIMIR LA IMAGEN") } });//FIN AJAX }); /*--------------------------MÉTODOS-----------------------------*/ /**********************************************************************/ //CALCULA EL TAMAÑO DEL ARCHIVO DE UNA IMAGEN function calcula_tamano() { tam = file.size; while (tam >= 1024) { tam = tam / 1024; } tamano_img = tam.toFixed(2); }; /**********************************************************************/ //MUESTRA UNA IMAGEN CON LA BARRA DE CARGA HASTA QUE SE VISUALICE LA IMAGEN COMPRIMIDA function show_progressbar() { /* //CREA UNA ETIQUETA IMG var progress_bar = document.createElement('img'); //ASIGNA UN ID A LA ETIQUETA progress_bar.id = "barra_cargando"; //RUTA DE LA IMAGEN progress_bar.src = '../IMG_WEB/progress_bar.gif'; document.getElementById('icompres').appendChild(progress_bar);*/ var div_auxiliar = document.createElement('div'); div_auxiliar.id = "div_aux"; document.getElementById('icompres').appendChild(div_auxiliar); $('#div_aux').width(ancho); $('#div_aux').height(alto); var progress_bar = document.createElement('div'); progress_bar.id = "barra_cargando"; document.getElementById('div_aux').appendChild(progress_bar); $('#barra_cargando').addClass("cssload-loader"); }; function eliminarDiv() { $('div').remove('#barra_cargando'); $('div').remove('#div_aux'); }; XXVII //MOSTRAR LA IMAGEN COMPRIMIDA function mostrarImgComprimida(base64) { //CREA UNA ETIQUETA IMG var img_comp = document.createElement('img'); //ASIGNA UN ID A LA ETIQUETA img_comp.id = "img_compress"; //RUTA DE LA IMAGEN img_comp.src = base64; document.getElementById('icompres').appendChild(img_comp); $('#img_compress').addClass("img_style"); }; //ELIMINA LA ETIQUETA DE LA IMAGEN COMPRIMIDA function eliminarImgComprimida() { $('#img_compress').remove(); }; //ELIMINA LA ETIQUETA PARA MOSTRAR UNA IMAGEN function eliminarImgOriginal() { $('#imagen_original').remove(); }; //OCULTA LOS BOTONES PARA DESCARGAR Y COMPRIMIR function ocultar() { $("#MainContent_btn_descargar").attr("style", "visibility: hidden"); $("#btn_comprimir").attr("style", "visibility: hidden"); }; //OCULTA LOS CUADROS QUE TIENEN LA INFORMACIÓN DE LAS IMÁGENES function ocultarInfo() { $("#info_org").css("visibility", "hidden"); $("#info_comp").css("visibility", "hidden"); }; //MUESTRA UN CUADRO CON LA INFORMACIÓN DE LA IMAGEN ORIGINAL function mostrarInfoOrginal() { $("#info_org").css("visibility", "visible"); }; //MUESTRA UN CUADRO CON LA INFORMACIÓN DE LA IMAGEN COMPRIMIDA function mostrarInfo() { $("#info_comp").css("visibility", "visible"); }; //MUESTRA EL BOTÓN DE DESCARGA Y OCULTA EL BOTÓN PARA COMPRIMIR function mostrar() { $("#MainContent_btn_descargar").attr("style", "visibility: visible"); $("#btn_comprimir").attr("style", "visibility: hidden"); }; }); XXVIII ANEXO B Manual de Usuario Este documento está diseñado para proporcionar una guía del manejo de cada una de las opciones de la Aplicación FotoCompressApp. A continuación se describe cada una de las pantallas a las que puede acceder el usuario. 1. Pantalla de inicio de la aplicación La página principal está compuesta por un menú con cuatro opciones: Inicio, Aplicación, Documentación y Contacto. 2. Dar clic en la opción INICIO. A continuación se visualiza una pantalla, la cual contiene una breve descripción de la Aplicación. XXIX 3. Para regresar al menú principal, dar clic en el logotipo fotoCompress. Regresar al menú principal 4. La siguiente opción del menú principal es Aplicación. XXX Dar clic para escoger la imagen 5. En esta ventana lo primero que se debe hacer el cargar una imagen. Para ello dar clic el botón Seleccionar un archivo. En seguida aparece la pantalla para escoger la imagen que desea comprimir. Esta imagen no debe exceder las dimensiones de 1600x1200 o 1200x1600. 6. Seleccione la imagen y seguidamente dar clic en abrir como se visualiza en la siguiente pantalla. 7. La imagen seleccionada aparece en la siguiente pantalla. Además en el lado superior derecho se muestra un botón que permite realizar la compresión. XXXI 8. Al dar clic en el botón Comprimir se muestra una barra indicando que se está cargando la imagen comprimida. 9. Una vez que la imagen se haya cargado completamente, aparece la siguiente mensaje, indicando que la imagen subida se ha comprimido exitosamente. XXXII 10. En caso de que la imagen exceda los límites establecidos anteriormente, se mostrará el siguiente mensaje de ERROR. De clic en Aceptar, e intente subir otra imagen con menor dimensión. 11. En la siguiente ventana, al lado derecho se puede visualizar la imagen comprimida y en la parte superior un botón de descarga, para que pueda guardar la imagen en el disco de la PC. En la parte inferior se muestran las características de la imagen y en qué porcentaje se realizó la compresión. XXXIII 12. Para descargar la imagen comprimida, dar clic en el botón DESCARGAR, inmediatamente el archivo lo puede visualizar en la parte inferior izquierda de la ventana. Imagen comprimida, 13. En el menú principal, para revisar la Documentación acerca del desarrollo descargada de la Aplicación se tiene la siguiente opción. En esta ventana se detallan las clases y componentes más importantes acerca del desarrollo de la Librería de Compresión y la Aplicación Web. XXXIV 14. Por último se tiene una página de Contacto, donde constan datos del desarrollador del presente proyecto. XXXV