Mercurial > sdl-ios-xcode
view src/video/SDL_gamma.c @ 1667:1fddae038bc8 SDL-1.3
Implemented many compatibility functions
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 29 May 2006 03:53:21 +0000 |
parents | 782fd950bd46 |
children | 4da1ee79c9af |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" /* Gamma correction support */ #ifdef HAVE_MATH_H #include <math.h> /* Used for calculating gamma ramps */ #else /* Math routines from uClibc: http://www.uclibc.org */ #include "math_private.h" #include "e_sqrt.h" #include "e_pow.h" #include "e_log.h" #define pow(x, y) __ieee754_pow(x, y) #define log(x) __ieee754_log(x) #endif #include "SDL_sysvideo.h" static void CalculateGammaRamp (float gamma, Uint16 * ramp) { int i; /* 0.0 gamma is all black */ if (gamma <= 0.0f) { for (i = 0; i < 256; ++i) { ramp[i] = 0; } return; } else /* 1.0 gamma is identity */ if (gamma >= 1.0f) { for (i = 0; i < 256; ++i) { ramp[i] = (i << 8) | i; } return; } else /* Calculate a real gamma ramp */ { int value; gamma = 1.0f / gamma; for (i = 0; i < 256; ++i) { value = (int) (pow ((double) i / 256.0, gamma) * 65535.0 + 0.5); if (value > 65535) { value = 65535; } ramp[i] = (Uint16) value; } } } static void CalculateGammaFromRamp (float *gamma, Uint16 * ramp) { /* The following is adapted from a post by Garrett Bass on OpenGL Gamedev list, March 4, 2000. */ float sum = 0.0f; int i, count = 0; *gamma = 1.0; for (i = 1; i < 256; ++i) { if ((ramp[i] != 0) && (ramp[i] != 65535)) { double B = (double) i / 256.0; double A = ramp[i] / 65535.0; sum += (float) (log (A) / log (B)); count++; } } if (count && sum > 0.0f) { *gamma = 1.0f / (sum / count); } } int SDL_SetGamma (float red, float green, float blue) { SDL_VideoDevice *_this = SDL_GetVideoDevice (); int succeeded; succeeded = -1; /* Prefer using SetGammaRamp(), as it's more flexible */ { Uint16 ramp[3][256]; CalculateGammaRamp (red, ramp[0]); CalculateGammaRamp (green, ramp[1]); CalculateGammaRamp (blue, ramp[2]); succeeded = SDL_SetGammaRamp (ramp[0], ramp[1], ramp[2]); } if ((succeeded < 0) && _this->SetGamma) { SDL_ClearError (); succeeded = _this->SetGamma (_this, red, green, blue); } return succeeded; } /* Calculating the gamma by integrating the gamma ramps isn't exact, so this function isn't officially supported. */ int SDL_GetGamma (float *red, float *green, float *blue) { SDL_VideoDevice *_this = SDL_GetVideoDevice (); int succeeded; succeeded = -1; /* Prefer using GetGammaRamp(), as it's more flexible */ { Uint16 ramp[3][256]; succeeded = SDL_GetGammaRamp (ramp[0], ramp[1], ramp[2]); if (succeeded >= 0) { CalculateGammaFromRamp (red, ramp[0]); CalculateGammaFromRamp (green, ramp[1]); CalculateGammaFromRamp (blue, ramp[2]); } } if ((succeeded < 0) && _this->GetGamma) { SDL_ClearError (); succeeded = _this->GetGamma (_this, red, green, blue); } return succeeded; } int SDL_SetGammaRamp (const Uint16 * red, const Uint16 * green, const Uint16 * blue) { SDL_VideoDevice *_this = SDL_GetVideoDevice (); int succeeded; SDL_Surface *screen = SDL_PublicSurface; /* Verify the screen parameter */ if (!screen) { SDL_SetError ("No video mode has been set"); return -1; } /* Lazily allocate the gamma tables */ if (!SDL_CurrentWindow.gamma) { SDL_GetGammaRamp (0, 0, 0); } /* Fill the gamma table with the new values */ if (red) { SDL_memcpy (&SDL_CurrentWindow.gamma[0 * 256], red, 256 * sizeof (*SDL_CurrentWindow.gamma)); } if (green) { SDL_memcpy (&SDL_CurrentWindow.gamma[1 * 256], green, 256 * sizeof (*SDL_CurrentWindow.gamma)); } if (blue) { SDL_memcpy (&SDL_CurrentWindow.gamma[2 * 256], blue, 256 * sizeof (*SDL_CurrentWindow.gamma)); } /* Try to set the gamma ramp in the driver */ succeeded = -1; if (_this->SetGammaRamp) { succeeded = _this->SetGammaRamp (_this, SDL_CurrentWindow.gamma); } else { SDL_SetError ("Gamma ramp manipulation not supported"); } return succeeded; } int SDL_GetGammaRamp (Uint16 * red, Uint16 * green, Uint16 * blue) { SDL_VideoDevice *_this = SDL_GetVideoDevice (); /* Lazily allocate the gamma table */ if (!SDL_CurrentWindow.gamma) { SDL_CurrentWindow.gamma = SDL_malloc (3 * 256 * sizeof (*SDL_CurrentWindow.gamma)); if (!SDL_CurrentWindow.gamma) { SDL_OutOfMemory (); return -1; } if (_this->GetGammaRamp) { /* Get the real hardware gamma */ _this->GetGammaRamp (_this, SDL_CurrentWindow.gamma); } else { /* Assume an identity gamma */ int i; for (i = 0; i < 256; ++i) { SDL_CurrentWindow.gamma[0 * 256 + i] = (i << 8) | i; SDL_CurrentWindow.gamma[1 * 256 + i] = (i << 8) | i; SDL_CurrentWindow.gamma[2 * 256 + i] = (i << 8) | i; } } } /* Just copy from our internal table */ if (red) { SDL_memcpy (red, &SDL_CurrentWindow.gamma[0 * 256], 256 * sizeof (*red)); } if (green) { SDL_memcpy (green, &SDL_CurrentWindow.gamma[1 * 256], 256 * sizeof (*green)); } if (blue) { SDL_memcpy (blue, &SDL_CurrentWindow.gamma[2 * 256], 256 * sizeof (*blue)); } return 0; } /* vi: set ts=4 sw=4 expandtab: */