為了完成這個需求,花了幾天時間,各種求助。對於我這個菜鳥初學者而言確實有些難度。
在此整理一下,希望大家少走彎路。可能沒考慮內存泄露等方面,因為我還沒看這方面的東西,只滿足需求先。
新建一個cocos2dx項目OpenCamera
由於要使用Cpp和OC混編,我們基於Cpp建一個混編類。
即先建一個C++類,再改后綴名到mm,主編碼風格使用C++的。
在ios文件夾下新建C++類UtilBridge
將UtilBridge.cpp改名為UtilBridge.mm,在文件中隨便打個空格保存一下。
聲明靜態方法后,各文件如下:
.h
1 // 2 // UtilBridge.h 3 // OpenCamera 4 // 5 // Created by HanHongmin on 13-12-30. 6 // 7 // 8 9 #ifndef __OpenCamera__UtilBridge__ 10 #define __OpenCamera__UtilBridge__ 11 12 #include "cocos2d.h" 13 using namespace cocos2d; 14 class UtilBridge:public CCObject{ 15 public: 16 static void openCamera(); 17 }; 18 19 #endif /* defined(__OpenCamera__UtilBridge__) */
.mm
1 // 2 // UtilBridge.cpp 3 // OpenCamera 4 // 5 // Created by HanHongmin on 13-12-30. 6 // 7 // 8 9 #include "UtilBridge.h" 10 11 void UtilBridge::openCamera(){ 12 13 }
打開ios攝像頭等要用到oc代碼,大家可以去搜一下原理。這里要用到一個代理類,我沒有改RootViewController,而是新寫了一個OC類,這么干我不知道會不會有問題,如果有請大家指出。
新建OC類PickerDelegate繼承NSObject,文件創建好之后在聲明中加上所需接口,之后文件內容如下:
.h
1 // 2 // PickerDelegate.h 3 // OpenCamera 4 // 5 // Created by HanHongmin on 13-12-30. 6 // 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface PickerDelegate : NSObject<UINavigationControllerDelegate,UIImagePickerControllerDelegate> 12 13 @end
.m
1 // 2 // PickerDelegate.m 3 // OpenCamera 4 // 5 // Created by HanHongmin on 13-12-30. 6 // 7 // 8 9 #import "PickerDelegate.h" 10 11 @implementation PickerDelegate 12 13 14 -(id) init 15 { 16 if(self = [super init]) 17 { 18 } 19 return self; 20 } 21 22 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 23 { 24 //CCLog("selected"); 25 //處理數據 26 UIImage* image = [info valueForKey:UIImagePickerControllerOriginalImage]; 27 28 [picker dismissModalViewControllerAnimated: YES]; 29 [picker release]; 30 } 31 32 33 - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker 34 { 35 //CCLog("cancle"); 36 [picker dismissModalViewControllerAnimated: YES]; 37 [picker release]; 38 } 39 40 @end
回到UtilBridge.mm實現openCamera方法
注意:在mm中#include "PickerDelegate.h",不要寫道.h文件中。
#include "PickerDelegate.h" void UtilBridge::openCamera(){ UIImagePickerController *picker = [[UIImagePickerController alloc] init]; //設置圖像來源類型(先判斷系統中哪種圖像源是可用的) if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { picker.sourceType = UIImagePickerControllerSourceTypeCamera; }else if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]){ picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; }else { picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; } PickerDelegate* delegate = [[PickerDelegate alloc] init]; picker.delegate = delegate; [[UIApplication sharedApplication].keyWindow.rootViewController presentModalViewController:picker animated:YES]; }
在HelloWorld::init方法中調用openCamera
bool HelloWorld::init() { if ( !CCLayer::init() ) { return false; } UtilBridge::openCamera(); return true; }
運行一下,報錯了...
貌似跟橫豎屏有關,把項目調整到豎屏,再試試。我的需求就是豎屏,所以深層次的原因我就不找啦~~~
模擬器沒有攝像頭設備,所以打開的是圖庫,試攝像頭要到真機上。
我們在PickerDelegate中能夠拿到UIImage,拿到后轉變成cocos2dx可用的格式,回調HelloWord的方法再干一些事,比如顯示出來。
關於把方法當參數傳進來之類的我一概不懂,所以在PickerDelegate中直接調HelloWorld,所以.m改成.mm以實現混編。
我們先說UIImage的數據轉換
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { //CCLog("selected"); //處理數據 UIImage* image = [info valueForKey:UIImagePickerControllerOriginalImage]; CGImageRef imageRef = [image CGImage]; NSUInteger width = CGImageGetWidth(imageRef); NSUInteger height = CGImageGetHeight(imageRef); CCLog("%i,%i",width,height); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); unsigned char* rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char)); NSUInteger bytesPerPixel = 4; NSUInteger bytesPerRow = bytesPerPixel * width; NSUInteger bitsPerComponent = 8; CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace); CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); CGContextRelease(context); cocos2d::CCTexture2D *pickedImage = new cocos2d::CCTexture2D(); pickedImage->initWithData(rawData, cocos2d::kCCTexture2DPixelFormat_RGBA8888, width, height, cocos2d::CCSizeMake(width, height)); CCLOG("%f,%f",pickedImage->getContentSize().width,pickedImage->getContentSize().height); [picker dismissModalViewControllerAnimated: YES]; [picker release]; }
以上,我們已經把圖片數據轉換到了CCTexture2D,至於為何這么轉,我也是搜來噠~注意引入響應頭文件,這個以后就不說了。
HelloWorld聲明和定義接口,接收CCTexture2D並干一些我們想干的事。
.h
void pickedPhoto(CCTexture2D* texture);
.cpp
void HelloWorld::pickedPhoto(CCTexture2D* texture){ CCSprite* sprite = CCSprite::createWithTexture(texture); this->addChild(sprite); }
OK,試一下。報錯啦
斷點停在了this->addChild(sprite);這一行。根據java的經驗,this指針怎么可能是bad access...如果他是空指針,
delegate里的layer->pickedPhoto(pickedImage);就報啦。當然這不是java,比較糾結。
這里費死了勁,因為不會C++嘛,最后試來試去,HelloWorld的layer忘了設置tag。
CCScene* HelloWorld::scene() { CCScene *scene = CCScene::create(); HelloWorld *layer = HelloWorld::create(); layer->setTag(1); scene->addChild(layer); return scene; }
試一下是OK了,但是攝像頭拍照的圖為啥是橫着的呢?
再次搜來搜去,解決之~
新建OC category擴展UIImage


UIImage+fixOrientation.h文件
1 // 2 // UIImage+fixOrientation.h 3 // OpenCamera 4 // 5 // Created by HanHongmin on 13-12-30. 6 // 7 // 8 9 #import <UIKit/UIKit.h> 10 11 @interface UIImage (fixOrientation) 12 -(UIImage*) fixOrientation; 13 @end
UIImage+fixOrientation.m文件
1 // 2 // UIImage+fixOrientation.m 3 // OpenCamera 4 // 5 // Created by HanHongmin on 13-12-30. 6 // 7 // 8 9 #import "UIImage+fixOrientation.h" 10 11 @implementation UIImage (fixOrientation) 12 - (UIImage *)fixOrientation { 13 if (self.imageOrientation == UIImageOrientationUp) return self; 14 15 UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); 16 [self drawInRect:(CGRect){0, 0, self.size}]; 17 UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext(); 18 UIGraphicsEndImageContext(); 19 return normalizedImage; 20 } 21 @end
以上有啥不明白的,自己搜去吧我也說不明白。這個東西用了之后,據說手機內存會突然增大大概40-50M,求良葯啊
在PickerDelegate中引用上面的頭文件,得到UIImage后調一下。
UIImage* image = [info valueForKey:UIImagePickerControllerOriginalImage];
image = [image fixOrientation];
試試~~
圖片拾取后發現只顯示了一部分,我在控制台看到攝像頭拍完后圖片是2448x3264的,所以這里應該沒啥問題。
自行處理一下吧。我在項目中用的時候,sprite是早就創建好的,大小是整個屏幕,只是獲得Texture的時候更換到了sprite中,沒啥問題的。
至於如何調節分辨率啥的,有空再研究吧。
