XenevaOS
Loading...
Searching...
No Matches
nanojpg.h
Go to the documentation of this file.
1#ifndef INCLUDED_JPEG_DECODER_H
2#define INCLUDED_JPEG_DECODER_H
3
4// This is a cosmetic restructing and port to C++ class of 'NanoJPEG', found
5// at http://keyj.s2000.ws/?p=137. It's been made somewhat thread safe in that
6// all context information is pulled into an object, rather than being global
7// as the original was. Other than that, the original is superior in
8// configurability, comments, cleanliness, portability, etc. and should be
9// preferred. The only other possible benefit this version can claim is that
10// it's crammed into one header file.
11//
12// Scott Graham <scott.jpegdecoder@h4ck3r.net>
13//
14// The original license follows:
15//
16// NanoJPEG -- KeyJ's Tiny Baseline JPEG Decoder
17// version 1.0 (2009-04-29)
18// by Martin J. Fiedler <martin.fiedler@gmx.net>
19//
20// This software is published under the terms of KeyJ's Research License,
21// version 0.2. Usage of this software is subject to the following conditions:
22// 0. There's no warranty whatsoever. The author(s) of this software can not
23// be held liable for any damages that occur when using this software.
24// 1. This software may be used freely for both non-commercial and commercial
25// purposes.
26// 2. This software may be redistributed freely as long as no fees are charged
27// for the distribution and this license information is included.
28// 3. This software may be modified freely except for this license information,
29// which must not be changed in any way.
30// 4. If anything other than configuration, indentation or comments have been
31// altered in the code, the original author(s) must receive a copy of the
32// modified code.
33
34#include <string.h>
35#include <stdint.h>
36
37namespace Jpeg
38{
39 class Decoder
40 {
41 public:
43 {
44 OK = 0, // decoding successful
45 NotAJpeg, // not a JPEG file
46 Unsupported, // unsupported format
47 OutOfMemory, // out of memory
48 InternalError, // internal error
49 SyntaxError, // syntax error
50 Internal_Finished, // used internally, will never be reported
51 };
52
53 // decode the raw data. object is very large, and probably shouldn't
54 // go on the stack.
55 Decoder(const unsigned char* data, uint32_t size, void *(*allocFunc)(uint32_t), void(*freeFunc)(void*));
56 ~Decoder();
57
58 // the result of decode
59 DecodeResult GetResult() const;
60
61 // all remaining functions below are only valid if GetResult() == OK.
62
63 int GetWidth() const;
64 int GetHeight() const;
65 bool IsColor() const;
66
67 // if IsColor() then 24bit as R,G,B bytes
68 // else 8 bit luminance
69 unsigned char* GetImage() const;
70
71 // in bytes
72 uint32_t GetImageSize() const;
73
77 //
78 // Implementation follows
79 //
83
84 private:
85
86 struct VlcCode {
87 unsigned char bits, code;
88 };
89
90#pragma pack(push,1)
91 struct Component {
92 int cid;
93 int ssx, ssy;
94 int width, height;
95 int stride;
96 int qtsel;
97 int actabsel, dctabsel;
98 int dcpred;
99 unsigned char *pixels;
100 };
101#pragma pack(pop)
102
103 struct Context {
104 DecodeResult error;
105 const unsigned char *pos;
106 int size;
107 int length;
108 int width, height;
109 int mbwidth, mbheight;
110 int mbsizex, mbsizey;
111 int ncomp;
112 Component comp[3];
113 int qtused, qtavail;
114 unsigned char qtab[4][64];
115 VlcCode vlctab[4][65536];
116 int buf, bufbits;
117 int block[64];
118 int rstinterval;
119 unsigned char *rgb;
120 };
121
122
123 Context ctx;
124 char ZZ[64];
125 void *(*AllocMem)(uint32_t);
126 void(*FreeMem)(void*);
127
128
129 inline unsigned char _Clip(const int x) {
130 return (x < 0) ? 0 : ((x > 0xFF) ? 0xFF : (unsigned char)x);
131 }
132
133 enum {
134 W1 = 2841,
135 W2 = 2676,
136 W3 = 2408,
137 W5 = 1609,
138 W6 = 1108,
139 W7 = 565,
140 };
141
142 inline void _RowIDCT(int* blk) {
143 int x0, x1, x2, x3, x4, x5, x6, x7, x8;
144 if (!((x1 = blk[4] << 11)
145 | (x2 = blk[6])
146 | (x3 = blk[2])
147 | (x4 = blk[1])
148 | (x5 = blk[7])
149 | (x6 = blk[5])
150 | (x7 = blk[3])))
151 {
152 blk[0] = blk[1] = blk[2] = blk[3] = blk[4] = blk[5] = blk[6] = blk[7] = blk[0] << 3;
153 return;
154 }
155 x0 = (blk[0] << 11) + 128;
156 x8 = W7 * (x4 + x5);
157 x4 = x8 + (W1 - W7) * x4;
158 x5 = x8 - (W1 + W7) * x5;
159 x8 = W3 * (x6 + x7);
160 x6 = x8 - (W3 - W5) * x6;
161 x7 = x8 - (W3 + W5) * x7;
162 x8 = x0 + x1;
163 x0 -= x1;
164 x1 = W6 * (x3 + x2);
165 x2 = x1 - (W2 + W6) * x2;
166 x3 = x1 + (W2 - W6) * x3;
167 x1 = x4 + x6;
168 x4 -= x6;
169 x6 = x5 + x7;
170 x5 -= x7;
171 x7 = x8 + x3;
172 x8 -= x3;
173 x3 = x0 + x2;
174 x0 -= x2;
175 x2 = (181 * (x4 + x5) + 128) >> 8;
176 x4 = (181 * (x4 - x5) + 128) >> 8;
177 blk[0] = (x7 + x1) >> 8;
178 blk[1] = (x3 + x2) >> 8;
179 blk[2] = (x0 + x4) >> 8;
180 blk[3] = (x8 + x6) >> 8;
181 blk[4] = (x8 - x6) >> 8;
182 blk[5] = (x0 - x4) >> 8;
183 blk[6] = (x3 - x2) >> 8;
184 blk[7] = (x7 - x1) >> 8;
185 }
186
187 inline void _ColIDCT(const int* blk, unsigned char *out, int stride) {
188 int x0, x1, x2, x3, x4, x5, x6, x7, x8;
189 if (!((x1 = blk[8 * 4] << 8)
190 | (x2 = blk[8 * 6])
191 | (x3 = blk[8 * 2])
192 | (x4 = blk[8 * 1])
193 | (x5 = blk[8 * 7])
194 | (x6 = blk[8 * 5])
195 | (x7 = blk[8 * 3])))
196 {
197 x1 = _Clip(((blk[0] + 32) >> 6) + 128);
198 for (x0 = 8; x0; --x0) {
199 *out = (unsigned char)x1;
200 out += stride;
201 }
202 return;
203 }
204 x0 = (blk[0] << 8) + 8192;
205 x8 = W7 * (x4 + x5) + 4;
206 x4 = (x8 + (W1 - W7) * x4) >> 3;
207 x5 = (x8 - (W1 + W7) * x5) >> 3;
208 x8 = W3 * (x6 + x7) + 4;
209 x6 = (x8 - (W3 - W5) * x6) >> 3;
210 x7 = (x8 - (W3 + W5) * x7) >> 3;
211 x8 = x0 + x1;
212 x0 -= x1;
213 x1 = W6 * (x3 + x2) + 4;
214 x2 = (x1 - (W2 + W6) * x2) >> 3;
215 x3 = (x1 + (W2 - W6) * x3) >> 3;
216 x1 = x4 + x6;
217 x4 -= x6;
218 x6 = x5 + x7;
219 x5 -= x7;
220 x7 = x8 + x3;
221 x8 -= x3;
222 x3 = x0 + x2;
223 x0 -= x2;
224 x2 = (181 * (x4 + x5) + 128) >> 8;
225 x4 = (181 * (x4 - x5) + 128) >> 8;
226 *out = _Clip(((x7 + x1) >> 14) + 128); out += stride;
227 *out = _Clip(((x3 + x2) >> 14) + 128); out += stride;
228 *out = _Clip(((x0 + x4) >> 14) + 128); out += stride;
229 *out = _Clip(((x8 + x6) >> 14) + 128); out += stride;
230 *out = _Clip(((x8 - x6) >> 14) + 128); out += stride;
231 *out = _Clip(((x0 - x4) >> 14) + 128); out += stride;
232 *out = _Clip(((x3 - x2) >> 14) + 128); out += stride;
233 *out = _Clip(((x7 - x1) >> 14) + 128);
234 }
235
236#define JPEG_DECODER_THROW(e) do { ctx.error = e; return; } while (0)
237
238 inline int _ShowBits(int bits) {
239 unsigned char newbyte;
240 if (!bits) return 0;
241 while (ctx.bufbits < bits) {
242 if (ctx.size <= 0) {
243 ctx.buf = (ctx.buf << 8) | 0xFF;
244 ctx.bufbits += 8;
245 continue;
246 }
247 newbyte = *ctx.pos++;
248 ctx.size--;
249 ctx.bufbits += 8;
250 ctx.buf = (ctx.buf << 8) | newbyte;
251 if (newbyte == 0xFF) {
252 if (ctx.size) {
253 unsigned char marker = *ctx.pos++;
254 ctx.size--;
255 switch (marker) {
256 case 0: break;
257 case 0xD9: ctx.size = 0; break;
258 default:
259 if ((marker & 0xF8) != 0xD0)
260 ctx.error = SyntaxError;
261 else {
262 ctx.buf = (ctx.buf << 8) | marker;
263 ctx.bufbits += 8;
264 }
265 }
266 }
267 else
268 ctx.error = SyntaxError;
269 }
270 }
271 return (ctx.buf >> (ctx.bufbits - bits)) & ((1 << bits) - 1);
272 }
273
274 inline void _SkipBits(int bits) {
275 if (ctx.bufbits < bits)
276 (void)_ShowBits(bits);
277 ctx.bufbits -= bits;
278 }
279
280 inline int _GetBits(int bits) {
281 int res = _ShowBits(bits);
282 _SkipBits(bits);
283 return res;
284 }
285
286 inline void _ByteAlign(void) {
287 ctx.bufbits &= 0xF8;
288 }
289
290 inline void _Skip(int count) {
291 ctx.pos += count;
292 ctx.size -= count;
293 ctx.length -= count;
294 if (ctx.size < 0) ctx.error = SyntaxError;
295 }
296
297 inline unsigned short _Decode16(const unsigned char *pos) {
298 return (pos[0] << 8) | pos[1];
299 }
300
301 inline void _DecodeLength(void) {
302 if (ctx.size < 2) JPEG_DECODER_THROW(SyntaxError);
303 ctx.length = _Decode16(ctx.pos);
304 if (ctx.length > ctx.size) JPEG_DECODER_THROW(SyntaxError);
305 _Skip(2);
306 }
307
308 inline void _SkipMarker(void) {
309 _DecodeLength();
310 _Skip(ctx.length);
311 }
312
313 inline void _DecodeSOF(void) {
314 int i, ssxmax = 0, ssymax = 0;
315 Component* c;
316 _DecodeLength();
317 if (ctx.length < 9) JPEG_DECODER_THROW(SyntaxError);
318 if (ctx.pos[0] != 8) JPEG_DECODER_THROW(Unsupported);
319 ctx.height = _Decode16(ctx.pos + 1);
320 ctx.width = _Decode16(ctx.pos + 3);
321 ctx.ncomp = ctx.pos[5];
322 _Skip(6);
323 switch (ctx.ncomp) {
324 case 1:
325 case 3:
326 break;
327 default:
329 }
330 if (ctx.length < (ctx.ncomp * 3)) JPEG_DECODER_THROW(SyntaxError);
331 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
332 c->cid = ctx.pos[0];
333 if (!(c->ssx = ctx.pos[1] >> 4)) JPEG_DECODER_THROW(SyntaxError);
334 if (c->ssx & (c->ssx - 1)) JPEG_DECODER_THROW(Unsupported); // non-power of two
335 if (!(c->ssy = ctx.pos[1] & 15)) JPEG_DECODER_THROW(SyntaxError);
336 if (c->ssy & (c->ssy - 1)) JPEG_DECODER_THROW(Unsupported); // non-power of two
337 if ((c->qtsel = ctx.pos[2]) & 0xFC) JPEG_DECODER_THROW(SyntaxError);
338 _Skip(3);
339 ctx.qtused |= 1 << c->qtsel;
340 if (c->ssx > ssxmax) ssxmax = c->ssx;
341 if (c->ssy > ssymax) ssymax = c->ssy;
342 }
343 ctx.mbsizex = ssxmax << 3;
344 ctx.mbsizey = ssymax << 3;
345 ctx.mbwidth = (ctx.width + ctx.mbsizex - 1) / ctx.mbsizex;
346 ctx.mbheight = (ctx.height + ctx.mbsizey - 1) / ctx.mbsizey;
347 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
348 c->width = (ctx.width * c->ssx + ssxmax - 1) / ssxmax;
349 c->stride = (c->width + 7) & 0x7FFFFFF8;
350 c->height = (ctx.height * c->ssy + ssymax - 1) / ssymax;
351 c->stride = ctx.mbwidth * ctx.mbsizex * c->ssx / ssxmax;
352 if (((c->width < 3) && (c->ssx != ssxmax)) || ((c->height < 3) && (c->ssy != ssymax))) JPEG_DECODER_THROW(Unsupported);
353 uint32_t step1 = ctx.mbheight * ctx.mbsizey;
354 uint32_t step2 = step1 * c->ssy;
355 uint32_t step3 = step2 / ssymax;
356 uint32_t total = c->stride * step3;
357
358 if (!(c->pixels = (unsigned char*)AllocMem(c->stride * (ctx.mbheight * ctx.mbsizey * c->ssy / ssymax)))) JPEG_DECODER_THROW(OutOfMemory);
359 }
360 if (ctx.ncomp == 3) {
361 ctx.rgb = (unsigned char*)AllocMem(ctx.width * ctx.height * ctx.ncomp);
362 if (!ctx.rgb) JPEG_DECODER_THROW(OutOfMemory);
363 }
364 _Skip(ctx.length);
365 }
366
367 inline void _DecodeDHT(void) {
368 int codelen, currcnt, remain, spread, i, j;
369 VlcCode *vlc;
370 unsigned char counts[16];
371 _DecodeLength();
372 while (ctx.length >= 17) {
373 i = ctx.pos[0];
374 if (i & 0xEC) JPEG_DECODER_THROW(SyntaxError);
375 if (i & 0x02) JPEG_DECODER_THROW(Unsupported);
376 i = (i | (i >> 3)) & 3; // combined DC/AC + tableid value
377 for (codelen = 1; codelen <= 16; ++codelen)
378 counts[codelen - 1] = ctx.pos[codelen];
379 _Skip(17);
380 vlc = &ctx.vlctab[i][0];
381 remain = spread = 65536;
382 for (codelen = 1; codelen <= 16; ++codelen) {
383 spread >>= 1;
384 currcnt = counts[codelen - 1];
385 if (!currcnt) continue;
386 if (ctx.length < currcnt) JPEG_DECODER_THROW(SyntaxError);
387 remain -= currcnt << (16 - codelen);
388 if (remain < 0) JPEG_DECODER_THROW(SyntaxError);
389 for (i = 0; i < currcnt; ++i) {
390 register unsigned char code = ctx.pos[i];
391 for (j = spread; j; --j) {
392 vlc->bits = (unsigned char)codelen;
393 vlc->code = code;
394 ++vlc;
395 }
396 }
397 _Skip(currcnt);
398 }
399 while (remain--) {
400 vlc->bits = 0;
401 ++vlc;
402 }
403 }
404 if (ctx.length) JPEG_DECODER_THROW(SyntaxError);
405 }
406
407 inline void _DecodeDQT(void) {
408 int i;
409 unsigned char *t;
410 _DecodeLength();
411 while (ctx.length >= 65) {
412 i = ctx.pos[0];
413 if (i & 0xFC) JPEG_DECODER_THROW(SyntaxError);
414 ctx.qtavail |= 1 << i;
415 t = &ctx.qtab[i][0];
416 for (i = 0; i < 64; ++i)
417 t[i] = ctx.pos[i + 1];
418 _Skip(65);
419 }
420 if (ctx.length) JPEG_DECODER_THROW(SyntaxError);
421 }
422
423 inline void _DecodeDRI(void) {
424 _DecodeLength();
425 if (ctx.length < 2) JPEG_DECODER_THROW(SyntaxError);
426 ctx.rstinterval = _Decode16(ctx.pos);
427 _Skip(ctx.length);
428 }
429
430 inline int _GetVLC(VlcCode* vlc, unsigned char* code) {
431 int value = _ShowBits(16);
432 int bits = vlc[value].bits;
433 if (!bits) { ctx.error = SyntaxError; return 0; }
434 _SkipBits(bits);
435 value = vlc[value].code;
436 if (code) *code = (unsigned char)value;
437 bits = value & 15;
438 if (!bits) return 0;
439 value = _GetBits(bits);
440 if (value < (1 << (bits - 1)))
441 value += ((-1) << bits) + 1;
442 return value;
443 }
444
445 inline void _DecodeBlock(Component* c, unsigned char* out) {
446 unsigned char code;
447 int value, coef = 0;
448 memset(ctx.block, 0, sizeof(ctx.block));
449 c->dcpred += _GetVLC(&ctx.vlctab[c->dctabsel][0], NULL);
450 ctx.block[0] = (c->dcpred) * ctx.qtab[c->qtsel][0];
451 do {
452 value = _GetVLC(&ctx.vlctab[c->actabsel][0], &code);
453 if (!code) break; // EOB
454 if (!(code & 0x0F) && (code != 0xF0)) JPEG_DECODER_THROW(SyntaxError);
455 coef += (code >> 4) + 1;
456 if (coef > 63) JPEG_DECODER_THROW(SyntaxError);
457 ctx.block[(int)ZZ[coef]] = value * ctx.qtab[c->qtsel][coef];
458 } while (coef < 63);
459 for (coef = 0; coef < 64; coef += 8)
460 _RowIDCT(&ctx.block[coef]);
461 for (coef = 0; coef < 8; ++coef)
462 _ColIDCT(&ctx.block[coef], &out[coef], c->stride);
463 }
464
465 inline void _DecodeScan(void) {
466 int i, mbx, mby, sbx, sby;
467 int rstcount = ctx.rstinterval, nextrst = 0;
468 Component* c;
469 _DecodeLength();
470 if (ctx.length < (4 + 2 * ctx.ncomp)) JPEG_DECODER_THROW(SyntaxError);
471 if (ctx.pos[0] != ctx.ncomp) JPEG_DECODER_THROW(Unsupported);
472 _Skip(1);
473 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
474 if (ctx.pos[0] != c->cid) JPEG_DECODER_THROW(SyntaxError);
475 if (ctx.pos[1] & 0xEE) JPEG_DECODER_THROW(SyntaxError);
476 c->dctabsel = ctx.pos[1] >> 4;
477 c->actabsel = (ctx.pos[1] & 1) | 2;
478 _Skip(2);
479 }
480 if (ctx.pos[0] || (ctx.pos[1] != 63) || ctx.pos[2]) JPEG_DECODER_THROW(Unsupported);
481 _Skip(ctx.length);
482 for (mby = 0; mby < ctx.mbheight; ++mby)
483 for (mbx = 0; mbx < ctx.mbwidth; ++mbx) {
484 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c)
485 for (sby = 0; sby < c->ssy; ++sby)
486 for (sbx = 0; sbx < c->ssx; ++sbx) {
487 _DecodeBlock(c, &c->pixels[((mby * c->ssy + sby) * c->stride + mbx * c->ssx + sbx) << 3]);
488 if (ctx.error)
489 return;
490 }
491 if (ctx.rstinterval && !(--rstcount)) {
492 _ByteAlign();
493 i = _GetBits(16);
494 if (((i & 0xFFF8) != 0xFFD0) || ((i & 7) != nextrst)) JPEG_DECODER_THROW(SyntaxError);
495 nextrst = (nextrst + 1) & 7;
496 rstcount = ctx.rstinterval;
497 for (i = 0; i < 3; ++i)
498 ctx.comp[i].dcpred = 0;
499 }
500 }
501 ctx.error = Internal_Finished;
502 }
503
504 enum {
505 CF4A = (-9),
506 CF4B = (111),
507 CF4C = (29),
508 CF4D = (-3),
509 CF3A = (28),
510 CF3B = (109),
511 CF3C = (-9),
512 CF3X = (104),
513 CF3Y = (27),
514 CF3Z = (-3),
515 CF2A = (139),
516 CF2B = (-11),
517 };
518
519 inline unsigned char CF(const int x) {
520 return _Clip((x + 64) >> 7);
521 }
522
523 inline void _UpsampleH(Component* c) {
524 const int xmax = c->width - 3;
525 unsigned char *out, *lin, *lout;
526 int x, y;
527 out = (unsigned char*)AllocMem((c->width * c->height) << 1);
529 lin = c->pixels;
530 lout = out;
531 for (y = c->height; y; --y) {
532 lout[0] = CF(CF2A * lin[0] + CF2B * lin[1]);
533 lout[1] = CF(CF3X * lin[0] + CF3Y * lin[1] + CF3Z * lin[2]);
534 lout[2] = CF(CF3A * lin[0] + CF3B * lin[1] + CF3C * lin[2]);
535 for (x = 0; x < xmax; ++x) {
536 lout[(x << 1) + 3] = CF(CF4A * lin[x] + CF4B * lin[x + 1] + CF4C * lin[x + 2] + CF4D * lin[x + 3]);
537 lout[(x << 1) + 4] = CF(CF4D * lin[x] + CF4C * lin[x + 1] + CF4B * lin[x + 2] + CF4A * lin[x + 3]);
538 }
539 lin += c->stride;
540 lout += c->width << 1;
541 lout[-3] = CF(CF3A * lin[-1] + CF3B * lin[-2] + CF3C * lin[-3]);
542 lout[-2] = CF(CF3X * lin[-1] + CF3Y * lin[-2] + CF3Z * lin[-3]);
543 lout[-1] = CF(CF2A * lin[-1] + CF2B * lin[-2]);
544 }
545 c->width <<= 1;
546 c->stride = c->width;
547 FreeMem(c->pixels);
548 c->pixels = out;
549 }
550
551 inline void _UpsampleV(Component* c) {
552 const int w = c->width, s1 = c->stride, s2 = s1 + s1;
553 unsigned char *out, *cin, *cout;
554 int x, y;
555 out = (unsigned char*)AllocMem((c->width * c->height) << 1);
557 for (x = 0; x < w; ++x) {
558 cin = &c->pixels[x];
559 cout = &out[x];
560 *cout = CF(CF2A * cin[0] + CF2B * cin[s1]); cout += w;
561 *cout = CF(CF3X * cin[0] + CF3Y * cin[s1] + CF3Z * cin[s2]); cout += w;
562 *cout = CF(CF3A * cin[0] + CF3B * cin[s1] + CF3C * cin[s2]); cout += w;
563 cin += s1;
564 for (y = c->height - 3; y; --y) {
565 *cout = CF(CF4A * cin[-s1] + CF4B * cin[0] + CF4C * cin[s1] + CF4D * cin[s2]); cout += w;
566 *cout = CF(CF4D * cin[-s1] + CF4C * cin[0] + CF4B * cin[s1] + CF4A * cin[s2]); cout += w;
567 cin += s1;
568 }
569 cin += s1;
570 *cout = CF(CF3A * cin[0] + CF3B * cin[-s1] + CF3C * cin[-s2]); cout += w;
571 *cout = CF(CF3X * cin[0] + CF3Y * cin[-s1] + CF3Z * cin[-s2]); cout += w;
572 *cout = CF(CF2A * cin[0] + CF2B * cin[-s1]);
573 }
574 c->height <<= 1;
575 c->stride = c->width;
576 FreeMem(c->pixels);
577 c->pixels = out;
578 }
579
580 inline void _Convert() {
581 int i;
582 Component* c;
583 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
584 while ((c->width < ctx.width) || (c->height < ctx.height)) {
585 if (c->width < ctx.width) _UpsampleH(c);
586 if (ctx.error) return;
587 if (c->height < ctx.height) _UpsampleV(c);
588 if (ctx.error) return;
589 }
590 if ((c->width < ctx.width) || (c->height < ctx.height)) JPEG_DECODER_THROW(InternalError);
591 }
592
593 if (ctx.ncomp == 3) {
594 // convert to RGB
595 int x, yy;
596 unsigned char *prgb = ctx.rgb;
597 const unsigned char *py = ctx.comp[0].pixels;
598 const unsigned char *pcb = ctx.comp[1].pixels;
599 const unsigned char *pcr = ctx.comp[2].pixels;
600 for (yy = ctx.height; yy; --yy) {
601 for (x = 0; x < ctx.width; ++x) {
602 register int y = py[x] << 8;
603 register int cb = pcb[x] - 128;
604 register int cr = pcr[x] - 128;
605 *prgb++ = _Clip((y + 359 * cr + 128) >> 8);
606 *prgb++ = _Clip((y - 88 * cb - 183 * cr + 128) >> 8);
607 *prgb++ = _Clip((y + 454 * cb + 128) >> 8);
608 }
609 py += ctx.comp[0].stride;
610 pcb += ctx.comp[1].stride;
611 pcr += ctx.comp[2].stride;
612 }
613 }
614 else if (ctx.comp[0].width != ctx.comp[0].stride) {
615 // grayscale -> only remove stride
616 unsigned char *pin = &ctx.comp[0].pixels[ctx.comp[0].stride];
617 unsigned char *pout = &ctx.comp[0].pixels[ctx.comp[0].width];
618 int y;
619 for (y = ctx.comp[0].height - 1; y; --y) {
620 memcpy(pout, pin, ctx.comp[0].width);
621 pin += ctx.comp[0].stride;
622 pout += ctx.comp[0].width;
623 }
624 ctx.comp[0].stride = ctx.comp[0].width;
625 }
626 }
627
628 DecodeResult _Decode(const unsigned char* jpeg, const int size) {
629 ctx.pos = (const unsigned char*)jpeg;
630 ctx.size = size & 0x7FFFFFFF;
631 if (ctx.size < 2) return NotAJpeg;
632 if ((ctx.pos[0] ^ 0xFF) | (ctx.pos[1] ^ 0xD8)) return NotAJpeg;
633 _Skip(2);
634 while (!ctx.error) {
635 if ((ctx.size < 2) || (ctx.pos[0] != 0xFF)) return SyntaxError;
636 _Skip(2);
637 switch (ctx.pos[-1]) {
638 case 0xC0: _DecodeSOF(); break;
639 case 0xC4: _DecodeDHT(); break;
640 case 0xDB: _DecodeDQT(); break;
641 case 0xDD: _DecodeDRI(); break;
642 case 0xDA: _DecodeScan(); break;
643 case 0xFE: _SkipMarker(); break;
644 default:
645 if ((ctx.pos[-1] & 0xF0) == 0xE0){
646 _SkipMarker();
647 }
648 else
649 return Unsupported;
650 }
651 }
652 if (ctx.error != Internal_Finished) return ctx.error;
653 ctx.error = OK;
654 _Convert();
655 return ctx.error;
656 }
657 };
658
659
660 inline Decoder::Decoder(const unsigned char* data, uint32_t size, void *(*allocFunc)(uint32_t), void(*freeFunc)(void*))
661 : AllocMem(allocFunc)
662 , FreeMem(freeFunc)
663 {
664 // should be static data, but this keeps us as a header
665 char temp[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18,
666 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
667 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45,
668 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 };
669 memcpy(ZZ, temp, sizeof(ZZ));
670 memset(&ctx, 0, sizeof(Context));
671 /* _KePrint("ctx -> %x calling decoder, %x\r\n", &ctx, data);
672 _KePrint("size : %d _Decode %x\r\n", size, &Decoder::_Decode);*/
673 _Decode(data, size);
674 }
675
676 inline Decoder::DecodeResult Decoder::GetResult() const { return ctx.error; }
677 inline int Decoder::GetWidth() const { return ctx.width; }
678 inline int Decoder::GetHeight() const { return ctx.height; }
679 inline bool Decoder::IsColor() const { return ctx.ncomp != 1; }
680 inline unsigned char* Decoder::GetImage() const { return (ctx.ncomp == 1) ? ctx.comp[0].pixels : ctx.rgb; }
681 inline uint32_t Decoder::GetImageSize(void) const { return ctx.width * ctx.height * ctx.ncomp; }
682
684 {
685 int i;
686 for (i = 0; i < 3; ++i)
687 if (ctx.comp[i].pixels) FreeMem((void*)ctx.comp[i].pixels);
688 if (ctx.rgb) FreeMem((void*)ctx.rgb);
689 }
690
691}
692
693#endif
XETime t
Definition main.cpp:53
void * memcpy(void *Dest, const void *Src, ACPI_SIZE Count)
Definition utclib.c:310
void * memset(void *Dest, int Value, ACPI_SIZE Count)
Definition utclib.c:346
unsigned int uint32_t
Definition acefiex.h:163
UINT32 void * Context
Definition acevents.h:322
#define NULL
Definition actypes.h:561
Definition nanojpg.h:40
Decoder(const unsigned char *data, uint32_t size, void *(*allocFunc)(uint32_t), void(*freeFunc)(void *))
Definition nanojpg.h:660
bool IsColor() const
Definition nanojpg.h:679
int GetWidth() const
Definition nanojpg.h:677
uint32_t GetImageSize() const
Definition nanojpg.h:681
~Decoder()
Definition nanojpg.h:683
unsigned char * GetImage() const
Definition nanojpg.h:680
int GetHeight() const
Definition nanojpg.h:678
DecodeResult
Definition nanojpg.h:43
@ OK
Definition nanojpg.h:44
@ InternalError
Definition nanojpg.h:48
@ Unsupported
Definition nanojpg.h:46
@ OutOfMemory
Definition nanojpg.h:47
@ Internal_Finished
Definition nanojpg.h:50
@ SyntaxError
Definition nanojpg.h:49
@ NotAJpeg
Definition nanojpg.h:45
DecodeResult GetResult() const
Definition nanojpg.h:676
Definition nanojpg.h:38
ostream cout(static_cast< streambuf * >(0))
istream cin(static_cast< streambuf * >(0))
#define JPEG_DECODER_THROW(e)
Definition nanojpg.h:236
int x
Definition term.cpp:49