网上关于cocos 和 camera交互的并不多,有些细节还没有处理,权当备注一下。
参考org.cocos2dx.lib里的Cocos2dxWebView和Cocos2dxVideoView的实现。
原理:创建一个cameraSurfaceView加在cocos2dActivity的mFrameLayout的下层。
通过ClippingNode,把当前游戏mGLSurfaceView裁剪,可以露出自定义的cameraSurfaceView。
首先要把mGLSurfaceView弄成透明的:
修改这两处就可以:
在libcocos2dx项目的org.cocos2dx.lib项目中的Cocos2dxActivity.java文件中,修改init()方法:
this.mGLSurfaceView.setZOrderOnTop(true); this.mGLSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT); this.mGLSurfaceView.setEGLConfigChooser(8,8,16,0);
在libcocos2dx项目的org.cocos2dx.lib项目中的Cocos2dxRenderer.java文件中,修改onSurfaceCreated()方法:
pGL10.glDisable(GL10.GL_DITHER); pGL10.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST); pGL10.glClearColor(0,0); pGL10.glEnable(GL10.GL_CULL_FACE); pGL10.glShadeModel(GL10.GL_SMOOTH);
具体可以参考: http://www.cocoachina.com/bbs/read.php?tid=224544&page=1&toread=1#tpc
其中CameraView里面旋转和保存比较蛋疼。
创建CameraView的时候要回调再设置CameraView的大小,保持跟Camera预览的大小比例一致,否者图像会变形拉伸:
我这里是720X1280的分辨率,以及按高度适配.
设置CameraView的大小:
public void cameraHasOpened() { WindowManager wm = mActivity.getWindowManager(); int screenWidth = wm.getDefaultDisplay().getWidth(); int screenHeight = wm.getDefaultDisplay().getHeight(); Point disPos = new Point(screenWidth/2-mSurfacePosX,screenHeight/2 - mSurfacePosY); Camera camera = mCameraView.getCamera(); int width = mSurfaceWidth; int height = mSurfaceWidth; if(camera != null) { Size size = camera.getParameters().getPreviewSize(); height = (int) (1.0F * width * size.width /size.height); } Log.e("width: height:",width+ "--- " +height + "----- " +disPos.x + " ---- "+disPos.y + "[sw:"+screenWidth + ","+screenHeight+"]"); FrameLayout.LayoutParams lParams = new FrameLayout.LayoutParams( width,height,Gravity.CENTER); // set size lParams.setMargins(0,disPos.y,disPos.x,0); mCameraView.setLayoutParams(lParams); }
设置CameraView的位置:
public void calcCameraSizeAndPos(int width,int posX,int posY) { //设计的分辨率 int designWidth = 720; int designHeight = 1280; //按高度进行适配 WindowManager wm = mActivity.getWindowManager(); int screenWidth = wm.getDefaultDisplay().getWidth(); int screenHeight = wm.getDefaultDisplay().getHeight(); float rate = 1.0f * screenHeight / designHeight; mSurfaceWidth = (int)(rate * width); int desCenPosX = designWidth / 2; int desCenPosY = designHeight / 2; int disDesCenPosX = desCenPosX - posX; int disDesCenPosY = desCenPosY - posY; int curCenPosX = screenWidth/2; int curCenPosY = screenHeight/2; mSurfacePosX = (int)(curCenPosX + rate * disDesCenPosX); mSurfacePosY = (int)(curCenPosY + rate * disDesCenPosY); }
最后当保存完图片的时候发现第一次调用Sprite::create(savedFileName)的时候,图像一直是空但是图片是保存成功的,最后绕了一下,手动先创建texture,image,
然后再创建sprite就好了。
//保存图片后native的回调
void TestScene::replaceCameraPic(bool isSuc,const string& filename) { static int saveTime = 0; log("replaceCameraPic"); if (isSuc && FileUtils::getInstance()->isFileExist(filename) == true) { g_userSave->setStringForKey("cameraFile",filename); scheduleOnce([&](float dt){ auto cFileName = g_userSave->getStringForKey("cameraFile"); if(m_isFirstSet) { Director::getInstance()->getTextureCache()->addImage(cFileName); auto image = new (std::nothrow) Image(); bool bRet = image->initWithImageFile(cFileName); auto texture = new (std::nothrow) Texture2D(); if (texture && texture->initWithImage(image)) { Rect rect = Rect::ZERO; rect.size = texture->getContentSize(); auto frame = SpriteFrame::createWithTexture(texture,rect); m_iconSp->setSpriteFrame(frame); delete image; } m_isFirstSet = false; } else { auto sp = Sprite::create(cFileName); m_iconSp->setSpriteFrame(sp->getSpriteFrame()); } auto curSize = m_iconSp->getContentSize(); m_iconSp->setScale(380 / curSize.width); },0.1f,"xx"); } else { log("save file Failed"); } }本地调用:
//拍照后的回调 #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) UICameraViewHelp::getInstance()->setImageSaveCallBack(std::bind(&TestScene::replaceCameraPic,this,std::placeholders::_1,std::placeholders::_2)); #endif //打开摄像头 auto btn = MySprite::create("tuijian.png",[&](Node* node){ log("createCamera"); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) UICameraViewHelp::getInstance()->createCamera(380,360,640); #endif }); btn->setAnchorPoint(Vec2(1,0)); btn->setPosition(vec2Creater(0,-300)); addChild(btn); //拍照 auto btn2 = MySprite::create("sound_1.png",[&](Node* node){ log("takeCameraPic"); time_t rawtime; struct tm * timeinfo; time(&rawtime); timeinfo = localtime(&rawtime); string filename = String::createWithFormat("%d_%d_%d_%d_%d_%d.png",timeinfo->tm_year + 1900,timeinfo->tm_mon,timeinfo->tm_mday,timeinfo->tm_hour,timeinfo->tm_min,timeinfo->tm_sec)->getCString(); filename = FileUtils::getInstance()->getWritablePath() + filename; #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) UICameraViewHelp::getInstance()->takeCameraPic(filename); #endif }); btn2->setAnchorPoint(Vec2(1,0)); btn2->setPosition(vec2Creater(0,-400)); addChild(btn2); //切换前后摄像头 auto btn3 = MySprite::create("sound_2.png",[&](Node* node){ log("switchCamera"); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) UICameraViewHelp::getInstance()->switchCamera(); #endif }); btn3->setAnchorPoint(Vec2(1,0)); btn3->setPosition(vec2Creater(0,-500)); addChild(btn3); //删除照相机 auto btn4 = MySprite::create("pingfen2.png",[&](Node* node){ log("destoryCamera"); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) UICameraViewHelp::getInstance()->destoryCamera(); #endif }); btn4->setAnchorPoint(Vec2(1,0)); btn4->setPosition(vec2Creater(0,-600)); addChild(btn4);
c++代码:
UICameraViewHelp.h
#pragma once #include <iostream> using namespace std; class UICameraViewHelp { public: static UICameraViewHelp* getInstance(); enum class EventType { CAMERA_CREATE = 0,CAMERA_TAKEPIC = 1,CAMERA_SIWTCH = 2,CAMERA_DESTORY = 3 }; void createCamera(int width,int posx,int posY); void takeCameraPic(const string& fileName); void switchCamera(); void destoryCamera(); void setImageSaveCallBack(std::function<void(bool,string)> callBack){ imageSaveCallBack = callBack; }; public: std::function<void(bool,string)> imageSaveCallBack; private: static UICameraViewHelp* m_instance; };
UICameraViewHelp-android.cpp
#include "UICameraViewHelp.h" #include <stdlib.h> #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include <jni.h> #include <string> #include "jni/JniHelper.h" #define CLASS_NAME "cn/edaysoft/toolkit/CameraViewHelp" #endif USING_NS_CC; extern "C" { void Java_cn_edaysoft_toolkit_CameraViewHelp_imgeSaved(JNIEnv * env,jobject obj,jboolean isSuc,jstring jFileName) { auto charFileName = env->GetStringUTFChars(jFileName,NULL); std::string fileName = charFileName; if (UICameraViewHelp::getInstance()->imageSaveCallBack) { UICameraViewHelp::getInstance()->imageSaveCallBack(isSuc,fileName); } env->ReleaseStringUTFChars(jFileName,charFileName); } } UICameraViewHelp* UICameraViewHelp::m_instance = nullptr; UICameraViewHelp* UICameraViewHelp::getInstance() { if (m_instance == nullptr) { m_instance = new UICameraViewHelp; } return m_instance; } void UICameraViewHelp::createCamera(int width,int posY) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo t; if (JniHelper::getStaticMethodInfo(t,CLASS_NAME,"handle_createCameraView","(III)V")) { t.env->CallStaticVoidMethod(t.classID,t.methodID,width,posx,posY); t.env->DeleteLocalRef(t.classID); } #endif } void UICameraViewHelp::takeCameraPic(const string& fileName) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo t; if (JniHelper::getStaticMethodInfo(t,"handle_takeCameraPic","(Ljava/lang/String;)V")) { jstring stringArg = t.env->NewStringUTF(fileName.c_str()); t.env->CallStaticVoidMethod(t.classID,stringArg); t.env->DeleteLocalRef(t.classID); t.env->DeleteLocalRef(stringArg); } #endif } void UICameraViewHelp::switchCamera() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo t; if (JniHelper::getStaticMethodInfo(t,"handle_switchCamera","()V")) { t.env->CallStaticVoidMethod(t.classID,t.methodID); t.env->DeleteLocalRef(t.classID); } #endif } void UICameraViewHelp::destoryCamera() { #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo t; if (JniHelper::getStaticMethodInfo(t,"handle_removeCamera",t.methodID); t.env->DeleteLocalRef(t.classID); } #endif }
java文件:
CameraViewHelp.java
package cn.edaysoft.toolkit; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.cocos2dx.lib.Cocos2dxActivity; import org.cocos2dx.lib.Cocos2dxVideoHelper; import org.cocos2dx.lib.Cocos2dxVideoView; import org.cocos2dx.lib.Cocos2dxWebView; import org.cocos2dx.lib.Cocos2dxWebViewHelper; import cn.edaysoft.toolkit.CameraSurfaceView.CamOpenCallback; import android.graphics.Point; import android.graphics.Rect; import android.hardware.Camera; import android.hardware.Camera.Size; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import android.util.SparseArray; import android.view.Gravity; import android.view.WindowManager; import android.widget.FrameLayout; /** * @author eday * */ /** * @author eday * */ public class CameraViewHelp implements CamOpenCallback { private final static int Camera_CREATE = 0; private final static int Camera_TAKEPIC = 1; private final static int Camera_SWITCH = 2; private final static int Camera_REMOVE = 3; private static int mSurfaceWidth = 0; private static int mSurfacePosX = 0; private static int mSurfacePosY = 0; private static FrameLayout mLayout; private Cocos2dxActivity mActivity = null; private CameraSurfaceView mCameraView = null; private static CameraViewHelp mInstance = null; static CameraHandler mCameraHandler = null; public static native void imgeSaved(boolean isSuc,String fileName); public CameraViewHelp(Cocos2dxActivity activity,FrameLayout layout) { mInstance = this; mActivity = activity; mLayout = layout; CameraViewHelp.mCameraHandler = new CameraHandler(this); } public static CameraViewHelp getInstance() { return mInstance; } private CameraSurfaceView getCameraView() { return mCameraView; } static class CameraHandler extends Handler{ WeakReference<CameraViewHelp> mReference; CameraHandler(CameraViewHelp helper){ mReference = new WeakReference<CameraViewHelp>(helper); } @Override public void handleMessage(Message msg) { switch (msg.what) { case Camera_CREATE: { CameraViewHelp helper = mReference.get(); Point p = (Point)(msg.obj); mInstance.calcCameraSizeAndPos(msg.arg1,p.x,p.y); helper.createCameraView(); break; } case Camera_TAKEPIC: { CameraViewHelp helper = mReference.get(); String fileName = (String)(msg.obj); helper.takeCameraPic(fileName); break; } case Camera_SWITCH: { CameraViewHelp helper = mReference.get(); helper.switchCamera(); break; } case Camera_REMOVE:{ CameraViewHelp helper = mReference.get(); helper.removeCamera(); break; } default: break; } super.handleMessage(msg); } } public void calcCameraSizeAndPos(int width,int posY) { //设计的分辨率 int designWidth = 720; int designHeight = 1280; //按高度进行适配 WindowManager wm = mActivity.getWindowManager(); int screenWidth = wm.getDefaultDisplay().getWidth(); int screenHeight = wm.getDefaultDisplay().getHeight(); float rate = 1.0f * screenHeight / designHeight; mSurfaceWidth = (int)(rate * width); int desCenPosX = designWidth / 2; int desCenPosY = designHeight / 2; int disDesCenPosX = desCenPosX - posX; int disDesCenPosY = desCenPosY - posY; int curCenPosX = screenWidth/2; int curCenPosY = screenHeight/2; mSurfacePosX = (int)(curCenPosX + rate * disDesCenPosX); mSurfacePosY = (int)(curCenPosY + rate * disDesCenPosY); } public static void handle_createCameraView(int width,int posY) { Log.e("handle_createCameraView"," " + width + " "+posX + " " + posY); if(mInstance.getCameraView() == null) { Message msg = new Message(); msg.what = Camera_CREATE; msg.arg1 = width; Point pos = new Point(posX,posY); msg.obj = pos; mCameraHandler.sendMessage(msg); } } @SuppressWarnings("unused") public void createCameraView() { mActivity.runOnUiThread(new Runnable() { @Override public void run() { mCameraView = new CameraSurfaceView(mActivity,mInstance); mLayout.addView(mCameraView); // mCameraView.setZOrderOnTop(true); } }); } public void cameraHasOpened() { WindowManager wm = mActivity.getWindowManager(); int screenWidth = wm.getDefaultDisplay().getWidth(); int screenHeight = wm.getDefaultDisplay().getHeight(); Point disPos = new Point(screenWidth/2-mSurfacePosX,0); mCameraView.setLayoutParams(lParams); } public static void handle_takeCameraPic(String fileName) { Log.e("handle_takeCameraPic",fileName); Message msg = new Message(); msg.what = Camera_TAKEPIC; msg.obj = fileName; mCameraHandler.sendMessage(msg); } public void takeCameraPic(String fileName) { if(mCameraView!=null) { mCameraView.doTakePicture(fileName); } } public static void handle_switchCamera() { Log.e("handle_switchCamera",""); Message msg = new Message(); msg.what = Camera_SWITCH; mCameraHandler.sendMessage(msg); } public void switchCamera() { if(mCameraView!=null) { mCameraView.doSwitchBackOrFront(); } } public static void handle_removeCamera() { Log.e("handle_removeCamera",""); Message msg = new Message(); msg.what = Camera_REMOVE; mCameraHandler.sendMessage(msg); } public void removeCamera() { if(mCameraView!=null) { mCameraView.doDestoryCamera(); mLayout.removeView(mCameraView); mCameraView = null; } } }
CameraSurfaceView.java
package cn.edaysoft.toolkit; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import org.cocos2dx.lib.Cocos2dxActivity; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.ImageFormat; import android.graphics.Matrix; import android.hardware.Camera; import android.hardware.Camera.CameraInfo; import android.hardware.Camera.PictureCallback; import android.hardware.Camera.ShutterCallback; import android.hardware.Camera.Size; import android.media.ExifInterface; import android.net.Uri; import android.os.Environment; import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback { public interface CamOpenCallback { public void cameraHasOpened(); } private static final String TAG = CameraSurfaceView.class.getSimpleName(); private Camera mCamera = null; private boolean isPreviewing; private SurfaceHolder mSurfaceHolder; private Camera.Parameters mParams; private float mPreviwRate = -1f; private CamOpenCallback mCallBack = null; private String fileName = ""; private int cameraPosition = 0;//1代表前置摄像头,0代表后置摄像头 private boolean mSaving = false; private Cocos2dxActivity mAcvitity; public CameraSurfaceView(Cocos2dxActivity activity,CamOpenCallback callBack) { super(activity); // TODO Auto-generated constructor stub mAcvitity = activity; mSurfaceHolder = this.getHolder(); mSurfaceHolder.addCallback(this); isPreviewing = false; mCallBack = callBack; } public Camera getCamera() { return mCamera; } @Override public void surfaceChanged(SurfaceHolder holder,int format,int width,int height) { // TODO Auto-generated method stub } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub doOpenCamera(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub doDestoryCamera(); } /**打开Camera * @param callback */ @SuppressWarnings("deprecation") public void doOpenCamera(){ Log.i(TAG,"Camera open...."); mCamera = Camera.open(); // mCamera.enableShutterSound(false); Log.i(TAG,"Camera open over...."); // float previewRate = DisplayUtil.getScreenRate(this); doStartPreview(mSurfaceHolder,1); if(mCallBack != null) { mCallBack.cameraHasOpened(); } } /**开启预览 * @param holder * @param previewRate */ public void doStartPreview(SurfaceHolder holder,float previewRate){ Log.i(TAG,"doStartPreview..."); if(isPreviewing){ mCamera.stopPreview(); return; } // List<Camera.Size> pictureSizes = mCamera.getParameters().getSupportedPictureSizes(); // List<Camera.Size> previewSizes = mCamera.getParameters().getSupportedPreviewSizes(); // // for (int i=0; i<pictureSizes.size(); i++) { // Camera.Size pSize = pictureSizes.get(i); // Log.i(TAG+"-initCamera","-PictureSize.width = "+pSize.width+"-PictureSize.height = "+pSize.height); // } // // for (int i=0; i<previewSizes.size(); i++) { // Camera.Size pSize = previewSizes.get(i); // Log.i(TAG+"-initCamera","-previewSize.width = "+pSize.width+"-previewSize.height = "+pSize.height); // } // try { mParams = mCamera.getParameters(); //重新get一次 Log.i(TAG,"初始设置:PreviewSize--With = " + mParams.getPreviewSize().width + "Height = " + mParams.getPreviewSize().height); Log.i(TAG,"初始设置:PictureSize--With = " + mParams.getPictureSize().width + "Height = " + mParams.getPictureSize().height); mParams= mCamera.getParameters(); //获取摄像头参数 // // 设置预览照片时每秒显示多少帧的最小值和最大值[华为手机设置后会黑屏] // mParams.setPreviewFpsRange(4,10); // // 设置图片格式 mParams.setPictureFormat(ImageFormat.JPEG); // 设置JPG照片的质量 mParams.set("jpeg-quality",85); // 设置照片的大小 Size pictureSize = getOptimalPreviewSize(mParams.getSupportedPictureSizes(),4,3); mParams.setPictureSize(pictureSize.width,pictureSize.height); Size previewSize = getOptimalPreviewSize(mParams.getSupportedPreviewSizes(),3); mParams.setPreviewSize(previewSize.width,previewSize.height); Log.i(TAG,"设置:PreviewSize--With = " + previewSize.width + "Height = " + previewSize.height); Log.i(TAG,"设置:PictureSize--With = " +pictureSize.width + "Height = " + pictureSize.height); // 横竖屏镜头自动调整 if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) { mParams.set("orientation","portrait"); // mCamera.setDisplayOrientation(90); // 在2.2以上可以使用 } else// 如果是横屏 { mParams.set("orientation","landscape"); // mCamera.setDisplayOrientation(0); // 在2.2以上可以使用 } mCamera.setParameters(mParams); // 通过SurfaceView显示取景画面 mCamera.setPreviewDisplay(mSurfaceHolder); // 开始预览 mCamera.startPreview(); isPreviewing = true; mPreviwRate = previewRate; mParams = mCamera.getParameters(); //重新get一次 Log.i(TAG,"最终设置:PreviewSize--With = " + mParams.getPreviewSize().width + "Height = " + mParams.getPreviewSize().height); Log.i(TAG,"最终设置:PictureSize--With = " + mParams.getPictureSize().width + "Height = " + mParams.getPictureSize().height); } catch (Exception e) { e.printStackTrace(); } } public void doDestoryCamera() { if(null != mCamera) { mCamera.setPreviewCallback(null); //!!这个必须在前,不然退出出错 mCamera.stopPreview(); isPreviewing = false; mCamera.release(); mCamera = null; } } @SuppressWarnings("deprecation") public void doTakePicture(String fileName) { this.fileName = fileName; if(mSaving == false && isPreviewing && (mCamera != null)) { mSaving = true; mCamera.takePicture(mShutterCallback,null,mJpegPictureCallback); // takePic("/storage/emulated/0/DCIM/Screenshots/"+fileName); } } void takePic(String fileName) { mSaving = false; this.setDrawingCacheEnabled(true); Bitmap bitmap = Bitmap.createBitmap(this.getDrawingCache()); this.setDrawingCacheEnabled(false); Log.e(TAG,"saveBitmap:pngName = " + fileName); try { FileOutputStream fout = new FileOutputStream(fileName); BufferedOutputStream bos = new BufferedOutputStream(fout); bitmap.compress(Bitmap.CompressFormat.PNG,100,bos); bos.flush(); bos.close(); CameraViewHelp.getInstance().imgeSaved(true,fileName); Log.i(TAG,"saveBitmap成功"); } catch (IOException e) { // TODO Auto-generated catch block Log.i(TAG,"saveBitmap:失败"); CameraViewHelp.getInstance().imgeSaved(false,fileName); e.printStackTrace(); } } private void openScreenshot(File imageFile) { Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); Uri uri = Uri.fromFile(imageFile); intent.setDataAndType(uri,"image/*"); mAcvitity.startActivity(intent); } public void doSwitchBackOrFront() { int cameraCount = 0; CameraInfo cameraInfo = new CameraInfo(); cameraCount = Camera.getNumberOfCameras();//得到摄像头的个数 for(int i = 0; i < cameraCount; i++ ) { Camera.getCameraInfo(i,cameraInfo);//得到每一个摄像头的信息 if(cameraPosition == 0) { //现在是后置,变更为前置 if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { //代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置 doDestoryCamera(); mCamera = Camera.open(i);//打开当前选中的摄像头 doStartPreview(mSurfaceHolder,1); cameraPosition = 1; break; } } else { //现在是前置, 变更为后置 if(cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { //代表摄像头的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置 doDestoryCamera(); mCamera = Camera.open(i);//打开当前选中的摄像头 doStartPreview(mSurfaceHolder,1); cameraPosition = 0; break; } } } } /*为了实现拍照的快门声音及拍照保存照片需要下面三个回调变量*/ ShutterCallback mShutterCallback = new ShutterCallback() //快门按下的回调,在这里我们可以设置类似播放“咔嚓”声之类的操作。默认的就是咔嚓。 { public void onShutter() { // TODO Auto-generated method stub Log.i(TAG,"myShutterCallback:onShutter..."); } }; PictureCallback mJpegPictureCallback = new PictureCallback() //对jpeg图像数据的回调,最重要的一个回调 { public void onPictureTaken(byte[] data,Camera camera) { // TODO Auto-generated method stub Log.i(TAG,"myJpegCallback:onPictureTaken..."); Bitmap b = null; if(null != data) { b = BitmapFactory.decodeByteArray(data,data.length);//data是字节数据,将其解析成位图 mCamera.stopPreview(); isPreviewing = false; } //保存图片到sdcard if(null != b) { //设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation",90)失效。 //图片竟然不能旋转了,故这里要旋转下 float rotateDegree = 90.0f; float sx = 1.0f; if(cameraPosition == 1) { rotateDegree = -90.0f; sx = -1.0f; } Bitmap rotaBitmap = getRotateBitmap(b,rotateDegree,sx,1.0f ); saveBitmap(rotaBitmap,fileName); } //再次进入预览 mCamera.startPreview(); isPreviewing = true; mSaving = false; } }; private int getDisplayOritation(int degrees,int cameraId) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId,info); int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; } else { result = (info.orientation - degrees + 360) % 360; } return result; } private int getDispalyRotation() { int i = mAcvitity.getWindowManager().getDefaultDisplay().getRotation(); switch (i) { case Surface.ROTATION_0: return 0; case Surface.ROTATION_90: return 90; case Surface.ROTATION_180: return 180; case Surface.ROTATION_270: return 270; } return 0; } public static Bitmap getRotateBitmap(Bitmap b,float rotateDegree,float sx,float sy) { Matrix matrix = new Matrix(); matrix.postRotate((float)rotateDegree); matrix.postScale(sx,sy); Bitmap rotaBitmap = Bitmap.createBitmap(b,b.getWidth(),b.getHeight(),matrix,false); return rotaBitmap; } public static void saveBitmap(Bitmap b,String fileName) { String path = ""; String pngName = path + fileName; Log.e(TAG,"saveBitmap:pngName = " + pngName); try { FileOutputStream fout = new FileOutputStream(pngName); BufferedOutputStream bos = new BufferedOutputStream(fout); b.compress(Bitmap.CompressFormat.PNG,bos); bos.flush(); bos.close(); CameraViewHelp.getInstance().imgeSaved(true,pngName); Log.i(TAG,"saveBitmap成功"); } catch (IOException e) { // TODO Auto-generated catch block Log.i(TAG,"saveBitmap:失败"); CameraViewHelp.getInstance().imgeSaved(false,pngName); e.printStackTrace(); } } private Size getOptimalPreviewSize(List<Size> sizes,int w,int h) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) w / h; if (sizes == null) return null; Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = h; // Try to find an size match aspect ratio and size for (Size size : sizes) { double ratio = (double) size.width / size.height; if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } // Cannot find the one match the aspect ratio,ignore the requirement if (optimalSize == null) { minDiff = Double.MAX_VALUE; for (Size size : sizes) { if (Math.abs(size.height - targetHeight) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - targetHeight); } } } return optimalSize; } /** * 读取图片的旋转的角度 * * @param path * 图片绝对路径 * @return 图片的旋转角度 */ private static int getBitmapDegree(String path) { int degree = 0; try { // 从指定路径下读取图片,并获取其EXIF信息 ExifInterface exifInterface = new ExifInterface(path); // 获取图片的旋转信息 int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; } /** * 将图片按照某个角度进行旋转 * * @param bm * 需要旋转的图片 * @param degree * 旋转角度 * @return 旋转后的图片 */ public static Bitmap rotateBitmapByDegree(Bitmap bm,int degree) { Bitmap returnBm = null; // 根据旋转角度,生成旋转矩阵 Matrix matrix = new Matrix(); matrix.postRotate(degree); try { // 将原始图片按照旋转矩阵进行旋转,并得到新的图片 returnBm = Bitmap.createBitmap(bm,bm.getWidth(),bm.getHeight(),true); } catch (OutOfMemoryError e) { } if (returnBm == null) { returnBm = bm; } if (bm != returnBm) { bm.recycle(); } return returnBm; } }
参考的链接比较多:
http://blog.csdn.net/nickey_1314/article/details/41696467
http://blog.csdn.net/yanzi1225627/article/details/33028041
http://blog.csdn.net/gf771115/article/details/19438409
http://blog.csdn.net/dlutbrucezhang/article/details/8571715
http://blog.csdn.net/dlutbrucezhang/article/details/8571715
有的SDK直接可以接入实现Camera但是看着好麻烦:https://www.accompanying.me/2016/05/17/Cocos2dxAccessCamera/