1八、圖片 & 多媒體

1、圖片處理

1.一、BitMap

image

1.Bitmap介紹android

Bitmap實如今android.graphics包中。可是Bitmap類的構造函數是私有的,外面並不能實例化,只能是經過JNI實例化。算法

這必然是某個輔助類提供了建立Bitmap的接口,而這個類的實現經過JNI接口來實例化Bitmap的,這個類就是BitmapFactory。編程

Bitmap是一片連續的內存空間,而咱們的應用程序的內存是散亂的,若是當零散的空間下容納不了bitmap時就致使OOM。數組

2.BitmapFactory緩存

image

其中提供的一個Opitions屬性能夠用來提早獲取到圖片的寬高信息,下面會介紹。網絡

2.Bitmap優化app

當前有一張圖片,大小僅爲1M,可是其規格爲3648*2736,如今須要加載此圖片總像素數=3648*2736=9980928jsp

假設如今像素採用ARGB_4444標準,則其佔用的總空間爲:
圖片佔用空間=總像素數 *像素的單位 ----> 9980928 * 2bytes=19961856bytes = 19M > 16M  OOM內存溢出ide

因此咱們必須對圖片進行縮放才能加載:函數

假設:
圖片的寬和高: 3648 * 2736 屏幕的寬和高: 320 * 480

計算縮放比:
寬度縮放比例: 3648 / 320 = 11 高度縮放比例: 2736 / 480 = 5

比較寬和高的縮放比例, 哪個大用哪個進行縮放
縮放後的圖片:
3648 / 11 = 331
2736 / 11 = 248
縮放後圖片的寬和高: 331* 248
331* 248=882088 * 2bytes=160K

a22c3152-2354-44a5-a1d9-3ca23c142e73

3.解析圖片的三種方式

1.使用BitmapFactory解析圖片

78550ecf-1412-4659-ad77-cd44e52fe1aa

2.使用BitmapDrawable解析圖片

9f920025-6e75-4225-98ea-a1f2e8cbb8ec

3.使用InputStream和BitmapDrawable繪製

27c8f43d-d402-4f20-a466-15cd4c50792a

1.二、圖片特效

圖片的特效包括,圖形的縮放、鏡面、倒影、旋轉、位移等。圖片的特效是將原圖的圖形矩陣乘以一個特效矩陣,造成一個新的圖形矩陣來實現的。
Matrix維護了一個3*3的矩陣去更改像素點的座標。
圖形的默認矩陣用數組表示爲:
{ 1, 0, 0,     表示向量x = 1x + 0y + 0z
  0, 1, 0,     表示向量y = 0x + 1y + 0z
  0, 0, 1 }    表示向量z = 0x + 0y + 1z
經過更改圖形矩陣的值,能夠作出縮放/鏡面/倒影等圖片特效。

1.縮放

0f2ac410-065a-42a4-a499-0cbf4727088c

2.鏡面

f34cc74c-e920-4cc0-beeb-4b16a0bd6cf4

惟一不一樣的地方在矩陣處

3.倒影

1807c6d8-1ef1-471e-95c6-d7ae32da6b87

4.旋轉

b982289c-3955-47a0-9039-22c1bc49ef2e

5.位移

5619153f-7493-470a-bc5e-64460480d97b

1.三、顏色過濾器

Android提供了顏色過濾器來進行顏色處理。

a)ColorMatrixColorFilter:經過使用一個4*5的顏色矩陣來建立一個顏色過濾器,改變圖片的顏色信息。

b) 圖形顏色默認矩陣是一個4x5的矩陣, 數組表現爲:

{1, 0, 0, 0, 0, // red  1*R + 0*G + 0*B + 0*A + 0

0, 1, 0, 0, 0, // green  0*R + 1*G + 0*B + 0*A + 0

0, 0, 1, 0, 0, // blue 0*R + 0*G + 1*B + 0*A + 0

0, 0, 0, 1, 0} // alpha 0*R + 0*G + 0*B + 1*A + 0

