計算機表示圖形的幾種方法。
阿新 • • 發佈:2019-01-06
案例載入一張大圖
在android中當載入的圖片過大(解析度高)時導致圖片無法正常檢視甚至會報oom異常,所以當載入一張大圖時需要設定其縮放的比例係數
package com.example.loadBigImage; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapFactory.Options; import android.graphics.Point; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.ImageView; public class MainActivity extends Activity { private ImageView iv; private int height; private int width; @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //用來顯示小狗的照片 iv = (ImageView) findViewById(R.id.iv); //【1】獲取手機的解析度 windowmanager smsManager telephoneManager WindowManager wm= (WindowManager) getSystemService(WINDOW_SERVICE); height = wm.getDefaultDisplay().getHeight(); width = wm.getDefaultDisplay().getWidth(); System.out.println("width:"+width+"-----height:"+height); // Point point=new Point(); // wm.getDefaultDisplay().getSize(point); // int width=point.x; // int height=point.y; // System.out.println("width:"+width+"-----height:"+height); } //載入一張大圖片 public void click(View v){ //建立一個位圖工廠的配置引數 BitmapFactory.Options options=new Options(); //解碼器不去真正地解析點陣圖 只獲取圖片的寬和高資訊 options.inJustDecodeBounds=true; //載入圖片內容 申請記憶體超過16M(取決於裝置dvm分配的記憶體大小,無法改變)會報記憶體溢位錯誤 oom out of memory BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg",options); //【2】獲取圖片的寬和高資訊 int imgwidth=options.outWidth; int imgheight=options.outHeight; //【3】計算縮放比 int scale=1; int scaleX=imgwidth/width; int scaleY=imgheight/height; if(scaleX>=scaleY&&scaleX>scale){ scale=scaleX; }else if(scaleY>=scaleX&&scaleY>scale){ scale=scaleY; } System.out.println("縮放比:"+scale); //[4]按照縮放比進行顯示 設定縮放參數 options.inSampleSize=scale;//理解為原圖的取樣比,按照這個標準對原圖取樣將減少記憶體使用。 //[5]按照縮放比 進行解析點陣圖 options.inJustDecodeBounds=false; Bitmap bitmap=BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg",options); //[6]把bitmap顯示到iv上 iv.setImageBitmap(bitmap); } }
1掌握WindowManager的使用
2瞭解BitmapFactory的使用
3理解縮放比例係數
建立一個原圖的副本
比如我們在美圖秀秀中對一張圖片進行操作後,儲存時提醒你儲存為副本或是覆蓋原圖,此時就應用到了建立原圖副本進行操作的邏輯。
package com.example.copybitmap; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.ImageView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //顯示原圖 ImageView iv_src=(ImageView) findViewById(R.id.iv_src); //顯示副本 ImageView iv_copy=(ImageView) findViewById(R.id.iv_copy); //[1]先把dog.png圖片轉換成bitmap 顯示到iv_src上 getResource() 獲取當前工程中的資源 Bitmap srcBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.dog); //[1.1]操作圖片 //srcBitmap.setPixel(50, 50, Color.RED);//修改哪一點座標的顏色 //TODO iv_src.setImageBitmap(srcBitmap); //[2]建立原圖的副本 //[2.1]建立一個模板 相當於建立了一個和原圖一樣的空白的白紙 Bitmap copybitmap=Bitmap.createBitmap(srcBitmap.getWidth(),srcBitmap.getHeight(),srcBitmap.getConfig()); //[2.2]想作畫需要一個畫筆 Paint paint=new Paint(); //[2.3]建立一個畫布 把白紙鋪到畫布上 Canvas canvas=new Canvas(copybitmap); //[2.4]開始作畫 canvas.drawBitmap(srcBitmap, new Matrix(), paint); //[2.5]操作畫出來的小狗照片 for (int i = 0; i < 20; i++) { copybitmap.setPixel(100+i, 50, Color.RED); } //[3]把copybitmap顯示到iv_copy上 iv_copy.setImageBitmap(copybitmap); } }
圖片處理常用api
旋轉,縮放,平移,鏡面,倒影等。
//[2]建立原圖的副本 //[2.1]建立一個模板 相當於建立了一個和原圖一樣的空白的白紙 Bitmap copybitmap=Bitmap.createBitmap(srcBitmap.getWidth(),srcBitmap.getHeight(),srcBitmap.getConfig()); //[2.2]想作畫需要一個畫筆 Paint paint=new Paint(); //[2.3]建立一個畫布 把白紙鋪到畫布上 Canvas canvas=new Canvas(copybitmap); //[2.4]開始作畫 Matrix matrix=new Matrix(); //[2.5]對圖片進行旋轉 設定旋轉角度 以及旋轉中心 //matrix.setRotate(20, srcBitmap.getWidth()/2, srcBitmap.getHeight()/2); //[2.6]對圖片進行縮放 // matrix.setScale(0.5f, 0.5f); //[2.7]對圖片進行平移 //matrix.setTranslate(30f, 0); //[2.8]鏡面效果 兩個方法一起用 //matrix.setScale(-1.0f, 1); //post是在上一次修改基礎上再次進行修改 set每次操作都是最新的 會覆蓋上次的操作 //matrix.postTranslate(srcBitmap.getWidth(), 0);//翻轉後再移動回原位置 //[2.9]倒影效果 matrix.setScale(1, -1); //post是在上一次修改基礎上再次進行修改 set每次操作都是最新的 會覆蓋上次的操作 matrix.postTranslate(0, srcBitmap.getHeight()); canvas.drawBitmap(srcBitmap,matrix, paint); //[3]把copybitmap顯示到iv_copy上 iv_copy.setImageBitmap(copybitmap);
鏡面效果示意圖
畫畫板小應用(畫圖並將圖片儲存到sd卡)
public class MainActivity extends Activity {
private Canvas canvas;
private ImageView iv;
private Bitmap srcBitmap;
private Paint paint;
private Bitmap copyBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//用來顯示我們畫的內容
iv = (ImageView) findViewById(R.id.iv);
srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
//[2]獲取原圖的副本 相當於是一張空白的白紙
copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//建立一個畫筆
paint = new Paint();
canvas = new Canvas(copyBitmap);
//開始作畫
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
// canvas.drawLine(20, 30, 100, 100, paint);
iv.setImageBitmap(copyBitmap);
//[3]給iv設定一個觸控事件
iv.setOnTouchListener(new OnTouchListener() {
private int startX;
private int startY;
@Override
public boolean onTouch(View v, MotionEvent event) {
int action=event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN://按下
//獲取開始劃線的位置
System.out.println("觸控view");
startX = (int) event.getX();
startY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE://移動
//獲取結束位置
int stopX=(int) event.getX();
int stopY=(int) event.getY();
//不停地劃線
canvas.drawLine(startX, startY, stopX, stopY, paint);
//再次顯示在iv上
iv.setImageBitmap(copyBitmap);
//更新一下開始座標和結束座標
startX=stopX;
startY=stopY;
break;
case MotionEvent.ACTION_UP://擡起
break;
}
//True if the listener has consumed the event, false otherwise.
return true;//true 監聽器處理完當前事件了 可以進行之後的監聽
}
});
}
//點選按鈕改變畫筆的顏色
public void click1(View v){
paint.setColor(Color.RED);
}
//加粗
public void click2(View v){
paint.setStrokeWidth(5);
}
//儲存
public void click3(View v){
/**
* format 儲存圖片的格式
* quality 質量
* SystemClock.uptimeMillis() 當前手機的開機時間
*/
try {
//儲存到sdcard 需要開啟sdcard許可權
File file=new File(Environment.getExternalStorageDirectory().getPath(),SystemClock.uptimeMillis()+".png");
FileOutputStream fos=new FileOutputStream(file);
copyBitmap.compress(CompressFormat.PNG, 100, fos);
//傳送一條廣播 欺騙系統圖庫的應用
Intent intent=new Intent();
//設定action
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));
//傳送一條廣播
sendBroadcast(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
}
撕衣服小案例
原理:兩張圖片疊放再一起,觸控上面那張穿衣服圖片的地方變透明,下方沒穿衣服的圖片就顯示出來。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//用來顯示操作後的圖片
final ImageView iv=(ImageView) findViewById(R.id.iv);
//[1]獲取要操作的圖片 原圖 穿衣服的
Bitmap srcBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.m2);
//[2]建立一個副本 相當於一個和原圖大小一樣的白紙
final Bitmap alterBitmap=Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//建立畫筆
Paint paint=new Paint();
//建立畫筆 對alterBitmap進行作畫操作 把白紙鋪到畫布上
Canvas canvas=new Canvas(alterBitmap);
//開始作畫 按照srcBitmap作為模板作畫
canvas.drawBitmap(srcBitmap, new Matrix(), paint);
iv.setImageBitmap(alterBitmap);
//[3]給iv設定一個觸控事件
iv.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
//具體判斷一下觸控事件
switch(event.getAction()){
case MotionEvent.ACTION_MOVE: //移動事件
for (int i = -5; i <5; i++) {//移動一次,通過迴圈往外擴五個畫素,依次使其變透明。
for (int j =-5; j < 5; j++) {
if(Math.sqrt(i*i+j*j)<5){//撕一個圓
//所到之處變透明
try {
alterBitmap.setPixel((int)event.getX()+i,(int)event.getY()+j, Color.TRANSPARENT);
} catch (Exception e) {
}
}
}
}
//更新一下iv
iv.setImageBitmap(alterBitmap);
break;
}
return true;
}
});
}
}