@@ -343,228 +343,3 @@ static const ISzAlloc g_Alloc = { SzAlloc, SzFree };
343
343
344
344
#endif //INCLUDE_LZMA
345
345
346
-
347
- #ifdef INCLUDE_PNG_FILTER
348
- #ifdef INCLUDE_PNG_CODEC
349
- int paeth_predictor (int a , int b , int c );
350
- #else
351
- #define int_abs (a ) (((a)<0)?(-(a)):(a))
352
- static int paeth_predictor (int a , int b , int c ) {
353
- int p , pa , pb , pc ;
354
-
355
- p = a + b - c ;
356
- pa = int_abs (p - a );
357
- pb = int_abs (p - b );
358
- pc = int_abs (p - c );
359
- if ((pa <= pb ) && (pa <= pc ))
360
- return a ;
361
- else if (pb <= pc )
362
- return b ;
363
- return c ;
364
- }
365
- #endif
366
-
367
- enum PNG_Filter_Types {
368
- PNG_FILTER_SUB = 1 ,
369
- PNG_FILTER_UP ,
370
- PNG_FILTER_AVERAGE ,
371
- PNG_FILTER_PAETH
372
- };
373
-
374
- static REBYTE get_png_filter_type (REBVAL * val ) {
375
- if (IS_WORD (val )) {
376
- switch (VAL_WORD_SYM (val )) {
377
- case SYM_SUB : return PNG_FILTER_SUB ;
378
- case SYM_UP : return PNG_FILTER_UP ;
379
- case SYM_AVERAGE : return PNG_FILTER_AVERAGE ;
380
- case SYM_PAETH : return PNG_FILTER_PAETH ;
381
- }
382
- }
383
- else if (IS_INTEGER (val )) {
384
- return MIN (PNG_FILTER_PAETH , MAX (0 , VAL_INT32 (val )));
385
- }
386
- Trap1 (RE_INVALID_ARG , val );
387
- return 0 ; // to make xcode happy
388
- }
389
-
390
- // See: https://www.rfc-editor.org/rfc/rfc2083.html#page-31
391
- // https://en.wikipedia.org/wiki/Portable_Network_Graphics#Filtering
392
- /***********************************************************************
393
- **
394
- */ REBNATIVE (filter )
395
- /*
396
- // filter: native [
397
- // "PNG delta filter"
398
- // data [binary!] "Input"
399
- // width [number!] "Scanline width"
400
- // type [integer! word!] "1..4 or one of: [sub up average paeth]"
401
- // /skip bpp [integer!] "Bytes per pixel"
402
- // ]
403
- ***********************************************************************/
404
- {
405
- REBVAL * val_data = D_ARG (1 );
406
- REBVAL * val_width = D_ARG (2 );
407
- REBVAL * val_type = D_ARG (3 );
408
- REBOOL ref_skip = D_REF (4 );
409
- REBVAL * val_bpp = D_ARG (5 );
410
-
411
- REBSER * ser ;
412
- REBYTE * bin = VAL_BIN_DATA (val_data );
413
- REBYTE * scan , * prev , * temp , * out ;
414
- REBCNT r , c , rows , bytes ;
415
- REBINT width = AS_INT32 (val_width );
416
- REBYTE filter = get_png_filter_type (val_type );
417
- REBCNT bpp = ref_skip ? VAL_INT32 (val_bpp ) : 1 ;
418
-
419
- bytes = VAL_LEN (val_data );
420
-
421
- if (width <= 1 || width > bytes )
422
- Trap1 (RE_INVALID_ARG , val_width );
423
- if (bpp < 1 || bpp > width )
424
- Trap1 (RE_INVALID_ARG , val_bpp );
425
-
426
- rows = bytes / width ;
427
- ser = Make_Binary (bytes );
428
- out = BIN_DATA (ser );
429
-
430
- temp = malloc (width );
431
- if (!temp ) {
432
- Trap0 (RE_NO_MEMORY );
433
- return R_NONE ;
434
- }
435
- memset (temp , 0 , width );
436
-
437
- prev = temp ;
438
- for (r = 0 ; r < rows ; r ++ ) {
439
- scan = bin + (r * width );
440
- out = BIN_SKIP (ser , r * width );
441
-
442
- switch (filter ) {
443
- case PNG_FILTER_SUB :
444
- for (c = 0 ; c < bpp ; c ++ )
445
- out [c ] = scan [c ];
446
- for (c = bpp ; c < width ; c ++ )
447
- out [c ] = scan [c ] - scan [c - bpp ];
448
- break ;
449
- case PNG_FILTER_UP :
450
- for (c = 0 ; c < width ; c ++ )
451
- out [c ] = scan [c ] - prev [c ];
452
- break ;
453
- case PNG_FILTER_AVERAGE :
454
- for (c = 0 ; c < bpp ; c ++ )
455
- out [c ] = scan [c ] - (prev [c ] >> 1 );
456
- for (c = bpp ; c < width ; c ++ )
457
- out [c ] = scan [c ] - ((scan [c - bpp ] + prev [c ]) >> 1 ) & 0xFF ;
458
- break ;
459
- case PNG_FILTER_PAETH :
460
- for (c = 0 ; c < bpp ; c ++ )
461
- out [c ] = scan [c ] - prev [c ];
462
- for (c = bpp ; c < width ; c ++ )
463
- out [c ] = scan [c ] - paeth_predictor (scan [c - bpp ], prev [c ], prev [c - bpp ]);
464
- break ;
465
- }
466
- prev = scan ;
467
- }
468
- free (temp );
469
- SET_BINARY (D_RET , ser );
470
- VAL_TAIL (D_RET ) = bytes ;
471
- return R_RET ;
472
- }
473
-
474
- /***********************************************************************
475
- **
476
- */ REBNATIVE (unfilter )
477
- /*
478
- // unfilter: native [
479
- // "Reversed PNG delta filter"
480
- // data [binary!] "Input"
481
- // width [number!] "Scanline width (not counting the type byte)"
482
- // /as "Filter type. If not used, type is decoded from first byte on each line."
483
- // type [integer! word!] "1..4 or one of: [sub up average paeth]"
484
- // /skip
485
- // bpp [integer!] "Bytes per pixel"
486
- // ]
487
- ***********************************************************************/
488
- {
489
- REBVAL * val_data = D_ARG (1 );
490
- REBVAL * val_width = D_ARG (2 );
491
- REBOOL ref_as = D_REF (3 );
492
- REBVAL * val_type = D_ARG (4 );
493
- REBOOL ref_skip = D_REF (5 );
494
- REBVAL * val_bpp = D_ARG (6 );
495
-
496
- REBSER * ser ;
497
- REBYTE * bin = VAL_BIN_DATA (val_data );
498
- REBINT width = AS_INT32 (val_width );
499
- REBCNT r , c , rows ;
500
- REBYTE * scan , * prev , * temp , * out ;
501
- REBYTE filter = 0 ;
502
- REBCNT bytes = VAL_LEN (val_data );
503
- REBCNT bpp = ref_skip ? VAL_INT32 (val_bpp ) : 1 ;
504
-
505
- if (!ref_as ) width ++ ;
506
- if (width <= 1 || width > bytes )
507
- Trap1 (RE_INVALID_ARG , val_width );
508
- if (bpp < 1 || bpp > width )
509
- Trap1 (RE_INVALID_ARG , val_bpp );
510
-
511
- rows = ceil (bytes / width );
512
- ser = Make_Binary (bytes );
513
- out = BIN_DATA (ser );
514
-
515
- if (ref_as )
516
- filter = get_png_filter_type (val_type );
517
-
518
- temp = malloc (width );
519
- if (!temp ) {
520
- Trap0 (RE_NO_MEMORY );
521
- return R_NONE ;
522
- }
523
- memset (temp , 0 , width );
524
-
525
- if (!ref_as ) width -- ;
526
-
527
- prev = temp ;
528
- for (r = 0 ; r < rows ; r ++ ) {
529
- if (ref_as ) {
530
- scan = bin + r * width ;
531
- out = BIN_SKIP (ser , r * width );
532
- } else {
533
- scan = bin + r * (width + 1 );
534
- out = BIN_SKIP (ser , r * (width ));
535
- filter = scan [0 ];
536
- scan ++ ;
537
- }
538
-
539
- switch (filter ) {
540
- case PNG_FILTER_SUB :
541
- for (c = 0 ; c < bpp ; c ++ )
542
- out [c ] = scan [c ];
543
- for (c = bpp ; c < width ; c ++ )
544
- out [c ] = scan [c ] + out [c - bpp ];
545
- break ;
546
- case PNG_FILTER_UP :
547
- for (c = 0 ; c < width ; c ++ )
548
- out [c ] = scan [c ] + prev [c ];
549
- break ;
550
- case PNG_FILTER_AVERAGE :
551
- for (c = 0 ; c < bpp ; c ++ )
552
- out [c ] = scan [c ] + (prev [c ] >> 1 ) & 0xFF ;
553
- for (c = bpp ; c < width ; c ++ )
554
- out [c ] = scan [c ] + ((out [c - bpp ] + prev [c ]) >> 1 ) & 0xFF ;
555
- break ;
556
- case PNG_FILTER_PAETH :
557
- for (c = 0 ; c < bpp ; c ++ )
558
- out [c ] = scan [c ] + prev [c ];
559
- for (c = bpp ; c < width ; c ++ )
560
- out [c ] = scan [c ] + paeth_predictor (out [c - bpp ], prev [c ], prev [c - bpp ]);
561
- break ;
562
- }
563
- prev = out ;
564
- }
565
- free (temp );
566
- SET_BINARY (D_RET , ser );
567
- VAL_TAIL (D_RET ) = ref_as ? bytes : bytes - rows ;
568
- return R_RET ;
569
- }
570
- #endif //INCLUDE_PNG_FILTER
0 commit comments