Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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