dithering.ino 4.2 KB

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