手機拍照及簡單的圖片壓縮
阿新 • • 發佈:2018-03-01
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);
}
}
手機拍照及簡單的圖片壓縮