Cody Tolene 2 лет назад
Родитель
Сommit
34f92668aa

+ 4 - 6
firmware-update/camera_model.h

@@ -6,16 +6,14 @@
 /**
  * The dithering algorithms available.
  */
-enum DitheringAlgorithm : uint8_t
-{
+enum DitheringAlgorithm : uint8_t {
     FLOYD_STEINBERG,
     JARVIS_JUDICE_NINKE,
     STUCKI
 };
 
-class CameraModel
-{
-private:
+class CameraModel {
+   private:
     static CameraModel *instance;
     // Private constructor to prevent instantiation.
     CameraModel();
@@ -40,7 +38,7 @@ private:
      */
     DitheringAlgorithm ditherAlgorithm;
 
-public:
+   public:
     static CameraModel *getInstance();
 
     // Getter functions

+ 13 - 42
firmware-update/camera_model.ino

@@ -2,8 +2,7 @@
 
 CameraModel *CameraModel::instance = nullptr;
 
-CameraModel::CameraModel()
-{
+CameraModel::CameraModel() {
     // Set up defaults.
     isDitheringDisabled = false;
     isFlashEnabled = false;
@@ -12,63 +11,35 @@ CameraModel::CameraModel()
     ditherAlgorithm = FLOYD_STEINBERG;
 }
 
-CameraModel *CameraModel::getInstance()
-{
-    if (instance == nullptr)
-    {
+CameraModel *CameraModel::getInstance() {
+    if (instance == nullptr) {
         instance = new CameraModel();
     }
     return instance;
 }
 
 // Getter implementations
-bool CameraModel::getIsDitheringDisabled()
-{
-    return isDitheringDisabled;
-}
+bool CameraModel::getIsDitheringDisabled() { return isDitheringDisabled; }
 
-bool CameraModel::getIsFlashEnabled()
-{
-    return isFlashEnabled;
-}
+bool CameraModel::getIsFlashEnabled() { return isFlashEnabled; }
 
-bool CameraModel::getIsInverted()
-{
-    return isInverted;
-}
+bool CameraModel::getIsInverted() { return isInverted; }
 
-bool CameraModel::getIsStreamEnabled()
-{
-    return isStreamEnabled;
-}
+bool CameraModel::getIsStreamEnabled() { return isStreamEnabled; }
 
-DitheringAlgorithm CameraModel::getDitherAlgorithm()
-{
-    return ditherAlgorithm;
-}
+DitheringAlgorithm CameraModel::getDitherAlgorithm() { return ditherAlgorithm; }
 
 // Setter implementations
-void CameraModel::setIsDitheringDisabled(bool value)
-{
+void CameraModel::setIsDitheringDisabled(bool value) {
     isDitheringDisabled = value;
 }
 
-void CameraModel::setIsFlashEnabled(bool value)
-{
-    isFlashEnabled = value;
-}
+void CameraModel::setIsFlashEnabled(bool value) { isFlashEnabled = value; }
 
-void CameraModel::setIsInverted(bool value)
-{
-    isInverted = value;
-}
+void CameraModel::setIsInverted(bool value) { isInverted = value; }
 
-void CameraModel::setIsStreamEnabled(bool value)
-{
-    isStreamEnabled = value;
-}
+void CameraModel::setIsStreamEnabled(bool value) { isStreamEnabled = value; }
 
-void CameraModel::setDitherAlgorithm(DitheringAlgorithm algorithm)
-{
+void CameraModel::setDitherAlgorithm(DitheringAlgorithm algorithm) {
     ditherAlgorithm = algorithm;
 }

+ 70 - 45
firmware-update/dithering.ino

@@ -1,14 +1,11 @@
 #include "dithering.h"
 
-void dither_image(camera_fb_t *frame_buffer)
-{
+void dither_image(camera_fb_t* frame_buffer) {
     // Get the camera model reference.
-    CameraModel *model = CameraModel::getInstance();
+    CameraModel* model = CameraModel::getInstance();
 
-    for (uint8_t y = 0; y < frame_buffer->height; ++y)
-    {
-        for (uint8_t x = 0; x < frame_buffer->width; ++x)
-        {
+    for (uint8_t y = 0; y < frame_buffer->height; ++y) {
+        for (uint8_t x = 0; x < frame_buffer->width; ++x) {
             size_t current = (y * frame_buffer->width) + x;
             uint8_t oldpixel = frame_buffer->buf[current];
             uint8_t newpixel = oldpixel >= 128 ? 255 : 0;
@@ -16,44 +13,72 @@ void dither_image(camera_fb_t *frame_buffer)
             int8_t quant_error = oldpixel - newpixel;
 
             // Apply error diffusion based on the selected algorithm
-            switch (model->getDitherAlgorithm())
-            {
-            case JARVIS_JUDICE_NINKE:
-                frame_buffer->buf[(y * frame_buffer->width) + x + 1] += quant_error * 7 / 48;
-                frame_buffer->buf[(y * frame_buffer->width) + x + 2] += quant_error * 5 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 2] += quant_error * 3 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] += quant_error * 5 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x] += quant_error * 7 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] += quant_error * 5 / 48;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 2] += quant_error * 3 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x - 2] += quant_error * 1 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x - 1] += quant_error * 3 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x] += quant_error * 5 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x + 1] += quant_error * 3 / 48;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x + 2] += quant_error * 1 / 48;
-                break;
-            case STUCKI:
-                frame_buffer->buf[(y * frame_buffer->width) + x + 1] += quant_error * 8 / 42;
-                frame_buffer->buf[(y * frame_buffer->width) + x + 2] += quant_error * 4 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 2] += quant_error * 2 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] += quant_error * 4 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x] += quant_error * 8 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] += quant_error * 4 / 42;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 2] += quant_error * 2 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x - 2] += quant_error * 1 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x - 1] += quant_error * 2 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x] += quant_error * 4 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x + 1] += quant_error * 2 / 42;
-                frame_buffer->buf[(y + 2) * frame_buffer->width + x + 2] += quant_error * 1 / 42;
-                break;
-            case FLOYD_STEINBERG:
-            default:
-                // Default to Floyd-Steinberg dithering if an invalid algorithm is selected
-                frame_buffer->buf[(y * frame_buffer->width) + x + 1] += quant_error * 7 / 16;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] += quant_error * 3 / 16;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x] += quant_error * 5 / 16;
-                frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] += quant_error * 1 / 16;
-                break;
+            switch (model->getDitherAlgorithm()) {
+                case JARVIS_JUDICE_NINKE:
+                    frame_buffer->buf[(y * frame_buffer->width) + x + 1] +=
+                        quant_error * 7 / 48;
+                    frame_buffer->buf[(y * frame_buffer->width) + x + 2] +=
+                        quant_error * 5 / 48;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x - 2] +=
+                        quant_error * 3 / 48;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] +=
+                        quant_error * 5 / 48;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x] +=
+                        quant_error * 7 / 48;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] +=
+                        quant_error * 5 / 48;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x + 2] +=
+                        quant_error * 3 / 48;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x - 2] +=
+                        quant_error * 1 / 48;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x - 1] +=
+                        quant_error * 3 / 48;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x] +=
+                        quant_error * 5 / 48;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x + 1] +=
+                        quant_error * 3 / 48;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x + 2] +=
+                        quant_error * 1 / 48;
+                    break;
+                case STUCKI:
+                    frame_buffer->buf[(y * frame_buffer->width) + x + 1] +=
+                        quant_error * 8 / 42;
+                    frame_buffer->buf[(y * frame_buffer->width) + x + 2] +=
+                        quant_error * 4 / 42;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x - 2] +=
+                        quant_error * 2 / 42;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] +=
+                        quant_error * 4 / 42;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x] +=
+                        quant_error * 8 / 42;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] +=
+                        quant_error * 4 / 42;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x + 2] +=
+                        quant_error * 2 / 42;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x - 2] +=
+                        quant_error * 1 / 42;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x - 1] +=
+                        quant_error * 2 / 42;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x] +=
+                        quant_error * 4 / 42;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x + 1] +=
+                        quant_error * 2 / 42;
+                    frame_buffer->buf[(y + 2) * frame_buffer->width + x + 2] +=
+                        quant_error * 1 / 42;
+                    break;
+                case FLOYD_STEINBERG:
+                default:
+                    // Default to Floyd-Steinberg dithering if an invalid
+                    // algorithm is selected
+                    frame_buffer->buf[(y * frame_buffer->width) + x + 1] +=
+                        quant_error * 7 / 16;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x - 1] +=
+                        quant_error * 3 / 16;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x] +=
+                        quant_error * 5 / 16;
+                    frame_buffer->buf[(y + 1) * frame_buffer->width + x + 1] +=
+                        quant_error * 1 / 16;
+                    break;
             }
         }
     }

