AnteriorPosterior

8.14. Ejemplo completo: leer información de un fichero BMP

  Curso: Programación en C# (2015), por Nacho Cabanes

8.14. Ejemplo completo: leer información de un fichero BMP

Hemos estado extrayendo algo de información de ficheros BMP. Ahora vamos a ir un poco más allá y a tratar de obtener muchos de los detalles que hay en su cabecera. El formato de dicha cabecera es el siguiente:


FICHEROS .BMP 

Un fichero BMP está compuesto por las siguientes partes: 
una cabecera de fichero, una cabecera del bitmap, una tabla de colores 
y los bytes que definirán la imagen.

En concreto, los datos que forman la cabecera de fichero y la cabecera de bitmap 
son los siguientes:

TIPO DE INFORMACIÓN	- POSICIÓN EN EL ARCHIVO
Tipo de fichero (letras BM)	0-1
Tamaño del archivo	2-5
Reservado	6-7
Reservado	8-9
Inicio de los datos de la imagen	10-13
Tamaño de la cabecera de bitmap	14-17
Anchura (píxeles)	18-21
Altura (píxeles)	22-25
Número de planos	26-27
Tamaño de cada punto	28-29
Compresión (0=no comprimido)	30-33
Tamaño de la imagen	34-37
Resolución horizontal	38-41
Resolución vertical	42-45
Tamaño de la tabla de color	46-49
Contador de colores importantes	50-53

Por tanto, será fácil hacer que se nos muestren algunos detales, como su ancho, su alto, la resolución y si la imagen está comprimida o no:

?// Ejemplo_08_14a.cs
// Información de un fichero BMP, con BinaryReader
// Introducción a C#, por Nacho Cabanes
 
using System;
using System.IO;
 
public class Ejemplo_08_14a
{
    public static void Main()
    {
        Console.WriteLine("Información de imágenes BMP");
        Console.WriteLine("Dime el nombre del fichero: ");
        string nombre = Console.ReadLine();
 
        if (! File.Exists( nombre) )
        {
            Console.WriteLine("No encontrado!");
        }
        else
        {
            BinaryReader fichero = new BinaryReader(
                File.Open(nombre, FileMode.Open));
 
            // Leo los dos primeros bytes
            char marca1 = Convert.ToChar( fichero.ReadByte() );
            char marca2 = Convert.ToChar( fichero.ReadByte() );
 
            if ((marca1 !='B') || (marca2 !='M'))
                Console.WriteLine("No parece un fichero BMP");
            else
            { 
                Console.WriteLine("Marca del fichero: {0}{1}", 
                    marca1, marca2);
 
                // Posición 18: ancho
                fichero.BaseStream.Seek(18, SeekOrigin.Begin);          
                int ancho = fichero.ReadInt32();
                Console.WriteLine("Ancho: {0}", ancho);
 
                // A continuación: alto
                int alto = fichero.ReadInt32();
                Console.WriteLine("Alto: {0}", alto);
 
                // Posición 30: compresión
                fichero.BaseStream.Seek(30, SeekOrigin.Begin); 
                int compresion = fichero.ReadInt32();
                switch (compresion) 
                {
                    case 0: Console.WriteLine("Sin compresión"); 
                        break;
                    case 1: Console.WriteLine("Compresión RLE 8 bits"); 
                        break;
                    case 2: Console.WriteLine("Compresión RLE 4 bits"); 
                        break;
                }
 
                // 4 bytes después: resolución horizontal
                fichero.BaseStream.Seek(4, SeekOrigin.Current); 
                int resolH = fichero.ReadInt32();
                Console.WriteLine("Resolución Horiz.: {0}", resolH);
 
                // A continuación: resolución vertical
                int resolV = fichero.ReadInt32();
                Console.WriteLine("Resolución Vertical: {0}", resolV);
 
                fichero.Close();
            } 
        }
    }  
}
 

Podemos hacerlo también con un FileStream, que simplificará ciertas operaciones, como la lectura, que se puede hacer toda en un bloque, pero a cambio complicará otras operaciones, como el cálculo de los valores enteros, que habrá que componer a partir de los 4 bytes que los forman:

?// Ejemplo_08_14b.cs
// Información de un fichero BMP, con FileStream
// Introducción a C#, por Nacho Cabanes
 
using System;
using System.IO;
 
public class Ejemplo_08_14b
{
    public static void Main()
    {
        Console.WriteLine("Información de imágenes BMP");
        Console.WriteLine("Dime el nombre del fichero: ");
        string nombre = Console.ReadLine();
 
        if (! File.Exists( nombre) )
        {
            Console.WriteLine("No encontrado!");
        }
        else
        {
            FileStream fichero = File.OpenRead(nombre);
            int tamanyoCabecera = 54;
            byte[] cabecera = new byte[tamanyoCabecera];
 
            int cantidadLeida = fichero.Read(cabecera, 0, tamanyoCabecera);
            fichero.Close();
 
            if (cantidadLeida != tamanyoCabecera)            
            {
                Console.WriteLine("No se ha podido leer la cabecera");
            }
            else
            {
                // Analizo los dos primeros bytes
                char marca1 = Convert.ToChar( cabecera[0] );
                char marca2 = Convert.ToChar( cabecera[1] );
 
                if ((marca1 !='B') || (marca2 !='M'))
                    Console.WriteLine("No parece un fichero BMP");
                else
                { 
                    Console.WriteLine("Marca del fichero: {0}{1}", 
                        marca1, marca2);
 
                    int ancho = cabecera[18] + // Convierto 4 bytes a Int32
                        cabecera[19] * 256  + cabecera[20] * 256  * 256 +
                        cabecera[21] * 256 * 256 * 256;
                    Console.WriteLine("Ancho: {0}", ancho);
 
                    int alto = cabecera[22] +
                        cabecera[23] * 256  + cabecera[24] * 256  * 256 +
                        cabecera[25] * 256 * 256 * 256;
                    Console.WriteLine("Alto: {0}", alto);
 
                    int compresion = cabecera[30];
                    switch (compresion) 
                    {
                        case 0: Console.WriteLine("Sin compresión"); 
                            break;
                        case 1: Console.WriteLine("Compresión RLE 8 bits"); 
                            break;
                        case 2: Console.WriteLine("Compresión RLE 4 bits"); 
                            break;
                    }
 
                    int resolH = cabecera[38] +
                        cabecera[39] * 256  + cabecera[40] * 256  * 256 +
                        cabecera[41] * 256 * 256 * 256;
                    Console.WriteLine("Resolución Horiz.: {0}", resolH);
 
                    int resolV = cabecera[42] +
                        cabecera[43] * 256  + cabecera[44] * 256  * 256 +
                        cabecera[45] * 256 * 256 * 256;
                    Console.WriteLine("Resolución Vertical: {0}", resolV);
                } 
            }
        }
    }  
}
 

Ejercicios propuestos:

Ejercicio propuesto 8.14.1: Localiza en Internet información sobre el formato de imágenes PCX. Crea un programa que diga el ancho, alto y número de colores de una imagen PCX.
Ejercicio propuesto 8.14.2: Localiza en Internet información sobre el formato de imágenes GIF. Crea un programa que diga el subformato, ancho, alto y número de colores de una imagen GIF.

Actualizado el: 22-03-2015 17:07

AnteriorPosterior