2012-07-31

Android 手機資料庫(四) - 將圖片存入資料庫的方法

我們都知道一般照片都是放在手機的圖片資料夾下,很少會放到資料庫內

不過為了怕應用程式需要的照片不小心被刪了而讓應用程式出錯,所以

就需要把圖片存進資料庫內,這裡我就來介紹怎麼樣把照片存進資料庫和取出

注意:這部份因為有關係到資料庫,所以為了不讓程式碼太多,所以我只show出
如何取出和存入圖片的程式碼,所以對資料庫需要有一定的認識,這部份請參考
前三篇(第一篇第二篇第三篇)的介紹。


存入的程式碼
//圖片
 ImageView imageView_save = (ImageView) findViewById(R.id.img_newphoto);
               
        //imageView轉Bitmap
        //imageView_save.setDrawingCacheEnabled(true);
        //建立圖片的緩存,圖片的緩存本身就是一個Bitmap
        imageView_save.buildDrawingCache();
        //取得緩存圖片的Bitmap檔
        Bitmap bmp=imageView_save.getDrawingCache();
          
            //轉換為圖片指定大小
            //獲得圖片的寬高
            int width = bmp.getWidth();
            int height = bmp.getHeight();
            // 設置想要的大小
            int newWidth = 480;
            int newHeight = 525;
            // 計算缩放比例
            float scaleWidth = ((float) newWidth) / width;
            float scaleHeight = ((float) newHeight) / height;
            // 取得想要缩放的matrix參數
            Matrix matrix = new Matrix();
            matrix.postScale(scaleWidth, scaleHeight);
            // 得到新的圖片
            Bitmap newbm = Bitmap.createBitmap(bmp, 0, 0, width, height, matrix,true);
             
          
            // 先把 bitmap 轉成 byte
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            newbm.compress(Bitmap.CompressFormat.JPEG, 100, stream );
            byte bytes[] = stream.toByteArray();
            // Android 2.2以上才有內建Base64,其他要自已找Libary或是用Blob存入SQLite
            // 把byte變成base64
            String base64 = Base64.encodeToString(bytes, Base64.DEFAULT); 
           
            //放img進去SQLite
            ContentValues cv = new ContentValues();
            cv.put("image", base64);
           //添加方法
           long long1 = db.insert(table_name, "", cv)



取出的程式碼
//取出資料
        Cursor cursor = db.rawQuery("select * from newimg where season = '秋'", null);
        
        //用陣列存圖片,陣列大小 = 取出資料的筆數
 Drawable[] Drawablelist = new Drawable[cursor.getCount()];
 Bitmap[] bmplist = new Bitmap[cursor.getCount()];
        
        //取得資料表筆數
        int rows_num = cursor.getCount(); 
  if(rows_num != 0) {

          //將指標移至第一筆資料
   cursor.moveToFirst(); 
            
   for(int i=0; i<rows_num; i++) {
            // 把Base64變回bytes
     byte bytes[] = Base64.decode(cursor.getString(2), Base64.DEFAULT);

            //用BitmapFactory生成bitmap
     bmplist[i] = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 
       
     //轉換Bitmap為Drawable
            Drawable drawable = new BitmapDrawable(bmplist[i]);

            //存入Drawable陣列中
     Drawablelist[i]=drawable;

            //將指標移至下一筆資料
            cursor.moveToNext();  
          }
        }

        //關閉Cursor
 cursor.close(); 
        //關閉資料庫,釋放記憶體 
 dbHelper.close(); 



後記:

          在存入時我有多用了縮放圖片,而在取出時因程式需要,所以有把Bitmap

再轉換為Drawable,這個可以看個人程式上的需求去做改變,不一定要照copy

程式是死的,人是活的,希望大家都能寫出一支好的程式,感謝。

2 則留言:

  1. 你好~
    不好意思有點關於存取圖片的問題想要問你~
    就是我是用surfaceview然後依照你的方法去存進資料庫
    取出圖片用imageview
    可是取出時卻一直變成黑色的畫面
    不知道是什麼原因?

    回覆刪除
  2. 作者您好
    我想請教一下我的dataBase欄位是設定BLOB,使用以下代碼存入bitmap
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    Bitmap photos=GT.PicAngle(GT.getBitmap(uri));
    photos.compress(Bitmap.CompressFormat.JPEG, 100, stream );
    byte bytes1[] = stream.toByteArray();
    densitypic.add(bytes1);//儲存壓縮圖片至資料庫

    我也是利用cursor取資料,Log印出getCount是5,但是
    奇怪的是我都會再cursor.moveToFirst(); 或者 cursor.moveToNext();
    我有在cursor.moveToNext();包過try catch,catch下再做一次cursor.moveToNext();
    那次竟然就可以通過了,但是在抓最後一張圖是又出錯,
    最奇妙的是不是每次都出錯,我刪除資料再重新拍照,有時候可以成功取出,這個問題困繞我幾天了

    錯誤代碼是:
    Failed to read row 0, column 0 from a CursorWindow which has 0 rows, 3 columns.
    java.lang.RuntimeException: Unable to start activity ComponentInfo{tw.com.main/tw.com.main.Infodetail}:
    java.lang.IllegalStateException: Couldn't read row 0, col 0 from CursorWindow.
    Make sure the Cursor is initialized correctly before accessing data from it.

    不知道作者是否有相同經驗,或解決辦法可以不吝伺教 感謝!!

    回覆刪除

您的寶貴建議是我前進的動力!