1 #include <time.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 #include "bitmap/JPEG.h"
6 #include "idct/TrivialC.h"
7 #include "idct/IEEE1180.h"
8 #include "StreamBitStream.h"
9 #include "PtrMacro.h"
10
11 using namespace Framework;
12
13 //IDCT::CInterface* CJPEG::m_pIDCT = IDCT::CTrivialC::GetInstance();
14 IDCT::CInterface* CJPEG::m_pIDCT = IDCT::CIEEE1180::GetInstance();
15
16 unsigned char CJPEG::m_nZigZag[64] =
17 {
18 0, 1, 8, 16, 9, 2, 3, 10,
19 17, 24, 32, 25, 18, 11, 4, 5,
20 12, 19, 26, 33, 40, 48, 41, 34,
21 27, 20, 13, 6, 7, 14, 21, 28,
22 35, 42, 49, 56, 57, 50, 43, 36,
23 29, 22, 15, 23, 30, 37, 44, 51,
24 58, 59, 52, 45, 38, 31, 39, 46,
25 53, 60, 61, 54, 47, 55, 62, 63
26 };
27
CJPEG(CStream & pStream)28 CJPEG::CJPEG(CStream& pStream)
29 {
30 m_stream = new CStreamBitStream(pStream);
31
32 for(int i = 0; i < 4; i++)
33 {
34 m_Qt[i].pQ = NULL;
35
36 for(int j = 0; j < 16; j++)
37 {
38 m_ACHt[i].pV[j] = NULL;
39 m_DCHt[i].pV[j] = NULL;
40 }
41
42 m_ACHt[i].nCodeTable = NULL;
43 m_DCHt[i].nCodeTable = NULL;
44 }
45
46 m_Frame.pCompoment = NULL;
47 m_Scan.pComponent = NULL;
48 }
49
~CJPEG()50 CJPEG::~CJPEG()
51 {
52 for(int i = 0; i < 4; i++)
53 {
54 if(m_Qt[i].pQ != NULL)
55 {
56 free(m_Qt[i].pQ);
57 }
58
59 for(int j = 0; j < 16; j++)
60 {
61 if(m_ACHt[i].pV[j] != NULL)
62 {
63 free(m_ACHt[i].pV[j]);
64 }
65 if(m_DCHt[i].pV[j] != NULL)
66 {
67 free(m_DCHt[i].pV[j]);
68 }
69 }
70
71 if(m_ACHt[i].nCodeTable != NULL)
72 {
73 free(m_ACHt[i].nCodeTable);
74 }
75
76 if(m_DCHt[i].nCodeTable != NULL)
77 {
78 free(m_DCHt[i].nCodeTable);
79 }
80 }
81
82 if(m_Frame.pCompoment != NULL)
83 {
84 free(m_Frame.pCompoment);
85 }
86
87 if(m_Scan.pComponent != NULL)
88 {
89 free(m_Scan.pComponent);
90 }
91
92 delete m_stream;
93 }
94
ReadBitmap(CStream & stream)95 CBitmap CJPEG::ReadBitmap(CStream& stream)
96 {
97 CJPEG JPEG(stream);
98 return JPEG.Process();
99 }
100
101 /////////////////////////////////////////////////////
102 //Huffman -----------------------------------------//
103 /////////////////////////////////////////////////////
104
HuffGetBit()105 uint8 CJPEG::HuffGetBit()
106 {
107 if(m_stream->IsOnByteBoundary())
108 {
109 if(m_nHuffSkipNext)
110 {
111 uint8 markerEscape = m_stream->GetBits_MSBF(8);
112 assert(markerEscape == 0x00);
113 m_nHuffSkipNext = false;
114 }
115 if(m_stream->PeekBits_MSBF(8) == 0xFF)
116 {
117 //Trap if we want to...
118 uint16 fullMarker = m_stream->PeekBits_MSBF(16);
119 assert(fullMarker == 0xFF00);
120 m_nHuffSkipNext = true;
121 }
122 }
123
124 return (uint8)m_stream->GetBits_MSBF(1);
125 }
126
HuffDecode(HUFFMANTABLE * t)127 uint8 CJPEG::HuffDecode(HUFFMANTABLE* t)
128 {
129 int i = 0;
130 int16 nCode = HuffGetBit();
131
132 while(nCode > t->nMax[i])
133 {
134 nCode <<= 1;
135 nCode |= HuffGetBit();
136 i++;
137 }
138
139 int j = nCode - t->nMin[i];
140 return t->pV[i][j];
141 }
142
HuffReceive(unsigned int nBits)143 uint32 CJPEG::HuffReceive(unsigned int nBits)
144 {
145 uint32 nTemp = 0;
146 for(unsigned int i = 0; i < nBits; i++)
147 {
148 nTemp <<= 1;
149 nTemp |= HuffGetBit();
150 }
151
152 return nTemp;
153 }
154
HuffExtend(uint32 nV,unsigned int nBits)155 uint32 CJPEG::HuffExtend(uint32 nV, unsigned int nBits)
156 {
157 uint32 nVt = (1 << (nBits - 1));
158 if(nV < nVt)
159 {
160 nVt = (0xFFFFFFFF << nBits) + 1;
161 nV += nVt;
162 }
163 return nV;
164 }
165
HuffGenerateSizeTable(HUFFMANTABLE * t)166 uint8* CJPEG::HuffGenerateSizeTable(HUFFMANTABLE* t)
167 {
168 unsigned int nSize = 0;
169 for(unsigned int i = 0; i < 16; i++)
170 {
171 nSize += t->nL[i];
172 }
173
174 nSize++;
175 unsigned char* pTemp = (unsigned char*)malloc(nSize);
176 unsigned int k = 0;
177
178 for(unsigned int i = 0; i < 16; i++)
179 {
180 unsigned int j = 1;
181 while(j <= t->nL[i])
182 {
183 pTemp[k] = (i + 1);
184 k++;
185 j++;
186 }
187 }
188
189 pTemp[k] = 0;
190 return pTemp;
191 }
192
HuffGenerateCodeTable(uint8 * pS)193 uint16* CJPEG::HuffGenerateCodeTable(uint8* pS)
194 {
195 unsigned int nSize = 0;
196 while(pS[nSize] != 0)
197 {
198 nSize++;
199 }
200
201 uint16* pTemp = (uint16*)malloc(nSize * 2);
202 unsigned int k = 0;
203 unsigned int nCode = 0;
204 unsigned int s = pS[k];
205
206 while(1)
207 {
208 while(pS[k] == s)
209 {
210 pTemp[k] = nCode;
211 nCode++;
212 k++;
213 }
214 if(pS[k] == 0) break;
215 while(pS[k] != s)
216 {
217 nCode <<= 1;
218 s++;
219 }
220 }
221
222 return pTemp;
223 }
224
HuffGenerateMinMaxTables(HUFFMANTABLE * t)225 void CJPEG::HuffGenerateMinMaxTables(HUFFMANTABLE* t)
226 {
227 memset(t->nMin, 0xFF, 16 * 2);
228 memset(t->nMax, 0xFF, 16 * 2);
229
230 int j = 0;
231 for(int i = 0; i < 16; i++)
232 {
233 if(t->nL[i] == 0)
234 {
235 t->nMax[i] = -1;
236 continue;
237 }
238 t->nMin[i] = t->nCodeTable[j];
239 j = j + t->nL[i] - 1;
240 t->nMax[i] = t->nCodeTable[j];
241 j++;
242 }
243
244 }
245
HuffGenerateSubTables(HUFFMANTABLE * t)246 void CJPEG::HuffGenerateSubTables(HUFFMANTABLE* t)
247 {
248 uint8* pDCS = HuffGenerateSizeTable(t);
249
250 if(t->nCodeTable != NULL)
251 {
252 free(t->nCodeTable);
253 }
254
255 t->nCodeTable = HuffGenerateCodeTable(pDCS);
256 HuffGenerateMinMaxTables(t);
257 free(pDCS);
258 }
259
DecodeMCU(int nComponent,uint8 * pData,int * nDC)260 unsigned int CJPEG::DecodeMCU(int nComponent, uint8* pData, int* nDC)
261 {
262 int16 nBlock[64], nTempBlock[64];
263 unsigned int i, t, s, r, z;
264 int nDiff;
265
266 i = 0;
267 while(m_Frame.pCompoment[nComponent].nC != m_Scan.pComponent[i].nCs)
268 {
269 i++;
270 }
271
272 QUANTIZATIONTABLE* pQt = &m_Qt[m_Frame.pCompoment[nComponent].nTq];
273 HUFFMANTABLE* pACHt = &m_ACHt[m_Scan.pComponent[i].nTdTa & 0x0F];
274 HUFFMANTABLE* pDCHt = &m_DCHt[(m_Scan.pComponent[i].nTdTa & 0xF0) >> 4];
275
276 memset(nBlock, 0, sizeof(int16) * 64);
277
278 i = HuffDecode(pDCHt);
279 nDiff = HuffReceive(i);
280 nDiff = HuffExtend(nDiff, i);
281
282 *nDC += nDiff;
283 nBlock[0] = *nDC;
284
285 for(i = 1; i < 64; i++)
286 {
287 t = HuffDecode(pACHt);
288 s = t % 16;
289 r = t >> 4;
290 if(s == 0)
291 {
292 if(r == 15)
293 {
294 i += 16 - 1;
295 }
296 else
297 {
298 break;
299 }
300 }
301 else
302 {
303 i += r;
304 }
305 z = HuffReceive(s);
306 z = HuffExtend(z, s);
307 if(i < 0x40)
308 {
309 nBlock[i] = (signed)z;
310 }
311 else
312 {
313 assert(0);
314 //nBlock[i] = 0;
315 }
316 }
317
318 //Dequantize
319 for(i = 0; i < 64; i++)
320 {
321 nBlock[i] *= ((int8*)pQt->pQ)[i];
322 }
323
324 //Un-ZigZag
325 for(i = 0; i < 64; i++)
326 {
327 nTempBlock[m_nZigZag[i]] = nBlock[i];
328 }
329 memcpy(nBlock, nTempBlock, sizeof(short) * 64);
330
331 m_pIDCT->Transform(nBlock, nTempBlock);
332
333 for(i = 0; i < 64; i++)
334 {
335 if(nTempBlock[i] > 127)
336 {
337 nTempBlock[i] = 127;
338 }
339 if(nTempBlock[i] < -128)
340 {
341 nTempBlock[i] = -128;
342 }
343 pData[i] = ((uint8)nTempBlock[i]) - 128;
344 }
345
346 return 1;
347 }
348
FixRange(double nNumber)349 uint8 CJPEG::FixRange(double nNumber)
350 {
351 if(nNumber < 0)
352 {
353 return 0x00;
354 }
355
356 if(nNumber > 255)
357 {
358 return 0xFF;
359 }
360
361 return (uint8)nNumber;
362 }
363
Draw8x8Block(unsigned int nX,unsigned int nY,uint8 * pReMap,uint8 * pY,uint8 * pCr,uint8 * pCb)364 void CJPEG::Draw8x8Block(unsigned int nX, unsigned int nY, uint8 *pReMap, uint8* pY, uint8* pCr, uint8* pCb)
365 {
366 uint32* pImage = reinterpret_cast<uint32*>(m_bitmap.GetPixels());
367
368 for(unsigned int y = 0; y < 8; y++)
369 {
370 for(unsigned int x = 0; x < 8; x++)
371 {
372 double nYT = pY[(y * 8) + x];
373 double nCrT = pCr[pReMap[(y * 8) + x]];
374 double nCbT = pCb[pReMap[(y * 8) + x]];
375
376 //R = Y + 1.402 *(Cr-128)
377 //G = Y - 0.34414*(Cb-128) - 0.71414*(Cr-128)
378 //B = Y + 1.772 *(Cb-128)
379
380 uint8 nR = FixRange(nYT + 1.402 * (nCrT - 128));
381 uint8 nG = FixRange(nYT - 0.344114 * (nCbT - 128) - 0.71414 * (nCrT - 128));
382 uint8 nB = FixRange(nYT + 1.772 * (nCbT - 128));
383
384 unsigned int xofs = (nX + x);
385 unsigned int yofs = (nY + y);
386 if(xofs >= m_Frame.nCX) continue;
387 if(yofs >= m_Frame.nCY) continue;
388
389 pImage[(yofs * m_Frame.nCX) + xofs] = 0xFF000000 | (nB << 16) | (nG << 8) | (nR);
390 }
391 }
392 }
393
Decode()394 unsigned int CJPEG::Decode()
395 {
396 uint8 nY[256], nCb[64], nCr[64];
397 uint8 nReMap[256];
398 uint8 nTab1[64], nTab2[64], nTab3[64], nTab4[64];
399 uint8 nSampX, nBX;
400 uint8 nSampY, nBY;
401 unsigned int i, j;
402 unsigned int nCX, nCY;
403 int nYDC, nCrDC, nCbDC;
404
405 m_nHuffSkipNext = false;
406
407 //Validate some stuff
408 if(m_Frame.nType != 0xFFC0)
409 {
410 return JERROR_NOTBASELINE;
411 }
412 if(m_Frame.nComponents != 3 && m_Scan.nComponents != 3)
413 {
414 return JERROR_NOT3CHANNELS;
415 }
416
417 //Y is always 0?
418 nSampX = m_Frame.pCompoment[0].nHV & 0x0F;
419 nSampY = m_Frame.pCompoment[0].nHV >> 4;
420 if(nSampX == 1 && nSampY == 2)
421 {
422 return JERROR_UNSUPPORTED_YSCALING;
423 }
424 if(nSampX == 2 && nSampY == 1)
425 {
426 return JERROR_UNSUPPORTED_YSCALING;
427 }
428
429 m_bitmap = CBitmap(m_Frame.nCX, m_Frame.nCY, 32);
430
431 //Allocate some space for the components
432 nCX = ((m_Frame.nCX + 15) / 16) * 16;
433 nCY = ((m_Frame.nCY + 15) / 16) * 16;
434
435 nBX = nCX / (8 * nSampX);
436 nBY = nCY / (8 * nSampY);
437
438 //TODO: Figure that out...
439 for(i = 0; i < 16; i++)
440 {
441 for(j = 0; j < 16; j++)
442 {
443 nReMap[(i * 16) + j] = ((i / 2) * 8) + j / 2;
444 }
445 }
446
447 for(i = 0; i < 8; i++)
448 {
449 for(j = 0; j < 8; j++)
450 {
451 nTab1[(i * 8) + j] = nReMap[(i * 16) + j];
452 }
453 for(j = 8; j < 16; j++)
454 {
455 nTab2[(i * 8) + (j - 8)] = nReMap[(i * 16) + j];
456 }
457 }
458 for(i = 8; i < 16; i++)
459 {
460 for(j = 0; j < 8; j++)
461 {
462 nTab3[((i - 8) * 8) + j] = nReMap[(i * 16) + j];
463 }
464 for(j = 8; j < 16; j++)
465 {
466 nTab4[((i - 8) * 8) + (j - 8)] = nReMap[(i * 16) + j];
467 }
468 }
469
470 nYDC = 0;
471 nCrDC = 0;
472 nCbDC = 0;
473
474 if(nSampX == 1 && nSampY == 1)
475 {
476 for(j = 0; j < nBY; j++)
477 {
478 for(i = 0; i < nBX; i++)
479 {
480 DecodeMCU(0, nY, &nYDC);
481 DecodeMCU(1, nCb, &nCbDC);
482 DecodeMCU(2, nCr, &nCrDC);
483
484 Draw8x8Block((i * 8), (j * 8), nTab1, nY, nCr, nCb);
485 }
486 }
487 }
488
489 if(nSampX == 2 && nSampY == 2)
490 {
491 for(j = 0; j < nBY; j++)
492 {
493 for(i = 0; i < nBX; i++)
494 {
495 DecodeMCU(0, nY + 0x0000, &nYDC);
496 DecodeMCU(0, nY + 0x0040, &nYDC);
497 DecodeMCU(0, nY + 0x0080, &nYDC);
498 DecodeMCU(0, nY + 0x00C0, &nYDC);
499
500 DecodeMCU(1, nCb, &nCbDC);
501
502 DecodeMCU(2, nCr, &nCrDC);
503
504 Draw8x8Block((i * 16) + 0, (j * 16) + 0, nTab1, nY + 0x0000, nCr, nCb);
505 Draw8x8Block((i * 16) + 8, (j * 16) + 0, nTab2, nY + 0x0040, nCr, nCb);
506 Draw8x8Block((i * 16) + 0, (j * 16) + 8, nTab3, nY + 0x0080, nCr, nCb);
507 Draw8x8Block((i * 16) + 8, (j * 16) + 8, nTab4, nY + 0x00C0, nCr, nCb);
508
509 }
510 }
511 }
512
513 return 0;
514 }
515
Process()516 CBitmap CJPEG::Process()
517 {
518 unsigned int nError = 0;
519 uint16 nMarker = 0;
520
521 while(nMarker != 0xFFD9 && nError == 0)
522 {
523 m_stream->SeekToByteAlign();
524 nMarker = (uint16)m_stream->GetBits_MSBF(16);
525
526 switch(nMarker)
527 {
528 case 0xFFC0:
529 //SOF0 - Start of frame (Baseline DCT)
530 nError = ProcessSOF0();
531 break;
532 case 0xFFC4:
533 //DHT - Define Huffman Table
534 nError = ProcessDHT();
535 break;
536 case 0xFFD8:
537 //SOI - Start of Image
538 break;
539 case 0xFFD9:
540 //EOI - End of Image
541 //Decoding was successful
542 break;
543 case 0xFFDA:
544 //SOS - Start of Scan
545 nError = ProcessSOS();
546 break;
547 case 0xFFDB:
548 //DQT - Define Quantization Table
549 nError = ProcessDQT();
550 break;
551 case 0xFFE0:
552 case 0xFFEC:
553 case 0xFFEE:
554 //APPx - Application defined x
555 ProcessAPPx();
556 break;
557 case 0xFFFE:
558 //COM - Comment
559 ProcessCOM();
560 break;
561 default:
562 nError = JERROR_UNKNMARKER;
563 break;
564 }
565 }
566
567 return m_bitmap;
568 }
569
ProcessSOF0()570 unsigned int CJPEG::ProcessSOF0()
571 {
572 uint16 nLength;
573 unsigned int i;
574
575 nLength = (uint16)m_stream->GetBits_MSBF(16);
576
577 m_Frame.nType = 0xFFC0;
578 m_Frame.nPrecision = (uint8)m_stream->GetBits_MSBF(8);
579 m_Frame.nCY = (uint16)m_stream->GetBits_MSBF(16);
580 m_Frame.nCX = (uint16)m_stream->GetBits_MSBF(16);
581 m_Frame.nComponents = (uint8)m_stream->GetBits_MSBF(8);
582
583 if(m_Frame.pCompoment != NULL)
584 {
585 free(m_Frame.pCompoment);
586 }
587
588 m_Frame.pCompoment = (FRAMECOMPONENT*)malloc(sizeof(FRAMECOMPONENT) * m_Frame.nComponents);
589
590 for(i = 0; i < m_Frame.nComponents; i++)
591 {
592 m_Frame.pCompoment[i].nC = (uint8)m_stream->GetBits_MSBF(8);
593 m_Frame.pCompoment[i].nHV = (uint8)m_stream->GetBits_MSBF(8);
594 m_Frame.pCompoment[i].nTq = (uint8)m_stream->GetBits_MSBF(8);
595 }
596
597 return 0;
598 }
599
ProcessDHT()600 unsigned int CJPEG::ProcessDHT()
601 {
602 uint16 nLength = (uint16)m_stream->GetBits_MSBF(16);
603 nLength -= 2;
604
605 while(nLength != 0)
606 {
607 uint8 nTemp = (uint8)m_stream->GetBits_MSBF(8);
608
609 uint16 nHtDst = nTemp & 0x0F;
610 if(nHtDst > 4)
611 {
612 return JERROR_HTDEST_INVALID;
613 }
614
615 HUFFMANTABLE* t(nullptr);
616 if(nTemp & 0x10)
617 {
618 t = &m_ACHt[nHtDst];
619 }
620 else
621 {
622 t = &m_DCHt[nHtDst];
623 }
624
625 for(unsigned int i = 0; i < 16; i++)
626 {
627 t->nL[i] = (uint8)m_stream->GetBits_MSBF(8);
628 }
629
630 for(unsigned int i = 0; i < 16; i++)
631 {
632 if(t->pV[i] != NULL)
633 {
634 free(t->pV[i]);
635 t->pV[i] = NULL;
636 }
637
638 if(t->nL[i] == 0) continue;
639
640 t->pV[i] = (uint8*)malloc(t->nL[i]);
641 for(unsigned int j = 0; j < t->nL[i]; j++)
642 {
643 t->pV[i][j] = (uint8)m_stream->GetBits_MSBF(8);
644 }
645
646 nLength -= t->nL[i];
647 }
648
649 t->nTcTh = nTemp;
650 HuffGenerateSubTables(t);
651 nLength -= 17;
652 }
653
654 return 0;
655 }
656
ProcessSOS()657 unsigned int CJPEG::ProcessSOS()
658 {
659 uint16 nLength;
660 unsigned int i;
661
662 nLength = (uint16)m_stream->GetBits_MSBF(16);
663
664 m_Scan.nComponents = (uint8)m_stream->GetBits_MSBF(8);
665
666 FREEPTR(m_Scan.pComponent);
667
668 m_Scan.pComponent = (SCANCOMPONENT*)malloc(sizeof(SCANCOMPONENT) * m_Scan.nComponents);
669
670 for(i = 0; i < m_Scan.nComponents; i++)
671 {
672 m_Scan.pComponent[i].nCs = (uint8)m_stream->GetBits_MSBF(8);
673 m_Scan.pComponent[i].nTdTa = (uint8)m_stream->GetBits_MSBF(8);
674 }
675
676 m_Scan.nStartSpectral = (uint8)m_stream->GetBits_MSBF(8);
677 m_Scan.nEndSpectral = (uint8)m_stream->GetBits_MSBF(8);
678 m_Scan.nAhAl = (uint8)m_stream->GetBits_MSBF(8);
679
680 return Decode();
681 }
682
ProcessDQT()683 unsigned int CJPEG::ProcessDQT()
684 {
685 uint16 nLength = (uint16)m_stream->GetBits_MSBF(16);
686 nLength -= 2;
687
688 while(nLength != 0)
689 {
690 uint8 nTemp8 = (uint8)m_stream->GetBits_MSBF(8);
691 uint16 nQtDst = nTemp8 & 0x0F;
692
693 if(nQtDst > 4)
694 {
695 return JERROR_QTDEST_INVALID;
696 }
697
698 FREEPTR(m_Qt[nQtDst].pQ);
699
700 if(nTemp8 & 0x10)
701 {
702 return JERROR_QT16BITS;
703 }
704
705 m_Qt[nQtDst].pQ = (uint8*)malloc(64);
706
707 for(unsigned int i = 0; i < 64; i++)
708 {
709 m_Qt[nQtDst].pQ[i] = (uint8)m_stream->GetBits_MSBF(8);
710 }
711 m_Qt[nQtDst].nPqTq = nTemp8;
712
713 nLength -= 0x41;
714 }
715
716 return 0;
717 }
718
ProcessAPPx()719 void CJPEG::ProcessAPPx()
720 {
721 uint16 nLength = (uint16)m_stream->GetBits_MSBF(16);
722 nLength -= 2;
723
724 for(unsigned int i = 0; i < nLength; i++)
725 {
726 m_stream->GetBits_MSBF(8);
727 }
728 }
729
ProcessCOM()730 void CJPEG::ProcessCOM()
731 {
732 uint16 nLength;
733 unsigned int i;
734
735 nLength = (uint16)m_stream->GetBits_MSBF(16);
736 nLength -= 2;
737
738 for(i = 0; i < nLength; i++)
739 {
740 m_stream->GetBits_MSBF(8);
741 }
742
743 /*
744 uint8* pCom;
745 pData->Read(&nLenght, 2);
746 nLenght = SWAP16(nLenght);
747 pCom = (unsigned char*)malloc(nLenght);
748 pData->Read(pCom, nLenght - 2);
749 //Humm...
750 CJPEG::LogPrint("Comment: %s\n", pCom);
751 free(pCom);
752 */
753 }
754