c_model_jpeg_test.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. //-----------------------------------------------------------------------------
  2. //(C) 2020 ultraembedded https://github.com/ultraembedded/core_jpeg
  3. //(C) 2024 Victor Suarez Rovere <suarezvictor@gmail.com>
  4. //License: Apache-2.0
  5. //-----------------------------------------------------------------------------
  6. #include "jpeg_dqt.h"
  7. #include "jpeg_dht.h"
  8. #include "jpeg_idct.h"
  9. #include "jpeg_bit_buffer.h"
  10. #include "jpeg_mcu_block.h"
  11. struct jpeg_state
  12. {
  13. jpeg_dqt m_dqt;
  14. jpeg_dht m_dht;
  15. jpeg_idct m_idct;
  16. jpeg_bit_buffer m_bit_buffer;
  17. jpeg_mcu_block m_mcu_dec;
  18. jpeg_state() :
  19. m_bit_buffer(bit_buffer, sizeof(bit_buffer)),
  20. m_mcu_dec(&m_bit_buffer, &m_dht)
  21. {
  22. }
  23. private:
  24. uint8_t bit_buffer[1<<20];
  25. };
  26. static uint16_t m_width;
  27. static uint16_t m_height;
  28. typedef enum eJpgMode
  29. {
  30. JPEG_MONOCHROME,
  31. JPEG_YCBCR_444,
  32. JPEG_YCBCR_420,
  33. JPEG_UNSUPPORTED
  34. } t_jpeg_mode;
  35. static t_jpeg_mode m_mode;
  36. static uint8_t m_dqt_table[3];
  37. #define get_byte(_buf, _idx) _buf[_idx++]
  38. #define get_word(_buf, _idx) ((_buf[_idx++] << 8) | (_buf[_idx++]))
  39. static uint8_t m_output_r[640*480];
  40. static uint8_t m_output_g[640*480];
  41. static uint8_t m_output_b[640*480];
  42. //#define dprintf_blk(_name, _arr, _max) for (int __i=0;__i<_max;__i++) { dprintf("%s: %d -> %d\n", _name, __i, _arr[__i]); }
  43. #define dprintf_blk(_name, _arr, _max) dprintf("BLK, max %d\n", _max);
  44. //-----------------------------------------------------------------------------
  45. // ConvertYUV2RGB: Convert from YUV to RGB
  46. //-----------------------------------------------------------------------------
  47. static void ConvertYUV2RGB(int block_num, int *y, int *cb, int *cr)
  48. {
  49. int x_blocks = (m_width / 8);
  50. // If width is not a multiple of 8, round up
  51. if (m_width % 8)
  52. x_blocks++;
  53. int x_start = (block_num % x_blocks) * 8;
  54. int y_start = (block_num / x_blocks) * 8;
  55. if (m_mode == JPEG_MONOCHROME)
  56. {
  57. for (int i=0;i<64;i++)
  58. {
  59. int r = 128 + y[i];
  60. int g = 128 + y[i];
  61. int b = 128 + y[i];
  62. // Avoid overflows
  63. r = (r & 0xffffff00) ? (r >> 24) ^ 0xff : r;
  64. g = (g & 0xffffff00) ? (g >> 24) ^ 0xff : g;
  65. b = (b & 0xffffff00) ? (b >> 24) ^ 0xff : b;
  66. int _x = x_start + (i % 8);
  67. int _y = y_start + (i / 8);
  68. int offset = (_y * m_width) + _x;
  69. dprintf("RGB: r=%d g=%d b=%d -> %d\n", r, g, b, offset);
  70. m_output_r[offset] = r;
  71. m_output_g[offset] = g;
  72. m_output_b[offset] = b;
  73. }
  74. }
  75. else
  76. {
  77. for (int i=0;i<64;i++)
  78. {
  79. int r = 128 + y[i] + (cr[i] * 1.402);
  80. int g = 128 + y[i] - (cb[i] * 0.34414) - (cr[i] * 0.71414);
  81. int b = 128 + y[i] + (cb[i] * 1.772);
  82. // Avoid overflows
  83. r = (r & 0xffffff00) ? (r >> 24) ^ 0xff : r;
  84. g = (g & 0xffffff00) ? (g >> 24) ^ 0xff : g;
  85. b = (b & 0xffffff00) ? (b >> 24) ^ 0xff : b;
  86. int _x = x_start + (i % 8);
  87. int _y = y_start + (i / 8);
  88. int offset = (_y * m_width) + _x;
  89. if (_x < m_width && _y < m_height)
  90. {
  91. dprintf("RGB: r=%d g=%d b=%d -> %d [x=%d,y=%d]\n", r, g, b, offset, _x, _y);
  92. m_output_r[offset] = r;
  93. m_output_g[offset] = g;
  94. m_output_b[offset] = b;
  95. }
  96. }
  97. }
  98. }
  99. //-----------------------------------------------------------------------------
  100. // DecodeImage: Decode image data section (supports 4:4:4, 4:2:0, monochrom)
  101. //-----------------------------------------------------------------------------
  102. static bool DecodeImage(jpeg_state& st)
  103. {
  104. jpeg_dqt& m_dqt = st.m_dqt;
  105. jpeg_dht& m_dht = st.m_dht;
  106. jpeg_idct& m_idct = st.m_idct;
  107. jpeg_bit_buffer& m_bit_buffer = st.m_bit_buffer;
  108. jpeg_mcu_block& m_mcu_dec = st.m_mcu_dec;
  109. int16_t dc_coeff_Y = 0;
  110. int16_t dc_coeff_Cb= 0;
  111. int16_t dc_coeff_Cr= 0;
  112. int32_t sample_out[64];
  113. int block_out[64];
  114. int y_dct_out[4*64];
  115. int cb_dct_out[64];
  116. int cr_dct_out[64];
  117. int count = 0;
  118. int loop = 0;
  119. int block_num = 0;
  120. while (!m_bit_buffer.eof())
  121. {
  122. // [Y0 Y1 Y2 Y3 Cb Cr] x N
  123. if (m_mode == JPEG_YCBCR_420)
  124. {
  125. dprintf("In DecodeImage:%d\r\n", __LINE__);
  126. // Y0
  127. count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
  128. dprintf("In DecodeImage:%d, count %d\r\n", __LINE__, count);
  129. m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
  130. dprintf_blk("DCT-IN", block_out, 64);
  131. m_idct.process(block_out, &y_dct_out[0]);
  132. dprintf("In DecodeImage:%d\r\n", __LINE__);
  133. // Y1
  134. count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
  135. m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
  136. dprintf_blk("DCT-IN", block_out, 64);
  137. m_idct.process(block_out, &y_dct_out[64]);
  138. dprintf("In DecodeImage:%d\r\n", __LINE__);
  139. // Y2
  140. count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
  141. m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
  142. dprintf_blk("DCT-IN", block_out, 64);
  143. m_idct.process(block_out, &y_dct_out[128]);
  144. dprintf("In DecodeImage:%d\r\n", __LINE__);
  145. // Y3
  146. count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
  147. m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
  148. dprintf_blk("DCT-IN", block_out, 64);
  149. m_idct.process(block_out, &y_dct_out[192]);
  150. dprintf("In DecodeImage:%d\r\n", __LINE__);
  151. // Cb
  152. count = m_mcu_dec.decode(DHT_TABLE_CX_DC_IDX, dc_coeff_Cb, sample_out);
  153. m_dqt.process_samples(m_dqt_table[1], sample_out, block_out, count);
  154. dprintf_blk("DCT-IN", block_out, 64);
  155. m_idct.process(block_out, &cb_dct_out[0]);
  156. dprintf("In DecodeImage:%d\r\n", __LINE__);
  157. // Cr
  158. count = m_mcu_dec.decode(DHT_TABLE_CX_DC_IDX, dc_coeff_Cr, sample_out);
  159. m_dqt.process_samples(m_dqt_table[2], sample_out, block_out, count);
  160. dprintf_blk("DCT-IN", block_out, 64);
  161. m_idct.process(block_out, &cr_dct_out[0]);
  162. // Expand Cb/Cr samples to match Y0-3
  163. int cb_dct_out_x2[256];
  164. int cr_dct_out_x2[256];
  165. for (int i=0;i<64;i++)
  166. {
  167. int x = i % 8;
  168. int y = i / 16;
  169. int sub_idx = (y * 8) + (x / 2);
  170. cb_dct_out_x2[i] = cb_dct_out[sub_idx];
  171. cr_dct_out_x2[i] = cr_dct_out[sub_idx];
  172. }
  173. for (int i=0;i<64;i++)
  174. {
  175. int x = i % 8;
  176. int y = i / 16;
  177. int sub_idx = (y * 8) + 4 + (x / 2);
  178. cb_dct_out_x2[64 + i] = cb_dct_out[sub_idx];
  179. cr_dct_out_x2[64 + i] = cr_dct_out[sub_idx];
  180. }
  181. for (int i=0;i<64;i++)
  182. {
  183. int x = i % 8;
  184. int y = i / 16;
  185. int sub_idx = 32 + (y * 8) + (x / 2);
  186. cb_dct_out_x2[128+i] = cb_dct_out[sub_idx];
  187. cr_dct_out_x2[128+i] = cr_dct_out[sub_idx];
  188. }
  189. for (int i=0;i<64;i++)
  190. {
  191. int x = i % 8;
  192. int y = i / 16;
  193. int sub_idx = 32 + (y * 8) + 4 + (x / 2);
  194. cb_dct_out_x2[192 + i] = cb_dct_out[sub_idx];
  195. cr_dct_out_x2[192 + i] = cr_dct_out[sub_idx];
  196. }
  197. int mcu_width = m_width / 8;
  198. if (m_width % 8)
  199. mcu_width++;
  200. // Output all 4 blocks of pixels
  201. ConvertYUV2RGB((block_num/2) + 0, &y_dct_out[0], &cb_dct_out_x2[0], &cr_dct_out_x2[0]);
  202. ConvertYUV2RGB((block_num/2) + 1, &y_dct_out[64], &cb_dct_out_x2[64], &cr_dct_out_x2[64]);
  203. ConvertYUV2RGB((block_num/2) + mcu_width + 0, &y_dct_out[128], &cb_dct_out_x2[128], &cr_dct_out_x2[128]);
  204. ConvertYUV2RGB((block_num/2) + mcu_width + 1, &y_dct_out[192], &cb_dct_out_x2[192], &cr_dct_out_x2[192]);
  205. block_num += 4;
  206. if (++loop == (mcu_width / 2))
  207. {
  208. block_num += (mcu_width * 2);
  209. loop = 0;
  210. }
  211. }
  212. // [Y Cb Cr] x N
  213. else if (m_mode == JPEG_YCBCR_444)
  214. {
  215. // Y
  216. count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
  217. m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
  218. dprintf_blk("DCT-IN", block_out, 64);
  219. m_idct.process(block_out, &y_dct_out[0]);
  220. // Cb
  221. count = m_mcu_dec.decode(DHT_TABLE_CX_DC_IDX, dc_coeff_Cb, sample_out);
  222. m_dqt.process_samples(m_dqt_table[1], sample_out, block_out, count);
  223. dprintf_blk("DCT-IN", block_out, 64);
  224. m_idct.process(block_out, &cb_dct_out[0]);
  225. // Cr
  226. count = m_mcu_dec.decode(DHT_TABLE_CX_DC_IDX, dc_coeff_Cr, sample_out);
  227. m_dqt.process_samples(m_dqt_table[2], sample_out, block_out, count);
  228. dprintf_blk("DCT-IN", block_out, 64);
  229. m_idct.process(block_out, &cr_dct_out[0]);
  230. ConvertYUV2RGB(block_num++, y_dct_out, cb_dct_out, cr_dct_out);
  231. }
  232. // [Y] x N
  233. else if (m_mode == JPEG_MONOCHROME)
  234. {
  235. // Y
  236. count = m_mcu_dec.decode(DHT_TABLE_Y_DC_IDX, dc_coeff_Y, sample_out);
  237. m_dqt.process_samples(m_dqt_table[0], sample_out, block_out, count);
  238. dprintf_blk("DCT-IN", block_out, 64);
  239. m_idct.process(block_out, &y_dct_out[0]);
  240. ConvertYUV2RGB(block_num++, y_dct_out, cb_dct_out, cr_dct_out);
  241. }
  242. }
  243. return true;
  244. }
  245. extern "C" int ultraembedded_jpeg_decompress(const uint8_t *jpegdata, size_t jpegdata_size, uint8_t *dst)
  246. {
  247. #warning this needs to be initialized here until calling c++ constructors from the linker script works
  248. static jpeg_state st;
  249. jpeg_dqt& m_dqt = st.m_dqt;
  250. jpeg_dht& m_dht = st.m_dht;
  251. jpeg_idct& m_idct = st.m_idct;
  252. jpeg_bit_buffer& m_bit_buffer = st.m_bit_buffer;
  253. jpeg_mcu_block& m_mcu_dec = st.m_mcu_dec;
  254. // source data file
  255. uint8_t *buf = (uint8_t *) jpegdata;
  256. int len = jpegdata_size;
  257. m_dqt.reset();
  258. m_dht.reset();
  259. m_idct.reset();
  260. m_mode = JPEG_UNSUPPORTED;
  261. uint8_t last_b = 0;
  262. int decode_done = 0;
  263. for (int i=0;i<len;)
  264. {
  265. if(last_b == 0xFF)
  266. dprintf("New section at offset %d:\r\n", i);
  267. uint8_t b = buf[i++];
  268. //-----------------------------------------------------------------------------
  269. // SOI: Start of image
  270. //-----------------------------------------------------------------------------
  271. if (last_b == 0xFF && b == 0xd8)
  272. dprintf("Section: SOI\r\n");
  273. //-----------------------------------------------------------------------------
  274. // SOF0: Indicates that this is a baseline DCT-based JPEG
  275. //-----------------------------------------------------------------------------
  276. else if (last_b == 0xFF && b == 0xc0)
  277. {
  278. dprintf("Section: SOF0\r\n");
  279. int seg_start = i;
  280. // Length of the segment
  281. uint16_t seg_len = get_word(buf, i);
  282. // Precision of the frame data
  283. uint8_t precision = get_byte(buf,i);
  284. // Image height in pixels
  285. m_height = get_word(buf, i);
  286. // Image width in pixels
  287. m_width = get_word(buf, i);
  288. if(m_width != 640 || m_height != 480)
  289. return 0;
  290. //FIXME: needed?
  291. memset(m_output_r, 0, m_height * m_width);
  292. memset(m_output_g, 0, m_height * m_width);
  293. memset(m_output_b, 0, m_height * m_width);
  294. // # of components (n) in frame, 1 for monochrom, 3 for colour images
  295. uint8_t num_comps = get_byte(buf,i);
  296. assert(num_comps <= 3);
  297. dprintf(" x=%d, y=%d, components=%d\r\n", m_width, m_height, num_comps);
  298. uint8_t comp_id[3];
  299. uint8_t comp_sample_factor[3];
  300. uint8_t horiz_factor[3];
  301. uint8_t vert_factor[3];
  302. for (int x=0;x<num_comps;x++)
  303. {
  304. // First byte identifies the component
  305. comp_id[x] = get_byte(buf,i);
  306. // id: 1 = Y, 2 = Cb, 3 = Cr
  307. // Second byte represents sampling factor (first four MSBs represent horizonal, last four LSBs represent vertical)
  308. comp_sample_factor[x] = get_byte(buf,i);
  309. horiz_factor[x] = comp_sample_factor[x] >> 4;
  310. vert_factor[x] = comp_sample_factor[x] & 0xF;
  311. // Third byte represents which quantization table to use for this component
  312. m_dqt_table[x] = get_byte(buf,i);
  313. dprintf(" num: %d a: %02x b: %02x\r\n", comp_id[x], comp_sample_factor[x], m_dqt_table[x]);
  314. dprintf(" horiz_factor: %d, vert_factor: %d\r\n", horiz_factor[x], vert_factor[x]);
  315. }
  316. m_mode = JPEG_UNSUPPORTED;
  317. // Single component (Y)
  318. if (num_comps == 1)
  319. {
  320. dprintf(" Mode: Monochrome\r\n");
  321. m_mode = JPEG_MONOCHROME;
  322. }
  323. // Colour image (YCbCr)
  324. else if (num_comps == 3)
  325. {
  326. // YCbCr ordering expected
  327. if (comp_id[0] == 1 && comp_id[1] == 2 && comp_id[2] == 3)
  328. {
  329. if (horiz_factor[0] == 1 && vert_factor[0] == 1 &&
  330. horiz_factor[1] == 1 && vert_factor[1] == 1 &&
  331. horiz_factor[2] == 1 && vert_factor[2] == 1)
  332. {
  333. m_mode = JPEG_YCBCR_444;
  334. dprintf(" Mode: YCbCr 4:4:4\r\n");
  335. }
  336. else if (horiz_factor[0] == 2 && vert_factor[0] == 2 &&
  337. horiz_factor[1] == 1 && vert_factor[1] == 1 &&
  338. horiz_factor[2] == 1 && vert_factor[2] == 1)
  339. {
  340. m_mode = JPEG_YCBCR_420;
  341. dprintf(" Mode: YCbCr 4:2:0\r\n");
  342. }
  343. }
  344. }
  345. i = seg_start + seg_len;
  346. }
  347. //-----------------------------------------------------------------------------
  348. // DQT: Quantisation table
  349. //-----------------------------------------------------------------------------
  350. else if (last_b == 0xFF && b == 0xdb)
  351. {
  352. dprintf("Section: DQT Table\r\n");
  353. int seg_start = i;
  354. uint16_t seg_len = get_word(buf, i);
  355. m_dqt.process(&buf[i], seg_len);
  356. i = seg_start + seg_len;
  357. }
  358. //-----------------------------------------------------------------------------
  359. // DHT: Huffman table
  360. //-----------------------------------------------------------------------------
  361. else if (last_b == 0xFF && b == 0xc4)
  362. {
  363. int seg_start = i;
  364. uint16_t seg_len = get_word(buf, i);
  365. dprintf("Section: DHT Table\r\n");
  366. m_dht.process(&buf[i], seg_len);
  367. i = seg_start + seg_len;
  368. }
  369. //-----------------------------------------------------------------------------
  370. // EOI: End of image
  371. //-----------------------------------------------------------------------------
  372. else if (last_b == 0xFF && b == 0xd9)
  373. {
  374. dprintf("Section: EOI\r\n");
  375. break;
  376. }
  377. //-----------------------------------------------------------------------------
  378. // SOS: Start of Scan Segment (SOS)
  379. //-----------------------------------------------------------------------------
  380. else if (last_b == 0xFF && b == 0xda)
  381. {
  382. dprintf("Section: SOS\r\n");
  383. int seg_start = i;
  384. if (m_mode == JPEG_UNSUPPORTED)
  385. {
  386. dprintf("ERROR: Unsupported JPEG mode\r\n");
  387. break;
  388. }
  389. uint16_t seg_len = get_word(buf, i);
  390. // Component count (n)
  391. uint8_t comp_count = get_byte(buf,i);
  392. // Component data
  393. for (int x=0;x<comp_count;x++)
  394. {
  395. // First byte denotes component ID
  396. uint8_t comp_id = get_byte(buf,i);
  397. // Second byte denotes the Huffman table used (first four MSBs denote Huffman table for DC, and last four LSBs denote Huffman table for AC)
  398. uint8_t comp_table = get_byte(buf,i);
  399. dprintf(" %d: ID=%x Table=%x\r\n", x, comp_id, comp_table);
  400. }
  401. // Skip bytes
  402. get_byte(buf,i);
  403. get_byte(buf,i);
  404. get_byte(buf,i);
  405. i = seg_start + seg_len;
  406. //-----------------------------------------------------------------------
  407. // Process data segment
  408. //-----------------------------------------------------------------------
  409. if(last_b == 0xFF)
  410. dprintf("Reset bit_buffer to %d:\r\n", len);
  411. m_bit_buffer.reset(len);
  412. while (i < len)
  413. {
  414. b = buf[i];
  415. if (m_bit_buffer.push(b))
  416. i++;
  417. // Marker detected (reverse one byte)
  418. else
  419. {
  420. i--;
  421. break;
  422. }
  423. }
  424. decode_done = DecodeImage(st);
  425. }
  426. //-----------------------------------------------------------------------------
  427. // Unsupported / Skipped
  428. //-----------------------------------------------------------------------------
  429. else if (last_b == 0xFF && b == 0xc2)
  430. {
  431. dprintf("Section: SOF2\r\n");
  432. int seg_start = i;
  433. uint16_t seg_len = get_word(buf, i);
  434. i = seg_start + seg_len;
  435. dprintf("ERROR: Progressive JPEG not supported\r\n");
  436. break; // ERROR: Not supported
  437. }
  438. else if (last_b == 0xFF && b == 0xdd)
  439. {
  440. dprintf("Section: DRI\r\n");
  441. int seg_start = i;
  442. uint16_t seg_len = get_word(buf, i);
  443. i = seg_start + seg_len;
  444. }
  445. else if (last_b == 0xFF && b >= 0xd0 && b <= 0xd7)
  446. {
  447. dprintf("Section: RST%d\r\n", b - 0xd0);
  448. int seg_start = i;
  449. uint16_t seg_len = get_word(buf, i);
  450. i = seg_start + seg_len;
  451. }
  452. else if (last_b == 0xFF && b >= 0xe0 && b <= 0xef)
  453. {
  454. dprintf("Section: APP%d\r\n", b - 0xe0);
  455. int seg_start = i;
  456. uint16_t seg_len = get_word(buf, i);
  457. i = seg_start + seg_len;
  458. }
  459. else if (last_b == 0xFF && b == 0xfe)
  460. {
  461. dprintf("Section: COM\r\n");
  462. int seg_start = i;
  463. uint16_t seg_len = get_word(buf, i);
  464. i = seg_start + seg_len;
  465. }
  466. last_b = b;
  467. }
  468. if (decode_done)
  469. {
  470. #warning don't assume all dest bytes are contiguous
  471. for (int y=0;y<m_height;y++)
  472. for (int x=0;x<m_width;x++)
  473. {
  474. if(x < m_width -1) //this is to avoid last column
  475. {
  476. dst[0] = m_output_r[(y*m_width)+x];
  477. dst[1] = m_output_g[(y*m_width)+x];
  478. dst[2] = m_output_b[(y*m_width)+x];
  479. }
  480. dst += sizeof(uint32_t);
  481. }
  482. dprintf("Done decoding\r\n");
  483. }
  484. else
  485. dprintf("ERROR: Can't decode\r\n");
  486. return decode_done ? 0 : -1;
  487. }