Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

356 linhas
12 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2004—2020 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #include <../legacy/lol/base/assert.h>
  14. #include "image-private.h"
  15. namespace lol
  16. {
  17. static float u8tof32(uint8_t pixel)
  18. {
  19. //return pow((float)pixel / 255.f, global_gamma);
  20. return pixel / 255.f;
  21. }
  22. static vec4 u8tof32(u8vec4 pixel)
  23. {
  24. //vec4 ret;
  25. //ret.r = pow((float)pixel.r / 255.f, global_gamma);
  26. //ret.g = pow((float)pixel.g / 255.f, global_gamma);
  27. //ret.b = pow((float)pixel.b / 255.f, global_gamma);
  28. return (vec4)pixel / 255.f;
  29. }
  30. static vec3 u8tof32(u8vec3 pixel)
  31. {
  32. //vec3 ret;
  33. //ret.r = pow((float)pixel.r / 255.f, global_gamma);
  34. //ret.g = pow((float)pixel.g / 255.f, global_gamma);
  35. //ret.b = pow((float)pixel.b / 255.f, global_gamma);
  36. return (vec3)pixel / 255.f;
  37. }
  38. static uint8_t f32tou8(float pixel)
  39. {
  40. return (uint8_t)(pixel * 255.99f);
  41. }
  42. static u8vec3 f32tou8(vec3 pixel)
  43. {
  44. return (u8vec3)(pixel * 255.99f);
  45. }
  46. static u8vec4 f32tou8(vec4 pixel)
  47. {
  48. return (u8vec4)(pixel * 255.99f);
  49. }
  50. /*
  51. * Pixel-level image manipulation
  52. */
  53. PixelFormat image::format() const
  54. {
  55. return m_data->m_format;
  56. }
  57. /* Conversion rules matrix
  58. *
  59. * From: To→ 1 2 3 4 5 6
  60. * Y_8 1 . o o x x x
  61. * RGB_8 2 ~ . o ~ x x
  62. * RGBA_8 3 ~ o . ~ x x
  63. * Y_F32 4 # ~ ~ . o o
  64. * RGB_F32 5 ~ # ~ # . o
  65. * RGBA_F32 6 ~ ~ # ~ o .
  66. *
  67. * . no conversion necessary
  68. * ~ intermediate conversion to RGBA_F32 or RGB_F32
  69. * o easy conversion (add/remove alpha and/or convert gray→color)
  70. * x lossless conversion (u8 to float)
  71. * # lossy conversion (dithering and/or convert color→gray)
  72. */
  73. void image::set_format(PixelFormat fmt)
  74. {
  75. PixelFormat old_fmt = m_data->m_format;
  76. /* Preliminary intermediate conversions */
  77. if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_F32)
  78. set_format(PixelFormat::RGBA_F32);
  79. else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::Y_F32)
  80. set_format(PixelFormat::RGBA_F32);
  81. else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_8)
  82. set_format(PixelFormat::RGBA_F32);
  83. else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_8)
  84. set_format(PixelFormat::RGBA_F32);
  85. else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::RGBA_8)
  86. set_format(PixelFormat::RGBA_F32);
  87. else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_F32)
  88. set_format(PixelFormat::RGB_F32);
  89. else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGB_8)
  90. set_format(PixelFormat::RGB_F32);
  91. else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::Y_8)
  92. set_format(PixelFormat::RGB_F32);
  93. else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::Y_8)
  94. set_format(PixelFormat::RGB_F32);
  95. else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::Y_8)
  96. set_format(PixelFormat::Y_F32);
  97. else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::Y_8)
  98. set_format(PixelFormat::Y_F32);
  99. old_fmt = m_data->m_format;
  100. /* Set the new active pixel format */
  101. m_data->m_format = fmt;
  102. ivec2 isize = size();
  103. int count = isize.x * isize.y;
  104. /* If we never used this format, allocate a new buffer: we will
  105. * obviously need it. */
  106. if (m_data->m_pixels[(int)fmt] == nullptr)
  107. {
  108. PixelDataBase *data = nullptr;
  109. #if __GNUC__
  110. #pragma GCC diagnostic push
  111. #pragma GCC diagnostic error "-Wswitch"
  112. #endif
  113. switch (fmt)
  114. {
  115. case PixelFormat::Unknown:
  116. break;
  117. case PixelFormat::Y_8:
  118. data = new PixelData<PixelFormat::Y_8>(isize); break;
  119. case PixelFormat::RGB_8:
  120. data = new PixelData<PixelFormat::RGB_8>(isize); break;
  121. case PixelFormat::RGBA_8:
  122. data = new PixelData<PixelFormat::RGBA_8>(isize); break;
  123. case PixelFormat::Y_F32:
  124. data = new PixelData<PixelFormat::Y_F32>(isize); break;
  125. case PixelFormat::RGB_F32:
  126. data = new PixelData<PixelFormat::RGB_F32>(isize); break;
  127. case PixelFormat::RGBA_F32:
  128. data = new PixelData<PixelFormat::RGBA_F32>(isize); break;
  129. }
  130. #if __GNUC__
  131. #pragma GCC diagnostic pop
  132. #endif
  133. ASSERT(data, "invalid pixel type %d", (int)fmt);
  134. m_data->m_pixels[(int)fmt] = data;
  135. }
  136. /* If the requested format is already the current format, or if the
  137. * current format is invalid, there is nothing to convert. */
  138. if (fmt == old_fmt || old_fmt == PixelFormat::Unknown)
  139. return;
  140. /* Easy conversions: just add or remove channels */
  141. if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::RGB_8)
  142. {
  143. uint8_t *src = (uint8_t *)m_data->m_pixels[(int)old_fmt]->data();
  144. u8vec3 *dest = (u8vec3 *)m_data->m_pixels[(int)fmt]->data();
  145. for (int n = 0; n < count; ++n)
  146. dest[n] = u8vec3(src[n]);
  147. }
  148. else if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::RGBA_8)
  149. {
  150. uint8_t *src = (uint8_t *)m_data->m_pixels[(int)old_fmt]->data();
  151. u8vec4 *dest = (u8vec4 *)m_data->m_pixels[(int)fmt]->data();
  152. for (int n = 0; n < count; ++n)
  153. dest[n] = u8vec4(u8vec3(src[n]), 255);
  154. }
  155. else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGB_8)
  156. {
  157. u8vec4 *src = (u8vec4 *)m_data->m_pixels[(int)old_fmt]->data();
  158. u8vec3 *dest = (u8vec3 *)m_data->m_pixels[(int)fmt]->data();
  159. for (int n = 0; n < count; ++n)
  160. dest[n] = src[n].rgb;
  161. }
  162. else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::RGBA_8)
  163. {
  164. u8vec3 *src = (u8vec3 *)m_data->m_pixels[(int)old_fmt]->data();
  165. u8vec4 *dest = (u8vec4 *)m_data->m_pixels[(int)fmt]->data();
  166. for (int n = 0; n < count; ++n)
  167. dest[n] = u8vec4(src[n], 255);
  168. }
  169. else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGB_F32)
  170. {
  171. vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->data();
  172. vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->data();
  173. for (int n = 0; n < count; ++n)
  174. dest[n] = src[n].rgb;
  175. }
  176. else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::RGBA_F32)
  177. {
  178. vec3 *src = (vec3 *)m_data->m_pixels[(int)old_fmt]->data();
  179. vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->data();
  180. for (int n = 0; n < count; ++n)
  181. dest[n] = vec4(src[n], 1.f);
  182. }
  183. else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGB_F32)
  184. {
  185. float *src = (float *)m_data->m_pixels[(int)old_fmt]->data();
  186. vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->data();
  187. for (int n = 0; n < count; ++n)
  188. dest[n] = vec3(src[n]);
  189. }
  190. else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::RGBA_F32)
  191. {
  192. float *src = (float *)m_data->m_pixels[(int)old_fmt]->data();
  193. vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->data();
  194. for (int n = 0; n < count; ++n)
  195. dest[n] = vec4(vec3(src[n]), 1.0f);
  196. }
  197. /* Lossless conversions: u8 to float */
  198. else if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::Y_F32)
  199. {
  200. uint8_t *src = (uint8_t *)m_data->m_pixels[(int)old_fmt]->data();
  201. float *dest = (float *)m_data->m_pixels[(int)fmt]->data();
  202. for (int n = 0; n < count; ++n)
  203. dest[n] = u8tof32(src[n]);
  204. }
  205. else if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::RGB_F32)
  206. {
  207. uint8_t *src = (uint8_t *)m_data->m_pixels[(int)old_fmt]->data();
  208. vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->data();
  209. for (int n = 0; n < count; ++n)
  210. dest[n] = u8tof32(u8vec3(src[n]));
  211. }
  212. else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::RGB_F32)
  213. {
  214. u8vec3 *src = (u8vec3 *)m_data->m_pixels[(int)old_fmt]->data();
  215. vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->data();
  216. for (int n = 0; n < count; ++n)
  217. dest[n] = u8tof32(src[n]);
  218. }
  219. else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGB_F32)
  220. {
  221. u8vec4 *src = (u8vec4 *)m_data->m_pixels[(int)old_fmt]->data();
  222. vec3 *dest = (vec3 *)m_data->m_pixels[(int)fmt]->data();
  223. for (int n = 0; n < count; ++n)
  224. dest[n] = u8tof32(src[n].rgb);
  225. }
  226. else if (old_fmt == PixelFormat::Y_8 && fmt == PixelFormat::RGBA_F32)
  227. {
  228. uint8_t *src = (uint8_t *)m_data->m_pixels[(int)old_fmt]->data();
  229. vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->data();
  230. for (int n = 0; n < count; ++n)
  231. dest[n] = u8tof32(u8vec4(u8vec3(src[n]), 255));
  232. }
  233. else if (old_fmt == PixelFormat::RGB_8 && fmt == PixelFormat::RGBA_F32)
  234. {
  235. u8vec3 *src = (u8vec3 *)m_data->m_pixels[(int)old_fmt]->data();
  236. vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->data();
  237. for (int n = 0; n < count; ++n)
  238. dest[n] = u8tof32(u8vec4(src[n], 255));
  239. }
  240. else if (old_fmt == PixelFormat::RGBA_8 && fmt == PixelFormat::RGBA_F32)
  241. {
  242. u8vec4 *src = (u8vec4 *)m_data->m_pixels[(int)old_fmt]->data();
  243. vec4 *dest = (vec4 *)m_data->m_pixels[(int)fmt]->data();
  244. for (int n = 0; n < count; ++n)
  245. dest[n] = u8tof32(src[n]);
  246. }
  247. /* Other conversions */
  248. else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::Y_F32)
  249. {
  250. vec3 *src = (vec3 *)m_data->m_pixels[(int)old_fmt]->data();
  251. float *dest = (float *)m_data->m_pixels[(int)fmt]->data();
  252. vec3 const coeff(0.299f, 0.587f, 0.114f);
  253. for (int n = 0; n < count; ++n)
  254. dest[n] = dot(coeff, src[n]);
  255. }
  256. else if (old_fmt == PixelFormat::Y_F32 && fmt == PixelFormat::Y_8)
  257. {
  258. float *src = (float *)m_data->m_pixels[(int)old_fmt]->data();
  259. uint8_t *dest = (uint8_t *)m_data->m_pixels[(int)fmt]->data();
  260. for (int n = 0; n < count; ++n)
  261. dest[n] = f32tou8(src[n]);
  262. }
  263. else if (old_fmt == PixelFormat::RGB_F32 && fmt == PixelFormat::RGB_8)
  264. {
  265. vec3 *src = (vec3 *)m_data->m_pixels[(int)old_fmt]->data();
  266. u8vec3 *dest = (u8vec3 *)m_data->m_pixels[(int)fmt]->data();
  267. for (int n = 0; n < count; ++n)
  268. dest[n] = f32tou8(src[n]);
  269. }
  270. else if (old_fmt == PixelFormat::RGBA_F32 && fmt == PixelFormat::RGBA_8)
  271. {
  272. vec4 *src = (vec4 *)m_data->m_pixels[(int)old_fmt]->data();
  273. u8vec4 *dest = (u8vec4 *)m_data->m_pixels[(int)fmt]->data();
  274. for (int n = 0; n < count; ++n)
  275. dest[n] = f32tou8(src[n]);
  276. #if 0
  277. init_tables();
  278. for (int y = 0; y < isize.y; y++)
  279. for (int x = 0; x < isize.x; x++)
  280. for (i = 0; i < 4; i++)
  281. {
  282. double p, e;
  283. uint8_t d;
  284. p = src[4 * (y * isize.x + x) + i];
  285. if (p < 0.) d = 0.;
  286. else if (p > 1.) d = 255;
  287. else d = (int)(255.999 * pow(p, 1. / global_gamma));
  288. dest[4 * (y * isize.x + x) + i] = d;
  289. e = (p - u8tof32(d)) / 16;
  290. if (x < isize.x - 1)
  291. src[4 * (y * isize.x + x + 1) + i] += e * 7;
  292. if (y < isize.y - 1)
  293. {
  294. if (x > 0)
  295. src[4 * ((y + 1) * isize.x + x - 1) + i] += e * 3;
  296. src[4 * ((y + 1) * isize.x + x) + i] += e * 5;
  297. if (x < isize.x - 1)
  298. src[4 * ((y + 1) * isize.x + x + 1) + i] += e;
  299. }
  300. }
  301. #endif
  302. }
  303. else
  304. {
  305. ASSERT(false, "Unable to find image conversion from %d to %d",
  306. (int)old_fmt, (int)fmt);
  307. }
  308. }
  309. } /* namespace lol */