圖像縮放
一、圖像縮放的方式在c和java中我都講過、現在講一下在android中如何利用api方便快速的縮放圖片。主要有一下集中方式:
(1)、加載圖片到內存,利用matrix設置縮放、傾斜、旋轉屬性來創建圖片。

public Bitmap SmallImage(Bitmap bitmap,int newHeight , int newWidth){ int h = bitmap.getHeight(); int w = bitmap.getWidth(); float heightScale = ((float) newHeight) / h;// 計算縮放因子 float widthScale = ((float) newWidth) / w; Matrix matrix = new Matrix(); matrix.postScale(widthScale,heightScale); // 設置圖片的旋轉角度 // // matrix.postRotate(-30); // // 設置圖片的傾斜 // // matrix.postSkew(0.1f, 0.1f); Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true); return newBitmap; }
這種方法可以任意改變圖像的大小,但是會加載原圖片資源到內存中,通過matrix的屬性對圖像像素矩陣做了相應的變化后創建圖片,一般在需要對圖像進行其他的處理如傾斜、旋轉等操作時用到,時間復雜度和內存消耗都比較大。
(2)不加載圖像到內存直接獲取圖像的寬高對圖像進行壓縮。且只能用來縮小,不能放大。
當options.inJustDecodeBounds=true時,不加載圖片到內存里,但加載了圖片的信息。
當options.inJustDecodeBounds=false時,就會加載圖片到內存,且若又option作為參數,則按照參數的縮放要求生成新的圖片。
但是值得注意的是平時我們加載的不是位圖,如jpg、png等。它們都是經過壓縮的圖,當它們加載成位圖的時候就會明顯比它們是jpg的時候大,即得到的寬高都會比原來的大很多。

public Bitmap SmallImage2(int newHeight , int newWidth) { BitmapFactory.Options options=new BitmapFactory.Options(); options.inJustDecodeBounds=true;//(設為true 圖片不加入內存效率高) BitmapFactory.decodeResource(getResources(),R.drawable.zyh , options); // BitmapFactory.decodeFile(imagePath, options); int outWidth = options.outWidth; int outHeight = options.outHeight; System.out.println("jpg圖"+outHeight+","+outWidth); //經實驗證明,縮小的倍數只能是整數倍。 options.inSampleSize=(outHeight/newHeight+outWidth/newWidth)/2; options.inJustDecodeBounds=false; Bitmap newBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.zyh , options); Bitmap newBitmap2 = BitmapFactory.decodeResource(getResources(),R.drawable.zyh); System.out.println("目標位圖:"+newBitmap.getHeight()+","+newBitmap.getWidth()); System.out.println("原圖位圖:::"+newBitmap2.getHeight()+","+newBitmap2.getWidth()); return newBitmap; }
打印的結果:
jpg圖:900,1440
目標位圖:591,945
原圖位圖:::2363,3780
我調用該函數的語句為:Bitmap bitmap = SmallImage2(200,320); 從結果來看我們最后生成的高、寬為:591、945,而我們要求生成的圖為200、320相差太大了。
原因:用decode從資源drawable中加載圖像時候,會根據不同的文件夾加載不同分辨率圖像,會自動對圖像進行縮放。
這種方式效率很高,但是不能整數倍縮小。
(3)android 2.2新加的一個工具類:ThumbnailUtils。
public static Bitmap extractThumbnail(Bitmap source, int width, int height, int options)
第一個是源圖像,第二、三個是縮放后輸出圖像的寬高,第四個參數是縮放方式,當然我們可以調用下面函數來實現縮放:
public static Bitmap extractThumbnail(Bitmap source, int width, int height)
其實這個函數調用的也是上面一個函數,只是第四個參數的縮放方式采取的默認值:OPTIONS_NONE。
網上一些文章說是對前面2種方法的加工,其實在你傳入圖片的時候就已經加載圖片到內存了應該沒有第二種方式什么事,看源碼發現是對第一種方式的封裝,並且源圖片使用完了后調用source.recycle()釋放源圖像的內存,效率應該是介於第一種與第二種高。
但是采用下面的代碼測試,我發現采用采用第一種和第三種方式放大圖片時,當多次(2-3)點擊click按鈕時采用第1種方式沒事,采用第三者方式反而outofmemory內存溢出了,若有大神知道麻煩告知一下,小弟謝過:

public class MainActivity extends AppCompatActivity { ImageView imageView; Bitmap bt; String imagePath = "data/data/com.example.lammy.imagetest/files/xr.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ImageView) findViewById(R.id.image); } //從圖庫中獲取 public void click(View view) { bt = BitmapFactory.decodeResource(getResources() , R.drawable.xr); Bitmap bitmap = SmallImage(bt,7500,4000); // Bitmap bitmap = SmallImage2(200,320); // Bitmap bitmap = SmallImage3(bt,7500,4000); imageView.setImageBitmap(bitmap); } //圖縮小 public Bitmap SmallImage(Bitmap bitmap,int newHeight , int newWidth){ int h = bitmap.getHeight(); int w = bitmap.getWidth(); float heightScale = ((float) newHeight) / h;// 計算縮放因子 float widthScale = ((float) newWidth) / w; Matrix matrix = new Matrix(); matrix.postScale(widthScale,heightScale); // 設置圖片的旋轉角度 // // matrix.postRotate(-30); // // 設置圖片的傾斜 // // matrix.postSkew(0.1f, 0.1f); Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true); System.out.println("目標位圖:"+newBitmap.getHeight()+","+newBitmap.getWidth()); return newBitmap; } public Bitmap SmallImage2(int newHeight , int newWidth) { BitmapFactory.Options options=new BitmapFactory.Options(); options.inJustDecodeBounds=true;//(設為true 圖片不加入內存效率高) BitmapFactory.decodeResource(getResources(),R.drawable.zyh , options); // BitmapFactory.decodeFile(imagePath, options); int outWidth = options.outWidth; int outHeight = options.outHeight; System.out.println("jpg圖"+outHeight+","+outWidth); //經實驗證明,縮小的倍數只能是整數倍。 options.inSampleSize=(outHeight/newHeight+outWidth/newWidth)/2; options.inJustDecodeBounds=false; Bitmap newBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.zyh , options); Bitmap newBitmap2 = BitmapFactory.decodeResource(getResources(),R.drawable.zyh); System.out.println("目標位圖:"+newBitmap.getHeight()+","+newBitmap.getWidth()); System.out.println("原圖位圖:::"+newBitmap2.getHeight()+","+newBitmap2.getWidth()); return newBitmap; } public Bitmap SmallImage3(Bitmap bitmapt ,int newHeight , int newWidth) { Bitmap newBitmap = ThumbnailUtils.extractThumbnail(bitmapt,newWidth,newHeight); System.out.println("目標位圖:"+newBitmap.getHeight()+","+newBitmap.getWidth()); return newBitmap; } }
圖像旋轉
一、用matrixde 的方式進行,最后一個參數filter是否保持原來圖像的比例,通常matrix中包含縮放的時候用true,若只是平移、旋轉則可不需要用到(即為false)。為false的時候效率要比為true的時候高很多,這里得注意取舍。
createBitmap(Bitmap source, int x, int y, int width, int height,
Matrix m, boolean filter)
* * @param origin 原圖 * @param angle 旋轉角度,可正可負 * @return 旋轉后的圖片 */ public static Bitmap rotateBitmap(Bitmap origin, float angle) { if (origin == null) { return null; } Matrix matrix = new Matrix(); matrix.setRotate(angle); Bitmap newBM = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false); if (newBM.equals(origin)) { return newBM; } return newBM; }