test

Dependencies:   Nanopb iSerial mbed BaseJpegDecode FatFileSystem SDFileSystem RingBuffer Camera_LS_Y201

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleJpegDecode.cpp Source File

SimpleJpegDecode.cpp

00001 #include "SimpleJpegDecode.h"
00002 
00003 #define DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);} while(0);
00004 #define ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
00005 
00006 
00007 #define _1_4020 45
00008 #define _0_3441 11
00009 #define _0_7139 23
00010 #define _1_7718 57
00011 #define _0_0012 0
00012 
00013 int adjust(int r) {
00014     if (r >= 0) {
00015         if (r <= 255) {
00016             return r;
00017         } else {
00018             return 255;
00019         }
00020     } else {
00021         return 0;
00022     }
00023 }
00024     
00025 void convYUVtoRGB(uint8_t rgb[], int y, int u, int v)
00026 {
00027     rgb[0] = adjust((y*32             + v*_1_4020)/32 + 128);
00028     rgb[1] = adjust((y*32 - u*_0_3441 - v*_0_7139)/32 + 128);
00029     rgb[2] = adjust((y*32 + u*_1_7718 - v*_0_0012)/32 + 128);
00030 }
00031 
00032 SimpleJpegDecode::SimpleJpegDecode(uint8_t output_mode)
00033 {
00034     m_output_mode = output_mode;
00035     clearOnResult();
00036 }
00037 
00038 
00039 void SimpleJpegDecode::output(int mcu, int block, int scan, int value)
00040 {
00041     int sc = (block < yblock) ? 0 : 1;
00042     inputBLOCK(mcu, block, scan, value * qt[sc][scan]);
00043 }
00044 
00045 void SimpleJpegDecode::outputDC(int mcu, int block, int value)
00046 {
00047     output(mcu, block, 0, value);
00048     DC_count++;
00049 }
00050 
00051 void SimpleJpegDecode::outputAC(int mcu, int block, int scan, int value)
00052 {
00053     output(mcu, block, scan, value);
00054     AC_count++;
00055 }
00056 
00057 void SimpleJpegDecode::outputMARK(uint8_t c)
00058 {
00059 }
00060 
00061 void SimpleJpegDecode::format_YUV(int mcu, int block, int8_t* values)
00062 {
00063     if (block < yblock+1) {
00064         memcpy(m_block_data[block], values, 64);
00065         return;
00066     }
00067     int mcu_x_count = (width+15)/16;
00068     int mcu_x = mcu % mcu_x_count;
00069     int mcu_y = mcu / mcu_x_count;
00070     uint8_t yuv[3];
00071     if (yblock == 2) {
00072         for(int y = 0; y < 8; y++) {
00073             for(int x = 0; x < 16; x++) {
00074                 yuv[0] = m_block_data[x/8][y*8+x%8] + 128;
00075                 yuv[1] = m_block_data[2][y*8+x/2] + 128;
00076                 yuv[2] = values[y*8+x/2] + 128;
00077                 onResult(mcu_x * 16 + x, mcu_y * 8 + y, yuv);
00078             }
00079         }
00080     } else if (yblock == 4) {
00081         for(int y = 0; y < 16; y++) {
00082             for(int x = 0; x < 16; x++) {
00083                 yuv[0] = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8] + 128;
00084                 yuv[1] = m_block_data[4][(y/2)*8+x/2] + 128;
00085                 yuv[2] = values[(y/2)*8+x/2] + 128;
00086                 onResult(mcu_x * 16 + x, mcu_y * 16 + y, yuv);
00087             }
00088         }
00089     } else {
00090         ASSERT(yblock == 2 || yblock == 4);
00091     }    
00092 }
00093 
00094 void SimpleJpegDecode::format_RGB24(int mcu, int block, int8_t* values)
00095 {
00096     if (block < yblock+1) {
00097         memcpy(m_block_data[block], values, 64);
00098         return;
00099     }
00100     int mcu_x_count = (width+15)/16;
00101     int mcu_x = mcu % mcu_x_count;
00102     int mcu_y = mcu / mcu_x_count;
00103     uint8_t rgb[3];
00104     if (yblock == 2) {
00105         for(int y = 0; y < 8; y++) {
00106             for(int x = 0; x < 16; x++) {
00107                 int8_t yuv_y = m_block_data[x/8][y*8+x%8];
00108                 int8_t yuv_u = m_block_data[2][y*8+x/2];
00109                 int8_t yuv_v = values[y*8+x/2];
00110                 convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v);
00111                 onResult(mcu_x * 16 + x, mcu_y * 8 + y, rgb);
00112             }
00113         }
00114     } else if (yblock == 4) {
00115         for(int y = 0; y < 16; y++) {
00116             for(int x = 0; x < 16; x++) {
00117                 int8_t yuv_y = m_block_data[(y/8)*2+x/8][(y%8)*8+x%8];
00118                 int8_t yuv_u = m_block_data[4][(y/2)*8+x/2];
00119                 int8_t yuv_v = values[(y/2)*8+x/2];
00120                 convYUVtoRGB(rgb, yuv_y, yuv_u, yuv_v);
00121                 onResult(mcu_x * 16 + x, mcu_y * 16 + y, rgb);
00122             }
00123         }
00124     } else {
00125         ASSERT(yblock == 2 || yblock == 4);
00126     }    
00127 }
00128 
00129 void SimpleJpegDecode::outputBLOCK(int mcu, int block, int8_t* values)
00130 {
00131     BLOCK_count++;
00132     if (m_output_mode == YUV) {
00133         format_YUV(mcu, block, values);
00134     } else if (m_output_mode == RGB24) {
00135         format_RGB24(mcu, block, values);
00136     } else {
00137         ASSERT(m_output_mode == YUV || m_output_mode == RGB24);
00138     }    
00139 }
00140 
00141 void SimpleJpegDecode::onResult(int x, int y, uint8_t* yuv)
00142 {
00143   if(m_pCbItem && m_pCbMeth)
00144     (m_pCbItem->*m_pCbMeth)(x, y, yuv);
00145   else if(m_pCb)
00146     m_pCb(x, y, yuv);
00147 }
00148 
00149 void SimpleJpegDecode::setOnResult( void (*pMethod)(int, int, uint8_t*) )
00150 {
00151   m_pCb = pMethod;
00152   m_pCbItem = NULL;
00153   m_pCbMeth = NULL;
00154 }
00155 
00156 void SimpleJpegDecode::clearOnResult()
00157 {
00158   m_pCb = NULL;
00159   m_pCbItem = NULL;
00160   m_pCbMeth = NULL;
00161 }