to_jpg.cpp 6.3 KB

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