Problem z wczytywaniem formatu BMP

0

Witam, piszę program który ma wczytać w trybie binarnym plik w formacie bmp a następnie go odwrócić. W specyfikacji formatu bmp doczytałem że każdy wiersz jest wyrównywany do 4 bajtów. Więc napisałem taki fragment kodu który wczytuje plik:

 
struct Pixel
{
 unsigned char b, g, r;
};

...

 ifstream ifs("widok3.bmp", ios::binary);
 
 char* temp = new char[sizeof(BITMAPFILEHEADER)];
 ifs.read(temp, sizeof(BITMAPFILEHEADER));
 BITMAPFILEHEADER* bfh = (BITMAPFILEHEADER*)(temp);
 
 
 temp = new char[sizeof(BITMAPINFOHEADER)];
 ifs.read(temp, sizeof(BITMAPINFOHEADER));
 BITMAPINFOHEADER* bih = (BITMAPINFOHEADER*)(temp);

 
 ifs.seekg(bfh->bfOffBits, ios::beg); // bfOffBits wskazuje początek danych obrazka
 
 int width = bih->biWidth;
 if(width % 4) width += 4 - (width % 4); // piksele w bitmapie są wyrównywane do 4 bajtów
 
 Pixel** pixs = new Pixel*[bih->biHeight];
 for(int i=0; i<bih->biHeight; i++)
 {
   temp = new char[3*width];
   ifs.read(temp, 3*width);
   pixs[i] = (Pixel*)(temp); 
   
  }

Po takim wczytaniu obrazka o rozdzielczości 77x33 mam tablice 80x33 i wydawało mi się że 0 którymi uzupełniane są wiersze będą znajdować się w tablicy na pozycjach [0-32][77],[78],[79] a tymczasem są one ustawiane na końcu wiersza [31] i w całym wierszu [32]. Czy to jest błąd z wczytywaniem obrazka czy źle zrozumiałem budowę formatu bmp?

0

Jesteś pewien, że twój kod zaokrągla do 4 bajtów, a nie do 12?

Dodatkowo jeżeli masz zamiar wykorzystywać tę funkcję w większym programie, to obsługuj wyjątki, przy złym wczytaniu bitmapy memleaka masz gwarantowanego.

0

Eee czemu alokujesz i wczytujesz nagłówek DWA razy?
Zaokrąglanie w górę do wielokrotności 4:

width = (width+3) & ~3;
0

Dzięki za pomoc. Źle wyrównywałem do 4 bajtów. Poprawnie jest tak:

  
int width = bih->biWidth;
 if(width*3 % 4) width = (width*3) + 4 - ((width*3) % 4); // piksele w bitmapie są wyrównywane do 4 bajtów
 
 Pixel** pixs = new Pixel*[bih->biHeight];
 for(int i=0; i<bih->biHeight; i++)
 {
   temp = new char[width];
   ifs.read(temp, width);
   pixs[i] = (Pixel*)(temp); 
   
  }
0
  1. Bitmapa może mieć różny rozmiar pikseli: 1bpp, 8bpp, 16bpp, 24bpp, 32bpp (BITMAPINFOHEADER::biBitCount)

  2. Bitmapa może być skompresowana (BITMAPINFOHEADER::biCompression), trzeba to sprawdzić

  3. Nie, piksele nie są wyrównane do 4 bajtów, piksele leżą jedne przy drugich bez żadnych przerw np. w bitmapie monochromatycznej (1bpp) w jednym bajcie jest 8 pikseli

  4. Za to linia jest wyrównana do 4 bajtów

  5. Po co ta zmienna temp? Po co w ogóle alokujesz header'y na stercie? (pytanie retoryczne ofc)

1 użytkowników online, w tym zalogowanych: 0, gości: 1