2012年8月8日 星期三

Filter4Cam 實作: 27. 選擇濾鏡之二

since: 2012/08/08
update: 2013/04/18


套用個別濾鏡

A. 建立濾鏡類別

     1. 基底濾鏡(用來讓其它濾鏡類別繼承使用)
         a. Xcode > File > New > File...
             iOS > Cocoa Touch > Objective-C class > Next
            Class: FilterBase
            Subclass of: NSObject
            > Next
            Targets: Filter4Cam
            > Create

         b. 開啟 FilterBase.h 檔案, 修改如下:
#import <Foundation/Foundation.h>

@interface FilterBase : NSObject
{
   
}

//@add for apply Filter
- (CIImage *)filterImage:(CIImage *)sourceImage;

//@add for debug use
- (void)showAllFilters; // 顯示內建可用的所有濾鏡名稱
- (void)showCategoryFilters:(NSString *)categoryName; // 顯示特定分類的濾鏡名稱
- (void)showFilterAttributes:(NSString *)filterName; // 顯示特定濾鏡的屬性

@end

         c. 開啟 FilterBase.m 檔案, 修改如下:
#import "FilterBase.h"

@implementation FilterBase

//@add for apply Filter
- (CIImage *)filterImage:(CIImage *)sourceImage
{
    return sourceImage; // just return the source
}

// 顯示內建可用的所有濾鏡名稱
- (void)showAllFilters
{
    NSArray *properties = [CIFilter filterNamesInCategory:kCICategoryBuiltIn];
    NSLog(@"\n AllFilters = \n %@", properties);
}

// 顯示特定分類的濾鏡名稱
- (void)showCategoryFilters:(NSString *)categoryName
{
    NSArray *properties = [CIFilter filterNamesInCategory:categoryName];
    NSLog(@"\n %@ Category: \n %@", categoryName, properties);
}

// 顯示特定濾鏡的屬性
- (void)showFilterAttributes:(NSString *)filterName
{
    CIFilter *filter = [CIFilter filterWithName:filterName];
    NSLog(@"\n %@ Filter: \n %@", filterName, [filter attributes]);
}

@end

*************************************************

     2. 墨魚濾鏡(復古風格)
          a. Xcode > File > New > File...
              iOS > Cocoa Touch > Objective-C class > Next

             Class: SepiaFilter
             Subclass of: NSObject
             > Next

            Targets: Filter4Cam

             > Create

          b. 開啟 SepiaFilter.h 檔案, 修改如下:
#import <Foundation/Foundation.h>

//@add
#import "FilterBase.h"

//@interface SepiaFilter : NSObject
//@update: 墨魚濾鏡
@interface SepiaFilter : FilterBase
{
   
}

@end

          c. 開啟 SepiaFilter.m 檔案, 修改如下:
#import "SepiaFilter.h"

@implementation SepiaFilter

//@add for apply Filter
- (CIImage *)filterImage:(CIImage *)sourceImage
{
    CIFilter *coreImageFilter = [CIFilter filterWithName:@"CISepiaTone"];

    [coreImageFilter setValue:sourceImage forKey:kCIInputImageKey];

    [coreImageFilter setValue:[NSNumber numberWithFloat:0.8] forKey:@"inputIntensity"];
   
    return [coreImageFilter outputImage];
}

//@add
- (id)init
{
    if (self = [super init]) {
        //[self showAllFilters];
       
        //[self showCategoryFilters:kCICategoryColorEffect];
        //[self showCategoryFilters:kCICategoryColorAdjustment];
        //[self showCategoryFilters:kCICategoryGenerator];
        //[self showCategoryFilters:kCICategoryStylize];
       
        //[self showFilterAttributes:@"CISepiaTone"];
       
        /*
        CISepiaTone Filter:
        {
            CIAttributeFilterCategories =     (
                                               CICategoryColorEffect,
                                               CICategoryVideo,
                                               CICategoryInterlaced,
                                               CICategoryNonSquarePixels,
                                               CICategoryStillImage,
                                               CICategoryBuiltIn
                                               );
            CIAttributeFilterDisplayName = "Sepia Tone";
            CIAttributeFilterName = CISepiaTone;
            inputImage =     {
                CIAttributeClass = CIImage;
                CIAttributeType = CIAttributeTypeImage;
            };
            inputIntensity =     {
                CIAttributeClass = NSNumber;
                CIAttributeDefault = 1;
                CIAttributeIdentity = 0;
                CIAttributeMax = 1;
                CIAttributeMin = 0;
                CIAttributeSliderMax = 1;
                CIAttributeSliderMin = 0;
                CIAttributeType = CIAttributeTypeScalar;
            };
        }
        */
    }
   
    return self;
}

