to_bmp.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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 "img_converters.h"
  17. #include "soc/efuse_reg.h"
  18. #include "esp_heap_caps.h"
  19. #include "yuv.h"
  20. #include "sdkconfig.h"
  21. #include "esp_jpg_decode.h"
  22. #if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
  23. #include "esp32-hal-log.h"
  24. #define TAG ""
  25. #else
  26. #include "esp_log.h"
  27. static const char* TAG = "to_bmp";
  28. #endif
  29. static const int BMP_HEADER_LEN = 54;
  30. typedef struct {
  31. uint32_t filesize;
  32. uint32_t reserved;
  33. uint32_t fileoffset_to_pixelarray;
  34. uint32_t dibheadersize;
  35. int32_t width;
  36. int32_t height;
  37. uint16_t planes;
  38. uint16_t bitsperpixel;
  39. uint32_t compression;
  40. uint32_t imagesize;
  41. uint32_t ypixelpermeter;
  42. uint32_t xpixelpermeter;
  43. uint32_t numcolorspallette;
  44. uint32_t mostimpcolor;
  45. } bmp_header_t;
  46. typedef struct {
  47. uint16_t width;
  48. uint16_t height;
  49. uint16_t data_offset;
  50. const uint8_t *input;
  51. uint8_t *output;
  52. } rgb_jpg_decoder;
  53. static void *_malloc(size_t size)
  54. {
  55. return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  56. }
  57. //output buffer and image width
  58. static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data)
  59. {
  60. rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
  61. if(!data){
  62. if(x == 0 && y == 0){
  63. //write start
  64. jpeg->width = w;
  65. jpeg->height = h;
  66. //if output is null, this is BMP
  67. if(!jpeg->output){
  68. jpeg->output = (uint8_t *)_malloc((w*h*3)+jpeg->data_offset);
  69. if(!jpeg->output){
  70. return false;
  71. }
  72. }
  73. } else {
  74. //write end
  75. }
  76. return true;
  77. }
  78. size_t jw = jpeg->width*3;
  79. size_t t = y * jw;
  80. size_t b = t + (h * jw);
  81. size_t l = x * 3;
  82. uint8_t *out = jpeg->output+jpeg->data_offset;
  83. uint8_t *o = out;
  84. size_t iy, ix;
  85. w = w * 3;
  86. for(iy=t; iy<b; iy+=jw) {
  87. o = out+iy+l;
  88. for(ix=0; ix<w; ix+= 3) {
  89. o[ix] = data[ix+2];
  90. o[ix+1] = data[ix+1];
  91. o[ix+2] = data[ix];
  92. }
  93. data+=w;
  94. }
  95. return true;
  96. }
  97. //input buffer
  98. static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len)
  99. {
  100. rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
  101. if(buf) {
  102. memcpy(buf, jpeg->input + index, len);
  103. }
  104. return len;
  105. }
  106. static bool jpg2rgb888(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale)
  107. {
  108. rgb_jpg_decoder jpeg;
  109. jpeg.width = 0;
  110. jpeg.height = 0;
  111. jpeg.input = src;
  112. jpeg.output = out;
  113. jpeg.data_offset = 0;
  114. if(esp_jpg_decode(src_len, scale, _jpg_read, _rgb_write, (void*)&jpeg) != ESP_OK){
  115. return false;
  116. }
  117. return true;
  118. }
  119. bool jpg2bmp(const uint8_t *src, size_t src_len, uint8_t ** out, size_t * out_len)
  120. {
  121. rgb_jpg_decoder jpeg;
  122. jpeg.width = 0;
  123. jpeg.height = 0;
  124. jpeg.input = src;
  125. jpeg.output = NULL;
  126. jpeg.data_offset = BMP_HEADER_LEN;
  127. if(esp_jpg_decode(src_len, JPG_SCALE_NONE, _jpg_read, _rgb_write, (void*)&jpeg) != ESP_OK){
  128. return false;
  129. }
  130. size_t output_size = jpeg.width*jpeg.height*3;
  131. jpeg.output[0] = 'B';
  132. jpeg.output[1] = 'M';
  133. bmp_header_t * bitmap = (bmp_header_t*)&jpeg.output[2];
  134. bitmap->reserved = 0;
  135. bitmap->filesize = output_size+BMP_HEADER_LEN;
  136. bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN;
  137. bitmap->dibheadersize = 40;
  138. bitmap->width = jpeg.width;
  139. bitmap->height = -jpeg.height;//set negative for top to bottom
  140. bitmap->planes = 1;
  141. bitmap->bitsperpixel = 24;
  142. bitmap->compression = 0;
  143. bitmap->imagesize = output_size;
  144. bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI
  145. bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI
  146. bitmap->numcolorspallette = 0;
  147. bitmap->mostimpcolor = 0;
  148. *out = jpeg.output;
  149. *out_len = output_size+BMP_HEADER_LEN;
  150. return true;
  151. }
  152. bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf)
  153. {
  154. int pix_count = 0;
  155. if(format == PIXFORMAT_JPEG) {
  156. return jpg2rgb888(src_buf, src_len, rgb_buf, JPG_SCALE_NONE);
  157. } else if(format == PIXFORMAT_RGB888) {
  158. memcpy(rgb_buf, src_buf, src_len);
  159. } else if(format == PIXFORMAT_RGB565) {
  160. int i;
  161. uint8_t hb, lb;
  162. pix_count = src_len / 2;
  163. for(i=0; i<pix_count; i++) {
  164. hb = *src_buf++;
  165. lb = *src_buf++;
  166. *rgb_buf++ = (lb & 0x1F) << 3;
  167. *rgb_buf++ = (hb & 0x07) << 5 | (lb & 0xE0) >> 3;
  168. *rgb_buf++ = hb & 0xF8;
  169. }
  170. } else if(format == PIXFORMAT_GRAYSCALE) {
  171. int i;
  172. uint8_t b;
  173. pix_count = src_len;
  174. for(i=0; i<pix_count; i++) {
  175. b = *src_buf++;
  176. *rgb_buf++ = b;
  177. *rgb_buf++ = b;
  178. *rgb_buf++ = b;
  179. }
  180. } else if(format == PIXFORMAT_YUV422) {
  181. pix_count = src_len / 2;
  182. int i, maxi = pix_count / 2;
  183. uint8_t y0, y1, u, v;
  184. uint8_t r, g, b;
  185. for(i=0; i<maxi; i++) {
  186. y0 = *src_buf++;
  187. u = *src_buf++;
  188. y1 = *src_buf++;
  189. v = *src_buf++;
  190. yuv2rgb(y0, u, v, &r, &g, &b);
  191. *rgb_buf++ = b;
  192. *rgb_buf++ = g;
  193. *rgb_buf++ = r;
  194. yuv2rgb(y1, u, v, &r, &g, &b);
  195. *rgb_buf++ = b;
  196. *rgb_buf++ = g;
  197. *rgb_buf++ = r;
  198. }
  199. }
  200. return true;
  201. }
  202. bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len)
  203. {
  204. if(format == PIXFORMAT_JPEG) {
  205. return jpg2bmp(src, src_len, out, out_len);
  206. }
  207. *out = NULL;
  208. *out_len = 0;
  209. int pix_count = width*height;
  210. size_t out_size = (pix_count * 3) + BMP_HEADER_LEN;
  211. uint8_t * out_buf = (uint8_t *)_malloc(out_size);
  212. if(!out_buf) {
  213. ESP_LOGE(TAG, "_malloc failed! %u", out_size);
  214. return false;
  215. }
  216. out_buf[0] = 'B';
  217. out_buf[1] = 'M';
  218. bmp_header_t * bitmap = (bmp_header_t*)&out_buf[2];
  219. bitmap->reserved = 0;
  220. bitmap->filesize = out_size;
  221. bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN;
  222. bitmap->dibheadersize = 40;
  223. bitmap->width = width;
  224. bitmap->height = -height;//set negative for top to bottom
  225. bitmap->planes = 1;
  226. bitmap->bitsperpixel = 24;
  227. bitmap->compression = 0;
  228. bitmap->imagesize = pix_count * 3;
  229. bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI
  230. bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI
  231. bitmap->numcolorspallette = 0;
  232. bitmap->mostimpcolor = 0;
  233. uint8_t * rgb_buf = out_buf + BMP_HEADER_LEN;
  234. uint8_t * src_buf = src;
  235. //convert data to RGB888
  236. if(format == PIXFORMAT_RGB888) {
  237. memcpy(rgb_buf, src_buf, pix_count*3);
  238. } else if(format == PIXFORMAT_RGB565) {
  239. int i;
  240. uint8_t hb, lb;
  241. for(i=0; i<pix_count; i++) {
  242. hb = *src_buf++;
  243. lb = *src_buf++;
  244. *rgb_buf++ = (lb & 0x1F) << 3;
  245. *rgb_buf++ = (hb & 0x07) << 5 | (lb & 0xE0) >> 3;
  246. *rgb_buf++ = hb & 0xF8;
  247. }
  248. } else if(format == PIXFORMAT_GRAYSCALE) {
  249. int i;
  250. uint8_t b;
  251. for(i=0; i<pix_count; i++) {
  252. b = *src_buf++;
  253. *rgb_buf++ = b;
  254. *rgb_buf++ = b;
  255. *rgb_buf++ = b;
  256. }
  257. } else if(format == PIXFORMAT_YUV422) {
  258. int i, maxi = pix_count / 2;
  259. uint8_t y0, y1, u, v;
  260. uint8_t r, g, b;
  261. for(i=0; i<maxi; i++) {
  262. y0 = *src_buf++;
  263. u = *src_buf++;
  264. y1 = *src_buf++;
  265. v = *src_buf++;
  266. yuv2rgb(y0, u, v, &r, &g, &b);
  267. *rgb_buf++ = b;
  268. *rgb_buf++ = g;
  269. *rgb_buf++ = r;
  270. yuv2rgb(y1, u, v, &r, &g, &b);
  271. *rgb_buf++ = b;
  272. *rgb_buf++ = g;
  273. *rgb_buf++ = r;
  274. }
  275. }
  276. *out = out_buf;
  277. *out_len = out_size;
  278. return true;
  279. }
  280. bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len)
  281. {
  282. return fmt2bmp(fb->buf, fb->len, fb->width, fb->height, fb->format, out, out_len);
  283. }