Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

79 rader
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 <lol/main.h>
  14. /*
  15. * Generic error diffusion functions
  16. */
  17. namespace lol
  18. {
  19. /* Perform a generic error diffusion dithering. The first non-zero
  20. * element in ker is treated as the current pixel. All other non-zero
  21. * elements are the error diffusion coefficients.
  22. * Making the matrix generic is not terribly slower: the performance
  23. * hit is around 4% for Floyd-Steinberg and 13% for JaJuNi, with the
  24. * benefit of a lot less code. */
  25. Image Image::DitherEdiff(array2d<float> const &kernel, ScanMode scan) const
  26. {
  27. Image dst = *this;
  28. ivec2 size = dst.GetSize();
  29. ivec2 ksize = (ivec2)kernel.GetSize();
  30. int kx;
  31. for (kx = 0; kx < ksize.x; kx++)
  32. if (kernel[kx][0] > 0.f)
  33. break;
  34. float *pixels = dst.Lock<PixelFormat::Y_F32>();
  35. for (int y = 0; y < size.y; y++)
  36. {
  37. bool reverse = (y & 1) && (scan == ScanMode::Serpentine);
  38. for (int x = 0; x < size.x; x++)
  39. {
  40. int x2 = reverse ? size.x - 1 - x : x;
  41. int s = reverse ? -1 : 1;
  42. float p = pixels[y * size.x + x2];
  43. float q = p < 0.5f ? 0.f : 1.f;
  44. pixels[y * size.x + x2] = q;
  45. float e = (p - q);
  46. for (int j = 0; j < ksize.y && y < size.y - j; j++)
  47. for (int i = 0; i < ksize.x; i++)
  48. {
  49. if (j == 0 && i <= kx)
  50. continue;
  51. if (x + i - kx < 0 || x + i - kx >= size.x)
  52. continue;
  53. pixels[(y + j) * size.x + x2 + (i - kx) * s]
  54. += e * kernel[i][j];
  55. }
  56. }
  57. }
  58. dst.Unlock(pixels);
  59. return dst;
  60. }
  61. } /* namespace lol */