Interpretare i metadati XMP in ALAssetRepresentation


95

Quando un utente apporta alcune modifiche (ritaglio, rimozione occhi rossi, ...) alle foto nell'app Photos.app integrata su iOS, le modifiche non vengono applicate al fullResolutionImagerestituito dal file ALAssetRepresentation.

Tuttavia, le modifiche vengono applicate a thumbnaile fullScreenImagerestituite da ALAssetRepresentation. Inoltre, le informazioni sulle modifiche applicate possono essere trovate nel ALAssetRepresentationdizionario dei metadati di tramite la chiave @"AdjustmentXMP".

Vorrei applicare queste modifiche al fullResolutionImageme stesso per preservare la coerenza. Ho scoperto che su iOS6 + CIFilter è filterArrayFromSerializedXMP: inputImageExtent:error:possibile convertire questi metadati XMP in un array di CIFilter:

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];
}

Tuttavia, questo funziona solo per alcuni filtri (ritaglio, miglioramento automatico) ma non per altri come la rimozione degli occhi rossi. In questi casi, le CIFilters non hanno alcun effetto visibile. Pertanto, le mie domande:

  • Qualcuno è a conoscenza di un modo per creare la rimozione degli occhi rossi CIFilter? (In un modo coerente con Photos.app. Il filtro con la chiave kCIImageAutoAdjustRedEyenon è sufficiente. Ad esempio, non prende parametri per la posizione degli occhi.)
  • C'è la possibilità di generare e applicare questi filtri con iOS 5?

Questo collegamento è a un'altra domanda di Stackoverflow che fornisce un algoritmo per gli occhi rossi. Non è molto ma è un inizio. stackoverflow.com/questions/133675/red-eye-reduction-algorithm
Roecrew

Su iOS 7 il codice elencato applica correttamente il filtro per la rimozione degli occhi rossi (filtro interno CIRedEyeCorrections).
paiv

Risposte:


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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.