Сохранение CGImageRef в файл png?
В моем приложении Какао я загружаю файл.jpg с диска, манипулирую им. Теперь его нужно записать на диск в виде файла.png. Как ты можешь это сделать?
Спасибо за вашу помощь!
5 ответов
Создать CGImageDestination
, проходя kUTTypePNG
как тип файла для создания. Добавьте изображение, затем определите конечный пункт.
С помощью 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;
}
Вам нужно будет добавить ImageIO
а также CoreServices
(или же 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 был примерно на 10% быстрее, чем подход UIImage на моем iPhone 5s. В симуляторе подход UIImage был быстрее. Вероятно, стоит проверить каждую из них на вашей конкретной ситуации на устройстве, если вы действительно обеспокоены производительностью.
Вот 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)
}
Принятая версия 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
}
}
Предоставленные решения, вероятно, все еще работают нормально, но для этого есть более новый API вCoreImage
который делает то же самое и немного более «быстрый» в использовании:
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!)
}