fadi ladhari
/
GPS_System_with_Google_Maps
hello_world
Fork of GPS_System_with_Google_Maps by
picojpeg/picojpeg.c@3:3c7906d60f89, 2012-12-13 (annotated)
- Committer:
- Ifrah
- Date:
- Thu Dec 13 23:59:40 2012 +0000
- Revision:
- 3:3c7906d60f89
Getting Google Maps based on the GPS coordinates
Who changed what in which revision?
User | Revision | Line number | New 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 | } |