unity 启动相机_Unity3D研究院之打开照相机与本地相册进行裁剪显示(三十三)...-程序员宅基地

技术标签: unity 启动相机  

最近做项目需要用到这个功能,就是在Unity中调用Android本地相册或直接打开摄像机拍照并且裁剪一部分用于用户头像,今天研究了一下,那么研究出成果了MOMO一定要分享给大家。Unity与Android的交互还有谁不会?? 如果有不会的朋友请看MOMO之前的文章喔,Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)这里有关交互的方式就不详细说明,主要将如何在Unity中打开摄像机、在Unity中打开本地相册,选一个照片后如何进行裁剪,最后将图片转换成Texture显示在U3D的世界当中。

首先看看Eclipse中的Android插件部分,我的包名是com.xys请大家与MOMO保持一致,Unity工程中也需要是这个包名噢。

UnityTestActivity.java 这个类是Unity的插件主类,在这里调用是打开摄像机 还是本地相册的方法。

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

packagecom.xys;

importandroid.content.Context;

importandroid.content.Intent;

importandroid.os.Bundle;

importcom.unity3d.player.UnityPlayerActivity;

publicclassUnityTestActivityextendsUnityPlayerActivity{

//public class UnityTestActivity extends Activity {

ContextmContext=null;

@Override

publicvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

mContext=this;

}

//Unity中会调用这个方法,用于区分打开摄像机 开始本地相册

publicvoidTakePhoto(Stringstr)

{

Intentintent=newIntent(mContext,WebViewActivity.class);

intent.putExtra("type",str);

this.startActivity(intent);

}

}

然后是WebViewActivity.java 这里主要处理用户打开摄像机或本地相册后如何进行裁剪图片,并且把裁剪的图片储存在本地文件中。

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

packagecom.xys;

importjava.io.File;

importjava.io.FileNotFoundException;

importjava.io.FileOutputStream;

importjava.io.IOException;

importcom.unity3d.player.UnityPlayer;

importandroid.app.Activity;

importandroid.content.Intent;

importandroid.graphics.Bitmap;

importandroid.net.Uri;

importandroid.os.Bundle;

importandroid.os.Environment;

importandroid.provider.MediaStore;

importandroid.view.KeyEvent;

importandroid.widget.ImageView;

publicclassWebViewActivityextendsActivity

{

ImageViewimageView=null;

publicstaticfinalintNONE=0;

publicstaticfinalintPHOTOHRAPH=1;// 拍照

publicstaticfinalintPHOTOZOOM=2;// 缩放

publicstaticfinalintPHOTORESOULT=3;// 结果

publicstaticfinalStringIMAGE_UNSPECIFIED="image/*";

publicfinalstaticStringFILE_NAME="image.png";

publicfinalstaticStringDATA_URL="/data/data/";

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

imageView=(ImageView)this.findViewById(R.id.imageID);

Stringtype=this.getIntent().getStringExtra("type");

//在这里判断是打开本地相册还是直接照相

if(type.equals("takePhoto"))

{

Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);

intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(newFile(Environment.getExternalStorageDirectory(),"temp.jpg")));

startActivityForResult(intent,PHOTOHRAPH);

}else

{

Intentintent=newIntent(Intent.ACTION_PICK,null);

intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,IMAGE_UNSPECIFIED);

startActivityForResult(intent,PHOTOZOOM);

}

}

@Override

protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){

if(resultCode==NONE)

return;

// 拍照

if(requestCode==PHOTOHRAPH){

//设置文件保存路径这里放在跟目录下

Filepicture=newFile(Environment.getExternalStorageDirectory()+"/temp.jpg");

startPhotoZoom(Uri.fromFile(picture));

}

if(data==null)

return;

// 读取相册缩放图片

if(requestCode==PHOTOZOOM){

startPhotoZoom(data.getData());

}

// 处理结果

if(requestCode==PHOTORESOULT){

Bundleextras=data.getExtras();

if(extras!=null){

Bitmapphoto=extras.getParcelable("data");

imageView.setImageBitmap(photo);

try{

SaveBitmap(photo);

}catch(IOExceptione){

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

super.onActivityResult(requestCode,resultCode,data);

}

publicvoidstartPhotoZoom(Uriuri){

Intentintent=newIntent("com.android.camera.action.CROP");

intent.setDataAndType(uri,IMAGE_UNSPECIFIED);

intent.putExtra("crop","true");

// aspectX aspectY 是宽高的比例

intent.putExtra("aspectX",1);

intent.putExtra("aspectY",1);

// outputX outputY 是裁剪图片宽高

intent.putExtra("outputX",300);

intent.putExtra("outputY",300);

intent.putExtra("return-data",true);

startActivityForResult(intent,PHOTORESOULT);

}

publicvoidSaveBitmap(Bitmapbitmap)throwsIOException{

FileOutputStreamfOut=null;

//注解1

Stringpath="/mnt/sdcard/Android/data/com.xys/files";

try{

//查看这个路径是否存在,

//如果并没有这个路径,

//创建这个路径

FiledestDir=newFile(path);

if(!destDir.exists())

{

destDir.mkdirs();

}

fOut=newFileOutputStream(path+"/"+FILE_NAME);

}catch(FileNotFoundExceptione){

e.printStackTrace();

}

//将Bitmap对象写入本地路径中,Unity在去相同的路径来读取这个文件

bitmap.compress(Bitmap.CompressFormat.PNG,100,fOut);

try{

fOut.flush();

}catch(IOExceptione){

e.printStackTrace();

}

try{

fOut.close();

}catch(IOExceptione){

e.printStackTrace();

}

}

@Override

publicbooleanonKeyDown(intkeyCode,KeyEventevent)

{

if(keyCode==KeyEvent.KEYCODE_BACK&&event.getRepeatCount()==0)

{

//当用户点击返回键是 通知Unity开始在"/mnt/sdcard/Android/data/com.xys/files";路径中读取图片资源,并且现在在Unity中

UnityPlayer.UnitySendMessage("Main Camera","message",FILE_NAME);

}

returnsuper.onKeyDown(keyCode,event);

}

}

注解1:主要是路径”/mnt/sdcard/Android/data/com.xys/files”,如下图所示,我们在这里把文件保存在这个路径下。为什么要把图片2进制文件写在这里呢? 还记得以前MOMO给大家说过在Unity中访问Android或IOS本地2进制文件时用到的这个路径,

Application.persistentDataPath   该路径等价于 /mnt/sdcard/Android/data/com.xys/files ,当然后者的包名是对应的工程包名,这样在Unity中可以找到对应裁剪后的图片文件,并且显示在Unity中。

AndroidManifest.xml  这个文件也没什么好说的,大家看看吧。

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

package="com.xys"

android:versionCode="1"

android:versionName="1.0">

android:icon="@drawable/ic_launcher"

android:label="@string/app_name">

android:name=".UnityTestActivity"

android:label="@string/app_name">

android:name=".WebViewActivity">

然后把上面的Android工程打包做成插件放在Unity中。如下图所示,这个我的Unity工程中对应的路径。如果看不懂的朋友请看我之前的文章哈。

然后看Test.cs脚本,它直接挂在摄像机身上。

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

usingUnityEngine;

usingSystem.Collections;

usingSystem.IO;

publicclassTest:MonoBehaviour

{

publicGUISkinskin;

Texturetexture;

voidUpdate()

{

if(Input.GetKeyDown(KeyCode.Escape)||Input.GetKeyDown(KeyCode.Home))

{

Application.Quit();

}

}

voidOnGUI()

{

GUI.skin=skin;

if(GUILayout.Button("打开手机相册"))

{

//调用我们制作的Android插件打开手机相册

AndroidJavaClassjc=newAndroidJavaClass("com.unity3d.player.UnityPlayer");

AndroidJavaObjectjo=jc.GetStatic("currentActivity");

jo.Call("TakePhoto","takeSave");

}

if(GUILayout.Button("打开手机摄像机"))

{

//调用我们制作的Android插件打开手机摄像机

AndroidJavaClassjc=newAndroidJavaClass("com.unity3d.player.UnityPlayer");

AndroidJavaObjectjo=jc.GetStatic("currentActivity");

jo.Call("TakePhoto","takePhoto");

}

if(texture!=null)

{

//注意! 我们在这里绘制Texture对象,该对象是通过

//我们制作的Android插件得到的,当这个对象不等于空的时候

//直接绘制。

GUI.DrawTexture(newRect(100,300,300,300),texture);

}

}

voidmessgae(stringstr)

{

//在Android插件中通知Unity开始去指定路径中找图片资源

StartCoroutine(LoadTexture(str));

}

IEnumeratorLoadTexture(stringname)

{

//注解1

stringpath="file://"+Application.persistentDataPath+"/"+name;

WWWwww=newWWW(path);

while(!www.isDone)

{

}

yieldreturnwww;

//为贴图赋值

texture=www.texture;

}

}

注解1:请大家一定要注意这个路径的写法, 前面一定要加 “File://” 不然无法读取。OK说了这么多我们看看这个项目运行的效果,激动人心的时刻来临啦 嚯嚯嚯嚯!!!

1.首次进入的画面, 这里的图片是我刚刚从相册选择的

2.打开相册我们选择一张图片

3. 选择一张图片,我们进行裁剪

最后我们返回到Unity中界面。新的图片Unity已经完成读取,界面上已经修改成刚刚我裁剪的啦,哇咔咔。 怎么样,还不错啦? 哈哈后。这个做用户头像肯定给力 蛤蛤。

如果点击打开摄像机按钮,拍照完毕后会提示裁剪,裁减完毕返回到Unity界面中同样能看到效果。

最后MOMO将本篇博文的源码放出来,  源码包括Android的工程 与Unity的工程,雨松MOMO祝大家学习愉快,大家互相学习互相进步,加油哇咔咔,啦啦啦。

最后编辑:2015-07-03作者:雨松MOMO

专注移动互联网,Unity3D游戏开发

捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39548541/article/details/112023468

智能推荐

874计算机科学基础综合,2018年四川大学874计算机科学专业基础综合之计算机操作系统考研仿真模拟五套题...-程序员宅基地

文章浏览阅读1.1k次。一、选择题1. 串行接口是指( )。A. 接口与系统总线之间串行传送,接口与I/0设备之间串行传送B. 接口与系统总线之间串行传送,接口与1/0设备之间并行传送C. 接口与系统总线之间并行传送,接口与I/0设备之间串行传送D. 接口与系统总线之间并行传送,接口与I/0设备之间并行传送【答案】C2. 最容易造成很多小碎片的可变分区分配算法是( )。A. 首次适应算法B. 最佳适应算法..._874 计算机科学专业基础综合题型

XShell连接失败:Could not connect to '192.168.191.128' (port 22): Connection failed._could not connect to '192.168.17.128' (port 22): c-程序员宅基地

文章浏览阅读9.7k次,点赞5次,收藏15次。连接xshell失败,报错如下图,怎么解决呢。1、通过ps -e|grep ssh命令判断是否安装ssh服务2、如果只有客户端安装了,服务器没有安装,则需要安装ssh服务器,命令:apt-get install openssh-server3、安装成功之后,启动ssh服务,命令:/etc/init.d/ssh start4、通过ps -e|grep ssh命令再次判断是否正确启动..._could not connect to '192.168.17.128' (port 22): connection failed.

杰理之KeyPage【篇】_杰理 空白芯片 烧入key文件-程序员宅基地

文章浏览阅读209次。00000000_杰理 空白芯片 烧入key文件

一文读懂ChatGPT,满足你对chatGPT的好奇心_引发对chatgpt兴趣的表述-程序员宅基地

文章浏览阅读475次。2023年初,“ChatGPT”一词在社交媒体上引起了热议,人们纷纷探讨它的本质和对社会的影响。就连央视新闻也对此进行了报道。作为新传专业的前沿人士,我们当然不能忽视这一热点。本文将全面解析ChatGPT,打开“技术黑箱”,探讨它对新闻与传播领域的影响。_引发对chatgpt兴趣的表述

中文字符频率统计python_用Python数据分析方法进行汉字声调频率统计分析-程序员宅基地

文章浏览阅读259次。用Python数据分析方法进行汉字声调频率统计分析木合塔尔·沙地克;布合力齐姑丽·瓦斯力【期刊名称】《电脑知识与技术》【年(卷),期】2017(013)035【摘要】该文首先用Python程序,自动获取基本汉字字符集中的所有汉字,然后用汉字拼音转换工具pypinyin把所有汉字转换成拼音,最后根据所有汉字的拼音声调,统计并可视化拼音声调的占比.【总页数】2页(13-14)【关键词】数据分析;数据可..._汉字声调频率统计

linux输出信息调试信息重定向-程序员宅基地

文章浏览阅读64次。最近在做一个android系统移植的项目,所使用的开发板com1是调试串口,就是说会有uboot和kernel的调试信息打印在com1上(ttySAC0)。因为后期要使用ttySAC0作为上层应用通信串口,所以要把所有的调试信息都给去掉。参考网上的几篇文章,自己做了如下修改,终于把调试信息重定向到ttySAC1上了,在这做下记录。参考文章有:http://blog.csdn.net/longt..._嵌入式rootfs 输出重定向到/dev/console

随便推点

uniapp 引入iconfont图标库彩色symbol教程_uniapp symbol图标-程序员宅基地

文章浏览阅读1.2k次,点赞4次,收藏12次。1,先去iconfont登录,然后选择图标加入购物车 2,点击又上角车车添加进入项目我的项目中就会出现选择的图标 3,点击下载至本地,然后解压文件夹,然后切换到uniapp打开终端运行注:要保证自己电脑有安装node(没有安装node可以去官网下载Node.js 中文网)npm i -g iconfont-tools(mac用户失败的话在前面加个sudo,password就是自己的开机密码吧)4,终端切换到上面解压的文件夹里面,运行iconfont-tools 这些可以默认也可以自己命名(我是自己命名的_uniapp symbol图标

C、C++ 对于char*和char[]的理解_c++ char*-程序员宅基地

文章浏览阅读1.2w次,点赞25次,收藏192次。char*和char[]都是指针,指向第一个字符所在的地址,但char*是常量的指针,char[]是指针的常量_c++ char*

Sublime Text2 使用教程-程序员宅基地

文章浏览阅读930次。代码编辑器或者文本编辑器,对于程序员来说,就像剑与战士一样,谁都想拥有一把可以随心驾驭且锋利无比的宝剑,而每一位程序员,同样会去追求最适合自己的强大、灵活的编辑器,相信你和我一样,都不会例外。我用过的编辑器不少,真不少~ 但却没有哪款让我特别心仪的,直到我遇到了 Sublime Text 2 !如果说“神器”是我能给予一款软件最高的评价,那么我很乐意为它封上这么一个称号。它小巧绿色且速度非

对10个整数进行按照从小到大的顺序排序用选择法和冒泡排序_对十个数进行大小排序java-程序员宅基地

文章浏览阅读4.1k次。一、选择法这是每一个数出来跟后面所有的进行比较。2.冒泡排序法,是两个相邻的进行对比。_对十个数进行大小排序java

物联网开发笔记——使用网络调试助手连接阿里云物联网平台(基于MQTT协议)_网络调试助手连接阿里云连不上-程序员宅基地

文章浏览阅读2.9k次。物联网开发笔记——使用网络调试助手连接阿里云物联网平台(基于MQTT协议)其实作者本意是使用4G模块来实现与阿里云物联网平台的连接过程,但是由于自己用的4G模块自身的限制,使得阿里云连接总是无法建立,已经联系客服返厂检修了,于是我在此使用网络调试助手来演示如何与阿里云物联网平台建立连接。一.准备工作1.MQTT协议说明文档(3.1.1版本)2.网络调试助手(可使用域名与服务器建立连接)PS:与阿里云建立连解释,最好使用域名来完成连接过程,而不是使用IP号。这里我跟阿里云的售后工程师咨询过,表示对应_网络调试助手连接阿里云连不上

<<<零基础C++速成>>>_无c语言基础c++期末速成-程序员宅基地

文章浏览阅读544次,点赞5次,收藏6次。运算符与表达式任何高级程序设计语言中,表达式都是最基本的组成部分,可以说C++中的大部分语句都是由表达式构成的。_无c语言基础c++期末速成