Interpretieren Sie XMP-Metadaten in ALAssetRepresentation

95

Wenn ein Benutzer einige Änderungen (Zuschneiden, Entfernen roter Augen, ...) an Fotos in der integrierten Photos.app vornimmt unter iOS , werden die Änderungen nicht auf die fullResolutionImagevom entsprechenden Änderungen angewendet ALAssetRepresentation.

Die Änderungen werden jedoch auf die thumbnailund die fullScreenImagevon der zurückgegeben ALAssetRepresentation. Informationen zu den vorgenommenen Änderungen finden Sie imALAssetRepresentation Metadatenwörterbuch des Schlüssels @"AdjustmentXMP".

Ich möchte diese Änderungen auf fullResolutionImagemich selbst anwenden , um die Konsistenz zu bewahren. Ich habe herausgefunden, dass auf iOS6 + CIFilter ‚s filterArrayFromSerializedXMP: inputImageExtent:error:kann diese XMP-Metadaten in ein Array von konvertieren 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];
}

Dies funktioniert jedoch nur für einige Filter (Zuschneiden, automatische Verbesserung), nicht jedoch für andere wie das Entfernen roter Augen. In diesen Fällen ist dieCIFilter s keine sichtbare Wirkung. Daher meine Fragen:

  • Ist jemandem eine Möglichkeit bekannt, rote Augen zu entfernen? CIFilter ? (In einer Weise, die mit der Photos.app übereinstimmt. Der Filter mit dem Schlüssel kCIImageAutoAdjustRedEyereicht nicht aus. ZB werden keine Parameter für die Position der Augen verwendet.)
  • Gibt es eine Möglichkeit, diese Filter unter iOS 5 zu generieren und anzuwenden?
andreas
quelle
Dieser Link führt zu einer anderen Stackoverflow-Frage, die einen Algorithmus für rote Augen bereitstellt. Es ist nicht viel, aber es ist ein Anfang. stackoverflow.com/questions/133675/red-eye-reduction-algorithm
Roecrew
Unter iOS 7 wendet der aufgelistete Code den Filter zum Entfernen roter Augen (interner Filter CIRedEyeCorrections) korrekt an.
Paiv

Antworten:

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
quelle