jomjol 5 лет назад
Родитель
Сommit
b418525b3b
39 измененных файлов с 1170 добавлено и 498 удалено
  1. 113 66
      code/components/jomjol_controlcamera/ClassControllCamera.cpp
  2. 4 2
      code/components/jomjol_controlcamera/ClassControllCamera.h
  3. 3 2
      code/components/jomjol_fileserver_ota/server_help.cpp
  4. 1 1
      code/components/jomjol_fileserver_ota/server_help.h
  5. 1 1
      code/components/jomjol_flowcontroll/CMakeLists.txt
  6. 10 2
      code/components/jomjol_flowcontroll/ClassFlow.cpp
  7. 6 0
      code/components/jomjol_flowcontroll/ClassFlow.h
  8. 69 60
      code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp
  9. 12 1
      code/components/jomjol_flowcontroll/ClassFlowAlignment.h
  10. 57 69
      code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp
  11. 11 2
      code/components/jomjol_flowcontroll/ClassFlowAnalog.h
  12. 110 2
      code/components/jomjol_flowcontroll/ClassFlowControll.cpp
  13. 7 0
      code/components/jomjol_flowcontroll/ClassFlowControll.h
  14. 73 67
      code/components/jomjol_flowcontroll/ClassFlowDigit.cpp
  15. 10 0
      code/components/jomjol_flowcontroll/ClassFlowDigit.h
  16. 12 3
      code/components/jomjol_flowcontroll/ClassFlowImage.cpp
  17. 4 2
      code/components/jomjol_flowcontroll/ClassFlowImage.h
  18. 26 11
      code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
  19. 3 1
      code/components/jomjol_flowcontroll/ClassFlowMQTT.h
  20. 54 24
      code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp
  21. 14 2
      code/components/jomjol_flowcontroll/ClassFlowMakeImage.h
  22. 58 0
      code/components/jomjol_helper/Helper.cpp
  23. 10 1
      code/components/jomjol_helper/Helper.h
  24. 305 111
      code/components/jomjol_image_proc/CFindTemplate.cpp
  25. 49 16
      code/components/jomjol_image_proc/CFindTemplate.h
  26. 3 3
      code/components/jomjol_logfile/ClassLogFile.cpp
  27. 53 2
      code/components/jomjol_tfliteclass/CTfLiteClass.cpp
  28. 4 0
      code/components/jomjol_tfliteclass/CTfLiteClass.h
  29. 11 1
      code/components/jomjol_tfliteclass/server_tflite.cpp
  30. 6 1
      code/components/jomjol_tfliteclass/server_tflite.h
  31. 57 31
      code/main/server_main.cpp
  32. 2 2
      code/main/version.cpp
  33. 2 2
      code/sdkconfig
  34. 7 7
      code/sdkconfig.old
  35. 2 2
      code/version.cpp
  36. BIN
      firmware/bootloader.bin
  37. BIN
      firmware/firmware.bin
  38. BIN
      firmware/html.zip
  39. 1 1
      sd-card/html/edit_reference.html

+ 113 - 66
code/components/jomjol_controlcamera/ClassControllCamera.cpp

@@ -8,32 +8,9 @@
 #include "Helper.h"
 #include "CFindTemplate.h"
 
-// #include "camera_define.h"
 
-/////////////////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////////////////
 #define BOARD_ESP32CAM_AITHINKER
 
-/**
- * 2. Kconfig setup
- * 
- * If you have a Kconfig file, copy the content from
- *  https://github.com/espressif/esp32-camera/blob/master/Kconfig into it.
- * In case you haven't, copy and paste this Kconfig file inside the src directory.
- * This Kconfig file has definitions that allows more control over the camera and
- * how it will be initialized.
- */
-
-/**
- * 3. Enable PSRAM on sdkconfig:
- * 
- * CONFIG_ESP32_SPIRAM_SUPPORT=y
- * 
- * More info on
- * https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support
- */
-
-// ================================ CODE ======================================
 
 #include <esp_event_loop.h>
 #include <esp_log.h>
@@ -47,31 +24,8 @@
 
 #include "esp_camera.h"
 
-// WROVER-KIT PIN Map
-#ifdef BOARD_WROVER_KIT
-
-#define CAM_PIN_PWDN -1  //power down is not used
-#define CAM_PIN_RESET -1 //software reset will be performed
-#define CAM_PIN_XCLK 21
-#define CAM_PIN_SIOD 26
-#define CAM_PIN_SIOC 27
-
-#define CAM_PIN_D7 35
-#define CAM_PIN_D6 34
-#define CAM_PIN_D5 39
-#define CAM_PIN_D4 36
-#define CAM_PIN_D3 19
-#define CAM_PIN_D2 18
-#define CAM_PIN_D1 5
-#define CAM_PIN_D0 4
-#define CAM_PIN_VSYNC 25
-#define CAM_PIN_HREF 23
-#define CAM_PIN_PCLK 22
-
-#endif
 
 // ESP32Cam (AiThinker) PIN Map
-#ifdef BOARD_ESP32CAM_AITHINKER
 
 #define CAM_PIN_PWDN (gpio_num_t) 32
 #define CAM_PIN_RESET -1 //software reset will be performed
@@ -91,8 +45,6 @@
 #define CAM_PIN_HREF 23
 #define CAM_PIN_PCLK 22
 