+ 5 - 9
firmware-update/firmware.ino

@@ -8,8 +8,7 @@
 camera_config_t config;
 
 // Entry point of the program.
-void setup()
-{
+void setup() {
     // Set up the camera model.
     CameraModel *model = CameraModel::getInstance();
 
@@ -45,22 +44,19 @@ void setup()
     config.fb_count = 1;
 
     // Begin serial communication.
-    Serial.begin(230400); // 115200
+    Serial.begin(230400);  // 115200
 
     // Initialize the camera.
     initialize(&config);
 }
 
 // Main loop of the program.
-void loop()
-{
+void loop() {
     // Get the camera model reference.
     CameraModel *model = CameraModel::getInstance();
-    if (model->getIsStreamEnabled())
-    {
+    if (model->getIsStreamEnabled()) {
         camera_fb_t *frame_buffer = esp_camera_fb_get();
-        if (frame_buffer)
-        {
+        if (frame_buffer) {
             process_image(frame_buffer);
             // Return the frame buffer back to the camera driver.
             esp_camera_fb_return(frame_buffer);

+ 1 - 1
firmware-update/initialize.h

@@ -1,8 +1,8 @@
 #ifndef INITIALIZE_H
 #define INITIALIZE_H
 
-#include <esp_camera.h>
 #include <FS.h>
+#include <esp_camera.h>
 
 #include "camera_model.h"
 #include "pins.h"

+ 3 - 6
firmware-update/initialize.ino

@@ -1,11 +1,9 @@
 #include "initialize.h"
 
-void initialize(camera_config_t *config)
-{
+void initialize(camera_config_t *config) {
     // Initialize camera.
     esp_err_t err = esp_camera_init(config);
-    if (err != ESP_OK)
-    {
+    if (err != ESP_OK) {
         return;
     }
 
@@ -13,8 +11,7 @@ void initialize(camera_config_t *config)
     CameraModel *model = CameraModel::getInstance();
 
     // Check if the flash is already on, if it is turn it off.
-    if (model->getIsFlashEnabled())
-    {
+    if (model->getIsFlashEnabled()) {
         pinMode(FLASH_GPIO_NUM, OUTPUT);
         digitalWrite(FLASH_GPIO_NUM, LOW);
         model->setIsFlashEnabled(false);

+ 1 - 1
firmware-update/process_image.h

@@ -1,8 +1,8 @@
 #ifndef PROCESS_IMAGE_H
 #define PROCESS_IMAGE_H
 
-#include <esp_camera.h>
 #include <FS.h>
+#include <esp_camera.h>
 
 #include "camera_model.h"
 #include "dithering.h"

+ 29 - 34
firmware-update/process_image.ino

@@ -1,61 +1,56 @@
 #include "process_image.h"
 
-void process_image(camera_fb_t *frame_buffer)
-{
+void process_image(camera_fb_t *frame_buffer) {
     // Get the camera model reference.
     CameraModel *model = CameraModel::getInstance();
 
-    // If dithering is not disabled, perform dithering on the image. Dithering is the
-    // process of approximating the look of a high-resolution grayscale image in a
-    // lower resolution by binary values (black & white), thereby representing
-    // different shades of gray.
-    if (!model->getIsDitheringDisabled())
-    {
-        dither_image(frame_buffer); // Invokes the dithering process on the frame buffer.
+    // If dithering is not disabled, perform dithering on the image. Dithering
+    // is the process of approximating the look of a high-resolution grayscale
+    // image in a lower resolution by binary values (black & white), thereby
+    // representing different shades of gray.
+    if (!model->getIsDitheringDisabled()) {
+        dither_image(frame_buffer);  // Invokes the dithering process on the
+                                     // frame buffer.
     }
 
     uint8_t flipper_y = 0;
 
     // Iterating over specific rows of the frame buffer.
-    for (uint8_t y = 28; y < 92; ++y)
-    {
-        Serial.print("Y:");      // Print "Y:" for every new row.
-        Serial.write(flipper_y); // Send the row identifier as a byte.
+    for (uint8_t y = 28; y < 92; ++y) {
+        Serial.print("Y:");       // Print "Y:" for every new row.
+        Serial.write(flipper_y);  // Send the row identifier as a byte.
 
-        // Calculate the actual y index in the frame buffer 1D array by multiplying the
-        // y value with the width of the frame buffer. This gives the starting index of
-        // the row in the 1D array.
+        // Calculate the actual y index in the frame buffer 1D array by
+        // multiplying the y value with the width of the frame buffer. This
+        // gives the starting index of the row in the 1D array.
         size_t true_y = y * frame_buffer->width;
 
         // Iterating over specific columns of each row in the frame buffer.
-        for (uint8_t x = 16; x < 144; x += 8)
-        { // step by 8 as we're packing 8 pixels per byte.
+        for (uint8_t x = 16; x < 144;
+             x += 8) {  // step by 8 as we're packing 8 pixels per byte.
             uint8_t packed_pixels = 0;
             // Packing 8 pixel values into one byte.
-            for (uint8_t bit = 0; bit < 8; ++bit)
-            {
+            for (uint8_t bit = 0; bit < 8; ++bit) {
                 // Check the invert flag and pack the pixels accordingly.
-                if (model->getIsInverted())
-                {
-                    // If invert is true, consider pixel as 1 if it's more than 127.
-                    if (frame_buffer->buf[true_y + x + bit] > 127)
-                    {
+                if (model->getIsInverted()) {
+                    // If invert is true, consider pixel as 1 if it's more than
+                    // 127.
+                    if (frame_buffer->buf[true_y + x + bit] > 127) {
                         packed_pixels |= (1 << (7 - bit));
                     }
-                }
-                else
-                {
-                    // If invert is false, consider pixel as 1 if it's less than 127.
-                    if (frame_buffer->buf[true_y + x + bit] < 127)
-                    {
+                } else {
+                    // If invert is false, consider pixel as 1 if it's less than
+                    // 127.
+                    if (frame_buffer->buf[true_y + x + bit] < 127) {
                         packed_pixels |= (1 << (7 - bit));
                     }
                 }
             }
-            Serial.write(packed_pixels); // Sending packed pixel byte.
+            Serial.write(packed_pixels);  // Sending packed pixel byte.
         }
 
-        ++flipper_y;    // Move to the next row.
-        Serial.flush(); // Ensure all data in the Serial buffer is sent before moving to the next iteration.
+        ++flipper_y;     // Move to the next row.
+        Serial.flush();  // Ensure all data in the Serial buffer is sent before
+                         // moving to the next iteration.
     }
 }

+ 1 - 1
firmware-update/save_picture.h

@@ -1,8 +1,8 @@
 #ifndef SAVE_PICTURE_H
 #define SAVE_PICTURE_H
 
-#include <esp_camera.h>
 #include <SD_MMC.h>
+#include <esp_camera.h>
 
 /**
  * Save the current picture to the onboard SD card.

+ 11 - 21
firmware-update/save_picture.ino

@@ -1,12 +1,10 @@
 #include "save_picture.h"
 
-void save_picture()
-{
+void save_picture() {
     sensor_t *cam = esp_camera_sensor_get();
 
     // Check if the sensor is valid.
-    if (!cam)
-    {
+    if (!cam) {
         Serial.println("Failed to acquire camera sensor");
         return;
     }
@@ -15,25 +13,20 @@ void save_picture()
     cam->set_pixformat(cam, PIXFORMAT_JPEG);
 
     // Set frame size based on available PSRAM.
-    if (psramFound())
-    {
+    if (psramFound()) {
         cam->set_framesize(cam, FRAMESIZE_UXGA);
-    }
-    else
-    {
+    } else {
         cam->set_framesize(cam, FRAMESIZE_SVGA);
     }
 
     // Get a frame buffer from camera.
     camera_fb_t *frame_buffer = esp_camera_fb_get();
-    if (!frame_buffer)
-    {
+    if (!frame_buffer) {
         // Camera capture failed
         return;
     }
 
-    if (!SD_MMC.begin())
-    {
+    if (!SD_MMC.begin()) {
         // SD Card Mount Failed.
         esp_camera_fb_return(frame_buffer);
         return;
@@ -47,17 +40,14 @@ void save_picture()
     fs::FS &fs = SD_MMC;
     File file = fs.open(path.c_str(), FILE_WRITE);
 
-    if (!file)
-    {
+    if (!file) {
         // Failed to open file in writing mode
-    }
-    else
-    {
-        if (file.write(frame_buffer->buf, frame_buffer->len) != frame_buffer->len)
-        {
+    } else {
+        if (file.write(frame_buffer->buf, frame_buffer->len) !=
+            frame_buffer->len) {
             // Failed to write the image to the file
         }
-        file.close(); // Close the file in any case.
+        file.close();  // Close the file in any case.
     }
 
     // Update framesize back to the default.

+ 1 - 1
firmware-update/serial_commands.h

@@ -1,8 +1,8 @@
 #ifndef SERIAL_COMMANDS_H
 #define SERIAL_COMMANDS_H
 
-#include <esp_camera.h>
 #include <FS.h>
+#include <esp_camera.h>
 
 #include "camera_model.h"
 #include "pins.h"

+ 56 - 61
firmware-update/serial_commands.ino

@@ -1,72 +1,67 @@
 #include "serial_commands.h"
 
-void serial_commands()
-{
-    if (Serial.available() > 0)
-    {
+void serial_commands() {
+    if (Serial.available() > 0) {
         // Get the camera model reference.
         CameraModel *model = CameraModel::getInstance();
 
         char input = Serial.read();
         sensor_t *cam = esp_camera_sensor_get();
 
-        switch (input)
-        {
-        case '>': // Toggle dithering.
-            model->setIsDitheringDisabled(
-                !model->getIsDitheringDisabled());
-            break;
-        case '<': // Toggle invert.
-            model->setIsInverted(
-                !model->getIsInverted());
-            break;
-        case 'b': // Remove brightness.
-            cam->set_contrast(cam, cam->status.brightness - 1);
-            break;
-        case 'B': // Add brightness.
-            cam->set_contrast(cam, cam->status.brightness + 1);
-            break;
-        case 'c': // Remove contrast.
-            cam->set_contrast(cam, cam->status.contrast - 1);
-            break;
-        case 'C': // Add contrast.
-            cam->set_contrast(cam, cam->status.contrast + 1);
-            break;
-        case 'f': // Turn the flash off.
-            pinMode(FLASH_GPIO_NUM, OUTPUT);
-            digitalWrite(FLASH_GPIO_NUM, LOW);
-            model->setIsFlashEnabled(false);
-            break;
-        case 'F': // Turn the flash on.
-            pinMode(FLASH_GPIO_NUM, OUTPUT);
-            digitalWrite(FLASH_GPIO_NUM, HIGH);
-            model->setIsFlashEnabled(true);
-            break;
-        case 'P': // Save image to the onboard SD card.
-            // @todo - Future feature.
-            // save_picture();
-            break;
-        case 'M': // Toggle Mirror.
-            cam->set_hmirror(cam, !cam->status.hmirror);
-            break;
-        case 's': // Stop stream.
-            model->setIsStreamEnabled(false);
-            break;
-        case 'S': // Start stream.
-            model->setIsStreamEnabled(true);
-            break;
-        case '0': // Use Floyd Steinberg dithering.
-            model->setDitherAlgorithm(FLOYD_STEINBERG);
-            break;
-        case '1': // Use Jarvis Judice dithering.
-            model->setDitherAlgorithm(JARVIS_JUDICE_NINKE);
-            break;
-        case '2': // Use Stucki dithering.
-            model->setDitherAlgorithm(STUCKI);
-            break;
-        default:
-            // Do nothing.
-            break;
+        switch (input) {
+            case '>':  // Toggle dithering.
+                model->setIsDitheringDisabled(!model->getIsDitheringDisabled());
+                break;
+            case '<':  // Toggle invert.
+                model->setIsInverted(!model->getIsInverted());
+                break;
+            case 'b':  // Remove brightness.
+                cam->set_contrast(cam, cam->status.brightness - 1);
+                break;
+            case 'B':  // Add brightness.
+                cam->set_contrast(cam, cam->status.brightness + 1);
+                break;
+            case 'c':  // Remove contrast.
+                cam->set_contrast(cam, cam->status.contrast - 1);
+                break;
+            case 'C':  // Add contrast.
+                cam->set_contrast(cam, cam->status.contrast + 1);
+                break;
+            case 'f':  // Turn the flash off.
+                pinMode(FLASH_GPIO_NUM, OUTPUT);
+                digitalWrite(FLASH_GPIO_NUM, LOW);
+                model->setIsFlashEnabled(false);
+                break;
+            case 'F':  // Turn the flash on.
+                pinMode(FLASH_GPIO_NUM, OUTPUT);
+                digitalWrite(FLASH_GPIO_NUM, HIGH);
+                model->setIsFlashEnabled(true);
+                break;
+            case 'P':  // Save image to the onboard SD card.
+                // @todo - Future feature.
+                // save_picture();
+                break;
+            case 'M':  // Toggle Mirror.
+                cam->set_hmirror(cam, !cam->status.hmirror);
+                break;
+            case 's':  // Stop stream.
+                model->setIsStreamEnabled(false);
+                break;
+            case 'S':  // Start stream.
+                model->setIsStreamEnabled(true);
+                break;
+            case '0':  // Use Floyd Steinberg dithering.
+                model->setDitherAlgorithm(FLOYD_STEINBERG);
+                break;
+            case '1':  // Use Jarvis Judice dithering.
+                model->setDitherAlgorithm(JARVIS_JUDICE_NINKE);
+                break;
+            case '2':  // Use Stucki dithering.
+                model->setDitherAlgorithm(STUCKI);
+                break;
+            default:
+                // Do nothing.
+                break;
         }
     }
 }