25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

183 lines
5.7 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2004-2014 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #include <lol/engine-internal.h>
  11. #include "image-private.h"
  12. namespace lol
  13. {
  14. static vec4 u8tof32(u8vec4 pixel)
  15. {
  16. //vec4 ret;
  17. //ret.r = pow((float)pixel.r / 255.f, global_gamma);
  18. //ret.g = pow((float)pixel.g / 255.f, global_gamma);
  19. //ret.b = pow((float)pixel.b / 255.f, global_gamma);
  20. return (vec4)pixel / 255.f;
  21. }
  22. static u8vec4 f32tou8(vec4 pixel)
  23. {
  24. return (u8vec4)(pixel * 255.99f);
  25. }
  26. /*
  27. * Pixel-level image manipulation
  28. */
  29. PixelFormat Image::GetFormat() const
  30. {
  31. return m_data->m_format;
  32. }
  33. void Image::SetFormat(PixelFormat fmt)
  34. {
  35. PixelFormat old_fmt = m_data->m_format;
  36. /* Preliminary intermediate conversions */
  37. if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_F32)
  38. SetFormat(PixelFormat::RGBA_F32);
  39. else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::Y_F32)
  40. SetFormat(PixelFormat::RGBA_F32);
  41. else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_8)
  42. SetFormat(PixelFormat::RGBA_F32);
  43. else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_8)
  44. SetFormat(PixelFormat::RGBA_F32);
  45. old_fmt = m_data->m_format;
  46. /* Set the new active pixel format */
  47. m_data->m_format = fmt;
  48. ivec2 size = GetSize();
  49. int count = size.x * size.y;
  50. /* If we never used this format, allocate a new buffer: we will
  51. * obviously need it. */
  52. if (m_data->m_pixels[(int)fmt] == nullptr)
  53. {
  54. PixelDataBase *data = nullptr;
  55. #if __GNUC__
  56. #pragma GCC diagnostic push
  57. #pragma GCC diagnostic error "-Wswitch"
  58. #endif
  59. switch (fmt)
  60. {
  61. case PixelFormat::Unknown:
  62. break;
  63. case PixelFormat::Y_8:
  64. data = new PixelData<PixelFormat::Y_8>(size); break;
  65. case PixelFormat::RGB_8:
  66. data = new PixelData<PixelFormat::RGB_8>(size); break;
  67. case PixelFormat::RGBA_8:
  68. data = new PixelData<PixelFormat::RGBA_8>(size); break;
  69. case PixelFormat::Y_F32:
  70. data = new PixelData<PixelFormat::Y_F32>(size); break;
  71. case PixelFormat::RGB_F32:
  72. data = new PixelData<PixelFormat::RGB_F32>(size); break;
  73. case PixelFormat::RGBA_F32:
  74. data = new PixelData<PixelFormat::RGBA_F32>(size); break;
  75. }
  76. #if __GNUC__
  77. #pragma GCC diagnostic pop
  78. #endif
  79. ASSERT(data, "invalid pixel type %d", (int)fmt);
  80. m_data->m_pixels[(int)fmt] = data;
  81. }
  82. /* If the requested format is already the current format, or if the
  83. * current format is invalid, there is nothing to convert. */
  84. if (fmt == old_fmt || old_fmt == PixelFormat::Unknown)
  85. return;
  86. /* Convert pixels */
  87. if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGBA_F32)
  88. {
  89. u8vec4 *src = (u8vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
  90. vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->Data();
  91. for (int n = 0; n < count; ++n)
  92. dest[n] = u8tof32(src[n]);
  93. }
  94. else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::RGBA_F32)
  95. {
  96. u8vec3 *src = (u8vec3 *)m_data->m_pixels[(int)old_fmt]->Data();
  97. vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->Data();
  98. for (int n = 0; n < count; ++n)
  99. dest[n] = u8tof32(u8vec4(src[n], 255));
  100. }
  101. else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGBA_8)
  102. {
  103. vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
  104. u8vec4 *dest = (u8vec4 *)m_data->m_pixels[(int)fmt]->Data();
  105. for (int n = 0; n < count; ++n)
  106. dest[n] = f32tou8(src[n]);
  107. #if 0
  108. init_tables();
  109. for (int y = 0; y < size.y; y++)
  110. for (int x = 0; x < size.x; x++)
  111. for (i = 0; i < 4; i++)
  112. {
  113. double p, e;
  114. uint8_t d;
  115. p = src[4 * (y * size.x + x) + i];
  116. if (p < 0.) d = 0.;
  117. else if (p > 1.) d = 255;
  118. else d = (int)(255.999 * pow(p, 1. / global_gamma));
  119. dest[4 * (y * size.x + x) + i] = d;
  120. e = (p - u8tof32(d)) / 16;
  121. if (x < size.x - 1)
  122. src[4 * (y * size.x + x + 1) + i] += e * 7;
  123. if (y < size.y - 1)
  124. {
  125. if (x > 0)
  126. src[4 * ((y + 1) * size.x + x - 1) + i] += e * 3;
  127. src[4 * ((y + 1) * size.x + x) + i] += e * 5;
  128. if (x < size.x - 1)
  129. src[4 * ((y + 1) * size.x + x + 1) + i] += e;
  130. }
  131. }
  132. #endif
  133. }
  134. else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_F32)
  135. {
  136. float *src = (float *)m_data->m_pixels[(int)old_fmt]->Data();
  137. vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->Data();
  138. for (int n = 0; n < count; ++n)
  139. dest[n] = vec4(vec3(src[n]), 1.0f);
  140. }
  141. else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_F32)
  142. {
  143. vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->Data();
  144. float *dest = (float *)m_data->m_pixels[(int)fmt]->Data();
  145. vec3 const coeff(0.299f, 0.587f, 0.114f);
  146. for (int n = 0; n < count; ++n)
  147. dest[n] = dot(coeff, src[n].rgb);
  148. }
  149. else
  150. {
  151. ASSERT(false, "Unable to find proper conversion");
  152. }
  153. }
  154. } /* namespace lol */