-#endif
-
 static const char *TAG = "example:take_picture";
 
 static camera_config_t camera_config = {
@@ -128,14 +80,11 @@ static camera_config_t camera_config = {
     .fb_count = 1       //if more than one, i2s runs in continuous mode. Use only with JPEG
 };
 
-/////////////////////////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////////////////////////
 
 #include "driver/ledc.h"
 
 CCamera Camera;
 
-
 #define FLASH_GPIO GPIO_NUM_4
 #define BLINK_GPIO GPIO_NUM_33
 
@@ -145,8 +94,6 @@ typedef struct {
 } jpg_chunking_t;
 
 
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////
 #define LEDC_LS_CH2_GPIO       (4)
 #define LEDC_LS_CH2_CHANNEL    LEDC_CHANNEL_2
 #define LEDC_LS_TIMER          LEDC_TIMER_1
@@ -172,14 +119,6 @@ void test(){
 
 
 
-
-////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
 static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){
     jpg_chunking_t *j = (jpg_chunking_t *)arg;
     if(!index){
@@ -200,12 +139,102 @@ void CCamera::SetQualitySize(int qual, framesize_t resol)
     s->set_framesize(s, resol); 
     ActualResolution = resol;
     ActualQuality = qual;
+
+    if (resol == FRAMESIZE_QVGA)
+    {
+        image_height = 240;
+        image_width = 320;             
+    }
+    if (resol == FRAMESIZE_VGA)
+    {
+        image_height = 480;
+        image_width = 640;             
+    }
+    if (resol == FRAMESIZE_SVGA)
+    {
+        image_height = 600;
+        image_width = 800;             
+    }
+    if (resol == FRAMESIZE_XGA)
+    {
+        image_height = 768;
+        image_width = 1024;             
+    }
+    if (resol == FRAMESIZE_SXGA)
+    {
+        image_height = 1024;
+        image_width = 1280;             
+    }
+    if (resol == FRAMESIZE_UXGA)
+    {
+        image_height = 1200;
+        image_width = 1600;             
+    }
+
+}
+
+
+esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
+{
+    string ftype;
+    static const int BMP_HEADER_LEN = 54;           // von to_bmp.c !!!!!!!!!!!!!!! 
+
+    LEDOnOff(true);
+
+    if (delay > 0) 
+    {
+        LightOnOff(true);
+        const TickType_t xDelay = delay / portTICK_PERIOD_MS;
+        vTaskDelay( xDelay );
+    }
+
+    camera_fb_t * fb = esp_camera_fb_get();
+    if (!fb) {
+        ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed");
+        LEDOnOff(false);
+        return ESP_FAIL;
+    }
+    LEDOnOff(false);    
+    
+    uint8_t * buf = NULL;
+    size_t buf_len = 0;   
+
+    frame2bmp(fb, &buf, &buf_len);
+
+    int _len_zw = buf_len - BMP_HEADER_LEN;
+    uint8_t  *_buf_zeiger = buf + BMP_HEADER_LEN;
+
+    stbi_uc* p_target;
+    stbi_uc* p_source;    
+    int channels = 3;
+    int width = image_width;
+    int height = image_height;
+
+    for (int x = 0; x < width; ++x)
+        for (int y = 0; y < height; ++y)
+        {
+            p_target = _Image->rgb_image + (channels * (y * width + x));
+            p_source = _buf_zeiger + (channels * (y * width + x));
+            p_target[0] = p_source[2];
+            p_target[1] = p_source[1];
+            p_target[2] = p_source[0];
+        }
+
+//    _Image->CopyFromMemory(_buf_zeiger, _len_zw); 
+
+    free(buf);
+
+    if (delay > 0) 
+    {
+        LightOnOff(false);
+    }
+
+    return ESP_OK;    
 }
 
 
 esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
 {
-//    nm =  "/sdcard/josef_zw.bmp";
     string ftype;
 
     LEDOnOff(true);
@@ -286,15 +315,29 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
     size_t fb_len = 0;
     int64_t fr_start = esp_timer_get_time();
 
+
+    LEDOnOff(true);
+
+    if (delay > 0) 
+    {
+        LightOnOff(true);
+        const TickType_t xDelay = delay / portTICK_PERIOD_MS;
+        vTaskDelay( xDelay );
+    }
+
+
     fb = esp_camera_fb_get();
     if (!fb) {
         ESP_LOGE(TAGCAMERACLASS, "Camera capture failed");
         httpd_resp_send_500(req);
         return ESP_FAIL;
     }
+
+    LEDOnOff(false); 
+    
     res = httpd_resp_set_type(req, "image/jpeg");
     if(res == ESP_OK){
-        res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
+        res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=raw.jpg");
     }
 
     if(res == ESP_OK){
@@ -312,6 +355,12 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
     int64_t fr_end = esp_timer_get_time();
     
     ESP_LOGI(TAGCAMERACLASS, "JPG: %uKB %ums", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000));
+
+    if (delay > 0) 
+    {
+        LightOnOff(false);
+    }
+
     return res;
 }
 
@@ -369,7 +418,7 @@ void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol
             if (strcmp(_size, "SXGA") == 0)
                 resol = FRAMESIZE_SXGA;     // 1280x1024
             if (strcmp(_size, "UXGA") == 0)
-                resol = FRAMESIZE_UXGA;     // 1600x1200                
+                 resol = FRAMESIZE_UXGA;     // 1600x1200   
         }
         if (httpd_query_key_value(_query, "quality", _qual, 10) == ESP_OK)
         {
@@ -409,8 +458,6 @@ CCamera::CCamera()
 
 esp_err_t CCamera::InitCam()
 {
-    printf("Init Flash\n");
-    //power up the camera if PWDN pin is defined
     if(CAM_PIN_PWDN != -1){
         // Init the GPIO
         gpio_pad_select_gpio(CAM_PIN_PWDN);

+ 4 - 2
code/components/jomjol_controlcamera/ClassControllCamera.h

@@ -10,6 +10,7 @@
 #include "esp_camera.h"
 #include <string>
 #include <esp_http_server.h>
+#include "CFindTemplate.h"
 
 
 #define CAMERA_MODEL_AI_THINKER
@@ -24,6 +25,8 @@ class CCamera {
         framesize_t ActualResolution;
 
     public:
+        int image_height, image_width;
+        
         CCamera();
         esp_err_t InitCam();
 
@@ -35,9 +38,8 @@ class CCamera {
 
         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);
 };
 
 

+ 3 - 2
code/components/jomjol_fileserver_ota/server_help.cpp

@@ -25,7 +25,7 @@ char scratch[SCRATCH_BUFSIZE];
     (strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
 
 
-esp_err_t send_file(httpd_req_t *req, std::string filename,  struct stat * file_stat)
+esp_err_t send_file(httpd_req_t *req, std::string filename)
 {
     FILE *fd = OpenFileAndWait(filename.c_str(), "r");
     if (!fd) {
@@ -35,7 +35,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename,  struct stat * file_
         return ESP_FAIL;
     }
 
-    ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", filename.c_str(), file_stat->st_size);
+    ESP_LOGI(TAG, "Sending file : %s ...", filename.c_str());
     set_content_type_from_file(req, filename.c_str());
 
     /* Retrieve the pointer to scratch buffer for temporary storage */
@@ -67,6 +67,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename,  struct stat * file_
 
 
 
+
 /* Copies the full path into destination buffer and returns
  * pointer to path (skipping the preceding base path) */
 const char* get_path_from_uri(char *dest, const char *base_path, const char *uri, size_t destsize)

+ 1 - 1
code/components/jomjol_fileserver_ota/server_help.h

@@ -5,6 +5,6 @@
 
 const char* get_path_from_uri(char *dest, const char *base_path, const char *uri, size_t destsize);
 
-esp_err_t send_file(httpd_req_t *req, std::string filename, struct stat * file_stat);
+esp_err_t send_file(httpd_req_t *req, std::string filename);
 
 esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename);

+ 1 - 1
code/components/jomjol_flowcontroll/CMakeLists.txt

@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
 
 idf_component_register(SRCS ${app_sources}
                     INCLUDE_DIRS "."
-                    REQUIRES jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_fileserver_ota)
+                    REQUIRES jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_fileserver_ota jomjol_image_proc)
 
 

+ 10 - 2
code/components/jomjol_flowcontroll/ClassFlow.cpp

@@ -9,9 +9,11 @@
 void ClassFlow::SetInitialParameter(void)
 {
 	ListFlowControll = NULL;
+	previousElement = NULL;	
 }
 
-//std::vector<string> ClassFlow::ZerlegeZeile(std::string input, std::string delimiter);
+
+
 
 std::vector<string> ClassFlow::ZerlegeZeile(std::string input, std::string delimiter)
 {
@@ -55,7 +57,6 @@ bool ClassFlow::GetNextParagraph(FILE* pfile, string& aktparamgraph)
 ClassFlow::ClassFlow(void)
 {
 	SetInitialParameter();
-	ListFlowControll = NULL;
 }
 
 ClassFlow::ClassFlow(std::vector<ClassFlow*> * lfc)
@@ -64,6 +65,13 @@ ClassFlow::ClassFlow(std::vector<ClassFlow*> * lfc)
 	ListFlowControll = lfc;
 }
 
+ClassFlow::ClassFlow(std::vector<ClassFlow*> * lfc, ClassFlow *_prev)
+{
+	SetInitialParameter();	
+	ListFlowControll = lfc;
+	previousElement = _prev;
+}	
+
 bool ClassFlow::ReadParameter(FILE* pfile, string &aktparamgraph)
 {
 	return false;

+ 6 - 0
code/components/jomjol_flowcontroll/ClassFlow.h

@@ -16,7 +16,10 @@ using namespace std;
 struct HTMLInfo
 {
 	float val;
+	CImageBasis *image = NULL;
+	CImageBasis *image_org = NULL;
 	std::string filename;
+	std::string filename_org;	
 };
 
 
@@ -30,12 +33,15 @@ protected:
 	bool getNextLine(FILE* pfile, string* rt);
 
 	std::vector<ClassFlow*>* ListFlowControll;
+	ClassFlow *previousElement;
 
 	virtual void SetInitialParameter(void);
 
 public:
 	ClassFlow(void);
 	ClassFlow(std::vector<ClassFlow*> * lfc);
+	ClassFlow(std::vector<ClassFlow*> * lfc, ClassFlow *_prev);	
+	
 	virtual bool ReadParameter(FILE* pfile, string &aktparamgraph);
 	virtual bool doFlow(string time);
 	virtual string getHTMLSingleStep(string host);

+ 69 - 60
code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp

@@ -1,29 +1,51 @@
 #include "ClassFlowAlignment.h"
+#include "ClassFlowMakeImage.h"
+#include "ClassFlow.h"
 
 #include "ClassLogFile.h"
 
-ClassFlowAlignment::ClassFlowAlignment()
+bool AlignmentExtendedDebugging = true;
+
+
+void ClassFlowAlignment::SetInitialParameter(void)
 {
     initalrotate = 0;
     anz_ref = 0;
     suchex = 40;
     suchey = 40;
     initialmirror = false;
+    SaveAllFiles = false;
     namerawimage =  "/sdcard/img_tmp/raw.jpg";
     ListFlowControll = NULL;
+    AlignAndCutImage = NULL;
+    ImageBasis = NULL;
+    ImageTMP = NULL;
+    previousElement = NULL;
+    ref_dx[0] = 0; ref_dx[1] = 0;
+    ref_dy[0] = 0; ref_dy[1] = 0;
 }
 
 ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
 {
-    initalrotate = 0;
-    anz_ref = 0;
-    suchex = 40;
-    suchey = 40;
-    initialmirror = false;
-    namerawimage =  "/sdcard/img_tmp/raw.jpg";    
+    SetInitialParameter();
     ListFlowControll = lfc;
+
+    for (int i = 0; i < ListFlowControll->size(); ++i)
+    {
+        if (((*ListFlowControll)[i])->name().compare("ClassFlowMakeImage") == 0)
+        {
+            ImageBasis = ((ClassFlowMakeImage*) (*ListFlowControll)[i])->rawImage;
+        }
+    }
+
+    if (!ImageBasis)            // die Funktion Bilder aufnehmen existiert nicht --> muss erst erzeugt werden NUR ZU TESTZWECKEN
+    {
+        if (AlignmentExtendedDebugging) printf("CImageBasis musste erzeugt werden\n");
+        ImageBasis = new CImageBasis(namerawimage);
+    }
 }
 
+
 bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
 {
     std::vector<string> zerlegt;
@@ -59,11 +81,18 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
         }               
         if ((zerlegt.size() == 3) && (anz_ref < 2))
         {
-            this->reffilename[anz_ref] = FormatFileName("/sdcard" + zerlegt[0]);
-            this->ref_x[anz_ref] = std::stod(zerlegt[1]);
-            this->ref_y[anz_ref] = std::stod(zerlegt[2]);
+            reffilename[anz_ref] = FormatFileName("/sdcard" + zerlegt[0]);
+            ref_x[anz_ref] = std::stod(zerlegt[1]);
+            ref_y[anz_ref] = std::stod(zerlegt[2]);
             anz_ref++;
         }
+
+        if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
+        {
+            if (toUpper(zerlegt[1]) == "TRUE")
+                SaveAllFiles = true;
+        }
+
     }
     return true;
 
@@ -80,72 +109,52 @@ string ClassFlowAlignment::getHTMLSingleStep(string host)
 }
 
 
-bool ClassFlowAlignment::doFlow(string time)
+bool ClassFlowAlignment::doFlow(string time) 
 {
-    string input = namerawimage;
-    string output = "/sdcard/img_tmp/rot.jpg";
-    string output3 = "/sdcard/img_tmp/rot_roi.jpg";
-    string output2 = "/sdcard/img_tmp/alg.jpg";
-    string output4 = "/sdcard/img_tmp/alg_roi.jpg";
-    string output1 = "/sdcard/img_tmp/mirror.jpg";
+    if (!ImageTMP) 
+        ImageTMP = new CImageBasis(ImageBasis);
 
-    input = FormatFileName(input);
-    output = FormatFileName(output);
-    output2 = FormatFileName(output2);
+    if (AlignAndCutImage)
+        delete AlignAndCutImage;
+    AlignAndCutImage = new CAlignAndCutImage(ImageBasis, ImageTMP);   
 
+    CRotate rt(AlignAndCutImage, ImageTMP);
 
     if (initialmirror){
-        CRotate *rt;
-        rt = new CRotate(input);
-        if (!rt->ImageOkay()){
-            LogFile.WriteToFile("ClassFlowAlignment::doFlow CRotate Inital Mirror raw.jpg not okay!");
-            delete rt;
-            return false;
-        }
         printf("do mirror\n");
-        rt->Mirror();
-        rt->SaveToFile(output1);
-        input = output1;
-        delete rt;
+        rt.Mirror();
+        if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
     }
-
-
+ 
     if (initalrotate != 0)
     {
-        CRotate *rt = NULL;
-        printf("Load rotationfile: %s\n", input.c_str());
-        rt = new CRotate(input);
-        if (!rt->ImageOkay()){
-            LogFile.WriteToFile("ClassFlowAlignment::doFlow CRotate raw.jpg not okay!");
-            delete rt;
-            return false;
-        }
-        rt->Rotate(this->initalrotate);
-        rt->SaveToFile(output);
-        delete rt;
-    }
-    else
-    {
-        CopyFile(input, output);
+        rt.Rotate(initalrotate);
+        if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
     }
 
-    CAlignAndCutImage *caic;
-    caic = new CAlignAndCutImage(output);
-    caic->Align(this->reffilename[0], this->ref_x[0], this->ref_y[0], this->reffilename[1], this->ref_x[1], this->ref_y[1], suchex, suchey, output3);
-    caic->SaveToFile(output2);
+    AlignAndCutImage->Align(reffilename[0], ref_x[0], ref_y[0], reffilename[1], ref_x[1], ref_y[1], suchex, suchey, "");
+    AlignAndCutImage->GetRefSize(ref_dx, ref_dy);
+    if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
 
-    printf("Startwriting Output4:%s\n", output4.c_str());
-    if (output4.length() > 0)
+    if (SaveAllFiles)
     {
-        caic->drawRect(ref_x[0], ref_y[0], caic->t0_dx, caic->t0_dy, 255, 0, 0, 2);
-        caic->drawRect(ref_x[1], ref_y[1], caic->t1_dx, caic->t1_dy, 255, 0, 0, 2);
-        caic->SaveToFile(output4);
-        printf("Write output4: %s\n", output4.c_str());
+        DrawRef(ImageTMP);
+        ImageTMP->SaveToFile(FormatFileName("/sdcard/img_tmp/alg_roi.jpg"));
     }
 
-    delete caic;
+    if (ImageTMP)       // nuss gelöscht werden, um Speicherplatz für das Laden von tflite zu haben
+    {
+        delete ImageTMP;
+        ImageTMP = NULL;
+    }  
 
-    // Align mit Templates
     return true;
 }
 
+
+void ClassFlowAlignment::DrawRef(CImageBasis *_zw)
+{
+    _zw->drawRect(ref_x[0], ref_y[0], ref_dx[0], ref_dy[0], 255, 0, 0, 2);
+    _zw->drawRect(ref_x[1], ref_y[1], ref_dx[1], ref_dy[1], 255, 0, 0, 2);
+}
+

+ 12 - 1
code/components/jomjol_flowcontroll/ClassFlowAlignment.h

@@ -15,13 +15,24 @@ protected:
     bool initialmirror;
     string reffilename[2];
     int ref_x[2], ref_y[2];
+    int ref_dx[2], ref_dy[2];
     int anz_ref;
     int suchex, suchey;
     string namerawimage;
+    bool SaveAllFiles;
+    CAlignAndCutImage *AlignAndCutImage;
+
+    void SetInitialParameter(void);
 
 public:
-    ClassFlowAlignment();
+    CImageBasis *ImageBasis, *ImageTMP;
+    
     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);

+ 57 - 69
code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp

@@ -16,21 +16,30 @@ static const char* TAG = "flow_analog";
 
 bool debugdetailanalog = false;
 
-ClassFlowAnalog::ClassFlowAnalog() : ClassFlowImage(TAG)
+void ClassFlowAnalog::SetInitialParameter(void)
 {
     string cnnmodelfile = "";
     modelxsize = 1;
     modelysize = 1;
     ListFlowControll = NULL;
-}
+    previousElement = NULL;   
+    SaveAllFiles = false; 
+}   
 
 ClassFlowAnalog::ClassFlowAnalog(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
 {
-    string cnnmodelfile = "";
-    modelxsize = 1;
-    modelysize = 1;
-}
+    SetInitialParameter();
+    ListFlowControll = lfc;
+
+    for (int i = 0; i < ListFlowControll->size(); ++i)
+    {
+        if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0)
+        {
+            flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i];
+        }
+    }
 
+}
 
 
 string ClassFlowAnalog::getReadout()
@@ -113,8 +122,18 @@ bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph)
             neuroi->deltax = std::stoi(zerlegt[3]);
             neuroi->deltay = std::stoi(zerlegt[4]);
             neuroi->result = -1;
+            neuroi->image = NULL;
+            neuroi->image_org = NULL;
             ROI.push_back(neuroi);
         }
+
+        if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
+        {
+            if (toUpper(zerlegt[1]) == "TRUE")
+                SaveAllFiles = true;
+        }
+
+
     }
     return true;
 }
