Final

Dependencies:   DebounceIn NokiaLCD WiflyInterface mbed

Fork of Websocket_Wifly_HelloWorld by Samuel Mokrani

Committer:
Ifrah
Date:
Fri Dec 14 15:40:21 2012 +0000
Revision:
5:c4c66c630011
Parent:
3:3c7906d60f89
Final

Who changed what in which revision?

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