Rev 4634 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5 | Plagman | 1 | /************************************************************************************************** |
2 | KPLIB.C: Ken's Picture LIBrary written by Ken Silverman |
||
1440 | terminx | 3 | Copyright (c) 1998-2008 Ken Silverman |
5 | Plagman | 4 | Ken Silverman's official web site: http://advsys.net/ken |
5 | |||
6 | Features of KPLIB.C: |
||
1440 | terminx | 7 | * Routines for decoding JPG/PNG/GIF/PCX/TGA/BMP/DDS/CEL. |
5 | Plagman | 8 | See kpgetdim(), kprender(), and optional helper function: kpzload(). |
1440 | terminx | 9 | * Routines for reading files out of ZIP/GRP files. All ZIP/GRP functions start with "kz". |
5 | Plagman | 10 | * Multi-platform support: Dos/Windows/Linux/Mac/etc.. |
11 | * Compact code, all in a single source file. Yeah, bad design on my part... but makes life |
||
12 | easier for everyone else - you simply add a single C file to your project, throw a few |
||
13 | externs in there, add the function calls, and you're done! |
||
14 | |||
15 | Brief history: |
||
16 | 1998?: Wrote KPEG, a JPEG viewer for DOS |
||
17 | 2000: Wrote KPNG, a PNG viewer for DOS |
||
18 | 2001: Combined KPEG & KPNG, ported to Visual C, and made it into a library called KPLIB.C |
||
1440 | terminx | 19 | 2002: Added support for TGA,GIF,CEL,ZIP |
5 | Plagman | 20 | 2003: Added support for BMP |
21 | 05/18/2004: Added support for 8&24 bit PCX |
||
22 | 12/09/2005: Added support for progressive JPEG |
||
194 | terminx | 23 | 01/05/2006: Added support for DDS |
1440 | terminx | 24 | 07/28/2007: Added support for GRP (Build Engine archive) |
5 | Plagman | 25 | |
26 | I offer this code to the community for free use - all I ask is that my name be included in the |
||
27 | credits. |
||
28 | |||
29 | -Ken S. |
||
30 | **************************************************************************************************/ |
||
31 | |||
512 | Plagman | 32 | #include "compat.h" |
4634 | terminx | 33 | #include "kplib.h" |
5 | Plagman | 34 | #include <string.h> |
35 | #include <fcntl.h> |
||
36 | #include <sys/types.h> |
||
37 | #include <sys/stat.h> |
||
38 | #include <stdio.h> |
||
39 | #include <stdlib.h> |
||
40 | |||
2630 | helixhorne | 41 | #if defined(__POWERPC__) || defined(GEKKO) |
5 | Plagman | 42 | #define BIGENDIAN 1 |
43 | #endif |
||
44 | |||
45 | #ifdef BIGENDIAN |
||
1205 | terminx | 46 | static uint32_t LSWAPIB(uint32_t a) { return(((a>>8)&0xff00)+((a&0xff00)<<8)+(a<<24)+(a>>24)); } |
47 | static uint16_t SSWAPIB(uint16_t a) { return((a>>8)+(a<<8)); } |
||
5 | Plagman | 48 | #define LSWAPIL(a) (a) |
49 | #define SSWAPIL(a) (a) |
||
50 | #else |
||
51 | #define LSWAPIB(a) (a) |
||
52 | #define SSWAPIB(a) (a) |
||
1205 | terminx | 53 | static uint32_t LSWAPIL(uint32_t a) { return(((a>>8)&0xff00)+((a&0xff00)<<8)+(a<<24)+(a>>24)); } |
54 | static uint16_t SSWAPIL(uint16_t a) { return((a>>8)+(a<<8)); } |
||
5 | Plagman | 55 | #endif |
56 | |||
1479 | terminx | 57 | #if !defined(_WIN32) |
5 | Plagman | 58 | #include <unistd.h> |
59 | #include <dirent.h> |
||
1442 | qbix79 | 60 | typedef long long __int64; |
1440 | terminx | 61 | static __inline int32_t _lrotl(int32_t i, int sh) |
109 | terminx | 62 | { return((i>>(-sh))|(i<<sh)); } |
2008 | helixhorne | 63 | /*__inline*/ int32_t filelength(int h) |
5 | Plagman | 64 | { |
109 | terminx | 65 | struct stat st; |
66 | if (fstat(h,&st) < 0) return(-1); |
||
67 | return(st.st_size); |
||
5 | Plagman | 68 | } |
69 | #define _fileno fileno |
||
70 | #else |
||
71 | #include <io.h> |
||
72 | #endif |
||
73 | |||
1479 | terminx | 74 | #if defined(_WIN32) |
5 | Plagman | 75 | #define WIN32_LEAN_AND_MEAN |
76 | #include <windows.h> |
||
77 | #endif |
||
78 | |||
79 | #ifndef O_BINARY |
||
80 | #define O_BINARY 0 |
||
81 | #endif |
||
82 | #if !defined(max) |
||
83 | #define max(a,b) (((a) > (b)) ? (a) : (b)) |
||
84 | #endif |
||
85 | #if !defined(min) |
||
86 | #define min(a,b) (((a) < (b)) ? (a) : (b)) |
||
87 | #endif |
||
88 | |||
2292 | helixhorne | 89 | #if defined __clang__ && __clang_major__==3 |
90 | // clang 3.1 SVN r149129, assertion failure with inline asm |
||
91 | # define NOASM 1 |
||
92 | #endif |
||
93 | |||
5 | Plagman | 94 | #if defined(__GNUC__) |
4513 | hendricks2 | 95 | #undef _inline |
5 | Plagman | 96 | #define _inline inline |
97 | #endif |
||
98 | |||
109 | terminx | 99 | //use GCC-specific extension to force symbol name to be something in particular to override underscoring. |
5 | Plagman | 100 | #if defined(__GNUC__) && defined(__i386__) && !defined(NOASM) |
101 | #define ASMNAME(x) asm(x) |
||
102 | #else |
||
103 | #define ASMNAME(x) |
||
104 | #endif |
||
105 | |||
1440 | terminx | 106 | static intptr_t frameplace; |
4634 | terminx | 107 | static int32_t bytesperline, xres, yres; |
5 | Plagman | 108 | |
1205 | terminx | 109 | static const int32_t pow2mask[32] = |
584 | terminx | 110 | { |
111 | 0x00000000,0x00000001,0x00000003,0x00000007, |
||
112 | 0x0000000f,0x0000001f,0x0000003f,0x0000007f, |
||
113 | 0x000000ff,0x000001ff,0x000003ff,0x000007ff, |
||
114 | 0x00000fff,0x00001fff,0x00003fff,0x00007fff, |
||
115 | 0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff, |
||
116 | 0x000fffff,0x001fffff,0x003fffff,0x007fffff, |
||
117 | 0x00ffffff,0x01ffffff,0x03ffffff,0x07ffffff, |
||
118 | 0x0fffffff,0x1fffffff,0x3fffffff,0x7fffffff, |
||
119 | }; |
||
1205 | terminx | 120 | static const int32_t pow2long[32] = |
584 | terminx | 121 | { |
122 | 0x00000001,0x00000002,0x00000004,0x00000008, |
||
123 | 0x00000010,0x00000020,0x00000040,0x00000080, |
||
124 | 0x00000100,0x00000200,0x00000400,0x00000800, |
||
125 | 0x00001000,0x00002000,0x00004000,0x00008000, |
||
126 | 0x00010000,0x00020000,0x00040000,0x00080000, |
||
127 | 0x00100000,0x00200000,0x00400000,0x00800000, |
||
128 | 0x01000000,0x02000000,0x04000000,0x08000000, |
||
3178 | helixhorne | 129 | 0x10000000,0x20000000,0x40000000,(int32_t)0x80000000, |
584 | terminx | 130 | }; |
5 | Plagman | 131 | |
109 | terminx | 132 | //Hack for peekbits,getbits,suckbits (to prevent lots of duplicate code) |
133 | // 0: PNG: do 12-byte chunk_header removal hack |
||
134 | // !=0: ZIP: use 64K buffer (olinbuf) |
||
1205 | terminx | 135 | static int32_t zipfilmode; |
4634 | terminx | 136 | kzfilestate kzfs; |
5 | Plagman | 137 | |
4310 | terminx | 138 | // GCC 4.6 LTO build fix |
139 | #ifdef USING_LTO |
||
140 | # define B_KPLIB_STATIC |
||
141 | #else |
||
142 | # define B_KPLIB_STATIC static |
||
143 | #endif |
||
144 | |||
5 | Plagman | 145 | //Initialized tables (can't be in union) |
146 | //jpg: png: |
||
147 | // crmul 16384 abstab10 4096 |
||
148 | // cbmul 16384 hxbit 472 |
||
149 | // dct 4608 pow2mask 128* |
||
150 | // colclip 4096 |
||
151 | // colclipup8 4096 |
||
152 | // colclipup16 4096 |
||
153 | // unzig 256 |
||
154 | // pow2mask 128* |
||
155 | // dcflagor 64 |
||
156 | |||
4310 | terminx | 157 | B_KPLIB_STATIC int32_t ATTRIBUTE((used)) palcol[256] ASMNAME("palcol"); |
158 | static int32_t paleng, bakcol, numhufblocks, zlibcompflags; |
||
4634 | terminx | 159 | static int8_t kcoltype, filtype, bitdepth; |
5 | Plagman | 160 | |
161 | //============================ KPNGILIB begins =============================== |
||
162 | |||
163 | //07/31/2000: KPNG.C first ported to C from READPNG.BAS |
||
164 | //10/11/2000: KPNG.C split into 2 files: KPNG.C and PNGINLIB.C |
||
165 | //11/24/2000: Finished adding support for coltypes 4&6 |
||
166 | //03/31/2001: Added support for Adam7-type interlaced images |
||
167 | //Currently, there is no support for: |
||
168 | // * 16-bit color depth |
||
169 | // * Some useless ancillary chunks, like: gAMA(gamma) & pHYs(aspect ratio) |
||
170 | |||
109 | terminx | 171 | //.PNG specific variables: |
1205 | terminx | 172 | static int32_t bakr = 0x80, bakg = 0x80, bakb = 0x80; //this used to be public... |
173 | static int32_t gslidew = 0, gslider = 0, xm, xmn[4], xr0, xr1, xplc, yplc; |
||
737 | qbix79 | 174 | static intptr_t nfplace; |
1205 | terminx | 175 | static int32_t clen[320], cclen[19], bitpos, filt, xsiz, ysiz; |
2286 | helixhorne | 176 | int32_t xsizbpl, ixsiz, ixoff, iyoff, ixstp, iystp, intlac, nbpl; |
177 | B_KPLIB_STATIC int32_t ATTRIBUTE((used)) trnsrgb ASMNAME("trnsrgb"); |
||
1205 | terminx | 178 | static int32_t ccind[19] = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; |
179 | static int32_t hxbit[59][2], ibuf0[288], nbuf0[32], ibuf1[32], nbuf1[32]; |
||
1440 | terminx | 180 | static const uint8_t *filptr; |
181 | static uint8_t slidebuf[32768], opixbuf0[4], opixbuf1[4]; |
||
2286 | helixhorne | 182 | static uint8_t pnginited = 0; |
183 | B_KPLIB_STATIC uint8_t olinbuf[131072] ASMNAME("olinbuf"); //WARNING:max xres is: 131072/bpp-1 |
||
184 | B_KPLIB_STATIC int32_t ATTRIBUTE((used)) abstab10[1024] ASMNAME("abstab10"); |
||
5 | Plagman | 185 | |
109 | terminx | 186 | //Variables to speed up dynamic Huffman decoding: |
5 | Plagman | 187 | #define LOGQHUFSIZ0 9 |
188 | #define LOGQHUFSIZ1 6 |
||
1205 | terminx | 189 | static int32_t qhufval0[1<<LOGQHUFSIZ0], qhufval1[1<<LOGQHUFSIZ1]; |
1440 | terminx | 190 | static uint8_t qhufbit0[1<<LOGQHUFSIZ0], qhufbit1[1<<LOGQHUFSIZ1]; |
5 | Plagman | 191 | |
1454 | terminx | 192 | #if defined(_MSC_VER) && !defined(NOASM) |
5 | Plagman | 193 | |
4315 | hendricks2 | 194 | #if defined(BIGENDIAN) |
1205 | terminx | 195 | static _inline uint32_t bswap(uint32_t a) |
5 | Plagman | 196 | { |
109 | terminx | 197 | _asm |
198 | { |
||
199 | mov eax, a |
||
200 | bswap eax |
||
201 | } |
||
5 | Plagman | 202 | } |
4315 | hendricks2 | 203 | #endif |
5 | Plagman | 204 | |
1205 | terminx | 205 | static _inline int32_t bitrev(int32_t b, int32_t c) |
5 | Plagman | 206 | { |
109 | terminx | 207 | _asm |
208 | { |
||
209 | mov edx, b |
||
210 | mov ecx, c |
||
211 | xor eax, eax |
||
1762 | terminx | 212 | beg: shr edx, 1 |
109 | terminx | 213 | adc eax, eax |
214 | sub ecx, 1 |
||
1452 | terminx | 215 | jnz short beg |
109 | terminx | 216 | } |
5 | Plagman | 217 | } |
218 | |||
194 | terminx | 219 | #elif defined(__GNUC__) && defined(__i386__) && !defined(NOASM) |
5 | Plagman | 220 | |
4315 | hendricks2 | 221 | #if defined(BIGENDIAN) |
1205 | terminx | 222 | static inline uint32_t bswap(uint32_t a) |
5 | Plagman | 223 | { |
1762 | terminx | 224 | __asm__ __volatile__("bswap %0" : "+r"(a) : : "cc"); |
109 | terminx | 225 | return a; |
5 | Plagman | 226 | } |
4315 | hendricks2 | 227 | #endif |
5 | Plagman | 228 | |
1205 | terminx | 229 | static inline int32_t bitrev(int32_t b, int32_t c) |
5 | Plagman | 230 | { |
1205 | terminx | 231 | int32_t a = 0; |
584 | terminx | 232 | __asm__ __volatile__( |
109 | terminx | 233 | "xorl %%eax, %%eax\n\t0:\n\tshrl $1, %%ebx\n\tadcl %%eax, %%eax\n\tsubl $1, %%ecx\n\tjnz 0b" |
1762 | terminx | 234 | : "+a"(a), "+b"(b), "+c"(c) : : "cc"); |
109 | terminx | 235 | return a; |
5 | Plagman | 236 | } |
237 | |||
238 | #else |
||
239 | |||
4315 | hendricks2 | 240 | #if defined(BIGENDIAN) |
1205 | terminx | 241 | static inline uint32_t bswap(uint32_t a) |
194 | terminx | 242 | { |
243 | return(((a&0xff0000)>>8) + ((a&0xff00)<<8) + (a<<24) + (a>>24)); |
||
244 | } |
||
4315 | hendricks2 | 245 | #endif |
5 | Plagman | 246 | |
1205 | terminx | 247 | static inline int32_t bitrev(int32_t b, int32_t c) |
194 | terminx | 248 | { |
1205 | terminx | 249 | int32_t i, j; |
1229 | terminx | 250 | for (i=1,j=0,c=(1<<c); i<c; i+=i) { j += j; if (b&i) j++; } |
194 | terminx | 251 | return(j); |
252 | } |
||
253 | |||
5 | Plagman | 254 | #endif |
255 | |||
1440 | terminx | 256 | static uint8_t fakebuf[8], *nfilptr; |
1205 | terminx | 257 | static int32_t nbitpos; |
584 | terminx | 258 | static void suckbitsnextblock() |
5 | Plagman | 259 | { |
4634 | terminx | 260 | if (zipfilmode) |
109 | terminx | 261 | { |
262 | //NOTE: should only read bytes inside compsize, not 64K!!! :/ |
||
4634 | terminx | 263 | int32_t n; |
264 | *(int32_t *) &olinbuf[0] = *(int32_t *) &olinbuf[sizeof(olinbuf)-4]; |
||
265 | n = min((unsigned) (kzfs.compleng-kzfs.comptell), sizeof(olinbuf)-4); |
||
266 | fread(&olinbuf[4], n, 1, kzfs.fil); |
||
109 | terminx | 267 | kzfs.comptell += n; |
268 | bitpos -= ((sizeof(olinbuf)-4)<<3); |
||
4634 | terminx | 269 | return; |
109 | terminx | 270 | } |
4634 | terminx | 271 | |
272 | if (nfilptr) |
||
273 | { |
||
274 | filptr = nfilptr; nfilptr = 0; |
||
275 | bitpos -= ((nbitpos-4)<<3); |
||
276 | return; |
||
277 | } |
||
278 | //if (n_from_suckbits < 4) will it crash? |
||
279 | |||
280 | //|===|===|crc|lng|typ|===|===| |
||
281 | // \ fakebuf: / |
||
282 | // |===|===| |
||
283 | //----x O---x O-------- |
||
284 | nbitpos = LSWAPIL(*(int32_t *)&filptr[8]); |
||
285 | nfilptr = (uint8_t *)&filptr[nbitpos+12]; |
||
286 | *(int32_t *)&fakebuf[0] = *(int32_t *)&filptr[0]; //Copy last dword of IDAT chunk |
||
4647 | hendricks2 | 287 | if (*(int32_t *)&filptr[12] == (int32_t)LSWAPIB(0x54414449)) //Copy 1st dword of next IDAT chunk |
4634 | terminx | 288 | *(int32_t *)&fakebuf[4] = *(int32_t *)&filptr[16]; |
289 | filptr = &fakebuf[4]; bitpos -= 32; |
||
5 | Plagman | 290 | } |
291 | |||
1205 | terminx | 292 | static _inline int32_t peekbits(int32_t n) { return((LSWAPIB(*(int32_t *)&filptr[bitpos>>3])>>(bitpos&7))&pow2mask[n]); } |
4634 | terminx | 293 | static _inline void suckbits(int32_t n) { bitpos += n; if (bitpos < 0) return; suckbitsnextblock(); } |
1205 | terminx | 294 | static _inline int32_t getbits(int32_t n) { int32_t i = peekbits(n); suckbits(n); return(i); } |
5 | Plagman | 295 | |
1205 | terminx | 296 | static int32_t hufgetsym(int32_t *hitab, int32_t *hbmax) |
5 | Plagman | 297 | { |
1205 | terminx | 298 | int32_t v, n; |
5 | Plagman | 299 | |
109 | terminx | 300 | v = n = 0; |
584 | terminx | 301 | do { v = (v<<1)+getbits(1)+hbmax[n]-hbmax[n+1]; n++; } |
302 | while (v >= 0); |
||
109 | terminx | 303 | return(hitab[hbmax[n]+v]); |
5 | Plagman | 304 | } |
305 | |||
109 | terminx | 306 | //This did not result in a speed-up on P4-3.6Ghz (02/22/2005) |
1205 | terminx | 307 | //static int32_t hufgetsym_skipb (int32_t *hitab, int32_t *hbmax, int32_t n, int32_t addit) |
5 | Plagman | 308 | //{ |
1205 | terminx | 309 | // int32_t v; |
5 | Plagman | 310 | // |
311 | // v = bitrev(getbits(n),n)+addit; |
||
312 | // do { v = (v<<1)+getbits(1)+hbmax[n]-hbmax[n+1]; n++; } while (v >= 0); |
||
313 | // return(hitab[hbmax[n]+v]); |
||
314 | //} |
||
315 | |||
1440 | terminx | 316 | static void qhufgencode(int32_t *hitab, int32_t *hbmax, int32_t *qhval, uint8_t *qhbit, int32_t numbits) |
5 | Plagman | 317 | { |
1205 | terminx | 318 | int32_t i, j, k, n, r; |
5 | Plagman | 319 | |
109 | terminx | 320 | //r is the bit reverse of i. Ex: if: i = 1011100111, r = 1110011101 |
321 | i = r = 0; |
||
1229 | terminx | 322 | for (n=1; n<=numbits; n++) |
323 | for (k=hbmax[n-1]; k<hbmax[n]; k++) |
||
324 | for (j=i+pow2mask[numbits-n]; i<=j; i++) |
||
109 | terminx | 325 | { |
326 | r = bitrev(i,numbits); |
||
327 | qhval[r] = hitab[k]; |
||
1205 | terminx | 328 | qhbit[r] = (uint8_t)n; |
109 | terminx | 329 | } |
1229 | terminx | 330 | for (j=pow2mask[numbits]; i<=j; i++) |
109 | terminx | 331 | { |
332 | r = bitrev(i,numbits); |
||
5 | Plagman | 333 | |
109 | terminx | 334 | //k = 0; |
335 | //for(n=0;n<numbits;n++) |
||
336 | // k = (k<<1) + ((r>>n)&1) + hbmax[n]-hbmax[n+1]; |
||
337 | // |
||
338 | //n = numbits; |
||
339 | //k = hbmax[n]-r; |
||
340 | // |
||
341 | //j = peekbits(LOGQHUFSIZ); i = qhufval[j]; j = qhufbit[j]; |
||
342 | // |
||
343 | //i = j = 0; |
||
344 | //do |
||
345 | //{ |
||
346 | // i = (i<<1)+getbits(1)+nbuf0[j]-nbuf0[j+1]; j++; |
||
347 | //} while (i >= 0); |
||
348 | //i = ibuf0[nbuf0[j]+i]; |
||
349 | //qhval[r] = k; |
||
5 | Plagman | 350 | |
109 | terminx | 351 | qhbit[r] = 0; //n-32; |
352 | } |
||
5 | Plagman | 353 | |
109 | terminx | 354 | // //hufgetsym_skipb related code: |
355 | //for(k=n=0;n<numbits;n++) k = (k<<1)+hbmax[n]-hbmax[n+1]; |
||
356 | //return(k); |
||
5 | Plagman | 357 | } |
358 | |||
109 | terminx | 359 | //inbuf[inum] : Bit length of each symbol |
360 | //inum : Number of indices |
||
361 | //hitab[inum] : Indices from size-ordered list to original symbol |
||
362 | //hbmax[0-31] : Highest index (+1) of n-bit symbol |
||
4634 | terminx | 363 | |
1205 | terminx | 364 | static void hufgencode(int32_t *inbuf, int32_t inum, int32_t *hitab, int32_t *hbmax) |
5 | Plagman | 365 | { |
4634 | terminx | 366 | int32_t i, tbuf[31], *tbufptr, *hbmaxptr; |
5 | Plagman | 367 | |
4634 | terminx | 368 | Bmemset(tbuf, 0, sizeof(tbuf)); |
1229 | terminx | 369 | for (i=inum-1; i>=0; i--) tbuf[inbuf[i]]++; |
109 | terminx | 370 | tbuf[0] = hbmax[0] = 0; //Hack to remove symbols of length 0? |
4634 | terminx | 371 | for (i=0; i<28; i += 4) |
372 | { |
||
373 | tbufptr = &tbuf[i]; |
||
374 | hbmaxptr = &hbmax[i]; |
||
375 | |||
376 | *(hbmaxptr+1) = *hbmaxptr + *tbufptr; |
||
377 | *(hbmaxptr+2) = *(hbmaxptr+1) + *(tbufptr+1); |
||
378 | *(hbmaxptr+3) = *(hbmaxptr+2) + *(tbufptr+2); |
||
379 | *(hbmaxptr+4) = *(hbmaxptr+3) + *(tbufptr+3); |
||
380 | } |
||
381 | |||
382 | tbufptr = &tbuf[i]; |
||
383 | hbmaxptr = &hbmax[i]; |
||
384 | |||
385 | *(hbmaxptr+1) = *hbmaxptr + *tbufptr; |
||
386 | *(hbmaxptr+2) = *(hbmaxptr+1) + *(tbufptr+1); |
||
387 | *(hbmaxptr+3) = *(hbmaxptr+2) + *(tbufptr+2); |
||
388 | |||
1229 | terminx | 389 | for (i=0; i<inum; i++) if (inbuf[i]) hitab[hbmax[inbuf[i]]++] = i; |
5 | Plagman | 390 | } |
391 | |||
1205 | terminx | 392 | static int32_t initpass() //Interlaced images have 7 "passes", non-interlaced have 1 |
5 | Plagman | 393 | { |
1205 | terminx | 394 | int32_t i, j, k; |
5 | Plagman | 395 | |
109 | terminx | 396 | do |
397 | { |
||
398 | i = (intlac<<2); |
||
399 | ixoff = ((0x04020100>>i)&15); |
||
400 | iyoff = ((0x00402010>>i)&15); |
||
401 | if (((ixoff >= xsiz) || (iyoff >= ysiz)) && (intlac >= 2)) { i = -1; intlac--; } |
||
584 | terminx | 402 | } |
403 | while (i < 0); |
||
109 | terminx | 404 | j = ((0x33221100>>i)&15); ixstp = (1<<j); |
405 | k = ((0x33322110>>i)&15); iystp = (1<<k); |
||
5 | Plagman | 406 | |
109 | terminx | 407 | //xsiz=12 0123456789ab |
408 | //j=3,ixoff=0 0 1 ((12+(1<<3)-1 - 0)>>3) = 2 |
||
409 | //j=3,ixoff=4 2 ((12+(1<<3)-1 - 4)>>3) = 1 |
||
410 | //j=2,ixoff=2 3 4 5 ((12+(1<<2)-1 - 2)>>2) = 3 |
||
411 | //j=1,ixoff=1 6 7 8 9 a b ((12+(1<<1)-1 - 1)>>1) = 6 |
||
412 | ixsiz = ((xsiz+ixstp-1-ixoff)>>j); //It's confusing! See the above example. |
||
413 | nbpl = (bytesperline<<k); |
||
5 | Plagman | 414 | |
109 | terminx | 415 | //Initialize this to make filters fast: |
4634 | terminx | 416 | xsizbpl = ((0x04021301>>(kcoltype<<2))&15)*ixsiz; |
109 | terminx | 417 | switch (bitdepth) |
418 | { |
||
1440 | terminx | 419 | case 1: xsizbpl = ((xsizbpl+7)>>3); break; |
420 | case 2: xsizbpl = ((xsizbpl+3)>>2); break; |
||
421 | case 4: xsizbpl = ((xsizbpl+1)>>1); break; |
||
109 | terminx | 422 | } |
5 | Plagman | 423 | |
1440 | terminx | 424 | Bmemset(olinbuf,0,(xsizbpl+1)*sizeof(olinbuf[0])); |
1205 | terminx | 425 | *(int32_t *)&opixbuf0[0] = *(int32_t *)&opixbuf1[0] = 0; |
4634 | terminx | 426 | xplc = xsizbpl; yplc = iyoff; xm = 0; filt = -1; |
5 | Plagman | 427 | |
4634 | terminx | 428 | i = ixoff; i = (((-(i>=0))|(ixstp-1))&i); |
109 | terminx | 429 | k = (((-(yplc>=0))|(iystp-1))&yplc); |
430 | nfplace = k*bytesperline + (i<<2) + frameplace; |
||
5 | Plagman | 431 | |
109 | terminx | 432 | //Precalculate x-clipping to screen borders (speeds up putbuf) |
433 | //Equation: (0 <= xr <= ixsiz) && (0 <= xr*ixstp+globxoffs+ixoff <= xres) |
||
4634 | terminx | 434 | xr0 = max((-ixoff+(1<<j)-1)>>j,0); |
435 | xr1 = min((xres-ixoff+(1<<j)-1)>>j,ixsiz); |
||
109 | terminx | 436 | xr0 = ixsiz-xr0; |
437 | xr1 = ixsiz-xr1; |
||
5 | Plagman | 438 | |
4634 | terminx | 439 | if (kcoltype == 4) { xr0 = xr0*2; xr1 = xr1*2; } |
440 | else if (kcoltype == 2) { xr0 = xr0*3-2; xr1 = xr1*3-2; } |
||
441 | else if (kcoltype == 6) { xr0 = xr0*4-2; xr1 = xr1*4-2; } |
||
109 | terminx | 442 | else |
443 | { |
||
331 | terminx | 444 | switch (bitdepth) |
109 | terminx | 445 | { |
1440 | terminx | 446 | case 1: xr0 += ((-ixsiz)&7)+7; |
109 | terminx | 447 | xr1 += ((-ixsiz)&7)+7; break; |
1440 | terminx | 448 | case 2: xr0 = ((xr0+((-ixsiz)&3)+3)<<1); |
109 | terminx | 449 | xr1 = ((xr1+((-ixsiz)&3)+3)<<1); break; |
1440 | terminx | 450 | case 4: xr0 = ((xr0+((-ixsiz)&1)+1)<<2); |
109 | terminx | 451 | xr1 = ((xr1+((-ixsiz)&1)+1)<<2); break; |
452 | } |
||
453 | } |
||
454 | ixstp <<= 2; |
||
455 | return(0); |
||
5 | Plagman | 456 | } |
457 | |||
1454 | terminx | 458 | #if defined(_MSC_VER) && !defined(NOASM) |
5 | Plagman | 459 | |
1205 | terminx | 460 | static _inline int32_t Paeth686(int32_t a, int32_t b, int32_t c) |
5 | Plagman | 461 | { |
109 | terminx | 462 | _asm |
463 | { |
||
1440 | terminx | 464 | push ebx |
465 | push esi |
||
466 | push edi |
||
109 | terminx | 467 | mov eax, a |
468 | mov ebx, b |
||
469 | mov ecx, c |
||
470 | mov edx, ecx |
||
471 | sub edx, eax |
||
472 | sub edx, ebx |
||
473 | lea edx, abstab10[edx*4+2048] |
||
474 | mov esi, [ebx*4+edx] |
||
475 | mov edi, [ecx*4+edx] |
||
476 | cmp edi, esi |
||
477 | cmovge edi, esi |
||
478 | cmovge ecx, ebx |
||
479 | cmp edi, [eax*4+edx] |
||
480 | cmovl eax, ecx |
||
1440 | terminx | 481 | pop edi |
482 | pop esi |
||
483 | pop ebx |
||
109 | terminx | 484 | } |
5 | Plagman | 485 | } |
486 | |||
1205 | terminx | 487 | static _inline void rgbhlineasm(int32_t c, int32_t d, int32_t t, int32_t b) |
5 | Plagman | 488 | { |
109 | terminx | 489 | _asm |
490 | { |
||
1440 | terminx | 491 | push ebx |
492 | push edi |
||
493 | |||
109 | terminx | 494 | mov ecx, c |
495 | mov edx, d |
||
496 | mov edi, t |
||
497 | mov ebx, b |
||
498 | sub ecx, edx |
||
1452 | terminx | 499 | jle short endit |
109 | terminx | 500 | add edx, offset olinbuf |
584 | terminx | 501 | cmp dword ptr trnsrgb, 0 |
1452 | terminx | 502 | jz short begit2 |
1762 | terminx | 503 | begit: |
584 | terminx | 504 | mov eax, dword ptr [ecx+edx] |
505 | or eax, 0xff000000 |
||
506 | cmp eax, dword ptr trnsrgb |
||
1452 | terminx | 507 | jne short skipit |
584 | terminx | 508 | and eax, 0xffffff |
1762 | terminx | 509 | skipit: |
584 | terminx | 510 | sub ecx, 3 |
511 | mov [edi], eax |
||
512 | lea edi, [edi+ebx] |
||
1452 | terminx | 513 | jnz short begit |
514 | jmp short endit |
||
1762 | terminx | 515 | begit2: |
584 | terminx | 516 | mov eax, dword ptr [ecx+edx] |
517 | or eax, 0xff000000 |
||
518 | sub ecx, 3 |
||
519 | mov [edi], eax |
||
520 | lea edi, [edi+ebx] |
||
1452 | terminx | 521 | jnz short begit2 |
1762 | terminx | 522 | endit: |
1440 | terminx | 523 | pop edi |
524 | pop ebx |
||
109 | terminx | 525 | } |
584 | terminx | 526 | } |
5 | Plagman | 527 | |
1205 | terminx | 528 | static _inline void pal8hlineasm(int32_t c, int32_t d, int32_t t, int32_t b) |
5 | Plagman | 529 | { |
109 | terminx | 530 | _asm |
531 | { |
||
532 | mov ecx, c |
||
533 | mov edx, d |
||
1440 | terminx | 534 | sub ecx, edx |
1452 | terminx | 535 | jle short endit |
1440 | terminx | 536 | |
537 | push ebx |
||
538 | push edi |
||
109 | terminx | 539 | mov edi, t |
540 | mov ebx, b |
||
541 | add edx, offset olinbuf |
||
1762 | terminx | 542 | begit:movzx eax, byte ptr [ecx+edx] |
584 | terminx | 543 | mov eax, dword ptr palcol[eax*4] |
544 | sub ecx, 1 |
||
545 | mov [edi], eax |
||
546 | lea edi, [edi+ebx] |
||
1452 | terminx | 547 | jnz short begit |
1440 | terminx | 548 | pop edi |
549 | pop ebx |
||
1762 | terminx | 550 | endit: |
109 | terminx | 551 | } |
584 | terminx | 552 | } |
5 | Plagman | 553 | |
194 | terminx | 554 | #elif defined(__GNUC__) && defined(__i386__) && !defined(NOASM) |
5 | Plagman | 555 | |
1205 | terminx | 556 | static inline int32_t Paeth686(int32_t a, int32_t b, int32_t c) |
5 | Plagman | 557 | { |
584 | terminx | 558 | __asm__ __volatile__( |
1440 | terminx | 559 | "movl %%ecx, %%edx \n" |
560 | "subl %%eax, %%edx \n" |
||
561 | "subl %%ebx, %%edx \n" |
||
562 | "leal (abstab10+2048)(,%%edx,4), %%edx \n" |
||
563 | "movl (%%edx,%%ebx,4), %%esi \n" |
||
564 | "movl (%%edx,%%ecx,4), %%edi \n" |
||
565 | "cmpl %%esi, %%edi \n" |
||
566 | "cmovgel %%esi, %%edi \n" |
||
567 | "cmovgel %%ebx, %%ecx \n" |
||
568 | "cmpl (%%edx,%%eax,4), %%edi \n" |
||
569 | "cmovgel %%eax, %%ecx \n" |
||
1762 | terminx | 570 | : "+c"(c) : "a"(a), "b"(b) : "edx","esi","edi","memory","cc" |
571 | ); |
||
109 | terminx | 572 | return c; |
5 | Plagman | 573 | } |
574 | |||
109 | terminx | 575 | //Note: "cmove eax,?" may be faster than "jne ?:and eax,?" but who cares |
1205 | terminx | 576 | static inline void rgbhlineasm(int32_t c, int32_t d, int32_t t, int32_t b) |
5 | Plagman | 577 | { |
584 | terminx | 578 | __asm__ __volatile__( |
1440 | terminx | 579 | "subl %%edx, %%ecx \n" |
580 | "jle 3f \n" |
||
581 | "addl $olinbuf, %%edx \n" |
||
582 | "cmpl $0, trnsrgb(,1) \n" |
||
583 | "jz 2f \n" |
||
584 | "0: movl (%%ecx,%%edx,1), %%eax \n" |
||
585 | "orl $0xff000000, %%eax \n" |
||
586 | "cmpl trnsrgb(,1), %%eax \n" |
||
587 | "jne 1f \n" |
||
588 | "andl $0xffffff, %%eax \n" |
||
589 | "1: subl $3, %%ecx \n" |
||
590 | "movl %%eax, (%%edi) \n" |
||
591 | "leal (%%edi,%%ebx,1), %%edi \n" |
||
592 | "jnz 0b \n" |
||
593 | "jmp 3f \n" |
||
594 | "2: movl (%%ecx,%%edx,1), %%eax \n" |
||
595 | "orl $0xff000000, %%eax \n" |
||
596 | "subl $3, %%ecx \n" |
||
597 | "movl %%eax, (%%edi) \n" |
||
598 | "leal (%%edi,%%ebx,1), %%edi \n" |
||
599 | "jnz 2b \n" |
||
600 | "3: \n" |
||
1762 | terminx | 601 | : "+c"(c), "+d"(d), "+D"(t) : "b"(b) : "eax","memory","cc" |
602 | ); |
||
5 | Plagman | 603 | } |
604 | |||
1205 | terminx | 605 | static inline void pal8hlineasm(int32_t c, int32_t d, int32_t t, int32_t b) |
5 | Plagman | 606 | { |
584 | terminx | 607 | __asm__ __volatile__( |
1440 | terminx | 608 | "subl %%edx, %%ecx \n" |
609 | "jle 1f \n" |
||
610 | "addl $olinbuf, %%edx \n" |
||
611 | "0: movzbl (%%ecx,%%edx,1), %%eax \n" |
||
612 | "movl palcol(,%%eax,4), %%eax \n" |
||
613 | "subl $1, %%ecx \n" |
||
614 | "movl %%eax, (%%edi) \n" |
||
615 | "leal (%%edi,%%ebx,1), %%edi \n" |
||
616 | "jnz 0b \n" |
||
617 | "1: \n" |
||
1762 | terminx | 618 | : "+c"(c), "+d"(d), "+D"(t) : "b"(b) : "eax","memory","cc" |
619 | ); |
||
5 | Plagman | 620 | } |
621 | |||
622 | #else |
||
623 | |||
1205 | terminx | 624 | static inline int32_t Paeth686(int32_t a, int32_t b, int32_t c) |
194 | terminx | 625 | { |
4634 | terminx | 626 | const int32_t *ptr = &abstab10[(c-a)-(b-512)]; |
627 | const int32_t esi = *(ptr+b); |
||
628 | int32_t edi = *(ptr+c); |
||
629 | if (edi >= esi) edi = esi, c = b; |
||
630 | return (edi < *(ptr+a)) ? c : a; |
||
194 | terminx | 631 | } |
5 | Plagman | 632 | |
1205 | terminx | 633 | static inline void rgbhlineasm(int32_t x, int32_t xr1, intptr_t p, int32_t ixstp) |
194 | terminx | 634 | { |
1205 | terminx | 635 | int32_t i; |
194 | terminx | 636 | if (!trnsrgb) |
637 | { |
||
1229 | terminx | 638 | for (; x>xr1; p+=ixstp,x-=3) *(int32_t *)p = (*(int32_t *)&olinbuf[x])|LSWAPIB(0xff000000); |
194 | terminx | 639 | return; |
640 | } |
||
1229 | terminx | 641 | for (; x>xr1; p+=ixstp,x-=3) |
194 | terminx | 642 | { |
1205 | terminx | 643 | i = (*(int32_t *)&olinbuf[x])|LSWAPIB(0xff000000); |
194 | terminx | 644 | if (i == trnsrgb) i &= LSWAPIB(0xffffff); |
1205 | terminx | 645 | *(int32_t *)p = i; |
194 | terminx | 646 | } |
647 | } |
||
648 | |||
1205 | terminx | 649 | static inline void pal8hlineasm(int32_t x, int32_t xr1, intptr_t p, int32_t ixstp) |
194 | terminx | 650 | { |
1229 | terminx | 651 | for (; x>xr1; p+=ixstp,x--) *(int32_t *)p = palcol[olinbuf[x]]; |
194 | terminx | 652 | } |
653 | |||
5 | Plagman | 654 | #endif |
655 | |||
194 | terminx | 656 | //Autodetect filter |
657 | // /f0: 0000000... |
||
658 | // /f1: 1111111... |
||
659 | // /f2: 2222222... |
||
660 | // /f3: 1333333... |
||
661 | // /f3: 3333333... |
||
662 | // /f4: 4444444... |
||
663 | // /f5: 0142321... |
||
1205 | terminx | 664 | static int32_t filter1st, filterest; |
1440 | terminx | 665 | static void putbuf(const uint8_t *buf, int32_t leng) |
5 | Plagman | 666 | { |
1205 | terminx | 667 | int32_t i, x; |
737 | qbix79 | 668 | intptr_t p; |
5 | Plagman | 669 | |
109 | terminx | 670 | if (filt < 0) |
671 | { |
||
672 | if (leng <= 0) return; |
||
194 | terminx | 673 | filt = buf[0]; |
674 | if (filter1st < 0) filter1st = filt; else filterest |= (1<<filt); |
||
109 | terminx | 675 | i = 1; |
584 | terminx | 676 | } |
677 | else i = 0; |
||
5 | Plagman | 678 | |
109 | terminx | 679 | while (i < leng) |
680 | { |
||
681 | x = i+xplc; if (x > leng) x = leng; |
||
682 | switch (filt) |
||
683 | { |
||
684 | case 0: |
||
1762 | terminx | 685 | while (i < x) { olinbuf[xplc] = buf[i]; xplc--; i++; } |
109 | terminx | 686 | break; |
687 | case 1: |
||
1762 | terminx | 688 | while (i < x) |
689 | { |
||
690 | olinbuf[xplc] = (uint8_t)(opixbuf1[xm] += buf[i]); |
||
691 | xm = xmn[xm]; xplc--; i++; |
||
692 | } |
||
109 | terminx | 693 | break; |
694 | case 2: |
||
1762 | terminx | 695 | while (i < x) { olinbuf[xplc] += (uint8_t)buf[i]; xplc--; i++; } |
109 | terminx | 696 | break; |
697 | case 3: |
||
1762 | terminx | 698 | while (i < x) |
699 | { |
||
700 | opixbuf1[xm] = olinbuf[xplc] = (uint8_t)(((opixbuf1[xm]+olinbuf[xplc])>>1)+buf[i]); |
||
701 | xm = xmn[xm]; xplc--; i++; |
||
702 | } |
||
109 | terminx | 703 | break; |
704 | case 4: |
||
1762 | terminx | 705 | while (i < x) |
706 | { |
||
707 | opixbuf1[xm] = (uint8_t)(Paeth686(opixbuf1[xm],olinbuf[xplc],opixbuf0[xm])+buf[i]); |
||
708 | opixbuf0[xm] = olinbuf[xplc]; |
||
709 | olinbuf[xplc] = opixbuf1[xm]; |
||
710 | xm = xmn[xm]; xplc--; i++; |
||
711 | } |
||
109 | terminx | 712 | break; |
713 | } |
||
5 | Plagman | 714 | |
109 | terminx | 715 | if (xplc > 0) return; |
5 | Plagman | 716 | |
109 | terminx | 717 | //Draw line! |
1205 | terminx | 718 | if ((uint32_t)yplc < (uint32_t)yres) |
109 | terminx | 719 | { |
720 | x = xr0; p = nfplace; |
||
4634 | terminx | 721 | switch (kcoltype) |
109 | terminx | 722 | { |
1440 | terminx | 723 | case 2: rgbhlineasm(x,xr1,p,ixstp); break; |
109 | terminx | 724 | case 4: |
1762 | terminx | 725 | for (; x>xr1; p+=ixstp,x-=2) |
726 | *(int32_t *)p = (palcol[olinbuf[x]]&LSWAPIB(0xffffff))|LSWAPIL((int32_t)olinbuf[x-1]); |
||
109 | terminx | 727 | break; |
728 | case 6: |
||
1762 | terminx | 729 | for (; x>xr1; p+=ixstp,x-=4) |
730 | { |
||
731 | *(char *)(p) = olinbuf[x ]; //B |
||
732 | *(char *)(p+1) = olinbuf[x+1]; //G |
||
733 | *(char *)(p+2) = olinbuf[x+2]; //R |
||
734 | *(char *)(p+3) = olinbuf[x-1]; //A |
||
735 | } |
||
109 | terminx | 736 | break; |
737 | default: |
||
1762 | terminx | 738 | switch (bitdepth) |
739 | { |
||
740 | case 1: for (; x>xr1; p+=ixstp,x--) *(int32_t *)p = palcol[olinbuf[x>>3]>>(x&7)]; break; |
||
741 | case 2: for (; x>xr1; p+=ixstp,x-=2) *(int32_t *)p = palcol[olinbuf[x>>3]>>(x&6)]; break; |
||
742 | case 4: for (; x>xr1; p+=ixstp,x-=4) *(int32_t *)p = palcol[olinbuf[x>>3]>>(x&4)]; break; |
||
743 | case 8: pal8hlineasm(x,xr1,p,ixstp); break; //for(;x>xr1;p+=ixstp,x-- ) *(int32_t *)p = palcol[olinbuf[x]]; break; |
||
744 | } |
||
109 | terminx | 745 | break; |
746 | } |
||
747 | nfplace += nbpl; |
||
748 | } |
||
5 | Plagman | 749 | |
1205 | terminx | 750 | *(int32_t *)&opixbuf0[0] = *(int32_t *)&opixbuf1[0] = 0; |
109 | terminx | 751 | xplc = xsizbpl; yplc += iystp; |
4634 | terminx | 752 | if ((intlac) && (yplc >= ysiz)) { intlac--; initpass(); } |
194 | terminx | 753 | if (i < leng) |
754 | { |
||
755 | filt = buf[i++]; |
||
756 | if (filter1st < 0) filter1st = filt; else filterest |= (1<<filt); |
||
584 | terminx | 757 | } |
758 | else filt = -1; |
||
109 | terminx | 759 | } |
5 | Plagman | 760 | } |
761 | |||
762 | static void initpngtables() |
||
763 | { |
||
1205 | terminx | 764 | int32_t i, j, k; |
5 | Plagman | 765 | |
109 | terminx | 766 | //hxbit[0-58][0-1] is a combination of 4 different tables: |
767 | // 1st parameter: [0-29] are distances, [30-58] are lengths |
||
768 | // 2nd parameter: [0]: extra bits, [1]: base number |
||
5 | Plagman | 769 | |
109 | terminx | 770 | j = 1; k = 0; |
1229 | terminx | 771 | for (i=0; i<30; i++) |
109 | terminx | 772 | { |
773 | hxbit[i][1] = j; j += (1<<k); |
||
774 | hxbit[i][0] = k; k += ((i&1) && (i >= 2)); |
||
775 | } |
||
776 | j = 3; k = 0; |
||
1229 | terminx | 777 | for (i=257; i<285; i++) |
109 | terminx | 778 | { |
779 | hxbit[i+30-257][1] = j; j += (1<<k); |
||
780 | hxbit[i+30-257][0] = k; k += ((!(i&3)) && (i >= 264)); |
||
781 | } |
||
782 | hxbit[285+30-257][1] = 258; hxbit[285+30-257][0] = 0; |
||
5 | Plagman | 783 | |
4634 | terminx | 784 | for (i=0; i<512; i++) abstab10[512+i] = abstab10[512-i] = i; |
5 | Plagman | 785 | } |
786 | |||
1205 | terminx | 787 | static int32_t kpngrend(const char *kfilebuf, int32_t kfilength, |
4634 | terminx | 788 | intptr_t daframeplace, int32_t dabytesperline, int32_t daxres, int32_t dayres) |
5 | Plagman | 789 | { |
1205 | terminx | 790 | int32_t i, j, k, bfinal, btype, hlit, hdist, leng; |
791 | int32_t slidew, slider; |
||
792 | //int32_t qhuf0v, qhuf1v; |
||
5 | Plagman | 793 | |
654 | terminx | 794 | UNREFERENCED_PARAMETER(kfilength); |
795 | |||
109 | terminx | 796 | if (!pnginited) { pnginited = 1; initpngtables(); } |
5 | Plagman | 797 | |
4647 | hendricks2 | 798 | if ((*(int32_t *)&kfilebuf[0] != (int32_t)LSWAPIB(0x474e5089)) || (*(int32_t *)&kfilebuf[4] != (int32_t)LSWAPIB(0x0a1a0a0d))) |
109 | terminx | 799 | return(-1); //"Invalid PNG file signature" |
1440 | terminx | 800 | filptr = (uint8_t *)&kfilebuf[8]; |
5 | Plagman | 801 | |
194 | terminx | 802 | trnsrgb = 0; filter1st = -1; filterest = 0; |
5 | Plagman | 803 | |
109 | terminx | 804 | while (1) |
805 | { |
||
1205 | terminx | 806 | leng = LSWAPIL(*(int32_t *)&filptr[0]); i = *(int32_t *)&filptr[4]; |
109 | terminx | 807 | filptr = &filptr[8]; |
5 | Plagman | 808 | |
4647 | hendricks2 | 809 | if (i == (int32_t)LSWAPIB(0x52444849)) //IHDR (must be first) |
109 | terminx | 810 | { |
1205 | terminx | 811 | xsiz = LSWAPIL(*(int32_t *)&filptr[0]); if (xsiz <= 0) return(-1); |
812 | ysiz = LSWAPIL(*(int32_t *)&filptr[4]); if (ysiz <= 0) return(-1); |
||
109 | terminx | 813 | bitdepth = filptr[8]; if (!((1<<bitdepth)&0x116)) return(-1); //"Bit depth not supported" |
4634 | terminx | 814 | kcoltype = filptr[9]; if (!((1<<kcoltype)&0x5d)) return(-1); //"Color type not supported" |
109 | terminx | 815 | if (filptr[10]) return(-1); //"Only *flate is supported" |
816 | if (filptr[11]) return(-1); //"Filter not supported" |
||
817 | if (filptr[12] >= 2) return(-1); //"Unsupported interlace type" |
||
818 | intlac = filptr[12]*7; //0=no interlace/1=Adam7 interlace |
||
5 | Plagman | 819 | |
109 | terminx | 820 | //Save code by making grayscale look like a palette color scheme |
4634 | terminx | 821 | if ((!kcoltype) || (kcoltype == 4)) |
109 | terminx | 822 | { |
823 | j = 0xff000000; k = (255 / ((1<<bitdepth)-1))*0x10101; |
||
824 | paleng = (1<<bitdepth); |
||
1229 | terminx | 825 | for (i=0; i<paleng; i++,j+=k) palcol[i] = LSWAPIB(j); |
109 | terminx | 826 | } |
827 | } |
||
4647 | hendricks2 | 828 | else if (i == (int32_t)LSWAPIB(0x45544c50)) //PLTE (must be before IDAT) |
109 | terminx | 829 | { |
830 | paleng = leng/3; |
||
1229 | terminx | 831 | for (i=paleng-1; i>=0; i--) palcol[i] = LSWAPIB((LSWAPIL(*(int32_t *)&filptr[i*3])>>8)|0xff000000); |
109 | terminx | 832 | } |
4647 | hendricks2 | 833 | else if (i == (int32_t)LSWAPIB(0x44474b62)) //bKGD (must be after PLTE and before IDAT) |
109 | terminx | 834 | { |
4634 | terminx | 835 | switch (kcoltype) |
109 | terminx | 836 | { |
1440 | terminx | 837 | case 0: case 4: |
1762 | terminx | 838 | bakcol = (((int32_t)filptr[0]<<8)+(int32_t)filptr[1])*255/((1<<bitdepth)-1); |
109 | terminx | 839 | bakcol = bakcol*0x10101+0xff000000; break; |
1440 | terminx | 840 | case 2: case 6: |
1762 | terminx | 841 | if (bitdepth == 8) |
842 | { bakcol = (((int32_t)filptr[1])<<16)+(((int32_t)filptr[3])<<8)+((int32_t)filptr[5])+0xff000000; } |
||
843 | else |
||
844 | { |
||
845 | for (i=0,bakcol=0xff000000; i<3; i++) |
||
846 | bakcol += ((((((int32_t)filptr[i<<1])<<8)+((int32_t)filptr[(i<<1)+1]))/257)<<(16-(i<<3))); |
||
847 | } |
||
109 | terminx | 848 | break; |
849 | case 3: |
||
1762 | terminx | 850 | bakcol = palcol[filptr[0]]; break; |
109 | terminx | 851 | } |
852 | bakr = ((bakcol>>16)&255); |
||
853 | bakg = ((bakcol>>8)&255); |
||
854 | bakb = (bakcol&255); |
||
855 | bakcol = LSWAPIB(bakcol); |
||
856 | } |
||
4647 | hendricks2 | 857 | else if (i == (int32_t)LSWAPIB(0x534e5274)) //tRNS (must be after PLTE and before IDAT) |
109 | terminx | 858 | { |
4634 | terminx | 859 | switch (kcoltype) |
109 | terminx | 860 | { |
861 | case 0: |
||
1762 | terminx | 862 | if (bitdepth <= 8) |
863 | palcol[(int32_t)filptr[1]] &= LSWAPIB(0xffffff); |
||
109 | terminx | 864 | //else {} // /c0 /d16 not yet supported |
865 | break; |
||
866 | case 2: |
||
1762 | terminx | 867 | if (bitdepth == 8) |
868 | { trnsrgb = LSWAPIB((((int32_t)filptr[1])<<16)+(((int32_t)filptr[3])<<8)+((int32_t)filptr[5])+0xff000000); } |
||
109 | terminx | 869 | //else {} //WARNING: PNG docs say: MUST compare all 48 bits :( |
870 | break; |
||
871 | case 3: |
||
1762 | terminx | 872 | for (i=min(leng,paleng)-1; i>=0; i--) |
873 | palcol[i] &= LSWAPIB((((int32_t)filptr[i])<<24)|0xffffff); |
||
109 | terminx | 874 | break; |
1440 | terminx | 875 | default:; |
109 | terminx | 876 | } |
877 | } |
||
4647 | hendricks2 | 878 | else if (i == (int32_t)LSWAPIB(0x54414449)) { break; } //IDAT |
5 | Plagman | 879 | |
1205 | terminx | 880 | filptr = &filptr[leng+4]; //crc = LSWAPIL(*(int32_t *)&filptr[-4]); |
109 | terminx | 881 | } |
5 | Plagman | 882 | |
109 | terminx | 883 | //Initialize this for the getbits() function |
884 | zipfilmode = 0; |
||
885 | filptr = &filptr[leng-4]; bitpos = -((leng-4)<<3); nfilptr = 0; |
||
886 | //if (leng < 4) will it crash? |
||
5 | Plagman | 887 | |
109 | terminx | 888 | frameplace = daframeplace; |
889 | bytesperline = dabytesperline; |
||
890 | xres = daxres; |
||
891 | yres = dayres; |
||
4634 | terminx | 892 | switch (kcoltype) |
109 | terminx | 893 | { |
1440 | terminx | 894 | case 4: xmn[0] = 1; xmn[1] = 0; break; |
895 | case 2: xmn[0] = 1; xmn[1] = 2; xmn[2] = 0; break; |
||
896 | case 6: xmn[0] = 1; xmn[1] = 2; xmn[2] = 3; xmn[3] = 0; break; |
||
897 | default: xmn[0] = 0; break; |
||
109 | terminx | 898 | } |
899 | switch (bitdepth) |
||
900 | { |
||
1440 | terminx | 901 | case 1: for (i=2; i<256; i++) palcol[i] = palcol[i&1]; break; |
902 | case 2: for (i=4; i<256; i++) palcol[i] = palcol[i&3]; break; |
||
903 | case 4: for (i=16; i<256; i++) palcol[i] = palcol[i&15]; break; |
||
109 | terminx | 904 | } |
5 | Plagman | 905 | |
109 | terminx | 906 | //coltype: bitdepth: format: |
907 | // 0 1,2,4,8,16 I |
||
908 | // 2 8,16 RGB |
||
909 | // 3 1,2,4,8 P |
||
910 | // 4 8,16 IA |
||
911 | // 6 8,16 RGBA |
||
4634 | terminx | 912 | xsizbpl = ((0x04021301>>(kcoltype<<2))&15)*xsiz; |
109 | terminx | 913 | switch (bitdepth) |
914 | { |
||
1440 | terminx | 915 | case 1: xsizbpl = ((xsizbpl+7)>>3); break; |
916 | case 2: xsizbpl = ((xsizbpl+3)>>2); break; |
||
917 | case 4: xsizbpl = ((xsizbpl+1)>>1); break; |
||
109 | terminx | 918 | } |
919 | //Tests to see if xsiz > allocated space in olinbuf |
||
920 | //Note: xsizbpl gets re-written inside initpass() |
||
921 | if ((xsizbpl+1)*sizeof(olinbuf[0]) > sizeof(olinbuf)) return(-1); |
||
5 | Plagman | 922 | |
109 | terminx | 923 | initpass(); |
5 | Plagman | 924 | |
109 | terminx | 925 | slidew = 0; slider = 16384; |
194 | terminx | 926 | zlibcompflags = getbits(16); //Actually 2 fields: 8:compmethflags, 8:addflagscheck |
109 | terminx | 927 | do |
928 | { |
||
929 | bfinal = getbits(1); btype = getbits(2); |
||
930 | if (btype == 0) |
||
931 | { |
||
932 | //Raw (uncompressed) |
||
933 | suckbits((-bitpos)&7); //Synchronize to start of next byte |
||
934 | i = getbits(16); if ((getbits(16)^i) != 0xffff) return(-1); |
||
1229 | terminx | 935 | for (; i; i--) |
109 | terminx | 936 | { |
937 | if (slidew >= slider) |
||
938 | { |
||
939 | putbuf(&slidebuf[(slider-16384)&32767],16384); slider += 16384; |
||
194 | terminx | 940 | if ((yplc >= yres) && (intlac < 2)) goto kpngrend_goodret; |
109 | terminx | 941 | } |
1205 | terminx | 942 | slidebuf[(slidew++)&32767] = (uint8_t)getbits(8); |
109 | terminx | 943 | } |
944 | continue; |
||
945 | } |
||
946 | if (btype == 3) continue; |
||
5 | Plagman | 947 | |
109 | terminx | 948 | if (btype == 1) //Fixed Huffman |
949 | { |
||
950 | hlit = 288; hdist = 32; i = 0; |
||
1229 | terminx | 951 | for (; i<144; i++) clen[i] = 8; //Fixed bit sizes (literals) |
952 | for (; i<256; i++) clen[i] = 9; //Fixed bit sizes (literals) |
||
953 | for (; i<280; i++) clen[i] = 7; //Fixed bit sizes (EOI,lengths) |
||
954 | for (; i<288; i++) clen[i] = 8; //Fixed bit sizes (lengths) |
||
955 | for (; i<320; i++) clen[i] = 5; //Fixed bit sizes (distances) |
||
109 | terminx | 956 | } |
957 | else //Dynamic Huffman |
||
958 | { |
||
1440 | terminx | 959 | numhufblocks++; |
109 | terminx | 960 | hlit = getbits(5)+257; hdist = getbits(5)+1; j = getbits(4)+4; |
1229 | terminx | 961 | for (i=0; i<j; i++) cclen[ccind[i]] = getbits(3); |
962 | for (; i<19; i++) cclen[ccind[i]] = 0; |
||
109 | terminx | 963 | hufgencode(cclen,19,ibuf0,nbuf0); |
5 | Plagman | 964 | |
109 | terminx | 965 | j = 0; k = hlit+hdist; |
966 | while (j < k) |
||
967 | { |
||
968 | i = hufgetsym(ibuf0,nbuf0); |
||
969 | if (i < 16) { clen[j++] = i; continue; } |
||
970 | if (i == 16) |
||
1229 | terminx | 971 | { for (i=getbits(2)+3; i; i--) { clen[j] = clen[j-1]; j++; } } |
109 | terminx | 972 | else |
973 | { |
||
974 | if (i == 17) i = getbits(3)+3; else i = getbits(7)+11; |
||
1229 | terminx | 975 | for (; i; i--) clen[j++] = 0; |
109 | terminx | 976 | } |
977 | } |
||
978 | } |
||
5 | Plagman | 979 | |
109 | terminx | 980 | hufgencode(clen,hlit,ibuf0,nbuf0); |
981 | //qhuf0v = //hufgetsym_skipb related code |
||
982 | qhufgencode(ibuf0,nbuf0,qhufval0,qhufbit0,LOGQHUFSIZ0); |
||
5 | Plagman | 983 | |
109 | terminx | 984 | hufgencode(&clen[hlit],hdist,ibuf1,nbuf1); |
985 | //qhuf1v = //hufgetsym_skipb related code |
||
986 | qhufgencode(ibuf1,nbuf1,qhufval1,qhufbit1,LOGQHUFSIZ1); |
||
5 | Plagman | 987 | |
109 | terminx | 988 | while (1) |
989 | { |
||
990 | if (slidew >= slider) |
||
991 | { |
||
992 | putbuf(&slidebuf[(slider-16384)&32767],16384); slider += 16384; |
||
194 | terminx | 993 | if ((yplc >= yres) && (intlac < 2)) goto kpngrend_goodret; |
109 | terminx | 994 | } |
5 | Plagman | 995 | |
109 | terminx | 996 | k = peekbits(LOGQHUFSIZ0); |
1205 | terminx | 997 | if (qhufbit0[k]) { i = qhufval0[k]; suckbits((int32_t)qhufbit0[k]); } |
584 | terminx | 998 | else i = hufgetsym(ibuf0,nbuf0); |
109 | terminx | 999 | //else i = hufgetsym_skipb(ibuf0,nbuf0,LOGQHUFSIZ0,qhuf0v); //hufgetsym_skipb related code |
5 | Plagman | 1000 | |
1205 | terminx | 1001 | if (i < 256) { slidebuf[(slidew++)&32767] = (uint8_t)i; continue; } |
109 | terminx | 1002 | if (i == 256) break; |
1003 | i = getbits(hxbit[i+30-257][0]) + hxbit[i+30-257][1]; |
||
5 | Plagman | 1004 | |
109 | terminx | 1005 | k = peekbits(LOGQHUFSIZ1); |
1205 | terminx | 1006 | if (qhufbit1[k]) { j = qhufval1[k]; suckbits((int32_t)qhufbit1[k]); } |
584 | terminx | 1007 | else j = hufgetsym(ibuf1,nbuf1); |
109 | terminx | 1008 | //else j = hufgetsym_skipb(ibuf1,nbuf1,LOGQHUFSIZ1,qhuf1v); //hufgetsym_skipb related code |
5 | Plagman | 1009 | |
109 | terminx | 1010 | j = getbits(hxbit[j][0]) + hxbit[j][1]; |
584 | terminx | 1011 | i += slidew; do { slidebuf[slidew&32767] = slidebuf[(slidew-j)&32767]; slidew++; } |
1012 | while (slidew < i); |
||
109 | terminx | 1013 | } |
584 | terminx | 1014 | } |
1015 | while (!bfinal); |
||
5 | Plagman | 1016 | |
109 | terminx | 1017 | slider -= 16384; |
1018 | if (!((slider^slidew)&32768)) |
||
1019 | putbuf(&slidebuf[slider&32767],slidew-slider); |
||
1020 | else |
||
1021 | { |
||
1022 | putbuf(&slidebuf[slider&32767],(-slider)&32767); |
||
1023 | putbuf(slidebuf,slidew&32767); |
||
1024 | } |
||
194 | terminx | 1025 | |
4634 | terminx | 1026 | kpngrend_goodret: |
1440 | terminx | 1027 | if (!(filterest&~(1<<filter1st))) filtype = (int8_t)filter1st; |
194 | terminx | 1028 | else if ((filter1st == 1) && (!(filterest&~(1<<3)))) filtype = 3; |
1029 | else filtype = 5; |
||
4634 | terminx | 1030 | if (kcoltype == 4) paleng = 0; //For /c4, palcol/paleng used as LUT for "*0x10101": alpha is invalid! |
109 | terminx | 1031 | return(0); |
5 | Plagman | 1032 | } |
1033 | |||
1034 | //============================= KPNGILIB ends ================================ |
||
1035 | //============================ KPEGILIB begins =============================== |
||
1036 | |||
109 | terminx | 1037 | //11/01/2000: This code was originally from KPEG.C |
1038 | // All non 32-bit color drawing was removed |
||
1039 | // "Motion" JPG code was removed |
||
1040 | // A lot of parameters were added to kpeg() for library usage |
||
1205 | terminx | 1041 | static int32_t kpeginited = 0; |
1042 | static int32_t clipxdim, clipydim; |
||
5 | Plagman | 1043 | |
1205 | terminx | 1044 | static int32_t hufmaxatbit[8][20], hufvalatbit[8][20], hufcnt[8]; |
1440 | terminx | 1045 | static uint8_t hufnumatbit[8][20], huftable[8][256]; |
1205 | terminx | 1046 | static int32_t hufquickval[8][1024], hufquickbits[8][1024], hufquickcnt[8]; |
1047 | static int32_t quantab[4][64], dct[12][64], lastdc[4], unzig[64], zigit[64]; //dct:10=MAX (says spec);+2 for hacks |
||
1440 | terminx | 1048 | static uint8_t gnumcomponents, dcflagor[64]; |
1205 | terminx | 1049 | static int32_t gcompid[4], gcomphsamp[4], gcompvsamp[4], gcompquantab[4], gcomphsampshift[4], gcompvsampshift[4]; |
1050 | static int32_t lnumcomponents, lcompid[4], lcompdc[4], lcompac[4], lcomphsamp[4], lcompvsamp[4], lcompquantab[4]; |
||
1051 | static int32_t lcomphvsamp0, lcomphsampshift0, lcompvsampshift0; |
||
1052 | static int32_t colclip[1024], colclipup8[1024], colclipup16[1024]; |
||
1440 | terminx | 1053 | /*static uint8_t pow2char[8] = {1,2,4,8,16,32,64,128};*/ |
5 | Plagman | 1054 | |
1454 | terminx | 1055 | #if defined(_MSC_VER) && !defined(NOASM) |
5 | Plagman | 1056 | |
1205 | terminx | 1057 | static _inline int32_t mulshr24(int32_t a, int32_t d) |
5 | Plagman | 1058 | { |
109 | terminx | 1059 | _asm |
1060 | { |
||
1061 | mov eax, a |
||
1062 | imul d |
||
1063 | shrd eax, edx, 24 |
||
1064 | } |
||
5 | Plagman | 1065 | } |
1066 | |||
1205 | terminx | 1067 | static _inline int32_t mulshr32(int32_t a, int32_t d) |
5 | Plagman | 1068 | { |
109 | terminx | 1069 | _asm |
1070 | { |
||
1071 | mov eax, a |
||
1072 | imul d |
||
1073 | mov eax, edx |
||
1074 | } |
||
5 | Plagman | 1075 | } |
1076 | |||
194 | terminx | 1077 | #elif defined(__GNUC__) && defined(__i386__) && !defined(NOASM) |
5 | Plagman | 1078 | |
1079 | #define mulshr24(a,d) \ |
||
1205 | terminx | 1080 | ({ int32_t __a=(a), __d=(d); \ |
5 | Plagman | 1081 | __asm__ __volatile__ ("imull %%edx; shrdl $24, %%edx, %%eax" \ |
1082 | : "+a" (__a), "+d" (__d) : : "cc"); \ |
||
1083 | __a; }) |
||
1084 | |||
1085 | #define mulshr32(a,d) \ |
||
1205 | terminx | 1086 | ({ int32_t __a=(a), __d=(d); \ |
5 | Plagman | 1087 | __asm__ __volatile__ ("imull %%edx" \ |
1088 | : "+a" (__a), "+d" (__d) : : "cc"); \ |
||
1089 | __d; }) |
||
1090 | |||
1091 | #else |
||
1092 | |||
1205 | terminx | 1093 | static inline int32_t mulshr24(int32_t a, int32_t b) |
194 | terminx | 1094 | { |
1205 | terminx | 1095 | return((int32_t)((((__int64)a)*((__int64)b))>>24)); |
194 | terminx | 1096 | } |
5 | Plagman | 1097 | |
1205 | terminx | 1098 | static inline int32_t mulshr32(int32_t a, int32_t b) |
194 | terminx | 1099 | { |
1205 | terminx | 1100 | return((int32_t)((((__int64)a)*((__int64)b))>>32)); |
194 | terminx | 1101 | } |
1102 | |||
5 | Plagman | 1103 | #endif |
1104 | |||
1205 | terminx | 1105 | static int32_t cosqr16[8] = //cosqr16[i] = ((cos(PI*i/16)*sqrt(2))<<24); |
1762 | terminx | 1106 | {23726566,23270667,21920489,19727919,16777216,13181774,9079764,4628823}; |
4101 | hendricks2 | 1107 | static int32_t crmul[4096], cbmul[4096]; |
5 | Plagman | 1108 | |
584 | terminx | 1109 | static void initkpeg() |
5 | Plagman | 1110 | { |
4101 | hendricks2 | 1111 | int32_t i, j, x, y; |
5 | Plagman | 1112 | |
109 | terminx | 1113 | x = 0; //Back & forth diagonal pattern (aligning bytes for best compression) |
1229 | terminx | 1114 | for (i=0; i<16; i+=2) |
109 | terminx | 1115 | { |
1229 | terminx | 1116 | for (y=8-1; y>=0; y--) |
109 | terminx | 1117 | if ((unsigned)(i-y) < (unsigned)8) unzig[x++] = (y<<3)+i-y; |
1229 | terminx | 1118 | for (y=0; y<8; y++) |
109 | terminx | 1119 | if ((unsigned)(i+1-y) < (unsigned)8) unzig[x++] = (y<<3)+i+1-y; |
1120 | } |
||
1229 | terminx | 1121 | for (i=64-1; i>=0; i--) zigit[unzig[i]] = i; |
1122 | for (i=64-1; i>=0; i--) dcflagor[i] = (uint8_t)(1<<(unzig[i]>>3)); |
||
5 | Plagman | 1123 | |
1229 | terminx | 1124 | for (i=0; i<128; i++) colclip[i] = i+128; |
1125 | for (i=128; i<512; i++) colclip[i] = 255; |
||
1126 | for (i=512; i<896; i++) colclip[i] = 0; |
||
1127 | for (i=896; i<1024; i++) colclip[i] = i-896; |
||
1128 | for (i=0; i<1024; i++) |
||
109 | terminx | 1129 | { |
1130 | colclipup8[i] = (colclip[i]<<8); |
||
1131 | colclipup16[i] = (colclip[i]<<16)+0xff000000; //Hack: set alphas to 255 |
||
1132 | } |
||
5 | Plagman | 1133 | #if defined(BIGENDIAN) |
1229 | terminx | 1134 | for (i=0; i<1024; i++) |
109 | terminx | 1135 | { |
1136 | colclip[i] = bswap(colclip[i]); |
||
1137 | colclipup8[i] = bswap(colclipup8[i]); |
||
1138 | colclipup16[i] = bswap(colclipup16[i]); |
||
1139 | } |
||
5 | Plagman | 1140 | #endif |
1141 | |||
1229 | terminx | 1142 | for (i=0; i<2048; i++) |
109 | terminx | 1143 | { |
4101 | hendricks2 | 1144 | j = i-1024; |
1145 | crmul[(i<<1)+0] = j*1470104; //1.402*1048576 |
||
1146 | crmul[(i<<1)+1] = j*-748830; //-0.71414*1048576 |
||
1147 | cbmul[(i<<1)+0] = j*-360857; //-0.34414*1048576 |
||
1148 | cbmul[(i<<1)+1] = j*1858077; //1.772*1048576 |
||
109 | terminx | 1149 | } |
5 | Plagman | 1150 | |
1440 | terminx | 1151 | Bmemset((void *)&dct[10][0],0,64*2*sizeof(dct[0][0])); |
5 | Plagman | 1152 | } |
1153 | |||
1205 | terminx | 1154 | static void huffgetval(int32_t index, int32_t curbits, int32_t num, int32_t *daval, int32_t *dabits) |
5 | Plagman | 1155 | { |
1205 | terminx | 1156 | int32_t b, v, pow2, *hmax; |
5 | Plagman | 1157 | |
109 | terminx | 1158 | hmax = &hufmaxatbit[index][0]; |
1159 | pow2 = pow2long[curbits-1]; |
||
1160 | if (num&pow2) v = 1; else v = 0; |
||
1229 | terminx | 1161 | for (b=1; b<=16; b++) |
109 | terminx | 1162 | { |
1163 | if (v < hmax[b]) |
||
1164 | { |
||
1165 | *dabits = b; |
||
1166 | *daval = huftable[index][hufvalatbit[index][b]+v]; |
||
1167 | return; |
||
1168 | } |
||
1169 | pow2 >>= 1; v <<= 1; |
||
1170 | if (num&pow2) v++; |
||
1171 | } |
||
1172 | *dabits = 16; *daval = 0; |
||
5 | Plagman | 1173 | } |
1174 | |||
1440 | terminx | 1175 | static void invdct8x8(int32_t *dc, uint8_t dcflag) |
5 | Plagman | 1176 | { |
331 | terminx | 1177 | #define SQRT2 23726566 //(sqrt(2))<<24 |
1178 | #define C182 31000253 //(cos(PI/8)*2)<<24 |
||
1179 | #define C18S22 43840978 //(cos(PI/8)*sqrt(2)*2)<<24 |
||
1180 | #define C38S22 18159528 //(cos(PI*3/8)*sqrt(2)*2)<<24 |
||
1205 | terminx | 1181 | int32_t *edc, t0, t1, t2, t3, t4, t5, t6, t7; |
5 | Plagman | 1182 | |
109 | terminx | 1183 | edc = dc+64; |
1184 | do |
||
1185 | { |
||
1186 | if (dcflag&1) //pow2char[z]) |
||
1187 | { |
||
1188 | t3 = dc[2] + dc[6]; |
||
1189 | t2 = (mulshr32(dc[2]-dc[6],SQRT2<<6)<<2) - t3; |
||
1190 | t4 = dc[0] + dc[4]; t5 = dc[0] - dc[4]; |
||
1191 | t0 = t4+t3; t3 = t4-t3; t1 = t5+t2; t2 = t5-t2; |
||
1192 | t4 = (mulshr32(dc[5]-dc[3]+dc[1]-dc[7],C182<<6)<<2); |
||
1193 | t7 = dc[1] + dc[7] + dc[5] + dc[3]; |
||
1194 | t6 = (mulshr32(dc[3]-dc[5],C18S22<<5)<<3) + t4 - t7; |
||
1195 | t5 = (mulshr32(dc[1]+dc[7]-dc[5]-dc[3],SQRT2<<6)<<2) - t6; |
||
1196 | t4 = (mulshr32(dc[1]-dc[7],C38S22<<6)<<2) - t4 + t5; |
||
1197 | dc[0] = t0+t7; dc[7] = t0-t7; dc[1] = t1+t6; dc[6] = t1-t6; |
||
1198 | dc[2] = t2+t5; dc[5] = t2-t5; dc[4] = t3+t4; dc[3] = t3-t4; |
||
1199 | } |
||
1200 | dc += 8; dcflag >>= 1; |
||
584 | terminx | 1201 | } |
1202 | while (dc < edc); |
||
109 | terminx | 1203 | dc -= 32; edc -= 24; |
1204 | do |
||
1205 | { |
||
1206 | t3 = dc[2*8-32] + dc[6*8-32]; |
||
1207 | t2 = (mulshr32(dc[2*8-32]-dc[6*8-32],SQRT2<<6)<<2) - t3; |
||
1208 | t4 = dc[0*8-32] + dc[4*8-32]; t5 = dc[0*8-32] - dc[4*8-32]; |
||
1209 | t0 = t4+t3; t3 = t4-t3; t1 = t5+t2; t2 = t5-t2; |
||
1210 | t4 = (mulshr32(dc[5*8-32]-dc[3*8-32]+dc[1*8-32]-dc[7*8-32],C182<<6)<<2); |
||
1211 | t7 = dc[1*8-32] + dc[7*8-32] + dc[5*8-32] + dc[3*8-32]; |
||
1212 | t6 = (mulshr32(dc[3*8-32]-dc[5*8-32],C18S22<<5)<<3) + t4 - t7; |
||
1213 | t5 = (mulshr32(dc[1*8-32]+dc[7*8-32]-dc[5*8-32]-dc[3*8-32],SQRT2<<6)<<2) - t6; |
||
1214 | t4 = (mulshr32(dc[1*8-32]-dc[7*8-32],C38S22<<6)<<2) - t4 + t5; |
||
1215 | dc[0*8-32] = t0+t7; dc[7*8-32] = t0-t7; dc[1*8-32] = t1+t6; dc[6*8-32] = t1-t6; |
||
1216 | dc[2*8-32] = t2+t5; dc[5*8-32] = t2-t5; dc[4*8-32] = t3+t4; dc[3*8-32] = t3-t4; |
||
1217 | dc++; |
||
584 | terminx | 1218 | } |
1219 | while (dc < edc); |
||
5 | Plagman | 1220 | } |
1221 | |||
1440 | terminx | 1222 | static void yrbrend(int32_t x, int32_t y, int32_t *ldct) |
5 | Plagman | 1223 | { |
1205 | terminx | 1224 | int32_t i, j, ox, oy, xx, yy, xxx, yyy, xxxend, yyyend, yv, cr = 0, cb = 0, *odc, *dc, *dc2; |
1440 | terminx | 1225 | intptr_t p, pp; |
5 | Plagman | 1226 | |
1440 | terminx | 1227 | odc = ldct; dc2 = &ldct[10<<6]; |
1229 | terminx | 1228 | for (yy=0; yy<(lcompvsamp[0]<<3); yy+=8) |
109 | terminx | 1229 | { |
4634 | terminx | 1230 | oy = y+yy; if ((unsigned)oy >= (unsigned)clipydim) { odc += (lcomphsamp[0]<<6); continue; } |
1231 | pp = oy*bytesperline + ((x)<<2) + frameplace; |
||
1229 | terminx | 1232 | for (xx=0; xx<(lcomphsamp[0]<<3); xx+=8,odc+=64) |
109 | terminx | 1233 | { |
4634 | terminx | 1234 | ox = x+xx; if ((unsigned)ox >= (unsigned)clipxdim) continue; |
109 | terminx | 1235 | p = pp+(xx<<2); |
1236 | dc = odc; |
||
1440 | terminx | 1237 | if (lnumcomponents > 1) dc2 = &ldct[(lcomphvsamp0<<6)+((yy>>lcompvsampshift0)<<3)+(xx>>lcomphsampshift0)]; |
109 | terminx | 1238 | xxxend = min(clipxdim-ox,8); |
1239 | yyyend = min(clipydim-oy,8); |
||
1240 | if ((lcomphsamp[0] == 1) && (xxxend == 8)) |
||
1241 | { |
||
1229 | terminx | 1242 | for (yyy=0; yyy<yyyend; yyy++) |
109 | terminx | 1243 | { |
1229 | terminx | 1244 | for (xxx=0; xxx<8; xxx++) |
109 | terminx | 1245 | { |
1246 | yv = dc[xxx]; |
||
1440 | terminx | 1247 | cr = (dc2[xxx+64]>>(20-1))&~1; |
1248 | cb = (dc2[xxx ]>>(20-1))&~1; |
||
1205 | terminx | 1249 | ((int32_t *)p)[xxx] = colclipup16[(unsigned)(yv+crmul[cr+2048])>>22]+ |
1229 | terminx | 1250 | colclipup8[(unsigned)(yv+crmul[cr+2049]+cbmul[cb+2048])>>22]+ |
1251 | colclip[(unsigned)(yv+cbmul[cb+2049])>>22]; |
||
109 | terminx | 1252 | } |
1253 | p += bytesperline; |
||
1254 | dc += 8; |
||
1255 | if (!((yyy+1)&(lcompvsamp[0]-1))) dc2 += 8; |
||
1256 | } |
||
1257 | } |
||
1258 | else if ((lcomphsamp[0] == 2) && (xxxend == 8)) |
||
1259 | { |
||
1229 | terminx | 1260 | for (yyy=0; yyy<yyyend; yyy++) |
109 | terminx | 1261 | { |
1229 | terminx | 1262 | for (xxx=0; xxx<8; xxx+=2) |
109 | terminx | 1263 | { |
1264 | yv = dc[xxx]; |
||
1440 | terminx | 1265 | cr = (dc2[(xxx>>1)+64]>>(20-1))&~1; |
1266 | cb = (dc2[(xxx>>1)]>>(20-1))&~1; |
||
109 | terminx | 1267 | i = crmul[cr+2049]+cbmul[cb+2048]; |
1268 | cr = crmul[cr+2048]; |
||
1269 | cb = cbmul[cb+2049]; |
||
1205 | terminx | 1270 | ((int32_t *)p)[xxx] = colclipup16[(unsigned)(yv+cr)>>22]+ |
1229 | terminx | 1271 | colclipup8[(unsigned)(yv+ i)>>22]+ |
1272 | colclip[(unsigned)(yv+cb)>>22]; |
||
109 | terminx | 1273 | yv = dc[xxx+1]; |
1205 | terminx | 1274 | ((int32_t *)p)[xxx+1] = colclipup16[(unsigned)(yv+cr)>>22]+ |
1229 | terminx | 1275 | colclipup8[(unsigned)(yv+ i)>>22]+ |
1276 | colclip[(unsigned)(yv+cb)>>22]; |
||
109 | terminx | 1277 | } |
1278 | p += bytesperline; |
||
1279 | dc += 8; |
||
1280 | if (!((yyy+1)&(lcompvsamp[0]-1))) dc2 += 8; |
||
1281 | } |
||
1282 | } |
||
1283 | else |
||
1284 | { |
||
1229 | terminx | 1285 | for (yyy=0; yyy<yyyend; yyy++) |
109 | terminx | 1286 | { |
1287 | i = 0; j = 1; |
||
1229 | terminx | 1288 | for (xxx=0; xxx<xxxend; xxx++) |
109 | terminx | 1289 | { |
1290 | yv = dc[xxx]; |
||
1291 | j--; |
||
1292 | if (!j) |
||
1293 | { |
||
1294 | j = lcomphsamp[0]; |
||
1440 | terminx | 1295 | cr = (dc2[i+64]>>(20-1))&~1; |
1296 | cb = (dc2[i ]>>(20-1))&~1; |
||
109 | terminx | 1297 | i++; |
1298 | } |
||
1205 | terminx | 1299 | ((int32_t *)p)[xxx] = colclipup16[(unsigned)(yv+crmul[cr+2048])>>22]+ |
1229 | terminx | 1300 | colclipup8[(unsigned)(yv+crmul[cr+2049]+cbmul[cb+2048])>>22]+ |
1301 | colclip[(unsigned)(yv+cbmul[cb+2049])>>22]; |
||
109 | terminx | 1302 | } |
1303 | p += bytesperline; |
||
1304 | dc += 8; |
||
1305 | if (!((yyy+1)&(lcompvsamp[0]-1))) dc2 += 8; |
||
1306 | } |
||
1307 | } |
||
1308 | } |
||
1309 | } |
||
5 | Plagman | 1310 | } |
1440 | terminx | 1311 | void (*kplib_yrbrend_func)(int32_t,int32_t,int32_t *) = yrbrend; |
5 | Plagman | 1312 | |
4597 | terminx | 1313 | #define KPEG_GETBITS(curbits, minbits, num, kfileptr, kfileend)\ |
1314 | while (curbits < minbits)\ |
||
1315 | {\ |
||
1316 | ch = *kfileptr++; num = (num<<8)+((int)ch); curbits += 8;\ |
||
1317 | if (ch == 255) { kfileptr++; if (kfileptr >= kfileend) { num <<= 8; curbits += 8; /*Hack to prevent read overrun on valid JPG by stuffing extra byte*/ } }\ |
||
1318 | } |
||
1319 | |||
1320 | |||
1205 | terminx | 1321 | static int32_t kpegrend(const char *kfilebuf, int32_t kfilength, |
4634 | terminx | 1322 | intptr_t daframeplace, int32_t dabytesperline, int32_t daxres, int32_t dayres) |
5 | Plagman | 1323 | { |
2537 | hendricks2 | 1324 | int32_t i, j, v, leng = 0, xdim = 0, ydim = 0, index, prec, restartcnt, restartinterval; |
1440 | terminx | 1325 | int32_t x, y, z, xx, yy, zz, *dc = NULL, num, curbits, c, daval, dabits, *hqval, *hqbits, hqcnt, *quanptr = NULL; |
1205 | terminx | 1326 | int32_t passcnt = 0, ghsampmax = 0, gvsampmax = 0, glhsampmax = 0, glvsampmax = 0, glhstep, glvstep; |
2228 | hendricks2 | 1327 | int32_t eobrun, Ss, Se, Ah, Al, Alut[2], dctx[12], dcty[12], ldctx[12], /* ldcty[12], */ lshx[4], lshy[4]; |
1440 | terminx | 1328 | int16_t *dctbuf = 0, *dctptr[12], *ldctptr[12], *dcs = NULL; |
1329 | uint8_t ch, marker, dcflag; |
||
4597 | terminx | 1330 | const uint8_t *kfileptr, *kfileend; |
5 | Plagman | 1331 | |
109 | terminx | 1332 | if (!kpeginited) { kpeginited = 1; initkpeg(); } |
5 | Plagman | 1333 | |
1440 | terminx | 1334 | kfileptr = (uint8_t *)kfilebuf; |
4597 | terminx | 1335 | kfileend = &kfileptr[kfilength]; |
5 | Plagman | 1336 | |
1205 | terminx | 1337 | if (*(uint16_t *)kfileptr == SSWAPIB(0xd8ff)) kfileptr += 2; |
109 | terminx | 1338 | else return(-1); //"%s is not a JPEG file\n",filename |
5 | Plagman | 1339 | |
109 | terminx | 1340 | restartinterval = 0; |
1229 | terminx | 1341 | for (i=0; i<4; i++) lastdc[i] = 0; |
1342 | for (i=0; i<8; i++) hufcnt[i] = 0; |
||
5 | Plagman | 1343 | |
4634 | terminx | 1344 | kcoltype = 0; bitdepth = 8; //For PNGOUT |
109 | terminx | 1345 | do |
1346 | { |
||
1347 | ch = *kfileptr++; if (ch != 255) continue; |
||
584 | terminx | 1348 | do { marker = *kfileptr++; } |
1349 | while (marker == 255); |
||
109 | terminx | 1350 | if (marker != 0xd9) //Don't read past end of buffer |
1351 | { |
||
737 | qbix79 | 1352 | leng = ((intptr_t)kfileptr[0]<<8)+(intptr_t)kfileptr[1]-2; |
109 | terminx | 1353 | kfileptr += 2; |
1354 | } |
||
1205 | terminx | 1355 | //printf("fileoffs=%08x, marker=%02x,leng=%d",((int32_t)kfileptr)-((int32_t)kfilebuf)-2,marker,leng); |
331 | terminx | 1356 | switch (marker) |
109 | terminx | 1357 | { |
1440 | terminx | 1358 | case 0xc0: case 0xc1: case 0xc2: |
1762 | terminx | 1359 | //processit! |
1360 | kfileptr++; //numbits = *kfileptr++; |
||
5 | Plagman | 1361 | |
1205 | terminx | 1362 | ydim = SSWAPIL(*(uint16_t *)&kfileptr[0]); |
1363 | xdim = SSWAPIL(*(uint16_t *)&kfileptr[2]); |
||
1440 | terminx | 1364 | //printf("%s: %ld / %ld = %ld\n",filename,xdim*ydim*3,kfilength,(xdim*ydim*3)/kfilength); |
5 | Plagman | 1365 | |
109 | terminx | 1366 | frameplace = daframeplace; |
1367 | bytesperline = dabytesperline; |
||
1368 | xres = daxres; |
||
1369 | yres = dayres; |
||
1370 | gnumcomponents = kfileptr[4]; |
||
1371 | kfileptr += 5; |
||
1372 | ghsampmax = gvsampmax = glhsampmax = glvsampmax = 0; |
||
1229 | terminx | 1373 | for (z=0; z<gnumcomponents; z++) |
109 | terminx | 1374 | { |
1375 | gcompid[z] = kfileptr[0]; |
||
1376 | gcomphsamp[z] = (kfileptr[1]>>4); |
||
1377 | gcompvsamp[z] = (kfileptr[1]&15); |
||
1378 | gcompquantab[z] = kfileptr[2]; |
||
1229 | terminx | 1379 | for (i=0; i<8; i++) if (gcomphsamp[z] == pow2long[i]) { gcomphsampshift[z] = i; break; } |
1380 | for (i=0; i<8; i++) if (gcompvsamp[z] == pow2long[i]) { gcompvsampshift[z] = i; break; } |
||
109 | terminx | 1381 | if (gcomphsamp[z] > ghsampmax) { ghsampmax = gcomphsamp[z]; glhsampmax = gcomphsampshift[z]; } |
1382 | if (gcompvsamp[z] > gvsampmax) { gvsampmax = gcompvsamp[z]; glvsampmax = gcompvsampshift[z]; } |
||
1383 | kfileptr += 3; |
||
1384 | } |
||
5 | Plagman | 1385 | |
109 | terminx | 1386 | break; |
1387 | case 0xc4: //Huffman table |
||
1762 | terminx | 1388 | do |
1389 | { |
||
1390 | ch = *kfileptr++; leng--; |
||
1391 | if (ch >= 16) { index = ch-12; } |
||
1392 | else { index = ch; } |
||
1393 | Bmemcpy((void *)&hufnumatbit[index][1],(void *)kfileptr,16); kfileptr += 16; |
||
1394 | leng -= 16; |
||
5 | Plagman | 1395 | |
1762 | terminx | 1396 | v = 0; hufcnt[index] = 0; |
1397 | hufquickcnt[index] = 0; |
||
1398 | for (i=1; i<=16; i++) |
||
1399 | { |
||
1400 | hufmaxatbit[index][i] = v+hufnumatbit[index][i]; |
||
1401 | hufvalatbit[index][i] = hufcnt[index]-v; |
||
1402 | Bmemcpy((void *)&huftable[index][hufcnt[index]],(void *)kfileptr,(int32_t)hufnumatbit[index][i]); |
||
1403 | if (i <= 10) |
||
1404 | for (c=0; c<hufnumatbit[index][i]; c++) |
||
1405 | for (j=(1<<(10-i)); j>0; j--) |
||
1406 | { |
||
1407 | hufquickval[index][hufquickcnt[index]] = huftable[index][hufcnt[index]+c]; |
||
1408 | hufquickbits[index][hufquickcnt[index]] = i; |
||
1409 | hufquickcnt[index]++; |
||
1410 | } |
||
1411 | kfileptr += hufnumatbit[index][i]; |
||
1412 | leng -= hufnumatbit[index][i]; |
||
1413 | hufcnt[index] += hufnumatbit[index][i]; |
||
1414 | v = ((v+hufnumatbit[index][i])<<1); |
||
1415 | } |
||
1416 | |||
109 | terminx | 1417 | } |
1762 | terminx | 1418 | while (leng > 0); |
109 | terminx | 1419 | break; |
1420 | case 0xdb: |
||
1762 | terminx | 1421 | do |
109 | terminx | 1422 | { |
1762 | terminx | 1423 | ch = *kfileptr++; leng--; |
1424 | index = (ch&15); |
||
1425 | prec = (ch>>4); |
||
1426 | for (z=0; z<64; z++) |
||
1427 | { |
||
1428 | v = (int32_t)(*kfileptr++); |
||
1429 | if (prec) v = (v<<8)+((int32_t)(*kfileptr++)); |
||
1430 | v <<= 19; |
||
1431 | if (unzig[z]&7) v = mulshr24(v,cosqr16[unzig[z]&7 ]); |
||
1432 | if (unzig[z]>>3) v = mulshr24(v,cosqr16[unzig[z]>>3]); |
||
1433 | quantab[index][unzig[z]] = v; |
||
1434 | } |
||
1435 | leng -= 64; |
||
1436 | if (prec) leng -= 64; |
||
109 | terminx | 1437 | } |
1762 | terminx | 1438 | while (leng > 0); |
109 | terminx | 1439 | break; |
1440 | case 0xdd: |
||
1762 | terminx | 1441 | restartinterval = SSWAPIL(*(uint16_t *)&kfileptr[0]); |
109 | terminx | 1442 | kfileptr += leng; |
1443 | break; |
||
1444 | case 0xda: |
||
1762 | terminx | 1445 | if ((xdim <= 0) || (ydim <= 0)) { if (dctbuf) Bfree(dctbuf); return(-1); } |
5 | Plagman | 1446 | |
1527 | terminx | 1447 | lnumcomponents = (int32_t)(*kfileptr++); if (!lnumcomponents) { if (dctbuf) Bfree(dctbuf); return(-1); } |
4634 | terminx | 1448 | if (lnumcomponents > 1) kcoltype = 2; |
1229 | terminx | 1449 | for (z=0; z<lnumcomponents; z++) |
109 | terminx | 1450 | { |
1451 | lcompid[z] = kfileptr[0]; |
||
1452 | lcompdc[z] = (kfileptr[1]>>4); |
||
1453 | lcompac[z] = (kfileptr[1]&15); |
||
1454 | kfileptr += 2; |
||
1455 | } |
||
5 | Plagman | 1456 | |
109 | terminx | 1457 | Ss = kfileptr[0]; |
1458 | Se = kfileptr[1]; |
||
1459 | Ah = (kfileptr[2]>>4); |
||
1460 | Al = (kfileptr[2]&15); |
||
1461 | kfileptr += 3; |
||
1462 | //printf("passcnt=%d, Ss=%d, Se=%d, Ah=%d, Al=%d\n",passcnt,Ss,Se,Ah,Al); |
||
5 | Plagman | 1463 | |
109 | terminx | 1464 | if ((!passcnt) && ((Ss) || (Se != 63) || (Ah) || (Al))) |
1465 | { |
||
1229 | terminx | 1466 | for (z=zz=0; z<gnumcomponents; z++) |
109 | terminx | 1467 | { |
1468 | dctx[z] = ((xdim+(ghsampmax<<3)-1)>>(glhsampmax+3)) << gcomphsampshift[z]; |
||
1469 | dcty[z] = ((ydim+(gvsampmax<<3)-1)>>(glvsampmax+3)) << gcompvsampshift[z]; |
||
1470 | zz += dctx[z]*dcty[z]; |
||
1471 | } |
||
1205 | terminx | 1472 | z = zz*64*sizeof(int16_t); |
1527 | terminx | 1473 | dctbuf = (int16_t *)Bmalloc(z); if (!dctbuf) return(-1); |
1440 | terminx | 1474 | Bmemset(dctbuf,0,z); |
1229 | terminx | 1475 | for (z=zz=0; z<gnumcomponents; z++) { dctptr[z] = &dctbuf[zz*64]; zz += dctx[z]*dcty[z]; } |
109 | terminx | 1476 | } |
5 | Plagman | 1477 | |
109 | terminx | 1478 | glhstep = glvstep = 0x7fffffff; |
1229 | terminx | 1479 | for (z=0; z<lnumcomponents; z++) |
1480 | for (zz=0; zz<gnumcomponents; zz++) |
||
109 | terminx | 1481 | if (lcompid[z] == gcompid[zz]) |
1482 | { |
||
1483 | ldctptr[z] = dctptr[zz]; |
||
1484 | ldctx[z] = dctx[zz]; |
||
2228 | hendricks2 | 1485 | // ldcty[z] = dcty[zz]; |
109 | terminx | 1486 | lcomphsamp[z] = gcomphsamp[zz]; |
1487 | lcompvsamp[z] = gcompvsamp[zz]; |
||
1488 | lcompquantab[z] = gcompquantab[zz]; |
||
1489 | if (!z) |
||
1490 | { |
||
1491 | lcomphsampshift0 = gcomphsampshift[zz]; |
||
1492 | lcompvsampshift0 = gcompvsampshift[zz]; |
||
1493 | } |
||
1494 | lshx[z] = glhsampmax-gcomphsampshift[zz]+3; |
||
1495 | lshy[z] = glvsampmax-gcompvsampshift[zz]+3; |
||
1496 | if (gcomphsampshift[zz] < glhstep) glhstep = gcomphsampshift[zz]; |
||
1497 | if (gcompvsampshift[zz] < glvstep) glvstep = gcompvsampshift[zz]; |
||
1498 | } |
||
1499 | glhstep = (ghsampmax>>glhstep); lcomphsamp[0] = min(lcomphsamp[0],glhstep); glhstep <<= 3; |
||
1500 | glvstep = (gvsampmax>>glvstep); lcompvsamp[0] = min(lcompvsamp[0],glvstep); glvstep <<= 3; |
||
1501 | lcomphvsamp0 = lcomphsamp[0]*lcompvsamp[0]; |
||
5 | Plagman | 1502 | |
4634 | terminx | 1503 | clipxdim = min(xdim,xres); |
1504 | clipydim = min(ydim,yres); |
||
5 | Plagman | 1505 | |
109 | terminx | 1506 | Alut[0] = (1<<Al); Alut[1] = -Alut[0]; |
5 | Plagman | 1507 | |
109 | terminx | 1508 | restartcnt = restartinterval; eobrun = 0; marker = 0xd0; |
1509 | num = 0; curbits = 0; |
||
1229 | terminx | 1510 | for (y=0; y<ydim; y+=glvstep) |
1511 | for (x=0; x<xdim; x+=glhstep) |
||
109 | terminx | 1512 | { |
1440 | terminx | 1513 | if (kfileptr-4-(uint8_t *)kfilebuf >= kfilength) goto kpegrend_break2; //rest of file is missing! |
5 | Plagman | 1514 | |
109 | terminx | 1515 | if (!dctbuf) dc = dct[0]; |
1229 | terminx | 1516 | for (c=0; c<lnumcomponents; c++) |
109 | terminx | 1517 | { |
1518 | hqval = &hufquickval[lcompac[c]+4][0]; |
||
1519 | hqbits = &hufquickbits[lcompac[c]+4][0]; |
||
1520 | hqcnt = hufquickcnt[lcompac[c]+4]; |
||
1521 | if (!dctbuf) quanptr = &quantab[lcompquantab[c]][0]; |
||
1229 | terminx | 1522 | for (yy=0; yy<(lcompvsamp[c]<<3); yy+=8) |
1523 | for (xx=0; xx<(lcomphsamp[c]<<3); xx+=8) |
||
1762 | terminx | 1524 | { |
1525 | //NOTE: Might help to split this code into firstime vs. refinement (!Ah vs. Ah!=0) |
||
5 | Plagman | 1526 | |
109 | terminx | 1527 | if (dctbuf) dcs = &ldctptr[c][(((y+yy)>>lshy[c])*ldctx[c] + ((x+xx)>>lshx[c]))<<6]; |
5 | Plagman | 1528 | |
109 | terminx | 1529 | //Get DC |
1530 | if (!Ss) |
||
1531 | { |
||
4597 | terminx | 1532 | KPEG_GETBITS(curbits, 16, num, kfileptr, kfileend); |
109 | terminx | 1533 | if (!Ah) |
1534 | { |
||
1535 | i = ((num>>(curbits-10))&1023); |
||
1536 | if (i < hufquickcnt[lcompdc[c]]) |
||
584 | terminx | 1537 | { daval = hufquickval[lcompdc[c]][i]; curbits -= hufquickbits[lcompdc[c]][i]; } |
109 | terminx | 1538 | else { huffgetval(lcompdc[c],curbits,num,&daval,&dabits); curbits -= dabits; } |
5 | Plagman | 1539 | |
109 | terminx | 1540 | if (daval) |
1541 | { |
||
4597 | terminx | 1542 | KPEG_GETBITS(curbits, daval, num, kfileptr, kfileend); |
109 | terminx | 1543 | curbits -= daval; v = ((unsigned)num >> curbits) & pow2mask[daval]; |
1544 | if (v <= pow2mask[daval-1]) v -= pow2mask[daval]; |
||
1545 | lastdc[c] += v; |
||
1546 | } |
||
1205 | terminx | 1547 | if (!dctbuf) dc[0] = lastdc[c]; else dcs[0] = (int16_t)(lastdc[c]<<Al); |
109 | terminx | 1548 | } |
1205 | terminx | 1549 | else if (num&(pow2long[--curbits])) dcs[0] |= ((int16_t)Alut[0]); |
109 | terminx | 1550 | } |
5 | Plagman | 1551 | |
109 | terminx | 1552 | //Get AC |
1440 | terminx | 1553 | if (!dctbuf) Bmemset((void *)&dc[1],0,63*4); |
109 | terminx | 1554 | z = max(Ss,1); dcflag = 1; |
1555 | if (eobrun <= 0) |
||
1556 | { |
||
1229 | terminx | 1557 | for (; z<=Se; z++) |
109 | terminx | 1558 | { |
4597 | terminx | 1559 | KPEG_GETBITS(curbits, 16, num, kfileptr, kfileend); |
109 | terminx | 1560 | i = ((num>>(curbits-10))&1023); |
1561 | if (i < hqcnt) |
||
584 | terminx | 1562 | { daval = hqval[i]; curbits -= hqbits[i]; } |
109 | terminx | 1563 | else { huffgetval(lcompac[c]+4,curbits,num,&daval,&dabits); curbits -= dabits; } |
5 | Plagman | 1564 | |
109 | terminx | 1565 | zz = (daval>>4); daval &= 15; |
1566 | if (daval) |
||
1567 | { |
||
1568 | if (Ah) |
||
1569 | { |
||
4597 | terminx | 1570 | KPEG_GETBITS(curbits, 8, num, kfileptr, kfileend); |
109 | terminx | 1571 | if (num&(pow2long[--curbits])) daval = Alut[0]; else daval = Alut[1]; |
1572 | } |
||
1573 | } |
||
1574 | else if (zz < 15) |
||
1575 | { |
||
1576 | eobrun = pow2long[zz]; |
||
1577 | if (zz) |
||
1578 | { |
||
4597 | terminx | 1579 | KPEG_GETBITS(curbits, zz, num, kfileptr, kfileend); |
109 | terminx | 1580 | curbits -= zz; eobrun += ((unsigned)num >> curbits) & pow2mask[zz]; |
1581 | } |
||
1582 | if (!Ah) eobrun--; |
||
1583 | break; |
||
1584 | } |
||
1585 | if (Ah) |
||
1586 | { |
||
1587 | do |
||
1588 | { |
||
1589 | if (dcs[z]) |
||
1590 | { |
||
4597 | terminx | 1591 | KPEG_GETBITS(curbits, 8, num, kfileptr, kfileend); |
1440 | terminx | 1592 | if (num&(pow2long[--curbits])) dcs[z] += (int16_t)Alut[dcs[z] < 0]; |
584 | terminx | 1593 | } |
1594 | else if (--zz < 0) break; |
||
109 | terminx | 1595 | z++; |
584 | terminx | 1596 | } |
1597 | while (z <= Se); |
||
1440 | terminx | 1598 | if (daval) dcs[z] = (int16_t)daval; |
109 | terminx | 1599 | } |
1600 | else |
||
1601 | { |
||
1602 | z += zz; if (z > Se) break; |
||
5 | Plagman | 1603 | |
4597 | terminx | 1604 | KPEG_GETBITS(curbits, daval, num, kfileptr, kfileend); |
109 | terminx | 1605 | curbits -= daval; v = ((unsigned)num >> curbits) & pow2mask[daval]; |
2164 | helixhorne | 1606 | if (daval>=1 /* FIXME ? */ && v <= pow2mask[daval-1]) v -= pow2mask[daval]; |
109 | terminx | 1607 | dcflag |= dcflagor[z]; |
1205 | terminx | 1608 | if (!dctbuf) dc[unzig[z]] = v; else dcs[z] = (int16_t)(v<<Al); |
109 | terminx | 1609 | } |
1610 | } |
||
584 | terminx | 1611 | } |
1612 | else if (!Ah) eobrun--; |
||
109 | terminx | 1613 | if ((Ah) && (eobrun > 0)) |
1614 | { |
||
1615 | eobrun--; |
||
1229 | terminx | 1616 | for (; z<=Se; z++) |
109 | terminx | 1617 | { |
1618 | if (!dcs[z]) continue; |
||
4597 | terminx | 1619 | KPEG_GETBITS(curbits, 8, num, kfileptr, kfileend); |
1205 | terminx | 1620 | if (num&(pow2long[--curbits])) dcs[z] += ((int16_t)Alut[dcs[z] < 0]); |
109 | terminx | 1621 | } |
1622 | } |
||
5 | Plagman | 1623 | |
109 | terminx | 1624 | if (!dctbuf) |
1625 | { |
||
1229 | terminx | 1626 | for (z=64-1; z>=0; z--) dc[z] *= quanptr[z]; |
109 | terminx | 1627 | invdct8x8(dc,dcflag); dc += 64; |
1628 | } |
||
1629 | } |
||
1630 | } |
||
5 | Plagman | 1631 | |
1440 | terminx | 1632 | if (!dctbuf) kplib_yrbrend_func(x,y,&dct[0][0]); |
5 | Plagman | 1633 | |
109 | terminx | 1634 | restartcnt--; |
1635 | if (!restartcnt) |
||
1636 | { |
||
1637 | kfileptr += 1-(curbits>>3); curbits = 0; |
||
1638 | if ((kfileptr[-2] != 255) || (kfileptr[-1] != marker)) kfileptr--; |
||
1639 | marker++; if (marker >= 0xd8) marker = 0xd0; |
||
1640 | restartcnt = restartinterval; |
||
1229 | terminx | 1641 | for (i=0; i<4; i++) lastdc[i] = 0; |
109 | terminx | 1642 | eobrun = 0; |
1643 | } |
||
1644 | } |
||
1762 | terminx | 1645 | kpegrend_break2:; |
109 | terminx | 1646 | if (!dctbuf) return(0); |
1647 | passcnt++; kfileptr -= ((curbits>>3)+1); break; |
||
1440 | terminx | 1648 | case 0xd9: break; |
1649 | default: kfileptr += leng; break; |
||
109 | terminx | 1650 | } |
584 | terminx | 1651 | } |
1440 | terminx | 1652 | while (kfileptr-(uint8_t *)kfilebuf < kfilength); |
5 | Plagman | 1653 | |
109 | terminx | 1654 | if (!dctbuf) return(0); |
5 | Plagman | 1655 | |
109 | terminx | 1656 | lnumcomponents = gnumcomponents; |
1229 | terminx | 1657 | for (i=0; i<gnumcomponents; i++) |
109 | terminx | 1658 | { |
1659 | lcomphsamp[i] = gcomphsamp[i]; gcomphsamp[i] <<= 3; |
||
1660 | lcompvsamp[i] = gcompvsamp[i]; gcompvsamp[i] <<= 3; |
||
1661 | lshx[i] = glhsampmax-gcomphsampshift[i]+3; |
||
1662 | lshy[i] = glvsampmax-gcompvsampshift[i]+3; |
||
1663 | } |
||
1664 | lcomphsampshift0 = gcomphsampshift[0]; |
||
1665 | lcompvsampshift0 = gcompvsampshift[0]; |
||
1666 | lcomphvsamp0 = (lcomphsamp[0]<<lcompvsampshift0); |
||
1229 | terminx | 1667 | for (y=0; y<ydim; y+=gcompvsamp[0]) |
1668 | for (x=0; x<xdim; x+=gcomphsamp[0]) |
||
109 | terminx | 1669 | { |
1670 | dc = dct[0]; |
||
1229 | terminx | 1671 | for (c=0; c<gnumcomponents; c++) |
1672 | for (yy=0; yy<gcompvsamp[c]; yy+=8) |
||
1673 | for (xx=0; xx<gcomphsamp[c]; xx+=8,dc+=64) |
||
109 | terminx | 1674 | { |
1675 | dcs = &dctptr[c][(((y+yy)>>lshy[c])*dctx[c] + ((x+xx)>>lshx[c]))<<6]; |
||
1676 | quanptr = &quantab[gcompquantab[c]][0]; |
||
1229 | terminx | 1677 | for (z=0; z<64; z++) dc[z] = ((int32_t)dcs[zigit[z]])*quanptr[z]; |
1440 | terminx | 1678 | invdct8x8(dc,0xff); |
109 | terminx | 1679 | } |
1440 | terminx | 1680 | kplib_yrbrend_func(x,y,&dct[0][0]); |
109 | terminx | 1681 | } |
5 | Plagman | 1682 | |
1527 | terminx | 1683 | Bfree(dctbuf); return(0); |
5 | Plagman | 1684 | } |
1685 | |||
1686 | //============================== KPEGILIB ends ============================== |
||
1687 | //================================ GIF begins ================================ |
||
1688 | |||
1440 | terminx | 1689 | static uint8_t suffix[4100], filbuffer[768], tempstack[4096]; |
1205 | terminx | 1690 | static int32_t prefix[4100]; |
5 | Plagman | 1691 | |
1205 | terminx | 1692 | static int32_t kgifrend(const char *kfilebuf, int32_t kfilelength, |
4634 | terminx | 1693 | intptr_t daframeplace, int32_t dabytesperline, int32_t daxres, int32_t dayres) |
5 | Plagman | 1694 | { |
1205 | terminx | 1695 | int32_t i, x, y, xsiz, ysiz, yinc, xend, xspan, yspan, currstr, numbitgoal; |
1696 | int32_t lzcols, dat, blocklen, bitcnt, xoff, transcol, backcol, *lptr; |
||
1440 | terminx | 1697 | intptr_t yoff; |
109 | terminx | 1698 | char numbits, startnumbits, chunkind, ilacefirst; |
1502 | terminx | 1699 | const uint8_t *ptr, *cptr = NULL; |
4634 | terminx | 1700 | int32_t daglobxoffs = 0, daglobyoffs = 0; |
1440 | terminx | 1701 | |
654 | terminx | 1702 | UNREFERENCED_PARAMETER(kfilelength); |
1703 | |||
4634 | terminx | 1704 | kcoltype = 3; bitdepth = 8; //For PNGOUT |
5 | Plagman | 1705 | |
1490 | terminx | 1706 | if ((kfilebuf[0] != 'G') || (kfilebuf[1] != 'I') || (kfilebuf[2] != 'F')) return(-1); |
109 | terminx | 1707 | paleng = (1<<((kfilebuf[10]&7)+1)); |
1440 | terminx | 1708 | ptr = (uint8_t *)&kfilebuf[13]; |
584 | terminx | 1709 | if (kfilebuf[10]&128) { cptr = ptr; ptr += paleng*3; } |
109 | terminx | 1710 | transcol = -1; |
1711 | while ((chunkind = *ptr++) == '!') |
||
1762 | terminx | 1712 | { |
1713 | //! 0xf9 leng flags ? ? transcol |
||
1205 | terminx | 1714 | if (ptr[0] == 0xf9) { if (ptr[2]&1) transcol = (int32_t)(((uint8_t)ptr[5])); } |
109 | terminx | 1715 | ptr++; |
584 | terminx | 1716 | do { i = *ptr++; ptr += i; } |
1717 | while (i); |
||
109 | terminx | 1718 | } |
1719 | if (chunkind != ',') return(-1); |
||
5 | Plagman | 1720 | |
1205 | terminx | 1721 | xoff = SSWAPIB(*(uint16_t *)&ptr[0]); |
1722 | yoff = SSWAPIB(*(uint16_t *)&ptr[2]); |
||
1723 | xspan = SSWAPIB(*(uint16_t *)&ptr[4]); |
||
1724 | yspan = SSWAPIB(*(uint16_t *)&ptr[6]); ptr += 9; |
||
584 | terminx | 1725 | if (ptr[-1]&64) { yinc = 8; ilacefirst = 1; } |
109 | terminx | 1726 | else { yinc = 1; ilacefirst = 0; } |
1727 | if (ptr[-1]&128) |
||
1728 | { |
||
1729 | paleng = (1<<((ptr[-1]&7)+1)); |
||
1730 | cptr = ptr; ptr += paleng*3; |
||
1731 | } |
||
5 | Plagman | 1732 | |
1229 | terminx | 1733 | for (i=0; i<paleng; i++) |
1205 | terminx | 1734 | palcol[i] = LSWAPIB((((int32_t)cptr[i*3])<<16) + (((int32_t)cptr[i*3+1])<<8) + ((int32_t)cptr[i*3+2]) + 0xff000000); |
1229 | terminx | 1735 | for (; i<256; i++) palcol[i] = LSWAPIB(0xff000000); |
109 | terminx | 1736 | if (transcol >= 0) palcol[transcol] &= LSWAPIB(~0xff000000); |
5 | Plagman | 1737 | |
109 | terminx | 1738 | //Handle GIF files with different logical&image sizes or non-0 offsets (added 05/15/2004) |
1205 | terminx | 1739 | xsiz = SSWAPIB(*(uint16_t *)&kfilebuf[6]); |
1740 | ysiz = SSWAPIB(*(uint16_t *)&kfilebuf[8]); |
||
109 | terminx | 1741 | if ((xoff != 0) || (yoff != 0) || (xsiz != xspan) || (ysiz != yspan)) |
1742 | { |
||
1205 | terminx | 1743 | int32_t xx[4], yy[4]; |
1744 | if (kfilebuf[10]&128) backcol = palcol[(uint8_t)kfilebuf[11]]; else backcol = 0; |
||
5 | Plagman | 1745 | |
109 | terminx | 1746 | //Fill border to backcol |
1205 | terminx | 1747 | lptr = (int32_t *)(yy[0]*dabytesperline+daframeplace); |
1229 | terminx | 1748 | for (y=yy[0]; y<yy[1]; y++,lptr=(int32_t *)(((intptr_t)lptr)+dabytesperline)) |
1749 | for (x=xx[0]; x<xx[3]; x++) lptr[x] = backcol; |
||
1750 | for (; y<yy[2]; y++,lptr=(int32_t *)(((intptr_t)lptr)+dabytesperline)) |
||
584 | terminx | 1751 | { |
1229 | terminx | 1752 | for (x=xx[0]; x<xx[1]; x++) lptr[x] = backcol; |
1753 | for (x=xx[2]; x<xx[3]; x++) lptr[x] = backcol; |
||
109 | terminx | 1754 | } |
1229 | terminx | 1755 | for (; y<yy[3]; y++,lptr=(int32_t *)(((intptr_t)lptr)+dabytesperline)) |
1756 | for (x=xx[0]; x<xx[3]; x++) lptr[x] = backcol; |
||
5 | Plagman | 1757 | |
109 | terminx | 1758 | daglobxoffs += xoff; //Offset bitmap image by extra amount |
1759 | daglobyoffs += yoff; |
||
1760 | } |
||
5 | Plagman | 1761 | |
109 | terminx | 1762 | xspan += daglobxoffs; |
1763 | yspan += daglobyoffs; //UGLY HACK |
||
1764 | y = daglobyoffs; |
||
1205 | terminx | 1765 | if ((uint32_t)y < (uint32_t)dayres) |
584 | terminx | 1766 | { yoff = y*dabytesperline+daframeplace; x = daglobxoffs; xend = xspan; } |
109 | terminx | 1767 | else |
584 | terminx | 1768 | { x = daglobxoffs+0x80000000; xend = xspan+0x80000000; } |
5 | Plagman | 1769 | |
1205 | terminx | 1770 | lzcols = (1<<(*ptr)); startnumbits = (uint8_t)((*ptr)+1); ptr++; |
1229 | terminx | 1771 | for (i=lzcols-1; i>=0; i--) { suffix[i] = (uint8_t)(prefix[i] = i); } |
109 | terminx | 1772 | currstr = lzcols+2; numbits = startnumbits; numbitgoal = (lzcols<<1); |
1773 | blocklen = *ptr++; |
||
1425 | terminx | 1774 | Bmemcpy(filbuffer,ptr,blocklen); ptr += blocklen; |
109 | terminx | 1775 | bitcnt = 0; |
1776 | while (1) |
||
1777 | { |
||
1205 | terminx | 1778 | dat = (LSWAPIB(*(int32_t *)&filbuffer[bitcnt>>3])>>(bitcnt&7)) & (numbitgoal-1); |
109 | terminx | 1779 | bitcnt += numbits; |
1780 | if ((bitcnt>>3) > blocklen-3) |
||
1781 | { |
||
1205 | terminx | 1782 | *(int16_t *)filbuffer = *(int16_t *)&filbuffer[bitcnt>>3]; |
109 | terminx | 1783 | i = blocklen-(bitcnt>>3); |
1205 | terminx | 1784 | blocklen = (int32_t)*ptr++; |
1425 | terminx | 1785 | Bmemcpy(&filbuffer[i],ptr,blocklen); ptr += blocklen; |
109 | terminx | 1786 | bitcnt &= 7; blocklen += i; |
1787 | } |
||
1788 | if (dat == lzcols) |
||
1789 | { |
||
1790 | currstr = lzcols+2; numbits = startnumbits; numbitgoal = (lzcols<<1); |
||
1791 | continue; |
||
1792 | } |
||
1793 | if ((currstr == numbitgoal) && (numbits < 12)) |
||
584 | terminx | 1794 | { numbits++; numbitgoal <<= 1; } |
5 | Plagman | 1795 | |
109 | terminx | 1796 | prefix[currstr] = dat; |
1229 | terminx | 1797 | for (i=0; dat>=lzcols; dat=prefix[dat]) tempstack[i++] = suffix[dat]; |
1205 | terminx | 1798 | tempstack[i] = (uint8_t)prefix[dat]; |
1799 | suffix[currstr-1] = suffix[currstr] = (uint8_t)dat; |
||
5 | Plagman | 1800 | |
1229 | terminx | 1801 | for (; i>=0; i--) |
109 | terminx | 1802 | { |
1205 | terminx | 1803 | if ((uint32_t)x < (uint32_t)daxres) |
1804 | *(int32_t *)(yoff+(x<<2)) = palcol[(int32_t)tempstack[i]]; |
||
109 | terminx | 1805 | x++; |
1806 | if (x == xend) |
||
1807 | { |
||
1808 | y += yinc; |
||
1809 | if (y >= yspan) |
||
331 | terminx | 1810 | switch (yinc) |
109 | terminx | 1811 | { |
1440 | terminx | 1812 | case 8: if (!ilacefirst) { y = daglobyoffs+2; yinc = 4; break; } |
109 | terminx | 1813 | ilacefirst = 0; y = daglobyoffs+4; yinc = 8; break; |
1440 | terminx | 1814 | case 4: y = daglobyoffs+1; yinc = 2; break; |
1815 | case 2: case 1: return(0); |
||
109 | terminx | 1816 | } |
1205 | terminx | 1817 | if ((uint32_t)y < (uint32_t)dayres) |
584 | terminx | 1818 | { yoff = y*dabytesperline+daframeplace; x = daglobxoffs; xend = xspan; } |
109 | terminx | 1819 | else |
584 | terminx | 1820 | { x = daglobxoffs+0x80000000; xend = xspan+0x80000000; } |
109 | terminx | 1821 | } |
1822 | } |
||
1823 | currstr++; |
||
1824 | } |
||
5 | Plagman | 1825 | } |
1826 | |||
1827 | //=============================== GIF ends ================================== |
||
1828 | //============================== CEL begins ================================= |
||
1829 | |||
109 | terminx | 1830 | // //old .CEL format: |
1440 | terminx | 1831 | //int16_t id = 0x9119, xdim, ydim, xoff, yoff, id = 0x0008; |
1205 | terminx | 1832 | //int32_t imagebytes, filler[4]; |
109 | terminx | 1833 | //char pal6bit[256][3], image[ydim][xdim]; |
4634 | terminx | 1834 | #ifdef KPCEL |
1205 | terminx | 1835 | static int32_t kcelrend(const char *buf, int32_t fleng, |
4634 | terminx | 1836 | intptr_t daframeplace, int32_t dabytesperline, int32_t daxres, int32_t dayres) |
5 | Plagman | 1837 | { |
1205 | terminx | 1838 | int32_t i, x, y, x0, x1, y0, y1, xsiz, ysiz; |
109 | terminx | 1839 | const char *cptr; |
5 | Plagman | 1840 | |
654 | terminx | 1841 | UNREFERENCED_PARAMETER(fleng); |
1842 | |||
4634 | terminx | 1843 | kcoltype = 3; bitdepth = 8; paleng = 256; //For PNGOUT |
5 | Plagman | 1844 | |
1205 | terminx | 1845 | xsiz = (int32_t)SSWAPIB(*(uint16_t *)&buf[2]); if (xsiz <= 0) return(-1); |
1846 | ysiz = (int32_t)SSWAPIB(*(uint16_t *)&buf[4]); if (ysiz <= 0) return(-1); |
||
5 | Plagman | 1847 | |
109 | terminx | 1848 | cptr = &buf[32]; |
1229 | terminx | 1849 | for (i=0; i<256; i++) |
109 | terminx | 1850 | { |
1205 | terminx | 1851 | palcol[i] = (((int32_t)cptr[0])<<18) + |
1852 | (((int32_t)cptr[1])<<10) + |
||
1853 | (((int32_t)cptr[2])<< 2) + LSWAPIB(0xff000000); |
||
109 | terminx | 1854 | cptr += 3; |
1855 | } |
||
5 | Plagman | 1856 | |
4634 | terminx | 1857 | x0 = 0; x1 = xsiz; |
1858 | y0 = 0; y1 = ysiz; |
||
1229 | terminx | 1859 | for (y=y0; y<y1; y++) |
1860 | for (x=x0; x<x1; x++) |
||
109 | terminx | 1861 | { |
1205 | terminx | 1862 | if (((uint32_t)x < (uint32_t)daxres) && ((uint32_t)y < (uint32_t)dayres)) |
1863 | *(int32_t *)(y*dabytesperline+x*4+daframeplace) = palcol[cptr[0]]; |
||
109 | terminx | 1864 | cptr++; |
1865 | } |
||
1866 | return(0); |
||
5 | Plagman | 1867 | } |
4634 | terminx | 1868 | #endif |
5 | Plagman | 1869 | |
1870 | //=============================== CEL ends ================================== |
||
1871 | //============================= TARGA begins ================================ |
||
1872 | |||
1205 | terminx | 1873 | static int32_t ktgarend(const char *header, int32_t fleng, |
4634 | terminx | 1874 | intptr_t daframeplace, int32_t dabytesperline, int32_t daxres, int32_t dayres) |
5 | Plagman | 1875 | { |
1502 | terminx | 1876 | int32_t i = 0, x, y, pi, xi, yi, x0, x1, y0, y1, xsiz, ysiz, rlestat, colbyte, pixbyte; |
737 | qbix79 | 1877 | intptr_t p; |
5 | Plagman | 1878 | |