Coder Social home page Coder Social logo

stackblur-go's Introduction

stackblur-go

Go Reference build

Go port of Mario Klingemann's Stackblur algorithm.

Stackblur is a compromise between Gaussian blur and Box blur, but it creates much better looking blurs than Box blur and it is ~7x faster than Gaussian blur.

Comparing to the Javascript implementation the Go version is at least 50% faster (depending on the image size and blur radius), applied on the same image with the same bluring radius.

Benchmark

Radius Javascript Go
20 ~15ms ~7.4ms

Installation

First, install Go, set your GOPATH, and make sure $GOPATH/bin is on your PATH.

$ export GOPATH="$HOME/go"
$ export PATH="$PATH:$GOPATH/bin"

Next download the project and build the binary file.

$ go get -u -f github.com/esimov/stackblur-go
$ cd cmd && go build -o $GOPATH/bin/stackblur

CLI example

The provided CLI example supports the following flags:

$ stackblur --help

Usage of stackblur:
  -gif
    	Output Gif
  -in string
    	Source
  -out string
    	Destination
  -radius int
    	Radius (default 20)

The command below will generate the blurred version of the source image.

$ stackblur -in image/sample.png -out image/output.png -radius 10

The cli command supports a -gif flag, which if set as true it visualize the bluring process by outputting the result into a gif file.

API

The usage of the API is very simple: you need to expose an image file and a blur radius to the Process function. This will return the blurred version of the original image.

stackblur.Process(src, blurRadius)

Results

Original image Blurred image

License

This project is under the MIT License. See the LICENSE file for the full license text.

stackblur-go's People

Contributors

esimov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

stackblur-go's Issues

Why the channel?

Not really an issue, just a question: what is the purpose of the done chan struct{} channel? Also in the example program you just call the function and time it without using the channel. IMHO if an explication would need some sort of notification it is probably better implemented outside of the Process function.

SemVer and API design in v1.0.0, v1.0.1, v1.0.2

Thank you for providing a Go package for the stackblur algorithm.

I'm currently using version v1.0.1, and wanted to update to the newer v1.0.2. When doing that, I ran into a problem, and so I wanted to report it in this issue for your consideration. There are probably different paths to deal with this, and at the end of this issue I provide a suggested resolution.

The API of [email protected] as seen here defines Process:

func Process(src image.Image, radius uint32) image.Image

But the API of [email protected] (seen here) breaks SemVer rule 8 by introducing a backwards incompatible change (the Process function is no longer provided) without also incrementing the major version number.

I also preferred the API of v1.0.1 more than v1.0.2 because it made the input parameter easier to understand: it just needed to implement the image.Image interface. In v1.0.2, the Run function takes input interface{}, and for a user who reads the function's documentation:

// Run takes an image or pixel data as input and returns
// it's blurred version by applying the blur radius defined as parameter.
func Run(input interface{}, radius uint32) (image.Image, error)

It might not be clear what types of input are allowed (interface{} doesn't communicate any restrictions, and the comment doesn't elaborate beyond "image or pixel data"). It requires users to read source code or to do trial and error, and it's hard to be confident it won't stop working in a future version.

(However, APIs in both v1.0.1 and v1.0.2 are definitely an improvement over the v1.0.0 API.)

Proposed Path Forward

Resolve SemVer violation

Each of v1.0.0, v1.0.1 and v1.0.2 offers a different, incompatible interface, so users of this package need to modify their code whenever moving between its patch versions. It can become especially problematic if someone's project has dependencies that themselves use different versions of this API.

It's normal to change APIs in order to improve them during v0, before a package reaches version v1.0.0, but it should be avoided after that since the purpose of v1.0.0 (and future minor and patch revisions) is to say "this API is meant to be stable".

If you think this package is ready to commit to a stable API and you just need to pick which one it is, Go 1.16 introduced module retraction. So it would be possible to:

retract v1.0.0 // provides an API that isn't optimal for v1
retract v1.0.1 // makes a backwards incompatible change
retract v1.0.2 // also makes a backwards incompatible change

