Dependencies:   mbed

Committer:
XkLi
Date:
Tue Oct 11 01:24:18 2011 +0000
Revision:
0:c546b51ecf0b
v1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
XkLi 0:c546b51ecf0b 1 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 2 // picojpeg v1.0 - Public domain, Rich Geldreich <richgel99@gmail.com>
XkLi 0:c546b51ecf0b 3 // Last modified Nov. 27, 2010
XkLi 0:c546b51ecf0b 4 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 5 #include "picojpeg.h"
XkLi 0:c546b51ecf0b 6 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 7 typedef unsigned char uint8;
XkLi 0:c546b51ecf0b 8 typedef unsigned short uint16;
XkLi 0:c546b51ecf0b 9 typedef signed char int8;
XkLi 0:c546b51ecf0b 10 typedef signed short int16;
XkLi 0:c546b51ecf0b 11 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 12 // Change as needed - the PJPG_MAX_WIDTH/PJPG_MAX_HEIGHT checks are only present
XkLi 0:c546b51ecf0b 13 // to quickly detect bogus files.
XkLi 0:c546b51ecf0b 14 #define PJPG_MAX_WIDTH 16384
XkLi 0:c546b51ecf0b 15 #define PJPG_MAX_HEIGHT 16384
XkLi 0:c546b51ecf0b 16
XkLi 0:c546b51ecf0b 17 #define PJPG_MAXCOMPSINSCAN 3
XkLi 0:c546b51ecf0b 18 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 19 typedef enum
XkLi 0:c546b51ecf0b 20 {
XkLi 0:c546b51ecf0b 21 M_SOF0 = 0xC0,
XkLi 0:c546b51ecf0b 22 M_SOF1 = 0xC1,
XkLi 0:c546b51ecf0b 23 M_SOF2 = 0xC2,
XkLi 0:c546b51ecf0b 24 M_SOF3 = 0xC3,
XkLi 0:c546b51ecf0b 25
XkLi 0:c546b51ecf0b 26 M_SOF5 = 0xC5,
XkLi 0:c546b51ecf0b 27 M_SOF6 = 0xC6,
XkLi 0:c546b51ecf0b 28 M_SOF7 = 0xC7,
XkLi 0:c546b51ecf0b 29
XkLi 0:c546b51ecf0b 30 M_JPG = 0xC8,
XkLi 0:c546b51ecf0b 31 M_SOF9 = 0xC9,
XkLi 0:c546b51ecf0b 32 M_SOF10 = 0xCA,
XkLi 0:c546b51ecf0b 33 M_SOF11 = 0xCB,
XkLi 0:c546b51ecf0b 34
XkLi 0:c546b51ecf0b 35 M_SOF13 = 0xCD,
XkLi 0:c546b51ecf0b 36 M_SOF14 = 0xCE,
XkLi 0:c546b51ecf0b 37 M_SOF15 = 0xCF,
XkLi 0:c546b51ecf0b 38
XkLi 0:c546b51ecf0b 39 M_DHT = 0xC4,
XkLi 0:c546b51ecf0b 40
XkLi 0:c546b51ecf0b 41 M_DAC = 0xCC,
XkLi 0:c546b51ecf0b 42
XkLi 0:c546b51ecf0b 43 M_RST0 = 0xD0,
XkLi 0:c546b51ecf0b 44 M_RST1 = 0xD1,
XkLi 0:c546b51ecf0b 45 M_RST2 = 0xD2,
XkLi 0:c546b51ecf0b 46 M_RST3 = 0xD3,
XkLi 0:c546b51ecf0b 47 M_RST4 = 0xD4,
XkLi 0:c546b51ecf0b 48 M_RST5 = 0xD5,
XkLi 0:c546b51ecf0b 49 M_RST6 = 0xD6,
XkLi 0:c546b51ecf0b 50 M_RST7 = 0xD7,
XkLi 0:c546b51ecf0b 51
XkLi 0:c546b51ecf0b 52 M_SOI = 0xD8,
XkLi 0:c546b51ecf0b 53 M_EOI = 0xD9,
XkLi 0:c546b51ecf0b 54 M_SOS = 0xDA,
XkLi 0:c546b51ecf0b 55 M_DQT = 0xDB,
XkLi 0:c546b51ecf0b 56 M_DNL = 0xDC,
XkLi 0:c546b51ecf0b 57 M_DRI = 0xDD,
XkLi 0:c546b51ecf0b 58 M_DHP = 0xDE,
XkLi 0:c546b51ecf0b 59 M_EXP = 0xDF,
XkLi 0:c546b51ecf0b 60
XkLi 0:c546b51ecf0b 61 M_APP0 = 0xE0,
XkLi 0:c546b51ecf0b 62 M_APP15 = 0xEF,
XkLi 0:c546b51ecf0b 63
XkLi 0:c546b51ecf0b 64 M_JPG0 = 0xF0,
XkLi 0:c546b51ecf0b 65 M_JPG13 = 0xFD,
XkLi 0:c546b51ecf0b 66 M_COM = 0xFE,
XkLi 0:c546b51ecf0b 67
XkLi 0:c546b51ecf0b 68 M_TEM = 0x01,
XkLi 0:c546b51ecf0b 69
XkLi 0:c546b51ecf0b 70 M_ERROR = 0x100
XkLi 0:c546b51ecf0b 71 } JPEG_MARKER;
XkLi 0:c546b51ecf0b 72
XkLi 0:c546b51ecf0b 73 #define RST0 0xD0
XkLi 0:c546b51ecf0b 74 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 75 const int8 ZAG[] =
XkLi 0:c546b51ecf0b 76 {
XkLi 0:c546b51ecf0b 77 0, 1, 8, 16, 9, 2, 3, 10,
XkLi 0:c546b51ecf0b 78 17, 24, 32, 25, 18, 11, 4, 5,
XkLi 0:c546b51ecf0b 79 12, 19, 26, 33, 40, 48, 41, 34,
XkLi 0:c546b51ecf0b 80 27, 20, 13, 6, 7, 14, 21, 28,
XkLi 0:c546b51ecf0b 81 35, 42, 49, 56, 57, 50, 43, 36,
XkLi 0:c546b51ecf0b 82 29, 22, 15, 23, 30, 37, 44, 51,
XkLi 0:c546b51ecf0b 83 58, 59, 52, 45, 38, 31, 39, 46,
XkLi 0:c546b51ecf0b 84 53, 60, 61, 54, 47, 55, 62, 63,
XkLi 0:c546b51ecf0b 85 };
XkLi 0:c546b51ecf0b 86 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 87 // 128 bytes
XkLi 0:c546b51ecf0b 88 static int16 gCoeffBuf[8*8];
XkLi 0:c546b51ecf0b 89
XkLi 0:c546b51ecf0b 90 // 8*8*4 bytes * 3 = 768
XkLi 0:c546b51ecf0b 91 static uint8 gMCUBufR[256];
XkLi 0:c546b51ecf0b 92 static uint8 gMCUBufG[256];
XkLi 0:c546b51ecf0b 93 static uint8 gMCUBufB[256];
XkLi 0:c546b51ecf0b 94
XkLi 0:c546b51ecf0b 95 // 256 bytes
XkLi 0:c546b51ecf0b 96 static int16 gQuant0[8*8];
XkLi 0:c546b51ecf0b 97 static int16 gQuant1[8*8];
XkLi 0:c546b51ecf0b 98
XkLi 0:c546b51ecf0b 99 // 6 bytes
XkLi 0:c546b51ecf0b 100 static int16 gLastDC[3];
XkLi 0:c546b51ecf0b 101
XkLi 0:c546b51ecf0b 102 typedef struct HuffTableT
XkLi 0:c546b51ecf0b 103 {
XkLi 0:c546b51ecf0b 104 uint16 mMinCode[16];
XkLi 0:c546b51ecf0b 105 uint16 mMaxCode[16];
XkLi 0:c546b51ecf0b 106 uint8 mValPtr[16];
XkLi 0:c546b51ecf0b 107 } HuffTable;
XkLi 0:c546b51ecf0b 108
XkLi 0:c546b51ecf0b 109 // DC - 192
XkLi 0:c546b51ecf0b 110 static HuffTable gHuffTab0;
XkLi 0:c546b51ecf0b 111
XkLi 0:c546b51ecf0b 112 static uint8 gHuffVal0[16];
XkLi 0:c546b51ecf0b 113
XkLi 0:c546b51ecf0b 114 static HuffTable gHuffTab1;
XkLi 0:c546b51ecf0b 115 static uint8 gHuffVal1[16];
XkLi 0:c546b51ecf0b 116
XkLi 0:c546b51ecf0b 117 // AC - 672
XkLi 0:c546b51ecf0b 118 static HuffTable gHuffTab2;
XkLi 0:c546b51ecf0b 119 static uint8 gHuffVal2[256];
XkLi 0:c546b51ecf0b 120
XkLi 0:c546b51ecf0b 121 static HuffTable gHuffTab3;
XkLi 0:c546b51ecf0b 122 static uint8 gHuffVal3[256];
XkLi 0:c546b51ecf0b 123
XkLi 0:c546b51ecf0b 124 static uint8 gValidHuffTables;
XkLi 0:c546b51ecf0b 125 static uint8 gValidQuantTables;
XkLi 0:c546b51ecf0b 126
XkLi 0:c546b51ecf0b 127 static uint8 gTemFlag;
XkLi 0:c546b51ecf0b 128 #define MAX_IN_BUF_SIZE 256
XkLi 0:c546b51ecf0b 129 static uint8 gInBuf[MAX_IN_BUF_SIZE];
XkLi 0:c546b51ecf0b 130 static uint8 gInBufOfs;
XkLi 0:c546b51ecf0b 131 static uint8 gInBufLeft;
XkLi 0:c546b51ecf0b 132
XkLi 0:c546b51ecf0b 133 static uint16 gBitBuf;
XkLi 0:c546b51ecf0b 134 static uint8 gBitsLeft;
XkLi 0:c546b51ecf0b 135 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 136 static uint16 gImageXSize;
XkLi 0:c546b51ecf0b 137 static uint16 gImageYSize;
XkLi 0:c546b51ecf0b 138 static uint8 gCompsInFrame;
XkLi 0:c546b51ecf0b 139 static uint8 gCompIdent[3];
XkLi 0:c546b51ecf0b 140 static uint8 gCompHSamp[3];
XkLi 0:c546b51ecf0b 141 static uint8 gCompVSamp[3];
XkLi 0:c546b51ecf0b 142 static uint8 gCompQuant[3];
XkLi 0:c546b51ecf0b 143
XkLi 0:c546b51ecf0b 144 static uint16 gRestartInterval;
XkLi 0:c546b51ecf0b 145 static uint16 gNextRestartNum;
XkLi 0:c546b51ecf0b 146 static uint16 gRestartsLeft;
XkLi 0:c546b51ecf0b 147
XkLi 0:c546b51ecf0b 148 static uint8 gCompsInScan;
XkLi 0:c546b51ecf0b 149 static uint8 gCompList[3];
XkLi 0:c546b51ecf0b 150 static uint8 gCompDCTab[3]; // 0,1
XkLi 0:c546b51ecf0b 151 static uint8 gCompACTab[3]; // 0,1
XkLi 0:c546b51ecf0b 152
XkLi 0:c546b51ecf0b 153 static pjpeg_scan_type_t gScanType;
XkLi 0:c546b51ecf0b 154
XkLi 0:c546b51ecf0b 155 static uint8 gMaxBlocksPerMCU;
XkLi 0:c546b51ecf0b 156 static uint8 gMaxMCUXSize;
XkLi 0:c546b51ecf0b 157 static uint8 gMaxMCUYSize;
XkLi 0:c546b51ecf0b 158 static uint16 gMaxMCUSPerRow;
XkLi 0:c546b51ecf0b 159 static uint16 gMaxMCUSPerCol;
XkLi 0:c546b51ecf0b 160 static uint16 gNumMCUSRemaining;
XkLi 0:c546b51ecf0b 161 static uint8 gMCUOrg[6];
XkLi 0:c546b51ecf0b 162
XkLi 0:c546b51ecf0b 163 static pjpeg_need_bytes_callback_t g_pNeedBytesCallback;
XkLi 0:c546b51ecf0b 164 static void *g_pCallback_data;
XkLi 0:c546b51ecf0b 165 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 166 static uint8 fillInBuf(void)
XkLi 0:c546b51ecf0b 167 {
XkLi 0:c546b51ecf0b 168 unsigned char status;
XkLi 0:c546b51ecf0b 169
XkLi 0:c546b51ecf0b 170 // Reserve a few bytes at the beginning of the buffer for putting back ("stuffing") chars.
XkLi 0:c546b51ecf0b 171 gInBufOfs = 4;
XkLi 0:c546b51ecf0b 172 gInBufLeft = 0;
XkLi 0:c546b51ecf0b 173
XkLi 0:c546b51ecf0b 174 status = (*g_pNeedBytesCallback)(gInBuf + gInBufOfs, MAX_IN_BUF_SIZE - gInBufOfs, &gInBufLeft, g_pCallback_data);
XkLi 0:c546b51ecf0b 175 if (status)
XkLi 0:c546b51ecf0b 176 return status;
XkLi 0:c546b51ecf0b 177
XkLi 0:c546b51ecf0b 178 return 0;
XkLi 0:c546b51ecf0b 179 }
XkLi 0:c546b51ecf0b 180 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 181 static uint8 getChar(void)
XkLi 0:c546b51ecf0b 182 {
XkLi 0:c546b51ecf0b 183 if (!gInBufLeft)
XkLi 0:c546b51ecf0b 184 {
XkLi 0:c546b51ecf0b 185 fillInBuf();
XkLi 0:c546b51ecf0b 186 if (!gInBufLeft)
XkLi 0:c546b51ecf0b 187 {
XkLi 0:c546b51ecf0b 188 gTemFlag = ~gTemFlag;
XkLi 0:c546b51ecf0b 189 return gTemFlag ? 0xFF : 0xD9;
XkLi 0:c546b51ecf0b 190 }
XkLi 0:c546b51ecf0b 191 }
XkLi 0:c546b51ecf0b 192
XkLi 0:c546b51ecf0b 193 gInBufLeft--;
XkLi 0:c546b51ecf0b 194 return gInBuf[gInBufOfs++];
XkLi 0:c546b51ecf0b 195 }
XkLi 0:c546b51ecf0b 196 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 197 static void stuffChar(uint8 i)
XkLi 0:c546b51ecf0b 198 {
XkLi 0:c546b51ecf0b 199 gInBufOfs--;
XkLi 0:c546b51ecf0b 200 gInBuf[gInBufOfs] = i;
XkLi 0:c546b51ecf0b 201 gInBufLeft++;
XkLi 0:c546b51ecf0b 202 }
XkLi 0:c546b51ecf0b 203 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 204 static uint8 getOctet(uint8 FFCheck)
XkLi 0:c546b51ecf0b 205 {
XkLi 0:c546b51ecf0b 206 uint8 c = getChar();
XkLi 0:c546b51ecf0b 207
XkLi 0:c546b51ecf0b 208 if ((FFCheck) && (c == 0xFF))
XkLi 0:c546b51ecf0b 209 {
XkLi 0:c546b51ecf0b 210 uint8 n = getChar();
XkLi 0:c546b51ecf0b 211
XkLi 0:c546b51ecf0b 212 if (n)
XkLi 0:c546b51ecf0b 213 {
XkLi 0:c546b51ecf0b 214 stuffChar(n);
XkLi 0:c546b51ecf0b 215 stuffChar(0xFF);
XkLi 0:c546b51ecf0b 216 }
XkLi 0:c546b51ecf0b 217 }
XkLi 0:c546b51ecf0b 218
XkLi 0:c546b51ecf0b 219 return c;
XkLi 0:c546b51ecf0b 220 }
XkLi 0:c546b51ecf0b 221 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 222 static uint16 getBits(uint8 numBits, uint8 FFCheck)
XkLi 0:c546b51ecf0b 223 {
XkLi 0:c546b51ecf0b 224 uint8 origBits = numBits;
XkLi 0:c546b51ecf0b 225 uint16 ret = gBitBuf;
XkLi 0:c546b51ecf0b 226
XkLi 0:c546b51ecf0b 227 if (numBits > 8)
XkLi 0:c546b51ecf0b 228 {
XkLi 0:c546b51ecf0b 229 numBits -= 8;
XkLi 0:c546b51ecf0b 230
XkLi 0:c546b51ecf0b 231 gBitBuf <<= gBitsLeft;
XkLi 0:c546b51ecf0b 232
XkLi 0:c546b51ecf0b 233 gBitBuf |= getOctet(FFCheck);
XkLi 0:c546b51ecf0b 234
XkLi 0:c546b51ecf0b 235 gBitBuf <<= (8 - gBitsLeft);
XkLi 0:c546b51ecf0b 236
XkLi 0:c546b51ecf0b 237 ret = (ret & 0xFF00) | (gBitBuf >> 8);
XkLi 0:c546b51ecf0b 238 }
XkLi 0:c546b51ecf0b 239
XkLi 0:c546b51ecf0b 240 if (gBitsLeft < numBits)
XkLi 0:c546b51ecf0b 241 {
XkLi 0:c546b51ecf0b 242 gBitBuf <<= gBitsLeft;
XkLi 0:c546b51ecf0b 243
XkLi 0:c546b51ecf0b 244 gBitBuf |= getOctet(FFCheck);
XkLi 0:c546b51ecf0b 245
XkLi 0:c546b51ecf0b 246 gBitBuf <<= (numBits - gBitsLeft);
XkLi 0:c546b51ecf0b 247
XkLi 0:c546b51ecf0b 248 gBitsLeft = 8 - (numBits - gBitsLeft);
XkLi 0:c546b51ecf0b 249 }
XkLi 0:c546b51ecf0b 250 else
XkLi 0:c546b51ecf0b 251 {
XkLi 0:c546b51ecf0b 252 gBitsLeft = (uint8)(gBitsLeft - numBits);
XkLi 0:c546b51ecf0b 253 gBitBuf <<= numBits;
XkLi 0:c546b51ecf0b 254 }
XkLi 0:c546b51ecf0b 255
XkLi 0:c546b51ecf0b 256 return ret >> (16 - origBits);
XkLi 0:c546b51ecf0b 257 }
XkLi 0:c546b51ecf0b 258 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 259 static uint16 getBits1(uint8 numBits)
XkLi 0:c546b51ecf0b 260 {
XkLi 0:c546b51ecf0b 261 return getBits(numBits, 0);
XkLi 0:c546b51ecf0b 262 }
XkLi 0:c546b51ecf0b 263 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 264 static uint16 getBits2(uint8 numBits)
XkLi 0:c546b51ecf0b 265 {
XkLi 0:c546b51ecf0b 266 return getBits(numBits, 1);
XkLi 0:c546b51ecf0b 267 }
XkLi 0:c546b51ecf0b 268 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 269 static uint8 getBit(void)
XkLi 0:c546b51ecf0b 270 {
XkLi 0:c546b51ecf0b 271 uint8 ret = 0;
XkLi 0:c546b51ecf0b 272 if (gBitBuf & 0x8000)
XkLi 0:c546b51ecf0b 273 ret = 1;
XkLi 0:c546b51ecf0b 274
XkLi 0:c546b51ecf0b 275 if (!gBitsLeft)
XkLi 0:c546b51ecf0b 276 {
XkLi 0:c546b51ecf0b 277 gBitBuf |= getOctet(1);
XkLi 0:c546b51ecf0b 278
XkLi 0:c546b51ecf0b 279 gBitsLeft += 8;
XkLi 0:c546b51ecf0b 280 }
XkLi 0:c546b51ecf0b 281
XkLi 0:c546b51ecf0b 282 gBitsLeft--;
XkLi 0:c546b51ecf0b 283 gBitBuf <<= 1;
XkLi 0:c546b51ecf0b 284
XkLi 0:c546b51ecf0b 285 return ret;
XkLi 0:c546b51ecf0b 286 }
XkLi 0:c546b51ecf0b 287 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 288 static uint16 getExtendTest(uint8 i)
XkLi 0:c546b51ecf0b 289 {
XkLi 0:c546b51ecf0b 290 switch (i)
XkLi 0:c546b51ecf0b 291 {
XkLi 0:c546b51ecf0b 292 case 0: return 0;
XkLi 0:c546b51ecf0b 293 case 1: return 0x0001;
XkLi 0:c546b51ecf0b 294 case 2: return 0x0002;
XkLi 0:c546b51ecf0b 295 case 3: return 0x0004;
XkLi 0:c546b51ecf0b 296 case 4: return 0x0008;
XkLi 0:c546b51ecf0b 297 case 5: return 0x0010;
XkLi 0:c546b51ecf0b 298 case 6: return 0x0020;
XkLi 0:c546b51ecf0b 299 case 7: return 0x0040;
XkLi 0:c546b51ecf0b 300 case 8: return 0x0080;
XkLi 0:c546b51ecf0b 301 case 9: return 0x0100;
XkLi 0:c546b51ecf0b 302 case 10: return 0x0200;
XkLi 0:c546b51ecf0b 303 case 11: return 0x0400;
XkLi 0:c546b51ecf0b 304 case 12: return 0x0800;
XkLi 0:c546b51ecf0b 305 case 13: return 0x1000;
XkLi 0:c546b51ecf0b 306 case 14: return 0x2000;
XkLi 0:c546b51ecf0b 307 case 15: return 0x4000;
XkLi 0:c546b51ecf0b 308 default: return 0;
XkLi 0:c546b51ecf0b 309 }
XkLi 0:c546b51ecf0b 310 }
XkLi 0:c546b51ecf0b 311 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 312 static int16 getExtendOffset(uint8 i)
XkLi 0:c546b51ecf0b 313 {
XkLi 0:c546b51ecf0b 314 switch (i)
XkLi 0:c546b51ecf0b 315 {
XkLi 0:c546b51ecf0b 316 case 0: return 0;
XkLi 0:c546b51ecf0b 317 case 1: return ((-1)<<1) + 1;
XkLi 0:c546b51ecf0b 318 case 2: return ((-1)<<2) + 1;
XkLi 0:c546b51ecf0b 319 case 3: return ((-1)<<3) + 1;
XkLi 0:c546b51ecf0b 320 case 4: return ((-1)<<4) + 1;
XkLi 0:c546b51ecf0b 321 case 5: return ((-1)<<5) + 1;
XkLi 0:c546b51ecf0b 322 case 6: return ((-1)<<6) + 1;
XkLi 0:c546b51ecf0b 323 case 7: return ((-1)<<7) + 1;
XkLi 0:c546b51ecf0b 324 case 8: return ((-1)<<8) + 1;
XkLi 0:c546b51ecf0b 325 case 9: return ((-1)<<9) + 1;
XkLi 0:c546b51ecf0b 326 case 10: return ((-1)<<10) + 1;
XkLi 0:c546b51ecf0b 327 case 11: return ((-1)<<11) + 1;
XkLi 0:c546b51ecf0b 328 case 12: return ((-1)<<12) + 1;
XkLi 0:c546b51ecf0b 329 case 13: return ((-1)<<13) + 1;
XkLi 0:c546b51ecf0b 330 case 14: return ((-1)<<14) + 1;
XkLi 0:c546b51ecf0b 331 case 15: return ((-1)<<15) + 1;
XkLi 0:c546b51ecf0b 332 default: return 0;
XkLi 0:c546b51ecf0b 333 }
XkLi 0:c546b51ecf0b 334 };
XkLi 0:c546b51ecf0b 335 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 336 static int16 huffExtend(uint16 x, uint8 s)
XkLi 0:c546b51ecf0b 337 {
XkLi 0:c546b51ecf0b 338 return ((x < getExtendTest(s)) ? ((int16)x + getExtendOffset(s)) : (int16)x);
XkLi 0:c546b51ecf0b 339 }
XkLi 0:c546b51ecf0b 340 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 341 static uint8 huffDecode(const HuffTable* pHuffTable, const uint8* pHuffVal)
XkLi 0:c546b51ecf0b 342 {
XkLi 0:c546b51ecf0b 343 uint8 i = 0;
XkLi 0:c546b51ecf0b 344 uint8 j;
XkLi 0:c546b51ecf0b 345 uint16 code = getBit();
XkLi 0:c546b51ecf0b 346
XkLi 0:c546b51ecf0b 347 for ( ; ; )
XkLi 0:c546b51ecf0b 348 {
XkLi 0:c546b51ecf0b 349 uint16 maxCode;
XkLi 0:c546b51ecf0b 350
XkLi 0:c546b51ecf0b 351 if (i == 16)
XkLi 0:c546b51ecf0b 352 return 0;
XkLi 0:c546b51ecf0b 353
XkLi 0:c546b51ecf0b 354 maxCode = pHuffTable->mMaxCode[i];
XkLi 0:c546b51ecf0b 355 if ((code <= maxCode) && (maxCode != 0xFFFF))
XkLi 0:c546b51ecf0b 356 break;
XkLi 0:c546b51ecf0b 357
XkLi 0:c546b51ecf0b 358 i++;
XkLi 0:c546b51ecf0b 359 code <<= 1;
XkLi 0:c546b51ecf0b 360 code |= getBit();
XkLi 0:c546b51ecf0b 361 }
XkLi 0:c546b51ecf0b 362
XkLi 0:c546b51ecf0b 363 j = pHuffTable->mValPtr[i];
XkLi 0:c546b51ecf0b 364 j = (uint8)(j + (code - pHuffTable->mMinCode[i]));
XkLi 0:c546b51ecf0b 365
XkLi 0:c546b51ecf0b 366 return pHuffVal[j];
XkLi 0:c546b51ecf0b 367 }
XkLi 0:c546b51ecf0b 368 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 369 static void huffCreate(const uint8* pBits, HuffTable* pHuffTable)
XkLi 0:c546b51ecf0b 370 {
XkLi 0:c546b51ecf0b 371 uint8 i = 0;
XkLi 0:c546b51ecf0b 372 uint8 j = 0;
XkLi 0:c546b51ecf0b 373
XkLi 0:c546b51ecf0b 374 uint16 code = 0;
XkLi 0:c546b51ecf0b 375
XkLi 0:c546b51ecf0b 376 for ( ; ; )
XkLi 0:c546b51ecf0b 377 {
XkLi 0:c546b51ecf0b 378 uint8 num = pBits[i];
XkLi 0:c546b51ecf0b 379
XkLi 0:c546b51ecf0b 380 if (!num)
XkLi 0:c546b51ecf0b 381 {
XkLi 0:c546b51ecf0b 382 pHuffTable->mMinCode[i] = 0x0000;
XkLi 0:c546b51ecf0b 383 pHuffTable->mMaxCode[i] = 0xFFFF;
XkLi 0:c546b51ecf0b 384 pHuffTable->mValPtr[i] = 0;
XkLi 0:c546b51ecf0b 385 }
XkLi 0:c546b51ecf0b 386 else
XkLi 0:c546b51ecf0b 387 {
XkLi 0:c546b51ecf0b 388 pHuffTable->mMinCode[i] = code;
XkLi 0:c546b51ecf0b 389 pHuffTable->mMaxCode[i] = code + num - 1;
XkLi 0:c546b51ecf0b 390 pHuffTable->mValPtr[i] = j;
XkLi 0:c546b51ecf0b 391
XkLi 0:c546b51ecf0b 392 j = (uint8)(j + num);
XkLi 0:c546b51ecf0b 393
XkLi 0:c546b51ecf0b 394 code = (uint16)(code + num);
XkLi 0:c546b51ecf0b 395 }
XkLi 0:c546b51ecf0b 396
XkLi 0:c546b51ecf0b 397 code <<= 1;
XkLi 0:c546b51ecf0b 398
XkLi 0:c546b51ecf0b 399 i++;
XkLi 0:c546b51ecf0b 400 if (i > 15)
XkLi 0:c546b51ecf0b 401 break;
XkLi 0:c546b51ecf0b 402 }
XkLi 0:c546b51ecf0b 403 }
XkLi 0:c546b51ecf0b 404 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 405 static HuffTable* getHuffTable(uint8 index)
XkLi 0:c546b51ecf0b 406 {
XkLi 0:c546b51ecf0b 407 // 0-1 = DC
XkLi 0:c546b51ecf0b 408 // 2-3 = AC
XkLi 0:c546b51ecf0b 409 switch (index)
XkLi 0:c546b51ecf0b 410 {
XkLi 0:c546b51ecf0b 411 case 0: return &gHuffTab0;
XkLi 0:c546b51ecf0b 412 case 1: return &gHuffTab1;
XkLi 0:c546b51ecf0b 413 case 2: return &gHuffTab2;
XkLi 0:c546b51ecf0b 414 case 3: return &gHuffTab3;
XkLi 0:c546b51ecf0b 415 default: return 0;
XkLi 0:c546b51ecf0b 416 }
XkLi 0:c546b51ecf0b 417 }
XkLi 0:c546b51ecf0b 418 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 419 static uint8* getHuffVal(uint8 index)
XkLi 0:c546b51ecf0b 420 {
XkLi 0:c546b51ecf0b 421 // 0-1 = DC
XkLi 0:c546b51ecf0b 422 // 2-3 = AC
XkLi 0:c546b51ecf0b 423 switch (index)
XkLi 0:c546b51ecf0b 424 {
XkLi 0:c546b51ecf0b 425 case 0: return gHuffVal0;
XkLi 0:c546b51ecf0b 426 case 1: return gHuffVal1;
XkLi 0:c546b51ecf0b 427 case 2: return gHuffVal2;
XkLi 0:c546b51ecf0b 428 case 3: return gHuffVal3;
XkLi 0:c546b51ecf0b 429 default: return 0;
XkLi 0:c546b51ecf0b 430 }
XkLi 0:c546b51ecf0b 431 }
XkLi 0:c546b51ecf0b 432 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 433 static uint16 getMaxHuffCodes(uint8 index)
XkLi 0:c546b51ecf0b 434 {
XkLi 0:c546b51ecf0b 435 return (index < 2) ? 12 : 255;
XkLi 0:c546b51ecf0b 436 }
XkLi 0:c546b51ecf0b 437 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 438 static uint8 readDHTMarker(void)
XkLi 0:c546b51ecf0b 439 {
XkLi 0:c546b51ecf0b 440 uint8 bits[16];
XkLi 0:c546b51ecf0b 441 uint16 left = getBits1(16);
XkLi 0:c546b51ecf0b 442
XkLi 0:c546b51ecf0b 443 if (left < 2)
XkLi 0:c546b51ecf0b 444 return PJPG_BAD_DHT_MARKER;
XkLi 0:c546b51ecf0b 445
XkLi 0:c546b51ecf0b 446 left -= 2;
XkLi 0:c546b51ecf0b 447
XkLi 0:c546b51ecf0b 448 while (left)
XkLi 0:c546b51ecf0b 449 {
XkLi 0:c546b51ecf0b 450 uint8 i, tableIndex, index;
XkLi 0:c546b51ecf0b 451 uint8* pHuffVal;
XkLi 0:c546b51ecf0b 452 HuffTable* pHuffTable;
XkLi 0:c546b51ecf0b 453 uint16 count, totalRead;
XkLi 0:c546b51ecf0b 454
XkLi 0:c546b51ecf0b 455 index = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 456
XkLi 0:c546b51ecf0b 457 if ( ((index & 0xF) > 1) || ((index & 0xF0) > 0x10) )
XkLi 0:c546b51ecf0b 458 return PJPG_BAD_DHT_INDEX;
XkLi 0:c546b51ecf0b 459
XkLi 0:c546b51ecf0b 460 tableIndex = ((index >> 3) & 2) + (index & 1);
XkLi 0:c546b51ecf0b 461
XkLi 0:c546b51ecf0b 462 pHuffTable = getHuffTable(tableIndex);
XkLi 0:c546b51ecf0b 463 pHuffVal = getHuffVal(tableIndex);
XkLi 0:c546b51ecf0b 464
XkLi 0:c546b51ecf0b 465 gValidHuffTables |= (1 << tableIndex);
XkLi 0:c546b51ecf0b 466
XkLi 0:c546b51ecf0b 467 count = 0;
XkLi 0:c546b51ecf0b 468 for (i = 0; i <= 15; i++)
XkLi 0:c546b51ecf0b 469 {
XkLi 0:c546b51ecf0b 470 uint8 n = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 471 bits[i] = n;
XkLi 0:c546b51ecf0b 472 count = (uint16)(count + n);
XkLi 0:c546b51ecf0b 473 }
XkLi 0:c546b51ecf0b 474
XkLi 0:c546b51ecf0b 475 if (count > getMaxHuffCodes(tableIndex))
XkLi 0:c546b51ecf0b 476 return PJPG_BAD_DHT_COUNTS;
XkLi 0:c546b51ecf0b 477
XkLi 0:c546b51ecf0b 478 for (i = 0; i < count; i++)
XkLi 0:c546b51ecf0b 479 pHuffVal[i] = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 480
XkLi 0:c546b51ecf0b 481 totalRead = 1 + 16 + count;
XkLi 0:c546b51ecf0b 482
XkLi 0:c546b51ecf0b 483 if (left < totalRead)
XkLi 0:c546b51ecf0b 484 return PJPG_BAD_DHT_MARKER;
XkLi 0:c546b51ecf0b 485
XkLi 0:c546b51ecf0b 486 left = (uint16)(left - totalRead);
XkLi 0:c546b51ecf0b 487
XkLi 0:c546b51ecf0b 488 huffCreate(bits, pHuffTable);
XkLi 0:c546b51ecf0b 489 }
XkLi 0:c546b51ecf0b 490
XkLi 0:c546b51ecf0b 491 return 0;
XkLi 0:c546b51ecf0b 492 }
XkLi 0:c546b51ecf0b 493 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 494 static void createWinogradQuant(int16* pQuant);
XkLi 0:c546b51ecf0b 495
XkLi 0:c546b51ecf0b 496 static uint8 readDQTMarker(void)
XkLi 0:c546b51ecf0b 497 {
XkLi 0:c546b51ecf0b 498 uint16 left = getBits1(16);
XkLi 0:c546b51ecf0b 499
XkLi 0:c546b51ecf0b 500 if (left < 2)
XkLi 0:c546b51ecf0b 501 return PJPG_BAD_DQT_MARKER;
XkLi 0:c546b51ecf0b 502
XkLi 0:c546b51ecf0b 503 left -= 2;
XkLi 0:c546b51ecf0b 504
XkLi 0:c546b51ecf0b 505 while (left)
XkLi 0:c546b51ecf0b 506 {
XkLi 0:c546b51ecf0b 507 uint8 i;
XkLi 0:c546b51ecf0b 508 uint8 n = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 509 uint8 prec = n >> 4;
XkLi 0:c546b51ecf0b 510 uint16 totalRead;
XkLi 0:c546b51ecf0b 511
XkLi 0:c546b51ecf0b 512 n &= 0x0F;
XkLi 0:c546b51ecf0b 513
XkLi 0:c546b51ecf0b 514 if (n > 1)
XkLi 0:c546b51ecf0b 515 return PJPG_BAD_DQT_TABLE;
XkLi 0:c546b51ecf0b 516
XkLi 0:c546b51ecf0b 517 gValidQuantTables |= (n ? 2 : 1);
XkLi 0:c546b51ecf0b 518
XkLi 0:c546b51ecf0b 519 // read quantization entries, in zag order
XkLi 0:c546b51ecf0b 520 for (i = 0; i < 64; i++)
XkLi 0:c546b51ecf0b 521 {
XkLi 0:c546b51ecf0b 522 uint16 temp = getBits1(8);
XkLi 0:c546b51ecf0b 523
XkLi 0:c546b51ecf0b 524 if (prec)
XkLi 0:c546b51ecf0b 525 temp = (temp << 8) + getBits1(8);
XkLi 0:c546b51ecf0b 526
XkLi 0:c546b51ecf0b 527 if (n)
XkLi 0:c546b51ecf0b 528 gQuant1[i] = (int16)temp;
XkLi 0:c546b51ecf0b 529 else
XkLi 0:c546b51ecf0b 530 gQuant0[i] = (int16)temp;
XkLi 0:c546b51ecf0b 531 }
XkLi 0:c546b51ecf0b 532
XkLi 0:c546b51ecf0b 533 createWinogradQuant(n ? gQuant1 : gQuant0);
XkLi 0:c546b51ecf0b 534
XkLi 0:c546b51ecf0b 535 totalRead = 64 + 1;
XkLi 0:c546b51ecf0b 536
XkLi 0:c546b51ecf0b 537 if (prec)
XkLi 0:c546b51ecf0b 538 totalRead += 64;
XkLi 0:c546b51ecf0b 539
XkLi 0:c546b51ecf0b 540 if (left < totalRead)
XkLi 0:c546b51ecf0b 541 return PJPG_BAD_DQT_LENGTH;
XkLi 0:c546b51ecf0b 542
XkLi 0:c546b51ecf0b 543 left = (uint16)(left - totalRead);
XkLi 0:c546b51ecf0b 544 }
XkLi 0:c546b51ecf0b 545
XkLi 0:c546b51ecf0b 546 return 0;
XkLi 0:c546b51ecf0b 547 }
XkLi 0:c546b51ecf0b 548 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 549 static uint8 readSOFMarker(void)
XkLi 0:c546b51ecf0b 550 {
XkLi 0:c546b51ecf0b 551 uint8 i;
XkLi 0:c546b51ecf0b 552 uint16 left = getBits1(16);
XkLi 0:c546b51ecf0b 553
XkLi 0:c546b51ecf0b 554 if (getBits1(8) != 8)
XkLi 0:c546b51ecf0b 555 return PJPG_BAD_PRECISION;
XkLi 0:c546b51ecf0b 556
XkLi 0:c546b51ecf0b 557 gImageYSize = getBits1(16);
XkLi 0:c546b51ecf0b 558
XkLi 0:c546b51ecf0b 559 if ((!gImageYSize) || (gImageYSize > PJPG_MAX_HEIGHT))
XkLi 0:c546b51ecf0b 560 return PJPG_BAD_HEIGHT;
XkLi 0:c546b51ecf0b 561
XkLi 0:c546b51ecf0b 562 gImageXSize = getBits1(16);
XkLi 0:c546b51ecf0b 563
XkLi 0:c546b51ecf0b 564 if ((!gImageXSize) || (gImageXSize > PJPG_MAX_WIDTH))
XkLi 0:c546b51ecf0b 565 return PJPG_BAD_WIDTH;
XkLi 0:c546b51ecf0b 566
XkLi 0:c546b51ecf0b 567 gCompsInFrame = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 568
XkLi 0:c546b51ecf0b 569 if (gCompsInFrame > 3)
XkLi 0:c546b51ecf0b 570 return PJPG_TOO_MANY_COMPONENTS;
XkLi 0:c546b51ecf0b 571
XkLi 0:c546b51ecf0b 572 if (left != (gCompsInFrame + gCompsInFrame + gCompsInFrame + 8))
XkLi 0:c546b51ecf0b 573 return PJPG_BAD_SOF_LENGTH;
XkLi 0:c546b51ecf0b 574
XkLi 0:c546b51ecf0b 575 for (i = 0; i < gCompsInFrame; i++)
XkLi 0:c546b51ecf0b 576 {
XkLi 0:c546b51ecf0b 577 gCompIdent[i] = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 578 gCompHSamp[i] = (uint8)getBits1(4);
XkLi 0:c546b51ecf0b 579 gCompVSamp[i] = (uint8)getBits1(4);
XkLi 0:c546b51ecf0b 580 gCompQuant[i] = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 581
XkLi 0:c546b51ecf0b 582 if (gCompQuant[i] > 1)
XkLi 0:c546b51ecf0b 583 return PJPG_UNSUPPORTED_QUANT_TABLE;
XkLi 0:c546b51ecf0b 584 }
XkLi 0:c546b51ecf0b 585
XkLi 0:c546b51ecf0b 586 return 0;
XkLi 0:c546b51ecf0b 587 }
XkLi 0:c546b51ecf0b 588 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 589 // Used to skip unrecognized markers.
XkLi 0:c546b51ecf0b 590 static uint8 skipVariableMarker(void)
XkLi 0:c546b51ecf0b 591 {
XkLi 0:c546b51ecf0b 592 uint16 left = getBits1(16);
XkLi 0:c546b51ecf0b 593
XkLi 0:c546b51ecf0b 594 if (left < 2)
XkLi 0:c546b51ecf0b 595 return PJPG_BAD_VARIABLE_MARKER;
XkLi 0:c546b51ecf0b 596
XkLi 0:c546b51ecf0b 597 left -= 2;
XkLi 0:c546b51ecf0b 598
XkLi 0:c546b51ecf0b 599 while (left)
XkLi 0:c546b51ecf0b 600 {
XkLi 0:c546b51ecf0b 601 getBits1(8);
XkLi 0:c546b51ecf0b 602 left--;
XkLi 0:c546b51ecf0b 603 }
XkLi 0:c546b51ecf0b 604
XkLi 0:c546b51ecf0b 605 return 0;
XkLi 0:c546b51ecf0b 606 }
XkLi 0:c546b51ecf0b 607 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 608 // Read a define restart interval (DRI) marker.
XkLi 0:c546b51ecf0b 609 static uint8 readDRIMarker(void)
XkLi 0:c546b51ecf0b 610 {
XkLi 0:c546b51ecf0b 611 if (getBits1(16) != 4)
XkLi 0:c546b51ecf0b 612 return PJPG_BAD_DRI_LENGTH;
XkLi 0:c546b51ecf0b 613
XkLi 0:c546b51ecf0b 614 gRestartInterval = getBits1(16);
XkLi 0:c546b51ecf0b 615
XkLi 0:c546b51ecf0b 616 return 0;
XkLi 0:c546b51ecf0b 617 }
XkLi 0:c546b51ecf0b 618 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 619 // Read a start of scan (SOS) marker.
XkLi 0:c546b51ecf0b 620 static uint8 readSOSMarker(void)
XkLi 0:c546b51ecf0b 621 {
XkLi 0:c546b51ecf0b 622 uint8 i;
XkLi 0:c546b51ecf0b 623 uint16 left = getBits1(16);
XkLi 0:c546b51ecf0b 624 uint8 spectral_start, spectral_end, successive_high, successive_low;
XkLi 0:c546b51ecf0b 625
XkLi 0:c546b51ecf0b 626 gCompsInScan = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 627
XkLi 0:c546b51ecf0b 628 left -= 3;
XkLi 0:c546b51ecf0b 629
XkLi 0:c546b51ecf0b 630 if ( (left != (gCompsInScan + gCompsInScan + 3)) || (gCompsInScan < 1) || (gCompsInScan > PJPG_MAXCOMPSINSCAN) )
XkLi 0:c546b51ecf0b 631 return PJPG_BAD_SOS_LENGTH;
XkLi 0:c546b51ecf0b 632
XkLi 0:c546b51ecf0b 633 for (i = 0; i < gCompsInScan; i++)
XkLi 0:c546b51ecf0b 634 {
XkLi 0:c546b51ecf0b 635 uint8 cc = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 636 uint8 c = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 637 uint8 ci;
XkLi 0:c546b51ecf0b 638
XkLi 0:c546b51ecf0b 639 left -= 2;
XkLi 0:c546b51ecf0b 640
XkLi 0:c546b51ecf0b 641 for (ci = 0; ci < gCompsInFrame; ci++)
XkLi 0:c546b51ecf0b 642 if (cc == gCompIdent[ci])
XkLi 0:c546b51ecf0b 643 break;
XkLi 0:c546b51ecf0b 644
XkLi 0:c546b51ecf0b 645 if (ci >= gCompsInFrame)
XkLi 0:c546b51ecf0b 646 return PJPG_BAD_SOS_COMP_ID;
XkLi 0:c546b51ecf0b 647
XkLi 0:c546b51ecf0b 648 gCompList[i] = ci;
XkLi 0:c546b51ecf0b 649 gCompDCTab[ci] = (c >> 4) & 15;
XkLi 0:c546b51ecf0b 650 gCompACTab[ci] = (c & 15);
XkLi 0:c546b51ecf0b 651 }
XkLi 0:c546b51ecf0b 652
XkLi 0:c546b51ecf0b 653 spectral_start = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 654 spectral_end = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 655 successive_high = (uint8)getBits1(4);
XkLi 0:c546b51ecf0b 656 successive_low = (uint8)getBits1(4);
XkLi 0:c546b51ecf0b 657
XkLi 0:c546b51ecf0b 658 left -= 3;
XkLi 0:c546b51ecf0b 659
XkLi 0:c546b51ecf0b 660 while (left)
XkLi 0:c546b51ecf0b 661 {
XkLi 0:c546b51ecf0b 662 getBits1(8);
XkLi 0:c546b51ecf0b 663 left--;
XkLi 0:c546b51ecf0b 664 }
XkLi 0:c546b51ecf0b 665
XkLi 0:c546b51ecf0b 666 return 0;
XkLi 0:c546b51ecf0b 667 }
XkLi 0:c546b51ecf0b 668 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 669 static uint8 nextMarker(void)
XkLi 0:c546b51ecf0b 670 {
XkLi 0:c546b51ecf0b 671 uint8 c;
XkLi 0:c546b51ecf0b 672 uint8 bytes = 0;
XkLi 0:c546b51ecf0b 673
XkLi 0:c546b51ecf0b 674 do
XkLi 0:c546b51ecf0b 675 {
XkLi 0:c546b51ecf0b 676 do
XkLi 0:c546b51ecf0b 677 {
XkLi 0:c546b51ecf0b 678 bytes++;
XkLi 0:c546b51ecf0b 679
XkLi 0:c546b51ecf0b 680 c = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 681
XkLi 0:c546b51ecf0b 682 } while (c != 0xFF);
XkLi 0:c546b51ecf0b 683
XkLi 0:c546b51ecf0b 684 do
XkLi 0:c546b51ecf0b 685 {
XkLi 0:c546b51ecf0b 686 c = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 687
XkLi 0:c546b51ecf0b 688 } while (c == 0xFF);
XkLi 0:c546b51ecf0b 689
XkLi 0:c546b51ecf0b 690 } while (c == 0);
XkLi 0:c546b51ecf0b 691
XkLi 0:c546b51ecf0b 692 // If bytes > 0 here, there where extra bytes before the marker (not good).
XkLi 0:c546b51ecf0b 693
XkLi 0:c546b51ecf0b 694 return c;
XkLi 0:c546b51ecf0b 695 }
XkLi 0:c546b51ecf0b 696 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 697 // Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is
XkLi 0:c546b51ecf0b 698 // encountered.
XkLi 0:c546b51ecf0b 699 static uint8 processMarkers(uint8* pMarker)
XkLi 0:c546b51ecf0b 700 {
XkLi 0:c546b51ecf0b 701 for ( ; ; )
XkLi 0:c546b51ecf0b 702 {
XkLi 0:c546b51ecf0b 703 uint8 c = nextMarker();
XkLi 0:c546b51ecf0b 704
XkLi 0:c546b51ecf0b 705 switch (c)
XkLi 0:c546b51ecf0b 706 {
XkLi 0:c546b51ecf0b 707 case M_SOF0:
XkLi 0:c546b51ecf0b 708 case M_SOF1:
XkLi 0:c546b51ecf0b 709 case M_SOF2:
XkLi 0:c546b51ecf0b 710 case M_SOF3:
XkLi 0:c546b51ecf0b 711 case M_SOF5:
XkLi 0:c546b51ecf0b 712 case M_SOF6:
XkLi 0:c546b51ecf0b 713 case M_SOF7:
XkLi 0:c546b51ecf0b 714 // case M_JPG:
XkLi 0:c546b51ecf0b 715 case M_SOF9:
XkLi 0:c546b51ecf0b 716 case M_SOF10:
XkLi 0:c546b51ecf0b 717 case M_SOF11:
XkLi 0:c546b51ecf0b 718 case M_SOF13:
XkLi 0:c546b51ecf0b 719 case M_SOF14:
XkLi 0:c546b51ecf0b 720 case M_SOF15:
XkLi 0:c546b51ecf0b 721 case M_SOI:
XkLi 0:c546b51ecf0b 722 case M_EOI:
XkLi 0:c546b51ecf0b 723 case M_SOS:
XkLi 0:c546b51ecf0b 724 {
XkLi 0:c546b51ecf0b 725 *pMarker = c;
XkLi 0:c546b51ecf0b 726 return 0;
XkLi 0:c546b51ecf0b 727 }
XkLi 0:c546b51ecf0b 728 case M_DHT:
XkLi 0:c546b51ecf0b 729 {
XkLi 0:c546b51ecf0b 730 readDHTMarker();
XkLi 0:c546b51ecf0b 731 break;
XkLi 0:c546b51ecf0b 732 }
XkLi 0:c546b51ecf0b 733 // Sorry, no arithmitic support at this time. Dumb patents!
XkLi 0:c546b51ecf0b 734 case M_DAC:
XkLi 0:c546b51ecf0b 735 {
XkLi 0:c546b51ecf0b 736 return PJPG_NO_ARITHMITIC_SUPPORT;
XkLi 0:c546b51ecf0b 737 }
XkLi 0:c546b51ecf0b 738 case M_DQT:
XkLi 0:c546b51ecf0b 739 {
XkLi 0:c546b51ecf0b 740 readDQTMarker();
XkLi 0:c546b51ecf0b 741 break;
XkLi 0:c546b51ecf0b 742 }
XkLi 0:c546b51ecf0b 743 case M_DRI:
XkLi 0:c546b51ecf0b 744 {
XkLi 0:c546b51ecf0b 745 readDRIMarker();
XkLi 0:c546b51ecf0b 746 break;
XkLi 0:c546b51ecf0b 747 }
XkLi 0:c546b51ecf0b 748 //case M_APP0: /* no need to read the JFIF marker */
XkLi 0:c546b51ecf0b 749
XkLi 0:c546b51ecf0b 750 case M_JPG:
XkLi 0:c546b51ecf0b 751 case M_RST0: /* no parameters */
XkLi 0:c546b51ecf0b 752 case M_RST1:
XkLi 0:c546b51ecf0b 753 case M_RST2:
XkLi 0:c546b51ecf0b 754 case M_RST3:
XkLi 0:c546b51ecf0b 755 case M_RST4:
XkLi 0:c546b51ecf0b 756 case M_RST5:
XkLi 0:c546b51ecf0b 757 case M_RST6:
XkLi 0:c546b51ecf0b 758 case M_RST7:
XkLi 0:c546b51ecf0b 759 case M_TEM:
XkLi 0:c546b51ecf0b 760 {
XkLi 0:c546b51ecf0b 761 return PJPG_UNEXPECTED_MARKER;
XkLi 0:c546b51ecf0b 762 }
XkLi 0:c546b51ecf0b 763 default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
XkLi 0:c546b51ecf0b 764 {
XkLi 0:c546b51ecf0b 765 skipVariableMarker();
XkLi 0:c546b51ecf0b 766 break;
XkLi 0:c546b51ecf0b 767 }
XkLi 0:c546b51ecf0b 768 }
XkLi 0:c546b51ecf0b 769 }
XkLi 0:c546b51ecf0b 770 // return 0;
XkLi 0:c546b51ecf0b 771 }
XkLi 0:c546b51ecf0b 772 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 773 // Finds the start of image (SOI) marker.
XkLi 0:c546b51ecf0b 774 static uint8 locateSOIMarker(void)
XkLi 0:c546b51ecf0b 775 {
XkLi 0:c546b51ecf0b 776 uint16 bytesleft;
XkLi 0:c546b51ecf0b 777
XkLi 0:c546b51ecf0b 778 uint8 lastchar = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 779
XkLi 0:c546b51ecf0b 780 uint8 thischar = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 781
XkLi 0:c546b51ecf0b 782 /* ok if it's a normal JPEG file without a special header */
XkLi 0:c546b51ecf0b 783
XkLi 0:c546b51ecf0b 784 if ((lastchar == 0xFF) && (thischar == M_SOI))
XkLi 0:c546b51ecf0b 785 return 0;
XkLi 0:c546b51ecf0b 786
XkLi 0:c546b51ecf0b 787 bytesleft = 4096; //512;
XkLi 0:c546b51ecf0b 788
XkLi 0:c546b51ecf0b 789 for ( ; ; )
XkLi 0:c546b51ecf0b 790 {
XkLi 0:c546b51ecf0b 791 if (--bytesleft == 0)
XkLi 0:c546b51ecf0b 792 return PJPG_NOT_JPEG;
XkLi 0:c546b51ecf0b 793
XkLi 0:c546b51ecf0b 794 lastchar = thischar;
XkLi 0:c546b51ecf0b 795
XkLi 0:c546b51ecf0b 796 thischar = (uint8)getBits1(8);
XkLi 0:c546b51ecf0b 797
XkLi 0:c546b51ecf0b 798 if (lastchar == 0xFF)
XkLi 0:c546b51ecf0b 799 {
XkLi 0:c546b51ecf0b 800 if (thischar == M_SOI)
XkLi 0:c546b51ecf0b 801 break;
XkLi 0:c546b51ecf0b 802 else if (thischar == M_EOI) //getBits1 will keep returning M_EOI if we read past the end
XkLi 0:c546b51ecf0b 803 return PJPG_NOT_JPEG;
XkLi 0:c546b51ecf0b 804 }
XkLi 0:c546b51ecf0b 805 }
XkLi 0:c546b51ecf0b 806
XkLi 0:c546b51ecf0b 807 /* Check the next character after marker: if it's not 0xFF, it can't
XkLi 0:c546b51ecf0b 808 be the start of the next marker, so the file is bad */
XkLi 0:c546b51ecf0b 809
XkLi 0:c546b51ecf0b 810 thischar = (uint8)((gBitBuf >> 8) & 0xFF);
XkLi 0:c546b51ecf0b 811
XkLi 0:c546b51ecf0b 812 if (thischar != 0xFF)
XkLi 0:c546b51ecf0b 813 return PJPG_NOT_JPEG;
XkLi 0:c546b51ecf0b 814
XkLi 0:c546b51ecf0b 815 return 0;
XkLi 0:c546b51ecf0b 816 }
XkLi 0:c546b51ecf0b 817 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 818 // Find a start of frame (SOF) marker.
XkLi 0:c546b51ecf0b 819 static uint8 locateSOFMarker(void)
XkLi 0:c546b51ecf0b 820 {
XkLi 0:c546b51ecf0b 821 uint8 c;
XkLi 0:c546b51ecf0b 822
XkLi 0:c546b51ecf0b 823 uint8 status = locateSOIMarker();
XkLi 0:c546b51ecf0b 824 if (status)
XkLi 0:c546b51ecf0b 825 return status;
XkLi 0:c546b51ecf0b 826
XkLi 0:c546b51ecf0b 827 status = processMarkers(&c);
XkLi 0:c546b51ecf0b 828 if (status)
XkLi 0:c546b51ecf0b 829 return status;
XkLi 0:c546b51ecf0b 830
XkLi 0:c546b51ecf0b 831 switch (c)
XkLi 0:c546b51ecf0b 832 {
XkLi 0:c546b51ecf0b 833 case M_SOF2:
XkLi 0:c546b51ecf0b 834 {
XkLi 0:c546b51ecf0b 835 return PJPG_UNSUPPORTED_MODE;
XkLi 0:c546b51ecf0b 836 }
XkLi 0:c546b51ecf0b 837 case M_SOF0: /* baseline DCT */
XkLi 0:c546b51ecf0b 838 {
XkLi 0:c546b51ecf0b 839 status = readSOFMarker();
XkLi 0:c546b51ecf0b 840 if (status)
XkLi 0:c546b51ecf0b 841 return status;
XkLi 0:c546b51ecf0b 842
XkLi 0:c546b51ecf0b 843 break;
XkLi 0:c546b51ecf0b 844 }
XkLi 0:c546b51ecf0b 845 case M_SOF9:
XkLi 0:c546b51ecf0b 846 {
XkLi 0:c546b51ecf0b 847 return PJPG_NO_ARITHMITIC_SUPPORT;
XkLi 0:c546b51ecf0b 848 }
XkLi 0:c546b51ecf0b 849 case M_SOF1: /* extended sequential DCT */
XkLi 0:c546b51ecf0b 850 default:
XkLi 0:c546b51ecf0b 851 {
XkLi 0:c546b51ecf0b 852 return PJPG_UNSUPPORTED_MARKER;
XkLi 0:c546b51ecf0b 853 }
XkLi 0:c546b51ecf0b 854 }
XkLi 0:c546b51ecf0b 855
XkLi 0:c546b51ecf0b 856 return 0;
XkLi 0:c546b51ecf0b 857 }
XkLi 0:c546b51ecf0b 858 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 859 // Find a start of scan (SOS) marker.
XkLi 0:c546b51ecf0b 860 static uint8 locateSOSMarker(uint8* pFoundEOI)
XkLi 0:c546b51ecf0b 861 {
XkLi 0:c546b51ecf0b 862 uint8 c;
XkLi 0:c546b51ecf0b 863 uint8 status;
XkLi 0:c546b51ecf0b 864
XkLi 0:c546b51ecf0b 865 *pFoundEOI = 0;
XkLi 0:c546b51ecf0b 866
XkLi 0:c546b51ecf0b 867 status = processMarkers(&c);
XkLi 0:c546b51ecf0b 868 if (status)
XkLi 0:c546b51ecf0b 869 return status;
XkLi 0:c546b51ecf0b 870
XkLi 0:c546b51ecf0b 871 if (c == M_EOI)
XkLi 0:c546b51ecf0b 872 {
XkLi 0:c546b51ecf0b 873 *pFoundEOI = 1;
XkLi 0:c546b51ecf0b 874 return 0;
XkLi 0:c546b51ecf0b 875 }
XkLi 0:c546b51ecf0b 876 else if (c != M_SOS)
XkLi 0:c546b51ecf0b 877 return PJPG_UNEXPECTED_MARKER;
XkLi 0:c546b51ecf0b 878
XkLi 0:c546b51ecf0b 879 return readSOSMarker();
XkLi 0:c546b51ecf0b 880 }
XkLi 0:c546b51ecf0b 881 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 882 static uint8 init(void)
XkLi 0:c546b51ecf0b 883 {
XkLi 0:c546b51ecf0b 884 gImageXSize = 0;
XkLi 0:c546b51ecf0b 885 gImageYSize = 0;
XkLi 0:c546b51ecf0b 886 gCompsInFrame = 0;
XkLi 0:c546b51ecf0b 887 gRestartInterval = 0;
XkLi 0:c546b51ecf0b 888 gCompsInScan = 0;
XkLi 0:c546b51ecf0b 889 gValidHuffTables = 0;
XkLi 0:c546b51ecf0b 890 gValidQuantTables = 0;
XkLi 0:c546b51ecf0b 891 gTemFlag = 0;
XkLi 0:c546b51ecf0b 892 gInBufOfs = 0;
XkLi 0:c546b51ecf0b 893 gInBufLeft = 0;
XkLi 0:c546b51ecf0b 894 gBitBuf = 0;
XkLi 0:c546b51ecf0b 895 gBitsLeft = 8;
XkLi 0:c546b51ecf0b 896
XkLi 0:c546b51ecf0b 897 getBits1(8);
XkLi 0:c546b51ecf0b 898 getBits1(8);
XkLi 0:c546b51ecf0b 899
XkLi 0:c546b51ecf0b 900 return 0;
XkLi 0:c546b51ecf0b 901 }
XkLi 0:c546b51ecf0b 902 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 903 // This method throws back into the stream any bytes that where read
XkLi 0:c546b51ecf0b 904 // into the bit buffer during initial marker scanning.
XkLi 0:c546b51ecf0b 905 static void fixInBuffer(void)
XkLi 0:c546b51ecf0b 906 {
XkLi 0:c546b51ecf0b 907 /* In case any 0xFF's where pulled into the buffer during marker scanning */
XkLi 0:c546b51ecf0b 908
XkLi 0:c546b51ecf0b 909 if (gBitsLeft > 0)
XkLi 0:c546b51ecf0b 910 stuffChar((uint8)gBitBuf);
XkLi 0:c546b51ecf0b 911
XkLi 0:c546b51ecf0b 912 stuffChar((uint8)(gBitBuf >> 8));
XkLi 0:c546b51ecf0b 913
XkLi 0:c546b51ecf0b 914 gBitsLeft = 8;
XkLi 0:c546b51ecf0b 915 getBits2(8);
XkLi 0:c546b51ecf0b 916 getBits2(8);
XkLi 0:c546b51ecf0b 917 }
XkLi 0:c546b51ecf0b 918 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 919 // Restart interval processing.
XkLi 0:c546b51ecf0b 920 static uint8 processRestart(void)
XkLi 0:c546b51ecf0b 921 {
XkLi 0:c546b51ecf0b 922 // Let's scan a little bit to find the marker, but not _too_ far.
XkLi 0:c546b51ecf0b 923 // 1536 is a "fudge factor" that determines how much to scan.
XkLi 0:c546b51ecf0b 924 uint16 i;
XkLi 0:c546b51ecf0b 925 uint8 c = 0;
XkLi 0:c546b51ecf0b 926
XkLi 0:c546b51ecf0b 927 for (i = 1536; i > 0; i--)
XkLi 0:c546b51ecf0b 928 if (getChar() == 0xFF)
XkLi 0:c546b51ecf0b 929 break;
XkLi 0:c546b51ecf0b 930
XkLi 0:c546b51ecf0b 931 if (i == 0)
XkLi 0:c546b51ecf0b 932 return PJPG_BAD_RESTART_MARKER;
XkLi 0:c546b51ecf0b 933
XkLi 0:c546b51ecf0b 934 for ( ; i > 0; i--)
XkLi 0:c546b51ecf0b 935 if ((c = getChar()) != 0xFF)
XkLi 0:c546b51ecf0b 936 break;
XkLi 0:c546b51ecf0b 937
XkLi 0:c546b51ecf0b 938 if (i == 0)
XkLi 0:c546b51ecf0b 939 return PJPG_BAD_RESTART_MARKER;
XkLi 0:c546b51ecf0b 940
XkLi 0:c546b51ecf0b 941 // Is it the expected marker? If not, something bad happened.
XkLi 0:c546b51ecf0b 942 if (c != (gNextRestartNum + M_RST0))
XkLi 0:c546b51ecf0b 943 return PJPG_BAD_RESTART_MARKER;
XkLi 0:c546b51ecf0b 944
XkLi 0:c546b51ecf0b 945 // Reset each component's DC prediction values.
XkLi 0:c546b51ecf0b 946 gLastDC[0] = 0;
XkLi 0:c546b51ecf0b 947 gLastDC[1] = 0;
XkLi 0:c546b51ecf0b 948 gLastDC[2] = 0;
XkLi 0:c546b51ecf0b 949
XkLi 0:c546b51ecf0b 950 gRestartsLeft = gRestartInterval;
XkLi 0:c546b51ecf0b 951
XkLi 0:c546b51ecf0b 952 gNextRestartNum = (gNextRestartNum + 1) & 7;
XkLi 0:c546b51ecf0b 953
XkLi 0:c546b51ecf0b 954 // Get the bit buffer going again...
XkLi 0:c546b51ecf0b 955
XkLi 0:c546b51ecf0b 956 gBitsLeft = 8;
XkLi 0:c546b51ecf0b 957 getBits2(8);
XkLi 0:c546b51ecf0b 958 getBits2(8);
XkLi 0:c546b51ecf0b 959
XkLi 0:c546b51ecf0b 960 return 0;
XkLi 0:c546b51ecf0b 961 }
XkLi 0:c546b51ecf0b 962 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 963 static uint8 findEOI(void)
XkLi 0:c546b51ecf0b 964 {
XkLi 0:c546b51ecf0b 965 uint8 c;
XkLi 0:c546b51ecf0b 966 uint8 status;
XkLi 0:c546b51ecf0b 967
XkLi 0:c546b51ecf0b 968 // Prime the bit buffer
XkLi 0:c546b51ecf0b 969 gBitsLeft = 8;
XkLi 0:c546b51ecf0b 970 getBits1(8);
XkLi 0:c546b51ecf0b 971 getBits1(8);
XkLi 0:c546b51ecf0b 972
XkLi 0:c546b51ecf0b 973 // The next marker _should_ be EOI
XkLi 0:c546b51ecf0b 974 status = processMarkers(&c);
XkLi 0:c546b51ecf0b 975 if (status)
XkLi 0:c546b51ecf0b 976 return status;
XkLi 0:c546b51ecf0b 977
XkLi 0:c546b51ecf0b 978 //gTotalBytesRead -= in_buf_left;
XkLi 0:c546b51ecf0b 979 if (c != M_EOI)
XkLi 0:c546b51ecf0b 980 return PJPG_UNEXPECTED_MARKER;
XkLi 0:c546b51ecf0b 981
XkLi 0:c546b51ecf0b 982 return 0;
XkLi 0:c546b51ecf0b 983 }
XkLi 0:c546b51ecf0b 984 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 985 static uint8 checkHuffTables(void)
XkLi 0:c546b51ecf0b 986 {
XkLi 0:c546b51ecf0b 987 uint8 i;
XkLi 0:c546b51ecf0b 988
XkLi 0:c546b51ecf0b 989 for (i = 0; i < gCompsInScan; i++)
XkLi 0:c546b51ecf0b 990 {
XkLi 0:c546b51ecf0b 991 uint8 compDCTab = gCompDCTab[gCompList[i]];
XkLi 0:c546b51ecf0b 992 uint8 compACTab = gCompACTab[gCompList[i]] + 2;
XkLi 0:c546b51ecf0b 993
XkLi 0:c546b51ecf0b 994 if ( ((gValidHuffTables & (1 << compDCTab)) == 0) ||
XkLi 0:c546b51ecf0b 995 ((gValidHuffTables & (1 << compACTab)) == 0) )
XkLi 0:c546b51ecf0b 996 return PJPG_UNDEFINED_HUFF_TABLE;
XkLi 0:c546b51ecf0b 997 }
XkLi 0:c546b51ecf0b 998
XkLi 0:c546b51ecf0b 999 return 0;
XkLi 0:c546b51ecf0b 1000 }
XkLi 0:c546b51ecf0b 1001 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 1002 static uint8 checkQuantTables(void)
XkLi 0:c546b51ecf0b 1003 {
XkLi 0:c546b51ecf0b 1004 uint8 i;
XkLi 0:c546b51ecf0b 1005
XkLi 0:c546b51ecf0b 1006 for (i = 0; i < gCompsInScan; i++)
XkLi 0:c546b51ecf0b 1007 {
XkLi 0:c546b51ecf0b 1008 uint8 compQuantMask = gCompQuant[gCompList[i]] ? 2 : 1;
XkLi 0:c546b51ecf0b 1009
XkLi 0:c546b51ecf0b 1010 if ((gValidQuantTables & compQuantMask) == 0)
XkLi 0:c546b51ecf0b 1011 return PJPG_UNDEFINED_QUANT_TABLE;
XkLi 0:c546b51ecf0b 1012 }
XkLi 0:c546b51ecf0b 1013
XkLi 0:c546b51ecf0b 1014 return 0;
XkLi 0:c546b51ecf0b 1015 }
XkLi 0:c546b51ecf0b 1016 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 1017 static uint8 initScan(void)
XkLi 0:c546b51ecf0b 1018 {
XkLi 0:c546b51ecf0b 1019 uint8 foundEOI;
XkLi 0:c546b51ecf0b 1020 uint8 status = locateSOSMarker(&foundEOI);
XkLi 0:c546b51ecf0b 1021 if (status)
XkLi 0:c546b51ecf0b 1022 return status;
XkLi 0:c546b51ecf0b 1023 if (foundEOI)
XkLi 0:c546b51ecf0b 1024 return PJPG_UNEXPECTED_MARKER;
XkLi 0:c546b51ecf0b 1025
XkLi 0:c546b51ecf0b 1026 status = checkHuffTables();
XkLi 0:c546b51ecf0b 1027 if (status)
XkLi 0:c546b51ecf0b 1028 return status;
XkLi 0:c546b51ecf0b 1029
XkLi 0:c546b51ecf0b 1030 status = checkQuantTables();
XkLi 0:c546b51ecf0b 1031 if (status)
XkLi 0:c546b51ecf0b 1032 return status;
XkLi 0:c546b51ecf0b 1033
XkLi 0:c546b51ecf0b 1034 gLastDC[0] = 0;
XkLi 0:c546b51ecf0b 1035 gLastDC[1] = 0;
XkLi 0:c546b51ecf0b 1036 gLastDC[2] = 0;
XkLi 0:c546b51ecf0b 1037
XkLi 0:c546b51ecf0b 1038 if (gRestartInterval)
XkLi 0:c546b51ecf0b 1039 {
XkLi 0:c546b51ecf0b 1040 gRestartsLeft = gRestartInterval;
XkLi 0:c546b51ecf0b 1041 gNextRestartNum = 0;
XkLi 0:c546b51ecf0b 1042 }
XkLi 0:c546b51ecf0b 1043
XkLi 0:c546b51ecf0b 1044 fixInBuffer();
XkLi 0:c546b51ecf0b 1045
XkLi 0:c546b51ecf0b 1046 return 0;
XkLi 0:c546b51ecf0b 1047 }
XkLi 0:c546b51ecf0b 1048 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 1049 static uint8 initFrame(void)
XkLi 0:c546b51ecf0b 1050 {
XkLi 0:c546b51ecf0b 1051 if (gCompsInFrame == 1)
XkLi 0:c546b51ecf0b 1052 {
XkLi 0:c546b51ecf0b 1053 if ((gCompHSamp[0] != 1) || (gCompVSamp[0] != 1))
XkLi 0:c546b51ecf0b 1054 return PJPG_UNSUPPORTED_SAMP_FACTORS;
XkLi 0:c546b51ecf0b 1055
XkLi 0:c546b51ecf0b 1056 gScanType = PJPG_GRAYSCALE;
XkLi 0:c546b51ecf0b 1057
XkLi 0:c546b51ecf0b 1058 gMaxBlocksPerMCU = 1;
XkLi 0:c546b51ecf0b 1059 gMCUOrg[0] = 0;
XkLi 0:c546b51ecf0b 1060
XkLi 0:c546b51ecf0b 1061 gMaxMCUXSize = 8;
XkLi 0:c546b51ecf0b 1062 gMaxMCUYSize = 8;
XkLi 0:c546b51ecf0b 1063 }
XkLi 0:c546b51ecf0b 1064 else if (gCompsInFrame == 3)
XkLi 0:c546b51ecf0b 1065 {
XkLi 0:c546b51ecf0b 1066 if ( ((gCompHSamp[1] != 1) || (gCompVSamp[1] != 1)) ||
XkLi 0:c546b51ecf0b 1067 ((gCompHSamp[2] != 1) || (gCompVSamp[2] != 1)) )
XkLi 0:c546b51ecf0b 1068 return PJPG_UNSUPPORTED_SAMP_FACTORS;
XkLi 0:c546b51ecf0b 1069
XkLi 0:c546b51ecf0b 1070 if ((gCompHSamp[0] == 1) && (gCompVSamp[0] == 1))
XkLi 0:c546b51ecf0b 1071 {
XkLi 0:c546b51ecf0b 1072 gScanType = PJPG_YH1V1;
XkLi 0:c546b51ecf0b 1073
XkLi 0:c546b51ecf0b 1074 gMaxBlocksPerMCU = 3;
XkLi 0:c546b51ecf0b 1075 gMCUOrg[0] = 0;
XkLi 0:c546b51ecf0b 1076 gMCUOrg[1] = 1;
XkLi 0:c546b51ecf0b 1077 gMCUOrg[2] = 2;
XkLi 0:c546b51ecf0b 1078
XkLi 0:c546b51ecf0b 1079 gMaxMCUXSize = 8;
XkLi 0:c546b51ecf0b 1080 gMaxMCUYSize = 8;
XkLi 0:c546b51ecf0b 1081 }
XkLi 0:c546b51ecf0b 1082 else if ((gCompHSamp[0] == 2) && (gCompVSamp[0] == 2))
XkLi 0:c546b51ecf0b 1083 {
XkLi 0:c546b51ecf0b 1084 gScanType = PJPG_YH2V2;
XkLi 0:c546b51ecf0b 1085
XkLi 0:c546b51ecf0b 1086 gMaxBlocksPerMCU = 6;
XkLi 0:c546b51ecf0b 1087 gMCUOrg[0] = 0;
XkLi 0:c546b51ecf0b 1088 gMCUOrg[1] = 0;
XkLi 0:c546b51ecf0b 1089 gMCUOrg[2] = 0;
XkLi 0:c546b51ecf0b 1090 gMCUOrg[3] = 0;
XkLi 0:c546b51ecf0b 1091 gMCUOrg[4] = 1;
XkLi 0:c546b51ecf0b 1092 gMCUOrg[5] = 2;
XkLi 0:c546b51ecf0b 1093
XkLi 0:c546b51ecf0b 1094 gMaxMCUXSize = 16;
XkLi 0:c546b51ecf0b 1095 gMaxMCUYSize = 16;
XkLi 0:c546b51ecf0b 1096 }
XkLi 0:c546b51ecf0b 1097 else
XkLi 0:c546b51ecf0b 1098 return PJPG_UNSUPPORTED_SAMP_FACTORS;
XkLi 0:c546b51ecf0b 1099 }
XkLi 0:c546b51ecf0b 1100 else
XkLi 0:c546b51ecf0b 1101 return PJPG_UNSUPPORTED_COLORSPACE;
XkLi 0:c546b51ecf0b 1102
XkLi 0:c546b51ecf0b 1103 gMaxMCUSPerRow = (gImageXSize + (gMaxMCUXSize - 1)) >> ((gMaxMCUXSize == 8) ? 3 : 4);
XkLi 0:c546b51ecf0b 1104 gMaxMCUSPerCol = (gImageYSize + (gMaxMCUYSize - 1)) >> ((gMaxMCUYSize == 8) ? 3 : 4);
XkLi 0:c546b51ecf0b 1105
XkLi 0:c546b51ecf0b 1106 gNumMCUSRemaining = gMaxMCUSPerRow * gMaxMCUSPerCol;
XkLi 0:c546b51ecf0b 1107
XkLi 0:c546b51ecf0b 1108 return 0;
XkLi 0:c546b51ecf0b 1109 }
XkLi 0:c546b51ecf0b 1110 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1111 #define DCT_SCALE_BITS 7
XkLi 0:c546b51ecf0b 1112
XkLi 0:c546b51ecf0b 1113 #define DCT_SCALE (1U << DCT_SCALE_BITS)
XkLi 0:c546b51ecf0b 1114
XkLi 0:c546b51ecf0b 1115 #define DESCALE(x) (((x) + (1U << (DCT_SCALE_BITS - 1))) >> DCT_SCALE_BITS)
XkLi 0:c546b51ecf0b 1116
XkLi 0:c546b51ecf0b 1117 #define WFIX(x) ((x) * DCT_SCALE + 0.5f)
XkLi 0:c546b51ecf0b 1118
XkLi 0:c546b51ecf0b 1119 #define WINOGRAD_QUANT_SCALE_BITS 10
XkLi 0:c546b51ecf0b 1120
XkLi 0:c546b51ecf0b 1121 const uint8 gWinogradQuant[] =
XkLi 0:c546b51ecf0b 1122 {
XkLi 0:c546b51ecf0b 1123 128, 178, 178, 167, 246, 167, 151, 232,
XkLi 0:c546b51ecf0b 1124 232, 151, 128, 209, 219, 209, 128, 101,
XkLi 0:c546b51ecf0b 1125 178, 197, 197, 178, 101, 69, 139, 167,
XkLi 0:c546b51ecf0b 1126 177, 167, 139, 69, 35, 96, 131, 151,
XkLi 0:c546b51ecf0b 1127 151, 131, 96, 35, 49, 91, 118, 128,
XkLi 0:c546b51ecf0b 1128 118, 91, 49, 46, 81, 101, 101, 81,
XkLi 0:c546b51ecf0b 1129 46, 42, 69, 79, 69, 42, 35, 54,
XkLi 0:c546b51ecf0b 1130 54, 35, 28, 37, 28, 19, 19, 10,
XkLi 0:c546b51ecf0b 1131 };
XkLi 0:c546b51ecf0b 1132
XkLi 0:c546b51ecf0b 1133 static void createWinogradQuant(int16* pQuant)
XkLi 0:c546b51ecf0b 1134 {
XkLi 0:c546b51ecf0b 1135 uint8 i;
XkLi 0:c546b51ecf0b 1136
XkLi 0:c546b51ecf0b 1137 for (i = 0; i < 64; i++)
XkLi 0:c546b51ecf0b 1138 {
XkLi 0:c546b51ecf0b 1139 long x = pQuant[i];
XkLi 0:c546b51ecf0b 1140 x *= gWinogradQuant[i];
XkLi 0:c546b51ecf0b 1141 pQuant[i] = (int16)((x + (1 << (WINOGRAD_QUANT_SCALE_BITS - DCT_SCALE_BITS - 1))) >> (WINOGRAD_QUANT_SCALE_BITS - DCT_SCALE_BITS));
XkLi 0:c546b51ecf0b 1142 }
XkLi 0:c546b51ecf0b 1143 }
XkLi 0:c546b51ecf0b 1144
XkLi 0:c546b51ecf0b 1145 // 1/cos(4*pi/16)
XkLi 0:c546b51ecf0b 1146 // 362, 256+106
XkLi 0:c546b51ecf0b 1147 #define b1 362
XkLi 0:c546b51ecf0b 1148
XkLi 0:c546b51ecf0b 1149 // 1/cos(6*pi/16)
XkLi 0:c546b51ecf0b 1150 // 669, 256+256+157
XkLi 0:c546b51ecf0b 1151 #define b2 669
XkLi 0:c546b51ecf0b 1152
XkLi 0:c546b51ecf0b 1153 // 1/cos(4*pi/16)
XkLi 0:c546b51ecf0b 1154 // 362, 256+106
XkLi 0:c546b51ecf0b 1155 #define b3 362
XkLi 0:c546b51ecf0b 1156
XkLi 0:c546b51ecf0b 1157 // 1/cos(2*pi/16)
XkLi 0:c546b51ecf0b 1158 // 277, 256+21
XkLi 0:c546b51ecf0b 1159 #define b4 277
XkLi 0:c546b51ecf0b 1160
XkLi 0:c546b51ecf0b 1161 // 1/(cos(2*pi/16) + cos(6*pi/16))
XkLi 0:c546b51ecf0b 1162 // 196, 196
XkLi 0:c546b51ecf0b 1163 #define b5 196
XkLi 0:c546b51ecf0b 1164
XkLi 0:c546b51ecf0b 1165 static int16 imul_b1_b3(int16 w)
XkLi 0:c546b51ecf0b 1166 {
XkLi 0:c546b51ecf0b 1167 long x = (w * 362L);
XkLi 0:c546b51ecf0b 1168 x += 128L;
XkLi 0:c546b51ecf0b 1169 return (int16)(x >> 8);
XkLi 0:c546b51ecf0b 1170 }
XkLi 0:c546b51ecf0b 1171
XkLi 0:c546b51ecf0b 1172 static int16 imul_b2(int16 w)
XkLi 0:c546b51ecf0b 1173 {
XkLi 0:c546b51ecf0b 1174 long x = (w * 669L);
XkLi 0:c546b51ecf0b 1175 x += 128L;
XkLi 0:c546b51ecf0b 1176 return (int16)(x >> 8);
XkLi 0:c546b51ecf0b 1177 }
XkLi 0:c546b51ecf0b 1178
XkLi 0:c546b51ecf0b 1179 static int16 imul_b4(int16 w)
XkLi 0:c546b51ecf0b 1180 {
XkLi 0:c546b51ecf0b 1181 long x = (w * 277L);
XkLi 0:c546b51ecf0b 1182 x += 128L;
XkLi 0:c546b51ecf0b 1183 return (int16)(x >> 8);
XkLi 0:c546b51ecf0b 1184 }
XkLi 0:c546b51ecf0b 1185
XkLi 0:c546b51ecf0b 1186 static int16 imul_b5(int16 w)
XkLi 0:c546b51ecf0b 1187 {
XkLi 0:c546b51ecf0b 1188 long x = (w * 196L);
XkLi 0:c546b51ecf0b 1189 x += 128L;
XkLi 0:c546b51ecf0b 1190 return (int16)(x >> 8);
XkLi 0:c546b51ecf0b 1191 }
XkLi 0:c546b51ecf0b 1192
XkLi 0:c546b51ecf0b 1193 static uint8 clamp(int16 s)
XkLi 0:c546b51ecf0b 1194 {
XkLi 0:c546b51ecf0b 1195 if ((uint16)s > 255U)
XkLi 0:c546b51ecf0b 1196 {
XkLi 0:c546b51ecf0b 1197 if (s < 0)
XkLi 0:c546b51ecf0b 1198 return 0;
XkLi 0:c546b51ecf0b 1199 else if (s > 255)
XkLi 0:c546b51ecf0b 1200 return 255;
XkLi 0:c546b51ecf0b 1201 }
XkLi 0:c546b51ecf0b 1202
XkLi 0:c546b51ecf0b 1203 return (uint8)s;
XkLi 0:c546b51ecf0b 1204 }
XkLi 0:c546b51ecf0b 1205
XkLi 0:c546b51ecf0b 1206 static void idctRows(void)
XkLi 0:c546b51ecf0b 1207 {
XkLi 0:c546b51ecf0b 1208 uint8 i;
XkLi 0:c546b51ecf0b 1209 int16* pSrc = gCoeffBuf;
XkLi 0:c546b51ecf0b 1210
XkLi 0:c546b51ecf0b 1211 for (i = 0; i < 8; i++)
XkLi 0:c546b51ecf0b 1212 {
XkLi 0:c546b51ecf0b 1213 int16 src4 = *(pSrc+5);
XkLi 0:c546b51ecf0b 1214 int16 src7 = *(pSrc+3);
XkLi 0:c546b51ecf0b 1215 int16 x4 = src4 - src7;
XkLi 0:c546b51ecf0b 1216 int16 x7 = src4 + src7;
XkLi 0:c546b51ecf0b 1217
XkLi 0:c546b51ecf0b 1218 int16 src5 = *(pSrc+1);
XkLi 0:c546b51ecf0b 1219 int16 src6 = *(pSrc+7);
XkLi 0:c546b51ecf0b 1220 int16 x5 = src5 + src6;
XkLi 0:c546b51ecf0b 1221 int16 x6 = src5 - src6;
XkLi 0:c546b51ecf0b 1222
XkLi 0:c546b51ecf0b 1223 int16 tmp1 = imul_b5(x4 - x6);
XkLi 0:c546b51ecf0b 1224 int16 stg26 = imul_b4(x6) - tmp1;
XkLi 0:c546b51ecf0b 1225
XkLi 0:c546b51ecf0b 1226 int16 x24 = tmp1 - imul_b2(x4);
XkLi 0:c546b51ecf0b 1227
XkLi 0:c546b51ecf0b 1228 int16 x15 = x5 - x7;
XkLi 0:c546b51ecf0b 1229 int16 x17 = x5 + x7;
XkLi 0:c546b51ecf0b 1230
XkLi 0:c546b51ecf0b 1231 int16 tmp2 = stg26 - x17;
XkLi 0:c546b51ecf0b 1232 int16 tmp3 = imul_b1_b3(x15) - tmp2;
XkLi 0:c546b51ecf0b 1233 int16 x44 = tmp3 + x24;
XkLi 0:c546b51ecf0b 1234
XkLi 0:c546b51ecf0b 1235 int16 src0 = *(pSrc+0);
XkLi 0:c546b51ecf0b 1236 int16 src1 = *(pSrc+4);
XkLi 0:c546b51ecf0b 1237 int16 x30 = src0 + src1;
XkLi 0:c546b51ecf0b 1238 int16 x31 = src0 - src1;
XkLi 0:c546b51ecf0b 1239
XkLi 0:c546b51ecf0b 1240 int16 src2 = *(pSrc+2);
XkLi 0:c546b51ecf0b 1241 int16 src3 = *(pSrc+6);
XkLi 0:c546b51ecf0b 1242 int16 x12 = src2 - src3;
XkLi 0:c546b51ecf0b 1243 int16 x13 = src2 + src3;
XkLi 0:c546b51ecf0b 1244
XkLi 0:c546b51ecf0b 1245 int16 x32 = imul_b1_b3(x12) - x13;
XkLi 0:c546b51ecf0b 1246
XkLi 0:c546b51ecf0b 1247 int16 x40 = x30 + x13;
XkLi 0:c546b51ecf0b 1248 int16 x43 = x30 - x13;
XkLi 0:c546b51ecf0b 1249 int16 x41 = x31 + x32;
XkLi 0:c546b51ecf0b 1250 int16 x42 = x31 - x32;
XkLi 0:c546b51ecf0b 1251
XkLi 0:c546b51ecf0b 1252 *(pSrc+0) = x40 + x17;
XkLi 0:c546b51ecf0b 1253 *(pSrc+1) = x41 + tmp2;
XkLi 0:c546b51ecf0b 1254 *(pSrc+2) = x42 + tmp3;
XkLi 0:c546b51ecf0b 1255 *(pSrc+3) = x43 - x44;
XkLi 0:c546b51ecf0b 1256 *(pSrc+4) = x43 + x44;
XkLi 0:c546b51ecf0b 1257 *(pSrc+5) = x42 - tmp3;
XkLi 0:c546b51ecf0b 1258 *(pSrc+6) = x41 - tmp2;
XkLi 0:c546b51ecf0b 1259 *(pSrc+7) = x40 - x17;
XkLi 0:c546b51ecf0b 1260
XkLi 0:c546b51ecf0b 1261 pSrc += 8;
XkLi 0:c546b51ecf0b 1262 }
XkLi 0:c546b51ecf0b 1263 }
XkLi 0:c546b51ecf0b 1264
XkLi 0:c546b51ecf0b 1265 static void idctCols(void)
XkLi 0:c546b51ecf0b 1266 {
XkLi 0:c546b51ecf0b 1267 uint8 i;
XkLi 0:c546b51ecf0b 1268
XkLi 0:c546b51ecf0b 1269 int16* pSrc = gCoeffBuf;
XkLi 0:c546b51ecf0b 1270
XkLi 0:c546b51ecf0b 1271 for (i = 0; i < 8; i++)
XkLi 0:c546b51ecf0b 1272 {
XkLi 0:c546b51ecf0b 1273 int16 src4 = *(pSrc+5*8);
XkLi 0:c546b51ecf0b 1274 int16 src7 = *(pSrc+3*8);
XkLi 0:c546b51ecf0b 1275 int16 x4 = src4 - src7;
XkLi 0:c546b51ecf0b 1276 int16 x7 = src4 + src7;
XkLi 0:c546b51ecf0b 1277
XkLi 0:c546b51ecf0b 1278 int16 src5 = *(pSrc+1*8);
XkLi 0:c546b51ecf0b 1279 int16 src6 = *(pSrc+7*8);
XkLi 0:c546b51ecf0b 1280 int16 x5 = src5 + src6;
XkLi 0:c546b51ecf0b 1281 int16 x6 = src5 - src6;
XkLi 0:c546b51ecf0b 1282
XkLi 0:c546b51ecf0b 1283 int16 tmp1 = imul_b5(x4 - x6);
XkLi 0:c546b51ecf0b 1284 int16 stg26 = imul_b4(x6) - tmp1;
XkLi 0:c546b51ecf0b 1285
XkLi 0:c546b51ecf0b 1286 int16 x24 = tmp1 - imul_b2(x4);
XkLi 0:c546b51ecf0b 1287
XkLi 0:c546b51ecf0b 1288 int16 x15 = x5 - x7;
XkLi 0:c546b51ecf0b 1289 int16 x17 = x5 + x7;
XkLi 0:c546b51ecf0b 1290
XkLi 0:c546b51ecf0b 1291 int16 tmp2 = stg26 - x17;
XkLi 0:c546b51ecf0b 1292 int16 tmp3 = imul_b1_b3(x15) - tmp2;
XkLi 0:c546b51ecf0b 1293 int16 x44 = tmp3 + x24;
XkLi 0:c546b51ecf0b 1294
XkLi 0:c546b51ecf0b 1295 int16 src0 = *(pSrc+0*8);
XkLi 0:c546b51ecf0b 1296 int16 src1 = *(pSrc+4*8);
XkLi 0:c546b51ecf0b 1297 int16 x30 = src0 + src1;
XkLi 0:c546b51ecf0b 1298 int16 x31 = src0 - src1;
XkLi 0:c546b51ecf0b 1299
XkLi 0:c546b51ecf0b 1300 int16 src2 = *(pSrc+2*8);
XkLi 0:c546b51ecf0b 1301 int16 src3 = *(pSrc+6*8);
XkLi 0:c546b51ecf0b 1302 int16 x12 = src2 - src3;
XkLi 0:c546b51ecf0b 1303 int16 x13 = src2 + src3;
XkLi 0:c546b51ecf0b 1304
XkLi 0:c546b51ecf0b 1305 int16 x32 = imul_b1_b3(x12) - x13;
XkLi 0:c546b51ecf0b 1306
XkLi 0:c546b51ecf0b 1307 int16 x40 = x30 + x13;
XkLi 0:c546b51ecf0b 1308 int16 x43 = x30 - x13;
XkLi 0:c546b51ecf0b 1309 int16 x41 = x31 + x32;
XkLi 0:c546b51ecf0b 1310 int16 x42 = x31 - x32;
XkLi 0:c546b51ecf0b 1311
XkLi 0:c546b51ecf0b 1312 *(pSrc+0*8) = clamp(DESCALE(x40 + x17) + 128);
XkLi 0:c546b51ecf0b 1313 *(pSrc+1*8) = clamp(DESCALE(x41 + tmp2) + 128);
XkLi 0:c546b51ecf0b 1314 *(pSrc+2*8) = clamp(DESCALE(x42 + tmp3) + 128);
XkLi 0:c546b51ecf0b 1315 *(pSrc+3*8) = clamp(DESCALE(x43 - x44) + 128);
XkLi 0:c546b51ecf0b 1316 *(pSrc+4*8) = clamp(DESCALE(x43 + x44) + 128);
XkLi 0:c546b51ecf0b 1317 *(pSrc+5*8) = clamp(DESCALE(x42 - tmp3) + 128);
XkLi 0:c546b51ecf0b 1318 *(pSrc+6*8) = clamp(DESCALE(x41 - tmp2) + 128);
XkLi 0:c546b51ecf0b 1319 *(pSrc+7*8) = clamp(DESCALE(x40 - x17) + 128);
XkLi 0:c546b51ecf0b 1320
XkLi 0:c546b51ecf0b 1321 pSrc++;
XkLi 0:c546b51ecf0b 1322 }
XkLi 0:c546b51ecf0b 1323 }
XkLi 0:c546b51ecf0b 1324
XkLi 0:c546b51ecf0b 1325 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1326 static uint8 addAndClamp(uint8 a, int16 b)
XkLi 0:c546b51ecf0b 1327 {
XkLi 0:c546b51ecf0b 1328 b = a + b;
XkLi 0:c546b51ecf0b 1329
XkLi 0:c546b51ecf0b 1330 if ((uint16)b > 255U)
XkLi 0:c546b51ecf0b 1331 {
XkLi 0:c546b51ecf0b 1332 if (b < 0)
XkLi 0:c546b51ecf0b 1333 return 0;
XkLi 0:c546b51ecf0b 1334 else if (b > 255)
XkLi 0:c546b51ecf0b 1335 return 255;
XkLi 0:c546b51ecf0b 1336 }
XkLi 0:c546b51ecf0b 1337
XkLi 0:c546b51ecf0b 1338 return (uint8)b;
XkLi 0:c546b51ecf0b 1339 }
XkLi 0:c546b51ecf0b 1340 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1341 static uint8 subAndClamp(uint8 a, int16 b)
XkLi 0:c546b51ecf0b 1342 {
XkLi 0:c546b51ecf0b 1343 b = a - b;
XkLi 0:c546b51ecf0b 1344
XkLi 0:c546b51ecf0b 1345 if ((uint16)b > 255U)
XkLi 0:c546b51ecf0b 1346 {
XkLi 0:c546b51ecf0b 1347 if (b < 0)
XkLi 0:c546b51ecf0b 1348 return 0;
XkLi 0:c546b51ecf0b 1349 else if (b > 255)
XkLi 0:c546b51ecf0b 1350 return 255;
XkLi 0:c546b51ecf0b 1351 }
XkLi 0:c546b51ecf0b 1352
XkLi 0:c546b51ecf0b 1353 return (uint8)b;
XkLi 0:c546b51ecf0b 1354 }
XkLi 0:c546b51ecf0b 1355 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1356 // 103/256
XkLi 0:c546b51ecf0b 1357 //R = Y + 1.402 (Cr-128)
XkLi 0:c546b51ecf0b 1358
XkLi 0:c546b51ecf0b 1359 // 88/256, 183/256
XkLi 0:c546b51ecf0b 1360 //G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
XkLi 0:c546b51ecf0b 1361
XkLi 0:c546b51ecf0b 1362 // 198/256
XkLi 0:c546b51ecf0b 1363 //B = Y + 1.772 (Cb-128)
XkLi 0:c546b51ecf0b 1364 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1365 static void upsampleCb(uint8 srcOfs, uint8 dstOfs)
XkLi 0:c546b51ecf0b 1366 {
XkLi 0:c546b51ecf0b 1367 // Cb - affects G and B
XkLi 0:c546b51ecf0b 1368 uint8 x, y;
XkLi 0:c546b51ecf0b 1369 int16* pSrc = gCoeffBuf + srcOfs;
XkLi 0:c546b51ecf0b 1370 uint8* pDstG = gMCUBufG + dstOfs;
XkLi 0:c546b51ecf0b 1371 uint8* pDstB = gMCUBufB + dstOfs;
XkLi 0:c546b51ecf0b 1372 for (y = 0; y < 4; y++)
XkLi 0:c546b51ecf0b 1373 {
XkLi 0:c546b51ecf0b 1374 for (x = 0; x < 4; x++)
XkLi 0:c546b51ecf0b 1375 {
XkLi 0:c546b51ecf0b 1376 uint8 cb = (uint8)*pSrc++;
XkLi 0:c546b51ecf0b 1377 int16 cbG, cbB;
XkLi 0:c546b51ecf0b 1378
XkLi 0:c546b51ecf0b 1379 cbG = ((cb * 88U) >> 8U) - 44U;
XkLi 0:c546b51ecf0b 1380 pDstG[0] = subAndClamp(pDstG[0], cbG);
XkLi 0:c546b51ecf0b 1381 pDstG[1] = subAndClamp(pDstG[1], cbG);
XkLi 0:c546b51ecf0b 1382 pDstG[8] = subAndClamp(pDstG[8], cbG);
XkLi 0:c546b51ecf0b 1383 pDstG[9] = subAndClamp(pDstG[9], cbG);
XkLi 0:c546b51ecf0b 1384
XkLi 0:c546b51ecf0b 1385 cbB = (cb + ((cb * 198U) >> 8U)) - 227U;
XkLi 0:c546b51ecf0b 1386 pDstB[0] = addAndClamp(pDstB[0], cbB);
XkLi 0:c546b51ecf0b 1387 pDstB[1] = addAndClamp(pDstB[1], cbB);
XkLi 0:c546b51ecf0b 1388 pDstB[8] = addAndClamp(pDstB[8], cbB);
XkLi 0:c546b51ecf0b 1389 pDstB[9] = addAndClamp(pDstB[9], cbB);
XkLi 0:c546b51ecf0b 1390
XkLi 0:c546b51ecf0b 1391 pDstG += 2;
XkLi 0:c546b51ecf0b 1392 pDstB += 2;
XkLi 0:c546b51ecf0b 1393 }
XkLi 0:c546b51ecf0b 1394
XkLi 0:c546b51ecf0b 1395 pSrc = pSrc - 4 + 8;
XkLi 0:c546b51ecf0b 1396 pDstG = pDstG - 8 + 16;
XkLi 0:c546b51ecf0b 1397 pDstB = pDstB - 8 + 16;
XkLi 0:c546b51ecf0b 1398 }
XkLi 0:c546b51ecf0b 1399 }
XkLi 0:c546b51ecf0b 1400 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1401 // 103/256
XkLi 0:c546b51ecf0b 1402 //R = Y + 1.402 (Cr-128)
XkLi 0:c546b51ecf0b 1403
XkLi 0:c546b51ecf0b 1404 // 88/256, 183/256
XkLi 0:c546b51ecf0b 1405 //G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
XkLi 0:c546b51ecf0b 1406
XkLi 0:c546b51ecf0b 1407 // 198/256
XkLi 0:c546b51ecf0b 1408 //B = Y + 1.772 (Cb-128)
XkLi 0:c546b51ecf0b 1409 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1410 static void upsampleCr(uint8 srcOfs, uint8 dstOfs)
XkLi 0:c546b51ecf0b 1411 {
XkLi 0:c546b51ecf0b 1412 // Cr - affects R and G
XkLi 0:c546b51ecf0b 1413 uint8 x, y;
XkLi 0:c546b51ecf0b 1414 int16* pSrc = gCoeffBuf + srcOfs;
XkLi 0:c546b51ecf0b 1415 uint8* pDstR = gMCUBufR + dstOfs;
XkLi 0:c546b51ecf0b 1416 uint8* pDstG = gMCUBufG + dstOfs;
XkLi 0:c546b51ecf0b 1417 for (y = 0; y < 4; y++)
XkLi 0:c546b51ecf0b 1418 {
XkLi 0:c546b51ecf0b 1419 for (x = 0; x < 4; x++)
XkLi 0:c546b51ecf0b 1420 {
XkLi 0:c546b51ecf0b 1421 uint8 cr = (uint8)*pSrc++;
XkLi 0:c546b51ecf0b 1422 int16 crR, crG;
XkLi 0:c546b51ecf0b 1423
XkLi 0:c546b51ecf0b 1424 crR = (cr + ((cr * 103U) >> 8U)) - 179;
XkLi 0:c546b51ecf0b 1425 pDstR[0] = addAndClamp(pDstR[0], crR);
XkLi 0:c546b51ecf0b 1426 pDstR[1] = addAndClamp(pDstR[1], crR);
XkLi 0:c546b51ecf0b 1427 pDstR[8] = addAndClamp(pDstR[8], crR);
XkLi 0:c546b51ecf0b 1428 pDstR[9] = addAndClamp(pDstR[9], crR);
XkLi 0:c546b51ecf0b 1429
XkLi 0:c546b51ecf0b 1430 crG = ((cr * 183U) >> 8U) - 91;
XkLi 0:c546b51ecf0b 1431 pDstG[0] = subAndClamp(pDstG[0], crG);
XkLi 0:c546b51ecf0b 1432 pDstG[1] = subAndClamp(pDstG[1], crG);
XkLi 0:c546b51ecf0b 1433 pDstG[8] = subAndClamp(pDstG[8], crG);
XkLi 0:c546b51ecf0b 1434 pDstG[9] = subAndClamp(pDstG[9], crG);
XkLi 0:c546b51ecf0b 1435
XkLi 0:c546b51ecf0b 1436 pDstR += 2;
XkLi 0:c546b51ecf0b 1437 pDstG += 2;
XkLi 0:c546b51ecf0b 1438 }
XkLi 0:c546b51ecf0b 1439
XkLi 0:c546b51ecf0b 1440 pSrc = pSrc - 4 + 8;
XkLi 0:c546b51ecf0b 1441 pDstR = pDstR - 8 + 16;
XkLi 0:c546b51ecf0b 1442 pDstG = pDstG - 8 + 16;
XkLi 0:c546b51ecf0b 1443 }
XkLi 0:c546b51ecf0b 1444 }
XkLi 0:c546b51ecf0b 1445 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1446 static void copyY(uint8 dstOfs)
XkLi 0:c546b51ecf0b 1447 {
XkLi 0:c546b51ecf0b 1448 uint8 i;
XkLi 0:c546b51ecf0b 1449 uint8* pRDst = gMCUBufR + dstOfs;
XkLi 0:c546b51ecf0b 1450 uint8* pGDst = gMCUBufG + dstOfs;
XkLi 0:c546b51ecf0b 1451 uint8* pBDst = gMCUBufB + dstOfs;
XkLi 0:c546b51ecf0b 1452 int16* pSrc = gCoeffBuf;
XkLi 0:c546b51ecf0b 1453
XkLi 0:c546b51ecf0b 1454 for (i = 64; i > 0; i--)
XkLi 0:c546b51ecf0b 1455 {
XkLi 0:c546b51ecf0b 1456 uint8 c = (uint8)*pSrc++;
XkLi 0:c546b51ecf0b 1457
XkLi 0:c546b51ecf0b 1458 *pRDst++ = c;
XkLi 0:c546b51ecf0b 1459 *pGDst++ = c;
XkLi 0:c546b51ecf0b 1460 *pBDst++ = c;
XkLi 0:c546b51ecf0b 1461 }
XkLi 0:c546b51ecf0b 1462 }
XkLi 0:c546b51ecf0b 1463 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1464 static void convertCb(uint8 dstOfs)
XkLi 0:c546b51ecf0b 1465 {
XkLi 0:c546b51ecf0b 1466 uint8 i;
XkLi 0:c546b51ecf0b 1467 uint8* pDstG = gMCUBufG + dstOfs;
XkLi 0:c546b51ecf0b 1468 uint8* pDstB = gMCUBufB + dstOfs;
XkLi 0:c546b51ecf0b 1469 int16* pSrc = gCoeffBuf;
XkLi 0:c546b51ecf0b 1470
XkLi 0:c546b51ecf0b 1471 for (i = 64; i > 0; i--)
XkLi 0:c546b51ecf0b 1472 {
XkLi 0:c546b51ecf0b 1473 uint8 cb = (uint8)*pSrc++;
XkLi 0:c546b51ecf0b 1474 int16 cbG, cbB;
XkLi 0:c546b51ecf0b 1475
XkLi 0:c546b51ecf0b 1476 cbG = ((cb * 88U) >> 8U) - 44U;
XkLi 0:c546b51ecf0b 1477 *pDstG++ = subAndClamp(pDstG[0], cbG);
XkLi 0:c546b51ecf0b 1478
XkLi 0:c546b51ecf0b 1479 cbB = (cb + ((cb * 198U) >> 8U)) - 227U;
XkLi 0:c546b51ecf0b 1480 *pDstB++ = addAndClamp(pDstB[0], cbB);
XkLi 0:c546b51ecf0b 1481 }
XkLi 0:c546b51ecf0b 1482 }
XkLi 0:c546b51ecf0b 1483 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1484 static void convertCr(uint8 dstOfs)
XkLi 0:c546b51ecf0b 1485 {
XkLi 0:c546b51ecf0b 1486 uint8 i;
XkLi 0:c546b51ecf0b 1487 uint8* pDstR = gMCUBufR + dstOfs;
XkLi 0:c546b51ecf0b 1488 uint8* pDstG = gMCUBufG + dstOfs;
XkLi 0:c546b51ecf0b 1489 int16* pSrc = gCoeffBuf;
XkLi 0:c546b51ecf0b 1490
XkLi 0:c546b51ecf0b 1491 for (i = 64; i > 0; i--)
XkLi 0:c546b51ecf0b 1492 {
XkLi 0:c546b51ecf0b 1493 uint8 cr = (uint8)*pSrc++;
XkLi 0:c546b51ecf0b 1494 int16 crR, crG;
XkLi 0:c546b51ecf0b 1495
XkLi 0:c546b51ecf0b 1496 crR = (cr + ((cr * 103U) >> 8U)) - 179;
XkLi 0:c546b51ecf0b 1497 *pDstR++ = addAndClamp(pDstR[0], crR);
XkLi 0:c546b51ecf0b 1498
XkLi 0:c546b51ecf0b 1499 crG = ((cr * 183U) >> 8U) - 91;
XkLi 0:c546b51ecf0b 1500 *pDstG++ = subAndClamp(pDstG[0], crG);
XkLi 0:c546b51ecf0b 1501 }
XkLi 0:c546b51ecf0b 1502 }
XkLi 0:c546b51ecf0b 1503 /*----------------------------------------------------------------------------*/
XkLi 0:c546b51ecf0b 1504 static void transformBlock(uint8 mcuBlock)
XkLi 0:c546b51ecf0b 1505 {
XkLi 0:c546b51ecf0b 1506 idctRows();
XkLi 0:c546b51ecf0b 1507 idctCols();
XkLi 0:c546b51ecf0b 1508
XkLi 0:c546b51ecf0b 1509 switch (gScanType)
XkLi 0:c546b51ecf0b 1510 {
XkLi 0:c546b51ecf0b 1511 case PJPG_GRAYSCALE:
XkLi 0:c546b51ecf0b 1512 {
XkLi 0:c546b51ecf0b 1513 copyY(0);
XkLi 0:c546b51ecf0b 1514 break;
XkLi 0:c546b51ecf0b 1515 }
XkLi 0:c546b51ecf0b 1516 case PJPG_YH1V1:
XkLi 0:c546b51ecf0b 1517 {
XkLi 0:c546b51ecf0b 1518 switch (mcuBlock)
XkLi 0:c546b51ecf0b 1519 {
XkLi 0:c546b51ecf0b 1520 case 0:
XkLi 0:c546b51ecf0b 1521 {
XkLi 0:c546b51ecf0b 1522 copyY(0);
XkLi 0:c546b51ecf0b 1523 break;
XkLi 0:c546b51ecf0b 1524 }
XkLi 0:c546b51ecf0b 1525 case 1:
XkLi 0:c546b51ecf0b 1526 {
XkLi 0:c546b51ecf0b 1527 convertCb(0);
XkLi 0:c546b51ecf0b 1528 break;
XkLi 0:c546b51ecf0b 1529 }
XkLi 0:c546b51ecf0b 1530 case 2:
XkLi 0:c546b51ecf0b 1531 {
XkLi 0:c546b51ecf0b 1532 convertCr(0);
XkLi 0:c546b51ecf0b 1533 break;
XkLi 0:c546b51ecf0b 1534 }
XkLi 0:c546b51ecf0b 1535 }
XkLi 0:c546b51ecf0b 1536
XkLi 0:c546b51ecf0b 1537 break;
XkLi 0:c546b51ecf0b 1538 }
XkLi 0:c546b51ecf0b 1539 case PJPG_YH2V2:
XkLi 0:c546b51ecf0b 1540 {
XkLi 0:c546b51ecf0b 1541 switch (mcuBlock)
XkLi 0:c546b51ecf0b 1542 {
XkLi 0:c546b51ecf0b 1543 case 0:
XkLi 0:c546b51ecf0b 1544 {
XkLi 0:c546b51ecf0b 1545 copyY(0);
XkLi 0:c546b51ecf0b 1546 break;
XkLi 0:c546b51ecf0b 1547 }
XkLi 0:c546b51ecf0b 1548 case 1:
XkLi 0:c546b51ecf0b 1549 {
XkLi 0:c546b51ecf0b 1550 copyY(64);
XkLi 0:c546b51ecf0b 1551 break;
XkLi 0:c546b51ecf0b 1552 }
XkLi 0:c546b51ecf0b 1553 case 2:
XkLi 0:c546b51ecf0b 1554 {
XkLi 0:c546b51ecf0b 1555 copyY(128);
XkLi 0:c546b51ecf0b 1556 break;
XkLi 0:c546b51ecf0b 1557 }
XkLi 0:c546b51ecf0b 1558 case 3:
XkLi 0:c546b51ecf0b 1559 {
XkLi 0:c546b51ecf0b 1560 copyY(192);
XkLi 0:c546b51ecf0b 1561 break;
XkLi 0:c546b51ecf0b 1562 }
XkLi 0:c546b51ecf0b 1563 case 4:
XkLi 0:c546b51ecf0b 1564 {
XkLi 0:c546b51ecf0b 1565 upsampleCb(0, 0);
XkLi 0:c546b51ecf0b 1566 upsampleCb(4, 64);
XkLi 0:c546b51ecf0b 1567 upsampleCb(4*8, 128);
XkLi 0:c546b51ecf0b 1568 upsampleCb(4+4*8, 192);
XkLi 0:c546b51ecf0b 1569 break;
XkLi 0:c546b51ecf0b 1570 }
XkLi 0:c546b51ecf0b 1571 case 5:
XkLi 0:c546b51ecf0b 1572 {
XkLi 0:c546b51ecf0b 1573 upsampleCr(0, 0);
XkLi 0:c546b51ecf0b 1574 upsampleCr(4, 64);
XkLi 0:c546b51ecf0b 1575 upsampleCr(4*8, 128);
XkLi 0:c546b51ecf0b 1576 upsampleCr(4+4*8, 192);
XkLi 0:c546b51ecf0b 1577 break;
XkLi 0:c546b51ecf0b 1578 }
XkLi 0:c546b51ecf0b 1579 }
XkLi 0:c546b51ecf0b 1580 }
XkLi 0:c546b51ecf0b 1581 }
XkLi 0:c546b51ecf0b 1582 }
XkLi 0:c546b51ecf0b 1583 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 1584 static uint8 decodeNextMCU(void)
XkLi 0:c546b51ecf0b 1585 {
XkLi 0:c546b51ecf0b 1586 uint8 status;
XkLi 0:c546b51ecf0b 1587 uint8 mcuBlock;
XkLi 0:c546b51ecf0b 1588
XkLi 0:c546b51ecf0b 1589 if (gRestartInterval)
XkLi 0:c546b51ecf0b 1590 {
XkLi 0:c546b51ecf0b 1591 if (gRestartsLeft == 0)
XkLi 0:c546b51ecf0b 1592 {
XkLi 0:c546b51ecf0b 1593 status = processRestart();
XkLi 0:c546b51ecf0b 1594 if (status)
XkLi 0:c546b51ecf0b 1595 return status;
XkLi 0:c546b51ecf0b 1596 }
XkLi 0:c546b51ecf0b 1597 gRestartsLeft--;
XkLi 0:c546b51ecf0b 1598 }
XkLi 0:c546b51ecf0b 1599
XkLi 0:c546b51ecf0b 1600 for (mcuBlock = 0; mcuBlock < gMaxBlocksPerMCU; mcuBlock++)
XkLi 0:c546b51ecf0b 1601 {
XkLi 0:c546b51ecf0b 1602 uint8 componentID = gMCUOrg[mcuBlock];
XkLi 0:c546b51ecf0b 1603 uint8 compQuant = gCompQuant[componentID];
XkLi 0:c546b51ecf0b 1604 uint8 compDCTab = gCompDCTab[componentID];
XkLi 0:c546b51ecf0b 1605 uint8 numExtraBits, compACTab, k;
XkLi 0:c546b51ecf0b 1606 const int16* pQ = compQuant ? gQuant1 : gQuant0;
XkLi 0:c546b51ecf0b 1607 uint16 r, dc;
XkLi 0:c546b51ecf0b 1608
XkLi 0:c546b51ecf0b 1609 uint8 s = huffDecode(compDCTab ? &gHuffTab1 : &gHuffTab0, compDCTab ? gHuffVal1 : gHuffVal0);
XkLi 0:c546b51ecf0b 1610
XkLi 0:c546b51ecf0b 1611 r = 0;
XkLi 0:c546b51ecf0b 1612 numExtraBits = s & 0xF;
XkLi 0:c546b51ecf0b 1613 if (numExtraBits)
XkLi 0:c546b51ecf0b 1614 r = getBits2(numExtraBits);
XkLi 0:c546b51ecf0b 1615 dc = huffExtend(r, s);
XkLi 0:c546b51ecf0b 1616
XkLi 0:c546b51ecf0b 1617 dc = dc + gLastDC[componentID];
XkLi 0:c546b51ecf0b 1618 gLastDC[componentID] = dc;
XkLi 0:c546b51ecf0b 1619
XkLi 0:c546b51ecf0b 1620 gCoeffBuf[0] = dc * pQ[0];
XkLi 0:c546b51ecf0b 1621
XkLi 0:c546b51ecf0b 1622 compACTab = gCompACTab[componentID];
XkLi 0:c546b51ecf0b 1623
XkLi 0:c546b51ecf0b 1624 for (k = 1; k < 64; k++)
XkLi 0:c546b51ecf0b 1625 {
XkLi 0:c546b51ecf0b 1626 uint16 extraBits;
XkLi 0:c546b51ecf0b 1627
XkLi 0:c546b51ecf0b 1628 s = huffDecode(compACTab ? &gHuffTab3 : &gHuffTab2, compACTab ? gHuffVal3 : gHuffVal2);
XkLi 0:c546b51ecf0b 1629
XkLi 0:c546b51ecf0b 1630 extraBits = 0;
XkLi 0:c546b51ecf0b 1631 numExtraBits = s & 0xF;
XkLi 0:c546b51ecf0b 1632 if (numExtraBits)
XkLi 0:c546b51ecf0b 1633 extraBits = getBits2(numExtraBits);
XkLi 0:c546b51ecf0b 1634
XkLi 0:c546b51ecf0b 1635 r = s >> 4;
XkLi 0:c546b51ecf0b 1636 s &= 15;
XkLi 0:c546b51ecf0b 1637
XkLi 0:c546b51ecf0b 1638 if (s)
XkLi 0:c546b51ecf0b 1639 {
XkLi 0:c546b51ecf0b 1640 int16 ac;
XkLi 0:c546b51ecf0b 1641
XkLi 0:c546b51ecf0b 1642 if (r)
XkLi 0:c546b51ecf0b 1643 {
XkLi 0:c546b51ecf0b 1644 if ((k + r) > 63)
XkLi 0:c546b51ecf0b 1645 return PJPG_DECODE_ERROR;
XkLi 0:c546b51ecf0b 1646
XkLi 0:c546b51ecf0b 1647 while (r)
XkLi 0:c546b51ecf0b 1648 {
XkLi 0:c546b51ecf0b 1649 gCoeffBuf[ZAG[k++]] = 0;
XkLi 0:c546b51ecf0b 1650 r--;
XkLi 0:c546b51ecf0b 1651 }
XkLi 0:c546b51ecf0b 1652 }
XkLi 0:c546b51ecf0b 1653
XkLi 0:c546b51ecf0b 1654 ac = huffExtend(extraBits, s);
XkLi 0:c546b51ecf0b 1655
XkLi 0:c546b51ecf0b 1656 gCoeffBuf[ZAG[k]] = ac * pQ[k];
XkLi 0:c546b51ecf0b 1657 }
XkLi 0:c546b51ecf0b 1658 else
XkLi 0:c546b51ecf0b 1659 {
XkLi 0:c546b51ecf0b 1660 if (r == 15)
XkLi 0:c546b51ecf0b 1661 {
XkLi 0:c546b51ecf0b 1662 if ((k + 16) > 64)
XkLi 0:c546b51ecf0b 1663 return PJPG_DECODE_ERROR;
XkLi 0:c546b51ecf0b 1664
XkLi 0:c546b51ecf0b 1665 for (r = 16; r > 0; r--)
XkLi 0:c546b51ecf0b 1666 gCoeffBuf[ZAG[k++]] = 0;
XkLi 0:c546b51ecf0b 1667
XkLi 0:c546b51ecf0b 1668 k--; // - 1 because the loop counter is k
XkLi 0:c546b51ecf0b 1669 }
XkLi 0:c546b51ecf0b 1670 else
XkLi 0:c546b51ecf0b 1671 break;
XkLi 0:c546b51ecf0b 1672 }
XkLi 0:c546b51ecf0b 1673 }
XkLi 0:c546b51ecf0b 1674
XkLi 0:c546b51ecf0b 1675 while (k < 64)
XkLi 0:c546b51ecf0b 1676 gCoeffBuf[ZAG[k++]] = 0;
XkLi 0:c546b51ecf0b 1677
XkLi 0:c546b51ecf0b 1678 transformBlock(mcuBlock);
XkLi 0:c546b51ecf0b 1679 }
XkLi 0:c546b51ecf0b 1680
XkLi 0:c546b51ecf0b 1681 return 0;
XkLi 0:c546b51ecf0b 1682 }
XkLi 0:c546b51ecf0b 1683 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 1684 unsigned char pjpeg_decode_mcu(void)
XkLi 0:c546b51ecf0b 1685 {
XkLi 0:c546b51ecf0b 1686 uint8 status;
XkLi 0:c546b51ecf0b 1687
XkLi 0:c546b51ecf0b 1688 if (!gNumMCUSRemaining)
XkLi 0:c546b51ecf0b 1689 return PJPG_NO_MORE_BLOCKS;
XkLi 0:c546b51ecf0b 1690
XkLi 0:c546b51ecf0b 1691 status = decodeNextMCU();
XkLi 0:c546b51ecf0b 1692 if (status)
XkLi 0:c546b51ecf0b 1693 return status;
XkLi 0:c546b51ecf0b 1694
XkLi 0:c546b51ecf0b 1695 gNumMCUSRemaining--;
XkLi 0:c546b51ecf0b 1696
XkLi 0:c546b51ecf0b 1697 return 0;
XkLi 0:c546b51ecf0b 1698 }
XkLi 0:c546b51ecf0b 1699 //------------------------------------------------------------------------------
XkLi 0:c546b51ecf0b 1700 unsigned char pjpeg_decode_init(pjpeg_image_info_t *pInfo, pjpeg_need_bytes_callback_t pNeed_bytes_callback, void *pCallback_data)
XkLi 0:c546b51ecf0b 1701 {
XkLi 0:c546b51ecf0b 1702 uint8 status;
XkLi 0:c546b51ecf0b 1703
XkLi 0:c546b51ecf0b 1704 g_pNeedBytesCallback = pNeed_bytes_callback;
XkLi 0:c546b51ecf0b 1705 g_pCallback_data = pCallback_data;
XkLi 0:c546b51ecf0b 1706
XkLi 0:c546b51ecf0b 1707 status = init();
XkLi 0:c546b51ecf0b 1708 if (status)
XkLi 0:c546b51ecf0b 1709 return status;
XkLi 0:c546b51ecf0b 1710
XkLi 0:c546b51ecf0b 1711 status = locateSOFMarker();
XkLi 0:c546b51ecf0b 1712 if (status)
XkLi 0:c546b51ecf0b 1713 return status;
XkLi 0:c546b51ecf0b 1714
XkLi 0:c546b51ecf0b 1715 status = initFrame();
XkLi 0:c546b51ecf0b 1716 if (status)
XkLi 0:c546b51ecf0b 1717 return status;
XkLi 0:c546b51ecf0b 1718
XkLi 0:c546b51ecf0b 1719 status = initScan();
XkLi 0:c546b51ecf0b 1720 if (status)
XkLi 0:c546b51ecf0b 1721 return status;
XkLi 0:c546b51ecf0b 1722
XkLi 0:c546b51ecf0b 1723 pInfo->m_width = gImageXSize;
XkLi 0:c546b51ecf0b 1724 pInfo->m_height = gImageYSize;
XkLi 0:c546b51ecf0b 1725 pInfo->m_comps = gCompsInFrame;
XkLi 0:c546b51ecf0b 1726 pInfo->m_scanType = gScanType;
XkLi 0:c546b51ecf0b 1727 pInfo->m_MCUSPerRow = gMaxMCUSPerRow;
XkLi 0:c546b51ecf0b 1728 pInfo->m_MCUSPerCol = gMaxMCUSPerCol;
XkLi 0:c546b51ecf0b 1729 pInfo->m_MCUWidth = gMaxMCUXSize;
XkLi 0:c546b51ecf0b 1730 pInfo->m_MCUHeight = gMaxMCUYSize;
XkLi 0:c546b51ecf0b 1731 pInfo->m_pMCUBufR = gMCUBufR;
XkLi 0:c546b51ecf0b 1732 pInfo->m_pMCUBufG = gMCUBufG;
XkLi 0:c546b51ecf0b 1733 pInfo->m_pMCUBufB = gMCUBufB;
XkLi 0:c546b51ecf0b 1734
XkLi 0:c546b51ecf0b 1735 return 0;
XkLi 0:c546b51ecf0b 1736 }