Bodmer / TJpg_Decoder

Jpeg decoder library based on Tiny JPEG Decompressor
Other
222 stars 42 forks source link

stream from http without storing it in an array #45

Closed SirCooper closed 1 year ago

SirCooper commented 1 year ago

I've implemented a streaming option. The largest picture, i've streamed so far, was following: https://upload.wikimedia.org/wikipedia/commons/f/f7/Yosemite-stream.jpg (1,024 × 768 pixels, file size: 146 KB, MIME type: image/jpeg), TJpgDec.setJpgScale(4), duration: ~2837 millis This way, i was able, to load big images from HTML without overload, or using huge parts of the ram for the array. works on esp32, should work on esp8266 new code: TJPG_decoder.h 19

    #if defined (TJPEG_LOAD_HTTP_LIBRARY)
    #if defined (ESP8266) 
      #include <esp8266wifi.h>
      #include <esp8266httpclient.h>
    #elif defined (ESP32)          
      #include <WiFi.h>
      #include <HTTPClient.h>    
    #endif
  #endif

TJPG_decoder.h 60

#if defined (TJPGD_LOAD_HTTP_LIBRARY)
  HTTPClient* jpg_http = NULL;
#endif

TJPG_decoder.h 81

#if defined (TJPGD_LOAD_HTTP_LIBRARY)
  JRESULT drawJpgFromStream(int32_t x, int32_t y,  char* http_stream) ;
#endif

TJPG_decoder.cpp 96

#ifdef TJPGD_LOAD_HTTP_LIBRARY
  else if (thisPtr->jpg_source ==  TJPG_STREAM)
  {             
    if (thisPtr->array_index + len > thisPtr->array_size) 
    {
      len = thisPtr->array_size - thisPtr->array_index;
    }

    if(thisPtr->jpg_http->connected())
    {
      uint8_t _buff[len];
      WiFiClient* const stream = thisPtr->jpg_http->getStreamPtr();
      if (stream->available()) stream->readBytes(_buff, len);
      yield();    
      if (buf)
      {
        memcpy_P(buf,_buff,len);
      }
      thisPtr->array_index = thisPtr->array_index + len;
    }
  }
#endif

TJPG_decoder.cpp 179

#if defined (TJPGD_LOAD_HTTP_LIBRARY

/***************************************************************************************
** Function name:           drawJpg
** Description:             Draw a named jpg file at x,y (name in char array)
***************************************************************************************/

JRESULT TJpg_Decoder::drawJpgFromStream(int32_t x, int32_t y, char* http_stream) {
  JDEC jdec;
  JRESULT jresult = JDR_OK;

  jpg_source = TJPG_STREAM;

  jpeg_x = x;
  jpeg_y = y;
  array_size  = 0;
  array_index  = 0;

  jdec.swap = _swap;        
  jpg_http = new HTTPClient;
  Serial.println(http_stream);
  jpg_http->begin(http_stream);
  long httpCode = jpg_http->GET();
  if(httpCode)Serial.printf("[HTTP] GET... code: %d\n", httpCode);
  if (httpCode == HTTP_CODE_OK) 
  {
    Serial.println("file started");
    array_size = jpg_http->getSize();
    Serial.println(array_size);
    array_index = 0;
  }

  // Analyse input data
  jresult = jd_prepare(&jdec, jd_input, workspace, TJPGD_WORKSPACE_SIZE, 0);

  // Extract image and render
  if (jresult == JDR_OK)jresult = jd_decomp(&jdec, jd_output, jpgScale);

  if(jpg_http->connected())
  {
    WiFiClient* const stream = jpg_http->getStreamPtr();
    stream->stop();
    stream->flush();
  }
  jpg_http->end();
  delete jpg_http;
  jpg_http = NULL;

  return jresult;
}

#endif
SirCooper commented 1 year ago

tried it with following picture: https://upload.wikimedia.org/wikipedia/commons/0/00/Center_of_the_Milky_Way_GalaxyIV%E2%80%93_Composite.jpg ‎(9.725 × 4.862 Pixel, Dateigröße: 17,36 MB, MIME-Typ: image/jpeg) , TJpgDec.setJpgScale(4) took 12869 millis, but worked :) TJpgDec.setJpgScale(8) took 22164 millis

Bodmer commented 1 year ago

Looks good. Can you create a pull request?