OpenRaider  0.1.4-dev
Open Source Tomb Raider Game Engine implementation
pixel.cpp
Go to the documentation of this file.
1 
8 #include "global.h"
9 #include "utils/pixel.h"
10 
11 unsigned char* generateColorTexture(glm::vec4 rgba, unsigned int width,
12  unsigned int height, unsigned int bpp) {
13  assert(width > 0);
14  assert(height > 0);
15  assert((bpp == 24) || (bpp == 32));
16 
17  unsigned char* image = new unsigned char[height * width * (bpp / 8)];
18  for (unsigned int i = 0; i < (width * height); i++) {
19  image[i * (bpp / 8)] = (unsigned char)(rgba.r * 255);
20  image[(i * (bpp / 8)) + 1] = (unsigned char)(rgba.g * 255);
21  image[(i * (bpp / 8)) + 2] = (unsigned char)(rgba.b * 255);
22  if (bpp == 32) {
23  image[(i * (bpp / 8)) + 3] = (unsigned char)(rgba.a * 255);
24  }
25  }
26  return image;
27 }
28 
29 void argb2rgba32(unsigned char* image, unsigned int w, unsigned int h) {
30  assert(image != nullptr);
31  assert(w > 0);
32  assert(h > 0);
33 
34  for (unsigned int i = 0; i < (w * h); ++i) {
35  // 32-bit ARGB to RGBA
36  unsigned char swap = image[i * 4];
37  image[i * 4] = image[(i * 4) + 1];
38  image[(i * 4) + 1] = image[(i * 4) + 2];
39  image[(i * 4) + 2] = image[(i * 4) + 3];
40  image[(i * 4) + 3] = swap;
41  }
42 }
43 
44 unsigned char* argb16to32(unsigned char* image, unsigned int w, unsigned int h) {
45  assert(image != nullptr);
46  assert(w > 0);
47  assert(h > 0);
48 
49  unsigned char* img = new unsigned char[w * h * 4];
50  for (unsigned int i = 0; i < (w * h); ++i) {
51  // arrr.rrgg gggb.bbbb shift to 5bit
52  img[i * 4] = (image[(i * 2) + 1] & 0x80) ? 0xFF : 0; // A
53  img[(i * 4) + 1] = (image[(i * 2) + 1] & 0x7C) >> 2; // R
54  img[(i * 4) + 2] = (image[(i * 2) + 1] & 0x03) << 3;
55  img[(i * 4) + 2] |= (image[i * 2] & 0xE0) >> 5; // G
56  img[(i * 4) + 3] = image[i * 2] & 0x1F; // B
57 
58  img[(i * 4) + 1] <<= 3; // R
59  img[(i * 4) + 2] <<= 3; // G
60  img[(i * 4) + 3] <<= 3; // B
61  }
62  return img;
63 }
64 
65 unsigned char* grayscale2rgba(unsigned char* image, unsigned int w, unsigned int h) {
66  assert(image != nullptr);
67  assert(w > 0);
68  assert(h > 0);
69 
70  unsigned char* img = new unsigned char[w * h * 4];
71  for (unsigned int i = 0; i < (w * h); i++) {
72  img[i * 4] = image[i];
73  img[(i * 4) + 1] = image[i];
74  img[(i * 4) + 2] = image[i];
75  img[(i * 4) + 3] = (image[i] == 0) ? 0 : 255;
76  }
77  return img;
78 }
79 
80 #define NEXT_POWER(x) do { \
81  unsigned int i; \
82  for (i = 1; i < (x); i *= 2); \
83  (x) = i; \
84 } while (false);
85 
86 // This code based off on gluScaleImage()
87 unsigned char* scaleBuffer(unsigned char* image, unsigned int* w, unsigned int* h,
88  unsigned int bpp) {
89  unsigned int width = *w;
90  unsigned int height = *h;
91  assert(image != nullptr);
92  assert(width > 0);
93  assert(height > 0);
94  assert((bpp % 8) == 0);
95 
96  unsigned int components = bpp / 8;
97  unsigned int original_height = height;
98  unsigned int original_width = width;
99 
100  NEXT_POWER(height);
101  NEXT_POWER(width);
102 
103  // Check to see if scaling is needed
104  if (height == original_height && width == original_width)
105  return nullptr;
106 
107  *w = width;
108  *h = height;
109 
110  unsigned char* timage = new unsigned char[height * width * components];
111  float* tempin = new float[original_width * original_height * components];
112  float* tempout = new float[width * height * components];
113 
114  // Copy user data to float format.
115  for (unsigned int i = 0; i < original_height * original_width * components; ++i) {
116  tempin[i] = (float)image[i];
117  }
118 
119  // Determine which filter to use by checking ratios.
120  float sx;
121  if (width > 1) {
122  sx = (float)(original_width - 1) / (float)(width - 1);
123  } else {
124  sx = (float)(original_width - 1);
125  }
126 
127  float sy;
128  if (height > 1) {
129  sy = (float)(original_height - 1) / (float)(height - 1);
130  } else {
131  sy = (float)(original_height - 1);
132  }
133 
134  if (sx < 1.0 && sy < 1.0) { // Magnify both width and height: use weighted sample of 4 pixels
135  for (unsigned int i = 0; i < height; ++i) {
136  unsigned int i0 = (unsigned int)(i * sy);
137  unsigned int i1 = i0 + 1;
138 
139  if (i1 >= original_height) {
140  i1 = original_height - 1;
141  }
142 
143  float alpha = i * sy - i0;
144 
145  for (unsigned int j = 0; j < width; ++j) {
146  unsigned int j0 = (unsigned int)(j * sx);
147  unsigned int j1 = j0 + 1;
148 
149  if (j1 >= original_width) {
150  j1 = original_width - 1;
151  }
152 
153  float beta = j * sx - j0;
154 
155  // Compute weighted average of pixels in rect (i0,j0)-(i1,j1)
156  float* src00 = tempin + (i0 * original_width + j0) * components;
157  float* src01 = tempin + (i0 * original_width + j1) * components;
158  float* src10 = tempin + (i1 * original_width + j0) * components;
159  float* src11 = tempin + (i1 * original_width + j1) * components;
160 
161  float* dst = tempout + (i * width + j) * components;
162 
163  for (unsigned int k = 0; k < components; ++k) {
164  float s1 = *src00++ * (1.0f - beta) + *src01++ * beta;
165  float s2 = *src10++ * (1.0f - beta) + *src11++ * beta;
166  *dst++ = s1 * (1.0f - alpha) + s2 * alpha;
167  }
168  }
169  }
170  } else { // Shrink width and/or height: use an unweighted box filter
171  for (unsigned int i = 0; i < height; ++i) {
172  unsigned int i0 = (unsigned int)(i * sy);
173  unsigned int i1 = i0 + 1;
174 
175  if (i1 >= original_height) {
176  i1 = original_height - 1;
177  }
178 
179  for (unsigned int j = 0; j < width; ++j) {
180  unsigned int j0 = (unsigned int)(j * sx);
181  unsigned int j1 = j0 + 1;
182 
183  if (j1 >= original_width) {
184  j1 = original_width - 1;
185  }
186 
187  float* dst = tempout + (i * width + j) * components;
188 
189  // Compute average of pixels in the rectangle (i0,j0)-(i1,j1)
190  for (unsigned int k = 0; k < components; ++k) {
191  float sum = 0.0;
192 
193  for (unsigned int ii = i0; ii <= i1; ++ii) {
194  for (unsigned int jj = j0; jj <= j1; ++jj) {
195  sum += *(tempin + (ii * original_width + jj)
196  * components + k);
197  }
198  }
199 
200  sum /= (j1 - j0 + 1) * (i1 - i0 + 1);
201  *dst++ = sum;
202  }
203  }
204  }
205  }
206 
207  // Copy to our results.
208  for (unsigned int i = 0; i < height * width * components; ++i) {
209  timage[i] = (unsigned char)tempout[i];
210  }
211 
212  // Delete our temp buffers.
213  delete [] tempin;
214  delete [] tempout;
215 
216  return timage;
217 }
218 
unsigned char * argb16to32(unsigned char *image, unsigned int w, unsigned int h)
Definition: pixel.cpp:44
unsigned char * scaleBuffer(unsigned char *image, unsigned int *w, unsigned int *h, unsigned int bpp)
Definition: pixel.cpp:87
Included everywhere.
Pixel buffer utilities.
#define assert(x)
Definition: global.h:124
unsigned char * grayscale2rgba(unsigned char *image, unsigned int w, unsigned int h)
Definition: pixel.cpp:65
void argb2rgba32(unsigned char *image, unsigned int w, unsigned int h)
Definition: pixel.cpp:29
#define NEXT_POWER(x)
Definition: pixel.cpp:80
unsigned char * generateColorTexture(glm::vec4 rgba, unsigned int width, unsigned int height, unsigned int bpp)
Definition: pixel.cpp:11