網絡圖片框架

網絡圖片框架

  1. 大圖片的處理原理
  2. ImageView(原生)
  3. SmartImageView(廢棄)
  4. Glide(Google)
  5. Picasso(Square)
  6. Fresco(FaceBooK)
  7. Universal ImageLoader(UIL)

01-圖片的處理原理

  1. 安卓中圖片支持的像素點: (jpg,png,webp)
    Config.ARGB_4444 =16bit = 2byte
    Config.ARGB_8888 =32bit = 4byte(默認)
    Config.RGB_565 = 16bit = 2byte
  2. 大圖片的加載 設置圖片的壓縮比例讀取
    • 位圖類的作用:對於大圖片他都會等比例的縮放到ImageView中 與在選項中屬性中的比例設置無關,
    • 總結:只要圖片的大小大於手機的分辨率,那麼ImageView加載位圖後都會等比例的縮放後適配在手機屏幕中 1.如果直接讀取會報ooM異常,如果在位圖設置選項比例後讀取的方法後讀取就不回會報異常,異常位圖中設置的 比例與顯示在屏幕中的比例無關,因爲位圖會自動適配加載到ImageView中,

//代碼步驟
  1. 獲取圖片的元數據中的寬width和高height
  2. 然後再獲取ImageView控件的寬和高 iv_width 和 iv_height
  3. 分別計算寬和高應該縮放的倍率,然後取最大值Math.max(widht/iv_width,height/iv_height) = smpleSize(縮放比例);
  4. 將jpg轉換爲Bitmap的時候,將sampleSize作爲參數傳入進去,讓API去縮放.得到一個縮放後的bitmap
  5. 將縮放後的bitmap顯示到ImageView   

<ImageView 
        android:layout_width="match_parent"
        android:layout_height="match_parent"  //下面需要獲得該控件的長度.
        android:id="@+id/iv"
        />

public class MainActivity extends Activity {
  private ImageView iv;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    iv = (ImageView) findViewById(R.id.iv);
    //下面可以在onCreate的中可以獲得控件的長度
    //iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListen() {
    //@Override
    //public void onGlobalLayout() {
    //      int iv_height = iv.getHeight();
    //      int iv_width = iv.getWidth();
    //  }
    //});
    //注意此處的因爲在OnCreate()的繪製View,在這裏不能夠獲得控件的長度.
    int iv_height = iv.getHeight();
    int iv_width = iv.getWidth();
    Log.d("tag", "iv_height="+iv_height+"/iv_width="+iv_width);
  }

  public void load(View view){
    //最普通的方式(不對圖片進行等比例縮放時)加載圖片的兩行核心代碼
    //Bitmap bitmap = BitmapFactory.decodeFile("/mnt/sdcard/dog.jpg");
    //iv.setImageBitmap(bitmap);

    File file = new File(Environment.getExternalStorageDirectory(),"me.jpg");
    //先將jpg或者png轉換爲Bitmap,然後將Bitmap設置給ImageView即可

    Options opts = new Options();
    //告訴bitmapFactory僅僅去獲取圖片的元數據(寬高),而不是去加載整個圖片
    opts.inJustDecodeBounds = true;
    //1. 獲取圖片的元數據中的寬width和高height
    //如果傳入了opts.inJustDecodeBounds = true的opts,那麼該方法的返回值就爲null
    //該方法將獲取到的結果又保存到了opts對象上,此時的返回值是null
    BitmapFactory.decodeFile(file.getAbsolutePath(), opts);
    int width = opts.outWidth;
    int height = opts.outHeight;

    //2. 然後再獲取ImageView控件的寬和高 iv_width 和 iv_height
    /*
     * 注意:imageView的寬和高寫的是match_parent才能獲取到,如果是wrap則拿到的是0
     * 注意: 獲取控件的尺寸信息,一定要等界面完全繪製完了再去拿,不要再onCreate中獲取控件的寬和高
     */
    int iv_height = iv.getHeight();
    int iv_width = iv.getWidth();

    Log.d("tag", "width="+width+"/height="+height+"\niv_width="+iv_width+"/iv_height="+iv_height);

    //3. 分別計算寬和高應該縮放的倍率,然後取最大值Math.max(widht/iv_width,height/iv_height) = smpleSize(縮放比例);
  //sampleSize=0-1之間的話  算作1 
    int sampleSize = Math.max(width/iv_width, height/iv_height);
    Log.d("tag", "sampleSize="+sampleSize);
    //4. 將jpg轉換爲Bitmap的時候,將sampleSize作爲參數傳入進去,讓API去縮放.得到一個縮放後的bitmap
    opts.inJustDecodeBounds = false;//改爲false就代表需要真正的加載圖片
    opts.inSampleSize = sampleSize;//設置等比例縮放的倍率 
    Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), opts);

    //5. 將縮放後的bitmap顯示到ImageView
    iv.setImageBitmap(bitmap);
  }
}

