ios - create - Convierta UIImage a NSData sin usar UIImagePngrepresentation o UIImageJpegRepresentation
uiimage frame swift 4 (3)
Necesito convertir UIImage
a NSData
pero sin usar UIImagePngRepresentation
o UIImageJpegRepresentation
, para imágenes de photolib puedo usar el método assetlib como se mencionó aquí. Usando ALAssetsLibrary y ALAsset saca la imagen como NSData , pero para imagen capturada, la url de conjunto no existe en este caso. Necesito convertir UIImage
directamente a bytes con datos exif, ¿cómo puedo lograr esto? por favor ayuda
H bastan
Basado en tu comentario:
... Quiero guardar el retorno de la imagen capturada por la cámara del dispositivo, a través del método de delegado UIImagepicker en el directorio de documentos ...
Parece que su objetivo real es guardar la imagen con datos EXIF en el directorio de documentos y no específicamente obtener el UIImage como un objeto NSData con los datos EXIF. En ese caso, puede hacer lo siguiente en su implementación de imagePickerController:didFinishPickingMediaWithInfo:
// Get your image.
UIImage *capturedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
// Get your metadata (includes the EXIF data).
NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
// Create your file URL.
NSFileManager *defaultManager = [NSFileManager defaultManager];
NSURL *docsURL = [[defaultManager URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
NSURL *outputURL = [docsURL URLByAppendingPathComponent:@"imageWithEXIFData.jpg"];
// Set your compression quuality (0.0 to 1.0).
NSMutableDictionary *mutableMetadata = [metadata mutableCopy];
[mutableMetadata setObject:@(1.0) forKey:(__bridge NSString *)kCGImageDestinationLossyCompressionQuality];
// Create an image destination.
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((__bridge CFURLRef)outputURL, kUTTypeJPEG , 1, NULL);
if (imageDestination == NULL ) {
// Handle failure.
NSLog(@"Error -> failed to create image destination.");
return;
}
// Add your image to the destination.
CGImageDestinationAddImage(imageDestination, capturedImage.CGImage, (__bridge CFDictionaryRef)mutableMetadata);
// Finalize the destination.
if (CGImageDestinationFinalize(imageDestination) == NO) {
// Handle failure.
NSLog(@"Error -> failed to finalize the image.");
}
CFRelease(imageDestination);
Desde mis pruebas, el tiempo de ejecución fue casi igual o más rápido que hacerlo:
NSData *data = UIImageJPEGRepresentation(capturedImage, 1.0);
[data writeToURL:outputURL atomically:YES];
... y te quedas con los datos EXIF!
También puede enviarlo a una cola en segundo plano si desea asegurarse de que su interfaz de usuario se mantenga receptiva:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Do the image saving here...
});
Nota importante: Deberá agregar ImageIO.framework
y MobileCoreServices.framework
a las fases de compilación de su destino e importarlas en la clase en la que guarda la imagen:
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
Otras notas Tengo entendido que en este caso no estamos creando una pérdida de generación al guardar la imagen como se propone en el ejemplo. Estamos utilizando la propiedad CGImage de UIImage y, como indica la documentación:
Los datos de imagen de cuarzo subyacentes
Puedes probar algo como esto. No estoy seguro si es el mejor método. Pero vale la pena un tiro. En caso de que la URL de la imagen esté disponible, puede probar initWithContentsOfUrl
NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/test/isajf/isajf/test.jpg"];
Tuve un problema similar, pero por razones de seguridad no quería escribir los datos en el sistema de archivos predeterminado como lo sugirió Wes. También quería poder agregar metadatos a mi imagen. Mi solución fue la siguiente:
- (NSData *)dataFromImage:(UIImage *)image metadata:(NSDictionary *)metadata mimetype:(NSString *)mimetype
{
NSMutableData *imageData = [NSMutableData data];
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef)mimetype, NULL);
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, uti, 1, NULL);
if (imageDestination == NULL)
{
NSLog(@"Failed to create image destination");
imageData = nil;
}
else
{
CGImageDestinationAddImage(imageDestination, image.CGImage, (__bridge CFDictionaryRef)metadata);
if (CGImageDestinationFinalize(imageDestination) == NO)
{
NSLog(@"Failed to finalise");
imageData = nil;
}
CFRelease(imageDestination);
}
CFRelease(uti);
return imageData;
}
Para usarlo, harías lo siguiente:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata];
NSString *mimeType = @"image/jpeg"; // ideally this would be dynamically set. Not defaulted to a jpeg!
// you could add to the metadata dictionary (after converting it to a mutable copy) if you needed to.
// convert to NSData
NSData *imageData = [self dataFromImage:image metadata:metadata mimetype:mimeType];
// ...
}