Obtener valores RGB para cada píxel de un mapa de bits de 24 bpp para la conversión a formato GBA en C

StackOverflow https://stackoverflow.com/questions/1531268

  •  20-09-2019
  •  | 
  •  

Pregunta

quiero leer los valores RGB para cada píxel de un archivo .bmp, por lo que puede convertir el bmp en un formato adecuado para GBA (Game Boy Advance).

Necesito obtener sólo el RGB para cada píxel y luego escribir esta información en un archivo.

Estoy tratando de utilizar las estructuras <windows.h>:

typedef struct
{
    char signature[2];
    unsigned int fileSize;
    unsigned int reserved;
    unsigned int offset;
}BmpHeader;

typedef struct
{
    unsigned int headerSize;
    unsigned int width;
    unsigned int height;
    unsigned short planeCount;
    unsigned short bitDepth;
    unsigned int compression;
    unsigned int compressedImageSize;
    unsigned int horizontalResolution;
    unsigned int verticalResolution;
    unsigned int numColors;
    unsigned int importantColors;

}BmpImageInfo;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    unsigned char reserved;
}Rgb;

typedef struct
{
    BmpHeader header;
    BmpImageInfo info;
    Rgb colors[256];
    unsigned short image[1];
}BmpFile;

pero yo sólo necesito RGB estructura. Así que digamos que leí "in.bmp":

FILE *inFile, *outFile;
inFile = fopen("C://in.bmp", "rb");

Rgb Palette[256];
for(i=0;i<256;i++)
{
   fread(&Palette[i],sizeof(Rgb),1,inFile);
}

fclose(inFile);

¿Es esto correcto? ¿Cómo se escribe sólo la información RGB en un archivo?

¿Fue útil?

Solución

Es necesario primero para obtener el número de colores disponibles en la paleta incrustado. Este servicio está disponible en la cabecera DIB.

A continuación, puede leer todos los componentes de color que contienen la paleta.

Se puede ver toda la información de cabecera como el desplazamiento saber Whereto buscan: http: //en.wikipedia. org / wiki / BMP_file_format.

Esto debería funcionar: (Edit: Añadir un código para escribir en el archivo)

FILE *inFile, *outFile;
BMPHeader header;
BMPImageInfo info;
RGB *palette, *p;
int i = 0;

inFile = fopen("C://in.bmp", "rb");
if( !inFile )
   return;

if( fread(&header, sizeof(BMPHeader), 1, inFile) != 1 )
   return; // Manage error and close file

if( fread&info, sizeof(BMPImageInfo), 1, inFile) != 1 )
   return; // Manage error and close file

if( info.numColors > 0 )
{
   palette = (RGB*)malloc(sizeof(RGB) * info.numColors);
   if( fread(palette, sizeof(RGB), info.numColors, inFile) != info.numColors )
      return; // manage error and close file
}

fclose(inFile)

// Binary method => if read later by another computer
outFile = fopen("path", "wb");
if( !outFile )
   return;

if( fwrite(&info.numColors, sizeof(unsigned int), 1, outFile) != 1 )
   return; // Manage Error and close file

if( fwrite(&palette, sizeof(RGB), info.numColors, outFile) != info.numColors )
   return; // Manage error and close file

fclose(outFile);

// Text method => if read later by human
outFile = fopen("path", "w");
if( !outFile )
   return;

for( i=0; i<info.numColors; ++i )
{
   p = &palette[i];
   if( fprintf(outFile, "R:%d, G:%d, B:%d\n", p->red, p->green, p->blue) < 0 )
      return; // Manage error and close file
}

fclose(outFile);

Otros consejos

Si está en Windows se puede utilizar el LoadBitmap función de Win32

dada entonces la manija convertirlo en un mapa de bits DIB y llegar a los píxeles de esa manera

Hice un poco de prueba y ampliado programa de Patrice un poco. No soy un buen programador C, por lo que todo el crédito va a él y mis partes no son tan elegante como su -. Lo siento por eso

Advertencia:. Enorme por delante código fuente

#include <stdio.h>
#pragma pack(2)


typedef struct
{
    char signature[2];
    unsigned int fileSize;
    unsigned int reserved;
    unsigned int offset;
} BmpHeader;