顏色矩陣的每一行的最後一個值更改時,其對應的顏色值就會發生改變,因此更改顏色只需修改其對應顏色矩陣行的最後一項的值便可,最大值範圍爲255

a)首先咱們聲明一個初始化矩陣數組和顏色過濾器

bfecdb3b-394a-44bb-b94d-e59a90c01e5e

b)重寫progressBar的onProgressChanged方法,並修改矩陣數組的值後,從新建立新的顏色過濾器。

3d5ac1ed-5794-4e1e-b441-1c55d47fd652

58fcefef-0aea-4b7f-b9ed-449019633160

1.四、手繪

a)首先在佈局文件建立一個ImageView,讓其寬高都填充父窗體,並在代碼中進行實例化,並設置它的Touch事件。

mIv = (ImageView) findViewById(R.id.iv);
mIv.setOnTouchListener(this);

b) 而後重寫onTouch(View v, MotionEvent event)方法對手勢進行操做

@Override
public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    switch (action) {
    case MotionEvent.ACTION_DOWN:
        mStartX = (int) event.getX();
        mStartY = (int) event.getY();
        if(mBitmap == null){
            mBitmap = Bitmap.createBitmap(mIv.getWidth(),mIv.getHeight(),Config.ARGB_8888);
            // 畫布
            mCanvas = new Canvas(mBitmap);
            // 設置背景色白色
            mCanvas.drawColor(Color.WHITE);
            mPaint = new Paint();
            // 設置畫筆顏色爲紅色,線條粗細爲5
            mPaint.setColor(Color.RED);
            mPaint.setStrokeWidth(5);
        }
        break;
    case MotionEvent.ACTION_MOVE:
        // 記錄移動到的位置座標
        int moveX = (int) event.getX();
        int moveY = (int) event.getY();
        // 繪製線條,鏈接起始位置和當前位置
        mCanvas.drawLine(mStartX, mStartY, moveX, moveY, mPaint);
        // 設置顯示
        mIv.setImageBitmap(mBitmap);
        // 將起始位置改成爲當前移動到的位置
        mStartX = moveX;
        mStartY = moveY;
        break;
    case MotionEvent.ACTION_UP:
        break;
    }
    return true;
}

c) 上述基本功能已經完成,咱們還須要一個清空的方法

// 清除界面
public void clear(View view){
    mBitmap = null;
    mIv.setImageBitmap(null);
}

1.五、三級緩存

1. 簡介

如今android應用中不可避免的要使用圖片,有些圖片是能夠變化的,須要每次啓動時從網絡拉取。

如今有一個問題:假如每次啓動的時候都從網絡拉取圖片的話,勢必會消耗不少流量。在當前的情況下,對於非wifi用戶來講,流量仍是很貴的,

一個很耗流量的應用,其用戶數量級確定要受到影響。固然,我想,向百度美拍這樣的應用,必然也有其內部的圖片緩存策略。總之,圖片緩存是很重要並且是必須的。

2.圖片緩存的原理

實現圖片緩存也不難,須要有相應的cache策略。這裏我採用 內存-文件-網絡 三層cache機制,其中內存緩存包括強引用緩存和軟引用緩存(SoftReference),

其實網絡不算cache,這裏姑且也把它劃到緩存的層次結構中。當根據url向網絡拉取圖片的時候,先從內存中找,若是內存中沒有,再從緩存文件中查找,

若是緩存文件中也沒有,再從網絡上經過http請求拉取圖片。在鍵值對(key-value)中,這個圖片緩存的key是圖片url的hash值,value就是bitmap。因此,

按照這個邏輯,只要一個url被下載過,其圖片就被緩存起來了。

關於Java中對象的軟引用(SoftReference),若是一個對象具備軟引用,內存空間足夠,垃圾回收器就不會回收它;若是內存空間不足了,就會回收這些對象的內存。

