Import from neverball-1.3.1.tar.gz
[neverball-archive.git] / share / image.c
blob0e8c6eb7969458e7760e7299f1e415e89cb36670
1 /*
2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
15 #include <SDL.h>
16 #include <SDL_ttf.h>
17 #include <SDL_image.h>
18 #include <string.h>
19 #include <math.h>
21 #include "glext.h"
22 #include "image.h"
23 #include "config.h"
25 /*---------------------------------------------------------------------------*/
27 void image_snap(char *filename)
29 int w = config_get_d(CONFIG_WIDTH);
30 int h = config_get_d(CONFIG_HEIGHT);
31 int i;
33 SDL_Surface *buf = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 24,
34 RMASK, GMASK, BMASK, 0);
35 SDL_Surface *img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 24,
36 RMASK, GMASK, BMASK, 0);
38 glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, buf->pixels);
40 for (i = 0; i < h; i++)
41 memcpy((GLubyte *) img->pixels + 3 * w * i,
42 (GLubyte *) buf->pixels + 3 * w * (h - i), 3 * w);
44 SDL_SaveBMP(img, filename);
46 SDL_FreeSurface(img);
47 SDL_FreeSurface(buf);
50 void image_size(int *W, int *H, int w, int h)
52 *W = 1;
53 *H = 1;
55 while (*W < w) *W *= 2;
56 while (*H < h) *H *= 2;
59 /*---------------------------------------------------------------------------*/
61 static const GLenum format[5] = {
63 GL_LUMINANCE,
64 GL_LUMINANCE_ALPHA,
65 GL_RGB,
66 GL_RGBA
70 * Create on OpenGL texture object using the given SDL surface and
71 * format, scaled using the current scale factor. When scaling,
72 * assume dimensions are used only for layout and lie about the size.
74 GLuint make_image_from_surf(int *w, int *h, SDL_Surface *s)
76 int t = config_get_d(CONFIG_TEXTURES);
78 GLuint o = 0;
80 glGenTextures(1, &o);
81 glBindTexture(GL_TEXTURE_2D, o);
83 if (t > 1)
85 int w = s->w / t;
86 int h = s->h / t;
88 /* Create a new buffer and copy the scaled image to it. */
90 SDL_Surface *d = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
91 s->format->BitsPerPixel,
92 s->format->Rmask,
93 s->format->Gmask,
94 s->format->Bmask,
95 s->format->Amask);
96 if (d)
98 SDL_LockSurface(s);
99 SDL_LockSurface(d);
101 if (s->format->BitsPerPixel == 32)
102 gluScaleImage(GL_RGBA,
103 s->w, s->h, GL_UNSIGNED_BYTE, s->pixels,
104 d->w, d->h, GL_UNSIGNED_BYTE, d->pixels);
105 else
106 gluScaleImage(GL_RGB,
107 s->w, s->h, GL_UNSIGNED_BYTE, s->pixels,
108 d->w, d->h, GL_UNSIGNED_BYTE, d->pixels);
110 SDL_UnlockSurface(d);
111 SDL_UnlockSurface(s);
113 /* Load the scaled image. */
115 if (s->format->BitsPerPixel == 32)
116 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->w, d->h, 0,
117 GL_RGBA, GL_UNSIGNED_BYTE, d->pixels);
118 else
119 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, d->w, d->h, 0,
120 GL_RGB, GL_UNSIGNED_BYTE, d->pixels);
122 SDL_FreeSurface(d);
125 else
127 /* Load the unscaled image. */
129 if (s->format->BitsPerPixel == 32)
130 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, s->w, s->h, 0,
131 GL_RGBA, GL_UNSIGNED_BYTE, s->pixels);
132 else
133 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, s->w, s->h, 0,
134 GL_RGB, GL_UNSIGNED_BYTE, s->pixels);
137 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
138 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
141 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
143 if (w) *w = s->w;
144 if (h) *h = s->h;
146 return o;
149 /*---------------------------------------------------------------------------*/
152 * Load an image from the named file. If the image is not RGBA,
153 * convert it to RGBA. Return an OpenGL texture object.
155 GLuint make_image_from_file(int *W, int *H,
156 int *w, int *h, const char *name)
158 SDL_Surface *src;
159 SDL_Surface *dst;
160 SDL_Rect rect;
162 GLuint o = 0;
164 /* Load the file. */
166 if ((src = IMG_Load(config_data(name))))
168 int w2;
169 int h2;
171 image_size(&w2, &h2, src->w, src->h);
173 if (w) *w = src->w;
174 if (h) *h = src->h;
176 /* Create a new destination surface. */
178 if ((dst = SDL_CreateRGBSurface(SDL_SWSURFACE, w2, h2, 32,
179 RMASK, GMASK, BMASK, AMASK)))
181 /* Copy source pixels to the center of the destination. */
183 rect.x = (Sint16) (w2 - src->w) / 2;
184 rect.y = (Sint16) (h2 - src->h) / 2;
186 SDL_SetAlpha(src, 0, 0);
187 SDL_BlitSurface(src, NULL, dst, &rect);
189 o = make_image_from_surf(W, H, dst);
191 SDL_FreeSurface(dst);
193 SDL_FreeSurface(src);
195 return o;
198 /*---------------------------------------------------------------------------*/
201 * Render the given string using the given font. Transfer the image
202 * to a surface of power-of-2 size large enough to fit the string.
203 * Return an OpenGL texture object.
205 GLuint make_image_from_font(int *W, int *H,
206 int *w, int *h, const char *text, TTF_Font *font)
208 SDL_Color fg = { 0xFF, 0xFF, 0xFF, 0xFF };
210 SDL_Surface *src;
211 SDL_Surface *dst;
212 SDL_Rect rect;
214 GLuint o = 0;
216 /* Render the text. */
218 if (text && strlen(text) > 0)
220 if ((src = TTF_RenderText_Blended(font, text, fg)))
222 int w2;
223 int h2;
225 image_size(&w2, &h2, src->w, src->h);
227 if (w) *w = src->w;
228 if (h) *h = src->h;
230 /* Create a new destination surface. */
232 if ((dst = SDL_CreateRGBSurface(SDL_SWSURFACE, w2, h2, 32,
233 RMASK, GMASK, BMASK, AMASK)))
235 /* Copy source pixels to the center of the destination. */
237 rect.x = (Sint16) (w2 - src->w) / 2;
238 rect.y = (Sint16) (h2 - src->h) / 2;
240 SDL_SetAlpha(src, 0, 0);
241 SDL_BlitSurface(src, NULL, dst, &rect);
243 glPushAttrib(GL_PIXEL_MODE_BIT);
245 /* Clamp RGB to white so glyphs are alpha-blended cleanly. */
247 glPixelTransferf(GL_RED_BIAS, 1.0f);
248 glPixelTransferf(GL_GREEN_BIAS, 1.0f);
249 glPixelTransferf(GL_BLUE_BIAS, 1.0f);
251 /* Create the image using the new surface. */
253 o = make_image_from_surf(W, H, dst);
255 glPopAttrib();
257 SDL_FreeSurface(dst);
259 SDL_FreeSurface(src);
262 else
264 if (W) *W = 0;
265 if (H) *H = 0;
266 if (w) *w = 0;
267 if (h) *h = 0;
269 return o;
272 /*---------------------------------------------------------------------------*/