在
智能电视TV开发---录像 的基础上实现拍照功能同时修改了
智能电视TV开发---录像 里面的预览竖屏的时候,预览图像旋转了90°的问题。
一、录像实现
其实录像部分我们既可以使用Android提供的MediaRecoder也可以自己来实现,实现方式与下面的拍照功能类似,要实现PreviewCallback这个接口,具体的代码如下:
package com.jwzhangjie.smarttv_client.media.Video;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import com.jwzhangjie.smarttv_client.utils.AppLogger;
import com.jwzhangjie.smarttv_client.utils.DateUtils;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.PreviewCallback;
import android.os.Environment;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class SmartVideoSurfaceView extends SurfaceView implements Callback{
private SurfaceHolder mHolder;
private Camera mCamera;
private boolean previewRunning = false;
private int type = 0;
private String sdDir;
public SmartVideoSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
initConfig();
}
private void initConfig(){
mHolder = this.getHolder();
mHolder.addCallback(this);
if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
sdDir = Environment.getExternalStorageDirectory().toString();
}else {
sdDir = "/mnt/sdcard";
}
}
public Camera getVideoCamera(){
return mCamera;
}
public SurfaceHolder getMyHolder(){
return mHolder;
}
/**
* 拍照功能
*/
public void getPhoto(){
if (mCamera != null) {
type = 0;
mCamera.setOneShotPreviewCallback(pCallback);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera = Camera.open();
Camera.Parameters params = mCamera.getParameters();
if (getContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
params.set("orientation", "portrait");
params.set("rotation", 90);
//不然预览会颠倒90°
mCamera.setDisplayOrientation(90);
}else {
params.set("orientation", "landscape");
mCamera.setDisplayOrientation(0);
}
mCamera.setParameters(params);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
if (mCamera != null) {
if (previewRunning) {
mCamera.stopPreview();
}
try {
Camera.Parameters params = mCamera.getParameters();
params.setPreviewSize(width, height);
params.setPreviewFormat(ImageFormat.JPEG);
mCamera.setParameters(params);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
mCamera.autoFocus(null);//自动对焦
previewRunning = true;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mCamera != null) {
mCamera.stopPreview();
previewRunning = false;
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
PreviewCallback pCallback = new PreviewCallback(){
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
switch (type) {
case 0://拍照
camera.takePicture(null, null, jpeg);
break;
}
}
};
PictureCallback jpeg = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
StringBuilder builder = new StringBuilder(sdDir);
builder.append("/");
builder.append(DateUtils.getCurrentTime());
builder.append(".jpeg");
AppLogger.e(builder.toString());
//自定义文件保留路径,以拍摄时间命名
File file = new File(builder.toString());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩的流里面
bos.flush();
bos.close();
bitmap.recycle();
builder.setLength(0);
builder = null;
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
这里我实现的是拍照功能,所以我实现的预览回调接口是setOneShotPreviewCallback。
效果图如下:
预览界面截图:
实际的拍照效果:
二、添加水印
其实添加水印也就是获取要Bitmap的Canvas,然后再canvas绘制内容,最后save保存,把绘制的图像保存在要添加水印的Bitmap上面,代码如下:
这里只给出修改部分的代码:
PictureCallback jpeg = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
StringBuilder builder = new StringBuilder(sdDir);
builder.append("/");
builder.append(DateUtils.getCurrentTime());
builder.append(".jpg");
bitmap = createWaterMark(bitmap, null, "jwzhangjie制作");
//自定义文件保留路径,以拍摄时间命名
File file = new File(builder.toString());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);//将图片压缩的流里面
bos.flush();
bos.close();
bitmap.recycle();
builder.setLength(0);
builder = null;
} catch (Exception e) {
e.printStackTrace();
}
}
};
/**
* 添加水印效果
* @param src
* @param watermark
* @param title
* @return
*/
public Bitmap createWaterMark(Bitmap src, Bitmap watermark, String title){
if (src != null) {
int w = src.getWidth();
int h = src.getHeight();
//创建一个空白的画布
Bitmap tempBitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
Canvas canvas = new Canvas(tempBitmap);
//在 0,0坐标开始画入src
canvas.drawBitmap(src, 0, 0, null);
Paint paint = new Paint();
//绘制水印
if (watermark != null) {
int ww = watermark.getWidth();
int hh = watermark.getHeight();
paint.setAlpha(50);
// 在src的右下角画入水印
canvas.drawBitmap(watermark, w - ww + 5, h - hh + 5, paint);
}
//绘制文字
if (title != null) {
String familyName = "宋体";
Typeface font = Typeface.create(familyName, Typeface.BOLD);
TextPaint textPaint = new TextPaint();
textPaint.setColor(Color.RED);
textPaint.setTypeface(font);
textPaint.setTextSize(22);
//这里是自动换行
// StaticLayout layout = new StaticLayout(title, textPaint, w, Alignment.ALIGN_NORMAL, 1.0F, 0.0F, true);
// layout.draw(canvas);
//文字加在中央
canvas.drawText(title, w/2, 40, textPaint);
}
//保存画布
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
return tempBitmap;
}else {
return null;
}
}
效果图如下:
其中,上面的红色部分是我添加的水印