to_bmp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  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. #include "esp_system.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_bmp";
  29. #endif
  30. static const int BMP_HEADER_LEN = 54;
  31. typedef struct {
  32. uint32_t filesize;
  33. uint32_t reserved;
  34. uint32_t fileoffset_to_pixelarray;
  35. uint32_t dibheadersize;
  36. int32_t width;
  37. int32_t height;
  38. uint16_t planes;
  39. uint16_t bitsperpixel;
  40. uint32_t compression;
  41. uint32_t imagesize;
  42. uint32_t ypixelpermeter;
  43. uint32_t xpixelpermeter;
  44. uint32_t numcolorspallette;
  45. uint32_t mostimpcolor;
  46. } bmp_header_t;
  47. typedef struct {
  48. uint16_t width;
  49. uint16_t height;
  50. uint16_t data_offset;
  51. const uint8_t *input;
  52. uint8_t *output;
  53. } rgb_jpg_decoder;
  54. static void *_malloc(size_t size)
  55. {
  56. // check if SPIRAM is enabled and allocate on SPIRAM if allocatable
  57. #if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC))
  58. return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
  59. #endif
  60. // try allocating in internal memory
  61. return malloc(size);
  62. }
  63. //output buffer and image width
  64. static bool _rgb_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data)
  65. {
  66. rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
  67. if(!data){
  68. if(x == 0 && y == 0){
  69. //write start
  70. jpeg->width = w;
  71. jpeg->height = h;
  72. //if output is null, this is BMP
  73. if(!jpeg->output){
  74. jpeg->output = (uint8_t *)_malloc((w*h*3)+jpeg->data_offset);
  75. if(!jpeg->output){
  76. return false;
  77. }
  78. }
  79. } else {
  80. //write end
  81. }
  82. return true;
  83. }
  84. size_t jw = jpeg->width*3;
  85. size_t t = y * jw;
  86. size_t b = t + (h * jw);
  87. size_t l = x * 3;
  88. uint8_t *out = jpeg->output+jpeg->data_offset;
  89. uint8_t *o = out;
  90. size_t iy, ix;
  91. w = w * 3;
  92. for(iy=t; iy<b; iy+=jw) {
  93. o = out+iy+l;
  94. for(ix=0; ix<w; ix+= 3) {
  95. o[ix] = data[ix+2];
  96. o[ix+1] = data[ix+1];
  97. o[ix+2] = data[ix];
  98. }
  99. data+=w;
  100. }
  101. return true;
  102. }
  103. static bool _rgb565_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data)
  104. {
  105. rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
  106. if(!data){
  107. if(x == 0 && y == 0){
  108. //write start
  109. jpeg->width = w;
  110. jpeg->height = h;
  111. //if output is null, this is BMP
  112. if(!jpeg->output){
  113. jpeg->output = (uint8_t *)_malloc((w*h*3)+jpeg->data_offset);
  114. if(!jpeg->output){
  115. return false;
  116. }
  117. }
  118. } else {
  119. //write end
  120. }
  121. return true;
  122. }
  123. size_t jw = jpeg->width*3;
  124. size_t jw2 = jpeg->width*2;
  125. size_t t = y * jw;
  126. size_t t2 = y * jw2;
  127. size_t b = t + (h * jw);
  128. size_t l = x * 2;
  129. uint8_t *out = jpeg->output+jpeg->data_offset;
  130. uint8_t *o = out;
  131. size_t iy, iy2, ix, ix2;
  132. w = w * 3;
  133. for(iy=t, iy2=t2; iy<b; iy+=jw, iy2+=jw2) {
  134. o = out+iy2+l;
  135. for(ix2=ix=0; ix<w; ix+= 3, ix2 +=2) {
  136. uint16_t r = data[ix];
  137. uint16_t g = data[ix+1];
  138. uint16_t b = data[ix+2];
  139. uint16_t c = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
  140. o[ix2+1] = c>>8;
  141. o[ix2] = c&0xff;
  142. }
  143. data+=w;
  144. }
  145. return true;
  146. }
  147. //input buffer
  148. static unsigned int _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len)
  149. {
  150. rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
  151. if(buf) {
  152. memcpy(buf, jpeg->input + index, len);
  153. }
  154. return len;
  155. }
  156. static bool jpg2rgb888(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale)
  157. {
  158. rgb_jpg_decoder jpeg;
  159. jpeg.width = 0;
  160. jpeg.height = 0;
  161. jpeg.input = src;
  162. jpeg.output = out;
  163. jpeg.data_offset = 0;
  164. if(esp_jpg_decode(src_len, scale, _jpg_read, _rgb_write, (void*)&jpeg) != ESP_OK){
  165. return false;
  166. }
  167. return true;
  168. }
  169. bool jpg2rgb565(const uint8_t *src, size_t src_len, uint8_t * out, jpg_scale_t scale)
  170. {
  171. rgb_jpg_decoder jpeg;
  172. jpeg.width = 0;
  173. jpeg.height = 0;
  174. jpeg.input = src;
  175. jpeg.output = out;
  176. jpeg.data_offset = 0;
  177. if(esp_jpg_decode(src_len, scale, _jpg_read, _rgb565_write, (void*)&jpeg) != ESP_OK){
  178. return false;
  179. }
  180. return true;
  181. }
  182. bool jpg2bmp(const uint8_t *src, size_t src_len, uint8_t ** out, size_t * out_len)
  183. {
  184. rgb_jpg_decoder jpeg;
  185. jpeg.width = 0;
  186. jpeg.height = 0;
  187. jpeg.input = src;
  188. jpeg.output = NULL;
  189. jpeg.data_offset = BMP_HEADER_LEN;
  190. if(esp_jpg_decode(src_len, JPG_SCALE_NONE, _jpg_read, _rgb_write, (void*)&jpeg) != ESP_OK){
  191. return false;
  192. }
  193. size_t output_size = jpeg.width*jpeg.height*3;
  194. jpeg.output[0] = 'B';
  195. jpeg.output[1] = 'M';
  196. bmp_header_t * bitmap = (bmp_header_t*)&jpeg.output[2];
  197. bitmap->reserved = 0;
  198. bitmap->filesize = output_size+BMP_HEADER_LEN;
  199. bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN;
  200. bitmap->dibheadersize = 40;
  201. bitmap->width = jpeg.width;
  202. bitmap->height = -jpeg.height;//set negative for top to bottom
  203. bitmap->planes = 1;
  204. bitmap->bitsperpixel = 24;
  205. bitmap->compression = 0;
  206. bitmap->imagesize = output_size;
  207. bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI
  208. bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI
  209. bitmap->numcolorspallette = 0;
  210. bitmap->mostimpcolor = 0;
  211. *out = jpeg.output;
  212. *out_len = output_size+BMP_HEADER_LEN;
  213. return true;
  214. }
  215. bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf)
  216. {
  217. int pix_count = 0;
  218. if(format == PIXFORMAT_JPEG) {
  219. return jpg2rgb888(src_buf, src_len, rgb_buf, JPG_SCALE_NONE);
  220. } else if(format == PIXFORMAT_RGB888) {
  221. memcpy(rgb_buf, src_buf, src_len);
  222. } else if(format == PIXFORMAT_RGB565) {
  223. int i;
  224. uint8_t hb, lb;
  225. pix_count = src_len / 2;
  226. for(i=0; i<pix_count; i++) {
  227. hb = *src_buf++;
  228. lb = *src_buf++;
  229. *rgb_buf++ = (lb & 0x1F) << 3;
  230. *rgb_buf++ = (hb & 0x07) << 5 | (lb & 0xE0) >> 3;
  231. *rgb_buf++ = hb & 0xF8;
  232. }
  233. } else if(format == PIXFORMAT_GRAYSCALE) {
  234. int i;
  235. uint8_t b;
  236. pix_count = src_len;
  237. for(i=0; i<pix_count; i++) {
  238. b = *src_buf++;
  239. *rgb_buf++ = b;
  240. *rgb_buf++ = b;
  241. *rgb_buf++ = b;
  242. }
  243. } else if(format == PIXFORMAT_YUV422) {
  244. pix_count = src_len / 2;
  245. int i, maxi = pix_count / 2;
  246. uint8_t y0, y1, u, v;
  247. uint8_t r, g, b;
  248. for(i=0; i<maxi; i++) {
  249. y0 = *src_buf++;
  250. u = *src_buf++;
  251. y1 = *src_buf++;
  252. v = *src_buf++;
  253. yuv2rgb(y0, u, v, &r, &g, &b);
  254. *rgb_buf++ = b;
  255. *rgb_buf++ = g;
  256. *rgb_buf++ = r;
  257. yuv2rgb(y1, u, v, &r, &g, &b);
  258. *rgb_buf++ = b;
  259. *rgb_buf++ = g;
  260. *rgb_buf++ = r;
  261. }
  262. }
  263. return true;
  264. }
  265. 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)
  266. {
  267. if(format == PIXFORMAT_JPEG) {
  268. return jpg2bmp(src, src_len, out, out_len);
  269. }
  270. *out = NULL;
  271. *out_len = 0;
  272. int pix_count = width*height;
  273. size_t out_size = (pix_count * 3) + BMP_HEADER_LEN;
  274. uint8_t * out_buf = (uint8_t *)_malloc(out_size);
  275. if(!out_buf) {
  276. ESP_LOGE(TAG, "_malloc failed! %u", out_size);
  277. return false;
  278. }
  279. out_buf[0] = 'B';
  280. out_buf[1] = 'M';
  281. bmp_header_t * bitmap = (bmp_header_t*)&out_buf[2];
  282. bitmap->reserved = 0;
  283. bitmap->filesize = out_size;
  284. bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN;
  285. bitmap->dibheadersize = 40;
  286. bitmap->width = width;
  287. bitmap->height = -height;//set negative for top to bottom
  288. bitmap->planes = 1;
  289. bitmap->bitsperpixel = 24;
  290. bitmap->compression = 0;
  291. bitmap->imagesize = pix_count * 3;
  292. bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI
  293. bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI
  294. bitmap->numcolorspallette = 0;
  295. bitmap->mostimpcolor = 0;
  296. uint8_t * rgb_buf = out_buf + BMP_HEADER_LEN;
  297. uint8_t * src_buf = src;
  298. //convert data to RGB888
  299. if(format == PIXFORMAT_RGB888) {
  300. memcpy(rgb_buf, src_buf, pix_count*3);
  301. } else if(format == PIXFORMAT_RGB565) {
  302. int i;
  303. uint8_t hb, lb;
  304. for(i=0; i<pix_count; i++) {
  305. hb = *src_buf++;
  306. lb = *src_buf++;
  307. *rgb_buf++ = (lb & 0x1F) << 3;
  308. *rgb_buf++ = (hb & 0x07) << 5 | (lb & 0xE0) >> 3;
  309. *rgb_buf++ = hb & 0xF8;
  310. }
  311. } else if(format == PIXFORMAT_GRAYSCALE) {
  312. int i;
  313. uint8_t b;
  314. for(i=0; i<pix_count; i++) {
  315. b = *src_buf++;
  316. *rgb_buf++ = b;
  317. *rgb_buf++ = b;
  318. *rgb_buf++ = b;
  319. }
  320. } else if(format == PIXFORMAT_YUV422) {
  321. int i, maxi = pix_count / 2;
  322. uint8_t y0, y1, u, v;
  323. uint8_t r, g, b;
  324. for(i=0; i<maxi; i++) {
  325. y0 = *src_buf++;
  326. u = *src_buf++;
  327. y1 = *src_buf++;
  328. v = *src_buf++;
  329. yuv2rgb(y0, u, v, &r, &g, &b);
  330. *rgb_buf++ = b;
  331. *rgb_buf++ = g;
  332. *rgb_buf++ = r;
  333. yuv2rgb(y1, u, v, &r, &g, &b);
  334. *rgb_buf++ = b;
  335. *rgb_buf++ = g;
  336. *rgb_buf++ = r;
  337. }
  338. }
  339. *out = out_buf;
  340. *out_len = out_size;
  341. return true;
  342. }
  343. bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len)
  344. {
  345. return fmt2bmp(fb->buf, fb->len, fb->width, fb->height, fb->format, out, out_len);
  346. }