@end

*************************************************

     3. 假色濾鏡(將圖片的內容對應到二種顏色)
          a. Xcode > File > New > File...
              iOS > Cocoa Touch > Objective-C class > Next

             Class: FalseFilter
             Subclass of: NSObject
             > Next

            Targets: Filter4Cam

             > Create

          b. 開啟 FalseFilter.h 檔案, 修改如下:
#import <Foundation/Foundation.h>


//@add
#import "FilterBase.h"

//@interface FalseFilter : NSObject
//@update: 假色濾鏡
@interface FalseFilter : FilterBase
{
  
}

@end

          c. 開啟 FalseFilter.m 檔案, 修改如下:
#import "FalseFilter.h"

@implementation FalseFilter

//@add for apply Filter
- (CIImage *)filterImage:(CIImage *)sourceImage
{
    // 假色濾鏡(False Color filter), 將圖片的內容對應到二種顏色.   
    CIFilter *coreImageFilter = [CIFilter filterWithName:@"CIFalseColor"];
    [coreImageFilter setValue:sourceImage forKey:kCIInputImageKey];

    [coreImageFilter setValue:[CIColor colorWithRed:0.145 green:0.016 blue:0.308] forKey:@"inputColor0"];

    [coreImageFilter setValue:[CIColor colorWithRed:0.972 green:0.912 blue:0.762] forKey:@"inputColor1"];
   
    return [coreImageFilter outputImage];
}

//@add
- (id)init
{
    if (self = [super init]) {
        //[self showFilterAttributes:@"CIFalseColor"];
       
        /*
        CIFalseColor Filter:
        {
            CIAttributeFilterCategories =     (
                                               CICategoryColorEffect,
                                               CICategoryVideo,
                                               CICategoryInterlaced,
                                               CICategoryNonSquarePixels,
                                               CICategoryStillImage,
                                               CICategoryBuiltIn
                                               );
            CIAttributeFilterDisplayName = "False Color";
            CIAttributeFilterName = CIFalseColor;
            inputColor0 =     {
                CIAttributeClass = CIColor;
                CIAttributeDefault = "(0.3 0 0 1)";
                CIAttributeType = CIAttributeTypeColor;
            };
            inputColor1 =     {
                CIAttributeClass = CIColor;
                CIAttributeDefault = "(1 0.9 0.8 1)";
                CIAttributeType = CIAttributeTypeColor;
            };
            inputImage =     {
                CIAttributeClass = CIImage;
                CIAttributeType = CIAttributeTypeImage;
            };
        }
        */
    }
   
    return self;
}

@end

*************************************************

     4. 顏色調節濾鏡(調整顏色的: 飽和, 對比與亮度)
          a. Xcode > File > New > File...
              iOS > Cocoa Touch > Objective-C class > Next

             Class: ColorFilter
             Subclass of: NSObject
             > Next

            Targets: Filter4Cam

             > Create

          b. 開啟 ColorFilter.h 檔案, 修改如下:
#import <Foundation/Foundation.h>

//@add
#import "FilterBase.h"

//@interface ColorFilter : NSObject
//@update: 顏色調節濾鏡
@interface ColorFilter : FilterBase
{
   
}

@end

          c. 開啟 ColorFilter.m 檔案, 修改如下:

#import "ColorFilter.h"

@implementation ColorFilter

//@add for apply Filter
- (CIImage *)filterImage:(CIImage *)sourceImage
{
    // 顏色調節濾鏡(調整顏色的: 飽和, 對比與亮度)
    CIFilter *coreImageFilter = [CIFilter filterWithName:@"CIColorControls"];
    [coreImageFilter setValue:sourceImage forKey:kCIInputImageKey];
   
    // 亮度: -1~1 (default:0)
    [coreImageFilter setValue:[NSNumber numberWithFloat:0.0] forKey:@"inputBrightness"];
   
    // 對比度: 0~4 (default:1)
    [coreImageFilter setValue:[NSNumber numberWithFloat:1.8] forKey:@"inputContrast"];
   
    // 飽和度: 0~2 (default:1)
    [coreImageFilter setValue:[NSNumber numberWithFloat:1.6] forKey:@"inputSaturation"];
   
    return [coreImageFilter outputImage];
}

