Last active
January 16, 2019 02:33
-
-
Save kanryu/93761cd903d205e1b57f87f139183386 to your computer and use it in GitHub Desktop.
Trying define PNG's unfilter with Halide
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Specification: | |
// https://www.w3.org/TR/PNG-Filters.html | |
#include "Halide.h" | |
using namespace Halide; | |
Expr none_unfilter(Expr raw) { | |
return raw; | |
} | |
Expr sub_unfilter(Expr raw, Expr left) { | |
return left+raw; | |
} | |
Expr top_unfilter(Expr raw, Expr top) { | |
return top+raw; | |
} | |
Expr average_unfilter(Expr raw, Expr left, Expr top) { | |
return floor(left+top)/2+raw; | |
} | |
Expr paeth_unfilter(Expr raw, Expr left, Expr top, Expr upperleft) { | |
Expr a = left; // left | |
Expr b = top; // adobe | |
Expr c = upperleft; // upper left | |
Expr p = a + b - c; // initial estimate | |
Expr pa = abs(p - a); // distance to a, b, c | |
Expr pb = abs(p - a); | |
Expr pc = abs(p - a); | |
// return nearest of a,b,c, | |
// breaking ties in order a,b,c. | |
return select(pa <= pb && pa <= pc, a, | |
select(pb <= pc, b, | |
c) | |
); | |
} | |
namespace { | |
class Unfilter : public Halide::Generator<Unfilter> { | |
public: | |
Input<Buffer<uint8_t>> input{ "input", 3 }; | |
Input<Buffer<uint8_t>> types{ "types", 2 }; | |
Output<Buffer<uint8_t>> output{ "output", 3 }; | |
Func clamped, unfilter_x, unfilter_y, unfilter; | |
Unfilter() | |
: Halide::Generator<Unfilter>() | |
, unfilter_x("unfilter_x") | |
, unfilter_y("unfilter_y") | |
, unfilter("unfilter") | |
{ | |
} | |
void generate() { | |
Var x("x"), y("y"), z("z"), c("c"), t("t"); | |
Var xi("xi"), yi("yi"); | |
clamped = BoundaryConditions::constant_exterior(input, 0, | |
{{input.dim(0).min(), input.dim(0).extent()}, | |
{input.dim(1).min(), input.dim(1).extent()}}); | |
RDom xd(1, input.dim(0).extent()); | |
RDom yd(1, input.dim(1).extent()); | |
unfilter_x(xd, yd, c) = | |
select(types(0, yd)==0, none_unfilter(clamped(xd, yd, c)), | |
select(types(0, yd)==1, sub_unfilter(clamped(xd, yd, c), unfilter_x(xd-1, yd, c)), | |
select(types(0, yd)==2, top_unfilter(clamped(xd, yd, c), unfilter_x(xd, yd-1, c)), | |
select(types(0, yd)==3, average_unfilter(clamped(xd, yd, c), unfilter_x(xd-1, yd, c), unfilter_x(xd, yd-1, c)), | |
paeth_unfilter(clamped(x, y, c), unfilter_x(xd-1, yd, c), unfilter_x(xd, yd-1, c), unfilter_x(xd-1, yd-1, c)))))); | |
unfilter_x(0, yd, c) = | |
select(types(0, yd)==0, none_unfilter(clamped(0, yd, c)), | |
select(types(0, yd)==1, sub_unfilter(clamped(0, yd, c), 0), | |
select(types(0, yd)==2, top_unfilter(clamped(0, yd, c), unfilter_x(0, yd-1, c)), | |
select(types(0, yd)==3, average_unfilter(clamped(0, yd, c), 0, unfilter_x(0, yd-1, c)), | |
paeth_unfilter(clamped(0, yd, c), 0, unfilter_x(0, yd-1, c), 0))))); | |
unfilter_x(xd, 0, c) = | |
select(types(0, 0)==0, none_unfilter(clamped(xd, 0, c)), | |
select(types(0, 0)==1, sub_unfilter(clamped(xd, 0, c), unfilter_x(xd-1, 0, c)), | |
select(types(0, 0)==2, top_unfilter(clamped(xd, 0, c), 0), | |
select(types(0, 0)==3, average_unfilter(clamped(xd, 0, c), unfilter_x(xd-1, 0, c), 0), | |
paeth_unfilter(clamped(xd, 0, c), unfilter_x(xd-1, 0, c), 0, 0))))); | |
unfilter_x(0, 0, c) = | |
select(types(0, 0)==0, none_unfilter(clamped(0, 0, c)), | |
select(types(0, 0)==1, sub_unfilter(clamped(0, 0, c), 0), | |
select(types(0, 0)==2, top_unfilter(clamped(0, 0, c), 0), | |
select(types(0, 0)==3, average_unfilter(clamped(0, 0, c), 0, 0), | |
paeth_unfilter(clamped(0, 0, c), 0, 0, 0))))); | |
unfilter_y(x, y, c) = unfilter_x(x, y, c); | |
unfilter_x.compute_at(unfilter_y, y).vectorize(x, 16); | |
unfilter_y.parallel(y); | |
unfilter(x, y, c) = unfilter_y(x, y, c); | |
unfilter.tile(x, y, xi, yi, 16, 16); | |
output(x, y, c) = unfilter(x, y, c); | |
} | |
}; | |
} // namespace | |
HALIDE_REGISTER_GENERATOR(Unfilter, unfilter) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Although this Genrator build succeeds, it fails at run time and can not create a library.