[C] Wczytywanie bitmapy - problem

0

Witam serdecznie
Mam do napisania pewien projekcik związany z kompresją plików graficznych zapisanych w formacie BMP. Na samym początku pojawił się problem z wczytywaniem bitmapy, podsyłam mój kod (praktycznie znalezione na forum):

#include <stdio.h>
#include <stdlib.h>

struct FileHeader {
  short bfType;
  int bfSize;
  short bfReserved1;
  short bfReserved2;
  short bfOffBits;
  }File;
   
struct PictureHeader {
  int biSize;
  int biWidth;
  int biHeight;
  short biPlanes;
  short biBitCount;
  int biCompression;
  int biSizeImage;
  int biXPelsPerMeter;
  int biYPelsPerMeter;
  int biClrUsed;
  int biClrImportant;
  }Picture;

void readBMP(){
    FILE *bmpFile = fopen("bitmapa.bmp", "rb");
    system("cls");
    printf("\n INFORMACJE O BITMAPIE\n\n"); 
    fread(&File.bfType,sizeof(File.bfType),1,bmpFile);
    printf(" Typ: %x",File.bfType);

    fread(&File.bfSize,sizeof(File.bfSize),1,bmpFile);
    printf("\n Rozmiar pliku: %d bajtow",File.bfSize);
   
    fread(&File.bfReserved1,sizeof(File.bfReserved1),1,bmpFile);
    printf("\n Zarezerwowane1: %d",File.bfReserved1);
         
    fread(&File.bfReserved2,sizeof(File.bfReserved2),1,bmpFile);
    printf("\n Zarezerwowane2: %d",File.bfReserved2);
     
    fread(&File.bfOffBits,sizeof(File.bfOffBits),1,bmpFile);
    printf("\n Pozycja danych obrazkowych: %d",File.bfOffBits);   
    
    printf("\n"); 
    fseek(bmpFile,14,SEEK_SET);
    fread(&Picture.biSize,sizeof(Picture.biSize),1,bmpFile);
    printf("\n Wielkosc naglowka informacyjnego: %d",Picture.biSize);   

    fread(&Picture.biWidth,sizeof(Picture.biWidth),1,bmpFile);
    printf("\n Szerokosc: %d pikseli",Picture.biWidth);

    fread(&Picture.biHeight,sizeof(Picture.biHeight),1,bmpFile);
    printf("\n Wysokosc: %d pikseli",Picture.biHeight);  
     
    fread(&Picture.biPlanes,sizeof(Picture.biPlanes),1,bmpFile);
    printf("\n Liczba platow (zwykle 0): %d",Picture.biPlanes);
     
    fread(&Picture.biBitCount,sizeof(Picture.biBitCount),1,bmpFile);
    printf("\n Liczba bitow na piksel: %d (1, 4, 8, or 24)",Picture.biBitCount); 
   
    fread(&Picture.biCompression,sizeof(Picture.biCompression),1,bmpFile);
    printf("\n Kompresja: %d (0=none, 1=RLE-8, 2=RLE-4)",Picture.biCompression);

    fread(&Picture.biSizeImage,sizeof(Picture.biSizeImage),1,bmpFile);
    printf("\n Rozmiar samego rysunku: %d",Picture.biSizeImage);

     
    fread(&Picture.biXPelsPerMeter,sizeof(Picture.biXPelsPerMeter),1,bmpFile);
    printf("\n Rozdzielczosc pozioma: %d",Picture.biXPelsPerMeter);    
   
    fread(&Picture.biYPelsPerMeter,sizeof(Picture.biYPelsPerMeter),1,bmpFile);
    printf("\n Rozdzielczosc pionowa: %d",Picture.biYPelsPerMeter);
     
    fread(&Picture.biClrUsed,sizeof(Picture.biClrUsed),1,bmpFile);
    printf("\n Liczba kolorow w palecie: %d",Picture.biClrUsed);
     
    fread(&Picture.biClrImportant,sizeof(Picture.biClrImportant),1,bmpFile);
    printf("\n Wazne kolory w palecie: %d",Picture.biClrImportant);
    fclose(bmpFile);
    }

int main(int argc, char *argv[])
{
  
  unsigned int i, j=0, k=0, p=0;
  //----------------------------------------------------------------------------Wczytywanie danych o bitmapie
  readBMP(); 
  printf("\n");
  //----------------------------------------------------------------------------Czytanie danych obrazka
  //printf("\n\n Dane obrazka:\n\n");
  FILE *bmpFile = fopen("bitmapa.bmp", "rb");
  unsigned char bmpImg;
  //int tabSize=Picture.biSizeImage/4;
  //unsigned char red[tabSize], green[tabSize], blue[tabSize];
  fseek(bmpFile,File.bfOffBits,SEEK_SET);
  for (i = File.bfOffBits; i < File.bfSize; i++) { 
      if(!(j%4)){
          printf("\n%3d  ", j/4);
          }
      fseek(bmpFile,i,SEEK_SET);
      fread(&bmpImg, 1, 1, bmpFile);
      printf("%.3d   ",bmpImg); 
      j++;
      }

  printf("\n\n");
  system("PAUSE");	
  return 0;
}

Program pobiera kolory z pliku "bitmapa.bmp" i teraz mam wątpliwości. Z tego co czytałem kolory powinny być zapisane jako "RGBx" a są chyba zapisane "RGBRGB...RGBxxx" przy czym ilość powtórzeń składowych pojedynczego koloru (RGB) odpowiada długości linii, i na końcu linii dopisywane są trzy bajty zer (testowałem na pliku 7x6 pixeli).
Druga sprawa - kolory są zapisywane jako RGB czy BGR? Bo z tego co zauważyłem wychodzi chyba BGR.
Z góry dziękuję za wszelką pomoc

0

Kolory w bitmapie 24bitowej (RGB po 8 bitów kolor, 24bity na piksel) są zapisane w kolejności BGR tak jak słusznie zauważyłeś.
Bezpośrednio po nagłówku są sekwencje bajtów ostatniej linii obrazka (w bmp ostatnia linia jest zapisywana na początku pliku) wygląda to mniej więcej tak:

{nagłówek}BGRBGRBGR...

w strukturach opisujących nagłówek bym dodał unsigned, O ile dobrze pamiętam wartości w polach nagłówkach są zapisywane jako liczby dodatnie, a nie U2. Nie jestem na 100% pewien, że to błąd, ale jak ja robiłem wczytywanie bitmapy to dawałem unsigned.

0

Z tego co czytałem kolory powinny być zapisane jako "RGBx" a są chyba zapisane "RGBRGB...RGBxxx" przy czym ilość powtórzeń składowych pojedynczego koloru (RGB) odpowiada długości linii, i na końcu linii dopisywane są trzy bajty zer (testowałem na pliku 7x6 pixeli).

Każdy wiersz bitmapy RGB (scanline) musi być wyrównany do wielokrotności czterech bajtów, stąd te trzy bajty na końcu.

0

Dzięki ludzie :-) Już sobie poradziłem z problemem (wczoraj wieczorkiem odpaliłem kompresję bitmapy algorytmem RLE)
Pozdrawiam

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