@@ -162,77 +181,42 @@ bool ClassFlowAnalog::doFlow(string time)
 
 bool ClassFlowAnalog::doAlignAndCut(string time)
 {
-    string input = "/sdcard/img_tmp/alg.jpg";
-    string input_roi = "/sdcard/img_tmp/alg_roi.jpg";
-    string ioresize = "/sdcard/img_tmp/resize.bmp";
-    string output;
-    string nm;
-    input = FormatFileName(input);
-    input_roi = FormatFileName(input_roi);   
-
-    CResizeImage *rs;
-    CImageBasis *img_roi = NULL;
-    CAlignAndCutImage *caic = new CAlignAndCutImage(input);
-
-    if (!caic->ImageOkay()){
-        if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut not okay!");
-        delete caic;
-        return false;
-    }
-
-    if (input_roi.length() > 0){
-        img_roi = new CImageBasis(input_roi);
-        if (!img_roi->ImageOkay()){
-            if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut ImageRoi not okay!");
-            delete caic;
-            delete img_roi;
-            return false;
-        }
-    }
+    CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage();    
 
     for (int i = 0; i < ROI.size(); ++i)
     {
         printf("Analog %d - Align&Cut\n", i);
-        output = "/sdcard/img_tmp/" + ROI[i]->name + ".jpg";
-        output = FormatFileName(output);
-        caic->CutAndSave(output, ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay);
-
-        rs = new CResizeImage(output);
-        if (!rs->ImageOkay()){
-            if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut CResizeImage(output);!");
-            delete caic;
-            delete rs;
-            return false;
-        }
 
-        rs->Resize(modelxsize, modelysize);
-        ioresize = "/sdcard/img_tmp/ra" + std::to_string(i) + ".bmp";
-        ioresize = FormatFileName(ioresize);
-        rs->SaveToFile(ioresize);
-        delete rs;
+        CResizeImage *rs = caic->CutAndSave(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay);
+        if (ROI[i]->image_org)
+            delete ROI[i]->image_org;
+        ROI[i]->image_org = new CImageBasis((CImageBasis*) rs);
 
-        if (img_roi)
-        {
-            int r = 0;
-            int g = 255;
-            int b = 0;
-            img_roi->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, r, g, b, 1);
-            img_roi->drawCircle((int) (ROI[i]->posx + ROI[i]->deltax/2), (int)  (ROI[i]->posy + ROI[i]->deltay/2), (int) (ROI[i]->deltax/2), r, g, b, 2);
-            img_roi->drawLine((int) (ROI[i]->posx + ROI[i]->deltax/2), (int) ROI[i]->posy, (int) (ROI[i]->posx + ROI[i]->deltax/2), (int) (ROI[i]->posy + ROI[i]->deltay), r, g, b, 2);
-            img_roi->drawLine((int) ROI[i]->posx, (int) (ROI[i]->posy + ROI[i]->deltay/2), (int) ROI[i]->posx + ROI[i]->deltax, (int) (ROI[i]->posy + ROI[i]->deltay/2), r, g, b, 2);
-        }
+        if (SaveAllFiles) rs->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".jpg"));
+
+        rs->Resize(modelxsize, modelysize);
+        if (SaveAllFiles) rs->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp"));
+        if (ROI[i]->image)
+            delete ROI[i]->image;
+        ROI[i]->image = rs;
     }
-    delete caic;
 
+    return true;
+} 
+
+void ClassFlowAnalog::DrawROI(CImageBasis *_zw)
+{
+    int r = 0;
+    int g = 255;
+    int b = 0;
 
-    if (img_roi)
+    for (int i = 0; i < ROI.size(); ++i)
     {
-        img_roi->SaveToFile(input_roi);
-        delete img_roi;
+        _zw->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, r, g, b, 1);
+        _zw->drawCircle((int) (ROI[i]->posx + ROI[i]->deltax/2), (int)  (ROI[i]->posy + ROI[i]->deltay/2), (int) (ROI[i]->deltax/2), r, g, b, 2);
+        _zw->drawLine((int) (ROI[i]->posx + ROI[i]->deltax/2), (int) ROI[i]->posy, (int) (ROI[i]->posx + ROI[i]->deltax/2), (int) (ROI[i]->posy + ROI[i]->deltay), r, g, b, 2);
+        _zw->drawLine((int) ROI[i]->posx, (int) (ROI[i]->posy + ROI[i]->deltay/2), (int) ROI[i]->posx + ROI[i]->deltax, (int) (ROI[i]->posy + ROI[i]->deltay/2), r, g, b, 2);
     }
-
-
-    return true;
 } 
 
 bool ClassFlowAnalog::doNeuralNetwork(string time)
@@ -265,7 +249,8 @@ bool ClassFlowAnalog::doNeuralNetwork(string time)
 
 #ifndef OHNETFLITE
 //        LogFile.WriteToFile("ClassFlowAnalog::doNeuralNetwork vor CNN tflite->LoadInputImage(ioresize)");
-        tflite->LoadInputImage(ioresize);
+//        tflite->LoadInputImage(ioresize);
+        tflite->LoadInputImageBasis(ROI[i]->image);        
         tflite->Invoke();
         if (debugdetailanalog) LogFile.WriteToFile("Nach Invoke");
 
@@ -278,9 +263,12 @@ bool ClassFlowAnalog::doNeuralNetwork(string time)
 //        printf("Result sin, cos, ziffer: %f, %f, %f\n", f1, f2, result);  
         ROI[i]->result = result * 10;
 
-        printf("Result Analog%i: %f\n", i, ROI[i]->result);           
+        printf("Result Analog%i: %f\n", i, ROI[i]->result); 
 
-        LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time); 
+        if (isLogImage)
+        {
+            LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time, ROI[i]->image_org);
+        }
     }
 #ifndef OHNETFLITE
         delete tflite;

+ 11 - 2
code/components/jomjol_flowcontroll/ClassFlowAnalog.h

@@ -1,10 +1,12 @@
 #pragma once
 #include "ClassFlowImage.h"
+#include "ClassFlowAlignment.h"
 // #include "CTfLiteClass.h"
 
 struct roianalog {
     int posx, posy, deltax, deltay;
     float result;
+    CImageBasis *image, *image_org;
     string name;
 };
 
@@ -17,14 +19,21 @@ protected:
     string cnnmodelfile;
     int modelxsize, modelysize;
     int ZeigerEval(float zahl, int ziffer_vorgaenger);
+    bool SaveAllFiles;    
+
+    ClassFlowAlignment* flowpostalignment;
+
+	void SetInitialParameter(void);        
 
 public:
-    ClassFlowAnalog();
     ClassFlowAnalog(std::vector<ClassFlow*>* lfc);
+
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool doFlow(string time);
     string getHTMLSingleStep(string host);
-    string getReadout();    
+    string getReadout();   
+
+    void DrawROI(CImageBasis *_zw); 
 
     bool doNeuralNetwork(string time); 
     bool doAlignAndCut(string time);

+ 110 - 2
code/components/jomjol_flowcontroll/ClassFlowControll.cpp

@@ -11,6 +11,9 @@
 
 static const char* TAG = "flow_controll";
 
+bool flowcontrolldebugdetail = true;
+
+
 std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _host){
     std::string _classname = "";
     std::string result = "";
@@ -68,6 +71,9 @@ void ClassFlowControll::SetInitialParameter(void)
     AutoStart = false;
     SetupModeActive = false;
     AutoIntervall = 10;
+    flowdigit = NULL;
+    flowanalog = NULL;
+    flowpostprocessing = NULL;
 }
 
 bool ClassFlowControll::isAutoStart(long &_intervall)
@@ -83,13 +89,25 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
     _type = trim(_type);
 
     if (toUpper(_type).compare("[MAKEIMAGE]") == 0)
+    {
         cfc = new ClassFlowMakeImage(&FlowControll);
+        flowmakeimage = (ClassFlowMakeImage*) cfc;
+    }
     if (toUpper(_type).compare("[ALIGNMENT]") == 0)
+    {
         cfc = new ClassFlowAlignment(&FlowControll);
+        flowalignment = (ClassFlowAlignment*) cfc;
+    }
     if (toUpper(_type).compare("[ANALOG]") == 0)
+    {
         cfc = new ClassFlowAnalog(&FlowControll);
+        flowanalog = (ClassFlowAnalog*) cfc;
+    }
     if (toUpper(_type).compare("[DIGITS]") == 0)
+    {
         cfc = new ClassFlowDigit(&FlowControll);
+        flowdigit = (ClassFlowDigit*) cfc;
+    }
     if (toUpper(_type).compare("[MQTT]") == 0)
         cfc = new ClassFlowMQTT(&FlowControll);
     if (toUpper(_type).compare("[POSTPROCESSING]") == 0)
@@ -139,6 +157,7 @@ void ClassFlowControll::InitFlow(std::string config)
         cfc = CreateClassFlow(line);
         if (cfc)
         {
+            printf("Start ReadParameter\n");
             cfc->ReadParameter(pFile, line);
         }
         else
@@ -158,9 +177,7 @@ std::string ClassFlowControll::getActStatus(){
 }
 
 void ClassFlowControll::doFlowMakeImageOnly(string time){
-    bool result = true;
     std::string zw_time;
-    int repeat = 0;
 
     for (int i = 0; i < FlowControll.size(); ++i)
     {
@@ -181,6 +198,25 @@ bool ClassFlowControll::doFlow(string time)
     std::string zw_time;
     int repeat = 0;
 
+
+/////////////////////////////////////////////////////
+    int aInternalFreeHeapSizeAtEnd, aInternalFreeHeapSizeAtStart;
+    aInternalFreeHeapSizeAtStart = getInternalESPHeapSize(); 
+
+    if (flowcontrolldebugdetail){
+        std::string aStartEspInfoStr = "ClassFlowAnalog::doFlow - Start: " + getESPHeapInfo();
+        LogFile.WriteToFile(aStartEspInfoStr);
+    }    
+
+    aInternalFreeHeapSizeAtEnd = getInternalESPHeapSize(); 
+    if (flowcontrolldebugdetail){
+        std::string aStartEspInfoStr = "ClassFlowAnalog::doFlow - Now : " + getESPHeapInfo();
+        LogFile.WriteToFile(aStartEspInfoStr);
+
+    }
+
+/////////////////////////////////////////////////////////
+
     for (int i = 0; i < FlowControll.size(); ++i)
     {
         zw_time = gettimestring("%Y%m%d-%H%M%S");
@@ -202,6 +238,14 @@ bool ClassFlowControll::doFlow(string time)
         {
             result = true;
         }
+
+        aInternalFreeHeapSizeAtEnd = getInternalESPHeapSize(); 
+        if (flowcontrolldebugdetail){
+            std::string aStartEspInfoStr = "ClassFlowAnalog::doFlow - Now : " + getESPHeapInfo();
+            LogFile.WriteToFile(aStartEspInfoStr);
+
+        }
+
     }
     zw_time = gettimestring("%Y%m%d-%H%M%S");    
     aktstatus = zw_time + ": Flow is done";
@@ -362,4 +406,68 @@ int ClassFlowControll::CleanTempFolder() {
     ESP_LOGI(TAG, "%d files deleted", deleted);
     
     return 0;
+}
+
+
+esp_err_t ClassFlowControll::SendRawJPG(httpd_req_t *req)
+{
+    return flowmakeimage->SendRawJPG(req);
+}
+
+
+ImageData* ClassFlowControll::GetJPGStream(std::string _fn)
+{
+    printf("ClassFlowControll::GetJPGStream %s\n", _fn.c_str());
+    ImageData* ret = NULL;
+
+    if (_fn == "alg.jpg")
+    {
+        return flowalignment->ImageBasis->writeToMemoryAsJPG();  
+    }
+
+    if (_fn == "alg_roi.jpg")
+    {
+        CImageBasis* _imgzw = new CImageBasis(flowalignment->ImageBasis);
+        flowalignment->DrawRef(_imgzw);
+        if (flowdigit) flowdigit->DrawROI(_imgzw);
+        if (flowanalog) flowanalog->DrawROI(_imgzw);
+        ret = _imgzw->writeToMemoryAsJPG();
+        delete _imgzw;
+        return ret;
+    }
+
+
+    std::vector<HTMLInfo*> htmlinfo;
+    htmlinfo = GetAllDigital();
+    for (int i = 0; i < htmlinfo.size(); ++i)
+    {
+        if (_fn == htmlinfo[i]->filename)
+        {
+            if (htmlinfo[i]->image)
+                return htmlinfo[i]->image->writeToMemoryAsJPG();
+        }
+        if (_fn == htmlinfo[i]->filename_org)
+        {
+            if (htmlinfo[i]->image_org)
+                return htmlinfo[i]->image_org->writeToMemoryAsJPG();        
+        }
+    }
+
+    htmlinfo = GetAllAnalog();
+    for (int i = 0; i < htmlinfo.size(); ++i)
+    {
+        if (_fn == htmlinfo[i]->filename)
+        {
+            if (htmlinfo[i]->image)
+                return htmlinfo[i]->image->writeToMemoryAsJPG();
+        }
+        if (_fn == htmlinfo[i]->filename_org)
+        {
+            if (htmlinfo[i]->image_org)
+                return htmlinfo[i]->image_org->writeToMemoryAsJPG();        
+        }
+    }
+
+    printf("Kein internes Bild gefunden - suche auf SD-Karte\n");
+    return NULL;
 }

+ 7 - 0
code/components/jomjol_flowcontroll/ClassFlowControll.h

@@ -17,6 +17,10 @@ class ClassFlowControll :
 protected:
 	std::vector<ClassFlow*> FlowControll;
 	ClassFlowPostProcessing* flowpostprocessing;
+	ClassFlowAlignment* flowalignment;	
+	ClassFlowAnalog* flowanalog;
+	ClassFlowDigit* flowdigit;
+	ClassFlowMakeImage* flowmakeimage;
 	ClassFlow* CreateClassFlow(std::string _type);
 
 	bool AutoStart;
@@ -35,6 +39,9 @@ public:
 	string GetPrevalue();	
 	bool ReadParameter(FILE* pfile, string& aktparamgraph);	
 
+	ImageData* GetJPGStream(std::string _fn);
+	esp_err_t SendRawJPG(httpd_req_t *req);
+
 	std::string doSingleStep(std::string _stepname, std::string _host);
 
 	bool isAutoStart(long &_intervall);

+ 73 - 67
code/components/jomjol_flowcontroll/ClassFlowDigit.cpp

@@ -1,5 +1,6 @@
 #include "ClassFlowDigit.h"
 
+
 //#include "CFindTemplate.h"
 //#include "CTfLiteClass.h"
 
@@ -15,19 +16,49 @@
 
 static const char* TAG = "flow_digital";
 
-ClassFlowDigit::ClassFlowDigit() : ClassFlowImage(TAG)
+
+void ClassFlowDigit::SetInitialParameter(void)
 {
     string cnnmodelfile = "";
     modelxsize = 1;
     modelysize = 1;
     ListFlowControll = NULL;
+    previousElement = NULL;    
+    SaveAllFiles = false;
+}    
+
+ClassFlowDigit::ClassFlowDigit() : ClassFlowImage(TAG)
+{
+    SetInitialParameter();
 }
 
 ClassFlowDigit::ClassFlowDigit(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
 {
-    string cnnmodelfile = "";
-    modelxsize = 1;
-    modelysize = 1;
+    SetInitialParameter();
+    ListFlowControll = lfc;
+
+    for (int i = 0; i < ListFlowControll->size(); ++i)
+    {
+        if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0)
+        {
+            flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i];
+        }
+    }
+}
+
+ClassFlowDigit::ClassFlowDigit(std::vector<ClassFlow*>* lfc, ClassFlow *_prev) : ClassFlowImage(lfc, _prev, TAG)
+{
+    SetInitialParameter();
+    ListFlowControll = lfc;
+    previousElement = _prev;
+
+    for (int i = 0; i < ListFlowControll->size(); ++i)
+    {
+        if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0)
+        {
+            flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i];
+        }
+    }    
 }
 
 string ClassFlowDigit::getReadout()
