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 if (!(c->pixels = (unsigned char*)AllocMem(c->stride * (ctx.mbheight * ctx.mbsizey * c->ssy / ssymax)))) JPEG_DECODER_THROW(OutOfMemory);
354 }
355 if (ctx.ncomp == 3) {
356 ctx.rgb = (unsigned char*)AllocMem(ctx.width * ctx.height * ctx.ncomp);
357 if (!ctx.rgb) JPEG_DECODER_THROW(OutOfMemory);
358 }
359 _Skip(ctx.length);
360 }
361
362 inline void _DecodeDHT(void) {
363 int codelen, currcnt, remain, spread, i, j;
364 VlcCode *vlc;
365 unsigned char counts[16];
366 _DecodeLength();
367 while (ctx.length >= 17) {
368 i = ctx.pos[0];
369 if (i & 0xEC) JPEG_DECODER_THROW(SyntaxError);
370 if (i & 0x02) JPEG_DECODER_THROW(Unsupported);
371 i = (i | (i >> 3)) & 3; // combined DC/AC + tableid value
372 for (codelen = 1; codelen <= 16; ++codelen)
373 counts[codelen - 1] = ctx.pos[codelen];
374 _Skip(17);
375 vlc = &ctx.vlctab[i][0];
376 remain = spread = 65536;
377 for (codelen = 1; codelen <= 16; ++codelen) {
378 spread >>= 1;
379 currcnt = counts[codelen - 1];
380 if (!currcnt) continue;
381 if (ctx.length < currcnt) JPEG_DECODER_THROW(SyntaxError);
382 remain -= currcnt << (16 - codelen);
383 if (remain < 0) JPEG_DECODER_THROW(SyntaxError);
384 for (i = 0; i < currcnt; ++i) {
385 register unsigned char code = ctx.pos[i];
386 for (j = spread; j; --j) {
387 vlc->bits = (unsigned char)codelen;
388 vlc->code = code;
389 ++vlc;
390 }
391 }
392 _Skip(currcnt);
393 }
394 while (remain--) {
395 vlc->bits = 0;
396 ++vlc;
397 }
398 }
399 if (ctx.length) JPEG_DECODER_THROW(SyntaxError);
400 }
401
402 inline void _DecodeDQT(void) {
403 int i;
404 unsigned char *t;
405 _DecodeLength();
406 while (ctx.length >= 65) {
407 i = ctx.pos[0];
408 if (i & 0xFC) JPEG_DECODER_THROW(SyntaxError);
409 ctx.qtavail |= 1 << i;
410 t = &ctx.qtab[i][0];
411 for (i = 0; i < 64; ++i)
412 t[i] = ctx.pos[i + 1];
413 _Skip(65);
414 }
415 if (ctx.length) JPEG_DECODER_THROW(SyntaxError);
416 }
417
418 inline void _DecodeDRI(void) {
419 _DecodeLength();
420 if (ctx.length < 2) JPEG_DECODER_THROW(SyntaxError);
421 ctx.rstinterval = _Decode16(ctx.pos);
422 _Skip(ctx.length);
423 }
424
425 inline int _GetVLC(VlcCode* vlc, unsigned char* code) {
426 int value = _ShowBits(16);
427 int bits = vlc[value].bits;
428 if (!bits) { ctx.error = SyntaxError; return 0; }
429 _SkipBits(bits);
430 value = vlc[value].code;
431 if (code) *code = (unsigned char)value;
432 bits = value & 15;
433 if (!bits) return 0;
434 value = _GetBits(bits);
435 if (value < (1 << (bits - 1)))
436 value += ((-1) << bits) + 1;
437 return value;
438 }
439
440 inline void _DecodeBlock(Component* c, unsigned char* out) {
441 unsigned char code;
442 int value, coef = 0;
443 memset(ctx.block, 0, sizeof(ctx.block));
444 c->dcpred += _GetVLC(&ctx.vlctab[c->dctabsel][0], NULL);
445 ctx.block[0] = (c->dcpred) * ctx.qtab[c->qtsel][0];
446 do {
447 value = _GetVLC(&ctx.vlctab[c->actabsel][0], &code);
448 if (!code) break; // EOB
449 if (!(code & 0x0F) && (code != 0xF0)) JPEG_DECODER_THROW(SyntaxError);
450 coef += (code >> 4) + 1;
451 if (coef > 63) JPEG_DECODER_THROW(SyntaxError);
452 ctx.block[(int)ZZ[coef]] = value * ctx.qtab[c->qtsel][coef];
453 } while (coef < 63);
454 for (coef = 0; coef < 64; coef += 8)
455 _RowIDCT(&ctx.block[coef]);
456 for (coef = 0; coef < 8; ++coef)
457 _ColIDCT(&ctx.block[coef], &out[coef], c->stride);
458 }
459
460 inline void _DecodeScan(void) {
461 int i, mbx, mby, sbx, sby;
462 int rstcount = ctx.rstinterval, nextrst = 0;
463 Component* c;
464 _DecodeLength();
465 if (ctx.length < (4 + 2 * ctx.ncomp)) JPEG_DECODER_THROW(SyntaxError);
466 if (ctx.pos[0] != ctx.ncomp) JPEG_DECODER_THROW(Unsupported);
467 _Skip(1);
468 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
469 if (ctx.pos[0] != c->cid) JPEG_DECODER_THROW(SyntaxError);
470 if (ctx.pos[1] & 0xEE) JPEG_DECODER_THROW(SyntaxError);
471 c->dctabsel = ctx.pos[1] >> 4;
472 c->actabsel = (ctx.pos[1] & 1) | 2;
473 _Skip(2);
474 }
475 if (ctx.pos[0] || (ctx.pos[1] != 63) || ctx.pos[2]) JPEG_DECODER_THROW(Unsupported);
476 _Skip(ctx.length);
477 for (mby = 0; mby < ctx.mbheight; ++mby)
478 for (mbx = 0; mbx < ctx.mbwidth; ++mbx) {
479 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c)
480 for (sby = 0; sby < c->ssy; ++sby)
481 for (sbx = 0; sbx < c->ssx; ++sbx) {
482 _DecodeBlock(c, &c->pixels[((mby * c->ssy + sby) * c->stride + mbx * c->ssx + sbx) << 3]);
483 if (ctx.error)
484 return;
485 }
486 if (ctx.rstinterval && !(--rstcount)) {
487 _ByteAlign();
488 i = _GetBits(16);
489 if (((i & 0xFFF8) != 0xFFD0) || ((i & 7) != nextrst)) JPEG_DECODER_THROW(SyntaxError);
490 nextrst = (nextrst + 1) & 7;
491 rstcount = ctx.rstinterval;
492 for (i = 0; i < 3; ++i)
493 ctx.comp[i].dcpred = 0;
494 }
495 }
496 ctx.error = Internal_Finished;
497 }
498
499 enum {
500 CF4A = (-9),
501 CF4B = (111),
502 CF4C = (29),
503 CF4D = (-3),
504 CF3A = (28),
505 CF3B = (109),
506 CF3C = (-9),
507 CF3X = (104),
508 CF3Y = (27),
509 CF3Z = (-3),
510 CF2A = (139),
511 CF2B = (-11),
512 };
513
514 inline unsigned char CF(const int x) {
515 return _Clip((x + 64) >> 7);
516 }
517
518 inline void _UpsampleH(Component* c) {
519 const int xmax = c->width - 3;
520 unsigned char *out, *lin, *lout;
521 int x, y;
522 out = (unsigned char*)AllocMem((c->width * c->height) << 1);
524 lin = c->pixels;
525 lout = out;
526 for (y = c->height; y; --y) {
527 lout[0] = CF(CF2A * lin[0] + CF2B * lin[1]);
528 lout[1] = CF(CF3X * lin[0] + CF3Y * lin[1] + CF3Z * lin[2]);
529 lout[2] = CF(CF3A * lin[0] + CF3B * lin[1] + CF3C * lin[2]);
530 for (x = 0; x < xmax; ++x) {
531 lout[(x << 1) + 3] = CF(CF4A * lin[x] + CF4B * lin[x + 1] + CF4C * lin[x + 2] + CF4D * lin[x + 3]);
532 lout[(x << 1) + 4] = CF(CF4D * lin[x] + CF4C * lin[x + 1] + CF4B * lin[x + 2] + CF4A * lin[x + 3]);
533 }
534 lin += c->stride;
535 lout += c->width << 1;
536 lout[-3] = CF(CF3A * lin[-1] + CF3B * lin[-2] + CF3C * lin[-3]);
537 lout[-2] = CF(CF3X * lin[-1] + CF3Y * lin[-2] + CF3Z * lin[-3]);
538 lout[-1] = CF(CF2A * lin[-1] + CF2B * lin[-2]);
539 }
540 c->width <<= 1;
541 c->stride = c->width;
542 FreeMem(c->pixels);
543 c->pixels = out;
544 }
545
546 inline void _UpsampleV(Component* c) {
547 const int w = c->width, s1 = c->stride, s2 = s1 + s1;
548 unsigned char *out, *cin, *cout;
549 int x, y;
550 out = (unsigned char*)AllocMem((c->width * c->height) << 1);
552 for (x = 0; x < w; ++x) {
553 cin = &c->pixels[x];
554 cout = &out[x];
555 *cout = CF(CF2A * cin[0] + CF2B * cin[s1]); cout += w;
556 *cout = CF(CF3X * cin[0] + CF3Y * cin[s1] + CF3Z * cin[s2]); cout += w;
557 *cout = CF(CF3A * cin[0] + CF3B * cin[s1] + CF3C * cin[s2]); cout += w;
558 cin += s1;
559 for (y = c->height - 3; y; --y) {
560 *cout = CF(CF4A * cin[-s1] + CF4B * cin[0] + CF4C * cin[s1] + CF4D * cin[s2]); cout += w;
561 *cout = CF(CF4D * cin[-s1] + CF4C * cin[0] + CF4B * cin[s1] + CF4A * cin[s2]); cout += w;
562 cin += s1;
563 }
564 cin += s1;
565 *cout = CF(CF3A * cin[0] + CF3B * cin[-s1] + CF3C * cin[-s2]); cout += w;
566 *cout = CF(CF3X * cin[0] + CF3Y * cin[-s1] + CF3Z * cin[-s2]); cout += w;
567 *cout = CF(CF2A * cin[0] + CF2B * cin[-s1]);
568 }
569 c->height <<= 1;
570 c->stride = c->width;
571 FreeMem(c->pixels);
572 c->pixels = out;
573 }
574
575 inline void _Convert() {
576 int i;
577 Component* c;
578 for (i = 0, c = ctx.comp; i < ctx.ncomp; ++i, ++c) {
579 while ((c->width < ctx.width) || (c->height < ctx.height)) {
580 if (c->width < ctx.width) _UpsampleH(c);
581 if (ctx.error) return;
582 if (c->height < ctx.height) _UpsampleV(c);
583 if (ctx.error) return;
584 }
585 if ((c->width < ctx.width) || (c->height < ctx.height)) JPEG_DECODER_THROW(InternalError);
586 }
587
588 if (ctx.ncomp == 3) {
589 // convert to RGB
590 int x, yy;
591 unsigned char *prgb = ctx.rgb;
592 const unsigned char *py = ctx.comp[0].pixels;
593 const unsigned char *pcb = ctx.comp[1].pixels;
594 const unsigned char *pcr = ctx.comp[2].pixels;
595 for (yy = ctx.height; yy; --yy) {
596 for (x = 0; x < ctx.width; ++x) {
597 register int y = py[x] << 8;
598 register int cb = pcb[x] - 128;
599 register int cr = pcr[x] - 128;
600 *prgb++ = _Clip((y + 359 * cr + 128) >> 8);
601 *prgb++ = _Clip((y - 88 * cb - 183 * cr + 128) >> 8);
602 *prgb++ = _Clip((y + 454 * cb + 128) >> 8);
603 }
604 py += ctx.comp[0].stride;
605 pcb += ctx.comp[1].stride;
606 pcr += ctx.comp[2].stride;
607 }
608 }
609 else if (ctx.comp[0].width != ctx.comp[0].stride) {
610 // grayscale -> only remove stride
611 unsigned char *pin = &ctx.comp[0].pixels[ctx.comp[0].stride];
612 unsigned char *pout = &ctx.comp[0].pixels[ctx.comp[0].width];
613 int y;
614 for (y = ctx.comp[0].height - 1; y; --y) {
615 memcpy(pout, pin, ctx.comp[0].width);
616 pin += ctx.comp[0].stride;
617 pout += ctx.comp[0].width;
618 }
619 ctx.comp[0].stride = ctx.comp[0].width;
620 }
621 }
622
623 DecodeResult _Decode(const unsigned char* jpeg, const int size) {
624 ctx.pos = (const unsigned char*)jpeg;
625 ctx.size = size & 0x7FFFFFFF;
626 if (ctx.size < 2) return NotAJpeg;
627 if ((ctx.pos[0] ^ 0xFF) | (ctx.pos[1] ^ 0xD8)) return NotAJpeg;
628 _Skip(2);
629 while (!ctx.error) {
630 if ((ctx.size < 2) || (ctx.pos[0] != 0xFF)) return SyntaxError;
631 _Skip(2);
632 switch (ctx.pos[-1]) {
633 case 0xC0: _DecodeSOF(); break;
634 case 0xC4: _DecodeDHT(); break;
635 case 0xDB: _DecodeDQT(); break;
636 case 0xDD: _DecodeDRI(); break;
637 case 0xDA: _DecodeScan(); break;
638 case 0xFE: _SkipMarker(); break;
639 default:
640 if ((ctx.pos[-1] & 0xF0) == 0xE0){
641 _SkipMarker();
642 //_KePrint("Skip marker found \r\n");
643 }
644 else
645 return Unsupported;
646 }
647 }
648 _KePrint("Converting \n");
649 if (ctx.error != Internal_Finished) return ctx.error;
650 ctx.error = OK;
651 _Convert();
652 return ctx.error;
653 }
654 };
655
656
657 inline Decoder::Decoder(const unsigned char* data, uint32_t size, void *(*allocFunc)(uint32_t), void(*freeFunc)(void*))
658 : AllocMem(allocFunc)
659 , FreeMem(freeFunc)
660 {
661 // should be static data, but this keeps us as a header
662 char temp[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18,
663 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35,
664 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45,
665 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 };
666 memcpy(ZZ, temp, sizeof(ZZ));
667 memset(&ctx, 0, sizeof(Context));
668 _KePrint("ctx -> %x \r\n", &ctx);
669 _Decode(data, size);
670 }
671
672 inline Decoder::DecodeResult Decoder::GetResult() const { return ctx.error; }
673 inline int Decoder::GetWidth() const { return ctx.width; }
674 inline int Decoder::GetHeight() const { return ctx.height; }
675 inline bool Decoder::IsColor() const { return ctx.ncomp != 1; }
676 inline unsigned char* Decoder::GetImage() const { return (ctx.ncomp == 1) ? ctx.comp[0].pixels : ctx.rgb; }
677 inline uint32_t Decoder::GetImageSize(void) const { return ctx.width * ctx.height * ctx.ncomp; }
678
680 {
681 int i;
682 for (i = 0; i < 3; ++i)
683 if (ctx.comp[i].pixels) FreeMem((void*)ctx.comp[i].pixels);
684 if (ctx.rgb) FreeMem((void*)ctx.rgb);
685 }
686
687}
688
689#endif
XETime t
Definition main.cpp:53
XE_LIB void _KePrint(const char *text,...)
_KePrint – kernel printing function, uses kernel serial console to print strings
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:657
bool IsColor() const
Definition nanojpg.h:675
int GetWidth() const
Definition nanojpg.h:673
uint32_t GetImageSize() const
Definition nanojpg.h:677
~Decoder()
Definition nanojpg.h:679
unsigned char * GetImage() const
Definition nanojpg.h:676
int GetHeight() const
Definition nanojpg.h:674
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:672
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