From 9af911808bde2b6aa26384cd4b1dcf697b68a2ca Mon Sep 17 00:00:00 2001 From: cybermind <iddqd_mail@mail.ru> Date: Sun, 31 Mar 2013 14:59:38 +0600 Subject: [PATCH] [*] Grayscale works in OpenGL too --- src/include/icons.h | 1 + src/include/video.h | 4 ++-- src/ui/icons.cpp | 25 +++++------------------ src/video/graphic.cpp | 46 ++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/include/icons.h b/src/include/icons.h index 94a410799..f97a237dc 100644 --- a/src/include/icons.h +++ b/src/include/icons.h @@ -126,6 +126,7 @@ public: public: CGraphic *G; /// Graphic data + CGraphic *GrayScale; /// Icon when drawn grayscaled int Frame; /// Frame number in graphic private: std::string Ident; /// Icon identifier diff --git a/src/include/video.h b/src/include/video.h index a86ae566b..020b4f3f7 100644 --- a/src/include/video.h +++ b/src/include/video.h @@ -107,11 +107,11 @@ public: static CGraphic *New(const std::string &file, int w = 0, int h = 0); static CGraphic *ForceNew(const std::string &file, int w = 0, int h = 0); - CGraphic *Clone() const; + CGraphic *Clone(bool grayscale = false) const; static void Free(CGraphic *g); - void Load(); + void Load(bool grayscale = false); void Flip(); void UseDisplayFormat(); void Resize(int w, int h); diff --git a/src/ui/icons.cpp b/src/ui/icons.cpp index 448d34238..8307f089f 100644 --- a/src/ui/icons.cpp +++ b/src/ui/icons.cpp @@ -60,7 +60,7 @@ static IconMap Icons; /// Map of ident to icon. /** ** CIcon constructor */ -CIcon::CIcon(const std::string &ident) : G(NULL), Frame(0), Ident(ident) +CIcon::CIcon(const std::string &ident) : G(NULL), GrayScale(NULL), Frame(0), Ident(ident) { } @@ -70,6 +70,7 @@ CIcon::CIcon(const std::string &ident) : G(NULL), Frame(0), Ident(ident) CIcon::~CIcon() { CGraphic::Free(this->G); + CGraphic::Free(this->GrayScale); } /** @@ -111,6 +112,7 @@ void CIcon::Load() { Assert(G); G->Load(); + GrayScale = G->Clone(true); if (Frame >= G->NumFrames) { DebugPrint("Invalid icon frame: %s - %d\n" _C_ Ident.c_str() _C_ Frame); Frame = 0; @@ -134,30 +136,13 @@ void CIcon::DrawIcon(const CPlayer &player, const PixelPos &pos) const } /** -** Draw icon at pos. +** Draw grayscale icon at pos. ** ** @param pos display pixel position */ void CIcon::DrawGrayscaleIcon(const PixelPos &pos) const { - SDL_LockSurface(this->G->Surface); - SDL_Color colors[256], backup[256]; - SDL_Palette &pal = *this->G->Surface->format->palette; - memcpy(backup, pal.colors, sizeof(SDL_Color) * 256); - for (int i = 0; i < 256; ++i) { - int gray = 0.21 * pal.colors[i].r + 0.72 * pal.colors[i].g + 0.07 * pal.colors[i].b; - colors[i].r = colors[i].g = colors[i].b = gray; - } - SDL_SetColors(this->G->Surface, &colors[0], 0, 256); - if (this->G->SurfaceFlip) { - SDL_SetColors(this->G->SurfaceFlip, &colors[0], 0, 256); - } - SDL_UnlockSurface(this->G->Surface); - this->G->DrawFrameClip(this->Frame, pos.x, pos.y); - SDL_LockSurface(this->G->Surface); - SDL_SetColors(this->G->Surface, &backup[0], 0, 256); - SDL_UnlockSurface(this->G->Surface); - + this->GrayScale->DrawFrameClip(this->Frame, pos.x, pos.y); } /** diff --git a/src/video/graphic.cpp b/src/video/graphic.cpp index 385826a2a..c609b0ba5 100644 --- a/src/video/graphic.cpp +++ b/src/video/graphic.cpp @@ -587,13 +587,15 @@ CGraphic *CGraphic::ForceNew(const std::string &file, int w, int h) /** ** Clone a graphic +** +** @param grayscale Make grayscale texture */ -CGraphic *CGraphic::Clone() const +CGraphic *CGraphic::Clone(bool grayscale) const { CGraphic *g = CGraphic::ForceNew(this->File, this->Width, this->Height); if (this->IsLoaded()) { - g->Load(); + g->Load(grayscale); } return g; @@ -664,8 +666,10 @@ void CGraphic::GenFramesMap() /** ** Load a graphic +** +** @param grayscale Make a grayscale surface */ -void CGraphic::Load() +void CGraphic::Load(bool grayscale) { if (Surface) { return; @@ -700,6 +704,42 @@ void CGraphic::Load() NumFrames = GraphicWidth / Width * GraphicHeight / Height; + if (grayscale) { + SDL_LockSurface(Surface); + const SDL_PixelFormat *f = Surface->format; + const int bpp = Surface->format->BytesPerPixel; + const double redGray = 0.21; + const double greenGray = 0.72; + const double blueGray = 0.07; + switch (bpp) { + case 1: { + SDL_Color colors[256]; + SDL_Palette &pal = *Surface->format->palette; + for (int i = 0; i < 256; ++i) { + const int gray = redGray * pal.colors[i].r + greenGray * pal.colors[i].g + blueGray * pal.colors[i].b; + colors[i].r = colors[i].g = colors[i].b = gray; + } + SDL_SetColors(Surface, &colors[0], 0, 256); + break; + } + case 4: { + Uint32* p; + for (int i = 0; i < Height; ++i) { + for (int j = 0; j < Width; ++j) { + p = (Uint32 *)(Surface->pixels) + i * Width + j * bpp; + const Uint32 gray = ((Uint8)((*p) * redGray) >> f->Rshift) + + ((Uint8)(*(p + 1) * greenGray) >> f->Gshift) + + ((Uint8)(*(p + 2) * blueGray) >> f->Bshift) + + ((Uint8)(*(p + 3)) >> f->Ashift); + *p = gray; + } + } + break; + } + } + SDL_UnlockSurface(Surface); + } + #if defined(USE_OPENGL) || defined(USE_GLES) if (UseOpenGL) { MakeTexture(this);