Any changes are to allow conversion to BMP
Dependents: Color_Targeting_Catapult
Fork of BaseJpegDecode by
BaseJpegDecode.cpp
- Committer:
- va009039
- Date:
- 2012-11-05
- Revision:
- 3:a7547692071d
- Parent:
- 2:5b1dd4e34857
- Child:
- 4:e243fa781e5c
File content as of revision 3:a7547692071d:
#include "mbed.h" #include "BaseJpegDecode.h" #if 0 #define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0); #define DBG_WAIT(A) wait_ms(A) #else #define DBG(...) #define DBG_WAIT(A) #endif #if 1 #define DBG_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);}; #else #define DBG_ASSERT(A) #endif #ifdef JPEG_USE_REPORT_CODE #define REPORT_CODE(A) (A) #else #define REPORT_CODE(A) #endif #define MARK_SOF0 0xc0 #define MARK_DHT 0xc4 #define MARK_RST0 0xd0 #define MARK_RST7 0xd7 #define MARK_SOI 0xd8 #define MARK_EOI 0xd9 #define MARK_SOS 0xda #define MARK_DQT 0xdb #define MARK_DRI 0xdd #define MARK_APP 0xe0 #define SEQ_INIT 0 #define SEQ_MARK 1 #define SEQ_SEG_LEN 2 #define SEQ_SEG_LEN2 3 #define SEQ_SEG_BODY 4 #define SEQ_SOS 5 #define SEQ_SOS2 6 #define HT_DC 0 #define HT_AC 1 BaseJpegDecode::BaseJpegDecode() { yblock = JPEG_MCU_YBLOCK; // 2 or 4 clear(); pHD = new HuffmanDecode; DBG_ASSERT(pHD); qt[0] = new uint8_t[64]; qt[1] = new uint8_t[64]; DBG_ASSERT(qt[0]); DBG_ASSERT(qt[1]); } void BaseJpegDecode::clear() { m_seq = SEQ_INIT; } void BaseJpegDecode::input(uint8_t* buf, int len) { for(int i = 0; i < len; i++) { input(buf[i]); } } void BaseJpegDecode::restart() { m_block = 0; m_scan = 0; m_pre_DC_value[0] = 0; m_pre_DC_value[1] = 0; m_pre_DC_value[2] = 0; m_bitpat.clear(); m_huff = NULL; } void BaseJpegDecode::inputDQT(uint8_t c, int pos, int len) { if (pos == 0 || pos == 65) { m_param1 = c; DBG_ASSERT(m_param1 == 0 || m_param1 == 1); } else { qt[m_param1][(pos%65)-1] = c; } } void BaseJpegDecode::inputSOF(uint8_t c, int pos, int len) { switch(pos) { case 1: height = (height&0x00ff) | (c<<8); break; case 2: height = (height&0xff00) | c; break; case 3: width = (width&0x00ff) | (c<<8); break; case 4: width = (width&0xff00) | c; break; case 7: if (c == 0x22) { yblock = 4; } else if (c == 0x21) { yblock = 2; } else { DBG_ASSERT(c == 0x22 || c == 0x21); } break; } } void BaseJpegDecode::input(uint8_t c) { switch(m_seq) { case SEQ_INIT: if (c == 0xff) { m_seq = SEQ_MARK; } break; case SEQ_MARK: outputMARK(c); if (c == MARK_SOI || c == MARK_EOI) { m_seq = SEQ_INIT; break; } m_mark = c; m_seq = SEQ_SEG_LEN; break; case SEQ_SEG_LEN: m_seg_len = c; m_seq = SEQ_SEG_LEN2; break; case SEQ_SEG_LEN2: m_seg_len <<= 8; m_seg_len |= c; m_seg_len -= 2; m_seg_pos = 0; m_seq = SEQ_SEG_BODY; break; case SEQ_SEG_BODY: if (m_mark == MARK_DQT) { inputDQT(c, m_seg_pos, m_seg_len); } else if (m_mark == MARK_SOF0) { inputSOF(c, m_seg_pos, m_seg_len); } if (++m_seg_pos < m_seg_len) { break; } if (m_mark == MARK_SOS) { m_seq = SEQ_SOS; m_mcu = 0; restart(); break; } m_seq = SEQ_INIT; break; case SEQ_SOS: if (c == 0xff) { m_seq = SEQ_SOS2; break; } inputScan(c); break; case SEQ_SOS2: if (c == 0x00) { inputScan(0xff); m_seq = SEQ_SOS; break; } else if (c >= MARK_RST0 && c <= MARK_RST7) { restart(); m_seq = SEQ_SOS; break; } outputMARK(c); m_seq = SEQ_INIT; break; default: break; } } void BaseJpegDecode::inputScan(uint8_t c) { m_bitpat += c; while(m_bitpat.size() > 0) { int tc = (m_scan == 0) ? HT_DC : HT_AC; int th = (m_block < yblock) ? 0 : 1; DBG("%d %d %08x %d\n", tc, th, m_bitpat.peek(32), m_bitpat.size()); if (m_huff == NULL) { m_huff = pHD->Lookup(tc, th, &m_bitpat); if (m_huff == NULL) { break; } m_bitpat.get(m_huff->code_size); // skip code } if (m_huff->value_size > m_bitpat.size()) { break; } DBG("%d %d %d %02x\n", m_huff->run, m_huff->value_size, m_huff->code_size, m_huff->code); int value = pHD->getValue(m_huff, &m_bitpat); if (tc == HT_DC) { int sc = 0; // Y if (m_block == yblock) { sc = 1; // Cb } else if (m_block == (yblock+1)) { sc = 2; // Cr } value += m_pre_DC_value[sc]; outputDC(m_mcu, m_block, value); m_pre_DC_value[sc] = value; m_scan++; REPORT_CODE(report_scan_dc_count++); } else { // AC if (m_huff->value_size == 0 && m_huff->run == 0) { // EOB DBG("AC EOB\n"); outputAC(m_mcu, m_block, 63, 0); m_scan = 64; } else { for(int i = 0; i < m_huff->run; i++) { //outputAC(m_mcu, m_block, m_scan, 0); m_scan++; } outputAC(m_mcu, m_block, m_scan, value); m_scan++; } if (m_scan >= 64) { m_scan = 0; if (++m_block >= (yblock+2)) { m_block = 0; m_mcu++; } } REPORT_CODE(report_scan_ac_count++); } m_huff = NULL; REPORT_CODE(report_scan_count++); } }