android 拍照并保存带有时间的图片到本地

ps:我觉得这个还是写在前面比较好。

做这个功能遇到了一个问题就是拍照后通过uri获得bitmap保存到本地特别大,压缩到50%都有10mb左右,而相机拍摄后保存到sd的照片才两三兆左右,所以就对图片进行了采样处理,宽高为800*1200,这样保存到sd的图片只有300kb~500kb,而且清晰度还可以,保存速度也比之前不处理的快很多。


最近做了一个拍照然后给照片添加时间并保存到本地的功能。一共分三步。

一、拍照

首先添加权限

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
然后,记得添加权限申请,这里没写。

Intent intent = new Intent((MediaStore.ACTION_IMAGE_CAPTURE));
File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis() + ".jpg");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    photoUri = FileProvider.getUriForFile(activity, FP_AUTHORITIES, file);
    //第二种方式,无需其他操作
    ContentValues contentValues = new ContentValues(1);
    contentValues.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
    photoUri = activity.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
} else {
    photoUri = Uri.fromFile(file);
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
if(fragment == null)
    activity.startActivityForResult(intent, CODE_PHOTO);
else
    fragment.startActivityForResult(intent,CODE_PHOTO);
其中getUriForFile()方法的第二个参数是在清单文件中添加的provider的authorities属性值

    provider配置

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="(这里随便写)"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
provider>

    file_paths添加:

    android 拍照并保存带有时间的图片到本地_第1张图片

    这样拍照功能就写完了,拍照完成后photoUri中就会有图片的路径等信息。

二、添加时间

添加时间需要拿到bitmap对象,但是刚拍完照的照片直接拿到内存会特别大,避免内存溢出,先对图片做下采样处理,降低像素。

//采样
public static Bitmap getResizeBitmap(Uri uri, int destHeight, int destWidth)
{
    if(uri == null)
        return null;
    //第一次采样
    BitmapFactory.Options options = new BitmapFactory.Options();
    //该属性设置为true只会加载图片的边框进来,并不会加载图片具体的像素点
    options.inJustDecodeBounds = true;
    //第一次加载图片,这时只会加载图片的边框进来,并不会加载图片中的像素点
    BitmapFactory.decodeFile(uri.getPath(), options);
    //获得原图的宽和高
    int outWidth = options.outWidth;
    int outHeight = options.outHeight;
    //定义缩放比例
    int sampleSize = 1;
    while (outHeight / sampleSize > destHeight || outWidth / sampleSize > destWidth) {
        //如果宽高的任意一方的缩放比例没有达到要求,都继续增大缩放比例
        //sampleSize应该为2的n次幂,如果给sampleSize设置的数字不是2的n次幂,那么系统会就近取值
        sampleSize *= 2;
    }
    /********************************************************************************************/
    //至此,第一次采样已经结束,我们已经成功的计算出了sampleSize的大小
    /********************************************************************************************/
    //二次采样开始
    //二次采样时我需要将图片加载出来显示,不能只加载图片的框架,因此inJustDecodeBounds属性要设置为false
    options.inJustDecodeBounds = false;
    //设置缩放比例
    options.inSampleSize = sampleSize;
    options.inPreferredConfig = Config.RGB_565;
    //加载图片并返回
    return BitmapFactory.decodeFile(uri.getPath(), options);
}
然后给bitmap添加白色文字
//在bitmap右下角添加字体,默认白色
public static Bitmap getBitmapWithText(Bitmap bitmap, String text)
{
    if(bitmap == null)
        return bitmap;
    int w = bitmap.getWidth();
    int h = bitmap.getHeight();
    Bitmap newBitmap = Bitmap.createBitmap(w, h, Config.RGB_565);
    Canvas mCanvas = new Canvas(newBitmap);
    // 往位图中开始画入src原始图片
    mCanvas.drawBitmap(bitmap, 0, 0, null);
    //添加文字
    TextPaint tp = new TextPaint();
    tp.setTypeface(Typeface.DEFAULT);
    tp.setAntiAlias(true);
    tp.setColor(Color.WHITE);
    int textSize = h/10 > w/15 ? w/15 : h/10;
    tp.setTextSize(textSize);
    float textWidth = tp.measureText(text);
    mCanvas.drawText(text, w-textWidth-textSize, h-(textSize/2), tp);
    mCanvas.save(Canvas.ALL_SAVE_FLAG);
    mCanvas.restore();

    return newBitmap;
}
三、保存bitmap到sd卡
public static boolean saveBitmapToSD(Bitmap bitmap, String path)
{
    boolean flag = false;
    if(bitmap == null || path == null || path.length() == 0)
        return flag;
    File file = new File(path);
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.PNG,100,fos);
        fos.flush();
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        if(fos != null)
        {
            flag = true;
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return flag;
}
因为保存图片到sd卡可能会造成卡顿,而且项目后面用到的图片需要是处理完成的,所以这里我就用了asynctask来处理了一下。
class SaveImageAsyncTask extends AsyncTask
{

    private Bitmap bitmap;
    private String path;
    public SaveImageAsyncTask(Bitmap bitmap, String path) {
        this.bitmap = bitmap;
        this.path = path;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        showSaveImageDialog();
    }

    @Override
    protected Boolean doInBackground(Void... voids) {

        return ImageFactory.saveBitmapToSD(bitmap,path);
    }

    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        bitmap = null;
        hideSaveImageDialog();
        onEditImageOver();
    }
}
其中的dialog自己随便写就好了。


你可能感兴趣的:(android 拍照并保存带有时间的图片到本地)