//@add
- (id)init
{
    if (self = [super init]) {
        //[self showFilterAttributes:@"CIColorControls"];
       
        /*
        CIColorControls Filter:
        {
            CIAttributeFilterCategories =     (
                                               CICategoryColorAdjustment,
                                               CICategoryVideo,
                                               CICategoryStillImage,
                                               CICategoryInterlaced,
                                               CICategoryNonSquarePixels,
                                               CICategoryBuiltIn
                                               );
            CIAttributeFilterDisplayName = "Color Controls";
            CIAttributeFilterName = CIColorControls;
            inputBrightness =     {
                CIAttributeClass = NSNumber;
                CIAttributeDefault = 0;
                CIAttributeIdentity = 0;
                CIAttributeSliderMax = 1;
                CIAttributeSliderMin = "-1";
                CIAttributeType = CIAttributeTypeScalar;
            };
            inputContrast =     {
                CIAttributeClass = NSNumber;
                CIAttributeDefault = 1;
                CIAttributeIdentity = 1;
                CIAttributeSliderMax = 4;
                CIAttributeSliderMin = 0;
                CIAttributeType = CIAttributeTypeScalar;
            };
            inputImage =     {
                CIAttributeClass = CIImage;
                CIAttributeType = CIAttributeTypeImage;
            };
            inputSaturation =     {
                CIAttributeClass = NSNumber;
                CIAttributeDefault = 1;
                CIAttributeIdentity = 1;
                CIAttributeSliderMax = 2;
                CIAttributeSliderMin = 0;
                CIAttributeType = CIAttributeTypeScalar;
            };
        }
        */
    }
   
    return self;
}

@end

*************************************************

     5. 複合濾鏡(在此為: "假色濾鏡" 與 "顏色調節濾鏡")
          a. Xcode > File > New > File...
              iOS > Cocoa Touch > Objective-C class > Next

             Class: ComboFilter
             Subclass of: NSObject
             > Next

            Targets: Filter4Cam

             > Create

          b. 開啟 ComboFilter.h 檔案, 修改如下:
#import <Foundation/Foundation.h>

//@add
#import "FilterBase.h"

//@interface ComboFilter : NSObject
//@update: 複合濾鏡
@interface ComboFilter : FilterBase
{
   
}

@end

          c. 開啟 ComboFilter.m 檔案, 修改如下:
#import "ComboFilter.h"


@implementation ComboFilter

//@add
- (CIImage *)filterImage:(CIImage *)sourceImage
{
    // 複合濾鏡 (在此為: "假色濾鏡" 與 "顏色調節濾鏡")
   
    /* 假色濾鏡 */
    CIFilter *coreImageFilter1 = [CIFilter filterWithName:@"CIFalseColor"];

    [coreImageFilter1 setValue:sourceImage forKey:kCIInputImageKey];

    [coreImageFilter1 setValue:[CIColor colorWithRed:0.145 green:0.016 blue:0.308] forKey:@"inputColor0"];

    [coreImageFilter1 setValue:[CIColor colorWithRed:0.972 green:0.912 blue:0.762] forKey:@"inputColor1"];
   
    /* 顏色調節濾鏡 */
    CIFilter *coreImageFilter2 = [CIFilter filterWithName:@"CIColorControls"];

    [coreImageFilter2 setValue:[coreImageFilter1 outputImage] forKey:kCIInputImageKey];
   
    // 亮度: -1~1 (default:0)
    [coreImageFilter2 setValue:[NSNumber numberWithFloat:0.0] forKey:@"inputBrightness"];
   
    // 對比度: 0~4 (default:1)
    [coreImageFilter2 setValue:[NSNumber numberWithFloat:1.8] forKey:@"inputContrast"];
   
    // 飽和度: 0~2 (default:1)
    [coreImageFilter2 setValue:[NSNumber numberWithFloat:1.6] forKey:@"inputSaturation"];
   
    return [coreImageFilter2 outputImage];
}

//@add
- (id)init
{
    if (self = [super init]) {
       
    }
   
    return self;
}

@end

-----------------------------------------------------------------------------

B. 儲存所有的濾鏡物件

     1. 開啟 GlobalDataClass.h 檔案, 修改如下:
#import <Foundation/Foundation.h>


//@add
#import "SepiaFilter.h"
#import "FalseFilter.h"
#import "ColorFilter.h"
#import "ComboFilter.h"

