Bitmapy, wczytywanie plików, double buffer 1 Wstęp teoretyczny

Transkrypt

Bitmapy, wczytywanie plików, double buffer 1 Wstęp teoretyczny
Grafika komputerowa 2D
Instrukcja
laboratoryjna
5
Temat: Bitmapy, wczytywanie plików, double buffer
Przygotował: dr inż. Grzegorz Łukawski, mgr inż. Maciej Lasota, mgr inż. Tomasz
Michno
1 Wstęp teoretyczny
Biblioteka Allegro wraz z wywołaniem funkcji set_gfx_mode tworzy w pamięci bitmapę
o nazwie screen, reprezentującą obszar ekranu na którym można rysować. Biblioteka dostarcza
również możliwość tworzenia własnych bitmap przez użytkownika. Możemy je podzielić na:
•
Memory Bitmap (standardowa bitmapa przechowywana w pamięci RAM)
•
Sub Bitmap (bitmapa potomna, będąca częścią bitmapy-rodzica)
•
Video Memory Bitmap (specjalny rodzaj bitmap, wykorzystywany np. w grach,
dostosowany do sprzętowego wspomagania niektórych operacji)
•
System Bitmap (specjalny rodzaj bitmap, który zawiera część cech zwykłych bitmap (np.
przechowywanie w pamięci RAM) oraz bitmap typu video)
Więcej o różnicach pomiędzy powyższymi typami bitmap:
http://www.allegro.cc/manual/4/api/bitmap-objects/
Każda bitmapa w Allegro jest reprezentowana przez typ BITMAP, który ma następującą strukturę:
typedef struct BITMAP
int w, h;
int clip;
int cl, cr, ct, cb;
clip !=)
unsigned char *line[];
- rozmiar bitmapy w pikselach (w- szer., h- wys.)
- !=0, jeśli włączono obcinanie
- współrzędne prostokąta obcinającego (używane jeśli
- wskaźniki na początek każdej linii obrazu
1.1 Tworzenie bitmap
Bitmapy można tworzyć wywołując funkcję CreateBitmap:
BITMAP *create_bitmap(int width, int height);
gdzie:
width – szerokość
height – wysokość
1/6
Jeśli tworzenie zakończyło się pomyślnie, funkcja zwraca wskaźnik na bitmapę, w przeciwnym
wypadku wartość NULL.
Utworzone bitmapy należy zawsze usuwać z pamięci za pomocą funkcji destroy_bitmap:
void destroy_bitmap(BITMAP *bitmap);
Inne przydatne funkcje:
BITMAP *create_bitmap_ex(int color_depth, int Utworzenie zwykłej bitmapy o podanej
width, int height);
w parametrze color_depth głębi kolorów
BITMAP
*create_sub_bitmap(BITMAP Utworzenie sub-bitmapy, jako parametry
*parent, int x, y, width, height);
należy podać: wskaźnik na bitmapę- rodzica,
oraz prostokąt obcinający - punkt startowy
(x,y) oraz rozmiar (width, height)
BITMAP *create_video_bitmap(int width, int Utworzenie bitmapy typu video-bitmap
height);
BITMAP *create_system_bitmap(int width, int Utworzenie bitmapy systemowej
height);
void set_clip_rect(BITMAP *bitmap, int x1, int Ustawienie prostokąta obcinającego dla
y1, int x2, int y2);
bitmapy
void set_color_depth(int depth);
Ustawienie głębi bitowej dla ekranu
aplikacji i bitmap, należy wywoływać ją
przed funkcją set_gfx_mode() (na początku
aplilacji)
1.2 Obsługa plików graficznych
Biblioteka Allegro posiada zaimplementowane funkcje służące do odczytu i zapisu plików
graficznych. Obsługiwane formaty to: BMP, PCX, TGA i LBM.
Do wczytywania bitmapy służy funkcja load_bitmap:
BITMAP *load_bitmap(const char *filename, RGB *pal);
gdzie:
filename – ścieżka dostępu do pliku
2/6
pal – tablica (o rozmiarze 256), która będzie przechowywała paletę obrazu; można użyć zmiennej
typu PALETTE.
Każdą wczytaną bitmapę należy po użyciu usuwać z pamięci za pomocą destroy_bitmap.
Przykład użycia (zaczerpnięty z dokumentacji: http://www.allegro.cc/manual/4/api/loading-imagefiles/load_bitmap):
BITMAP *bmp;
PALETTE palette;
...
bmp = load_bitmap("image.pcx", palette);
if (!bmp)
abort_on_error("Couldn't load image.pcx!");
...
destroy_bitmap(bmp);
Bitmapy można zapisywać do pliku za pomocą save_bitmap:
int save_bitmap(const char *filename, BITMAP *bmp, const RGB *pal);
gdzie:
filename – ścieżka do pliku do zapisu
bmp – wskaźnik na bitmapę, która ma zostać zapisana
pal – paleta (można ją uzyskać za pomocą funkcji get_palette(PALETTE p)).
1.3 Kopiowanie prostokątnych obszarów pomiędzy bitmapami
W celu skopiowania prostokątnego obszaru jednej bitmapy do drugiej bitmapy, wywołujemy
funkcję blit:
void blit(BITMAP *source, BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int
width, int height);
gdzie:
source – bitmapa źródłowa
dest – bitmapa docelowa (bitmapa źródłowa i docelowa może też być tą samą bitmapą)
source_x, source_y – lewy górny punkt kopiowanego obszaru
dest_x, dest_y – lewy górny punkt obszaru docelowego
width, height – szerokość i wysokość prostokąta
Funkcja blit jest wykorzystywana w technice Doble Buffering'u (Podwójnego Buforowania). Polega
ona na używaniu do płynnego wyświetlania obrazu na ekranie dwóch buforów o tym samym
3/6
rozmiarze. Bufory wyświetlane są na ekranie naprzemiennie, przy czym rysowanie klatki odbywa
się zawsze na niewidocznym buforze. Dzięki temu unika się m. in. migotania obrazu i artefaktów.
W bibliotece Allegro jednym buforem może być bitmapa screen, a drugim dowolna bitmapa
o rozmiarze ekranu. Obraz rysowany jest na drugiej bitmapie, a następnie za pomocą funkcji blit
jest kopiowany na ekran (pierwszą bitmapę – screen).
1.4 Duszki – Sprite'y
Sprite'y są specjalnymi rodzajami bitmap, które najczęściej służą do tworzenia postaci lub innych
elementów wyświetlanych na ekranie (np. z wykorzystaniem transformacji 2D). W bibliotece
Allegro obsługuje się je identycznie jak zwykłe bitmapy. Dodatkowo udostępnione są następujące
funkcje:
void draw_sprite(BITMAP *bmp, BITMAP Rysuje sprite'a na bitmapie bmp w punkcie
*sprite, int x, int y);
określonym przez x oraz y
void stretch_sprite(BITMAP *bmp, BITMAP Pozwala narysować sprite'a, zmieniając jego
*sprite, int x, int y, int w, int h);
rozmiar. Parametry:
w – nowa szerokość
h – nowa wysokość
void rotate_sprite(BITMAP *bmp, BITMAP Rysuje sprite'a obróconego o kąt angle
*sprite, int x, int y, fixed angle);
void pivot_sprite(BITMAP *bmp, BITMAP Rysuje sprite'a obróconego
*sprite, int x, int y, int cx, int cy, fixed angle);
względem punktu cx, cy
o kąt
void
draw_sprite_v_flip(BITMAP
BITMAP *sprite, int x, int y);
*bmp, Rysuje sprite'a z obróceniem pionowym
void
draw_sprite_h_flip(BITMAP
BITMAP *sprite, int x, int y);
*bmp, Rysuje sprite'a z obróceniem poziomym
void draw_sprite_vh_flip(BITMAP
BITMAP *sprite, int x, int y);
*bmp, Rysuje sprite'a
i poziomym
z obróceniem
angle
pionowym
void rotate_scaled_sprite(BITMAP *bmp, Rysuje sprite'a obróconego o kąt angle oraz
BITMAP *sprite, int x, int y, fixed angle, fixed przeskalowanego przez współczynnik scale
scale);
void pivot_scaled_sprite(BITMAP *bmp, Rysuje sprite'a obróconego o kąt angle
BITMAP *sprite, int x, int y, int cx, int cy, fixed względem punktu cx, cy oraz przeskalowanego
angle, fixed scale);
przez współczynnik scale
4/6
void stretch_blit(BITMAP *source, BITMAP Funkcja blit z możliwością zmiany rozmiaru
*dest, int source_x, source_y, source_width, prostokąta na bitmapie docelowej
source_height, int dest_x, dest_y, dest_width,
dest_height);
W powyższych funkcjach przy obrotach pojawia się typ fixed, który przyjmuje wartości od 0 do
256 (0 – brak obrotu, 256 – pełny obrót). Aby ułatwić sobie zadanie, warto zadeklarować zmienną
typu float, przechowującą kąt, a następnie użyć funkcji itofix(liczba), która zamieni ją na typ fixed,
np.:
float kat = 0;
// ...
rotate_sprite(screen, bitmapa, 0, 0, itofix(kat));
Zmienną kat możemy zwiększać lub zmniejszać o małe kroki, dzięki czemu uzyskamy płynny obrót
(należy pamiętać, że kąt może mieć wartości tylko z przedziału od 0 do 256), np.:
kat += 0.5;
if (kat > 256) kat = 0;
Przezroczystość tła sprite'a:
Często sprite'y służą do przechowywania np. postaci lub innych elementów planszy w grach.
Pojawia się wtedy problem z tłem, które po wstawieniu obrazka do aplikacji przesłania elementy za
postacią. Twórcy biblioteki Allegro wymyślili bardzo prosty sposób na ten problem – uznali, że
kolor różowy (255, 0, 255) będzie tak rzadko używany, że uznają go za domyślny kolor
przezroczystości przy rysowaniu sprite'a
Jak widać na przykładzie – sprite biegnącego konia ma różowe tło, po narysowaniu go w programie
5/6
z użyciem draw_sprite, jest ono automatycznie usuwane.
2 Zadania
1. Napisz program, który będzie:
◦ wyświetlał obraz wczytany z pliku w całym oknie aplikacji
◦ wyświetlał na tle pierwszego obrazka dowolny sprite wczytany z dysku
◦ sprite powinien być przesuwany po ekranie w dowolny sposób (automatycznie, bez
interakcji użytkownika)
2. Napisz program który będzie:
◦ wczytywał dowolny plik z dysku
◦ pozwalał z użyciem dowolnie wybranego zestawu klawiszy na wykonywanie jednej
z podanych operacji: obrotu, skalowania lub odwrócenia poziomego i pionowego
◦ zapisywał zawartość ekranu do dowolnego pliku
6/6