只要垃圾回收器沒有回收它,該對象就能夠被程序使用。軟引用可用來實現內存敏感的高 速緩存。使用軟引用能防止內存泄露,加強程序的健壯性。 

固然,這種回收機制只存在於Android 2.3版本以前,Android 2.3以後垃圾回收器會更傾向於回收軟引用、弱引用,它們變得再也不可靠。

從代碼上來講,採用一個ImageManager來負責圖片的管理和緩存,函數接口爲public void loadBitmap(String url, Handler handler) ;其中url爲要下載的圖片地址,

handler爲圖片下載成功後的回調,在handler中處理message,而message中包含了圖片的信息以及bitmap對象。ImageManager中使用的ImageMemoryCache(內存緩存)、

ImageFileCache(文件緩存)以及LruCache(最近最久未使用緩存)會在後續文章中介紹。

3838b7ba-3094-4194-8ab6-8ceea57891bc

2、多媒體

1.一、音頻播放

一、MediaPlayer

該播放器同時只能播放一個音樂文件,文件大小並無限制。MediaPlayer必須嚴格按照狀態圖操做,不然就會出現錯誤。

032294fb-e009-4714-971b-2b118f637bc1

MediaPlayer播放的實例:

// 建立MediaPlayer對象
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(Environment.getExternalStorageDirectory() + "/bg.mp3");
// 準備
mediaPlayer.prepare();
// 判斷當前音樂是否在播放
boolean isPlaying = mediaPlayer.isPlaying();
if(!isPlaying){
    mediaPlayer.start();
}else{
    Toast.makeText(this,"音樂正在播放中",0).show();
}

二、SoundPool

SoundPool特色是能夠自行設置聲音的品質、音量、播放比率等參數。而且它能夠同時管理多個音頻流,每一個流都有獨自的ID,對某個音頻流的管理都是經過ID進行的。

a)SoundPool最大隻能申請1M的內存空間,只能用一些很短的聲音片斷,而不是用它來播放歌曲或者作遊戲背景音樂。

b)SoundPool提供了pause和stop方法,但這些方法建議最好不要輕易使用,由於有些時候它們可能會使你的程序莫名其妙的終止。

c)SoundPool的效率問題。其實SoundPool的效率在這些播放類中算是很好的,這可能會影響用戶體驗。

d7fe9422-87e3-4e59-80ec-151e0251009d

SoundPool播放的實例:

// 建立SoundPool對象
SoundPool soundPool = new SoundPool(1,AudioManager.STREAM_MUSIC,1);
// 加載SoundPool音樂文件
int soundID = soundPool.load(this,R.raw.shoot1,1);
// 播放soundPool音樂
soundPool.play(soundID,1,1,0,0,1);

1.二、視頻播放

1.第一種

a)第一種方式能夠經過surfaceView和MediaPlayer來實現該功能,首先建立一個SufaceView實例

2.第二種

a)設置佈局文件,佈局文件比較簡單,所以這裏只給你VideoView標籤。

mSurface = (SurfaceView) findViewById(R.id.sfv);     
mHolder = mSurface.getHolder();
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

b) 而後經過以下代碼播放,注意視頻知支持mp4格式

/ 建立播放器對象
MediaPlayer player = new MediaPlayer();
// 獲取音樂路徑
String path = "/mnt/sdcard/oppo.mp4";
// 給播放器設置音樂路徑
player.setDataSource(path);
// 設置音樂格式
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
// 設置輸出畫面
player.setDisplay(mHolder);
// 準備
player.prepare();
// 播放
player.start();

 

2.第二種

a)設置佈局文件,佈局文件比較簡單,所以這裏只給你VideoView標籤。

<VideoView 
    android:id="@+id/video"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

b) 設置VideoView的播放文件路徑和媒體控制器,調用start方法便可播放媒體文件,固然如今只是讓當前類實現了MediaController接口

