将CGImageRef保存到png文件?

29 cocoa png core-graphics cgimage

在我的Cocoa应用程序中,我从磁盘加载一个.jpg文件,操纵它.现在需要将其作为.png文件写入磁盘.你怎么能这样做?

谢谢你的帮助!

Sam*_*fes 97

使用CGImageDestination和传递kUTTypePNG是正确的方法.这是一个快速片段:

@import MobileCoreServices; // or `@import CoreServices;` on Mac
@import ImageIO;

BOOL CGImageWriteToFile(CGImageRef image, NSString *path) {
    CFURLRef url = (__bridge CFURLRef)[NSURL fileURLWithPath:path];
    CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);
    if (!destination) {
        NSLog(@"Failed to create CGImageDestination for %@", path);
        return NO;
    }

    CGImageDestinationAddImage(destination, image, nil);

    if (!CGImageDestinationFinalize(destination)) {
        NSLog(@"Failed to write image to %@", path);
        CFRelease(destination);
        return NO;
    }

    CFRelease(destination);
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

您需要在项目中添加ImageIOCoreServices(或MobileCoreServices在iOS上)并包含标题.


如果您使用的是iOS并且不需要适用于Mac的解决方案,则可以使用更简单的方法:

// `image` is a CGImageRef
// `path` is a NSString with the path to where you want to save it
[UIImagePNGRepresentation([UIImage imageWithCGImage:image]) writeToFile:path atomically:YES];
Run Code Online (Sandbox Code Playgroud)

在我的测试中,ImageIO方法比 iPhone 5s上的UIImage方法快10%左右.在模拟器中,UIImage方法更快.如果您真的关心性能,那么可能值得在设备上针对您的特定情况进行测试.


Dan*_*ing 21

这是一个macOS友好的Swift 3&4示例:

@discardableResult func writeCGImage(_ image: CGImage, to destinationURL: URL) -> Bool {
    guard let destination = CGImageDestinationCreateWithURL(destinationURL as CFURL, kUTTypePNG, 1, nil) else { return false }
    CGImageDestinationAddImage(destination, image, nil)
    return CGImageDestinationFinalize(destination)
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*sey 20

创建一个CGImageDestination,kUTTypePNG作为要创建的文件类型传递.添加图像,然后完成目标.

  • 请参阅我的答案,了解这样做的一个例子. (3认同)

gbk*_*gbk 6

Swift 5+采用版本

import Foundation
import CoreGraphics
import CoreImage
import ImageIO
import MobileCoreServices

extension CIImage {
  
  public func convertToCGImage() -> CGImage? {
    let context = CIContext(options: nil)
    if let cgImage = context.createCGImage(self, from: self.extent) {
      return cgImage
    }
    return nil
  }
  
  public func data() -> Data? {
    convertToCGImage()?.pngData()
  }
}

extension CGImage {
  
  public func pngData() -> Data? {
    let cfdata: CFMutableData = CFDataCreateMutable(nil, 0)
    if let destination = CGImageDestinationCreateWithData(cfdata, kUTTypePNG as CFString, 1, nil) {
      CGImageDestinationAddImage(destination, self, nil)
      if CGImageDestinationFinalize(destination) {
        return cfdata as Data
      }
    }
    
    return nil
  }
}
Run Code Online (Sandbox Code Playgroud)