programming_tutorials/16_sdl_image.txt

354 lines
12 KiB
Plaintext

Írjunk egy Kép osztályt:
Ez az osztály az SDL_Surface-eket segít majd nekünk kezelni.
A függvények pszeudokódja az UML diagram alatt található.
Amit fontos tudni, hogy egy SDL_Surface sok formátumot tud kezelni.
(Ezek elérhetőek az SDL_pixels.h-ban.)
Mi a kép osztályt úgy fogjuk megírni, hogy alapból csak az RGBA8888 formátumot tudja kezelni.
(SDL_PIXELFORMAT_RGBA8888 enum az SDL_pixels.h-ban.)
Ez azt jelenti, hogy minden pixel 1 byte-os, és egy pixel 4 színből áll,
r(red) g(green) b(blue) a(alpha) sorrendben.
(Pontosan ezért van a Color osztályban to_key, és form_key függvény.)
Szóval a kép adatai Uint8 tömbként:
r0, g0, b0, a0, r1, g1, b1, a1, ...
Ezt egy egy dimenziós tömbként kell tuni kezelni. Erre a képlet: "x * _surface->w + y"
|---------------------------------------------------------------------------------------|
| class Image |
|---------------------------------------------------------------------------------------|
| + void create(const Uint32 flags, const int width, const int height); |
| |
| + void enable_transparent_color(const Color &color); |
| + void disable_transparent_color(); |
| + bool has_transparent_color(); |
| + Color get_transparent_color(); |
| |
| + Color get_color_mod(); |
| + void set_color_mod(const Color &color); |
| |
| + Color get_alpha_mod(); |
| + void set_alpha_mod(const Uint8 alpha); |
| |
| + SDL_BlendMode get_blend_mode(); |
| + void set_blend_mode(const SDL_BlendMode mode); |
| |
| + Rect2 get_clip_rect(); |
| + void set_clip_rect(const Rect2 &rect); |
| |
| + void duplicate(Image *into); |
| |
| + void fill_rect(const Rect2 &rect, const Color &color); |
| + void fill_rects(const Vector<Rect2> &rects, const Color &color); |
| + void set_pixel(const int x, const int y, const Color &color); |
| + Color get_pixel(const int x, const int y); |
| |
| + void blit_surface(const Image &source, const Rect2 &srcrect, const Rect2 &dstrect); |
| |
| + void lock(); | -> a pixelek módosításához le kell zárni a surface-t,
| + void unlock(); | -> majd fel kell oldani
| |
| + void free(); |
| |
| + void load_bmp(const String &file_name); |
| + void save_bmp(const String &file_name); |
| |
| + Uint32 get_width() const; |
| + Uint32 get_height() const; |
| |
| + SDL_Surface *get_surface(); |
| |
| + Image(); |
| + Image(const String &file_name); |
| + virtual ~Image(); |
| |
| - SDL_Surface *_surface; |
|---------------------------------------------------------------------------------------|
------------------------------------------------------------------------------------------
create:
if (_surface):
free();
//SDL_PIXELFORMAT_RGBA8888 SDL_pixels.h ból
SDL_CreateRGBSurfaceWithFormat(flags, width, height, 32, SDL_PIXELFORMAT_RGBA8888);
------------------------------------------------------------------------------------------
enable_transparent_color:
if (!SDL_SetColorKey(_surface, 1, color.to_key())):
printf("enable_transparent_color error.\n");
------------------------------------------------------------------------------------------
disable_transparent_color:
if (!SDL_SetColorKey(_surface, 0, 0)):
printf("disable_transparent_color error.\n");
------------------------------------------------------------------------------------------
has_transparent_color:
return SDL_HasColorKey(_surface);
------------------------------------------------------------------------------------------
get_transparent_color:
uint32_t key;
SDL_GetColorKey(_surface, &key);
return Color(key);
------------------------------------------------------------------------------------------
get_color_mod:
Uint8 r;
Uint8 g;
Uint8 b;
SDL_GetSurfaceColorMod(_surface, &r, &g, &b);
return Color(r, g, b);
------------------------------------------------------------------------------------------
set_color_mod:
SDL_SetSurfaceColorMod(_surface, color.r, color.g, color.b);
------------------------------------------------------------------------------------------
get_alpha_mod:
Uint8 a;
SDL_GetSurfaceAlphaMod(_surface, &a);
return a;
------------------------------------------------------------------------------------------
set_alpha_mod:
SDL_SetSurfaceAlphaMod(_surface, alpha);
------------------------------------------------------------------------------------------
get_blend_mode:
SDL_BlendMode mode;
SDL_GetSurfaceBlendMode(_surface, &mode);
return mode;
------------------------------------------------------------------------------------------
set_blend_mode:
SDL_SetSurfaceBlendMode(_surface, mode);
------------------------------------------------------------------------------------------
get_clip_rect:
SDL_Rect r;
SDL_GetClipRect(_surface, &r);
Rect2 rect;
rect.x = r.x;
rect.y = r.y;
rect.w = r.w;
rect.h = r.h;
return rect;
------------------------------------------------------------------------------------------
set_clip_rect:
SDL_Rect r;
r.x = rect.x;
r.y = rect.y;
r.w = rect.w;
r.h = rect.h;
SDL_SetClipRect(_surface, &r);
------------------------------------------------------------------------------------------
duplicate:
if (into == nullptr):
return;
into->_surface = SDL_DuplicateSurface(_surface);
------------------------------------------------------------------------------------------
fill_rect:
SDL_Rect r;
r.x = rect.x;
r.y = rect.y;
r.w = rect.w;
r.h = rect.h;
SDL_FillRect(_surface, &r, color.to_key());
------------------------------------------------------------------------------------------
fill_rects:
SDL_Rect *r = new SDL_Rect[rects.size()];
for (int i = 0; i < rects.size(); ++i):
r[i].x = rects[i].x;
r[i].y = rects[i].y;
r[i].w = rects[i].w;
r[i].h = rects[i].h;
SDL_FillRects(_surface, r, rects.size(), color.to_key());
delete[] r;
------------------------------------------------------------------------------------------
set_pixel:
if (_surface == nullptr):
return;
Uint32 *p = reinterpret_cast<Uint32 *>(_surface->pixels);
p[x * _surface->w + y] = color.to_key();
Megj.:
(lehetne Uint8-á is castolni, akkor vissza lehetne szedni egyesével a pixelek értékeit,
nyilván ekkor az indexet-et meg kell szorozni 4-el. -> mivel 1 intben 4db byte van.)
(Uint8, és uint8_t, Uint32 és uint32_t ugyan az, csak az egyik az <int_types.h>/ban van, a másik az sdl/ben.)
------------------------------------------------------------------------------------------
get_pixel:
if (_surface == nullptr):
return Color();
Uint32 *p = reinterpret_cast<Uint32 *>(_surface->pixels);
return Color(p[x * _surface->w + y]);
set_pixel megjegyzése ide is érvényes.
------------------------------------------------------------------------------------------
blit_surface:
SDL_Rect sr;
sr.x = srcrect.x;
sr.y = srcrect.y;
sr.w = srcrect.w;
sr.h = srcrect.h;
SDL_Rect dr;
dr.x = dstrect.x;
dr.y = dstrect.y;
dr.w = dstrect.w;
dr.h = dstrect.h;
SDL_BlitSurface(source._surface, &sr, _surface, &dr);
------------------------------------------------------------------------------------------
lock:
SDL_LockSurface(_surface);
------------------------------------------------------------------------------------------
unlock:
SDL_UnlockSurface(_surface);
------------------------------------------------------------------------------------------
free:
SDL_FreeSurface(_surface);
_surface = nullptr;
Megj.:
Deallokálja a surface-t. Azért nem a destruktor csinálja ezt, mert közben is tudni
kell surface-eket deallokálni. Pl load_bmp(), etc
------------------------------------------------------------------------------------------
load_bmp:
if (_surface != nullptr):
free();
_surface = SDL_LoadBMP(file_name.c_str());
if (_surface != nullptr && _surface->format->format != SDL_PIXELFORMAT_RGBA8888):
//Nem ARGB8888 as formátum, konvertáljuk át
SDL_Surface *n = SDL_ConvertSurfaceFormat(_surface, SDL_PIXELFORMAT_RGBA8888, 0);
free();
_surface = n;
------------------------------------------------------------------------------------------
save_bmp:
SDL_SaveBMP(_surface, file_name.c_str());
------------------------------------------------------------------------------------------
get_width:
if (_surface == nullptr):
return 0;
return _surface->w;
------------------------------------------------------------------------------------------
get_height:
if (_surface == nullptr):
return 0;
return _surface->h;
------------------------------------------------------------------------------------------
get_surface:
return _surface;
------------------------------------------------------------------------------------------
Image():
_surface = nullptr;
------------------------------------------------------------------------------------------
Image(const String &file_name):
_surface = nullptr;
load_bmp(file_name);
------------------------------------------------------------------------------------------
~Image:
free();
------------------------------------------------------------------------------------------