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