Сохранение PHAsset с CIGaussianBlur и CIAffineClamp
Прежде всего, я спросил моего старшего и даже нашего начальника в офисе, но они не отвечают на мой вопрос. - КАК СОХРАНИТЬ ФАСЕТ С ДВУМ ФИЛЬТРАМИ, ПРИМЕНЯЕМЫМИ В ТО ЖЕ ВРЕМЯ?
У меня есть проект, который использует PHAssets для редактирования метаданных активов (фото / видео). Теперь я могу изменять изображения, применяя теги и фильтры. Смотрите этот пример: http://dev.classmethod.jp/references/ios8-photo-kit-4/
Недавно у меня была проблема с дополнительной границей, сгенерированной CIGaussianBlur, и я узнал, что мне нужен фильтр CIAffineClamp для решения проблемы: CIGaussianBlur и CIAffineClamp на iOS 6
К сожалению, я не знаю, как сохранить PHAsset или изменить PHAsset, когда есть два фильтра, которые мне нужно применить. Вот мой код в применении двух фильтров:
// G: If Blur, then adjust first the frame before applying blur!
if ([filterName isEqualToString:@"CIGaussianBlur"])
{
[filter setValue:inputImageForFilter forKey:@"inputImage"];
CGFloat blurLevel = 20.0f;
[filter setValue:[NSNumber numberWithFloat:blurLevel] forKey:@"inputRadius"];
CIImage* filterInputImage = [CIImage imageWithCGImage:originalImage.CGImage];
CIFilter* filter = [CIFilter filterWithName:filterName];
CIFilter *clampFilter = [CIFilter filterWithName:@"CIAffineClamp"];
[clampFilter setDefaults];
[clampFilter setValue:filterInputImage forKey:kCIInputImageKey];
[filter setValue:clampFilter.outputImage forKey:kCIInputImageKey];
[filter setValue:@10.0f forKey:@"inputRadius"];
CIImage* filterOutputImage = [filter valueForKey:kCIOutputImageKey];
CGImageRef createdImage = [context createCGImage:filterOutputImage fromRect:[filterInputImage extent]];
UIImage* outputImage = [UIImage imageWithCGImage:createdImage];
dispatch_async(dispatch_get_main_queue(), ^{
strongSelf.capturedImageView.image = outputImage;
strongSelf.capturedImageView.contentMode = UIViewContentModeScaleAspectFit;
[strongSelf.capturedImageView layoutSubviews];
});
strongSelf.appliedFilter.filterName = filterName;
strongSelf.appliedFilter.editingInput = contentEditingInput;
strongSelf.appliedFilter.outputImage = filterOutputImage;
CGImageRelease(createdImage);
createdImage = nil;
}
А вот мой код в сохранении данных:
- (void)doneButtonAction:(id)sender
{
// G: Handle Nil FilterName for Fixing Crash :)
if (self.appliedFilter.filterName == nil) {
// G: just pop to the view controller next to root, which is the Camera View Controller in Photo Mode.
[self.navigationController popToViewController:self.navigationController.viewControllers[1] animated:YES];
}
else{
// Create a PHAdjustmentData object that describes the filter that was applied.
PHAdjustmentData *adjustmentData = [[PHAdjustmentData alloc] initWithFormatIdentifier:AdjustmentFormatIdentifier formatVersion:@"1.0" data:[self.appliedFilter.filterName dataUsingEncoding:NSUTF8StringEncoding]];
PHAdjustmentData *affineClamp = [[PHAdjustmentData alloc] initWithFormatIdentifier:AdjustmentFormatIdentifier formatVersion:@"1.0" data:[@"CIAffineClamp" dataUsingEncoding:NSUTF8StringEncoding]];
/*
Create a PHContentEditingOutput object and write a JPEG representation
of the filtered object to the renderedContentURL.
*/
PHContentEditingOutput *contentEditingOutput = [[PHContentEditingOutput alloc] initWithContentEditingInput:self.appliedFilter.editingInput];
NSData *jpegData = [self.appliedFilter.outputImage aapl_jpegRepresentationWithCompressionQuality:0.9f];
[jpegData writeToURL:[contentEditingOutput renderedContentURL] atomically:YES];
[contentEditingOutput setAdjustmentData:adjustmentData];
if ([self.appliedFilter.filterName isEqualToString:@"CIGaussianBlur"]) {
[contentEditingOutput setAdjustmentData:affineClamp];
}
// Ask the shared PHPhotoLinrary to perform the changes.
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *request = [PHAssetChangeRequest changeRequestForAsset:self.photo.asset];
request.contentEditingOutput = contentEditingOutput;
} completionHandler:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"Error: %@", error);
}
}];
// G: just pop to the view controller next to root, which is the Camera View Controller in Photo Mode.
[self.navigationController popToViewController:self.navigationController.viewControllers[1] animated:YES];
}
}
Опять же, сохранение кода части данных работает очень хорошо, если у меня есть только 1 фильтр для применения. Итак, еще раз, моя проблема заключается в том, как настроить данные, когда нужно применить два фильтра. Огромное спасибо. Я считаю, что мой вопрос так ясен.;) Ждем ваших ответов.
1 ответ
Прежде всего, я не знаю, как вы можете переопределить фильтр * без получения ошибки (сначала он должен быть объявлен вне вашей структуры управления, а затем вы переопределите его внутри).
Вот простая процедура, которая применит ваше размытие и вернет изображение с искомыми экстентами.
- (CIImage*)blurImage:(CIImage*)sourceImage withRadius:(NSNumber*)blurRadius {
CGRect originalExtent = sourceImage.extent;
CIImage *clampedImaged = [sourceImage imageByClampingToExtent];
CIImage *blurredImage = [clampedImaged imageByApplyingFilter:@"CIGaussianBlur" withInputParameters:@{@"inputRadius" : blurRadius}];
return [blurredImage imageByCroppingToRect:originalExtent];
}
В противном случае, я не могу сказать вам, на что ссылаются originalImage или inputImageForFilter, поэтому трудно предположить, где находится зависание. Вы можете отлаживать эту строку построчно и использовать функцию взгляда Xcode (значок глазного яблока), чтобы убедиться, что объекты CIImage, генерируемые из каждого фильтра, соответствуют вашим ожиданиям.