一、加載圖檔到記憶體
ImageView iv = (ImageView) findViewById(R.id.iv);
//iv ---- jpg---bitmapfactory---bitmap
//建立位圖圖像
//顯示大圖的時候抛出來了記憶體溢出的異常,看起來圖檔也不大,為什麼會抛出異常呢?
//> 原因是Android系統計算位圖的時候,使用32位去表示 argb 8 + 8 + 8 + 8 =32 4個位元組的大小
Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/big.jpg");
//顯示位圖圖像
iv.setImageBitmap(bitmap);
二、加載大記憶體圖檔到記憶體
ImageView iv = (ImageView) findViewById(R.id.iv);
//iv ---- jpg---bitmapfactory---bitmap
//建立位圖圖像
//顯示大圖的時候抛出來了記憶體溢出的異常,看起來圖檔也不大,為什麼會抛出異常呢?
//> 原因是Android系統計算位圖的時候,使用32位去表示 argb 8 + 8 + 8 + 8 =32 4個位元組的大小
//定義一個解析圖檔的選項對象
Options opts = new Options();
//設定圖檔的采樣率,寬度是原來的1/4像素個數 ,高度也是原來的1/4像素個數 ,那麼解析的到的圖檔将是原圖的1/16
/*
* 一般這個采樣率都不會直接編寫,而是取目前圖檔的分辨率和 螢幕的分辨率的寬高比例
*/
//1.得到螢幕的分辨率
//得到系統的視窗服務
WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
//得到目前顯示相關的對象
Display display = manager.getDefaultDisplay();
int height = display.getHeight();
int width = display.getWidth();
System.out.println("螢幕的分辨率是:"+width+"---height="+height);
//2.得到圖檔的分辨率
String imgWidth = null;
try {
//擷取到檔案裡面儲存的頭額外資訊
ExifInterface exif = new ExifInterface("/mnt/sdcard/big.jpg");
String imgHeight = exif.getAttribute(ExifInterface.TAG_IMAGE_LENGTH) ; //擷取到圖檔的高度
imgWidth = exif.getAttribute(ExifInterface.TAG_IMAGE_WIDTH) ; //擷取到圖檔的寬度
System.out.println("圖檔的分辨率是:"+imgWidth+"-----height="+imgHeight);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int w = Integer.parseInt(imgWidth) / width ;
// imghe
//一般是去寬高比例的中間值,或者取最大的那一個值
opts.inSampleSize = 4 ;
Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/big.jpg" , opts);
//顯示位圖圖像
iv.setImageBitmap(bitmap);
三、位圖的操作方式
3.1 圖像的縮放
public void scale(View v){
//縮放圖檔
//1.顯示原圖
Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/tp1.jpg");
iv_src.setImageBitmap(bitmap);
//2.顯示縮放的圖檔
//要想顯示縮放的圖檔,并不是直接對原圖進行縮放,而是對原圖的一份拷貝進行縮放
//a.建立一份原圖的拷貝 --根據原圖得到一份空白的位圖拷貝
//舉個例子:八駿圖,要做一付赝品, 寬高必須與之一樣,否則人家一眼就看穿了。
Bitmap copyBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
//b.定義出來一個畫闆 、畫架 ,裡面擺放着原來的空白紙張,表名要在這張紙上作畫了
Canvas canvas = new Canvas(copyBitmap);
//c. 建立一個畫筆
Paint paint = new Paint();
//d.建立矩陣 :1:1的比例圖檔
Matrix matrix = new Matrix();
//設定圖像的縮放比率,寬度是原來的20% ,高度是原來的80%
matrix.setScale(2f, 2f);
//e.開始作畫: 參照哪一付圖開始作畫
canvas.drawBitmap(bitmap, matrix, paint);
//如果以上幾個步驟都已經走完了,那麼代表着空白紙張上已經有圖像
iv_target.setImageBitmap(copyBitmap);
}
3.2 圖像的旋轉
public void scale(View v){
//縮放圖檔
//1.顯示原圖
Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/tp1.jpg");
iv_src.setImageBitmap(bitmap);
//2.顯示縮放的圖檔
//要想顯示縮放的圖檔,并不是直接對原圖進行縮放,而是對原圖的一份拷貝進行縮放
//a.建立一份原圖的拷貝 --根據原圖得到一份空白的位圖拷貝
//舉個例子:八駿圖,要做一付赝品, 寬高必須與之一樣,否則人家一眼就看穿了。
Bitmap copyBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
//b.定義出來一個畫闆 、畫架 ,裡面擺放着原來的空白紙張,表名要在這張紙上作畫了
Canvas canvas = new Canvas(copyBitmap);
//c. 建立一個畫筆
Paint paint = new Paint();
//d.建立矩陣 :1:1的比例圖檔
Matrix matrix = new Matrix();
//以圖檔的中心為旋轉點,旋轉90度
matrix.setRotate(90 , copyBitmap.getWidth()/2 ,copyBitmap.getHeight()/2);
//e.開始作畫: 參照哪一付圖開始作畫
canvas.drawBitmap(bitmap, matrix, paint);
//如果以上幾個步驟都已經走完了,那麼代表着空白紙張上已經有圖像
iv_target.setImageBitmap(copyBitmap);
}
3.3 圖像的旋轉
public void scale(View v){
//縮放圖檔
//1.顯示原圖
Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/tp1.jpg");
iv_src.setImageBitmap(bitmap);
//2.顯示縮放的圖檔
//要想顯示縮放的圖檔,并不是直接對原圖進行縮放,而是對原圖的一份拷貝進行縮放
//a.建立一份原圖的拷貝 --根據原圖得到一份空白的位圖拷貝
//舉個例子:八駿圖,要做一付赝品, 寬高必須與之一樣,否則人家一眼就看穿了。
Bitmap copyBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
//b.定義出來一個畫闆 、畫架 ,裡面擺放着原來的空白紙張,表名要在這張紙上作畫了
Canvas canvas = new Canvas(copyBitmap);
//c. 建立一個畫筆
Paint paint = new Paint();
//d.建立矩陣 :1:1的比例圖檔
Matrix matrix = new Matrix();
matrix.setTranslate(50, 50);
//e.開始作畫: 參照哪一付圖開始作畫
canvas.drawBitmap(bitmap, matrix, paint);
//如果以上幾個步驟都已經走完了,那麼代表着空白紙張上已經有圖像
iv_target.setImageBitmap(copyBitmap);
}
3.4 圖檔的左右翻轉
public void scale(View v){
//縮放圖檔
//1.顯示原圖
Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/tp1.jpg");
iv_src.setImageBitmap(bitmap);
//2.顯示縮放的圖檔
//要想顯示縮放的圖檔,并不是直接對原圖進行縮放,而是對原圖的一份拷貝進行縮放
//a.建立一份原圖的拷貝 --根據原圖得到一份空白的位圖拷貝
//舉個例子:八駿圖,要做一付赝品, 寬高必須與之一樣,否則人家一眼就看穿了。
Bitmap copyBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
//b.定義出來一個畫闆 、畫架 ,裡面擺放着原來的空白紙張,表名要在這張紙上作畫了
Canvas canvas = new Canvas(copyBitmap);
//c. 建立一個畫筆
Paint paint = new Paint();
//d.建立矩陣 :1:1的比例圖檔
Matrix matrix = new Matrix();
//把水準的坐标,全部變成負數,縱坐标不許要更改。
matrix.setScale(-1, 1);
// 由于橫坐标都變成了負數,是以圖檔就跑到螢幕的左邊去了,必須移動回來。
//不過,注意:移動的時候,不能使用setXXX這種方式移動。這種setXXX它并不會在原來的圖檔修改基礎上再執行。
matrix.postTranslate(copyBitmap.getWidth(), 0);
//e.開始作畫: 參照哪一付圖開始作畫
canvas.drawBitmap(bitmap, matrix, paint);
//如果以上幾個步驟都已經走完了,那麼代表着空白紙張上已經有圖像
iv_target.setImageBitmap(copyBitmap);
}
3.5 操作圖檔的使用步驟
1. 建立一份原圖的拷貝
//a.建立一份原圖的拷貝 --根據原圖得到一份空白的位圖拷貝
//舉個例子:八駿圖,要做一付赝品, 寬高必須與之一樣,否則人家一眼就看穿了。
Bitmap copyBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
2. 定義畫闆,指定使用的空白紙張
//b.定義出來一個畫闆 、畫架 ,裡面擺放着原來的空白紙張,表名要在這張紙上作畫了
Canvas canvas = new Canvas(copyBitmap);
3. 定義畫筆
//c. 建立一個畫筆
Paint paint = new Paint();
4. 定義矩陣
//d.建立矩陣 :1:1的比例圖檔
Matrix matrix = new Matrix();
//設定圖像的縮放比率,寬度是原來的20% ,高度是原來的80%
matrix.setScale(2f, 2f);
5. 開始作畫
//e.開始作畫: 參照哪一付圖開始作畫
canvas.drawBitmap(bitmap, matrix, paint);
6. 顯示畫好的圖檔
//如果以上幾個步驟都已經走完了,那麼代表着空白紙張上已經有圖像
iv_target.setImageBitmap(copyBitmap);
3.6 圖檔操作的例題:随手塗鴉
/**
* 所謂的随手塗鴉,實際上就是在一個bitmap上作畫,然後把這個畫好的bitmap顯示到iamgeView上,
* 我們并不是直接在imageView上作畫,
*
*/
public class MainActivity extends Activity implements OnClickListener{
Paint paint ;
Bitmap bitmap ;
Canvas canvas ;
ImageView iv ;
float density ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
density = metrics.density;
int dpi = metrics.densityDpi;
System.out.println("density ==="+density +"---dpi="+dpi);
//定義一個畫筆
paint = new Paint();
//預設畫筆就是5的寬度
paint.setStrokeWidth(5);
//建立一個空白的位圖對象 300*300的寬高,并且是32位的位圖圖像
bitmap = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888);
//建立畫闆
canvas = new Canvas(bitmap);
//先畫一遍白色的背景
canvas.drawColor(Color.WHITE);
findViewById(R.id.red).setOnClickListener(this);
findViewById(R.id.green).setOnClickListener(this);
findViewById(R.id.blue).setOnClickListener(this);
findViewById(R.id.yellow).setOnClickListener(this);
findViewById(R.id.purple).setOnClickListener(this);
SeekBar seekBar = (SeekBar) findViewById(R.id.seekBar1);
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
//停止移動
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//得到目前seekbar的進度
int progress = seekBar.getProgress();
paint.setStrokeWidth(progress);
Toast.makeText(MainActivity.this, "目前的畫筆粗細值為:"+progress, 0).show();
}
//開始移動
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
//正在移動
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
}
});
//為了在imageview上作畫,必須對imageView進行觸摸事件監聽
iv = (ImageView) findViewById(R.id.iv);
iv.setOnTouchListener(new OnTouchListener() {
float startX ;
float startY ;
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {//判斷目前的動作,
case MotionEvent.ACTION_DOWN: //按下的動作
System.out.println("donw-----");
//擷取到目前按下的坐标點
startX = event.getX() /*/density*/;
startY = event.getY() /*/density*/;
break;
case MotionEvent.ACTION_MOVE: //移動的動作
float stopX = event.getX()/*/density*/;
float stopY = event.getY()/*/density*/;
//開始作畫,畫線條,把線條畫到bitmap上
canvas.drawLine(startX, startY, stopX, stopY, paint);
//顯示圖檔
iv.setImageBitmap(bitmap);
startX = stopX;
startY = stopY;
System.out.println("move-----");
break;
case MotionEvent.ACTION_UP: //彈起的動作
System.out.println("up-----");
break;
}
//如果傳回true,代表的是這個觸摸事件到此結束,系統不要把這個事件再向下傳遞了,我們要自己處理這個事件
//如果是false:代表的時候事件仍将繼續往下傳遞,下面還有一些監聽器也需要捕捉到這個事件
return true;
}
});
}
@Override
public void onClick(View v) {
String str = "";
switch (v.getId()) {
case R.id.red:
str = "紅色";
paint.setColor(Color.RED);
break;
case R.id.green:
str = "綠色";
paint.setColor(Color.GREEN);
break;
case R.id.blue:
str = "藍色";
paint.setColor(Color.BLUE);
break;
case R.id.yellow:
str = "黃色";
paint.setColor(Color.YELLOW);
break;
case R.id.purple:
str = "紫色";
paint.setColor(0xFFFF00FF);
break;
}
Toast.makeText(this, "目前的畫筆顔色是:"+str, 0).show();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
//如果目前選中的itemid 是r.id.save ,儲存
if (item.getItemId() == R.id.save){
Toast.makeText(this, "儲存圖檔", 0).show();
//儲存bitmap
try {
OutputStream stream = new FileOutputStream("/mnt/sdcard/"+System.currentTimeMillis()+".jpg");
//儲存位圖到指定的路徑底下:
//參數一: 儲存的類型,參數二:儲存的精确品質、參數三:儲存的路徑
bitmap.compress(CompressFormat.JPEG, 100, stream);
Toast.makeText(this, "儲存圖檔成功", 0).show();
//要想讓圖庫顯示畫好的圖檔,可以在此發送一個廣播,欺騙系統,讓它以為現在SD卡被挂載進來了,再一次掃描SD卡
Intent intent = new Intent();
//SD卡被挂載的動作
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
Uri data = Uri.fromFile(Environment.getExternalStorageDirectory());
intent.setData(data);
sendBroadcast(intent);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
四、getX和 getRawX的差別
* getX:目前點選的坐标位置與控件的左邊距離是多少
* getRawX:目前點選的坐标位置與螢幕的左邊距離是多少