int main(int argc, char **argv) { // The camera pipe is specialized on the 2592x1968 images that // come in, so we'll just use an image instead of a uniform image. ImageParam input(UInt(16), 2); ImageParam matrix_3200(Float(32), 2, "m3200"), matrix_7000(Float(32), 2, "m7000"); Param<float> color_temp("color_temp"); //, 3200.0f); Param<float> gamma("gamma"); //, 1.8f); Param<float> contrast("contrast"); //, 10.0f); Param<int> blackLevel("blackLevel"); //, 25); Param<int> whiteLevel("whiteLevel"); //, 1023); // shift things inwards to give us enough padding on the // boundaries so that we don't need to check bounds. We're going // to make a 2560x1920 output image, just like the FCam pipe, so // shift by 16, 12. We also convert it to be signed, so we can deal // with values that fall below 0 during processing. Func shifted; shifted(x, y) = cast<int16_t>(input(x+16, y+12)); // Parameterized output type, because LLVM PTX (GPU) backend does not // currently allow 8-bit computations int bit_width = atoi(argv[1]); Type result_type = UInt(bit_width); // Pick a target target = get_target_from_environment(); // Build the pipeline Func processed = process(shifted, result_type, matrix_3200, matrix_7000, color_temp, gamma, contrast, blackLevel, whiteLevel); std::vector<Argument> args = {color_temp, gamma, contrast, blackLevel, whiteLevel, input, matrix_3200, matrix_7000}; // TODO: it would be more efficient to call compile_to() a single time with the right arguments processed.compile_to_static_library("curved", args, "curved", target); processed.compile_to_assembly("curved.s", args, target); return 0; }
int main(int argc, char **argv) { // First define the function that gives the initial state. { Func initial; // The initial state is a quantity of two chemicals present at each pixel initial(x, y, c) = random_float(); initial.compile_to_static_library("reaction_diffusion_init", {}, "reaction_diffusion_init"); } // Then the function that updates the state. Also depends on user input. { ImageParam state(Float(32), 3); Param<int> mouse_x, mouse_y; Expr a = state(x, y, 0), b = state(x, y, 1); Func clamped = BoundaryConditions::repeat_edge(state); RDom kernel(-2, 5); Func g, gaussian; g(x) = exp(-x*x*0.3f); gaussian(x) = g(x) / sum(g(kernel)); gaussian.compute_root(); Func blur_x, blur_y; blur_x(x, y, c) = sum(gaussian(kernel) * clamped(x + kernel, y, c)); blur_y(x, y, c) = sum(gaussian(kernel) * blur_x(x, y + kernel, c)); // Diffusion Expr new_a = blur_y(x, y, 0); Expr new_b = blur_y(x, y, 1); // Reaction Expr f = 0.08f; Expr k = 0.16f; new_a += 0.4f * (a - a*a*a - b + k); new_b += 0.4f * f * (a - b); new_a = clamp(new_a, 0.0f, 1.0f); new_b = clamp(new_b, 0.0f, 1.0f); Func new_state; new_state(x, y, c) = select(c == 0, new_a, new_b); // Finally add some noise at the edges to keep things moving Expr r = lerp(-0.05f, 0.05f, random_float()); new_state(x, 0, c) += r; new_state(x, 1023, c) += r; new_state(0, y, c) += r; new_state(1023, y, c) += r; new_state .vectorize(x, 4) .bound(c, 0, 2).unroll(c); Var yi; new_state.split(y, y, yi, 16).parallel(y); blur_x.store_at(new_state, y).compute_at(new_state, yi); blur_x.vectorize(x, 4); clamped.store_at(new_state, y).compute_at(new_state, yi); new_state.compile_to_static_library("reaction_diffusion_update", {state, mouse_x, mouse_y}, "reaction_diffusion_update"); } // Now the function that converts the state into an argb image. { ImageParam state(Float(32), 3); Expr a = state(x, y, 0), b = state(x, y, 1); Expr alpha = 255 << 24; Expr red = cast<int32_t>(a * 255) * (1 << 16); Expr green = 0; Expr blue = cast<int32_t>(b * 255); Func render; render(x, y) = alpha + red + green + blue; render.vectorize(x, 4); Var yi; render.split(y, y, yi, 16).parallel(y); render.compile_to_static_library("reaction_diffusion_render", {state}, "reaction_diffusion_render"); } return 0; }