3. 圖片的特效處理

- 01-縮放


public void scale(View view){
    //獲取一個logo.png的bitmap形式,然後縮放2倍,然後展示到ImageView
    /*
     * 1. 獲取一個模特加載原始Bitmap
     */
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
    /*
     * 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
     */
    Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
    /*
     * 3. 將畫紙放到畫板上
     */
    Canvas canvas = new Canvas(newBitmap);
  //畫的方法
    Matrix matrix = new Matrix();
    float[] values = {
        2,0,0,
        0,1,0,
        0,0,1
        };
    matrix.setValues(values);
  //  matrix.setScale(2f, 1f);//這種方法的設置也是可以的
    /*
     * 4. 將模特畫到畫紙上
     * 參數1:模特對象
     */
    canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
    /*
     * 5. 將畫好的紙設置給ImageView
     */
    iv.setImageBitmap(newBitmap);
 }

- 02-平移


public void translate(View view){
/*
 * 1. 獲取一個模特加載原始Bitmap
 */
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
/*
 * 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
 */
Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
/*
 * 3. 將畫紙放到畫板上
 */
Canvas canvas = new Canvas(newBitmap);
Matrix matrix = new Matrix();
//參數1:x方向的平移值
//參數2:y方向的平移值
matrix.setTranslate(20, 20);
//每一個像素點在用矩陣的表示
/*
 * 4. 將模特畫到畫紙上
 * 參數1:模特對象
 */
canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
/*
 * 5. 將畫好的紙設置給ImageView
 */
iv.setImageBitmap(newBitmap);
}

- 03-鏡面


public void reverse(View view){
    /*
     * 1. 獲取一個模特加載原始Bitmap
     */
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
    /*
     * 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
     */
    Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
    /*
     * 3. 將畫紙放到畫板上
     */
    Canvas canvas = new Canvas(newBitmap);
    Matrix matrix = new Matrix();
    float[] values = {
        1,0,0,
        0,-1,0,
        0,0,1
        };
    matrix.setValues(values);
    //matrix.setScale(1f, 1f);//這種方法的設置也是可以的
    //在讓矩陣線y平移一個bitmap的高度值
    //matrix.setTranslate(0, bitmap.getHeight());
    //在原來值的基礎上再次修改
    matrix.postTranslate(bitmap.getWidth(),0);
    /*
     * 4. 將模特畫到畫紙上
     * 參數1:模特對象
     */
    canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
    /*
     * 5. 將畫好的紙設置給ImageView
     */
    iv.setImageBitmap(newBitmap);
  }

- 04-倒影


