1. 程式人生 > >手機拍照及簡單的圖片壓縮

手機拍照及簡單的圖片壓縮

tostring empty itl nts map amp ffffff manage 創建目錄

凝視都在代碼裏,這裏就不再說了。特別註意cnClick中的//TODO凝視以及onActivityResult方法中的凝視
效果圖

技術分享圖片

權限:

 <!-- 在SD卡中創建與刪除文件權限 -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <!-- 向SD卡寫入數據權限 -->
    <uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

使得屏幕不旋轉:

    <activity
       android:name=".MainActivity_21_Photo_Compress_Img"
       android:screenOrientation="portrait"/>

1、布局:
1.1主界面的布局:activity_main_21

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android
="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#F6F6F6" android:fitsSystemWindows="true" android:orientation="vertical">
<RelativeLayout
android:id="@+id/search_gold_expert_back_title" android:layout_width="match_parent" android:layout_height="50dp" android:background="#ec434b" android:gravity="center_vertical" android:orientation="horizontal">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="點擊icon" android:textColor="#ffffff" android:textSize="20sp"/> </RelativeLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:overScrollMode="never" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/iv_image" android:layout_width="310dp" android:layout_height="250dp" android:layout_gravity="center_horizontal" android:layout_margin="10dp" android:src="@mipmap/ic_launcher"/> <TextView android:id="@+id/show_tv_21" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:background="#ec434b" android:gravity="center" android:onClick="onClick" android:paddingBottom="10dp" android:paddingTop="10dp" android:text="顯示結果" android:textColor="#4F4F4F" android:textSize="16sp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:lineSpacingMultiplier="1.4" android:text="拍照得到照片的原路徑" android:textColor="#4F4F4F" android:textSize="16sp"/> <TextView android:id="@+id/result_url_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:lineSpacingMultiplier="1.4" android:textColor="#4F4F4F" android:textSize="16sp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:lineSpacingMultiplier="1.4" android:text="拍照得到照片的大小" android:textColor="#4F4F4F" android:textSize="16sp"/> <TextView android:id="@+id/photo_src_size" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:lineSpacingMultiplier="1.4" android:textColor="#4F4F4F" android:textSize="16sp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:lineSpacingMultiplier="1.4" android:text="壓縮後的圖片的路徑" android:textColor="#4F4F4F" android:textSize="16sp"/> <TextView android:id="@+id/result_url_tv_2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:lineSpacingMultiplier="1.4" android:textColor="#4F4F4F" android:textSize="16sp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:lineSpacingMultiplier="1.4" android:text="壓縮後照片的大小" android:textColor="#4F4F4F" android:textSize="16sp"/> <TextView android:id="@+id/photo_compress_size" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:lineSpacingMultiplier="1.4" android:textColor="#4F4F4F" android:textSize="16sp"/> </LinearLayout> </ScrollView> </LinearLayout>

1.2popupwindow的布局:photo_select_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/dialog_container"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#000000"
        />

    <TextView
        android:id="@+id/pic_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#f6f6f6"
        android:gravity="center"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:text="從相冊中選取"
        android:textSize="20sp"
        />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#000000"
        />

    <TextView
        android:id="@+id/pic_from_take_photo_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#f6f6f6"
        android:gravity="center"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:text="拍照"
        android:textSize="20sp"
        />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#000000"
        />

    <TextView
        android:id="@+id/cancle_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#f6f6f6"
        android:gravity="center"
        android:paddingBottom="10dp"
        android:paddingTop="10dp"
        android:text="取消"
        android:textSize="20sp"
        />

</LinearLayout>

2、工具類及其它準備的東西
2.1:Utils

 /**
     * 把浮點型數據轉換成小數點後2位的數
     * @param f
     * @return
     */
    public static String getNumAccuracy_2(float f) {

        //構造方法的字符格式這裏假設小數不足2位,會以0補足.
        DecimalFormat decimalFormat = new DecimalFormat(".00");
        //format 返回的是字符串
        String result = decimalFormat.format(f);
        return result;

    }

