Given CIImage, what's the fastest way to write data to disk?
I work with PhotoKit and implement filters that users can apply to photos in their Photo Library. I am currently getting an image by applying a filter, returning the edited version as CIImage
, and then converting CIImage
to NSData
with UIImageJPEGRepresentation
, so I can write this to disk. While this works great when users are trying to edit really large (e.g. 30MB) photos, it can take over 30 seconds, with 98% of the time being spent on UIImageJPEGRepresentation
(stat derived from tools).
I'm looking for a more efficient way to save my edited photo to disk without sacrificing quality if possible.
I understand that it UIImagePNGRepresentation
might result in better quality, but this is even slower than the JPEG rendering.
This is what I am doing now, on the default priority ( qos_class_utility
) thread :
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)
source to share
I would suggest passing the CGImage directly to ImageIO using CGImageDestination. You can pass a dictionary to CGImageDestinationAddImage to specify the compression quality, image orientation, etc.
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
}
source to share