1
4
5# include "luametatex.h"
6
7
14
15
16
17static int pnglib_applyfilter(lua_State *L)
18{
19 size_t size;
20 const char *s = luaL_checklstring(L, 1, &size);
21 int xsize = lmt_tointeger(L, 2);
22 int ysize = lmt_tointeger(L, 3);
23 int slice = lmt_tointeger(L, 4);
24 int len = xsize * slice + 1;
25 int n = 0;
26 int m = len - 1;
27 unsigned char *t;
28 if (ysize * len != (int) size) {
29 tex_formatted_warning("png filter", "sizes don't match: %i expected, %i provided", ysize *len, size);
30 return 0;
31 }
32 t = lmt_memory_malloc(size);
33 if (! t) {
34 tex_normal_warning("png filter", "not enough memory");
35 return 0;
36 }
37 memcpy(t, s, size);
38 for (int i = 0; i < ysize; i++) {
39 switch (t[n]) {
40 case 0 :
41 break;
42 case 1 :
43 for (int j = n + slice + 1; j <= n + m; j++) {
44 t[j] = (unsigned char) (t[j] + t[j-slice]);
45 }
46 break;
47 case 2 :
48 if (i > 0) {
49 for (int j = n + 1; j <= n + m; j++) {
50 t[j] = (unsigned char) (t[j] + t[j-len]);
51 }
52 }
53 break;
54 case 3 :
55 if (i > 0) {
56 for (int j = n + 1; j <= n + slice; j++) {
57 t[j] = (unsigned char) (t[j] + t[j-len]/2);
58 }
59 for (int j = n + slice + 1; j <= n + m; j++) {
60 t[j] = (unsigned char) (t[j] + (t[j-slice] + t[j-len])/2);
61 }
62 } else {
63 for (int j = n + slice + 1; j <= n + m; j++) {
64 t[j] = (unsigned char) (t[j] + t[j-slice]/2);
65 }
66 }
67 break;
68 case 4 :
69 if (i > 0) {
70 for (int j = n + 1; j <= n + slice; j++) {
71 int p = j - len;
72 t[j] = (unsigned char) (t[j] + t[p]);
73 }
74 for (int j = n + slice + 1; j <= n + m; j++) {
75 int p = j - len;
76 unsigned char a = t[j-slice];
77 unsigned char b = t[p];
78 unsigned char c = t[p-slice];
79 int pa = b - c;
80 int pb = a - c;
81 int pc = pa + pb;
82 if (pa < 0) { pa = - pa; }
83 if (pb < 0) { pb = - pb; }
84 if (pc < 0) { pc = - pc; }
85 t[j] = (unsigned char) (t[j] + ((pa <= pb && pa <= pc) ? a : ((pb <= pc) ? b : c)));
86 }
87 } else {
88
89
104 }
105 break;
106 default:
107 break;
108 }
109 n = n + len;
110 }
111
112 {
113 int j = 0;
114 int m = 0;
115 for (int i = 0; i < ysize; i++) {
116
117 (void) memmove(&t[m], &t[j+1], (size_t)len - 1);
118 j += len;
119 m += len - 1;
120 }
121 lua_pushlstring(L, (char *) t, size-ysize);
122
132 }
133 lmt_memory_free(t);
134 return 1;
135}
136
137
138
139static int pnglib_splitmask(lua_State *L)
140{
141 size_t size;
142 const char *t = luaL_checklstring(L, 1, &size);
143 int xsize = lmt_tointeger(L, 2);
144 int ysize = lmt_tointeger(L, 3);
145 int bpp = lmt_tointeger(L, 4);
146 int bytes = lmt_tointeger(L, 5);
147 int slice = (bpp + 1) * bytes;
148 int len = xsize * slice;
149 int blen = bpp * bytes;
150 int mlen = bytes;
151 int nt = 0;
152 int nb = 0;
153 int nm = 0;
154 int bsize = ysize * xsize * blen;
155 int msize = ysize * xsize * mlen;
156 char *b, *m;
157
158 if (ysize * len != (int) size) {
159 tex_formatted_warning("png split", "sizes don't match: %i expected, %i provided", ysize * len, size);
160 return 0;
161 }
162 b = lmt_memory_malloc(bsize);
163 m = lmt_memory_malloc(msize);
164 if (! (b && m)) {
165 tex_normal_warning("png split mask", "not enough memory");
166 return 0;
167 }
168
169 switch (blen) {
170 case 1:
171
172 for (int i = 0; i < ysize * xsize; i++) {
173 b[nb++] = t[nt++];
174 m[nm++] = t[nt++];
175 }
176 break;
177 case 3:
178
179 for (int i = 0; i < ysize * xsize; i++) {
180
185 memcpy(&b[nb], &t[nt], 3);
186 nt += 3;
187 nb += 3;
188 m[nm++] = t[nt++];
189 }
190 break;
191 default:
192
193 for (int i = 0; i < ysize * xsize; i++) {
194 memcpy (&b[nb], &t[nt], blen);
195 nt += blen;
196 nb += blen;
197 memcpy (&m[nm], &t[nt], mlen);
198 nt += mlen;
199 nm += mlen;
200 }
201 break;
202 }
203 lua_pushlstring(L, b, bsize);
204 lmt_memory_free(b);
205 lua_pushlstring(L, m, msize);
206 lmt_memory_free(m);
207 return 2;
208}
209
210
211
212static int pnglib_interlace(lua_State *L)
213{
214 int xstarts[] = { 0, 4, 0, 2, 0, 1, 0 };
215 int ystarts[] = { 0, 0, 4, 0, 2, 0, 1 };
216 int xsteps[] = { 8, 8, 4, 4, 2, 2, 1 };
217 int ysteps[] = { 8, 8, 8, 4, 4, 2, 2 };
218 size_t isize = 0;
219 size_t psize = 0;
220 const char *inp;
221 const char *pre;
222 char *out;
223 int xsize, ysize, xstep, ystep, xstart, ystart, slice, pass, nx, ny;
224 int target, start, step, size;
225
226 xsize = lmt_tointeger(L, 1);
227 ysize = lmt_tointeger(L, 2);
228 slice = lmt_tointeger(L, 3);
229 pass = lmt_tointeger(L, 4);
230 if (pass < 1 || pass > 7) {
231 tex_formatted_warning("png interlace", "bass pass: %i (1..7)", pass);
232 return 0;
233 }
234 pass = pass - 1;
235
236 nx = (xsize + xsteps[pass] - xstarts[pass] - 1) / xsteps[pass];
237 ny = (ysize + ysteps[pass] - ystarts[pass] - 1) / ysteps[pass];
238
239 xstart = xstarts[pass];
240 xstep = xsteps[pass];
241 ystart = ystarts[pass];
242 ystep = ysteps[pass];
243
244 xstep = xstep * slice;
245 xstart = xstart * slice;
246 xsize = xsize * slice;
247 target = ystart * xsize + xstart;
248 ystep = ystep * xsize;
249
250 step = nx * xstep;
251 size = ysize * xsize;
252 start = 0;
253
254 inp = luaL_checklstring(L, 5, &isize);
255 pre = NULL;
256 out = NULL;
257 if (pass > 0) {
258 pre = luaL_checklstring(L, 6, &psize);
259 if ((int) psize < size) {
260 tex_formatted_warning("png interlace", "output sizes don't match: %i expected, %i provided", psize, size);
261 return 0;
262 }
263 }
264
265 out = lmt_memory_malloc(size);
266 if (out) {
267 if (pass == 0) {
268 memset(out, 0, size);
269 }
270 else {
271 memcpy(out, pre, psize);
272 }
273 } else {
274 tex_normal_warning("png interlace", "not enough memory");
275 return 0;
276 }
277 switch (slice) {
278 case 1:
279 for (int j = 0; j < ny; j++) {
280 int t = target + j * ystep;
281 for (int i = t; i < t + step; i += xstep) {
282 out[i] = inp[start];
283 start = start + slice;
284 }
285 }
286 break;
287 case 2:
288 for (int j = 0; j < ny; j++) {
289 int t = target + j * ystep;
290 for (int i = t; i < t + step; i += xstep) {
291 out[i] = inp[start];
292 out[i+1] = inp[start+1];
293 start = start + slice;
294 }
295 }
296 break;
297 case 3:
298 for (int j = 0; j < ny; j++) {
299 int t = target + j * ystep;
300 for (int i = t; i < t + step;i += xstep) {
301 out[i] = inp[start];
302 out[i+1] = inp[start+1];
303 out[i+2] = inp[start+2];
304 start = start + slice;
305 }
306 }
307 break;
308 default:
309 for (int j = 0; j < ny; j++) {
310 int t = target + j * ystep;
311 for (int i = t; i < t + step; i += xstep) {
312 memcpy(&out[i], &inp[start], slice);
313 start = start + slice;
314 }
315 }
316 break;
317 }
318 lua_pushlstring(L, out, size);
319 lmt_memory_free(out);
320 return 1;
321}
322
323
324
325# define extract1(a,b) ((a >> b) & 0x01)
326# define extract2(a,b) ((a >> b) & 0x03)
327# define extract4(a,b) ((a >> b) & 0x0F)
328
329static int pnglib_expand(lua_State *L)
330{
331 size_t tsize;
332 const char *t = luaL_checklstring(L, 1, &tsize);
333 char *o = NULL;
334 int n = 0;
335 int k = 0;
336 int xsize = lmt_tointeger(L, 2);
337 int ysize = lmt_tointeger(L, 3);
338 int parts = lmt_tointeger(L, 4);
339 int xline = lmt_tointeger(L, 5);
340 int factor = lua_toboolean(L, 6);
341 int size = ysize * xsize;
342 int extra = ysize * xsize + 16;
343 if (xline*ysize > (int) tsize) {
344 tex_formatted_warning("png expand","expand sizes don't match: %i expected, %i provided",size,parts*tsize);
345 return 0;
346 }
347 o = lmt_memory_malloc(extra);
348 if (! o) {
349 tex_normal_warning ("png expand", "not enough memory");
350 return 0;
351 }
352
353 if (factor) {
354 switch (parts) {
355 case 4:
356 for (int i = 0; i < ysize; i++) {
357 k = i * xsize;
358 for (int j = n; j < n + xline; j++) {
359 unsigned char v = t[j];
360 o[k++] = (unsigned char) extract4 (v, 4) * 0x11;
361 o[k++] = (unsigned char) extract4 (v, 0) * 0x11;
362 }
363 n = n + xline;
364 }
365 break;
366 case 2:
367 for (int i = 0; i < ysize; i++) {
368 k = i * xsize;
369 for (int j = n; j < n + xline; j++) {
370 unsigned char v = t[j];
371 for (int b = 6; b >= 0; b -= 2) {
372 o[k++] = (unsigned char) extract2 (v, b) * 0x55;
373 }
374 }
375 n = n + xline;
376 }
377 break;
378 default:
379 for (int i = 0; i < ysize; i++) {
380 k = i * xsize;
381 for (int j = n; j < n + xline; j++) {
382 unsigned char v = t[j];
383 for (int b = 7; b >= 0; b--) {
384 o[k++] = (unsigned char) extract1 (v, b) * 0xFF;
385 }
386 }
387 n = n + xline;
388 }
389 break;
390 }
391 } else {
392 switch (parts) {
393 case 4:
394 for (int i = 0; i < ysize; i++) {
395 k = i * xsize;
396 for (int j = n; j < n + xline; j++) {
397 unsigned char v = t[j];
398 o[k++] = (unsigned char) extract4 (v, 4);
399 o[k++] = (unsigned char) extract4 (v, 0);
400 }
401 n = n + xline;
402 }
403 break;
404 case 2:
405 for (int i = 0; i < ysize; i++) {
406 k = i * xsize;
407 for (int j = n; j < n + xline; j++) {
408 unsigned char v = t[j];
409 for (int b = 6; b >= 0; b -= 2) {
410 o[k++] = (unsigned char) extract2 (v, b);
411 }
412 }
413 n = n + xline;
414 }
415 break;
416 default:
417 for (int i = 0; i < ysize; i++) {
418 k = i * xsize;
419 for (int j = n; j < n + xline; j++) {
420 unsigned char v = t[j];
421 for (int b = 7; b >= 0; b--) {
422 o[k++] = (unsigned char) extract1 (v, b);
423 }
424 }
425 n = n + xline;
426 }
427 break;
428 }
429 }
430 lua_pushlstring(L, o, size);
431 lmt_memory_free(o);
432 return 1;
433}
434
435
440
441static int pnglib_tocmyk(lua_State *L)
442{
443 size_t tsize;
444 const char *t = luaL_checklstring(L, 1, &tsize);
445 int depth = lmt_optinteger(L, 2, 0);
446 if ((tsize > 0) && (depth == 8 || depth == 16)) {
447 size_t osize = 0;
448 char *o = NULL;
449 if (depth == 8) {
450 o = lmt_memory_malloc(4 * (tfloor(tsize/3) + 1));
451 } else {
452 o = lmt_memory_malloc(8 * (tfloor(tsize/6) + 1));
453 }
454 if (! o) {
455 tex_normal_warning ("png tocmyk", "not enough memory");
456 return 0;
457 } else if (depth == 8) {
458
466 for (size_t i = 0; i < tsize; ) {
467 o[osize++] = (const char) (0xFF - t[i++]);
468 o[osize++] = (const char) (0xFF - t[i++]);
469 o[osize++] = (const char) (0xFF - t[i++]);
470 o[osize++] = '\0';
471 }
472 } else {
473
474
486 for (size_t i = 0; i < tsize; ) {
487 o[osize++] = (const char) (0xFF - t[i++]);
488 o[osize++] = (const char) (0xFF - t[i++]);
489 o[osize++] = (const char) (0xFF - t[i++]);
490 o[osize++] = (const char) (0xFF - t[i++]);
491 o[osize++] = (const char) (0xFF - t[i++]);
492 o[osize++] = (const char) (0xFF - t[i++]);
493 o[osize++] = '\0';
494 o[osize++] = '\0';
495 }
496 }
497 lua_pushlstring(L, o, osize-1);
498 lmt_memory_free(o);
499 } else {
500 lua_pushnil(L);
501 }
502 return 1;
503}
504
505
506
507static int pnglib_tomask(lua_State *L)
508{
509 size_t tsize, ssize;
510 const char *t = luaL_checklstring(L, 1, &tsize);
511 const char *s = luaL_checklstring(L, 2, &ssize);
512 size_t xsize = lmt_tosizet(L, 3);
513 size_t ysize = lmt_tosizet(L, 4);
514 int colordepth = lmt_tointeger(L, 5);
515 size_t osize = xsize * ysize;
516 if (osize == tsize) {
517 char *o = lmt_memory_malloc(osize);
518 char *v = lmt_memory_calloc(256,1);
519 size_t len = xsize * colordepth / 8;
520 size_t k = 0;
521 memset(v, 0xFF, 256);
522 memcpy(v, s, ssize > 256 ? 256 : ssize);
523 for (size_t i = 0; i < ysize; i++) {
524 size_t f = i * len;
525 size_t l = f + len;
526 switch (colordepth) {
527 case 8:
528 for (size_t j = f; j < l; j++) {
529 int c = t[j];
530 o[k++] = (unsigned char) v[c];
531 }
532 break;
533 case 4:
534 for (size_t j = f; j < l; j++) {
535 int c = t[j];
536 o[k++] = (unsigned char) v[(c >> 4) & 0x0F];
537 o[k++] = (unsigned char) v[(c >> 0) & 0x0F];
538 }
539 break;
540 case 2:
541 for (size_t j = f; j < l; j++) {
542 int c = t[j];
543 o[k++] = (unsigned char) v[(c >> 6) & 0x03];
544 o[k++] = (unsigned char) v[(c >> 4) & 0x03];
545 o[k++] = (unsigned char) v[(c >> 2) & 0x03];
546 o[k++] = (unsigned char) v[(c >> 0) & 0x03];
547 }
548 break;
549 default:
550 for (size_t j = f; j < l; j++) {
551 int c = t[j];
552 o[k++] = (unsigned char) v[(c >> 7) & 0x01];
553 o[k++] = (unsigned char) v[(c >> 6) & 0x01];
554 o[k++] = (unsigned char) v[(c >> 5) & 0x01];
555 o[k++] = (unsigned char) v[(c >> 4) & 0x01];
556 o[k++] = (unsigned char) v[(c >> 3) & 0x01];
557 o[k++] = (unsigned char) v[(c >> 2) & 0x01];
558 o[k++] = (unsigned char) v[(c >> 1) & 0x01];
559 o[k++] = (unsigned char) v[(c >> 0) & 0x01];
560 }
561 break;
562 }
563 }
564 lua_pushlstring(L, o, osize);
565 lmt_memory_free(o);
566 } else {
567 lua_pushnil(L);
568 }
569 return 1;
570}
571static int pnglib_makemask(lua_State *L)
572{
573 size_t size;
574 const char *content = luaL_checklstring(L, 1, &size);
575 char mapping[256] = { 0x00 };
576 char *mask = lmt_memory_malloc(size);
577 switch (lua_type(L, 2)) {
578 case LUA_TNUMBER:
579 {
580 int n = lua_tointeger(L, 2);
581 n = n < 0 ? 0 : n > 255 ? 255 : n;
582 for (int i = 0; i <= n; i++) {
583 mapping[i] = 0xFF;
584 }
585 }
586 break;
587 case LUA_TTABLE:
588 {
589 int n = (int) lua_rawlen(L, 2);
590 for (int i = 1; i <= n; i++) {
591 if (lua_rawgeti(L, 2, i) == LUA_TTABLE) {
592 int m = (int) lua_rawlen(L, -1);
593 if (m == 3) {
594 int b, e, v;
595 lua_rawgeti(L, -1, 1);
596 lua_rawgeti(L, -2, 2);
597 lua_rawgeti(L, -3, 3);
598 b = lua_tointeger(L, -3);
599 e = lua_tointeger(L, -2);
600 v = lua_tointeger(L, -1);
601 b = b < 0 ? 0 : b > 255 ? 255 : b;
602 e = e < 0 ? 0 : e > 255 ? 255 : e;
603 v = v < 0 ? 0 : v > 255 ? 255 : v;
604 for (int i = b; i <= e; i++) {
605 mapping[i] = (char) v;
606 }
607 lua_pop(L, 3);
608 }
609 }
610 lua_pop(L, 1);
611 }
612 }
613 case LUA_TSTRING:
614 {
615 size_t l = 0;
616 const char *m = luaL_checklstring(L, 1, &l);
617 memcpy(mask, m, l > size ? size : l);
618 }
619 break;
620 default:
621 break;
622 }
623 for (int i = 0; i < size; i++) {
624 mask[i] = (unsigned char) mapping[(unsigned char) content[i]];
625 }
626 lua_pushlstring(L, mask, size);
627 lua_pushlstring(L, mapping, 256);
628 lmt_memory_free(mask);
629 return 2;
630}
631
632static const struct luaL_Reg pngdecodelib_function_list[] = {
633 { "applyfilter", pnglib_applyfilter },
634 { "splitmask", pnglib_splitmask },
635 { "interlace", pnglib_interlace },
636 { "expand", pnglib_expand },
637 { "tocmyk", pnglib_tocmyk },
638 { "tomask", pnglib_tomask },
639 { "makemask", pnglib_makemask },
640 { NULL, NULL },
641};
642
643int luaopen_pngdecode(lua_State *L)
644{
645 lua_newtable(L);
646 luaL_setfuncs(L, pngdecodelib_function_list, 0);
647 return 1;
648}
649
650
651
652static const struct luaL_Reg pdfdecodelib_function_list[] = {
653 { NULL, NULL }
654};
655
656int luaopen_pdfdecode(lua_State *L)
657{
658 lua_newtable(L);
659 luaL_setfuncs(L, pdfdecodelib_function_list, 0);
660 return 1;
661}
662 |