to_jpg.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 <stddef.h>
  15. #include <string.h>
  16. #include "esp_attr.h"
  17. #include "soc/efuse_reg.h"
  18. #include "esp_heap_caps.h"
  19. #include "esp_camera.h"
  20. #include "img_converters.h"
  21. #include "jpge.h"
  22. #include "yuv.h"
  23. #include "esp_system.h"
  24. #if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+
  25. #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
  26. #include "esp32/spiram.h"
  27. #elif CONFIG_IDF_TARGET_ESP32S2
  28. #include "esp32s2/spiram.h"
  29. #elif CONFIG_IDF_TARGET_ESP32S3
  30. #include "esp32s3/spiram.h"
  31. #else
  32. #error Target CONFIG_IDF_TARGET is not supported
  33. #endif
  34. #else // ESP32 Before IDF 4.0
  35. #include "esp_spiram.h"
  36. #endif
  37. #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
  38. #include "esp32-hal-log.h"
  39. #define TAG ""
  40. #else
  41. #include "esp_log.h"
  42. static const char* TAG = "to_jpg";
  43. #endif
  44. static void *_malloc(size_t size)
  45. {
  46. void * res = malloc(size);
  47. if(res) {
  48. return res;
  49. }
  50. return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  51. }
  52. static IRAM_ATTR void convert_line_format(uint8_t * src, pixformat_t format, uint8_t * dst, size_t width, size_t in_channels, size_t line)
  53. {
  54. int i=0, o=0, l=0;
  55. if(format == PIXFORMAT_GRAYSCALE) {
  56. memcpy(dst, src + line * width, width);
  57. } else if(format == PIXFORMAT_RGB888) {
  58. l = width * 3;
  59. src += l * line;
  60. for(i=0; i<l; i+=3) {
  61. dst[o++] = src[i+2];
  62. dst[o++] = src[i+1];
  63. dst[o++] = src[i];
  64. }
  65. } else if(format == PIXFORMAT_RGB565) {
  66. l = width * 2;
  67. src += l * line;
  68. for(i=0; i<l; i+=2) {
  69. dst[o++] = src[i] & 0xF8;
  70. dst[o++] = (src[i] & 0x07) << 5 | (src[i+1] & 0xE0) >> 3;
  71. dst[o++] = (src[i+1] & 0x1F) << 3;
  72. }
  73. } else if(format == PIXFORMAT_YUV422) {
  74. uint8_t y0, y1, u, v;
  75. uint8_t r, g, b;
  76. l = width * 2;
  77. src += l * line;
  78. for(i=0; i<l; i+=4) {
  79. y0 = src[i];
  80. u = src[i+1];
  81. y1 = src[i+2];
  82. v = src[i+3];
  83. yuv2rgb(y0, u, v, &r, &g, &b);
  84. dst[o++] = r;
  85. dst[o++] = g;
  86. dst[o++] = b;
  87. yuv2rgb(y1, u, v, &r, &g, &b);
  88. dst[o++] = r;
  89. dst[o++] = g;
  90. dst[o++] = b;
  91. }
  92. }
  93. }
  94. bool convert_image(uint8_t *src, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpge::output_stream *dst_stream)
  95. {
  96. int num_channels = 3;
  97. jpge::subsampling_t subsampling = jpge::H2V2;
  98. if(format == PIXFORMAT_GRAYSCALE) {
  99. num_channels = 1;
  100. subsampling = jpge::Y_ONLY;
  101. }
  102. if(!quality) {
  103. quality = 1;
  104. } else if(quality > 100) {
  105. quality = 100;
  106. }
  107. jpge::params comp_params = jpge::params();
  108. comp_params.m_subsampling = subsampling;
  109. comp_params.m_quality = quality;
  110. jpge::jpeg_encoder dst_image;
  111. if (!dst_image.init(dst_stream, width, height, num_channels, comp_params)) {
  112. ESP_LOGE(TAG, "JPG encoder init failed");
  113. return false;
  114. }
  115. uint8_t* line = (uint8_t*)_malloc(width * num_channels);
  116. if(!line) {
  117. ESP_LOGE(TAG, "Scan line malloc failed");
  118. return false;
  119. }
  120. for (int i = 0; i < height; i++) {
  121. convert_line_format(src, format, line, width, num_channels, i);
  122. if (!dst_image.process_scanline(line)) {
  123. ESP_LOGE(TAG, "JPG process line %u failed", i);
  124. free(line);
  125. return false;
  126. }
  127. }
  128. free(line);
  129. if (!dst_image.process_scanline(NULL)) {
  130. ESP_LOGE(TAG, "JPG image finish failed");
  131. return false;
  132. }
  133. dst_image.deinit();
  134. return true;
  135. }
  136. class callback_stream : public jpge::output_stream {
  137. protected:
  138. jpg_out_cb ocb;
  139. void * oarg;
  140. size_t index;
  141. public:
  142. callback_stream(jpg_out_cb cb, void * arg) : ocb(cb), oarg(arg), index(0) { }
  143. virtual ~callback_stream() { }
  144. virtual bool put_buf(const void* data, int len)
  145. {
  146. index += ocb(oarg, index, data, len);
  147. return true;
  148. }
  149. virtual size_t get_size() const
  150. {
  151. return index;
  152. }
  153. };
  154. bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg)
  155. {
  156. callback_stream dst_stream(cb, arg);
  157. return convert_image(src, width, height, format, quality, &dst_stream);
  158. }
  159. bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg)
  160. {
  161. return fmt2jpg_cb(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, cb, arg);
  162. }
  163. class memory_stream : public jpge::output_stream {
  164. protected:
  165. uint8_t *out_buf;
  166. size_t max_len, index;
  167. public:
  168. memory_stream(void *pBuf, uint buf_size) : out_buf(static_cast<uint8_t*>(pBuf)), max_len(buf_size), index(0) { }
  169. virtual ~memory_stream() { }
  170. virtual bool put_buf(const void* pBuf, int len)
  171. {
  172. if (!pBuf) {
  173. //end of image
  174. return true;
  175. }
  176. if ((size_t)len > (max_len - index)) {
  177. //ESP_LOGW(TAG, "JPG output overflow: %d bytes (%d,%d,%d)", len - (max_len - index), len, index, max_len);
  178. len = max_len - index;
  179. }
  180. if (len) {
  181. memcpy(out_buf + index, pBuf, len);
  182. index += len;
  183. }
  184. return true;
  185. }
  186. virtual size_t get_size() const
  187. {
  188. return index;
  189. }
  190. };
  191. bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len)
  192. {
  193. //todo: allocate proper buffer for holding JPEG data
  194. //this should be enough for CIF frame size
  195. int jpg_buf_len = 128*1024;
  196. uint8_t * jpg_buf = (uint8_t *)_malloc(jpg_buf_len);
  197. if(jpg_buf == NULL) {
  198. ESP_LOGE(TAG, "JPG buffer malloc failed");
  199. return false;
  200. }
  201. memory_stream dst_stream(jpg_buf, jpg_buf_len);
  202. if(!convert_image(src, width, height, format, quality, &dst_stream)) {
  203. free(jpg_buf);
  204. return false;
  205. }
  206. *out = jpg_buf;
  207. *out_len = dst_stream.get_size();
  208. return true;
  209. }
  210. bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len)
  211. {
  212. return fmt2jpg(fb->buf, fb->len, fb->width, fb->height, fb->format, quality, out, out_len);
  213. }