Final

Dependencies:   DebounceIn NokiaLCD WiflyInterface mbed

Fork of Websocket_Wifly_HelloWorld by Samuel Mokrani

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers picojpeg.c Source File

picojpeg.c

00001 //------------------------------------------------------------------------------
00002 // picojpeg v1.0 - Public domain, Rich Geldreich <richgel99@gmail.com>
00003 // Last modified Nov. 27, 2010
00004 //------------------------------------------------------------------------------
00005 #include "picojpeg.h"
00006 //------------------------------------------------------------------------------
00007 typedef unsigned char   uint8;
00008 typedef unsigned short  uint16;
00009 typedef signed char     int8;
00010 typedef signed short    int16;
00011 //------------------------------------------------------------------------------
00012 // Change as needed - the PJPG_MAX_WIDTH/PJPG_MAX_HEIGHT checks are only present
00013 // to quickly detect bogus files.
00014 #define PJPG_MAX_WIDTH 16384
00015 #define PJPG_MAX_HEIGHT 16384
00016 
00017 #define PJPG_MAXCOMPSINSCAN 3
00018 //------------------------------------------------------------------------------
00019 typedef enum
00020 {
00021    M_SOF0  = 0xC0,
00022    M_SOF1  = 0xC1,
00023    M_SOF2  = 0xC2,
00024    M_SOF3  = 0xC3,
00025 
00026    M_SOF5  = 0xC5,
00027    M_SOF6  = 0xC6,
00028    M_SOF7  = 0xC7,
00029 
00030    M_JPG   = 0xC8,
00031    M_SOF9  = 0xC9,
00032    M_SOF10 = 0xCA,
00033    M_SOF11 = 0xCB,
00034 
00035    M_SOF13 = 0xCD,
00036    M_SOF14 = 0xCE,
00037    M_SOF15 = 0xCF,
00038 
00039    M_DHT   = 0xC4,
00040 
00041    M_DAC   = 0xCC,
00042 
00043    M_RST0  = 0xD0,
00044    M_RST1  = 0xD1,
00045    M_RST2  = 0xD2,
00046    M_RST3  = 0xD3,
00047    M_RST4  = 0xD4,
00048    M_RST5  = 0xD5,
00049    M_RST6  = 0xD6,
00050    M_RST7  = 0xD7,
00051 
00052    M_SOI   = 0xD8,
00053    M_EOI   = 0xD9,
00054    M_SOS   = 0xDA,
00055    M_DQT   = 0xDB,
00056    M_DNL   = 0xDC,
00057    M_DRI   = 0xDD,
00058    M_DHP   = 0xDE,
00059    M_EXP   = 0xDF,
00060 
00061    M_APP0  = 0xE0,
00062    M_APP15 = 0xEF,
00063 
00064    M_JPG0  = 0xF0,
00065    M_JPG13 = 0xFD,
00066    M_COM   = 0xFE,
00067 
00068    M_TEM   = 0x01,
00069 
00070    M_ERROR = 0x100
00071 } JPEG_MARKER;
00072 
00073 #define RST0 0xD0
00074 //------------------------------------------------------------------------------
00075 const int8 ZAG[] = 
00076 {
00077    0,  1,  8, 16,  9,  2,  3, 10,
00078    17, 24, 32, 25, 18, 11,  4,  5,
00079    12, 19, 26, 33, 40, 48, 41, 34,
00080    27, 20, 13,  6,  7, 14, 21, 28,
00081    35, 42, 49, 56, 57, 50, 43, 36,
00082    29, 22, 15, 23, 30, 37, 44, 51,
00083    58, 59, 52, 45, 38, 31, 39, 46,
00084    53, 60, 61, 54, 47, 55, 62, 63,
00085 };
00086 //------------------------------------------------------------------------------
00087 // 128 bytes
00088 static int16 gCoeffBuf[8*8];
00089 
00090 // 8*8*4 bytes * 3 = 768
00091 static uint8 gMCUBufR[256];
00092 static uint8 gMCUBufG[256];
00093 static uint8 gMCUBufB[256];
00094 
00095 // 256 bytes
00096 static int16 gQuant0[8*8];
00097 static int16 gQuant1[8*8];
00098 
00099 // 6 bytes
00100 static int16 gLastDC[3];
00101 
00102 typedef struct HuffTableT
00103 {
00104    uint16 mMinCode[16];
00105    uint16 mMaxCode[16];
00106    uint8 mValPtr[16];
00107 } HuffTable;
00108 
00109 // DC - 192
00110 static HuffTable gHuffTab0;
00111 
00112 static uint8 gHuffVal0[16];
00113 
00114 static HuffTable gHuffTab1;
00115 static uint8 gHuffVal1[16];
00116 
00117 // AC - 672
00118 static HuffTable gHuffTab2;
00119 static uint8 gHuffVal2[256];
00120 
00121 static HuffTable gHuffTab3;
00122 static uint8 gHuffVal3[256];
00123 
00124 static uint8 gValidHuffTables;
00125 static uint8 gValidQuantTables;
00126 
00127 static uint8 gTemFlag;
00128 #define MAX_IN_BUF_SIZE 256
00129 static uint8 gInBuf[MAX_IN_BUF_SIZE];
00130 static uint8 gInBufOfs;
00131 static uint8 gInBufLeft;
00132 
00133 static uint16 gBitBuf;
00134 static uint8 gBitsLeft;
00135 //------------------------------------------------------------------------------
00136 static uint16 gImageXSize;
00137 static uint16 gImageYSize;
00138 static uint8 gCompsInFrame;
00139 static uint8 gCompIdent[3];
00140 static uint8 gCompHSamp[3];
00141 static uint8 gCompVSamp[3];
00142 static uint8 gCompQuant[3];
00143 
00144 static uint16 gRestartInterval;
00145 static uint16 gNextRestartNum;
00146 static uint16 gRestartsLeft;
00147 
00148 static uint8 gCompsInScan;
00149 static uint8 gCompList[3];
00150 static uint8 gCompDCTab[3]; // 0,1
00151 static uint8 gCompACTab[3]; // 0,1
00152 
00153 static pjpeg_scan_type_t gScanType;
00154 
00155 static uint8 gMaxBlocksPerMCU;
00156 static uint8 gMaxMCUXSize;
00157 static uint8 gMaxMCUYSize;
00158 static uint16 gMaxMCUSPerRow;
00159 static uint16 gMaxMCUSPerCol;
00160 static uint16 gNumMCUSRemaining;
00161 static uint8 gMCUOrg[6];
00162 
00163 static pjpeg_need_bytes_callback_t g_pNeedBytesCallback;
00164 static void *g_pCallback_data;
00165 //------------------------------------------------------------------------------
00166 static uint8 fillInBuf(void)
00167 {
00168    unsigned char status;
00169 
00170    // Reserve a few bytes at the beginning of the buffer for putting back ("stuffing") chars.
00171    gInBufOfs = 4;
00172    gInBufLeft = 0;
00173 
00174    status = (*g_pNeedBytesCallback)(gInBuf + gInBufOfs, MAX_IN_BUF_SIZE - gInBufOfs, &gInBufLeft, g_pCallback_data);
00175    if (status)
00176       return status;
00177       
00178    return 0;
00179 }   
00180 //------------------------------------------------------------------------------
00181 static uint8 getChar(void)
00182 {
00183    if (!gInBufLeft)
00184    {
00185       fillInBuf();
00186       if (!gInBufLeft)
00187       {
00188          gTemFlag = ~gTemFlag;
00189          return gTemFlag ? 0xFF : 0xD9;
00190       } 
00191    }
00192    
00193    gInBufLeft--;
00194    return gInBuf[gInBufOfs++];
00195 }
00196 //------------------------------------------------------------------------------
00197 static void stuffChar(uint8 i)
00198 {
00199    gInBufOfs--;
00200    gInBuf[gInBufOfs] = i;
00201    gInBufLeft++;
00202 }
00203 //------------------------------------------------------------------------------
00204 static uint8 getOctet(uint8 FFCheck)
00205 {
00206    uint8 c = getChar();
00207       
00208    if ((FFCheck) && (c == 0xFF))
00209    {
00210       uint8 n = getChar();
00211 
00212       if (n)
00213       {
00214          stuffChar(n);
00215          stuffChar(0xFF);
00216       }
00217    }
00218 
00219    return c;
00220 }
00221 //------------------------------------------------------------------------------
00222 static uint16 getBits(uint8 numBits, uint8 FFCheck)
00223 {
00224    uint8 origBits = numBits;
00225    uint16 ret = gBitBuf;
00226    
00227    if (numBits > 8)
00228    {
00229       numBits -= 8;
00230       
00231       gBitBuf <<= gBitsLeft;
00232       
00233       gBitBuf |= getOctet(FFCheck);
00234       
00235       gBitBuf <<= (8 - gBitsLeft);
00236       
00237       ret = (ret & 0xFF00) | (gBitBuf >> 8);
00238    }
00239       
00240    if (gBitsLeft < numBits)
00241    {
00242       gBitBuf <<= gBitsLeft;
00243       
00244       gBitBuf |= getOctet(FFCheck);
00245       
00246       gBitBuf <<= (numBits - gBitsLeft);
00247                         
00248       gBitsLeft = 8 - (numBits - gBitsLeft);
00249    }
00250    else
00251    {
00252       gBitsLeft = (uint8)(gBitsLeft - numBits);
00253       gBitBuf <<= numBits;
00254    }
00255    
00256    return ret >> (16 - origBits);
00257 }
00258 //------------------------------------------------------------------------------
00259 static uint16 getBits1(uint8 numBits)
00260 {
00261    return getBits(numBits, 0);
00262 }
00263 //------------------------------------------------------------------------------
00264 static uint16 getBits2(uint8 numBits)
00265 {
00266    return getBits(numBits, 1);
00267 }
00268 //------------------------------------------------------------------------------
00269 static uint8 getBit(void)
00270 {
00271    uint8 ret = 0;
00272    if (gBitBuf & 0x8000) 
00273       ret = 1;
00274    
00275    if (!gBitsLeft)
00276    {
00277       gBitBuf |= getOctet(1);
00278 
00279       gBitsLeft += 8;
00280    }
00281    
00282    gBitsLeft--;
00283    gBitBuf <<= 1;
00284    
00285    return ret;
00286 }
00287 //------------------------------------------------------------------------------
00288 static uint16 getExtendTest(uint8 i)
00289 {
00290    switch (i)
00291    {
00292       case 0: return 0;
00293       case 1: return 0x0001;
00294       case 2: return 0x0002;
00295       case 3: return 0x0004;
00296       case 4: return 0x0008;
00297       case 5: return 0x0010; 
00298       case 6: return 0x0020;
00299       case 7: return 0x0040;
00300       case 8:  return 0x0080;
00301       case 9:  return 0x0100;
00302       case 10: return 0x0200;
00303       case 11: return 0x0400;
00304       case 12: return 0x0800;
00305       case 13: return 0x1000;
00306       case 14: return 0x2000; 
00307       case 15: return 0x4000;
00308       default: return 0;
00309    }      
00310 }
00311 //------------------------------------------------------------------------------
00312 static int16 getExtendOffset(uint8 i)
00313 { 
00314    switch (i)
00315    {
00316       case 0: return 0;
00317       case 1: return ((-1)<<1) + 1; 
00318       case 2: return ((-1)<<2) + 1; 
00319       case 3: return ((-1)<<3) + 1; 
00320       case 4: return ((-1)<<4) + 1; 
00321       case 5: return ((-1)<<5) + 1; 
00322       case 6: return ((-1)<<6) + 1; 
00323       case 7: return ((-1)<<7) + 1; 
00324       case 8: return ((-1)<<8) + 1; 
00325       case 9: return ((-1)<<9) + 1;
00326       case 10: return ((-1)<<10) + 1; 
00327       case 11: return ((-1)<<11) + 1; 
00328       case 12: return ((-1)<<12) + 1; 
00329       case 13: return ((-1)<<13) + 1; 
00330       case 14: return ((-1)<<14) + 1; 
00331       case 15: return ((-1)<<15) + 1;
00332       default: return 0;
00333    }
00334 };
00335 //------------------------------------------------------------------------------
00336 static int16 huffExtend(uint16 x, uint8 s)
00337 {
00338    return ((x < getExtendTest(s)) ? ((int16)x + getExtendOffset(s)) : (int16)x);
00339 }
00340 //------------------------------------------------------------------------------
00341 static uint8 huffDecode(const HuffTable* pHuffTable, const uint8* pHuffVal)
00342 {
00343    uint8 i = 0;
00344    uint8 j;
00345    uint16 code = getBit();
00346 
00347    for ( ; ; )
00348    {
00349       uint16 maxCode;
00350 
00351       if (i == 16)
00352          return 0;
00353 
00354       maxCode = pHuffTable->mMaxCode[i];
00355       if ((code <= maxCode) && (maxCode != 0xFFFF))
00356          break;
00357 
00358       i++;
00359       code <<= 1;
00360       code |= getBit();
00361    }
00362 
00363    j = pHuffTable->mValPtr[i];
00364    j = (uint8)(j + (code - pHuffTable->mMinCode[i]));
00365 
00366    return pHuffVal[j];
00367 }
00368 //------------------------------------------------------------------------------
00369 static void huffCreate(const uint8* pBits, HuffTable* pHuffTable)
00370 {
00371    uint8 i = 0;
00372    uint8 j = 0;
00373 
00374    uint16 code = 0;
00375       
00376    for ( ; ; )
00377    {
00378       uint8 num = pBits[i];
00379       
00380       if (!num)
00381       {
00382          pHuffTable->mMinCode[i] = 0x0000;
00383          pHuffTable->mMaxCode[i] = 0xFFFF;
00384          pHuffTable->mValPtr[i] = 0;
00385       }
00386       else
00387       {
00388          pHuffTable->mMinCode[i] = code;
00389          pHuffTable->mMaxCode[i] = code + num - 1;
00390          pHuffTable->mValPtr[i] = j;
00391          
00392          j = (uint8)(j + num);
00393          
00394          code = (uint16)(code + num);
00395       }
00396       
00397       code <<= 1;
00398       
00399       i++;
00400       if (i > 15)
00401          break;
00402    }
00403 }
00404 //------------------------------------------------------------------------------
00405 static HuffTable* getHuffTable(uint8 index)
00406 {
00407    // 0-1 = DC
00408    // 2-3 = AC
00409    switch (index)
00410    {
00411       case 0: return &gHuffTab0;
00412       case 1: return &gHuffTab1;
00413       case 2: return &gHuffTab2;
00414       case 3: return &gHuffTab3;
00415       default: return 0;
00416    }
00417 }
00418 //------------------------------------------------------------------------------
00419 static uint8* getHuffVal(uint8 index)
00420 {
00421    // 0-1 = DC
00422    // 2-3 = AC
00423    switch (index)
00424    {
00425       case 0: return gHuffVal0;
00426       case 1: return gHuffVal1;
00427       case 2: return gHuffVal2;
00428       case 3: return gHuffVal3;
00429       default: return 0;
00430    }
00431 }
00432 //------------------------------------------------------------------------------
00433 static uint16 getMaxHuffCodes(uint8 index)
00434 {
00435    return (index < 2) ? 12 : 255;
00436 }
00437 //------------------------------------------------------------------------------
00438 static uint8 readDHTMarker(void)
00439 {
00440    uint8 bits[16];
00441    uint16 left = getBits1(16);
00442 
00443    if (left < 2)
00444       return PJPG_BAD_DHT_MARKER;
00445 
00446    left -= 2;
00447 
00448    while (left)
00449    {
00450       uint8 i, tableIndex, index;
00451       uint8* pHuffVal;
00452       HuffTable* pHuffTable;
00453       uint16 count, totalRead;
00454             
00455       index = (uint8)getBits1(8);
00456       
00457       if ( ((index & 0xF) > 1) || ((index & 0xF0) > 0x10) )
00458          return PJPG_BAD_DHT_INDEX;
00459       
00460       tableIndex = ((index >> 3) & 2) + (index & 1);
00461       
00462       pHuffTable = getHuffTable(tableIndex);
00463       pHuffVal = getHuffVal(tableIndex);
00464       
00465       gValidHuffTables |= (1 << tableIndex);
00466             
00467       count = 0;
00468       for (i = 0; i <= 15; i++)
00469       {
00470          uint8 n = (uint8)getBits1(8);
00471          bits[i] = n;
00472          count = (uint16)(count + n);
00473       }
00474       
00475       if (count > getMaxHuffCodes(tableIndex))
00476          return PJPG_BAD_DHT_COUNTS;
00477 
00478       for (i = 0; i < count; i++)
00479          pHuffVal[i] = (uint8)getBits1(8);
00480 
00481       totalRead = 1 + 16 + count;
00482 
00483       if (left < totalRead)
00484          return PJPG_BAD_DHT_MARKER;
00485 
00486       left = (uint16)(left - totalRead);
00487 
00488       huffCreate(bits, pHuffTable);
00489    }
00490       
00491    return 0;
00492 }
00493 //------------------------------------------------------------------------------
00494 static void createWinogradQuant(int16* pQuant);
00495 
00496 static uint8 readDQTMarker(void)
00497 {
00498    uint16 left = getBits1(16);
00499 
00500    if (left < 2)
00501       return PJPG_BAD_DQT_MARKER;
00502 
00503    left -= 2;
00504 
00505    while (left)
00506    {
00507       uint8 i;
00508       uint8 n = (uint8)getBits1(8);
00509       uint8 prec = n >> 4;
00510       uint16 totalRead;
00511 
00512       n &= 0x0F;
00513 
00514       if (n > 1)
00515          return PJPG_BAD_DQT_TABLE;
00516 
00517       gValidQuantTables |= (n ? 2 : 1);         
00518 
00519       // read quantization entries, in zag order
00520       for (i = 0; i < 64; i++)
00521       {
00522          uint16 temp = getBits1(8);
00523 
00524          if (prec)
00525             temp = (temp << 8) + getBits1(8);
00526 
00527          if (n)
00528             gQuant1[i] = (int16)temp;            
00529          else
00530             gQuant0[i] = (int16)temp;            
00531       }
00532       
00533       createWinogradQuant(n ? gQuant1 : gQuant0);
00534 
00535       totalRead = 64 + 1;
00536 
00537       if (prec)
00538          totalRead += 64;
00539 
00540       if (left < totalRead)
00541          return PJPG_BAD_DQT_LENGTH;
00542 
00543       left = (uint16)(left - totalRead);
00544    }
00545    
00546    return 0;
00547 }
00548 //------------------------------------------------------------------------------
00549 static uint8 readSOFMarker(void)
00550 {
00551    uint8 i;
00552    uint16 left = getBits1(16);
00553 
00554    if (getBits1(8) != 8)   
00555       return PJPG_BAD_PRECISION;
00556 
00557    gImageYSize = getBits1(16);
00558 
00559    if ((!gImageYSize) || (gImageYSize > PJPG_MAX_HEIGHT))
00560       return PJPG_BAD_HEIGHT;
00561 
00562    gImageXSize = getBits1(16);
00563 
00564    if ((!gImageXSize) || (gImageXSize > PJPG_MAX_WIDTH))
00565       return PJPG_BAD_WIDTH;
00566 
00567    gCompsInFrame = (uint8)getBits1(8);
00568 
00569    if (gCompsInFrame > 3)
00570       return PJPG_TOO_MANY_COMPONENTS;
00571 
00572    if (left != (gCompsInFrame + gCompsInFrame + gCompsInFrame + 8))
00573       return PJPG_BAD_SOF_LENGTH;
00574    
00575    for (i = 0; i < gCompsInFrame; i++)
00576    {
00577       gCompIdent[i] = (uint8)getBits1(8);
00578       gCompHSamp[i] = (uint8)getBits1(4);
00579       gCompVSamp[i] = (uint8)getBits1(4);
00580       gCompQuant[i] = (uint8)getBits1(8);
00581       
00582       if (gCompQuant[i] > 1)
00583          return PJPG_UNSUPPORTED_QUANT_TABLE;
00584    }
00585    
00586    return 0;
00587 }
00588 //------------------------------------------------------------------------------
00589 // Used to skip unrecognized markers.
00590 static uint8 skipVariableMarker(void)
00591 {
00592    uint16 left = getBits1(16);
00593 
00594    if (left < 2)
00595       return PJPG_BAD_VARIABLE_MARKER;
00596 
00597    left -= 2;
00598 
00599    while (left)
00600    {
00601       getBits1(8);
00602       left--;
00603    }
00604    
00605    return 0;
00606 }
00607 //------------------------------------------------------------------------------
00608 // Read a define restart interval (DRI) marker.
00609 static uint8 readDRIMarker(void)
00610 {
00611    if (getBits1(16) != 4)
00612       return PJPG_BAD_DRI_LENGTH;
00613 
00614    gRestartInterval = getBits1(16);
00615    
00616    return 0;
00617 }
00618 //------------------------------------------------------------------------------
00619 // Read a start of scan (SOS) marker.
00620 static uint8 readSOSMarker(void)
00621 {
00622    uint8 i;
00623    uint16 left = getBits1(16);
00624    uint8 spectral_start, spectral_end, successive_high, successive_low;
00625 
00626    gCompsInScan = (uint8)getBits1(8);
00627 
00628    left -= 3;
00629 
00630    if ( (left != (gCompsInScan + gCompsInScan + 3)) || (gCompsInScan < 1) || (gCompsInScan > PJPG_MAXCOMPSINSCAN) )
00631       return PJPG_BAD_SOS_LENGTH;
00632    
00633    for (i = 0; i < gCompsInScan; i++)
00634    {
00635       uint8 cc = (uint8)getBits1(8);
00636       uint8 c = (uint8)getBits1(8);
00637       uint8 ci;
00638       
00639       left -= 2;
00640      
00641       for (ci = 0; ci < gCompsInFrame; ci++)
00642          if (cc == gCompIdent[ci])
00643             break;
00644 
00645       if (ci >= gCompsInFrame)
00646          return PJPG_BAD_SOS_COMP_ID;
00647 
00648       gCompList[i]    = ci;
00649       gCompDCTab[ci] = (c >> 4) & 15;
00650       gCompACTab[ci] = (c & 15);
00651    }
00652 
00653    spectral_start  = (uint8)getBits1(8);
00654    spectral_end    = (uint8)getBits1(8);
00655    successive_high = (uint8)getBits1(4);
00656    successive_low  = (uint8)getBits1(4);
00657 
00658    left -= 3;
00659 
00660    while (left)                  
00661    {
00662       getBits1(8);
00663       left--;
00664    }
00665    
00666    return 0;
00667 }
00668 //------------------------------------------------------------------------------
00669 static uint8 nextMarker(void)
00670 {
00671    uint8 c;
00672    uint8 bytes = 0;
00673 
00674    do
00675    {
00676       do
00677       {
00678          bytes++;
00679 
00680          c = (uint8)getBits1(8);
00681 
00682       } while (c != 0xFF);
00683 
00684       do
00685       {
00686          c = (uint8)getBits1(8);
00687 
00688       } while (c == 0xFF);
00689 
00690    } while (c == 0);
00691 
00692    // If bytes > 0 here, there where extra bytes before the marker (not good).
00693 
00694    return c;
00695 }
00696 //------------------------------------------------------------------------------
00697 // Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is
00698 // encountered.
00699 static uint8 processMarkers(uint8* pMarker)
00700 {
00701    for ( ; ; )
00702    {
00703       uint8 c = nextMarker();
00704 
00705       switch (c)
00706       {
00707          case M_SOF0:
00708          case M_SOF1:
00709          case M_SOF2:
00710          case M_SOF3:
00711          case M_SOF5:
00712          case M_SOF6:
00713          case M_SOF7:
00714          //      case M_JPG:
00715          case M_SOF9:
00716          case M_SOF10:
00717          case M_SOF11:
00718          case M_SOF13:
00719          case M_SOF14:
00720          case M_SOF15:
00721          case M_SOI:
00722          case M_EOI:
00723          case M_SOS:
00724          {
00725             *pMarker = c;
00726             return 0;
00727          }
00728          case M_DHT:
00729          {
00730             readDHTMarker();
00731             break;
00732          }
00733          // Sorry, no arithmitic support at this time. Dumb patents!
00734          case M_DAC:
00735          {
00736             return PJPG_NO_ARITHMITIC_SUPPORT;
00737          }
00738          case M_DQT:
00739          {
00740             readDQTMarker();
00741             break;
00742          }
00743          case M_DRI:
00744          {
00745             readDRIMarker();
00746             break;
00747          }
00748          //case M_APP0:  /* no need to read the JFIF marker */
00749 
00750          case M_JPG:
00751          case M_RST0:    /* no parameters */
00752          case M_RST1:
00753          case M_RST2:
00754          case M_RST3:
00755          case M_RST4:
00756          case M_RST5:
00757          case M_RST6:
00758          case M_RST7:
00759          case M_TEM:
00760          {
00761             return PJPG_UNEXPECTED_MARKER;
00762          }
00763          default:    /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
00764          {
00765             skipVariableMarker();
00766             break;
00767          }
00768       }
00769    }
00770 //   return 0;
00771 }
00772 //------------------------------------------------------------------------------
00773 // Finds the start of image (SOI) marker.
00774 static uint8 locateSOIMarker(void)
00775 {
00776    uint16 bytesleft;
00777    
00778    uint8 lastchar = (uint8)getBits1(8);
00779 
00780    uint8 thischar = (uint8)getBits1(8);
00781 
00782    /* ok if it's a normal JPEG file without a special header */
00783 
00784    if ((lastchar == 0xFF) && (thischar == M_SOI))
00785       return 0;
00786 
00787    bytesleft = 4096; //512;
00788 
00789    for ( ; ; )
00790    {
00791       if (--bytesleft == 0)
00792          return PJPG_NOT_JPEG;
00793 
00794       lastchar = thischar;
00795 
00796       thischar = (uint8)getBits1(8);
00797 
00798       if (lastchar == 0xFF) 
00799       {
00800          if (thischar == M_SOI)
00801             break;
00802          else if (thischar == M_EOI)    //getBits1 will keep returning M_EOI if we read past the end
00803             return PJPG_NOT_JPEG;
00804       }
00805    }
00806 
00807    /* Check the next character after marker: if it's not 0xFF, it can't
00808    be the start of the next marker, so the file is bad */
00809 
00810    thischar = (uint8)((gBitBuf >> 8) & 0xFF);
00811 
00812    if (thischar != 0xFF)
00813       return PJPG_NOT_JPEG;
00814       
00815    return 0;
00816 }
00817 //------------------------------------------------------------------------------
00818 // Find a start of frame (SOF) marker.
00819 static uint8 locateSOFMarker(void)
00820 {
00821    uint8 c;
00822 
00823    uint8 status = locateSOIMarker();
00824    if (status)
00825       return status;
00826    
00827    status = processMarkers(&c);
00828    if (status)
00829       return status;
00830 
00831    switch (c)
00832    {
00833       case M_SOF2:
00834       {
00835          return PJPG_UNSUPPORTED_MODE;
00836       }
00837       case M_SOF0:  /* baseline DCT */
00838       {
00839          status = readSOFMarker();
00840          if (status)
00841             return status;
00842             
00843          break;
00844       }
00845       case M_SOF9:  
00846       {
00847          return PJPG_NO_ARITHMITIC_SUPPORT;
00848       }
00849       case M_SOF1:  /* extended sequential DCT */
00850       default:
00851       {
00852          return PJPG_UNSUPPORTED_MARKER;
00853       }
00854    }
00855    
00856    return 0;
00857 }
00858 //------------------------------------------------------------------------------
00859 // Find a start of scan (SOS) marker.
00860 static uint8 locateSOSMarker(uint8* pFoundEOI)
00861 {
00862    uint8 c;
00863    uint8 status;
00864 
00865    *pFoundEOI = 0;
00866       
00867    status = processMarkers(&c);
00868    if (status)
00869       return status;
00870 
00871    if (c == M_EOI)
00872    {
00873       *pFoundEOI = 1;
00874       return 0;
00875    }
00876    else if (c != M_SOS)
00877       return PJPG_UNEXPECTED_MARKER;
00878 
00879    return readSOSMarker();
00880 }
00881 //------------------------------------------------------------------------------
00882 static uint8 init(void)
00883 {
00884    gImageXSize = 0;
00885    gImageYSize = 0;
00886    gCompsInFrame = 0;
00887    gRestartInterval = 0;
00888    gCompsInScan = 0;
00889    gValidHuffTables = 0;
00890    gValidQuantTables = 0;
00891    gTemFlag = 0;
00892    gInBufOfs = 0;
00893    gInBufLeft = 0;
00894    gBitBuf = 0;
00895    gBitsLeft = 8;
00896 
00897    getBits1(8);
00898    getBits1(8);
00899 
00900    return 0;
00901 }
00902 //------------------------------------------------------------------------------
00903 // This method throws back into the stream any bytes that where read
00904 // into the bit buffer during initial marker scanning.
00905 static void fixInBuffer(void)
00906 {
00907    /* In case any 0xFF's where pulled into the buffer during marker scanning */
00908 
00909    if (gBitsLeft > 0)  
00910       stuffChar((uint8)gBitBuf);
00911    
00912    stuffChar((uint8)(gBitBuf >> 8));
00913    
00914    gBitsLeft = 8;
00915    getBits2(8);
00916    getBits2(8);
00917 }
00918 //------------------------------------------------------------------------------
00919 // Restart interval processing.
00920 static uint8 processRestart(void)
00921 {
00922    // Let's scan a little bit to find the marker, but not _too_ far.
00923    // 1536 is a "fudge factor" that determines how much to scan.
00924    uint16 i;
00925    uint8 c = 0;
00926 
00927    for (i = 1536; i > 0; i--)
00928       if (getChar() == 0xFF)
00929          break;
00930 
00931    if (i == 0)
00932       return PJPG_BAD_RESTART_MARKER;
00933    
00934    for ( ; i > 0; i--)
00935       if ((c = getChar()) != 0xFF)
00936          break;
00937 
00938    if (i == 0)
00939       return PJPG_BAD_RESTART_MARKER;
00940 
00941    // Is it the expected marker? If not, something bad happened.
00942    if (c != (gNextRestartNum + M_RST0))
00943       return PJPG_BAD_RESTART_MARKER;
00944 
00945    // Reset each component's DC prediction values.
00946    gLastDC[0] = 0;
00947    gLastDC[1] = 0;
00948    gLastDC[2] = 0;
00949 
00950    gRestartsLeft = gRestartInterval;
00951 
00952    gNextRestartNum = (gNextRestartNum + 1) & 7;
00953 
00954    // Get the bit buffer going again...
00955 
00956    gBitsLeft = 8;
00957    getBits2(8);
00958    getBits2(8);
00959    
00960    return 0;
00961 }
00962 //------------------------------------------------------------------------------
00963 static uint8 findEOI(void)
00964 {
00965    uint8 c;
00966    uint8 status;
00967 
00968    // Prime the bit buffer
00969    gBitsLeft = 8;
00970    getBits1(8);
00971    getBits1(8);
00972 
00973    // The next marker _should_ be EOI
00974    status = processMarkers(&c);
00975    if (status)
00976       return status;
00977    
00978    //gTotalBytesRead -= in_buf_left;
00979    if (c != M_EOI)
00980       return PJPG_UNEXPECTED_MARKER;
00981    
00982    return 0;
00983 }
00984 //------------------------------------------------------------------------------
00985 static uint8 checkHuffTables(void)
00986 {
00987    uint8 i;
00988 
00989    for (i = 0; i < gCompsInScan; i++)
00990    {
00991       uint8 compDCTab = gCompDCTab[gCompList[i]];
00992       uint8 compACTab = gCompACTab[gCompList[i]] + 2;
00993       
00994       if ( ((gValidHuffTables & (1 << compDCTab)) == 0) ||
00995            ((gValidHuffTables & (1 << compACTab)) == 0) )
00996          return PJPG_UNDEFINED_HUFF_TABLE;           
00997    }
00998    
00999    return 0;
01000 }
01001 //------------------------------------------------------------------------------
01002 static uint8 checkQuantTables(void)
01003 {
01004    uint8 i;
01005 
01006    for (i = 0; i < gCompsInScan; i++)
01007    {
01008       uint8 compQuantMask = gCompQuant[gCompList[i]] ? 2 : 1;
01009       
01010       if ((gValidQuantTables & compQuantMask) == 0)
01011          return PJPG_UNDEFINED_QUANT_TABLE;
01012    }         
01013 
01014    return 0;         
01015 }
01016 //------------------------------------------------------------------------------
01017 static uint8 initScan(void)
01018 {
01019    uint8 foundEOI;
01020    uint8 status = locateSOSMarker(&foundEOI);
01021    if (status)
01022       return status;
01023    if (foundEOI)
01024       return PJPG_UNEXPECTED_MARKER;
01025    
01026    status = checkHuffTables();
01027    if (status)
01028       return status;
01029 
01030    status = checkQuantTables();
01031    if (status)
01032       return status;
01033 
01034    gLastDC[0] = 0;
01035    gLastDC[1] = 0;
01036    gLastDC[2] = 0;
01037 
01038    if (gRestartInterval)
01039    {
01040       gRestartsLeft = gRestartInterval;
01041       gNextRestartNum = 0;
01042    }
01043 
01044    fixInBuffer();
01045 
01046    return 0;
01047 }
01048 //------------------------------------------------------------------------------
01049 static uint8 initFrame(void)
01050 {
01051    if (gCompsInFrame == 1)
01052    {
01053       if ((gCompHSamp[0] != 1) || (gCompVSamp[0] != 1))
01054          return PJPG_UNSUPPORTED_SAMP_FACTORS;
01055 
01056       gScanType = PJPG_GRAYSCALE;
01057 
01058       gMaxBlocksPerMCU = 1;
01059       gMCUOrg[0] = 0;
01060 
01061       gMaxMCUXSize     = 8;
01062       gMaxMCUYSize     = 8;
01063    }
01064    else if (gCompsInFrame == 3)
01065    {
01066       if ( ((gCompHSamp[1] != 1) || (gCompVSamp[1] != 1)) ||
01067          ((gCompHSamp[2] != 1) || (gCompVSamp[2] != 1)) )
01068          return PJPG_UNSUPPORTED_SAMP_FACTORS;
01069 
01070       if ((gCompHSamp[0] == 1) && (gCompVSamp[0] == 1))
01071       {
01072          gScanType = PJPG_YH1V1;
01073 
01074          gMaxBlocksPerMCU = 3;
01075          gMCUOrg[0] = 0;
01076          gMCUOrg[1] = 1;
01077          gMCUOrg[2] = 2;
01078                   
01079          gMaxMCUXSize = 8;
01080          gMaxMCUYSize = 8;
01081       }
01082       else if ((gCompHSamp[0] == 2) && (gCompVSamp[0] == 2))
01083       {
01084          gScanType = PJPG_YH2V2;
01085 
01086          gMaxBlocksPerMCU = 6;
01087          gMCUOrg[0] = 0;
01088          gMCUOrg[1] = 0;
01089          gMCUOrg[2] = 0;
01090          gMCUOrg[3] = 0;
01091          gMCUOrg[4] = 1;
01092          gMCUOrg[5] = 2;
01093 
01094          gMaxMCUXSize = 16;
01095          gMaxMCUYSize = 16;
01096       }
01097       else
01098          return PJPG_UNSUPPORTED_SAMP_FACTORS;
01099    }
01100    else
01101       return PJPG_UNSUPPORTED_COLORSPACE;
01102 
01103    gMaxMCUSPerRow = (gImageXSize + (gMaxMCUXSize - 1)) >> ((gMaxMCUXSize == 8) ? 3 : 4);
01104    gMaxMCUSPerCol = (gImageYSize + (gMaxMCUYSize - 1)) >> ((gMaxMCUYSize == 8) ? 3 : 4);
01105    
01106    gNumMCUSRemaining = gMaxMCUSPerRow * gMaxMCUSPerCol;
01107    
01108    return 0;
01109 }
01110 /*----------------------------------------------------------------------------*/
01111 #define DCT_SCALE_BITS   7
01112 
01113 #define DCT_SCALE       (1U << DCT_SCALE_BITS)
01114 
01115 #define DESCALE(x)   (((x) + (1U << (DCT_SCALE_BITS - 1))) >> DCT_SCALE_BITS)
01116 
01117 #define WFIX(x) ((x) * DCT_SCALE + 0.5f)
01118 
01119 #define WINOGRAD_QUANT_SCALE_BITS 10
01120 
01121 const uint8 gWinogradQuant[] = 
01122 {
01123    128,  178,  178,  167,  246,  167,  151,  232,
01124    232,  151,  128,  209,  219,  209,  128,  101,
01125    178,  197,  197,  178,  101,   69,  139,  167,
01126    177,  167,  139,   69,   35,   96,  131,  151,
01127    151,  131,   96,   35,   49,   91,  118,  128,
01128    118,   91,   49,   46,   81,  101,  101,   81,
01129    46,   42,   69,   79,   69,   42,   35,   54,
01130    54,   35,   28,   37,   28,   19,   19,   10,
01131 };   
01132 
01133 static void createWinogradQuant(int16* pQuant)
01134 {
01135    uint8 i;
01136    
01137    for (i = 0; i < 64; i++) 
01138    {
01139       long x = pQuant[i];
01140       x *= gWinogradQuant[i];
01141       pQuant[i] = (int16)((x + (1 << (WINOGRAD_QUANT_SCALE_BITS - DCT_SCALE_BITS - 1))) >> (WINOGRAD_QUANT_SCALE_BITS - DCT_SCALE_BITS));
01142    }
01143 }
01144 
01145 // 1/cos(4*pi/16)
01146 // 362, 256+106
01147 #define b1 362
01148 
01149 // 1/cos(6*pi/16)
01150 // 669, 256+256+157
01151 #define b2 669
01152 
01153 // 1/cos(4*pi/16)
01154 // 362, 256+106
01155 #define b3 362
01156 
01157 // 1/cos(2*pi/16)
01158 // 277, 256+21
01159 #define b4 277
01160 
01161 // 1/(cos(2*pi/16) + cos(6*pi/16))
01162 // 196, 196
01163 #define b5 196
01164 
01165 static int16 imul_b1_b3(int16 w)
01166 {
01167    long x = (w * 362L);
01168    x += 128L;
01169    return (int16)(x >> 8);
01170 }
01171 
01172 static int16 imul_b2(int16 w)
01173 {
01174    long x = (w * 669L);
01175    x += 128L;
01176    return (int16)(x >> 8);
01177 }
01178 
01179 static int16 imul_b4(int16 w)
01180 {
01181    long x = (w * 277L);
01182    x += 128L;
01183    return (int16)(x >> 8);
01184 }
01185 
01186 static int16 imul_b5(int16 w)
01187 {
01188    long x = (w * 196L);
01189    x += 128L;
01190    return (int16)(x >> 8);
01191 }
01192 
01193 static uint8 clamp(int16 s)
01194 {
01195    if ((uint16)s > 255U)
01196    {
01197       if (s < 0) 
01198          return 0; 
01199       else if (s > 255) 
01200          return 255;
01201    }
01202       
01203    return (uint8)s;
01204 }
01205 
01206 static void idctRows(void)
01207 {
01208    uint8 i;
01209    int16* pSrc = gCoeffBuf;
01210          
01211    for (i = 0; i < 8; i++)
01212    {
01213       int16 src4 = *(pSrc+5);
01214       int16 src7 = *(pSrc+3);
01215       int16 x4  = src4 - src7;
01216       int16 x7  = src4 + src7;
01217 
01218       int16 src5 = *(pSrc+1);
01219       int16 src6 = *(pSrc+7);
01220       int16 x5  = src5 + src6;
01221       int16 x6  = src5 - src6;
01222 
01223       int16 tmp1 = imul_b5(x4 - x6);
01224       int16 stg26 = imul_b4(x6) - tmp1;
01225 
01226       int16 x24 = tmp1 - imul_b2(x4);
01227 
01228       int16 x15 = x5 - x7;
01229       int16 x17 = x5 + x7;
01230 
01231       int16 tmp2 = stg26 - x17;
01232       int16 tmp3 = imul_b1_b3(x15) - tmp2;
01233       int16 x44 = tmp3 + x24;
01234 
01235       int16 src0 = *(pSrc+0);
01236       int16 src1 = *(pSrc+4);
01237       int16 x30 = src0 + src1;
01238       int16 x31 = src0 - src1;
01239 
01240       int16 src2 = *(pSrc+2);
01241       int16 src3 = *(pSrc+6);
01242       int16 x12 = src2 - src3;
01243       int16 x13 = src2 + src3;
01244 
01245       int16 x32 = imul_b1_b3(x12) - x13;
01246 
01247       int16 x40 = x30 + x13;
01248       int16 x43 = x30 - x13;
01249       int16 x41 = x31 + x32;
01250       int16 x42 = x31 - x32;
01251 
01252       *(pSrc+0) = x40 + x17;
01253       *(pSrc+1) = x41 + tmp2;
01254       *(pSrc+2) = x42 + tmp3;
01255       *(pSrc+3) = x43 - x44;
01256       *(pSrc+4) = x43 + x44;
01257       *(pSrc+5) = x42 - tmp3;
01258       *(pSrc+6) = x41 - tmp2;
01259       *(pSrc+7) = x40 - x17;
01260                   
01261       pSrc += 8;
01262    }      
01263 }
01264 
01265 static void idctCols(void)
01266 {
01267    uint8 i;
01268       
01269    int16* pSrc = gCoeffBuf;
01270    
01271    for (i = 0; i < 8; i++)
01272    {
01273       int16 src4 = *(pSrc+5*8);
01274       int16 src7 = *(pSrc+3*8);
01275       int16 x4  = src4 - src7;
01276       int16 x7  = src4 + src7;
01277 
01278       int16 src5 = *(pSrc+1*8);
01279       int16 src6 = *(pSrc+7*8);
01280       int16 x5  = src5 + src6;
01281       int16 x6  = src5 - src6;
01282 
01283       int16 tmp1 = imul_b5(x4 - x6);
01284       int16 stg26 = imul_b4(x6) - tmp1;
01285 
01286       int16 x24 = tmp1 - imul_b2(x4);
01287 
01288       int16 x15 = x5 - x7;
01289       int16 x17 = x5 + x7;
01290 
01291       int16 tmp2 = stg26 - x17;
01292       int16 tmp3 = imul_b1_b3(x15) - tmp2;
01293       int16 x44 = tmp3 + x24;
01294 
01295       int16 src0 = *(pSrc+0*8);
01296       int16 src1 = *(pSrc+4*8);
01297       int16 x30 = src0 + src1;
01298       int16 x31 = src0 - src1;
01299 
01300       int16 src2 = *(pSrc+2*8);
01301       int16 src3 = *(pSrc+6*8);
01302       int16 x12 = src2 - src3;
01303       int16 x13 = src2 + src3;
01304 
01305       int16 x32 = imul_b1_b3(x12) - x13;
01306 
01307       int16 x40 = x30 + x13;
01308       int16 x43 = x30 - x13;
01309       int16 x41 = x31 + x32;
01310       int16 x42 = x31 - x32;
01311 
01312       *(pSrc+0*8) = clamp(DESCALE(x40 + x17)  + 128);
01313       *(pSrc+1*8) = clamp(DESCALE(x41 + tmp2) + 128);
01314       *(pSrc+2*8) = clamp(DESCALE(x42 + tmp3) + 128);
01315       *(pSrc+3*8) = clamp(DESCALE(x43 - x44)  + 128);
01316       *(pSrc+4*8) = clamp(DESCALE(x43 + x44)  + 128);
01317       *(pSrc+5*8) = clamp(DESCALE(x42 - tmp3) + 128);
01318       *(pSrc+6*8) = clamp(DESCALE(x41 - tmp2) + 128);
01319       *(pSrc+7*8) = clamp(DESCALE(x40 - x17)  + 128);
01320 
01321       pSrc++;      
01322    }      
01323 }
01324 
01325 /*----------------------------------------------------------------------------*/
01326 static uint8 addAndClamp(uint8 a, int16 b)
01327 {
01328    b = a + b;
01329    
01330    if ((uint16)b > 255U)
01331    {
01332       if (b < 0)
01333          return 0;
01334       else if (b > 255)
01335          return 255;
01336    }
01337       
01338    return (uint8)b;
01339 }
01340 /*----------------------------------------------------------------------------*/
01341 static uint8 subAndClamp(uint8 a, int16 b)
01342 {
01343    b = a - b;
01344 
01345    if ((uint16)b > 255U)
01346    {
01347       if (b < 0)
01348          return 0;
01349       else if (b > 255)
01350          return 255;
01351    }
01352 
01353    return (uint8)b;
01354 }
01355 /*----------------------------------------------------------------------------*/
01356 // 103/256
01357 //R = Y + 1.402 (Cr-128)
01358 
01359 // 88/256, 183/256
01360 //G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
01361 
01362 // 198/256
01363 //B = Y + 1.772 (Cb-128)
01364 /*----------------------------------------------------------------------------*/
01365 static void upsampleCb(uint8 srcOfs, uint8 dstOfs)
01366 {
01367    // Cb - affects G and B
01368    uint8 x, y;
01369    int16* pSrc = gCoeffBuf + srcOfs;
01370    uint8* pDstG = gMCUBufG + dstOfs;
01371    uint8* pDstB = gMCUBufB + dstOfs;
01372    for (y = 0; y < 4; y++)
01373    {
01374       for (x = 0; x < 4; x++)
01375       {
01376          uint8 cb = (uint8)*pSrc++;
01377          int16 cbG, cbB;
01378 
01379          cbG = ((cb * 88U) >> 8U) - 44U;
01380          pDstG[0] = subAndClamp(pDstG[0], cbG);
01381          pDstG[1] = subAndClamp(pDstG[1], cbG);
01382          pDstG[8] = subAndClamp(pDstG[8], cbG);
01383          pDstG[9] = subAndClamp(pDstG[9], cbG);
01384 
01385          cbB = (cb + ((cb * 198U) >> 8U)) - 227U;
01386          pDstB[0] = addAndClamp(pDstB[0], cbB);
01387          pDstB[1] = addAndClamp(pDstB[1], cbB);
01388          pDstB[8] = addAndClamp(pDstB[8], cbB);
01389          pDstB[9] = addAndClamp(pDstB[9], cbB);
01390 
01391          pDstG += 2;
01392          pDstB += 2;
01393       }
01394 
01395       pSrc = pSrc - 4 + 8;
01396       pDstG = pDstG - 8 + 16;
01397       pDstB = pDstB - 8 + 16;
01398    }
01399 }   
01400 /*----------------------------------------------------------------------------*/
01401 // 103/256
01402 //R = Y + 1.402 (Cr-128)
01403 
01404 // 88/256, 183/256
01405 //G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
01406 
01407 // 198/256
01408 //B = Y + 1.772 (Cb-128)
01409 /*----------------------------------------------------------------------------*/
01410 static void upsampleCr(uint8 srcOfs, uint8 dstOfs)
01411 {
01412    // Cr - affects R and G
01413    uint8 x, y;
01414    int16* pSrc = gCoeffBuf + srcOfs;
01415    uint8* pDstR = gMCUBufR + dstOfs;
01416    uint8* pDstG = gMCUBufG + dstOfs;
01417    for (y = 0; y < 4; y++)
01418    {
01419       for (x = 0; x < 4; x++)
01420       {
01421          uint8 cr = (uint8)*pSrc++;
01422          int16 crR, crG;
01423 
01424          crR = (cr + ((cr * 103U) >> 8U)) - 179;
01425          pDstR[0] = addAndClamp(pDstR[0], crR);
01426          pDstR[1] = addAndClamp(pDstR[1], crR);
01427          pDstR[8] = addAndClamp(pDstR[8], crR);
01428          pDstR[9] = addAndClamp(pDstR[9], crR);
01429          
01430          crG = ((cr * 183U) >> 8U) - 91;
01431          pDstG[0] = subAndClamp(pDstG[0], crG);
01432          pDstG[1] = subAndClamp(pDstG[1], crG);
01433          pDstG[8] = subAndClamp(pDstG[8], crG);
01434          pDstG[9] = subAndClamp(pDstG[9], crG);
01435          
01436          pDstR += 2;
01437          pDstG += 2;
01438       }
01439 
01440       pSrc = pSrc - 4 + 8;
01441       pDstR = pDstR - 8 + 16;
01442       pDstG = pDstG - 8 + 16;
01443    }
01444 }   
01445 /*----------------------------------------------------------------------------*/
01446 static void copyY(uint8 dstOfs)
01447 {
01448    uint8 i;
01449    uint8* pRDst = gMCUBufR + dstOfs;
01450    uint8* pGDst = gMCUBufG + dstOfs;
01451    uint8* pBDst = gMCUBufB + dstOfs;
01452    int16* pSrc = gCoeffBuf;
01453    
01454    for (i = 64; i > 0; i--)
01455    {
01456       uint8 c = (uint8)*pSrc++;
01457       
01458       *pRDst++ = c;
01459       *pGDst++ = c;
01460       *pBDst++ = c;
01461    }
01462 }
01463 /*----------------------------------------------------------------------------*/
01464 static void convertCb(uint8 dstOfs)
01465 {
01466    uint8 i;
01467    uint8* pDstG = gMCUBufG + dstOfs;
01468    uint8* pDstB = gMCUBufB + dstOfs;
01469    int16* pSrc = gCoeffBuf;
01470 
01471    for (i = 64; i > 0; i--)
01472    {
01473       uint8 cb = (uint8)*pSrc++;
01474       int16 cbG, cbB;
01475 
01476       cbG = ((cb * 88U) >> 8U) - 44U;
01477       *pDstG++ = subAndClamp(pDstG[0], cbG);
01478 
01479       cbB = (cb + ((cb * 198U) >> 8U)) - 227U;
01480       *pDstB++ = addAndClamp(pDstB[0], cbB);
01481    }
01482 }
01483 /*----------------------------------------------------------------------------*/
01484 static void convertCr(uint8 dstOfs)
01485 {
01486    uint8 i;
01487    uint8* pDstR = gMCUBufR + dstOfs;
01488    uint8* pDstG = gMCUBufG + dstOfs;
01489    int16* pSrc = gCoeffBuf;
01490 
01491    for (i = 64; i > 0; i--)
01492    {
01493       uint8 cr = (uint8)*pSrc++;
01494       int16 crR, crG;
01495 
01496       crR = (cr + ((cr * 103U) >> 8U)) - 179;
01497       *pDstR++ = addAndClamp(pDstR[0], crR);
01498 
01499       crG = ((cr * 183U) >> 8U) - 91;
01500       *pDstG++ = subAndClamp(pDstG[0], crG);
01501    }
01502 }
01503 /*----------------------------------------------------------------------------*/
01504 static void transformBlock(uint8 mcuBlock)
01505 {
01506    idctRows();
01507    idctCols();
01508    
01509    switch (gScanType)
01510    {
01511       case PJPG_GRAYSCALE:
01512       {
01513          copyY(0);
01514          break;
01515       }
01516       case PJPG_YH1V1:
01517       {
01518          switch (mcuBlock)
01519          {
01520             case 0:
01521             {
01522                copyY(0);
01523                break;
01524             }
01525             case 1:
01526             {
01527                convertCb(0);
01528                break;
01529             }
01530             case 2:
01531             {
01532                convertCr(0);
01533                break;
01534             }
01535          }
01536 
01537          break;
01538       }
01539       case PJPG_YH2V2:
01540       {
01541          switch (mcuBlock)
01542          {
01543             case 0:
01544             {
01545                copyY(0);
01546                break;
01547             }
01548             case 1:
01549             {
01550                copyY(64);
01551                break;
01552             }
01553             case 2:
01554             {
01555                copyY(128);
01556                break;
01557             }
01558             case 3:
01559             {
01560                copyY(192);
01561                break;
01562             }
01563             case 4:
01564             {
01565                upsampleCb(0, 0);
01566                upsampleCb(4, 64);
01567                upsampleCb(4*8, 128);
01568                upsampleCb(4+4*8, 192);
01569                break;
01570             }
01571             case 5:
01572             {
01573                upsampleCr(0, 0);
01574                upsampleCr(4, 64);
01575                upsampleCr(4*8, 128);
01576                upsampleCr(4+4*8, 192);
01577                break;
01578             }
01579          }
01580       }         
01581    }      
01582 }
01583 //------------------------------------------------------------------------------
01584 static uint8 decodeNextMCU(void)
01585 {
01586    uint8 status;
01587    uint8 mcuBlock;   
01588 
01589    if (gRestartInterval) 
01590    {
01591       if (gRestartsLeft == 0)
01592       {
01593          status = processRestart();
01594          if (status)
01595             return status;
01596       }
01597       gRestartsLeft--;
01598    }      
01599    
01600    for (mcuBlock = 0; mcuBlock < gMaxBlocksPerMCU; mcuBlock++)
01601    {
01602       uint8 componentID = gMCUOrg[mcuBlock];
01603       uint8 compQuant = gCompQuant[componentID];    
01604       uint8 compDCTab = gCompDCTab[componentID];
01605       uint8 numExtraBits, compACTab, k;
01606       const int16* pQ = compQuant ? gQuant1 : gQuant0;
01607       uint16 r, dc;
01608 
01609       uint8 s = huffDecode(compDCTab ? &gHuffTab1 : &gHuffTab0, compDCTab ? gHuffVal1 : gHuffVal0);
01610       
01611       r = 0;
01612       numExtraBits = s & 0xF;
01613       if (numExtraBits)
01614          r = getBits2(numExtraBits);
01615       dc = huffExtend(r, s);
01616             
01617       dc = dc + gLastDC[componentID];
01618       gLastDC[componentID] = dc;
01619             
01620       gCoeffBuf[0] = dc * pQ[0];
01621 
01622       compACTab = gCompACTab[componentID];
01623                         
01624       for (k = 1; k < 64; k++)
01625       {
01626          uint16 extraBits;
01627 
01628          s = huffDecode(compACTab ? &gHuffTab3 : &gHuffTab2, compACTab ? gHuffVal3 : gHuffVal2);
01629 
01630          extraBits = 0;
01631          numExtraBits = s & 0xF;
01632          if (numExtraBits)
01633             extraBits = getBits2(numExtraBits);
01634 
01635          r = s >> 4;
01636          s &= 15;
01637 
01638          if (s)
01639          {
01640             int16 ac;
01641 
01642             if (r)
01643             {
01644                if ((k + r) > 63)
01645                   return PJPG_DECODE_ERROR;
01646 
01647                while (r)
01648                {
01649                   gCoeffBuf[ZAG[k++]] = 0;
01650                   r--;
01651                }
01652             }
01653 
01654             ac = huffExtend(extraBits, s);
01655             
01656             gCoeffBuf[ZAG[k]] = ac * pQ[k]; 
01657          }
01658          else
01659          {
01660             if (r == 15)
01661             {
01662                if ((k + 16) > 64)
01663                   return PJPG_DECODE_ERROR;
01664                
01665                for (r = 16; r > 0; r--)
01666                   gCoeffBuf[ZAG[k++]] = 0;
01667                
01668                k--; // - 1 because the loop counter is k
01669             }
01670             else
01671                break;
01672          }
01673       }
01674       
01675       while (k < 64)
01676          gCoeffBuf[ZAG[k++]] = 0;
01677 
01678       transformBlock(mcuBlock); 
01679    }
01680          
01681    return 0;
01682 }
01683 //------------------------------------------------------------------------------
01684 unsigned char pjpeg_decode_mcu(void)
01685 {
01686    uint8 status;
01687 
01688    if (!gNumMCUSRemaining)
01689       return PJPG_NO_MORE_BLOCKS;
01690       
01691    status = decodeNextMCU();
01692    if (status)
01693       return status;
01694       
01695    gNumMCUSRemaining--;
01696    
01697    return 0;
01698 }
01699 //------------------------------------------------------------------------------
01700 unsigned char pjpeg_decode_init(pjpeg_image_info_t *pInfo, pjpeg_need_bytes_callback_t pNeed_bytes_callback, void *pCallback_data)
01701 {
01702    uint8 status;
01703 
01704    g_pNeedBytesCallback = pNeed_bytes_callback;
01705    g_pCallback_data = pCallback_data;
01706     
01707    status = init();
01708    if (status)
01709       return status;
01710       
01711    status = locateSOFMarker();
01712    if (status)
01713       return status;
01714 
01715    status = initFrame();
01716    if (status)
01717       return status;
01718 
01719    status = initScan();
01720    if (status)
01721       return status;
01722 
01723    pInfo->m_width = gImageXSize;
01724    pInfo->m_height = gImageYSize;
01725    pInfo->m_comps = gCompsInFrame;
01726    pInfo->m_scanType = gScanType;
01727    pInfo->m_MCUSPerRow = gMaxMCUSPerRow;
01728    pInfo->m_MCUSPerCol = gMaxMCUSPerCol;
01729    pInfo->m_MCUWidth = gMaxMCUXSize;
01730    pInfo->m_MCUHeight = gMaxMCUYSize;
01731    pInfo->m_pMCUBufR = gMCUBufR;
01732    pInfo->m_pMCUBufG = gMCUBufG;
01733    pInfo->m_pMCUBufB = gMCUBufB;
01734       
01735    return 0;
01736 }