VideoView video = (VideoView) findViewById(R.id.video);
video.setVideoPath("/mnt/sdcard/oppo.mp4");
video.setMediaController(new MediaController(this));
// 開始播放
video.start();
// 設置當前播放器窗口爲焦點
video.requestFocus();

c)這時,視頻已經能夠播放,若是想實現本身的業務邏輯,能夠定義類實現MediaPlayerControl接口,其中提供大量的回調方法供咱們使用。

1.三、傳感器

Android手機中內置了不少傳感器,其主要類型有:方向、加速度(重力)、光線、磁場、距離(臨近性)、溫度等。

image

1.傳感器的使用

a) 獲取傳感器管理器SensorManager

SensorManager sm = (SensorManager) getSystemService(SENSOR_SERVICE);

b) 經過傳感器管理器對象得到指定類型的傳感器:

// 獲取指定傳感器對象,獲取系統默認的重力加速度傳感器
Sensor sensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

c) 經過傳感器管理器對象得到手機中全部的傳感器

// 獲取手機支持的全部傳感器
List<Sensor> sensorList = sm.getSensorList(Sensor.TYPE_ALL);
for (int i = 0; i < sensorList.size(); i++) {
    Sensor sensor = sensorList.get(i);
    // 獲取傳感器名稱
    String name = sensor.getName();
    // 獲取傳感器廠商
    String vendor = sensor.getVendor();
    // 獲取傳感器版本號
    int version = sensor.getVersion();
}

d) 使用傳感器管理器對象註冊傳感器來使一個傳感器工做:

sm.registerListener(new SensorEventListener() {
    // 當傳感器改變時觸發該函數
    @Override
    public void onSensorChanged(SensorEvent event) {
        
    }
    // 當傳感器精度更改時觸發該函數
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        
    }
},sensor,SensorManager.SENSOR_DELAY_NORMAL);

(1) listener :傳感器事件監聽器

(2) sensor :要被註冊的傳感器對象

(3) rate  :採樣率,分爲最快、遊戲、普通、用戶界面幾種當應用程序請求特定的採樣率時,其實只是對傳感器子系統的一個建議,不保證特定的採樣率可用。

採樣率的四種類型詳解:
最快: SensorManager.SENSOR_DELAY_FASTEST,最低延遲,通常不是特別敏感的處理不推薦使用,該種模式可能形成耗電,因爲傳遞的爲原始數據,

       算法不處理好會影響遊戲邏輯和UI的性能
遊戲: SensorManager.SENSOR_DELAY_GAME,遊戲延遲,通常絕大多數的實時性較高的遊戲都使用該級別
普通: SensorManager.SENSOR_DELAY_NORMAL,標準延遲,對於通常的益智類或EASY級別的遊戲可使用,但太低的採樣率可能對一些賽車類遊戲有跳幀現象

用戶界面: SensorManager.SENSOR_DELAY_UI,通常對於屏幕方向自動旋轉使用,相對節省電能和邏輯處理,通常遊戲開發中咱們不使用

總結:因爲傳感器比較多,這裏只是簡單的概述,後續會花大量的時間整理傳感器的使用。

1.四、攝像頭

調用系統攝像頭進行拍照和攝像無需添加權限,直接調用便可。只需知道系統攝像頭的action和category就能夠調用系統攝像頭。

a)打開Android源碼,查看」\packages\apps\」文件文件目錄下的Camera應用,即系統攝像頭的應用程序。打開其清單文件文件,查看其Activity的action和category信息。

b)Camera類的action和category

<intent-filter>
    <action android:name="android.media.action.IMAGE_CAPTURE" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

VideoCamera類的action和category

<intent-filter>
    <action android:name="android.media.action.VIDEO_CAMERA" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

c) 已知調用系統攝像頭拍照和攝像功能對應的action和category信息,採用隱式調用的方式調用Activity。

因爲但願在調用拍照或攝像功能後回到當前應用的界面,且得知拍照或攝像的結果如何是否成功使用startActivityForResult方法開啓Activity,並重寫onActivityResult方法處理回傳的數據。

