Unity3D研究院之打开照相机与本地相册进行裁剪显示
来源:互联网 发布:如何通过网络定位找人 编辑:程序博客网 时间:2024/05/16 17:52
最近做项目需要用到这个功能,就是在Unity中调用Android本地相册或直接打开摄像机拍照并且裁剪一部分用于用户头像,今天研究了一下,那么研究出成果了MOMO一定要分享给大家。Unity与Android的交互还有谁不会?? 如果有不会的朋友请看MOMO之前的文章喔,Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)这里有关交互的方式就不详细说明,主要将如何在Unity中打开摄像机、在Unity中打开本地相册,选一个照片后如何进行裁剪,最后将图片转换成Texture显示在U3D的世界当中。
首先看看Eclipse中的Android插件部分,我的包名是com.xys请大家与MOMO保持一致,Unity工程中也需要是这个包名噢。
UnityTestActivity.java 这个类是Unity的插件主类,在这里调用是打开摄像机 还是本地相册的方法。
package com.xys; import android.content.Context;import android.content.Intent;import android.os.Bundle;import com.unity3d.player.UnityPlayerActivity; public class UnityTestActivity extends UnityPlayerActivity {//public class UnityTestActivity extends Activity { Context mContext = null; @Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mContext = this;} //Unity中会调用这个方法,用于区分打开摄像机 开始本地相册 public void TakePhoto(String str) { Intent intent = new Intent(mContext,WebViewActivity.class); intent.putExtra("type", str); this.startActivity(intent); }}
然后是WebViewActivity.java 这里主要处理用户打开摄像机或本地相册后如何进行裁剪图片,并且把裁剪的图片储存在本地文件中。
package com.xys; import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException; import com.unity3d.player.UnityPlayer; import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.view.KeyEvent;import android.widget.ImageView; public class WebViewActivity extends Activity{ ImageView imageView = null; 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/*"; public final static String FILE_NAME = "image.png"; public final static String DATA_URL = "/data/data/"; @Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); imageView = (ImageView) this.findViewById(R.id.imageID); String type = this.getIntent().getStringExtra("type"); //在这里判断是打开本地相册还是直接照相if(type.equals("takePhoto")){ Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "temp.jpg"))); startActivityForResult(intent, PHOTOHRAPH);}else{ Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED); startActivityForResult(intent, PHOTOZOOM);} } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == NONE) return; // 拍照 if (requestCode == PHOTOHRAPH) { //设置文件保存路径这里放在跟目录下 File picture = new File(Environment.getExternalStorageDirectory() + "/temp.jpg"); startPhotoZoom(Uri.fromFile(picture)); } if (data == null) return; // 读取相册缩放图片 if (requestCode == PHOTOZOOM) { startPhotoZoom(data.getData()); } // 处理结果 if (requestCode == PHOTORESOULT) { Bundle extras = data.getExtras(); if (extras != null) { Bitmap photo = extras.getParcelable("data"); imageView.setImageBitmap(photo); try { SaveBitmap(photo);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} } } super.onActivityResult(requestCode, resultCode, data); } public void startPhotoZoom(Uri uri) { Intent intent = new Intent("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); } public void SaveBitmap(Bitmap bitmap) throws IOException { FileOutputStream fOut = null; //注解1String path = "/mnt/sdcard/Android/data/com.xys/files";try { //查看这个路径是否存在, //如果并没有这个路径, //创建这个路径 File destDir = new File(path); if (!destDir.exists()) { destDir.mkdirs(); } fOut = new FileOutputStream(path + "/" + FILE_NAME) ;} catch (FileNotFoundException e) {e.printStackTrace();}//将Bitmap对象写入本地路径中,Unity在去相同的路径来读取这个文件bitmap.compress(Bitmap.CompressFormat.PNG, 100, fOut);try {fOut.flush();} catch (IOException e) {e.printStackTrace();}try {fOut.close();} catch (IOException e) {e.printStackTrace();}} @Overridepublic boolean onKeyDown(int keyCode, KeyEvent event){if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0){ //当用户点击返回键是 通知Unity开始在"/mnt/sdcard/Android/data/com.xys/files";路径中读取图片资源,并且现在在Unity中 UnityPlayer.UnitySendMessage("Main Camera","message",FILE_NAME); }return super.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 这个文件也没什么好说的,大家看看吧。
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xys" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".UnityTestActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".WebViewActivity"> </activity> </application> <!-- 连接互联网的权限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- SDCard中创建与删除文件权限 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><!-- SDCard写入数据权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/></manifest>
然后把上面的Android工程打包做成插件放在Unity中。如下图所示,这个我的Unity工程中对应的路径。如果看不懂的朋友请看我之前的文章哈。
然后看Test.cs脚本,它直接挂在摄像机身上。
using UnityEngine;using System.Collections;using System.IO; public class Test : MonoBehaviour{public GUISkin skin;Texture texture; void Update (){ if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Home)) { Application.Quit(); }} void OnGUI(){ GUI.skin = skin; if(GUILayout.Button("打开手机相册")){ //调用我们制作的Android插件打开手机相册 AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); jo.Call("TakePhoto","takeSave"); }if(GUILayout.Button("打开手机摄像机")){ //调用我们制作的Android插件打开手机摄像机 AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); jo.Call("TakePhoto","takePhoto"); }if(texture != null){//注意! 我们在这里绘制Texture对象,该对象是通过//我们制作的Android插件得到的,当这个对象不等于空的时候//直接绘制。GUI.DrawTexture(new Rect(100,300,300,300),texture);}} void messgae(string str){//在Android插件中通知Unity开始去指定路径中找图片资源StartCoroutine(LoadTexture(str)); } IEnumerator LoadTexture(string name) {//注解1string path = "file://" + Application.persistentDataPath +"/" + name; WWW www = new WWW(path);while (!www.isDone){ }yield return www;//为贴图赋值texture = www.texture; }}
注解1:请大家一定要注意这个路径的写法, 前面一定要加 “File://” 不然无法读取。OK说了这么多我们看看这个项目运行的效果,激动人心的时刻来临啦 嚯嚯嚯嚯!!!
1.首次进入的画面, 这里的图片是我刚刚从相册选择的
2.打开相册我们选择一张图片
3. 选择一张图片,我们进行裁剪
最后我们返回到Unity中界面。新的图片Unity已经完成读取,界面上已经修改成刚刚我裁剪的啦,哇咔咔。 怎么样,还不错啦? 哈哈后。这个做用户头像肯定给力 蛤蛤。
- 本文固定链接: http://www.xuanyusong.com/archives/1480
- 转载请注明: 雨松MOMO 2012年07月13日 于 雨松MOMO程序研究院 发表
- Unity3D研究院之打开照相机与本地相册进行裁剪显示
- Unity3D研究院之打开照相机与本地相册进行裁剪显示
- Unity3D研究院之打开照相机与本地相册进行裁剪显示
- Unity3打开照相机与本地相册进行裁剪显示
- IOS研究院之打开照相机与本地相册选择图片
- IOS研究院之打开照相机与本地相册选择图片
- IOS研究院之打开照相机与本地相册选择图片
- IOS研究院之打开照相机与本地相册选择图片(六)
- IOS研究之打开照相机与本地相册选择图片
- 打开照相机与本地相册选择图片
- IOS 打开照相机与本地相册选择图片(六)
- IOS学习:打开照相机与本地相册选择图片
- IOS打开照相机与本地相册选择图片
- IOS打开照相机与本地相册选择图片
- iOS打开照相机与本地相册选择图片
- iOS-打开照相机&打开本地相册&图片上传
- 访问本地相册、照相机
- Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)
- Unity接入微信SDK——iOS(接入微信SDK)
- 改善异步调用代码的写法
- Atom Teletype:我们一起来写代码吧
- java面试题
- GMSSL SM9-签名验签流程
- Unity3D研究院之打开照相机与本地相册进行裁剪显示
- URL中“#”、 “?”、“&”号的作用
- Springboot + Thymeleaf,用mvn spring-boot:run启动则找不到模板文件
- 拦截器
- 页面ajax提交form 表单 以及后台接收
- 解决进入Activity默认焦点选中第一个EditText,并弹出软键盘。
- Android 系统服务一览表
- 洛谷3613:睡觉困难综合症(LCT+机巧的位运算)
- 生成进度条(动态生成文件,并前端显示生成进度)