Comments (6)
Same as here. But if you need animated background you should not specify single image as a background, rather blurring sourceImage
e.g.:
sourceImage.composited(over: sourceImage.applyBlur())
applyBlur
is not real and method
from cabbage.
And this is possible implementation for image blaring if that is what you needed (it is not clear from your questions):
extension CIImage {
convenience init(color: UIColor) {
self.init(color: CIColor(cgColor: color.cgColor))
}
enum Filter {
case
darkenBlendMode(UIColor),
gaussianBlur(radius: Double),
overlayBlendMode(CIImage)
var name: String {
switch self {
case .darkenBlendMode:
return "CIDarkenBlendMode"
case .gaussianBlur:
return "CIGaussianBlur"
case .overlayBlendMode:
return "CIOverlayBlendMode"
}
}
var parameters: [String: Any] {
switch self {
case .darkenBlendMode(let color):
return [kCIInputBackgroundImageKey: CIImage(color: color)]
case .gaussianBlur(let radius):
return [kCIInputRadiusKey: radius]
case .overlayBlendMode(let image):
return [kCIInputBackgroundImageKey: image]
}
}
}
func applying(_ filter: Filter, when shouldApply: Bool = true) -> CIImage {
guard shouldApply else { return self }
return applyingFilter(filter.name, parameters: filter.parameters)
}
}
extension CIImage {
func blurred(
radius: Double = 20,
color: UIColor = UIColor.white.withAlphaComponent(0.4)
) -> CIImage {
applying(
.overlayBlendMode(CIImage(
color: CIColor(
red: color.rgba().r,
green: color.rgba().g,
blue: color.rgba().b,
alpha: color.rgba().a
)
))
)
.applying(.gaussianBlur(radius: radius))
}
}
extension UIColor {
func rgba() -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {
let components = cgColor.components ?? []
switch cgColor.numberOfComponents {
case 4:
return (components[0], components[1], components[2], components[3])
case 2:
return (components[0], components[0], components[0], components[1])
default:
return (0, 0, 0, 1)
}
}
}
from cabbage.
I tried the Blurred method and it didn't work
from cabbage.
I think you just don't see it, because blurred image is hidden underneath the source image. I'm not a guru in AVFoundation
so try playing with transforms. I tried to implement quick fix to make background image fill the render size. And seems like it works at least for me:
func applyEffect(
to sourceImage: CIImage,
at time: CMTime,
renderSize: CGSize
) -> CIImage {
let scaleToFillValue = renderSize.height / sourceImage.extent.height
let scaledImage = sourceImage.transformed(by: .init(scaleX: scaleToFillValue, y: scaleToFillValue))
let scaledImageWithFixedOrigin = scaledImage.transformed(
by: .init(
translationX: -renderSize.width / 2,
y: -(scaledImage.extent.origin.y + renderSize.height) / 2
)
)
return sourceImage.composited(over: scaledImageWithFixedOrigin.blurred(radius: 50, color: #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0.2)))
}
from cabbage.
Thank you for your reply. It is indeed blocked by the source image. I changed the position of the blurred image with the method you mentioned, and the effect is great!
from cabbage.
Here is an example VideoCompositionProvider
for blurring background from current video frame. Thanks for @Alexey-Matjuk he showed us the start point.
@available(iOS 10.0, *)
final class BlurredBackgroundComposition: VideoCompositionProvider {
public enum Effect {
case gaussianBlur(sigma: Double, isDark: Bool)
}
private var effect: Effect! = nil
private var resizeFilter: CIFilter! = nil
init(appliedEffect: Effect) {
self.effect = appliedEffect
self.resizeFilter = CIFilter(name:"CILanczosScaleTransform")!
}
func applyEffect(
to sourceImage: CIImage,
at time: CMTime,
renderSize: CGSize
) -> CIImage {
autoreleasepool {
var backgroundImage: CIImage? = sourceImage
switch effect {
case .gaussianBlur(let sigma, let isDark):
// Compute calculation for aspectFill render size
let scale = renderSize.height / sourceImage.extent.height
let aspectRatio = renderSize.width / (sourceImage.extent.width * scale)
// Pass parameters to filter
resizeFilter.setValue(scale, forKey: kCIInputScaleKey)
resizeFilter.setValue(aspectRatio, forKey: kCIInputAspectRatioKey)
resizeFilter.setValue(sourceImage, forKey: kCIInputImageKey)
// Get output image
guard let scaledImage = resizeFilter.outputImage else {
return sourceImage
}
// First clamp to extend (will make infinity edges)
// then apply gaussian blur and crop result image to non cropped image extend
// to remove black edges from the image
// transform image to original position and final step is
// blending result image with our dark color if needed
backgroundImage = scaledImage.clampedToExtent()
.applyingGaussianBlur(sigma: sigma)
.cropped(to: scaledImage.extent)
.transformed(by: CGAffineTransform(translationX: -scaledImage.extent.origin.x, y: -scaledImage.extent.origin.y))
.apply(color: isDark ? UIColor.black.withAlphaComponent(0.6) : nil)
case .none: break
}
// Return new composited image
return sourceImage.composited(over: backgroundImage!)
}
}
}
CIImage extension for apply
function:
import CoreImage
import UIKit
extension CIImage {
func apply(color: UIColor? = nil) -> CIImage {
guard let color = color else {
return self
}
let filter = CIFilter(name: "CIDarkenBlendMode")
filter?.setDefaults()
filter?.setValue(self, forKey: kCIInputImageKey)
filter?.setValue(CIImage(color: CIColor(color: color)), forKey: kCIInputBackgroundImageKey)
if let outputImage = filter?.outputImage {
return outputImage
}
return self
}
}
And here is example of usage:
// Create your timeline
let timeline = ...
timeline.renderSize = renderSize
// Blurred background (will create from current visible frame)
timeline.passingThroughVideoCompositionProvider = BlurredBackgroundComposition(appliedEffect: .gaussianBlur(sigma: 25, isDark: false))
NOTE: When we use custom VideoCompositionProvider
item transitions looks different I don't know why? It's looks like background image appears later then video frame. Any help will be appreciated.
from cabbage.
Related Issues (20)
- 添加片段过多内存暴增
- Use Kingfisher to report an error
- About the text overlay, edit, drag and drop, zoom. HOT 1
- CIImage Memory leak HOT 2
- Overlay H.265 Video with Transparency HOT 4
- option to change number of frames on export
- Sound gone when scaled video HOT 1
- Multiple timelines HOT 1
- black screen when the audio overlay goes to finish HOT 2
- transition demo not work HOT 1
- 如何知道轨道和片段之间的关系
- Is this framework support multiple layer blend mode? HOT 1
- Capture the current frame in composed player item HOT 1
- avplayer seek后,影音不同步 HOT 1
- Exported video appears to be darker (colour shifting) HOT 3
- Orientation problem: some videos are rotated by 90 or 180 degrees
- Example of merging several videos in sequence
- Example project doesn't work on Xcode 15 HOT 1
- 导出视频需要的时间太长
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cabbage.