Interpretar metadatos XMP en ALAssetRepresentation

95

Cuando un usuario realiza algunos cambios (recorte, eliminación de ojos rojos, ...) a las fotos en la aplicación Photos.app incorporada en iOS, los cambios no se aplican a los fullResolutionImagedevueltos por el correspondiente ALAssetRepresentation.

Sin embargo, los cambios se aplican a thumbnaily los fullScreenImagedevuelve ALAssetRepresentation. Además, la información sobre los cambios aplicados se puede encontrar en el ALAssetRepresentationdiccionario de metadatos de a través de la clave @"AdjustmentXMP".

Me gustaría aplicar estos cambios a fullResolutionImagemí mismo para preservar la coherencia. He descubierto que en iOS 6 + CIFilter 's filterArrayFromSerializedXMP: inputImageExtent:error:puede convertir esta XMP metadatos a una serie de CIFilter' s:

ALAssetRepresentation *rep; 
NSString *xmpString = rep.metadata[@"AdjustmentXMP"];
NSData *xmpData = [xmpString dataUsingEncoding:NSUTF8StringEncoding];

CIImage *image = [CIImage imageWithCGImage:rep.fullResolutionImage];

NSError *error = nil;
NSArray *filterArray = [CIFilter filterArrayFromSerializedXMP:xmpData 
                                             inputImageExtent:image.extent 
                                                        error:&error];
if (error) {
     NSLog(@"Error during CIFilter creation: %@", [error localizedDescription]);
}

CIContext *context = [CIContext contextWithOptions:nil];

for (CIFilter *filter in filterArray) {
     [filter setValue:image forKey:kCIInputImageKey];
     image = [filter outputImage];
}

Sin embargo, esto solo funciona para algunos filtros (recorte, mejora automática), pero no para otros como la eliminación de ojos rojos. En estos casos, los CIFilters no tienen ningún efecto visible. Por eso, mis preguntas:

  • ¿Alguien conoce alguna forma de crear la eliminación de ojos rojos CIFilter? (De manera consistente con Photos.app. El filtro con la clave kCIImageAutoAdjustRedEyeno es suficiente. Por ejemplo, no toma parámetros para la posición de los ojos).
  • ¿Existe la posibilidad de generar y aplicar estos filtros en iOS 5?
andreas
fuente
Este enlace es a otra pregunta de Stackoverflow que proporciona un algoritmo para ojos rojos. No es mucho, pero es un comienzo. stackoverflow.com/questions/133675/red-eye-reduction-algorithm
Roecrew
En iOS 7, el código enumerado aplica correctamente el filtro de eliminación de ojos rojos (filtro interno CIRedEyeCorrections).
paiv

Respuestas:

2
ALAssetRepresentation* representation = [[self assetAtIndex:index] defaultRepresentation];

// Create a buffer to hold the data for the asset's image
uint8_t *buffer = (Byte*)malloc(representation.size); // Copy the data from the asset into the buffer
NSUInteger length = [representation getBytes:buffer fromOffset: 0.0  length:representation.size error:nil];

if (length==0)
    return nil;

// Convert the buffer into a NSData object, and free the buffer after.

NSData *adata = [[NSData alloc] initWithBytesNoCopy:buffer length:representation.size freeWhenDone:YES];

// Set up a dictionary with a UTI hint. The UTI hint identifies the type
// of image we are dealing with (that is, a jpeg, png, or a possible
// RAW file).

// Specify the source hint.

NSDictionary* sourceOptionsDict = [NSDictionary dictionaryWithObjectsAndKeys:

(id)[representation UTI], kCGImageSourceTypeIdentifierHint, nil];

// Create a CGImageSource with the NSData. A image source can
// contain x number of thumbnails and full images.

CGImageSourceRef sourceRef = CGImageSourceCreateWithData((CFDataRef) adata,  (CFDictionaryRef) sourceOptionsDict);

[adata release];

CFDictionaryRef imagePropertiesDictionary;

// Get a copy of the image properties from the CGImageSourceRef.

imagePropertiesDictionary = CGImageSourceCopyPropertiesAtIndex(sourceRef,0, NULL);

CFNumberRef imageWidth = (CFNumberRef)CFDictionaryGetValue(imagePropertiesDictionary, kCGImagePropertyPixelWidth);

CFNumberRef imageHeight = (CFNumberRef)CFDictionaryGetValue(imagePropertiesDictionary, kCGImagePropertyPixelHeight);

int w = 0;

int h = 0;

CFNumberGetValue(imageWidth, kCFNumberIntType, &w);

CFNumberGetValue(imageHeight, kCFNumberIntType, &h);

// Clean up memory

CFRelease(imagePropertiesDictionary);
Yash Golwara
fuente