typedef struct
{
    unsigned int headerSize;
    unsigned int width;
    unsigned int height;
    unsigned short planeCount;
    unsigned short bitDepth;
    unsigned int compression;
    unsigned int compressedImageSize;
    unsigned int horizontalResolution;
    unsigned int verticalResolution;
    unsigned int numColors;
    unsigned int importantColors;

} BmpImageInfo;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    //unsigned char reserved; Removed for convenience in fread; info.bitDepth/8 doesn't seem to work for some reason
} Rgb;


int main( int argc, char **argv ) {

    FILE *inFile;
    BmpHeader header;
    BmpImageInfo info;
    Rgb *palette;
    int i = 0;

    printf( "Opening file %s for reading.\n", argv[1] );

    inFile = fopen( argv[1], "rb" );
    if( !inFile ) {
        printf( "Error opening file %s.\n", argv[1] );
        return -1;
    }

    if( fread(&header, 1, sizeof(BmpHeader), inFile) != sizeof(BmpHeader) ) {
        printf( "Error reading bmp header.\n" );
        return -1;
    }

    if( fread(&info, 1, sizeof(BmpImageInfo), inFile) != sizeof(BmpImageInfo) ) {
        printf( "Error reading image info.\n" );
        return -1;
    }

    if( info.numColors > 0 ) {
        printf( "Reading palette.\n" );
        palette = (Rgb*)malloc(sizeof(Rgb) * info.numColors);
        if( fread(palette, sizeof(Rgb), info.numColors, inFile) != (info.numColors * sizeof(Rgb)) ) {
            printf( "Error reading palette.\n" );
            return -1; // error
        }
    }

    printf( "Opening file %s for writing.\n", argv[2] );
    FILE *outFile = fopen( argv[2], "wb" );
    if( !outFile ) {
        printf( "Error opening outputfile.\n" );
        return -1;
    }
    Rgb *pixel = (Rgb*) malloc( sizeof(Rgb) );
    int read, j;
    for( j=0; j<info.height; j++ ) {
        printf( "------ Row %d\n", j+1 );
        read = 0;
        for( i=0; i<info.width; i++ ) {
            if( fread(pixel, 1, sizeof(Rgb), inFile) != sizeof(Rgb) ) {
                printf( "Error reading pixel!\n" );
                return -1;
            }
            read += sizeof(Rgb);
            printf( "Pixel %d: %3d %3d %3d\n", i+1, pixel->red, pixel->green, pixel->blue );
        }
        if( read % 4 != 0 ) {
            read = 4 - (read%4);
            printf( "Padding: %d bytes\n", read );
            fread( pixel, read, 1, inFile );
        }
    }

    printf( "Done.\n" );
    fclose(inFile);
    fclose(outFile);

    printf( "\nBMP-Info:\n" );
    printf( "Width x Height: %i x %i\n", info.width, info.height );
    printf( "Depth: %i\n", (int)info.bitDepth );

    return 0;

}

Este programa lee la información de los píxeles almacenados en el archivo. Se necesita el relleno en cuenta, pero sólo funciona con las BMP con 24 bits por píxel profundidad de color (Si necesita otras profundidades, usted tiene que personalizar la estructura RGB). Espero que esto le ayuda, pero como ya he dicho, es sólo una extensión de código de Patrice.

Aquí hay un ejemplo de salida de mi testfile:

$ ./a.out test.bmp out.txt
Opening file test.bmp for reading.
Opening file out.txt for writing.
------ Row 1
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3:   0   0   0
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 2
Pixel 1:   0   0   0
Pixel 2: 232  33  33
Pixel 3:   0   0   0
Pixel 4: 232  33  33
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 3
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3: 232  33  33
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 4
Pixel 1:   0   0   0
Pixel 2: 232  33  33
Pixel 3:   0   0   0
Pixel 4: 232  33  33
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 5
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3:   0   0   0
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
Done.

BMP-Info:
Width x Height: 5 x 5
Depth: 24

Edit: Sí, mi imagen está mostrando una cruz roja. Tenga en cuenta que la imagen se almacena en posición invertida para la fila 1 del archivo es en realidad la fila 5 de la imagen. D'oh olvidó de escribir algo para presentar el código se abre, pero esto se deja como un ejercicio de usted;)

.

