Skip to content

Commit cbad7a7

Browse files
committed
Build: separating optional PNG filter natives from compression code
1 parent 924854c commit cbad7a7

File tree

3 files changed

+260
-226
lines changed

3 files changed

+260
-226
lines changed

make/rebol3.nest

+6-1
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,11 @@ include-lzma-compression: [
444444
core-files: %core/u-lzma.c
445445
]
446446

447+
include-png-filter-native: [
448+
config: INCLUDE_PNG_FILTER
449+
core-files: %core/u-png-filter.c
450+
]
451+
447452
include-view: [
448453
; currently only on Windows!
449454
host-files: :host-files-view
@@ -500,7 +505,7 @@ include-codec-ico: [
500505
]
501506
include-codec-json: [mezz-lib-files: %mezz/codec-json.reb ]
502507
include-codec-xml: [mezz-lib-files: %mezz/codec-xml.reb ]
503-
include-codec-pdf: [mezz-lib-files: %mezz/codec-pdf.reb config: INCLUDE_PNG_FILTER] ; pdf may use special png pre-compression
508+
include-codec-pdf: [mezz-lib-files: %mezz/codec-pdf.reb :include-png-filter-native] ; pdf may use special png pre-compression
504509
include-codec-swf: [mezz-lib-files: %mezz/codec-swf.reb ]
505510
include-codec-wav: [mezz-lib-files: %mezz/codec-wav.reb ]
506511
include-codec-unixtime: [mezz-lib-files: %mezz/codec-unixtime.reb ]

src/core/u-compress.c

-225
Original file line numberDiff line numberDiff line change
@@ -343,228 +343,3 @@ static const ISzAlloc g_Alloc = { SzAlloc, SzFree };
343343

344344
#endif //INCLUDE_LZMA
345345

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

Comments
 (0)