dithering.ino 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #include "dithering.h"
  2. void dither_image(camera_fb_t *frame_buffer)
  3. {
  4. // Get the camera model reference.
  5. CameraModel *model = CameraModel::getInstance();
  6. for (uint8_t y = 0; y < frame_buffer->height; ++y)
  7. {
  8. for (uint8_t x = 0; x < frame_buffer->width; ++x)
  9. {
  10. size_t current = (y * frame_buffer->width) + x;
  11. uint8_t oldpixel = frame_buffer->buf[current];
  12. uint8_t newpixel = oldpixel >= 128 ? 255 : 0;
  13. frame_buffer->buf[current] = newpixel;
  14. int8_t quant_error = oldpixel - newpixel;
  15. // Apply error diffusion based on the selected algorithm
  16. switch (model->getDitherAlgorithm())
  17. {
  18. case JARVIS_JUDICE_NINKE:
  19. frame_buffer->buf[(y * frame_buffer->width) + x + 1] += quant_error * 7 / 48;
  20. frame_buffer->buf[(y * frame_buffer->width) + x + 2] += quant_error * 5 / 48;
  21. frame_buffer->buf[(y + 1) * frame_buffer->width + x - 2] += quant_error * 3 / 48;
  22. frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] += quant_error * 5 / 48;
  23. frame_buffer->buf[(y + 1) * frame_buffer->width + x] += quant_error * 7 / 48;
  24. frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] += quant_error * 5 / 48;
  25. frame_buffer->buf[(y + 1) * frame_buffer->width + x + 2] += quant_error * 3 / 48;
  26. frame_buffer->buf[(y + 2) * frame_buffer->width + x - 2] += quant_error * 1 / 48;
  27. frame_buffer->buf[(y + 2) * frame_buffer->width + x - 1] += quant_error * 3 / 48;
  28. frame_buffer->buf[(y + 2) * frame_buffer->width + x] += quant_error * 5 / 48;
  29. frame_buffer->buf[(y + 2) * frame_buffer->width + x + 1] += quant_error * 3 / 48;
  30. frame_buffer->buf[(y + 2) * frame_buffer->width + x + 2] += quant_error * 1 / 48;
  31. break;
  32. case STUCKI:
  33. frame_buffer->buf[(y * frame_buffer->width) + x + 1] += quant_error * 8 / 42;
  34. frame_buffer->buf[(y * frame_buffer->width) + x + 2] += quant_error * 4 / 42;
  35. frame_buffer->buf[(y + 1) * frame_buffer->width + x - 2] += quant_error * 2 / 42;
  36. frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] += quant_error * 4 / 42;
  37. frame_buffer->buf[(y + 1) * frame_buffer->width + x] += quant_error * 8 / 42;
  38. frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] += quant_error * 4 / 42;
  39. frame_buffer->buf[(y + 1) * frame_buffer->width + x + 2] += quant_error * 2 / 42;
  40. frame_buffer->buf[(y + 2) * frame_buffer->width + x - 2] += quant_error * 1 / 42;
  41. frame_buffer->buf[(y + 2) * frame_buffer->width + x - 1] += quant_error * 2 / 42;
  42. frame_buffer->buf[(y + 2) * frame_buffer->width + x] += quant_error * 4 / 42;
  43. frame_buffer->buf[(y + 2) * frame_buffer->width + x + 1] += quant_error * 2 / 42;
  44. frame_buffer->buf[(y + 2) * frame_buffer->width + x + 2] += quant_error * 1 / 42;
  45. break;
  46. case FLOYD_STEINBERG:
  47. default:
  48. // Default to Floyd-Steinberg dithering if an invalid algorithm is selected
  49. frame_buffer->buf[(y * frame_buffer->width) + x + 1] += quant_error * 7 / 16;
  50. frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] += quant_error * 3 / 16;
  51. frame_buffer->buf[(y + 1) * frame_buffer->width + x] += quant_error * 5 / 16;
  52. frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] += quant_error * 1 / 16;
  53. break;
  54. }
  55. }
  56. }
  57. }