Android开发 Bitmap图像处理详解 前言 将Res位图资源转成Bitmap 将指定文件转成Bitmap 将Drawable矢量图资源转成Bitmap 将Uri转成Bitmap 将Bitmap输出成文件 镜像垂直翻转 镜像水平翻转 旋转图片 压缩图片质量,降低图片存储大小 压缩图片尺寸 获取图片的角度属性与将图片角度属性设置回去
Bitmap开发涉及到方方面面,比如裁剪图片,压缩图片,镜像图片,旋转图片,各种转存图片等等,是必需掌握Android开发技巧,Android开发提供了2个类来实现这些需求,Bitmap类与BitmapFactory类。此博客会持续更新各种实际需求。
将Res位图资源转成Bitmap
请注意,使用这个方法会出现Bitmap为null的问题。这个问题可能是因为资源id异常引起的。特别是你使用了分module形式构建的app
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
将指定文件转成Bitmap
Bitmap bitmap = BitmapFactory.decodeFile(getContext().getExternalCacheDir() + File.separator + "demo1.png");
将Drawable矢量图资源转成Bitmap
public static Bitmap getBitmapFromDrawable(Context context, @DrawableRes int drawableId) { Drawable drawable = ContextCompat.getDrawable(context, drawableId); if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } else if (drawable instanceof VectorDrawable || drawable instanceof VectorDrawableCompat) { Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } else { throw new IllegalArgumentException("unsupported drawable type"); } }
将Uri转成Bitmap
@Override public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); //相册选择图片 if (requestCode == GALLERY_RESULT_CODE && resultCode == RESULT_OK) { final Uri uri = data.getData(); try (InputStream inputStream = getActivity().getApplicationContext().getContentResolver().openInputStream(uri)) { Bitmap bitmap = BitmapFactory.decodeStream(inputStream);//得到bitmap } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return; } }
将Bitmap输出成文件
Bitmap bitmap = BitmapFactory.decodeFile(getContext().getExternalCacheDir() + File.separator + "demo1.png"); File file = new File(getContext().getExternalCacheDir(), "demo.jpg"); try (FileOutputStream fileOutputStream = new FileOutputStream(file)) { //参数1:输出的图片格式 参数2:输出图片的压缩质量(范围值为0-100) 参数3:输出流 bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileOutputStream); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
镜像垂直翻转
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); Matrix matrix = new Matrix(); matrix.postScale(1, -1); //镜像垂直翻转 Bitmap changBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
镜像水平翻转
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); Matrix matrix = new Matrix(); matrix.postScale(-1, 1); //镜像水平翻转 Bitmap changBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); mBinding.weatherIcon.setImageBitmap(changBitmap);
旋转图片
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); Matrix matrix = new Matrix(); matrix.postRotate(-90); //旋转-90度 Bitmap changBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); mBinding.weatherIcon.setImageBitmap(changBitmap);
压缩图片质量,降低图片存储大小
原理其实很简单就是利用compress方法,一点一点的降低图片质量,最后压缩到需要的目标存储大小
/** * 压缩图片 * @param bitmap bitmap图片 压缩 * @param targetKB 目标压缩大小 * @return */ private Bitmap compressImage(Bitmap bitmap, int targetKB){ Bitmap outBitmap = null; ByteArrayInputStream bais = null; ByteArrayOutputStream baos = null; try { baos = new ByteArrayOutputStream(); int quality = 80; bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos); while ((baos.toByteArray().length/1024) > targetKB){ quality = quality-10; baos.reset(); bitmap.compress(Bitmap.CompressFormat.JPEG,quality,baos); } bais = new ByteArrayInputStream(baos.toByteArray()); outBitmap = BitmapFactory.decodeStream(bais); bais.close(); baos.close(); } catch (Exception e) { e.printStackTrace(); onError(e); } finally { try { bais.close(); baos.close(); } catch (IOException e) { e.printStackTrace(); } } return outBitmap; }
压缩图片尺寸
原理是利用BitmapFactory.decodeStream方法,传入options,以降幂的方式等比例的压缩到目标尺寸,关键是options.inSampleSize = be;这个属性的配置
/** * 尺寸压缩 * @param bitmap */ private Bitmap sizeCompres(Bitmap bitmap,float targetWidth,float targetHeight){ Bitmap handleBitmap = null; try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bitmap.compress(Bitmap.CompressFormat.JPEG,100,baos); // 判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出 if (baos.toByteArray().length / 1024 > 1024) { baos.reset();// 重置baos即清空baos bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);// 这里压缩50%,把压缩后的数据存放到baos中 } ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(bais,null,options); options.inJustDecodeBounds = false; int imageWidth = options.outWidth; int imageHeight = options.outHeight; int be = 1; if (imageWidth>imageHeight && imageWidth>targetWidth){ be = Math.round(imageWidth/targetWidth); }else if (imageHeight>imageWidth && imageHeight>targetHeight){ be = Math.round(imageHeight/targetHeight); } if (be <= 1){ be =1;//如果小于1等于1就不需要压缩直接返回 } options.inSampleSize = be; bais = new ByteArrayInputStream(baos.toByteArray());//bais运行到这里可能已经清空了,所以需要再次添加 handleBitmap = BitmapFactory.decodeStream(bais,null,options); bais.close(); baos.close(); } catch (Exception e) { e.printStackTrace(); } return handleBitmap; }
获取图片的角度属性与将图片角度属性设置回去
获取图片的角度属性很重要,这里说明下,因为我们在压缩或者读取图片成Bitmap后在保存到文件里会丢失图片的角度,这样下次在查看这张图片的时候极有可能是倒的图片
try { ExifInterface exifInterface = new ExifInterface(inpPath);//获取图片角度 mDegrees = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1); int angle = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1); switch (angle){ case ExifInterface.ORIENTATION_ROTATE_270: mDegrees = 270; break; case ExifInterface.ORIENTATION_ROTATE_180: mDegrees = 180; break; case ExifInterface.ORIENTATION_ROTATE_90: mDegrees = 90; break; default: mDegrees = 0; break; } } catch (IOException e) { e.printStackTrace(); }
将图片角度设置回去
Matrix matrix = new Matrix(); matrix.setRotate(mDegrees, bitmap.getWidth(), bitmap.getHeight()); Bitmap finishBitmap = Bitmap.createBitmap(finishBitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix,true);
End