SDL_gamma.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:6k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_gamma.c,v 1.4 2002/04/22 21:38:03 wmay Exp $";
  21. #endif
  22. /* Gamma correction support */
  23. #define USE_MATH_H /* Used for calculating gamma ramps */
  24. #ifdef USE_MATH_H
  25. #include <math.h>
  26. #endif
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include "SDL_error.h"
  30. #include "SDL_sysvideo.h"
  31. #ifdef USE_MATH_H
  32. static void CalculateGammaRamp(float gamma, Uint16 *ramp)
  33. {
  34. int i;
  35. /* 0.0 gamma is all black */
  36. if ( gamma <= 0.0 ) {
  37. for ( i=0; i<256; ++i ) {
  38. ramp[i] = 0;
  39. }
  40. return;
  41. } else
  42. /* 1.0 gamma is identity */
  43. if ( gamma == 1.0 ) {
  44. for ( i=0; i<256; ++i ) {
  45. ramp[i] = (i << 8) | i;
  46. }
  47. return;
  48. } else
  49. /* Calculate a real gamma ramp */
  50. { int value;
  51. gamma = 1.0f / gamma;
  52. for ( i=0; i<256; ++i ) {
  53. value = (int)(pow((double)i/256.0, gamma)*65535.0+0.5);
  54. if ( value > 65535 ) {
  55. value = 65535;
  56. }
  57. ramp[i] = (Uint16)value;
  58. }
  59. }
  60. }
  61. static void CalculateGammaFromRamp(float *gamma, Uint16 *ramp)
  62. {
  63. /* The following is adapted from a post by Garrett Bass on OpenGL
  64.    Gamedev list, March 4, 2000.
  65.  */
  66. float sum = 0.0;
  67. int i, count = 0;
  68. *gamma = 1.0;
  69. for ( i = 1; i < 256; ++i ) {
  70.     if ( (ramp[i] != 0) && (ramp[i] != 65535) ) {
  71.         double B = (double)i / 256.0;
  72.         double A = ramp[i] / 65535.0;
  73.         sum += (float) ( log(A) / log(B) );
  74.         count++;
  75.     }
  76. }
  77. if ( count && sum ) {
  78. *gamma = 1.0f / (sum / count);
  79. }
  80. }
  81. #endif /* USE_MATH_H */
  82. int SDL_SetGamma(float red, float green, float blue)
  83. {
  84. int succeeded;
  85. SDL_VideoDevice *video = current_video;
  86. SDL_VideoDevice *this  = current_video;
  87. succeeded = -1;
  88. #ifdef USE_MATH_H
  89. /* Prefer using SetGammaRamp(), as it's more flexible */
  90. {
  91. Uint16 ramp[3][256];
  92. CalculateGammaRamp(red, ramp[0]);
  93. CalculateGammaRamp(green, ramp[1]);
  94. CalculateGammaRamp(blue, ramp[2]);
  95. succeeded = SDL_SetGammaRamp(ramp[0], ramp[1], ramp[2]);
  96. }
  97. #else
  98. SDL_SetError("Gamma correction not supported");
  99. #endif
  100. if ( (succeeded < 0) && video->SetGamma ) {
  101. SDL_ClearError();
  102. succeeded = video->SetGamma(this, red, green, blue);
  103. }
  104. return succeeded;
  105. }
  106. /* Calculating the gamma by integrating the gamma ramps isn't exact,
  107.    so this function isn't officially supported.
  108. */
  109. int SDL_GetGamma(float *red, float *green, float *blue)
  110. {
  111. int succeeded;
  112. SDL_VideoDevice *video = current_video;
  113. SDL_VideoDevice *this  = current_video;
  114. succeeded = -1;
  115. #ifdef USE_MATH_H
  116. /* Prefer using GetGammaRamp(), as it's more flexible */
  117. {
  118. Uint16 ramp[3][256];
  119. succeeded = SDL_GetGammaRamp(ramp[0], ramp[1], ramp[2]);
  120. if ( succeeded >= 0 ) {
  121. CalculateGammaFromRamp(red, ramp[0]);
  122. CalculateGammaFromRamp(green, ramp[1]);
  123. CalculateGammaFromRamp(blue, ramp[2]);
  124. }
  125. }
  126. #else
  127. SDL_SetError("Gamma correction not supported");
  128. #endif
  129. if ( (succeeded < 0) && video->GetGamma ) {
  130. SDL_ClearError();
  131. succeeded = video->GetGamma(this, red, green, blue);
  132. }
  133. return succeeded;
  134. }
  135. int SDL_SetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  136. {
  137. int succeeded;
  138. SDL_VideoDevice *video = current_video;
  139. SDL_VideoDevice *this  = current_video;
  140. SDL_Surface *screen = SDL_PublicSurface;
  141. /* Verify the screen parameter */
  142. if ( !screen ) {
  143. SDL_SetError("No video mode has been set");
  144. return -1;
  145. }
  146. /* Lazily allocate the gamma tables */
  147. if ( ! video->gamma ) {
  148. SDL_GetGammaRamp(0, 0, 0);
  149. }
  150. /* Fill the gamma table with the new values */
  151. if ( red ) {
  152. memcpy(&video->gamma[0*256], red, 256*sizeof(*video->gamma));
  153. }
  154. if ( green ) {
  155. memcpy(&video->gamma[1*256], green, 256*sizeof(*video->gamma));
  156. }
  157. if ( blue ) {
  158. memcpy(&video->gamma[2*256], blue, 256*sizeof(*video->gamma));
  159. }
  160. /* Gamma correction always possible on split palettes */
  161. if ( (screen->flags & SDL_HWPALETTE) == SDL_HWPALETTE ) {
  162. SDL_Palette *pal = screen->format->palette;
  163. /* If physical palette has been set independently, use it */
  164. if(video->physpal)
  165.         pal = video->physpal;
  166.       
  167. SDL_SetPalette(screen, SDL_PHYSPAL,
  168.        pal->colors, 0, pal->ncolors);
  169. return 0;
  170. }
  171. /* Try to set the gamma ramp in the driver */
  172. succeeded = -1;
  173. if ( video->SetGammaRamp ) {
  174. succeeded = video->SetGammaRamp(this, video->gamma);
  175. } else {
  176. SDL_SetError("Gamma ramp manipulation not supported");
  177. }
  178. return succeeded;
  179. }
  180. int SDL_GetGammaRamp(Uint16 *red, Uint16 *green, Uint16 *blue)
  181. {
  182. SDL_VideoDevice *video = current_video;
  183. SDL_VideoDevice *this  = current_video;
  184. /* Lazily allocate the gamma table */
  185. if ( ! video->gamma ) {
  186. video->gamma = malloc(3*256*sizeof(*video->gamma));
  187. if ( ! video->gamma ) {
  188. SDL_OutOfMemory();
  189. return -1;
  190. }
  191. if ( video->GetGammaRamp ) {
  192. /* Get the real hardware gamma */
  193. video->GetGammaRamp(this, video->gamma);
  194. } else {
  195. /* Assume an identity gamma */
  196. int i;
  197. for ( i=0; i<256; ++i ) {
  198. video->gamma[0*256+i] = (i << 8) | i;
  199. video->gamma[1*256+i] = (i << 8) | i;
  200. video->gamma[2*256+i] = (i << 8) | i;
  201. }
  202. }
  203. }
  204. /* Just copy from our internal table */
  205. if ( red ) {
  206. memcpy(red, &video->gamma[0*256], 256*sizeof(*red));
  207. }
  208. if ( green ) {
  209. memcpy(green, &video->gamma[1*256], 256*sizeof(*green));
  210. }
  211. if ( blue ) {
  212. memcpy(blue, &video->gamma[2*256], 256*sizeof(*blue));
  213. }
  214. return 0;
  215. }