esp_jpg_decode.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include "esp_jpg_decode.h"
  15. #include "esp_system.h"
  16. #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+
  17. #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
  18. #include "esp32/rom/tjpgd.h"
  19. #elif CONFIG_IDF_TARGET_ESP32S2
  20. #include "tjpgd.h"
  21. #elif CONFIG_IDF_TARGET_ESP32S3
  22. #include "esp32s3/rom/tjpgd.h"
  23. #else
  24. #error Target CONFIG_IDF_TARGET is not supported
  25. #endif
  26. #else // ESP32 Before IDF 4.0
  27. #include "rom/tjpgd.h"
  28. #endif
  29. #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
  30. #include "esp32-hal-log.h"
  31. #define TAG ""
  32. #else
  33. #include "esp_log.h"
  34. static const char* TAG = "esp_jpg_decode";
  35. #endif
  36. typedef struct {
  37. jpg_scale_t scale;
  38. jpg_reader_cb reader;
  39. jpg_writer_cb writer;
  40. void * arg;
  41. size_t len;
  42. size_t index;
  43. } esp_jpg_decoder_t;
  44. static const char * jd_errors[] = {
  45. "Succeeded",
  46. "Interrupted by output function",
  47. "Device error or wrong termination of input stream",
  48. "Insufficient memory pool for the image",
  49. "Insufficient stream input buffer",
  50. "Parameter error",
  51. "Data format error",
  52. "Right format but not supported",
  53. "Not supported JPEG standard"
  54. };
  55. static uint32_t _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
  56. {
  57. uint16_t x = rect->left;
  58. uint16_t y = rect->top;
  59. uint16_t w = rect->right + 1 - x;
  60. uint16_t h = rect->bottom + 1 - y;
  61. uint8_t *data = (uint8_t *)bitmap;
  62. esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device;
  63. if (jpeg->writer) {
  64. return jpeg->writer(jpeg->arg, x, y, w, h, data);
  65. }
  66. return 0;
  67. }
  68. static uint32_t _jpg_read(JDEC *decoder, uint8_t *buf, uint32_t len)
  69. {
  70. esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device;
  71. if (jpeg->len && len > (jpeg->len - jpeg->index)) {
  72. len = jpeg->len - jpeg->index;
  73. }
  74. if (len) {
  75. len = jpeg->reader(jpeg->arg, jpeg->index, buf, len);
  76. if (!len) {
  77. ESP_LOGE(TAG, "Read Fail at %u/%u", jpeg->index, jpeg->len);
  78. }
  79. jpeg->index += len;
  80. }
  81. return len;
  82. }
  83. esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg)
  84. {
  85. static uint8_t work[3100];
  86. JDEC decoder;
  87. esp_jpg_decoder_t jpeg;
  88. jpeg.len = len;
  89. jpeg.reader = reader;
  90. jpeg.writer = writer;
  91. jpeg.arg = arg;
  92. jpeg.scale = scale;
  93. jpeg.index = 0;
  94. JRESULT jres = jd_prepare(&decoder, _jpg_read, work, 3100, &jpeg);
  95. if(jres != JDR_OK){
  96. ESP_LOGE(TAG, "JPG Header Parse Failed! %s", jd_errors[jres]);
  97. return ESP_FAIL;
  98. }
  99. uint16_t output_width = decoder.width / (1 << (uint8_t)(jpeg.scale));
  100. uint16_t output_height = decoder.height / (1 << (uint8_t)(jpeg.scale));
  101. //output start
  102. writer(arg, 0, 0, output_width, output_height, NULL);
  103. //output write
  104. jres = jd_decomp(&decoder, _jpg_write, (uint8_t)jpeg.scale);
  105. //output end
  106. writer(arg, output_width, output_height, output_width, output_height, NULL);
  107. if (jres != JDR_OK) {
  108. ESP_LOGE(TAG, "JPG Decompression Failed! %s", jd_errors[jres]);
  109. return ESP_FAIL;
  110. }
  111. //check if all data has been consumed.
  112. if (len && jpeg.index < len) {
  113. _jpg_read(&decoder, NULL, len - jpeg.index);
  114. }
  115. return ESP_OK;
  116. }