Bladeren bron

Camera settings (#3029)

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload
michael 1 jaar geleden
bovenliggende
commit
88b531ae8b
55 gewijzigde bestanden met toevoegingen van 6219 en 4713 verwijderingen
  1. 669 578
      code/components/jomjol_controlcamera/ClassControllCamera.cpp
  2. 93 59
      code/components/jomjol_controlcamera/ClassControllCamera.h
  3. 58 30
      code/components/jomjol_controlcamera/ov2640_sharpness.cpp
  4. 142 145
      code/components/jomjol_controlcamera/server_camera.cpp
  5. 0 1
      code/components/jomjol_controlcamera/server_camera.h
  6. 402 393
      code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp
  7. 51 54
      code/components/jomjol_flowcontroll/ClassFlowAlignment.h
  8. 425 141
      code/components/jomjol_flowcontroll/ClassFlowTakeImage.cpp
  9. 9 31
      code/components/jomjol_flowcontroll/ClassFlowTakeImage.h
  10. 460 266
      code/components/jomjol_flowcontroll/MainFlowControl.cpp
  11. 61 8
      code/components/jomjol_flowcontroll/MainFlowControl.h
  12. 554 444
      code/components/jomjol_helper/Helper.cpp
  13. 309 353
      code/components/jomjol_image_proc/CRotateImage.cpp
  14. 27 28
      code/components/jomjol_image_proc/CRotateImage.h
  15. 25 4
      param-docs/expert-params.txt
  16. 15 0
      param-docs/parameter-pages/TakeImage/CamAeLevel.md
  17. 13 0
      param-docs/parameter-pages/TakeImage/CamAec.md
  18. 13 0
      param-docs/parameter-pages/TakeImage/CamAec2.md
  19. 15 0
      param-docs/parameter-pages/TakeImage/CamAecValue.md
  20. 10 0
      param-docs/parameter-pages/TakeImage/CamAgc.md
  21. 13 0
      param-docs/parameter-pages/TakeImage/CamAgcGain.md
  22. 13 0
      param-docs/parameter-pages/TakeImage/CamAutoSharpness.md
  23. 10 0
      param-docs/parameter-pages/TakeImage/CamAwb.md
  24. 10 0
      param-docs/parameter-pages/TakeImage/CamAwbGain.md
  25. 10 0
      param-docs/parameter-pages/TakeImage/CamBpc.md
  26. 10 0
      param-docs/parameter-pages/TakeImage/CamBrightness.md
  27. 5 0
      param-docs/parameter-pages/TakeImage/CamColorbar.md
  28. 11 0
      param-docs/parameter-pages/TakeImage/CamContrast.md
  29. 13 0
      param-docs/parameter-pages/TakeImage/CamDcw.md
  30. 10 0
      param-docs/parameter-pages/TakeImage/CamDenoise.md
  31. 21 0
      param-docs/parameter-pages/TakeImage/CamGainceiling.md
  32. 10 0
      param-docs/parameter-pages/TakeImage/CamHmirror.md
  33. 10 0
      param-docs/parameter-pages/TakeImage/CamLenc.md
  34. 10 0
      param-docs/parameter-pages/TakeImage/CamQuality.md
  35. 10 0
      param-docs/parameter-pages/TakeImage/CamRawGma.md
  36. 11 0
      param-docs/parameter-pages/TakeImage/CamSaturation.md
  37. 13 0
      param-docs/parameter-pages/TakeImage/CamSharpness.md
  38. 21 0
      param-docs/parameter-pages/TakeImage/CamSpecialEffect.md
  39. 10 0
      param-docs/parameter-pages/TakeImage/CamVflip.md
  40. 18 0
      param-docs/parameter-pages/TakeImage/CamWbMode.md
  41. 10 0
      param-docs/parameter-pages/TakeImage/CamWpc.md
  42. 13 0
      param-docs/parameter-pages/TakeImage/CamZoom.md
  43. 14 0
      param-docs/parameter-pages/TakeImage/CamZoomOffsetX.md
  44. 14 0
      param-docs/parameter-pages/TakeImage/CamZoomOffsetY.md
  45. 13 0
      param-docs/parameter-pages/TakeImage/CamZoomSize.md
  46. 136 123
      sd-card/config/config.ini
  47. 64 50
      sd-card/html/edit_alignment.html
  48. 29 12
      sd-card/html/edit_analog.html
  49. 472 545
      sd-card/html/edit_config_template.html
  50. 71 26
      sd-card/html/edit_digits.html
  51. 557 411
      sd-card/html/edit_reference.html
  52. 30 28
      sd-card/html/index.html
  53. 223 185
      sd-card/html/overview.html
  54. 172 174
      sd-card/html/readconfigcommon.js
  55. 811 624
      sd-card/html/readconfigparam.js

File diff suppressed because it is too large
+ 669 - 578
code/components/jomjol_controlcamera/ClassControllCamera.cpp


+ 93 - 59
code/components/jomjol_controlcamera/ClassControllCamera.h

@@ -15,66 +15,100 @@
 #include "CImageBasis.h"
 #include "CImageBasis.h"
 #include "../../include/defines.h"
 #include "../../include/defines.h"
 
 
-class CCamera {
-    protected:
-        int ActualQuality;
-        framesize_t ActualResolution;
-        int brightness, contrast, saturation, autoExposureLevel;
-        bool isFixedExposure;
-        int waitbeforepicture_org;
-        int led_intensity = 4095;
-
-        void ledc_init(void);
-        bool CameraInitSuccessful = false;
-        bool demoMode = false;
-
-        bool loadNextDemoImage(camera_fb_t *fb);
-        long GetFileSize(std::string filename);
-
-        void SetCamWindow(sensor_t *s, int resolution, int xOffset, int yOffset, int xLength, int yLength);
-        void SetImageWidthHeightFromResolution(framesize_t resol);
-
-    public:
-        int image_height, image_width;
-        bool imageZoomEnabled = false;
-        int imageZoomMode = 0;
-        int imageZoomOffsetX = 0;
-        int imageZoomOffsetY = 0;
-        bool imageNegative = false;
-        bool imageAec2 = false;
-        bool imageAutoSharpness = false;
-        int imageSharpnessLevel = 0;
-    #ifdef GRAYSCALE_AS_DEFAULT
-        bool imageGrayscale = true;
-    #else
-        bool imageGrayscale = false;
-    #endif
-        
-        CCamera();
-        esp_err_t InitCam();
-
-        void LightOnOff(bool status);
-        void LEDOnOff(bool status);
-        esp_err_t CaptureToHTTP(httpd_req_t *req, int delay = 0);
-        esp_err_t CaptureToStream(httpd_req_t *req, bool FlashlightOn);
-        void SetQualitySize(int qual, framesize_t resol, bool zoomEnabled, int zoomMode, int zoomOffsetX, int zoomOffsetY);
-        bool SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation, int _autoExposureLevel, bool _grayscale, bool _negative, bool _aec2, int _sharpnessLevel);
-        void SetZoom(bool zoomEnabled, int zoomMode, int zoomOffsetX, int zoomOffsetY);
-        void GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol, bool &zoomEnabled, int &zoomMode, int &zoomOffsetX, int &zoomOffsetY);
-        void SetLEDIntensity(float _intrel);
-        bool testCamera(void);
-        void EnableAutoExposure(int flash_duration);
-        bool getCameraInitSuccessful();
-        void useDemoMode(void);
-       
-
-        framesize_t TextToFramesize(const char * text);
-
-        esp_err_t CaptureToFile(std::string nm, int delay = 0);
-        esp_err_t CaptureToBasisImage(CImageBasis *_Image, int delay = 0);
-};
+typedef enum
+{
+    OV2640_MODE_UXGA,
+    OV2640_MODE_SVGA,
+    OV2640_MODE_CIF
+} ov2640_sensor_mode_t;
 
 
+typedef struct
+{
+    framesize_t ImageFrameSize = FRAMESIZE_VGA; // 0 - 10
+    gainceiling_t ImageGainceiling;             // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
 
 
-extern CCamera Camera;
+    int ImageQuality;    // 0 - 63
+    int ImageBrightness; // (-2 to 2) - set brightness
+    int ImageContrast;   //-2 - 2
+    int ImageSaturation; //-2 - 2
+    int ImageSharpness;  //-2 - 2
+    bool ImageAutoSharpness;
+    int ImageSpecialEffect; // 0 - 6
+    int ImageWbMode;        // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
+    int ImageAwb;           // white balance enable (0 or 1)
+    int ImageAwbGain;       // Auto White Balance enable (0 or 1)
+    int ImageAec;           // auto exposure off (1 or 0)
+    int ImageAec2;          // automatic exposure sensor  (0 or 1)
+    int ImageAeLevel;       // auto exposure levels (-2 to 2)
+    int ImageAecValue;      // set exposure manually  (0-1200)
+    int ImageAgc;           // auto gain off (1 or 0)
+    int ImageAgcGain;       // set gain manually (0 - 30)
+    int ImageBpc;           // black pixel correction
+    int ImageWpc;           // white pixel correction
+    int ImageRawGma;        // (1 or 0)
+    int ImageLenc;          // lens correction (1 or 0)
+    int ImageHmirror;       // (0 or 1) flip horizontally
+    int ImageVflip;         // Invert image (0 or 1)
+    int ImageDcw;           // downsize enable (1 or 0)
+
+    int ImageWidth;
+    int ImageHeight;
+
+    int ImageLedIntensity;
+
+    bool ImageZoomEnabled;
+    int ImageZoomMode;
+    int ImageZoomOffsetX;
+    int ImageZoomOffsetY;
+    int ImageZoomSize;
+
+    int WaitBeforePicture;
+    bool isImageSize;
+
+    bool CameraInitSuccessful;
+    bool changedCameraSettings;
+    bool DemoMode;
+    bool SaveAllFiles;
+} camera_controll_config_temp_t;
+
+extern camera_controll_config_temp_t CCstatus;
 
 
+class CCamera
+{
+protected:
+    void ledc_init(void);
+    bool loadNextDemoImage(camera_fb_t *fb);
+    long GetFileSize(std::string filename);
+    void SetCamWindow(sensor_t *s, int resolution, int xOffset, int yOffset, int xTotal, int yTotal, int xOutput, int yOutput);
+    void SetImageWidthHeightFromResolution(framesize_t resol);
+
+public:
+    CCamera(void);
+    esp_err_t InitCam(void);
+	
+    void LightOnOff(bool status);
+    void LEDOnOff(bool status);
+
+    esp_err_t setSensorDatenFromCCstatus(void);
+    esp_err_t getSensorDatenToCCstatus(void);
+
+    esp_err_t CaptureToHTTP(httpd_req_t *req, int delay = 0);
+    esp_err_t CaptureToStream(httpd_req_t *req, bool FlashlightOn);
+
+    void SetQualityZoomSize(int qual, framesize_t resol, bool zoomEnabled, int zoomOffsetX, int zoomOffsetY, int imageSize);
+    void SetZoomSize(bool zoomEnabled, int zoomOffsetX, int zoomOffsetY, int imageSize);
+    void SetCamSharpness(bool _autoSharpnessEnabled, int _sharpnessLevel);
+    
+	void SetLEDIntensity(float _intrel);
+    bool testCamera(void);
+    bool getCameraInitSuccessful(void);
+    void useDemoMode(void);
+
+    framesize_t TextToFramesize(const char *text);
+	
+    esp_err_t CaptureToFile(std::string nm, int delay = 0);
+    esp_err_t CaptureToBasisImage(CImageBasis *_Image, int delay = 0);
+};
+
+extern CCamera Camera;
 #endif
 #endif

+ 58 - 30
code/components/jomjol_controlcamera/ov2640_sharpness.cpp

@@ -3,71 +3,78 @@
 #include "ov2640_sharpness.h"
 #include "ov2640_sharpness.h"
 
 
 
 
