Swift Mac开发:如何使用CIImage实现多张图片垂直拼接合并
macOS Swift 5 使用CIImage上下拼接多张图片实现方案
核心实现逻辑
- 完全基于CoreImage框架实现,兼容macOS 11+系统,无UIKit依赖,完美适配你的开发环境
- 利用坐标位移+内置合成滤镜实现图片拼接,支持任意数量图片批量处理
后续开发步骤代码实现
基于你已编写的图片加载代码,后续拼接流程如下:
import CoreImage import AppKit // macOS系统需导入AppKit使用NSImage相关能力 // 1. 校验图片加载结果合法性 guard let img1 = img1, let img2 = img2 else { print("图片资源加载失败") return } // 2. 计算拼接后总画布尺寸 let totalWidth = max(img1.extent.width, img2.extent.width) let totalHeight = img1.extent.height + img2.extent.height let finalExtent = CGRect(x: 0, y: 0, width: totalWidth, height: totalHeight) // 3. 对第二张图片做坐标位移,拼接至第一张底部 // 注意:CIImage坐标系原点在左下角,向下拼接需要升高y轴坐标 let moveTransform = CGAffineTransform(translationX: 0, y: img1.extent.height) guard let movedImg2 = img2.transformed(by: moveTransform) as? CIImage else { print("图片坐标位移失败") return } // 4. 调用合成滤镜完成拼接 guard let compositeFilter = CIFilter(name: "CISourceOverCompositing") else { print("合成滤镜创建失败") return } compositeFilter.setValue(movedImg2, forKey: kCIInputImageKey) compositeFilter.setValue(img1, forKey: kCIInputBackgroundImageKey) guard let mergedCIImage = compositeFilter.outputImage else { print("图片合成失败") return }
配套工具方法
CIImage转NSImage(用于界面展示/本地存储)
func ciImageToNSImage(_ ciImage: CIImage, targetSize: CGSize) -> NSImage? { let imageRep = NSCIImageRep(ciImage: ciImage) let resultImage = NSImage(size: targetSize) resultImage.addRepresentation(imageRep) return resultImage } // 调用示例 let finalSize = CGSize(width: totalWidth, height: totalHeight) if let finalNSImage = ciImageToNSImage(mergedCIImage, targetSize: finalSize) { // 可直接赋值给NSImageView展示,或转为PNG/JPG数据写入本地文件 }
通用多图批量拼接方法
func verticalMergeCIImages(_ imageList: [CIImage]) -> CIImage? { guard !imageList.isEmpty else { return nil } guard imageList.count > 1 else { return imageList.first } var mergeResult = imageList.first! var totalHeight = mergeResult.extent.height for index in 1..<imageList.count { let nextImage = imageList[index] // 位移当前图片到已拼接内容的底部 let transform = CGAffineTransform(translationX: 0, y: totalHeight) guard let movedNext = nextImage.transformed(by: transform) as? CIImage else { return nil } // 执行合成 guard let filter = CIFilter(name: "CISourceOverCompositing") else { return nil } filter.setValue(movedNext, forKey: kCIInputImageKey) filter.setValue(mergeResult, forKey: kCIInputBackgroundImageKey) guard let newResult = filter.outputImage else { return nil } mergeResult = newResult totalHeight += nextImage.extent.height } return mergeResult }
注意事项
- 如果需要所有图片宽度统一,拼接前可使用
CILanczosScaleTransform滤镜对宽度不一致的图片做等比缩放,避免拼接后出现错位 - 合成后的CIImage如果需要保存到本地,可通过
NSBitmapImageRep转为对应格式的二进制数据后写入文件
内容的提问来源于stack exchange,提问作者Buzka91
相关产品推荐
相关产品推荐

