最近做个小游戏需要调用手机图库和摄像头并裁减图片,发现网上很多教程不是太全,有的安卓端裁减不了大图,下面是完整代码,可以裁减高清图的。
完整拼图游戏下载:
@L_301_0@
1、首先是跨平台入口代码,iOS平台需要把ImageCrop.cpp改成ImageCrop.mm,并且在AppController.mm里调用setVIEwController(voID* vIEwController)把rootVIEw传进来初始化m_vIEwController
#ifndef ImageCrop_hpp#define ImageCrop_hpp#include <stdio.h>#include "cocos2d.h"USING_NS_CC;#define kImageCropEvent "ImageCropEvent"class ImageCrop {public: ImageCrop(); static ImageCroP* getInstance(); static voID destroyInstance(); voID openCamera(std::function<voID(std::string)> callback); voID openPhoto(std::function<voID(std::string)> callback);#if ( CC_TARGET_PLATFORM == CC_PLATFORM_IOS) //设置AppController iOS平台在AppController.mm里调用把rootVIEwController传递过来 voID setVIEwController(voID* vIEwController); voID *m_vIEwController;#endifprivate: static ImageCroP* _instance; std::function<voID(std::string)> _callback;};#endif//// ImageCrop.cpp// PhotoCrop//// Created by xujw on 15/12/28.////#include "ImageCrop.hpp"#if ( CC_TARGET_PLATFORM == CC_PLATFORM_IOS)#import "ImagePickerVIEwController.h"#import "RootVIEwController.h"#endif#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)#include "platform/androID/jni/JniHelper.h"#include <jni.h>#define JAVA_CLASS "org/cocos2dx/cpp/ImageCrop"#define JAVA_FUNC_OPEN_PHOTO "openPhoto"#define JAVA_FUNC_OPEN_CAMERA "openCamera"#endifImageCrop::ImageCrop():_callback(nullptr){ Director::getInstance()->getEventdispatcher()->addCustomEventListener(kImageCropEvent,[=](EventCustom *event) { std::string *imgPath = (std::string*)event->getUserData(); _callback(*imgPath); });}ImageCroP* ImageCrop::_instance = nullptr;ImageCroP* ImageCrop::getInstance(){ if (!_instance) { _instance = new (std::nothrow) ImageCrop(); } return _instance;}voID ImageCrop::destroyInstance(){ CC_SAFE_DELETE(_instance);}voID ImageCrop::openCamera(std::function<voID (std::string)> callback){ _callback = callback;#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) ImagePickerVIEwController * imagePickerVIEwController = [[ImagePickerVIEwController alloc]initWithNibname:nil bundle:nil]; RootVIEwController *_vIEwController = (RootVIEwController*)m_vIEwController; [_vIEwController.vIEw addSubvIEw:imagePickerVIEwController.vIEw]; [imagePickerVIEwController takePhoto];#endif#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo info; bool ret = JniHelper::getStaticmethodInfo(info,JAVA_CLASS,JAVA_FUNC_OPEN_CAMERA,"()V"); if (ret) { info.env->CallStaticVoIDMethod(info.classID,info.methodID); }#endif}voID ImageCrop::openPhoto(std::function<voID (std::string)> callback){ _callback = callback;#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) ImagePickerVIEwController * imagePickerVIEwController = [[ImagePickerVIEwController alloc]initWithNibname:nil bundle:nil]; RootVIEwController *_vIEwController = (RootVIEwController*)m_vIEwController; [_vIEwController.vIEw addSubvIEw:imagePickerVIEwController.vIEw]; [imagePickerVIEwController localPhoto];#endif#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo info; bool ret = JniHelper::getStaticmethodInfo(info,JAVA_FUNC_OPEN_PHOTO,info.methodID); }#endif}#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)voID ImageCrop::setVIEwController(voID *vIEwController){ m_vIEwController = vIEwController;}#endif//--------Java回调C++--------native 方法#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)extern "C"{ voID Java_org_cocos2dx_cpp_ImageCrop_onImageSaved(jnienv *env,jobject thiz,Jstring path) { std::string strPath = JniHelper::Jstring2string(path); //必须这样,否则由于线程问题会显示黑块无法正常创建精灵 Director::getInstance()->getScheduler()->performFunctionInCocosThread([=,strPath]()mutable{ Director::getInstance()->getEventdispatcher()->dispatchCustomEvent(kImageCropEvent,&strPath); }); }}#endif
2、iOS端代码,.m文件改成.mm文件
#ifndef ImagePickerVIEwController_h#define ImagePickerVIEwController_h#import <UIKit/UIKit.h>@interface ImagePickerVIEwController:UIVIEwController<UINavigationControllerDelegate,UIImagePickerControllerDelegate>{ Nsstring *filePath;}//打开本地相册-(voID)localPhoto;//打开相机-(voID)takePhoto;@end#endif#import <Foundation/Foundation.h>#import "ImagePickerVIEwController.h"@interface ImagePickerVIEwController ()@end@implementation ImagePickerVIEwController-(voID)vIEwDIDLoad{ [super vIEwDIDLoad];}-(voID)vIEwDIDUnload{ [super vIEwDIDUnload];}-(voID)dIDReceiveMemoryWarning{ [super dIDReceiveMemoryWarning];}-(voID)localPhoto{ NSLog(@"-(voID)localPhoto"); UIImagePickerController *picker = [[UIImagePickerController alloc]init]; picker.delegate = self; picker.sourceType = UIImagePickerControllerSourceTypePhotolibrary; picker.allowsEditing = YES; [self presentVIEwController:picker animated:YES completion:^(voID) { NSLog(@"ImageVIEwController is presented"); }]; [picker release];}-(voID)takePhoto{ UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera; if ([UIImagePickerController isSourceTypeAvailable:sourceType]) { UIImagePickerController *picker = [[UIImagePickerController alloc]init]; picker.delegate = self; //设置拍照后可以编辑 picker.allowsEditing = YES; picker.sourceType = sourceType; [self presentVIEwController:picker animated:YES completion:^(voID) { NSLog(@"ImageVIEwController is presented"); }]; } else { NSLog(@"模拟器无法使用相机,请在真机中调试"); } NSLog(@"-(voID)takePhoto");}-(voID)imagePickerController:(UIImagePickerController *)picker dIDFinishPickingMediawithInfo:(NSDictionary<Nsstring *,ID> *)info{ Nsstring *type = [info objectForKey:@"UIImagePickerControllerMediaType"]; if ([type isEqualToString:@"public.image"]) { //先把图片转成NSData //原始图// UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalimage"]; UIImage *image = [info objectForKey:@"UIImagePickerControllerEditedImage"]; NSData *data; if (UIImagePNGRepresentation(image) == nil) { data = UIImageJPEGRepresentation(image,1.0); } else { data = UIImagePNGRepresentation(image); } //图片保存路径 //这里将图片放在沙盒的documents/image文件夹中 Nsstring *documentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"documents"]; Nsstring *imgPath = [documentsPath stringByAppendingPathComponent:@"image"]; //文件管理器 NSfileManager *fileManager = [NSfileManager defaultManager]; //生成唯一字符串 Nsstring *uuID = [[NSUUID UUID]UUIDString]; //生成文件名 Nsstring *filename = [Nsstring stringWithFormat:@"%@.png",uuID]; //把刚刚由图片转成的data对象拷贝至沙盒中 并保存为xxxxx-xxxx-xxx...xxx.png /******保存之前最好先清空下,不然占用磁盘越来越大********/ [fileManager removeItemAtPath:imgPath error:nil]; /*************************************************/ [fileManager createDirectoryAtPath:imgPath withIntermediateDirectorIEs:YES attributes:nil error:nil]; [fileManager createfileAtPath:[imgPath stringByAppendingPathComponent:filename] contents:data attributes:nil]; //得到选择后沙盒中图片的完整路径 filePath = [[Nsstring alloc]initWithFormat:@"%@",[imgPath stringByAppendingPathComponent:filename]]; //关闭相册界面 [picker dismissVIEwControllerAnimated:YES completion:^(voID){}]; //通知ImageCrop完成取图 std::string strfilePath = [filePath UTF8String]; cocos2d::Director::getInstance()->getEventdispatcher()->dispatchCustomEvent("ImageCropEvent",&strfilePath); }}-(voID)imagePickerControllerDIDCancel:(UIImagePickerController *)picker{ NSLog(@"您取消了照片选择"); [picker dismissVIEwControllerAnimated:YES completion:^(voID){}];}@end
3、安卓端,安卓平台需要把ImageCrop.java导入工程包里(src下org.cocos2dx.cpp包里),在主activity(AppActivity.java)的onCreate里调用ImageCrop.getInstance().initimageCrop(this)初始化,然后重载onActivityResult并回调ImageCrop的onActivityResult方法
ImageCrop.java:
package org.cocos2dx.cpp;import java.io.file;import java.io.fileNotFoundException;import androID.app.Activity;import androID.content.Intent;import androID.graphics.Bitmap;import androID.graphics.BitmapFactory;import androID.net.Uri;import androID.os.Environment;import androID.provIDer.MediaStore;import androID.util.Log;public class ImageCrop { public static final int NONE = 0; public static final int PHOTOHRAPH = 1; public static final int PHOTOZOOM = 2; public static final int PHOTORESOulT = 3; public static final String IMAGE_UnspecIFIED = "image/*"; private static ImageCrop instance = null; private static Activity activity = null; private static String TAG = "ImageCrop"; public static native voID onImageSaved(String path); //拍摄照片保存路径 private static String savePath = Environment.getExternalStorageDirectory() +"/CropImage"; private static String photoname = ""; private static Uri imguri = null; public static ImageCrop getInstance() { if(null == instance) { instance = new ImageCrop(); } return instance; } //初始化 public voID init(Activity activity) { ImageCrop.activity = activity; } //打开相册 static public voID openPhoto() { Intent intent = new Intent(Intent.ACTION_PICK,null); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,IMAGE_UnspecIFIED); activity.startActivityForResult(intent,PHOTOZOOM); } //打开相机 static public voID openCamera() { file destDir = new file(savePath); if (!destDir.exists()) { destDir.mkdirs(); } photoname = "temp.jpg"; file file = new file(savePath + "/" + photoname); imguri = Uri.fromfile(file); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT,imguri); activity.startActivityForResult(intent,PHOTOHRAPH); } //回调 public voID onActivityResult(int requestCode,int resultCode,Intent data) { if (resultCode == NONE) return; // 拍照 不能使用data,因为没有返回是空的 if (requestCode == PHOTOHRAPH) { if (imguri == null) { Log.e(TAG,"PHOTOHRAPH imguri is null"); return; } startPhotoZoom(imguri); } if (requestCode == PHOTOZOOM) { // 读取相册缩放图片 if (data==null ) { Log.e(TAG,"data is null"); return; } if (data.getData()==null) { Log.e(TAG,"data.getData() is null"); return; } startPhotoZoom(data.getData()); } // 处理结果 if (requestCode == PHOTORESOulT) { Bitmap bitmap = decodeUriAsBitmap(imguri); if (bitmap == null) { Log.e(TAG,"bitmap is null"); } Log.e("ImageCrop","图片已经保存,通知c++层,"); onImageSaved(savePath + "/" + photoname); } } public voID startPhotoZoom(Uri uri) { photoname = System.currentTimeMillis() + ".jpg"; file file = new file(savePath,photoname); imguri = Uri.fromfile(file); Intent intent = new Intent("com.androID.camera.action.CROP"); intent.setDataAndType(uri,IMAGE_UnspecIFIED); intent.putExtra("crop","true"); intent.putExtra("aspectX",1); intent.putExtra("aspectY",1); intent.putExtra("outputX",600); intent.putExtra("outputY",600); intent.putExtra("return-data",false); intent.putExtra(MediaStore.EXTRA_OUTPUT,imguri); activity.startActivityForResult(intent,PHOTORESOulT); } private Bitmap decodeUriAsBitmap(Uri uri) { Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeStream(activity.getContentResolver().openinputStream(uri)); } catch (fileNotFoundException e) { // Todo: handle exception e.printstacktrace(); return null; } return bitmap; }}
4、示例
HelloWorld工程里直接引入ImageCrop.hpp,调用拍照或者打开相册即可,裁减完成后会返回图片保存路径,直接就可以在C++环境里创建精灵等 *** 作了,欧了!
#include "HelloWorldScene.h"#include "ImageCrop.hpp"USING_NS_CC;Scene* HelloWorld::createScene(){ // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene;}// on "init" you need to initialize your instancebool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); ///////////////////////////// // 2. add a menu item with "X" image,which is clicked to quit the program // you may modify it. // add a "close" icon to exit the progress. it's an autorelease object auto closeItem = MenuItemImage::create( "Closenormal.png","CloseSelected.png",CC_CALLBACK_1(HelloWorld::menuCloseCallback,this)); closeItem->setposition(Vec2(origin.x + visibleSize.wIDth - closeItem->getContentSize().wIDth/2,origin.y + closeItem->getContentSize().height/2)); auto openPhoto = MenuItemFont::create("打开相册",[=](Ref*) { ImageCrop::getInstance()->openPhoto([=](std::string path) { cclOG("photo path:%s",path.c_str()); _img -> removeFromParent(); _img = Sprite::create(path); this->addChild(_img); _img->setposition(Vec2(visibleSize.wIDth/2 + origin.x,visibleSize.height/2 + origin.y)); }); }); openPhoto->setposition(Vec2(origin.x + openPhoto->getContentSize().wIDth/2,origin.y + openPhoto->getContentSize().height/2)); auto openCamera = MenuItemFont::create("打开相机",[=](Ref*) { ImageCrop::getInstance()->openCamera([=](std::string path) { cclOG("photo path:%s",path.c_str()); _img -> removeFromParent(); _img = Sprite::create(path); this->addChild(_img); _img->setposition(Vec2(visibleSize.wIDth/2 + origin.x,visibleSize.height/2 + origin.y)); }); }); openCamera->setposition(Vec2(origin.x + openCamera->getContentSize().wIDth/2,origin.y + openCamera->getContentSize().height)); auto menu = Menu::create(closeItem,openPhoto,openCamera,NulL); menu->setposition(Vec2::ZERO); this->addChild(menu,1); ///////////////////////////// // 3. add your codes below... // add a label shows "Hello World" // create and initialize a label auto label = Label::createWithTTF("Hello World","Fonts/Marker Felt.ttf",24); // position the label on the center of the screen label->setposition(Vec2(origin.x + visibleSize.wIDth/2,origin.y + visibleSize.height - label->getContentSize().height)); // add the label as a child to this layer this->addChild(label,1); // add "HelloWorld" splash screen" _img = Sprite::create("HelloWorld.png"); // position the sprite on the center of the screen _img->setposition(Vec2(visibleSize.wIDth/2 + origin.x,visibleSize.height/2 + origin.y)); // add the sprite as a child to this layer this->addChild(_img,0); return true;}voID HelloWorld::menuCloseCallback(Ref* pSender){ Director::getInstance()->end();#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0);#endif}
本文参考:
http://www.jb51.cc/article/p-fgjeqgzd-bbz.html
http://www.myexception.cn/operating-system/1937511.html
总结以上是内存溢出为你收集整理的cocos2d-x调用摄像头和相册并裁减图片全部内容,希望文章能够帮你解决cocos2d-x调用摄像头和相册并裁减图片所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)