-#define OV2640_MAXLEVEL_SHARPNESS 6
-
 const static uint8_t OV2640_SHARPNESS_AUTO[]=
 const static uint8_t OV2640_SHARPNESS_AUTO[]=
 {
 {
-    0xFF, 0x00, 0xff,
-    0x92, 0x01, 0xff,
+	//reg, val, mask
+    0xFF, 0x00, 0xFF,
+    0x92, 0x01, 0xFF,
     0x93, 0x20, 0x20,
     0x93, 0x20, 0x20,
     0x00, 0x00, 0x00
     0x00, 0x00, 0x00
 };
 };
 
 
 const static uint8_t OV2640_SHARPNESS_MANUAL[]=
 const static uint8_t OV2640_SHARPNESS_MANUAL[]=
 {
 {
-    0xFF, 0x00, 0xff,
-    0x92, 0x01, 0xff,
+	//reg, val, mask
+    0xFF, 0x00, 0xFF,
+    0x92, 0x01, 0xFF,
     0x93, 0x00, 0x20,
     0x93, 0x00, 0x20,
     0x00, 0x00, 0x00
     0x00, 0x00, 0x00
 };
 };
 
 
 const static uint8_t OV2640_SHARPNESS_LEVEL0[]=
 const static uint8_t OV2640_SHARPNESS_LEVEL0[]=
 {
 {
-    0xFF, 0x00, 0xff,
-    0x92, 0x01, 0xff,
-    0x93, 0xc0, 0x1f,
+	//reg, val, mask
+    0xFF, 0x00, 0xFF,
+    0x92, 0x01, 0xFF,
+    0x93, 0xC0, 0x1F,
     0x00, 0x00, 0x00
     0x00, 0x00, 0x00
 };
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL1[]=
 const static uint8_t OV2640_SHARPNESS_LEVEL1[]=
 {
 {
-    0xFF, 0x00, 0xff,
-    0x92, 0x01, 0xff,
-    0x93, 0xc1, 0x1f,
+	//reg, val, mask
+    0xFF, 0x00, 0xFF,
+    0x92, 0x01, 0xFF,
+    0x93, 0xC1, 0x1F,
     0x00, 0x00, 0x00
     0x00, 0x00, 0x00
 };
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL2[]=
 const static uint8_t OV2640_SHARPNESS_LEVEL2[]=
 {
 {
-    0xFF, 0x00, 0xff,
-    0x92, 0x01, 0xff,
-    0x93, 0xc2, 0x1f,
+	//reg, val, mask
+    0xFF, 0x00, 0xFF,
+    0x92, 0x01, 0xFF,
+    0x93, 0xC2, 0x1F,
     0x00, 0x00, 0x00
     0x00, 0x00, 0x00
 };
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL3[]=
 const static uint8_t OV2640_SHARPNESS_LEVEL3[]=
 {
 {
-    0xFF, 0x00, 0xff,
-    0x92, 0x01, 0xff,
-    0x93, 0xc4, 0x1f,
+	//reg, val, mask
+    0xFF, 0x00, 0xFF,
+    0x92, 0x01, 0xFF,
+    0x93, 0xC4, 0x1F,
     0x00, 0x00, 0x00
     0x00, 0x00, 0x00
 };
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL4[]=
 const static uint8_t OV2640_SHARPNESS_LEVEL4[]=
 {
 {
-    0xFF, 0x00, 0xff,
-    0x92, 0x01, 0xff,
-    0x93, 0xc8, 0x1f,
+	//reg, val, mask
+    0xFF, 0x00, 0xFF,
+    0x92, 0x01, 0xFF,
+    0x93, 0xC8, 0x1F,
     0x00, 0x00, 0x00
     0x00, 0x00, 0x00
 };
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL5[]=
 const static uint8_t OV2640_SHARPNESS_LEVEL5[]=
 {
 {
-    0xFF, 0x00, 0xff,
-    0x92, 0x01, 0xff,
-    0x93, 0xd0, 0x1f,
+	//reg, val, mask
+    0xFF, 0x00, 0xFF,
+    0x92, 0x01, 0xFF,
+    0x93, 0xD0, 0x1F,
     0x00, 0x00, 0x00
     0x00, 0x00, 0x00
 };
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL6[]=
 const static uint8_t OV2640_SHARPNESS_LEVEL6[]=
 {
 {
-    0xFF, 0x00, 0xff,
-    0x92, 0x01, 0xff,
-    0x93, 0xdf, 0x1f,
+	//reg, val, mask
+    0xFF, 0x00, 0xFF,
+    0x92, 0x01, 0xFF,
+    0x93, 0xDF, 0x1F,
     0x00, 0x00, 0x00
     0x00, 0x00, 0x00
 };
 };
 
 
@@ -82,6 +89,9 @@ const static uint8_t *OV2640_SETTING_SHARPNESS[]=
     OV2640_SHARPNESS_LEVEL6  // +3 sharpness
     OV2640_SHARPNESS_LEVEL6  // +3 sharpness
 };
 };
 
 
+#define OV2640_MAXLEVEL_SHARPNESS 6
+
+
 static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
 static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
 {
 {
     uint8_t address;
     uint8_t address;
@@ -91,34 +101,52 @@ static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
     const uint8_t *pdata = ptab;
     const uint8_t *pdata = ptab;
 
 
     if (pdata == NULL)
     if (pdata == NULL)
+	{
         return -1;
         return -1;
+	}
 
 
     while (1)
     while (1)
     {   
     {   
         address = *pdata++;
         address = *pdata++;
         value = *pdata++;
         value = *pdata++;
         mask = *pdata++;
         mask = *pdata++;
+		
         if ((address == 0) && (value == 0) && (mask == 0))
         if ((address == 0) && (value == 0) && (mask == 0))
+		{
             break;
             break;
+		}
+		
         sensor->set_reg(sensor, address, mask, value);
         sensor->set_reg(sensor, address, mask, value);
     }   
     }   
 
 
     return 0;
     return 0;
 }
 }
 
 
+
 int ov2640_enable_auto_sharpness(sensor_t *sensor)
 int ov2640_enable_auto_sharpness(sensor_t *sensor)
 {
 {
     table_mask_write(sensor, OV2640_SHARPNESS_AUTO);
     table_mask_write(sensor, OV2640_SHARPNESS_AUTO);
+	
     return 0;
     return 0;
 }
 }
 
 
 
 
 int ov2640_set_sharpness(sensor_t *sensor, int sharpness)
 int ov2640_set_sharpness(sensor_t *sensor, int sharpness)
 {
 {
-    if ((sharpness < -3) || (sharpness > OV2640_MAXLEVEL_SHARPNESS - 3))
-        return -1;
+	int sharpness_temp = 0;
+	
+    if (sharpness < -3)
+	{
+        sharpness_temp = -3;
+	}
+	
+    if (sharpness > OV2640_MAXLEVEL_SHARPNESS - 3)
+	{
+        sharpness_temp = OV2640_MAXLEVEL_SHARPNESS - 3;
+	}	
 
 
     table_mask_write(sensor, OV2640_SHARPNESS_MANUAL);
     table_mask_write(sensor, OV2640_SHARPNESS_MANUAL);
-    table_mask_write(sensor, OV2640_SETTING_SHARPNESS[sharpness + 3]);
+    table_mask_write(sensor, OV2640_SETTING_SHARPNESS[sharpness_temp + 3]);
+	
     return 0;
     return 0;
 }
 }

+ 142 - 145
code/components/jomjol_controlcamera/server_camera.cpp

@@ -5,6 +5,7 @@
 
 
 #include "esp_camera.h"
 #include "esp_camera.h"
 #include "ClassControllCamera.h"
 #include "ClassControllCamera.h"
+#include "MainFlowControl.h"
 
 
 #include "ClassLogFile.h"
 #include "ClassLogFile.h"
 #include "esp_log.h"
 #include "esp_log.h"
@@ -13,191 +14,183 @@
 
 
 static const char *TAG = "server_cam";
 static const char *TAG = "server_cam";
 
 
-
-void PowerResetCamera(){
-
-        ESP_LOGD(TAG, "Resetting camera by power down line");
-        gpio_config_t conf;
-        conf.intr_type = GPIO_INTR_DISABLE;
-        conf.pin_bit_mask = 1LL << GPIO_NUM_32;
-        conf.mode = GPIO_MODE_OUTPUT;
-        conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
-        conf.pull_up_en = GPIO_PULLUP_DISABLE;
-        gpio_config(&conf);
-
-        // carefull, logic is inverted compared to reset pin
-        gpio_set_level(GPIO_NUM_32, 1);
-        vTaskDelay(1000 / portTICK_PERIOD_MS);
-        gpio_set_level(GPIO_NUM_32, 0);
-        vTaskDelay(1000 / portTICK_PERIOD_MS);
+void PowerResetCamera()
+{
+    ESP_LOGD(TAG, "Resetting camera by power down line");
+    gpio_config_t conf;
+    conf.intr_type = GPIO_INTR_DISABLE;
+    conf.pin_bit_mask = 1LL << GPIO_NUM_32;
+    conf.mode = GPIO_MODE_OUTPUT;
+    conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
+    conf.pull_up_en = GPIO_PULLUP_DISABLE;
+    gpio_config(&conf);
+
+    // carefull, logic is inverted compared to reset pin
+    gpio_set_level(GPIO_NUM_32, 1);
+    vTaskDelay(1000 / portTICK_PERIOD_MS);
+    gpio_set_level(GPIO_NUM_32, 0);
+    vTaskDelay(1000 / portTICK_PERIOD_MS);
 }
 }
 
 
-
 esp_err_t handler_lightOn(httpd_req_t *req)
 esp_err_t handler_lightOn(httpd_req_t *req)
 {
 {
-    #ifdef DEBUG_DETAIL_ON   
-        LogFile.WriteHeapInfo("handler_lightOn - Start");
-        ESP_LOGD(TAG, "handler_lightOn uri: %s", req->uri);
-    #endif
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("handler_lightOn - Start");
+    ESP_LOGD(TAG, "handler_lightOn uri: %s", req->uri);
+#endif
 
 
-    if (Camera.getCameraInitSuccessful()) 
+    if (Camera.getCameraInitSuccessful())
     {
     {
         Camera.LightOnOff(true);
         Camera.LightOnOff(true);
-        const char* resp_str = (const char*) req->user_ctx;
+        const char *resp_str = (const char *)req->user_ctx;
         httpd_resp_send(req, resp_str, strlen(resp_str));
         httpd_resp_send(req, resp_str, strlen(resp_str));
     }
     }
-    else 
+    else
     {
     {
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lighton not available!");
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lighton not available!");
         return ESP_ERR_NOT_FOUND;
         return ESP_ERR_NOT_FOUND;
     }
     }
 
 
-    #ifdef DEBUG_DETAIL_ON   
-        LogFile.WriteHeapInfo("handler_lightOn - Done");
-    #endif
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("handler_lightOn - Done");
+#endif
 
 
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
-
 esp_err_t handler_lightOff(httpd_req_t *req)
 esp_err_t handler_lightOff(httpd_req_t *req)
 {
 {
-    #ifdef DEBUG_DETAIL_ON   
-        LogFile.WriteHeapInfo("handler_lightOff - Start");
-        ESP_LOGD(TAG, "handler_lightOff uri: %s", req->uri);
-    #endif
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("handler_lightOff - Start");
+    ESP_LOGD(TAG, "handler_lightOff uri: %s", req->uri);
+#endif
 
 
-    if (Camera.getCameraInitSuccessful()) 
+    if (Camera.getCameraInitSuccessful())
     {
     {
         Camera.LightOnOff(false);
         Camera.LightOnOff(false);
-        const char* resp_str = (const char*) req->user_ctx;
-        httpd_resp_send(req, resp_str, strlen(resp_str));       
+        const char *resp_str = (const char *)req->user_ctx;
+        httpd_resp_send(req, resp_str, strlen(resp_str));
     }
     }
-    else 
+    else
     {
     {
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lightoff not available!");
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lightoff not available!");
         return ESP_ERR_NOT_FOUND;
         return ESP_ERR_NOT_FOUND;
     }
     }
 
 
-    #ifdef DEBUG_DETAIL_ON   
-        LogFile.WriteHeapInfo("handler_lightOff - Done");
-    #endif
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("handler_lightOff - Done");
+#endif
 
 
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
-
 esp_err_t handler_capture(httpd_req_t *req)
 esp_err_t handler_capture(httpd_req_t *req)
 {
 {
-    #ifdef DEBUG_DETAIL_ON   
-        LogFile.WriteHeapInfo("handler_capture - Start");
-    #endif
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("handler_capture - Start");
+#endif
 
 
-    if (Camera.getCameraInitSuccessful()) 
+    if (Camera.getCameraInitSuccessful())
     {
     {
-        int quality;
-        framesize_t res;
-        bool zoomEnabled;
-        int zoomMode;
-        int zoomOffsetX;
-        int zoomOffsetY;
-
-        Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
-
-        #ifdef DEBUG_DETAIL_ON
-            ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
-        #endif
+#ifdef DEBUG_DETAIL_ON
+        ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
+#endif
 
 
-        Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
+        // wenn die Kameraeinstellungen durch Erstellen eines neuen Referenzbildes verändert wurden, müssen sie neu gesetzt werden
+        if (CFstatus.changedCameraSettings)
+        {
+            Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
+            Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
+            CFstatus.changedCameraSettings = false;
+        }
 
 
         esp_err_t result;
         esp_err_t result;
         result = Camera.CaptureToHTTP(req);
         result = Camera.CaptureToHTTP(req);
 
 
-        #ifdef DEBUG_DETAIL_ON   
-            LogFile.WriteHeapInfo("handler_capture - Done");
-        #endif
+#ifdef DEBUG_DETAIL_ON
+        LogFile.WriteHeapInfo("handler_capture - Done");
+#endif
 
 
         return result;
         return result;
     }
     }
-        else 
+    else
     {
     {
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture not available!");
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture not available!");
         return ESP_ERR_NOT_FOUND;
         return ESP_ERR_NOT_FOUND;
     }
     }
 }
 }
 
 
-
 esp_err_t handler_capture_with_light(httpd_req_t *req)
 esp_err_t handler_capture_with_light(httpd_req_t *req)
 {
 {
-    #ifdef DEBUG_DETAIL_ON  
-        LogFile.WriteHeapInfo("handler_capture_with_light - Start");
-    #endif
-    
-    if (Camera.getCameraInitSuccessful()) 
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("handler_capture_with_light - Start");
+#endif
+
+    if (Camera.getCameraInitSuccessful())
     {
     {
         char _query[100];
         char _query[100];
         char _delay[10];
         char _delay[10];
-
-        int quality;
-        framesize_t res;    
-        bool zoomEnabled;
-        int zoomMode;
-        int zoomOffsetX;
-        int zoomOffsetY;
         int delay = 2500;
         int delay = 2500;
 
 
         if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
         if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
         {
         {
             ESP_LOGD(TAG, "Query: %s", _query);
             ESP_LOGD(TAG, "Query: %s", _query);
+
             if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
             if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
             {
             {
-                #ifdef DEBUG_DETAIL_ON   
-                    ESP_LOGD(TAG, "Delay: %s", _delay);
-                #endif        
+#ifdef DEBUG_DETAIL_ON
+                ESP_LOGD(TAG, "Delay: %s", _delay);
+#endif
                 delay = atoi(_delay);
                 delay = atoi(_delay);
 
 
                 if (delay < 0)
                 if (delay < 0)
+                {
                     delay = 0;
                     delay = 0;
+                }
             }
             }
         }
         }
 
 
-        Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
+#ifdef DEBUG_DETAIL_ON
+        ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
+#endif
 
 
-        #ifdef DEBUG_DETAIL_ON
-            ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
-        #endif
+        // wenn die Kameraeinstellungen durch Erstellen eines neuen Referenzbildes verändert wurden, müssen sie neu gesetzt werden
+        if (CFstatus.changedCameraSettings)
+        {
+            Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
+            Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
+            CFstatus.changedCameraSettings = false;
+        }
 
 
-        Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
         Camera.LightOnOff(true);
         Camera.LightOnOff(true);
         const TickType_t xDelay = delay / portTICK_PERIOD_MS;
         const TickType_t xDelay = delay / portTICK_PERIOD_MS;
-        vTaskDelay( xDelay );
+        vTaskDelay(xDelay);
 
 
         esp_err_t result;
         esp_err_t result;
-        result = Camera.CaptureToHTTP(req);  
+        result = Camera.CaptureToHTTP(req);
 
 
         Camera.LightOnOff(false);
         Camera.LightOnOff(false);
 
 
-        #ifdef DEBUG_DETAIL_ON   
-            LogFile.WriteHeapInfo("handler_capture_with_light - Done");
-        #endif
+#ifdef DEBUG_DETAIL_ON
+        LogFile.WriteHeapInfo("handler_capture_with_light - Done");
+#endif
 
 
         return result;
         return result;
     }
     }
-        else 
+    else
     {
     {
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture_with_flashlight not available!");
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture_with_flashlight not available!");
         return ESP_ERR_NOT_FOUND;
         return ESP_ERR_NOT_FOUND;
     }
     }
 }
 }
 
 
-
 esp_err_t handler_capture_save_to_file(httpd_req_t *req)
 esp_err_t handler_capture_save_to_file(httpd_req_t *req)
 {
 {
-    #ifdef DEBUG_DETAIL_ON   
-        LogFile.WriteHeapInfo("handler_capture_save_to_file - Start");
-    #endif
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("handler_capture_save_to_file - Start");
+#endif
 
 
-    if (Camera.getCameraInitSuccessful()) 
+    if (Camera.getCameraInitSuccessful())
     {
     {
         char _query[100];
         char _query[100];
         char _delay[10];
         char _delay[10];
@@ -205,98 +198,102 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
         char filename[100];
         char filename[100];
         std::string fn = "/sdcard/";
         std::string fn = "/sdcard/";
 
 
-
-        int quality;
-        framesize_t res;    
-        bool zoomEnabled;
-        int zoomMode;
-        int zoomOffsetX;
-        int zoomOffsetY;
-
         if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
         if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
         {
         {
             ESP_LOGD(TAG, "Query: %s", _query);
             ESP_LOGD(TAG, "Query: %s", _query);
+
             if (httpd_query_key_value(_query, "filename", filename, 100) == ESP_OK)
             if (httpd_query_key_value(_query, "filename", filename, 100) == ESP_OK)
             {
             {
                 fn.append(filename);
                 fn.append(filename);
-                #ifdef DEBUG_DETAIL_ON   
-                    ESP_LOGD(TAG, "Filename: %s", fn.c_str());
-                #endif
+#ifdef DEBUG_DETAIL_ON
+                ESP_LOGD(TAG, "Filename: %s", fn.c_str());
+#endif
             }
             }
             else
             else
+            {
                 fn.append("noname.jpg");
                 fn.append("noname.jpg");
+            }
 
 
             if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
             if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
             {
             {
-                #ifdef DEBUG_DETAIL_ON   
-                    ESP_LOGD(TAG, "Delay: %s", _delay);
-                #endif
+#ifdef DEBUG_DETAIL_ON
+                ESP_LOGD(TAG, "Delay: %s", _delay);
+#endif
                 delay = atoi(_delay);
                 delay = atoi(_delay);
 
 
                 if (delay < 0)
                 if (delay < 0)
+                {
                     delay = 0;
                     delay = 0;
+                }
             }
             }
         }
         }
         else
         else
+        {
             fn.append("noname.jpg");
             fn.append("noname.jpg");
+        }
 
 
-        Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
-        #ifdef DEBUG_DETAIL_ON   
-            ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
-        #endif
-        Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
+#ifdef DEBUG_DETAIL_ON
+        ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
+#endif
+
+        // wenn die Kameraeinstellungen durch Erstellen eines neuen Referenzbildes verändert wurden, müssen sie neu gesetzt werden
+        if (CFstatus.changedCameraSettings)
+        {
+            Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
+            Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
+            CFstatus.changedCameraSettings = false;
+        }
 
 
         esp_err_t result;
         esp_err_t result;
-        result = Camera.CaptureToFile(fn, delay);  
+        result = Camera.CaptureToFile(fn, delay);
 
 
-        const char* resp_str = (const char*) fn.c_str();
+        const char *resp_str = (const char *)fn.c_str();
         httpd_resp_send(req, resp_str, strlen(resp_str));
         httpd_resp_send(req, resp_str, strlen(resp_str));
 
 
-        #ifdef DEBUG_DETAIL_ON   
-            LogFile.WriteHeapInfo("handler_capture_save_to_file - Done");
-        #endif
+#ifdef DEBUG_DETAIL_ON
+        LogFile.WriteHeapInfo("handler_capture_save_to_file - Done");
+#endif
 
 
         return result;
         return result;
     }
     }
-    else 
+    else
     {
     {
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /save not available!");
         httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /save not available!");
         return ESP_ERR_NOT_FOUND;
         return ESP_ERR_NOT_FOUND;
     }
     }
 }
 }
 
 
-
 void register_server_camera_uri(httpd_handle_t server)
 void register_server_camera_uri(httpd_handle_t server)
 {
 {
-#ifdef DEBUG_DETAIL_ON   
+#ifdef DEBUG_DETAIL_ON
     ESP_LOGI(TAG, "server_part_camera - Registering URI handlers");
     ESP_LOGI(TAG, "server_part_camera - Registering URI handlers");
 #endif
 #endif
 
 
-    httpd_uri_t camuri = { };
-    camuri.method    = HTTP_GET;
+    httpd_uri_t camuri = {};
+    camuri.method = HTTP_GET;
 
 
-    camuri.uri       = "/lighton";
-    camuri.handler   = handler_lightOn;
-    camuri.user_ctx  = (void*) "Light On";    
+    camuri.uri = "/lighton";
+    camuri.handler = handler_lightOn;
+    camuri.user_ctx = (void *)"Light On";
     httpd_register_uri_handler(server, &camuri);
     httpd_register_uri_handler(server, &camuri);
 
 
-    camuri.uri       = "/lightoff";
-    camuri.handler   = handler_lightOff;
-    camuri.user_ctx  = (void*) "Light Off"; 
-    httpd_register_uri_handler(server, &camuri);    
-
-    camuri.uri       = "/capture";
-    camuri.handler   = handler_capture;
-    camuri.user_ctx  = NULL; 
-    httpd_register_uri_handler(server, &camuri);      
-
-    camuri.uri       = "/capture_with_flashlight";
-    camuri.handler   = handler_capture_with_light;
-    camuri.user_ctx  = NULL; 
-    httpd_register_uri_handler(server, &camuri);  
-
-    camuri.uri       = "/save";
-    camuri.handler   = handler_capture_save_to_file;
-    camuri.user_ctx  = NULL; 
-    httpd_register_uri_handler(server, &camuri);    
+    camuri.uri = "/lightoff";
+    camuri.handler = handler_lightOff;
+    camuri.user_ctx = (void *)"Light Off";
+    httpd_register_uri_handler(server, &camuri);
+
+    camuri.uri = "/capture";
+    camuri.handler = handler_capture;
+    camuri.user_ctx = NULL;
+    httpd_register_uri_handler(server, &camuri);
+
+    camuri.uri = "/capture_with_flashlight";
+    camuri.handler = handler_capture_with_light;
+    camuri.user_ctx = NULL;
+    httpd_register_uri_handler(server, &camuri);
+
+    camuri.uri = "/save";
+    camuri.handler = handler_capture_save_to_file;
+    camuri.user_ctx = NULL;
+    httpd_register_uri_handler(server, &camuri);
 }
 }

+ 0 - 1
code/components/jomjol_controlcamera/server_camera.h

@@ -10,7 +10,6 @@
 //#include "ClassControllCamera.h"
 //#include "ClassControllCamera.h"
 
 
 void register_server_camera_uri(httpd_handle_t server);
 void register_server_camera_uri(httpd_handle_t server);
-
 void PowerResetCamera();
 void PowerResetCamera();
 
 
 #endif
 #endif

+ 402 - 393
code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp

@@ -1,393 +1,402 @@
-#include "ClassFlowAlignment.h"
-#include "ClassFlowTakeImage.h"
-#include "ClassFlow.h"
-#include "MainFlowControl.h"
-
-#include "CRotateImage.h"
-#include "esp_log.h"
-
-
-#include "ClassLogFile.h"
-#include "psram.h"
-#include "../../include/defines.h"
-
-
-static const char *TAG = "ALIGN";
-
-// #define DEBUG_DETAIL_ON  
-
-
-void ClassFlowAlignment::SetInitialParameter(void)
-{
-    initialrotate = 0;
-    anz_ref = 0;
-    initialmirror = false;
-    use_antialiasing = false;
-    initialflip = false;
-    SaveAllFiles = false;
-    namerawimage =  "/sdcard/img_tmp/raw.jpg";
-    FileStoreRefAlignment = "/sdcard/config/align.txt";
-    ListFlowControll = NULL;
-    AlignAndCutImage = NULL;
-    ImageBasis = NULL;
-    ImageTMP = NULL;
-    #ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
-    AlgROI = (ImageData*)malloc_psram_heap(std::string(TAG) + "->AlgROI", sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
-    #endif
-    previousElement = NULL;
-    disabled = false;
-    SAD_criteria = 0.05;
-}
-
-
-ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
-{
-    SetInitialParameter();
-    ListFlowControll = lfc;
-
-    for (int i = 0; i < ListFlowControll->size(); ++i)
-    {
-        if (((*ListFlowControll)[i])->name().compare("ClassFlowTakeImage") == 0)
-        {
-            ImageBasis = ((ClassFlowTakeImage*) (*ListFlowControll)[i])->rawImage;
-        }
-    }
-
-    if (!ImageBasis)            // the function take pictures does not exist --> must be created first ONLY FOR TEST PURPOSES
-    {
-        ESP_LOGD(TAG, "CImageBasis had to be created");
-        ImageBasis = new CImageBasis("ImageBasis", namerawimage);
-    }
-}
-
-
-bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
-{
-    std::vector<string> splitted;
-    int suchex = 40;
-    int suchey = 40;
-    int alg_algo = 0; //default=0; 1 =HIGHACCURACY; 2= FAST; 3= OFF //add disable aligment algo |01.2023
-
-
-    aktparamgraph = trim(aktparamgraph);
-
-    if (aktparamgraph.size() == 0)
-        if (!this->GetNextParagraph(pfile, aktparamgraph))
-            return false;
-
-    if (aktparamgraph.compare("[Alignment]") != 0)       //Paragraph does not fit Alignment
-        return false;
-
-    while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
-    {
-        splitted = ZerlegeZeile(aktparamgraph);
-        if ((toUpper(splitted[0]) == "FLIPIMAGESIZE") && (splitted.size() > 1))
-        {
-            if (toUpper(splitted[1]) == "TRUE")
-                initialflip = true;
-        }
-        if ((toUpper(splitted[0]) == "INITIALMIRROR") && (splitted.size() > 1))
-        {
-            if (toUpper(splitted[1]) == "TRUE")
-                initialmirror = true;
-        }
-        if (((toUpper(splitted[0]) == "initialrotate") || (toUpper(splitted[0]) == "INITIALROTATE")) && (splitted.size() > 1))
-        {
-            this->initialrotate = std::stod(splitted[1]);
-        }
-        if ((toUpper(splitted[0]) == "SEARCHFIELDX") && (splitted.size() > 1))
-        {
-            suchex = std::stod(splitted[1]);
-        }   
-        if ((toUpper(splitted[0]) == "SEARCHFIELDY") && (splitted.size() > 1))
-        {
-            suchey = std::stod(splitted[1]);
-        }   
-        if ((toUpper(splitted[0]) == "ANTIALIASING") && (splitted.size() > 1))
-        {
-            if (toUpper(splitted[1]) == "TRUE")
-                use_antialiasing = true;
-        }   
-        if ((splitted.size() == 3) && (anz_ref < 2))
-        {
-            References[anz_ref].image_file = FormatFileName("/sdcard" + splitted[0]);
-            References[anz_ref].target_x = std::stod(splitted[1]);
-            References[anz_ref].target_y = std::stod(splitted[2]);
-            anz_ref++;
-        }
-
-        if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
-        {
-            if (toUpper(splitted[1]) == "TRUE")
-                SaveAllFiles = true;
-        }
-        if ((toUpper(splitted[0]) == "ALIGNMENTALGO") && (splitted.size() > 1))
-        {
-            #ifdef DEBUG_DETAIL_ON
-                std::string zw2 = "Alignment mode selected: " + splitted[1];
-                LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
-            #endif
-            if (toUpper(splitted[1]) == "HIGHACCURACY")
-                alg_algo = 1;
-            if (toUpper(splitted[1]) == "FAST")
-                alg_algo = 2;
-            if (toUpper(splitted[1]) == "OFF") //no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
-                alg_algo = 3;
-        }
-    }
-
-    for (int i = 0; i < anz_ref; ++i)
-    {
-        References[i].search_x = suchex;
-        References[i].search_y = suchey;
-        References[i].fastalg_SAD_criteria = SAD_criteria;
-        References[i].alignment_algo = alg_algo;
-        #ifdef DEBUG_DETAIL_ON
-            std::string zw2 = "Alignment mode written: " + std::to_string(alg_algo);
-            LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
-        #endif
-    }
-
-    //no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
-    if(References[0].alignment_algo != 3){
-        LoadReferenceAlignmentValues();
-    }
-    
-    return true;
-
-}
-
-
-string ClassFlowAlignment::getHTMLSingleStep(string host)
-{
-    string result;
-
-    result =          "<p>Rotated Image: </p> <p><img src=\"" + host + "/img_tmp/rot.jpg\"></p>\n";
-    result = result + "<p>Found Alignment: </p> <p><img src=\"" + host + "/img_tmp/rot_roi.jpg\"></p>\n";
-    result = result + "<p>Aligned Image: </p> <p><img src=\"" + host + "/img_tmp/alg.jpg\"></p>\n";
-    return result;
-}
-
-
-bool ClassFlowAlignment::doFlow(string time) 
-{
-    #ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
-        if (!AlgROI)  // AlgROI needs to be allocated before ImageTMP to avoid heap fragmentation
-        {
-            AlgROI = (ImageData*)heap_caps_realloc(AlgROI, sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);     
-            if (!AlgROI) 
-            {
-                LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlgROI");
-                LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
-            }
-        }
-
-        if (AlgROI)
-        {
-            ImageBasis->writeToMemoryAsJPG((ImageData*)AlgROI, 90);
-        }
-    #endif
-
-    if (!ImageTMP) 
-    {
-        ImageTMP = new CImageBasis("tmpImage", ImageBasis); // Make sure the name does not get change, it is relevant for the PSRAM allocation!
-        if (!ImageTMP) 
-        {
-            LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tmpImage -> Exec this round aborted!");
-            LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
-            return false;
-        }
-    }
-
-    delete AlignAndCutImage;
-    AlignAndCutImage = new CAlignAndCutImage("AlignAndCutImage", ImageBasis, ImageTMP);
-    if (!AlignAndCutImage) 
-    {
-        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlignAndCutImage -> Exec this round aborted!");
-        LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
-        return false;
-    }
-
-    CRotateImage rt("rawImage", AlignAndCutImage, ImageTMP, initialflip);
-    if (initialflip)
-    {
-        int _zw = ImageBasis->height;
-        ImageBasis->height = ImageBasis->width;
-        ImageBasis->width = _zw;
-
-        _zw = ImageTMP->width;
-        ImageTMP->width = ImageTMP->height;
-        ImageTMP->height = _zw;
-    }
-
-    if (initialmirror)
-    {
-        ESP_LOGD(TAG, "do mirror");
-        rt.Mirror();
-        
-        if (SaveAllFiles)
-            AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
-    }
- 
-    if ((initialrotate != 0) || initialflip)
-    {
-        if (use_antialiasing)
-            rt.RotateAntiAliasing(initialrotate);
-        else
-            rt.Rotate(initialrotate);
-        
-        if (SaveAllFiles)
-            AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
-    }
-
-
-        //no align algo if set to 3 = off //add disable aligment algo |01.2023
-        if(References[0].alignment_algo != 3){
-            if (!AlignAndCutImage->Align(&References[0], &References[1])) 
-            {
-                SaveReferenceAlignmentValues();
-            }
-        }// no align
-
-
-    #ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
-        if (AlgROI) {
-            //no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
-            if(References[0].alignment_algo != 3){
-                DrawRef(ImageTMP);
-            }
-            flowctrl.DigitalDrawROI(ImageTMP);
-            flowctrl.AnalogDrawROI(ImageTMP);
-            ImageTMP->writeToMemoryAsJPG((ImageData*)AlgROI, 90);
-        }
-    #endif
-    
-    if (SaveAllFiles)
-    {
-        AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
-        ImageTMP->SaveToFile(FormatFileName("/sdcard/img_tmp/alg_roi.jpg"));
-    }
-
-    // must be deleted to have memory space for loading tflite
-    delete ImageTMP;
-    ImageTMP = NULL;
-
-    //no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
-    if(References[0].alignment_algo != 3){
-        LoadReferenceAlignmentValues();
-    }
-
-    return true;
-}
-
-
-void ClassFlowAlignment::SaveReferenceAlignmentValues()
-{
-    FILE* pFile;
-    std::string zwtime, zwvalue;
-
-    pFile = fopen(FileStoreRefAlignment.c_str(), "w");
-
-    if (strlen(zwtime.c_str()) == 0)
-    {
-        time_t rawtime;
-        struct tm* timeinfo;
-        char buffer[80];
-
-        time(&rawtime);
-        timeinfo = localtime(&rawtime);
-
-        strftime(buffer, 80, "%Y-%m-%dT%H:%M:%S", timeinfo);
-        zwtime = std::string(buffer);
-    }
-
-    fputs(zwtime.c_str(), pFile);
-    fputs("\n", pFile);
-
-    zwvalue = std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_y);
-    zwvalue = zwvalue + "\t" +std::to_string(References[0].fastalg_SAD)+ "\t" +std::to_string(References[0].fastalg_min); 
-    zwvalue = zwvalue + "\t" +std::to_string(References[0].fastalg_max)+ "\t" +std::to_string(References[0].fastalg_avg); 
-    fputs(zwvalue.c_str(), pFile);
-    fputs("\n", pFile);
-
-    zwvalue = std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_y);
-    zwvalue = zwvalue + "\t" +std::to_string(References[1].fastalg_SAD)+ "\t" +std::to_string(References[1].fastalg_min); 
-    zwvalue = zwvalue + "\t" +std::to_string(References[1].fastalg_max)+ "\t" +std::to_string(References[1].fastalg_avg); 
-    fputs(zwvalue.c_str(), pFile);
-    fputs("\n", pFile);
-
-    fclose(pFile);
-}
-
-
-bool ClassFlowAlignment::LoadReferenceAlignmentValues(void)
-{
-    FILE* pFile;
-    char zw[1024];
-    string zwvalue;
-    std::vector<string> splitted;  
-
-
-    pFile = fopen(FileStoreRefAlignment.c_str(), "r");
-    if (pFile == NULL)
-        return false;
-
-    fgets(zw, 1024, pFile);
-    ESP_LOGD(TAG, "%s", zw);
-
-    fgets(zw, 1024, pFile);
-    splitted = ZerlegeZeile(std::string(zw), " \t");
-    if (splitted.size() < 6)
-    {
-        fclose(pFile);
-        return false;
-    }
-
-    References[0].fastalg_x = stoi(splitted[0]);
-    References[0].fastalg_y = stoi(splitted[1]);
-    References[0].fastalg_SAD = stof(splitted[2]);
-    References[0].fastalg_min = stoi(splitted[3]);
-    References[0].fastalg_max = stoi(splitted[4]);
-    References[0].fastalg_avg = stof(splitted[5]);
-
-    fgets(zw, 1024, pFile);
-    splitted = ZerlegeZeile(std::string(zw));
-    if (splitted.size() < 6)
-    {
-        fclose(pFile);
-        return false;
-    }
-
-    References[1].fastalg_x = stoi(splitted[0]);
-    References[1].fastalg_y = stoi(splitted[1]);
-    References[1].fastalg_SAD = stof(splitted[2]);
-    References[1].fastalg_min = stoi(splitted[3]);
-    References[1].fastalg_max = stoi(splitted[4]);
-    References[1].fastalg_avg = stof(splitted[5]);
-
-    fclose(pFile);
-
-
-    /*#ifdef DEBUG_DETAIL_ON
-        std::string _zw = "\tLoadReferences[0]\tx,y:\t" + std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_x);
-        _zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
-        _zw = _zw + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
-        LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
-        _zw = "\tLoadReferences[1]\tx,y:\t" + std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_x);
-        _zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
-        _zw = _zw + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
-        LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
-    #endif*/
-
-    return true;
-}
-
-
-void ClassFlowAlignment::DrawRef(CImageBasis *_zw)
-{
-    if (_zw->ImageOkay()) 
-    {
-        _zw->drawRect(References[0].target_x, References[0].target_y, References[0].width, References[0].height, 255, 0, 0, 2);
-        _zw->drawRect(References[1].target_x, References[1].target_y, References[1].width, References[1].height, 255, 0, 0, 2);
-    }
-}
+#include "ClassFlowAlignment.h"
+#include "ClassFlowTakeImage.h"
+#include "ClassFlow.h"
+#include "MainFlowControl.h"
+
+#include "CRotateImage.h"
+#include "esp_log.h"
+
+#include "ClassLogFile.h"
+#include "psram.h"
+#include "../../include/defines.h"
+
+static const char *TAG = "ALIGN";
+
+// #define DEBUG_DETAIL_ON
+
+void ClassFlowAlignment::SetInitialParameter(void)
+{
+    initialrotate = 0;
+    anz_ref = 0;
+    use_antialiasing = false;
+    initialflip = false;
+    SaveAllFiles = false;
+    namerawimage = "/sdcard/img_tmp/raw.jpg";
+    FileStoreRefAlignment = "/sdcard/config/align.txt";
+    ListFlowControll = NULL;
+    AlignAndCutImage = NULL;
+    ImageBasis = NULL;
+    ImageTMP = NULL;
+#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
+    AlgROI = (ImageData *)malloc_psram_heap(std::string(TAG) + "->AlgROI", sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
+#endif
+    previousElement = NULL;
+    disabled = false;
+    SAD_criteria = 0.05;
+}
+
+ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow *> *lfc)
+{
+    SetInitialParameter();
+    ListFlowControll = lfc;
+
+    for (int i = 0; i < ListFlowControll->size(); ++i)
+    {
+        if (((*ListFlowControll)[i])->name().compare("ClassFlowTakeImage") == 0)
+        {
+            ImageBasis = ((ClassFlowTakeImage *)(*ListFlowControll)[i])->rawImage;
+        }
+    }
+
+    if (!ImageBasis) // the function take pictures does not exist --> must be created first ONLY FOR TEST PURPOSES
+    {
+        ESP_LOGD(TAG, "CImageBasis had to be created");
+        ImageBasis = new CImageBasis("ImageBasis", namerawimage);
+    }
+}
+
+bool ClassFlowAlignment::ReadParameter(FILE *pfile, string &aktparamgraph)
+{
+    std::vector<string> splitted;
+    int suchex = 40;
+    int suchey = 40;
+    int alg_algo = 0; // default=0; 1 =HIGHACCURACY; 2= FAST; 3= OFF //add disable aligment algo |01.2023
+
+    aktparamgraph = trim(aktparamgraph);
+
+    if (aktparamgraph.size() == 0)
+    {
+        if (!this->GetNextParagraph(pfile, aktparamgraph))
+        {
+            return false;
+        }
+    }
+
+    if (aktparamgraph.compare("[Alignment]") != 0)
+    {
+        // Paragraph does not fit Alignment
+        return false;
+    }
+
+    while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
+    {
+        splitted = ZerlegeZeile(aktparamgraph);
+
+        if ((toUpper(splitted[0]) == "FLIPIMAGESIZE") && (splitted.size() > 1))
+        {
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                initialflip = true;
+            }
+        }
+        else if (((toUpper(splitted[0]) == "initialrotate") || (toUpper(splitted[0]) == "INITIALROTATE")) && (splitted.size() > 1))
+        {
+            this->initialrotate = std::stod(splitted[1]);
+        }
+        else if ((toUpper(splitted[0]) == "SEARCHFIELDX") && (splitted.size() > 1))
+        {
+            suchex = std::stod(splitted[1]);
+        }
+        else if ((toUpper(splitted[0]) == "SEARCHFIELDY") && (splitted.size() > 1))
+        {
+            suchey = std::stod(splitted[1]);
+        }
+        else if ((toUpper(splitted[0]) == "ANTIALIASING") && (splitted.size() > 1))
+        {
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                use_antialiasing = true;
+            }
+        }
+        else if ((splitted.size() == 3) && (anz_ref < 2))
+        {
+            References[anz_ref].image_file = FormatFileName("/sdcard" + splitted[0]);
+            References[anz_ref].target_x = std::stod(splitted[1]);
+            References[anz_ref].target_y = std::stod(splitted[2]);
+            anz_ref++;
+        }
+
+        else if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
+        {
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                SaveAllFiles = true;
+            }
+        }
+        else if ((toUpper(splitted[0]) == "ALIGNMENTALGO") && (splitted.size() > 1))
+        {
+#ifdef DEBUG_DETAIL_ON
+            std::string zw2 = "Alignment mode selected: " + splitted[1];
+            LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
+#endif
+            if (toUpper(splitted[1]) == "HIGHACCURACY")
+            {
+                alg_algo = 1;
+            }
+            if (toUpper(splitted[1]) == "FAST")
+            {
+                alg_algo = 2;
+            }
+            if (toUpper(splitted[1]) == "OFF")
+            {
+                // no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
+                alg_algo = 3;
+            }
+        }
+    }
+
+    for (int i = 0; i < anz_ref; ++i)
+    {
+        References[i].search_x = suchex;
+        References[i].search_y = suchey;
+        References[i].fastalg_SAD_criteria = SAD_criteria;
+        References[i].alignment_algo = alg_algo;
+#ifdef DEBUG_DETAIL_ON
+        std::string zw2 = "Alignment mode written: " + std::to_string(alg_algo);
+        LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
+#endif
+    }
+
+    // no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
+    if (References[0].alignment_algo != 3)
+    {
+        LoadReferenceAlignmentValues();
+    }
+
+    return true;
+}
+
+string ClassFlowAlignment::getHTMLSingleStep(string host)
+{
+    string result;
+
+    result = "<p>Rotated Image: </p> <p><img src=\"" + host + "/img_tmp/rot.jpg\"></p>\n";
+    result = result + "<p>Found Alignment: </p> <p><img src=\"" + host + "/img_tmp/rot_roi.jpg\"></p>\n";
+    result = result + "<p>Aligned Image: </p> <p><img src=\"" + host + "/img_tmp/alg.jpg\"></p>\n";
+    return result;
+}
+
+bool ClassFlowAlignment::doFlow(string time)
+{
+#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
+    if (!AlgROI) // AlgROI needs to be allocated before ImageTMP to avoid heap fragmentation
+    {
+        AlgROI = (ImageData *)heap_caps_realloc(AlgROI, sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
+
+        if (!AlgROI)
+        {
+            LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlgROI");
+            LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
+        }
+    }
+
+    if (AlgROI)
+    {
+        ImageBasis->writeToMemoryAsJPG((ImageData *)AlgROI, 90);
+    }
+#endif
+
+    if (!ImageTMP)
+    {
+        ImageTMP = new CImageBasis("tmpImage", ImageBasis); // Make sure the name does not get change, it is relevant for the PSRAM allocation!
+
+        if (!ImageTMP)
+        {
+            LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tmpImage -> Exec this round aborted!");
+            LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
+            return false;
+        }
+    }
+
+    delete AlignAndCutImage;
+    AlignAndCutImage = new CAlignAndCutImage("AlignAndCutImage", ImageBasis, ImageTMP);
+
+    if (!AlignAndCutImage)
+    {
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlignAndCutImage -> Exec this round aborted!");
+        LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
+        return false;
+    }
+
+    CRotateImage rt("rawImage", AlignAndCutImage, ImageTMP, initialflip);
+
+    if (initialflip)
+    {
+        int _zw = ImageBasis->height;
+        ImageBasis->height = ImageBasis->width;
+        ImageBasis->width = _zw;
+
+        _zw = ImageTMP->width;
+        ImageTMP->width = ImageTMP->height;
+        ImageTMP->height = _zw;
+    }
+
+    if ((initialrotate != 0) || initialflip)
+    {
+        if (use_antialiasing)
+        {
+            rt.RotateAntiAliasing(initialrotate);
+        }
+        else
+        {
+            rt.Rotate(initialrotate);
+        }
+
+        if (SaveAllFiles)
+        {
+            AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
+        }
+    }
+
+    // no align algo if set to 3 = off //add disable aligment algo |01.2023
+    if (References[0].alignment_algo != 3)
+    {
+        if (!AlignAndCutImage->Align(&References[0], &References[1]))
+        {
+            SaveReferenceAlignmentValues();
+        }
+    } // no align
+
+#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
+    if (AlgROI)
+    {
+        // no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
+        if (References[0].alignment_algo != 3)
+        {
+            DrawRef(ImageTMP);
+        }
+
+        flowctrl.DigitalDrawROI(ImageTMP);
+        flowctrl.AnalogDrawROI(ImageTMP);
+        ImageTMP->writeToMemoryAsJPG((ImageData *)AlgROI, 90);
+    }
+#endif
+
+    if (SaveAllFiles)
+    {
+        AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
+        ImageTMP->SaveToFile(FormatFileName("/sdcard/img_tmp/alg_roi.jpg"));
+    }
+
+    // must be deleted to have memory space for loading tflite
+    delete ImageTMP;
+    ImageTMP = NULL;
+
+    // no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
+    if (References[0].alignment_algo != 3)
+    {
+        LoadReferenceAlignmentValues();
+    }
+
+    return true;
+}
+
+void ClassFlowAlignment::SaveReferenceAlignmentValues()
+{
+    FILE *pFile;
+    std::string zwtime, zwvalue;
+
+    pFile = fopen(FileStoreRefAlignment.c_str(), "w");
+
+    if (strlen(zwtime.c_str()) == 0)
+    {
+        time_t rawtime;
+        struct tm *timeinfo;
+        char buffer[80];
+
+        time(&rawtime);
+        timeinfo = localtime(&rawtime);
+
+        strftime(buffer, 80, "%Y-%m-%dT%H:%M:%S", timeinfo);
+        zwtime = std::string(buffer);
+    }
+
+    fputs(zwtime.c_str(), pFile);
+    fputs("\n", pFile);
+
+    zwvalue = std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_y);
+    zwvalue = zwvalue + "\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
+    zwvalue = zwvalue + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
+    fputs(zwvalue.c_str(), pFile);
+    fputs("\n", pFile);
+
+    zwvalue = std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_y);
+    zwvalue = zwvalue + "\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
+    zwvalue = zwvalue + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
+    fputs(zwvalue.c_str(), pFile);
+    fputs("\n", pFile);
+
+    fclose(pFile);
+}
+
+bool ClassFlowAlignment::LoadReferenceAlignmentValues(void)
+{
+    FILE *pFile;
+    char zw[1024];
+    string zwvalue;
+    std::vector<string> splitted;
+
+    pFile = fopen(FileStoreRefAlignment.c_str(), "r");
+
+    if (pFile == NULL)
+        return false;
+
+    fgets(zw, 1024, pFile);
+    ESP_LOGD(TAG, "%s", zw);
+
+    fgets(zw, 1024, pFile);
+    splitted = ZerlegeZeile(std::string(zw), " \t");
+
+    if (splitted.size() < 6)
+    {
+        fclose(pFile);
+        return false;
+    }
+
+    References[0].fastalg_x = stoi(splitted[0]);
+    References[0].fastalg_y = stoi(splitted[1]);
+    References[0].fastalg_SAD = stof(splitted[2]);
+    References[0].fastalg_min = stoi(splitted[3]);
+    References[0].fastalg_max = stoi(splitted[4]);
+    References[0].fastalg_avg = stof(splitted[5]);
+
+    fgets(zw, 1024, pFile);
+    splitted = ZerlegeZeile(std::string(zw));
+
+    if (splitted.size() < 6)
+    {
+        fclose(pFile);
+        return false;
+    }
+
+    References[1].fastalg_x = stoi(splitted[0]);
+    References[1].fastalg_y = stoi(splitted[1]);
+    References[1].fastalg_SAD = stof(splitted[2]);
+    References[1].fastalg_min = stoi(splitted[3]);
+    References[1].fastalg_max = stoi(splitted[4]);
+    References[1].fastalg_avg = stof(splitted[5]);
+
+    fclose(pFile);
+
+    /*#ifdef DEBUG_DETAIL_ON
+        std::string _zw = "\tLoadReferences[0]\tx,y:\t" + std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_x);
+        _zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
+        _zw = _zw + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
+        LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
+        _zw = "\tLoadReferences[1]\tx,y:\t" + std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_x);
+        _zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
+        _zw = _zw + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
+        LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
+    #endif*/
+
+    return true;
+}
+
+void ClassFlowAlignment::DrawRef(CImageBasis *_zw)
+{
+    if (_zw->ImageOkay())
+    {
+        _zw->drawRect(References[0].target_x, References[0].target_y, References[0].width, References[0].height, 255, 0, 0, 2);
+        _zw->drawRect(References[1].target_x, References[1].target_y, References[1].width, References[1].height, 255, 0, 0, 2);
+    }
+}

+ 51 - 54
code/components/jomjol_flowcontroll/ClassFlowAlignment.h

@@ -1,54 +1,51 @@
-#pragma once
-
-#ifndef CLASSFLOWALIGNMENT_H
-#define CLASSFLOWALIGNMENT_H
-
-#include "ClassFlow.h"
-#include "Helper.h"
-#include "CAlignAndCutImage.h"
-#include "CFindTemplate.h"
-
-#include <string>
-
-using namespace std;
-
-class ClassFlowAlignment :
-    public ClassFlow
-{
-protected:
-    float initialrotate;
-    bool initialmirror;
-    bool initialflip;
-    bool use_antialiasing;
-    RefInfo References[2];
-    int anz_ref;
-    string namerawimage;
-    bool SaveAllFiles;
-    CAlignAndCutImage *AlignAndCutImage;
-    std::string FileStoreRefAlignment;
-    float SAD_criteria;
-
-    void SetInitialParameter(void);
-    bool LoadReferenceAlignmentValues(void);
-    void SaveReferenceAlignmentValues();
-
-public:
-    CImageBasis *ImageBasis, *ImageTMP;
-    #ifdef ALGROI_LOAD_FROM_MEM_AS_JPG 
-    ImageData *AlgROI;
-    #endif
-    
-    ClassFlowAlignment(std::vector<ClassFlow*>* lfc);
-
-    CAlignAndCutImage* GetAlignAndCutImage(){return AlignAndCutImage;};
-
-    void DrawRef(CImageBasis *_zw);
-
-    bool ReadParameter(FILE* pfile, string& aktparamgraph);
-    bool doFlow(string time);
-    string getHTMLSingleStep(string host);
-    string name(){return "ClassFlowAlignment";};
-};
-
-
-#endif //CLASSFLOWALIGNMENT_H
+#pragma once
+
+#ifndef CLASSFLOWALIGNMENT_H
+#define CLASSFLOWALIGNMENT_H
+
+#include "ClassFlow.h"
+#include "Helper.h"
+#include "CAlignAndCutImage.h"
+#include "CFindTemplate.h"
+
+#include <string>
+
+using namespace std;
+
+class ClassFlowAlignment : public ClassFlow
+{
+protected:
+    float initialrotate;
+    bool initialflip;
+    bool use_antialiasing;
+    RefInfo References[2];
+    int anz_ref;
+    string namerawimage;
+    bool SaveAllFiles;
+    CAlignAndCutImage *AlignAndCutImage;
+    std::string FileStoreRefAlignment;
+    float SAD_criteria;
+
+    void SetInitialParameter(void);
+    bool LoadReferenceAlignmentValues(void);
+    void SaveReferenceAlignmentValues();
+
+public:
+    CImageBasis *ImageBasis, *ImageTMP;
+#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
+    ImageData *AlgROI;
+#endif
+
+    ClassFlowAlignment(std::vector<ClassFlow *> *lfc);
+
+    CAlignAndCutImage *GetAlignAndCutImage() { return AlignAndCutImage; };
+
+    void DrawRef(CImageBasis *_zw);
+
+    bool ReadParameter(FILE *pfile, string &aktparamgraph);
+    bool doFlow(string time);
+    string getHTMLSingleStep(string host);
+    string name() { return "ClassFlowAlignment"; };
+};
+
+#endif // CLASSFLOWALIGNMENT_H

+ 425 - 141
code/components/jomjol_flowcontroll/ClassFlowTakeImage.cpp

@@ -1,9 +1,15 @@
+#include <iostream>
+#include <string>
+#include <vector>
+#include <regex>
+
 #include "ClassFlowTakeImage.h"
 #include "ClassFlowTakeImage.h"
 #include "Helper.h"
 #include "Helper.h"
 #include "ClassLogFile.h"
 #include "ClassLogFile.h"
 
 
 #include "CImageBasis.h"
 #include "CImageBasis.h"
 #include "ClassControllCamera.h"
 #include "ClassControllCamera.h"
+#include "MainFlowControl.h"
 
 
 #include "esp_wifi.h"
 #include "esp_wifi.h"
 #include "esp_log.h"
 #include "esp_log.h"
@@ -12,14 +18,14 @@
 
 
 #include <time.h>
 #include <time.h>
 
 
-// #define DEBUG_DETAIL_ON 
-
+// #define DEBUG_DETAIL_ON
 // #define WIFITURNOFF
 // #define WIFITURNOFF
 
 
-static const char* TAG = "TAKEIMAGE";
+static const char *TAG = "TAKEIMAGE";
 
 
-esp_err_t ClassFlowTakeImage::camera_capture(){
-    string nm =  namerawimage;
+esp_err_t ClassFlowTakeImage::camera_capture(void)
+{
+    string nm = namerawimage;
     Camera.CaptureToFile(nm);
     Camera.CaptureToFile(nm);
     time(&TimeImageTaken);
     time(&TimeImageTaken);
     localtime(&TimeImageTaken);
     localtime(&TimeImageTaken);
@@ -30,204 +36,479 @@ esp_err_t ClassFlowTakeImage::camera_capture(){
 void ClassFlowTakeImage::takePictureWithFlash(int flash_duration)
 void ClassFlowTakeImage::takePictureWithFlash(int flash_duration)
 {
 {
     // in case the image is flipped, it must be reset here //
     // in case the image is flipped, it must be reset here //
-    rawImage->width = image_width;          
-    rawImage->height = image_height;
-    /////////////////////////////////////////////////////////////////////////////////////
+    rawImage->width = CCstatus.ImageWidth;
+    rawImage->height = CCstatus.ImageHeight;
+
     ESP_LOGD(TAG, "flash_duration: %d", flash_duration);
     ESP_LOGD(TAG, "flash_duration: %d", flash_duration);
+
     Camera.CaptureToBasisImage(rawImage, flash_duration);
     Camera.CaptureToBasisImage(rawImage, flash_duration);
+
     time(&TimeImageTaken);
     time(&TimeImageTaken);
     localtime(&TimeImageTaken);
     localtime(&TimeImageTaken);
 
 
-    if (SaveAllFiles) rawImage->SaveToFile(namerawimage);
+    if (CCstatus.SaveAllFiles)
+    {
+        rawImage->SaveToFile(namerawimage);
+    }
 }
 }
 
 
 void ClassFlowTakeImage::SetInitialParameter(void)
 void ClassFlowTakeImage::SetInitialParameter(void)
 {
 {
-    waitbeforepicture = 5;
-    isImageSize = false;
-    ImageQuality = -1;    
     TimeImageTaken = 0;
     TimeImageTaken = 0;
-    ImageQuality = 5;
     rawImage = NULL;
     rawImage = NULL;
-    ImageSize = FRAMESIZE_VGA;
-    ZoomEnabled = false;
-    ZoomMode = 0;
-    zoomOffsetX = 0;
-    zoomOffsetY = 0;
-    ImageNegative = false;
-    ImageAec2 = false;
-#ifdef GRAYSCALE_AS_DEFAULT
-    ImageGrayscale = true;
-#else
-    ImageGrayscale = false;
-#endif
-    SaveAllFiles = false;
     disabled = false;
     disabled = false;
-    FixedExposure = false;
     namerawimage = "/sdcard/img_tmp/raw.jpg";
     namerawimage = "/sdcard/img_tmp/raw.jpg";
-}     
-
-
-ClassFlowTakeImage::ClassFlowTakeImage(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
-{
-    imagesLocation = "/log/source";
-    imagesRetention = 5;
-    SetInitialParameter();
 }
 }
 
 
-
-bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
+// auslesen der Kameraeinstellungen aus der config.ini
+// wird beim Start aufgerufen
+bool ClassFlowTakeImage::ReadParameter(FILE *pfile, string &aktparamgraph)
 {
 {
+    Camera.getSensorDatenToCCstatus(); // Kamera >>> CCstatus
+
     std::vector<string> splitted;
     std::vector<string> splitted;
 
 
     aktparamgraph = trim(aktparamgraph);
     aktparamgraph = trim(aktparamgraph);
-    int _brightness = 0;
-    int _contrast = 0;
-    int _saturation = 0;
-    int _sharpness = 0;
-    int _autoExposureLevel = 0;
 
 
     if (aktparamgraph.size() == 0)
     if (aktparamgraph.size() == 0)
+    {
         if (!this->GetNextParagraph(pfile, aktparamgraph))
         if (!this->GetNextParagraph(pfile, aktparamgraph))
+        {
             return false;
             return false;
+        }
+    }
 
 
-    if (aktparamgraph.compare("[TakeImage]") != 0)       // Paragraph does not fit TakeImage
+    if (aktparamgraph.compare("[TakeImage]") != 0)
+    {
+        // Paragraph does not fit TakeImage
         return false;
         return false;
+    }
 
 
     while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
     while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
     {
     {
         splitted = ZerlegeZeile(aktparamgraph);
         splitted = ZerlegeZeile(aktparamgraph);
-        if ((toUpper(splitted[0]) ==  "RAWIMAGESLOCATION") && (splitted.size() > 1))
+
+        if ((toUpper(splitted[0]) == "RAWIMAGESLOCATION") && (splitted.size() > 1))
         {
         {
             imagesLocation = "/sdcard" + splitted[1];
             imagesLocation = "/sdcard" + splitted[1];
             isLogImage = true;
             isLogImage = true;
         }
         }
-        if ((toUpper(splitted[0]) == "IMAGEQUALITY") && (splitted.size() > 1))
-            ImageQuality = std::stod(splitted[1]);
 
 
-        if ((toUpper(splitted[0]) == "ZOOM") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "RAWIMAGESRETENTION") && (splitted.size() > 1))
+        {
+            this->imagesRetention = std::stod(splitted[1]);
+        }
+
+        else if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
         {
         {
             if (toUpper(splitted[1]) == "TRUE")
             if (toUpper(splitted[1]) == "TRUE")
-                ZoomEnabled = true;
-            else if (toUpper(splitted[1]) == "FALSE")
-                ZoomEnabled = false;
-        }
-        if ((toUpper(splitted[0]) == "ZOOMMODE") && (splitted.size() > 1))
-            ZoomMode = std::stod(splitted[1]);
-        if ((toUpper(splitted[0]) == "ZOOMOFFSETX") && (splitted.size() > 1))
-            zoomOffsetX = std::stod(splitted[1]);
-        if ((toUpper(splitted[0]) == "ZOOMOFFSETY") && (splitted.size() > 1))
-            zoomOffsetY = std::stod(splitted[1]);
-        if ((toUpper(splitted[0]) == "GRAYSCALE") && (splitted.size() > 1))
+            {
+                CCstatus.SaveAllFiles = 1;
+            }
+            else
+            {
+                CCstatus.SaveAllFiles = 0;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "WAITBEFORETAKINGPICTURE") && (splitted.size() > 1))
+        {
+            int _WaitBeforePicture = std::stoi(splitted[1]);
+            if (_WaitBeforePicture != 0)
+            {
+                CCstatus.WaitBeforePicture = _WaitBeforePicture;
+            }
+            else
+            {
+                CCstatus.WaitBeforePicture = 2;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMGAINCEILING") && (splitted.size() > 1))
+        {
+            std::string _ImageGainceiling = toUpper(splitted[1]);
+            if (_ImageGainceiling == "X4")
+            {
+                CCstatus.ImageGainceiling = GAINCEILING_4X;
+            }
+            else if (_ImageGainceiling == "X8")
+            {
+                CCstatus.ImageGainceiling = GAINCEILING_8X;
+            }
+            else if (_ImageGainceiling == "X16")
+            {
+                CCstatus.ImageGainceiling = GAINCEILING_16X;
+            }
+            else if (_ImageGainceiling == "X32")
+            {
+                CCstatus.ImageGainceiling = GAINCEILING_32X;
+            }
+            else if (_ImageGainceiling == "X64")
+            {
+                CCstatus.ImageGainceiling = GAINCEILING_64X;
+            }
+            else if (_ImageGainceiling == "X128")
+            {
+                CCstatus.ImageGainceiling = GAINCEILING_128X;
+            }
+            else
+            {
+                CCstatus.ImageGainceiling = GAINCEILING_2X;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMQUALITY") && (splitted.size() > 1))
+        {
+            int _ImageQuality = std::stoi(splitted[1]);
+            if ((_ImageQuality >= 0) && (_ImageQuality <= 63))
+            {
+                CCstatus.ImageQuality = _ImageQuality;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMBRIGHTNESS") && (splitted.size() > 1))
+        {
+            int _ImageBrightness = std::stoi(splitted[1]);
+            if ((_ImageBrightness >= -2) && (_ImageBrightness <= 2))
+            {
+                CCstatus.ImageBrightness = _ImageBrightness;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMCONTRAST") && (splitted.size() > 1))
+        {
+            int _ImageContrast = std::stoi(splitted[1]);
+            if ((_ImageContrast >= -2) && (_ImageContrast <= 2))
+            {
+                CCstatus.ImageContrast = _ImageContrast;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMSATURATION") && (splitted.size() > 1))
+        {
+            int _ImageSaturation = std::stoi(splitted[1]);
+            if ((_ImageSaturation >= -2) && (_ImageSaturation <= 2))
+            {
+                CCstatus.ImageSaturation = _ImageSaturation;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMSHARPNESS") && (splitted.size() > 1))
+        {
+            int _ImageSharpness = std::stoi(splitted[1]);
+            if ((_ImageSharpness >= -2) && (_ImageSharpness <= 2))
+            {
+                CCstatus.ImageSharpness = _ImageSharpness;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMAUTOSHARPNESS") && (splitted.size() > 1))
         {
         {
             if (toUpper(splitted[1]) == "TRUE")
             if (toUpper(splitted[1]) == "TRUE")
-                ImageGrayscale = true;
-            else if (toUpper(splitted[1]) == "FALSE")
-                ImageGrayscale = false;
+            {
+                CCstatus.ImageAutoSharpness = 1;
+            }
+            else
+            {
+                CCstatus.ImageAutoSharpness = 0;
+            }
         }
         }
-        if ((toUpper(splitted[0]) == "NEGATIVE") && (splitted.size() > 1))
+
+        else if ((toUpper(splitted[0]) == "CAMSPECIALEFFECT") && (splitted.size() > 1))
+        {
+            std::string _ImageSpecialEffect = toUpper(splitted[1]);
+            if (_ImageSpecialEffect == "NEGATIVE")
+            {
+                CCstatus.ImageSpecialEffect = 1;
+            }
+            else if (_ImageSpecialEffect == "GRAYSCALE")
+            {
+                CCstatus.ImageSpecialEffect = 2;
+            }
+            else if (_ImageSpecialEffect == "RED")
+            {
+                CCstatus.ImageSpecialEffect = 3;
+            }
+            else if (_ImageSpecialEffect == "GREEN")
+            {
+                CCstatus.ImageSpecialEffect = 4;
+            }
+            else if (_ImageSpecialEffect == "BLUE")
+            {
+                CCstatus.ImageSpecialEffect = 5;
+            }
+            else if (_ImageSpecialEffect == "RETRO")
+            {
+                CCstatus.ImageSpecialEffect = 6;
+            }
+            else
+            {
+                CCstatus.ImageSpecialEffect = 0;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMWBMODE") && (splitted.size() > 1))
+        {
+            std::string _ImageWbMode = toUpper(splitted[1]);
+            if (_ImageWbMode == "SUNNY")
+            {
+                CCstatus.ImageWbMode = 1;
+            }
+            else if (_ImageWbMode == "CLOUDY")
+            {
+                CCstatus.ImageWbMode = 2;
+            }
+            else if (_ImageWbMode == "OFFICE")
+            {
+                CCstatus.ImageWbMode = 3;
+            }
+            else if (_ImageWbMode == "HOME")
+            {
+                CCstatus.ImageWbMode = 4;
+            }
+            else
+            {
+                CCstatus.ImageWbMode = 0;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMAWB") && (splitted.size() > 1))
         {
         {
             if (toUpper(splitted[1]) == "TRUE")
             if (toUpper(splitted[1]) == "TRUE")
-                ImageNegative = true;
-            else if (toUpper(splitted[1]) == "FALSE")
-                ImageNegative = false;
+            {
+                CCstatus.ImageAwb = 1;
+            }
+            else
+            {
+                CCstatus.ImageAwb = 0;
+            }
         }
         }
-        if ((toUpper(splitted[0]) == "AEC2") && (splitted.size() > 1))
+
+        else if ((toUpper(splitted[0]) == "CAMAWBGAIN") && (splitted.size() > 1))
+        {
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.ImageAwbGain = 1;
+            }
+            else
+            {
+                CCstatus.ImageAwbGain = 0;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMAEC") && (splitted.size() > 1))
+        {
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.ImageAec = 1;
+            }
+            else
+            {
+                CCstatus.ImageAec = 0;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMAEC2") && (splitted.size() > 1))
+        {
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.ImageAec2 = 1;
+            }
+            else
+            {
+                CCstatus.ImageAec2 = 0;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMAELEVEL") && (splitted.size() > 1))
+        {
+            int _ImageAeLevel = std::stoi(splitted[1]);
+            if ((_ImageAeLevel >= -2) && (_ImageAeLevel <= 2))
+            {
+                CCstatus.ImageAeLevel = _ImageAeLevel;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMAECVALUE") && (splitted.size() > 1))
+        {
+            int _ImageAecValue = std::stoi(splitted[1]);
+            if ((_ImageAecValue >= 0) && (_ImageAecValue <= 1200))
+            {
+                CCstatus.ImageAecValue = _ImageAecValue;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMAGC") && (splitted.size() > 1))
         {
         {
             if (toUpper(splitted[1]) == "TRUE")
             if (toUpper(splitted[1]) == "TRUE")
-                ImageAec2 = true;
-            else if (toUpper(splitted[1]) == "FALSE")
-                ImageAec2 = false;
+            {
+                CCstatus.ImageAgc = 1;
+            }
+            else
+            {
+                CCstatus.ImageAgc = 0;
+            }
         }
         }
-        if ((toUpper(splitted[0]) == "AUTOEXPOSURELEVEL") && (splitted.size() > 1))
-            _autoExposureLevel = std::stod(splitted[1]);
 
 
-        if ((toUpper(splitted[0]) == "IMAGESIZE") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "CAMAGCGAIN") && (splitted.size() > 1))
         {
         {
-            ImageSize = Camera.TextToFramesize(splitted[1].c_str());
-            isImageSize = true;
+            int _ImageAgcGain = std::stoi(splitted[1]);
+            if ((_ImageAgcGain >= 0) && (_ImageAgcGain <= 30))
+            {
+                CCstatus.ImageAgcGain = _ImageAgcGain;
+            }
         }
         }
 
 
-        if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "CAMBPC") && (splitted.size() > 1))
         {
         {
             if (toUpper(splitted[1]) == "TRUE")
             if (toUpper(splitted[1]) == "TRUE")
-                SaveAllFiles = true;
+            {
+                CCstatus.ImageBpc = 1;
+            }
+            else
+            {
+                CCstatus.ImageBpc = 0;
+            }
         }
         }
-        
-        if ((toUpper(splitted[0]) == "WAITBEFORETAKINGPICTURE") && (splitted.size() > 1))
+
+        else if ((toUpper(splitted[0]) == "CAMWPC") && (splitted.size() > 1))
         {
         {
-            waitbeforepicture = stoi(splitted[1]);
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.ImageWpc = 1;
+            }
+            else
+            {
+                CCstatus.ImageWpc = 0;
+            }
         }
         }
 
 
-        if ((toUpper(splitted[0]) == "RAWIMAGESRETENTION") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "CAMRAWGMA") && (splitted.size() > 1))
         {
         {
-            this->imagesRetention = std::stoi(splitted[1]);
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.ImageRawGma = 1;
+            }
+            else
+            {
+                CCstatus.ImageRawGma = 0;
+            }
         }
         }
 
 
-        if ((toUpper(splitted[0]) == "BRIGHTNESS") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "CAMLENC") && (splitted.size() > 1))
         {
         {
-            _brightness = stoi(splitted[1]);
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.ImageLenc = 1;
+            }
+            else
+            {
+                CCstatus.ImageLenc = 0;
+            }
         }
         }
 
 
-        if ((toUpper(splitted[0]) == "CONTRAST") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "CAMHMIRROR") && (splitted.size() > 1))
         {
         {
-            _contrast = stoi(splitted[1]);
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.ImageHmirror = 1;
+            }
+            else
+            {
+                CCstatus.ImageHmirror = 0;
+            }
         }
         }
 
 
-        if ((toUpper(splitted[0]) == "SATURATION") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "CAMVFLIP") && (splitted.size() > 1))
         {
         {
-            _saturation = stoi(splitted[1]);
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.ImageVflip = 1;
+            }
+            else
+            {
+                CCstatus.ImageVflip = 0;
+            }
         }
         }
 
 
-        if ((toUpper(splitted[0]) == "SHARPNESS") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "CAMDCW") && (splitted.size() > 1))
         {
         {
-            _sharpness = stoi(splitted[1]);
+            if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.ImageDcw = 1;
+            }
+            else
+            {
+                CCstatus.ImageDcw = 0;
+            }
         }
         }
 
 
-        if ((toUpper(splitted[0]) == "FIXEDEXPOSURE") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "CAMZOOM") && (splitted.size() > 1))
         {
         {
             if (toUpper(splitted[1]) == "TRUE")
             if (toUpper(splitted[1]) == "TRUE")
-                FixedExposure = true;  
+            {
+                CCstatus.ImageZoomEnabled = 1;
+            }
+            else
+            {
+                CCstatus.ImageZoomEnabled = 0;
+            }
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMZOOMOFFSETX") && (splitted.size() > 1))
+        {
+            CCstatus.ImageZoomOffsetX = std::stoi(splitted[1]);
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMZOOMOFFSETY") && (splitted.size() > 1))
+        {
+            CCstatus.ImageZoomOffsetY = std::stoi(splitted[1]);
+        }
+
+        else if ((toUpper(splitted[0]) == "CAMZOOMSIZE") && (splitted.size() > 1))
+        {
+            int _ImageZoomSize = std::stoi(splitted[1]);
+            if (_ImageZoomSize >= 0)
+            {
+                CCstatus.ImageZoomSize = _ImageZoomSize;
+            }
         }
         }
 
 
-        if ((toUpper(splitted[0]) == "LEDINTENSITY") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "LEDINTENSITY") && (splitted.size() > 1))
         {
         {
-            float ledintensity = stof(splitted[1]);
-            ledintensity = min((float) 100, ledintensity);
-            ledintensity = max((float) 0, ledintensity);
+            float ledintensity = std::stof(splitted[1]);
             Camera.SetLEDIntensity(ledintensity);
             Camera.SetLEDIntensity(ledintensity);
         }
         }
 
 
-        if ((toUpper(splitted[0]) == "DEMO") && (splitted.size() > 1))
+        else if ((toUpper(splitted[0]) == "DEMO") && (splitted.size() > 1))
         {
         {
             if (toUpper(splitted[1]) == "TRUE")
             if (toUpper(splitted[1]) == "TRUE")
+            {
+                CCstatus.DemoMode = true;
                 Camera.useDemoMode();
                 Camera.useDemoMode();
+            }
+            else
+            {
+                CCstatus.DemoMode = false;
+            }
         }
         }
     }
     }
 
 
-    Camera.SetBrightnessContrastSaturation(_brightness, _contrast, _saturation, _autoExposureLevel, ImageGrayscale, ImageNegative, ImageAec2, _sharpness);
-    Camera.SetQualitySize(ImageQuality, ImageSize, ZoomEnabled, ZoomMode, zoomOffsetX, zoomOffsetY);
+    Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
+    Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
 
 
-    image_width = Camera.image_width;
-    image_height = Camera.image_height;
     rawImage = new CImageBasis("rawImage");
     rawImage = new CImageBasis("rawImage");
-    rawImage->CreateEmptyImage(image_width, image_height, 3);
-
-    waitbeforepicture_store = waitbeforepicture;
-    if (FixedExposure && (waitbeforepicture > 0))
-    {
-//        ESP_LOGD(TAG, "Fixed Exposure enabled!");
-        int flash_duration = (int) (waitbeforepicture * 1000);
-        Camera.EnableAutoExposure(flash_duration);
-        waitbeforepicture = 0.2;
-//        flash_duration = (int) (waitbeforepicture * 1000);
-//        takePictureWithFlash(flash_duration);
-//        rawImage->SaveToFile("/sdcard/init2.jpg");
-    }
+    rawImage->CreateEmptyImage(CCstatus.ImageWidth, CCstatus.ImageHeight, 3);
 
 
     return true;
     return true;
 }
 }
 
 
+ClassFlowTakeImage::ClassFlowTakeImage(std::vector<ClassFlow *> *lfc) : ClassFlowImage(lfc, TAG)
+{
+    imagesLocation = "/log/source";
+    imagesRetention = 5;
+    SetInitialParameter();
+}
 
 
 string ClassFlowTakeImage::getHTMLSingleStep(string host)
 string ClassFlowTakeImage::getHTMLSingleStep(string host)
 {
 {
@@ -236,74 +517,78 @@ string ClassFlowTakeImage::getHTMLSingleStep(string host)
     return result;
     return result;
 }
 }
 
 
-
+// wird bei jeder Auswertrunde aufgerufen
 bool ClassFlowTakeImage::doFlow(string zwtime)
 bool ClassFlowTakeImage::doFlow(string zwtime)
 {
 {
     psram_init_shared_memory_for_take_image_step();
     psram_init_shared_memory_for_take_image_step();
 
 
     string logPath = CreateLogFolder(zwtime);
     string logPath = CreateLogFolder(zwtime);
 
 
-    int flash_duration = (int) (waitbeforepicture * 1000);
- 
-    #ifdef DEBUG_DETAIL_ON  
-        LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - Before takePictureWithFlash");
-    #endif
+    int flash_duration = (int)(CCstatus.WaitBeforePicture * 1000);
 
 
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - Before takePictureWithFlash");
+#endif
 
 
-    #ifdef WIFITURNOFF
-        esp_wifi_stop();        // to save power usage and 
-    #endif
+#ifdef WIFITURNOFF
+    esp_wifi_stop(); // to save power usage and
+#endif
 
 
-    takePictureWithFlash(flash_duration);
+    // wenn die Kameraeinstellungen durch Erstellen eines neuen Referenzbildes verändert wurden, müssen sie neu gesetzt werden
+    if (CFstatus.changedCameraSettings)
+    {
+        Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
+        Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
+        CFstatus.changedCameraSettings = false;
+    }
 
 
-    #ifdef WIFITURNOFF
-        esp_wifi_start();
-    #endif
+    takePictureWithFlash(flash_duration);
 
 
+#ifdef WIFITURNOFF
+    esp_wifi_start();
+#endif
 
 
-    #ifdef DEBUG_DETAIL_ON  
-        LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - After takePictureWithFlash");
-    #endif
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - After takePictureWithFlash");
+#endif
 
 
     LogImage(logPath, "raw", NULL, NULL, zwtime, rawImage);
     LogImage(logPath, "raw", NULL, NULL, zwtime, rawImage);
 
 
     RemoveOldLogs();
     RemoveOldLogs();
 
 
-    #ifdef DEBUG_DETAIL_ON  
-        LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - After RemoveOldLogs");
-    #endif
+#ifdef DEBUG_DETAIL_ON
+    LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - After RemoveOldLogs");
+#endif
 
 
     psram_deinit_shared_memory_for_take_image_step();
     psram_deinit_shared_memory_for_take_image_step();
 
 
     return true;
     return true;
 }
 }
 
 
-
 esp_err_t ClassFlowTakeImage::SendRawJPG(httpd_req_t *req)
 esp_err_t ClassFlowTakeImage::SendRawJPG(httpd_req_t *req)
 {
 {
-    int flash_duration = (int) (waitbeforepicture * 1000);
+    int flash_duration = (int)(CCstatus.WaitBeforePicture * 1000);
     time(&TimeImageTaken);
     time(&TimeImageTaken);
     localtime(&TimeImageTaken);
     localtime(&TimeImageTaken);
 
 
     return Camera.CaptureToHTTP(req, flash_duration);
     return Camera.CaptureToHTTP(req, flash_duration);
 }
 }
 
 
-
-ImageData* ClassFlowTakeImage::SendRawImage()
+ImageData *ClassFlowTakeImage::SendRawImage(void)
 {
 {
     CImageBasis *zw = new CImageBasis("SendRawImage", rawImage);
     CImageBasis *zw = new CImageBasis("SendRawImage", rawImage);
     ImageData *id;
     ImageData *id;
-    int flash_duration = (int) (waitbeforepicture * 1000);
+    int flash_duration = (int)(CCstatus.WaitBeforePicture * 1000);
     Camera.CaptureToBasisImage(zw, flash_duration);
     Camera.CaptureToBasisImage(zw, flash_duration);
     time(&TimeImageTaken);
     time(&TimeImageTaken);
     localtime(&TimeImageTaken);
     localtime(&TimeImageTaken);
 
 
-    id = zw->writeToMemoryAsJPG();    
+    id = zw->writeToMemoryAsJPG();
     delete zw;
     delete zw;
-    return id;  
+    return id;
 }
 }
 
 
-time_t ClassFlowTakeImage::getTimeImageTaken()
+time_t ClassFlowTakeImage::getTimeImageTaken(void)
 {
 {
     return TimeImageTaken;
     return TimeImageTaken;
 }
 }
@@ -312,4 +597,3 @@ ClassFlowTakeImage::~ClassFlowTakeImage(void)
 {
 {
     delete rawImage;
     delete rawImage;
 }
 }
-

+ 9 - 31
code/components/jomjol_flowcontroll/ClassFlowTakeImage.h

@@ -9,54 +9,32 @@
 
 
 #include <string>
 #include <string>
 
 
-class ClassFlowTakeImage :
-    public ClassFlowImage
+class ClassFlowTakeImage : public ClassFlowImage
 {
 {
 protected:
 protected:
-    float waitbeforepicture;
-    float waitbeforepicture_store;
-    framesize_t ImageSize;
-    bool isImageSize;
-    bool ZoomEnabled = false;
-    int ZoomMode = 0;
-    int zoomOffsetX = 0;
-    int zoomOffsetY = 0;
-    bool ImageGrayscale;
-    bool ImageNegative;
-    bool ImageAec2;
-    int ImageQuality;
     time_t TimeImageTaken;
     time_t TimeImageTaken;
     string namerawimage;
     string namerawimage;
-    int image_height, image_width;
-    bool SaveAllFiles;
-    bool FixedExposure;
 
 
-
-
-    void CopyFile(string input, string output);
-
-    esp_err_t camera_capture();
+    esp_err_t camera_capture(void);
     void takePictureWithFlash(int flash_duration);
     void takePictureWithFlash(int flash_duration);
 
 
-
-    void SetInitialParameter(void);       
+    void SetInitialParameter(void);
 
 
 public:
 public:
     CImageBasis *rawImage;
     CImageBasis *rawImage;
 
 
-    ClassFlowTakeImage(std::vector<ClassFlow*>* lfc);
+    ClassFlowTakeImage(std::vector<ClassFlow *> *lfc);
 
 
-    bool ReadParameter(FILE* pfile, string& aktparamgraph);
+    bool ReadParameter(FILE *pfile, string &aktparamgraph);
     bool doFlow(string time);
     bool doFlow(string time);
     string getHTMLSingleStep(string host);
     string getHTMLSingleStep(string host);
-    time_t getTimeImageTaken();
-    string name(){return "ClassFlowTakeImage";};
+    time_t getTimeImageTaken(void);
+    string name() { return "ClassFlowTakeImage"; };
 
 
-    ImageData* SendRawImage();
+    ImageData *SendRawImage(void);
     esp_err_t SendRawJPG(httpd_req_t *req);
     esp_err_t SendRawJPG(httpd_req_t *req);
 
 
     ~ClassFlowTakeImage(void);
     ~ClassFlowTakeImage(void);
 };
 };
 
 
-
-#endif //CLASSFFLOWTAKEIMAGE_H
+#endif // CLASSFFLOWTAKEIMAGE_H

File diff suppressed because it is too large
+ 460 - 266
code/components/jomjol_flowcontroll/MainFlowControl.cpp


+ 61 - 8
code/components/jomjol_flowcontroll/MainFlowControl.h

@@ -10,25 +10,78 @@
 #include "CImageBasis.h"
 #include "CImageBasis.h"
 #include "ClassFlowControll.h"
 #include "ClassFlowControll.h"
 
 
+typedef struct
+{
+    framesize_t ImageFrameSize = FRAMESIZE_VGA; // 0 - 10
+    gainceiling_t ImageGainceiling; // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
+
+    int ImageQuality;    // 0 - 63
+    int ImageBrightness; // (-2 to 2) - set brightness
+    int ImageContrast;   //-2 - 2
+    int ImageSaturation; //-2 - 2
+    int ImageSharpness;  //-2 - 2
+    bool ImageAutoSharpness;
+    int ImageSpecialEffect; // 0 - 6
+    int ImageWbMode;        // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
+    int ImageAwb;           // white balance enable (0 or 1)
+    int ImageAwbGain;       // Auto White Balance enable (0 or 1)
+    int ImageAec;           // auto exposure off (1 or 0)
+    int ImageAec2;          // automatic exposure sensor  (0 or 1)
+    int ImageAeLevel;       // auto exposure levels (-2 to 2)
+    int ImageAecValue;      // set exposure manually  (0-1200)
+    int ImageAgc;           // auto gain off (1 or 0)
+    int ImageAgcGain;       // set gain manually (0 - 30)
+    int ImageBpc;           // black pixel correction
+    int ImageWpc;           // white pixel correction
+    int ImageRawGma;        // (1 or 0)
+    int ImageLenc;          // lens correction (1 or 0)
+    int ImageHmirror;       // (0 or 1) flip horizontally
+    int ImageVflip;         // Invert image (0 or 1)
+    int ImageDcw;           // downsize enable (1 or 0)
+
+    int ImageWidth;
+    int ImageHeight;
+
+    int ImageLedIntensity;
+
+    bool ImageZoomEnabled;
+    int ImageZoomMode;
+    int ImageZoomOffsetX;
+    int ImageZoomOffsetY;
+    int ImageZoomSize;
+
+    int WaitBeforePicture;
+    bool isImageSize;
+
+    bool CameraInitSuccessful;
+    bool changedCameraSettings;
+    bool DemoMode;
+    bool SaveAllFiles;
+} camera_flow_config_temp_t;
+
+extern camera_flow_config_temp_t CFstatus;
 extern ClassFlowControll flowctrl;
 extern ClassFlowControll flowctrl;
 
 
+esp_err_t setCCstatusToCFstatus(void); // CCstatus >>> CFstatus
+esp_err_t setCFstatusToCCstatus(void); // CFstatus >>> CCstatus
+esp_err_t setCFstatusToCam(void);      // CFstatus >>> Kamera
 
 
 void register_server_main_flow_task_uri(httpd_handle_t server);
 void register_server_main_flow_task_uri(httpd_handle_t server);
 
 
-void CheckIsPlannedReboot();
-bool getIsPlannedReboot();
+void CheckIsPlannedReboot(void);
+bool getIsPlannedReboot(void);
 
 
-void InitializeFlowTask();
-void DeleteMainFlowTask();
-bool isSetupModusActive();
+void InitializeFlowTask(void);
+void DeleteMainFlowTask(void);
+bool isSetupModusActive(void);
 
 
-int getCountFlowRounds();
+int getCountFlowRounds(void);
 
 
 #ifdef ENABLE_MQTT
 #ifdef ENABLE_MQTT
 esp_err_t MQTTCtrlFlowStart(std::string _topic);
 esp_err_t MQTTCtrlFlowStart(std::string _topic);
-#endif //ENABLE_MQTT
+#endif // ENABLE_MQTT
 
 
 esp_err_t GetRawJPG(httpd_req_t *req);
 esp_err_t GetRawJPG(httpd_req_t *req);
 esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
 esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
 
 
-#endif //MAINFLOWCONTROL_H
+#endif // MAINFLOWCONTROL_H

+ 554 - 444
code/components/jomjol_helper/Helper.cpp

@@ -1,4 +1,4 @@
-//#pragma warning(disable : 4996)
+// #pragma warning(disable : 4996)
 
 
 #include "freertos/FreeRTOS.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/task.h"
@@ -14,7 +14,8 @@
 #include <math.h>
 #include <math.h>
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
-extern "C" {
+extern "C"
+{
 #endif
 #endif
 #include <dirent.h>
 #include <dirent.h>
 #ifdef __cplusplus
 #ifdef __cplusplus
@@ -32,7 +33,7 @@ extern "C" {
 #include "esp_vfs_fat.h"
 #include "esp_vfs_fat.h"
 #include "../sdmmc_common.h"
 #include "../sdmmc_common.h"
 
 
-static const char* TAG = "HELPER";
+static const char *TAG = "HELPER";
 
 
 using namespace std;
 using namespace std;
 
 
@@ -42,190 +43,205 @@ sdmmc_cid_t SDCardCid;
 sdmmc_csd_t SDCardCsd;
 sdmmc_csd_t SDCardCsd;
 bool SDCardIsMMC;
 bool SDCardIsMMC;
 
 
-// #define DEBUG_DETAIL_ON 
+// #define DEBUG_DETAIL_ON
 
 
 /////////////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////////////
-string getESPHeapInfo(){
+string getESPHeapInfo()
+{
 	string espInfoResultStr = "";
 	string espInfoResultStr = "";
 	char aMsgBuf[80];
 	char aMsgBuf[80];
 
 
-	size_t aFreeHeapSize  = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+	size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
 
 
-	size_t aFreeSPIHeapSize  = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
-	size_t aFreeInternalHeapSize  = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+	size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
+	size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 
 
 	size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
 	size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
 	size_t aHeapIntLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 	size_t aHeapIntLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 
 
-	size_t aMinFreeHeapSize =  heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
-	size_t aMinFreeInternalHeapSize =  heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
-
+	size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
+	size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 
 
-	sprintf(aMsgBuf,"Heap Total: %ld", (long) aFreeHeapSize);
+	sprintf(aMsgBuf, "Heap Total: %ld", (long)aFreeHeapSize);
 	espInfoResultStr += string(aMsgBuf);
 	espInfoResultStr += string(aMsgBuf);
 
 
-	sprintf(aMsgBuf," | SPI Free: %ld", (long) aFreeSPIHeapSize);
+	sprintf(aMsgBuf, " | SPI Free: %ld", (long)aFreeSPIHeapSize);
 	espInfoResultStr += string(aMsgBuf);
 	espInfoResultStr += string(aMsgBuf);
-	sprintf(aMsgBuf," | SPI Large Block:  %ld", (long) aHeapLargestFreeBlockSize);
+	sprintf(aMsgBuf, " | SPI Large Block:  %ld", (long)aHeapLargestFreeBlockSize);
 	espInfoResultStr += string(aMsgBuf);
 	espInfoResultStr += string(aMsgBuf);
-	sprintf(aMsgBuf," | SPI Min Free: %ld", (long) aMinFreeHeapSize);
+	sprintf(aMsgBuf, " | SPI Min Free: %ld", (long)aMinFreeHeapSize);
 	espInfoResultStr += string(aMsgBuf);
 	espInfoResultStr += string(aMsgBuf);
 
 
-	sprintf(aMsgBuf," | Int Free: %ld", (long) (aFreeInternalHeapSize));
+	sprintf(aMsgBuf, " | Int Free: %ld", (long)(aFreeInternalHeapSize));
 	espInfoResultStr += string(aMsgBuf);
 	espInfoResultStr += string(aMsgBuf);
-	sprintf(aMsgBuf," | Int Large Block:  %ld", (long) aHeapIntLargestFreeBlockSize);
+	sprintf(aMsgBuf, " | Int Large Block:  %ld", (long)aHeapIntLargestFreeBlockSize);
 	espInfoResultStr += string(aMsgBuf);
 	espInfoResultStr += string(aMsgBuf);
-	sprintf(aMsgBuf," | Int Min Free: %ld", (long) (aMinFreeInternalHeapSize));
+	sprintf(aMsgBuf, " | Int Min Free: %ld", (long)(aMinFreeInternalHeapSize));
 	espInfoResultStr += string(aMsgBuf);
 	espInfoResultStr += string(aMsgBuf);
-	
-	return 	espInfoResultStr;
-}
 
 
+	return espInfoResultStr;
+}
 
 
 size_t getESPHeapSize()
 size_t getESPHeapSize()
 {
 {
-   return heap_caps_get_free_size(MALLOC_CAP_8BIT);
+	return heap_caps_get_free_size(MALLOC_CAP_8BIT);
 }
 }
 
 
-
-size_t getInternalESPHeapSize() 
+size_t getInternalESPHeapSize()
 {
 {
-	return heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
+	return heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
 }
 }
 
 
-
-string getSDCardPartitionSize(){
+string getSDCardPartitionSize()
+{
 	FATFS *fs;
 	FATFS *fs;
-    uint32_t fre_clust, tot_sect;
+	uint32_t fre_clust, tot_sect;
 
 
-    /* Get volume information and free clusters of drive 0 */
-    f_getfree("0:", (DWORD *)&fre_clust, &fs);
-    tot_sect = ((fs->n_fatent - 2) * fs->csize) /1024 /(1024/SDCardCsd.sector_size);	//corrected by SD Card sector size (usually 512 bytes) and convert to MB
+	/* Get volume information and free clusters of drive 0 */
+	f_getfree("0:", (DWORD *)&fre_clust, &fs);
+	tot_sect = ((fs->n_fatent - 2) * fs->csize) / 1024 / (1024 / SDCardCsd.sector_size); // corrected by SD Card sector size (usually 512 bytes) and convert to MB
 
 
-	//ESP_LOGD(TAG, "%d MB total drive space (Sector size [bytes]: %d)", (int)tot_sect, (int)fs->ssize);
+	// ESP_LOGD(TAG, "%d MB total drive space (Sector size [bytes]: %d)", (int)tot_sect, (int)fs->ssize);
 
 
 	return std::to_string(tot_sect);
 	return std::to_string(tot_sect);
 }
 }
 
 
-
-string getSDCardFreePartitionSpace(){
+string getSDCardFreePartitionSpace()
+{
 	FATFS *fs;
 	FATFS *fs;
-    uint32_t fre_clust, fre_sect;
-  
-    /* Get volume information and free clusters of drive 0 */
-    f_getfree("0:", (DWORD *)&fre_clust, &fs);
-    fre_sect = (fre_clust * fs->csize) / 1024 /(1024/SDCardCsd.sector_size);	//corrected by SD Card sector size (usually 512 bytes) and convert to MB
+	uint32_t fre_clust, fre_sect;
+
+	/* Get volume information and free clusters of drive 0 */
+	f_getfree("0:", (DWORD *)&fre_clust, &fs);
+	fre_sect = (fre_clust * fs->csize) / 1024 / (1024 / SDCardCsd.sector_size); // corrected by SD Card sector size (usually 512 bytes) and convert to MB
 
 
-    //ESP_LOGD(TAG, "%d MB free drive space (Sector size [bytes]: %d)", (int)fre_sect, (int)fs->ssize);
+	// ESP_LOGD(TAG, "%d MB free drive space (Sector size [bytes]: %d)", (int)fre_sect, (int)fs->ssize);
 
 
 	return std::to_string(fre_sect);
 	return std::to_string(fre_sect);
 }
 }
 
 
-
-string getSDCardPartitionAllocationSize(){
+string getSDCardPartitionAllocationSize()
+{
 	FATFS *fs;
 	FATFS *fs;
-    uint32_t fre_clust, allocation_size;
-  
-    /* Get volume information and free clusters of drive 0 */
-    f_getfree("0:", (DWORD *)&fre_clust, &fs);
-    allocation_size = fs->ssize;
+	uint32_t fre_clust, allocation_size;
+
+	/* Get volume information and free clusters of drive 0 */
+	f_getfree("0:", (DWORD *)&fre_clust, &fs);
+	allocation_size = fs->ssize;
 
 
-    //ESP_LOGD(TAG, "SD Card Partition Allocation Size: %d bytes", allocation_size);
+	// ESP_LOGD(TAG, "SD Card Partition Allocation Size: %d bytes", allocation_size);
 
 
 	return std::to_string(allocation_size);
 	return std::to_string(allocation_size);
 }
 }
 
 
-
-void SaveSDCardInfo(sdmmc_card_t* card) {
+void SaveSDCardInfo(sdmmc_card_t *card)
+{
 	SDCardCid = card->cid;
 	SDCardCid = card->cid;
-    SDCardCsd = card->csd;
+	SDCardCsd = card->csd;
 	SDCardIsMMC = card->is_mmc;
 	SDCardIsMMC = card->is_mmc;
 }
 }
 
 
-
-string getSDCardManufacturer(){
+string getSDCardManufacturer()
+{
 	string SDCardManufacturer = SDCardParseManufacturerIDs(SDCardCid.mfg_id);
 	string SDCardManufacturer = SDCardParseManufacturerIDs(SDCardCid.mfg_id);
-	//ESP_LOGD(TAG, "SD Card Manufacturer: %s", SDCardManufacturer.c_str());
-	
+	// ESP_LOGD(TAG, "SD Card Manufacturer: %s", SDCardManufacturer.c_str());
+
 	return (SDCardManufacturer + " (ID: " + std::to_string(SDCardCid.mfg_id) + ")");
 	return (SDCardManufacturer + " (ID: " + std::to_string(SDCardCid.mfg_id) + ")");
 }
 }
 
 
-
-string getSDCardName(){
+string getSDCardName()
+{
 	char *SDCardName = SDCardCid.name;
 	char *SDCardName = SDCardCid.name;
-	//ESP_LOGD(TAG, "SD Card Name: %s", SDCardName); 
+	// ESP_LOGD(TAG, "SD Card Name: %s", SDCardName);
 
 
 	return std::string(SDCardName);
 	return std::string(SDCardName);
 }
 }
 
 
-
-string getSDCardCapacity(){
-	int SDCardCapacity = SDCardCsd.capacity / (1024/SDCardCsd.sector_size) / 1024;  // total sectors * sector size  --> Byte to MB (1024*1024)
-	//ESP_LOGD(TAG, "SD Card Capacity: %s", std::to_string(SDCardCapacity).c_str()); 
+string getSDCardCapacity()
+{
+	int SDCardCapacity = SDCardCsd.capacity / (1024 / SDCardCsd.sector_size) / 1024; // total sectors * sector size  --> Byte to MB (1024*1024)
+	// ESP_LOGD(TAG, "SD Card Capacity: %s", std::to_string(SDCardCapacity).c_str());
 
 
 	return std::to_string(SDCardCapacity);
 	return std::to_string(SDCardCapacity);
 }
 }
 
 
-
-string getSDCardSectorSize(){
+string getSDCardSectorSize()
+{
 	int SDCardSectorSize = SDCardCsd.sector_size;
 	int SDCardSectorSize = SDCardCsd.sector_size;
-	//ESP_LOGD(TAG, "SD Card Sector Size: %s bytes", std::to_string(SDCardSectorSize).c_str()); 
+	// ESP_LOGD(TAG, "SD Card Sector Size: %s bytes", std::to_string(SDCardSectorSize).c_str());
 
 
 	return std::to_string(SDCardSectorSize);
 	return std::to_string(SDCardSectorSize);
 }
 }
 
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 
-void memCopyGen(uint8_t* _source, uint8_t* _target, int _size)
+void memCopyGen(uint8_t *_source, uint8_t *_target, int _size)
 {
 {
-    for (int i = 0; i < _size; ++i)
-        *(_target + i) = *(_source + i);
+	for (int i = 0; i < _size; ++i)
+	{
+		*(_target + i) = *(_source + i);
+	}
 }
 }
 
 
-
 std::string FormatFileName(std::string input)
 std::string FormatFileName(std::string input)
 {
 {
 #ifdef ISWINDOWS_TRUE
 #ifdef ISWINDOWS_TRUE
-    input.erase(0, 1);
-    std::string os = "/";
-    std::string ns = "\\";
-    FindReplace(input, os, ns);
+	input.erase(0, 1);
+	std::string os = "/";
+	std::string ns = "\\";
+	FindReplace(input, os, ns);
 #endif
 #endif
-    return input;
+	return input;
 }
 }
 
 
+std::size_t file_size(const std::string &file_name)
+{
+	std::ifstream file(file_name.c_str(), std::ios::in | std::ios::binary);
+
+	if (!file)
+	{
+		return 0;
+	}
 
 
-std::size_t file_size(const std::string& file_name) {
-    std::ifstream file(file_name.c_str(),std::ios::in | std::ios::binary);
-    if (!file) return 0;
-    file.seekg (0, std::ios::end);
-    return static_cast<std::size_t>(file.tellg());
+	file.seekg(0, std::ios::end);
+	return static_cast<std::size_t>(file.tellg());
 }
 }
 
 
+void FindReplace(std::string &line, std::string &oldString, std::string &newString)
+{
+	const size_t oldSize = oldString.length();
 
 
-void FindReplace(std::string& line, std::string& oldString, std::string& newString) {
-    const size_t oldSize = oldString.length();
-
-    // do nothing if line is shorter than the string to find
-    if (oldSize > line.length()) return;
-
-    const size_t newSize = newString.length();
-    for (size_t pos = 0; ; pos += newSize) {
-        // Locate the substring to replace
-        pos = line.find(oldString, pos);
-        if (pos == std::string::npos) return;
-        if (oldSize == newSize) {
-            // if they're same size, use std::string::replace
-            line.replace(pos, oldSize, newString);
-        }
-        else {
-            // if not same size, replace by erasing and inserting
-            line.erase(pos, oldSize);
-            line.insert(pos, newString);
-        }
-    }
-}
+	// do nothing if line is shorter than the string to find
+	if (oldSize > line.length())
+	{
+		return;
+	}
+
+	const size_t newSize = newString.length();
 
 
+	for (size_t pos = 0;; pos += newSize)
+	{
+		// Locate the substring to replace
+		pos = line.find(oldString, pos);
+
+		if (pos == std::string::npos)
+		{
+			return;
+		}
+
+		if (oldSize == newSize)
+		{
+			// if they're same size, use std::string::replace
+			line.replace(pos, oldSize, newString);
+		}
+		else
+		{
+			// if not same size, replace by erasing and inserting
+			line.erase(pos, oldSize);
+			line.insert(pos, newString);
+		}
+	}
+}
 
 
 /**
 /**
  * Create a folder and its parent folders as needed
  * Create a folder and its parent folders as needed
@@ -237,56 +253,63 @@ bool MakeDir(std::string path)
 	LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Creating folder " + path + "...");
 	LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Creating folder " + path + "...");
 
 
 	bool bSuccess = false;
 	bool bSuccess = false;
-    int nRC = ::mkdir( path.c_str(), 0775 );
-    if( nRC == -1 )
-    {
-        switch( errno ) {
-            case ENOENT:
-                //parent didn't exist, try to create it
-				parent = path.substr(0, path.find_last_of('/'));
-        		LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Need to create parent folder first: " + parent);
-                if(MakeDir(parent)) {
-                    //Now, try to create again.
-                    bSuccess = 0 == ::mkdir( path.c_str(), 0775 );
-				}
-                else {
-        			LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to create parent folder: " + parent);
-                    bSuccess = false;
-				}
-                break;
-
-            case EEXIST:
-                //Done!
-                bSuccess = true;
-                break;
-				
-            default:
-				LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to create folder: " + path + " (errno: " + std::to_string(errno) + ")");
-                bSuccess = false;
-                break;
-        }
-    }
-    else {
-        bSuccess = true;
+	int nRC = ::mkdir(path.c_str(), 0775);
+
+	if (nRC == -1)
+	{
+		switch (errno)
+		{
+		case ENOENT:
+			// parent didn't exist, try to create it
+			parent = path.substr(0, path.find_last_of('/'));
+			LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Need to create parent folder first: " + parent);
+
+			if (MakeDir(parent))
+			{
+				// Now, try to create again.
+				bSuccess = 0 == ::mkdir(path.c_str(), 0775);
+			}
+			else
+			{
+				LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to create parent folder: " + parent);
+				bSuccess = false;
+			}
+			break;
+
+		case EEXIST:
+			// Done!
+			bSuccess = true;
+			break;
+
+		default:
+			LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to create folder: " + path + " (errno: " + std::to_string(errno) + ")");
+			bSuccess = false;
+			break;
+		}
+	}
+	else
+	{
+		bSuccess = true;
 	}
 	}
 
 
-    return bSuccess;
+	return bSuccess;
 }
 }
 
 
-
 bool ctype_space(const char c, string adddelimiter)
 bool ctype_space(const char c, string adddelimiter)
 {
 {
 	if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 11)
 	if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 11)
 	{
 	{
 		return true;
 		return true;
 	}
 	}
+
 	if (adddelimiter.find(c) != string::npos)
 	if (adddelimiter.find(c) != string::npos)
+	{
 		return true;
 		return true;
+	}
 
 
 	return false;
 	return false;
 }
 }
 
 
-
 string trim(string istring, string adddelimiter)
 string trim(string istring, string adddelimiter)
 {
 {
 	bool trimmed = false;
 	bool trimmed = false;
@@ -313,76 +336,87 @@ string trim(string istring, string adddelimiter)
 	}
 	}
 }
 }
 
 
-
 size_t findDelimiterPos(string input, string delimiter)
 size_t findDelimiterPos(string input, string delimiter)
 {
 {
 	size_t pos = std::string::npos;
 	size_t pos = std::string::npos;
-	size_t zw;
+	// size_t zw;
 	string akt_del;
 	string akt_del;
 
 
 	for (int anz = 0; anz < delimiter.length(); ++anz)
 	for (int anz = 0; anz < delimiter.length(); ++anz)
 	{
 	{
 		akt_del = delimiter[anz];
 		akt_del = delimiter[anz];
-		if ((zw = input.find(akt_del)) != std::string::npos)
+		size_t zw = input.find(akt_del);
+
+		if (zw != std::string::npos)
 		{
 		{
-			if (pos != std::string::npos)
+			if ((pos != std::string::npos) && (zw < pos))
 			{
 			{
-				if (zw < pos)
-					pos = zw;
+				pos = zw;
 			}
 			}
 			else
 			else
+			{
 				pos = zw;
 				pos = zw;
+			}
 		}
 		}
 	}
 	}
+
 	return pos;
 	return pos;
 }
 }
 
 
-
 bool RenameFile(string from, string to)
 bool RenameFile(string from, string to)
 {
 {
-//	ESP_LOGI(logTag, "Deleting file: %s", fn.c_str());
+	//	ESP_LOGI(logTag, "Deleting file: %s", fn.c_str());
 	/* Delete file */
 	/* Delete file */
-	FILE* fpSourceFile = fopen(from.c_str(), "rb");
-	if (!fpSourceFile)	// Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
+	FILE *fpSourceFile = fopen(from.c_str(), "rb");
+
+	// Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
+	if (!fpSourceFile)
 	{
 	{
 		ESP_LOGE(TAG, "DeleteFile: File %s existiert nicht!", from.c_str());
 		ESP_LOGE(TAG, "DeleteFile: File %s existiert nicht!", from.c_str());
 		return false;
 		return false;
 	}
 	}
+
 	fclose(fpSourceFile);
 	fclose(fpSourceFile);
 
 
 	rename(from.c_str(), to.c_str());
 	rename(from.c_str(), to.c_str());
+
 	return true;
 	return true;
 }
 }
 
 
-
 bool FileExists(string filename)
 bool FileExists(string filename)
 {
 {
-	FILE* fpSourceFile = fopen(filename.c_str(), "rb");
-	if (!fpSourceFile)	// Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
+	FILE *fpSourceFile = fopen(filename.c_str(), "rb");
+
+	// Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
+	if (!fpSourceFile)
 	{
 	{
 		return false;
 		return false;
 	}
 	}
+
 	fclose(fpSourceFile);
 	fclose(fpSourceFile);
-	return true;    
-}
 
 
+	return true;
+}
 
 
 bool DeleteFile(string fn)
 bool DeleteFile(string fn)
 {
 {
-//	ESP_LOGI(logTag, "Deleting file: %s", fn.c_str());
+	//	ESP_LOGI(logTag, "Deleting file: %s", fn.c_str());
 	/* Delete file */
 	/* Delete file */
-	FILE* fpSourceFile = fopen(fn.c_str(), "rb");
-	if (!fpSourceFile)	// Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
+	FILE *fpSourceFile = fopen(fn.c_str(), "rb");
+
+	// Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
+	if (!fpSourceFile)
 	{
 	{
 		ESP_LOGD(TAG, "DeleteFile: File %s existiert nicht!", fn.c_str());
 		ESP_LOGD(TAG, "DeleteFile: File %s existiert nicht!", fn.c_str());
 		return false;
 		return false;
 	}
 	}
+
 	fclose(fpSourceFile);
 	fclose(fpSourceFile);
 
 
 	unlink(fn.c_str());
 	unlink(fn.c_str());
-	return true;    
-}
 
 
+	return true;
+}
 
 
 bool CopyFile(string input, string output)
 bool CopyFile(string input, string output)
 {
 {
@@ -396,14 +430,16 @@ bool CopyFile(string input, string output)
 	}
 	}
 
 
 	char cTemp;
 	char cTemp;
-	FILE* fpSourceFile = fopen(input.c_str(), "rb");
-	if (!fpSourceFile)	// Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
+	FILE *fpSourceFile = fopen(input.c_str(), "rb");
+
+	// Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
+	if (!fpSourceFile)
 	{
 	{
 		ESP_LOGD(TAG, "File %s existiert nicht!", input.c_str());
 		ESP_LOGD(TAG, "File %s existiert nicht!", input.c_str());
 		return false;
 		return false;
 	}
 	}
 
 
-	FILE* fpTargetFile = fopen(output.c_str(), "wb");
+	FILE *fpTargetFile = fopen(output.c_str(), "wb");
 
 
 	// Code Section
 	// Code Section
 
 
@@ -418,53 +454,60 @@ bool CopyFile(string input, string output)
 	fclose(fpSourceFile);
 	fclose(fpSourceFile);
 	fclose(fpTargetFile);
 	fclose(fpTargetFile);
 	ESP_LOGD(TAG, "File copied: %s to %s", input.c_str(), output.c_str());
 	ESP_LOGD(TAG, "File copied: %s to %s", input.c_str(), output.c_str());
+
 	return true;
 	return true;
 }
 }
 
 
-
 string getFileFullFileName(string filename)
 string getFileFullFileName(string filename)
 {
 {
 	size_t lastpos = filename.find_last_of('/');
 	size_t lastpos = filename.find_last_of('/');
 
 
 	if (lastpos == string::npos)
 	if (lastpos == string::npos)
+	{
 		return "";
 		return "";
+	}
 
 
-//	ESP_LOGD(TAG, "Last position: %d", lastpos);
+	//	ESP_LOGD(TAG, "Last position: %d", lastpos);
 
 
 	string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
 	string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
 
 
 	return zw;
 	return zw;
 }
 }
 
 
-
 string getDirectory(string filename)
 string getDirectory(string filename)
 {
 {
 	size_t lastpos = filename.find('/');
 	size_t lastpos = filename.find('/');
 
 
 	if (lastpos == string::npos)
 	if (lastpos == string::npos)
+	{
 		lastpos = filename.find('\\');
 		lastpos = filename.find('\\');
+	}
 
 
 	if (lastpos == string::npos)
 	if (lastpos == string::npos)
+	{
 		return "";
 		return "";
+	}
 
 
-//	ESP_LOGD(TAG, "Directory: %d", lastpos);
+	//	ESP_LOGD(TAG, "Directory: %d", lastpos);
 
 
 	string zw = filename.substr(0, lastpos - 1);
 	string zw = filename.substr(0, lastpos - 1);
 	return zw;
 	return zw;
 }
 }
 
 
-
 string getFileType(string filename)
 string getFileType(string filename)
 {
 {
 	size_t lastpos = filename.rfind(".", filename.length());
 	size_t lastpos = filename.rfind(".", filename.length());
 	size_t neu_pos;
 	size_t neu_pos;
+
 	while ((neu_pos = filename.find(".", lastpos + 1)) > -1)
 	while ((neu_pos = filename.find(".", lastpos + 1)) > -1)
 	{
 	{
 		lastpos = neu_pos;
 		lastpos = neu_pos;
 	}
 	}
 
 
 	if (lastpos == string::npos)
 	if (lastpos == string::npos)
+	{
 		return "";
 		return "";
+	}
 
 
 	string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
 	string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
 	zw = toUpper(zw);
 	zw = toUpper(zw);
@@ -472,172 +515,213 @@ string getFileType(string filename)
 	return zw;
 	return zw;
 }
 }
 
 
-
 /* recursive mkdir */
 /* recursive mkdir */
-int mkdir_r(const char *dir, const mode_t mode) {
-    char tmp[FILE_PATH_MAX];
-    char *p = NULL;
-    struct stat sb;
-    size_t len;
-    
-    /* copy path */
-    len = strnlen (dir, FILE_PATH_MAX);
-    if (len == 0 || len == FILE_PATH_MAX) {
-        return -1;
-    }
-    memcpy (tmp, dir, len);
-    tmp[len] = '\0';
-
-    /* remove trailing slash */
-    if(tmp[len - 1] == '/') {
-        tmp[len - 1] = '\0';
-    }
-
-    /* check if path exists and is a directory */
-    if (stat (tmp, &sb) == 0) {
-        if (S_ISDIR (sb.st_mode)) {
-            return 0;
-        }
-    }
-    
-    /* recursive mkdir */
-    for(p = tmp + 1; *p; p++) {
-        if(*p == '/') {
-            *p = 0;
-            /* test path */
-            if (stat(tmp, &sb) != 0) {
-                /* path does not exist - create directory */
-                if (mkdir(tmp, mode) < 0) {
-                    return -1;
-                }
-            } else if (!S_ISDIR(sb.st_mode)) {
-                /* not a directory */
-                return -1;
-            }
-            *p = '/';
-        }
-    }
-    /* test path */
-    if (stat(tmp, &sb) != 0) {
-        /* path does not exist - create directory */
-        if (mkdir(tmp, mode) < 0) {
-            return -1;
-        }
-    } else if (!S_ISDIR(sb.st_mode)) {
-        /* not a directory */
-        return -1;
-    }
-    return 0;
-}
+int mkdir_r(const char *dir, const mode_t mode)
+{
+	char tmp[FILE_PATH_MAX];
+	char *p = NULL;
+	struct stat sb;
+	size_t len;
+
+	/* copy path */
+	len = strnlen(dir, FILE_PATH_MAX);
+
+	if (len == 0 || len == FILE_PATH_MAX)
+	{
+		return -1;
+	}
+
+	memcpy(tmp, dir, len);
+	tmp[len] = '\0';
+
+	/* remove trailing slash */
+	if (tmp[len - 1] == '/')
+	{
+		tmp[len - 1] = '\0';
+	}
+
+	/* check if path exists and is a directory */
+	if (stat(tmp, &sb) == 0)
+	{
+		if (S_ISDIR(sb.st_mode))
+		{
+			return 0;
+		}
+	}
+
+	/* recursive mkdir */
+	for (p = tmp + 1; *p; p++)
+	{
+		if (*p == '/')
+		{
+			*p = 0;
+
+			/* test path */
+			if (stat(tmp, &sb) != 0)
+			{
+				/* path does not exist - create directory */
+				if (mkdir(tmp, mode) < 0)
+				{
+					return -1;
+				}
+			}
+			else if (!S_ISDIR(sb.st_mode))
+			{
+				/* not a directory */
+				return -1;
+			}
+
+			*p = '/';
+		}
+	}
+
+	/* test path */
+	if (stat(tmp, &sb) != 0)
+	{
+		/* path does not exist - create directory */
+		if (mkdir(tmp, mode) < 0)
+		{
+			return -1;
+		}
+	}
+	else if (!S_ISDIR(sb.st_mode))
+	{
+		/* not a directory */
+		return -1;
+	}
 
 
+	return 0;
+}
 
 
 string toUpper(string in)
 string toUpper(string in)
 {
 {
 	for (int i = 0; i < in.length(); ++i)
 	for (int i = 0; i < in.length(); ++i)
+	{
 		in[i] = toupper(in[i]);
 		in[i] = toupper(in[i]);
-	
+	}
+
 	return in;
 	return in;
 }
 }
 
 
-
 string toLower(string in)
 string toLower(string in)
 {
 {
 	for (int i = 0; i < in.length(); ++i)
 	for (int i = 0; i < in.length(); ++i)
+	{
 		in[i] = tolower(in[i]);
 		in[i] = tolower(in[i]);
-	
+	}
+
 	return in;
 	return in;
 }
 }
 
 
-
 // CPU Temp
 // CPU Temp
 extern "C" uint8_t temprature_sens_read();
 extern "C" uint8_t temprature_sens_read();
 float temperatureRead()
 float temperatureRead()
 {
 {
-    return (temprature_sens_read() - 32) / 1.8;
+	return (temprature_sens_read() - 32) / 1.8;
 }
 }
 
 
-
-time_t addDays(time_t startTime, int days) {
-	struct tm* tm = localtime(&startTime);
+time_t addDays(time_t startTime, int days)
+{
+	struct tm *tm = localtime(&startTime);
 	tm->tm_mday += days;
 	tm->tm_mday += days;
 	return mktime(tm);
 	return mktime(tm);
 }
 }
 
 
-
-int removeFolder(const char* folderPath, const char* logTag) {
-	//ESP_LOGD(logTag, "Delete content in path %s", folderPath);
+int removeFolder(const char *folderPath, const char *logTag)
+{
+	// ESP_LOGD(logTag, "Delete content in path %s", folderPath);
 
 
 	DIR *dir = opendir(folderPath);
 	DIR *dir = opendir(folderPath);
-    if (!dir) {
-        ESP_LOGE(logTag, "Failed to stat dir: %s", folderPath);
-        return -1;
-    }
-
-    struct dirent *entry;
-    int deleted = 0;
-    while ((entry = readdir(dir)) != NULL) {
-        std::string path = string(folderPath) + "/" + entry->d_name;
-		if (entry->d_type == DT_REG) {
-			//ESP_LOGD(logTag, "Delete file %s", path.c_str());
-			if (unlink(path.c_str()) == 0) {
-				deleted ++;
-			} else {
+
+	if (!dir)
+	{
+		ESP_LOGE(logTag, "Failed to stat dir: %s", folderPath);
+		return -1;
+	}
+
+	struct dirent *entry;
+	int deleted = 0;
+
+	while ((entry = readdir(dir)) != NULL)
+	{
+		std::string path = string(folderPath) + "/" + entry->d_name;
+
+		if (entry->d_type == DT_REG)
+		{
+			// ESP_LOGD(logTag, "Delete file %s", path.c_str());
+			if (unlink(path.c_str()) == 0)
+			{
+				deleted++;
+			}
+			else
+			{
 				ESP_LOGE(logTag, "can't delete file: %s", path.c_str());
 				ESP_LOGE(logTag, "can't delete file: %s", path.c_str());
 			}
 			}
-        } else if (entry->d_type == DT_DIR) {
+		}
+		else if (entry->d_type == DT_DIR)
+		{
 			deleted += removeFolder(path.c_str(), logTag);
 			deleted += removeFolder(path.c_str(), logTag);
 		}
 		}
-    }
-    
-    closedir(dir);
-	if (rmdir(folderPath) != 0) {
+	}
+
+	closedir(dir);
+
+	if (rmdir(folderPath) != 0)
+	{
 		ESP_LOGE(logTag, "can't delete folder: %s", folderPath);
 		ESP_LOGE(logTag, "can't delete folder: %s", folderPath);
 	}
 	}
+
 	ESP_LOGD(logTag, "%d files in folder %s deleted.", deleted, folderPath);
 	ESP_LOGD(logTag, "%d files in folder %s deleted.", deleted, folderPath);
 
 
 	return deleted;
 	return deleted;
 }
 }
 
 
-
 std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter = "")
 std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter = "")
 {
 {
 	std::vector<string> Output;
 	std::vector<string> Output;
 	std::string delimiter = " =,";
 	std::string delimiter = " =,";
-    if (_delimiter.length() > 0){
-        delimiter = _delimiter;
-    }
+
+	if (_delimiter.length() > 0)
+	{
+		delimiter = _delimiter;
+	}
 
 
 	return ZerlegeZeile(input, delimiter);
 	return ZerlegeZeile(input, delimiter);
 }
 }
 
 
-
 std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
 std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
 {
 {
 	std::vector<string> Output;
 	std::vector<string> Output;
-	/* The input can have multiple formats: 
+	/* The input can have multiple formats:
 	 *  - key = value
 	 *  - key = value
-     *  - key = value1 value2 value3 ...
-     *  - key value1 value2 value3 ...
-	 *  
+	 *  - key = value1 value2 value3 ...
+	 *  - key value1 value2 value3 ...
+	 *
 	 * Examples:
 	 * Examples:
 	 *  - ImageSize = VGA
 	 *  - ImageSize = VGA
-	 *  - IO0 = input disabled 10 false false 
+	 *  - IO0 = input disabled 10 false false
 	 *  - main.dig1 28 144 55 100 false
 	 *  - main.dig1 28 144 55 100 false
-	 * 
+	 *
 	 * This causes issues eg. if a password key has a whitespace or equal sign in its value.
 	 * This causes issues eg. if a password key has a whitespace or equal sign in its value.
 	 * As a workaround and to not break any legacy usage, we enforce to only use the
 	 * As a workaround and to not break any legacy usage, we enforce to only use the
 	 * equal sign, if the key is "password"
 	 * equal sign, if the key is "password"
-	*/
-	if ((input.find("password") != string::npos) || (input.find("Token") != string::npos)) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence
+	 */
+	if ((input.find("password") != string::npos) || (input.find("Token") != string::npos))
+	{
+		// Line contains a password, use the equal sign as the only delimiter and only split on first occurrence
 		size_t pos = input.find("=");
 		size_t pos = input.find("=");
 		Output.push_back(trim(input.substr(0, pos), ""));
 		Output.push_back(trim(input.substr(0, pos), ""));
-		Output.push_back(trim(input.substr(pos +1, string::npos), ""));
+		Output.push_back(trim(input.substr(pos + 1, string::npos), ""));
 	}
 	}
-	else { // Legacy Mode
-		input = trim(input, delimiter);							// sonst werden delimiter am Ende (z.B. == im Token) gelöscht)
+	else
+	{
+		// Legacy Mode
+		input = trim(input, delimiter); // sonst werden delimiter am Ende (z.B. == im Token) gelöscht)
 		size_t pos = findDelimiterPos(input, delimiter);
 		size_t pos = findDelimiterPos(input, delimiter);
 		std::string token;
 		std::string token;
-		while (pos != std::string::npos) {
+
+		while (pos != std::string::npos)
+		{
 			token = input.substr(0, pos);
 			token = input.substr(0, pos);
 			token = trim(token, delimiter);
 			token = trim(token, delimiter);
 			Output.push_back(token);
 			Output.push_back(token);
@@ -645,34 +729,35 @@ std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
 			input = trim(input, delimiter);
 			input = trim(input, delimiter);
 			pos = findDelimiterPos(input, delimiter);
 			pos = findDelimiterPos(input, delimiter);
 		}
 		}
+
 		Output.push_back(input);
 		Output.push_back(input);
 	}
 	}
 
 
 	return Output;
 	return Output;
-
 }
 }
 
 
+std::string ReplaceString(std::string subject, const std::string &search, const std::string &replace)
+{
+	size_t pos = 0;
+
+	while ((pos = subject.find(search, pos)) != std::string::npos)
+	{
+		subject.replace(pos, search.length(), replace);
+		pos += replace.length();
+	}
 
 
-std::string ReplaceString(std::string subject, const std::string& search,
-                          const std::string& replace) {
-    size_t pos = 0;
-    while ((pos = subject.find(search, pos)) != std::string::npos) {
-         subject.replace(pos, search.length(), replace);
-         pos += replace.length();
-    }
-    return subject;
+	return subject;
 }
 }
 
 
-
 /* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
 /* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
 /* SD Card Manufacturer Database */
 /* SD Card Manufacturer Database */
-struct SDCard_Manufacturer_database {
+struct SDCard_Manufacturer_database
+{
 	string type;
 	string type;
 	int id;
 	int id;
 	string manufacturer;
 	string manufacturer;
 };
 };
 
 
-
 /* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
 /* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
 /* SD Card Manufacturer Database */
 /* SD Card Manufacturer Database */
 struct SDCard_Manufacturer_database sd_database[] = {
 struct SDCard_Manufacturer_database sd_database[] = {
@@ -857,242 +942,267 @@ struct SDCard_Manufacturer_database mmc_database[] = {
 };
 };
 
 
 /* Parse SD Card Manufacturer Database */
 /* Parse SD Card Manufacturer Database */
-string SDCardParseManufacturerIDs(int id) 
+string SDCardParseManufacturerIDs(int id)
 {
 {
-    if (SDCardIsMMC)
-    {
-        unsigned int id_cnt = sizeof(mmc_database) / sizeof(struct SDCard_Manufacturer_database);
-        string ret_val = "";
-
-        for (int i = 0; i < id_cnt; i++)
-	{
-	    if (mmc_database[i].id == id)
-	    {
-		return mmc_database[i].manufacturer;
-	    }
-	    else
-	    {
-		ret_val = "ID unknown (not in DB)";
-	    }
-	}
+	if (SDCardIsMMC)
+	{
+		unsigned int id_cnt = sizeof(mmc_database) / sizeof(struct SDCard_Manufacturer_database);
+		string ret_val = "";
 
 
-	return ret_val;
-    }
+		for (int i = 0; i < id_cnt; i++)
+		{
+			if (mmc_database[i].id == id)
+			{
+				return mmc_database[i].manufacturer;
+			}
+			else
+			{
+				ret_val = "ID unknown (not in DB)";
+			}
+		}
 
 
-    else
-    {
-	unsigned int id_cnt = sizeof(sd_database) / sizeof(struct SDCard_Manufacturer_database);
-	string ret_val = "";
+		return ret_val;
+	}
 
 
-	for (int i = 0; i < id_cnt; i++)
+	else
 	{
 	{
-	    if (sd_database[i].id == id)
-	    {
-		return sd_database[i].manufacturer;
-	    }
-	    else
-	    {
-		ret_val = "ID unknown (not in DB)";
-	    }
-	}
+		unsigned int id_cnt = sizeof(sd_database) / sizeof(struct SDCard_Manufacturer_database);
+		string ret_val = "";
 
 
-	return ret_val;
-    }
-}
+		for (int i = 0; i < id_cnt; i++)
+		{
+			if (sd_database[i].id == id)
+			{
+				return sd_database[i].manufacturer;
+			}
+			else
+			{
+				ret_val = "ID unknown (not in DB)";
+			}
+		}
 
 
+		return ret_val;
+	}
+}
 
 
 string RundeOutput(double _in, int _anzNachkomma)
 string RundeOutput(double _in, int _anzNachkomma)
 {
 {
-    std::stringstream stream;
-    int _zw = _in;    
-//    ESP_LOGD(TAG, "AnzNachkomma: %d", _anzNachkomma);
-
-    if (_anzNachkomma < 0) {
-        _anzNachkomma = 0;
-    }
-
-    if (_anzNachkomma > 0)
-    {
-        stream << std::fixed << std::setprecision(_anzNachkomma) << _in;
-        return stream.str();          
-    }
-    else
-    {
-        stream << _zw;
-    }
-
-
-    return stream.str();  
-}
+	std::stringstream stream;
+	int _zw = _in;
+	//    ESP_LOGD(TAG, "AnzNachkomma: %d", _anzNachkomma);
 
 
+	if (_anzNachkomma > 0)
+	{
+		stream << std::fixed << std::setprecision(_anzNachkomma) << _in;
+	}
+	else
+	{
+		stream << _zw;
+	}
 
 
-string getMac(void) {
-    uint8_t macInt[6];
-    char macFormated[6*2 + 5 + 1]; // AA:BB:CC:DD:EE:FF
+	return stream.str();
+}
+
+string getMac(void)
+{
+	uint8_t macInt[6];
+	char macFormated[6 * 2 + 5 + 1]; // AA:BB:CC:DD:EE:FF
 
 
-    esp_read_mac(macInt, ESP_MAC_WIFI_STA);
-    sprintf(macFormated, "%02X:%02X:%02X:%02X:%02X:%02X", macInt[0], macInt[1], macInt[2], macInt[3], macInt[4], macInt[5]); 
+	esp_read_mac(macInt, ESP_MAC_WIFI_STA);
+	sprintf(macFormated, "%02X:%02X:%02X:%02X:%02X:%02X", macInt[0], macInt[1], macInt[2], macInt[3], macInt[4], macInt[5]);
 
 
-    return macFormated;
+	return macFormated;
 }
 }
 
 
-
-void setSystemStatusFlag(SystemStatusFlag_t flag) {
+void setSystemStatusFlag(SystemStatusFlag_t flag)
+{
 	systemStatus = systemStatus | flag; // set bit
 	systemStatus = systemStatus | flag; // set bit
 
 
 	char buf[20];
 	char buf[20];
 	snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus());
 	snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus());
-    LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
+	LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
 }
 }
 
 
-
-void clearSystemStatusFlag(SystemStatusFlag_t flag) {
+void clearSystemStatusFlag(SystemStatusFlag_t flag)
+{
 	systemStatus = systemStatus | ~flag; // clear bit
 	systemStatus = systemStatus | ~flag; // clear bit
 
 
 	char buf[20];
 	char buf[20];
 	snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus());
 	snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus());
-    LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
+	LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
 }
 }
 
 
-
-int getSystemStatus(void) {
-    return systemStatus;
+int getSystemStatus(void)
+{
+	return systemStatus;
 }
 }
 
 
+bool isSetSystemStatusFlag(SystemStatusFlag_t flag)
+{
+	// ESP_LOGE(TAG, "Flag (0x%08X) is set (0x%08X): %d", flag, systemStatus , ((systemStatus & flag) == flag));
 
 
-bool isSetSystemStatusFlag(SystemStatusFlag_t flag) {
-	//ESP_LOGE(TAG, "Flag (0x%08X) is set (0x%08X): %d", flag, systemStatus , ((systemStatus & flag) == flag));
-
-	if ((systemStatus & flag) == flag) {
+	if ((systemStatus & flag) == flag)
+	{
 		return true;
 		return true;
 	}
 	}
-	else {
+	else
+	{
 		return false;
 		return false;
 	}
 	}
 }
 }
 
 
-
-time_t getUpTime(void) {
-    return (uint32_t)(esp_timer_get_time()/1000/1000); // in seconds
+time_t getUpTime(void)
+{
+	return (uint32_t)(esp_timer_get_time() / 1000 / 1000); // in seconds
 }
 }
 
 
-
-string getResetReason(void) {
+string getResetReason(void)
+{
 	std::string reasonText;
 	std::string reasonText;
 
 
-	switch(esp_reset_reason()) {
-		case ESP_RST_POWERON: reasonText = "Power-on event (or reset button)"; break;    //!< Reset due to power-on event
-		case ESP_RST_EXT: reasonText = "External pin"; break;        //!< Reset by external pin (not applicable for ESP32)
-		case ESP_RST_SW: reasonText = "Via esp_restart"; break;         //!< Software reset via esp_restart
-		case ESP_RST_PANIC: reasonText = "Exception/panic"; break;      //!< Software reset due to exception/panic
-		case ESP_RST_INT_WDT: reasonText = "Interrupt watchdog"; break;    //!< Reset (software or hardware) due to interrupt watchdog
-		case ESP_RST_TASK_WDT: reasonText = "Task watchdog"; break;   //!< Reset due to task watchdog
-		case ESP_RST_WDT: reasonText = "Other watchdogs"; break;        //!< Reset due to other watchdogs
-		case ESP_RST_DEEPSLEEP: reasonText = "Exiting deep sleep mode"; break;  //!< Reset after exiting deep sleep mode
-		case ESP_RST_BROWNOUT: reasonText = "Brownout"; break;   //!< Brownout reset (software or hardware)
-		case ESP_RST_SDIO: reasonText = "SDIO"; break;       //!< Reset over SDIO
-
-		case ESP_RST_UNKNOWN:   //!< Reset reason can not be determined
-		default: 
-			reasonText = "Unknown";
+	switch (esp_reset_reason())
+	{
+	case ESP_RST_POWERON:
+		reasonText = "Power-on event (or reset button)";
+		break; //!< Reset due to power-on event
+	case ESP_RST_EXT:
+		reasonText = "External pin";
+		break; //!< Reset by external pin (not applicable for ESP32)
+	case ESP_RST_SW:
+		reasonText = "Via esp_restart";
+		break; //!< Software reset via esp_restart
+	case ESP_RST_PANIC:
+		reasonText = "Exception/panic";
+		break; //!< Software reset due to exception/panic
+	case ESP_RST_INT_WDT:
+		reasonText = "Interrupt watchdog";
+		break; //!< Reset (software or hardware) due to interrupt watchdog
+	case ESP_RST_TASK_WDT:
+		reasonText = "Task watchdog";
+		break; //!< Reset due to task watchdog
+	case ESP_RST_WDT:
+		reasonText = "Other watchdogs";
+		break; //!< Reset due to other watchdogs
+	case ESP_RST_DEEPSLEEP:
+		reasonText = "Exiting deep sleep mode";
+		break; //!< Reset after exiting deep sleep mode
+	case ESP_RST_BROWNOUT:
+		reasonText = "Brownout";
+		break; //!< Brownout reset (software or hardware)
+	case ESP_RST_SDIO:
+		reasonText = "SDIO";
+		break; //!< Reset over SDIO
+
+	case ESP_RST_UNKNOWN: //!< Reset reason can not be determined
+	default:
+		reasonText = "Unknown";
 	}
 	}
-    return reasonText;
-}
 
 
+	return reasonText;
+}
 
 
 /**
 /**
  * Returns the current uptime  formated ad xxf xxh xxm [xxs]
  * Returns the current uptime  formated ad xxf xxh xxm [xxs]
  */
  */
-std::string getFormatedUptime(bool compact) {
+std::string getFormatedUptime(bool compact)
+{
 	char buf[20];
 	char buf[20];
-	#pragma GCC diagnostic ignored "-Wformat-truncation"
+#pragma GCC diagnostic ignored "-Wformat-truncation"
+
+	int uptime = getUpTime(); // in seconds
 
 
-    int uptime = getUpTime(); // in seconds
+	int days = int(floor(uptime / (3600 * 24)));
+	int hours = int(floor((uptime - days * 3600 * 24) / (3600)));
+	int minutes = int(floor((uptime - days * 3600 * 24 - hours * 3600) / (60)));
+	int seconds = uptime - days * 3600 * 24 - hours * 3600 - minutes * 60;
 
 
-    int days = int(floor(uptime / (3600*24)));
-    int hours = int(floor((uptime - days * 3600*24) / (3600)));
-    int minutes = int(floor((uptime - days * 3600*24 - hours * 3600) / (60)));
-    int seconds = uptime - days * 3600*24 - hours * 3600 - minutes * 60;
-    
-	if (compact) {
+	if (compact)
+	{
 		snprintf(buf, sizeof(buf), "%dd%02dh%02dm%02ds", days, hours, minutes, seconds);
 		snprintf(buf, sizeof(buf), "%dd%02dh%02dm%02ds", days, hours, minutes, seconds);
 	}
 	}
-	else {
+	else
+	{
 		snprintf(buf, sizeof(buf), "%3dd %02dh %02dm %02ds", days, hours, minutes, seconds);
 		snprintf(buf, sizeof(buf), "%3dd %02dh %02dm %02ds", days, hours, minutes, seconds);
 	}
 	}
 
 
 	return std::string(buf);
 	return std::string(buf);
 }
 }
 
 
-
-const char* get404(void) {
-    return 
-"<pre>\n\n\n\n"
-"        _\n"
-"    .__(.)< ( oh oh! This page does not exist! )\n"
-"    \\___)\n"
-"\n\n"
-"                You could try your <a href=index.html target=_parent>luck</a> here!</pre>\n"
-"<script>document.cookie = \"page=overview.html\"</script>"; // Make sure we load the overview page
+const char *get404(void)
+{
+	return "<pre>\n\n\n\n"
+		   "        _\n"
+		   "    .__(.)< ( oh oh! This page does not exist! )\n"
+		   "    \\___)\n"
+		   "\n\n"
+		   "                You could try your <a href=index.html target=_parent>luck</a> here!</pre>\n"
+		   "<script>document.cookie = \"page=overview.html\"</script>"; // Make sure we load the overview page
 }
 }
 
 
-
-std::string UrlDecode(const std::string& value)
+std::string UrlDecode(const std::string &value)
 {
 {
-    std::string result;
-    result.reserve(value.size());
-
-    for (std::size_t i = 0; i < value.size(); ++i)
-    {
-        auto ch = value[i];
-
-        if (ch == '%' && (i + 2) < value.size())
-        {
-            auto hex = value.substr(i + 1, 2);
-            auto dec = static_cast<char>(std::strtol(hex.c_str(), nullptr, 16));
-            result.push_back(dec);
-            i += 2;
-        }
-        else if (ch == '+')
-        {
-            result.push_back(' ');
-        }
-        else
-        {
-            result.push_back(ch);
-        }
-    }
-
-    return result;
-}
+	std::string result;
+	result.reserve(value.size());
+
+	for (std::size_t i = 0; i < value.size(); ++i)
+	{
+		auto ch = value[i];
+
+		if (ch == '%' && (i + 2) < value.size())
+		{
+			auto hex = value.substr(i + 1, 2);
+			auto dec = static_cast<char>(std::strtol(hex.c_str(), nullptr, 16));
+			result.push_back(dec);
+			i += 2;
+		}
+		else if (ch == '+')
+		{
+			result.push_back(' ');
+		}
+		else
+		{
+			result.push_back(ch);
+		}
+	}
 
 
+	return result;
+}
 
 
-bool replaceString(std::string& s, std::string const& toReplace, std::string const& replaceWith) {
-    return replaceString(s, toReplace, replaceWith, true);
+bool replaceString(std::string &s, std::string const &toReplace, std::string const &replaceWith)
+{
+	return replaceString(s, toReplace, replaceWith, true);
 }
 }
 
 
+bool replaceString(std::string &s, std::string const &toReplace, std::string const &replaceWith, bool logIt)
+{
+	std::size_t pos = s.find(toReplace);
 
 
-bool replaceString(std::string& s, std::string const& toReplace, std::string const& replaceWith, bool logIt) {
-    std::size_t pos = s.find(toReplace);
+	if (pos == std::string::npos)
+	{
+		// Not found
+		return false;
+	}
 
 
-    if (pos == std::string::npos) { // Not found
-        return false;
-    }
+	std::string old = s;
+	s.replace(pos, toReplace.length(), replaceWith);
 
 
-    std::string old = s;
-    s.replace(pos, toReplace.length(), replaceWith);
-    if (logIt) {
-        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Migrated Configfile line '" + old + "' to '" + s + "'");
-    }
-    return true;
+	if (logIt)
+	{
+		LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Migrated Configfile line '" + old + "' to '" + s + "'");
+	}
+
+	return true;
 }
 }
 
 
+bool isInString(std::string &s, std::string const &toFind)
+{
+	std::size_t pos = s.find(toFind);
 
 
-bool isInString(std::string& s, std::string const& toFind) {
-    std::size_t pos = s.find(toFind);
+	if (pos == std::string::npos)
+	{
+		// Not found
+		return false;
+	}
 
 
-    if (pos == std::string::npos) { // Not found
-        return false;
-    }
-    return true;
+	return true;
 }
 }

+ 309 - 353
code/components/jomjol_image_proc/CRotateImage.cpp

@@ -1,353 +1,309 @@
-#include <string>
-#include "CRotateImage.h"
-#include "psram.h"
-
-static const char *TAG = "C ROTATE IMG";
-
-CRotateImage::CRotateImage(std::string _name, CImageBasis *_org, CImageBasis *_temp, bool _flip) : CImageBasis(_name)
-{
-    rgb_image = _org->rgb_image;
-    channels = _org->channels;
-    width = _org->width;
-    height = _org->height;
-    bpp = _org->bpp;
-    externalImage = true;   
-    ImageTMP = _temp;   
-    ImageOrg = _org; 
-    islocked = false;
-    doflip = _flip;
-}
-
-
-void CRotateImage::Mirror(){
-    int memsize = width * height * channels;
-    uint8_t* odata;
-    if (ImageTMP)
-    {
-        odata = ImageTMP->RGBImageLock();
-    }
-    else
-    {
-        odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
-    }
-
-
-    int x_source, y_source;
-    stbi_uc* p_target;
-    stbi_uc* p_source;
-
-    RGBImageLock();
-
-    for (int x = 0; x < width; ++x)
-        for (int y = 0; y < height; ++y)
-        {
-            p_target = odata + (channels * (y * width + x));
-
-            x_source = width - x;
-            y_source = y;
-
-            p_source = rgb_image + (channels * (y_source * width + x_source));
-            for (int _channels = 0; _channels < channels; ++_channels)
-                p_target[_channels] = p_source[_channels];
-        }
-
-    //    memcpy(rgb_image, odata, memsize);
-    memCopy(odata, rgb_image, memsize);
-    if (!ImageTMP)
-        free_psram_heap(std::string(TAG) + "->odata", odata);
-
-    if (ImageTMP)
-        ImageTMP->RGBImageRelease();
-
-    RGBImageRelease();
-}
-
-void CRotateImage::Rotate(float _angle, int _centerx, int _centery)
-{
-    int org_width, org_height;
-    float m[2][3];
-
-    float x_center = _centerx;
-    float y_center = _centery;
-    _angle = _angle / 180 * M_PI;
-
-    if (doflip)
-    {
-        org_width = width;
-        org_height = height;
-        height = org_width;
-        width = org_height;
-        x_center =  x_center - (org_width/2) + (org_height/2);
-        y_center =  y_center + (org_width/2) - (org_height/2);
-        if (ImageOrg)
-        {
-            ImageOrg->height = height;
-            ImageOrg->width = width;
-        }
-    }
-    else
-    {
-        org_width = width;
-        org_height = height;
-    }
-
-    m[0][0] = cos(_angle);
-    m[0][1] = sin(_angle);
-    m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
-
-    m[1][0] = -m[0][1];
-    m[1][1] = m[0][0];
-    m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
-
-    if (doflip)
-    {
-        m[0][2] = m[0][2] + (org_width/2) - (org_height/2);
-        m[1][2] = m[1][2] - (org_width/2) + (org_height/2);
-    }
-
-    int memsize = width * height * channels;
-    uint8_t* odata;
-    if (ImageTMP)
-    {
-        odata = ImageTMP->RGBImageLock();
-    }
-    else
-    {
-        odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
-    }
-    
-
-    int x_source, y_source;
-    stbi_uc* p_target;
-    stbi_uc* p_source;
-
-    RGBImageLock();
-
-    for (int x = 0; x < width; ++x)
-        for (int y = 0; y < height; ++y)
-        {
-            p_target = odata + (channels * (y * width + x));
-
-            x_source = int(m[0][0] * x + m[0][1] * y);
-            y_source = int(m[1][0] * x + m[1][1] * y);
-
-            x_source += int(m[0][2]);
-            y_source += int(m[1][2]);
-
-            if ((x_source >= 0) && (x_source < org_width) && (y_source >= 0) && (y_source < org_height))
-            {
-                p_source = rgb_image + (channels * (y_source * org_width + x_source));
-                for (int _channels = 0; _channels < channels; ++_channels)
-                    p_target[_channels] = p_source[_channels];
-            }
-            else
-            {
-                for (int _channels = 0; _channels < channels; ++_channels)
-                    p_target[_channels] = 255;
-            }
-        }
-
-    //    memcpy(rgb_image, odata, memsize);
-    memCopy(odata, rgb_image, memsize);
-
-    if (!ImageTMP)
-    {
-        free_psram_heap(std::string(TAG) + "->odata", odata);
-    }
-    if (ImageTMP)
-        ImageTMP->RGBImageRelease();
-
-    RGBImageRelease();
-}
-
-
-
-void CRotateImage::RotateAntiAliasing(float _angle, int _centerx, int _centery)
-{
-    int org_width, org_height;
-    float m[2][3];
-
-    float x_center = _centerx;
-    float y_center = _centery;
-    _angle = _angle / 180 * M_PI;
-
-    if (doflip)
-    {
-        org_width = width;
-        org_height = height;
-        height = org_width;
-        width = org_height;
-        x_center =  x_center - (org_width/2) + (org_height/2);
-        y_center =  y_center + (org_width/2) - (org_height/2);
-        if (ImageOrg)
-        {
-            ImageOrg->height = height;
-            ImageOrg->width = width;
-        }
-    }
-    else
-    {
-        org_width = width;
-        org_height = height;
-    }
-
-    m[0][0] = cos(_angle);
-    m[0][1] = sin(_angle);
-    m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
-
-    m[1][0] = -m[0][1];
-    m[1][1] = m[0][0];
-    m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
-
-    if (doflip)
-    {
-        m[0][2] = m[0][2] + (org_width/2) - (org_height/2);
-        m[1][2] = m[1][2] - (org_width/2) + (org_height/2);
-    }
-
-    int memsize = width * height * channels;
-    uint8_t* odata;
-    if (ImageTMP)
-    {
-        odata = ImageTMP->RGBImageLock();
-    }
-    else
-    {
-        odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
-    }
-    
-
-    int x_source_1, y_source_1, x_source_2, y_source_2;
-    float x_source, y_source;
-    float quad_ul, quad_ur, quad_ol, quad_or;
-    stbi_uc* p_target;
-    stbi_uc *p_source_ul, *p_source_ur, *p_source_ol, *p_source_or;
-
-    RGBImageLock();
-
-    for (int x = 0; x < width; ++x)
-        for (int y = 0; y < height; ++y)
-        {
-            p_target = odata + (channels * (y * width + x));
-
-            x_source = (m[0][0] * x + m[0][1] * y);
-            y_source = (m[1][0] * x + m[1][1] * y);
-
-            x_source += (m[0][2]);
-            y_source += (m[1][2]);
-
-            x_source_1 = (int)x_source;
-            x_source_2 = x_source_1 + 1;
-            y_source_1 = (int)y_source;
-            y_source_2 = y_source_1 + 1;
-
-            quad_ul = (x_source_2 - x_source) * (y_source_2 - y_source);
-            quad_ur = (1- (x_source_2 - x_source)) * (y_source_2 - y_source);
-            quad_or = (x_source_2 - x_source) * (1-(y_source_2 - y_source));
-            quad_ol = (1- (x_source_2 - x_source)) * (1-(y_source_2 - y_source));
-
-
-            if ((x_source_1 >= 0) && (x_source_2 < org_width) && (y_source_1 >= 0) && (y_source_2 < org_height))
-            {
-                p_source_ul = rgb_image + (channels * (y_source_1 * org_width + x_source_1));
-                p_source_ur = rgb_image + (channels * (y_source_1 * org_width + x_source_2));
-                p_source_or = rgb_image + (channels * (y_source_2 * org_width + x_source_1));
-                p_source_ol = rgb_image + (channels * (y_source_2 * org_width + x_source_2));
-                for (int _channels = 0; _channels < channels; ++_channels)
-                {
-                    p_target[_channels] = (int)((float)p_source_ul[_channels] * quad_ul
-                                                + (float)p_source_ur[_channels] * quad_ur
-                                                + (float)p_source_or[_channels] * quad_or
-                                                + (float)p_source_ol[_channels] * quad_ol);
-                }
-            }
-            else
-            {
-                for (int _channels = 0; _channels < channels; ++_channels)
-                    p_target[_channels] = 255;
-            }
-        }
-
-    //    memcpy(rgb_image, odata, memsize);
-    memCopy(odata, rgb_image, memsize);
-
-    if (!ImageTMP)
-    {
-        free_psram_heap(std::string(TAG) + "->odata", odata);
-    }
-    if (ImageTMP)
-        ImageTMP->RGBImageRelease();
-
-    RGBImageRelease();
-}
-
-
-void CRotateImage::Rotate(float _angle)
-{
-//    ESP_LOGD(TAG, "width %d, height %d", width, height);
-    Rotate(_angle, width / 2, height / 2);
-}
-
-void CRotateImage::RotateAntiAliasing(float _angle)
-{
-//    ESP_LOGD(TAG, "width %d, height %d", width, height);
-    RotateAntiAliasing(_angle, width / 2, height / 2);
-}
-
-void CRotateImage::Translate(int _dx, int _dy)
-{
-    int memsize = width * height * channels;
-    uint8_t* odata;
-    if (ImageTMP)
-    {
-        odata = ImageTMP->RGBImageLock();
-    }
-    else
-    {
-        odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
-    }
-
-
-
-    int x_source, y_source;
-    stbi_uc* p_target;
-    stbi_uc* p_source;
-
-    RGBImageLock();
-
-    for (int x = 0; x < width; ++x)
-        for (int y = 0; y < height; ++y)
-        {
-            p_target = odata + (channels * (y * width + x));
-
-            x_source = x - _dx;
-            y_source = y - _dy;
-
-            if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height))
-            {
-                p_source = rgb_image + (channels * (y_source * width + x_source));
-                for (int _channels = 0; _channels < channels; ++_channels)
-                    p_target[_channels] = p_source[_channels];
-            }
-            else
-            {
-                for (int _channels = 0; _channels < channels; ++_channels)
-                    p_target[_channels] = 255;
-            }
-        }
-
-    //    memcpy(rgb_image, odata, memsize);
-    memCopy(odata, rgb_image, memsize);
-    if (!ImageTMP)
-    {
-        free_psram_heap(std::string(TAG) + "->odata", odata);
-    }
-
-    if (ImageTMP)
-    {
-        ImageTMP->RGBImageRelease();
-    }
-    RGBImageRelease();
-
-}
-
+#include <string>
+#include "CRotateImage.h"
+#include "psram.h"
+
+static const char *TAG = "C ROTATE IMG";
+
+CRotateImage::CRotateImage(std::string _name, CImageBasis *_org, CImageBasis *_temp, bool _flip) : CImageBasis(_name)
+{
+    rgb_image = _org->rgb_image;
+    channels = _org->channels;
+    width = _org->width;
+    height = _org->height;
+    bpp = _org->bpp;
+    externalImage = true;   
+    ImageTMP = _temp;   
+    ImageOrg = _org; 
+    islocked = false;
+    doflip = _flip;
+}
+
+void CRotateImage::Rotate(float _angle, int _centerx, int _centery)
+{
+    int org_width, org_height;
+    float m[2][3];
+
+    float x_center = _centerx;
+    float y_center = _centery;
+    _angle = _angle / 180 * M_PI;
+
+    if (doflip)
+    {
+        org_width = width;
+        org_height = height;
+        height = org_width;
+        width = org_height;
+        x_center =  x_center - (org_width/2) + (org_height/2);
+        y_center =  y_center + (org_width/2) - (org_height/2);
+        if (ImageOrg)
+        {
+            ImageOrg->height = height;
+            ImageOrg->width = width;
+        }
+    }
+    else
+    {
+        org_width = width;
+        org_height = height;
+    }
+
+    m[0][0] = cos(_angle);
+    m[0][1] = sin(_angle);
+    m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
+
+    m[1][0] = -m[0][1];
+    m[1][1] = m[0][0];
+    m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
+
+    if (doflip)
+    {
+        m[0][2] = m[0][2] + (org_width/2) - (org_height/2);
+        m[1][2] = m[1][2] - (org_width/2) + (org_height/2);
+    }
+
+    int memsize = width * height * channels;
+    uint8_t* odata;
+    if (ImageTMP)
+    {
+        odata = ImageTMP->RGBImageLock();
+    }
+    else
+    {
+        odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
+    }
+    
+
+    int x_source, y_source;
+    stbi_uc* p_target;
+    stbi_uc* p_source;
+
+    RGBImageLock();
+
+    for (int x = 0; x < width; ++x)
+        for (int y = 0; y < height; ++y)
+        {
+            p_target = odata + (channels * (y * width + x));
+
+            x_source = int(m[0][0] * x + m[0][1] * y);
+            y_source = int(m[1][0] * x + m[1][1] * y);
+
+            x_source += int(m[0][2]);
+            y_source += int(m[1][2]);
+
+            if ((x_source >= 0) && (x_source < org_width) && (y_source >= 0) && (y_source < org_height))
+            {
+                p_source = rgb_image + (channels * (y_source * org_width + x_source));
+                for (int _channels = 0; _channels < channels; ++_channels)
+                    p_target[_channels] = p_source[_channels];
+            }
+            else
+            {
+                for (int _channels = 0; _channels < channels; ++_channels)
+                    p_target[_channels] = 255;
+            }
+        }
+
+    //    memcpy(rgb_image, odata, memsize);
+    memCopy(odata, rgb_image, memsize);
+
+    if (!ImageTMP)
+    {
+        free_psram_heap(std::string(TAG) + "->odata", odata);
+    }
+    if (ImageTMP)
+        ImageTMP->RGBImageRelease();
+
+    RGBImageRelease();
+}
+
+
+
+void CRotateImage::RotateAntiAliasing(float _angle, int _centerx, int _centery)
+{
+    int org_width, org_height;
+    float m[2][3];
+
+    float x_center = _centerx;
+    float y_center = _centery;
+    _angle = _angle / 180 * M_PI;
+
+    if (doflip)
+    {
+        org_width = width;
+        org_height = height;
+        height = org_width;
+        width = org_height;
+        x_center =  x_center - (org_width/2) + (org_height/2);
+        y_center =  y_center + (org_width/2) - (org_height/2);
+        if (ImageOrg)
+        {
+            ImageOrg->height = height;
+            ImageOrg->width = width;
+        }
+    }
+    else
+    {
+        org_width = width;
+        org_height = height;
+    }
+
+    m[0][0] = cos(_angle);
+    m[0][1] = sin(_angle);
+    m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
+
+    m[1][0] = -m[0][1];
+    m[1][1] = m[0][0];
+    m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
+
+    if (doflip)
+    {
+        m[0][2] = m[0][2] + (org_width/2) - (org_height/2);
+        m[1][2] = m[1][2] - (org_width/2) + (org_height/2);
+    }
+
+    int memsize = width * height * channels;
+    uint8_t* odata;
+    if (ImageTMP)
+    {
+        odata = ImageTMP->RGBImageLock();
+    }
+    else
+    {
+        odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
+    }
+    
+
+    int x_source_1, y_source_1, x_source_2, y_source_2;
+    float x_source, y_source;
+    float quad_ul, quad_ur, quad_ol, quad_or;
+    stbi_uc* p_target;
+    stbi_uc *p_source_ul, *p_source_ur, *p_source_ol, *p_source_or;
+
+    RGBImageLock();
+
+    for (int x = 0; x < width; ++x)
+        for (int y = 0; y < height; ++y)
+        {
+            p_target = odata + (channels * (y * width + x));
+
+            x_source = (m[0][0] * x + m[0][1] * y);
+            y_source = (m[1][0] * x + m[1][1] * y);
+
+            x_source += (m[0][2]);
+            y_source += (m[1][2]);
+
+            x_source_1 = (int)x_source;
+            x_source_2 = x_source_1 + 1;
+            y_source_1 = (int)y_source;
+            y_source_2 = y_source_1 + 1;
+
+            quad_ul = (x_source_2 - x_source) * (y_source_2 - y_source);
+            quad_ur = (1- (x_source_2 - x_source)) * (y_source_2 - y_source);
+            quad_or = (x_source_2 - x_source) * (1-(y_source_2 - y_source));
+            quad_ol = (1- (x_source_2 - x_source)) * (1-(y_source_2 - y_source));
+
+
+            if ((x_source_1 >= 0) && (x_source_2 < org_width) && (y_source_1 >= 0) && (y_source_2 < org_height))
+            {
+                p_source_ul = rgb_image + (channels * (y_source_1 * org_width + x_source_1));
+                p_source_ur = rgb_image + (channels * (y_source_1 * org_width + x_source_2));
+                p_source_or = rgb_image + (channels * (y_source_2 * org_width + x_source_1));
+                p_source_ol = rgb_image + (channels * (y_source_2 * org_width + x_source_2));
+                for (int _channels = 0; _channels < channels; ++_channels)
+                {
+                    p_target[_channels] = (int)((float)p_source_ul[_channels] * quad_ul
+                                                + (float)p_source_ur[_channels] * quad_ur
+                                                + (float)p_source_or[_channels] * quad_or
+                                                + (float)p_source_ol[_channels] * quad_ol);
+                }
+            }
+            else
+            {
+                for (int _channels = 0; _channels < channels; ++_channels)
+                    p_target[_channels] = 255;
+            }
+        }
+
+    //    memcpy(rgb_image, odata, memsize);
+    memCopy(odata, rgb_image, memsize);
+
+    if (!ImageTMP)
+    {
+        free_psram_heap(std::string(TAG) + "->odata", odata);
+    }
+    if (ImageTMP)
+        ImageTMP->RGBImageRelease();
+
+    RGBImageRelease();
+}
+
+
+void CRotateImage::Rotate(float _angle)
+{
+//    ESP_LOGD(TAG, "width %d, height %d", width, height);
+    Rotate(_angle, width / 2, height / 2);
+}
+
+void CRotateImage::RotateAntiAliasing(float _angle)
+{
+//    ESP_LOGD(TAG, "width %d, height %d", width, height);
+    RotateAntiAliasing(_angle, width / 2, height / 2);
+}
+
+void CRotateImage::Translate(int _dx, int _dy)
+{
+    int memsize = width * height * channels;
+    uint8_t* odata;
+    if (ImageTMP)
+    {
+        odata = ImageTMP->RGBImageLock();
+    }
+    else
+    {
+        odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
+    }
+
+
+
+    int x_source, y_source;
+    stbi_uc* p_target;
+    stbi_uc* p_source;
+
+    RGBImageLock();
+
+    for (int x = 0; x < width; ++x)
+        for (int y = 0; y < height; ++y)
+        {
+            p_target = odata + (channels * (y * width + x));
+
+            x_source = x - _dx;
+            y_source = y - _dy;
+
+            if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height))
+            {
+                p_source = rgb_image + (channels * (y_source * width + x_source));
+                for (int _channels = 0; _channels < channels; ++_channels)
+                    p_target[_channels] = p_source[_channels];
+            }
+            else
+            {
+                for (int _channels = 0; _channels < channels; ++_channels)
+                    p_target[_channels] = 255;
+            }
+        }
+
+    //    memcpy(rgb_image, odata, memsize);
+    memCopy(odata, rgb_image, memsize);
+    if (!ImageTMP)
+    {
+        free_psram_heap(std::string(TAG) + "->odata", odata);
+    }
+
+    if (ImageTMP)
+    {
+        ImageTMP->RGBImageRelease();
+    }
+    RGBImageRelease();
+
+}
+

+ 27 - 28
code/components/jomjol_image_proc/CRotateImage.h

@@ -1,29 +1,28 @@
-#pragma once
-
-#ifndef CROTATEIMAGE_H
-#define CROTATEIMAGE_H
-
-#include "CImageBasis.h"
-
-
-class CRotateImage: public CImageBasis
-{
-
-    public:
-        CImageBasis *ImageTMP, *ImageOrg;
-        bool doflip;
-        CRotateImage(std::string name, std::string _image, bool _flip = false) : CImageBasis(name, _image) {ImageTMP = NULL; ImageOrg = NULL; doflip = _flip;};
-        CRotateImage(std::string name, uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp, bool _flip = false) : CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL;  ImageOrg = NULL; doflip = _flip;};
-        CRotateImage(std::string name, CImageBasis *_org, CImageBasis *_temp, bool _flip = false);
-
-        void Rotate(float _angle);
-        void RotateAntiAliasing(float _angle);
-       
-        void Rotate(float _angle, int _centerx, int _centery);
-        void RotateAntiAliasing(float _angle, int _centerx, int _centery);
-
-        void Translate(int _dx, int _dy);
-        void Mirror();
-};
-
+#pragma once
+
+#ifndef CROTATEIMAGE_H
+#define CROTATEIMAGE_H
+
+#include "CImageBasis.h"
+
+
+class CRotateImage: public CImageBasis
+{
+
+    public:
+        CImageBasis *ImageTMP, *ImageOrg;
+        bool doflip;
+        CRotateImage(std::string name, std::string _image, bool _flip = false) : CImageBasis(name, _image) {ImageTMP = NULL; ImageOrg = NULL; doflip = _flip;};
+        CRotateImage(std::string name, uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp, bool _flip = false) : CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL;  ImageOrg = NULL; doflip = _flip;};
+        CRotateImage(std::string name, CImageBasis *_org, CImageBasis *_temp, bool _flip = false);
+
+        void Rotate(float _angle);
+        void RotateAntiAliasing(float _angle);
+       
+        void Rotate(float _angle, int _centerx, int _centery);
+        void RotateAntiAliasing(float _angle, int _centerx, int _centery);
+
+        void Translate(int _dx, int _dy);
+};
+
 #endif //CROTATEIMAGE_H
 #endif //CROTATEIMAGE_H

+ 25 - 4
param-docs/expert-params.txt

@@ -1,8 +1,29 @@
-demo
 WaitBeforeTakingPicture
 WaitBeforeTakingPicture
-ImageQuality
-ImageSize
-FixedExposure
+CamFrameSize
+CamGainceiling
+CamQuality
+CamAutoSharpness
+CamSharpness
+CamSpecialEffect
+CamWbMode
+CamAwb
+CamAwbGain
+CamAec
+CamAec2
+CamAeLevel
+CamAecValue
+CamAgc
+CamAgcGain
+CamBpc
+CamWpc
+CamRawGma
+CamLenc
+CamDcw
+CamZoom
+CamZoomSize
+CamZoomOffsetX
+CamZoomOffsetY
+demo
 SearchFieldX
 SearchFieldX
 SearchFieldY
 SearchFieldY
 AlignmentAlgo
 AlignmentAlgo

+ 15 - 0
param-docs/parameter-pages/TakeImage/CamAeLevel.md

@@ -0,0 +1,15 @@
+# Parameter `CamAeLevel`
+Default Value: `0`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Auto-Exposure Compensation. Lower values produce darker image.
+
+Range (`-2` .. `2`)

+ 13 - 0
param-docs/parameter-pages/TakeImage/CamAec.md

@@ -0,0 +1,13 @@
+# Parameter `CamAec`
+Default Value: `true`
+    
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+      
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Auto-Exposure Control Algorithm

+ 13 - 0
param-docs/parameter-pages/TakeImage/CamAec2.md

@@ -0,0 +1,13 @@
+# Parameter `CamAec2`
+Default Value: `false`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+      
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Switch to "Auto-Exposure Control 2" Algorithm. This may resolve some over-exposure and under-exposure issues.

+ 15 - 0
param-docs/parameter-pages/TakeImage/CamAecValue.md

@@ -0,0 +1,15 @@
+# Parameter `CamAecValue`
+Default Value: `0`
+    
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+      
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+set Manuall-Exposure Control Value
+
+Range (`0` .. `1200`)

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamAgc.md

@@ -0,0 +1,10 @@
+# Parameter `CamAgc`
+Default Value: `true`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+This sets the Automatic Gain Control, how the camera responds to the overall level of light in the image.

+ 13 - 0
param-docs/parameter-pages/TakeImage/CamAgcGain.md

@@ -0,0 +1,13 @@
+# Parameter `CamAgcGain`
+Default Value: ` `
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+!!! Note
+    This is visible when AGC is off. Gain is an amplification of the values read from the image sensor. 
+
+Range (`0` .. `30`)

+ 13 - 0
param-docs/parameter-pages/TakeImage/CamAutoSharpness.md

@@ -0,0 +1,13 @@
+# Parameter `CamAutoSharpness`
+Default Value: `false`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+      
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+	
+AutoSharpness	

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamAwb.md

@@ -0,0 +1,10 @@
+# Parameter `CamAwb`
+Default Value: ` `
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Auto White Balance

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamAwbGain.md

@@ -0,0 +1,10 @@
+# Parameter `CamAwbGain`
+Default Value: ` `
+    
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+	
+Auto White Balance Gain

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamBpc.md

@@ -0,0 +1,10 @@
+# Parameter `CamBpc`
+Default Value: `true`
+    
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Black Pixel Correction

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamBrightness.md

@@ -0,0 +1,10 @@
+# Parameter `CamBrightness`
+Default Value: `0`
+      
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Image Brightness (`-2` .. `2`) 

+ 5 - 0
param-docs/parameter-pages/TakeImage/CamColorbar.md

@@ -0,0 +1,5 @@
+# Parameter `CamColorbar`
+Default Value: `false`
+    
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!

+ 11 - 0
param-docs/parameter-pages/TakeImage/CamContrast.md

@@ -0,0 +1,11 @@
+# Parameter `CamContrast`
+Default Value: `0`
+
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Image Contrast (`-2` .. `2`)
+

+ 13 - 0
param-docs/parameter-pages/TakeImage/CamDcw.md

@@ -0,0 +1,13 @@
+# Parameter `CamDcw`
+Default Value: `true`
+    
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+!!! Note
+    When DCW is on, the image that you receive will be the size that you requested (VGA, QQVGA, etc).
+    When DCW is off, the image that you receive will be one of UXGA, SVGA, or CIF. In other words, literally the actual image size as read from the sensor without any scaling.
+    Note that if DCW is off, and you pick a different image size, this implicitly turns DCW back on again (although this isn't reflected in the options). 

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamDenoise.md

@@ -0,0 +1,10 @@
+# Parameter `CamDenoise`
+Default Value: ` `
+    
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Denoise Image (not supported)

+ 21 - 0
param-docs/parameter-pages/TakeImage/CamGainceiling.md

@@ -0,0 +1,21 @@
+# Parameter `CamGainceiling`
+Default Value: `x2`
+    
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+!!! Note
+    This is visible when AGC is on.
+
+Available options:
+
+- `x2`
+- `x4`
+- `x8`
+- `x16`
+- `x32`
+- `x64`
+- `x128`

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamHmirror.md

@@ -0,0 +1,10 @@
+# Parameter `CamHmirror`
+Default Value: `false`
+    
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Option for initially mirroring the image on the original x-axis.

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamLenc.md

@@ -0,0 +1,10 @@
+# Parameter `CamLenc`
+Default Value: `true`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Lens Correction

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamQuality.md

@@ -0,0 +1,10 @@
+# Parameter `CamQuality`
+Default Value: `12`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+Quality index for pictures: `8` (highest quality) ... `63` (lowest quality)
+
+!!! Warning
+    Value below 12 could result in system instabilities!

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamRawGma.md

@@ -0,0 +1,10 @@
+# Parameter `CamRawGma`
+Default Value: ` `
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+RawGma

+ 11 - 0
param-docs/parameter-pages/TakeImage/CamSaturation.md

@@ -0,0 +1,11 @@
+# Parameter `CamSaturation`
+Default Value: `0`
+
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Image Saturation (`-2` .. `2`)
+

+ 13 - 0
param-docs/parameter-pages/TakeImage/CamSharpness.md

@@ -0,0 +1,13 @@
+# Parameter `CamSharpness`
+Default Value: `0`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+      
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Range (`-2` .. `2`)

+ 21 - 0
param-docs/parameter-pages/TakeImage/CamSpecialEffect.md

@@ -0,0 +1,21 @@
+# Parameter `CamSpecialEffect`
+Default Value: `no_effect`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+      
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Available options:
+
+- `no_effect`
+- `negative`
+- `grayscale`
+- `red`
+- `green`
+- `blue`
+- `retro`

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamVflip.md

@@ -0,0 +1,10 @@
+# Parameter `CamVflip`
+Default Value: `false`
+    
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Option for initially flip the image on the original y-axis. 

+ 18 - 0
param-docs/parameter-pages/TakeImage/CamWbMode.md

@@ -0,0 +1,18 @@
+# Parameter `CamWbMode`
+Default Value: `auto`
+
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+White Balance Mode
+
+Available options:
+
+- `auto`
+- `sunny`
+- `cloudy`
+- `office`
+- `home`

+ 10 - 0
param-docs/parameter-pages/TakeImage/CamWpc.md

@@ -0,0 +1,10 @@
+# Parameter `CamWpc`
+Default Value: `true`
+    
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+White Pixel Correction

+ 13 - 0
param-docs/parameter-pages/TakeImage/CamZoom.md

@@ -0,0 +1,13 @@
+# Parameter `CamZoom`
+Default Value: `false`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+Crop the camera sensor frame to `ImageSize` resolution instead of scaling it down.

+ 14 - 0
param-docs/parameter-pages/TakeImage/CamZoomOffsetX.md

@@ -0,0 +1,14 @@
+# Parameter `CamZoomOffsetX`
+Default Value: `0`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+`ZoomOffsetX` only applies when `Zoom` is enabled.
+X coordinate of the crop location within the camera sensor frame.

+ 14 - 0
param-docs/parameter-pages/TakeImage/CamZoomOffsetY.md

@@ -0,0 +1,14 @@
+# Parameter `CamZoomOffsetY`
+Default Value: `0`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+`ZoomOffsetY` only applies when `Zoom` is enabled.
+Y coordinate of the crop location within the camera sensor frame.

+ 13 - 0
param-docs/parameter-pages/TakeImage/CamZoomSize.md

@@ -0,0 +1,13 @@
+# Parameter `CamZoomSize`
+Default Value: `0`
+
+!!! Warning
+    This is an **Expert Parameter**! Only change it if you understand what it does!
+
+!!! Note
+    This parameter can also be set on the Reference Image configuration page!
+
+!!! Note
+    After changing this parameter you need to update your reference image and alignment markers!
+
+`CamZoomSize` only applies when `Zoom` is enabled.

+ 136 - 123
sd-card/config/config.ini

@@ -1,123 +1,136 @@
-[TakeImage]
-;RawImagesLocation = /log/source
-WaitBeforeTakingPicture = 5
-;RawImagesRetention = 15
-Brightness = 0
-Contrast = 0
-Saturation = 0
-Sharpness = 0
-LEDIntensity = 50
-ImageQuality = 12
-ImageSize = VGA
-Zoom = false
-ZoomMode = 0
-ZoomOffsetX = 0
-ZoomOffsetY = 0
-Grayscale = false
-Negative = false
-Aec2 = false
-AutoExposureLevel = 0
-FixedExposure = false
-Demo = false
-
-[Alignment]
-InitialRotate = 0.0
-InitialMirror = false
-SearchFieldX = 20
-SearchFieldY = 20
-AlignmentAlgo = Default
-FlipImageSize = false
-/config/ref0.jpg 103 271
-/config/ref1.jpg 442 142
-
-[Digits]
-Model = /config/dig-cont_0700_s3_q.tflite
-CNNGoodThreshold = 0.5
-;ROIImagesLocation = /log/digit
-;ROIImagesRetention = 3
-main.dig1 294 126 30 54 false
-main.dig2 343 126 30 54 false
-main.dig3 391 126 30 54 false
-
-[Analog]
-Model = /config/ana-cont_1300_s2.tflite
-CNNGoodThreshold = 0.5
-;ROIImagesLocation = /log/analog
-;ROIImagesRetention = 3
-main.ana1 432 230 92 92 false
-main.ana2 379 332 92 92 false
-main.ana3 283 374 92 92 false
-main.ana4 155 328 92 92 false
-
-[PostProcessing]
-main.DecimalShift = 0
-main.AnalogDigitalTransitionStart = 9.2
-PreValueUse = true
-PreValueAgeStartup = 720
-main.AllowNegativeRates = false
-main.MaxRateValue = 0.05
-;main.MaxRateType = AbsoluteChange
-main.ExtendedResolution = false
-main.IgnoreLeadingNaN = false
-ErrorMessage = true
-CheckDigitIncreaseConsistency = false
-
-;[MQTT]
-;Uri = mqtt://IP-ADRESS:1883
-;MainTopic = watermeter
-;ClientID = watermeter
-;user = USERNAME
-;password = PASSWORD
-RetainMessages = false
-HomeassistantDiscovery = false
-;MeterType = other
-;CACert = /config/certs/RootCA.pem
-;ClientCert = /config/certs/client.pem.crt
-;ClientKey = /config/certs/client.pem.key
-
-;[InfluxDB]
-;Uri = undefined
-;Database = undefined
-;Measurement = undefined
-;user = undefined
-;password = undefined
-
-;[InfluxDBv2]
-;Uri = undefined
-;Bucket = undefined
-;Measurement = undefined
-;Org = undefined
-;Token = undefined
-;main.Fieldname = undefined
-
-;[GPIO]
-;MainTopicMQTT = wasserzaehler/GPIO
-;IO0 = input disabled 10 false false 
-;IO1 = input disabled 10 false false 
-;IO3 = input disabled 10 false false 
-;IO4 = built-in-led disabled 10 false false 
-;IO12 = input-pullup disabled 10 false false 
-;IO13 = input-pullup disabled 10 false false
-LEDType = WS2812
-LEDNumbers = 2
-LEDColor = 150 150 150 
-
-[AutoTimer]
-AutoStart = true
-Interval = 5
-
-[DataLogging]
-DataLogActive = true
-DataFilesRetention = 3
-
-[Debug]
-LogLevel = 1
-LogfilesRetention = 3
-
-[System]
-TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
-;TimeServer = pool.ntp.org
-;Hostname = undefined
-RSSIThreshold = -75
-CPUFrequency = 160
-SetupMode = true
+[TakeImage]
+;RawImagesLocation = /log/source
+;RawImagesRetention = 15
+WaitBeforeTakingPicture = 2
+CamGainceiling = x4
+CamQuality = 8
+CamBrightness = 0
+CamContrast = 0
+CamSaturation = 0
+CamSharpness = 1
+CamAutoSharpness = false
+CamSpecialEffect = no_effect
+CamWbMode = auto
+CamAwb = true
+CamAwbGain = true
+CamAec = true
+CamAec2 = true
+CamAeLevel = 2
+CamAecValue = 500
+CamAgc = true
+CamAgcGain = 0
+CamBpc = true
+CamWpc = true
+CamRawGma = true
+CamLenc = true
+CamHmirror = false
+CamVflip = false
+CamDcw = true
+CamZoom = false
+CamZoomOffsetX = 0
+CamZoomOffsetY = 0
+CamZoomSize = 0
+LEDIntensity = 50
+Demo = false
+
+[Alignment]
+InitialRotate = 0.0
+InitialMirror = false
+SearchFieldX = 20
+SearchFieldY = 20
+AlignmentAlgo = Default
+FlipImageSize = false
+/config/ref0.jpg 103 271
+/config/ref1.jpg 442 142
+
+[Digits]
+Model = /config/dig-cont_0700_s3_q.tflite
+CNNGoodThreshold = 0.5
+;ROIImagesLocation = /log/digit
+;ROIImagesRetention = 3
+main.dig1 294 126 30 54 false
+main.dig2 343 126 30 54 false
+main.dig3 391 126 30 54 false
+
+[Analog]
+Model = /config/ana-cont_1300_s2.tflite
+CNNGoodThreshold = 0.5
+;ROIImagesLocation = /log/analog
+;ROIImagesRetention = 3
+main.ana1 432 230 92 92 false
+main.ana2 379 332 92 92 false
+main.ana3 283 374 92 92 false
+main.ana4 155 328 92 92 false
+
+[PostProcessing]
+main.DecimalShift = 0
+main.AnalogDigitalTransitionStart = 9.2
+PreValueUse = true
+PreValueAgeStartup = 720
+main.AllowNegativeRates = false
+main.MaxRateValue = 0.05
+;main.MaxRateType = AbsoluteChange
+main.ExtendedResolution = false
+main.IgnoreLeadingNaN = false
+ErrorMessage = true
+CheckDigitIncreaseConsistency = false
+
+;[MQTT]
+;Uri = mqtt://IP-ADRESS:1883
+;MainTopic = watermeter
+;ClientID = watermeter
+;user = USERNAME
+;password = PASSWORD
+RetainMessages = false
+HomeassistantDiscovery = false
+;MeterType = other
+;CACert = /config/certs/RootCA.pem
+;ClientCert = /config/certs/client.pem.crt
+;ClientKey = /config/certs/client.pem.key
+
+;[InfluxDB]
+;Uri = undefined
+;Database = undefined
+;Measurement = undefined
+;user = undefined
+;password = undefined
+
+;[InfluxDBv2]
+;Uri = undefined
+;Bucket = undefined
+;Measurement = undefined
+;Org = undefined
+;Token = undefined
+;main.Fieldname = undefined
+
+;[GPIO]
+;MainTopicMQTT = wasserzaehler/GPIO
+;IO0 = input disabled 10 false false 
+;IO1 = input disabled 10 false false 
+;IO3 = input disabled 10 false false 
+;IO4 = built-in-led disabled 10 false false 
+;IO12 = input-pullup disabled 10 false false 
+;IO13 = input-pullup disabled 10 false false
+LEDType = WS2812
+LEDNumbers = 2
+LEDColor = 150 150 150 
+
+[AutoTimer]
+AutoStart = true
+Interval = 5
+
+[DataLogging]
+DataLogActive = true
+DataFilesRetention = 3
+
+[Debug]
+LogLevel = 1
+LogfilesRetention = 3
+
+[System]
+TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
+;TimeServer = pool.ntp.org
+;Hostname = undefined
+RSSIThreshold = -75
+CPUFrequency = 160
+SetupMode = true

+ 64 - 50
sd-card/html/edit_alignment.html

@@ -113,49 +113,56 @@
     <hr />
     <hr />
 
 
 	<table>
 	<table>
-    <colgroup>
-        <col span="1" style="width: 33.3%;">
-        <col span="1" style="width: 33.3%;">
-        <col span="1" style="width: 33.3%;">
-    </colgroup>
-	  <tr>
-		<td>Marker: 
-			<select id="index" name="reference" onchange="ChangeSelection()">
-			  <option value="0" selected>Marker 1</option>
-			  <option value="1" >Marker 2</option>
-			</select>
-		</td>
-		<td colspan="2" style="padding-left: 22px; color: grey;">Filename: <output type="text" name="name" id="name" onchange="namechanged()"></td>
-	  </tr>
-	  <tr>
-		<td style="padding-top: 10px">x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()"></td>
-		<td style="padding-top: 10px">dx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchanged()"></td>
-		<td rowspan="2" style="padding-top: 10px;"><input class="button" type="button" value="Update Marker" onclick="CutOutReference()"></td>	
-	  </tr>
-	  <tr>
-		<td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()"></td>
-		<td>dy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()"></td>
-	  </tr>
-	  <tr>
-		<td style="vertical-align: bottom;">Selected Image Area:</td>
-		<td style="vertical-align: bottom;">Resulting Marker:</td>
-        <td><input class="button" type="button" id="enhancecontrast" value="Enhance Image Contrast" onclick="EnhanceContrast()"></td>	
-	  </tr> 
-	  <tr>
-		<td style="height:70px; vertical-align: top;"><img id="img_ref_org" src = ""></td>    <!--/img_tmp/ref_zw_org.jpg-->
-		<td style="height:70px; vertical-align: top;"><img id="img_ref" src = ""></td>        <!--/img_tmp/ref_zw.jpg-->
-	  </tr> 
-        <tr>
-            <td style="vertical-align:bottom;"><b>Reference Image:</b></td>
-            <td></td>
-            <td><input style="font-weight:bold;" class="button" type="submit" name="saveroi" id="savemarker" onclick="SaveToConfig()" value="Save New Marker">
-            </td>
-        </tr> 
-        <tr>
-            <td colspan="3"><canvas id="canvas" crossorigin></canvas></td>
-        </tr>
-    </table>
-
+		<colgroup>
+			<col span="1" style="width: 33.3%;">
+			<col span="1" style="width: 33.3%;">
+			<col span="1" style="width: 33.3%;">
+		</colgroup>
+	
+		<tr>
+			<td>Marker: 
+				<select id="index" name="reference" onchange="ChangeSelection()">
+					<option value="0" selected>Marker 1</option>
+					<option value="1" >Marker 2</option>
+				</select>
+			</td>
+			<td colspan="2" style="padding-left: 22px; color: grey;">Filename: <output type="text" name="name" id="name" onchange="namechanged()"></td>
+		</tr>
+	  
+		<tr>
+			<td style="padding-top: 10px">x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()"></td>
+			<td style="padding-top: 10px">dx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchanged()"></td>
+			<td rowspan="2" style="padding-top: 10px;"><input class="button" type="button" value="Update Marker" onclick="CutOutReference()"></td>	
+		</tr>
+	  
+		<tr>
+			<td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()"></td>
+			<td>dy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()"></td>
+		</tr>
+	  
+		<tr>
+			<td style="vertical-align: bottom;">Selected Image Area:</td>
+			<td style="vertical-align: bottom;">Resulting Marker:</td>
+			<td><input class="button" type="button" id="enhancecontrast" value="Enhance Image Contrast" onclick="EnhanceContrast()"></td>	
+		</tr> 
+	  
+		<tr>
+			<td style="height:70px; vertical-align: top;"><img id="img_ref_org" src = ""></td>    <!--/img_tmp/ref_zw_org.jpg-->
+			<td style="height:70px; vertical-align: top;"><img id="img_ref" src = ""></td>        <!--/img_tmp/ref_zw.jpg-->
+		</tr>
+	  
+		<tr>
+			<td style="vertical-align:bottom;"><b>Reference Image:</b></td>
+			<td></td>
+			<td>
+				<input style="font-weight:bold;" class="button" type="submit" name="saveroi" id="savemarker" onclick="SaveToConfig()" value="Save New Marker">
+			</td>
+		</tr>
+	  
+		<tr>
+			<td colspan="3"><canvas id="canvas" crossorigin></canvas></td>
+		</tr>
+	</table>
 
 
 <script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script> 
 <script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script> 
 <script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
 <script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
@@ -173,6 +180,7 @@ var canvas = document.getElementById('canvas'),
     domainname = getDomainname(),
     domainname = getDomainname(),
 	neueref1,
 	neueref1,
 	neueref2,
 	neueref2,
+	cofcat,	
     param;
     param;
     
     
 function doReboot() {
 function doReboot() {
@@ -290,8 +298,7 @@ function UpdateReference(){
         draw();
         draw();
     }
     }
 
 
-    _filenameurl = refInfo[aktindex]["name"].replace("/config/", "/img_tmp/");
-
+    var _filenameurl = refInfo[aktindex]["name"].replace("/config/", "/img_tmp/");
     var url = domainname + "/fileserver" + _filenameurl + "?"  + Date.now();
     var url = domainname + "/fileserver" + _filenameurl + "?"  + Date.now();
     document.getElementById("img_ref").src = url;
     document.getElementById("img_ref").src = url;
 
 
@@ -352,7 +359,7 @@ function openDescription() {
     if(window.location.hash) {
     if(window.location.hash) {
         var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
         var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
         if(hash == 'description') {
         if(hash == 'description') {
-            document.getElementById("desc_details").open = true;
+            document.getElementById("desc_details").open = false;
 		}
 		}
     }
     }
 }
 }
@@ -368,7 +375,7 @@ function LoadReference(){
         draw();
         draw();
     }
     }
 
 
-    _filenameurl = refInfo[aktindex]["name"];
+    var _filenameurl = refInfo[aktindex]["name"];
     var url = domainname + "/fileserver" + _filenameurl + "?"  + Date.now();
     var url = domainname + "/fileserver" + _filenameurl + "?"  + Date.now();
     document.getElementById("img_ref").src = url;
     document.getElementById("img_ref").src = url;
 	
 	
@@ -387,17 +394,23 @@ function LoadReference(){
 function init() {
 function init() {
     openDescription();
     openDescription();
     domainname = getDomainname();
     domainname = getDomainname();
-    loadConfig(domainname); 
+	
+    if (!loadConfig(domainname)) {
+		firework.launch('Configuration could not be loaded! Please reload the page!', 'danger', 30000);
+		return;
+    }
+
     ParseConfig();
     ParseConfig();
     param = getConfigParameters();
     param = getConfigParameters();
+	cofcat = getConfigCategory();
 
 
     document.getElementById("savemarker").disabled = true;
     document.getElementById("savemarker").disabled = true;
     document.getElementById("enhancecontrast").disabled = true;
     document.getElementById("enhancecontrast").disabled = true;
-
+	
     canvas.addEventListener('mousedown', mouseDown, false);
     canvas.addEventListener('mousedown', mouseDown, false);
     canvas.addEventListener('mouseup', mouseUp, false);
     canvas.addEventListener('mouseup', mouseUp, false);
     canvas.addEventListener('mousemove', mouseMove, false);
     canvas.addEventListener('mousemove', mouseMove, false);
-    loadCanvas(domainname + "/fileserver/config/reference.jpg");
+    loadCanvas(domainname + "/fileserver/config/reference.jpg");	
 
 
     //CopyReferenceToImgTmp(domainname);
     //CopyReferenceToImgTmp(domainname);
     refInfo = GetReferencesInfo();
     refInfo = GetReferencesInfo();
@@ -405,6 +418,7 @@ function init() {
     //UpdateReference();
     //UpdateReference();
 	LoadReference();
 	LoadReference();
     drawImage();
     drawImage();
+	draw();
 }
 }
 
 
 function drawImage(){
 function drawImage(){

+ 29 - 12
sd-card/html/edit_analog.html

@@ -125,7 +125,6 @@
 
 
 
 
 <div id="div1">
 <div id="div1">
-
     <table>
     <table>
         <colgroup>
         <colgroup>
             <col span="1" style="width: 22%;">
             <col span="1" style="width: 22%;">
@@ -133,9 +132,11 @@
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
         </colgroup>
         </colgroup>
+		
         <tr>
         <tr>
             <td colspan="4" style="padding: 0px"><class id="Numbers_text" style="color:black;">Number Sequence:</class></td>
             <td colspan="4" style="padding: 0px"><class id="Numbers_text" style="color:black;">Number Sequence:</class></td>
         </tr>
         </tr>
+		
         <tr>
         <tr>
             <td>
             <td>
                 <select id="Numbers_value1" onchange="numberChanged()">
                 <select id="Numbers_value1" onchange="numberChanged()">
@@ -156,15 +157,18 @@
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
         </colgroup>
         </colgroup>
+		
         <tr>
         <tr>
             <td style="padding: 0px">ROI:</td>
             <td style="padding: 0px">ROI:</td>
         </tr>
         </tr>
+		
         <tr>
         <tr>
             <td><select id="index" name="index" onchange="ChangeSelection()" tabindex=1></select></td>
             <td><select id="index" name="index" onchange="ChangeSelection()" tabindex=1></select></td>
             <td><input class="button" type="submit" id="newROI" name="newROI" onclick="newROI()" value="New ROI"></td>
             <td><input class="button" type="submit" id="newROI" name="newROI" onclick="newROI()" value="New ROI"></td>
             <td><input class="button" type="submit" id="renameROI" name="renameROI" onclick="renameROI()" value="Rename ROI"></td>	  
             <td><input class="button" type="submit" id="renameROI" name="renameROI" onclick="renameROI()" value="Rename ROI"></td>	  
             <td><input class="button" type="submit" id="deleteROI" name="deleteROI" onclick="deleteROI()" value="Delete ROI"></td>
             <td><input class="button" type="submit" id="deleteROI" name="deleteROI" onclick="deleteROI()" value="Delete ROI"></td>
         </tr>
         </tr>
+		
         <tr>       
         <tr>       
             <td class="multiplier">Multiplier: <output type="text" id="multiplier" name="multiplier"></output><br>
             <td class="multiplier">Multiplier: <output type="text" id="multiplier" name="multiplier"></output><br>
                 (only based on order)
                 (only based on order)
@@ -183,14 +187,17 @@
             <col span="1" style="width: 18%;">
             <col span="1" style="width: 18%;">
             <col span="1" style="width: 64%;">
             <col span="1" style="width: 64%;">
         </colgroup>
         </colgroup>
+		
         <tr>
         <tr>
             <td>x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()" tabindex=2></td>	  
             <td>x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()" tabindex=2></td>	  
             <td>Δx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchangeddx()" tabindex=4></td>
             <td>Δx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchangeddx()" tabindex=4></td>
         </tr>
         </tr>
+		
         <tr>
         <tr>
             <td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()" tabindex=3></td>	
             <td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()" tabindex=3></td>	
             <td>Δy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()" tabindex=5></td>
             <td>Δy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()" tabindex=5></td>
         </tr>
         </tr>
+		
         <tr>
         <tr>
             <td colspan="3"><input type="checkbox" id="CCW" name="CCW" value="0" onclick="changeCCW()" unchecked tabindex=8><label for="CCW">Counter clockwise rotation (CCW)</label></td>
             <td colspan="3"><input type="checkbox" id="CCW" name="CCW" value="0" onclick="changeCCW()" unchecked tabindex=8><label for="CCW">Counter clockwise rotation (CCW)</label></td>
         </tr>		
         </tr>		
@@ -202,7 +209,6 @@ The following settings are only used for easier setup, they are <b>not</b> persi
 <input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=9><label for="showall">Show all ROIs</label><br>
 <input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=9><label for="showall">Show all ROIs</label><br>
 <input type="checkbox" id="lockAspectRatio" name="lockAspectRatio" value="1" onclick="changelockAspectRatio()" checked tabindex=6><label for="lockAspectRatio"> Lock aspect ratio </label><br>
 <input type="checkbox" id="lockAspectRatio" name="lockAspectRatio" value="1" onclick="changelockAspectRatio()" checked tabindex=6><label for="lockAspectRatio"> Lock aspect ratio </label><br>
 <input type="checkbox" id="lockSizes" name="lockSizes" value="1" onclick="changelockSizes()" checked tabindex=7><label for="lockSizes"> Synchronize y, Δx and Δy between ROIs</label><br>
 <input type="checkbox" id="lockSizes" name="lockSizes" value="1" onclick="changelockSizes()" checked tabindex=7><label for="lockSizes"> Synchronize y, Δx and Δy between ROIs</label><br>
-
 <hr>
 <hr>
 
 
     <table>
     <table>
@@ -212,20 +218,23 @@ The following settings are only used for easier setup, they are <b>not</b> persi
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
         </colgroup>
         </colgroup>
+		
         <tr>
         <tr>
             <td colspan="3" style="vertical-align: bottom;"><b>Reference Image:</b></td>
             <td colspan="3" style="vertical-align: bottom;"><b>Reference Image:</b></td>
-            <!---<td><button class="button" id="reboot" type="button" onclick="doReboot()">Reboot device</button></td>-->
-            <td><input style="font-weight:bold;" class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save Config" tabindex=10></td>
+            <td>
+				<input style="font-weight:bold;" class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save Config" tabindex=10>
+			</td>
         </tr>
         </tr>
+		
         <tr>
         <tr>
             <td colspan="4"><canvas id="canvas" crossorigin></canvas></td>
             <td colspan="4"><canvas id="canvas" crossorigin></canvas></td>
         </tr>
         </tr>
     </table>
     </table>
 
 
-
     <script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script> 
     <script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script> 
     <script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
     <script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
-    <script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script>  
+    <script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script>
+	<script type="text/javascript" src="jquery-3.6.0.min.js?v=$COMMIT_HASH"></script>
     
     
 <script language="JavaScript">
 <script language="JavaScript">
     var canvas = document.getElementById('canvas'),
     var canvas = document.getElementById('canvas'),
@@ -595,7 +604,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
         if(window.location.hash) {
         if(window.location.hash) {
             var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
             var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
             if(hash == 'description') {
             if(hash == 'description') {
-                document.getElementById("desc_details").open = true;
+                document.getElementById("desc_details").open = false;
             }
             }
         }
         }
     }
     }
@@ -603,18 +612,26 @@ The following settings are only used for easier setup, they are <b>not</b> persi
     function init() {
     function init() {
         openDescription();
         openDescription();
         domainname = getDomainname();
         domainname = getDomainname();
-        canvas.addEventListener('mousedown', mouseDown, false);
-        canvas.addEventListener('mouseup', mouseUp, false);
-        canvas.addEventListener('mousemove', mouseMove, false);
-        loadCanvas(domainname + "/fileserver/config/reference.jpg");
-        loadConfig(domainname); 
+		
+		if (!loadConfig(domainname)) {
+			firework.launch('Configuration could not be loaded! Please reload the page!', 'danger', 30000);
+			return;
+		}
+	
         ParseConfig();
         ParseConfig();
         param = getConfigParameters(); 
         param = getConfigParameters(); 
         cofcat = getConfigCategory();
         cofcat = getConfigCategory();
+		
+        canvas.addEventListener('mousedown', mouseDown, false);
+        canvas.addEventListener('mouseup', mouseUp, false);
+        canvas.addEventListener('mousemove', mouseMove, false);
+        loadCanvas(domainname + "/fileserver/config/reference.jpg");		
+		
         UpdateNUMBERS();
         UpdateNUMBERS();
 
 
         /* Check if the ROIs have same dy and dx. If so, tick the sync checkbox */
         /* Check if the ROIs have same dy and dx. If so, tick the sync checkbox */
         var all_dx_dy_Identical = true;
         var all_dx_dy_Identical = true;
+		
         if (ROIInfo.length > 1) {
         if (ROIInfo.length > 1) {
             for (var i = 1; i < (ROIInfo.length); ++i) { // 2nd .. last ROI
             for (var i = 1; i < (ROIInfo.length); ++i) { // 2nd .. last ROI
                 if (parseInt(ROIInfo[i].dx) != parseInt(ROIInfo[0].dx) || parseInt(ROIInfo[i].dy) != parseInt(ROIInfo[0].dy)) { 
                 if (parseInt(ROIInfo[i].dx) != parseInt(ROIInfo[0].dx) || parseInt(ROIInfo[i].dy) != parseInt(ROIInfo[0].dy)) { 

File diff suppressed because it is too large
+ 472 - 545
sd-card/html/edit_config_template.html


+ 71 - 26
sd-card/html/edit_digits.html

@@ -11,7 +11,7 @@
         p {font-size: 1em;}
         p {font-size: 1em;}
 
 
         input[type=number] {
         input[type=number] {
-            width: 40px;
+            width: 60px;
             margin-right: 10px;
             margin-right: 10px;
             padding: 3px 5px;
             padding: 3px 5px;
             display: inline-block;
             display: inline-block;
@@ -123,17 +123,25 @@
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
         </colgroup>
         </colgroup>
+		
         <tr>
         <tr>
             <td colspan="4" style="padding: 0px"><class id="Numbers_text" style="color:black;">Number Sequence:</class></td>
             <td colspan="4" style="padding: 0px"><class id="Numbers_text" style="color:black;">Number Sequence:</class></td>
         </tr>
         </tr>
+		
         <tr>
         <tr>
             <td>
             <td>
                 <select id="Numbers_value1" onchange="numberChanged()">
                 <select id="Numbers_value1" onchange="numberChanged()">
                 </select>
                 </select>
             </td>
             </td>
-            <td><input class="button" type="submit" id="newNumber" name="newNumber" onclick="newNumber()" value="New Sequence"></td>
-            <td><input class="button" type="submit" id="renameNumber" name="renameNumber" onclick="renameNumber()" value="Rename Sequence"></td> 
-            <td><input class="button" type="submit" id="removeNumber" name="removeNumber" onclick="removeNumber()" value="Delete Sequence"></td>
+            <td>
+				<input class="button" type="submit" id="newNumber" name="newNumber" onclick="newNumber()" value="New Sequence">
+			</td>
+            <td>
+				<input class="button" type="submit" id="renameNumber" name="renameNumber" onclick="renameNumber()" value="Rename Sequence">
+			</td> 
+            <td>
+				<input class="button" type="submit" id="removeNumber" name="removeNumber" onclick="removeNumber()" value="Delete Sequence">
+			</td>
         </tr>
         </tr>
     </table>
     </table>
 
 
@@ -146,15 +154,26 @@
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
         </colgroup>
         </colgroup>
+		
         <tr>
         <tr>
             <td style="padding: 0px">ROI:</td>
             <td style="padding: 0px">ROI:</td>
         </tr>
         </tr>
+		
         <tr>
         <tr>
-            <td><select id="index" name="index" onchange="ChangeSelection()" tabindex=1></select></td>
-            <td><input class="button" type="submit" id="newROI" name="newROI" onclick="newROI()" value="New ROI"></td>
-            <td><input class="button" type="submit" id="renameROI" name="renameROI" onclick="renameROI()" value="Rename ROI"></td>	  
-            <td><input class="button" type="submit" id="deleteROI" name="deleteROI" onclick="deleteROI()" value="Delete ROI"></td>
+            <td>
+				<select id="index" name="index" onchange="ChangeSelection()" tabindex=1></select>
+			</td>
+            <td>
+				<input class="button" type="submit" id="newROI" name="newROI" onclick="newROI()" value="New ROI">
+			</td>
+            <td>
+				<input class="button" type="submit" id="renameROI" name="renameROI" onclick="renameROI()" value="Rename ROI">
+			</td>	  
+            <td>
+				<input class="button" type="submit" id="deleteROI" name="deleteROI" onclick="deleteROI()" value="Delete ROI">
+			</td>
         </tr>
         </tr>
+		
         <tr>       
         <tr>       
             <td class="multiplier">Multiplier: <output type="text" id="multiplier" name="multiplier"></output><br>
             <td class="multiplier">Multiplier: <output type="text" id="multiplier" name="multiplier"></output><br>
                 (only based on order)
                 (only based on order)
@@ -162,8 +181,12 @@
             <td class="multiplier">Multiplier: <output type="text" id="multiplier_decshift" name="multiplier_decshift"></output><br>
             <td class="multiplier">Multiplier: <output type="text" id="multiplier_decshift" name="multiplier_decshift"></output><br>
                 (order + decimal shift: <output type="text" id="decimalShift" name="decimalShift"></output>)
                 (order + decimal shift: <output type="text" id="decimalShift" name="decimalShift"></output>)
             </td>
             </td>
-            <td><input class="button" type="submit" id="movePrevious" onclick="movePrevious()" value="Move ROI Higher"></td> 
-            <td><input class="button" type="submit" id="moveNext" onclick="moveNext()" value="Move ROI Lower"></td>
+            <td>
+				<input class="button" type="submit" id="movePrevious" onclick="movePrevious()" value="Move ROI Higher">
+			</td> 
+            <td>
+				<input class="button" type="submit" id="moveNext" onclick="moveNext()" value="Move ROI Lower">
+			</td>
         </tr>
         </tr>
     </table>
     </table>
 
 
@@ -173,10 +196,12 @@
             <col span="1" style="width: 18%;">
             <col span="1" style="width: 18%;">
             <col span="1" style="width: 64%;">
             <col span="1" style="width: 64%;">
         </colgroup>
         </colgroup>
+		
         <tr>
         <tr>
             <td>x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()" tabindex=2></td>	  
             <td>x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()" tabindex=2></td>	  
             <td>Δx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchangeddx()" tabindex=4></td>
             <td>Δx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchangeddx()" tabindex=4></td>
-            </tr>
+        </tr>
+		
         <tr>
         <tr>
             <td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()" tabindex=3></td>	
             <td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()" tabindex=3></td>	
             <td>Δy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()" tabindex=5></td>
             <td>Δy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()" tabindex=5></td>
@@ -186,11 +211,11 @@
 
 
 
 
 <hr>
 <hr>
-The following settings are only used for easier setup, they are <b>not</b> persisted on the device:<br>
-<input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=10><label for="showall">Show all ROIs</label><br>
-<input type="checkbox" id="lockAspectRatio" name="lockAspectRatio" value="1" onclick="changelockAspectRatio()" checked tabindex=6><label for="lockAspectRatio"> Lock aspect ratio </label><br>
-<input type="checkbox" id="lockSizes" name="lockSizes" value="1" onclick="changelockSizes()" checked tabindex=7><label for="lockSizes"> Synchronize y, Δx and Δy between ROIs</label><br>
-<input type="checkbox" id="lockSpaceEquidistant" name="lockSpaceEquidistant" value="1" onclick="changeLockSpaceEquidistant()" checked tabindex=8>
+	The following settings are only used for easier setup, they are <b>not</b> persisted on the device:<br>
+	<input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=10><label for="showall">Show all ROIs</label><br>
+	<input type="checkbox" id="lockAspectRatio" name="lockAspectRatio" value="1" onclick="changelockAspectRatio()" checked tabindex=6><label for="lockAspectRatio"> Lock aspect ratio </label><br>
+	<input type="checkbox" id="lockSizes" name="lockSizes" value="1" onclick="changelockSizes()" checked tabindex=7><label for="lockSizes"> Synchronize y, Δx and Δy between ROIs</label><br>
+	<input type="checkbox" id="lockSpaceEquidistant" name="lockSpaceEquidistant" value="1" onclick="changeLockSpaceEquidistant()" checked tabindex=8>
     <label for="lockSpaceEquidistant">Keep equidistance of <input type="number" name="space" id="space" maxlength="2" max=99 step=1 onchange="valuemanualchangedspace()" tabindex=9> between all ROIs</label><br>
     <label for="lockSpaceEquidistant">Keep equidistance of <input type="number" name="space" id="space" maxlength="2" max=99 step=1 onchange="valuemanualchangedspace()" tabindex=9> between all ROIs</label><br>
 <hr>
 <hr>
 
 
@@ -201,10 +226,14 @@ The following settings are only used for easier setup, they are <b>not</b> persi
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
             <col span="1" style="width: 26%;">
         </colgroup>
         </colgroup>
+		
         <tr>
         <tr>
             <td colspan="3" style="vertical-align: bottom;"><b>Reference Image:</b></td>
             <td colspan="3" style="vertical-align: bottom;"><b>Reference Image:</b></td>
-            <td><input style="font-weight:bold;" class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save Config" tabindex=11></td>
-        </tr> 
+            <td>
+				<input style="font-weight:bold;" class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save Config" tabindex=11>
+			</td>
+        </tr>
+		
         <tr>
         <tr>
             <td colspan="4"><canvas id="canvas" crossorigin></canvas></td>
             <td colspan="4"><canvas id="canvas" crossorigin></canvas></td>
         </tr>
         </tr>
@@ -491,6 +520,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
         }
         }
 
 
         var _index = document.getElementById("index");
         var _index = document.getElementById("index");
+		
         while (_index.length){
         while (_index.length){
             _index.remove(0);
             _index.remove(0);
         }
         }
@@ -582,7 +612,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
         if(window.location.hash) {
         if(window.location.hash) {
             var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
             var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
             if(hash == 'description') {
             if(hash == 'description') {
-                document.getElementById("desc_details").open = true;
+                document.getElementById("desc_details").open = false;
             }
             }
         }
         }
     }
     }
@@ -590,14 +620,21 @@ The following settings are only used for easier setup, they are <b>not</b> persi
     function init() {
     function init() {
         openDescription();
         openDescription();
         domainname = getDomainname();
         domainname = getDomainname();
-        canvas.addEventListener('mousedown', mouseDown, false);
-        canvas.addEventListener('mouseup', mouseUp, false);
-        canvas.addEventListener('mousemove', mouseMove, false);
-        loadCanvas(domainname + "/fileserver/config/reference.jpg");
-        loadConfig(domainname); 
+		
+		if (!loadConfig(domainname)) {
+			firework.launch('Configuration could not be loaded! Please reload the page!', 'danger', 30000);
+			return;
+		}
+		
         ParseConfig();
         ParseConfig();
         param = getConfigParameters(); 
         param = getConfigParameters(); 
         cofcat = getConfigCategory();
         cofcat = getConfigCategory();
+		
+        canvas.addEventListener('mousedown', mouseDown, false);
+        canvas.addEventListener('mouseup', mouseUp, false);
+        canvas.addEventListener('mousemove', mouseMove, false);
+        loadCanvas(domainname + "/fileserver/config/reference.jpg");		
+		
         UpdateNUMBERS();
         UpdateNUMBERS();
 
 
         /* Check if the ROIs are equidistant. Only if not, untick the checkbox */
         /* Check if the ROIs are equidistant. Only if not, untick the checkbox */
@@ -717,6 +754,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
         }
         }
 
 
         erg = CreateNUMBER(_numbernew);
         erg = CreateNUMBER(_numbernew);
+		
         if (erg != "") {
         if (erg != "") {
             firework.launch(erg, 'danger', 30000);
             firework.launch(erg, 'danger', 30000);
         }
         }
@@ -844,14 +882,17 @@ The following settings are only used for easier setup, they are <b>not</b> persi
 
 
     function mouseUp() {
     function mouseUp() {
         drag = false;
         drag = false;
+		
         if (rect.w < 0) {
         if (rect.w < 0) {
             rect.w = -rect.w
             rect.w = -rect.w
             rect.startX-=rect.w
             rect.startX-=rect.w
         }
         }
+		
         if (rect.h < 0) {
         if (rect.h < 0) {
             rect.h = -rect.h
             rect.h = -rect.h
             rect.startY-=rect.h
             rect.startY-=rect.h
         }
         }
+		
         document.getElementById("refdx").value = rect.w;
         document.getElementById("refdx").value = rect.w;
         document.getElementById("refdy").value = rect.h;
         document.getElementById("refdy").value = rect.h;
         document.getElementById("refx").value = rect.startX;
         document.getElementById("refx").value = rect.startX;
@@ -876,10 +917,12 @@ The following settings are only used for easier setup, they are <b>not</b> persi
             }
             }
             document.getElementById("refdx").value = rect.w;
             document.getElementById("refdx").value = rect.w;
             document.getElementById("refdy").value = rect.h;
             document.getElementById("refdy").value = rect.h;
+			
             draw();
             draw();
         }
         }
         else {
         else {
             draw();
             draw();
+			
             var canvas = document.getElementById('canvas');
             var canvas = document.getElementById('canvas');
             var context = canvas.getContext('2d');
             var context = canvas.getContext('2d');
 
 
@@ -915,10 +958,10 @@ The following settings are only used for easier setup, they are <b>not</b> persi
             rect.startX = document.getElementById("refx").value;
             rect.startX = document.getElementById("refx").value;
             rect.startY = document.getElementById("refy").value; 
             rect.startY = document.getElementById("refy").value; 
 
 
-            draw();   
             if (lockSpaceEquidistant) {
             if (lockSpaceEquidistant) {
                 makeX_SpaceEquidistant();
                 makeX_SpaceEquidistant();
-            }   
+            }
+			
             draw();      
             draw();      
         }
         }
         document.getElementById("saveroi").disabled = false;
         document.getElementById("saveroi").disabled = false;
@@ -990,11 +1033,13 @@ The following settings are only used for easier setup, they are <b>not</b> persi
         _roialt= sel.options[sel.selectedIndex].text;
         _roialt= sel.options[sel.selectedIndex].text;
 
 
         var _roinew = prompt("Please enter a new name for the selected ROI", _roialt);
         var _roinew = prompt("Please enter a new name for the selected ROI", _roialt);
+		
         if (_roinew === null) {
         if (_roinew === null) {
             return; //break out of the function early because prompt was aborted
             return; //break out of the function early because prompt was aborted
         }
         }
 
 
         erg = RenameROI(_number, "digit", _roialt, _roinew);
         erg = RenameROI(_number, "digit", _roialt, _roinew);
+		
         if (erg != "") {
         if (erg != "") {
             firework.launch(erg, 'danger', 30000);
             firework.launch(erg, 'danger', 30000);
         }
         }

File diff suppressed because it is too large
+ 557 - 411
sd-card/html/edit_reference.html


+ 30 - 28
sd-card/html/index.html

@@ -21,21 +21,21 @@
         var streamPopup;
         var streamPopup;
         var streamFlashlight = false;
         var streamFlashlight = false;
         var streamWindowFeatures =
         var streamWindowFeatures =
-                'channelmode=no,directories=no,fullscreen=no,' +
-                'location=no,dependent=yes,menubar=no,resizable=no,scrollbars=no,' +
-                'status=no,toolbar=no,titlebar=no,' +
-                'left=10,top=260,width=640px,height=480px';
+            'channelmode=no,directories=no,fullscreen=no,' +
+            'location=no,dependent=yes,menubar=no,resizable=no,scrollbars=no,' +
+            'status=no,toolbar=no,titlebar=no,' +
+            'left=10,top=260,width=640px,height=480px';
 
 
-         function loadPage(page) {
+        function loadPage(page) {
             console.log("loadPage( " + page + " )");
             console.log("loadPage( " + page + " )");
 
 
-            if (streamPopup)   // Ensure that stream popup is closed because it's blocking web interface
+            if (streamPopup) {  // Ensure that stream popup is closed because it's blocking web interface
                 streamPopup.close();
                 streamPopup.close();
+			}
 
 
             asyncPageLoad(page);
             asyncPageLoad(page);
         }
         }
 
 
-
         async function asyncPageLoad(page ) {
         async function asyncPageLoad(page ) {
             console.log("  loading " + page + " ...");
             console.log("  loading " + page + " ...");
             document.cookie = "page="+page + "; path=/";
             document.cookie = "page="+page + "; path=/";
@@ -46,7 +46,6 @@
             });
             });
         }
         }
 
 
-
         function resetMenu() {
         function resetMenu() {
             [].forEach.call(document.querySelectorAll('.submenu'), function (el) {
             [].forEach.call(document.querySelectorAll('.submenu'), function (el) {
                 el.style.visibility = 'visible';
                 el.style.visibility = 'visible';
@@ -54,18 +53,20 @@
         }
         }
         
         
         function getCookie(cname) {
         function getCookie(cname) {
-        let name = cname + "=";
-        let decodedCookie = decodeURIComponent(document.cookie);
-        let ca = decodedCookie.split(';');
-        for(let i = 0; i <ca.length; i++) {
-            let c = ca[i];
-            while (c.charAt(0) == ' ') {
-            c = c.substring(1);
-            }
-            if (c.indexOf(name) == 0) {
-            return c.substring(name.length, c.length);
-            }
-        }
+			let name = cname + "=";
+			let decodedCookie = decodeURIComponent(document.cookie);
+			let ca = decodedCookie.split(';');
+			for(let i = 0; i <ca.length; i++) {
+				let c = ca[i];
+				
+				while (c.charAt(0) == ' ') {
+					c = c.substring(1);
+				}
+				
+				if (c.indexOf(name) == 0) {
+					return c.substring(name.length, c.length);
+				}
+			}
         return "";
         return "";
         }        
         }        
     </script>
     </script>
@@ -153,7 +154,7 @@
     HA_send_discovery_visibility();
     HA_send_discovery_visibility();
 
 
     if (getCookie("page") == "" || getCookie("page") == "reboot_page.html?v=$COMMIT_HASH") {
     if (getCookie("page") == "" || getCookie("page") == "reboot_page.html?v=$COMMIT_HASH") {
-    document.cookie = "page=overview.html?v=$COMMIT_HASH" + "; path=/";
+		document.cookie = "page=overview.html?v=$COMMIT_HASH" + "; path=/";
     }
     }
     console.log("Loading page: " + getCookie("page"));
     console.log("Loading page: " + getCookie("page"));
     document.getElementById('maincontent').src = getCookie("page");
     document.getElementById('maincontent').src = getCookie("page");
@@ -181,19 +182,18 @@
     }
     }
     */
     */
 
 
-
     function HA_send_discovery_visibility()	{
     function HA_send_discovery_visibility()	{
 		loadConfig(domainname); 
 		loadConfig(domainname); 
 		ParseConfig();
 		ParseConfig();
 		category = getConfigCategory();
 		category = getConfigCategory();
         param = getConfigParameters();
         param = getConfigParameters();
-		if (category["MQTT"]["enabled"] && param["MQTT"]["HomeassistantDiscovery"]["value1"] == "true") {
+		
+		if (category["MQTT"]["enabled"] && param["MQTT"]["HomeassistantDiscovery"].value == "true") {
             document.getElementById("ManualControl").style.display="";
             document.getElementById("ManualControl").style.display="";
             document.getElementById("HASendDiscovery").style.display="";
             document.getElementById("HASendDiscovery").style.display="";
         }
         }
 	}
 	}
 
 
-
     function HA_send_discovery() {
     function HA_send_discovery() {
     console.log("HA Discovery scheduled");
     console.log("HA Discovery scheduled");
     var url = getDomainname() + '/mqtt_publish_discovery'; 
     var url = getDomainname() + '/mqtt_publish_discovery'; 
@@ -207,15 +207,17 @@
 		xhttp.send();
 		xhttp.send();
     }
     }
 
 
-
     function start_livestream(streamFlashlight) {
     function start_livestream(streamFlashlight) {
-        if (streamPopup) 
+        if (streamPopup) {
             streamPopup.close();
             streamPopup.close();
+		}
 
 
-        if (streamFlashlight)
+        if (streamFlashlight) {
             streamPopup = window.open(getDomainname() + '/stream?flashlight=true','LivestreamWithlight',streamWindowFeatures);
             streamPopup = window.open(getDomainname() + '/stream?flashlight=true','LivestreamWithlight',streamWindowFeatures);
-        else
+		}
+        else {
             streamPopup = window.open(getDomainname() + '/stream','Livestream',streamWindowFeatures);
             streamPopup = window.open(getDomainname() + '/stream','Livestream',streamWindowFeatures);
+		}
 
 
         streamPopup.focus();
         streamPopup.focus();
     }
     }

+ 223 - 185
sd-card/html/overview.html

@@ -5,13 +5,64 @@
 <meta charset="UTF-8" />
 <meta charset="UTF-8" />
 
 
 <style>
 <style>
-.tg  {border-collapse:collapse;border-spacing:0;width:100%;min-width:600px;height:100%;color:darkslategray;}
-.tg th{min-width:325px;width:325px;height:20px;font-size:18px;text-align:left;font-weight:bold;padding:5px 10px 5px 10px;;overflow:hidden;word-break:normal;background-color:lightgrey;}
-.tg td{font-size:15px;padding:5px 10px 5px 10px;overflow:hidden;word-break:normal;}
-.tg .tg-1{font-size:15px;vertical-align: top; font-family:Arial, Helvetica, sans-serif !important;}
-.tg .tg-2{height:52px;font-size:15px;padding:3px 0px 3px 10px;vertical-align:middle;font-family:Arial, Helvetica, sans-serif !important;}
-.tg .tg-3{height:45px;font-size:15px;padding:3px 10px 3px 10px;vertical-align:middle;font-family:Arial, Helvetica, sans-serif !important;}
-.tg .tg-4{height:fit-content;font-size:15px;padding:5px 10px 5px 10px;vertical-align:text-top;font-family:Arial, Helvetica, sans-serif !important;}
+.tg  {
+	border-collapse:collapse;
+	border-spacing:0;
+	width:100%;
+	min-width:600px;
+	height:100%;
+	color:darkslategray;
+	}
+	
+.tg th{
+	min-width:325px;
+	width:325px;
+	height:20px;
+	font-size:18px;
+	text-align:left;
+	font-weight:bold;
+	padding:5px 10px 5px 10px;
+	overflow:hidden;
+	word-break:normal;
+	background-color:lightgrey;
+	}
+
+.tg td{
+	font-size:15px;
+	padding:5px 10px 5px 10px;
+	overflow:hidden;
+	word-break:normal;
+	}
+
+.tg .tg-1{
+	font-size:15px;
+	vertical-align: top;
+	font-family:Arial, Helvetica, sans-serif !important;
+	}
+
+.tg .tg-2{
+	height:52px;
+	font-size:15px;
+	padding:3px 0px 3px 10px;
+	vertical-align:middle;
+	font-family:Arial, Helvetica, sans-serif !important;
+	}
+
+.tg .tg-3{
+	height:45px;
+	font-size:15px;
+	padding:3px 10px 3px 10px;
+	vertical-align:middle;
+	font-family:Arial, Helvetica, sans-serif !important;
+	}
+
+.tg .tg-4{
+	height:fit-content;
+	font-size:15px;
+	padding:5px 10px 5px 10px;
+	vertical-align:text-top;
+	font-family:Arial, Helvetica, sans-serif !important;
+	}
 </style>
 </style>
 
 
 </head>
 </head>
@@ -78,221 +129,208 @@
 		</tr>
 		</tr>
 	</table>
 	</table>
 
 
-
 	<script type="text/javascript" src="jquery-3.6.0.min.js?v=$COMMIT_HASH"></script>
 	<script type="text/javascript" src="jquery-3.6.0.min.js?v=$COMMIT_HASH"></script>
 	<script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script> 
 	<script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script> 
 	<script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
 	<script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
 	<script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script>
 	<script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script>
+	
 	<script type="text/javascript">
 	<script type="text/javascript">
+		function addZero(i) {
+			if (i < 10) {
+				i = "0" + i;
+			}
+			return i;
+		}
 
 
-	function addZero(i) {
-	  if (i < 10) {
-		i = "0" + i;
-	  }
-	  return i;
-	}
-
-
-	$(document).ready(function() {
-		LoadData();
-		LoadROIImage();
-	});
-
-
-	function LoadData(){
-		loadValue("value", "value", "border-collapse: collapse; width: 100%");
-		loadValue("raw", "raw", "border-collapse: collapse; width: 100%");
-		loadValue("prevalue", "prevalue", "border-collapse: collapse; width: 100%");
-		loadValue("error", "error", "border-collapse: collapse; width: 100%");
-		loadStatus();
-		loadCPUTemp();
-		loadRSSI();
-		loadUptime();
-		loadRoundCounter();
-	}
-
-
-	function LoadROIImage(){
-		var d = new Date();
-		var timestamp = d.getTime();
-		var h = addZero(d.getHours());
-		var m = addZero(d.getMinutes());
-		var s = addZero(d.getSeconds());
-		document.getElementById("img").src = getDomainname() + '/img_tmp/alg_roi.jpg?timestamp=' + timestamp;
-		$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
-	}
-
-
-	function Refresh() {
-		setTimeout (function() {
+		$(document).ready(function() {
 			LoadData();
 			LoadData();
 			LoadROIImage();
 			LoadROIImage();
-			Refresh();
-		}, 300000);
-	}
-
-
-	function loadStatus() {
-		url = domainname + '/statusflow';     
-		var xhttp = new XMLHttpRequest();
-		xhttp.onreadystatechange = function() {
-			if (this.readyState == 4 && this.status == 200) {
-				var _rsp = xhttp.responseText;
-				$('#statusflow').html(_rsp);
-			}
+		});
+
+		function LoadData(){
+			loadValue("value", "value", "border-collapse: collapse; width: 100%");
+			loadValue("raw", "raw", "border-collapse: collapse; width: 100%");
+			loadValue("prevalue", "prevalue", "border-collapse: collapse; width: 100%");
+			loadValue("error", "error", "border-collapse: collapse; width: 100%");
+			loadStatus();
+			loadCPUTemp();
+			loadRSSI();
+			loadUptime();
+			loadRoundCounter();
 		}
 		}
-		xhttp.open("GET", url, true);
-		xhttp.send();
-	}
-
 
 
-	function loadCPUTemp() {
-		url = domainname + '/cpu_temperature';     
-		var xhttp = new XMLHttpRequest();
-		xhttp.onreadystatechange = function() {
-			if (this.readyState == 4 && this.status == 200) {
-				var _rsp = xhttp.responseText;
-				$('#cputemp').html("CPU Temperature: " +_rsp + "°C");
-			}
+		function LoadROIImage(){
+			var d = new Date();
+			var timestamp = d.getTime();
+			var h = addZero(d.getHours());
+			var m = addZero(d.getMinutes());
+			var s = addZero(d.getSeconds());
+			document.getElementById("img").src = getDomainname() + '/img_tmp/alg_roi.jpg?timestamp=' + timestamp;
+			$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
 		}
 		}
-		xhttp.open("GET", url, true);
-		xhttp.send();
-	}
 
 
+		function Refresh() {
+			setTimeout (function() {
+				LoadData();
+				LoadROIImage();
+				Refresh();
+			}, 300000);
+		}
 
 
-	function loadRSSI() {
-		url = domainname + '/rssi';     
-		var xhttp = new XMLHttpRequest();
-		xhttp.onreadystatechange = function() {
-			if (this.readyState == 4 && this.status == 200) {
-				var _rsp = xhttp.responseText;
-				
-				if (_rsp >= -55) {
-					$('#rssi').html("WIFI Signal: Excellent (" + _rsp + "dBm)");
-				}
-				else if (_rsp < -55 && _rsp >= -67) {
-					$('#rssi').html("WIFI Signal: Good (" + _rsp + "dBm)");
-				}
-				else if (_rsp < -67 && _rsp >= -78) {
-					$('#rssi').html("WIFI Signal: Fair (" + _rsp + "dBm)");
-				}
-				else if (_rsp < -78 && _rsp >= -85) {
-					$('#rssi').html("WIFI Signal: Weak (" + _rsp + "dBm)");
-				}
-				else {
-					$('#rssi').html("WIFI Signal: Unreliable (" + _rsp + "dBm)");
+		function loadStatus() {
+			url = domainname + '/statusflow';     
+			var xhttp = new XMLHttpRequest();
+			xhttp.onreadystatechange = function() {
+				if (this.readyState == 4 && this.status == 200) {
+					var _rsp = xhttp.responseText;
+					$('#statusflow').html(_rsp);
 				}
 				}
 			}
 			}
+			
+			xhttp.open("GET", url, true);
+			xhttp.send();
 		}
 		}
-		xhttp.open("GET", url, true);
-		xhttp.send();		
-	}
 
 
-
-	function loadUptime() {
-		url = domainname + '/uptime';     
-		var xhttp = new XMLHttpRequest();
-		xhttp.onreadystatechange = function() {
-			if (this.readyState == 4 && this.status == 200) {
-				var _rsp = xhttp.responseText;
-				$('#uptime').html("Uptime: " + _rsp);
+		function loadCPUTemp() {
+			url = domainname + '/cpu_temperature';     
+			var xhttp = new XMLHttpRequest();
+			xhttp.onreadystatechange = function() {
+				if (this.readyState == 4 && this.status == 200) {
+					var _rsp = xhttp.responseText;
+					$('#cputemp').html("CPU Temperature: " +_rsp + "°C");
+				}
 			}
 			}
+			
+			xhttp.open("GET", url, true);
+			xhttp.send();
 		}
 		}
-		xhttp.open("GET", url, true);
-		xhttp.send();
-	}
-
 
 
-	function loadRoundCounter() {
-		url = domainname + '/info?type=Round';     
-		var xhttp = new XMLHttpRequest();
-		xhttp.onreadystatechange = function() {
-			if (this.readyState == 4 && this.status == 200) {
-				var _rsp = xhttp.responseText;
-				$('#round').html("(Round: " + _rsp + ")");
+		function loadRSSI() {
+			url = domainname + '/rssi';     
+			var xhttp = new XMLHttpRequest();
+			xhttp.onreadystatechange = function() {
+				if (this.readyState == 4 && this.status == 200) {
+					var _rsp = xhttp.responseText;
+				
+					if (_rsp >= -55) {
+						$('#rssi').html("WIFI Signal: Excellent (" + _rsp + "dBm)");
+					}
+					else if (_rsp < -55 && _rsp >= -67) {
+						$('#rssi').html("WIFI Signal: Good (" + _rsp + "dBm)");
+					}
+					else if (_rsp < -67 && _rsp >= -78) {
+						$('#rssi').html("WIFI Signal: Fair (" + _rsp + "dBm)");
+					}
+					else if (_rsp < -78 && _rsp >= -85) {
+						$('#rssi').html("WIFI Signal: Weak (" + _rsp + "dBm)");
+					}
+					else {
+						$('#rssi').html("WIFI Signal: Unreliable (" + _rsp + "dBm)");
+					}
+				}
 			}
 			}
+			
+			xhttp.open("GET", url, true);
+			xhttp.send();		
 		}
 		}
-		xhttp.open("GET", url, true);
-		xhttp.send();
-	}
-		
-	
-	function loadValue(_type, _div, _style) {
-		url = domainname + '/value?all=true&type=' + _type;     
-		var xhttp = new XMLHttpRequest();
-		xhttp.onreadystatechange = function() {
-			if (this.readyState == 4 && this.status == 200) {
-			var _rsp = xhttp.responseText;
-			var _split = _rsp.split("\r");
-			if (typeof _style == undefined)
-				out = "<table>";
-			else
-				out = "<table style=\"" + _style + "\">";
 
 
-			if (_split.length == 1)
-			{
-				var _zer = ZerlegeZeile(_split[0], "\t")
-				if (_zer.length > 1)
-					out = _zer[1]; 
-				else
-					out = ""; 
-			}
-			else
-			{
-				for (var j = 0; j < _split.length; ++j)
-				{
-					var _zer = ZerlegeZeile(_split[j], "\t")
-					if (_zer.length == 1)
-						out = out + "<tr><td style=\"width: 22%; padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\">" + 
-							_zer[0] + "</td><td style=\"padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\"> </td></tr>"; 
-					else
-						out = out + "<tr><td style=\"width: 22%; padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\">" + 
-							_zer[0] + "</td><td style=\"padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\" >" + _zer[1] + "</td></tr>"; 
+		function loadUptime() {
+			url = domainname + '/uptime';     
+			var xhttp = new XMLHttpRequest();
+			xhttp.onreadystatechange = function() {
+				if (this.readyState == 4 && this.status == 200) {
+					var _rsp = xhttp.responseText;
+					$('#uptime').html("Uptime: " + _rsp);
 				}
 				}
-				out = out + "</table>"
+			}
+			
+			xhttp.open("GET", url, true);
+			xhttp.send();
+		}
 
 
+		function loadRoundCounter() {
+			url = domainname + '/info?type=Round';     
+			var xhttp = new XMLHttpRequest();
+			xhttp.onreadystatechange = function() {
+				if (this.readyState == 4 && this.status == 200) {
+					var _rsp = xhttp.responseText;
+					$('#round').html("(Round: " + _rsp + ")");
 				}
 				}
-			document.getElementById(_div).innerHTML = out;
 			}
 			}
-		};
-		xhttp.open("GET", url, true);
-		xhttp.send();		
-	}
+			
+			xhttp.open("GET", url, true);
+			xhttp.send();
+		}
 
 
+		function loadValue(_type, _div, _style) {
+			url = domainname + '/value?all=true&type=' + _type;     
+			var xhttp = new XMLHttpRequest();
+			xhttp.onreadystatechange = function() {
+				if (this.readyState == 4 && this.status == 200) {
+					var _rsp = xhttp.responseText;
+					var _split = _rsp.split("\r");
+					
+					if (typeof _style == undefined) {
+						out = "<table>";
+					}
+					else {
+						out = "<table style=\"" + _style + "\">";
+					}
+
+					if (_split.length == 1) {
+						var _zer = ZerlegeZeile(_split[0], "\t")
+					
+						if (_zer.length > 1) {
+							out = _zer[1];
+						}
+						else {
+							out = "";
+						}
+					}
+					else {
+						for (var j = 0; j < _split.length; ++j) {
+							var _zer = ZerlegeZeile(_split[j], "\t")
+						
+							if (_zer.length == 1) {
+								out = out + "<tr><td style=\"width: 22%; padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\">" + 
+								_zer[0] + "</td><td style=\"padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\"> </td></tr>"; 
+							}
+							else {
+								out = out + "<tr><td style=\"width: 22%; padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\">" + 
+								_zer[0] + "</td><td style=\"padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\" >" + _zer[1] + "</td></tr>";
+							}
+						}
+						out = out + "</table>"
+					}
+				document.getElementById(_div).innerHTML = out;
+				}
+			};
+			
+			xhttp.open("GET", url, true);
+			xhttp.send();		
+		}
 
 
-	function setImageMaxWidth()
-	{
-		loadConfig(domainname); 
-		ParseConfig();
-		param = getConfigParameters();
-		if(param["TakeImage"]["ImageSize"]["value1"] == "QVGA") {
-			if (param["Alignment"]["FlipImageSize"]["value1"] == "false") {
+		function setImageMaxWidth() {
+			loadConfig(domainname); 
+			ParseConfig();
+			param = getConfigParameters();
+			
+			if(param["TakeImage"]["CamFrameSize"].value == "QVGA") {
 				document.getElementById("img").style.maxWidth = "320px";
 				document.getElementById("img").style.maxWidth = "320px";
 			}
 			}
 			else {
 			else {
-				document.getElementById("img").style.maxWidth = "240px";
-			}
-		}
-		else {
-			if (param["Alignment"]["FlipImageSize"]["value1"] == "false") { 
 				document.getElementById("img").style.maxWidth = "640px";
 				document.getElementById("img").style.maxWidth = "640px";
 			}
 			}
-			else {
-				document.getElementById("img").style.maxWidth = "480px";
-			}
 		}
 		}
-	}
-
 
 
-	function init(){
-		domainname = getDomainname();
-		setImageMaxWidth();
-		Refresh();
-	}
+		function init(){
+			domainname = getDomainname();
+			setImageMaxWidth();
+			Refresh();
+		}
 
 
-	
-	init();
+		init();
 
 
-</script>
+	</script>
 </body>
 </body>
 </html>
 </html>

+ 172 - 174
sd-card/html/readconfigcommon.js

@@ -1,11 +1,13 @@
 function SaveConfigToServer(_domainname){
 function SaveConfigToServer(_domainname){
      // leere Zeilen am Ende löschen
      // leere Zeilen am Ende löschen
      var zw = config_split.length - 1;
      var zw = config_split.length - 1;
+	 
      while (config_split[zw] == "") {
      while (config_split[zw] == "") {
           config_split.pop();
           config_split.pop();
      }
      }
 
 
      var config_gesamt = "";
      var config_gesamt = "";
+	 
      for (var i = 0; i < config_split.length; ++i)
      for (var i = 0; i < config_split.length; ++i)
      {
      {
           config_gesamt = config_gesamt + config_split[i] + "\n";
           config_gesamt = config_gesamt + config_split[i] + "\n";
@@ -26,231 +28,227 @@ function UpdateConfig(zw, _index, _enhance, _domainname){
 
 
 function createReader(file) {
 function createReader(file) {
      var image = new Image();
      var image = new Image();
+	 
      reader.onload = function(evt) {
      reader.onload = function(evt) {
          var image = new Image();
          var image = new Image();
+		 
          image.onload = function(evt) {
          image.onload = function(evt) {
              var width = this.width;
              var width = this.width;
              var height = this.height;
              var height = this.height;
-             //alert (width); // will produce something like 198
          };
          };
+		 
          image.src = evt.target.result; 
          image.src = evt.target.result; 
      };
      };
+	 
      reader.readAsDataURL(file);
      reader.readAsDataURL(file);
  }
  }
 
 
 
 
-function ZerlegeZeile(input, delimiter = " =\t\r")
-     {
-          var Output = Array(0);
+function ZerlegeZeile(input, delimiter = " =\t\r") {
+    var Output = Array(0);
 //          delimiter = " =,\t";
 //          delimiter = " =,\t";
      
      
-          /* The input can have multiple formats: 
-           *  - key = value
-           *  - key = value1 value2 value3 ...
-           *  - key value1 value2 value3 ...
-           *  
-           * Examples:
-           *  - ImageSize = VGA
-           *  - IO0 = input disabled 10 false false 
-           *  - main.dig1 28 144 55 100 false
-           * 
-           * This causes issues eg. if a password key has a whitespace or equal sign in its value.
-           * As a workaround and to not break any legacy usage, we enforce to only use the
-           * equal sign, if the key is "password"
-           */
-          if (input.includes("password") || input.includes("Token")) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence
-               var pos = input.indexOf("=");
-               delimiter = " \t\r"
-               Output.push(trim(input.substr(0, pos), delimiter));
-               Output.push(trim(input.substr(pos +1, input.length), delimiter));
-          }
-          else { // Legacy Mode
-               input = trim(input, delimiter);
-               var pos = findDelimiterPos(input, delimiter);
-               var token;
-               while (pos > -1) {
-                    token = input.substr(0, pos);
-                    token = trim(token, delimiter);
-                    Output.push(token);
-                    input = input.substr(pos+1, input.length);
-                    input = trim(input, delimiter);
-                    pos = findDelimiterPos(input, delimiter);
-               }
-               Output.push(input);
-          }
+    /* The input can have multiple formats: 
+     *  - key = value
+     *  - key = value1 value2 value3 ...
+     *  - key value1 value2 value3 ...
+     *  
+     * Examples:
+     *  - ImageSize = VGA
+     *  - IO0 = input disabled 10 false false 
+     *  - main.dig1 28 144 55 100 false
+     * 
+     * This causes issues eg. if a password key has a whitespace or equal sign in its value.
+     * As a workaround and to not break any legacy usage, we enforce to only use the
+     * equal sign, if the key is "password"
+     */
+    if (input.includes("password") || input.includes("Token")) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence
+        var pos = input.indexOf("=");
+        delimiter = " \t\r"
+        Output.push(trim(input.substr(0, pos), delimiter));
+        Output.push(trim(input.substr(pos +1, input.length), delimiter));
+    }
+    else { // Legacy Mode
+        input = trim(input, delimiter);
+        var pos = findDelimiterPos(input, delimiter);
+        var token;
+        
+		while (pos > -1) {
+            token = input.substr(0, pos);
+            token = trim(token, delimiter);
+            Output.push(token);
+            input = input.substr(pos+1, input.length);
+            input = trim(input, delimiter);
+            pos = findDelimiterPos(input, delimiter);
+        }
+        
+		Output.push(input);
+    }
      
      
-          return Output;
-     }    
+    return Output;
+}    
 
 
 
 
-function findDelimiterPos(input, delimiter)
-     {
-          var pos = -1;
-          var zw;
-          var akt_del;
+function findDelimiterPos(input, delimiter) {
+    var pos = -1;
+    var zw;
+    var akt_del;
      
      
-          for (var anz = 0; anz < delimiter.length; ++anz)
-          {
-               akt_del = delimiter[anz];
-               zw = input.indexOf(akt_del);
-               if (zw > -1)
-               {
-                    if (pos > -1)
-                    {
-                         if (zw < pos)
-                              pos = zw;
-                    }
-                    else
-                         pos = zw;
-               }
-          }
-          return pos;
-     }
+    for (var anz = 0; anz < delimiter.length; ++anz) {
+        akt_del = delimiter[anz];
+        zw = input.indexOf(akt_del);
+        
+		if (zw > -1) {
+            if (pos > -1) {
+                if (zw < pos) {
+                    pos = zw;
+				}
+            }
+            else {
+                pos = zw;
+			}
+        }
+    }
+    
+	return pos;
+}
      
      
 
 
-function trim(istring, adddelimiter)
-     {
-          while ((istring.length > 0) && (adddelimiter.indexOf(istring[0]) >= 0)){
-               istring = istring.substr(1, istring.length-1);
-          }
+function trim(istring, adddelimiter) {
+    while ((istring.length > 0) && (adddelimiter.indexOf(istring[0]) >= 0)) {
+        istring = istring.substr(1, istring.length-1);
+    }
           
           
-          while ((istring.length > 0) && (adddelimiter.indexOf(istring[istring.length-1]) >= 0)){
-               istring = istring.substr(0, istring.length-1);
-          }
+    while ((istring.length > 0) && (adddelimiter.indexOf(istring[istring.length-1]) >= 0)) {
+        istring = istring.substr(0, istring.length-1);
+    }
 
 
-          return istring;
-     }
+    return istring;
+}
      
      
 
 
-function getConfig()
-{
-     return config_gesamt;
+function getConfig() {
+    return config_gesamt;
 }
 }
 
 
      
      
-function loadConfig(_domainname)
-{
-     var xhttp = new XMLHttpRequest();
-     try {
-          url = _domainname + '/fileserver/config/config.ini';     
-          xhttp.open("GET", url, false);
-          xhttp.send();
-          config_gesamt = xhttp.responseText;
-          config_gesamt = config_gesamt.replace("InitalRotate", "InitialRotate");         // Korrigiere Schreibfehler in config.ini !!!!!
-     }
-     catch (error)
-     {
-//	    firework.launch('Deleting Config.ini failed!', 'danger', 30000);
-     }
-     return true;
+function loadConfig(_domainname) {
+    var xhttp = new XMLHttpRequest();
+    
+	try {
+        url = _domainname + '/fileserver/config/config.ini';     
+        xhttp.open("GET", url, false);
+        xhttp.send();
+        config_gesamt = xhttp.responseText;
+        config_gesamt = config_gesamt.replace("InitalRotate", "InitialRotate");         // Korrigiere Schreibfehler in config.ini !!!!!
+    } catch (error) {}
+    
+	return true;
 }
 }
 
 
      
      
-function dataURLtoBlob(dataurl)
-{
-     var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
+function dataURLtoBlob(dataurl) {
+    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
           bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
           bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
-     while(n--){
-          u8arr[n] = bstr.charCodeAt(n);
-     }
-     return new Blob([u8arr], {type:mime});
+    
+	while(n--){
+        u8arr[n] = bstr.charCodeAt(n);
+    }
+    
+	return new Blob([u8arr], {type:mime});
 }	
 }	
  
  
 
 
-function FileCopyOnServer(_source, _target, _domainname = ""){
-     url = _domainname + "/editflow?task=copy&in=" + _source + "&out=" + _target;
-     var xhttp = new XMLHttpRequest();  
-     try {
-          xhttp.open("GET", url, false);
-          xhttp.send();     }
-     catch (error)
-     {
-//	    firework.launch('Deleting Config.ini failed!', 'danger', 30000);
-     }
+function FileCopyOnServer(_source, _target, _domainname = "") {
+    url = _domainname + "/editflow?task=copy&in=" + _source + "&out=" + _target;
+    var xhttp = new XMLHttpRequest();  
+    
+	try {
+        xhttp.open("GET", url, false);
+        xhttp.send();
+	} catch (error) {}
 }
 }
 
 
 
 
-function FileDeleteOnServer(_filename, _domainname = ""){
-     var xhttp = new XMLHttpRequest();
-     var okay = false;
-
-     xhttp.onreadystatechange = function() {
-          if (xhttp.readyState == 4) {
-               if (xhttp.status == 200) {
-                    okay = true;
-               } else if (xhttp.status == 0) {
-//				firework.launch('Server closed the connection abruptly!', 'danger', 30000);
-//                    location.reload()
-               } else {
-//				firework.launch('An error occured: ' + xhttp.responseText, 'danger', 30000);
-//                    location.reload()
-               }
-          }
-     };
-     try {
-          var url = _domainname + "/delete" + _filename;
-          xhttp.open("POST", url, false);
-          xhttp.send();
-     }
-     catch (error)
-     {
-//	    firework.launch('Deleting Config.ini failed!', 'danger', 30000);
-     }
+function FileDeleteOnServer(_filename, _domainname = "") {
+    var xhttp = new XMLHttpRequest();
+    var okay = false;
+
+    xhttp.onreadystatechange = function() {
+        if (xhttp.readyState == 4) {
+            if (xhttp.status == 200) {
+                okay = true;
+            } 
+			else if (xhttp.status == 0) {
+				// firework.launch('Server closed the connection abruptly!', 'danger', 30000);
+				// location.reload()
+            } 
+			else {
+				// firework.launch('An error occured: ' + xhttp.responseText, 'danger', 30000);
+				// location.reload()
+            }
+        }
+    };
+     
+	try {
+        var url = _domainname + "/delete" + _filename;
+        xhttp.open("POST", url, false);
+        xhttp.send();
+    } catch (error) {}
 
 
-     return okay;
+    return okay;
 }
 }
 
 
 
 
-function FileSendContent(_content, _filename, _domainname = ""){
-     var xhttp = new XMLHttpRequest();  
-     var okay = false;
+function FileSendContent(_content, _filename, _domainname = "") {
+    var xhttp = new XMLHttpRequest();  
+    var okay = false;
 
 
-     xhttp.onreadystatechange = function() {
-          if (xhttp.readyState == 4) {
-               if (xhttp.status == 200) {
-                    okay = true;
-               } else if (xhttp.status == 0) {
+    xhttp.onreadystatechange = function() {
+        if (xhttp.readyState == 4) {
+            if (xhttp.status == 200) {
+                okay = true;
+            } 
+			else if (xhttp.status == 0) {
 				firework.launch('Server closed the connection abruptly!', 'danger', 30000);
 				firework.launch('Server closed the connection abruptly!', 'danger', 30000);
-               } else {
+            } 
+			else {
 				firework.launch('An error occured: ' + xhttp.responseText, 'danger', 30000);
 				firework.launch('An error occured: ' + xhttp.responseText, 'danger', 30000);
-               }
-          }
-     };
-
-     try {
-          upload_path = _domainname + "/upload" + _filename;
-          xhttp.open("POST", upload_path, false);
-          xhttp.send(_content);
-     }
-     catch (error)
-     {
-//	    firework.launch('Deleting Config.ini failed!', 'danger', 30000);
-     }     
+            }
+        }
+    };
+
+    try {
+        upload_path = _domainname + "/upload" + _filename;
+        xhttp.open("POST", upload_path, false);
+        xhttp.send(_content);
+    } catch (error) {}
+	
     return okay;        
     return okay;        
 }
 }
 
 
 
 
 function MakeRefImageZW(zw, _enhance, _domainname){
 function MakeRefImageZW(zw, _enhance, _domainname){
-     var _filename = zw["name"].replace("/config/", "/img_tmp/");
+    var _filename = zw["name"].replace("/config/", "/img_tmp/");
 	 
 	 
-     var url = _domainname + "/editflow?task=cutref&in=/config/reference.jpg&out=" + _filename + "&x=" + zw["x"] + "&y="  + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
+    var url = _domainname + "/editflow?task=cutref&in=/config/reference.jpg&out=" + _filename + "&x=" + zw["x"] + "&y="  + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
      
      
-     if (_enhance == true){
-          url = url + "&enhance=true";
-     }
+    if (_enhance == true){
+        url = url + "&enhance=true";
+    }
 
 
-     var xhttp = new XMLHttpRequest();  
+    var xhttp = new XMLHttpRequest();  
      
      
-     try {
-          xhttp.open("GET", url, false);
-          xhttp.send();
-     } catch (error){}
-
-     if (xhttp.responseText == "CutImage Done") {
-          firework.launch('Image Contrast got enhanced', 'success', 5000);
-          return true;
-     }
-     else {
-          return false;
-     }
+    try {
+        xhttp.open("GET", url, false);
+        xhttp.send();
+    } catch (error){}
+
+    if (xhttp.responseText == "CutImage Done") {
+        firework.launch('Image Contrast got enhanced', 'success', 5000);
+        return true;
+    }
+    else {
+        return false;
+    }
 }
 }

File diff suppressed because it is too large
+ 811 - 624
sd-card/html/readconfigparam.js


Some files were not shown because too many files changed in this diff