Tafsirkan XMP-Metadata di ALAssetRepresentation

95

Saat pengguna membuat beberapa perubahan (memotong, menghilangkan mata merah, ...) pada foto di aplikasi Photos.app di iOS, perubahan tidak diterapkan ke yang fullResolutionImagedikembalikan oleh yang sesuai ALAssetRepresentation.

Namun, perubahan diterapkan ke thumbnaildan fullScreenImagedikembalikan oleh ALAssetRepresentation. Lebih lanjut, informasi tentang perubahan yang diterapkan dapat ditemukan di ALAssetRepresentationkamus metadata melalui kunci @"AdjustmentXMP".

Saya ingin menerapkan perubahan ini pada fullResolutionImagediri saya sendiri untuk menjaga konsistensi. Saya telah menemukan bahwa pada iOS6 + CIFilter 's filterArrayFromSerializedXMP: inputImageExtent:error:dapat mengkonversi ini XMP-metadata ke array 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];
}

Namun, ini hanya berfungsi untuk beberapa filter (memotong, menyempurnakan otomatis), tetapi tidak untuk filter lain seperti penghilangan mata merah. Dalam kasus ini, CIFilters tidak memiliki efek yang terlihat. Karena itu, pertanyaan saya:

  • Adakah yang tahu cara membuat penghilang mata merah CIFilter? (Dalam cara yang konsisten dengan Photos.app. Filter dengan kunci kCIImageAutoAdjustRedEyetidak cukup. Misalnya, tidak mengambil parameter untuk posisi mata.)
  • Apakah ada kemungkinan untuk membuat dan menerapkan filter ini di iOS 5?
andreas
sumber
Tautan ini ke pertanyaan Stackoverflow lain yang menyediakan algoritme untuk mata merah. Ini tidak banyak tapi ini sebuah permulaan. stackoverflow.com/questions/133675/red-eye-reduction-algorithm
Roecrew
Di iOS 7, kode yang terdaftar dengan benar menerapkan filter penghilang mata merah (filter internal CIRedEyeCorrections).
paiv

Jawaban:

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
sumber