Skip to content

Instantly share code, notes, and snippets.

@kanryu
Last active January 16, 2019 02:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kanryu/93761cd903d205e1b57f87f139183386 to your computer and use it in GitHub Desktop.
Save kanryu/93761cd903d205e1b57f87f139183386 to your computer and use it in GitHub Desktop.
Trying define PNG's unfilter with Halide
// 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)
@kanryu
Copy link
Author

kanryu commented Jan 16, 2019

cl  /O2 /Oi /Ot /GL /EHsc  /favor:blend /MD /Qpar /openmp /arch:AVX2  -I ../../Halide0/x64/include/ -I ../../Halide/tools/ -I ../../Halide/apps/support/  -I. ../unfilter_gen.cpp ../../Halide/tools/GenGen.cpp ../../Halide0/x64/Release/Halide.lib
unfilter_gen.cpp
GenGen.cpp
/out:unfilter_gen.exe
/ltcg
unfilter_gen.obj
GenGen.obj
../../Halide0/x64/Release/Halide.lib
        cp ../../Halide0/x64/Release/Halide.dll .
        unfilter_gen -g unfilter -o . target=host-no_runtime
Error:
Can't call Func "unfilter_x" because it has not yet been defined.
NMAKE : fatal error U1077: '.\unfilter_gen.EXE' : Return Code '0xc0000409'
Stop.

Although this Genrator build succeeds, it fails at run time and can not create a library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment