mirror of https://github.com/gohugoio/hugo
215 lines
4.8 KiB
Go
215 lines
4.8 KiB
Go
// 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)))
|
|
}
|