public void reverse(View view){
    /*
     * 1. 獲取一個模特加載原始Bitmap
     */
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
    /*
     * 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
     */
    Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
    /*
     * 3. 將畫紙放到畫板上
     */
    Canvas canvas = new Canvas(newBitmap);
    Matrix matrix = new Matrix();
    float[] values = {
        1,0,0,
        0,-1,0,
        0,0,1
        };
    matrix.setValues(values);
  //  matrix.setScale(f, -1f);//這種方法的設置也是可以的
    //在讓矩陣線y平移一個bitmap的高度值
//    matrix.setTranslate(0, bitmap.getHeight());
    //在原來值的基礎上再次修改
    matrix.postTranslate(0,bitmap.getHeight());
    /*
     * 4. 將模特畫到畫紙上
     * 參數1:模特對象
     */
    canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
    /*
     * 5. 將畫好的紙設置給ImageView
     */
    iv.setImageBitmap(newBitmap);
  }

- 05-旋轉


public void rotate(View view){
    /*
     * 1. 獲取一個模特加載原始Bitmap
     */
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.logo);
    /*
     * 2. 創建一張空白的畫紙,畫紙的大小跟ImageView一樣大即可
     */
    Bitmap newBitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
    /*
     * 3. 將畫紙放到畫板上
     */
    Canvas canvas = new Canvas(newBitmap);
    Matrix matrix = new Matrix();
    //默認繞着左上角旋轉
    //    matrix.setRotate(10);//0--360    0--2π
    matrix.setRotate(180, bitmap.getWidth()/2, bitmap.getHeight()/2);
    /*
     * 4. 將模特畫到畫紙上
     * 參數1:模特對象
     */
    canvas.drawBitmap(bitmap, matrix, null);//畫模特時不需要筆
    /*
     * 5. 將畫好的紙設置給ImageView
     */
    iv.setImageBitmap(newBitmap);
}

4. 實例:隨手塗鴉

01-監聽事件
02-監聽事件
03-保存圖片
04-在圖庫中預覽

public class MainActivity extends Activity {
  private ImageView iv;
  private Bitmap bitmap;
  private Canvas canvas;
  private Paint paint;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    iv = (ImageView) findViewById(R.id.iv);
    /*
     * 1. 給ImageView設置觸摸事件
     */
    /*
     * 2. 當滑動的時候,觸摸事件分爲3類:
     *  (1). down
     *    記錄一下(startX,startY)
     *  (2). move
     *    獲取到當前滑動到的座標(currentX,currentY)
     *    根據兩個座標劃線
     *    將畫好的Bitmap顯示到ImageView上
     *  (3). up
     *    
     */
    iv.setOnTouchListener(new OnTouchListener() {
      private float startX;
      private float startY;
      @Override
      public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
//          Log.d("tag", "down");
          //獲取當前事件的座標
          startX = event.getX();
          startY = event.getY();
          if (bitmap==null) {
            bitmap = Bitmap.createBitmap(iv.getWidth(), iv.getHeight(), Config.ARGB_8888);
            canvas = new Canvas(bitmap);
            //先給Bitmap繪製成白色的
            canvas.drawColor(Color.WHITE);
            paint = new Paint();
            paint.setColor(Color.RED);
            paint.setStrokeWidth(5);//畫筆的粗細 5個像素
          }
          break;
        case MotionEvent.ACTION_MOVE:
//          Log.d("tag", "move");
          float currentX = event.getX();
          float currentY = event.getY();
          //畫線
          canvas.drawLine(startX, startY, currentX, currentY, paint);
          //一個新線條的起點就是上一個線條的終點
          startX = currentX;
          startY = currentY;
          iv.setImageBitmap(bitmap);
          break;
        case MotionEvent.ACTION_UP:
//          Log.d("tag", "up");
          break;
        default:
          break;
        }
        //當前ImageView是否將這個事件給消費了
        return true;
      }
    });
  }
  public void save(View view) throws FileNotFoundException{
    //把Bitmap保存到sdcard上jpg
    if (bitmap==null) {
      Toast.makeText(this, "還沒畫呢,咋保存!", Toast.LENGTH_SHORT).show();
      return;
    }
    File file = new File(Environment.getExternalStorageDirectory(), "yuze_"+new Date().getTime()+".jpg");
    OutputStream fos = new FileOutputStream(file);
    /*
     * 參數1:壓縮的格式
     * 參數2:圖片的質量
     * 參數3:輸出流
     */
    boolean compress = bitmap.compress(CompressFormat.JPEG, 100, fos);
    Toast.makeText(this, compress?"成功":"失敗", Toast.LENGTH_SHORT).show();
    //給系統圖庫發送廣播,告訴圖庫我在sdcard上保存了文件,請求添加到你的預覽圖中
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
//此處也可以設置掛載內存卡的事件,但4.4後安卓系統在不兼容,只能系統自己內部自己調用.
    intent.setData(Uri.fromFile(file));
    sendBroadcast(intent);
  }
  public void clear(View view){
    bitmap = null;
    iv.setImageBitmap(bitmap);
  }
}