@@ -85,8 +116,17 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph)
             neuroi->deltax = std::stoi(zerlegt[3]);
             neuroi->deltay = std::stoi(zerlegt[4]);
             neuroi->resultklasse = -1;
+            neuroi->image = NULL;
+            neuroi->image_org = NULL;            
             ROI.push_back(neuroi);
         }
+
+        if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
+        {
+            if (toUpper(zerlegt[1]) == "TRUE")
+                SaveAllFiles = true;
+        }
+
     }
     return true;
 }
@@ -133,60 +173,24 @@ bool ClassFlowDigit::doFlow(string time)
 
 bool ClassFlowDigit::doAlignAndCut(string time)
 {
-    string input = "/sdcard/img_tmp/alg.jpg";
-    string input_roi = "/sdcard/img_tmp/alg_roi.jpg";
-    string ioresize = "/sdcard/img_tmp/resize.bmp";
-    string output;
-    string nm;
-    input = FormatFileName(input);
-    input_roi = FormatFileName(input_roi);   
-     
-    CResizeImage *rs;
-    CImageBasis *img_roi = NULL;
-    CAlignAndCutImage *caic = new CAlignAndCutImage(input);
-    if (!caic->ImageOkay()){
-        LogFile.WriteToFile("ClassFlowDigit::doAlignAndCut not okay!");
-        delete caic;
-        return false;
-    }
-
-    if (input_roi.length() > 0){
-        img_roi = new CImageBasis(input_roi);
-        if (!img_roi->ImageOkay()){
-            LogFile.WriteToFile("ClassFlowDigit::doAlignAndCut ImageRoi not okay!");
-            delete caic;
-            delete img_roi;
-            return false;
-        }
-    }
-
-
+    CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage();
 
     for (int i = 0; i < ROI.size(); ++i)
     {
         printf("DigitalDigit %d - Align&Cut\n", i);
-        output = "/sdcard/img_tmp/" + ROI[i]->name + ".jpg";
-        output = FormatFileName(output);
-        caic->CutAndSave(output, ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay);
+        CResizeImage *rs = caic->CutAndSave(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay);
 
-        rs = new CResizeImage(output);
-        rs->Resize(modelxsize, modelysize);
-        ioresize = "/sdcard/img_tmp/rd" + std::to_string(i) + ".bmp";
-        ioresize = FormatFileName(ioresize);
-        rs->SaveToFile(ioresize);
-        delete rs;
+        if (ROI[i]->image_org)
+            free(ROI[i]->image_org);
+        ROI[i]->image_org = new CImageBasis((CImageBasis*) rs);    
+        if (SaveAllFiles) rs->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".jpg"));
 
-        if (img_roi)
-        {
-            img_roi->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, 0, 0, 255, 2);
-        }
-    }
-    delete caic;
+        rs->Resize(modelxsize, modelysize);
+        if (SaveAllFiles) rs->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp"));
 
-    if (img_roi)
-    {
-        img_roi->SaveToFile(input_roi);
-        delete img_roi;
+        if (ROI[i]->image)
+            free(ROI[i]->image);
+        ROI[i]->image = rs;
     }
 
     return true;
@@ -196,17 +200,9 @@ bool ClassFlowDigit::doNeuralNetwork(string time)
 {
     string logPath = CreateLogFolder(time);
 
-    string input = "/sdcard/img_tmp/alg.jpg";
-    string ioresize = "/sdcard/img_tmp/resize.bmp";
-    string output;
-    string nm;
-    input = FormatFileName(input);
-
-
 #ifndef OHNETFLITE
     CTfLiteClass *tflite = new CTfLiteClass;  
-    string zwcnn = "/sdcard" + cnnmodelfile;
-    zwcnn = FormatFileName(zwcnn);
+    string zwcnn =  FormatFileName("/sdcard" + cnnmodelfile);
     printf(zwcnn.c_str());printf("\n");
     tflite->LoadModel(zwcnn); 
     tflite->MakeAllocate();
@@ -215,17 +211,18 @@ bool ClassFlowDigit::doNeuralNetwork(string time)
     for (int i = 0; i < ROI.size(); ++i)
     {
         printf("DigitalDigit %d - TfLite\n", i);
-        ioresize = "/sdcard/img_tmp/rd" + std::to_string(i) + ".bmp";
-        ioresize = FormatFileName(ioresize);
-//        printf("output: %s, ioresize: %s\n", output.c_str(), ioresize.c_str());
 
         ROI[i]->resultklasse = 0;
 #ifndef OHNETFLITE
-        ROI[i]->resultklasse = tflite->GetClassFromImage(ioresize);
+        ROI[i]->resultklasse = tflite->GetClassFromImageBasis(ROI[i]->image);
+
 #endif
         printf("Result Digit%i: %d\n", i, ROI[i]->resultklasse);
 
-        LogImage(logPath, ROI[i]->name, NULL, &ROI[i]->resultklasse, time);
+        if (isLogImage)
+        {
+            LogImage(logPath, ROI[i]->name, NULL, &ROI[i]->resultklasse, time, ROI[i]->image_org);
+        }
     }
 #ifndef OHNETFLITE
         delete tflite;
@@ -233,6 +230,11 @@ bool ClassFlowDigit::doNeuralNetwork(string time)
     return true;
 }
 
+void ClassFlowDigit::DrawROI(CImageBasis *_zw)
+{
+    for (int i = 0; i < ROI.size(); ++i)
+        _zw->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, 0, 0, 255, 2);
+}     
 
 std::vector<HTMLInfo*> ClassFlowDigit::GetHTMLInfo()
 {
@@ -241,10 +243,14 @@ std::vector<HTMLInfo*> ClassFlowDigit::GetHTMLInfo()
     for (int i = 0; i < ROI.size(); ++i)
     {
         HTMLInfo *zw = new HTMLInfo;
-        zw->filename = ROI[i]->name + ".jpg";
+        zw->filename = ROI[i]->name + ".bmp";
+        zw->filename_org = ROI[i]->name + ".jpg";
         zw->val = ROI[i]->resultklasse;
+        zw->image = ROI[i]->image;
+        zw->image_org = ROI[i]->image_org;
         result.push_back(zw);
     }
 
     return result;
-}
+}
+

+ 10 - 0
code/components/jomjol_flowcontroll/ClassFlowDigit.h

@@ -1,5 +1,6 @@
 #pragma once
 #include "ClassFlowImage.h"
+#include "ClassFlowAlignment.h"
 #include "Helper.h"
 
 #include <string>
@@ -8,6 +9,7 @@ struct roi {
     int posx, posy, deltax, deltay;
     int resultklasse;
     string name;
+    CImageBasis *image, *image_org;
     roi* next;
 };
 
@@ -18,19 +20,27 @@ protected:
     std::vector<roi*> ROI;
     string cnnmodelfile;
     int modelxsize, modelysize;
+    bool SaveAllFiles;
+
+    ClassFlowAlignment* flowpostalignment;
 
     bool doNeuralNetwork(string time); 
     bool doAlignAndCut(string time); 
 
+	void SetInitialParameter(void);    
+
 public:
     ClassFlowDigit();
     ClassFlowDigit(std::vector<ClassFlow*>* lfc);
+    ClassFlowDigit(std::vector<ClassFlow*>* lfc, ClassFlow *_prev);
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool doFlow(string time);
     string getHTMLSingleStep(string host); 
     string getReadout();
    	std::vector<HTMLInfo*> GetHTMLInfo();
 
+    void DrawROI(CImageBasis *_zw);        
+
     string name(){return "ClassFlowDigit";};
 };
 

+ 12 - 3
code/components/jomjol_flowcontroll/ClassFlowImage.cpp

@@ -5,6 +5,7 @@
 #include <dirent.h>
 #include "time_sntp.h"
 #include "ClassLogFile.h"
+#include "CFindTemplate.h"
 
 ClassFlowImage::ClassFlowImage(const char* logTag)
 {
@@ -12,12 +13,19 @@ ClassFlowImage::ClassFlowImage(const char* logTag)
 	isLogImage = false;
 }
 
-ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag) : ClassFlow((std::vector<ClassFlow*>*)lfc)
+ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag) : ClassFlow(lfc)
 {
 	this->logTag = logTag;
 	isLogImage = false;
 }
 
+ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, ClassFlow *_prev, const char* logTag) :  ClassFlow(lfc, _prev)
+{
+	this->logTag = logTag;
+	isLogImage = false;
+}
+
+
 string ClassFlowImage::CreateLogFolder(string time) {
 	if (!isLogImage)
 		return "";
@@ -32,7 +40,7 @@ string ClassFlowImage::CreateLogFolder(string time) {
 	return logPath;
 }
 
-void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time) {
+void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time, CImageBasis *_img) {
 	if (!isLogImage)
 		return;
 	
@@ -50,7 +58,8 @@ void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, i
 	string output = "/sdcard/img_tmp/" + name + ".jpg";
 	output = FormatFileName(output);
 	printf("save to file: %s\n", nm.c_str());
-	CopyFile(output, nm);
+	_img->SaveToFile(nm);
+//	CopyFile(output, nm);
 }
 
 void ClassFlowImage::RemoveOldLogs()

+ 4 - 2
code/components/jomjol_flowcontroll/ClassFlowImage.h

@@ -12,11 +12,13 @@ protected:
 	const char* logTag;
 
 	string CreateLogFolder(string time);
-	void LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time);
+	void LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time, CImageBasis *_img);
+
 
 public:
 	ClassFlowImage(const char* logTag);
 	ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag);
-
+	ClassFlowImage(std::vector<ClassFlow*> * lfc, ClassFlow *_prev, const char* logTag);
+	
 	void RemoveOldLogs();
 };

+ 26 - 11
code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp

@@ -6,7 +6,7 @@
 
 #include <time.h>
 
-ClassFlowMQTT::ClassFlowMQTT()
+void ClassFlowMQTT::SetInitialParameter(void)
 {
     uri = "";
     topic = "";
@@ -15,22 +15,21 @@ ClassFlowMQTT::ClassFlowMQTT()
     OldValue = "";
     flowpostprocessing = NULL;  
     user = "";
-    password = "";    
+    password = "";   
+    previousElement = NULL;
+    ListFlowControll = NULL;     
+}       
+
+ClassFlowMQTT::ClassFlowMQTT()
+{
+    SetInitialParameter();
 }
 
 ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc)
 {
-    uri = "";
-    topic = "";
-    topicError = "";
-    clientname = "watermeter";
-    OldValue = "";
-    flowpostprocessing = NULL;
-    user = "";
-    password = "";        
+    SetInitialParameter();
 
     ListFlowControll = lfc;
-
     for (int i = 0; i < ListFlowControll->size(); ++i)
     {
         if (((*ListFlowControll)[i])->name().compare("ClassFlowPostProcessing") == 0)
@@ -38,9 +37,25 @@ ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc)
             flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i];
         }
     }
+}
 
+ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc, ClassFlow *_prev)
+{
+    SetInitialParameter();
+
+    previousElement = _prev;
+    ListFlowControll = lfc;
+
+    for (int i = 0; i < ListFlowControll->size(); ++i)
+    {
+        if (((*ListFlowControll)[i])->name().compare("ClassFlowPostProcessing") == 0)
+        {
+            flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i];
+        }
+    }
 }
 