1.拍照功能

Intent intent = new Intent();
// 設置Action
intent.setAction("android.media.action.IMAGE_CAPTURE");
// 建立一個文件
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),"my.jsp");
// 建立Uri對象
Uri uri = Uri.fromFile(file);
// 設置圖片輸出路徑
intent.putExtra(MediaStore.EXTRA_OUTPUT,uri);
// 開啓Activity
startActivityForResult(intent,100);

2.攝像功能

Intent intent = new Intent();
intent.setAction("android.media.action.VIDEO_CAPTURE");
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),"myVedio.mp4");
Uri uri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT,uri);
startActivityForResult(intent,101);

3.自定義拍照

a)首先定義一個SurfaceView用做相機的預覽

SurfaceView mSurfaceView = (SurfaceView) this.findViewById(R.id.surfaceView);
SurfaceHolder holder = mSurfaceView.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.setKeepScreenOn(true);
holder.addCallback(new SurfaceCallback());

  b )建立SurfaceCallback來開啓預覽,其中提供了三個回調方法,方便咱們對相機預覽進行管理。

/**sufaceView的回調*/
private final class SurfaceCallback implements Callback {
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            mCamera = Camera.open(0);// 0:打開後置    1:打開前置 
            if(mCamera != null){
                mCamera.setPreviewDisplay(holder);
                mCamera.setDisplayOrientation(getPreviewDegree(NewCameraCheck.this));
                mCamera.startPreview();
            }else{
                Toast.makeText(NewCameraCheck.this, "獲取不到相機實例", Toast.LENGTH_SHORT).show();
            }          
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
        if(mCamera != null){
            parameters = mCamera.getParameters(); 
            parameters.setPictureFormat(PixelFormat.JPEG);  
            parameters.setPreviewSize(width, height);
            parameters.setPreviewFrameRate(5);
            parameters.setPictureSize(width, height);
            parameters.setJpegQuality(80);
        }else{
            Toast.makeText(NewCameraCheck.this, "獲取不到相機實例,沒法設置參數。", Toast.LENGTH_SHORT).show();
        }
    }
    // 在Surface銷燬時釋放資源
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if(mCamera != null){
            //mCamera.stopPreview();
            mCamera.release(); 
            mCamera = null;
        }
    }
}

c) 提供一個靜態方法用來對相機預覽的旋轉角度進行自動調整

// 提供一個靜態方法,用於根據手機方向得到相機預覽畫面旋轉的角度
public  int getPreviewDegree(Activity activity) {
    // 得到手機的方向
    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    mDegree = 0;
    // 根據手機的方向計算相機預覽畫面應該選擇的角度
    switch (rotation) {
    case Surface.ROTATION_0:
        mDegree = 90;
        break;
    case Surface.ROTATION_90:
        mDegree = 0;
        break;
    case Surface.ROTATION_180:
        mDegree = 270;
        break;
    case Surface.ROTATION_270:
        mDegree = 180;
        break;
    }
    return mDegree;
}

d) 咱們能夠經過調用Camera的tackPicture()方法進行拍照,若是咱們須要對焦拍照的話,使用下面這段代碼拍照

public void tackImage(){
    if(mCamera == null){
        Toast.makeText(NewCameraCheck.this, "獲取不到相機實例,拍照失敗!", Toast.LENGTH_SHORT).show();
        return;
    }
    mCamera.autoFocus(new AutoFocusCallback() {
        @Override
        public void onAutoFocus(boolean success, Camera camera) {
            mCamera.takePicture(null, null, new MyPictureCallback());
            //mCamera.startPreview();
        }
    });
}

e) 除此以外,咱們相機適配須要注意清單文件中的配置,固然還要記得添加權限

清單文件配置:
<activity
    android:name="com.hll.phoneuser.activity.NewCameraCheck"
    android:screenOrientation="portrait"
    android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen" />  
權限配置:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

4.自定義攝像

