cocos2d-x嵌入android的camera 实现前后摄像头的预览和保存

网上关于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,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, 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 posx, 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, CLASS_NAME, "handle_takeCameraPic", "(Ljava/lang/String;)V")) {
		jstring stringArg = t.env->NewStringUTF(fileName.c_str());
		t.env->CallStaticVoidMethod(t.classID, t.methodID, 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, CLASS_NAME, "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, CLASS_NAME, "handle_removeCamera", "()V")) {
		t.env->CallStaticVoidMethod(t.classID, 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 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);
	    }
	    
	    public static void handle_createCameraView(int width , int posX , 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,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);
	    }
	    
	    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(),4,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, 0, 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, 0, 0, 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, 100, 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, 0, 0, bm.getWidth(), bm.getHeight(), matrix, 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/





猜你喜欢

转载自blog.csdn.net/skillart/article/details/68941660