While publishing a newer version, such as v1.1.0, that provides an API that you expect will be stable going forward (for v1 major version). (Unfortunately, I don't believe it's possible to go back to v0 once a v1+ version is published.)

API design

I would suggest considering the following API design that tries to take the best from v1.0.1 and v1.0.2:

func _(src image.Image, radius int) (*image.NRGBA, error)

That is, the src parameter type is image.Image. If the caller wants to read and decode an image from disk, it's probably better for them to do it themselves (while having full control over how it's done, and how errors are handled), rather than depending on a package that provides a blur algorithm to do it. Trying to accept interface{} makes understanding the API harder without providing substantial benefits that can be depended on.

As another change, consider returning *image.NRGBA (a concrete type that stackblur uses internally anyway) instead of the image.Image interface. The *image.NRGBA concrete type already implements the image.Image interface, so callers that want that can use it trivially. But callers that happen to also use *image.NRGBA for image processing themselves can skip the overhead (or unsafe conversion code) of getting back from image.Image to a concrete type. (See this post and https://go.dev/s/style#interfaces for a more elaborated motivation.)

Finally, you could use int for radius since it's more common/simpler and sufficient—if radius < 1 an error will be returned. But fine to keep using uint32 too.

The function name can be something new, which would allow preserving backwards compatibility with Process from one of v1.0.0 or v1.0.1 (not both since they differ), and/or with Run from v1.0.2, while marking them as deprecated. Or it can be the same name if the earlier versions are retracted anyway.


Thanks very much for considering this issue! I'm happy to discuss this further. If there's agreement on what to do and you'd find it helpful, I can work on creating PRs for review, otherwise please feel free to resolve this as you see fit. Thanks again!

[BUG]stackblur-go may override source image to be blurred

Hi, once I use your stackblur-go to process images in batch, then I found when I call func "Process", the source image I passed in as parameter "src", it may be override in some cases. Intuitively, source image should be read-only, isn't it ?

Panic - Unknown format

I ran it with 2 pngs and I got main.go : 44 +0x6ae
The command was cli.exe -in Wallpaper.png -our Blur.png -radius 10

latest release tag is named "1.0.1" instead of "v1.0.1", and not recognized

Hello, thanks for offering this excellent Go package!

There are two releases published at https://github.com/esimov/stackblur-go/releases, 1.0.1 and 1.0.0, but the tag for 1.0.1 is missing the "v" prefix. That causes the release not to be recognized by Go tooling. It's still possible to use it as a pseudo-version:

$ go get -d 'github.com/esimov/stackblur-go@latest'      
go get: added github.com/esimov/stackblur-go v1.0.0
$ go get -d 'github.com/esimov/[email protected]' 
go: downloading github.com/esimov/stackblur-go v1.0.1-0.20190121110005-00e727e3c7a9
go get: upgraded github.com/esimov/stackblur-go v1.0.0 => v1.0.1-0.20190121110005-00e727e3c7a9

Reporting this in case it was an accidental omission. (It should be possible to publish commit 00e727e as v1.0.1 by creating a new tag with the "v" prefix included.)

Panic on grayscale images

Good day!

I got repeatable panic on grayscale images:

./main -in 511be36c3d8721964318518f9a2bb691.jpeg -out out.jpeg -radius 10
panic: runtime error: index out of range [786432] with length 786432

goroutine 1 [running]:
github.com/esimov/stackblur-go.toNRGBA({0x100526f60, 0x140000c2140})
	/Users/danil/blur/stackblur-go/stackblur.go:420 +0x3d0
github.com/esimov/stackblur-go.Process({0x100526f60, 0x140000c2140}, 0xa)
	/Users/danil/blur/stackblur-go/stackblur.go:83 +0xa4
main.main()
	/Users/danil/blur/stackblur-go/cmd/main.go:71 +0x1f8

Changing

si += 2
to simple si++ fixes the issue.
Please take a look.

Example image:
511be36c3d8721964318518f9a2bb691

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.