update: 2012/03/12
reference: I touchs: Filter4Cam 實作: 6. 測試 Camera Overlay 與 Filter Rectangle
A. 說明
1. 由於之後會在 Camera 上放置多個 Overlay 的 UI 元件, 因此將設備方向改變時
的程式碼調整, 由原本 Filter4CamHelper 類別提供的 orientationTransform: 方法,
移到 ViewController 類別內實作.
-----------------------------------------------------------------------------------------
B. 調整濾鏡視窗外框:
1. 開啓 ViewController.h 檔案, 調整如下:
....
@interface ViewController : GLKViewController <AVCaptureVideoDataOutputSampleBufferDelegate>
{
....
//@add for Camera Overlay UI
UIImageView *filterLensImageView;
....
}
....
//@add for Camera Overlay UI
@property (nonatomic, strong) UIImageView *filterLensImageView;
....
//@add for orientation Transform
- (CIImage *)orientationTransform:(CIImage *)sourceImage; // 方向轉變的調整
//@add for setting camera Overlay
- (void)cameraOverlay;
....
2. 開啓 ViewController.m 檔案, 調整如下:
....
//@add for Camera Overlay UI
@synthesize filterLensImageView = _filterLensImageView;
....
#pragma mark Getter
....
//@add for Camera Overlay UI
- (UIImageView *)filterLensImageView
{
if (_filterLensImageView == nil) {
_filterLensImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"filterLens.png"]];
}
return _filterLensImageView;
}
....
#pragma mark Utility Tools
//@add for setting camera Overlay
- (void)cameraOverlay
{
[self.filterLensImageView setFrame:CGRectMake(20, 80, 280, 280)];
[self.view addSubview:self.filterLensImageView];
}
//@add for orientation Transform(方向轉變的調整)
- (CIImage *)orientationTransform:(CIImage *)sourceImage
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
CGAffineTransform affineTransform; // 仿射轉換
// 設備垂直擺放
if (orientation == UIDeviceOrientationPortrait)
{
affineTransform = CGAffineTransformMakeRotation(-M_PI / 2);
}
// 設備垂直 180 度擺放
else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
affineTransform = CGAffineTransformMakeRotation(M_PI / 2);
}
// 設備水平向右擺放
else if (orientation == UIDeviceOrientationLandscapeRight) {
affineTransform = CGAffineTransformMakeRotation(M_PI);
}
// 設備水平向左擺放
else if (orientation == UIDeviceOrientationLandscapeLeft) {
affineTransform = CGAffineTransformMakeRotation(0);
}
//(2012/03/12 update)
// 其它 (UIDeviceOrientationFaceUp, UIDeviceOrientationFaceDown,
// UIDeviceOrientationUnknown)
else {
affineTransform = CGAffineTransformMakeRotation(0);
}
return [sourceImage imageByApplyingTransform:affineTransform];
}
....
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
// 將取得的 sampleBuffer 轉成 CVPixelBuffer
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
// 接著, 將 CVPixelBuffer 利用 Core Image 的初始化方法再轉成 CIImage.
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
//@add:濾鏡測試
//ciImage = [self filterTest:ciImage];
//@add:方向轉變的調整
//ciImage = [Filter4CamHelper orientationTransform:ciImage];
ciImage = [self orientationTransform:ciImage];
// 然後使用 CIContext 物件將其內容畫到 render buffer
[self.coreImageContext drawImage:ciImage atPoint:CGPointZero fromRect:[ciImage extent]];
// 最後, 在螢幕上呈現出來.
[self.glContext presentRenderbuffer:GL_RENDERBUFFER];
}
....
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//@add:helper Test
[self helperTest];
//@add: establish Render
[self establishRender];
//@add: establishCamera
[self establishCamera:kCameraBack];
//@add for setting camera Overlay
[self cameraOverlay];
//@add: startRunning
[self startRunningSession];
}
....// (2012/03/12 update)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
/*
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
*/
//@update
// 設備垂直擺放
if (interfaceOrientation == UIDeviceOrientationPortrait)
{
[self.filterLensImageView setFrame:CGRectMake(20, 80, 280, 280)];
}
// 設備垂直 180 度擺放
else if (interfaceOrientation == UIDeviceOrientationPortraitUpsideDown) {
[self.filterLensImageView setFrame:CGRectMake(20, 80, 280, 280)];
}
// 設備水平向右擺放
else if (interfaceOrientation == UIDeviceOrientationLandscapeRight) {
[self.filterLensImageView setFrame:CGRectMake(80, 20, 280, 280)];
}
// 設備水平向左擺放
else if (interfaceOrientation == UIDeviceOrientationLandscapeLeft) {
[self.filterLensImageView setFrame:CGRectMake(80, 20, 280, 280)];
}
// 其它 (UIDeviceOrientationFaceUp, UIDeviceOrientationFaceDown,
// UIDeviceOrientationUnknown)
else {
[self.filterLensImageView setFrame:CGRectMake(80, 20, 280, 280)];
}
return YES;
}
....
3. 編譯並執行
直向:
C. 濾鏡測試:
1. 開啓 ViewController.h 檔案, 調整如下:
....
//@add for orientation Transform
- (CIImage *)orientationTransform:(CIImage *)sourceImage; // 方向轉變的調整
- (void)filterOrientationTransform:(CIImage *)sourceImage; // 方向轉變的調整
....
2. 開啓 ViewController.m 檔案, 調整如下:
....
//@add for filter Orientation Transform (方向轉變的調整)
- (void)filterOrientationTransform:(CIImage *)sourceImage
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
// 設備垂直擺放
if (orientation == UIDeviceOrientationPortrait)
{
[self.coreImageContext drawImage:sourceImage
inRect:CGRectMake(23.5, 123.5, 274, 274) fromRect:[sourceImage extent]];
}
// 設備垂直 180 度擺放
else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
[self.coreImageContext drawImage:sourceImage
inRect:CGRectMake(23.5, 123.5, 274, 274) fromRect:[sourceImage extent]];
}
// 設備水平向右擺放
else if (orientation == UIDeviceOrientationLandscapeRight) {
[self.coreImageContext drawImage:sourceImage
inRect:CGRectMake(83.5, 23.5, 274, 274) fromRect:[sourceImage extent]];
}
// 設備水平向左擺放
else {
[self.coreImageContext drawImage:sourceImage
inRect:CGRectMake(83.5, 23.5, 274, 274) fromRect:[sourceImage extent]];
}
}
....
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
// 將取得的 sampleBuffer 轉成 CVPixelBuffer
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
// 接著, 將 CVPixelBuffer 利用 Core Image 的初始化方法再轉成 CIImage.
CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
//@add:濾鏡測試
//ciImage = [self filterTest:ciImage];
//@add:方向轉變的調整
//ciImage = [Filter4CamHelper orientationTransform:ciImage];
ciImage = [self orientationTransform:ciImage];
// 然後使用 CIContext 物件將其內容畫到 render buffer
[self.coreImageContext drawImage:ciImage atPoint:CGPointZero fromRect:[ciImage extent]];
//@add test for filter Rectangle
//@add:濾鏡測試
ciImage = [self filterTest:ciImage];
//[self.coreImageContext drawImage:ciImage inRect:CGRectMake(23.5, 123.5, 274, 274) fromRect:[ciImage extent]];
[self filterOrientationTransform:ciImage];
// 最後, 在螢幕上呈現出來.
[self.glContext presentRenderbuffer:GL_RENDERBUFFER];
}
....
3. 編譯並執行
直向:
-----------------------------------------------------------------------------------------
D. 調整濾鏡顯示範圍 (2012/03/12 update)
1. 開啓 ViewController.h 檔案, 修改如下:
....
@interface ViewController : GLKViewController <AVCaptureVideoDataOutputSampleBufferDelegate>
{
....
BOOL isUsingFrontCamera;
//@add 設備上一次方向是否為水平擺放(向左或向右皆算)
BOOL isPreviousOrientationLandscape;
....
}
....
@property (assign) BOOL isUsingFrontCamera;
//@add
@property (assign) BOOL isPreviousOrientationLandscape;
....
1. 開啓 ViewController.m 檔案, 修改如下:
....
@synthesize isUsingFrontCamera = _isUsingFrontCamera;
//@add
@synthesize isPreviousOrientationLandscape = _isPreviousOrientationLandscape;
....
- (void)filterOrientationTransform:(CIImage *)sourceImage
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
// 設備垂直擺放
if (orientation == UIDeviceOrientationPortrait)
{
//@add
self.isPreviousOrientationLandscape = NO;
[self.coreImageContext drawImage:sourceImage inRect:CGRectMake(23.5, 123.5, 274, 274)
// x 越小, 濾鏡越向右; y 負越多, 濾鏡越向上
fromRect:CGRectMake(23, -517.5, 274, 274)];
}
// 設備垂直 180 度擺放
else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
//@add
self.isPreviousOrientationLandscape = NO;
[self.coreImageContext drawImage:sourceImage inRect:CGRectMake(23.5, 123.5, 274, 274)
// x 負越多, 濾鏡越向左; y 越多, 濾鏡越向上
fromRect:CGRectMake(-458.5, 123, 274, 274)];
}
// 設備水平向右擺放
else if (orientation == UIDeviceOrientationLandscapeRight) {
//@add
self.isPreviousOrientationLandscape = YES;
[self.coreImageContext drawImage:sourceImage inRect:CGRectMake(83.5, 23.5, 274, 274)
// x 負越多, 濾鏡越向右; y 負越多, 濾鏡越向上
fromRect:CGRectMake(-557, -457.5, 274, 274)];
}
// 設備水平向左擺放(最穩定)
else if (orientation == UIDeviceOrientationLandscapeLeft) {
//@add
self.isPreviousOrientationLandscape = YES;
[self.coreImageContext drawImage:sourceImage inRect:CGRectMake(83.5, 23.5, 274, 274)
// x 越大, 濾鏡越向左; y 越多, 濾鏡越向上
fromRect:CGRectMake(83.5, 23.5, 274, 274)];
}
// 其它 (UIDeviceOrientationFaceUp, UIDeviceOrientationFaceDown,
// UIDeviceOrientationUnknown)
else {
//@在此不記錄上一次設備的方向
//@add:上一次設備為水平擺放
if (self.isPreviousOrientationLandscape == YES) {
[self.coreImageContext drawImage:sourceImage inRect:CGRectMake(83.5, 23.5, 274, 274)
// x 越大, 濾鏡越向左; y 越多, 濾鏡越向上
fromRect:CGRectMake(83.5, 23.5, 274, 274)];
}
//@add:上一次設備為垂直擺放
else {
[self.coreImageContext drawImage:sourceImage inRect:CGRectMake(23.5, 123.5, 274, 274)
// x 越大, 濾鏡越向左; y 越多, 濾鏡越向上
fromRect:CGRectMake(23.5, 123.5, 274, 274)];
}
}
}
....
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//@add
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationLandscapeLeft) {
self.isPreviousOrientationLandscape = YES;
}
else {
self.isPreviousOrientationLandscape = NO;
}
....
}
....
3. 編譯並執行:
直向:
沒有留言:
張貼留言
注意:只有此網誌的成員可以留言。