+
 bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
 {
     std::vector<string> zerlegt;

+ 3 - 1
code/components/jomjol_flowcontroll/ClassFlowMQTT.h

@@ -13,11 +13,13 @@ protected:
     std::string OldValue;
 	ClassFlowPostProcessing* flowpostprocessing;  
     std::string user, password;  
-
+	void SetInitialParameter(void);        
 
 public:
     ClassFlowMQTT();
     ClassFlowMQTT(std::vector<ClassFlow*>* lfc);
+    ClassFlowMQTT(std::vector<ClassFlow*>* lfc, ClassFlow *_prev);
+
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool doFlow(string time);
     string name(){return "ClassFlowMQTT";};

+ 54 - 24
code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp

@@ -16,30 +16,27 @@ esp_err_t ClassFlowMakeImage::camera_capture(){
 
 void ClassFlowMakeImage::takePictureWithFlash(int flashdauer)
 {
-    string nm = namerawimage;
-    if (isImageSize && (ImageQuality > 0))
-        Camera.SetQualitySize(ImageQuality, ImageSize);
-    printf("Start CaptureFile\n");
-    Camera.CaptureToFile(nm, flashdauer);
+    Camera.CaptureToBasisImage(rawImage, flashdauer);
+    if (SaveAllFiles) rawImage->SaveToFile(namerawimage);
 }
 
-
-ClassFlowMakeImage::ClassFlowMakeImage() : ClassFlowImage(TAG)
+void ClassFlowMakeImage::SetInitialParameter(void)
 {
     waitbeforepicture = 5;
     isImageSize = false;
     ImageQuality = -1;    
     TimeImageTaken = 0;
+    ImageQuality = 5;
+    rawImage = NULL;
+    ImageSize = FRAMESIZE_VGA;
+    SaveAllFiles = false;
     namerawimage =  "/sdcard/img_tmp/raw.jpg";
-}
+}     
+
 
 ClassFlowMakeImage::ClassFlowMakeImage(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
 {
-    waitbeforepicture = 5;
-    isImageSize = false;
-    ImageQuality = -1;
-    TimeImageTaken = 0;
-    namerawimage =  "/sdcard/img_tmp/raw.jpg";
+    SetInitialParameter();
 }
 
 bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
@@ -64,14 +61,28 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
             isLogImage = true;
         }
         if ((zerlegt[0] == "ImageQuality") && (zerlegt.size() > 1))
-            this->ImageQuality = std::stod(zerlegt[1]);
+            ImageQuality = std::stod(zerlegt[1]);
+
         if ((zerlegt[0] == "ImageSize") && (zerlegt.size() > 1))
         {
             ImageSize = Camera.TextToFramesize(zerlegt[1].c_str());
             isImageSize = true;
         }
+
+        if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
+        {
+            if (toUpper(zerlegt[1]) == "TRUE")
+                SaveAllFiles = true;
+        }
+
     }
-   
+
+    Camera.SetQualitySize(ImageQuality, ImageSize);
+    image_width = Camera.image_width;
+    image_height = Camera.image_height;
+    rawImage = new CImageBasis();
+    rawImage->CreateEmptyImage(image_width, image_height, 3);
+
     return true;
 }
 
@@ -84,27 +95,46 @@ string ClassFlowMakeImage::getHTMLSingleStep(string host)
 
 bool ClassFlowMakeImage::doFlow(string zwtime)
 {
-    ////////////////////////////////////////////////////////////////////
-    // TakeImage and Store into /image_tmp/raw.jpg  TO BE DONE
-    ////////////////////////////////////////////////////////////////////
-
     string logPath = CreateLogFolder(zwtime);
 
     int flashdauer = (int) waitbeforepicture * 1000;
-    
-
+ 
     takePictureWithFlash(flashdauer);
-    time(&TimeImageTaken);
-    localtime(&TimeImageTaken);
 
-    LogImage(logPath, "raw", NULL, NULL, zwtime);
+//    time(&TimeImageTaken);
+//    localtime(&TimeImageTaken);
 
+    LogImage(logPath, "raw", NULL, NULL, zwtime, rawImage);
     RemoveOldLogs();
 
     return true;
 }
 
+esp_err_t ClassFlowMakeImage::SendRawJPG(httpd_req_t *req)
+{
+    int flashdauer = (int) waitbeforepicture * 1000;
+    return Camera.CaptureToHTTP(req, flashdauer);
+}
+
+
+ImageData* ClassFlowMakeImage::SendRawImage()
+{
+    CImageBasis *zw = new CImageBasis(rawImage);
+    ImageData *id;
+    int flashdauer = (int) waitbeforepicture * 1000;
+    Camera.CaptureToBasisImage(zw, flashdauer);
+    id = zw->writeToMemoryAsJPG();    
+    delete zw;
+    return id;  
+}
+
 time_t ClassFlowMakeImage::getTimeImageTaken()
 {
     return TimeImageTaken;
 }
+
+ClassFlowMakeImage::~ClassFlowMakeImage(void)
+{
+    delete rawImage;
+}
+

+ 14 - 2
code/components/jomjol_flowcontroll/ClassFlowMakeImage.h

@@ -20,19 +20,31 @@ protected:
     int ImageQuality;
     time_t TimeImageTaken;
     string namerawimage;
+    int image_height, image_width;
+    bool SaveAllFiles;
+
 
     void CopyFile(string input, string output);
 
     esp_err_t camera_capture();
-    void takePictureWithFlash(int flashdauer);   
+    void takePictureWithFlash(int flashdauer);
+
+    void SetInitialParameter(void);       
 
 public:
-    ClassFlowMakeImage();
+    CImageBasis *rawImage;
+
     ClassFlowMakeImage(std::vector<ClassFlow*>* lfc);
+
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool doFlow(string time);
     string getHTMLSingleStep(string host);
     time_t getTimeImageTaken();
     string name(){return "ClassFlowMakeImage";};
+
+    ImageData* SendRawImage();
+    esp_err_t SendRawJPG(httpd_req_t *req);
+
+    ~ClassFlowMakeImage(void);
 };
 

+ 58 - 0
code/components/jomjol_helper/Helper.cpp

@@ -18,6 +18,64 @@
 
 using namespace std;
 
+/////////////////////////////////////////////////////////////////////////////////////////////
+string getESPHeapInfo(){
+	string espInfoResultStr = "";
+	char aMsgBuf[80];
+    
+	multi_heap_info_t aMultiHead_info ;
+	heap_caps_get_info (&aMultiHead_info,MALLOC_CAP_8BIT);
+	size_t aFreeHeapSize  = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+	size_t aMinFreeHeadSize =  heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
+	size_t aMinFreeHeapSize =  heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
+	size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
+	sprintf(aMsgBuf," Free Heap Size: %ld", (long) aFreeHeapSize);
+	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 aMinFreeInternalHeapSize =  heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
+
+	sprintf(aMsgBuf," Heap: %ld", (long) aFreeHeapSize);
+	espInfoResultStr += string(aMsgBuf);
+	sprintf(aMsgBuf," Min Free: %ld", (long) aMinFreeHeapSize);
+	espInfoResultStr += string(aMsgBuf);
+	sprintf(aMsgBuf," larg. Block:  %ld", (long) aHeapLargestFreeBlockSize);
+	espInfoResultStr += string(aMsgBuf);
+	sprintf(aMsgBuf," SPI Heap: %ld", (long) aFreeSPIHeapSize);
+	espInfoResultStr += string(aMsgBuf);
+	sprintf(aMsgBuf," Min Free Heap Size: %ld", (long) aMinFreeHeadSize);
+	sprintf(aMsgBuf," NOT_SPI Heap: %ld", (long) (aFreeHeapSize - aFreeSPIHeapSize));
+	espInfoResultStr += string(aMsgBuf);
+	sprintf(aMsgBuf," largest Block Size:  %ld", (long) aHeapLargestFreeBlockSize);
+	sprintf(aMsgBuf," Internal Heap: %ld", (long) (aFreeInternalHeapSize));
+	espInfoResultStr += string(aMsgBuf);
+	sprintf(aMsgBuf," Internal Min Heap free: %ld", (long) (aMinFreeInternalHeapSize));
+	espInfoResultStr += string(aMsgBuf);
+	return 	espInfoResultStr;
+}
+
+
+size_t getESPHeapSize(){
+   size_t aFreeHeapSize  = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+   return aFreeHeapSize;
+}
+
+size_t getInternalESPHeapSize() {
+	size_t aFreeInternalHeapSize  = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
+	return aFreeInternalHeapSize;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+void memCopyGen(uint8_t* _source, uint8_t* _target, int _size)
+{
+    for (int i = 0; i < _size; ++i)
+        *(_target + i) = *(_source + i);
+}
+
+
 
 FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec)
 {

+ 10 - 1
code/components/jomjol_helper/Helper.h

@@ -10,7 +10,7 @@ void FindReplace(std::string& line, std::string& oldString, std::string& newStri
 
 void CopyFile(string input, string output);
 
-FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec = 10);
+FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec = 1);
 
 size_t findDelimiterPos(string input, string delimiter);
 //string trim(string istring);
@@ -27,3 +27,12 @@ string toUpper(string in);
 float temperatureRead();
 
 time_t addDays(time_t startTime, int days);
+
+void memCopyGen(uint8_t* _source, uint8_t* _target, int _size);
+
+///////////////////////////
+size_t getInternalESPHeapSize();
+size_t getESPHeapSize();
+string getESPHeapInfo();
+
+/////////////////////////////

+ 305 - 111
code/components/jomjol_image_proc/CFindTemplate.cpp

@@ -14,60 +14,114 @@ using namespace std;
 
 #define GET_MEMORY malloc
 
-/*
-CResizeImage::CResizeImage(std::string _image, int _new_dx, int _new_dy)
+void writejpghelp(void *context, void *data, int size)
 {
-    CImageBasis::CImageBasis(_image);
+//    printf("Size all: %d, size %d\n", ((ImageData*)context)->size, size);
+    ImageData* _zw = (ImageData*) context;
+    uint8_t *voidstart = _zw->data;
+    uint8_t *datastart = (uint8_t*) data;
+    voidstart += _zw->size;
+
+    for (int i = 0; i < size; ++i)
+        *(voidstart + i) = *(datastart + i);
+
+    _zw->size += size;
+}
+
+
+ImageData* CImageBasis::writeToMemoryAsJPG(const int quality)
+{
+    ImageData* ii = new ImageData;
+
+    auto rv2 = stbi_write_jpg_to_func(writejpghelp, ii, width, height, channels, rgb_image, quality);
+
+    return ii;
+}
+
+bool CImageBasis::CopyFromMemory(uint8_t* _source, int _size)
+{
+    int gr = height * width * channels;
+    if (gr != _size)            // Größe passt nicht
+    {
+        printf("Kann Bild nicht von Speicher kopierte - Größen passen nicht zusammen: soll %d, ist %d\n", _size, gr);
+        return false;
+    }
+    memCopy(_source, rgb_image, _size);
+
+    return true;
 }
-*/
 
 uint8_t CImageBasis::GetPixelColor(int x, int y, int ch)
 {
     stbi_uc* p_source;
-    p_source = this->rgb_image + (this->channels * (y * this->width + x));
+    p_source = rgb_image + (channels * (y * width + x));
     return p_source[ch];
 }
 
 void CResizeImage::Resize(int _new_dx, int _new_dy)
 {
-    int memsize = _new_dx * _new_dy * this->channels;
+    int memsize = _new_dx * _new_dy * channels;
     uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
 
-    stbir_resize_uint8(this->rgb_image, this->width, this->height, 0, odata, _new_dx, _new_dy, 0, this->channels);
+    stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels);
 
-    stbi_image_free(this->rgb_image);
-    this->rgb_image = (unsigned char*)GET_MEMORY(memsize);
+    stbi_image_free(rgb_image);
+    rgb_image = (unsigned char*)GET_MEMORY(memsize);
 
-    this->memCopy(odata, this->rgb_image, memsize);
-    this->width = _new_dx;
-    this->height = _new_dy;
+    memCopy(odata, rgb_image, memsize);
+    width = _new_dx;
+    height = _new_dy;
     stbi_image_free(odata);
 }
 
+
+CRotate::CRotate(CImageBasis *_org, CImageBasis *_temp)
+{
+    rgb_image = _org->rgb_image;
+    channels = _org->channels;
+    width = _org->width;
+    height = _org->height;
+    bpp = _org->bpp;
+    externalImage = true;   
+    ImageTMP = _temp;    
+}
+
 void CRotate::Mirror(){
-    int memsize = this->width * this->height * this->channels;
-    uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
+    int memsize = width * height * channels;
+    uint8_t* odata;
+    if (ImageTMP)
+    {
+        odata = ImageTMP->rgb_image;
+    }
+    else
+    {
+        odata = (unsigned char*)GET_MEMORY(memsize);
+    }
+
 
     int x_source, y_source;
     stbi_uc* p_target;
     stbi_uc* p_source;
 
-    for (int x = 0; x < this->width; ++x)
-        for (int y = 0; y < this->height; ++y)
+    for (int x = 0; x < width; ++x)
+        for (int y = 0; y < height; ++y)
         {
-            p_target = odata + (this->channels * (y * this->width + x));
+            p_target = odata + (channels * (y * width + x));
 
-            x_source = this->width - x;
+            x_source = width - x;
             y_source = y;
 
-            p_source = this->rgb_image + (this->channels * (y_source * this->width + x_source));
-            for (int channels = 0; channels < this->channels; ++channels)
-                p_target[channels] = p_source[channels];
+            p_source = rgb_image + (channels * (y_source * width + x_source));
+            for (int _channels = 0; _channels < channels; ++_channels)
+                p_target[_channels] = p_source[_channels];
         }
 
-    //    memcpy(this->rgb_image, odata, memsize);
-    this->memCopy(odata, this->rgb_image, memsize);
-    stbi_image_free(odata);
+    //    memcpy(rgb_image, odata, memsize);
+    memCopy(odata, rgb_image, memsize);
+    if (!ImageTMP)
+    {
+        stbi_image_free(odata);
+    }
 }
 
 void CRotate::Rotate(float _angle, int _centerx, int _centery)
