前言
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