2012年8月18日 星期六

Running OpenGL on Linux Mint - 3

since: 2012/08/18
update: 2012/09/06

reference:
1. OpenGL Video Tutorial - Getting OpenGL Set Up on Linux
2. Howto Install OpenGL Development Environment
3. Computing Reference Wikispace - geany_settings
4. GLEW: The OpenGL Extension Wrangler Library

開發環境設定與繪圖測試

A. 檢查 OpenGL 與 GLUT 開發函式庫
     1. 說明:
          要讓 OpenGL 在 Linux 上正常運作, 至少要在檔案中找到 gl.hglut.h 檔案,
          它們通常位於 /usr/include/GL/ 目錄下.

     2. 檢查:
         $ cd /usr/include/GL/
         $ ls

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

B. 安裝 IDE(整合開發環境)
     1. Menu > Software Manager

     2. > Programming

     3. > geany

     4. > Install

     5. 備註:
         或直接執行
         $ sudo apt-get install geany

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

C. 開發環境設定與繪圖測試
     1. 開啟 Geany
         Menu > All applications (選單右上方)
         > Programming > Geany

     2. 查看/設定 專案的檔案目錄
          Edit > Preferences
         General > Startup > Project files:
         /home/lanli/projects

     3. 建立專案目錄:
         $ cd ~
         $ mkdir projects

     4. 新增 OpenGL 測試檔案
         開啓新檔案, 寫入以下程式碼, 存檔至 /home/lanli/projects/teapot.c
#include <GL/glut.h>

void init();
void display();

int main(int argc, char* argv[])
{
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
 glutInitWindowPosition(0, 0);
 glutInitWindowSize(300, 300);
 
 glutCreateWindow("OpenGL 3D View");
 
 init();
 glutDisplayFunc(display);
 
 glutMainLoop();

 return 0;
}

void init()
{
 glClearColor(0.0, 0.0, 0.0, 0.0);
 glMatrixMode(GL_PROJECTION);
 glOrtho(-5, 5, -5, 5, 5, 15);
 glMatrixMode(GL_MODELVIEW);
 gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
}

void display()
{
 glClear(GL_COLOR_BUFFER_BIT);
  
 glColor3f(1.0, 0, 0);
 glutWireTeapot(3);
 
 glFlush();
}

     5. 查看編譯設定
         Build > Set Build Commands

         (update: 2012/08/22)
     6. 調整編譯設定
         a. Build 的 Command 改成:
             gcc -Wall -o "%e.o" "%f" -lglut -lGL -lGLU -lSDL // -lSDL 非必要

         b.Execute 的 Command 改成: "./%e.o"        // 添加 .o

     7. 編譯並執行
         a. Build > Build
         b. Build > Execute

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

D. 使用 GLEW 的方式: (update: 2012/08/30)
     1. 說明:
         a. 調整編譯設定:
             將 Build 的 Command 改成: 
             gcc -Wall -o "%e.o" "%f" -lglut -lGLEW -lGL -lGLU

         b. 如果 GLEW 要跟 GLUT 一起使用的話, 必須要先 include glew.h, 然後才
     
include glut.h, 並且 glew.h 已經有 include glu.h 了.

         c. GLEW 的初始化必須要在全部的 glutInitxxx 及  glutCreateWindow 之後進行.
             (可以在註冊 callback functions 動作之前)

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

     2. 將 teapot.c 修改如下:
#include <stdio.h>
#include <stdlib.h>
#include <GL/glew.h>
#include <GL/glut.h>

void init();
void display();
void initGlew();

int main(int argc, char* argv[])
{
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
 glutInitWindowPosition(0, 0);
 glutInitWindowSize(300, 300);
 
 glutCreateWindow("OpenGL 3D View"); 
 initGlew();
 init();
 glutDisplayFunc(display);
 
 glutMainLoop();

 return 0;
}

void init()
{
 glClearColor(0.0, 0.0, 0.0, 0.0);
 glMatrixMode(GL_PROJECTION);
 glOrtho(-5, 5, -5, 5, 5, 15);
 glMatrixMode(GL_MODELVIEW);
 gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
}

void display()
{
 glClear(GL_COLOR_BUFFER_BIT);
  
 glColor3f(1.0, 0, 0);
 glutWireTeapot(3);
 
 glFlush();
}

void initGlew()
{
    GLenum err = glewInit();
   
    if(err !=  GLEW_OK)
    {
        fprintf(stderr, "glewInitError\n");
        exit(1);
    }
   
    fprintf(stderr, "GLEW initialized OK\n");
    fprintf(stderr, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));
}


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

     3. 編譯並執行
         a. Build > Build
         b. Build > Execute

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

