安卓开发之手机相机(Camera)应用

手机相机应用拍摄图片的旋转处理

讲解之前我说段废话,当你选择了语言开发时,你就要永远的学习下去,没有终点,除非你选择转行,要不然你不能停止。
好了,我们开始进入讲解过程:
我之所以讲相机的原因是在网上很多人也说过了相机的应用,但是他们漏掉了一个问题就是我们在做相机应用时,会出现一个问题,那就是拍摄出来的图片,不管我们怎么用手机拍摄出来的照片都是横向的,对于这个问题很多人没有在意,而我在做过相关项目时发现了这个小问题,但是大多数人都会忽略的问题。
下面我贴出代码解释一下:

为了很直观的看懂代码,我直接就写在一个Activity里面,其实在开发过程中这是一种不好代码编写方式,但是在以后我会按照开发过程中的代码编写方式来展现给大家。
今后看代码的时候,千万不要看着代码很长,就没有想看的心思,这样会对你又很大的局限,当你走上编程之路时,那才是真正的长,所以要学会强迫自己去看

我直接贴出代码:有几个要注意的地方我注释一下
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener,Callback,AutoFocusCallback{
    
    //这里的Callback一定是这包下的import android.view.SurfaceHolder.Callback的

    private SurfaceHolder surfaceHolder;
    private SurfaceView surfaceView;
    private ImageView disImageView;
    private Button paiButton;
    private boolean isClick;
    private Camera camera;
    private Bitmap reBitmap;
    private BitmapDrawable drawable;
    private String picPath = Environment.getExternalStorageDirectory().getAbsolutePath().toString()+"x"+System.currentTimeMillis()+".jpg";

    /**
     * 描述:将图片旋转到竖直方向并保存图片
     * 这里就是将图片旋转处理的地方
     * 我们先将图片旋转后在写入到sdcard里面去
     */
    PictureCallback jpeg = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            try{
                Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
                //旋转图片的显示方向
                int scale_t = 1,scale_a = 1;
                final int width = bitmap.getWidth();
                final int height = bitmap.getHeight();
                int newWidth = width*scale_t;
                int newHeight = height*scale_a;
                float scaleWidth = ((float)newWidth)/width;
                float scaleHeight = ((float)newHeight)/height;
                Matrix matrix = new Matrix();//使用这个类将图片旋转90度
                matrix.postScale(scaleWidth, scaleHeight);
                matrix.setRotate(90*scale_a);//其实这里的scale_a可以不用,只是这样写,看起来高大上
                reBitmap = Bitmap.createBitmap(bitmap,0,0,width,height);
                //存储图片
                File file = new File(picPath);
                BufferedOutputStream bStream = new BufferedOutputStream(new FileOutputStream(file));
                reBitmap.compress(Bitmap.CompressFormat.JPEG,100,bStream);
                bStream.flush();
                bStream.close();
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        inifindView();//初始化组件
    }
    /**
     * 描述:初始化组件
     */
    @SuppressWarnings("deprecation")
    private void inifindView() {
        surfaceView = (SurfaceView) findViewById(R.id.cameras);
        disImageView = (ImageView) findViewById(R.id.dis_imag);
        paiButton = (Button) findViewById(R.id.camera_bt);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        paiButton.setOnClickListener(this);
    }

    @SuppressWarnings("deprecation")
    @Override
    public void onClick(View v) {
        if(!isClick){
            camera.autoFocus(this);
            Toast.makeText(this,"自动聚焦",Toast.LENGTH_SHORT).show();  
            isClick = true;
        }else{
            camera.startPreview();
            if(reBitmap != null){
                drawable = new BitmapDrawable(reBitmap);
                disImageView.setBackgroundDrawable(drawable);
            }else{
                disImageView.setBackgroundColor(Color.WHITE);
            }
            isClick = false;
        }
    }
    /**
     * 描述:照相时,请求调焦
     */
    @SuppressWarnings("deprecation")
    @Override
    public void onAutoFocus(boolean success, Camera camera) {
        if(success){
            //设置参数
            Camera.Parameters parameters = camera.getParameters();
            parameters.setPictureFormat(PixelFormat.JPEG);
            parameters.setPictureSize(800,480);//这里请大家注意,这里的数字不是越大越好,如果过大,就会抛出异常,我自己的手机刚好这个数值上,如果你使用了我写的这数值而报错的话,请你将其数值改小
            camera.setParameters(parameters);
            camera.setDisplayOrientation(90);//这里必须写上,这是旋转90度,如果少了这个设置,即使我上面使用Matrix处理,图片依旧是横向的
            camera.takePicture(null, null, jpeg);
        }
    }

    /**
     * 描述:创建并打开默认摄像(一般是指后置摄像头)
     */
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if(camera == null){
            camera = Camera.open();//camera = Camera.open(cameraId);据说是打开和切换前后摄像头的方法,我在公司开发中没有用的过前置摄像头,所以我就没去弄过
            try{
                camera.setPreviewDisplay(surfaceHolder);//将其显示加载到SurfaceView上
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    @SuppressWarnings("deprecation")
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        //配置摄像的参数
        Camera.Parameters parameters = camera.getParameters();
        parameters.setPictureFormat(PixelFormat.JPEG);//图片的格式
        parameters.setPictureSize(800,480);//图片的大小,一定的注意,这里的数字不要太大,否则会报异常
        camera.setDisplayOrientation(90);//旋转90度
        camera.startPreview();
    }
    /**
     * 描述:结束照相时,调用的
     */
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.stopPreview();
        camera.release();
        camera = null;
    }
}
接下来就是简单的布局文件了
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <SurfaceView 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/cameras"
        />

    <Button 
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:id="@+id/camera_bt"
        android:layout_gravity="center_horizontal|bottom"
        android:text="拍照"
        android:background="@drawable/btn_round_n"
        android:textSize="13sp"
        android:layout_margin="2dp"
        />
    <ImageView 
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:id="@+id/dis_imag"
        android:background="#E9F6E8"
        android:layout_gravity="bottom|right"
        android:layout_margin="3dp"
        />
</FrameLayout>
其次是权限配置
  <!-- 在SDCard中创建与删除文件权限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <!-- 往SDCard写入数据权限 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-feature android:name="android.hardware.camera" />

最后是有图有真相
这里写图片描述
源代码下载地址:http://download.csdn.net/detail/qq_22183039/9477394
拍照的那个按钮我做了处理,如果想要源代码的可以到我博客上下载,我会上传到我的博客上
如果你真的想学好安卓,我建议还是去买点书或者其他的学习工具,我以前就买过这本书,我觉得可以,很详细,不妨去看看http://s.click.taobao.com/t?e=m%3D2%26s%3De%2FjSd5R7sk4cQipKwQzePOeEDrYVVa64K7Vc7tFgwiFRAdhuF14FMZYMEx%2BUAxGj1aH1Hk3GeOi1upsGVP%2BE7bIieqNcnEROPzWt%2BD5CzV2G%2FOj6X2BCoBtlrJbLMDAQEzj78aukG9UXhGhiqu2JwsYMXU3NNCg%2F&pvid=50_113.91.67.120_431_1459356271854

猜你喜欢

转载自blog.csdn.net/qq_22183039/article/details/51020777