网上关于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/