android 拍照以及压缩处理

启动拍照

如果只是拍照,调起 android 自身的拍照界面就行,两行代码。

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, TAKE_PIC_CODE);

拍完照之后的回调会在 onActivityResult 方法中。但是如果要指定拍照后照片的存储,可附加上如下代码

intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);

指定了照片的存储是位置在 uri。通过源码可以知道,要是我们指定了照片文件,那么在拍照回调里 intent 就不再返回照片数据了,而是帮我们写在了指定的路径下面了。所以我们只好记住路径,拍照成功回调的时候,自己再去取一下文件。网上查到的资料是这样解释源码的

if (mSaveUri != null) {
    OutputStream outputStream = null;
    try {
      //这里就是将拍好的照片写到了我们指定的路径下面,返回的时候就没有再把图片数据返回了
        outputStream = mContentResolver.openOutputStream(mSaveUri);
        outputStream.write(data);
        outputStream.close();
        setResult(RESULT_OK);
        finish();
    } catch (IOException ex) {
      // ignore exception
    } finally {
      Util.closeSilently(outputStream);
    }
} else {
  Bitmap bitmap = createCaptureBitmap(data);
  setResult(RESULT_OK,new Intent("inline-data").putExtra("data", bitmap));
  finish();
}

照片旋转

图片旋转是根据图片信息中的角度信息得出来是否要进行旋转吧,这里还没太深入探究,如果要进行旋转处理可以进行如下操作:

ExifInterface inface = null;
inface = new ExifInterface(path);//path 是图片文件的存储路径
int rotation = inface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);//这里就是读取照片中的信息,第一个入参说明了要读取的数据是水平方向角度吧,第二个入参不是很清楚,我看网上这么用,这里还可以填别的值,比如 ORIENTATION_NORMAL 得到的值好像没什么区别,具体不清楚。
int degree = 0;
//这里就是根据读取出来的水平方向角来赋值我们想要调整的角度,这里没有 360,因为 360 就是 0 嘛也就没有了。
switch(ratation){
    case ExifInterface.ORIENTATION_ROTATE_90:
      degree = 90;
      break;
    case ExifInterface.ORIENTATION_ROTATE_180:
      degree = 180;
      break;
    case ExifInterface.ORIENTATION_ROTATE_270:
      degree = 270;
      break;
}
Matrix matrix = new Matrix();
matrix.setRotate(degree);
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeigth(), matrix, true);//这里就是对图片 bitmap 通过矩阵进行了角度旋转,得到的 result 就是旋转后的图片了

图片压缩

图片的压缩可以有两种方式,一种是解码时,通过一些解码参数在解码的时候就将图片进行了压缩或者其他处理;另外一种是通过 bitmap 自身的 compress 方法进行 quality 的压缩。那么通过解码方式的压缩处理如下:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//这个属性标识了解码时是否只是解码文件尺寸而不载入内存
options.inPreferredConfig = Bitmap.Config.RGB_565;//这个属性标识了解码使用的色值,默认是 ARGB_8888,这个属性保留了 alpha 值,且每个占位 8 位,所以一个像素要 4 个字节的空间。如果是 RGB_565,去掉了 alpha 透明值,总共需要 2 个字节就可以了,还原度上看去和默认差别不大,所以如果对透明度没要求的可以用 RGB_888,其他属性就暂不讨论。
options.inSampleSize = sample;//这个属性就是修改尺寸的,压缩的关键。通常我们会指定一个压缩尺寸,比如 512 * 512,那么原图和要求的尺寸就会有一个比例,sample 值就是这个压缩比例。如果 sample < 1,压缩比例就默认为 1,如果 sample 是个奇数,那么压缩比例会是小于 sample 的最大的偶数,因为 inSampleSize 的值是以 2 倍数出现的。
options.inJustDecodeBounds = false;//之前设置会 true 的解码是为了先获取原图尺寸来计算压缩比例,等到真正解码时,要还原为 false,这样才能将图片载入内存
Bitmap bitmap = BitmapFactory.decodeFile(path, options);//path 就是文件来自哪里的路径。

通过 compress 方法压缩的处理如下:

BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
//首先先解码图片文件,这里 options 的属性都是默认的
ByteArrayOutputStream outStream = new ByteArrayOutputStream();//准备用来存放压缩图片的位数组
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outStream);//这里就是压缩关键,第一个入参是选择以哪种图片格式进行压缩,jpeg 是不带透明度的,所以如果以 jpeg 格式进行压缩,那 options.inPreferredConfig 就可以设置为 RGB_565,如果是 png,那质量不会损失,第二个入参是无效的。第二个入参就是质量数 0~100 之间,值越大质量越好。
ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
Bitmap result = BitmapFactory.decodeStream(inStream, null, null);//解码数据流的方式,将图片解码

两种方法比较来看,压缩比较显著的还是通过压缩尺寸方式,因为这是最直接的改变了图片的宽高,也就改变了像素点的个数,自然就小了。质量压缩的压缩效果没有压缩尺寸的方式来的好,具体是压缩什么不太清楚,但质量一但调到比较小的时候,失真就比较严重了,色彩偏差会很明显。所以既然这样,我们在保证质量压缩不失真的条件下,尽可能的压缩尺寸,同时考虑一下每个像素采用的色值,图片输出格式,这样基本可以保证压缩效果。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容