精华内容
参与话题
问答
  • win7打开摄像头照相拍照软件

    热门讨论 2010-08-26 10:03:07
    win7打开摄像头照相拍照软件,漂亮的很,,
  • C# 调用摄像头拍照(AForge实现)

    千次阅读 2020-03-26 22:12:16
    记一次摄像头调用前言:正文:1. **下载 AForge 库**2. **通过VS添加引用**3. **工具箱添加AForge的组件**4. **添加组件**5. 代码: 前言: C#调用摄像头是为了完成一个项目( 工厂物资管理系统....

    1、前言:

    C#调用摄像头是为了完成一个项目( 工厂物资管理系统. )中的人脸识别功能。
    对人脸识别感兴趣的小伙伴可以移步至:https://blog.csdn.net/qq_41971768/article/details/103823308

    在 C # 调用摄像头的实现过程中,我曾在博客上借鉴其他人的做法。在这里给出相应的博客地址如下:

    本文也是借鉴于第四篇博客。

    2、正文:

    2.1 下载 AForge 库

    进入AForge官网:http://www.aforgenet.com/framework/downloads.html下载AForge库:
    AForge.NET

    2.2 通过VS添加引用

    • AForge.Imaging ——图像处理和过滤器
    • AForge.Video ——视频处理类库
    • AForge.Controls—— 图像显示控件
    • 进入引用管理器如下图:引用管理器
    • 点击浏览:
    找到AForge.NET Framework-2.2.5-(libs only)\Release目录
    添加以下文件:
    	"AForge.Video.dll"
    	"AForge.Controls.dll" 
    	"AForge.dll" 
    	"AForge.Imaging.dll" 
    	"AForge.Video.DirectShow.dll" 
    

    添加引用

    • 添加结果如下:

    添加结果图

    2.3 工具箱添加AForge的组件

    • 打开工具箱>>右键>>添加选项卡>>输入名称AForge
      添加结果
    • 选中AForge>>右键>>选择项>>浏览进入AForge.NET Framework-2.2.5-(libs only)\Release目录>>选中 “AForge.Controls.dll”>>打开确认
    • 添加工具

    2.4 添加组件

    • 创建窗体>>添加图中组件;
    • 其中的videoSorcePlayer位于刚添加的工具集AForge中。
      添加组件
    • 我的设计效果
      设计效果

    2.5 代码:

    可以同时参考前言中第四位作者的代码。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    //using System.Drawing;
    using AForge.Video.DirectShow;
    using 工厂物资管理.Face;
    using Newtonsoft.Json;
    using System.Data.SqlClient;
    
    namespace 工厂物资管理
    {
        public partial class FaceLoginForm : Form
        {
    
            private FilterInfoCollection videoDevices = null;
            private VideoCaptureDevice videoSource = null;
            private string EmployeeID = null;
            private int Indexof = 0;
    
            private SqlConnection sqlConnection = null;
            private SqlCommand sqlCommand = null;
            public FaceLoginForm()
            {
                InitializeComponent();
    			//连接数据库部分
                this.sqlConnection = new SqlConnection(DB.DBConnStr.ConnStr);
                this.sqlCommand = new SqlCommand();
                this.sqlCommand.Connection = this.sqlConnection;
            }
    		
    		//检索摄像头事件
            private void Checkcam_Click(object sender, EventArgs e)
            {
                Camlist(); //调用相应方法
            }
    		//检索摄像头
            private void Camlist()
            {
                videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
                Cameralist.Items.Clear();   //清楚之前检索的内容
                if (videoDevices.Count == 0)
                {
                    MessageBox.Show("未找到摄像头设备");
                }
                else
                {
                    foreach (FilterInfo device in videoDevices)
                    {
    
                        Cameralist.Items.Add(device.Name);
                    }
                    if (Cameralist.Items.Count >= 1)
                    {
                        Cameralist.SelectedIndex = 0;   //设置一个默认选项
                    }
                }
    
            }
    		//打开摄像头按钮
            private void Select_button_Click(object sender, EventArgs e)
            {
                Indexof = Cameralist.SelectedIndex;
                if (Indexof < 0)
                {
                    MessageBox.Show("请选择一个摄像头");
                    return;
                }
                //添加try抛出异常,防止程序中断
                try   
                {
                    //在1个或以上摄像头进行切换时执行
                    videoSourcePlayer1.SignalToStop();
                    videoSourcePlayer1.WaitForStop();
                    this.pictureBox1.Visible = false;
                    this.videoSourcePlayer1.Visible = true;
                    //videoDevices[Indexof]确定出用哪个摄像头了。
                    videoSource = new VideoCaptureDevice(videoDevices[Indexof].MonikerString);
                    //设置下像素,这句话不写也可以正常运行:
                    //videoSource.VideoResolution = videoSource.VideoCapabilities[Indexof];
                    //在videoSourcePlayer1里显示
                    videoSourcePlayer1.VideoSource = videoSource;
                    videoSourcePlayer1.Start();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("请选择一个有效的摄像头");
                }
            }
    		
    		//抓拍登录按钮
            private void TiJiao_button_Click(object sender, EventArgs e)
            {
                if (videoSource == null)
                {
                    MessageBox.Show("请先打开摄像头");
                    return;
                }
                //videoSourcePlayer继承Control父类,定义 GetCurrentVideoFrame能输出bitmap
                Bitmap bitmap = videoSourcePlayer1.GetCurrentVideoFrame();
                //此处就得到了Bitmap格式的图像数据
                
                pictureBox1.Image = bitmap;   //将图像加载到pictureBox组件
                this.videoSourcePlayer1.Visible = false;
                this.pictureBox1.Visible = true;
                //这里停止摄像头继续工作 当然videoSourcePlayer里也定义了 Stop();用哪个都行
    
                //    string imagestr = this.pictureBox1.Image.ToString();
                //  
               bitmap = videoSourcePlayer1.GetCurrentVideoFrame();
                String imagestr=Util.ImgToBase64String(bitmap);
               // MessageBox.Show("01",imagestr.Substring(1,10));
                
                videoSourcePlayer1.Stop();
                //#############################
    			//至此图像抓取工作结束,下面内容是人脸识别的相关内容。
    			//############################
                checkFace(imagestr);
                if (this.EmployeeID != null)
                {
                    login();
                }
                // videoSourcePlayer1.SignalToStop(); videoSourcePlayer1.WaitForStop();
                //原文链接:https://blog.csdn.net/u013667895/article/details/78426649
            }
            private void login()
            {
                try
                {
                    if (sqlConnection.State != ConnectionState.Open)
                    {
                        sqlConnection.Open();
                    }
                    string sql = string.Format("select EmployeeID,EmployeePwd,EmployeeName,Employee.EmployeeTitle " +
                        "from Employee " +
                        "where Employee.EmployeeID = '{0}'", this.EmployeeID);
                    sqlCommand.CommandText = sql;
                    SqlDataReader sdr = sqlCommand.ExecuteReader();
                    if (sdr.HasRows)
                    {
                        //有返回行
                        sdr.Read();
    
                        if (sdr[0].ToString() == this.EmployeeID)
                        {//输入用户名和密码等于查询结果中用户名和密码
    
                            MainForm mform = new MainForm(sdr[3].ToString(), sdr[0].ToString(), sdr[2].ToString());
                            sdr.Close();
                            this.Hide();
                            mform.ShowDialog();
                            this.Close();
                            //this.Show();
                        }
                        else
                        {
                            sdr.Close();
                            MessageBox.Show("登陆失败,请重新尝试!", "SQL注入攻击无效,提示信息");
                        }
    
                    }
                    else
                    {
                        //无返回行
                        MessageBox.Show("登陆失败,请重新尝试!", "提示信息");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "数据库操作问题提示");
                    //throw;
                }
                finally
                {
                    sqlConnection.Close();
                }
            }
            private void checkFace(string image)
            {
                //识别
                SearchResult searchResult = FaceSearch.faceSearch(image);
                
                if (searchResult.error_msg.Equals("SUCCESS"))
                {
                    string score=searchResult.result.user_list[0].score;
                  //  MessageBox.Show(score);
                    if (Double.Parse(score)>85.0)
                    {
                        this.EmployeeID = searchResult.result.user_list[0].user_id;
                        MessageBox.Show("验证成功");
                    }
                    else
                    {
                        MessageBox.Show("未成功,请确认已采集人脸后再试!","验证失败");
                    }
                }
                else
                {
                    MessageBox.Show("未成功,请确认已采集人脸后再试!", "验证失败");
                }
            }
    
            private void FaceLoginForm_Load(object sender, EventArgs e)
            {
              //  String str=AuthService.getAccessToken();
              //  Token token = JsonConvert.DeserializeObject<Token>(str);
              //  MessageBox.Show(token.access_token);
            }
    
            private void FaceLoginForm_FormClosing(object sender, FormClosingEventArgs e)
            {
                if (videoSource != null)
                {
                    videoSourcePlayer1.Stop();
                }
            }
        }
    }
    
    

    2.6 效果展示

    登录失败
    验证成功

    谢谢浏览,希望能够帮到大家。
    欢迎大家留言,提出问题和意见。

    作者:卢松林
    许昌学院计算机科学与技术专业

    展开全文
  • 拍照

    2014-12-05 12:36:01
    近年来,拍照手机、电脑摄像头(PC-CAM)、监控等领域飞速发展,需求量日渐增长,CMOS图像传感器(CIS)作为这些应用的核心元件,其市场需求也越来越大。CIS芯片集光电、模拟电路和数字电路于一体,其设计、生产、测试、...

    参考:http://www.eccn.com/tech_260_2010051913335212.htm

    近年来,拍照手机、电脑摄像头(PC-CAM)、监控等领域飞速发展,需求量日渐增长,CMOS图像传感器(CIS)作为这些应用的核心元件,其市场需求也越来越大。CIS芯片集光电、模拟电路和数字电路于一体,其设计、生产、测试、封装以及最终应用与传统IC相比,都有其特别的地方,因此行业门槛也相对较高。

    北京思比科作为中国本土企业,是唯一基于自主专利技术开发成功高端CMOS图像传感器芯片并实现规模化生产的企业,近几年开发成功了一系列高品质图像传感器芯片。以下针对拍照手机,PC-CAM和监控三个领域的应用,具体介绍思比科的系列产品。

    1.拍照手机

    拍照手机可以实现预览、拍照、回显、录像和回放的全部功能。从传感器应用的角度,拍照手机可以分为以下两类:第一类是YUV型,即传感器输出标准的YUV图像数据,多媒体处理器接收后完成图像的编解码等后处理,传感器和多媒体处理器相对独立,SP80818(1/8 inch VGA)和SP82318(1/3.2 inch 2M)就是针对这种应用设计的。第二类是Raw Data型,传感器只输出原始数据,所有的图像处理和自动控制都由多媒体处理器来主导完成,SP80708(1/7 inch VGA)和SP83308(1/3 inch 3.2M)符合这种应用。以下分别介绍两种方案。

    1.1 YUV型

    YUV型的方案是目前中低端拍照手机普遍采用的一种方案,主要集中在VGA,1.3M和2M的拍照手机,要求传感器输出标准的YUV数据。传感器除了完成图像采集的功能外,还要完成图像处理和图像转换的功能。图1是SP80818和SP82318的结构框图以及YUV手机的结构图。其中传感器核(Sensor Core)部分包含有感光阵列、曝光控制和读出电路、可变增益放大器(PGA)和模数转换器(ADC),主要完成图像采集功能。传感器核输出的原始图像数据送到图像处理器(ISP),ISP完成一系列图像处理和图像转换功能,主要包含以下处理:灰度补偿、数字增益和白平衡、镜头阴影修正、坏点检测和修正、彩色插值、平滑处理和轮廓增强、GAMMA校正、色彩校正、亮度、饱和度和对比度调节、图像尺寸变换、色彩空间转换、图像数据打包输出。控制模块完成自动曝光控制,自动白平衡,50Hz/60Hz闪烁检测等功能,对传感器核和ISP进行控制,以及和多媒体处理器的通信(多媒体处理器通过串行总线接口访问传感器内部寄存器,实现对传感器的控制。)

    图1: YUV传感器SP0818和SP2318的结构框图及应用。

    虽然绝大多数主流的传感器设计公司都是按照以上功能来设计自己的产品,但由于设计能力和所采用的工艺性能的不同,市面上产品的性价比仍然会存在较大的差距。

    思比科在设计这些产品之前,已经做了大量的基础研究,从工艺,算法到电路原理都有了很多的突破,形成了以SuperPix和SuperImage为核心的技术特点,相关专利已经达到数十件以上,SuperPix技术具体体现在高性能的像素单元(Pixel)设计,高精度、高速度和超低功耗的CDS电路,PGA电路和ADC电路设计;SuperImage技术则主要包含一系列效果优良、实现简洁的算法,如自动白平衡,自动曝光控制,彩色插值,平滑去噪,轮廓增强等。

    YUV方案的优点在于照相模块的独立性和灵活性。工程师很容易完成不同的传感器和多媒体处理器之间的对接,而复杂繁琐的图像调试工作已经由照相模块的供应商完成,工程师只需要将多媒体处理器中传感器的配置参数更新就可以得到理想的图像效果。

    然而,随着手机市场的竞争加剧,客户对传感器的性价比要求越来越高,这种方案的缺点也越来越明显。由于传感器工艺的特殊性决定了在设计和制造过程中,不能使用超过4层的金属连线资源,这将大大增加逻辑关系复杂的图像处理电路的面积,从而增加传感器的成本。而另一方面,为了降低成本,传感器的感光单元尺寸越来越小,为了得到更好的图像质量,需要越来越复杂的算法对图像进行处理。基于以上原因,ISP的功能已经开始从传感器转移到多媒体处理器。对于规模庞大的多媒体处理器来说,ISP的集成对其成本不会有明显增加,而传感器的成本则有大幅度下降。因此?Raw Data方案也越来越被关注。

    1.2 Raw Data型

    Raw Data型方案是最有争议的一个方案,系统只要求传感器输出原始数据,后端多媒体处理器完成所有ISP和图像编解码等功能,和普通的数码相机的解决方案一样,而多媒体处理器则类似于数码相机中的核心处理器。 SP80708和SP83308就是基于这种应用方案设计的,其结构框图见图2。

    图2:Raw Data传感器SP0708和SP3308的结构框图。

    从结构上看,Raw Data型传感器实际是YUV 传感器去掉ISP和部分传感器控制功能之后的简化产品。

    这种方案在最低端手机和最高端手机中都有应用。如联发科的MTK6226和展讯6600D+华邦99685,就属于这一方案在低端手机上的应用。而可以支持到3.2M Raw Data 传感器,Broadcom的BCM2820甚至可以支持8M像素的Raw Data 传感器,很多高端手机采用了这些方案。

    对于3.2M以上的高像素拍照手机,Raw Data方案从系统设计的角度讲是合理的。高像素的拍照手机为了取代传统数码相机,对图像质量的要求已经达到专业级的要求。在提高模拟前端图像采集性能的同时,后端复杂的图像处理技术也是必不可少的。要把这些功能复杂的ISP集成到传感器中,几乎很难实现,比如复杂的彩色插值算法要求保存一帧的Raw Data,需要很大的缓冲,传感器中不可能做到;而性能越来越高的多媒体处理器,无论是处理能力,还是配备的缓冲,都非常适合来完成这个功能。从整个系统的结构和性价比来看,这种方案也是最有竞争力的。

    对于低端的VGA拍照手机,传感器的成本压力越来越大。Raw Data型的传感器是降低成本最有效的方案。联发科推出的一系列平台方案就恰好集成了图像处理的功能,MTK6226就是最典型的代表。

    Raw Data型方案目前也存在缺点,它需要传感器厂商和多媒体芯片或是平台厂商紧密配合,才能很顺利的完成系统集成。尤其是方案设计阶段,对不同的传感器,甚至相同的传感器搭配不同的镜头,都需要基于多媒体芯片重新调试图像效果。传感器厂商只有得到这些平台厂商的配合,才能完成design-in。

    目前手机市场的情况是YUV型和Raw Data型两种方案并存。思比科也有针对性的开发出了不同的产品,来满足客户多元化的需求。其中SP0818和SP2318满足YUV型手机客户的需求,而SP80708和SP83308则符合Raw Data型手机客户的要求。

    2.PC摄像头

    相对手机而言,PC摄像头(PC-CAM)是一个较为简单的应用。由于英特网的普及以及越来越流行的网络视频应用,PC-CAM的需求量也非常庞大。SP80708在满足手机应用的同时,也因为高性价比的优势而被大量使用在PC-CAM上。

    PC-CAM的方案非常简单,一颗DSP搭配一颗传感器,就组成了一个PC-CAM方案。图3是一个典型的PC-CAM的结构图。

    图3:典型的PC-CAM方案。

    SP80708采用了思比科最新的像素技术,感光度高达1.2V,足以满足PC-CAM对低照度的严格要求;色彩还原性好,原始数据经过简单处理就可以达到理想的效果;而像素尺寸缩小到3.2umx3.2um,可以较大幅度降低传感器成本。同时内嵌思比科特有的曝光控制算法,很大程度上提高了动态范围,在各种光照条件的复杂环境下,都能达到理想的曝光效果。

    PC-CAM也有很多种类。从传感器的分辨率来分,有30万像素,130万像素和200万像素的PC-CAM,早期甚至还有10万像素的产品。由于受到USB带宽的限制,PC-CAM很少有200万像素以上的产品。从传感器的类型来分,有使用Raw Data 传感器的PC-CAM,也有使用YUV 传感器的产品;绝大多数DSP都集成了ISP的功能,但多数的ISP只支持到VGA,所以大多数30万像素的PC-CAM都采用Raw Data的传感器,或是采用YUV 传感器的Raw Data输出,而130万像素和200万像素的产品则多使用YUV 传感器。

    从DSP的功能来分,PC-CAM又可以分为USB1.1和USB2.0两种,因为USB1.1的带款很窄,视频在传到PC之前需要压缩,所以USB1.1的DSP都集成了JPEG压缩的模块;而USB2.0则能够传输未经压缩的VGA视频流,因此USB2.0的PC-CAM视频质量优于USB1.1的产品。有些USB2.0的DSP也集成了JPEG模块,向下兼容USB1.1的应用,以保证产品能应用在非常低端的PC上。

    随着市场的多元化发展,PC-CAM产品的种类也越来越多。如有带语音输入功能的、有带自动聚焦和跟踪功能的。而最近出现的“免驱动”的PC-CAM,则有可能成为未来的主流产品。

    3.监控系统

    传统的监控系统几乎都采用CCD。随着CMOS 传感器技术的发展,CMOS的品质已经达到CCD相当的水平。而监控系统应用的普及,也面临着降低成本的压力。低成本的CMOS取代CCD在监控系统上应用的趋势已经非常明显。图4是采用CMOS 传感器的监控系统的典型结构。

    图4: IP camera解决方案。

    传感器将采集到的高品质图像数据转换成标准YUV格式,传给后边的处理器,处理器完成对视频的压缩,并通过有线或无线网络,将压缩后的视频流发送出去。因为监控系统的应用环境差别比较大,而且都是处于全天候工作状态,因此对传感器的要求非常高,比如传感器的动态范围,灵敏度,温度特性等,都比普通的传感器高出很多。思比科目前正在积极开发这类产品,预计在年内推出新一代宽动态范围,高灵敏度的传感器,满足监控领域的应用需求。

    思比科的产品完全根据客户的需求设计,具有性价比高,应用方便的特点。表1总结了思比科系列产品的技术指标,这些产品适用于各种解决方案,可以满足绝大多数客户的需求。

    表1: 思比科系列产品指标。


    展开全文
  • 目前支持谷歌、火狐浏览器
  • 近期小巫在学校有一个创新项目,也不是最近,是一个拖了很久的项目,之前一直没有去搞,最近因为要中期检查,搞得我跟小组成员一阵忙活,其实开发一款照相机软件并不太难,下面就是通过自定义的方式来实现手机照相的...

    Android自定义照相机实现

    近期小巫在学校有一个创新项目,也不是最近,是一个拖了很久的项目,之前一直没有去搞,最近因为要中期检查,搞得我跟小组成员一阵忙活,其实开发一款照相机软件并不太难,下面就是通过自定义的方式来实现手机照相的功能。

    创建一个项目:FingerTakePicture


    首先来搞一下界面:

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/FrameLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <!-- 显示预览图形 -->
    	<SurfaceView 
    	    android:id="@+id/surfaceView"
    	    android:layout_width="match_parent"
    	    android:layout_height="match_parent"
    	    />
    	<!-- 相对布局,放置两个按钮 -->
    	 	<RelativeLayout
    	    	android:id="@+id/buttonLayout"
    	    	android:layout_width="wrap_content"
    	    	android:layout_height="wrap_content"
    	    	android:visibility="gone"
    	    >
    	    <!-- 拍照按钮 -->
    	    <Button 
    	        android:id="@+id/takepicture"
    	        android:layout_width="wrap_content"
    	        android:layout_height="wrap_content"
    	        android:layout_alignParentRight="true"
    	        android:layout_alignParentBottom="true"
    	        android:background="@drawable/btn_tabkepicture_selector"
    	        android:onClick="btnOnclick"
    	        />
    	    <ImageView 
    	        android:id="@+id/scalePic"
    	        android:layout_width="wrap_content"
    	        android:layout_height="wrap_content"
    	        android:layout_alignParentLeft="true"
    	        android:layout_alignParentBottom="true"
    	        android:layout_marginLeft="5dp"
    	        android:background="@drawable/img_showpic_selector"
    	        android:onClick="imageClick"
    	        />
    	</RelativeLayout>
    </FrameLayout>

    界面效果(无法把预览给截屏下来滴):




    权限设置少不了:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.wwj.finger"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="4"
            android:targetSdkVersion="15" />
    
        <uses-permission android:name="android.permission.CAMERA" />
        <!-- 在SDCard中创建与删除文件权限 -->
        <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
        <!-- 往SDCard写入数据权限 -->
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name=".MainActivity"
                android:label="@string/title_activity_main" 
                >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity 
                android:name=".ShowPicActivity"
                android:label="@string/app_name"
                android:theme="@style/AppTheme"
                android:configChanges="orientation|keyboardHidden"
                ></activity>
        </application>
    
    </manifest>

    主Activity:

    package com.wwj.finger;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    
    import android.app.Activity;
    import android.content.Intent;
    import android.graphics.PixelFormat;
    import android.hardware.Camera;
    import android.hardware.Camera.PictureCallback;
    import android.os.Bundle;
    import android.os.Environment;
    import android.view.KeyEvent;
    import android.view.MotionEvent;
    import android.view.Surface;
    import android.view.SurfaceHolder;
    import android.view.SurfaceHolder.Callback;
    import android.view.SurfaceView;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Toast;
    
    /**
     * Android手指拍照
     * 
     * @author wwj
     * @date 2013/4/29
     */
    public class MainActivity extends Activity {
    	private View layout;
    	private Camera camera;
    	private Camera.Parameters parameters = null;
    
    	Bundle bundle = null; // 声明一个Bundle对象,用来存储数据
    
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		// 显示界面
    		setContentView(R.layout.activity_main);
    
    		layout = this.findViewById(R.id.buttonLayout);
    
    		SurfaceView surfaceView = (SurfaceView) this
    				.findViewById(R.id.surfaceView);
    		surfaceView.getHolder()
    				.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    		surfaceView.getHolder().setFixedSize(176, 144);	//设置Surface分辨率
    		surfaceView.getHolder().setKeepScreenOn(true);// 屏幕常亮
    		surfaceView.getHolder().addCallback(new SurfaceCallback());//为SurfaceView的句柄添加一个回调函数
    	}
    
    	/**
    	 * 按钮被点击触发的事件
    	 * 
    	 * @param v
    	 */
    	public void btnOnclick(View v) {
    		if (camera != null) {
    			switch (v.getId()) {
    			case R.id.takepicture:
    				// 拍照
    				camera.takePicture(null, null, new MyPictureCallback());
    				break;
    			}
    		}
    	}
    
    	/**
    	 * 图片被点击触发的时间
    	 * 
    	 * @param v
    	 */
    	public void imageClick(View v) {
    		if (v.getId() == R.id.scalePic) {
    			if (bundle == null) {
    				Toast.makeText(getApplicationContext(), R.string.takephoto,
    						Toast.LENGTH_SHORT).show();
    			} else {
    				Intent intent = new Intent(this, ShowPicActivity.class);
    				intent.putExtras(bundle);
    				startActivity(intent);
    			}
    		}
    	}
    
    	private final class MyPictureCallback implements PictureCallback {
    
    		@Override
    		public void onPictureTaken(byte[] data, Camera camera) {
    			try {
    				bundle = new Bundle();
    				bundle.putByteArray("bytes", data);	//将图片字节数据保存在bundle当中,实现数据交换
    				saveToSDCard(data); // 保存图片到sd卡中
    				Toast.makeText(getApplicationContext(), R.string.success,
    						Toast.LENGTH_SHORT).show();
    				camera.startPreview(); // 拍完照后,重新开始预览
    
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
    
    	/**
    	 * 将拍下来的照片存放在SD卡中
    	 * @param data	
    	 * @throws IOException
    	 */
    	public static void saveToSDCard(byte[] data) throws IOException {
    		Date date = new Date();
    		SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 格式化时间
    		String filename = format.format(date) + ".jpg";
    		File fileFolder = new File(Environment.getExternalStorageDirectory()
    				+ "/finger/");
    		if (!fileFolder.exists()) { // 如果目录不存在,则创建一个名为"finger"的目录
    			fileFolder.mkdir();
    		}
    		File jpgFile = new File(fileFolder, filename);
    		FileOutputStream outputStream = new FileOutputStream(jpgFile); // 文件输出流
    		outputStream.write(data); // 写入sd卡中
    		outputStream.close(); // 关闭输出流
    	}
    
    
    	private final class SurfaceCallback implements Callback {
    
    		// 拍照状态变化时调用该方法
    		@Override
    		public void surfaceChanged(SurfaceHolder holder, int format, int width,
    				int height) {
    			parameters = camera.getParameters(); // 获取各项参数
    			parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式
    			parameters.setPreviewSize(width, height); // 设置预览大小
    			parameters.setPreviewFrameRate(5);	//设置每秒显示4帧
    			parameters.setPictureSize(width, height); // 设置保存的图片尺寸
    			parameters.setJpegQuality(80); // 设置照片质量
    		}
    
    		// 开始拍照时调用该方法
    		@Override
    		public void surfaceCreated(SurfaceHolder holder) {
    			try {
    				camera = Camera.open(); // 打开摄像头
    				camera.setPreviewDisplay(holder); // 设置用于显示拍照影像的SurfaceHolder对象
    				camera.setDisplayOrientation(getPreviewDegree(MainActivity.this));
    				camera.startPreview(); // 开始预览
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    
    		}
    
    		// 停止拍照时调用该方法
    		@Override
    		public void surfaceDestroyed(SurfaceHolder holder) {
    			if (camera != null) {
    				camera.release(); // 释放照相机
    				camera = null;
    			}
    		}
    	}
    
    	/**
    	 * 点击手机屏幕是,显示两个按钮
    	 */
    	@Override
    	public boolean onTouchEvent(MotionEvent event) {
    		switch (event.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			layout.setVisibility(ViewGroup.VISIBLE); // 设置视图可见
    			break;
    		}
    		return true;
    	}
    
    	
    	@Override
    	public boolean onKeyDown(int keyCode, KeyEvent event) {
    		switch (keyCode) {
    		case KeyEvent.KEYCODE_CAMERA: // 按下拍照按钮
    			if (camera != null && event.getRepeatCount() == 0) {
    				// 拍照
    				//注:调用takePicture()方法进行拍照是传入了一个PictureCallback对象——当程序获取了拍照所得的图片数据之后
    				//,PictureCallback对象将会被回调,该对象可以负责对相片进行保存或传入网络
    				camera.takePicture(null, null, new MyPictureCallback());
    			}
    		}
    		return super.onKeyDown(keyCode, event);
    	}
    
    	// 提供一个静态方法,用于根据手机方向获得相机预览画面旋转的角度
    	public static int getPreviewDegree(Activity activity) {
    		// 获得手机的方向
    		int rotation = activity.getWindowManager().getDefaultDisplay()
    				.getRotation();
    		int degree = 0;
    		// 根据手机的方向计算相机预览画面应该选择的角度
    		switch (rotation) {
    		case Surface.ROTATION_0:
    			degree = 90;
    			break;
    		case Surface.ROTATION_90:
    			degree = 0;
    			break;
    		case Surface.ROTATION_180:
    			degree = 270;
    			break;
    		case Surface.ROTATION_270:
    			degree = 180;
    			break;
    		}
    		return degree;
    	}
    }
    


    用来显示图片的Activity:

    package com.wwj.finger;
    
    
    import android.app.Activity;
    import android.content.Intent;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Matrix;
    import android.os.Bundle;
    import android.widget.ImageView;
    
    public class ShowPicActivity extends Activity {
    	private ImageView ivPic = null; // 显示图片控件
    
    
    	/**
    	 * Activity在创建的时候回调的函数 主要用来初始化一些变量
    	 */
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.showpic);
    		ivPic = (ImageView) findViewById(R.id.ivPic);
    		setImageBitmap(getImageFormBundle());
    
    	}
    
    
    	/**
    	 * 将MainActivity传过来的图片显示在界面当中
    	 * 
    	 * @param bytes
    	 */
    	public void setImageBitmap(byte[] bytes) {
    		Bitmap cameraBitmap = byte2Bitmap();
    		// 根据拍摄的方向旋转图像(纵向拍摄时要需要将图像选择90度)
    		Matrix matrix = new Matrix();
    		matrix.setRotate(MainActivity.getPreviewDegree(this));
    		cameraBitmap = Bitmap
    				.createBitmap(cameraBitmap, 0, 0, cameraBitmap.getWidth(),
    						cameraBitmap.getHeight(), matrix, true);
    		ivPic.setImageBitmap(cameraBitmap);
    	}
    
    	/**
    	 * 从Bundle对象中获取数据
    	 * 
    	 * @return
    	 */
    	public byte[] getImageFormBundle() {
    		Intent intent = getIntent();
    		Bundle data = intent.getExtras();
    		byte[] bytes = data.getByteArray("bytes");
    		return bytes;
    	}
    
    	/**
    	 * 将字节数组的图形数据转换为Bitmap
    	 * 
    	 * @return
    	 */
    	private Bitmap byte2Bitmap() {
    		byte[] data = getImageFormBundle();
    		// 将byte数组转换成Bitmap对象
    		Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
    		return bitmap;
    	}
    }



    这是小巫那个创新项目的一小部分,已经完美实现简单的照相机功能了,保存图片不会像有些网友提供的代码给定一个特定的文件名,不能保存多张图片,还特定把一些方法封装了一下,有需要的朋友好好看看吧。


    展开全文
  • 我用下面的代码来实现拍照功能。但是它总是返回一个空白图像.错误出现在哪呢? Camera.Parameters p = camera.getParameters(); List<Size> sizes = p.getSupportedPictureSizes(); // Choose any one you ...
  • Android如何调用系统现有的照相机拍照与摄像

    千次下载 热门讨论 2013-11-25 23:20:31
    Android如何调用系统现有的照相机拍照与摄像,详细参见博客:http://www.cnblogs.com/plokmju/p/Android_SystemCamera.html
  • 前段时间在做face++相关的功能,对于照相机也是进行了一番研究,小有收获,解决了不少拍照预览图片模糊、部分机型黑屏等问题,目前已经保证了团队里面十多部安卓手机的完美适配。

             前段时间在做face++相关的功能,对于照相机也是进行了一番研究,小有收获,很感谢有一些大神已经写了相应的博客,让我在他们的项目上进行完善和优化,修复了一些bug,并对机型适配做了一些处理,目前已经保证了团队里面十多部安卓手机的完美适配,具体项目资源可以在http://download.csdn.net/detail/shan286/9799622这个网址上下载。好的,话不多说,直接上代码。

    1、首先是关于照相机的预览功能,这里就要说到SurfaceView这个控件,我在布局最底层放了一个自定义的MySurfaceView,然后在它的上层放一个自定义的TakePhotoView,这个TakePhotoView主要是用于当用户想要在拍照的时候绘制自己想要的图片时,就可以在这个View中实现,这里我是画了一个带橙色框框的图片放在了里面。MySurfaceView的代码如下:

    import android.content.Context;
    import android.graphics.PixelFormat;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    
    /**
     * Created by xueli on 2016/11/16.
     * 
     * 1、注意点:surfaceview变得可见时,surface被创建;surfaceview隐藏前,surface被销毁
     * 2、实现过程:继承SurfaceView并实现SurfaceHolder.Callback接口
     * ----> SurfaceView.getHolder()获得SurfaceHolder对象
     * ----> SurfaceHolder.addCallback(callback)添加回调函数
     * ----> SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布
     * ----> Canvas绘画
     * ----> SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示。
     */
    public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    
        private static final String TAG = "MySurfaceView";
        private Context mContext;
        private SurfaceHolder mSurfaceHolder;
    
        public MySurfaceView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mContext = context;
            mSurfaceHolder = getHolder();
            mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT);//translucent半透明 transparent透明
            mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            mSurfaceHolder.addCallback(this);
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            //在创建时激发,一般在这里调用画图的线程。
            Log.i(TAG, "surfaceCreated...");
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                   int height) {
            //在surface的大小发生改变时激发
            Log.i(TAG, "surfaceChanged...");
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            //销毁时激发,一般在这里将画图的线程停止、释放。
            Log.i(TAG, "surfaceDestroyed...");
            CameraInterface.getInstance().doStopCamera();
        }
    
        public SurfaceHolder getSurfaceHolder() {
            // SurfaceHolder当作surface的控制器,用来操纵surface
            return mSurfaceHolder;
        }
    
    }

    TakePhotoView的代码如下:

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.graphics.drawable.BitmapDrawable;
    import android.util.AttributeSet;
    import android.view.View;
    
    import com.sherry.ui.R;
    import com.sherry.util.DeviceInfoUtil;
    
    /**
     * Created by xueli on 2016/11/16.
     *
     * 自定义拍照框View
     *
     */
    public class TakePhotoView extends View {
    
        private Context mContext;
        private Paint mPaint;
    
        public TakePhotoView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.mContext = context;
            mPaint = new Paint();
            mPaint.setAntiAlias(false);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            // 拍照框预览的宽高设置
            Rect frame = new Rect(0, 0, DeviceInfoUtil.getScreenWidth(mContext), DeviceInfoUtil.getScreenHeight(mContext) * 17 / 25);
            
            mPaint.setColor(Color.GRAY);
            Rect faceRect = new Rect();
            faceRect.left = frame.left;
            faceRect.right = frame.right;
            faceRect.top = frame.top;
            faceRect.bottom = frame.bottom;
            canvas.drawBitmap(((BitmapDrawable) (getResources().getDrawable(R.drawable.take_photo_bg))).getBitmap(), null, faceRect, mPaint);
        }
    }

    2、照相机处理类------CameraInterface

    (1)在CameraInterface这个类里面对照相机进行一些处理,包括照相机的开启、预览、拍照、销毁等方法,这里参考博客http://blog.csdn.net/yanzi1225627/article/details/33028041,可以说给我提供了很大的帮助。不过我在它的实现上进行了优化和改进,解决了部分手机的黑屏、拍照或预览变形等问题。因为我这边要求的是拍照之后显示图片在下一个页面进行显示,所以拍照之后不会只是暂停然后继续进行预览,另外要注意的是,我这边使用的是前置摄像头,所以在doOpenCamera()方法中要判断手机摄像头的个数,让它选择开启前置摄像头。具体代码如下:

        /**
         * 打开Camera
         *
         * @param callback
         */
        public void doOpenCamera(CamOpenOverCallback callback) {
            Log.i(TAG, "Camera open....");
            mCamera = null;
            try {
                Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
                mCameraCount = Camera.getNumberOfCameras(); // 获得摄像头的个数
    
                for (int camIdx = 0; camIdx < mCameraCount; camIdx++) {
                    Camera.getCameraInfo(camIdx, cameraInfo); // get camerainfo
                    if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                        // 代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置
                        mCamera = Camera.open(camIdx);
                    }
                }
            } catch (Exception e) {
                Log.e(TAG, "摄像头未正常打开");
            }
    
            Log.i(TAG, "Camera open over....");
            callback.cameraHasOpened();
        }
    (2)接下来就说预览的这个方法doStartPreview(),方法里面的参数用的是设备的宽高。为了适配多个不同分辨率的机型,我这里对获取预览尺寸getPropPreviewSize()方法和获取拍照后的图片尺寸getPropPictureSize()方法进行了修改,传的是一个经过了处理的值,而不是某个固定值,至于这个值是怎么处理的,后面会细说。先上doStartPreview()方法的代码:

    public void doStartPreview(SurfaceHolder holder, int width, int height) {
            Log.i(TAG, "doStartPreview...");
            if (mCamera != null) {
    
                mParams = mCamera.getParameters();
                mParams.setPictureFormat(PixelFormat.JPEG);//设置拍照后存储的图片格式
                //设置PreviewSize和PictureSize
    
                Camera.Size previewSize = CamParaUtil.getInstance().getPropPreviewSize(
                        mParams.getSupportedPreviewSizes(), width, height);
                mParams.setPreviewSize(previewSize.width, previewSize.height);
                Camera.Size pictureSize = CamParaUtil.getInstance().getPropPictureSize(
                        mParams.getSupportedPictureSizes(), previewSize.width, previewSize.height);
                mParams.setPictureSize(pictureSize.width, pictureSize.height);
    
                mCamera.setDisplayOrientation(90);
    
                ......
        }
    首先,从上面这段代码中,我们可以看到在getPropPreviewSize()方法中,我不是传递固定的值,那么传的到底是什么呢,其实是我们手机屏幕的宽高。有人就会疑惑了,那个可以我们可以直接拿到啊,直接把它丢进去就好了呀,干嘛还费这么大的劲儿。这里就要说到每个手机所能提供的预览Size列表了。我这里用的是小米4,它提供的预览Size如下:


    我们知道小米4的分辨率是1920*1080,而我们预览的又是全屏,所以应该拿到全屏的Size,这里正好有对应的Size,所以就通过我优化的方法拿到了。但是如果没有和手机屏幕分辨率的Size呢?那就拿最大的,很多人就有疑问了,拿最大的不会有问题吗?这里就要说到我在开发过程中遇到的一个问题了。

    我在三星S6上面看了它提供的预览Size是没有三星S6的分辨率2560*1440的,同时其他的Size在原来的方法上也没找到匹配的,所以如果不选最大的,选择最小的那个,也就是176*144的话,就会出现预览特别模糊的情况。

    当然这个方法在其他多部手机上也进行了试验,是可以完美解决某些手机上模糊或变形等问题的。getPropPreviewSize()方法的代码如下:

    public Size getPropPreviewSize(List<Size> list, int minWidth, int minHeight) {
            Collections.sort(list, sizeComparator);
            Log.i(TAG, "PreviewSize : minWidth = " + minWidth);
            int i = 0;
            for (Size s : list) {
                Log.i(TAG, "PreviewSize : width = " + s.width + "height = " + s.height);
                if ((s.height == minWidth) && s.width >= minHeight) {
                    Log.i(TAG, "PreviewSize : w = " + s.width + "h = " + s.height);
                    break;
                }
                i++;
            }
            if (i == list.size()) {
                i = list.size() - 1;//如果没找到,就选最大的size
            }
            return list.get(i);
        }

    看了上面的代码又有人问了,你不是要找和分辨率相同的宽高吗?为什么是s.width >= minHeight而不是s.width == minHeight?

    这是因为我在匹配一台低分辨率的HTC手机时,发现它不是标准的800*480,它的高度其实只有768。所以我在判断的时候写的是s.width >= minHeight,而不是等于,其实就是用就近原则拿到我们预览的最合适的高度。当然大家会看到在getPropPreviewSize()方法的第二行有一句

    Collections.sort(list, sizeComparator);
    也就是让我们这个Size的列表进行了一个排序,这样最近的尺寸就是差异最小的。至于为什么那个HTC手机的高度是768呢?我发现HTC手机的底部的屏幕上有几个按键,或许是这几个按键占据了剩下那32个像素,当然这个没有实际根据,暂且搁在一边不管。

    (3)说完了预览的Size,接下来说说getPropPictureSize()方法,这里我传的参数是预览拿到的Size的宽高,也就是下面这句代码中的previewSize.width和previewSize.height。

    Camera.Size pictureSize = CamParaUtil.getInstance().getPropPictureSize(
                        mParams.getSupportedPictureSizes(), previewSize.width, previewSize.height);
    为什么要传这两个参数呢?前面获得预览Size的方法已经完美适配了多台手机,而我们的pictureSize肯定也希望拿到的是和预览看到的至少是相同比例的图片,这样我们拿到的图片才是没有变形的。所以我们只需要拿这两个参数和手机提供的pictureSize列表中的宽高进行比较就好,如果拿不到同样也拿最大的那个图片,原因我就不说了,前面其实说的很清楚了。我们的getPropPictureSize()方法的代码如下:

    public Size getPropPictureSize(List<Size> list, int minWidth, int minHeight) {
            Collections.sort(list, sizeComparator);
    
            int i = 0;
            for (Size s : list) {
                Log.i(TAG, "PreviewSize : width = " + s.width + "height = " + s.height);
                if (s.height == minHeight && s.width == minWidth) {
                    Log.i(TAG, "PreviewSize : w = " + s.width + "h = " + s.height);
                    break;
                }
                i++;
            }
            if (i == list.size()) {
                i = list.size() - 1;//如果没找到,就选最大的size
            }
            return list.get(i);
        }

    (4)开启了预览,自然也有在退出相应的Activity时关闭预览的方法,这里我写了两个关闭预览的方法doStopCamera()doDestroyedCamera(),代码如下:

        /**
         * 停止预览,不需要释放Camera
         */
        public void doStopCamera() {
            try {
                if (null != mCamera) {
                    mCamera.setPreviewCallback(null);
                    mCamera.stopPreview();
                }
            } catch (Exception e) {
                Log.e(TAG, e + "stopCamera");
            }
        }
    
        /**
         * 停止预览,释放Camera
         */
        public void doDestroyedCamera() {
            try {
                if (null != mCamera) {
                    mCamera.setPreviewCallback(null);
                    mCamera.stopPreview();
                    mCamera.release();
                    mCamera = null;
                }
            } catch (Exception e) {
                Log.e(TAG, e + "destoryCamera");
            }
        }
    为什么要用两个关闭预览的方法呢?这两个方法看起来差不多,唯一不同的是doStopCamera()方法没有释放了Camera,而doDestroyedCamera()方法释放了。这里就要说到另一个问题,在部分手机上测试的时候,我发现如果我们点击home键直接从拍照的这个页面退出或者点击back键之后,再重新进入拍照页面就会直接出现黑屏的问题。最终也是去查找了一下原因,原来是我们做这个操作时,那些手机里面的Camera被释放掉了,所以才会出现黑屏。因此我们要合理地释放Camera,在我们的Activity中,我是这样调用这两个方法的。

        @Override
        protected void onPause() {
            super.onPause();
            SurfaceHolder holder = vSurfaceView.getSurfaceHolder();
            vSurfaceView.surfaceDestroyed(holder);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            CameraInterface.getInstance().doDestroyedCamera();
        }
    而在上面代码的surfaceDestroyed()方法中我调用的是doStopCamera()方法,这样我们的Camera就不会被释放,可以顺利唤醒了。不过这里还要提到一点,就是在onResume()方法中加上一个判断,当我们的Surface还是无效的时候,让一个线程休眠50毫秒。因为我们的SurfaceView不可见的时候,Surface就会被销毁。onResume()方法中的处理如下:
        @Override
        protected void onResume() {
            super.onResume();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 解决三星S6等部分机型的黑屏问题
                    try {
                        SurfaceHolder holder = vSurfaceView.getSurfaceHolder();
                        while (!holder.getSurface().isValid()) {
                            Thread.sleep(50);
                        }
                        CameraInterface.getInstance().doStartPreview(holder,
                                DeviceInfoUtil.getScreenWidth(TakePhoto.this), DeviceInfoUtil.getScreenHeight(TakePhoto.this));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

    (4)我看到有人曾经说,想要做成微信扫一扫那样,下面有一部分不显示出来,但是发现预览的时候变形了。其实变形的原因除了是获取的预览Size有问题,还有一点就是我们的这个SurfaceView的宽高设置的不正确。请一定一定设置成全屏,另外说到微信扫一扫,其实也是全屏预览的,只是底部的控件把预览框盖住了一部分而已。想象摄像头拍的是正常的预览的样子,你非要把预览的样子改成一个和它比例不一样的,宽度相同,高度不同,不变形才怪。如果真的想制造一种我只用了不到一个屏幕的高度在拍照,可以使用相对布局,直接用下方的控件盖住一定的高度就好。至于大家会说拍出来的照片会把下面显示出来,那把拍出来的照片进行裁剪就好了呀。此外要注意的一点就是,在拍照页面对应的Activity中一定要设置好SurfaceView的宽高为全屏的宽高,也就是我在这个里面写的setSurfaceView()方法。对应的Activity和布局代码如下:

    import android.app.Activity;
    import android.content.Intent;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.SurfaceHolder;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    import android.widget.Toast;
    
    import com.sherry.face.CameraInterface;
    import com.sherry.face.MySurfaceView;
    import com.sherry.ui.R;
    import com.sherry.util.DeviceInfoUtil;
    import com.sherry.util.FileUtil;
    import com.sherry.util.ImageUtil;
    
    import java.io.File;
    
    /**
     * 拍照页面
     *
     * Created by xueli on 2016/11/15.
     */
    public class TakePhoto extends Activity implements CameraInterface.CamOpenOverCallback, View.OnClickListener {
    
        private static final String TAG = "TakePhoto";
        public static File mTempFile;
        private final int WHAT_TAKE_PHOTO_SUCCEED = 0;
        private String TEMP_PHONE_FILENAME = "";
    
        private MySurfaceView vSurfaceView;
        private Handler mHandler = new Handler() {
            @Override
            public void dispatchMessage(Message msg) {
                super.dispatchMessage(msg);
                switch (msg.what) {
                    case WHAT_TAKE_PHOTO_SUCCEED:
                        if (msg.obj != null) {
                            Uri uri = (Uri) msg.obj;
                            Intent intent = new Intent(TakePhoto.this, Preview.class);
                            intent.setDataAndType(uri, "image/*");
                            startActivity(intent);
                            finish();
    }
                        break;
                    default:
                        break;
                }
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.face_take_photo);
            setSurfaceView();
            Thread openThread = new Thread(){
                @Override
                public void run() {
                    CameraInterface.getInstance().doOpenCamera(TakePhoto.this);
                }
            };
            openThread.start();
            findView();
        }
    
        private void setSurfaceView() {
            vSurfaceView = (MySurfaceView) findViewById(R.id.sv_take_photo);
            ViewGroup.LayoutParams params = vSurfaceView.getLayoutParams();
            params.width = DeviceInfoUtil.getScreenWidth(this);
            params.height = DeviceInfoUtil.getScreenHeight(this);
            vSurfaceView.setLayoutParams(params);
        }
    
        private void findView() {
            RelativeLayout rl = (RelativeLayout) findViewById(R.id.rl_face_take_photo);
            RelativeLayout.LayoutParams rlPs = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
                    RelativeLayout.LayoutParams.WRAP_CONTENT);
            rlPs.width = DeviceInfoUtil.getScreenWidth(this);
            rlPs.height = DeviceInfoUtil.getScreenHeight(this);
            rl.setLayoutParams(rlPs);
    
            LinearLayout llBottom = (LinearLayout) findViewById(R.id.ll_face_take_photo);
            RelativeLayout.LayoutParams llPs = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
                    RelativeLayout.LayoutParams.WRAP_CONTENT);
            llPs.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            llPs.width = DeviceInfoUtil.getScreenWidth(this);
            llPs.height = DeviceInfoUtil.getScreenHeight(this) * 8 / 25;
            llBottom.setLayoutParams(llPs);
            Button btnTakePhoto = (Button) findViewById(R.id.btn_take_photo);
            btnTakePhoto.setOnClickListener(this);
        }
    
        @Override
        public void cameraHasOpened() {
            SurfaceHolder holder = vSurfaceView.getSurfaceHolder();
            CameraInterface.getInstance().doStartPreview(holder,
                    DeviceInfoUtil.getScreenWidth(TakePhoto.this), DeviceInfoUtil.getScreenHeight(TakePhoto.this));
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.btn_take_photo:
                    if (ImageUtil.hasSdcard()) {
                        FileUtil.prepareFile(Environment.getExternalStorageDirectory() + "/DCIM/"); // 准备文件夹
                        String fileName = ImageUtil.getPhotoFileName();
                        mTempFile = new File(Environment.getExternalStorageDirectory() + "/DCIM/", fileName);
                        TEMP_PHONE_FILENAME = fileName;
                        try {
                            CameraInterface.getInstance().doTakePicture();
                            Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/DCIM/",
                                    TEMP_PHONE_FILENAME));
                            Log.d(TAG, "Uri===" + String.valueOf(uri));
                            Message msgObj = mHandler.obtainMessage(WHAT_TAKE_PHOTO_SUCCEED, uri);
                            mHandler.sendMessageDelayed(msgObj, 2000);
                        } catch (Exception e) {
                            Toast.makeText(this, "您的设备未正常打开,请重试", Toast.LENGTH_LONG).show();
                            Log.e(TAG, e + "您的设备未正常打开,请重试");
                        }
                    } else {
                        Toast.makeText(this, "没找到SD卡", Toast.LENGTH_LONG).show();
                    }
                    break;
                default:
                    break;
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // 解决三星S6等部分机型的黑屏问题
                    try {
                        SurfaceHolder holder = vSurfaceView.getSurfaceHolder();
                        while (!holder.getSurface().isValid()) {
                            Thread.sleep(50);
                        }
                        CameraInterface.getInstance().doStartPreview(holder,
                                DeviceInfoUtil.getScreenWidth(TakePhoto.this), DeviceInfoUtil.getScreenHeight(TakePhoto.this));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            SurfaceHolder holder = vSurfaceView.getSurfaceHolder();
            vSurfaceView.surfaceDestroyed(holder);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            CameraInterface.getInstance().doDestroyedCamera();
        }
    }

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <RelativeLayout
            android:id="@+id/rl_face_take_photo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <com.sherry.face.MySurfaceView
                android:id="@+id/sv_take_photo"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
    
            <com.sherry.face.TakePhotoView
                android:id="@+id/tpv_take_photo"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </RelativeLayout>
    
        <LinearLayout
            android:id="@+id/ll_face_take_photo"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:background="@color/white">
    
            <Button
                android:id="@+id/btn_take_photo"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:padding="15dp"
                android:text="@string/take_photo"
                android:textColor="@color/white"
                android:textSize="@dimen/text_size_16" />
    
        </LinearLayout>
    
    </RelativeLayout>

    好的,关于照相机的预览、拍照、以及机型出现的各种问题解决方式就介绍到这里,最后别忘了在清单文件中加上照相机和SD卡读写权限:

        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.CAMERA" />
    
        <uses-feature android:name="android.hardware.camera" />
        <uses-feature android:name="android.hardware.camera.autofocus" />

    转载请注明http://write.blog.csdn.net/postedit/53189034。



    展开全文
  • 项目中最近需要用到摄像机拍照,起初的时候肯定怎么省事怎么来,直接就是调用系统的摄像机了,那么问题来了,调用系统摄像机的时候,发现不同的手机拍摄出的照片的旋转角度不一样。举个例子来说,小米手机拍摄出的...
  • 在程序中我使用手机相机拍一张照片,然后把这张图片保存在手机图库里面。然后我想获取图片的路径,再保存到数据库中。如何实现呢? public void onClick(View v){ switch(v.getId()) ... final CharSequence[] ...
  • 最近用到了android中的照相机功能,android中实现拍照的方式有两种,一种是调用系统自带的照相机进行拍照,此种方法较为简单,因为是android本身就已经实现了的;另一种就是自己来实现一个拍照程序,可按照自己的...
  • Android自定义照相机 预览拍照 切换前后置摄像头

    万次阅读 多人点赞 2014-02-18 23:29:07
    Android提供了Camera来控制拍照,步骤如下: (1)调用Camera的open()方法打开相机。 ...(2)调用Camera的getParameters()获取拍照参数,该方法返回一个Cmera....(3)调用Camera.Parameters对象对照相的参数进行
  • Android基础——跳转照相机界面拍照

    千次阅读 2018-01-06 10:21:38
    //一个简单的跳转转界面拍照 package com.animee.day07.demo03; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import ...
  • 1.首先拍照和保存文件肯定就需要申请权限 &lt;!-- 往SDCard写入数据权限 --&gt; &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&gt; &lt;!--...
  • 使用intent调用系统照相机拍照

    千次阅读 2016-09-15 09:05:06
    1.使用intent调用系统照相机拍照 static final int REQUEST_IMAGE_CAPTURE = 1; private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if ...
  • input file 拍照照相

    2017-10-10 16:27:00
    2019独角兽企业重金招聘Python工程师标准>>> ...
  • Android 调用系统照相机拍照和录像
  • 不止一次听到同学的抱怨,说Win7下貌似没有用摄像头拍照的功能。在XP系统中貌似是在“我的电脑”里就能找到摄像头,也可以直接拍照。...不到30行,就可以完成一个简单的照相程序。代码贴上,也做了简单的注释
  • 我们常见的上传文件或者图片 是...如果是上传照片图片,安卓机有一个问题,只能选取照片,不能去调取相机进行拍照。 而苹果机 ios系统的 会直接出现选择 相机拍照还是照片图库。 所以解决安卓调取照相机的问题,...
  • 1.调用照相机 //启动系统照相机 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); ...2.拍照后存储 @Override protected void onActivityResult(int requestCode, int resultCode,
  • 1、首先定义一个Button,android:click = "click" ...Intent intent = new Intent(); intent.setAction("android.media.action.IMAGE_CAPTURE"); intent.addCategory("android.intent.category.DEFAULT");...
  • 转载自:https://www.cnblogs.com/dongweiq/p/6478393.html需求:调用系统照相机进行拍照,并且保存到系统相册,调用系统相册的时候能看到系统相册的路径:String cameraPath=Environment....+ File.separator + ...
  • [UE4][Blueprint]虚幻4实现照相机拍照功能 创建渲染目标,绘制渲染目标,创建动态材质实例,设置实例图片参数为渲染目标,setbrush
  • android调用照相机拍照获取照片并…

    万次阅读 2014-06-23 13:17:54
    1.调用系统的照相机程序 Intent intent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE);  startActivityForResult(intent,TAKE_PHOTO_WITH_DATA); 2.在onActivityResult中处理返回的data final Bitmap photo = data...
  • 手机拍照然后上传图片时,路径不为空为什么总是上传失败啊?但是选择本地相册是成功的,照相之后打印出来的图片路径是/storage/emulated/0/Pictures/1476511270681.jpg。调取照相机的方法用了两种,第一种使用...
  • [Android] 拍照、截图、保存并显示在ImageView控件中

    万次阅读 多人点赞 2014-10-23 22:03:24
    作者购买了本《Android第一行代码 著:郭霖》,参照里面的内容完成.网上这类资料非常多,作者仅仅分享给初学者同时在线记录些内容,希望对大家有所帮助.首先,设置activity_main.xml为LinearLayout布局,添加函数实现点击...
  • android 自定义照相机

    万次阅读 热门讨论 2014-12-03 14:33:58
    做了一个dome,内容和功能都很简单,当练练手 部分代码参考了一个博客...具体就是调用系统的摄相机拍照保存到手机,以后返回相片的文件地址 效果图: 照相界面的布局文件: android:id="@+id/surfaceView
  • android拍照的两种方法

    千次阅读 2018-07-11 09:59:56
    android系统的照相功能,已实现2种方法,可供大家参考:1.调用系统摄像头来拍照首先,找到AndroidManifest.xml文件里加入用户权限&lt;uses-permission android:name="android.permission.CAMERA"&...
  • Android_照相机Camera_调用系统照相机返回data为空

    万次阅读 多人点赞 2013-11-24 09:29:56
    于是我查看了Android系统框架Camera应用程序,找到了关于系统照相机如何处理返回值data问题! 默认情况下,即不需要指定intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);照相机有自己默认的存储路径,拍摄的照片将...
  • 前言:这段时间也真是忙到死,本来一个月四篇的承诺,眼看就要打破了,咬着牙再出两篇,最近写工程时,遇到拍照和裁剪功能,也真是服了,各种问题有木有,最后终于找着了一个解决方案,就目前来讲,应用在工程中,还...

空空如也

1 2 3 4 5 ... 20
收藏数 147,033
精华内容 58,813
关键字:

拍照