Open Source Tomb Raider Engine
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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