Come valori RGB per ogni pixel da una bitmap 24bpp per la conversione in formato GBA in C

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

  •  20-09-2019
  •  | 
  •  

Domanda

Voglio leggere i valori RGB per ogni pixel da un file .bmp, in modo da poter convertire il bmp in un formato adatto per GBA (GameBoy Advance).

Ho bisogno di ottenere solo il RGB per ogni pixel e poi scrivere queste informazioni in un file.

Sto cercando di utilizzare le strutture <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;

, ma ho solo bisogno RGB struct. Quindi diciamo che ho letto "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);

È corretto? Come faccio a scrivere solo le informazioni RGB in un file?

È stato utile?

Soluzione

È necessario prima di ottenere il numero di colori disponibili nella tavolozza incorporato. Questo è disponibile in intestazione DIB.

Quindi è possibile leggere tutti i componenti di colore che contengono la tavolozza.

È possibile visualizzare tutte le informazioni di intestazione come offset per conoscere al quale cercare: http: //en.wikipedia. org / wiki / BMP_file_format .

Questo dovrebbe funzionare: (Edit: Aggiungere codice per scrivere nel file)

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);

Altri suggerimenti

Se siete su Windows è possibile utilizzare il LoadBitmap funzione dal win32

poi dato la maniglia convertirla in una bitmap DIB e raggiungere i pixel in questo modo

Ho fatto un po 'di test ed esteso il programma di Patrice un po'. Io non sono un buon programmatore C, così tutto il merito va a lui e le mie parti non sono così elegante come la sua -. Spiacente per quello

. Attenzione: enorme codice sorgente avanti

#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;

}

Questo programma legge le informazioni dei pixel memorizzate nel file. Prende l'imbottitura in considerazione, ma funziona solo con BMPS, con un 24 bit per profondità di colore dei pixel (Se avete bisogno di altre profondità, dovrete personalizzare la struct Rgb). Spero che questo ti aiuta, ma come ho detto, è solo un'estensione del codice di Patrice.

Ecco un esempio di output dal mio 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ì, la mia immagine è la visualizzazione di una croce rossa. Si noti che l'immagine viene memorizzata rovesciata così riga 1 del file è effettivamente riga 5 dell'immagine. D'oh dimenticato di scrivere qualcosa al file si apre il codice, ma questo è lasciato come un esercitazione a voi;)

.

Se avrete la garanzia che si tratta di una bitmap 24bpp non compresso e la sua larghezza è divisibile per 4, è relativamente semplice:

  1. Leggere un BmpHeader all'inizio del file.
  2. Senza cercare, leggere un BmpImageInfo.
  3. Cercare di byte BmpHeader del offset da all'inizio del file . Si noti che non v'è alcuna tavolozza (almeno, non uno si preoccupa) in bitmap a 24 bit!
  4. Leggi triplette BGR (in questo ordine, e non c'è reserved membro inutilizzato qui). Ci saranno (membri del BmpImageInfo) triplette width * abs(height). Se non ricordo male, se height è positivo (caso standard), la prima linea di colore di leggere sarà il in basso linea dell'immagine, salendo da lì. Se height è negativo, però, la prima linea di colore nel file è il top dell'immagine, scendendo da lì.

Se non è possibile effettuare tali garanzie, poi le cose si fanno un buon affare più complicato.

Disclaimer:. Sto gratuitamente tooting il mio proprio corno qui Anni fa ho scritto una piccola utility (un file di origine) di fare esattamente quello che si sta parlando, in un portatile (100% ANSI C) modo: glbmp libbmpread . La sua fonte potrebbe far luce sul problema -. Gestisce uncompresed (senza RLE) bitmap di qualsiasi profondità di bit, e dovrebbe funzionare bene su un GBA

Vedere pagina di Wikipedia di .bmp formato di file che fornisce un sacco di informazioni sulla struttura del file e dovrebbe aiutare a analizzarlo.

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

Nel codice è necessario prima di leggere l'indirizzo di partenza dei dati (specificato nel file di intestazione) e l'altezza dell'immagine. Poi cercano di questa posizione. Dopo aver letto in un pixel per pixel fila (intestazione specifica il numero di bit per pixel) e devono prendersi cura dell'imbottitura 32 bit al fine di esso. Si noti che l'immagine a 24 bit (RGB) in informazioni sono memorizzate in ordine BGR. Anche se il valore di altezza non è negativo, l'immagine viene memorizzata capovolta.

Non ho dimestichezza con il formato di file BMP, ma non mi è necessario leggere le informazioni di intestazione prima? Qualcosa di simile:

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

e leggere le informazioni dettagliate in immagine, che avrete bisogno di:

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

e leggere le informazioni tavolozza pure.

Una volta che avete che si sa la dimensione del file e dati di correzione. Si potrebbe pre-allocare lo spazio sufficiente e leggere tutto in una volta, che può essere più semplice. In alternativa si potrebbe leggere in blocchi e analizzare come si sta andando (riduce la possibilità di non avere abbastanza memoria, ma l'analisi è più complicato).

Potrai anche sapere dalla sezione di informazioni se la compressione è attivata, le dimensioni di immagine, ecc.

Se stai leggendo in tutto in una volta, passa alla compensazione dei dati, e di fare qualcosa di simile:

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

e così via. Ovviamente questo codice non è il controllo per gli errori, fine del tampone, e così via, quindi avrai bisogno di farlo. Probabilmente dovrete anche leggere nelle informazioni tavolozza per dare un senso ai dati di immagine.

O, come qualcun altro ha detto, guarda il formato spec su Wikipedia

Se il file BMP ha una tavolozza poi il codice seguente dovrebbe di lavoro:

  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);
  }

Si potrebbe trovare utile guardare qualche codice C che ho scritto molti anni fa per la lettura e la scrittura di file BMP, che si trova all'indirizzo:

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

Credo che gestisce le varie dimensioni bit pixel (1/2/4/8/24) così come la compressione RLE.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top