41

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

谢谢你的帮助!

4

4 回答 4

111

使用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;
}

您需要在项目中添加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];

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

于 2011-10-05T22:08:19.260 回答
33

这是一个 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)
}
于 2016-11-02T02:35:04.253 回答
23

创建一个CGImageDestinationkUTTypePNG作为要创建的文件类型传递。添加图像,然后确定目的地。

于 2009-08-24T09:40:04.140 回答
1

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
  }
}
于 2021-08-31T13:50:01.207 回答