├── demo.png
├── fizz.png
├── tiles.jpg
├── fisheye.png
├── ripple.png
├── spinning.png
├── README.md
├── fizz.svg
├── fisheye.svg
├── ripple.svg
├── spinning.svg
├── fizz.go
├── ripple.go
├── fisheye.go
└── spinning.go
/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unixpickle/feDisplacementMaps/HEAD/demo.png
--------------------------------------------------------------------------------
/fizz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unixpickle/feDisplacementMaps/HEAD/fizz.png
--------------------------------------------------------------------------------
/tiles.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unixpickle/feDisplacementMaps/HEAD/tiles.jpg
--------------------------------------------------------------------------------
/fisheye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unixpickle/feDisplacementMaps/HEAD/fisheye.png
--------------------------------------------------------------------------------
/ripple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unixpickle/feDisplacementMaps/HEAD/ripple.png
--------------------------------------------------------------------------------
/spinning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unixpickle/feDisplacementMaps/HEAD/spinning.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # What is this?
2 |
3 | This repository contains some experiments with SVG's [feDisplacementMap](http://www.w3.org/TR/SVG11/filters.html#feDisplacementMapElement) filter operation. Filters that use feDisplacementMap can distort the pixels of an image using a sort of mask.
4 |
5 | In this repository, I use Go programs to generate masks, and then I see what they look like in SVG files.
6 |
7 | # Demo
8 |
9 | Here is an example of something you can do with feDisplacementMaps. The original image is a tiled floor, like this:
10 |
11 | 
12 |
13 | And the distorted version looks like this:
14 |
15 | 
16 |
--------------------------------------------------------------------------------
/fizz.svg:
--------------------------------------------------------------------------------
1 |
2 |
15 |
--------------------------------------------------------------------------------
/fisheye.svg:
--------------------------------------------------------------------------------
1 |
2 |
15 |
--------------------------------------------------------------------------------
/ripple.svg:
--------------------------------------------------------------------------------
1 |
2 |
15 |
--------------------------------------------------------------------------------
/spinning.svg:
--------------------------------------------------------------------------------
1 |
2 |
15 |
--------------------------------------------------------------------------------
/fizz.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "image"
6 | "image/color"
7 | "image/png"
8 | "math"
9 | "os"
10 | )
11 |
12 | const Size = 512
13 |
14 | func main() {
15 | if len(os.Args) != 2 {
16 | fmt.Fprintln(os.Stderr, "Usage: fizz ")
17 | os.Exit(1)
18 | }
19 |
20 | image := image.NewRGBA(image.Rect(0, 0, Size, Size))
21 |
22 | for x := 0; x < Size; x++ {
23 | for y := 0; y < Size; y++ {
24 | distanceVecX := float64(x - Size/2)
25 | distanceVecY := float64(y - Size/2)
26 | mag := math.Sqrt(math.Pow(distanceVecX, 2) + math.Pow(distanceVecY, 2))
27 | distanceVecX /= mag
28 | distanceVecY /= mag
29 | pullFactor := math.Pow(-mag, 3)
30 | image.Set(x, y, color.RGBA{
31 | R: uint8(pullFactor*distanceVecX + 128),
32 | G: uint8(pullFactor*distanceVecY + 128),
33 | B: 128,
34 | A: 255,
35 | })
36 | }
37 | }
38 |
39 | out, err := os.Create(os.Args[1])
40 | if err != nil {
41 | fmt.Fprintln(os.Stderr, err)
42 | os.Exit(1)
43 | }
44 | defer out.Close()
45 | png.Encode(out, image)
46 | }
47 |
--------------------------------------------------------------------------------
/ripple.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "image"
6 | "image/color"
7 | "image/png"
8 | "math"
9 | "os"
10 | )
11 |
12 | const Size = 512
13 |
14 | func main() {
15 | if len(os.Args) != 2 {
16 | fmt.Fprintln(os.Stderr, "Usage: ripple ")
17 | os.Exit(1)
18 | }
19 |
20 | image := image.NewRGBA(image.Rect(0, 0, Size, Size))
21 |
22 | for x := 0; x < Size; x++ {
23 | for y := 0; y < Size; y++ {
24 | distanceVecX := float64(x - Size/2)
25 | distanceVecY := float64(y - Size/2)
26 | mag := math.Sqrt(math.Pow(distanceVecX, 2) + math.Pow(distanceVecY, 2))
27 | distanceVecX /= mag
28 | distanceVecY /= mag
29 | pullFactor := 30 * math.Sin(mag/15)
30 | image.Set(x, y, color.RGBA{
31 | R: uint8(pullFactor*distanceVecX + 128),
32 | G: uint8(pullFactor*distanceVecY + 128),
33 | B: 128,
34 | A: 255,
35 | })
36 | }
37 | }
38 |
39 | out, err := os.Create(os.Args[1])
40 | if err != nil {
41 | fmt.Fprintln(os.Stderr, err)
42 | os.Exit(1)
43 | }
44 | defer out.Close()
45 | png.Encode(out, image)
46 | }
47 |
--------------------------------------------------------------------------------
/fisheye.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "image"
6 | "image/color"
7 | "image/png"
8 | "math"
9 | "os"
10 | )
11 |
12 | const Size = 512
13 |
14 | func main() {
15 | if len(os.Args) != 2 {
16 | fmt.Fprintln(os.Stderr, "Usage: fisheye ")
17 | os.Exit(1)
18 | }
19 |
20 | image := image.NewRGBA(image.Rect(0, 0, Size, Size))
21 |
22 | for x := 0; x < Size; x++ {
23 | for y := 0; y < Size; y++ {
24 | distanceVecX := float64(x - Size/2)
25 | distanceVecY := float64(y - Size/2)
26 | mag := math.Sqrt(math.Pow(distanceVecX, 2) + math.Pow(distanceVecY, 2))
27 | maxMag := math.Sqrt2 * Size / 2
28 | displacement := (mag - maxMag/2) / (maxMag / 2)
29 | displacement /= maxMag / 128
30 | image.Set(x, y, color.RGBA{
31 | R: uint8(displacement*distanceVecX + 128),
32 | G: uint8(displacement*distanceVecY + 128),
33 | B: 128,
34 | A: 255,
35 | })
36 | }
37 | }
38 |
39 | out, err := os.Create(os.Args[1])
40 | if err != nil {
41 | fmt.Fprintln(os.Stderr, err)
42 | os.Exit(1)
43 | }
44 | defer out.Close()
45 | png.Encode(out, image)
46 | }
47 |
--------------------------------------------------------------------------------
/spinning.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "image"
6 | "image/color"
7 | "image/png"
8 | "math"
9 | "os"
10 | )
11 |
12 | const Size = 512
13 |
14 | func main() {
15 | if len(os.Args) != 2 {
16 | fmt.Fprintln(os.Stderr, "Usage: spinning ")
17 | os.Exit(1)
18 | }
19 |
20 | image := image.NewRGBA64(image.Rect(0, 0, Size, Size))
21 |
22 | for x := 0; x < Size; x++ {
23 | for y := 0; y < Size; y++ {
24 | distanceVecX := float64(x - Size/2)
25 | distanceVecY := float64(y - Size/2)
26 | mag := math.Sqrt(math.Pow(distanceVecX, 2) + math.Pow(distanceVecY, 2))
27 | angle := mag / (Size / 3)
28 | newX := math.Cos(angle)*distanceVecX - math.Sin(angle)*distanceVecY
29 | newY := math.Sin(angle)*distanceVecX + math.Cos(angle)*distanceVecY
30 | diffX := newX - distanceVecX
31 | diffY := newY - distanceVecY
32 | diffScaler := float64(0x8000) / Size
33 | image.Set(x, y, color.RGBA64{
34 | R: uint16(diffScaler*diffX + 0x8000),
35 | G: uint16(diffScaler*diffY + 0x8000),
36 | B: 0x8000,
37 | A: 0xffff,
38 | })
39 | }
40 | }
41 |
42 | out, err := os.Create(os.Args[1])
43 | if err != nil {
44 | fmt.Fprintln(os.Stderr, err)
45 | os.Exit(1)
46 | }
47 | defer out.Close()
48 | png.Encode(out, image)
49 | }
50 |
--------------------------------------------------------------------------------