E. 備註: (update: 2012/09/06)
     1. 後來在 geany 下使用 extern 變數時, 會造成編譯失敗的情況.
         ....
         extern void checkGLErrors(const char* caller);
         ....
         checkGLErrors("main here");
         ....

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

         main.c:(.text+0x70): undefined reference to `checkGLErrors'

         編譯失敗


     2. 試過安裝 codeblocks 來建立 OpenGL 專案, 編譯時也會出問題
         (可能是我不太熟  codeblocks). 

     3. 所以, 之後會改用 eclipse 來開發 OpenGL. 

2012年8月16日 星期四

Running OpenGL on Linux Mint - 2

since: 2012/08/15
update: 2012/08/29

reference:
1. Install Linux Mint 12 (Lisa) on 13inch MacBook Air
2. Things To Do after installing Linux Mint 13 (Maya)
3. How to quickly Install NVIDIA R302.11 Drivers Under Linux Mint 13
4. SDL, OpenGL, GLSL on the Mac and Linux
5. Linux 的3D加速--DRI
6. GLEW: The OpenGL Extension Wrangler Library
7. How to: Build GLEW on Debian

Update NVIDIA Graphics Drivers

A. 查詢系統目前資訊
      Menu > Terminal

     1. kernel 版本:
         $ uname -r
         3.2.0-23-generic

     2. 檔案系統的磁碟使用情況:
         $ df -h

     3. 記憶體使用情況:
          $ free -m

     4. 支援的 OpenGL 版本:
          $ glxinfo | grep "OpenGL version"

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

B. 更新軟體套件
      1. 更新系統軟體:
          $ sudo apt-get update
          $ sudo apt-get upgrade
          (備註: 亦可執行桌面右下方的 "Update Manager" 來更新套件)

      2. 安裝一般常用的工具:
          $ sudo apt-get install ubuntu-restricted-extras

          (update: 2012/08/24)
      3. 安裝其它軟體: (依個人需求而異)
          $ sudo apt-get install virtualbox // VirtualBox         
          $ sudo apt-get install gcin // 中文輸入法
          $ sudo apt-get install k3b // 燒錄軟體
          $ sudo apt-get install mercurial // 版本控制

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

C. 安裝 OpenGL 與相關開發套件
      1. 基本編譯環境
          $ sudo apt-get install build-essential

      2. OpenGL Library, Utility, Toolkit
          $ sudo apt-get install freeglut3
          $ sudo apt-get install freeglut3-dev

         
(update: 2012/08/29)
          $ sudo apt-get install libglew-dev // GLEW
             說明: 目前最新的 GLEW 版本為 1.9.0 已支援 OpenGL 4.3,
                       由於在此使用 apt 安裝, 因此版本為 1.6 支援 OpenGL 4.1.

          // GLEW build pre-req’s
          $ sudo apt-get install libxmu-headers libxmu-dev libxi-dev
          $ sudo apt-get install glew-utils // glewinfo

          $ glewinfo | grep "GLEW version"
         備註: 移除方式 (試過用編譯的方式, 版本仍未更新, 所以將其移除再安裝)
                   $ sudo apt-get --purge remove libglew1.6
                   $ sudo apt-get --purge remove glew-utils

      3. 其它 (update: 2012/08/18)
          $ sudo apt-get install libsdl-dev  // Simple Directmedia Layer

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

D. 更新 NVIDIA 顯卡驅動程式
      1. 下載:
           這邊直接下載對 OpenGL 4.3 提供 beta support 的版本來試試:
           OpenGL Driver Support ,
           檔名為: NVIDIA-Linux-x86_64-304.15.00.02.run

      2. 確認下載位置:
          $ cd ~/Downloads
          $ ls -al

      3. 進入第一個虛擬終端機:
           Ctrl + Alt + F1

      4. 檢查 Mint Display Manager(mdm) 的 process:
          $ ps aux | grep mdm

      5. 終止 Mint Display Manager 的行程:
           $ sudo killall mdm
           $ ps aux | grep mdm
           說明: 已經沒有 owner 為 rootmdm 相關行程.

      6. 開始安裝 Driver:
           $ cd ~/Downloads
           $ sudo sh NVIDIA-Linux-x86_64-304.15.00.02.run

          說明: a. 利用 Tab 鍵來切換選項. (切到 "Accept" 或 "YES")
                    b. 第一次安裝可能會失敗, 重新開機, 再從步驟 3 開始.
                    c. Install NVIDIA's 32-bit compatibility OpenGL libraries? YES

           $ sudo reboot

      7. 檢查目前所支援的 OpenGL 版本:
           $ glxinfo | grep "OpenGL version"

      8. 查看 NVIDIA Driver 狀況:
           $ nvidia-settings


2012年8月15日 星期三

Running OpenGL on Linux Mint - 1

since: 2012/08/15
update: 2012/08/21

reference:
Install Linux Mint 12 (Lisa) on 13inch MacBook Air


Install Linux Mint

A. 說明:
     1. 最新的 OpenGL 4.3 規格已在8月6日釋出, 詳見: Khronos Releases OpenGL 4.3.
         硬體方面, 許多顯卡的規格都是超前在軟體的支援前已準備好的; 軟體方面,
         部分顯卡晶片製造商也提供了對 4.3 版的 beta 支援供使用者下載, 如:
         NVIDIA OpenGL 4.3 Driver, 但是只有 WindowsLinux 的版本.

     2. Apple 對於 OpenGL 軟體的支援, 即使硬體方面(顯卡)都已支援到 4.2, 軟體方面
         仍然只支援到 3.2. 因此如果想使用 OpenGL 3.3 以上的版本, 就必須在 Windows
         或 Linux 平台上. (我選擇了 Linux)
         參考: 1. Mac OpenGL capabilities | RenderingPipeline
                   2. Mac OS X 10.8 Core Profile OpenGL Info

     3. 關於 Linux 版本, 將會使用 Linux Mint (Linux Mint - 维基百科), 主要是基於方便
         與友善的考量. 目前的版本為 Linux Mint 13 Maya, 在此下載了桌面環境為 MATE
         的 64 位元版本, 並燒錄成開機安裝光碟片.
        
     4. 硬體環境: (不是在我的 MBP 上, 是另一台 PC)
          Mother Board: P35-DS3
          CPU: Intel Core 2 Duo E6750 2.66GHZ
          RAM: 8GB
          HD: WDC SATA 250GB
          Display Card: Geforce GTX 560 Ti (Memory: 1GB)

     5. 安裝方式:
         由於安裝好 Linux 後, 需要再更新顯卡的驅動程式, 來提升對 OpenGL 的版本支援,
         因此在此採用完全的乾淨安裝方式, 來讓安裝的過程更加順利.
         備註: 其它裝方式, 還有: "安裝在 VM" 與 "製作多重開機系統".

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

B. 安裝 Linux Mint
     1. 從 BIOS 將 CD-ROM 調整為開機的第一順位, 將 "Linux Mint 13" 開機片放入
         光碟機, 重新開機.

     2. 載入桌面完成後, 用滑鼠雙擊 "Install Linux Mint" 開始進行安裝設定.
         (備註: Alt + PrintScreen 可截取螢幕圖片)

     3. 選擇在安裝過程中, 所使用的語言:
          English > Continue
          (update: 2012/08/21)
          為了讓之後的 "中文輸入" 順利執行, 改成:
          中文(繁體) > 繼續


     4. 硬體需求確認:
          a. 至少還有 5.9 GB 可用的磁碟空間
          b. 已經連接到網路
           > Continue

     5. 安裝類型:
          點選: Something else (可自行建立分割區, 或選擇多重分割區)
           > Continue

     6. 先利用 "Delete" 將所有分割區刪除.

     7. 磁碟分割區規劃:
         a. 說明:
             好幾年前, 我在安裝 Linux (RedHat, Fedora ....), 於分割磁區時, 都是先
             切出一塊 swap, 然後再切 / 分割區. 在此則先切 / 分割區, 再切 swap 區,
             比較不會不小心將 / 區切成 "邏輯磁碟", 而造成無法開機的情況.

         b. 磁碟空間規劃:
             磁碟總容量: 250 GB
             / 分割區: 240000 MB (約 234 GB)
             swap 區: 10999 MB (約 10.7 GB)

         c. 點選 "free space" 並按下 "Add".
             Mount point: /
             Type: Primary
             partition size: 240000 (MB)
             Use as: Ext4 journaling file system
              > OK

         d. 再次點選 "free space" 並按下 "Add".
             Use as: swap area
             Type: Primary
             partition size: 10998 (MB)
              > OK

         e. 在 Mount point 為 / 的分割區, 將 Format? 勾選起來,
             並於最下方的 "Device for boot loader installation" 選擇 Mount point
             為 / 的分割區, 在此為: /dev/sda1
              > Install Now

     8. 開始安裝:
         a. 選擇地區:
             Taipei > Continue

         b. 選擇鍵盤配置:
             English(US) > Continue           
             (update: 2012/08/21)
            為了讓之後的 "中文輸入" 順利執行, 改成:
            Chinese > Chinese > 繼續


         c. 基本資料設定:
             name: Lanli
             computer's name: P35-DS3
             username: lanli
             password: xxxxxxxx
             confirm: xxxxxxxx
              > Continue

         d. 開始安裝系統

     9. 安裝完成, 重新啓動

         從光碟機拿出安裝片, 並按下 "Enter"

     10. 登入系統:
            輸入帳號

            輸入密碼

            登入成功 (換張桌圖)

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. 套用 "複合濾鏡": ("假色濾鏡" 與 "顏色調節濾鏡")