hugo

Fork of github.com/gohugoio/hugo with reverse pagination support

git clone git://git.shimmy1996.com/hugo.git

resampling.go (4873B)

    1 // Copyright 2019 The Hugo Authors. All rights reserved.
    2 //
    3 // Licensed under the Apache License, Version 2.0 (the "License");
    4 // you may not use this file except in compliance with the License.
    5 // You may obtain a copy of the License at
    6 // http://www.apache.org/licenses/LICENSE-2.0
    7 //
    8 // Unless required by applicable law or agreed to in writing, software
    9 // distributed under the License is distributed on an "AS IS" BASIS,
   10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   11 // See the License for the specific language governing permissions and
   12 // limitations under the License.
   13 
   14 package images
   15 
   16 import "math"
   17 
   18 // We moved from imaging to the gift package for image processing at some point.
   19 // That package had more, but also less resampling filters. So we add the missing
   20 // ones here. They are fairly exotic, but someone may use them, so keep them here
   21 // for now.
   22 //
   23 // The filters below are ported from https://github.com/disintegration/imaging/blob/9aab30e6aa535fe3337b489b76759ef97dfaf362/resize.go#L369
   24 // MIT License.
   25 
   26 var (
   27 	// Hermite cubic spline filter (BC-spline; B=0; C=0).
   28 	hermiteResampling = resamp{
   29 		name:    "Hermite",
   30 		support: 1.0,
   31 		kernel: func(x float32) float32 {
   32 			x = absf32(x)
   33 			if x < 1.0 {
   34 				return bcspline(x, 0.0, 0.0)
   35 			}
   36 			return 0
   37 		},
   38 	}
   39 
   40 	// Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3).
   41 	mitchellNetravaliResampling = resamp{
   42 		name:    "MitchellNetravali",
   43 		support: 2.0,
   44 		kernel: func(x float32) float32 {
   45 			x = absf32(x)
   46 			if x < 2.0 {
   47 				return bcspline(x, 1.0/3.0, 1.0/3.0)
   48 			}
   49 			return 0
   50 		},
   51 	}
   52 
   53 	// Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5).
   54 	catmullRomResampling = resamp{
   55 		name:    "CatmullRomResampling",
   56 		support: 2.0,
   57 		kernel: func(x float32) float32 {
   58 			x = absf32(x)
   59 			if x < 2.0 {
   60 				return bcspline(x, 0.0, 0.5)
   61 			}
   62 			return 0
   63 		},
   64 	}
   65 
   66 	// BSpline is a smooth cubic filter (BC-spline; B=1; C=0).
   67 	bSplineResampling = resamp{
   68 		name:    "BSplineResampling",
   69 		support: 2.0,
   70 		kernel: func(x float32) float32 {
   71 			x = absf32(x)
   72 			if x < 2.0 {
   73 				return bcspline(x, 1.0, 0.0)
   74 			}
   75 			return 0
   76 		},
   77 	}
   78 
   79 	// Gaussian blurring filter.
   80 	gaussianResampling = resamp{
   81 		name:    "GaussianResampling",
   82 		support: 2.0,
   83 		kernel: func(x float32) float32 {
   84 			x = absf32(x)
   85 			if x < 2.0 {
   86 				return float32(math.Exp(float64(-2 * x * x)))
   87 			}
   88 			return 0
   89 		},
   90 	}
   91 
   92 	//  Hann-windowed sinc filter (3 lobes).
   93 	hannResampling = resamp{
   94 		name:    "HannResampling",
   95 		support: 3.0,
   96 		kernel: func(x float32) float32 {
   97 			x = absf32(x)
   98 			if x < 3.0 {
   99 				return sinc(x) * float32(0.5+0.5*math.Cos(math.Pi*float64(x)/3.0))
  100 			}
  101 			return 0
  102 		},
  103 	}
  104 
  105 	hammingResampling = resamp{
  106 		name:    "HammingResampling",
  107 		support: 3.0,
  108 		kernel: func(x float32) float32 {
  109 			x = absf32(x)
  110 			if x < 3.0 {
  111 				return sinc(x) * float32(0.54+0.46*math.Cos(math.Pi*float64(x)/3.0))
  112 			}
  113 			return 0
  114 		},
  115 	}
  116 
  117 	// Blackman-windowed sinc filter (3 lobes).
  118 	blackmanResampling = resamp{
  119 		name:    "BlackmanResampling",
  120 		support: 3.0,
  121 		kernel: func(x float32) float32 {
  122 			x = absf32(x)
  123 			if x < 3.0 {
  124 				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))
  125 			}
  126 			return 0
  127 		},
  128 	}
  129 
  130 	bartlettResampling = resamp{
  131 		name:    "BartlettResampling",
  132 		support: 3.0,
  133 		kernel: func(x float32) float32 {
  134 			x = absf32(x)
  135 			if x < 3.0 {
  136 				return sinc(x) * (3.0 - x) / 3.0
  137 			}
  138 			return 0
  139 		},
  140 	}
  141 
  142 	// Welch-windowed sinc filter (parabolic window, 3 lobes).
  143 	welchResampling = resamp{
  144 		name:    "WelchResampling",
  145 		support: 3.0,
  146 		kernel: func(x float32) float32 {
  147 			x = absf32(x)
  148 			if x < 3.0 {
  149 				return sinc(x) * (1.0 - (x * x / 9.0))
  150 			}
  151 			return 0
  152 		},
  153 	}
  154 
  155 	// Cosine-windowed sinc filter (3 lobes).
  156 	cosineResampling = resamp{
  157 		name:    "CosineResampling",
  158 		support: 3.0,
  159 		kernel: func(x float32) float32 {
  160 			x = absf32(x)
  161 			if x < 3.0 {
  162 				return sinc(x) * float32(math.Cos((math.Pi/2.0)*(float64(x)/3.0)))
  163 			}
  164 			return 0
  165 		},
  166 	}
  167 )
  168 
  169 // The following code is borrowed from https://raw.githubusercontent.com/disintegration/gift/master/resize.go
  170 // MIT licensed.
  171 type resamp struct {
  172 	name    string
  173 	support float32
  174 	kernel  func(float32) float32
  175 }
  176 
  177 func (r resamp) String() string {
  178 	return r.name
  179 }
  180 
  181 func (r resamp) Support() float32 {
  182 	return r.support
  183 }
  184 
  185 func (r resamp) Kernel(x float32) float32 {
  186 	return r.kernel(x)
  187 }
  188 
  189 func bcspline(x, b, c float32) float32 {
  190 	if x < 0 {
  191 		x = -x
  192 	}
  193 	if x < 1 {
  194 		return ((12-9*b-6*c)*x*x*x + (-18+12*b+6*c)*x*x + (6 - 2*b)) / 6
  195 	}
  196 	if x < 2 {
  197 		return ((-b-6*c)*x*x*x + (6*b+30*c)*x*x + (-12*b-48*c)*x + (8*b + 24*c)) / 6
  198 	}
  199 	return 0
  200 }
  201 
  202 func absf32(x float32) float32 {
  203 	if x < 0 {
  204 		return -x
  205 	}
  206 	return x
  207 }
  208 
  209 func sinc(x float32) float32 {
  210 	if x == 0 {
  211 		return 1
  212 	}
  213 	return float32(math.Sin(math.Pi*float64(x)) / (math.Pi * float64(x)))
  214 }