如何将分离出的RGB单通道生成为对应颜色的CGImage?
单通道数据生成带色彩的分离通道CGImage方案
要实现类似图像编辑软件里的分离通道显示效果(红/绿/蓝通道分别以对应色彩显示),必须补全缺失的颜色通道——因为单通道数据默认对应灰度颜色空间,CGImage无法直接将灰度图指定为某一个RGB通道来显示色彩。以下是两种高效实现方案:
方案一:补全通道后构建RGB格式CGImage
这是最直接的方式,通过填充其他通道为0,将单通道数据扩展为RGB格式图像:
- 红色通道:保留你的R通道数据,将G、B通道全部填充为0,合并为RGB格式后生成CGImage
- 绿色通道:保留G通道数据,R、B通道填充为0
- 蓝色通道:保留B通道数据,R、G通道填充为0
利用vImage可以高效完成通道合并,示例代码(Swift):
import Accelerate import CoreGraphics func createColoredChannelImage(from channelBuffer: vImage_Buffer, channel: RGBChannel, size: CGSize) -> CGImage? { // 创建全0的辅助通道Buffer guard let zeroBuffer = try? vImage_Buffer(width: Int(size.width), height: Int(size.height), bitsPerPixel: 8) else { return nil } defer { zeroBuffer.free() } memset(zeroBuffer.data, 0, zeroBuffer.rowBytes * zeroBuffer.height) // 按目标通道排序源Buffer let sourceBuffers: [vImage_Buffer] switch channel { case .red: sourceBuffers = [channelBuffer, zeroBuffer, zeroBuffer] case .green: sourceBuffers = [zeroBuffer, channelBuffer, zeroBuffer] case .blue: sourceBuffers = [zeroBuffer, zeroBuffer, channelBuffer] } // 创建交错式RGB Buffer guard let interleavedBuffer = try? vImage_Buffer(width: Int(size.width), height: Int(size.height), bitsPerPixel: 24) else { return nil } defer { interleavedBuffer.free() } // 平面转交错格式 let error = vImageConvert_PlanarToInterleaved_ARGB8888(&sourceBuffers, &interleavedBuffer, 0, UInt32(size.height), 0, 0) guard error == kvImageNoError else { return nil } // 生成CGImage let dataProvider = CGDataProvider(data: Data(bytesNoCopy: interleavedBuffer.data, count: interleavedBuffer.rowBytes * interleavedBuffer.height, deallocator: .free))! return CGImage(width: Int(size.width), height: Int(size.height), bitsPerComponent: 8, bitsPerPixel: 24, bytesPerRow: interleavedBuffer.rowBytes, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue), provider: dataProvider, decode: nil, shouldInterpolate: false, intent: .defaultIntent) } enum RGBChannel { case red, green, blue }
方案二:Core Image滤镜实时着色(内存更高效)
如果不想额外占用内存存储全0通道数据,可以直接用Core Image滤镜给生成的单通道灰度图着色,无需修改原始通道数据:
- 用
CIColorMonochrome滤镜,将灰度图的亮度映射到目标颜色的亮度,直接生成带色彩的通道图
示例代码(Swift):
import CoreImage import UIKit func tintChannelGrayscaleImage(_ grayscaleCGImage: CGImage, targetColor: UIColor) -> CGImage? { let ciImage = CIImage(cgImage: grayscaleCGImage) guard let colorFilter = CIFilter(name: "CIColorMonochrome") else { return nil } colorFilter.setValue(ciImage, forKey: kCIInputImageKey) colorFilter.setValue(CIColor(color: targetColor), forKey: kCIInputColorKey) colorFilter.setValue(1.0, forKey: kCIInputIntensityKey) guard let outputCI = colorFilter.outputImage else { return nil } let ciContext = CIContext(options: [.useSoftwareRenderer: false]) return ciContext.createCGImage(outputCI, from: outputCI.extent) } // 使用示例:将红色通道的灰度图转为红色调图像 // if let redGrayscaleImg = yourRedChannelGrayscaleCGImage { // let redColoredImg = tintChannelGrayscaleImage(redGrayscaleImg, targetColor: .red) // }
内容的提问来源于stack exchange,提问作者God of Biscuits
相关产品推荐
相关产品推荐