使用Camera+MediaRecoder + SurfaceView控件可實現錄製視頻的功能。

a)首先定義一個SurfaceView用做相機的預覽

setContentView(R.layout.activity_main);
SurfaceView mSurfaceView  = (SurfaceView) findViewById(R.id.surface);
SurfaceHolder holder = mSurfaceView .getHolder();
holder.addCallback(new MyVideoCallback());

b) 建立SurfaceCallback來開啓預覽,其中提供了三個回調方法,方便咱們對相機預覽進行管理。

class MyVideoCallback implements Callback{
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mCamera.open();
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        
    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mCamera.stopPreview();
        mCamera.release();
    }
}

c)開始錄像須要設置大量的參數,代碼中異常未處理,具體操做以下

// 中止預覽
mCamera.stopPreview();
// 解鎖攝像頭
mCamera.unlock();
// 初始化MediaRecorder對象
MediaRecorder recorder = new MediaRecorder();
// 給recorder設置攝像頭
recorder.setCamera(mCamera);
// 設置音頻源
recorder.setAudioSource(AudioSource.CAMCORDER);
// 設置視頻源
recorder.setVideoSource(VideoSource.CAMERA);
// 設置錄像質量參數
CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);
recorder.setProfile(profile);
// 設置錄像輸出路徑
recorder.setOutputFile(Environment.getExternalStorageDirectory().getAbsolutePath()+"/test.mp4");
// 設置預覽顯示對象
recorder.setPreviewDisplay(mHolder.getSurface());
// 準備
recorder.prepare();
recorder.start();

d) 若是想中止錄像的話,只須要調用以下代碼:

mRecorder.stop();
mRecorder.reset();
mRecorder.release();
mCamera.lock();
mCamera.startPreview();

e) 固然別忘記添加權限

<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

後續進階能夠參看:Android多媒體開發高級編程

3、拍照和相冊獲取圖片

首先調用系統的相機或打開相冊來獲取圖片

// 拍照
btnCamera.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(
                Environment.getExternalStorageDirectory(), "temp.jpg")));
        startActivityForResult(intent, PHOTOHRAPH);
    }
});
// 從相冊選擇
btnPhoto.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, PHOTOZOOM);
    }
});

在activity中的onActivityResult中進行回調獲取到打開的圖片

public static final int NONE = 0;
public static final int PHOTOHRAPH = 1;// 拍照
public static final int PHOTOZOOM = 2; // 縮放
public static final int PHOTORESULE = 3;// 結果  
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
    case NONE:
        return;
    case PHOTOHRAPH:    // 拍照
        // 設置文件保存路徑這裏放在根目錄下
        File picture = new File(Environment.getExternalStorageDirectory() + "/temp.jpg");
        startPhotoZoom(Uri.fromFile(picture));
        break;
    case PHOTOZOOM:    // 從相冊選擇
        startPhotoZoom(data.getData());
        break;
    case PHOTORESULE:
        Bundle extras = data.getExtras();
        if (extras != null) {
            Bitmap photo = extras.getParcelable("data");
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            photo.compress(Bitmap.CompressFormat.JPEG, 75, stream);// (0 - 100)壓縮文件
            
            // 設置頭像顯示
            mIvPhoto.setImageBitmap(photo);
            dialog.dismiss();
        }
        break;
    }
}

其中封裝的方法startPhotoZoom,是對圖片進行寬高和壓縮等處理:

public void startPhotoZoom(Uri uri) {
    Intent intent = new Intent("com.android.camera.action.CROP");
    intent.setDataAndType(uri, "image/*");
    intent.putExtra("crop", "true");
    // aspectX aspectY 是寬高的比例
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    // outputX outputY 是裁剪圖片寬高
    intent.putExtra("outputX", 64);
    intent.putExtra("outputY", 64);
    intent.putExtra("return-data", true);
    startActivityForResult(intent, PHOTORESULE);
}
相關文章
相關標籤/搜索