@interface GlobalDataClass : NSObject
{   
    //@add: array for storage filterCells
    NSMutableArray *filterCellArray;
    BOOL isUsingFilter;        // 有使用濾鏡?
    NSMutableString *filterID; // 濾鏡 ID
   
    //@add: 存放濾鏡物件的字典
    NSMutableDictionary *filterDictionary;
}

//@add
@property (nonatomic, strong) NSMutableArray *filterCellArray;
@property (assign) BOOL isUsingFilter;
@property (nonatomic, strong) NSMutableString *filterID;
@property (nonatomic, strong) NSMutableDictionary *filterDictionary;

//@add
+ (GlobalDataClass *)getInstance;

@end

     2. 開啟 GlobalDataClass.m 檔案, 修改如下:
....

//@add
@synthesize filterCellArray = _filterCellArray;
@synthesize isUsingFilter = _isUsingFilter;
@synthesize filterID = _filterID;
@synthesize filterDictionary = _filterDictionary;
....
//@add
- (NSMutableDictionary *)filterDictionary
{
    if (_filterDictionary == nil) {
        _filterDictionary = [[NSMutableDictionary alloc] init];
        [_filterDictionary setObject:[SepiaFilter new] forKey:@"filter0"];
        [_filterDictionary setObject:[FalseFilter new] forKey:@"filter1"];
        [_filterDictionary setObject:[ColorFilter new] forKey:@"filter2"];
        [_filterDictionary setObject:[ComboFilter new] forKey:@"filter3"];
    }
   
    return _filterDictionary;
}
....

-----------------------------------------------------------------------------

C. 濾鏡套用
     1. 開啟 ViewController.h 檔案, 修改如下:
....

@interface ViewController : GLKViewController <AVCaptureVideoDataOutputSampleBufferDelegate, UITableViewDelegate, UITableViewDataSource>
{
....
    GlobalDataClass *dataObj;
   
    // 目前使用的濾鏡物件
    FilterBase *currentFilter;
}
....
@property (nonatomic, strong) GlobalDataClass *dataObj;

@property (nonatomic, strong) FilterBase *currentFilter;
....//- (CIImage *)filterTest:(CIImage *)sourceImage;
....

     2. 開啟 ViewController.m 檔案, 修改如下:
....

// step 1:
@synthesize dataObj = _dataObj;
@synthesize currentFilter = _currentFilter;

....
// step 2:
//@add:filter Test
/*
- (CIImage *)filterTest:(CIImage *)sourceImage
{   
    self.coreImageFilter = [CIFilter filterWithName:@"CISepiaTone" keysAndValues:
                        kCIInputImageKey, sourceImage,
                        @"inputIntensity", [NSNumber numberWithFloat:0.8], nil];
   
    return [self.coreImageFilter outputImage];
}
*/

....
// step 3:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
....
    //@update
    if(self.dataObj.isUsingFilter == YES)
    {
        //@update: comment it
        /*
        // 濾鏡功能測試
        self.ciImage = [self filterTest:self.ciImage];
   
        // 畫出 "濾鏡範圍" 內的影像(含方向轉變的調整)
        [self drawFilteredImage:self.ciImage];
        */
       
        // check if key "filterID" exists:
        // objectForKey will return nil if a key doesn't exists.
        if (self.currentFilter = [self.dataObj.filterDictionary objectForKey:self.dataObj.filterID])
        // for Xcode: 4.6.2 update
        if ((self.currentFilter = [self.dataObj.filterDictionary objectForKey:self.dataObj.filterID]))

        {
            self.ciImage = [self.currentFilter filterImage:self.ciImage];
            [self drawFilteredImage:self.ciImage];
        }
    }
   
    // 最後, 在螢幕上呈現出來.
    [self.glContext presentRenderbuffer:GL_RENDERBUFFER];
}

....
// step 4:
- (void)viewDidUnload
{   
    [super viewDidUnload];
   
    //@add
    if ([EAGLContext currentContext] == self.glContext) {
        [EAGLContext setCurrentContext:nil];
    }
....
    self.dataObj = nil;
    self.currentFilter = nil;
}
....

-----------------------------------------------------------------------------

D. 編譯並執行:
     1. 未套用濾鏡:

     2. 套用 "墨魚濾鏡":

     3. 套用 "假色濾鏡":

     4. 套用 "顏色調節濾鏡":

     5. 套用 "複合濾鏡": ("假色濾鏡" 與 "顏色調節濾鏡")

沒有留言:

張貼留言

注意:只有此網誌的成員可以留言。