Core Graphics(ImageIO)在 macOS/iOS 中经常被用于图像处理,它不仅能进行绘制,还能完成 格式转换(例如 PNG → JPEG、TIFF → HEIC 等)。常见的流程是:
1、获取 CGImage
从 NSImage(macOS)或 UIImage(iOS)转换得到 CGImage。
2、创建 CGImageDestination
指定输出格式(JPEG、PNG、HEIC 等)。
3、设置压缩参数
比如 JPEG 的质量(kCGImageDestinationLossyCompressionQuality)。
4、写入并生成 Data 或文件
Swift实现Core Graphics
import AppKit
import ImageIO
import UniformTypeIdentifiers
/// 将 NSImage 转换为指定格式的 Data
/// - Parameters:
/// - image: 输入的 NSImage
/// - type: 目标格式(例如 kUTTypeJPEG / kUTTypePNG / kUTTypeHEIC)
/// - quality: 压缩质量(仅 lossy 格式有效,比如 JPEG/HEIC,取值 0~1)
/// - Returns: 转换后的 Data
func convertImageFormat(image: NSImage,
type: CFString,
quality: CGFloat = 1.0) -> Data? {
// Step 1: 获取 CGImage
guard let tiffData = image.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData),
let cgImage = bitmap.cgImage else {
print("无法获取 CGImage")
return nil
}
// Step 2: 创建目标 Data 容器
let outputData = NSMutableData()
// Step 3: 创建 CGImageDestination
guard let destination = CGImageDestinationCreateWithData(outputData, type, 1, nil) else {
print("无法创建 CGImageDestination")
return nil
}
// Step 4: 设置压缩参数
let options: CFDictionary
if type == kUTTypeJPEG || type == kUTTypeHEIC {
options = [kCGImageDestinationLossyCompressionQuality: quality] as CFDictionary
} else {
options = [:] as CFDictionary
}
// Step 5: 添加图像并写入
CGImageDestinationAddImage(destination, cgImage, options)
CGImageDestinationFinalize(destination)
return outputData as Data
}
/// 将图片直接写入文件
func saveImage(_ image: NSImage,
to url: URL,
type: CFString,
quality: CGFloat = 1.0) -> Bool {
guard let data = convertImageFormat(image: image, type: type, quality: quality) else {
return false
}
do {
try data.write(to: url)
print("已保存到 \(url.path)")
return true
} catch {
print("保存失败: \(error.localizedDescription)")
return false
}
}
使用示例
let image = NSImage(named: "example")!
// 转换为 JPEG,质量 0.8
let jpegURL = URL(fileURLWithPath: "/tmp/test.jpg")
saveImage(image, to: jpegURL, type: kUTTypeJPEG, quality: 0.8)
// 转换为 PNG(无损)
let pngURL = URL(fileURLWithPath: "/tmp/test.png")
saveImage(image, to: pngURL, type: kUTTypePNG)
// 转换为 HEIC(需要 macOS 10.13+)
if #available(macOS 10.13, *) {
let heicURL = URL(fileURLWithPath: "/tmp/test.heic")
saveImage(image, to: heicURL, type: kUTTypeHEIC, quality: 0.7)
}
支持的目标格式
在 Core Graphics / ImageIO 框架中,支持的图片格式主要通过 UTType(Uniform Type Identifier)来标识。
常用 Core Graphics 输出格式(通过 CGImageDestination):
1、JPEG:kUTTypeJPEG,扩展名 .jpg / .jpeg,有损压缩,可设置质量(0~1);
2、PNG:kUTTypePNG,扩展名 .png,无损压缩,透明支持;
3、TIFF:kUTTypeTIFF,扩展名 .tif / .tiff,无损,可多页(多帧);
4、GIF:kUTTypeGIF,扩展名 .gif,支持动画,但 Core Graphics 只能生成单帧;
5、BMP:kUTTypeBMP,扩展名 .bmp,无损,Windows 位图;
6、ICO:kUTTypeICO,扩展名 .ico,Windows 图标文件;
7、HEIF:kUTTypeHEIF,扩展名 .heif,HEIF 容器,可存储 JPEG/HEVC 图像;
8、HEIC:kUTTypeHEIC,扩展名 .heic,HEIF + HEVC 编码(iOS 11+/macOS 10.13+);
9、JPEG 2000:kUTTypeJPEG2000,扩展名 .jp2 / .j2k / .jpf / .jpx / .jpm,支持无损和有损压缩;
10、PDF:kUTTypePDF,扩展名 .pdf,矢量图或嵌入位图;
11、RAW:kUTTypeRawImage,扩展名 .raw / .cr2 / .nef / .arw / .dng / .orf / .rw2,相机原始格式,需要支持相机 RAW。
总结
Swift使用Core Graphics,可以实现多种不同图片格式之间的切换。
在macOS 12以后,Apple弃用了老的kUTTypeXXX变量,统一改用UTType。如果继续使用kUTTypeXXX变量,就会提示:
guard let destination = CGImageDestinationCreateWithData(outputData, kUTTypeJPEG , 1, nil) else { // 'kUTTypeJPEG' was deprecated in macOS 12.0: Use UTTypeJPEG or UTType.jpeg (swift) instead.
替代写法:使用UTType。
引入UTType框架:
import UniformTypeIdentifiers
使用UTType写法:
guard let destination = CGImageDestinationCreateWithData(
outputData,
UTType.jpeg.identifier as CFString, // 新的写法
1,
nil
) else {
print("无法创建 CGImageDestination")
completion(false)
return
}
如果不想要手写.identifier as CFString,可以继续使用旧的kUTTypeJPEG,只是会有提示信息。
相关文章
Apple二维图像绘制框架Core Graphics:https://fangjunyu.com/2024/12/16/apple%e4%ba%8c%e7%bb%b4%e5%9b%be%e5%83%8f%e7%bb%98%e5%88%b6%e6%a1%86%e6%9e%b6core-graphics/