【问题标题】:Saving PHAsset with CIGaussianBlur and CIAffineClamp使用 CIGaussianBlur 和 CIAffineClamp 保存 PHAsset
【发布时间】:2016-03-31 21:08:44
【问题描述】:

首先,我在办公室问了我的上司,甚至是我们的老板,但他们都没有回答我的问题。 - 如何保存同时应用两个过滤器的 PHASSET?

我有一个项目使用 PHAssets 来编辑资产(照片/视频)的元数据。现在,我可以通过应用标签和过滤器来修改图像。看这个例子:http://dev.classmethod.jp/references/ios8-photo-kit-4/

我最近遇到了一个由 CIGaussianBlur 生成的额外边框的问题,我了解到我必须使用 CIAffineClamp 过滤器来解决这个问题:CIGaussianBlur and CIAffineClamp on 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 个过滤器,则保存数据部分代码的效果非常好。再说一次,我的问题是当有两个过滤器要应用时如何调整数据。太感谢了。我相信我的问题很清楚。 ;) 期待您的回答。

【问题讨论】:

    标签: ios objective-c cifilter phasset


    【解决方案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 的 peek 功能(眼球图标)来确保每个过滤器生成的 CIImage 对象都是您所期望的。

    【讨论】:

    • 感谢您的回答。是的,我犯了一个错误,创建了一个新的 CIFilter 对象。无论如何,我想知道的是如何将图像保存为 PHAsset。
    • 好的,那么你的存档在哪里出了问题?
    • 保存部分在我的 doneButtonAction 方法中。就像我所说的那样,当我一次只应用 1 个过滤器时,该方法可以正常工作。例如:分离过滤器。它会在调用该方法时提示用户是否要修改照片。但是,当我使用 CIAffineClamp 应用模糊时,它在完成处理程序中给了我这个错误: — Error Domain=NSCocoaErrorDomain Code=-1 "(null)"
    • 这可能与您的保存程序无关,更多地与您使用过滤器的方式有关。我的意思是,将两个简单的过滤器链接在一起(如 CIColorControls 和 CIColorInvert),看看会发生什么。
    猜你喜欢
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-12
    • 1970-01-01
    相关资源
    最近更新 更多