Отдать браузеру большую картинку из progmem

Тема в разделе "ESP8266, ESP32", создана пользователем Vovka, 10 май 2024.

  1. Vovka

    Vovka Гик

    Вот тестовый код:

    Код (C++):
    #include <ESP8266WiFi.h>
    #include <WiFiClient.h>
    #include <ESP8266WebServer.h>

    //#define WFI_CONNECT_AP

    #ifdef WFI_CONNECT_AP
        #define AP_SSID    "TEST_AP"
        #define AP_PASSW    ""
    #else
        #ifndef STASSID
            #define STASSID "TP-Link"
            #define STAPSK  "12345678"
        #endif
        const char* ssid = STASSID;
        const char* password = STAPSK;
    #endif

    ESP8266WebServer server(80);

    static const uint8_t gif[] PROGMEM = {
      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00,
        0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x2c,
        0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x02,
        0x19, 0x8c, 0x8f, 0xa9, 0xcb, 0x9d, 0x00, 0x5f, 0x74, 0xb4,
        0x56, 0xb0, 0xb0, 0xd2, 0xf2, 0x35, 0x1e, 0x4c, 0x0c, 0x24,
        0x5a, 0xe6, 0x89, 0xa6, 0x4d, 0x01, 0x00, 0x3b
    };

    void handleRoot() {
      digitalWrite(LED_BUILTIN, 1);
      server.send(200, "text/plain", "hello from esp8266!");
      digitalWrite(LED_BUILTIN, 0);
    }

    void setup(void)
    {
      pinMode(LED_BUILTIN, OUTPUT);
      Serial.begin(115200);

    #ifdef WFI_CONNECT_AP
        WiFi.mode( WIFI_AP );
        WiFi.setAutoReconnect( 1 );
        WiFi.softAPConfig( IPAddress(192, 168, 1, 10), IPAddress(192, 168, 1, 1), IPAddress(255, 255, 255, 0) );
    #else
        WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
    #endif

        Serial.println("");

    #ifndef WFI_CONNECT_AP
      // Wait for connection
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.print("Connected to ");
      Serial.println(ssid);
    #endif
        Serial.print("IP address: ");
      Serial.println(WiFi.localIP());

      server.on("/", handleRoot);

    // 1111111111111111111111111111111111111111
      server.on("/g1", []() {
            char gif_colored[ sizeof(gif) ];
            memcpy_P( gif_colored, gif, sizeof(gif_colored) );
            server.send( 200, "image/gif", gif_colored, sizeof(gif_colored) );
      });

    // 2222222222222222222222222222222222222222
      server.on("/g2", []() {

            #define BUF_LEN 20

            char gif_colored[BUF_LEN];
            int a, L, d;
            L = sizeof(gif);
           
    //        server.sendHeader("Content-Type", "image/gif");
            server.send ( 200, "image/gif" );
            server.setContentLength( L );
    //        server.setContentLength(CONTENT_LENGTH_UNKNOWN);

            for( a=0; a<L; ) {
                d = L-a < BUF_LEN ? L-a : BUF_LEN;
                memcpy_P( gif_colored, gif, d );
              server.sendContent_P( gif_colored, d );
                a += d;
            }
            server.sendContent("");
      });

      server.begin();
      Serial.println("HTTP server started");
    }

    void loop(void) {
      server.handleClient();
    }
     
    Для варианта:
    HTML:
    http://192.168.1.10/g1
    картинка выводится,
    а если для больших картинок:
    HTML:
    http://192.168.1.10/g2
    - ошибка!
    Как исправить?
     
  2. parovoZZ

    parovoZZ Гуру

    а в логах что? Ошибка на какой стороне?
     
  3. Vovka

    Vovka Гик

    Вместо картинки выводит по центру экрана горизонтальную линию
     
  4. Asper Daffy

    Asper Daffy Иксперд

    Так и должно быть. При g2 Вы зачем-то скопировали массив в локальный, а потом с какого-то бодуна отправляете его методом sendContent_P, который предназначен для отправки из прогмема, а не из локального массива.

    Код (C++):
    memcpy_P( gif_colored, gif, d );
    server.sendContent_P( gif_colored, d ); // Но ведь gif_colored ни хера не в прогмем!
     
    Вы уж что-нибудь одно выбирайте. Или отправляйте прямо из прогмема методом отправки из прогмема, либо копируйте в локальный массив (неясно наюха), но тогда и отправляйте методом отправки из ОЗУ, как Вы это делали в функции для g1
     
    Andrey12, Vovka и DetSimen нравится это.