2.2:全局變量:CHEN

 /**
     * 圖片壓縮的邊界值。

以2M為例。超過2M,就對圖片進行壓縮 */ public static long img_compress_limit = 2 * 1048 * 1024; /** * 拍照後存儲照片的路徑 */ public static String img_path = Environment.getExternalStorageDirectory() + "/chen/img"; /** * 存放壓縮後的圖片的路徑 */ public static String img_compress_path = Environment.getExternalStorageDirectory() + "/chen/compress/"; public static int picWidth = 1000; public static int picHeight = 1000;

2.3:PopSelectListener

/**
 * 圖片來源選擇的popupwindow
 */
public interface PopSelectListener {

    void popSelect(int flag);
}

2.4:popupwindow:PhotoFromSelectPop

package com.chen.customviewdemo.view;


import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.PopupWindow;

import com.chen.customviewdemo.R;
import com.chen.customviewdemo.listener.PopSelectListener;

/**
 * 從底部出來的PopupWindow
 */
public class PhotoFromSelectPop {

    Context context;
    private PopupWindow popupWindow;
    View popupWindowView;

    public PhotoFromSelectPop(Context context) {
        this.context = context;
    }

    /**
     * 初始化
     */
    public void initPopupWindow(final PopSelectListener listener) {

        popupWindowView = LayoutInflater.from(context).inflate(R.layout.photo_select_layout, null);
        popupWindow = new PopupWindow(popupWindowView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, true);

        popupWindow.setAnimationStyle(R.style.BottompSelectAnimationShow);
        // 菜單背景色。加了一點透明度
        ColorDrawable dw = new ColorDrawable(0xddffffff);
        popupWindow.setBackgroundDrawable(dw);

        popupWindow.showAtLocation(LayoutInflater.from(context).inflate(R.layout.activity_main, null),
                Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);

        // 設置背景半透明
        backgroundAlpha(0.7f);

        popupWindow.setOnDismissListener(new popupDismissListener());

        popupWindowView.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return false;
            }
        });

        popupWindowView.findViewById(R.id.pic_tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                listener.popSelect(0);
                dimss();
            }
        });

        popupWindowView.findViewById(R.id.pic_from_take_photo_tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.popSelect(1);
                dimss();
            }
        });

        popupWindowView.findViewById(R.id.cancle_tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dimss();
            }
        });

    }

    /**
     * 設置加入屏幕的背景透明度
     *
     * @param bgAlpha
     */
    public void backgroundAlpha(float bgAlpha) {
        WindowManager.LayoutParams lp = ((Activity) context).getWindow().getAttributes();
        lp.alpha = bgAlpha; // 0.0-1.0
        ((Activity) context).getWindow().setAttributes(lp);
    }

    class popupDismissListener implements PopupWindow.OnDismissListener {

        @Override
        public void onDismiss() {
            backgroundAlpha(1f);
        }
    }

    public void dimss() {
        if (popupWindow != null) {
            popupWindow.dismiss();
        }
    }


}

2.4.1:styles.xml

   <style name="BottompSelectAnimationShow">
        <item name="android:windowEnterAnimation">@anim/bottom_enter</item>
        <item name="android:windowExitAnimation">@anim/bottom_exit</item>
    </style>

2.4.2:bottom_enter

<?

xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromYDelta="100%" android:toYDelta="0" android:duration="500"/> </set>

2.4.3:bottom_exit

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <translate
        android:duration="500"
        android:fromYDelta="0"
        android:toYDelta="100%"/>

</set>

2.5:FileHelper


import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;


public class FileHelper {

    /**
     * 檢查指定路徑下的文件尺寸
     *
     * @param filePath
     * @return
     */
    public static String checkFileSize(String filePath) {
        File file = new File(filePath);
        if (file.length() > CHEN.img_compress_limit) {
            System.out.print("照片大於2M進行壓縮=" + file.length());
            String compress_img = CHEN.img_compress_path + System.currentTimeMillis() + ".jpg";
            compressPic(filePath, compress_img);
            return compress_img;
        } else {
            return filePath;
        }
    }

