Any changes are to allow conversion to BMP
Dependencies: BaseJpegDecode Camera_LS_Y201 Motordriver Servo mbed
Fork of Bitmap_copy_copy by
SimpleJpegDecode/SimpleJpegDecode.cpp@1:d721e32cf79c, 2014-04-30 (annotated)
- Committer:
- kylepost3
- Date:
- Wed Apr 30 14:19:33 2014 +0000
- Revision:
- 1:d721e32cf79c
Final design project for ECE 4180. The device takes scans left to right taking pictures (In JPEG), converts the picture to BMP, and scans for red pixels. When the threshold of red pixels is reached, it fires the catapult and reloads.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kylepost3 | 1:d721e32cf79c | 1 | #include "SimpleJpegDecode.h" |
kylepost3 | 1:d721e32cf79c | 2 | |
kylepost3 | 1:d721e32cf79c | 3 | #define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0); |
kylepost3 | 1:d721e32cf79c | 4 | #define ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; |
kylepost3 | 1:d721e32cf79c | 5 | |
kylepost3 | 1:d721e32cf79c | 6 | |
kylepost3 | 1:d721e32cf79c | 7 | #define _1_4020 45 |
kylepost3 | 1:d721e32cf79c | 8 | #define _0_3441 11 |
kylepost3 | 1:d721e32cf79c | 9 | #define _0_7139 23 |
kylepost3 | 1:d721e32cf79c | 10 | #define _1_7718 57 |
kylepost3 | 1:d721e32cf79c | 11 | #define _0_0012 0 |
kylepost3 | 1:d721e32cf79c | 12 | |
kylepost3 | 1:d721e32cf79c | 13 | int adjust(int r) { |
kylepost3 | 1:d721e32cf79c | 14 | if (r >= 0) { |
kylepost3 | 1:d721e32cf79c | 15 | if (r <= 255) { |
kylepost3 | 1:d721e32cf79c | 16 | return r; |
kylepost3 | 1:d721e32cf79c | 17 | } else { |
kylepost3 | 1:d721e32cf79c | 18 | return 255; |
kylepost3 | 1:d721e32cf79c | 19 | } |
kylepost3 | 1:d721e32cf79c | 20 | } else { |
kylepost3 | 1:d721e32cf79c | 21 | return 0; |
kylepost3 | 1:d721e32cf79c | 22 | } |
kylepost3 | 1:d721e32cf79c | 23 | } |
kylepost3 | 1:d721e32cf79c | 24 | |
kylepost3 | 1:d721e32cf79c | 25 | void convYUVtoRGB(uint8_t rgb[], int y, int u, int v) |
kylepost3 | 1:d721e32cf79c | 26 | { |
kylepost3 | 1:d721e32cf79c | 27 | rgb[0] = adjust((y*32 + v*_1_4020)/32 + 128); |
kylepost3 | 1:d721e32cf79c | 28 | rgb[1] = adjust((y*32 - u*_0_3441 - v*_0_7139)/32 + 128); |
kylepost3 | 1:d721e32cf79c | 29 | rgb[2] = adjust((y*32 + u*_1_7718 - v*_0_0012)/32 + 128); |
kylepost3 | 1:d721e32cf79c | 30 | } |
kylepost3 | 1:d721e32cf79c | 31 | |
kylepost3 | 1:d721e32cf79c | 32 | SimpleJpegDecode::SimpleJpegDecode(uint8_t output_mode) |
kylepost3 | 1:d721e32cf79c | 33 | { |
kylepost3 | 1:d721e32cf79c | 34 | m_output_mode = output_mode; |
kylepost3 | 1:d721e32cf79c | 35 | clearOnResult(); |
kylepost3 | 1:d721e32cf79c | 36 | } |
kylepost3 | 1:d721e32cf79c | 37 | |
kylepost3 | 1:d721e32cf79c | 38 | |
kylepost3 | 1:d721e32cf79c | 39 | void SimpleJpegDecode::output(int mcu, int block, int scan, int value) |
kylepost3 | 1:d721e32cf79c | 40 | { |
kylepost3 | 1:d721e32cf79c | 41 | int sc = (block < yblock) ? 0 : 1; |
kylepost3 | 1:d721e32cf79c | 42 | inputBLOCK(mcu, block, scan, value * qt[sc][scan]); |
kylepost3 | 1:d721e32cf79c | 43 | } |
kylepost3 | 1:d721e32cf79c | 44 | |
kylepost3 | 1:d721e32cf79c | 45 | void SimpleJpegDecode::outputDC(int mcu, int block, int value) |
kylepost3 | 1:d721e32cf79c | 46 | { |
kylepost3 | 1:d721e32cf79c | 47 | output(mcu, block, 0, value); |
kylepost3 | 1:d721e32cf79c | 48 | DC_count++; |
kylepost3 | 1:d721e32cf79c | 49 | } |
kylepost3 | 1:d721e32cf79c | 50 | |
kylepost3 | 1:d721e32cf79c | 51 | void SimpleJpegDecode::outputAC(int mcu, int block, int scan, int value) |
kylepost3 | 1:d721e32cf79c | 52 | { |
kylepost3 | 1:d721e32cf79c | 53 | output(mcu, block, scan, value); |
kylepost3 | 1:d721e32cf79c | 54 | AC_count++; |
kylepost3 | 1:d721e32cf79c | 55 | } |
kylepost3 | 1:d721e32cf79c | 56 | |
kylepost3 | 1:d721e32cf79c | 57 | void SimpleJpegDecode::outputMARK(uint8_t c) |
kylepost3 | 1:d721e32cf79c | 58 | { |
kylepost3 | 1:d721e32cf79c | 59 | } |
kylepost3 | 1:d721e32cf79c | 60 | |
kylepost3 | 1:d721e32cf79c | 61 | void SimpleJpegDecode::format_YUV(int mcu, int block, int8_t* values) |
kylepost3 | 1:d721e32cf79c | 62 | { |
kylepost3 | 1:d721e32cf79c | 63 | if (block < yblock+1) { |
kylepost3 | 1:d721e32cf79c | 64 | memcpy(m_block_data[block], values, 64); |
kylepost3 | 1:d721e32cf79c | 65 | return; |
kylepost3 | 1:d721e32cf79c | 66 | } |
kylepost3 | 1:d721e32cf79c | 67 | int mcu_x_count = (width+15)/16; |
kylepost3 | 1:d721e32cf79c | 68 | int mcu_x = mcu % mcu_x_count; |
kylepost3 | 1:d721e32cf79c | 69 | int mcu_y = mcu / mcu_x_count; |
kylepost3 | 1:d721e32cf79c | 70 | uint8_t yuv[3]; |
kylepost3 | 1:d721e32cf79c | 71 | if (yblock == 2) { |
kylepost3 | 1:d721e32cf79c | 72 | for(int y = 0; y < 8; y++) { |
kylepost3 | 1:d721e32cf79c | 73 | for(int x = 0; x < 16; x++) { |
kylepost3 | 1:d721e32cf79c | 74 | yuv[0] = m_block_data[x/8][y*8+x%8] + 128; |
kylepost3 | 1:d721e32cf79c | 75 | yuv[1] = m_block_data[2][y*8+x/2] + 128; |
kylepost3 | 1:d721e32cf79c | 76 | yuv[2] = values[y*8+x/2] + 128; |
kylepost3 | 1:d721e32cf79c | 77 | onResult(mcu_x * 16 + x, mcu_y * 8 + y, yuv); |
kylepost3 | 1:d721e32cf79c | 78 | } |
kylepost3 | 1:d721e32cf79c | 79 | } |
kylepost3 | 1:d721e32cf79c | 80 | } else if (yblock == 4) { |
kylepost3 | 1:d721e32cf79c | 81 | for(int y = 0; y < 16; y++) { |
kylepost3 | 1:d721e32cf79c | 82 | for(int x = 0; x < 16; x++) { |
kylepost3 | 1:d721e32cf79c | 83 | yuv[0] = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8] + 128; |
kylepost3 | 1:d721e32cf79c | 84 | yuv[1] = m_block_data[4][(y/2)*8+x/2] + 128; |
kylepost3 | 1:d721e32cf79c | 85 | yuv[2] = values[(y/2)*8+x/2] + 128; |
kylepost3 | 1:d721e32cf79c | 86 | onResult(mcu_x * 16 + x, mcu_y * 16 + y, yuv); |
kylepost3 | 1:d721e32cf79c | 87 | } |
kylepost3 | 1:d721e32cf79c | 88 | } |
kylepost3 | 1:d721e32cf79c | 89 | } else { |
kylepost3 | 1:d721e32cf79c | 90 | ASSERT(yblock == 2 || yblock == 4); |
kylepost3 | 1:d721e32cf79c | 91 | } |
kylepost3 | 1:d721e32cf79c | 92 | } |
kylepost3 | 1:d721e32cf79c | 93 | |
kylepost3 | 1:d721e32cf79c | 94 | void SimpleJpegDecode::format_RGB24(int mcu, int block, int8_t* values) |
kylepost3 | 1:d721e32cf79c | 95 | { |
kylepost3 | 1:d721e32cf79c | 96 | if (block < yblock+1) { |
kylepost3 | 1:d721e32cf79c | 97 | memcpy(m_block_data[block], values, 64); |
kylepost3 | 1:d721e32cf79c | 98 | return; |
kylepost3 | 1:d721e32cf79c | 99 | } |
kylepost3 | 1:d721e32cf79c | 100 | int mcu_x_count = (width+15)/16; |
kylepost3 | 1:d721e32cf79c | 101 | int mcu_x = mcu % mcu_x_count; |
kylepost3 | 1:d721e32cf79c | 102 | int mcu_y = mcu / mcu_x_count; |
kylepost3 | 1:d721e32cf79c | 103 | uint8_t rgb[3]; |
kylepost3 | 1:d721e32cf79c | 104 | if (yblock == 2) { |
kylepost3 | 1:d721e32cf79c | 105 | for(int y = 0; y < 8; y++) { |
kylepost3 | 1:d721e32cf79c | 106 | for(int x = 0; x < 16; x++) { |
kylepost3 | 1:d721e32cf79c | 107 | int8_t yuv_y = m_block_data[x/8][y*8+x%8]; |
kylepost3 | 1:d721e32cf79c | 108 | int8_t yuv_u = m_block_data[2][y*8+x/2]; |
kylepost3 | 1:d721e32cf79c | 109 | int8_t yuv_v = values[y*8+x/2]; |
kylepost3 | 1:d721e32cf79c | 110 | convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v); |
kylepost3 | 1:d721e32cf79c | 111 | onResult(mcu_x * 16 + x, mcu_y * 8 + y, rgb); |
kylepost3 | 1:d721e32cf79c | 112 | } |
kylepost3 | 1:d721e32cf79c | 113 | } |
kylepost3 | 1:d721e32cf79c | 114 | } else if (yblock == 4) { |
kylepost3 | 1:d721e32cf79c | 115 | for(int y = 0; y < 16; y++) { |
kylepost3 | 1:d721e32cf79c | 116 | for(int x = 0; x < 16; x++) { |
kylepost3 | 1:d721e32cf79c | 117 | int8_t yuv_y = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8]; |
kylepost3 | 1:d721e32cf79c | 118 | int8_t yuv_u = m_block_data[4][(y/2)*8+x/2]; |
kylepost3 | 1:d721e32cf79c | 119 | int8_t yuv_v = values[(y/2)*8+x/2]; |
kylepost3 | 1:d721e32cf79c | 120 | convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v); |
kylepost3 | 1:d721e32cf79c | 121 | onResult(mcu_x * 16 + x, mcu_y * 16 + y, rgb); |
kylepost3 | 1:d721e32cf79c | 122 | } |
kylepost3 | 1:d721e32cf79c | 123 | } |
kylepost3 | 1:d721e32cf79c | 124 | } else { |
kylepost3 | 1:d721e32cf79c | 125 | ASSERT(yblock == 2 || yblock == 4); |
kylepost3 | 1:d721e32cf79c | 126 | } |
kylepost3 | 1:d721e32cf79c | 127 | } |
kylepost3 | 1:d721e32cf79c | 128 | |
kylepost3 | 1:d721e32cf79c | 129 | void SimpleJpegDecode::outputBLOCK(int mcu, int block, int8_t* values) |
kylepost3 | 1:d721e32cf79c | 130 | { |
kylepost3 | 1:d721e32cf79c | 131 | BLOCK_count++; |
kylepost3 | 1:d721e32cf79c | 132 | if (m_output_mode == YUV) { |
kylepost3 | 1:d721e32cf79c | 133 | format_YUV(mcu, block, values); |
kylepost3 | 1:d721e32cf79c | 134 | } else if (m_output_mode == RGB24) { |
kylepost3 | 1:d721e32cf79c | 135 | format_RGB24(mcu, block, values); |
kylepost3 | 1:d721e32cf79c | 136 | } else { |
kylepost3 | 1:d721e32cf79c | 137 | ASSERT(m_output_mode == YUV || m_output_mode == RGB24); |
kylepost3 | 1:d721e32cf79c | 138 | } |
kylepost3 | 1:d721e32cf79c | 139 | } |
kylepost3 | 1:d721e32cf79c | 140 | |
kylepost3 | 1:d721e32cf79c | 141 | void SimpleJpegDecode::onResult(int x, int y, uint8_t* yuv) |
kylepost3 | 1:d721e32cf79c | 142 | { |
kylepost3 | 1:d721e32cf79c | 143 | if(m_pCbItem && m_pCbMeth) |
kylepost3 | 1:d721e32cf79c | 144 | (m_pCbItem->*m_pCbMeth)(x, y, yuv); |
kylepost3 | 1:d721e32cf79c | 145 | else if(m_pCb) |
kylepost3 | 1:d721e32cf79c | 146 | m_pCb(x, y, yuv); |
kylepost3 | 1:d721e32cf79c | 147 | } |
kylepost3 | 1:d721e32cf79c | 148 | |
kylepost3 | 1:d721e32cf79c | 149 | void SimpleJpegDecode::setOnResult( void (*pMethod)(int, int, uint8_t*) ) |
kylepost3 | 1:d721e32cf79c | 150 | { |
kylepost3 | 1:d721e32cf79c | 151 | m_pCb = pMethod; |
kylepost3 | 1:d721e32cf79c | 152 | m_pCbItem = NULL; |
kylepost3 | 1:d721e32cf79c | 153 | m_pCbMeth = NULL; |
kylepost3 | 1:d721e32cf79c | 154 | } |
kylepost3 | 1:d721e32cf79c | 155 | |
kylepost3 | 1:d721e32cf79c | 156 | void SimpleJpegDecode::clearOnResult() |
kylepost3 | 1:d721e32cf79c | 157 | { |
kylepost3 | 1:d721e32cf79c | 158 | m_pCb = NULL; |
kylepost3 | 1:d721e32cf79c | 159 | m_pCbItem = NULL; |
kylepost3 | 1:d721e32cf79c | 160 | m_pCbMeth = NULL; |
kylepost3 | 1:d721e32cf79c | 161 | } |