Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

75 строки
2.0 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. #if defined HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include "core.h"
  14. /*
  15. * Bayer ordered dithering functions
  16. */
  17. namespace lol
  18. {
  19. static Image DitherHelper(Image const &image, Array2D<float> const &kernel,
  20. float scale, float angle);
  21. Image Image::DitherOrdered(Array2D<float> const &kernel) const
  22. {
  23. return DitherHelper(*this, kernel, 1.0f, 0.0f);
  24. }
  25. Image Image::DitherHalftone(float radius, float angle) const
  26. {
  27. /* Increasing the precision is necessary or the rotation will look
  28. * like crap. So we create a kernel PRECISION times larger, and ask
  29. * the ditherer to scale it by 1/PRECISION. */
  30. float const PRECISION = 4.f;
  31. int k = (radius * PRECISION * lol::sqrt(2.f) + 0.5f);
  32. Array2D<float> kernel = Image::HalftoneKernel(ivec2(k, k));
  33. return DitherHelper(*this, kernel, 1.f / PRECISION, angle + F_PI / 4.f);
  34. }
  35. static Image DitherHelper(Image const &image, Array2D<float> const &kernel,
  36. float scale, float angle)
  37. {
  38. ivec2 size = image.GetSize();
  39. ivec2 ksize = kernel.GetSize();
  40. float cost = lol::cos(angle);
  41. float sint = lol::sin(angle);
  42. Image ret = image;
  43. float *dstp = ret.Lock<PixelFormat::Y_F32>();
  44. for (int y = 0; y < size.y; y++)
  45. {
  46. for (int x = 0; x < size.x; x++)
  47. {
  48. int kx = (int)((cost * x - sint * y + 2 * size.x * size.y) / scale) % ksize.x;
  49. int ky = (int)((cost * y + sint * x + 2 * size.x * size.y) / scale) % ksize.y;
  50. float p = dstp[y * size.x + x];
  51. dstp[y * size.x + x] = (p > kernel[kx][ky]) ? 1.f : 0.f;
  52. }
  53. }
  54. ret.Unlock(dstp);
  55. return ret;
  56. }
  57. } /* namespace lol */