tavli

annotate src/image.cc @ 22:c2a2069a49ec

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