Franc[e]sco
11-02-2011, 09:51
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:
EDIT: Corretti alcuni errori con le dimensioni ma continua a dare lo stesso problema e con dimensioni piu piccole adesso
RI-EDIT: L'ho riprogrammato con l'alloineamento di bytes corretto ma continua a dare lo stesso problema x_x
RI-RI-EDIT: Riprogrammato utilizzando le struct degi header fornite in Windows.h, solito problema x___x
pastebin -> Click (http://pastebin.com/Amhe0V87)
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <Windows.h>
using namespace std;
int main() {
unsigned long width = 0,
height = 0,
imagesize = 0;
PBITMAPFILEHEADER h = NULL;
PBITMAPINFOHEADER p = NULL;
RGBTRIPLE *pixels = NULL;
FILE *file = NULL;
WORD padding = 0; // Padding, separatore delle righe
cout << "Inserisci la larghezza dell'immagine: ";
cin >> width;
cout << "Inserisci l'altezza dell'immagine: ";
cin >> height;
imagesize = width*height;
cout << "\nPopolando " << imagesize << " pixels... ";
pixels = new RGBTRIPLE[imagesize];
ZeroMemory(pixels, sizeof(RGBTRIPLE)*imagesize);
if(pixels != NULL){
for(unsigned long i=0; i<imagesize; i++){
pixels[i].rgbtBlue = 0;
pixels[i].rgbtGreen = 0;
pixels[i].rgbtRed = 0xFF; // Rosso
}
cout << "Fatto!\n";
} else cout << "Errore - Array dei pixel non allocato.\n";
cout << "Generando l'header... ";
// BMP Header
h = new BITMAPFILEHEADER;
ZeroMemory(h, sizeof(BITMAPFILEHEADER));
h->bfType = 0x4D42; // BM (Windows)
h->bfSize = sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
sizeof(RGBTRIPLE)*imagesize +
sizeof(padding)*height;
h->bfOffBits = 54;
// DIB Header
p = new BITMAPINFOHEADER;
ZeroMemory(p, sizeof(BITMAPINFOHEADER));
p->biSize = 40;
p->biWidth = width;
p->biHeight = height;
p->biPlanes = 1;
p->biBitCount = 24;
p->biSizeImage = sizeof(RGBTRIPLE)*imagesize +
sizeof(padding)*height;
p->biXPelsPerMeter = 2835;
p->biYPelsPerMeter = 2835;
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... ";
if(h != NULL && p != NULL){
fwrite (h, sizeof(BITMAPFILEHEADER), 1, file); // BMP Header
fwrite (p, sizeof(BITMAPINFOHEADER), 1, file); // DIB Header
cout << "Fatto! (" << sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) << " bytes)\n";
// Pixels
cout << "Scrivendo l'immagine... ";
if(pixels != NULL){
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(RGBTRIPLE), 1, file);
fwrite (&padding, sizeof(padding), 1, file); // 2 Bytes di Padding
pos -= width; // Va indietro di una riga
}
cout << "\nFatto! (" << p->biSizeImage << " bytes)\n";
} else cout << "Errore - Array dei pixel non allocato.\n";
} else cout << "Errore - Header non allocato.\n";
cout << "Dimensione totale file: " << h->bfSize << " bytes.\n";
} else cout << "Errore Scrittura!\n";
// Cleanup Memoria
delete[] pixels;
delete(h);
delete(p);
_getch();
return 0;
}
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:
EDIT: Corretti alcuni errori con le dimensioni ma continua a dare lo stesso problema e con dimensioni piu piccole adesso
RI-EDIT: L'ho riprogrammato con l'alloineamento di bytes corretto ma continua a dare lo stesso problema x_x
RI-RI-EDIT: Riprogrammato utilizzando le struct degi header fornite in Windows.h, solito problema x___x
pastebin -> Click (http://pastebin.com/Amhe0V87)
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <Windows.h>
using namespace std;
int main() {
unsigned long width = 0,
height = 0,
imagesize = 0;
PBITMAPFILEHEADER h = NULL;
PBITMAPINFOHEADER p = NULL;
RGBTRIPLE *pixels = NULL;
FILE *file = NULL;
WORD padding = 0; // Padding, separatore delle righe
cout << "Inserisci la larghezza dell'immagine: ";
cin >> width;
cout << "Inserisci l'altezza dell'immagine: ";
cin >> height;
imagesize = width*height;
cout << "\nPopolando " << imagesize << " pixels... ";
pixels = new RGBTRIPLE[imagesize];
ZeroMemory(pixels, sizeof(RGBTRIPLE)*imagesize);
if(pixels != NULL){
for(unsigned long i=0; i<imagesize; i++){
pixels[i].rgbtBlue = 0;
pixels[i].rgbtGreen = 0;
pixels[i].rgbtRed = 0xFF; // Rosso
}
cout << "Fatto!\n";
} else cout << "Errore - Array dei pixel non allocato.\n";
cout << "Generando l'header... ";
// BMP Header
h = new BITMAPFILEHEADER;
ZeroMemory(h, sizeof(BITMAPFILEHEADER));
h->bfType = 0x4D42; // BM (Windows)
h->bfSize = sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
sizeof(RGBTRIPLE)*imagesize +
sizeof(padding)*height;
h->bfOffBits = 54;
// DIB Header
p = new BITMAPINFOHEADER;
ZeroMemory(p, sizeof(BITMAPINFOHEADER));
p->biSize = 40;
p->biWidth = width;
p->biHeight = height;
p->biPlanes = 1;
p->biBitCount = 24;
p->biSizeImage = sizeof(RGBTRIPLE)*imagesize +
sizeof(padding)*height;
p->biXPelsPerMeter = 2835;
p->biYPelsPerMeter = 2835;
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... ";
if(h != NULL && p != NULL){
fwrite (h, sizeof(BITMAPFILEHEADER), 1, file); // BMP Header
fwrite (p, sizeof(BITMAPINFOHEADER), 1, file); // DIB Header
cout << "Fatto! (" << sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) << " bytes)\n";
// Pixels
cout << "Scrivendo l'immagine... ";
if(pixels != NULL){
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(RGBTRIPLE), 1, file);
fwrite (&padding, sizeof(padding), 1, file); // 2 Bytes di Padding
pos -= width; // Va indietro di una riga
}
cout << "\nFatto! (" << p->biSizeImage << " bytes)\n";
} else cout << "Errore - Array dei pixel non allocato.\n";
} else cout << "Errore - Header non allocato.\n";
cout << "Dimensione totale file: " << h->bfSize << " bytes.\n";
} else cout << "Errore Scrittura!\n";
// Cleanup Memoria
delete[] pixels;
delete(h);
delete(p);
_getch();
return 0;
}