Any changes are to allow conversion to BMP
Dependents: Color_Targeting_Catapult
Fork of BaseJpegDecode by
BaseJpegDecode.cpp@3:a7547692071d, 2012-11-05 (annotated)
- Committer:
- va009039
- Date:
- Mon Nov 05 22:47:05 2012 +0000
- Revision:
- 3:a7547692071d
- Parent:
- 2:5b1dd4e34857
- Child:
- 4:e243fa781e5c
change to AAN inverse DCT
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 1:bfbc18000cca | 1 | #include "mbed.h" |
va009039 | 1:bfbc18000cca | 2 | #include "BaseJpegDecode.h" |
va009039 | 1:bfbc18000cca | 3 | |
va009039 | 1:bfbc18000cca | 4 | #if 0 |
va009039 | 1:bfbc18000cca | 5 | #define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0); |
va009039 | 1:bfbc18000cca | 6 | #define DBG_WAIT(A) wait_ms(A) |
va009039 | 1:bfbc18000cca | 7 | #else |
va009039 | 1:bfbc18000cca | 8 | #define DBG(...) |
va009039 | 1:bfbc18000cca | 9 | #define DBG_WAIT(A) |
va009039 | 1:bfbc18000cca | 10 | #endif |
va009039 | 1:bfbc18000cca | 11 | |
va009039 | 1:bfbc18000cca | 12 | #if 1 |
va009039 | 1:bfbc18000cca | 13 | #define DBG_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; |
va009039 | 1:bfbc18000cca | 14 | #else |
va009039 | 1:bfbc18000cca | 15 | #define DBG_ASSERT(A) |
va009039 | 1:bfbc18000cca | 16 | #endif |
va009039 | 1:bfbc18000cca | 17 | |
va009039 | 1:bfbc18000cca | 18 | #ifdef JPEG_USE_REPORT_CODE |
va009039 | 1:bfbc18000cca | 19 | #define REPORT_CODE(A) (A) |
va009039 | 1:bfbc18000cca | 20 | #else |
va009039 | 1:bfbc18000cca | 21 | #define REPORT_CODE(A) |
va009039 | 1:bfbc18000cca | 22 | #endif |
va009039 | 1:bfbc18000cca | 23 | |
va009039 | 1:bfbc18000cca | 24 | #define MARK_SOF0 0xc0 |
va009039 | 1:bfbc18000cca | 25 | #define MARK_DHT 0xc4 |
va009039 | 1:bfbc18000cca | 26 | #define MARK_RST0 0xd0 |
va009039 | 1:bfbc18000cca | 27 | #define MARK_RST7 0xd7 |
va009039 | 1:bfbc18000cca | 28 | #define MARK_SOI 0xd8 |
va009039 | 1:bfbc18000cca | 29 | #define MARK_EOI 0xd9 |
va009039 | 1:bfbc18000cca | 30 | #define MARK_SOS 0xda |
va009039 | 1:bfbc18000cca | 31 | #define MARK_DQT 0xdb |
va009039 | 1:bfbc18000cca | 32 | #define MARK_DRI 0xdd |
va009039 | 1:bfbc18000cca | 33 | #define MARK_APP 0xe0 |
va009039 | 1:bfbc18000cca | 34 | |
va009039 | 1:bfbc18000cca | 35 | #define SEQ_INIT 0 |
va009039 | 1:bfbc18000cca | 36 | #define SEQ_MARK 1 |
va009039 | 1:bfbc18000cca | 37 | #define SEQ_SEG_LEN 2 |
va009039 | 1:bfbc18000cca | 38 | #define SEQ_SEG_LEN2 3 |
va009039 | 1:bfbc18000cca | 39 | #define SEQ_SEG_BODY 4 |
va009039 | 1:bfbc18000cca | 40 | #define SEQ_SOS 5 |
va009039 | 1:bfbc18000cca | 41 | #define SEQ_SOS2 6 |
va009039 | 1:bfbc18000cca | 42 | |
va009039 | 1:bfbc18000cca | 43 | #define HT_DC 0 |
va009039 | 1:bfbc18000cca | 44 | #define HT_AC 1 |
va009039 | 1:bfbc18000cca | 45 | |
va009039 | 1:bfbc18000cca | 46 | BaseJpegDecode::BaseJpegDecode() |
va009039 | 1:bfbc18000cca | 47 | { |
va009039 | 3:a7547692071d | 48 | yblock = JPEG_MCU_YBLOCK; // 2 or 4 |
va009039 | 1:bfbc18000cca | 49 | clear(); |
va009039 | 1:bfbc18000cca | 50 | pHD = new HuffmanDecode; |
va009039 | 1:bfbc18000cca | 51 | DBG_ASSERT(pHD); |
va009039 | 1:bfbc18000cca | 52 | qt[0] = new uint8_t[64]; |
va009039 | 1:bfbc18000cca | 53 | qt[1] = new uint8_t[64]; |
va009039 | 1:bfbc18000cca | 54 | DBG_ASSERT(qt[0]); |
va009039 | 1:bfbc18000cca | 55 | DBG_ASSERT(qt[1]); |
va009039 | 1:bfbc18000cca | 56 | } |
va009039 | 1:bfbc18000cca | 57 | |
va009039 | 1:bfbc18000cca | 58 | void BaseJpegDecode::clear() |
va009039 | 1:bfbc18000cca | 59 | { |
va009039 | 1:bfbc18000cca | 60 | m_seq = SEQ_INIT; |
va009039 | 1:bfbc18000cca | 61 | } |
va009039 | 1:bfbc18000cca | 62 | |
va009039 | 1:bfbc18000cca | 63 | void BaseJpegDecode::input(uint8_t* buf, int len) |
va009039 | 1:bfbc18000cca | 64 | { |
va009039 | 1:bfbc18000cca | 65 | for(int i = 0; i < len; i++) { |
va009039 | 1:bfbc18000cca | 66 | input(buf[i]); |
va009039 | 1:bfbc18000cca | 67 | } |
va009039 | 1:bfbc18000cca | 68 | } |
va009039 | 1:bfbc18000cca | 69 | |
va009039 | 1:bfbc18000cca | 70 | void BaseJpegDecode::restart() |
va009039 | 1:bfbc18000cca | 71 | { |
va009039 | 1:bfbc18000cca | 72 | m_block = 0; |
va009039 | 1:bfbc18000cca | 73 | m_scan = 0; |
va009039 | 2:5b1dd4e34857 | 74 | m_pre_DC_value[0] = 0; |
va009039 | 2:5b1dd4e34857 | 75 | m_pre_DC_value[1] = 0; |
va009039 | 2:5b1dd4e34857 | 76 | m_pre_DC_value[2] = 0; |
va009039 | 1:bfbc18000cca | 77 | m_bitpat.clear(); |
va009039 | 1:bfbc18000cca | 78 | m_huff = NULL; |
va009039 | 1:bfbc18000cca | 79 | } |
va009039 | 1:bfbc18000cca | 80 | |
va009039 | 1:bfbc18000cca | 81 | void BaseJpegDecode::inputDQT(uint8_t c, int pos, int len) |
va009039 | 1:bfbc18000cca | 82 | { |
va009039 | 1:bfbc18000cca | 83 | if (pos == 0 || pos == 65) { |
va009039 | 1:bfbc18000cca | 84 | m_param1 = c; |
va009039 | 1:bfbc18000cca | 85 | DBG_ASSERT(m_param1 == 0 || m_param1 == 1); |
va009039 | 1:bfbc18000cca | 86 | } else { |
va009039 | 1:bfbc18000cca | 87 | qt[m_param1][(pos%65)-1] = c; |
va009039 | 1:bfbc18000cca | 88 | } |
va009039 | 1:bfbc18000cca | 89 | } |
va009039 | 1:bfbc18000cca | 90 | |
va009039 | 1:bfbc18000cca | 91 | void BaseJpegDecode::inputSOF(uint8_t c, int pos, int len) |
va009039 | 1:bfbc18000cca | 92 | { |
va009039 | 1:bfbc18000cca | 93 | switch(pos) { |
va009039 | 1:bfbc18000cca | 94 | case 1: |
va009039 | 3:a7547692071d | 95 | height = (height&0x00ff) | (c<<8); |
va009039 | 1:bfbc18000cca | 96 | break; |
va009039 | 1:bfbc18000cca | 97 | case 2: |
va009039 | 3:a7547692071d | 98 | height = (height&0xff00) | c; |
va009039 | 3:a7547692071d | 99 | break; |
va009039 | 3:a7547692071d | 100 | case 3: |
va009039 | 3:a7547692071d | 101 | width = (width&0x00ff) | (c<<8); |
va009039 | 1:bfbc18000cca | 102 | break; |
va009039 | 1:bfbc18000cca | 103 | case 4: |
va009039 | 3:a7547692071d | 104 | width = (width&0xff00) | c; |
va009039 | 1:bfbc18000cca | 105 | break; |
va009039 | 1:bfbc18000cca | 106 | case 7: |
va009039 | 1:bfbc18000cca | 107 | if (c == 0x22) { |
va009039 | 3:a7547692071d | 108 | yblock = 4; |
va009039 | 1:bfbc18000cca | 109 | } else if (c == 0x21) { |
va009039 | 3:a7547692071d | 110 | yblock = 2; |
va009039 | 1:bfbc18000cca | 111 | } else { |
va009039 | 1:bfbc18000cca | 112 | DBG_ASSERT(c == 0x22 || c == 0x21); |
va009039 | 1:bfbc18000cca | 113 | } |
va009039 | 1:bfbc18000cca | 114 | break; |
va009039 | 1:bfbc18000cca | 115 | } |
va009039 | 1:bfbc18000cca | 116 | } |
va009039 | 1:bfbc18000cca | 117 | |
va009039 | 1:bfbc18000cca | 118 | void BaseJpegDecode::input(uint8_t c) |
va009039 | 1:bfbc18000cca | 119 | { |
va009039 | 1:bfbc18000cca | 120 | switch(m_seq) { |
va009039 | 1:bfbc18000cca | 121 | case SEQ_INIT: |
va009039 | 1:bfbc18000cca | 122 | if (c == 0xff) { |
va009039 | 1:bfbc18000cca | 123 | m_seq = SEQ_MARK; |
va009039 | 1:bfbc18000cca | 124 | } |
va009039 | 1:bfbc18000cca | 125 | break; |
va009039 | 1:bfbc18000cca | 126 | case SEQ_MARK: |
va009039 | 1:bfbc18000cca | 127 | outputMARK(c); |
va009039 | 1:bfbc18000cca | 128 | if (c == MARK_SOI || c == MARK_EOI) { |
va009039 | 1:bfbc18000cca | 129 | m_seq = SEQ_INIT; |
va009039 | 1:bfbc18000cca | 130 | break; |
va009039 | 1:bfbc18000cca | 131 | } |
va009039 | 1:bfbc18000cca | 132 | m_mark = c; |
va009039 | 1:bfbc18000cca | 133 | m_seq = SEQ_SEG_LEN; |
va009039 | 1:bfbc18000cca | 134 | break; |
va009039 | 1:bfbc18000cca | 135 | case SEQ_SEG_LEN: |
va009039 | 1:bfbc18000cca | 136 | m_seg_len = c; |
va009039 | 1:bfbc18000cca | 137 | m_seq = SEQ_SEG_LEN2; |
va009039 | 1:bfbc18000cca | 138 | break; |
va009039 | 1:bfbc18000cca | 139 | case SEQ_SEG_LEN2: |
va009039 | 1:bfbc18000cca | 140 | m_seg_len <<= 8; |
va009039 | 1:bfbc18000cca | 141 | m_seg_len |= c; |
va009039 | 1:bfbc18000cca | 142 | m_seg_len -= 2; |
va009039 | 1:bfbc18000cca | 143 | m_seg_pos = 0; |
va009039 | 1:bfbc18000cca | 144 | m_seq = SEQ_SEG_BODY; |
va009039 | 1:bfbc18000cca | 145 | break; |
va009039 | 1:bfbc18000cca | 146 | case SEQ_SEG_BODY: |
va009039 | 1:bfbc18000cca | 147 | if (m_mark == MARK_DQT) { |
va009039 | 1:bfbc18000cca | 148 | inputDQT(c, m_seg_pos, m_seg_len); |
va009039 | 1:bfbc18000cca | 149 | } else if (m_mark == MARK_SOF0) { |
va009039 | 1:bfbc18000cca | 150 | inputSOF(c, m_seg_pos, m_seg_len); |
va009039 | 1:bfbc18000cca | 151 | } |
va009039 | 1:bfbc18000cca | 152 | if (++m_seg_pos < m_seg_len) { |
va009039 | 1:bfbc18000cca | 153 | break; |
va009039 | 1:bfbc18000cca | 154 | } |
va009039 | 1:bfbc18000cca | 155 | if (m_mark == MARK_SOS) { |
va009039 | 1:bfbc18000cca | 156 | m_seq = SEQ_SOS; |
va009039 | 1:bfbc18000cca | 157 | m_mcu = 0; |
va009039 | 1:bfbc18000cca | 158 | restart(); |
va009039 | 1:bfbc18000cca | 159 | break; |
va009039 | 1:bfbc18000cca | 160 | } |
va009039 | 1:bfbc18000cca | 161 | m_seq = SEQ_INIT; |
va009039 | 1:bfbc18000cca | 162 | break; |
va009039 | 1:bfbc18000cca | 163 | case SEQ_SOS: |
va009039 | 1:bfbc18000cca | 164 | if (c == 0xff) { |
va009039 | 1:bfbc18000cca | 165 | m_seq = SEQ_SOS2; |
va009039 | 1:bfbc18000cca | 166 | break; |
va009039 | 1:bfbc18000cca | 167 | } |
va009039 | 1:bfbc18000cca | 168 | inputScan(c); |
va009039 | 1:bfbc18000cca | 169 | break; |
va009039 | 1:bfbc18000cca | 170 | case SEQ_SOS2: |
va009039 | 1:bfbc18000cca | 171 | if (c == 0x00) { |
va009039 | 1:bfbc18000cca | 172 | inputScan(0xff); |
va009039 | 1:bfbc18000cca | 173 | m_seq = SEQ_SOS; |
va009039 | 1:bfbc18000cca | 174 | break; |
va009039 | 1:bfbc18000cca | 175 | } else if (c >= MARK_RST0 && c <= MARK_RST7) { |
va009039 | 1:bfbc18000cca | 176 | restart(); |
va009039 | 1:bfbc18000cca | 177 | m_seq = SEQ_SOS; |
va009039 | 1:bfbc18000cca | 178 | break; |
va009039 | 1:bfbc18000cca | 179 | } |
va009039 | 1:bfbc18000cca | 180 | outputMARK(c); |
va009039 | 1:bfbc18000cca | 181 | m_seq = SEQ_INIT; |
va009039 | 1:bfbc18000cca | 182 | break; |
va009039 | 1:bfbc18000cca | 183 | default: |
va009039 | 1:bfbc18000cca | 184 | break; |
va009039 | 1:bfbc18000cca | 185 | } |
va009039 | 1:bfbc18000cca | 186 | } |
va009039 | 1:bfbc18000cca | 187 | |
va009039 | 1:bfbc18000cca | 188 | void BaseJpegDecode::inputScan(uint8_t c) |
va009039 | 1:bfbc18000cca | 189 | { |
va009039 | 1:bfbc18000cca | 190 | m_bitpat += c; |
va009039 | 1:bfbc18000cca | 191 | while(m_bitpat.size() > 0) { |
va009039 | 1:bfbc18000cca | 192 | int tc = (m_scan == 0) ? HT_DC : HT_AC; |
va009039 | 3:a7547692071d | 193 | int th = (m_block < yblock) ? 0 : 1; |
va009039 | 1:bfbc18000cca | 194 | DBG("%d %d %08x %d\n", tc, th, m_bitpat.peek(32), m_bitpat.size()); |
va009039 | 1:bfbc18000cca | 195 | if (m_huff == NULL) { |
va009039 | 1:bfbc18000cca | 196 | m_huff = pHD->Lookup(tc, th, &m_bitpat); |
va009039 | 1:bfbc18000cca | 197 | if (m_huff == NULL) { |
va009039 | 1:bfbc18000cca | 198 | break; |
va009039 | 1:bfbc18000cca | 199 | } |
va009039 | 1:bfbc18000cca | 200 | m_bitpat.get(m_huff->code_size); // skip code |
va009039 | 1:bfbc18000cca | 201 | } |
va009039 | 1:bfbc18000cca | 202 | if (m_huff->value_size > m_bitpat.size()) { |
va009039 | 1:bfbc18000cca | 203 | break; |
va009039 | 1:bfbc18000cca | 204 | } |
va009039 | 1:bfbc18000cca | 205 | DBG("%d %d %d %02x\n", m_huff->run, m_huff->value_size, m_huff->code_size, m_huff->code); |
va009039 | 1:bfbc18000cca | 206 | int value = pHD->getValue(m_huff, &m_bitpat); |
va009039 | 1:bfbc18000cca | 207 | if (tc == HT_DC) { |
va009039 | 2:5b1dd4e34857 | 208 | int sc = 0; // Y |
va009039 | 3:a7547692071d | 209 | if (m_block == yblock) { |
va009039 | 2:5b1dd4e34857 | 210 | sc = 1; // Cb |
va009039 | 3:a7547692071d | 211 | } else if (m_block == (yblock+1)) { |
va009039 | 2:5b1dd4e34857 | 212 | sc = 2; // Cr |
va009039 | 2:5b1dd4e34857 | 213 | } |
va009039 | 2:5b1dd4e34857 | 214 | value += m_pre_DC_value[sc]; |
va009039 | 1:bfbc18000cca | 215 | outputDC(m_mcu, m_block, value); |
va009039 | 2:5b1dd4e34857 | 216 | m_pre_DC_value[sc] = value; |
va009039 | 1:bfbc18000cca | 217 | m_scan++; |
va009039 | 1:bfbc18000cca | 218 | REPORT_CODE(report_scan_dc_count++); |
va009039 | 1:bfbc18000cca | 219 | } else { // AC |
va009039 | 1:bfbc18000cca | 220 | if (m_huff->value_size == 0 && m_huff->run == 0) { // EOB |
va009039 | 1:bfbc18000cca | 221 | DBG("AC EOB\n"); |
va009039 | 2:5b1dd4e34857 | 222 | outputAC(m_mcu, m_block, 63, 0); |
va009039 | 1:bfbc18000cca | 223 | m_scan = 64; |
va009039 | 1:bfbc18000cca | 224 | } else { |
va009039 | 1:bfbc18000cca | 225 | for(int i = 0; i < m_huff->run; i++) { |
va009039 | 2:5b1dd4e34857 | 226 | //outputAC(m_mcu, m_block, m_scan, 0); |
va009039 | 1:bfbc18000cca | 227 | m_scan++; |
va009039 | 1:bfbc18000cca | 228 | } |
va009039 | 1:bfbc18000cca | 229 | outputAC(m_mcu, m_block, m_scan, value); |
va009039 | 1:bfbc18000cca | 230 | m_scan++; |
va009039 | 1:bfbc18000cca | 231 | } |
va009039 | 1:bfbc18000cca | 232 | if (m_scan >= 64) { |
va009039 | 1:bfbc18000cca | 233 | m_scan = 0; |
va009039 | 3:a7547692071d | 234 | if (++m_block >= (yblock+2)) { |
va009039 | 1:bfbc18000cca | 235 | m_block = 0; |
va009039 | 1:bfbc18000cca | 236 | m_mcu++; |
va009039 | 1:bfbc18000cca | 237 | } |
va009039 | 1:bfbc18000cca | 238 | } |
va009039 | 1:bfbc18000cca | 239 | REPORT_CODE(report_scan_ac_count++); |
va009039 | 1:bfbc18000cca | 240 | } |
va009039 | 1:bfbc18000cca | 241 | m_huff = NULL; |
va009039 | 1:bfbc18000cca | 242 | REPORT_CODE(report_scan_count++); |
va009039 | 1:bfbc18000cca | 243 | } |
va009039 | 1:bfbc18000cca | 244 | } |