中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

【移動開發】Android相機、相冊獲取圖片顯示并保存到SD卡

發布時間:2020-06-30 19:18:38 來源:網絡 閱讀:22006 作者:zhf651555765 欄目:開發技術

   做過類似需求的同學都知道,Activity中通過如下代碼可以啟動相機,然后在重寫的onActivityResult方法中可以獲取到返回的照片數據:

Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(openCameraIntent, TAKE_PICTURE);

    在onActivityResult方法里通過IntentgetData方法獲取的數據轉換成bitmap并顯示在界面上,有時候會有取不到數據,或者顯示的bitmap會非常小,如果將bitmap保存到sd卡后會發現,圖片的分辨率很低,并且圖片大小也是經過壓縮的,不管將相機的像素設置多高,最后通過這種方式返回的bitmap總是經過壓縮了的。如果想獲得理想的照片大小和分辨率改如何處理呢?

    大家都知道,現在手機像素少則500W800W,多則4KW(某亞),就拿常見的800W像素的相機拍出來的照片來說,分辨率大概在3200*2400左右,照片大小在2M左右。試想一下,在Android系統中bitmap占用4個字節,3200*2400*4=?,結果大家自己算算,如果為了一張圖片,耗用這么大的內存,肯定是不合理的,并且,官方文檔中有說明,Android系統分配給每個應用的最大內存是16M,所以,系統為了防止應用內存占用過大,對于在應用內通過相機拍攝的圖片最終返回來的結果進行了壓縮,壓縮后的圖片變得很小,通過之前說的getData的方式只能滿足比如顯示個頭像這樣的需求。

    如果要顯示大圖,就會出現模糊的情況。那如何獲取清晰的大圖呢?我的解決思路如下:

   1.拍照時,將拍得的照片先保存在本地,通過修改之前的代碼如下:

Uri p_w_picpathUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),"p_w_picpath.jpg"));

   //指定照片保存路徑(SD卡),p_w_picpath.jpg為一個臨時文件,每次拍照后這個圖片都會被替換  

openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, p_w_picpathUri);


如何調取相機拍照,代碼如下:

/**拍照獲取相片**/
    private void doTakePhoto() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //調用系統相機
                                   
        Uri p_w_picpathUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(),"p_w_picpath.jpg"));
        //指定照片保存路徑(SD卡),p_w_picpath.jpg為一個臨時文件,每次拍照后這個圖片都會被替換
        intent.putExtra(MediaStore.EXTRA_OUTPUT, p_w_picpathUri);
                                   
        //直接使用,沒有縮小
        startActivityForResult(intent, PHOTO_WITH_CAMERA);  //用戶點擊了從相機獲取
    }



   2.onActivityResult方法中再將圖片取出,并經過縮小處理再顯示在界面上或上傳給服務器(壓縮比例自定義)

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
            case TAKE_PICTURE:
                //將保存在本地的圖片取出并縮小后顯示在界面上
    Bitmap bitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()+"/p_w_picpath.jpg");
  Bitmap newBitmap = zoomBitmap(bitmap, bitmap.getWidth() / SCALE, bitmap.getHeight() / SCALE);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
       //由于Bitmap內存占用較大,這里需要回收內存,否則會報out of memory異常
                bitmap.recycle();
                //將處理過的圖片顯示在界面上,并保存到本地
                iv_p_w_picpath.setImageBitmap(newBitmap);
                savePhotoToSDCard(newBitmap, Environment.getExternalStorageDirectory().getAbsolutePath(), String.valueOf(System.currentTimeMillis()));
                break;
            default:
                break;
            }
        }
    }

由于Androidbitmap分配的內存最大不超過8M,所以對使用完的較大的Bitmap要釋放內存,調用其recycle()方法即可。然后將縮小后的bitmap顯示在界面上或保存到SD卡,至于之前保存的原圖,可以刪掉,也可以放在那,下次拍照時,這張原圖就會被下一張照片覆蓋,所以SD卡上使用只有一張臨時圖片,占用也不是很大。


   以上講的是拍照獲取圖片,如果是從相冊中獲取圖片又如何處理呢,我的方法如下:


1.打開相冊選取圖片:

Intent openAlbumIntent = new Intent(Intent.ACTION_GET_CONTENT);
                    openAlbumIntent.setType("p_w_picpath/*");
                    startActivityForResult(openAlbumIntent, CHOOSE_PICTURE);


2.在onActivity方法中處理獲取到的圖片,思路和之前類似

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
            case CHOOSE_PICTURE:
                ContentResolver resolver = getContentResolver();
                //照片的原始資源地址
                Uri originalUri = data.getData();
                try {
                    //使用ContentProvider通過URI獲取原始圖片
                    Bitmap photo = MediaStore.Images.Media.getBitmap(resolver, originalUri);
                    if (photo != null) {
                        //為防止原始圖片過大導致內存溢出,這里先縮小原圖顯示,然后釋放原始Bitmap占用的內存
                        Bitmap smallBitmap = zoomBitmap(photo, photo.getWidth() / SCALE, photo.getHeight() / SCALE);
                        //釋放原始圖片占用的內存,防止out of memory異常發生
                        photo.recycle();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                        iv_p_w_picpath.setImageBitmap(smallBitmap);
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
            default:
                break;
            }
        }
    }

還有一個方法 zoomBitmap(),代碼如下:

