Interpretar metadados XMP em ALAssetRepresentation

95

Quando um usuário faz algumas alterações (corte, remoção de olhos vermelhos, ...) em fotos no Photos.app integrado no iOS, as alterações não são aplicadas ao fullResolutionImageretornado pelo correspondente ALAssetRepresentation.

No entanto, as alterações são aplicadas ao thumbnaile ao fullScreenImageretornado pelo ALAssetRepresentation. Além disso, informações sobre as alterações aplicadas podem ser encontradas no ALAssetRepresentationdicionário de metadados de por meio da chave @"AdjustmentXMP".

Eu gostaria de aplicar essas alterações a fullResolutionImagemim mesmo para preservar a consistência. Eu descobri que em iOS6 + CIFilter 's filterArrayFromSerializedXMP: inputImageExtent:error:pode converter este XMP metadados para uma matriz 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];
}

No entanto, isso funciona apenas para alguns filtros (corte, aprimoramento automático), mas não para outros, como remoção de olhos vermelhos. Nestes casos, os CIFilters não têm efeito visível. Portanto, minhas perguntas:

  • Alguém sabe de uma maneira de criar a remoção de olhos vermelhos CIFilter? (De forma consistente com o Photos.app. O filtro com a chave kCIImageAutoAdjustRedEyenão é suficiente. Por exemplo, não leva parâmetros para a posição dos olhos.)
  • Existe a possibilidade de gerar e aplicar esses filtros no iOS 5?
andreas
fonte
Este link é para outra questão Stackoverflow que fornece um algoritmo para olhos vermelhos. Não é muito, mas é um começo. stackoverflow.com/questions/133675/red-eye-reduction-algorithm
Roecrew
No iOS 7, o código listado aplica corretamente o filtro de remoção de olhos vermelhos (filtro interno CIRedEyeCorrections).
paiv

Respostas:

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
fonte