一般白色就是0,黑色就是1 單色點陣圖: 24位點陣圖 256色 安卓中預設使用32位的 將一個圖片放在SD卡上,使用BitmapFactory.decodeFile解析得Bitmap設置ImageView顯示 以上的圖片可以正常載入 異常現象 載入 的圖片過大,如2560*1520之類的,載入 時就會
安卓第十五天筆記-圖形圖像一些簡單處理
多媒體編程簡介--圖形的一般處理
1.電腦中圖形計算的大小
一般白色就是0,黑色就是1
單色點陣圖:
8位表示一個位元組,
大小:長*寬/8,表示大小,還有一些文件信息如創建時間,什麼工具創建之類的
24位點陣圖
一個像素表示24位
大小:長*寬*24/8
256色
1個像素可以表示256種顏色 一個位元組它的長度剛好是256 ,那麼一個像素點就是一個位元組
大小:長*寬
安卓中預設使用32位的
- 點陣圖的缺陷
- 放大到一定的比例會出會出現失真與鋸齒形狀
- 占用很大的存儲空間
2.載入一個圖片文件到存中
將一個圖片放在SD卡上,使用BitmapFactory.decodeFile解析得Bitmap設置ImageView顯示
ImageView iv = (ImageView) findViewById(R.id.iv); //載入圖片 //Bitmap bitmap =BitmapFactory.decodeFile("/mnt/sdcard/img7.jpg"); Bitmap bitmap =BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/img7.jpg"); //設置圖片 iv.setImageBitmap(bitmap);
以上的圖片可以正常載入
異常現象---載入 的圖片過大,如2560*1520之類的,載入 時就會報OutMemoryError記憶體溢出
java.lang.OutOfMemoryError
3.設置圖片的縮放
-
獲取圖片的大小寬和高
獲取圖片的寬高
-
jpg
//PNG圖片,不認識的。 ExifInterface exif = new ExifInterface("/mnt/sdcard/biger.jpg"); String width = exif.getAttribute(ExifInterface.TAG_IMAGE_WIDTH); String height = exif.getAttribute(ExifInterface.TAG_IMAGE_LENGTH);
-
png
Options opt = new Options(); //不會有bitmap返回,但是out的欄位有輸出 opt.inJustDecodeBounds = true; BitmapFactory.decodeFile("", opt); //得到圖片寬高 opt.outHeight; opt.outWidth ;
-
-
獲取屏幕的大小寬和高
//1. 獲取到屏幕解析度 WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE); Display display = manager.getDefaultDisplay(); Point outSize = new Point(); display.getSize(outSize); int x = outSize.x;
-
使用圖片的大小寬和屏幕的寬相除,圖片的高與屏幕的高相除,比大小,取最大值,或者取中間值
-
/** 圖片設置縮放比例 @author 劉楠 * 2016-3-3下午1:20:28 */ @SuppressLint("NewApi") public class MainActivity extends Activity { private static final String TAG = "MainActivity"; /* * 源圖片 */ private ImageView src; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 源圖片 src = (ImageView) findViewById(R.id.src); /*Options options = new Options(); options.inJustDecodeBounds=true; BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + "/2.jpg",options);*/ /** * 得到屏幕的寬高 */ WindowManager manager = (WindowManager) getSystemService(WINDOW_SERVICE); Display defaultDisplay = manager.getDefaultDisplay(); Point point = new Point(); defaultDisplay.getRealSize(point); int screenWidth = point.x; int screenHeight = point.y; Log.d(TAG, "屏幕寬:"+screenWidth); Log.d(TAG, "屏幕高:"+screenHeight); /* * jpg圖片解析 */ try { ExifInterface jpgExifInterface = new ExifInterface( Environment.getExternalStorageDirectory() + "/2.jpg"); /* * 圖片的寬度 */ String width = jpgExifInterface .getAttribute(ExifInterface.TAG_IMAGE_WIDTH); /* * 得到圖片的高度 */ String height = jpgExifInterface .getAttribute(ExifInterface.TAG_IMAGE_LENGTH); Log.d(TAG, "圖片寬:"+width); Log.d(TAG, "圖片高:"+height); //計算比例 int scale=Integer.parseInt(width)/screenWidth>Integer.parseInt(height)/screenHeight?Integer.parseInt(width)/screenWidth:Integer.parseInt(height)/screenHeight; //設置顯示 Log.d(TAG,"比例:"+scale); //調置採樣率,比例 Options opts = new Options(); opts.inSampleSize=scale; //使用工廠再次解析 Bitmap decodeFile = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + "/2.jpg", opts); //設置圖片顯示 src.setImageBitmap(decodeFile); } catch (IOException e) { e.printStackTrace(); } }
4.圖片的一些常用操作
-
圖片的平移
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* * 源圖片顯示 */ srcImage = (ImageView) findViewById(R.id.ivsrc); /* * 目標圖片 */ desImage = (ImageView) findViewById(R.id.ivdesc); /* * 獲取圖片資源 */ Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/bg.png"); //設置源圖片顯示 srcImage.setImageBitmap(bitmap); //創建一張記憶體中的圖片 Bitmap buffereImage = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); Canvas canvas = new Canvas(buffereImage); Paint paint = new Paint(); Matrix matrix = new Matrix(); //移動第一個參數x 水平, 第二個參數y高度,可以是負值 matrix.setTranslate(-20, -10); /* * 新圖 * 第一個參數:參照物 * 第二個matrix:矩陣 * 第三個參數:畫筆 */ canvas.drawBitmap(bitmap, matrix, paint); desImage.setImageBitmap(buffereImage); }
- 圖片的圖像旋轉 /* * degrees角度: * px:開始旋轉的水平坐標 * py:開始旋轉的垂直坐標 */ matrix.setRotate(45, bitmap.getWidth()/2, bitmap.getHeight()/2);
只需要更改Matrix
Matrix matrix = new Matrix();
//移動第一個參數x 水平, 第二個參數y高度,可以是負值
/*
* degrees角度:
* px:開始旋轉的水平坐標
* py:開始旋轉的垂直坐標
*/
matrix.setRotate(90, bitmap.getWidth()/2, bitmap.getHeight()/2);
-
圖片的鏡子效果
Matrix matrix = new Matrix(); //移動第一個參數x 水平, 第二個參數y高度,可以是負值 /* * 先把圖片水平翻轉 */ matrix.setScale(-1, 1); /* * 在再現在的效果上,水平移動圖片的寬度 */ matrix.postTranslate(bitmap.getWidth(), 0);
-
. 圖片的倒影效果
Matrix matrix = new Matrix(); //移動第一個參數x 水平, 第二個參數y高度,可以是負值 /* * 先把圖片垂直翻轉 */ matrix.setScale(1, -1); /* * 在再現在的效果上,垂直移動圖片的高度 */ matrix.postTranslate(0, bitmap.getHeight());
-
setXXX和 postXXX區別
前者是在原圖基礎上做變化,後者是在目前的效果基礎上做變化
5.自定義畫板塗鴉
佈局文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layoutwidth="matchparent" android:layoutheight="matchparent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="15dp" android:orientation="horizontal" > <!-- 畫筆顏色 --> <View android:id="@+id/red" android:layout_width="50dp" android:layout_height="50dp" android:background="#ff0000" /> <View android:id="@+id/green" android:layout_width="50dp" android:layout_height="50dp" android:background="#00ff00" /> <View android:id="@+id/blue" android:layout_width="50dp" android:layout_height="50dp" android:background="#0000ff" /> <View android:id="@+id/yellow" android:layout_width="50dp" android:layout_height="50dp" android:background="#ffff00" /> <View android:id="@+id/purple" android:layout_width="50dp" android:layout_height="50dp" android:background="#ff00ff" /> </LinearLayout> <!-- 畫筆粗細 --> <SeekBar android:id="@+id/seekbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="20" android:progress="5" android:thumb="@drawable/ok" /> <!-- 塗鴉的地方 --> <ImageView android:id="@+id/iv_result" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
菜單R.menu.main
<menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/save" android:orderInCategory="100" android:showAsAction="never" android:title="保存塗鴉"/> <item android:id="@+id/clear" android:orderInCategory="100" android:showAsAction="never" android:title="清除數據"/> </menu>
Activity
/** * 畫板塗鴉 * 1.在記憶體中生成一張圖片 * 2.為ImageView設置這張圖片 * 3.設置畫布,畫筆 * 4.為ImageView設置監聽事件 * @author 劉楠 * * 2016-3-3下午7:28:20 */ public class MainActivity extends Activity implements OnClickListener, OnSeekBarChangeListener, OnTouchListener{ private static final String TAG = "MainActivity"; /* * 進度條,用來改變畫筆粗細 */ private SeekBar seekBar; /* * 畫筆的顏色 */ private View red; private View green; private View blue; private View yellow; private View purple; /* * 畫板 */ Canvas canvas ; /* * 畫筆 */ Paint paint; private ImageView ivResult; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* * 畫板要畫的地方 */ ivResult = (ImageView) findViewById(R.id.iv_result); /* * 進度條,用來改變畫筆粗細 */ seekBar = (SeekBar) findViewById(R.id.seekbar); /* * 畫筆的顏色 */ red = findViewById(R.id.red); green = findViewById(R.id.green); blue = findViewById(R.id.blue); yellow = findViewById(R.id.yellow); purple = findViewById(R.id.purple); /* * 設置監聽事件 */ red.setOnClickListener(this); green.setOnClickListener(this); blue.setOnClickListener(this); yellow.setOnClickListener(this); purple.setOnClickListener(this); seekBar.setOnSeekBarChangeListener(this); /* * 記憶體中的圖 */ buffImage = Bitmap.createBitmap(300, 300, Config.ARGB_8888); /* * 畫板 */ canvas = new Canvas(buffImage); canvas.drawColor(Color.WHITE); /* * 畫布 */ paint = new Paint(); paint.setStrokeCap(Cap.ROUND); ivResult.setImageBitmap(buffImage); ivResult.setOnTouchListener(this); } /** * 進度條改變時 */ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } /** * 進度條觸摸時 */ @Override public void onStartTrackingTouch(SeekBar seekBar) { } /** * 進度條停止 */ @Override public void onStopTrackingTouch(SeekBar seekBar) { int progress = seekBar.getProgress(); paint.setStrokeWidth(progress); Toast.makeText(this, "當前畫筆粗細是:"+progress, Toast.LENGTH_SHORT).show(); } /** * 單擊事件監聽器 */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.red: paint.setColor(Color.RED); Log.d(TAG,"畫筆顏色:紅色"); break; case R.id.green: paint.setColor(Color.GREEN); Log.d(TAG,"畫筆顏色:綠色"); break; case R.id.blue: paint.setColor(Color.BLUE); Log.d(TAG,"畫筆顏色:藍色"); break; case R.id.yellow: paint.setColor(Color.YELLOW); Log.d(TAG,"畫筆顏色:黃色"); break; case R.id.purple: paint.setColor(0xffff00ff); Log.d(TAG,"畫筆顏色:祡色"); break; } } float startX ; float startY; /* * 記憶體中的圖 */ private Bitmap buffImage; /** * ImageView觸摸事件 */ @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.d(TAG, "down---"+event.getX()+" ::: "+event.getY()); startX = event.getX(); startY = event.getY(); canvas.drawLine(startX, startY, startX, startY, paint); ivResult.setImageBitmap(buffImage); break; case MotionEvent.ACTION_MOVE: Log.d(TAG, "move---"+event.getX()+" ::: "+event.getY()); float stopX = event.getX(); float stopY = event.getY(); canvas.drawLine(startX, startY, stopX, stopY, paint); ivResult.setImageBitmap(buffImage); startX = event.getX(); startY = event.getY(); break; case MotionEvent.ACTION_UP: Log.d(TAG, "up---"+event.getX()+" ::: "+event.getY()); break; } return true; } /** * 添加菜單 */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } /** * 菜單被選擇時的事件保存圖片與清除圖片 */ @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { switch (item.getItemId()) { case R.id.save: File file = new File(Environment.getExternalStorageDirectory(), System.currentTimeMillis()+".jpg"); try { OutputStream out = new FileOutputStream(file); buffImage.compress(CompressFormat.JPEG, 100, out); Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show(); } catch (FileNotFoundException e) { e.printStackTrace(); } /* * 發送通知告訴系統新增加了一張圖片 */ Intent intent =new Intent(); intent.setAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); //發送數據 intent.setData(Uri.fromFile(file)); //發送廣播 sendBroadcast(intent); break; case R.id.clear: /* * 清除畫板 */ canvas.drawColor(Color.WHITE); ivResult.setImageBitmap(buffImage); break; } return super.onMenuItemSelected(featureId, item); } }
保存在SD卡上的許可權
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
getX和getRawX的區別
- getX
當前的觸摸位置到控制項的左邊間距
- getRawX
當前的觸摸位置到屏幕的左邊間距
6.簡單撕衣服
原理:
- 1.準備兩張一樣的圖片,一張是穿有衣服的,另一張是沒有穿衣服的。
- 2.通過FrameLayout進行佈局,穿衣服的放上面,沒穿衣服的圖片放下麵。
- 3.通過觸摸事件進行判斷,手指划過的地方,讓穿衣服的圖片變成透明,就顯示到了下麵沒穿衣服的圖片。這樣效果就形成了。
佈局 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/after" /> <ImageView android:id="@+id/pre" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
Activty實現
/** * 撕衣服 * 1.準備兩張一樣的圖片,一張是穿有衣服的,另一張是沒有穿衣服的。 2.通過FrameLayout進行佈局或者相對佈局這裡使用相對,穿衣服的放上面,沒穿衣服的圖片放下麵。 3.通過觸摸事件進行判斷,手指划過的地方,讓穿衣服的圖片變成透明,就顯示到了下麵沒穿衣服的圖片。 * @author 劉楠 * * 2016-3-3下午11:22:08 */ public class MainActivity extends Activity implements OnTouchListener { private static final String TAG = "MainActivity"; /* * 前面的一張圖片 */ private ImageView pre; private Canvas canvas; private Bitmap buffImage; private static final int RADIUS = 10; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pre = (ImageView) findViewById(R.id.pre); /* * 通過這種方法讀取的bitmap是只讀的,不可修改 */ Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pre); /* * 記憶體中的生成一張同樣大小與配置的圖片 */ buffImage = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); canvas = new Canvas(buffImage); Paint paint = new Paint(); Matrix matrix = new Matrix(); /* * 畫圖 */ canvas.drawBitmap(bitmap, matrix, paint); pre.setImageBitmap(buffImage); /* * 設置監聽事件 */ pre.setOnTouchListener(this); } @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: Log.d(TAG, "move" + event.getX() + "------->" + event.getY()); int stopX = (int) event.getX(); int stopY = (int) event.getY(); // 這個判斷是計算邊界,因為超過了邊界為負值時會報錯 if (stopX >= RADIUS && stopX <= pre.getWidth() - RADIUS && stopY >= RADIUS && stopY <= pre.getHeight() - RADIUS) { /** * 計算圓,挖空一個半徑為RADIUS的實心圓 */ for (int radius = 0; radius <= RADIUS; radius++) { for (double angle = 0; angle <= 360; angle++) { int newX = (int) (stopX + radius * Math.cos(angle)); int newY = (int) (stopY + radius * Math.sin(angle)); buffImage.setPixel(newX, newY, Color.TRANSPARENT); } } pre.setImageBitmap(buffImage); } break; } return true; } }
7.簡易調色板的使用
佈局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="30sp" android:text="調色板" /> <SeekBar android:id="@+id/seekbar_red" android:layout_width="match_parent" android:layout_height="wrap_content" android:progress="50" android:max="100"/> <SeekBar android:id="@+id/seekbar_green" android:layout_width="match_parent" android:layout_height="wrap_content" android:progress="50" android:max="100"/> <SeekBar android:id="@+id/seekbar_blue" android:layout_width="match_parent" android:layout_height="wrap_content" android:progress="50" android:max="100"/> <SeekBar android:id="@+id/seekbar_alpha" android:layout_width="match_parent" android:layout_height="wrap_content" android:progress="50" android:max="100"/> <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
Activity
/** * 簡易調色板 步驟: 1.使用SeekBar來控制顏色的顯示比例 * * * @author 劉楠 * * 2016-3-3下午10:58:24 */ public class MainActivity extends Activity { private SeekBar seekbarRed; private ImageView iv; private Paint paint; private Matrix matrix; private Canvas canvas; private SeekBar seekbarGreen; private SeekBar seekbarBlue; private SeekBar seekbarAlpha; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); seekbarRed = (SeekBar) findViewById(R.id.seekbar_red); seekbarGreen = (SeekBar) findViewById(R.id.seekbar_green); seekbarBlue = (SeekBar) findViewById(R.id.seekbar_blue); seekbarAlpha = (SeekBar) findViewById(R.id.seekbar_alpha); iv = (ImageView) findViewById(R.id.iv); // 通過這種方法讀取的bitmap是只讀的,不可修改 final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pre14); final Bitmap buffImage = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); canvas = new Canvas(buffImage); paint = new Paint(); matrix = new Matrix(); canvas.drawBitmap(bitmap, matrix, paint); iv.setImageBitmap(buffImage); seekbarRed.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { int progress = seekBar.getProgress(); float value = progress / 50.0f; ColorMatrix cm = new ColorMatrix(); /* * * 顏色矩陣 */ cm.set(new float[] { 1 * value, 0, 0, 0, 0,// 紅色 0, 1, 0, 0, 0,// 綠色 0, 0, 1, 0, 0,// 藍色 0, 0, 0, 1, 0,// 透明度 }); // 給畫筆添加過濾器 // 給畫筆添加顏色過濾器 paint.setColorFilter(new ColorMatrixColorFilter(cm)); canvas.drawBitmap(bitmap, matrix, paint); iv.setImageBitmap(buffImage); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float value = progress / 50.0f; ColorMatrix cm = new ColorMatrix(); /* * * 顏色矩陣 */ cm.set(new float[] { 1 * value, 0, 0, 0, 0,// 紅色 0, 1, 0, 0, 0,// 綠色 0, 0, 1, 0, 0,// 藍色 0, 0, 0, 1, 0,// 透明度 }); // 給畫筆添加過濾器 // 給畫筆添加顏色過濾器 paint.setColorFilter(new ColorMatrixColorFilter(cm)); canvas.drawBitmap(bitmap, matrix, paint); iv.setImageBitmap(buffImage); } }); seekbarGreen.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) {