update: 2012/08/08
點選/取消 濾鏡
A. 新增: 記錄使用何種濾鏡的變數
1. 開啟 GlobalDataClass.h 檔案, 修改如下:
#import <Foundation/Foundation.h>
@interface GlobalDataClass : NSObject
{
//@add: array for storage filterCells
NSMutableArray *filterCellArray;
BOOL isUsingFilter; // 有使用濾鏡?
NSMutableString *filterID; // 濾鏡 ID
}
//@add
@property (nonatomic, strong) NSMutableArray *filterCellArray;
@property (assign) BOOL isUsingFilter;
@property (nonatomic, strong) NSMutableString *filterID;
//@add
+ (GlobalDataClass *)getInstance;
@end
*************************************************
2. 開啟 GlobalDataClass.m 檔案, 修改如下:
#import "GlobalDataClass.h"
@implementation GlobalDataClass
//@add
@synthesize filterCellArray = _filterCellArray;
@synthesize isUsingFilter = _isUsingFilter;
@synthesize filterID = _filterID;
#pragma mark Getter
//@add
- (NSMutableArray *)filterCellArray
{
if (_filterCellArray == nil) {
_filterCellArray = [[NSMutableArray alloc] init];
}
return _filterCellArray;
}
//@add
- (NSMutableString *)filterID
{
if (_filterID == nil) {
_filterID = [NSMutableString stringWithString:@"NoID"];
}
return _filterID;
}
....
-----------------------------------------------------------------------------
B. 在濾鏡表單的 Cell 新增 filterID 變數
1. 開啟 FilterCell.h 檔案, 修改如下:
#import <UIKit/UIKit.h>
//@add
#import "ConstantDefined.h"
#import "FilterTitleLabel.h"
//@add
@class FilterTitleLabel;
@interface FilterCell : UITableViewCell
{
//@add
// hold the sample picture for our filter
UIImageView *sampleImage; // 濾鏡效果的圖例
// the title of our filter
//UILabel *titleLabel;
//@update
FilterTitleLabel *titleLabel;
//@add
NSString *filterID;
}
//@add
@property (nonatomic, strong) UIImageView *sampleImage;
//@property (nonatomic, strong) UILabel *titleLabel;
//@update
@property (nonatomic, strong) FilterTitleLabel *titleLabel;
@property (nonatomic, strong) NSString *filterID;
@end
*************************************************
2. 開啟 FilterCell.m 檔案, 修改如下:
....
//@add
@synthesize sampleImage = _sampleImage;
@synthesize titleLabel = _titleLabel;
@synthesize filterID = _filterID;
....
//@add
- (void)dealloc
{
self.sampleImage = nil;
self.titleLabel = nil;
self.filterID = nil;
}
....
-----------------------------------------------------------------------------
C. 決定是否要在螢幕上畫出套用濾鏡的影像
(並調整 GlobalDataClass 類別變數)
1. 開啟 ViewController.h 檔案, 修改如下:
....
@interface ViewController : GLKViewController <AVCaptureVideoDataOutputSampleBufferDelegate, UITableViewDelegate, UITableViewDataSource>
{
....
BOOL isUsingFrontCamera; // 目前使用前置鏡頭?
BOOL isLastFrontCamera; // 上次是前置鏡頭?
//@update: comment it
//BOOL applyFilter; // 是否套用濾鏡? // (update: 2012/08/08)
....
// 設備上次的擺放方向(目前不記錄:FaceUp, FaceDown, 與 Unknown)
//
// Portrait, // 直擺
// PortraitUpsideDown, // 直擺, 上下顛倒
// LandscapeRight, // 橫擺朝右
// LandscapeLeft, // 橫擺朝左
// FaceUp, // 面朝上
// FaceDown, // 面朝下
// Unknown // 未知
enum kLastOrientation lastOrientation;
GlobalDataClass *dataObj;
}
....
@property (assign) BOOL isUsingFrontCamera;
@property (assign) BOOL isLastFrontCamera;
//@update: comment it
//@property (assign) BOOL applyFilter; // (update: 2012/08/08)
....
//@add for reusable Cells
@property (nonatomic, strong) NSMutableArray *reusableCells;
@property (nonatomic, strong) GlobalDataClass *dataObj;
....
*************************************************
2. 開啟 ViewController.m 檔案, 修改如下:
....
// step 1:
....
@synthesize isUsingFrontCamera = _isUsingFrontCamera;
@synthesize isLastFrontCamera = _isLastFrontCamera;
//@update: comment it
//@synthesize applyFilter = _applyFilter; // (update: 2012/08/08)
....
//@add for reusable Cells
@synthesize reusableCells = _reusableCells;
@synthesize dataObj = _dataObj;
....
// step 2:
#pragma mark Getter
....
//@add
- (GlobalDataClass *)dataObj
{
return [GlobalDataClass getInstance];
}
// step 3:
....
//@add:filter Test
- (CIImage *)filterTest:(CIImage *)sourceImage
{
//@update: comment it
//self.applyFilter = YES; // (update: 2012/08/08)
self.coreImageFilter = [CIFilter filterWithName:@"CISepiaTone" keysAndValues:
kCIInputImageKey, sourceImage,
@"inputIntensity", [NSNumber numberWithFloat:0.8], nil];
return [self.coreImageFilter outputImage];
}
....
// step 4:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//@update: comment it
//GlobalDataClass *dataObj = [GlobalDataClass getInstance];
self.dataObj.isUsingFilter = NO;
//NSLog(@"filterID = %@", dataObj.filterID); // NoID
....
//@update: comment it
//self.applyFilter = NO; // (update: 2012/08/08)
self.isUsingFrontCamera = NO; // 預設為後置鏡頭
self.isLastFrontCamera = NO; // 預設上次為後置鏡頭
lastOrientation = Unknown; // 設備上次的擺放方向: 未知
....
}
....
// step 5:
- (void)viewDidUnload
{
[super viewDidUnload];
//@add
if ([EAGLContext currentContext] == self.glContext) {
[EAGLContext setCurrentContext:nil];
}
self.glContext = nil;
self.filterDictionary = nil;
self.reusableCells = nil;
self.coreImageContext = nil;
self.coreImageFilter = nil;
self.ciImage = nil;
self.glView = nil;
self.session = nil;
self.filterLensImageView = nil;
self.filterListTableView = nil;
self.buttonView = nil;
self.saveButton = nil;
self.switchButton = nil;
self.torchButton = nil;
self.observerButton = nil;
self.dataObj = nil;
}
....
// step 6:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//@add
//@update: comment it
//GlobalDataClass *dataObj = [GlobalDataClass getInstance];
CGFloat filterCellRotationAngle; // filterCell Rotation Angle
....
/*
if (dataObj.filterCellArray.count > 0) {
for (FilterCell* filterCell in dataObj.filterCellArray) {
filterCell.transform = CGAffineTransformMakeRotation(filterCellRotationAngle);
}
}
*/
//@update
if (self.dataObj.filterCellArray.count > 0)
{
for (FilterCell* filterCell in self.dataObj.filterCellArray)
{
filterCell.transform = CGAffineTransformMakeRotation(filterCellRotationAngle);
}
}
return YES;
}
....
// step 7:
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
// 將取得的 sampleBuffer 轉成 CVPixelBuffer
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
//@update: use instance var (ciImage)
// 接著, 將 CVPixelBuffer 利用 Core Image 的初始化方法再轉成 CIImage.
self.ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
//@add:轉換原始影像的方向
self.ciImage = [self orientationTransform:self.ciImage];
// 然後使用 CIContext 物件將其內容畫到 render buffer
[self.coreImageContext drawImage:self.ciImage atPoint:CGPointZero fromRect:[self.ciImage extent]];
//@update
if(self.dataObj.isUsingFilter == YES)
{
// 濾鏡功能測試
self.ciImage = [self filterTest:self.ciImage];
// 畫出 "濾鏡範圍" 內的影像(含方向轉變的調整)
[self drawFilteredImage:self.ciImage];
}
// 最後, 在螢幕上呈現出來.
[self.glContext presentRenderbuffer:GL_RENDERBUFFER];
}
....
-----------------------------------------------------------------------------
D. 選取 / 取消選取 filter cell
(並調整 GlobalDataClass 類別變數, 幫 cell 記錄 filterID)
1. 開啟 HorizontalTableCell.h 檔案, 修改如下:
....
@interface HorizontalTableCell : UITableViewCell <UITableViewDelegate, UITableViewDataSource>
{
//@add
// we will rotate and add as a subview of our cell
UITableView *filterTableView;
// hold the filters for the category we are in
NSArray *filters;
//@add: lastIndexPath in tableView:didSelectRowAtIndexPath:
NSIndexPath *lastIndexPath;
GlobalDataClass *dataObj;
}
//@add
@property (nonatomic, strong) UITableView *filterTableView;
@property (nonatomic, strong) NSArray *filters;
@property (nonatomic, strong) NSIndexPath *lastIndexPath;
@property (nonatomic, strong) GlobalDataClass *dataObj;
@end
*************************************************
2. 開啟 HorizontalTableCell.m 檔案, 修改如下:
....
// step 1:
@synthesize filterTableView = _filterTableView;
@synthesize filters = _filters;
@synthesize lastIndexPath = _lastIndexPath;
@synthesize dataObj = _dataObj;
....
// step 2:
#pragma mark Getter
//@add:
// 記錄上次選取的資料列:
//
// 問題:
// 一開始尚未選取任何資料列時, lastIndexPath 預設為 nil,
// 第一次點選資料列時, 在 tableView:didSelectRowAtIndexPath: 中呼叫:
// int newRow = [indexPath row];
// int oldRow = [self.lastIndexPath row];
//
// 得到 oldRow 的值為 0, 如果點選的資料是第 1 列, newRow 的值也為 0,
// 會造成: 程式判斷成要 "取消選取濾鏡"
//
// 解決:
// 在初始化 lastIndexPath 時, 將其 indexPathForRow: 的值設為 -1
- (NSIndexPath *)lastIndexPath
{
if (_lastIndexPath == nil) {
_lastIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0];
}
return _lastIndexPath;
}
//@add
- (GlobalDataClass *)dataObj
{
return [GlobalDataClass getInstance];
}
....
// step 3:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
....
//@title text: we don't need to load that, just read it from our array of filters.
cell.titleLabel.text = [currentFilter objectForKey:@"Title"];
cell.filterID = [currentFilter objectForKey:@"FilterID"];
//NSLog(@"filterID = %@", cell.filterID);
//@add for storage filterCells
//
// 當沒有找到相同的 filterID 時, 才將新的 filterCell 存入 Array 裡.
//
/*
備註: 1. 當找到相同的 filterID 時, 不刪除其所屬的 cell.
因為, 如果刪除舊的 filterCell, 程式在執行時,
於拖拉"濾鏡表單" 時會 crash 掉.
2. 如果一律將 filterCell 儲存起來, 程式在執行時,
於每次拖拉"濾鏡表單" 時, 都會將新產生的 filterCell
(即使 filterID 名稱相同)存入 Array 裡.
*/
//@update: comment it
//GlobalDataClass *dataObj = [GlobalDataClass getInstance];
BOOL saveCell = YES;
//for (FilterCell* filterCell in dataObj.filterCellArray) {
//@update
for (FilterCell* filterCell in self.dataObj.filterCellArray) {
//if ([filterCell.titleLabel.text isEqualToString:cell.titleLabel.text])
//@update
if ([filterCell.filterID isEqualToString:cell.filterID])
{
saveCell = NO;
break;
}
}
if (saveCell) {
//[dataObj.filterCellArray addObject:cell];
//@update
[self.dataObj.filterCellArray addObject:cell];
}
//NSLog(@"self.dataObj.filterCellArray.count = %d", self.dataObj.filterCellArray.count);
return cell;
}
....
// step 4:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int newRow = [indexPath row];
int oldRow = [self.lastIndexPath row];
//NSLog(@"oldRow = %d", oldRow);
//NSLog(@"newRow = %d", newRow);
//@update comment it
//GlobalDataClass *dataObj = [GlobalDataClass getInstance];
// 選取濾鏡
if (newRow != oldRow)
{
self.lastIndexPath = indexPath;
//@TODO: 套用濾鏡功能
/* (此方式亦可)
FilterCell *cell = (FilterCell *)[tableView cellForRowAtIndexPath:indexPath];
NSLog(@"FilterID = %@, Title = %@", cell.filterID, cell.titleLabel.text);
*/
NSDictionary *currentFilter = [self.filters objectAtIndex:indexPath.row];
/*
NSString *FilterID = [currentFilter objectForKey:@"FilterID"];
NSString *Title = [currentFilter objectForKey:@"Title"];
NSString *ImageName = [currentFilter objectForKey:@"ImageName"];
NSLog(@"FilterID = %@, Title = %@, ImageName = %@", FilterID, Title, ImageName);
*/
self.dataObj.isUsingFilter = YES;
self.dataObj.filterID = [NSMutableString stringWithString:[currentFilter objectForKey:@"FilterID"]];
}
// 取消選取濾鏡
else
{
//self.lastIndexPath = nil; // -> not work at section:0 row:0
self.lastIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0];
[tableView deselectRowAtIndexPath:indexPath animated:NO];
//@TODO: 恢復原始影像
self.dataObj.isUsingFilter = NO;
self.dataObj.filterID = [NSMutableString stringWithString:@"NoID"];
}
NSLog(@"filterID = %@", self.dataObj.filterID);
}
....
// step 5:
- (void)dealloc
{
self.filterTableView = nil;
self.filters = nil;
self.lastIndexPath = nil;
self.dataObj = nil;
}
....
-----------------------------------------------------------------------------
E. 編譯並執行
1. 未套用濾鏡: 相機畫面
2. 未套用濾鏡: 拍照結果 (只會截取濾鏡方框內的影像)
3. 套用濾鏡: 相機畫面 (目前每個濾鏡效果都一樣)
4. 套用濾鏡: 拍照結果
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。