您的位置:首页 > 移动开发 > Android开发

Android调用相机拍照,压缩图片后保存SD卡中

2016-06-23 14:19 465 查看
最近在搞一个项目,需求是调用系统相机拍完照片后保存本地,再上传至后台服务器,但为了节省流量需要压缩上传,将图片压缩至100K以内。这个是在特定机器上运行,类似于手持POS机,但是它的相机几乎没有优化,对焦慢,而且拍照也不清晰,使用自己的手机调用系统相机拍照后图片大概有300K左右,自动已经压缩了,但这个机器没有优化,调用相机拍照后的图片和原图一样2M左右,太大了,必须要压缩!

网上找了些资料,也作为参考:Android图片压缩 质量压缩和尺寸压缩安卓相机拍摄照片,压缩后存储于SD卡

项目需要的效果为:



上代码:

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
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{

private Button openCamera,openCamera2;
private ImageView showImgView;

Uri photoUri;
String filePath;  //图片路径

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

findView();

}

private void findView() {
// TODO Auto-generated method stub
openCamera = (Button) findViewById(R.id.openCamera);
openCamera2 = (Button) findViewById(R.id.openCamera2);
showImgView = (ImageView) findViewById(R.id.showImgView);
openCamera.setOnClickListener(this);
openCamera2.setOnClickListener(this);
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()){
case R.id.openCamera:
//打卡相机前先检测SD卡是否可以用
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
photoUri = patrUri("file1");
startCamera(1001,photoUri);
}else{
Toast.makeText(MainActivity.this, "SD卡不可用", Toast.LENGTH_SHORT).show();
}
break;
case R.id.openCamera2:
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
photoUri = patrUri("file2");
startCamera(1002,photoUri);
}else{
Toast.makeText(MainActivity.this, "SD卡不可用", Toast.LENGTH_SHORT).show();
}
break;
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1001){
if(resultCode == RESULT_OK){
FileInputStream is = null;
try {
is = new FileInputStream(filePath);
Bitmap bitmap = BitmapFactory.decodeStream(is);
showImgView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
if(requestCode == 1002){
if(resultCode == RESULT_OK){

try {
Bitmap bitmap = compressBySize(filePath,480,800);  //设置压缩后图片的高度和宽度
saveFile(bitmap,filePath);
showImgView.setImageBitmap(bitmap);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

// 压缩图片尺寸
private static Bitmap compressBySize(String pathName, int targetWidth,
int targetHeight) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;// 不去真的解析图片,只是获取图片的头部信息,包含宽高等;
Bitmap bitmap = BitmapFactory.decodeFile(pathName, opts);
// 得到图片的宽度、高度;
float imgWidth = opts.outWidth;
float imgHeight = opts.outHeight;
// 分别计算图片宽度、高度与目标宽度、高度的比例;取大于等于该比例的最小整数;
int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth);
int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight);
opts.inSampleSize = 1;
if (widthRatio > 1 || widthRatio > 1) {
if (widthRatio > heightRatio) {
opts.inSampleSize = widthRatio;
} else {
opts.inSampleSize = heightRatio;
}
}
// 设置好缩放比例后,加载图片进内容;
opts.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(pathName, opts);
return bitmap;
}

//保存压缩后的图片
private void saveFile(Bitmap bitmap, String filePath2) throws IOException {
// TODO Auto-generated method stub
File testFile = new File(filePath2);
if (testFile.exists()) {
testFile.delete();
}

File myCaptureFile = new File(filePath2);
System.out.println("------filePath2==" + filePath2);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(myCaptureFile));
// 100表示不进行压缩,70表示压缩率为30%
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, bos);
bos.flush();
bos.close();
}

//打开相机
private void startCamera(int requestCode, Uri photoUri) {
// TODO Auto-generated method stub
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,photoUri);
startActivityForResult(intent, requestCode);
}

/**
* 图片保存路径  这里是在SD卡目录下创建了MyPhoto文件夹
* @param fileName
* @return
*/
private Uri patrUri(String fileName) {  //指定了图片的名字,可以使用时间来命名
// TODO Auto-generated method stub
String strPhotoName = fileName+".jpg";
String savePath = Environment.getExternalStorageDirectory().getPath()
+ "/MyPhoto/";
File dir = new File(savePath);
if (!dir.exists()) {
dir.mkdirs();
}
filePath = savePath + strPhotoName;
return Uri.fromFile(new File(dir, strPhotoName));
}
}


页面布局很简单,就两个Button跟一个ImageView,这里就不贴代码了。

效果图片:



SD卡中的图片:



可以看到,file2.jpg是压缩过的,file1.jpg是原图,因为是模拟器,效果不太明显,在真机上压缩后的图片在100K之内。

要调用相机和读写SD卡,最后不要忘了加权限。

代码下载

因为工作的原因,这里使用的是Myeclipse不过Eclipse也可以用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  压缩 图片 android