PDA

Visualizza la versione completa : [C++] Scrittura file bitmap (.bmp) e problema con header


KoutaOyamada
11-02-2011, 12:18
Ciao a tutti, mi sono appena iscritto e ho un problemino con gli header BMP. Volevo imparare a scrivere immagini bmp in c++ e cosė ho fatto un programmino di prova dove ho riprodotto la struttura dell'header seguendo lo schema di wikipedia. Questo programmino ti fa inserire le dimensioni dell'immagine e la genera riempiendola di rosso. Il problema č che per qualche strano motivo se l'immagine supera i 51x51 il programma comincia a comportarsi in modo strano:
51x51 = immagine corrotta
52x52 e oltre = si vede ma i pixel sono tutti sfasati (ogni riga di pixel č di un colore diverso, suppongo che manchi qualche byte da qualche parte che fa sfasare tutto)

Inizialmente ho pensato che l'array dei pixel si fosse incasinato, ma stampandolo sembra tutto a posto. Non riesco proprio a capire quale sia il problema, eccovi il source:

pastebin ---> Click (http://pastebin.com/5NgpeGMM)

#include <iostream>
#include <stdio.h>
#include <conio.h>
using namespace std;

#pragma pack(1) // Serve a non far sfasare l'allineamento dei byte
struct BITMAP_HEADER {
struct BITMAPFILEHEADER {
unsigned short signature;
unsigned long size;
unsigned short reserved1;
unsigned short reserved2;
unsigned long file_offset;
} bmp_header;

struct BITMAPV5HEADER {
unsigned long header_size;
unsigned long width;
unsigned long height;
unsigned short planes;
unsigned short bit_per_pix;
unsigned long compression;
unsigned long image_size;
unsigned long x_pix_per_m;
unsigned long y_pix_per_m;
unsigned long colors;
unsigned long important_colors;
} dib_header;
};

struct PIXEL {
unsigned char b;
unsigned char g;
unsigned char r;
};
#pragma pack()

int main() {
unsigned long width, height, imagesize;
PIXEL *pixels;
FILE *file;

cout << "Inserisci la larghezza dell'immagine: ";
cin >> width;
cout << "Inserisci l'altezza dell'immagine: ";
cin >> height;
imagesize = width*height;

cout << "\nPopolando i pixel... ";
pixels = new PIXEL[imagesize];
for(int i=0; i<imagesize; i++){
pixels[i].r = 0xFF; // Rosso
pixels[i].g = 0;
pixels[i].b = 0;
}
cout << "Fatto!\n";

cout << "Generando l'header... ";
BITMAP_HEADER header;
unsigned short padding = 0; // Padding, separatore delle righe

// BMP Header
header.bmp_header.signature = 0x4D42; // BM (Windows)
header.bmp_header.size = sizeof(header) + sizeof(PIXEL)*imagesize + sizeof(padding)*height + 2;
header.bmp_header.reserved1 = 0;
header.bmp_header.reserved2 = 0;
header.bmp_header.file_offset = 54;

// DIB Header
header.dib_header.header_size = 40;
header.dib_header.width = width;
header.dib_header.height = height;
header.dib_header.planes = 1;
header.dib_header.bit_per_pix = 24;
header.dib_header.compression = 0; // BI_RGB
header.dib_header.image_size = sizeof(PIXEL)*imagesize + sizeof(padding)*height;
header.dib_header.x_pix_per_m = 2835;
header.dib_header.y_pix_per_m = 2835;
header.dib_header.colors = 0;
header.dib_header.important_colors = 0;
cout << "Fatto!\n";

cout << "Creando il file... ";
file = fopen("test.bmp", "wb");
if(file != NULL){
cout << "Creato!\n";

// Header
cout << "Scrivendo l'header su file... ";
fwrite (&header, sizeof(header), 1, file); // Resto dell'Header
cout << "Fatto! (" << sizeof(header) << " bytes)\n";

// Pixels
cout << "Scrivendo l'immagine... ";
unsigned long pos = width * height; // Parte dall'ultima riga di pixels
while (pos != 0) {
for (unsigned long n = 0; n<width; n++) // Scrive tutti i pixel della riga
fwrite (&pixels[pos - width + n], sizeof(PIXEL), 1, file);
fwrite (&padding, sizeof(padding), 1, file); // 2 Bytes di Padding
pos -= width; // Va indietro di una riga
}
cout << "Fatto! (" << header.dib_header.image_size << " bytes)\n";
cout << "Dimensione totale file: " << header.bmp_header.size << " bytes.\n";
} else cout << "Errore Scrittura!\n";
delete[] pixels;

getch();
return 0;
}

linoma
11-02-2011, 19:47
Credo che il problema sia nel salvataggio di ogni riga della tua bitmap, se nn sbaglio deve essere multiplo di 2, credo che sia sbagliato il padding.

KoutaOyamada
13-02-2011, 10:36
Originariamente inviato da linoma
Credo che il problema sia nel salvataggio di ogni riga della tua bitmap, se nn sbaglio deve essere multiplo di 2, credo che sia sbagliato il padding.

Grazie! Finalmente ho capito l'unica cosa che mi mancava del formato bitmap! Il padding arrotonda la dimensione dele righe a multiplo di 4! Bastava fare un padding di 1 byte e scriverlo width%4 volte!

Loading