diff options
author | Bjørn Erik Pedersen <[email protected]> | 2019-08-26 19:12:41 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2019-08-28 15:59:54 +0200 |
commit | 823f53c861bb49aecc6104e0add39fc3b0729025 (patch) | |
tree | 64a55d1c41de09b67305ad69a3600f3091d4f1fc /resources/images/resampling.go | |
parent | f9978ed16476ca6d233a89669c62c798cdf9db9d (diff) | |
download | hugo-823f53c861bb49aecc6104e0add39fc3b0729025.tar.gz hugo-823f53c861bb49aecc6104e0add39fc3b0729025.zip |
Add a set of image filters
With this you can do variants of this:
```
{{ $img := resources.Get "images/misc/3-jenny.jpg" }}
{{ $img := $img.Resize "300x" }}
{{ $g1 := $img.Filter images.Grayscale }}
{{ $g2 := $img | images.Filter (images.Saturate 30) (images.GaussianBlur 3) }}
```
Fixes #6255
Diffstat (limited to 'resources/images/resampling.go')
-rw-r--r-- | resources/images/resampling.go | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/resources/images/resampling.go b/resources/images/resampling.go new file mode 100644 index 000000000..0cb267684 --- /dev/null +++ b/resources/images/resampling.go @@ -0,0 +1,214 @@ +// Copyright 2019 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package images + +import "math" + +// We moved from imaging to the gift package for image processing at some point. +// That package had more, but also less resampling filters. So we add the missing +// ones here. They are fairly exotic, but someone may use them, so keep them here +// for now. +// +// The filters below are ported from https://github.com/disintegration/imaging/blob/9aab30e6aa535fe3337b489b76759ef97dfaf362/resize.go#L369 +// MIT License. + +var ( + // Hermite cubic spline filter (BC-spline; B=0; C=0). + hermiteResampling = resamp{ + name: "Hermite", + support: 1.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 1.0 { + return bcspline(x, 0.0, 0.0) + } + return 0 + }, + } + + // Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3). + mitchellNetravaliResampling = resamp{ + name: "MitchellNetravali", + support: 2.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 2.0 { + return bcspline(x, 1.0/3.0, 1.0/3.0) + } + return 0 + }, + } + + // Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5). + catmullRomResampling = resamp{ + name: "CatmullRomResampling", + support: 2.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 2.0 { + return bcspline(x, 0.0, 0.5) + } + return 0 + }, + } + + // BSpline is a smooth cubic filter (BC-spline; B=1; C=0). + bSplineResampling = resamp{ + name: "BSplineResampling", + support: 2.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 2.0 { + return bcspline(x, 1.0, 0.0) + } + return 0 + }, + } + + // Gaussian blurring filter. + gaussianResampling = resamp{ + name: "GaussianResampling", + support: 2.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 2.0 { + return float32(math.Exp(float64(-2 * x * x))) + } + return 0 + }, + } + + // Hann-windowed sinc filter (3 lobes). + hannResampling = resamp{ + name: "HannResampling", + support: 3.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 3.0 { + return sinc(x) * float32(0.5+0.5*math.Cos(math.Pi*float64(x)/3.0)) + } + return 0 + }, + } + + hammingResampling = resamp{ + name: "HammingResampling", + support: 3.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 3.0 { + return sinc(x) * float32(0.54+0.46*math.Cos(math.Pi*float64(x)/3.0)) + } + return 0 + }, + } + + // Blackman-windowed sinc filter (3 lobes). + blackmanResampling = resamp{ + name: "BlackmanResampling", + support: 3.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 3.0 { + return sinc(x) * float32(0.42-0.5*math.Cos(math.Pi*float64(x)/3.0+math.Pi)+0.08*math.Cos(2.0*math.Pi*float64(x)/3.0)) + } + return 0 + }, + } + + bartlettResampling = resamp{ + name: "BartlettResampling", + support: 3.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 3.0 { + return sinc(x) * (3.0 - x) / 3.0 + } + return 0 + }, + } + + // Welch-windowed sinc filter (parabolic window, 3 lobes). + welchResampling = resamp{ + name: "WelchResampling", + support: 3.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 3.0 { + return sinc(x) * (1.0 - (x * x / 9.0)) + } + return 0 + }, + } + + // Cosine-windowed sinc filter (3 lobes). + cosineResampling = resamp{ + name: "CosineResampling", + support: 3.0, + kernel: func(x float32) float32 { + x = absf32(x) + if x < 3.0 { + return sinc(x) * float32(math.Cos((math.Pi/2.0)*(float64(x)/3.0))) + } + return 0 + }, + } +) + +// The following code is borrowed from https://raw.githubusercontent.com/disintegration/gift/master/resize.go +// MIT licensed. +type resamp struct { + name string + support float32 + kernel func(float32) float32 +} + +func (r resamp) String() string { + return r.name +} + +func (r resamp) Support() float32 { + return r.support +} + +func (r resamp) Kernel(x float32) float32 { + return r.kernel(x) +} + +func bcspline(x, b, c float32) float32 { + if x < 0 { + x = -x + } + if x < 1 { + return ((12-9*b-6*c)*x*x*x + (-18+12*b+6*c)*x*x + (6 - 2*b)) / 6 + } + if x < 2 { + return ((-b-6*c)*x*x*x + (6*b+30*c)*x*x + (-12*b-48*c)*x + (8*b + 24*c)) / 6 + } + return 0 +} + +func absf32(x float32) float32 { + if x < 0 { + return -x + } + return x +} + +func sinc(x float32) float32 { + if x == 0 { + return 1 + } + return float32(math.Sin(math.Pi*float64(x)) / (math.Pi * float64(x))) +} |