    /**
     * 壓縮圖片
     *
     * @param fromPicUrl
     */
    public static void compressPic(String fromPicUrl, String compress_img_path) {

        int width = CHEN.picWidth;
        int height = CHEN.picHeight;

        BitmapFactory.Options opts = new BitmapFactory.Options();
        opts.inJustDecodeBounds = true; // 翻譯:僅僅是解碼邊界
        // 當opts不為null時,但decodeFile返回空,
        // 不為圖片分配內存,僅僅獲取圖片的大小,並保存在opts的outWidth和outHeight
        Bitmap bitmap = BitmapFactory.decodeFile(fromPicUrl, opts);

        int srcWidth = opts.outWidth; // 獲得原始圖片的長
        int srcHeight = opts.outHeight; // 獲得原始圖片的寬
        Log.e("CHEN", "原始圖片的寬高=" + srcWidth + "/" + srcHeight);

        opts.inJustDecodeBounds = false; // 設置載入照片進入內存中
        int be = 0; // 縮放倍數(假設為2,則長,寬各自縮短一倍,整張圖片縮短至四分之中的一個)
        int x = 0; // 長的倍數
        int y = 0; // 寬的倍數

        if (srcWidth > srcHeight) {
            x = srcWidth / width;
            y = srcHeight / height;
        } else {
            x = srcWidth / height;
            y = srcHeight / width;
        }

        if (x > y) {
            be = y;
        } else {
            be = x;
        }

        if (be <= 0) {
            be = 1;
        }
        opts.inSampleSize = be; // 設置縮放倍數

        bitmap = BitmapFactory.decodeFile(fromPicUrl, opts); // 讀取縮放後的圖片

        srcWidth = bitmap.getWidth(); // 取得縮放後的長度
        srcHeight = bitmap.getHeight(); // 取得縮放後的寬度

        float scaleWidth = 0; // 定義截取的固定長度
        float scaleHeight = 0; // 定義截取的固定寬度
        if (srcWidth > srcHeight) {
            scaleWidth = (float) width / srcWidth; // 按固定大小縮放 sWidth 寫多大就多大
            scaleHeight = (float) height / srcHeight;
        } else {
            scaleWidth = (float) height / srcWidth; // 按固定大小縮放 sWidth 寫多大就多大
            scaleHeight = (float) width / srcHeight;
        }

        if (scaleHeight != 1.0 && scaleWidth != 1.0) {// 排除手機拍出來的就是320*240的
            Matrix matrix = new Matrix(); // 定義圖片的矩陣對象
            matrix.postScale(scaleWidth, scaleHeight); // 傳入縮放的比例值
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, srcWidth, srcHeight, matrix, false);// 取得320*240的圖片
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        bitmap.compress(Bitmap.CompressFormat.PNG, 60, baos);
        byte[] pictureByte = baos.toByteArray();

        // 釋放bitmap的內存,非常重要
        bitmap.recycle();

        // 將bitmap保存為文件
        OutputStream os = null;
        try {
            File file = new File(compress_img_path); // 定義保存照片的文件
            if (!file.exists()) {
                mkdirs(CHEN.img_compress_path, getname(compress_img_path));
            }
            os = new FileOutputStream(file); // 文件輸出流
            os.write(pictureByte, 0, pictureByte.length); // 寫入文件
        } catch (Exception e) {
            e.toString();
        } finally {
            try {
                if (os != null) {
                    os.close(); // 關閉文件輸出流
                }
            } catch (IOException e) {
                e.toString();
            }
        }
    }


    /**
     * 切割字符串,得到不包括路徑的文件名稱
     */
    public static String getname(String str) {
        String name = "";
        String[] ss = str.split("/");
        name = ss[ss.length - 1];
        return name;
    }


    /**
     * 創建目錄
     */
    public static File mkdirs(String path, String name) {
        File file = new File(path);
        if (!file.exists()) {
            try {
                file.mkdirs();
            } catch (Exception e) {
                return null;
            }
        }
        file = createNewFile(path + "/" + name);
        return file;
    }