獲取屏幕的寬高

5. 實例:撕衣服遊戲

01 - 獲取屏幕的寬高

//事先已在XML定義好了全景的背景圖..
public class MainActivity extends Activity {
  private ImageView iv;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    iv = (ImageView) findViewById(R.id.iv);
    // 重新在內存中創建一張空白的紙Bitmap,然後將up.jpg繪製到這張紙上
    // 獲取屏幕的寬和高
    Display display = getWindowManager().getDefaultDisplay();
    int width = display.getWidth();
    int height = display.getHeight();
    //獲取屏幕寬高的第二種方式:
    // Point outSize = new Point();
    // display.getSize(outSize);
    // outSize.x;outSize.y
    //這是上面的那張圖片的位圖,原圖是不能夠修改的,只有創建他的位圖的副本才能夠修改.
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
    // 192 288 288 432
    // 由於這個bitmap是來自本地的資源文件,因此該bitmap不能修改,只能讀.
    // bitmap.setPixel(20, 20, Color.TRANSPARENT);
    // 在內存中創建一張空白的bitmap纔是可以被修改的
    final Bitmap newbitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
    Canvas canvas = new Canvas(newbitmap);
    Matrix matrix = new Matrix();// 默認就是單位矩陣
//放大該圖片,該圖片的真實大小不能夠佈滿整個屏幕
    float[] values = { (width + 0f) / bitmap.getWidth(), 0, 0, 0, (height + 0f) / bitmap.getHeight(), 0, 0, 0, 1
    };
    matrix.setValues(values);
    canvas.drawBitmap(bitmap, matrix, null);
    iv.setImageBitmap(newbitmap);
    // 給ImageView設置手機滑動的監聽
    iv.setOnTouchListener(new OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
        // 獲取到當前觸摸到的座標,建議使用getRawX();
        int x = (int) event.getX();
        int y = (int) event.getY();
        int startX = x - 5;
        int endX = x + 5;
        int startY = y - 5;
        int endY = y + 5;
        for (int i = startX; i < endX; i++) {
          for (int j = startY; j < endY; j++) {
            // 設置像素點不會越界的條件
            if (i > 0 && i < 480 && j > 0 && j < 480) {
             // 將newbitmap對應的(x,y)的像素設置爲透明的
             newbitmap.setPixel(i, j, Color.TRANSPARENT);
            }
          }
        }
        // 重新將修改後的newbitmap設置給ImageView
        iv.setImageBitmap(newbitmap);
        return true;
      }
    });
  }
}

2. ImageView(原生)

3. SmartImageView(廢棄)

4. Glide(Google)

Glide.with(this).load("http://h.hiphotos.baidu.com/image/pic/item/0ff41bd5ad6eddc49e5987f53bdbb6fd52663305.jpg")
         .crossFade(5000)
         .skipMemoryCache(true)//不使用內存緩存
         .diskCacheStrategy(DiskCacheStrategy.ALL)
         .placeholder(R.drawable.ic_launcher)
         .error(R.drawable.error)
         .into(iv);

5. Picasso(Square)

6. Fresco(FaceBooK)

7. Universal ImageLoader(UIL)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章