@@ -86,17 +140,26 @@ void CRotate::Rotate(float _angle, int _centerx, int _centery)
     m[1][1] = m[0][0];
     m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
 
-    int memsize = this->width * this->height * this->channels;
-    uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
+    int memsize = width * height * channels;
+    uint8_t* odata;
+    if (ImageTMP)
+    {
+        odata = ImageTMP->rgb_image;
+    }
+    else
+    {
+        odata = (unsigned char*)GET_MEMORY(memsize);
+    }
+    
 
     int x_source, y_source;
     stbi_uc* p_target;
     stbi_uc* p_source;
 
-    for (int x = 0; x < this->width; ++x)
-        for (int y = 0; y < this->height; ++y)
+    for (int x = 0; x < width; ++x)
+        for (int y = 0; y < height; ++y)
         {
-            p_target = odata + (this->channels * (y * this->width + x));
+            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);
@@ -104,94 +167,112 @@ void CRotate::Rotate(float _angle, int _centerx, int _centery)
             x_source += int(m[0][2]);
             y_source += int(m[1][2]);
 
-            if ((x_source >= 0) && (x_source < this->width) && (y_source >= 0) && (y_source < this->height))
+            if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height))
             {
-                p_source = this->rgb_image + (this->channels * (y_source * this->width + x_source));
-                for (int channels = 0; channels < this->channels; ++channels)
-                    p_target[channels] = p_source[channels];
+                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 < this->channels; ++channels)
-                    p_target[channels] = 255;
+                for (int _channels = 0; _channels < channels; ++_channels)
+                    p_target[_channels] = 255;
             }
         }
 
-    //    memcpy(this->rgb_image, odata, memsize);
-    this->memCopy(odata, this->rgb_image, memsize);
-    stbi_image_free(odata);
+    //    memcpy(rgb_image, odata, memsize);
+    memCopy(odata, rgb_image, memsize);
+
+    if (!ImageTMP)
+    {
+        stbi_image_free(odata);
+    }
 }
 
 void CRotate::Rotate(float _angle)
 {
-    this->Rotate(_angle, this->width / 2, this->height / 2);
+//    printf("width %d, height %d\n", width, height);
+    Rotate(_angle, width / 2, height / 2);
 }
 
 void CRotate::Translate(int _dx, int _dy)
 {
-    int memsize = this->width * this->height * this->channels;
-    uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
+    int memsize = width * height * channels;
+    uint8_t* odata;
+    if (ImageTMP)
+    {
+        odata = ImageTMP->rgb_image;
+    }
+    else
+    {
+        odata = (unsigned char*)GET_MEMORY(memsize);
+    }
+
 
 
     int x_source, y_source;
     stbi_uc* p_target;
     stbi_uc* p_source;
 
-    for (int x = 0; x < this->width; ++x)
-        for (int y = 0; y < this->height; ++y)
+    for (int x = 0; x < width; ++x)
+        for (int y = 0; y < height; ++y)
         {
-            p_target = odata + (this->channels * (y * this->width + x));
+            p_target = odata + (channels * (y * width + x));
 
             x_source = x - _dx;
             y_source = y - _dy;
 
-            if ((x_source >= 0) && (x_source < this->width) && (y_source >= 0) && (y_source < this->height))
+            if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height))
             {
-                p_source = this->rgb_image + (this->channels * (y_source * this->width + x_source));
-                for (int channels = 0; channels < this->channels; ++channels)
-                    p_target[channels] = p_source[channels];
+                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 < this->channels; ++channels)
-                    p_target[channels] = 255;
+                for (int _channels = 0; _channels < channels; ++_channels)
+                    p_target[_channels] = 255;
             }
         }
 
-    //    memcpy(this->rgb_image, odata, memsize);
-    this->memCopy(odata, this->rgb_image, memsize);
-    stbi_image_free(odata);
+    //    memcpy(rgb_image, odata, memsize);
+    memCopy(odata, rgb_image, memsize);
+    if (!ImageTMP)
+    {
+        stbi_image_free(odata);
+    }
 }
 
 
-
+/*
 CFindTemplate::CFindTemplate(std::string _image)
 {
-    this->channels = 1;
-    this->rgb_image = stbi_load(_image.c_str(), &(this->width), &(this->height), &(this->bpp), this->channels);
+    channels = 1;
+    rgb_image = stbi_load(_image.c_str(), &(width), &(height), &(bpp), channels);
 }
+*/
 
 void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y)
 {
-    this->FindTemplate(_template, found_x, found_y, 0, 0);
+    FindTemplate(_template, found_x, found_y, 0, 0);
 }
 
 void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy)
 {
-    uint8_t* rgb_template = stbi_load(_template.c_str(), &tpl_width, &tpl_height, &tpl_bpp, this->channels);
+    uint8_t* rgb_template = stbi_load(_template.c_str(), &tpl_width, &tpl_height, &tpl_bpp, channels);
 
     int ow, ow_start, ow_stop;
     int oh, oh_start, oh_stop;
 
     if (_dx == 0)
     {
-        _dx = this->width;
+        _dx = width;
         *found_x = 0;
     }
 
     if (_dy == 0)
     {
-        _dy = this->height;
+        _dy = height;
         *found_y = 0;
     }
 
@@ -199,18 +280,18 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found
     ow_start = *found_x - _dx;
     ow_start = std::max(ow_start, 0);
     ow_stop = *found_x + _dx;
-    if ((ow_stop + tpl_width) > this->width)
-        ow_stop = this->width - tpl_width;
+    if ((ow_stop + tpl_width) > width)
+        ow_stop = width - tpl_width;
     ow = ow_stop - ow_start + 1;
 
     oh_start = *found_y - _dy;
     oh_start = std::max(oh_start, 0);
     oh_stop = *found_y + _dy;
-    if ((oh_stop + tpl_height) > this->height)
-        oh_stop = this->height - tpl_height;
+    if ((oh_stop + tpl_height) > height)
+        oh_stop = height - tpl_height;
     oh = oh_stop - oh_start + 1;
 
-    uint8_t* odata = (unsigned char*)GET_MEMORY(ow * oh * this->channels);
+    uint8_t* odata = (unsigned char*)GET_MEMORY(ow * oh * channels);
 
     double aktSAD;
     double minSAD = pow(tpl_width * tpl_height * 255, 2);
@@ -222,11 +303,11 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found
             for (int tpl_x = 0; tpl_x < tpl_width; tpl_x++)
                 for (int tpl_y = 0; tpl_y < tpl_height; tpl_y++)
                 {
-                    stbi_uc* p_org = this->rgb_image + (this->channels * ((youter + tpl_y) * this->width + (xouter + tpl_x)));
-                    stbi_uc* p_tpl = rgb_template + (this->channels * (tpl_y * tpl_width + tpl_x));
+                    stbi_uc* p_org = rgb_image + (channels * ((youter + tpl_y) * width + (xouter + tpl_x)));
+                    stbi_uc* p_tpl = rgb_template + (channels * (tpl_y * tpl_width + tpl_x));
                     aktSAD += pow(p_tpl[0] - p_org[0], 2);
                 }
-            stbi_uc* p_out = odata + (this->channels * ((youter - oh_start) * ow + (xouter - ow_start)));
+            stbi_uc* p_out = odata + (channels * ((youter - oh_start) * ow + (xouter - ow_start)));
 
             p_out[0] = int(sqrt(aktSAD / (tpl_width * tpl_height)));
             if (aktSAD < minSAD)
@@ -237,7 +318,7 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found
             }
         }
 
-    stbi_write_bmp("sdcard\\find.bmp", ow, oh, this->channels, odata);
+    stbi_write_bmp("sdcard\\find.bmp", ow, oh, channels, odata);
 
     stbi_image_free(odata);
     stbi_image_free(rgb_template);
@@ -245,14 +326,14 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found
 
 void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, std::string _imageout)
 {
-    this->FindTemplate(_template, found_x, found_y);
-    this->SaveToFile(_imageout);
+    FindTemplate(_template, found_x, found_y);
+    SaveToFile(_imageout);
 }
 
 void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy, std::string _imageout)
 {
-    this->FindTemplate(_template, found_x, found_y, _dx, _dy);
-    this->SaveToFile(_imageout);
+    FindTemplate(_template, found_x, found_y, _dx, _dy);
+    SaveToFile(_imageout);
 }
 
 