    /**
     * 創建文件
     */
    public static File createNewFile(String path) {
        File file = new File(path);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                return null;
            }
        }
        return file;
    }
}

3、主代碼


import android.content.Intent;
import android.net.Uri;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.chen.customviewdemo.listener.PopSelectListener;
import com.chen.customviewdemo.utils.CHEN;
import com.chen.customviewdemo.utils.FileHelper;
import com.chen.customviewdemo.utils.Utils;
import com.chen.customviewdemo.view.PhotoFromSelectPop;

import java.io.File;

/**
 * 拍照。並壓縮圖片
 */
public class MainActivity_21_Photo_Compress_Img extends BaseActivity implements View.OnClickListener, PopSelectListener {

    ImageView iv_image;
    TextView result_url_tv;
    TextView result_url_tv_2;
    TextView photo_src_size;
    TextView photo_compress_size;
    TextView show_tv_21;

    PhotoFromSelectPop photoFromSelectPop;

    String url;
    String imageName;

    String compress_url;

    @Override
    void initview() {
        setContentView(R.layout.activity_main_21);

        iv_image = (ImageView) findViewById(R.id.iv_image);
        result_url_tv = (TextView) findViewById(R.id.result_url_tv);
        result_url_tv_2 = (TextView) findViewById(R.id.result_url_tv_2);
        photo_src_size = (TextView) findViewById(R.id.photo_src_size);
        photo_compress_size = (TextView) findViewById(R.id.photo_compress_size);
        show_tv_21 = (TextView) findViewById(R.id.show_tv_21);

        iv_image.setOnClickListener(this);
        show_tv_21.setOnClickListener(this);

        File file = new File(CHEN.img_path);
        if (!file.exists()) {
            try {
                file.mkdirs();
                Toast.makeText(this, "路徑創建成功", Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                Toast.makeText(this, "路徑創建失敗", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.iv_image:

                photoFromSelectPop = new PhotoFromSelectPop(this);
                photoFromSelectPop.initPopupWindow(this);

                break;
            case R.id.show_tv_21:
                //TODO
                //點擊顯示結果。這僅僅是demo,沒有做太多推斷,不要有益報空指針。拍完照以後,等3秒左右再點擊

                result_url_tv.setText(url);

                File file = new File(url);

                photo_src_size.setText("圖片大小==KB==" + Utils.getNumAccuracy_2(file.length() / 1024f) + "---圖片大小==MB==" + Utils.getNumAccuracy_2(file.length() / (1024f * 1024f)));

                //壓縮
                result_url_tv_2.setText(compress_url);

                File compress_file = new File(compress_url);
                photo_compress_size.setText("圖片大小==KB==" + Utils.getNumAccuracy_2(compress_file.length() / 1024) + "---圖片大小==MB==" + Utils.getNumAccuracy_2(compress_file.length() / (1024f * 1024f)));


                break;
        }

    }

    @Override
    public void popSelect(int flag) {

        switch (flag) {
            case 0:

                Toast.makeText(this, "從相冊選取", Toast.LENGTH_SHORT).show();

                break;

            case 1:
                //拍照
                imageName = "/" + System.currentTimeMillis() + ".jpg";
                Intent intent_photo = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                intent_photo.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(CHEN.img_path, imageName)));
                startActivityForResult(intent_photo, 1002);
                break;

        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != 0) {
            url = CHEN.img_path + imageName;
            if (!TextUtils.isEmpty(url)) {

                //開一個子線程去處理壓縮。

這是由於,壓縮會由於一些原因先運行。即:拍照結束後,點擊確認button,會停一下,才跳轉回自己的界面。開了子線程去處理壓縮。會讓跳轉變的流暢一點 new Thread() { public void run() { //壓縮 compress_url = FileHelper.checkFileSize(url); } }.start(); } } else { result_url_tv.setText("沒有拍照,返回"); } super.onActivityResult(requestCode, resultCode, data); } }

手機拍照及簡單的圖片壓縮