to_jpg.cpp 6.5 KB

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