Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.1.0 #1

Merged
merged 4 commits into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# `blurry`

[![MIT License](https://img.shields.io/github/license/octu0/bluury)](https://github.com/octu0/blurry/blob/master/LICENSE)
[![MIT License](https://img.shields.io/github/license/octu0/blurry)](https://github.com/octu0/blurry/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/octu0/blurry?status.svg)](https://godoc.org/github.com/octu0/blurry)
[![Go Report Card](https://goreportcard.com/badge/github.com/octu0/blurry)](https://goreportcard.com/report/github.com/octu0/blurry)
[![Releases](https://img.shields.io/github/v/release/octu0/blurry)](https://github.com/octu0/blurry/releases)
Expand Down Expand Up @@ -78,6 +78,14 @@ img, err := blurry.Sobel(input)

![example](testdata/sobel.png)

### BlockMozaic

```go
img, err := blurry.Blockmozaic(input, 10)
```

![example](testdata/blockmozaic.png)

## CLI usage

Run it via docker.
Expand Down Expand Up @@ -105,9 +113,10 @@ USAGE:
blurry [global options] command [command options] [arguments...]

VERSION:
1.0.0
1.1.0

COMMANDS:
blockmozaic
boxblur
brightness
clone
Expand Down Expand Up @@ -140,21 +149,23 @@ darwin/amd64 Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
realize benchmark...
w/ src 320x240
benchmarking clone...
clone: 0.0186772ms
clone: 0.018641ms
benchmarking grayscale...
grayscale: 0.118339ms
grayscale: 0.133983ms
benchmarking brightness...
brightness: 0.0647984ms
brightness: 0.069466ms
benchmarking gammacorrection...
gammacorrection: 0.101544ms
gammacorrection: 0.102628ms
benchmarking contrast...
contrast: 0.0911908ms
contrast: 0.0696434ms
benchmarking boxblur...
boxblur: 0.565124ms
boxblur: 0.540886ms
benchmarking gaussianblur...
gaussianblur: 0.313639ms
gaussianblur: 0.317536ms
benchmarking sobel...
sobel: 0.121657ms
sobel: 0.128876ms
benchmarking blockmozaic...
blockmozaic: 0.348568ms
```

### Blur
Expand Down Expand Up @@ -250,7 +261,7 @@ installed as the build environment.
$ make build-generator
```

Compile `libblurry_runtime.a` and all kinds `libblurry_*.a` to make a static link.
Compile `libruntime.a` and all kinds `libblurry_*.a` to make a static link.

```shell
$ make generate
Expand Down
54 changes: 54 additions & 0 deletions blockmozaic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package blurry

/*
#cgo CFLAGS: -I${SRCDIR}
#cgo darwin LDFLAGS: -L${SRCDIR} -lruntime_osx -lblockmozaic_osx -ldl -lm
#cgo linux LDFLAGS: -L${SRCDIR} -lruntime_linux -lblockmozaic_linux -ldl -lm
#include <stdlib.h>

#include "bridge.h"
#ifdef __APPLE__
#include "libblockmozaic_osx.h"
#elif __linux__
#include "libblockmozaic_linux.h"
#endif

int libblockmozaic(unsigned char *src, int32_t width, int32_t height, int32_t block, unsigned char *out) {
halide_buffer_t in_rgba_buf = {0};
halide_buffer_t out_rgba_buf = {0};

bind_rgba_buf(&in_rgba_buf, src, width, height);
bind_rgba_buf(&out_rgba_buf, out, width, height);

int ret = blockmozaic(&in_rgba_buf, width, height, block, &out_rgba_buf);
free_buf(&in_rgba_buf);
free_buf(&out_rgba_buf);
return ret;
}
*/
import "C"
import (
"errors"
"image"
)

var (
ErrBlockmozaic = errors.New("contrast cgo call error")
)

func Blockmozaic(img *image.RGBA, block int) (*image.RGBA, error) {
width, height := wh(img)
out := GetNRGBA(width, height)

ret := C.libblockmozaic(
(*C.uchar)(&img.Pix[0]),
C.int(width),
C.int(height),
C.int(block),
(*C.uchar)(&out.Pix[0]),
)
if int(ret) != 0 {
return nil, ErrBlockmozaic
}
return out, nil
}
97 changes: 96 additions & 1 deletion blurry.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// +build ignore.

#define DEBUG 1
#define DEBUG 0

#include <Halide.h>
#include <halide_image_io.h>
Expand Down Expand Up @@ -222,6 +222,7 @@ Func boxblur_fn(Func input, Param<int32_t> width, Param<int32_t> height, Param<i
.fuse(xo, yo, ti)
.parallel(ti)
.vectorize(xi, 32);

return boxblur;
}

Expand Down Expand Up @@ -340,9 +341,54 @@ Func sobel_fn(Func input, Param<int32_t> width, Param<int32_t> height){
sobel.compute_root()
.parallel(ch);
gray.compute_root();

return sobel;
}

Func blockmozaic_fn(Func input, Param<int32_t> width, Param<int32_t> height, Param<int32_t> block_size){
Region src_bounds = {{0, width},{0, height},{0, 4}};
Func in = readI32(BoundaryConditions::repeat_edge(input, src_bounds), "in");

Var x("x"), y("y"), ch("ch");
Var xo("xo"), xi("xi");
Var yo("yo"), yi("yi");
Var ti("ti");

Expr block_size_half = block_size / 2;
Expr base = block_size_half * block_size_half; // width * height

RDom rd_block = RDom(-block_size_half, block_size_half, -block_size_half, block_size_half, "rd_block");
Func block_color = Func("block_color");
block_color(x, y, ch) = 0.0f;
Expr in_val = in(x + rd_block.x, y + rd_block.y, ch);
block_color(x, y, ch) += cast<float>(in_val);

Func avg_color = Func("avg_color");
avg_color(x, y, ch) = select(
ch == 3, 255,
block_color(x, y, ch) / base
);

Func blockmozaic = Func("blockmozaic");
Expr avg_val = avg_color(x + x % block_size, y + y % block_size, ch);
blockmozaic(x, y, ch) = cast<uint8_t>(avg_val);

avg_color.compute_root()
.parallel(y)
.vectorize(x, 32);

blockmozaic.compute_root()
.async()
.tile(x, y, xo, yo, xi, yi, 32, 32)
.fuse(xo, yo, ti)
.parallel(ti)
.vectorize(xi, 32);

in.compute_root();

return blockmozaic;
}

void generate_static_link(std::vector<Target::Feature> features, Func fn, std::vector<Argument> args, std::string name) {
std::string lib_name = "lib" + name;
std::string name_linux = lib_name + "_linux";
Expand Down Expand Up @@ -593,6 +639,27 @@ void generate_sobel(std::vector<Target::Feature> features) {
}, fn.name());
}

void generate_blockmozaic(std::vector<Target::Feature> features) {
ImageParam src(type_of<uint8_t>(), 3);

Param<int32_t> width{"width", 1920};
Param<int32_t> height{"height", 1080};
Param<int32_t> block{"block", 10};

init_input_rgba(src);

Func fn = blockmozaic_fn(
src.in(), width, height, block
);

init_output_rgba(fn.output_buffer());

printf("generate %s\n", fn.name().c_str());
generate_static_link(features, fn, {
src, width, height, block
}, fn.name());
}

void generate(std::vector<Target::Feature> features){
generate_runtime(features);
generate_clone(features);
Expand All @@ -603,6 +670,7 @@ void generate(std::vector<Target::Feature> features){
generate_boxblur(features);
generate_gaussianblur(features);
generate_sobel(features);
generate_blockmozaic(features);
}

void benchmark(Func fn, Buffer<uint8_t> buf_src) {
Expand Down Expand Up @@ -794,6 +862,27 @@ int main(int argc, char **argv) {
return 0;
}

if(strcmp(argv[1], "blockmozaic") == 0) {
Buffer<uint8_t> buf_src = load_and_convert_image(argv[2]);

Param<int32_t> width{"width", buf_src.get()->width()};
Param<int32_t> height{"height", buf_src.get()->height()};
Param<int32_t> block{"block", std::stoi(argv[3])};

Func fn = blockmozaic_fn(
wrapFunc(buf_src, "buf_src"), width, height, block
);
fn.compile_jit(get_jit_target_from_environment());

printf("realize %s...\n", fn.name().c_str());

Buffer<uint8_t> out = fn.realize({buf_src.get()->width(), buf_src.get()->height(), 3});

printf("save to %s\n", argv[4]);
save_image(out, argv[4]);
return 0;
}

if(strcmp(argv[1], "benchmark") == 0) {
printf("realize benchmark...\n");

Expand Down Expand Up @@ -848,6 +937,12 @@ int main(int argc, char **argv) {
wrapFunc(buf_src, "buf_src"), width, height
), buf_src);
}
{
Param<int32_t> block{"block", 10};
benchmark(blockmozaic_fn(
wrapFunc(buf_src, "buf_src"), width, height, block
), buf_src);
}
return 0;
}

Expand Down
47 changes: 47 additions & 0 deletions cli/bridge/blockmozaic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package bridge

import (
"log"

"gopkg.in/urfave/cli.v1"

"github.com/octu0/blurry"
)

func blockmozaicAction(c *cli.Context) error {
in, err := loadImage(c.String("input"))
if err != nil {
return err
}

out, err := blurry.Blockmozaic(in, c.Int("block"))
if err != nil {
return err
}

path, err := saveImage(out)
if err != nil {
return err
}
log.Printf("info: open %s", path)
return nil
}

func init() {
addCommand(cli.Command{
Name: "blockmozaic",
Action: blockmozaicAction,
Flags: []cli.Flag{
cli.StringFlag{
Name: "i,input",
Usage: "/path/to/input image",
Value: "./testdata/src.png",
},
cli.IntFlag{
Name: "b,block",
Usage: "block size",
Value: 10,
},
},
})
}
51 changes: 51 additions & 0 deletions cli/genrun/blockmozaic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package genrun

import (
"gopkg.in/urfave/cli.v1"
)

func blockmozaicAction(c *cli.Context) error {
runtimePath := c.String("runtime")
generateOutFilePath, err := generate(runtimePath, c.String("file"))
if err != nil {
return err
}

args := []string{
c.String("block"),
}
if err := runLocal(runtimePath, generateOutFilePath, c.String("input"), "blockmozaic", runArgs(args)); err != nil {
return err
}

return nil
}

func init() {
addCommand(cli.Command{
Name: "blockmozaic",
Action: blockmozaicAction,
Flags: []cli.Flag{
cli.StringFlag{
Name: "i,input",
Usage: "/path/to/input image",
Value: "./testdata/src.png",
},
cli.StringFlag{
Name: "r,runtime",
Usage: "halide runtime path",
Value: "./Halide-Runtime",
},
cli.StringFlag{
Name: "f,file",
Usage: "/path/to/blurry.cpp path",
Value: "./blurry.cpp",
},
cli.StringFlag{
Name: "block",
Usage: "block size",
Value: "10",
},
},
})
}
Binary file added libblockmozaic_linux.a
Binary file not shown.
Loading