| Line No. | Rev | Author | Line |
|---|---|---|---|
| 1 | 32 | kaklik | #define __JPEGDECODER_C__ |
| 2 | /****************************************************************************** |
||
| 3 | |||
| 4 | * FileName: JpegDecoder.c |
||
| 5 | * Dependencies: Image decoding library; project requires File System library |
||
| 6 | * Processor: PIC24/dsPIC30/dsPIC33/PIC32MX |
||
| 7 | * Compiler: C30 v2.01/C32 v0.00.18 |
||
| 8 | * Company: Microchip Technology, Inc. |
||
| 9 | |||
| 10 | * Software License Agreement |
||
| 11 | * |
||
| 12 | * Copyright © 2008 Microchip Technology Inc. All rights reserved. |
||
| 13 | * Microchip licenses to you the right to use, modify, copy and distribute |
||
| 14 | * Software only when embedded on a Microchip microcontroller or digital |
||
| 15 | * signal controller, which is integrated into your product or third party |
||
| 16 | * product (pursuant to the sublicense terms in the accompanying license |
||
| 17 | * agreement). |
||
| 18 | * |
||
| 19 | * You should refer to the license agreement accompanying this Software |
||
| 20 | * for additional information regarding your rights and obligations. |
||
| 21 | * |
||
| 22 | * SOFTWARE AND DOCUMENTATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY |
||
| 23 | * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY |
||
| 24 | * OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR |
||
| 25 | * PURPOSE. IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR |
||
| 26 | * OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, |
||
| 27 | * BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT |
||
| 28 | * DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, |
||
| 29 | * INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, |
||
| 30 | * COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY |
||
| 31 | * CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), |
||
| 32 | * OR OTHER SIMILAR COSTS. |
||
| 33 | |||
| 34 | Author Date Comments |
||
| 35 | -------------------------------------------------------------------------------- |
||
| 36 | Pradeep Budagutta 03-Mar-2008 First release |
||
| 37 | *******************************************************************************/ |
||
| 38 | |||
| 39 | #include "Image Decoders\ImageDecoder.h" |
||
| 40 | |||
| 41 | #ifdef IMG_SUPPORT_JPEG |
||
| 42 | |||
| 43 | #define JPEG_SAMPLE_1x1 0 |
||
| 44 | #define JPEG_SAMPLE_1x2 1 |
||
| 45 | #define JPEG_SAMPLE_2x1 2 |
||
| 46 | #define JPEG_SAMPLE_2x2 3 |
||
| 47 | |||
| 48 | /*****************************/ |
||
| 49 | /**** FUNCTION PROTOTYPES ****/ |
||
| 50 | /*****************************/ |
||
| 51 | void jpeg_idct_islow (SHORT *inbuf, WORD *quantptr); |
||
| 52 | |||
| 53 | /*************************/ |
||
| 54 | /**** DATA STRUCTURES ****/ |
||
| 55 | /*************************/ |
||
| 56 | typedef struct _JPEGDECODER |
||
| 57 | { |
||
| 58 | IMG_FILE *pImageFile; /* Image file pointer */ |
||
| 59 | |||
| 60 | /*********** From APP0 ***********/ |
||
| 61 | BYTE blJFIF; /* JFIF marker found flag */ |
||
| 62 | BYTE bMajorRev; /* Should be 1 */ |
||
| 63 | BYTE bMinorRev; /* Should be 0-2 but is not a show stopper */ |
||
| 64 | /*------- The x/y densities and thumbnail data are ignored --------*/ |
||
| 65 | |||
| 66 | /*********** From SOF0 ***********/ |
||
| 67 | BYTE bDataBits; /* Data precision, can be 8(, 12 or 16) */ |
||
| 68 | WORD wWidth; /* Width in pixels */ |
||
| 69 | WORD wHeight; /* Height in pixels */ |
||
| 70 | BYTE bChannels; /* Number of channels e.g. YCbCr = 3 */ |
||
| 71 | BYTE abChannelType[MAX_CHANNELS]; |
||
| 72 | BYTE abChannelHSampFactor[MAX_CHANNELS]; |
||
| 73 | BYTE abChannelVSampFactor[MAX_CHANNELS]; |
||
| 74 | BYTE abChannelQuantTableMap[MAX_CHANNELS]; |
||
| 75 | |||
| 76 | /*********** From DQT ***********/ |
||
| 77 | BYTE blQuantUses16bits; /* If flag is set, it is an error as 16 bit is not supported */ |
||
| 78 | WORD awQuantTable[MAX_CHANNELS][64]; /* Supports only 8 & 16 bit resolutions */ |
||
| 79 | |||
| 80 | /*********** From DRI ***********/ |
||
| 81 | WORD wRestartInterval; /* The restart interval in blocks */ |
||
| 82 | |||
| 83 | /*********** From DHT ***********/ |
||
| 84 | BYTE bHuffTables; |
||
| 85 | BYTE abHuffAcSymLen[MAX_HUFF_TABLES][16]; /* Supports only 8 bit resolution */ |
||
| 86 | BYTE abHuffAcSymbol[MAX_HUFF_TABLES][256]; /* Maximum possible symbols are 256 */ |
||
| 87 | BYTE abHuffDcSymLen[MAX_HUFF_TABLES][16]; /* Supports only 8 bit resolution */ |
||
| 88 | BYTE abHuffDcSymbol[MAX_HUFF_TABLES][16]; /* Maximum possible symbols are 16 for DC :-) */ |
||
| 89 | /*********** For Huffman-Decoding ***********/ |
||
| 90 | WORD awHuffAcSymStart[MAX_HUFF_TABLES][16]; /* Starting symbol for each length */ |
||
| 91 | WORD awHuffDcSymStart[MAX_HUFF_TABLES][16]; /* Starting symbol for each length */ |
||
| 92 | |||
| 93 | /*********** From SOS ***********/ |
||
| 94 | BYTE abChannelHuffAcTableMap[MAX_CHANNELS]; |
||
| 95 | BYTE abChannelHuffDcTableMap[MAX_CHANNELS]; |
||
| 96 | |||
| 97 | BYTE bError; |
||
| 98 | |||
| 99 | /*********** Work memory ***********/ |
||
| 100 | WORD wWorkBits; |
||
| 101 | BYTE bBitsAvailable; |
||
| 102 | BYTE bBlocksInOnePass; |
||
| 103 | SHORT asOneBlock[MAX_BLOCKS][64]; /* Temporary storage for a 8x8 block */ |
||
| 104 | WORD wBlockNumber; |
||
| 105 | BYTE abChannelMap[MAX_BLOCKS]; |
||
| 106 | BYTE bSubSampleType; |
||
| 107 | SHORT asPrevDcValue[MAX_CHANNELS]; |
||
| 108 | BYTE *pbCurrentHuffSymLenTable; |
||
| 109 | BYTE *pbCurrentHuffSymbolTable; |
||
| 110 | WORD *pwCurrentHuffSymStartTable; |
||
| 111 | WORD *pwCurrentQuantTable; |
||
| 112 | BYTE abDataBuffer[MAX_DATA_BUF_LEN]; |
||
| 113 | WORD wBufferLen; |
||
| 114 | WORD wBufferIndex; |
||
| 115 | BYTE bFirstBit; |
||
| 116 | |||
| 117 | WORD wPrevX; |
||
| 118 | WORD wPrevY; |
||
| 119 | } JPEGDECODER; |
||
| 120 | |||
| 121 | /**************************/ |
||
| 122 | /**** CONSTANT TABLES ****/ |
||
| 123 | /**************************/ |
||
| 124 | static const BYTE abZigzag[64] = |
||
| 125 | { |
||
| 126 | 0, 1, 8, 16, 9, 2, 3, 10, |
||
| 127 | 17, 24, 32, 25, 18, 11, 4, 5, |
||
| 128 | 12, 19, 26, 33, 40, 48, 41, 34, |
||
| 129 | 27, 20, 13, 6, 7, 14, 21, 28, |
||
| 130 | 35, 42, 49, 56, 57, 50, 43, 36, |
||
| 131 | 29, 22, 15, 23, 30, 37, 44, 51, |
||
| 132 | 58, 59, 52, 45, 38, 31, 39, 46, |
||
| 133 | 53, 60, 61, 54, 47, 55, 62, 63 |
||
| 134 | }; |
||
| 135 | |||
| 136 | /**************************/ |
||
| 137 | /******* FUNCTIONS *******/ |
||
| 138 | /**************************/ |
||
| 139 | |||
| 140 | /******************************************************************************* |
||
| 141 | Function: void JPEG_vResetDecoder(JPEGDECODER *pJpegDecoder) |
||
| 142 | |||
| 143 | Precondition: None |
||
| 144 | |||
| 145 | Overview: This function resets the variables so that new jpeg image can be |
||
| 146 | decoded |
||
| 147 | |||
| 148 | Input: JPEGDECODER |
||
| 149 | |||
| 150 | Output: None |
||
| 151 | *******************************************************************************/ |
||
| 152 | static void JPEG_vResetDecoder(JPEGDECODER *pJpegDecoder) |
||
| 153 | { |
||
| 154 | WORD wIndex; |
||
| 155 | BYTE *pbptr = (BYTE*)pJpegDecoder; |
||
| 156 | for(wIndex = 0; wIndex < sizeof(JPEGDECODER); wIndex++) |
||
| 157 | { |
||
| 158 | pbptr[wIndex] = 0; |
||
| 159 | } |
||
| 160 | } |
||
| 161 | |||
| 162 | /******************************************************************************* |
||
| 163 | Function: WORD JPEG_wReadWord(IMG_FILE *pfile) |
||
| 164 | |||
| 165 | Precondition: None |
||
| 166 | |||
| 167 | Overview: This function reads and returns a single word obtained as |
||
| 168 | Higher byte first followed by lower byte |
||
| 169 | |||
| 170 | Input: Image file |
||
| 171 | |||
| 172 | Output: One word |
||
| 173 | *******************************************************************************/ |
||
| 174 | static WORD JPEG_wReadWord(IMG_FILE *pfile) |
||
| 175 | { |
||
| 176 | BYTE btemp; |
||
| 177 | WORD wData; |
||
| 178 | |||
| 179 | IMG_FREAD(&btemp, sizeof(btemp), 1, pfile); |
||
| 180 | wData = btemp; |
||
| 181 | IMG_FREAD(&btemp, sizeof(btemp), 1, pfile); |
||
| 182 | wData = (wData << 8) | btemp; |
||
| 183 | |||
| 184 | return wData; |
||
| 185 | } |
||
| 186 | |||
| 187 | /******************************************************************************* |
||
| 188 | Function: BYTE JPEG_bReadByte(IMG_FILE *pfile) |
||
| 189 | |||
| 190 | Precondition: None |
||
| 191 | |||
| 192 | Overview: This function reads and returns a single byte from the file |
||
| 193 | |||
| 194 | Input: Image file |
||
| 195 | |||
| 196 | Output: One byte |
||
| 197 | *******************************************************************************/ |
||
| 198 | static BYTE JPEG_bReadByte(IMG_FILE *pfile) |
||
| 199 | { |
||
| 200 | BYTE bData; |
||
| 201 | |||
| 202 | IMG_FREAD(&bData, sizeof(bData), 1, pfile); |
||
| 203 | |||
| 204 | return bData; |
||
| 205 | } |
||
| 206 | |||
| 207 | /******************************************************************************* |
||
| 208 | Function: BYTE JPEG_bReadHeader(JPEGDECODER *pJpegDecoder) |
||
| 209 | |||
| 210 | Precondition: None |
||
| 211 | |||
| 212 | Overview: This function reads the JPEG file header and |
||
| 213 | fills the data structure |
||
| 214 | |||
| 215 | Input: JPEGDECODER |
||
| 216 | |||
| 217 | Output: Error code - '0' means no error |
||
| 218 | *******************************************************************************/ |
||
| 219 | static BYTE JPEG_bReadHeader(JPEGDECODER *pJpegDecoder) |
||
| 220 | { |
||
| 221 | BYTE blSOSOver = FALSE; |
||
| 222 | while(!IMG_FEOF(pJpegDecoder->pImageFile)) |
||
| 223 | { |
||
| 224 | BYTE btemp, bcount, bsection; |
||
| 225 | WORD wSegLen, wOffset; |
||
| 226 | |||
| 227 | if(blSOSOver == TRUE) |
||
| 228 | { |
||
| 229 | if(pJpegDecoder->bChannels == 1) |
||
| 230 | { |
||
| 231 | pJpegDecoder->bBlocksInOnePass = 1; |
||
| 232 | pJpegDecoder->bSubSampleType = JPEG_SAMPLE_1x1; |
||
| 233 | } |
||
| 234 | else if(pJpegDecoder->bChannels == 3) |
||
| 235 | { |
||
| 236 | if((pJpegDecoder->abChannelHSampFactor[0] == 1 && pJpegDecoder->abChannelVSampFactor[0] == 1) && |
||
| 237 | (pJpegDecoder->abChannelHSampFactor[1] == 1 && pJpegDecoder->abChannelVSampFactor[1] == 1) && |
||
| 238 | (pJpegDecoder->abChannelHSampFactor[2] == 1 && pJpegDecoder->abChannelVSampFactor[2] == 1)) |
||
| 239 | { |
||
| 240 | pJpegDecoder->bBlocksInOnePass = 3; |
||
| 241 | pJpegDecoder->abChannelMap[0] = 0; |
||
| 242 | pJpegDecoder->abChannelMap[1] = 1; |
||
| 243 | pJpegDecoder->abChannelMap[2] = 2; |
||
| 244 | pJpegDecoder->bSubSampleType = JPEG_SAMPLE_1x1; |
||
| 245 | } |
||
| 246 | else if((pJpegDecoder->abChannelHSampFactor[0] == 1 && pJpegDecoder->abChannelVSampFactor[0] == 2) && |
||
| 247 | (pJpegDecoder->abChannelHSampFactor[1] == 1 && pJpegDecoder->abChannelVSampFactor[1] == 1) && |
||
| 248 | (pJpegDecoder->abChannelHSampFactor[2] == 1 && pJpegDecoder->abChannelVSampFactor[2] == 1)) |
||
| 249 | { |
||
| 250 | pJpegDecoder->bBlocksInOnePass = 4; |
||
| 251 | pJpegDecoder->abChannelMap[0] = 0; |
||
| 252 | pJpegDecoder->abChannelMap[1] = 0; |
||
| 253 | pJpegDecoder->abChannelMap[2] = 1; |
||
| 254 | pJpegDecoder->abChannelMap[3] = 2; |
||
| 255 | pJpegDecoder->bSubSampleType = JPEG_SAMPLE_1x2; |
||
| 256 | } |
||
| 257 | else if((pJpegDecoder->abChannelHSampFactor[0] == 2 && pJpegDecoder->abChannelVSampFactor[0] == 1) && |
||
| 258 | (pJpegDecoder->abChannelHSampFactor[1] == 1 && pJpegDecoder->abChannelVSampFactor[1] == 1) && |
||
| 259 | (pJpegDecoder->abChannelHSampFactor[2] == 1 && pJpegDecoder->abChannelVSampFactor[2] == 1)) |
||
| 260 | { |
||
| 261 | pJpegDecoder->bBlocksInOnePass = 4; |
||
| 262 | pJpegDecoder->abChannelMap[0] = 0; |
||
| 263 | pJpegDecoder->abChannelMap[1] = 0; |
||
| 264 | pJpegDecoder->abChannelMap[2] = 1; |
||
| 265 | pJpegDecoder->abChannelMap[3] = 2; |
||
| 266 | pJpegDecoder->bSubSampleType = JPEG_SAMPLE_2x1; |
||
| 267 | } |
||
| 268 | else if((pJpegDecoder->abChannelHSampFactor[0] == 2 && pJpegDecoder->abChannelVSampFactor[0] == 2) && |
||
| 269 | (pJpegDecoder->abChannelHSampFactor[1] == 1 && pJpegDecoder->abChannelVSampFactor[1] == 1) && |
||
| 270 | (pJpegDecoder->abChannelHSampFactor[2] == 1 && pJpegDecoder->abChannelVSampFactor[2] == 1)) |
||
| 271 | { |
||
| 272 | pJpegDecoder->bBlocksInOnePass = 6; |
||
| 273 | pJpegDecoder->abChannelMap[0] = 0; |
||
| 274 | pJpegDecoder->abChannelMap[1] = 0; |
||
| 275 | pJpegDecoder->abChannelMap[2] = 0; |
||
| 276 | pJpegDecoder->abChannelMap[3] = 0; |
||
| 277 | pJpegDecoder->abChannelMap[4] = 1; |
||
| 278 | pJpegDecoder->abChannelMap[5] = 2; |
||
| 279 | pJpegDecoder->bSubSampleType = JPEG_SAMPLE_2x2; |
||
| 280 | } |
||
| 281 | else |
||
| 282 | { |
||
| 283 | JPEG_SendError(100); |
||
| 284 | } |
||
| 285 | } |
||
| 286 | return 0; |
||
| 287 | } |
||
| 288 | |||
| 289 | IMG_FREAD(&btemp, sizeof(btemp), 1, pJpegDecoder->pImageFile); |
||
| 290 | |||
| 291 | if(btemp != 0xFF) |
||
| 292 | { |
||
| 293 | continue; |
||
| 294 | } |
||
| 295 | |||
| 296 | IMG_FREAD(&bsection, sizeof(bsection), 1, pJpegDecoder->pImageFile); |
||
| 297 | switch(bsection) |
||
| 298 | { |
||
| 299 | case SOI: |
||
| 300 | case TEM: |
||
| 301 | case EOI: |
||
| 302 | case RST0: |
||
| 303 | case RST1: |
||
| 304 | case RST2: |
||
| 305 | case RST3: |
||
| 306 | case RST4: |
||
| 307 | case RST5: |
||
| 308 | case RST6: |
||
| 309 | case RST7: break; |
||
| 310 | |||
| 311 | case SOF0: /* Start of frame */ |
||
| 312 | wSegLen = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 313 | if(wSegLen <= 8) |
||
| 314 | { |
||
| 315 | JPEG_SendError(100); |
||
| 316 | break; |
||
| 317 | } |
||
| 318 | pJpegDecoder->bDataBits = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 319 | pJpegDecoder->wHeight = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 320 | pJpegDecoder->wWidth = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 321 | pJpegDecoder->bChannels = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 322 | if(wSegLen < 8 + (pJpegDecoder->bChannels * 3)) |
||
| 323 | { |
||
| 324 | JPEG_SendError(100); |
||
| 325 | break; |
||
| 326 | } |
||
| 327 | for(bcount = 0; bcount < pJpegDecoder->bChannels; bcount++) |
||
| 328 | { |
||
| 329 | pJpegDecoder->abChannelType[bcount] = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 330 | btemp = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 331 | pJpegDecoder->abChannelHSampFactor[bcount] = btemp >> 4; |
||
| 332 | pJpegDecoder->abChannelVSampFactor[bcount] = btemp & 0x0F; |
||
| 333 | pJpegDecoder->abChannelQuantTableMap[bcount] = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 334 | } |
||
| 335 | break; |
||
| 336 | |||
| 337 | case APP0: /* Start of Application */ |
||
| 338 | wSegLen = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 339 | if(wSegLen < 16) |
||
| 340 | { |
||
| 341 | JPEG_SendError(100); |
||
| 342 | break; |
||
| 343 | } |
||
| 344 | else |
||
| 345 | { |
||
| 346 | unsigned char buf[5]; |
||
| 347 | IMG_FREAD(buf, sizeof(buf[0]), 5, pJpegDecoder->pImageFile); |
||
| 348 | if(buf[0] == 'J' && buf[1] == 'F' && buf[2] == 'I' && buf[3] == 'F' && buf[4] == '\0') |
||
| 349 | { |
||
| 350 | pJpegDecoder->blJFIF = TRUE; |
||
| 351 | } |
||
| 352 | } |
||
| 353 | pJpegDecoder->bMajorRev = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 354 | pJpegDecoder->bMinorRev = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 355 | if(pJpegDecoder->bMajorRev != 1) |
||
| 356 | { |
||
| 357 | JPEG_SendError(100); |
||
| 358 | break; |
||
| 359 | } |
||
| 360 | /* Ignore other bytes in this segment */ |
||
| 361 | break; |
||
| 362 | |||
| 363 | case DRI: /* Start of Quantization table */ |
||
| 364 | wSegLen = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 365 | if(wSegLen == 4) |
||
| 366 | { |
||
| 367 | pJpegDecoder->wRestartInterval = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 368 | } |
||
| 369 | break; |
||
| 370 | |||
| 371 | case DQT: /* Start of Quantization table */ |
||
| 372 | wSegLen = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 373 | if(wSegLen < 67) |
||
| 374 | { |
||
| 375 | JPEG_SendError(100); |
||
| 376 | break; |
||
| 377 | } |
||
| 378 | |||
| 379 | do |
||
| 380 | { |
||
| 381 | BYTE bQTableIndex, bCounter; |
||
| 382 | |||
| 383 | btemp = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 384 | bQTableIndex = btemp & 0x0F; |
||
| 385 | pJpegDecoder->blQuantUses16bits |= (btemp >> 4); |
||
| 386 | |||
| 387 | for(bCounter = 0; bCounter < 64; bCounter++) |
||
| 388 | { |
||
| 389 | BYTE bData1, bData2 = 0; |
||
| 390 | if(pJpegDecoder->blQuantUses16bits == 0) |
||
| 391 | { |
||
| 392 | IMG_FREAD(&bData1, sizeof(BYTE), 1, pJpegDecoder->pImageFile); |
||
| 393 | pJpegDecoder->awQuantTable[bQTableIndex][abZigzag[bCounter]] = bData1; |
||
| 394 | } |
||
| 395 | else |
||
| 396 | { |
||
| 397 | IMG_FREAD(&bData1, sizeof(BYTE), 1, pJpegDecoder->pImageFile); |
||
| 398 | IMG_FREAD(&bData2, sizeof(BYTE), 1, pJpegDecoder->pImageFile); |
||
| 399 | pJpegDecoder->awQuantTable[bQTableIndex][abZigzag[bCounter]] = (((WORD)bData1) << 8) + (WORD)bData2; |
||
| 400 | } |
||
| 401 | } |
||
| 402 | wSegLen -= (pJpegDecoder->blQuantUses16bits == 0)? 65: 129; /* Table length + information byte */ |
||
| 403 | } while(wSegLen >= 67); |
||
| 404 | break; |
||
| 405 | |||
| 406 | case DHT: /* Start of Huffmann table */ |
||
| 407 | wSegLen = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 408 | if(wSegLen < 19) |
||
| 409 | { |
||
| 410 | JPEG_SendError(100); |
||
| 411 | break; |
||
| 412 | } |
||
| 413 | |||
| 414 | do |
||
| 415 | { |
||
| 416 | BYTE bHTableIndex, bCounter; |
||
| 417 | WORD wNumOfSymbols; |
||
| 418 | BYTE blIsAc; |
||
| 419 | BYTE *pbLenTable, *pbSymTable; |
||
| 420 | |||
| 421 | btemp = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 422 | bHTableIndex = btemp & 0x0F; |
||
| 423 | blIsAc = (btemp >> 4) & 0x01; |
||
| 424 | |||
| 425 | if(blIsAc == 0) |
||
| 426 | { |
||
| 427 | pbLenTable = (BYTE*)&pJpegDecoder->abHuffDcSymLen[bHTableIndex][0]; |
||
| 428 | pbSymTable = (BYTE*)&pJpegDecoder->abHuffDcSymbol[bHTableIndex][0]; |
||
| 429 | } |
||
| 430 | else |
||
| 431 | { |
||
| 432 | pbLenTable = (BYTE*)&pJpegDecoder->abHuffAcSymLen[bHTableIndex][0]; |
||
| 433 | pbSymTable = (BYTE*)&pJpegDecoder->abHuffAcSymbol[bHTableIndex][0]; |
||
| 434 | } |
||
| 435 | |||
| 436 | IMG_FREAD(pbLenTable, sizeof(BYTE), 16, pJpegDecoder->pImageFile); |
||
| 437 | |||
| 438 | for(bCounter = 0, wNumOfSymbols = 0; bCounter < 16; bCounter++) |
||
| 439 | { |
||
| 440 | wNumOfSymbols += pbLenTable[bCounter]; |
||
| 441 | } |
||
| 442 | |||
| 443 | wSegLen -= 17; /* This table length + information byte */ |
||
| 444 | |||
| 445 | if(wSegLen < wNumOfSymbols || (blIsAc == 1 && wNumOfSymbols > 256) || (blIsAc == 0 && wNumOfSymbols > 16)) |
||
| 446 | { |
||
| 447 | JPEG_SendError(100); |
||
| 448 | break; |
||
| 449 | } |
||
| 450 | |||
| 451 | IMG_FREAD(pbSymTable, sizeof(BYTE), wNumOfSymbols, pJpegDecoder->pImageFile); |
||
| 452 | wSegLen -= wNumOfSymbols; /* This table length + information byte */ |
||
| 453 | pJpegDecoder->bHuffTables++; |
||
| 454 | } while(wSegLen >= 19); |
||
| 455 | break; |
||
| 456 | |||
| 457 | case SOS: /* Start of Scan parameters */ |
||
| 458 | wSegLen = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 459 | if(wSegLen < 3) |
||
| 460 | { |
||
| 461 | JPEG_SendError(100); |
||
| 462 | break; |
||
| 463 | } |
||
| 464 | |||
| 465 | btemp = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 466 | wOffset = wSegLen - (3 + (btemp * 2)); |
||
| 467 | |||
| 468 | if(pJpegDecoder->bChannels != btemp || wSegLen < 3 + (btemp * 2)) |
||
| 469 | { |
||
| 470 | JPEG_SendError(100); |
||
| 471 | break; |
||
| 472 | } |
||
| 473 | else |
||
| 474 | { |
||
| 475 | BYTE bCounter, bChannelId = 0xFF; |
||
| 476 | |||
| 477 | for(bCounter = 0; bCounter < pJpegDecoder->bChannels; bCounter++) |
||
| 478 | { |
||
| 479 | BYTE bindex; |
||
| 480 | |||
| 481 | btemp = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 482 | for(bindex = 0; bindex < MAX_CHANNELS; bindex++) |
||
| 483 | { |
||
| 484 | if(pJpegDecoder->abChannelType[bindex] == btemp) |
||
| 485 | { |
||
| 486 | bChannelId = bindex; |
||
| 487 | break; |
||
| 488 | } |
||
| 489 | } |
||
| 490 | |||
| 491 | if(bChannelId < MAX_CHANNELS) |
||
| 492 | { |
||
| 493 | btemp = JPEG_bReadByte(pJpegDecoder->pImageFile); |
||
| 494 | pJpegDecoder->abChannelHuffAcTableMap[bChannelId] = btemp & 0x0F; |
||
| 495 | pJpegDecoder->abChannelHuffDcTableMap[bChannelId] = btemp >> 4; |
||
| 496 | } |
||
| 497 | } |
||
| 498 | IMG_FSEEK(pJpegDecoder->pImageFile, wOffset, 1); |
||
| 499 | } |
||
| 500 | blSOSOver = TRUE; |
||
| 501 | break; |
||
| 502 | |||
| 503 | default: /* Any other segment with length */ |
||
| 504 | wSegLen = JPEG_wReadWord(pJpegDecoder->pImageFile); |
||
| 505 | if(wSegLen < 2) |
||
| 506 | { |
||
| 507 | JPEG_SendError(100); |
||
| 508 | break; |
||
| 509 | } |
||
| 510 | IMG_FSEEK(pJpegDecoder->pImageFile, wSegLen - 2, 1); |
||
| 511 | } |
||
| 512 | } |
||
| 513 | return 0; |
||
| 514 | } |
||
| 515 | |||
| 516 | /******************************************************************************* |
||
| 517 | Function: BYTE JPEG_bGenerateHuffmanTables(JPEGDECODER *pJpegDecoder) |
||
| 518 | |||
| 519 | Precondition: None |
||
| 520 | |||
| 521 | Overview: This function generated the table required for Huffman decoding |
||
| 522 | from the data read from the header |
||
| 523 | |||
| 524 | Input: JPEGDECODER |
||
| 525 | |||
| 526 | Output: Error code - '0' means no error |
||
| 527 | *******************************************************************************/ |
||
| 528 | static BYTE JPEG_bGenerateHuffmanTables(JPEGDECODER *pJpegDecoder) |
||
| 529 | { |
||
| 530 | BYTE bLength, bTable; |
||
| 531 | |||
| 532 | for(bTable = 0; bTable < pJpegDecoder->bHuffTables / 2; bTable++) |
||
| 533 | { |
||
| 534 | pJpegDecoder->awHuffAcSymStart[bTable][0] = 0; |
||
| 535 | pJpegDecoder->awHuffDcSymStart[bTable][0] = 0; |
||
| 536 | |||
| 537 | for(bLength = 1; bLength < 16; bLength++) |
||
| 538 | { |
||
| 539 | pJpegDecoder->awHuffAcSymStart[bTable][bLength] = (pJpegDecoder->awHuffAcSymStart[bTable][bLength - 1] + pJpegDecoder->abHuffAcSymLen[bTable][bLength - 1]) << 1; |
||
| 540 | pJpegDecoder->awHuffDcSymStart[bTable][bLength] = (pJpegDecoder->awHuffDcSymStart[bTable][bLength - 1] + pJpegDecoder->abHuffDcSymLen[bTable][bLength - 1]) << 1; |
||
| 541 | } |
||
| 542 | } |
||
| 543 | return 0; |
||
| 544 | } |
||
| 545 | |||
| 546 | /******************************************************************************* |
||
| 547 | Function: BYTE JPEG_bGet1Bit(JPEGDECODER *pJpegDecoder) |
||
| 548 | |||
| 549 | Precondition: None |
||
| 550 | |||
| 551 | Overview: This function returns 1 bit as the lsb of the returned byte. |
||
| 552 | It automatically fills the buffer if it becomes empty. |
||
| 553 | It also converts 0xFF00 into 0. |
||
| 554 | |||
| 555 | Input: JPEGDECODER |
||
| 556 | |||
| 557 | Output: One bit |
||
| 558 | *******************************************************************************/ |
||
| 559 | static BYTE JPEG_bGet1Bit(JPEGDECODER *pJpegDecoder) |
||
| 560 | { |
||
| 561 | BYTE bBit = 0; |
||
| 562 | |||
| 563 | if(pJpegDecoder->wBufferIndex >= pJpegDecoder->wBufferLen) |
||
| 564 | { |
||
| 565 | pJpegDecoder->wBufferLen = IMG_FREAD(&pJpegDecoder->abDataBuffer[0], sizeof(BYTE), MAX_DATA_BUF_LEN, pJpegDecoder->pImageFile); |
||
| 566 | while(pJpegDecoder->abDataBuffer[pJpegDecoder->wBufferLen - 1] == 0xFF) |
||
| 567 | { |
||
| 568 | pJpegDecoder->wBufferLen--; |
||
| 569 | IMG_FSEEK(pJpegDecoder->pImageFile, -1, 1); |
||
| 570 | } |
||
| 571 | pJpegDecoder->wBufferIndex = 0; |
||
| 572 | } |
||
| 573 | |||
| 574 | while(pJpegDecoder->bBitsAvailable == 0) /* Be very careful to touch this part of code! You must know exactly what you are doing */ |
||
| 575 | { |
||
| 576 | pJpegDecoder->bBitsAvailable = 16; |
||
| 577 | pJpegDecoder->wWorkBits = pJpegDecoder->abDataBuffer[pJpegDecoder->wBufferIndex++]; |
||
| 578 | pJpegDecoder->wWorkBits = (pJpegDecoder->wWorkBits << 8) + pJpegDecoder->abDataBuffer[pJpegDecoder->wBufferIndex++]; |
||
| 579 | if(pJpegDecoder->wBufferIndex > pJpegDecoder->wBufferLen) /* wBufferIndex need not be even because of the below condition */ |
||
| 580 | { |
||
| 581 | pJpegDecoder->bBitsAvailable = 8; |
||
| 582 | } |
||
| 583 | else if((pJpegDecoder->wWorkBits & 0x00FF) == 0x00FF) |
||
| 584 | { |
||
| 585 | pJpegDecoder->bBitsAvailable = 8; |
||
| 586 | pJpegDecoder->wBufferIndex--; |
||
| 587 | } |
||
| 588 | else if(pJpegDecoder->wWorkBits >= 0xFF00) |
||
| 589 | { |
||
| 590 | if(pJpegDecoder->wWorkBits == 0xFF00) |
||
| 591 | { |
||
| 592 | pJpegDecoder->bBitsAvailable = 8; |
||
| 593 | } |
||
| 594 | } |
||
| 595 | } |
||
| 596 | |||
| 597 | bBit = (pJpegDecoder->wWorkBits & 0x8000)? 0x01: 0; |
||
| 598 | |||
| 599 | pJpegDecoder->wWorkBits <<= 1; |
||
| 600 | pJpegDecoder->bBitsAvailable--; |
||
| 601 | |||
| 602 | return bBit; |
||
| 603 | } |
||
| 604 | |||
| 605 | /******************************************************************************* |
||
| 606 | Function: WORD JPEG_wGetBits(JPEGDECODER *pJpegDecoder, BYTE bLen) |
||
| 607 | |||
| 608 | Precondition: None |
||
| 609 | |||
| 610 | Overview: This function returns bLen number of bits as the lsb of the |
||
| 611 | returned word and it automatically fills the buffer |
||
| 612 | if it becomes empty. |
||
| 613 | |||
| 614 | Input: JPEGDECODER, Number of bits |
||
| 615 | |||
| 616 | Output: Requested number of bits |
||
| 617 | *******************************************************************************/ |
||
| 618 | static WORD JPEG_wGetBits(JPEGDECODER *pJpegDecoder, BYTE bLen) |
||
| 619 | { |
||
| 620 | WORD wVal = 0; |
||
| 621 | |||
| 622 | wVal = pJpegDecoder->bFirstBit = JPEG_bGet1Bit(pJpegDecoder); |
||
| 623 | bLen--; |
||
| 624 | |||
| 625 | while(bLen) |
||
| 626 | { |
||
| 627 | wVal = (wVal << 1) + JPEG_bGet1Bit(pJpegDecoder); |
||
| 628 | bLen--; |
||
| 629 | } |
||
| 630 | |||
| 631 | return wVal; |
||
| 632 | } |
||
| 633 | |||
| 634 | /******************************************************************************* |
||
| 635 | Function: WORD JPEG_wGetRestartWord(JPEGDECODER *pJpegDecoder) |
||
| 636 | |||
| 637 | Precondition: File pointer must point to the restart word |
||
| 638 | |||
| 639 | Overview: Returns the restart word |
||
| 640 | |||
| 641 | Input: JPEGDECODER |
||
| 642 | |||
| 643 | Output: Restart word |
||
| 644 | *******************************************************************************/ |
||
| 645 | static WORD JPEG_wGetRestartWord(JPEGDECODER *pJpegDecoder) |
||
| 646 | { |
||
| 647 | WORD wRestartWord; |
||
| 648 | while((pJpegDecoder->bBitsAvailable & 0x07) != 0) /* This is to clearoff wnwanted bits to go to fresh byte */ |
||
| 649 | { |
||
| 650 | JPEG_bGet1Bit(pJpegDecoder); |
||
| 651 | } |
||
| 652 | wRestartWord = JPEG_wGetBits(pJpegDecoder, 16); |
||
| 653 | return(wRestartWord); |
||
| 654 | } |
||
| 655 | |||
| 656 | /******************************************************************************* |
||
| 657 | Function: SHORT JPEG_sGetBitsValue(JPEGDECODER *pJpegDecoder, BYTE bLen) |
||
| 658 | |||
| 659 | Precondition: None |
||
| 660 | |||
| 661 | Overview: Returns the signed value of the bLen bits of data |
||
| 662 | |||
| 663 | Input: JPEGDECODER, Number of bits |
||
| 664 | |||
| 665 | Output: Signed number |
||
| 666 | *******************************************************************************/ |
||
| 667 | static SHORT JPEG_sGetBitsValue(JPEGDECODER *pJpegDecoder, BYTE bLen) |
||
| 668 | { |
||
| 669 | WORD wVal = 0; |
||
| 670 | |||
| 671 | if(bLen != 0) |
||
| 672 | { |
||
| 673 | wVal = JPEG_wGetBits(pJpegDecoder, bLen); |
||
| 674 | if(pJpegDecoder->bFirstBit == 0) |
||
| 675 | { |
||
| 676 | wVal = ~(wVal | (0xFFFF << bLen)); |
||
| 677 | return ((SHORT)wVal * -1); |
||
| 678 | } |
||
| 679 | } |
||
| 680 | return (SHORT)wVal; |
||
| 681 | } |
||
| 682 | |||
| 683 | /******************************************************************************* |
||
| 684 | Function: BYTE JPEG_bGetNextHuffByte(JPEGDECODER *pJpegDecoder) |
||
| 685 | |||
| 686 | Precondition: File pointer must point to the Huffman data |
||
| 687 | |||
| 688 | Overview: Returns the Huffman decoded data |
||
| 689 | |||
| 690 | Input: JPEGDECODER |
||
| 691 | |||
| 692 | Output: Huffman decoded data |
||
| 693 | *******************************************************************************/ |
||
| 694 | static BYTE JPEG_bGetNextHuffByte(JPEGDECODER *pJpegDecoder) |
||
| 695 | { |
||
| 696 | BYTE bBits, bSymbol = 0; |
||
| 697 | WORD wBitPattern = 0, wSymbolOffset = 0; |
||
| 698 | |||
| 699 | for(bBits = 0; bBits < 16; bBits++) |
||
| 700 | { |
||
| 701 | BYTE bSymbols; |
||
| 702 | WORD wDiff; |
||
| 703 | |||
| 704 | wBitPattern = (wBitPattern << 1) + JPEG_bGet1Bit(pJpegDecoder); |
||
| 705 | bSymbols = pJpegDecoder->pbCurrentHuffSymLenTable[bBits]; |
||
| 706 | if(bSymbols == 0) |
||
| 707 | { |
||
| 708 | continue; |
||
| 709 | } |
||
| 710 | |||
| 711 | wDiff = wBitPattern - pJpegDecoder->pwCurrentHuffSymStartTable[bBits]; |
||
| 712 | if(wDiff < bSymbols) |
||
| 713 | { |
||
| 714 | bSymbol = pJpegDecoder->pbCurrentHuffSymbolTable[wSymbolOffset + wDiff]; |
||
| 715 | break; |
||
| 716 | } |
||
| 717 | wSymbolOffset += bSymbols; |
||
| 718 | } |
||
| 719 | return bSymbol; |
||
| 720 | } |
||
| 721 | |||
| 722 | #define range_limit(x) (x<0)?0:(x>0xFF)?0xFF:x |
||
| 723 | /******************************************************************************* |
||
| 724 | Function: BYTE JPEG_bDecodeOneBlock(JPEGDECODER *pJpegDecoder) |
||
| 725 | |||
| 726 | Precondition: File pointer must point to a new block of data |
||
| 727 | |||
| 728 | Overview: Decodes the 8x8 pixel values of all the channels |
||
| 729 | (A multiple of 8x8 block if subsampling is used) |
||
| 730 | |||
| 731 | Input: JPEGDECODER |
||
| 732 | |||
| 733 | Output: Error code - '0' means no error |
||
| 734 | *******************************************************************************/ |
||
| 735 | static BYTE JPEG_bDecodeOneBlock(JPEGDECODER *pJpegDecoder) |
||
| 736 | { |
||
| 737 | BYTE bBlock, bCounter; |
||
| 738 | |||
| 739 | IMG_vLoopCallback(); |
||
| 740 | for(bBlock = 0; bBlock < pJpegDecoder->bBlocksInOnePass; bBlock++) |
||
| 741 | { |
||
| 742 | BYTE bByteCount, bHuffbyte; |
||
| 743 | |||
| 744 | if((pJpegDecoder->wRestartInterval > 0) && (pJpegDecoder->wBlockNumber == pJpegDecoder->wRestartInterval * pJpegDecoder->bBlocksInOnePass)) |
||
| 745 | { |
||
| 746 | WORD wRestartWord = JPEG_wGetRestartWord(pJpegDecoder); |
||
| 747 | if(wRestartWord < 0xFFD0 || wRestartWord > 0xFFD7) |
||
| 748 | { |
||
| 749 | JPEG_SendError(100); |
||
| 750 | } |
||
| 751 | for(bCounter = 0; bCounter < MAX_CHANNELS; bCounter++) |
||
| 752 | { |
||
| 753 | pJpegDecoder->asPrevDcValue[bCounter] = 0; |
||
| 754 | } |
||
| 755 | pJpegDecoder->wBlockNumber = 0; |
||
| 756 | } |
||
| 757 | |||
| 758 | for(bCounter = 0; bCounter < 64; bCounter++) |
||
| 759 | { |
||
| 760 | pJpegDecoder->asOneBlock[bBlock][bCounter] = 0; |
||
| 761 | } |
||
| 762 | |||
| 763 | pJpegDecoder->pwCurrentQuantTable = &pJpegDecoder->awQuantTable[pJpegDecoder->abChannelQuantTableMap[pJpegDecoder->abChannelMap[bBlock]]][0]; |
||
| 764 | |||
| 765 | /* Decode DC value */ |
||
| 766 | bByteCount = 0; |
||
| 767 | pJpegDecoder->pbCurrentHuffSymLenTable = &pJpegDecoder->abHuffDcSymLen[pJpegDecoder->abChannelHuffDcTableMap[pJpegDecoder->abChannelMap[bBlock]]][0]; |
||
| 768 | pJpegDecoder->pbCurrentHuffSymbolTable = &pJpegDecoder->abHuffDcSymbol[pJpegDecoder->abChannelHuffDcTableMap[pJpegDecoder->abChannelMap[bBlock]]][0]; |
||
| 769 | pJpegDecoder->pwCurrentHuffSymStartTable = &pJpegDecoder->awHuffDcSymStart[pJpegDecoder->abChannelHuffDcTableMap[pJpegDecoder->abChannelMap[bBlock]]][0]; |
||
| 770 | bHuffbyte = JPEG_bGetNextHuffByte(pJpegDecoder); |
||
| 771 | pJpegDecoder->asOneBlock[bBlock][0] = JPEG_sGetBitsValue(pJpegDecoder, bHuffbyte & 0x0F) + pJpegDecoder->asPrevDcValue[pJpegDecoder->abChannelMap[bBlock]]; |
||
| 772 | pJpegDecoder->asPrevDcValue[pJpegDecoder->abChannelMap[bBlock]] = pJpegDecoder->asOneBlock[bBlock][0]; |
||
| 773 | |||
| 774 | /* Decode AC value */ |
||
| 775 | bByteCount = 1; |
||
| 776 | pJpegDecoder->pbCurrentHuffSymLenTable = &pJpegDecoder->abHuffAcSymLen[pJpegDecoder->abChannelHuffAcTableMap[pJpegDecoder->abChannelMap[bBlock]]][0]; |
||
| 777 | pJpegDecoder->pbCurrentHuffSymbolTable = &pJpegDecoder->abHuffAcSymbol[pJpegDecoder->abChannelHuffAcTableMap[pJpegDecoder->abChannelMap[bBlock]]][0]; |
||
| 778 | pJpegDecoder->pwCurrentHuffSymStartTable = &pJpegDecoder->awHuffAcSymStart[pJpegDecoder->abChannelHuffAcTableMap[pJpegDecoder->abChannelMap[bBlock]]][0]; |
||
| 779 | while(bByteCount < 64) |
||
| 780 | { |
||
| 781 | bHuffbyte = JPEG_bGetNextHuffByte(pJpegDecoder); |
||
| 782 | bByteCount += (bHuffbyte >> 4); |
||
| 783 | if(bHuffbyte == 0 /* EOB */) |
||
| 784 | { |
||
| 785 | break; |
||
| 786 | } |
||
| 787 | if(bByteCount > 63) |
||
| 788 | { |
||
| 789 | JPEG_SendError(100); |
||
| 790 | } |
||
| 791 | pJpegDecoder->asOneBlock[bBlock][abZigzag[bByteCount++]] = JPEG_sGetBitsValue(pJpegDecoder, bHuffbyte & 0x0F); |
||
| 792 | } |
||
| 793 | pJpegDecoder->wBlockNumber++; |
||
| 794 | jpeg_idct_islow(&pJpegDecoder->asOneBlock[bBlock][0],pJpegDecoder->pwCurrentQuantTable); |
||
| 795 | } |
||
| 796 | |||
| 797 | // SetVisualPage(1); |
||
| 798 | |||
| 799 | return 0; |
||
| 800 | } |
||
| 801 | |||
| 802 | #define JPEG_WRITE_TO_DISPLAY |
||
| 803 | /******************************************************************************* |
||
| 804 | Function: void JPEG_vInitDisplay(JPEGDECODER *pJpegDecoder) |
||
| 805 | |||
| 806 | Precondition: None |
||
| 807 | |||
| 808 | Overview: Initializes the (x, y) co-ordinates to (0, 0) |
||
| 809 | |||
| 810 | Input: JPEGDECODER |
||
| 811 | |||
| 812 | Output: None |
||
| 813 | *******************************************************************************/ |
||
| 814 | static void JPEG_vInitDisplay(JPEGDECODER *pJpegDecoder) |
||
| 815 | { |
||
| 816 | #ifndef JPEG_WRITE_TO_DISPLAY |
||
| 817 | printf("%4u %4u\n", pJpegDecoder->wWidth, pJpegDecoder->wHeight); |
||
| 818 | #else |
||
| 819 | pJpegDecoder->wPrevX = 0; |
||
| 820 | pJpegDecoder->wPrevY = 0; |
||
| 821 | // SetActivePage(1); |
||
| 822 | #endif |
||
| 823 | } |
||
| 824 | |||
| 825 | /******************************************************************************* |
||
| 826 | Function: BYTE JPEG_bPaintOneBlock(JPEGDECODER *pJpegDecoder) |
||
| 827 | |||
| 828 | Precondition: One block - 8x8 pixel data of all channels must be decoded |
||
| 829 | |||
| 830 | Overview: Displays one 8x8 on the screen |
||
| 831 | (A multiple of 8x8 block if subsampling is used) |
||
| 832 | |||
| 833 | Input: JPEGDECODER |
||
| 834 | |||
| 835 | Output: Error code - '0' means no error |
||
| 836 | *******************************************************************************/ |
||
| 837 | static BYTE JPEG_bPaintOneBlock(JPEGDECODER *pJpegDecoder) |
||
| 838 | { |
||
| 839 | BYTE bCounter; |
||
| 840 | |||
| 841 | #ifndef JPEG_WRITE_TO_DISPLAY |
||
| 842 | |||
| 843 | for(bCounter = 0; bCounter < 64; bCounter++) |
||
| 844 | { |
||
| 845 | printf("%3u %3u %3u\n", abBlockR[bCounter]&0xF8, abBlockG[bCounter]&0xFC, abBlockB[bCounter]&0xF8); |
||
| 846 | } |
||
| 847 | |||
| 848 | #else |
||
| 849 | |||
| 850 | WORD wX, wY; |
||
| 851 | bCounter = 0; |
||
| 852 | BYTE r,g,b; |
||
| 853 | |||
| 854 | if(pJpegDecoder->bSubSampleType == JPEG_SAMPLE_1x1) |
||
| 855 | { |
||
| 856 | SHORT *psY = &pJpegDecoder->asOneBlock[0][0], *psCb = &pJpegDecoder->asOneBlock[1][0], *psCr = &pJpegDecoder->asOneBlock[2][0]; |
||
| 857 | |||
| 858 | for(wY = 0; wY < 8; wY++) |
||
| 859 | { |
||
| 860 | for(wX = 0; wX < 8; wX++) |
||
| 861 | { |
||
| 862 | LONG s1 = ((*psY) + 128)*128, s2 = (*psCb), s3 = (*psCr); |
||
| 863 | r = range_limit((s1 + 180*s3)>>7); |
||
| 864 | g = range_limit((s1 - 44*s2 - 91*s3)>>7); |
||
| 865 | b = range_limit((s1 + 227*s2)>>7); |
||
| 866 | IMG_vSetColor(r, g, b); |
||
| 867 | IMG_vPutPixel(pJpegDecoder->wPrevX + wX, pJpegDecoder->wPrevY + wY); |
||
| 868 | psY++; psCb++; psCr++; |
||
| 869 | } |
||
| 870 | } |
||
| 871 | |||
| 872 | pJpegDecoder->wPrevX += 8; |
||
| 873 | |||
| 874 | if(pJpegDecoder->wPrevX >= pJpegDecoder->wWidth) |
||
| 875 | { |
||
| 876 | pJpegDecoder->wPrevX = 0; |
||
| 877 | pJpegDecoder->wPrevY += 8; |
||
| 878 | } |
||
| 879 | } |
||
| 880 | else if(pJpegDecoder->bSubSampleType == JPEG_SAMPLE_1x2) |
||
| 881 | { |
||
| 882 | SHORT *psY, *psCb = &pJpegDecoder->asOneBlock[2][0], *psCr = &pJpegDecoder->asOneBlock[3][0]; |
||
| 883 | BYTE bBlock, bOffsetY[2] = {0,8}; |
||
| 884 | |||
| 885 | for(bBlock = 0; bBlock < 2; bBlock++) |
||
| 886 | { |
||
| 887 | psY = &pJpegDecoder->asOneBlock[bBlock][0]; |
||
| 888 | psCb = &pJpegDecoder->asOneBlock[2][bBlock*32]; |
||
| 889 | psCr = &pJpegDecoder->asOneBlock[3][bBlock*32]; |
||
| 890 | for(wY = 0; wY < 8; wY++) |
||
| 891 | { |
||
| 892 | for(wX = 0; wX < 8; wX++) |
||
| 893 | { |
||
| 894 | LONG s1 = ((*psY) + 128)*128; |
||
| 895 | LONG s2 = psCb[(wY>>1)*8+wX]; |
||
| 896 | LONG s3 = psCr[(wY>>1)*8+wX]; |
||
| 897 | r = range_limit((s1 + 180*s3)>>7); |
||
| 898 | g = range_limit((s1 - 44*s2 - 91*s3)>>7); |
||
| 899 | b = range_limit((s1 + 227*s2)>>7); |
||
| 900 | IMG_vSetColor(r, g, b); |
||
| 901 | IMG_vPutPixel(pJpegDecoder->wPrevX + wX, |
||
| 902 | pJpegDecoder->wPrevY + bOffsetY[bBlock] + wY); |
||
| 903 | psY++; |
||
| 904 | } |
||
| 905 | } |
||
| 906 | } |
||
| 907 | |||
| 908 | pJpegDecoder->wPrevX += 8; |
||
| 909 | |||
| 910 | if(pJpegDecoder->wPrevX >= pJpegDecoder->wWidth) |
||
| 911 | { |
||
| 912 | pJpegDecoder->wPrevX = 0; |
||
| 913 | pJpegDecoder->wPrevY += 16; |
||
| 914 | } |
||
| 915 | } |
||
| 916 | else if(pJpegDecoder->bSubSampleType == JPEG_SAMPLE_2x1) |
||
| 917 | { |
||
| 918 | SHORT *psY, *psCb = &pJpegDecoder->asOneBlock[2][0], *psCr = &pJpegDecoder->asOneBlock[3][0]; |
||
| 919 | BYTE bBlock, bOffsetX[2] = {0,8}; |
||
| 920 | |||
| 921 | for(bBlock = 0; bBlock < 2; bBlock++) |
||
| 922 | { |
||
| 923 | psY = &pJpegDecoder->asOneBlock[bBlock][0]; |
||
| 924 | psCb = &pJpegDecoder->asOneBlock[2][bBlock*4]; |
||
| 925 | psCr = &pJpegDecoder->asOneBlock[3][bBlock*4]; |
||
| 926 | for(wY = 0; wY < 8; wY++) |
||
| 927 | { |
||
| 928 | for(wX = 0; wX < 8; wX++) |
||
| 929 | { |
||
| 930 | LONG s1 = ((*psY) + 128)*128; |
||
| 931 | LONG s2 = psCb[(wY*8)+(wX>>1)]; |
||
| 932 | LONG s3 = psCr[(wY*8)+(wX>>1)]; |
||
| 933 | r = range_limit((s1 + 180*s3)>>7); |
||
| 934 | g = range_limit((s1 - 44*s2 - 91*s3)>>7); |
||
| 935 | b = range_limit((s1 + 227*s2)>>7); |
||
| 936 | IMG_vSetColor(r, g, b); |
||
| 937 | IMG_vPutPixel(pJpegDecoder->wPrevX + bOffsetX[bBlock] + wX, |
||
| 938 | pJpegDecoder->wPrevY + wY); |
||
| 939 | psY++; |
||
| 940 | } |
||
| 941 | } |
||
| 942 | } |
||
| 943 | |||
| 944 | pJpegDecoder->wPrevX += 16; |
||
| 945 | |||
| 946 | if(pJpegDecoder->wPrevX >= pJpegDecoder->wWidth) |
||
| 947 | { |
||
| 948 | pJpegDecoder->wPrevX = 0; |
||
| 949 | pJpegDecoder->wPrevY += 8; |
||
| 950 | } |
||
| 951 | } |
||
| 952 | else if(pJpegDecoder->bSubSampleType == JPEG_SAMPLE_2x2) |
||
| 953 | { |
||
| 954 | SHORT *psY, *psCb, *psCr; |
||
| 955 | BYTE bBlock, bOffsetX[4] = {0,8,0,8}, bOffsetY[4] = {0,0,8,8}, bCbCrOffset[4] = {0,4,32,36}; |
||
| 956 | |||
| 957 | for(bBlock = 0; bBlock < 4; bBlock++) |
||
| 958 | { |
||
| 959 | psY = &pJpegDecoder->asOneBlock[bBlock][0]; |
||
| 960 | psCb = &pJpegDecoder->asOneBlock[4][bCbCrOffset[bBlock]]; |
||
| 961 | psCr = &pJpegDecoder->asOneBlock[5][bCbCrOffset[bBlock]]; |
||
| 962 | for(wY = 0; wY < 8; wY++) |
||
| 963 | { |
||
| 964 | for(wX = 0; wX < 8; wX++) |
||
| 965 | { |
||
| 966 | LONG s1 = ((*psY) + 128)*128; |
||
| 967 | LONG s2 = psCb[(wY>>1)*8+(wX>>1)]; |
||
| 968 | LONG s3 = psCr[(wY>>1)*8+(wX>>1)]; |
||
| 969 | r = range_limit((s1 + 180*s3)>>7); |
||
| 970 | g = range_limit((s1 - 44*s2 - 91*s3)>>7); |
||
| 971 | b = range_limit((s1 + 227*s2)>>7); |
||
| 972 | IMG_vSetColor(r, g, b); |
||
| 973 | IMG_vPutPixel(pJpegDecoder->wPrevX + bOffsetX[bBlock] + wX, |
||
| 974 | pJpegDecoder->wPrevY + bOffsetY[bBlock] + wY); |
||
| 975 | psY++; |
||
| 976 | } |
||
| 977 | } |
||
| 978 | } |
||
| 979 | |||
| 980 | pJpegDecoder->wPrevX += 16; |
||
| 981 | |||
| 982 | if(pJpegDecoder->wPrevX >= pJpegDecoder->wWidth) |
||
| 983 | { |
||
| 984 | pJpegDecoder->wPrevX = 0; |
||
| 985 | pJpegDecoder->wPrevY += 16; |
||
| 986 | } |
||
| 987 | } |
||
| 988 | |||
| 989 | #endif |
||
| 990 | return 0; |
||
| 991 | } |
||
| 992 | |||
| 993 | #ifndef IMG_USE_NON_BLOCKING_DECODING |
||
| 994 | |||
| 995 | /******************************************************************************* |
||
| 996 | Function: BYTE JPEG_bDecode(IMG_FILE *pfile, BOOL bFirstTime) |
||
| 997 | |||
| 998 | Precondition: The global variables of Image decoder must be set |
||
| 999 | |||
| 1000 | Overview: This function decodes and displays a jpeg image |
||
| 1001 | |||
| 1002 | Input: Image file, ignored BOOLean |
||
| 1003 | |||
| 1004 | Output: Error code - '0' means no error |
||
| 1005 | *******************************************************************************/ |
||
| 1006 | BYTE JPEG_bDecode(IMG_FILE *pfile, BOOL bFirstTime) |
||
| 1007 | { |
||
| 1008 | WORD whblocks, wvblocks; |
||
| 1009 | WORD wi, wj; |
||
| 1010 | JPEGDECODER JPEG_JpegDecoder; |
||
| 1011 | |||
| 1012 | JPEG_vResetDecoder(&JPEG_JpegDecoder); |
||
| 1013 | JPEG_JpegDecoder.pImageFile = pfile; |
||
| 1014 | if(JPEG_bReadHeader(&JPEG_JpegDecoder) != 0) |
||
| 1015 | { |
||
| 1016 | return JPEG_JpegDecoder.bError; |
||
| 1017 | } |
||
| 1018 | |||
| 1019 | IMG_wImageWidth = JPEG_JpegDecoder.wWidth; |
||
| 1020 | IMG_wImageHeight = JPEG_JpegDecoder.wHeight; |
||
| 1021 | IMG_vSetboundaries(); |
||
| 1022 | |||
| 1023 | JPEG_bGenerateHuffmanTables(&JPEG_JpegDecoder); |
||
| 1024 | |||
| 1025 | whblocks = JPEG_JpegDecoder.wWidth >> 3; |
||
| 1026 | wvblocks = JPEG_JpegDecoder.wHeight >> 3; |
||
| 1027 | |||
| 1028 | if(whblocks * 8 < JPEG_JpegDecoder.wWidth) /* Odd sizes */ |
||
| 1029 | { |
||
| 1030 | whblocks++; |
||
| 1031 | } |
||
| 1032 | |||
| 1033 | if(wvblocks * 8 < JPEG_JpegDecoder.wHeight) /* Odd sizes */ |
||
| 1034 | { |
||
| 1035 | wvblocks++; |
||
| 1036 | } |
||
| 1037 | |||
| 1038 | if(JPEG_JpegDecoder.bSubSampleType == JPEG_SAMPLE_1x2) |
||
| 1039 | { |
||
| 1040 | wvblocks = (wvblocks>>1) + (wvblocks&1); |
||
| 1041 | } |
||
| 1042 | else if(JPEG_JpegDecoder.bSubSampleType == JPEG_SAMPLE_2x1) |
||
| 1043 | { |
||
| 1044 | whblocks = (whblocks>>1) + (whblocks&1); |
||
| 1045 | } |
||
| 1046 | else if(JPEG_JpegDecoder.bSubSampleType == JPEG_SAMPLE_2x2) |
||
| 1047 | { |
||
| 1048 | wvblocks = (wvblocks>>1) + (wvblocks&1); |
||
| 1049 | whblocks = (whblocks>>1) + (whblocks&1); |
||
| 1050 | } |
||
| 1051 | |||
| 1052 | JPEG_vInitDisplay(&JPEG_JpegDecoder); |
||
| 1053 | |||
| 1054 | for(wi = 0; wi < whblocks; wi++) |
||
| 1055 | { |
||
| 1056 | for(wj = 0; wj < wvblocks; wj++) |
||
| 1057 | { |
||
| 1058 | IMG_vCheckAndAbort(); |
||
| 1059 | JPEG_bDecodeOneBlock(&JPEG_JpegDecoder); /* Fills a block after correcting the zigzag, dequantizing, IDCR and color conversion to RGB */ |
||
| 1060 | JPEG_bPaintOneBlock(&JPEG_JpegDecoder); /* Sends the block to the Graphics unit */ |
||
| 1061 | } |
||
| 1062 | } |
||
| 1063 | return JPEG_JpegDecoder.bError; |
||
| 1064 | } |
||
| 1065 | |||
| 1066 | #else |
||
| 1067 | |||
| 1068 | /******************************************************************************* |
||
| 1069 | Function: BYTE JPEG_bDecode(IMG_FILE *pfile, BOOL bFirstTime) |
||
| 1070 | |||
| 1071 | Precondition: The global variables of Image decoder must be set |
||
| 1072 | |||
| 1073 | Overview: This function decodes and displays a jpeg image |
||
| 1074 | |||
| 1075 | Input: Image file, BOOLean indicating if this is the first time calling |
||
| 1076 | the JPEG_bDecode function (needed to reset internal decoding |
||
| 1077 | state variables). If bFirstTime is TRUE, pfile must be set. |
||
| 1078 | If bFirstTime is FALSE, pfile is ignored (uses previously |
||
| 1079 | provided file handle). |
||
| 1080 | |||
| 1081 | Output: Error code - '0' means not yet completed |
||
| 1082 | *******************************************************************************/ |
||
| 1083 | BYTE JPEG_bDecode(IMG_FILE *pfile, BOOL bFirstTime) |
||
| 1084 | { |
||
| 1085 | static WORD whblocks, wvblocks; |
||
| 1086 | static WORD wi, wj; |
||
| 1087 | static JPEGDECODER JPEG_JpegDecoder; |
||
| 1088 | static enum |
||
| 1089 | { |
||
| 1090 | INITIAL, |
||
| 1091 | HEADER_DECODED, |
||
| 1092 | BLOCK_DECODE, |
||
| 1093 | DECODE_DONE |
||
| 1094 | } decodestate; |
||
| 1095 | |||
| 1096 | |||
| 1097 | if(bFirstTime) |
||
| 1098 | decodestate = INITIAL; |
||
| 1099 | |||
| 1100 | switch(decodestate) |
||
| 1101 | { |
||
| 1102 | |||
| 1103 | case INITIAL: JPEG_vResetDecoder(&JPEG_JpegDecoder); |
||
| 1104 | JPEG_JpegDecoder.pImageFile = pfile; |
||
| 1105 | if(JPEG_bReadHeader(&JPEG_JpegDecoder) != 0) |
||
| 1106 | { |
||
| 1107 | return 1; |
||
| 1108 | } |
||
| 1109 | decodestate = HEADER_DECODED; |
||
| 1110 | return 0; |
||
| 1111 | |||
| 1112 | case HEADER_DECODED: |
||
| 1113 | IMG_wImageWidth = JPEG_JpegDecoder.wWidth; |
||
| 1114 | IMG_wImageHeight = JPEG_JpegDecoder.wHeight; |
||
| 1115 | IMG_vSetboundaries(); |
||
| 1116 | |||
| 1117 | JPEG_bGenerateHuffmanTables(&JPEG_JpegDecoder); |
||
| 1118 | |||
| 1119 | whblocks = JPEG_JpegDecoder.wWidth >> 3; |
||
| 1120 | wvblocks = JPEG_JpegDecoder.wHeight >> 3; |
||
| 1121 | |||
| 1122 | if(whblocks * 8 < JPEG_JpegDecoder.wWidth) /* Odd sizes */ |
||
| 1123 | { |
||
| 1124 | whblocks++; |
||
| 1125 | } |
||
| 1126 | |||
| 1127 | if(wvblocks * 8 < JPEG_JpegDecoder.wHeight) /* Odd sizes */ |
||
| 1128 | { |
||
| 1129 | wvblocks++; |
||
| 1130 | } |
||
| 1131 | |||
| 1132 | if(JPEG_JpegDecoder.bSubSampleType == JPEG_SAMPLE_1x2) |
||
| 1133 | { |
||
| 1134 | wvblocks = (wvblocks>>1) + (wvblocks&1); |
||
| 1135 | } |
||
| 1136 | else if(JPEG_JpegDecoder.bSubSampleType == JPEG_SAMPLE_2x1) |
||
| 1137 | { |
||
| 1138 | whblocks = (whblocks>>1) + (whblocks&1); |
||
| 1139 | } |
||
| 1140 | else if(JPEG_JpegDecoder.bSubSampleType == JPEG_SAMPLE_2x2) |
||
| 1141 | { |
||
| 1142 | wvblocks = (wvblocks>>1) + (wvblocks&1); |
||
| 1143 | whblocks = (whblocks>>1) + (whblocks&1); |
||
| 1144 | } |
||
| 1145 | |||
| 1146 | JPEG_vInitDisplay(&JPEG_JpegDecoder); |
||
| 1147 | |||
| 1148 | wi = 0; |
||
| 1149 | wj = 0; |
||
| 1150 | |||
| 1151 | decodestate = BLOCK_DECODE; |
||
| 1152 | return 0; |
||
| 1153 | |||
| 1154 | case BLOCK_DECODE: if(wi < whblocks) |
||
| 1155 | { |
||
| 1156 | JPEG_bDecodeOneBlock(&JPEG_JpegDecoder); /* Fills a block after correcting the zigzag, dequantizing, IDCR and color conversion to RGB */ |
||
| 1157 | JPEG_bPaintOneBlock(&JPEG_JpegDecoder); /* Sends the block to the Graphics unit */ |
||
| 1158 | wj++; |
||
| 1159 | |||
| 1160 | if(wj >= wvblocks) |
||
| 1161 | { |
||
| 1162 | wj = 0; |
||
| 1163 | wi++; |
||
| 1164 | } |
||
| 1165 | return 0; |
||
| 1166 | } |
||
| 1167 | |||
| 1168 | decodestate = DECODE_DONE; |
||
| 1169 | // No break needed |
||
| 1170 | |||
| 1171 | case DECODE_DONE: return 1; |
||
| 1172 | |||
| 1173 | default: return 1; |
||
| 1174 | } |
||
| 1175 | } |
||
| 1176 | |||
| 1177 | #endif /* #ifndef IMG_USE_NON_BLOCKING_DECODING */ |
||
| 1178 | |||
| 1179 | #endif /* #ifdef IMG_SUPPORT_JPEG */ |
||
| 1180 | |||
| 1181 | #undef __JPEGDECODER_C__ |
Powered by WebSVN v2.8.3