Сохранение PHAsset с помощью CIGaussianBlur и CIAffineClamp

Прежде всего, я спросил своего старшего и даже нашего начальника в офисе, но они не отвечают на мой вопрос. - КАК СОХРАНИТЬ PHASSET С ДВУМЯ ФИЛЬТРАМИ, ПРИМЕНЯЕМЫМИ ОДНОВРЕМЕННО?

У меня есть проект, который использует 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 фильтр для применения. Итак, опять же, моя проблема заключается в том, как настроить данные, когда нужно применить два фильтра. Большое спасибо. Я считаю, что мой вопрос настолько ясен. ;) Ждем ваших ответов.


person Glenn Posadas    schedule 31.03.2016    source источник


Ответы (1)


Во-первых, я не знаю, как можно повторно объявить *filter, не получая при этом ошибки (сначала его нужно объявить вне вашей управляющей структуры, а затем вы повторно объявите его внутри).

Вот простая процедура, которая применит ваше размытие и вернет изображение с нужными вам размерами.

- (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, генерируемые каждым фильтром, соответствуют вашим ожиданиям.

person joelg    schedule 31.03.2016
comment
Спасибо за ответ. Да, я сделал ошибку, создав новый объект CIFilter. В любом случае, я хочу знать, как сохранить изображение как PHAsset. - person Glenn Posadas; 31.03.2016
comment
Итак, где ломается ваша процедура сохранения? - person joelg; 31.03.2016
comment
Часть сохранения находится в моем методе doneButtonAction. Как я уже сказал, этот метод отлично работает, когда я применяю только 1 фильтр за раз. Например: Постеризовать фильтр. Он подсказывает пользователю, хочет ли он ИЗМЕНИТЬ фотографию при вызове этого метода. Однако, когда я применяю размытие с помощью CIAffineClamp, это выдает мне эту ошибку в обработчике завершения: — Error Domain=NSCocoaErrorDomain Code=-1 (null) - person Glenn Posadas; 01.04.2016
comment
Вероятно, это не имеет ничего общего с вашей процедурой сохранения и больше связано с тем, как вы используете свои фильтры. Я имею в виду, соедините вместе два простых фильтра (например, CIColorControls и CIColorInvert) и посмотрите, что произойдет. - person joelg; 01.04.2016