Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

pixel.cpp 7.0KB

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