Si tiene la garantía de que se trata de un mapa de bits sin comprimir 24bpp y su anchura es divisible por 4, es relativamente simple:

  1. Leer un BmpHeader al inicio del archivo.
  2. Sin buscar, leer un BmpImageInfo.
  3. Tratar de bytes BmpHeader del offset de al principio del archivo . Tenga en cuenta que no hay una gama de colores (al menos, no uno que se preocupa) en mapas de bits de 24 bits!
  4. Leer trillizos BGR (en ese orden, y no hay ningún miembro sin usar reserved aquí). Habrá (miembros de BmpImageInfo) trillizos width * abs(height). Por lo que recuerdo, si height es positivo (el caso normal), la primera línea de color que lee será el fondo línea de la imagen, subiendo desde allí. Si height es negativo, sin embargo, la primera línea de color en el archivo es el top de la imagen, bajando desde allí.

Si no puede hacer esas garantías, entonces las cosas se ponen bastante más complicado.

exención de responsabilidad:. Estoy gratuitamente haciendo sonar mi molino aquí Hace años escribí una pequeña utilidad (un archivo de origen) para hacer exactamente lo que está hablando, en un portátil (100% ANSI C ida): GLBMP libbmpread . Su fuente podría arrojar alguna luz sobre su problema -. Maneja (sin RLE) uncompresed de cualquier profundidad de bits, y debería funcionar bien en un GBA

Ver página de Wikipedia de formato de archivo .bmp que proporciona una gran cantidad de información sobre la estructura del archivo y le ayudará a analizarlo.

http://en.wikipedia.org/wiki/BMP_file_format

En el código primero hay que leer la dirección inicial de los datos (especificada en el encabezado del archivo) y la altura de la imagen. A continuación, tratar de esta posición. Después de leer en un píxel a píxel fila (el encabezado especifica el número de bits por píxel) y tienen que cuidar del acolchado de 32 bits al final de la misma. Tenga en cuenta que una imagen de 24 bits (RGB) en la información se almacena con el fin BGR. Además, si el valor de la altura no es negativo, la imagen se almacena al revés.

No estoy familiarizado con el formato de archivo BMP, pero ¿no es necesario leer en la información del encabezado en primer lugar? Algo así como:

BmpHeader header;
fread(&header,sizeof(BmpHeader),1,inFile);

y leer la información detallada en la imagen, lo que se necesita:

BmpImageInfo info;
fread(&info,sizeof(BmpImageInfo),1,inFile);

y leer la información en la paleta también.

una vez que tenga que usted sabrá el tamaño del archivo y datos de corrección. Se podría pre-asignar espacio suficiente y leído en todos a la vez, lo que puede ser más simple. Como alternativa se puede leer en en trozos y analizar como vas (reduce la posibilidad de no tener suficiente memoria, pero el análisis es más complicado).

También sabrá de la sección de información si se habilita la compresión, las dimensiones de imagen, etc.

Si usted está leyendo en todos a la vez, saltar al desplazamiento de los datos, y hacer algo como:

Rgb* rgb = offset;
blueVal = rgb->blue;
greenVal = rgb->green;
redVal = rgb->red;
rgb += sizeof( Rgb );

y así sucesivamente. Obviamente que el código no es la comprobación de errores, al final del búfer, y así sucesivamente, por lo que tendrá que hacer eso. Es posible que también tiene que leer en la información de paleta para dar sentido a los datos de la imagen.

O, como alguien dijo, mira la especificación de formato de Wikipedia

Si el archivo BMP tiene una paleta entonces el siguiente código debe de trabajo:

  FILE *inFile, *outFile;
  inFile = fopen("C:/in.bmp", "rb");
  Rgb Palette[256];
  if ( inFile ) {
    // Bypass headers
    fseek(inFile, sizeof(BmpHeader) + sizeof(BmpImageInfo), SEEK_SET);
    // Load the whole palette
    fread(Palette, sizeof(Palette), 1, inFile);
    fclose(inFile);
  }

Puede que le resulte útil para mirar algo de código C que escribí hace muchos años para la lectura y escritura de archivos BMP, que se encuentra en:

http://david.tribble.com/src/bmp/bmp.html

Creo que maneja los diferentes tamaños de bits de píxeles (1/2/4/8/24), así como la compresión RLE.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top