给定CIImage,将图像数据写入磁盘的最快方法是什么?

时间:2015-01-12 06:23:13

标签: ios swift ciimage uiimagejpegrepresentation photokit

我正在使用PhotoKit,并已实施过滤器用户可以应用于照片库中的照片。我目前正在获取图片,应用过滤器,将修改后的版本作为CIImage返回,然后我使用CIImageNSData转换为UIImageJPEGRepresentation,以便我可以写出来到磁盘。虽然这种方法效果很好,但当用户尝试编辑非常大(如30 MB)的照片时,可能需要30秒才能完成此操作,98%的时间用于UIImageJPEGRepresentation(从乐器获得的统计数据)。

我正在寻找一种更有效的方法,将此编辑过的照片保存到磁盘,如果可能的话,不会影响质量。

我理解UIImagePNGRepresentation可能会提高质量,但这比JPEG表示更慢。

这是我目前正在做的,在默认优先级线程(qos_class_utility)上:

func jpegRepresentationOfImage(image: CIImage) -> NSData {
    let eaglContext = EAGLContext(API: .OpenGLES2)
    let ciContext = CIContext(EAGLContext: eaglContext)

    let outputImageRef = ciContext.createCGImage(image, fromRect: image.extent())
    let uiImage = UIImage(CGImage: outputImageRef, scale: 1.0, orientation: UIImageOrientation.Up)

    return UIImageJPEGRepresentation(uiImage, 0.9) //this takes upwards of 20-30 seconds with large photos!
}

//writing out to disk:
var error: NSError?
let success = jpegData.writeToURL(contentEditingOutput.renderedContentURL, options: NSDataWritingOptions.AtomicWrite, error: &error)

2 个答案:

答案 0 :(得分:6)

我建议使用CGImageDestination将CGImage直接传递给ImageIO。您可以将字典传递给CGImageDestinationAddImage以指示压缩质量,图像方向等。

CFDataRef save_cgimage_to_jpeg (CGImageRef image)
{
    CFMutableDataRef cfdata = CFDataCreateMutable(nil,0);
    CGImageDestinationRef dest = CGImageDestinationCreateWithData(data, CFSTR("public.jpeg"), 1, NULL);
    CGImageDestinationAddImage(dest, image, NULL);
    if(!CGImageDestinationFinalize(dest))
        ; // error
    CFRelease(dest);
    return cfdata
}

答案 1 :(得分:1)

尝试如下使用CIImage方法 writeJPEGRepresentation (适用于iOS 10)避开UIImage并加快编写速度。

extension CIImage {

    @objc func saveJPEG(_ name:String, inDirectoryURL:URL? = nil, quality:CGFloat = 1.0) -> String? {

        var destinationURL = inDirectoryURL

        if destinationURL == nil {
            destinationURL = try? FileManager.default.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        }

        if var destinationURL = destinationURL {

            destinationURL = destinationURL.appendingPathComponent(name)

            if let colorSpace = CGColorSpace(name: CGColorSpace.sRGB) {

                do {

                    let context = CIContext()

                    try context.writeJPEGRepresentation(of: self, to: destinationURL, colorSpace: colorSpace, options: [kCGImageDestinationLossyCompressionQuality as CIImageRepresentationOption : quality])

                    return destinationURL.path

                } catch {
                    return nil
                }
            }
        }

        return nil
    }
}

@objc关键字使您可以按以下方式在Objective-C中调用该方法:

NSString* path = [image saveJPEG:@"image.jpg" inDirectoryURL:url quality:1.0];

对于PNG,iOS 11具有类似的方法 writePNGRepresentation

   if #available(iOS 11.0, *) {

        if let colorSpace = CGColorSpace(name: CGColorSpace.sRGB) {

            do {
                let format = CIFormat.RGBA8

                try context.writePNGRepresentation(of: self, to: destinationURL, format: format, colorSpace: colorSpace)

                return destinationURL.path

            } catch {
                return nil
            }   
        }
    }