最近一直在审视以前做过的东西,关于android摄像头预览,预览界面上呈现矩形框,在前文(
)----http://blog.csdn.net/yanzi1225627/article/details/7934710已经实现。最近发现上层绘制矩形框,用surfaceview有点大材小用了。SurfaceView绘制动画更合适,只绘制个矩形框用ImageView足够了。但有些时候必须要用SurfaceView来实现。比如360手机安全卫士扫描二维码的实现应该就是通过上下两层SurfaceView实现的(见下图)。上层SurfaceView用于显示那个可以旋转的扫描示意框,底层SurfaceView预览摄像头视频。
废话不说了,稍候几天我会仿照上面360这个扫描二维码的界面做一个工程(结合PreviewCallback),公开出来。这次先谈用底层surfaceView+上层ImageView实现只拍摄矩形框中的图像。新建一个类继承ImageView,源码如下:
package yan.guoqi.rectphoto;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ImageView;
public class DrawImageView extends ImageView{
public DrawImageView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
Paint paint = new Paint();
{
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2.5f);//设置线宽
paint.setAlpha(100);
};
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawRect(new Rect(100, 200, 400, 500), paint);//绘制矩形
}
}
布局文件里与前文http://blog.csdn.net/yanzi1225627/article/details/8577756这里一样,只是在帧布局里加一个上面自定义的DrawImageView,整个布局文件示下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/BestWish"
tools:context=".RectPhoto" />
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<SurfaceView
android:id="@+id/previewSV"
android:layout_width="fill_parent"
android:layout_height="800px" />
<yan.guoqi.rectphoto.DrawImageView
android:id="@+id/drawIV"
android:layout_width="fill_parent"
android:layout_height="800px"
/>
</FrameLayout>
<ImageButton
android:id="@+id/photoImgBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/photo_img_btn"
android:layout_gravity="center" />
</LinearLayout>
在主程序文件里,onCreate()函数里设置底层SurfaceView为底层且透明(如果不设也可以,默认就是如此):
mPreviewSV.setZOrderOnTop(false);
mySurfaceHolder.setFormat(PixelFormat.TRANSPARENT);//translucent半透明 transparent透明
在主UI线程里的onCreate()函数里添加代码:
//绘制矩形的ImageView
mDrawIV = (yan.guoqi.rectphoto.DrawImageView)findViewById(R.id.drawIV);
mDrawIV.onDraw(new Canvas());
看上面的DrawImageView的函数里的onDraw,画的矩形是Rect(100, 200, 400, 500)。在onPictureTaken(byte[] data, Camera camera)函数里,先将图片旋转90度,大小成为宽×高(960×1280)。由于预览surfaceview的大小是宽×高(540×800),所以在onPictureTaken函数里将960×1280的图片缩放到540×800, 缩放相同大小后就可以用矩阵的坐标直接截取子图了。核心函数就是这两句:
//将960×1280缩放到540×800
Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
Bitmap rectBitmap = Bitmap.createBitmap(sizeBitmap, 100, 200, 300, 300);//截取
注意这个截取的函数参数和矩阵的坐标关系,分别是x轴 y轴起始坐标及 x轴宽度 y轴宽度。截取出来的图片大小应该是300×300. onPictureTaken()函数的源码如下:
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
Log.i(tag, "myJpegCallback:onPictureTaken...");
if(null != data){
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字节数据,将其解析成位图
myCamera.stopPreview();
isPreview = false;
}
//设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。图片竟然不能旋转了,故这里要旋转下
Matrix matrix = new Matrix();
matrix.postRotate((float)90.0);
Bitmap rotaBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, false);
//旋转后rotaBitmap是960×1280.预览surfaview的大小是540×800
//将960×1280缩放到540×800
Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
Bitmap rectBitmap = Bitmap.createBitmap(sizeBitmap, 100, 200, 300, 300);//截取
//保存图片到sdcard
if(null != rectBitmap)
{
saveJpeg(rectBitmap);
}
//再次进入预览
myCamera.startPreview();
isPreview = true;
}
涉及到的其他函数如saveJpeg()参见前文:
http://blog.csdn.net/yanzi1225627/article/details/8577756 重复的东西我就不发了。
效果图如下所示:
点击拍照,查看保存后的图片如下:
反思:
1,SurfaceView为啥 无论translucent半透明还是 transparent透明基本没啥区别?而且surfaceview的setAlpha函数不能用。
2,在这里surfaceview一定要在底层(默认如此),如果设成顶层会看不到红色矩形框。可以自己测试下。
3,最纠结的一点,第一副图片里的360扫描二维码的界面,底层的预览surfaceview是半透明的,底色是灰色的,只有中间的扫描矩形框是透明的,亮色。这一块究竟是怎么实现的??下午实验了n种方法愣是无济于事。我擦。。。如果有高人,希望能不吝指点下。 不过说实话,人家已经设计出来的产品界面看着就是好,不得不服阿。以后要多多模仿钻研这些成型产品的设计。
源码下载:http://download.csdn.net/detail/yanzi1225627/5063105
欢迎android爱好者加群248217350,备注:yanzi
----------------------------------------本文系原创,转载请注明作者:yanzi1225627
分享到:
相关推荐
Android开发摄像头SurfaceView预览 背景画图(矩形和圆形) 实现(双surfaceview,顶层画矩形框,底层预览视频); UI:三个按钮 预览 摄像 图片保存,预览界面 可以显示(矩形和圆形等图画)
利用camera类调用手机摄像头,且只拍摄SurfaceView预览界面特定区域内容(矩形取景框)(底层SurfaceView+上层绘制ImageView)
Android圆形相机预览窗口,圆形SurfaceView
Android SurfaceView 实现实时显示摄像头视频,详见博客:https://blog.csdn.net/qq_30297763/article/details/90241102
双SurfaceView实现手机摄像头预览、监听每一帧做处理绘制浮层效果(Demo画了一个矩形上去)
Android SurfaceView 实现实时显示摄像头视频,详见博客:https://blog.csdn.net/qq_30297763/article/details/90241102
android camera mirror 前置后置相机视频预览时左右镜像,实现镜子效果 基于以下网址实现的android studio项目源代码包,可以直接打开使用 https://blog.csdn.net/mbrose/article/details/80167781 代码做了一...
主要为大家详细介绍了Android中关于自定义相机预览界面拉伸问题,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
MainActivity类是调用系统摄像头 MyCameroActivity类是通过surfaceholder的方式调用camera拍照的,只用拍照功能。适合初学者的。
android surfaceview自定义拍照 绘制头像轮廓 注明:是借用网上的demo基础上进行修改的
Camera+SurfaceView拍照预览。
android摄像头预览界面呈现自定义的矩形框,只拍摄(矩形框)特定区域的图片,然后根据图片解析条码。
Android 入门视频播放器一般采用封装好的VideoView或MediaPlayer+SurfaceView两种类型,其中VideoView高度封装并不适合深入了解其中原理,下面利用SurfaceView+MediaPlay实现一个简单的视频播放器
android 系统播放器+SurfaceView实现播放,XML文件定义SurfaceView实现播放,并监听播放器准备,错误,完成,以及进度等函数
Android SurfaceView+MediaRecorder实现的录音波浪图
Android的SurfaceView实现图片缩放、滑动,网上资源不多,目前还有些问题,仅供参考。
Android中使用surfaceview开发的Camera相机,内容含有注释,非常清楚
Android MediaPlayer+SurfaceView+自定义控制器实现视频播放demo
调用手机前置摄像头拍照,可重复预览,重复拍照
最近公司有眼镜个人脸识别产品,需要安卓开发,网上找了找代码实现基于surfaceView +camera2 拍照功能