Skip to content

Commit

Permalink
image convolution filter
Browse files Browse the repository at this point in the history
  • Loading branch information
SusanDoggie committed Jan 9, 2018
1 parent 7a17e27 commit 416755f
Show file tree
Hide file tree
Showing 5 changed files with 388 additions and 23 deletions.
16 changes: 16 additions & 0 deletions Doggie.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@
0A72EF181F54FED200F0550A /* SFNTCMAP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A72EF171F54FED200F0550A /* SFNTCMAP.swift */; };
0A72EF1C1F55035200F0550A /* SFNTFontFace.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A72EF1B1F55035200F0550A /* SFNTFontFace.swift */; };
0A7314C01F3D7B720008461E /* ShapeSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7314BF1F3D7B720008461E /* ShapeSegment.swift */; };
0A74D68820047BA600330C86 /* ImageConvolution.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A74D68720047BA600330C86 /* ImageConvolution.swift */; };
0A74D68A20047BF700330C86 /* GaussianBlur.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A74D68920047BF700330C86 /* GaussianBlur.swift */; };
0A776FC61D9A0BA5005FC88F /* c11_atomic.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A776FC31D9A0BA5005FC88F /* c11_atomic.h */; };
0A78E1F91E98B20A00BD91AB /* Geometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A78E1F71E98B20A00BD91AB /* Geometry.swift */; };
0A792C751FDA28DB003C0290 /* PathBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A792C741FDA28DB003C0290 /* PathBuilder.swift */; };
Expand Down Expand Up @@ -309,6 +311,8 @@
0A72EF171F54FED200F0550A /* SFNTCMAP.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SFNTCMAP.swift; sourceTree = "<group>"; };
0A72EF1B1F55035200F0550A /* SFNTFontFace.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = SFNTFontFace.swift; sourceTree = "<group>"; };
0A7314BF1F3D7B720008461E /* ShapeSegment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ShapeSegment.swift; sourceTree = "<group>"; };
0A74D68720047BA600330C86 /* ImageConvolution.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageConvolution.swift; sourceTree = "<group>"; };
0A74D68920047BF700330C86 /* GaussianBlur.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GaussianBlur.swift; sourceTree = "<group>"; };
0A776FC31D9A0BA5005FC88F /* c11_atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = c11_atomic.h; sourceTree = "<group>"; };
0A776FC41D9A0BA5005FC88F /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; lineEnding = 0; path = module.modulemap; sourceTree = "<group>"; };
0A78E1F71E98B20A00BD91AB /* Geometry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Geometry.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -555,6 +559,7 @@
08458ACE1E2E627600D01813 /* Image */,
0A94BE9E1F108E8100F1BCD2 /* ImageCodec */,
0A39A6B31ED9342C00804004 /* ImageContext */,
0A74D68620047B7000330C86 /* ImageFilter */,
08458AD41E2E627600D01813 /* Maths */,
0A9AA83E1E54373E007A2B92 /* PDF */,
0A2107071E5BEEBB00F1E00E /* Shape */,
Expand Down Expand Up @@ -732,6 +737,15 @@
path = SFNTFontFace;
sourceTree = "<group>";
};
0A74D68620047B7000330C86 /* ImageFilter */ = {
isa = PBXGroup;
children = (
0A74D68720047BA600330C86 /* ImageConvolution.swift */,
0A74D68920047BF700330C86 /* GaussianBlur.swift */,
);
path = ImageFilter;
sourceTree = "<group>";
};
0A776FC21D9A0BA5005FC88F /* c11_atomic */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1220,6 +1234,7 @@
08458B351E2E627600D01813 /* Ellipse.swift in Sources */,
0A8535351F5937DA006FB85D /* CFFFontFace.swift in Sources */,
08B68A321ED07A2400F8D423 /* ColorSpace.swift in Sources */,
0A74D68820047BA600330C86 /* ImageConvolution.swift in Sources */,
0A39A6C51ED937C700804004 /* DrawGradient.swift in Sources */,
0A56E9111E35F02E00D93786 /* RectCollection.swift in Sources */,
0A52E2D91E6012140065EED6 /* PDFFilter.swift in Sources */,
Expand All @@ -1240,6 +1255,7 @@
0ABDF1AA1F2B34E6007EC7B2 /* ChromaticAdaptationAlgorithm.swift in Sources */,
08458B131E2E627600D01813 /* Fourier.swift in Sources */,
0AD3E6351F53DB6C003CC21A /* OpenTypeDecoder.swift in Sources */,
0A74D68A20047BF700330C86 /* GaussianBlur.swift in Sources */,
0A72EF181F54FED200F0550A /* SFNTCMAP.swift in Sources */,
08458B611E2E627600D01813 /* SDTask.swift in Sources */,
0AE71A041EF51DF80086923C /* AnyColorSpace.swift in Sources */,
Expand Down
10 changes: 10 additions & 0 deletions Sources/Doggie/Accelerate/AccelerateWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,13 @@ public func Radix2CircularConvolve(_ level: Int, _ signal: UnsafePointer<Complex
public func Radix2PowerCircularConvolve(_ level: Int, _ input: UnsafePointer<Complex>, _ in_stride: Int, _ in_count: Int, _ n: Double, _ output: UnsafeMutablePointer<Complex>, _ out_stride: Int) {
input._reboundToDouble { _input in output._reboundToDouble { Radix2PowerCircularConvolve(level, _input, _input.successor(), in_stride << 1, in_count, n, $0, $0.successor(), out_stride << 1) } }
}

@_inlineable
public func Radix2FiniteImpulseFilter(_ level: Int, _ signal: UnsafePointer<Double>, _ signal_stride: Int, _ signal_count: Int, _ kernel: UnsafePointer<Complex>, _ kernel_stride: Int, _ output: UnsafeMutablePointer<Double>, _ out_stride: Int) {
kernel._reboundToDouble { Radix2FiniteImpulseFilter(level, signal, signal_stride, signal_count, $0, $0.successor(), kernel_stride << 1, output, out_stride) }
}

@_inlineable
public func Radix2FiniteImpulseFilter(_ level: Int, _ signal: UnsafePointer<Complex>, _ signal_stride: Int, _ signal_count: Int, _ kernel: UnsafePointer<Complex>, _ kernel_stride: Int, _ output: UnsafeMutablePointer<Complex>, _ out_stride: Int) {
signal._reboundToDouble { _signal in kernel._reboundToDouble { _kernel in output._reboundToDouble { Radix2FiniteImpulseFilter(level, _signal, _signal.successor(), signal_stride << 1, signal_count, _kernel, _kernel.successor(), kernel_stride << 1, $0, $0.successor(), out_stride << 1) } } }
}
55 changes: 32 additions & 23 deletions Sources/Doggie/Accelerate/CircularConvolve.swift
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public func Radix2PowerCircularConvolve<T: BinaryFloatingPoint>(_ level: Int, _
}

@_inlineable
public func Radix2FiniteImpulseFilter(_ level: Int, _ signal: UnsafePointer<Double>, _ signal_stride: Int, _ signal_count: Int, _ kernel: UnsafePointer<Complex>, _ kernel_stride: Int, _ output: UnsafeMutablePointer<Double>, _ out_stride: Int) {
public func Radix2FiniteImpulseFilter<T: BinaryFloatingPoint>(_ level: Int, _ signal: UnsafePointer<T>, _ signal_stride: Int, _ signal_count: Int, _ kreal: UnsafePointer<T>, _ kimag: UnsafePointer<T>, _ kernel_stride: Int, _ output: UnsafeMutablePointer<T>, _ out_stride: Int) where T : FloatingMathProtocol {

let length = 1 << level
let half = length >> 1
Expand All @@ -203,22 +203,24 @@ public func Radix2FiniteImpulseFilter(_ level: Int, _ signal: UnsafePointer<Doub

var _treal = output
var _timag = output + out_stride
var _kernel = kernel
var _kreal = kreal
var _kimag = kimag

let t_stride = out_stride << 1

HalfRadix2CooleyTukey(level, signal, signal_stride, signal_count, _treal, _timag, t_stride)

_treal.pointee *= _kernel.pointee.real
_timag.pointee *= _kernel.pointee.imag
_treal.pointee *= _kreal.pointee
_timag.pointee *= _kimag.pointee
for _ in 1..<half {
_treal += t_stride
_timag += t_stride
_kernel += kernel_stride
_kreal += kernel_stride
_kimag += kernel_stride
let _tr = _treal.pointee
let _ti = _timag.pointee
let _kr = _kernel.pointee.real
let _ki = _kernel.pointee.imag
let _kr = _kreal.pointee
let _ki = _kimag.pointee
_treal.pointee = _tr * _kr - _ti * _ki
_timag.pointee = _tr * _ki + _ti * _kr
}
Expand All @@ -227,34 +229,41 @@ public func Radix2FiniteImpulseFilter(_ level: Int, _ signal: UnsafePointer<Doub
}

@_inlineable
public func Radix2FiniteImpulseFilter(_ level: Int, _ signal: UnsafePointer<Complex>, _ signal_stride: Int, _ signal_count: Int, _ kernel: UnsafePointer<Complex>, _ kernel_stride: Int, _ output: UnsafeMutablePointer<Complex>, _ out_stride: Int) {
public func Radix2FiniteImpulseFilter<T: BinaryFloatingPoint>(_ level: Int, _ sreal: UnsafePointer<T>, _ simag: UnsafePointer<T>, _ signal_stride: Int, _ signal_count: Int, _ kreal: UnsafePointer<T>, _ kimag: UnsafePointer<T>, _ kernel_stride: Int, _ _real: UnsafeMutablePointer<T>, _ _imag: UnsafeMutablePointer<T>, _ out_stride: Int) where T : FloatingMathProtocol {

let length = 1 << level

if signal_count == 0 {
var output = output
var _real = _real
var _imag = _imag
for _ in 0..<length {
output.pointee = Complex(0)
output += out_stride
_real.pointee = 0
_imag.pointee = 0
_real += out_stride
_imag += out_stride
}
return
}

Radix2CooleyTukey(level, signal, signal_stride, signal_count, output, out_stride)
Radix2CooleyTukey(level, sreal, simag, signal_stride, signal_count, _real, _imag, out_stride)

var _output = output
var _kernel = kernel
var _oreal = _real
var _oimag = _imag
var _kreal = kreal
var _kimag = kimag

for _ in 0..<length {
let _treal = _output.pointee.real
let _timag = _output.pointee.imag
let _kreal = _kernel.pointee.real
let _kimag = _kernel.pointee.imag
_output.pointee.real = _treal * _kreal - _timag * _kimag
_output.pointee.imag = _treal * _kimag + _timag * _kreal
_output += out_stride
_kernel += kernel_stride
let _tr = _oreal.pointee
let _ti = _oimag.pointee
let _kr = _kreal.pointee
let _ki = _kimag.pointee
_oreal.pointee = _tr * _kr - _ti * _ki
_oimag.pointee = _tr * _ki + _ti * _kr
_oreal += out_stride
_oimag += out_stride
_kreal += kernel_stride
_kimag += kernel_stride
}

InverseRadix2CooleyTukey(level, output, out_stride)
InverseRadix2CooleyTukey(level, _real, _imag, out_stride)
}
54 changes: 54 additions & 0 deletions Sources/Doggie/ImageFilter/GaussianBlur.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// GaussianBlur.swift
//
// The MIT License
// Copyright (c) 2015 - 2018 Susan Cheng. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

import Foundation

@_inlineable
public func GaussianBlur<Model>(_ image: Image<ColorPixel<Model>>, _ blur: Double) -> Image<ColorPixel<Model>> {

let t = 2 * blur * blur
let c = 1 / sqrt(.pi * t)
let _t = -1 / t

let s = Int(ceil(6 * blur)) >> 1

let filter = (-s...s).map { exp(Double($0 * $0) * _t) as Double * c }

return ImageConvolution(image, horizontal: filter, vertical: filter)
}

@_inlineable
public func GaussianBlur<Model>(_ image: Image<FloatColorPixel<Model>>, _ blur: Float) -> Image<FloatColorPixel<Model>> {

let t = 2 * blur * blur
let c = 1 / sqrt(.pi * t)
let _t = -1 / t

let s = Int(ceil(6 * blur)) >> 1

let filter = (-s...s).map { exp(Float($0 * $0) * _t) as Float * c }

return ImageConvolution(image, horizontal: filter, vertical: filter)
}
Loading

0 comments on commit 416755f

Please sign in to comment.