@@ -269,10 +350,10 @@ void CImageBasis::memCopy(uint8_t* _source, uint8_t* _target, int _size)
 
 bool CImageBasis::isInImage(int x, int y)
 {
-    if ((x < 0) || (x > this->width - 1))
+    if ((x < 0) || (x > width - 1))
         return false;
 
-    if ((y < 0) || (y > this->height- 1))
+    if ((y < 0) || (y > height- 1))
         return false;
 
     return true;
@@ -282,9 +363,9 @@ void CImageBasis::setPixelColor(int x, int y, int r, int g, int b)
 {
     stbi_uc* p_source;
 
-    p_source = this->rgb_image + (this->channels * (y * this->width + x));
+    p_source = rgb_image + (channels * (y * width + x));
     p_source[0] = r;
-    if (this-> channels > 2)
+    if ( channels > 2)
     {
         p_source[1] = g;
         p_source[2] = b;
@@ -383,7 +464,61 @@ void CImageBasis::drawCircle(int x1, int y1, int rad, int r, int g, int b, int t
 
 CImageBasis::CImageBasis()
 {
-    this->externalImage = false;
+    externalImage = false;
+}
+
+void CImageBasis::CreateEmptyImage(int _width, int _height, int _channels)
+{
+    bpp = _channels;
+    width = _width;
+    height = _height;
+    channels = _channels;
+
+    int memsize = width * height * channels;
+    rgb_image = (unsigned char*)GET_MEMORY(memsize);
+
+
+    stbi_uc* p_source;    
+
+    for (int x = 0; x < width; ++x)
+        for (int y = 0; y < height; ++y)
+        {
+            p_source = rgb_image + (channels * (y * width + x));
+            for (int _channels = 0; _channels < channels; ++_channels)
+                p_source[_channels] = (uint8_t) 0;
+        }
+
+
+}
+
+void CImageBasis::LoadFromMemory(stbi_uc *_buffer, int len)
+{
+//    if (rgb_image)
+//        free(rgb_image);
+    rgb_image = stbi_load_from_memory(_buffer, len, &width, &height, &channels, 3);
+    bpp = channels;
+//        STBIDEF stbi_uc *stbi_load_from_memory   (stbi_uc           const *buffer, int len   , int *x, int *y, int *channels_in_file, int desired_channels);
+
+}
+
+CImageBasis::CImageBasis(CImageBasis *_copyfrom)
+{
+    externalImage = false;
+    channels = _copyfrom->channels;
+    width = _copyfrom->width;
+    height = _copyfrom->height;
+    bpp = _copyfrom->bpp;
+
+    int memsize = width * height * channels;
+    rgb_image = (unsigned char*)GET_MEMORY(memsize);
+    if (!rgb_image)
+    {
+        printf(getESPHeapInfo().c_str());
+        printf("\nKein freier Speicher mehr!!!! Benötigt: %d %d %d %d\n", width, height, channels, memsize);
+        return;
+    }
+
+    memCopy(_copyfrom->rgb_image, rgb_image, memsize);
 }
 
 CImageBasis::CImageBasis(std::string _image)
@@ -391,13 +526,19 @@ CImageBasis::CImageBasis(std::string _image)
     channels = 3;
     externalImage = false;
     filename = _image;
-//    long freebefore = esp_get_free_heap_size();
+    long zwld = esp_get_free_heap_size();
+    printf("freeheapsize before: %ld\n", zwld);
 
     rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels);
-//    if (rgb_image == NULL)
-//        LogFile.WriteToFile("Image Load failed:" + _image + " FreeHeapSize before: " + to_string(freebefore) + " after: " + to_string(esp_get_free_heap_size()));
-    //    printf("CImageBasis after load\n");
-    //    printf("w %d, h %d, b %d, c %d", this->width, this->height, this->bpp, this->channels);
+    zwld = esp_get_free_heap_size();
+    printf("freeheapsize after : %ld\n", zwld);
+
+    std::string zw = "Image Load failed:" + _image + "\n";
+    if (rgb_image == NULL)
+        printf(zw.c_str());
+    zw = "CImageBasis after load " + _image + "\n";
+    printf(zw.c_str());
+    printf("w %d, h %d, b %d, c %d\n", width, height, bpp, channels);
 }
 
 bool CImageBasis::ImageOkay(){
@@ -406,12 +547,12 @@ bool CImageBasis::ImageOkay(){
 
 CImageBasis::CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp)
 {
-    this->rgb_image = _rgb_image;
-    this->channels = _channels;
-    this->width = _width;
-    this->height = _height;
-    this->bpp = _bpp;
-    this->externalImage = true;
+    rgb_image = _rgb_image;
+    channels = _channels;
+    width = _width;
+    height = _height;
+    bpp = _bpp;
+    externalImage = true;
 }
 
 void CImageBasis::Contrast(float _contrast)  //input range [-100..100]
@@ -424,16 +565,16 @@ void CImageBasis::Contrast(float _contrast)  //input range [-100..100]
     for (int x = 0; x < width; ++x)
         for (int y = 0; y < height; ++y)
         {
-            p_source = this->rgb_image + (this->channels * (y * this->width + x));
-            for (int channels = 0; channels < this->channels; ++channels)
-                p_source[channels] = (uint8_t) std::min(255, std::max(0, (int) (p_source[channels] * contrast + intercept)));
+            p_source = rgb_image + (channels * (y * width + x));
+            for (int _channels = 0; _channels < channels; ++_channels)
+                p_source[_channels] = (uint8_t) std::min(255, std::max(0, (int) (p_source[_channels] * contrast + intercept)));
         }
 }
 
 CImageBasis::~CImageBasis()
 {
-    if (!this->externalImage)
-        stbi_image_free(this->rgb_image);
+    if (!externalImage)
+        stbi_image_free(rgb_image);
 }
 
 void CImageBasis::SaveToFile(std::string _imageout)
@@ -442,25 +583,44 @@ void CImageBasis::SaveToFile(std::string _imageout)
 
     if ((typ == "jpg") || (typ == "JPG"))       // ACHTUNG PROBLEMATISCH IM ESP32
     {
-        stbi_write_jpg(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image, 0);
+        stbi_write_jpg(_imageout.c_str(), width, height, channels, rgb_image, 0);
     }
 
     if ((typ == "bmp") || (typ == "BMP"))
     {
-        stbi_write_bmp(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image);
+        stbi_write_bmp(_imageout.c_str(), width, height, channels, rgb_image);
     }
-    //    stbi_write_jpg(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image, 0);
-    //      stbi_write_bmp(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image);
 }
 
 
 
+CAlignAndCutImage::CAlignAndCutImage(CImageBasis *_org, CImageBasis *_temp)
+{
+    rgb_image = _org->rgb_image;
+    channels = _org->channels;
+    width = _org->width;
+    height = _org->height;
+    bpp = _org->bpp;
+    externalImage = true;    
+
+    ImageTMP = _temp;
+}
+
+void CAlignAndCutImage::GetRefSize(int *ref_dx, int *ref_dy)
+{
+    ref_dx[0] = t0_dx;
+    ref_dy[0] = t0_dy;
+    ref_dx[1] = t1_dx;
+    ref_dy[1] = t1_dy;
+}
+
 void CAlignAndCutImage::Align(std::string _template0, int ref0_x, int ref0_y, std::string _template1, int ref1_x, int ref1_y, int deltax, int deltay, std::string imageROI)
 {
     int dx, dy;
     int r0_x, r0_y, r1_x, r1_y;
 
-    CFindTemplate* ft = new CFindTemplate(this->filename);
+//    CFindTemplate* ft = new CFindTemplate(filename);
+    CFindTemplate* ft = new CFindTemplate(rgb_image, channels, width, height, bpp);
 
     r0_x = ref0_x;
     r0_y = ref0_y;
@@ -495,7 +655,7 @@ void CAlignAndCutImage::Align(std::string _template0, int ref0_x, int ref0_y, st
 
     if (imageROI.length() > 0)
     {
-        CImageBasis* imgzw = new CImageBasis(this->filename);
+        CImageBasis* imgzw = new CImageBasis(this);
         imgzw->drawRect(r0_x, r0_y, t0_dx, t0_dy, 255, 0, 0, 2);
         imgzw->drawRect(r1_x, r1_y, t1_dx, t1_dy, 255, 0, 0, 2);
         imgzw->SaveToFile(imageROI);
@@ -504,14 +664,16 @@ void CAlignAndCutImage::Align(std::string _template0, int ref0_x, int ref0_y, st
     }
 
     string zw = "\tdx:\t" + to_string(dx) + "\tdy:\t" + to_string(dy) + "\td_winkel:\t" + to_string(d_winkel);
-    LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
+//    LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
 
-    CRotate rt(this->rgb_image, this->channels, this->width, this->height, this->bpp);
+    CRotate rt(this, ImageTMP);
     rt.Translate(dx, dy);
     rt.Rotate(d_winkel, ref0_x, ref0_y);
     printf("Alignment: dx %d - dy %d - rot %f\n", dx, dy, d_winkel);
 }
 
+
+
 void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int dx, int dy)
 {
 
@@ -519,13 +681,13 @@ void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int d
 
     x2 = x1 + dx;
     y2 = y1 + dy;
-    x2 = min(x2, this->width - 1);
-    y2 = min(y2, this->height - 1);
+    x2 = min(x2, width - 1);
+    y2 = min(y2, height - 1);
 
     dx = x2 - x1;
     dy = y2 - y1;
 
-    int memsize = dx * dy * this->channels;
+    int memsize = dx * dy * channels;
     uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
 
     stbi_uc* p_target;
@@ -534,14 +696,46 @@ void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int d
     for (int x = x1; x < x2; ++x)
         for (int y = y1; y < y2; ++y)
         {
-            p_target = odata + (this->channels * ((y - y1) * dx + (x - x1)));
-            p_source = this->rgb_image + (this->channels * (y * this->width + x));
-            for (int channels = 0; channels < this->channels; ++channels)
-                p_target[channels] = p_source[channels];
+            p_target = odata + (channels * ((y - y1) * dx + (x - x1)));
+            p_source = rgb_image + (channels * (y * width + x));
+            for (int _channels = 0; _channels < channels; ++_channels)
+                p_target[_channels] = p_source[_channels];
         }
 
-    //    stbi_write_jpg(_template1.c_str(), dx, dy, this->channels, odata, 0);
-    stbi_write_bmp(_template1.c_str(), dx, dy, this->channels, odata);
+    //    stbi_write_jpg(_template1.c_str(), dx, dy, channels, odata, 0);
+    stbi_write_bmp(_template1.c_str(), dx, dy, channels, odata);
 
     stbi_image_free(odata);
 }
+
+CResizeImage* CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy)
+{
+    int x2, y2;
+
+    x2 = x1 + dx;
+    y2 = y1 + dy;
+    x2 = min(x2, width - 1);
+    y2 = min(y2, height - 1);
+
+    dx = x2 - x1;
+    dy = y2 - y1;
+
+    int memsize = dx * dy * channels;
+    uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
+
+    stbi_uc* p_target;
+    stbi_uc* p_source;
+
+    for (int x = x1; x < x2; ++x)
+        for (int y = y1; y < y2; ++y)
+        {
+            p_target = odata + (channels * ((y - y1) * dx + (x - x1)));
+            p_source = rgb_image + (channels * (y * width + x));
+            for (int _channels = 0; _channels < channels; ++_channels)
+                p_target[_channels] = p_source[_channels];
+        }
+
+    CResizeImage* rs = new CResizeImage(odata, channels, dx, dy, bpp);
+    rs->SetIndepended();
+    return rs;
+}

+ 49 - 16
code/components/jomjol_image_proc/CFindTemplate.h

@@ -15,12 +15,18 @@
 #include "stb_image_resize.h"
 
 
+#define MAX_JPG_SIZE 128000
+
+struct ImageData
+{
+    uint8_t data[MAX_JPG_SIZE];
+    size_t size = 0;
+};
+
+
 class CImageBasis
 {
     protected:
-        uint8_t* rgb_image;
-        int channels;
-        int width, height, bpp; 
         bool externalImage;
         std::string filename;
 
@@ -28,6 +34,10 @@ class CImageBasis
         bool isInImage(int x, int y);
 
     public:
+        uint8_t* rgb_image;
+        int channels;
+        int width, height, bpp; 
+
         int getWidth(){return this->width;};   
         int getHeight(){return this->height;};   
         int getChannels(){return this->channels;};   
@@ -37,11 +47,22 @@ class CImageBasis
         void setPixelColor(int x, int y, int r, int g, int b);
         void Contrast(float _contrast);
         bool ImageOkay();
+        bool CopyFromMemory(uint8_t* _source, int _size);
+
+        void SetIndepended(){externalImage = false;};
+
+        void CreateEmptyImage(int _width, int _height, int _channels);
 
 
         CImageBasis();
         CImageBasis(std::string _image);
         CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp);
+        CImageBasis(CImageBasis *_copyfrom);
+
+        void LoadFromMemory(stbi_uc *_buffer, int len);
+
+        ImageData* writeToMemoryAsJPG(const int quality = 90);       
+
         uint8_t GetPixelColor(int x, int y, int ch);
 
         ~CImageBasis();
@@ -53,7 +74,9 @@ class CFindTemplate : public CImageBasis
 {
     public:
         int tpl_width, tpl_height, tpl_bpp;    
-        CFindTemplate(std::string _image);
+//        CFindTemplate(std::string _image);
+        CFindTemplate(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {};
+
 
         void FindTemplate(std::string _template, int* found_x, int* found_y, std::string _imageout);
         void FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy, std::string _imageout);
@@ -64,8 +87,10 @@ class CFindTemplate : public CImageBasis
 class CRotate: public CImageBasis
 {
     public:
-        CRotate(std::string _image) : CImageBasis(_image) {};
-        CRotate(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {};
+        CImageBasis *ImageTMP;
+        CRotate(std::string _image) : CImageBasis(_image) {ImageTMP = NULL;};
+        CRotate(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL;};
+        CRotate(CImageBasis *_org, CImageBasis *_temp);
 
         void Rotate(float _angle);
         void Rotate(float _angle, int _centerx, int _centery);
@@ -74,23 +99,31 @@ class CRotate: public CImageBasis
 };
 
 
+class CResizeImage : public CImageBasis
+{
+public:
+    CResizeImage(std::string _image) : CImageBasis(_image) {};
+    CResizeImage(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {};
+
+//    CResizeImage(std::string _image, int _new_dx, int _new_dy);
+    void Resize(int _new_dx, int _new_dy);
+};
+
+
+
 class CAlignAndCutImage : public CImageBasis
 {
     public:
         int t0_dx, t0_dy, t1_dx, t1_dy;
-        CAlignAndCutImage(std::string _image) : CImageBasis(_image) {};
+        CImageBasis *ImageTMP;
+        CAlignAndCutImage(std::string _image) : CImageBasis(_image) {ImageTMP = NULL;};
+        CAlignAndCutImage(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL;};
+        CAlignAndCutImage(CImageBasis *_org, CImageBasis *_temp);
 
         void Align(std::string _template1, int x1, int y1, std::string _template2, int x2, int y2, int deltax = 40, int deltay = 40, std::string imageROI = "");
         void CutAndSave(std::string _template1, int x1, int y1, int dx, int dy);
-};
-
-
-class CResizeImage : public CImageBasis
-{
-public:
-    CResizeImage(std::string _image) : CImageBasis(_image) {};
-//    CResizeImage(std::string _image, int _new_dx, int _new_dy);
-    void Resize(int _new_dx, int _new_dy);
+        CResizeImage* CutAndSave(int x1, int y1, int dx, int dy);
+        void GetRefSize(int *ref_dx, int *ref_dy);
 };
 
 

+ 3 - 3
code/components/jomjol_logfile/ClassLogFile.cpp

@@ -19,7 +19,7 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool
         return;
     }
 
-    pFile = OpenFileAndWait(_fn.c_str(), "a+");
+    pFile = OpenFileAndWait(_fn.c_str(), "a");
 
     if (pFile!=NULL) {
         if (_time)
@@ -80,12 +80,12 @@ std::string ClassLogFile::GetCurrentFileName()
 {
     time_t rawtime;
     struct tm* timeinfo;
-    char buffer[30];
+    char buffer[60];
 
     time(&rawtime);
     timeinfo = localtime(&rawtime);
 
-    strftime(buffer, 30, logfile.c_str(), timeinfo);
+    strftime(buffer, 60, logfile.c_str(), timeinfo);
     std::string logpath = logroot + "/" + buffer; 
 
     return logpath;

+ 53 - 2
code/components/jomjol_tfliteclass/CTfLiteClass.cpp

@@ -21,6 +21,18 @@ float CTfLiteClass::GetOutputValue(int nr)
     return output2->data.f[nr];
 }
 
+int CTfLiteClass::GetClassFromImageBasis(CImageBasis *rs)
+{
+//  printf("Before Load image %s\n", _fn.c_str());
+    if (!LoadInputImageBasis(rs))
+      return -1000;
+
+    Invoke();
+    printf("After Invoke \n");
+
+    return GetOutClassification();
+}
+
 
 int CTfLiteClass::GetClassFromImage(std::string _fn)
 {
@@ -33,7 +45,6 @@ int CTfLiteClass::GetClassFromImage(std::string _fn)
   printf("After Invoke %s\n", _fn.c_str());
 
     return GetOutClassification();
-//    return 0;
 }
 
 int CTfLiteClass::GetOutClassification()
@@ -113,6 +124,46 @@ void CTfLiteClass::Invoke()
 }
 
 
+
+bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs)
+{
+    std::string zw = "ClassFlowAnalog::doNeuralNetwork nach LoadInputResizeImage: ";
+//    LogFile.WriteToFile(zw);
+
+
+    unsigned int w = rs->width;
+    unsigned int h = rs->height;
+    unsigned char red, green, blue;
+
+//    printf("Image: %s size: %d x %d\n", _fn.c_str(), w, h);
+
+    input_i = 0;
+    float* input_data_ptr = (interpreter->input(0))->data.f;
+
+    for (int y = 0; y < h; ++y)
+        for (int x = 0; x < w; ++x)
+            {
+                red = rs->GetPixelColor(x, y, 0);
+                green = rs->GetPixelColor(x, y, 1);
+                blue = rs->GetPixelColor(x, y, 2);
+                *(input_data_ptr) = (float) red;
+                input_data_ptr++;
+                *(input_data_ptr) = (float) green;
+                input_data_ptr++;
+                *(input_data_ptr) = (float) blue;
+                input_data_ptr++;
+
+//                printf("BMP: %f %f %f\n", (float) red, (float) green, (float) blue);
+
+            }
+    
+    if (debugdetailtflite) LogFile.WriteToFile("Nach dem Laden in input");
+
+    return true;
+}
+
+
+
 bool CTfLiteClass::LoadInputImage(std::string _fn)
 {
     std::string zw = "ClassFlowAnalog::doNeuralNetwork nach Load Image: " + _fn;
@@ -239,7 +290,7 @@ CTfLiteClass::CTfLiteClass()
     this->interpreter = nullptr;
     this->input = nullptr;
     this->output = nullptr;  
-    this->kTensorArenaSize = 600 * 1024;
+    this->kTensorArenaSize = 150 * 1024;   /// laut testfile: 108000 - bisher 600
     this->tensor_arena = new uint8_t[kTensorArenaSize]; 
 }
 

+ 4 - 0
code/components/jomjol_tfliteclass/CTfLiteClass.h

@@ -14,6 +14,8 @@
 #include "esp_err.h"
 #include "esp_log.h"
 
+#include "CFindTemplate.h"
+
 
 
 #define SUPRESS_TFLITE_ERRORS           // use, to avoid error messages from TFLITE
@@ -59,10 +61,12 @@ class CTfLiteClass
         void MakeAllocate();
         void GetInputTensorSize();
         bool LoadInputImage(std::string _fn);
+        bool LoadInputImageBasis(CImageBasis *rs);
         void Invoke();
         void GetOutPut();
         int GetOutClassification();
         int GetClassFromImage(std::string _fn);
+        int GetClassFromImageBasis(CImageBasis *rs);
 
         float GetOutputValue(int nr);
         void GetInputDimension(bool silent);

+ 11 - 1
code/components/jomjol_tfliteclass/server_tflite.cpp

@@ -29,6 +29,16 @@ bool flowisrunning = false;
 long auto_intervall = 0;
 bool auto_isrunning = false;
 
+ImageData* GetJPG(std::string _filename)
+{
+    return tfliteflow.GetJPGStream(_filename);
+}
+
+esp_err_t GetRawJPG(httpd_req_t *req)
+{
+    return tfliteflow.SendRawJPG(req);
+}
+
 bool isSetupModusActive() {
     return tfliteflow.getStatusSetupModus();
     return false;
@@ -171,7 +181,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
     {
         string txt, zw;
         
-        txt = "<p>Aligned Image: <p><img src=\"/img_tmp/alg.jpg\"> <p>\n";
+        txt = "<p>Aligned Image: <p><img src=\"/img_tmp/alg_roi.jpg\"> <p>\n";
         txt = txt + "Digital Counter: <p> ";
         httpd_resp_sendstr_chunk(req, txt.c_str()); 
         

+ 6 - 1
code/components/jomjol_tfliteclass/server_tflite.h

@@ -1,6 +1,7 @@
 #include <esp_log.h>
 
 #include <esp_http_server.h>
+#include "CFindTemplate.h"
 
 //#include "ClassControllCamera.h"
 
@@ -12,4 +13,8 @@ void KillTFliteTasks();
 
 void TFliteDoAutoStart();
 
-bool isSetupModusActive();
+bool isSetupModusActive();
+
+ImageData* GetJPG(std::string _filename);
+
+esp_err_t GetRawJPG(httpd_req_t *req);

+ 57 - 31
code/main/server_main.cpp

@@ -144,6 +144,7 @@ esp_err_t hello_main_handler(httpd_req_t *req)
     struct stat file_stat;
     printf("uri: %s\n", req->uri);
     int _pos;
+    esp_err_t res;
 
     char *base_path = (char*) req->user_ctx;
     std::string filetosend(base_path);
@@ -182,20 +183,8 @@ esp_err_t hello_main_handler(httpd_req_t *req)
         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
         return ESP_FAIL;
     }
-    if (stat(filetosend.c_str(), &file_stat) == -1) {
-        /* If file not present on SPIFFS check if URI
-         * corresponds to one of the hardcoded paths */
-        ESP_LOGE(TAG, "Failed to stat file : %s", filetosend.c_str());
-        /* Respond with 404 Not Found */
-        httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
-        return ESP_FAIL;
-    }
-    esp_err_t res;
-    res = httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
-    if (res != ESP_OK)
-        return res;
 
-    res = send_file(req, filetosend, &file_stat);
+    res = send_file(req, filetosend);
     if (res != ESP_OK)
         return res;
 
@@ -214,28 +203,13 @@ esp_err_t img_tmp_handler(httpd_req_t *req)
     std::string filetosend(base_path);
 
     const char *filename = get_path_from_uri(filepath, base_path,
-                                             req->uri  + sizeof("/img_tmp") - 1, sizeof(filepath));    
+                                             req->uri  + sizeof("/img_tmp/") - 1, sizeof(filepath));    
     printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
 
     filetosend = filetosend + "/img_tmp/" + std::string(filename);
     printf("File to upload: %s\n", filetosend.c_str());    
 
-    if (!filename) {
-        ESP_LOGE(TAG, "Filename is too long");
-        /* Respond with 500 Internal Server Error */
-        httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
-        return ESP_FAIL;
-    }
-    if (stat(filetosend.c_str(), &file_stat) == -1) {
-        /* If file not present on SPIFFS check if URI
-         * corresponds to one of the hardcoded paths */
-        ESP_LOGE(TAG, "Failed to stat file : %s", filetosend.c_str());
-        /* Respond with 404 Not Found */
-        httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
-        return ESP_FAIL;
-    }
-
-    esp_err_t res = send_file(req, filetosend, &file_stat);
+    esp_err_t res = send_file(req, filetosend);
     if (res != ESP_OK)
         return res;
 
@@ -244,6 +218,58 @@ esp_err_t img_tmp_handler(httpd_req_t *req)
     return ESP_OK;
 }
 
+esp_err_t img_tmp_virtual_handler(httpd_req_t *req)
+{
+    char filepath[50];
+
+    printf("uri: %s\n", req->uri);
+
+    char *base_path = (char*) req->user_ctx;
+    std::string filetosend(base_path);
+
+    const char *filename = get_path_from_uri(filepath, base_path,
+                                             req->uri  + sizeof("/img_tmp/") - 1, sizeof(filepath));    
+    printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
+
+    filetosend = std::string(filename);
+    printf("File to upload: %s\n", filetosend.c_str()); 
+
+    if (filetosend == "raw.jpg")
+    {
+        return GetRawJPG(req);
+    } 
+
+    ImageData *zw = GetJPG(filetosend);
+
+    if (zw)
+    {
+        ESP_LOGI(TAG, "Sending file : %s (%d bytes)...", filetosend.c_str(), zw->size);
+        set_content_type_from_file(req, filetosend.c_str());
+
+        if (httpd_resp_send_chunk(req, (char*) &(zw->data), zw->size) != ESP_OK) {
+                    ESP_LOGE(TAG, "File sending failed!");
+                    httpd_resp_sendstr_chunk(req, NULL);
+                    httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
+                    delete zw;
+                    return ESP_FAIL;
+        }    
+        ESP_LOGI(TAG, "File sending complete");    
+        /* Respond with an empty chunk to signal HTTP response completion */
+        httpd_resp_send_chunk(req, NULL, 0);
+
+        delete zw;
+        return ESP_OK;
+    }
+
+    // File wird nicht intern bereit gestellt --> klassischer weg:
+
+    return img_tmp_handler(req);
+}
+
+
+
+
+
 esp_err_t sysinfo_handler(httpd_req_t *req)
 {
     const char* resp_str; 
@@ -314,7 +340,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
     httpd_uri_t img_tmp_handle = {
         .uri       = "/img_tmp/*",  // Match all URIs of type /path/to/file
         .method    = HTTP_GET,
-        .handler   = img_tmp_handler,
+        .handler   = img_tmp_virtual_handler,
         .user_ctx  = (void*) base_path    // Pass server data as context
     };
     httpd_register_uri_handler(server, &img_tmp_handle);

+ 2 - 2
code/main/version.cpp

@@ -1,4 +1,4 @@
-const char* GIT_REV="793f928";
+const char* GIT_REV="f5c2810";
 const char* GIT_TAG="";
 const char* GIT_BRANCH="rolling";
-const char* BUILD_TIME="2020-12-07 20:40";
+const char* BUILD_TIME="2020-12-21 22:49";

+ 2 - 2
code/sdkconfig

@@ -537,8 +537,8 @@ CONFIG_FATFS_MAX_LFN=255
 CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
 # CONFIG_FATFS_API_ENCODING_UTF_16 is not set
 # CONFIG_FATFS_API_ENCODING_UTF_8 is not set
-CONFIG_FATFS_FS_LOCK=5
-CONFIG_FATFS_TIMEOUT_MS=10000
+CONFIG_FATFS_FS_LOCK=0
+CONFIG_FATFS_TIMEOUT_MS=100
 CONFIG_FATFS_PER_FILE_CACHE=y
 CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y
 # end of FAT Filesystem support

+ 7 - 7
code/sdkconfig.old

@@ -83,11 +83,11 @@ CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
 # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
 CONFIG_ESPTOOLPY_FLASHFREQ="40m"
 # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
-CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y
-# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
+# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
 # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
 # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
-CONFIG_ESPTOOLPY_FLASHSIZE="2MB"
+CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
 CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
 CONFIG_ESPTOOLPY_BEFORE_RESET=y
 # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
@@ -315,8 +315,8 @@ CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y
 CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4
 # CONFIG_ESP32_ULP_COPROC_ENABLED is not set
 CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0
-# CONFIG_ESP32_PANIC_PRINT_HALT is not set
-CONFIG_ESP32_PANIC_PRINT_REBOOT=y
+CONFIG_ESP32_PANIC_PRINT_HALT=y
+# CONFIG_ESP32_PANIC_PRINT_REBOOT is not set
 # CONFIG_ESP32_PANIC_SILENT_REBOOT is not set
 # CONFIG_ESP32_PANIC_GDBSTUB is not set
 CONFIG_ESP32_DEBUG_OCDAWARE=y
@@ -537,8 +537,8 @@ CONFIG_FATFS_MAX_LFN=255
 CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
 # CONFIG_FATFS_API_ENCODING_UTF_16 is not set
 # CONFIG_FATFS_API_ENCODING_UTF_8 is not set
-CONFIG_FATFS_FS_LOCK=5
-CONFIG_FATFS_TIMEOUT_MS=10000
+CONFIG_FATFS_FS_LOCK=0
+CONFIG_FATFS_TIMEOUT_MS=100
 CONFIG_FATFS_PER_FILE_CACHE=y
 CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y
 # end of FAT Filesystem support

+ 2 - 2
code/version.cpp

@@ -1,4 +1,4 @@
-const char* GIT_REV="793f928";
+const char* GIT_REV="f5c2810";
 const char* GIT_TAG="";
 const char* GIT_BRANCH="rolling";
-const char* BUILD_TIME="2020-12-07 20:40";
+const char* BUILD_TIME="2020-12-21 22:49";

BIN
firmware/bootloader.bin


BIN
firmware/firmware.bin


BIN
firmware/html.zip


+ 1 - 1
sd-card/html/edit_reference.html

@@ -87,7 +87,7 @@ table {
         }
             
         function loadRawImage(){
-            url = basepath + "/fileserver/img_tmp/raw.jpg" + "?session=" + Math.floor((Math.random() * 1000000) + 1);
+            url = basepath + "/img_tmp/raw.jpg" + "?session=" + Math.floor((Math.random() * 1000000) + 1);
             document.getElementById("finerotate").value = 0;
             document.getElementById("prerotateangle").value = getPreRotate();
             document.getElementById("mirror").checked = getMirror();