将 CGImageRef 保存为 png 文件?

发布于 2024-08-02 21:43:14 字数 94 浏览 8 评论 0原文

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

感谢您的帮助!

in my Cocoa application, I load a .jpg file from disk, manipulate it. Now it needs to be written to disk as a .png file. How can you do that?

Thanks for your help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

雨巷深深 2024-08-09 21:43:14

使用 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(或 iOS 上的 MobileCoreServices)添加到项目中并包含标头。


如果您使用的是 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 方法比 UIImage 方法快大约 10%我的 iPhone 5s。在模拟器中,UIImage 方法更快。如果您确实关心性能,那么可能值得针对您在设备上的特定情况进行测试。

Using CGImageDestination and passing kUTTypePNG is the correct approach. Here's a quick snippet:

@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;
}

You'll need to add ImageIO and CoreServices (or MobileCoreServices on iOS) to your project and include the headers.


If you're on iOS and don't need a solution that works on Mac too, you can use a simpler approach:

// `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];

In my tests, the ImageIO approach was about 10% faster than the UIImage approach on my iPhone 5s. In the simulator, the UIImage approach was faster. It's probably worth testing each for your particular situation on the device if you're really concerned with performance.

后来的我们 2024-08-09 21:43:14

这是 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)
}

Here is a macOS-friendly, Swift 3 & 4 example:

@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)
}
云雾 2024-08-09 21:43:14

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

Create a CGImageDestination, passing kUTTypePNG as the type of file to create. Add the image, then finalize the destination.

裸钻 2024-08-09 21:43:14

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
  }
}

Swift 5+ adopted version

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
  }
}
热情消退 2024-08-09 21:43:14

提供的解决方案可能仍然可以正常工作,但有一些更新的 API CoreImage 中的 this 具有相同的功能,并且使用起来更加“Swifty”:

import CoreImage

func write(cgimage: CGImage, to url: URL) throws {
    let cicontext = CIContext()
    let ciimage = CIImage(cgImage: cgimage)
    try cicontext.writePNGRepresentation(of: ciimage, to: url, format: .RGBA8, colorSpace: ciimage.colorSpace!)
}

The provided solutions probably still work fine but there is some newer API for this in CoreImage which does the same and is a bit more "Swifty" to use:

import CoreImage

func write(cgimage: CGImage, to url: URL) throws {
    let cicontext = CIContext()
    let ciimage = CIImage(cgImage: cgimage)
    try cicontext.writePNGRepresentation(of: ciimage, to: url, format: .RGBA8, colorSpace: ciimage.colorSpace!)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文