/** 縮放Bitmap圖片 **/
    public Bitmap zoomBitmap(Bitmap bitmap, int width, int height) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Matrix matrix = new Matrix();
        float scaleWidth = ((float) width / w);
        float scaleHeight = ((float) height / h);
        matrix.postScale(scaleWidth, scaleHeight);// 利用矩陣進行縮放不會造成內存溢出
        Bitmap newbmp = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
        return newbmp;
    }


至此,功能已實現。


   下面是本人項目中所實現的功能在這里總結一下:


   1.要想對從圖庫選擇的照片進行裁剪:

/**從相冊獲取圖片**/
    private Intent doPickPhotoFromGallery() {
        Intent intent = new Intent();
        intent.setType("p_w_picpath/*");  // 開啟Pictures畫面Type設定為p_w_picpath
        intent.setAction(Intent.ACTION_GET_CONTENT); //使用Intent.ACTION_GET_CONTENT這個Action
                                                                                                                                                                                                                                                                                                                                                                                                        
        //實現對圖片的裁剪,必須要設置圖片的屬性和大小
        intent.setType("p_w_picpath/*");  //獲取任意圖片類型
        intent.putExtra("crop", "true");  //滑動選中圖片區域
        intent.putExtra("aspectX", 1);  //裁剪框比例1:1
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", 300);  //輸出圖片大小
        intent.putExtra("outputY", 300);
        intent.putExtra("return-data", true);  //有返回值
                                                                                                                                                                                                                                                                                                                                                                                                        
        return intent;
    }

   調用此方法處:

Intent intent2 = doPickPhotoFromGallery();
startActivityForResult(intent2, PHOTO_WITH_DATA);

ActivityForResult中和上面一樣


   2.項目中要拍多少張 就保存多少張,顯示圖片列表:

   A.將拍照的照片或者圖庫選擇的圖片,保存到本地

創建圖片名,不能重復哦!

/** 為圖片創建不同的名稱用于保存,避免覆蓋 **/
public static String createFileName() {
    String fileName = "";
    Date date = new Date(System.currentTimeMillis()); // 系統當前時間
    SimpleDateFormat dateFormat = new SimpleDateFormat(
            "'IMG'_yyyyMMdd_HHmmss");
    fileName = dateFormat.format(date) + ".jpg";
    return fileName;
}

保存圖片到SD卡

/**Save p_w_picpath to the SD card**/
    public static void savePhotoToSDCard(String path, String photoName,
            Bitmap photoBitmap) {
        if (android.os.Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED)) {
            File dir = new File(path);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            File photoFile = new File(path, photoName); //在指定路徑下創建文件
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream(photoFile);
                if (photoBitmap != null) {
                    if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100,
                            fileOutputStream)) {
                        fileOutputStream.flush();
                    }
                }
            } catch (FileNotFoundException e) {
                photoFile.delete();
                e.printStackTrace();
            } catch (IOException e) {
                photoFile.delete();
                e.printStackTrace();
            } finally {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

 B.最后就是顯示圖片列表,因為我們要用到listView,自然少不了Adapter了,我們將保存到SD卡上的圖片名獲取到集合中,在自定義的適配器中根據名字加載圖片嘍!

   自定義圖片列表適配器代碼:

/**
 * 插入圖片列表適配器
 * @author ZHF
 *
 */
public class ImagesListAdapter extends BaseAdapter {
                                                                                                     
    private Context context;
    private List<String> p_w_picpathsList; //各個圖片的路徑
                                                                                                     
    public ImagesListAdapter(Context context, List<String> p_w_picpathsList) {
        this.context = context;
        this.p_w_picpathsList = p_w_picpathsList;
    }
                                                                                                     
    /**得到總的數量**/
    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return p_w_picpathsList.size();
    }
    /**根據ListView位置返回View**/
    @Override
    public Object getItem(int position) {
        return p_w_picpathsList.get(position);  //返回當前選中的item圖片的路徑
    }
    /**根據ListView位置得到List中的ID**/
    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;  //返回當前選中項的Id
    }
    /**根據位置得到View對象**/
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
                                                                                                         
        if(convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.newwrite_p_w_picpath_item, null);
        }
                                                                                                         
        ImageView img = (ImageView) convertView.findViewById(R.id.newwrite_et_content_p_w_picpath);  //圖片列表項
                                                                                                         
        if(!p_w_picpathsList.get(position).equals("")) {//沒有圖片
            Bitmap tempBitmap = BitmapFactory.decodeFile(p_w_picpathsList.get(position));//根據路徑顯示對應的圖片
            Bitmap newBitmap = new ImageManager(context).zoomBitmap(tempBitmap, tempBitmap.getWidth(), tempBitmap.getHeight() / 3);
            img.setImageBitmap(newBitmap);//對應的行上顯示對應的圖片
        }
        return convertView;
    }
}

   ok!完了,在顯示圖片的時候大家可能會碰到OOM(OutOfMemory)異常,在下一篇博客中我會具體解決了一下~



Demo已上傳!下載附件即可!










向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

永川市| 忻州市| 稷山县| 奉化市| 英德市| 贡嘎县| 应城市| 永顺县| 安泽县| 温宿县| 宜春市| 图木舒克市| 茌平县| 盘山县| 洛宁县| 习水县| 巴马| 大城县| 桐庐县| 灵石县| 吉林省| 余干县| 汝阳县| 泰兴市| 黎城县| 阜南县| 平舆县| 丽水市| 扎兰屯市| 浠水县| 土默特右旗| 余姚市| 临泉县| 遵化市| 丘北县| 漯河市| 顺平县| 武汉市| 麦盖提县| 安义县| 弥渡县|