From 8f6e6ffa6664435b81a88b72e7aa59706778b501 Mon Sep 17 00:00:00 2001 From: shogo4405 Date: Tue, 9 Dec 2025 22:14:46 +0900 Subject: [PATCH 1/2] Remove ScreenRendererByCPU. --- Examples/iOS/PublishViewModel.swift | 5 - Examples/iOS/UVCViewModel.swift | 5 - Examples/macOS/PublishViewModel.swift | 5 - .../Extension/vImage_Buffer+Extension.swift | 36 ---- .../Sources/Screen/AssetScreenObject.swift | 7 - .../Sources/Screen/ImageScreenObject.swift | 19 +- HaishinKit/Sources/Screen/Screen.swift | 23 +-- HaishinKit/Sources/Screen/ScreenObject.swift | 6 - .../Sources/Screen/ScreenRendererByCPU.swift | 184 ------------------ HaishinKit/Sources/Screen/Shape.swift | 40 ---- HaishinKit/Sources/Screen/ShapeFactory.swift | 34 ---- .../Sources/Screen/StreamScreenObject.swift | 7 - .../Sources/Screen/TextScreenObject.swift | 11 +- .../Screen/VideoTrackScreenObject.swift | 7 - 14 files changed, 16 insertions(+), 373 deletions(-) delete mode 100644 HaishinKit/Sources/Extension/vImage_Buffer+Extension.swift delete mode 100644 HaishinKit/Sources/Screen/ScreenRendererByCPU.swift delete mode 100644 HaishinKit/Sources/Screen/Shape.swift delete mode 100644 HaishinKit/Sources/Screen/ShapeFactory.swift diff --git a/Examples/iOS/PublishViewModel.swift b/Examples/iOS/PublishViewModel.swift index 2bc8e08db..80296b7cf 100644 --- a/Examples/iOS/PublishViewModel.swift +++ b/Examples/iOS/PublishViewModel.swift @@ -263,11 +263,6 @@ final class PublishViewModel: ObservableObject { guard let videoScreenObject else { return } - if await preference.isGPURendererEnabled { - await mixer.screen.isGPURendererEnabled = true - } else { - await mixer.screen.isGPURendererEnabled = false - } videoScreenObject.cornerRadius = 16.0 videoScreenObject.track = 1 videoScreenObject.horizontalAlignment = .right diff --git a/Examples/iOS/UVCViewModel.swift b/Examples/iOS/UVCViewModel.swift index b88d635ef..6681c39b7 100644 --- a/Examples/iOS/UVCViewModel.swift +++ b/Examples/iOS/UVCViewModel.swift @@ -197,11 +197,6 @@ final class UVCViewModel: ObservableObject { await makeSession(preference) } Task { @ScreenActor in - if await preference.isGPURendererEnabled { - await mixer.screen.isGPURendererEnabled = true - } else { - await mixer.screen.isGPURendererEnabled = false - } await mixer.screen.size = .init(width: 720, height: 1280) await mixer.screen.backgroundColor = UIColor.black.cgColor } diff --git a/Examples/macOS/PublishViewModel.swift b/Examples/macOS/PublishViewModel.swift index 18575d681..b4d4d7fb7 100644 --- a/Examples/macOS/PublishViewModel.swift +++ b/Examples/macOS/PublishViewModel.swift @@ -98,11 +98,6 @@ final class PublishViewModel: ObservableObject { await makeSession(preference) } Task { @ScreenActor in - if await preference.isGPURendererEnabled { - await mixer.screen.isGPURendererEnabled = true - } else { - await mixer.screen.isGPURendererEnabled = false - } let assetScreenObject = AssetScreenObject() assetScreenObject.size = .init(width: 180, height: 180) assetScreenObject.layoutMargin = .init(top: 16, left: 16, bottom: 0, right: 0) diff --git a/HaishinKit/Sources/Extension/vImage_Buffer+Extension.swift b/HaishinKit/Sources/Extension/vImage_Buffer+Extension.swift deleted file mode 100644 index 424884e2e..000000000 --- a/HaishinKit/Sources/Extension/vImage_Buffer+Extension.swift +++ /dev/null @@ -1,36 +0,0 @@ -import Accelerate -import CoreMedia -import CoreVideo -import Foundation - -extension vImage_Buffer { - init?(height: vImagePixelCount, width: vImagePixelCount, pixelBits: UInt32, flags: vImage_Flags) { - self.init() - guard vImageBuffer_Init( - &self, - height, - width, - pixelBits, - flags) == kvImageNoError else { - return nil - } - } - - @discardableResult - mutating func copy(to cvPixelBuffer: CVPixelBuffer, format: inout vImage_CGImageFormat) -> vImage_Error { - let cvImageFormat = vImageCVImageFormat_CreateWithCVPixelBuffer(cvPixelBuffer).takeRetainedValue() - vImageCVImageFormat_SetColorSpace(cvImageFormat, CGColorSpaceCreateDeviceRGB()) - defer { - if let dictionary = CVBufferCopyAttachments(cvPixelBuffer, .shouldNotPropagate) { - CVBufferSetAttachments(cvPixelBuffer, dictionary, .shouldPropagate) - } - } - return vImageBuffer_CopyToCVPixelBuffer( - &self, - &format, - cvPixelBuffer, - cvImageFormat, - nil, - vImage_Flags(kvImageNoFlags)) - } -} diff --git a/HaishinKit/Sources/Screen/AssetScreenObject.swift b/HaishinKit/Sources/Screen/AssetScreenObject.swift index 0436cc3f8..aec4e0d48 100644 --- a/HaishinKit/Sources/Screen/AssetScreenObject.swift +++ b/HaishinKit/Sources/Screen/AssetScreenObject.swift @@ -90,13 +90,6 @@ public final class AssetScreenObject: ScreenObject, ChromaKeyProcessable { } } - override public func makeImage(_ renderer: some ScreenRenderer) -> CGImage? { - guard let image: CIImage = makeImage(renderer) else { - return nil - } - return renderer.context.createCGImage(image, from: videoGravity.region(bounds, image: image.extent)) - } - override public func makeImage(_ renderer: some ScreenRenderer) -> CIImage? { guard let sampleBuffer, let pixelBuffer = sampleBuffer.imageBuffer else { return nil diff --git a/HaishinKit/Sources/Screen/ImageScreenObject.swift b/HaishinKit/Sources/Screen/ImageScreenObject.swift index 445a5008d..4dabe82e2 100644 --- a/HaishinKit/Sources/Screen/ImageScreenObject.swift +++ b/HaishinKit/Sources/Screen/ImageScreenObject.swift @@ -12,11 +12,15 @@ public final class ImageScreenObject: ScreenObject { } } - override public func makeImage(_ renderer: some ScreenRenderer) -> CGImage? { + override public func makeImage(_ renderer: some ScreenRenderer) -> CIImage? { let intersection = bounds.intersection(renderer.bounds) guard bounds != intersection else { - return cgImage + if let cgImage { + return CIImage(cgImage: cgImage) + } else { + return nil + } } // Handling when the drawing area is exceeded. @@ -39,15 +43,12 @@ public final class ImageScreenObject: ScreenObject { case .bottom: y = abs(bounds.origin.y) } - - return cgImage?.cropping(to: .init(origin: .init(x: x, y: y), size: intersection.size)) - } - - override public func makeImage(_ renderer: some ScreenRenderer) -> CIImage? { - guard let image: CGImage = makeImage(renderer) else { + + if let cgImage = cgImage?.cropping(to: .init(origin: .init(x: x, y: y), size: intersection.size)) { + return CIImage(cgImage: cgImage) + } else { return nil } - return CIImage(cgImage: image) } override public func makeBounds(_ size: CGSize) -> CGRect { diff --git a/HaishinKit/Sources/Screen/Screen.swift b/HaishinKit/Sources/Screen/Screen.swift index 90a7d04b7..d78520a92 100644 --- a/HaishinKit/Sources/Screen/Screen.swift +++ b/HaishinKit/Sources/Screen/Screen.swift @@ -42,21 +42,6 @@ public final class Screen: ScreenObjectContainerConvertible { } } - /// Specifies the gpu rendering enabled. - @available(*, deprecated) - public var isGPURendererEnabled = false { - didSet { - guard isGPURendererEnabled != oldValue else { - return - } - if isGPURendererEnabled { - renderer = ScreenRendererByGPU(dynamicRangeMode: dynamicRangeMode) - } else { - renderer = ScreenRendererByCPU(dynamicRangeMode: dynamicRangeMode) - } - } - } - #if os(macOS) /// Specifies the background color. public var backgroundColor: CGColor = NSColor.black.cgColor { @@ -92,15 +77,11 @@ public final class Screen: ScreenObjectContainerConvertible { guard dynamicRangeMode != oldValue else { return } - if isGPURendererEnabled { - renderer = ScreenRendererByGPU(dynamicRangeMode: dynamicRangeMode) - } else { - renderer = ScreenRendererByCPU(dynamicRangeMode: dynamicRangeMode) - } + renderer = ScreenRendererByGPU(dynamicRangeMode: dynamicRangeMode) CVPixelBufferPoolCreate(nil, nil, dynamicRangeMode.makePixelBufferAttributes(size), &pixelBufferPool) } } - private(set) var renderer: (any ScreenRenderer) = ScreenRendererByCPU(dynamicRangeMode: .sdr) { + private(set) var renderer: (any ScreenRenderer) = ScreenRendererByGPU(dynamicRangeMode: .sdr) { didSet { renderer.bounds = oldValue.bounds renderer.backgroundColor = oldValue.backgroundColor diff --git a/HaishinKit/Sources/Screen/ScreenObject.swift b/HaishinKit/Sources/Screen/ScreenObject.swift index ec8b8e97c..b84a822c5 100644 --- a/HaishinKit/Sources/Screen/ScreenObject.swift +++ b/HaishinKit/Sources/Screen/ScreenObject.swift @@ -92,12 +92,6 @@ open class ScreenObject { shouldInvalidateLayout = true } - /// Makes cgImage for offscreen image. - @available(*, deprecated, message: "It will be removed in the next major update. Please migrate to using CIImage instead.") - open func makeImage(_ renderer: some ScreenRenderer) -> CGImage? { - return nil - } - /// Makes ciImage for offscreen image. open func makeImage(_ renderer: some ScreenRenderer) -> CIImage? { return nil diff --git a/HaishinKit/Sources/Screen/ScreenRendererByCPU.swift b/HaishinKit/Sources/Screen/ScreenRendererByCPU.swift deleted file mode 100644 index c52db0115..000000000 --- a/HaishinKit/Sources/Screen/ScreenRendererByCPU.swift +++ /dev/null @@ -1,184 +0,0 @@ -import Accelerate -import AVFoundation -import CoreImage - -final class ScreenRendererByCPU: ScreenRenderer { - static let noFlags = vImage_Flags(kvImageNoFlags) - static let doNotTile = vImage_Flags(kvImageDoNotTile) - - var bounds: CGRect = .init(origin: .zero, size: Screen.size) - let imageOptions: [CIImageOption: Any]? - var synchronizationClock: CMClock? - var presentationTimeStamp: CMTime = .zero - - let context: CIContext - - var backgroundColor = CGColor(red: 0x00, green: 0x00, blue: 0x00, alpha: 0x00) { - didSet { - guard backgroundColor != oldValue, let components = backgroundColor.components else { - return - } - switch components.count { - case 2: - backgroundColorUInt8Array = [ - UInt8(components[1] * 255), - UInt8(components[0] * 255), - UInt8(components[0] * 255), - UInt8(components[0] * 255) - ] - case 3: - backgroundColorUInt8Array = [ - UInt8(components[2] * 255), - UInt8(components[0] * 255), - UInt8(components[1] * 255), - UInt8(components[1] * 255) - ] - case 4: - backgroundColorUInt8Array = [ - UInt8(components[3] * 255), - UInt8(components[0] * 255), - UInt8(components[1] * 255), - UInt8(components[2] * 255) - ] - default: - break - } - } - } - - private var format = vImage_CGImageFormat( - bitsPerComponent: 8, - bitsPerPixel: 32, - colorSpace: nil, - bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.first.rawValue), - version: 0, - decode: nil, - renderingIntent: .defaultIntent) - - private var images: [ScreenObject: vImage_Buffer] = [:] - private var canvas: vImage_Buffer = .init() - private var converter: vImageConverter? - private var shapeFactory = ShapeFactory() - private var pixelFormatType: OSType? { - didSet { - guard pixelFormatType != oldValue else { - return - } - converter = nil - } - } - private var backgroundColorUInt8Array: [UInt8] = [0x00, 0x00, 0x00, 0x00] - private lazy var choromaKeyProcessor: ChromaKeyProcessor? = { - return try? ChromaKeyProcessor() - }() - - init(dynamicRangeMode: DynamicRangeMode) { - context = dynamicRangeMode.makeCIContext() - if let colorSpace = dynamicRangeMode.colorSpace { - imageOptions = [.colorSpace: colorSpace] - } else { - imageOptions = nil - } - } - - func setTarget(_ pixelBuffer: CVPixelBuffer?) { - guard let pixelBuffer else { - return - } - pixelFormatType = pixelBuffer.pixelFormatType - if converter == nil { - let cvImageFormat = vImageCVImageFormat_CreateWithCVPixelBuffer(pixelBuffer).takeRetainedValue() - vImageCVImageFormat_SetColorSpace(cvImageFormat, CGColorSpaceCreateDeviceRGB()) - converter = try? vImageConverter.make( - sourceFormat: cvImageFormat, - destinationFormat: format - ) - } - guard let converter else { - return - } - vImageBuffer_InitForCopyFromCVPixelBuffer( - &canvas, - converter, - pixelBuffer, - vImage_Flags(kvImageNoAllocate) - ) - switch pixelFormatType { - case kCVPixelFormatType_32ARGB: - vImageBufferFill_ARGB8888( - &canvas, - &backgroundColorUInt8Array, - vImage_Flags(kvImageNoFlags) - ) - default: - break - } - } - - func layout(_ screenObject: ScreenObject) { - autoreleasepool { - guard let image: CGImage = screenObject.makeImage(self) else { - return - } - do { - images[screenObject]?.free() - var buffer = try vImage_Buffer(cgImage: image, format: format) - images[screenObject] = buffer - if 0 < screenObject.cornerRadius { - if var mask = shapeFactory.cornerRadius(image.size, cornerRadius: screenObject.cornerRadius) { - vImageOverwriteChannels_ARGB8888(&mask, &buffer, &buffer, 0x8, Self.noFlags) - } - } else { - if let screenObject = screenObject as? (any ChromaKeyProcessable), - let chromaKeyColor = screenObject.chromaKeyColor, - var mask = try choromaKeyProcessor?.makeMask(&buffer, chromeKeyColor: chromaKeyColor) { - vImageOverwriteChannels_ARGB8888(&mask, &buffer, &buffer, 0x8, Self.noFlags) - } - } - } catch { - logger.error(error) - } - } - } - - func draw(_ screenObject: ScreenObject) { - guard var image = images[screenObject] else { - return - } - - let origin = screenObject.bounds.origin - let start = Int(max(0, origin.y)) * canvas.rowBytes + Int(max(0, origin.x)) * 4 - - var destination = vImage_Buffer( - data: canvas.data.advanced(by: start), - height: image.height, - width: image.width, - rowBytes: canvas.rowBytes - ) - - switch pixelFormatType { - case kCVPixelFormatType_32ARGB: - switch screenObject.blendMode { - case .normal: - vImageCopyBuffer( - &image, - &destination, - 4, - Self.doNotTile - ) - case .alpha: - vImageAlphaBlend_ARGB8888( - &image, - &destination, - &destination, - Self.doNotTile - ) - } - default: - break - } - } - - func render() { - } -} diff --git a/HaishinKit/Sources/Screen/Shape.swift b/HaishinKit/Sources/Screen/Shape.swift deleted file mode 100644 index b255f022a..000000000 --- a/HaishinKit/Sources/Screen/Shape.swift +++ /dev/null @@ -1,40 +0,0 @@ -import Accelerate -import Foundation - -#if canImport(AppKit) -import AppKit -#endif - -#if canImport(UIKit) -import UIKit -#endif - -final class RoundedSquareShape: Shape { - var rect: CGRect = .zero - var cornerRadius: CGFloat = .zero - - func makeCGImage() -> CGImage? { - guard let context = CGContext( - data: nil, - width: Int(rect.width), - height: Int(rect.height), - bitsPerComponent: 8, - bytesPerRow: Int(rect.width), - space: CGColorSpaceCreateDeviceGray(), - bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue).rawValue - ) else { - return nil - } - let path = CGPath(roundedRect: rect, cornerWidth: cornerRadius, cornerHeight: cornerRadius, transform: nil) - #if canImport(AppKit) && !targetEnvironment(macCatalyst) - context.setFillColor(NSColor.white.cgColor) - #endif - #if canImport(UIKit) - context.setFillColor(UIColor.white.cgColor) - #endif - context.addPath(path) - context.closePath() - context.fillPath() - return context.makeImage() - } -} diff --git a/HaishinKit/Sources/Screen/ShapeFactory.swift b/HaishinKit/Sources/Screen/ShapeFactory.swift deleted file mode 100644 index 5b5b70aaa..000000000 --- a/HaishinKit/Sources/Screen/ShapeFactory.swift +++ /dev/null @@ -1,34 +0,0 @@ -import Accelerate -import CoreMedia -import Foundation - -protocol Shape { - func makeCGImage() -> CGImage? -} - -final class ShapeFactory { - private var imageBuffers: [String: vImage_Buffer] = [:] - private var roundedSquareShape = RoundedSquareShape() - - func cornerRadius(_ size: CGSize, cornerRadius: CGFloat) -> vImage_Buffer? { - let key = "\(size.width):\(size.height):\(cornerRadius)" - if let buffer = imageBuffers[key] { - return buffer - } - roundedSquareShape.rect = .init(origin: .zero, size: size) - roundedSquareShape.cornerRadius = cornerRadius - guard - let image = roundedSquareShape.makeCGImage() else { - return nil - } - imageBuffers[key] = try? vImage_Buffer(cgImage: image) - return imageBuffers[key] - } - - func removeAll() { - for buffer in imageBuffers.values { - buffer.free() - } - imageBuffers.removeAll() - } -} diff --git a/HaishinKit/Sources/Screen/StreamScreenObject.swift b/HaishinKit/Sources/Screen/StreamScreenObject.swift index 47086ea88..77827792c 100644 --- a/HaishinKit/Sources/Screen/StreamScreenObject.swift +++ b/HaishinKit/Sources/Screen/StreamScreenObject.swift @@ -71,13 +71,6 @@ public final class StreamScreenObject: ScreenObject, ChromaKeyProcessable { } } - override public func makeImage(_ renderer: some ScreenRenderer) -> CGImage? { - guard let image: CIImage = makeImage(renderer) else { - return nil - } - return renderer.context.createCGImage(image, from: videoGravity.region(bounds, image: image.extent)) - } - override public func makeImage(_ renderer: some ScreenRenderer) -> CIImage? { guard let sampleBuffer, let pixelBuffer = sampleBuffer.imageBuffer else { return nil diff --git a/HaishinKit/Sources/Screen/TextScreenObject.swift b/HaishinKit/Sources/Screen/TextScreenObject.swift index 5fcc60a84..07745b27f 100644 --- a/HaishinKit/Sources/Screen/TextScreenObject.swift +++ b/HaishinKit/Sources/Screen/TextScreenObject.swift @@ -79,7 +79,7 @@ public final class TextScreenObject: ScreenObject { return super.makeBounds(frameSize) } - override public func makeImage(_ renderer: some ScreenRenderer) -> CGImage? { + override public func makeImage(_ renderer: some ScreenRenderer) -> CIImage? { guard let context, let framesetter else { return nil } @@ -87,13 +87,10 @@ public final class TextScreenObject: ScreenObject { let frame = CTFramesetterCreateFrame(framesetter, .init(), path, nil) context.clear(context.boundingBoxOfPath) CTFrameDraw(frame, context) - return context.makeImage() - } - - override public func makeImage(_ renderer: some ScreenRenderer) -> CIImage? { - guard let image: CGImage = makeImage(renderer) else { + if let cgImage = context.makeImage() { + return CIImage(cgImage: cgImage) + } else { return nil } - return CIImage(cgImage: image) } } diff --git a/HaishinKit/Sources/Screen/VideoTrackScreenObject.swift b/HaishinKit/Sources/Screen/VideoTrackScreenObject.swift index 4f95f056c..d494d810f 100644 --- a/HaishinKit/Sources/Screen/VideoTrackScreenObject.swift +++ b/HaishinKit/Sources/Screen/VideoTrackScreenObject.swift @@ -73,13 +73,6 @@ public final class VideoTrackScreenObject: ScreenObject, ChromaKeyProcessable { return false } - override public func makeImage(_ renderer: some ScreenRenderer) -> CGImage? { - guard let image: CIImage = makeImage(renderer) else { - return nil - } - return renderer.context.createCGImage(image, from: videoGravity.region(bounds, image: image.extent)) - } - override public func makeImage(_ renderer: some ScreenRenderer) -> CIImage? { let presentationTimeStamp = renderer.presentationTimeStamp.convertTime(from: CMClockGetHostTimeClock(), to: renderer.synchronizationClock) guard let sampleBuffer = queue?.dequeue(presentationTimeStamp), From fc6b782bf4172bb02513b8dc1f3a0fcc003dc265 Mon Sep 17 00:00:00 2001 From: shogo4405 Date: Tue, 9 Dec 2025 22:33:05 +0900 Subject: [PATCH 2/2] default output color kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange. --- Examples/iOS/PreferenceView.swift | 3 -- Examples/iOS/PreferenceViewModel.swift | 1 - .../Sources/Mixer/DynamicRangeMode.swift | 31 ++++--------------- .../Sources/Screen/ImageScreenObject.swift | 2 +- 4 files changed, 7 insertions(+), 30 deletions(-) diff --git a/Examples/iOS/PreferenceView.swift b/Examples/iOS/PreferenceView.swift index cde685dbe..dd92dc17f 100644 --- a/Examples/iOS/PreferenceView.swift +++ b/Examples/iOS/PreferenceView.swift @@ -54,9 +54,6 @@ struct PreferenceView: View { Text(String(describing: view)).tag(view) } } - Toggle(isOn: $model.isGPURendererEnabled) { - Text("Use GPU rendering.") - } } header: { Text("Others") } diff --git a/Examples/iOS/PreferenceViewModel.swift b/Examples/iOS/PreferenceViewModel.swift index f775acaa0..76ae1ce67 100644 --- a/Examples/iOS/PreferenceViewModel.swift +++ b/Examples/iOS/PreferenceViewModel.swift @@ -33,7 +33,6 @@ final class PreferenceViewModel: ObservableObject { // MARK: - Others @Published var viewType: ViewType = .metal - var isGPURendererEnabled: Bool = true @Published var audioCaptureMode: AudioSourceServiceMode = .audioEngine init() { diff --git a/HaishinKit/Sources/Mixer/DynamicRangeMode.swift b/HaishinKit/Sources/Mixer/DynamicRangeMode.swift index ccd90c2aa..db1dfb368 100644 --- a/HaishinKit/Sources/Mixer/DynamicRangeMode.swift +++ b/HaishinKit/Sources/Mixer/DynamicRangeMode.swift @@ -45,15 +45,6 @@ public enum DynamicRangeMode: Sendable { ] } - private var pixelFormat: OSType { - switch self { - case .sdr: - return kCVPixelFormatType_32ARGB - case .hdr: - return kCVPixelFormatType_64RGBAHalf - } - } - func attach(_ pixelBuffer: CVPixelBuffer) { switch self { case .sdr: @@ -88,21 +79,11 @@ public enum DynamicRangeMode: Sendable { } func makePixelBufferAttributes(_ size: CGSize) -> CFDictionary { - switch self { - case .sdr: - return [ - kCVPixelBufferPixelFormatTypeKey: NSNumber(value: pixelFormat), - kCVPixelBufferMetalCompatibilityKey: kCFBooleanTrue, - kCVPixelBufferWidthKey: NSNumber(value: Int(size.width)), - kCVPixelBufferHeightKey: NSNumber(value: Int(size.height)) - ] as CFDictionary - case .hdr: - return [ - kCVPixelBufferPixelFormatTypeKey: NSNumber(value: videoFormat), - kCVPixelBufferMetalCompatibilityKey: kCFBooleanTrue, - kCVPixelBufferWidthKey: NSNumber(value: Int(size.width)), - kCVPixelBufferHeightKey: NSNumber(value: Int(size.height)) - ] as CFDictionary - } + return [ + kCVPixelBufferPixelFormatTypeKey: NSNumber(value: videoFormat), + kCVPixelBufferMetalCompatibilityKey: kCFBooleanTrue, + kCVPixelBufferWidthKey: NSNumber(value: Int(size.width)), + kCVPixelBufferHeightKey: NSNumber(value: Int(size.height)) + ] as CFDictionary } } diff --git a/HaishinKit/Sources/Screen/ImageScreenObject.swift b/HaishinKit/Sources/Screen/ImageScreenObject.swift index 4dabe82e2..2e426bec7 100644 --- a/HaishinKit/Sources/Screen/ImageScreenObject.swift +++ b/HaishinKit/Sources/Screen/ImageScreenObject.swift @@ -43,7 +43,7 @@ public final class ImageScreenObject: ScreenObject { case .bottom: y = abs(bounds.origin.y) } - + if let cgImage = cgImage?.cropping(to: .init(origin: .init(x: x, y: y), size: intersection.size)) { return CIImage(cgImage: cgImage) } else {