tavli

view src/image.cc @ 11:a8e26f163f99

poulia
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 27 Jun 2015 08:01:51 +0300
parents
children c2a2069a49ec
line source
1 #include <string.h>
2 #include "opengl.h"
3 #include "image.h"
4 #include "imago2.h"
7 static unsigned int next_pow2(unsigned int x);
9 Image::Image()
10 {
11 width = height = tex_width = tex_height = 0;
12 pixels = 0;
13 tex = 0;
14 tex_valid = false;
15 }
17 Image::~Image()
18 {
19 destroy();
20 }
22 Image::Image(const Image &img)
23 {
24 pixels = 0;
25 create(img.width, img.height, img.pixels);
26 }
28 Image &Image::operator =(const Image &img)
29 {
30 if(&img != this) {
31 create(img.width, img.height, img.pixels);
32 }
33 return *this;
34 }
36 bool Image::create(int width, int height, unsigned char *pixels)
37 {
38 destroy();
40 try {
41 unsigned char *tmp = new unsigned char[width * height * 3];
42 this->pixels = tmp;
43 this->width = width;
44 this->height = height;
45 }
46 catch(...) {
47 return false;
48 }
50 if(pixels) {
51 memcpy(this->pixels, pixels, width * height * 3);
52 }
53 return true;
54 }
56 void Image::destroy()
57 {
58 delete [] pixels;
59 pixels = 0;
60 width = height = 0;
62 if(tex) {
63 glDeleteTextures(1, &tex);
64 tex = 0;
65 tex_valid = false;
66 }
67 }
69 bool Image::load(const char *fname)
70 {
71 int xsz, ysz;
72 unsigned char *pix = (unsigned char*)img_load_pixels(fname, &xsz, &ysz, IMG_FMT_RGB24);
73 if(!pix) {
74 return false;
75 }
76 return create(xsz, ysz, pix);
77 }
79 unsigned int Image::texture() const
80 {
81 if(!pixels) {
82 return 0;
83 }
84 if(!tex) {
85 glGenTextures(1, &tex);
86 }
88 if(!tex_valid) {
89 tex_width = next_pow2(width);
90 tex_height = next_pow2(height);
92 glBindTexture(GL_TEXTURE_2D, tex);
93 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
94 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
96 if(GLEW_SGIS_generate_mipmap) {
97 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, 1);
99 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex_width, tex_height, 0, GL_RGB, GL_UNSIGNED_BYTE,
100 width == tex_width && height == tex_height ? pixels : 0);
101 if(width != tex_width || height != tex_height) {
102 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
103 }
104 } else {
105 gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, tex_width, tex_height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
106 }
108 if(GLEW_EXT_texture_filter_anisotropic) {
109 static float max_aniso = -1.0;
111 if(max_aniso < 0.0) {
112 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_aniso);
113 printf("using anisotropic filtering: x%g\n", max_aniso);
114 }
116 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso);
117 }
118 tex_valid = true;
119 }
120 return tex;
121 }
123 int Image::texture_width() const
124 {
125 return tex_width;
126 }
128 int Image::texture_height() const
129 {
130 return tex_height;
131 }
133 void Image::invalidate_texture()
134 {
135 tex_valid = false;
136 }
139 void clear_image(Image *img)
140 {
141 clear_image(img, 0, 0, 0);
142 }
144 void clear_image(Image *img, float r, float g, float b)
145 {
146 if(!img->pixels) {
147 return;
148 }
150 unsigned char col[3];
151 unsigned char *ptr = img->pixels;
152 int npix = img->width * img->height;
154 col[0] = (int)(r * 255.0);
155 col[1] = (int)(g * 255.0);
156 col[2] = (int)(b * 255.0);
158 for(int i=0; i<npix; i++) {
159 for(int j=0; j<3; j++) {
160 ptr[j] = col[j];
161 }
162 ptr += 3;
163 }
164 }
166 bool combine_image(Image *dest, const Image *aimg, const Image *bimg, ImgCombine op, float t)
167 {
168 int xsz = dest->width;
169 int ysz = dest->height;
170 int npixels = xsz * ysz;
171 int nbytes = npixels * 3;
172 int tint = (int)(t * 255);
174 if(aimg->width != xsz || bimg->width != xsz || aimg->height != ysz || bimg->height != ysz) {
175 return false;
176 }
178 unsigned char *dptr = dest->pixels;
179 const unsigned char *aptr = aimg->pixels;
180 const unsigned char *bptr = bimg->pixels;
182 switch(op) {
183 case IMG_OP_ADD:
184 for(int i=0; i<nbytes; i++) {
185 unsigned int x = *aptr++ + *bptr++;
186 *dptr++ = x > 255 ? 255 : x;
187 }
188 break;
190 case IMG_OP_SUB:
191 for(int i=0; i<nbytes; i++) {
192 int x = (int)*aptr++ - (int)*bptr++;
193 *dptr++ = x < 0 ? 0 : x;
194 }
195 break;
197 case IMG_OP_MUL:
198 for(int i=0; i<nbytes; i++) {
199 unsigned int x = ((unsigned int)*aptr++ * (unsigned int)*bptr++) >> 8;
200 *dptr++ = x > 255 ? 255 : x;
201 }
202 break;
204 case IMG_OP_LERP:
205 for(int i=0; i<nbytes; i++) {
206 int x = (int)*aptr + ((((int)*bptr - (int)*aptr) * tint) >> 8);
207 *dptr++ = x > 255 ? 255 : (x < 0 ? 0 : x);
208 }
209 break;
211 default:
212 break;
213 }
215 dest->invalidate_texture();
216 return true;
217 }
219 static unsigned int next_pow2(unsigned int x)
220 {
221 x--;
222 x = (x >> 1) | x;
223 x = (x >> 2) | x;
224 x = (x >> 4) | x;
225 x = (x >> 8) | x;
226 x = (x >> 16) | x;
227 return x + 1;
228 }