How to Store(Bitmap Image) and Retrieve Image from SQLite Database in Android

How to store(bitmap image) and retrieve image from sqlite database in android?

Setting Up the database

public class DatabaseHelper extends SQLiteOpenHelper {
// Database Version
private static final int DATABASE_VERSION = 1;

// Database Name
private static final String DATABASE_NAME = "database_name";

// Table Names
private static final String DB_TABLE = "table_image";

// column names
private static final String KEY_NAME = "image_name";
private static final String KEY_IMAGE = "image_data";

// Table create statement
private static final String CREATE_TABLE_IMAGE = "CREATE TABLE " + DB_TABLE + "("+
KEY_NAME + " TEXT," +
KEY_IMAGE + " BLOB);";

public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {

// creating table
db.execSQL(CREATE_TABLE_IMAGE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// on upgrade drop older tables
db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);

// create new table
onCreate(db);
}
}

Insert in the Database:

public void addEntry( String name, byte[] image) throws SQLiteException{
SQLiteDatabase database = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(KEY_NAME, name);
cv.put(KEY_IMAGE, image);
database.insert( DB_TABLE, null, cv );
}

Retrieving data:

 byte[] image = cursor.getBlob(1);

Note:

  1. Before inserting into database, you need to convert your Bitmap image into byte array first then apply it using database query.
  2. When retrieving from database, you certainly have a byte array of image, what you need to do is to convert byte array back to original image. So, you have to make use of BitmapFactory to decode.

Below is an Utility class which I hope could help you:

public class DbBitmapUtility {

// convert from bitmap to byte array
public static byte[] getBytes(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0, stream);
return stream.toByteArray();
}

// convert from byte array to bitmap
public static Bitmap getImage(byte[] image) {
return BitmapFactory.decodeByteArray(image, 0, image.length);
}
}


Further reading

If you are not familiar how to insert and retrieve into a database, go through this tutorial.

How to store and get image into/from a SQLite database android

Modify your method:

private void getUserInformation(){
Cursor data = databaseHelper.getUserInformation();

if(data.moveToFirst()) {
byte[] btyeArray = data.getBlob(2);
if(btyeArray != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(btyeArray , 0, btyeArray .length);
if(bitmap != null) {
mProfilePhoto.setImageBitmap(bitmap);
photo = bitmap;
}else
mProfilePhoto.setImageResource(R.drawable.defaultImage); // set your default Image here
} else {
mProfilePhoto.setImageResource(R.drawable.defaultImage); // set your default Image here
}
mProfileName = data.getString(1);

}
data.close();
}

in onActivityResult Bitmap photo define it as a global variable. and while calling addUserInformation send photo variable.

  case R.id.saveProfileButton:
//need to pass a bitmap insted of null
addUserInformation(name, photo);

Modify your DatabaseHelper method

public boolean addUserInformation(String username, Bitmap picture){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("USERNAME", username);
if(picture != null) {
byte[] data = getBitmapAsByteArray(picture);
values.put("PICTURE", data);
}
long id = db.insert(TABLE_NAME1, null, values);
db.close();
if(id == -1)
return false;
else
return true;

}

How to store image in SQLite database

You have to use "blob" to store image.

ex: to store a image in to db:

public void insertImg(int id , Bitmap img ) {   


byte[] data = getBitmapAsByteArray(img); // this is a function

insertStatement_logo.bindLong(1, id);
insertStatement_logo.bindBlob(2, data);

insertStatement_logo.executeInsert();
insertStatement_logo.clearBindings() ;

}

public static byte[] getBitmapAsByteArray(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0, outputStream);
return outputStream.toByteArray();
}

To retrieve a image from db:

public Bitmap getImage(int i){

String qu = "select img from table where feedid=" + i ;
Cursor cur = db.rawQuery(qu, null);

if (cur.moveToFirst()){
byte[] imgByte = cur.getBlob(0);
cur.close();
return BitmapFactory.decodeByteArray(imgByte, 0, imgByte.length);
}
if (cur != null && !cur.isClosed()) {
cur.close();
}

return null;
}

How to save bitmap from ImageView to database sqlite?

Convert Bitmap-->Byte array and then insert Byte array into DB,

Bitmap b = BitmapFactory.decodeResource(getResources(),
R.drawable.kitkat);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] img = bos.toByteArray();

ContentValues values = new ContentValues();
values.put("image", img);
SQLiteDatabase database = null;
try {
database = dbHelper.opendatabase();
database.insert("android_version", null, values);
} catch (Exception e) {
e.printStackTrace();
} finally {
database.close();
}

how to store a images and retrieve from sqlite database using bitmap or from drawable folder

Get bitmap from ImageView:

Bitmap bitmap = ((BitmapDrawable)ivImage.getDrawable()).getBitmap();

If you have bitmap of your image then go with this one:

Save in database:

public void insertImg(Bitmap img) {
byte[] data = getBitmapAsByteArray(img); // this is a function
//Now save this byte array data as blob in database
}

public static byte[] getBitmapAsByteArray(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0, outputStream);
return outputStream.toByteArray();
}

Retrieve from database:

public Bitmap getImage() {
//fetch byte array from your query cursor
byte[] imgByte = cur.getBlob(0);
return BitmapFactory.decodeByteArray(imgByte, 0, imgByte.length);
}

Set retrieved bitmap from database to ImageView:

ivImage.setImageBitmap(getImage());

But saving images as byte array in database is not a good practice. Because saving and retrieve images as byte array may be give an issue of outOfMemory. So if you have image url which you are getting from server then save that url as a string in database and retrieve it with same column where you have saved.

Or if you have any drawable image then save that drawable image name in database and retrieve with the same.

How to insert and retrieve image from Sqlite database in Android Studio

The messsage indicates that bytes is null. The documentation for getBlob states :-

The result and whether this method throws an exception when the column
value is null or the column type is not a blob type is
implementation-defined.

As such I believe that getBlob is returning a null and therefore that the likliehood is that nulls are getting inserted.

Consider the following based upon your DatabaseHelper :-

    mDB = new DatabaseHelper(this);
mDB.addData("Test001", "Test001", "email", "password", "xxc", null);
mDB.addData("Test002", "Test002", "email", "password", "xxc", new byte[]{0});
Cursor csr = mDB.getData();
DatabaseUtils.dumpCursor(csr);

while (csr.moveToNext()) {
bytes = csr.getBlob(6);
if (bytes == null) {
Log.d("OUCH", "Row " + String.valueOf(csr.getPosition()) + " is null");
} else {
Log.d("OK", "Row " + String.valueOf(csr.getPosition()) + " has byte array of length " + bytes.length);
}
Log.d("REPLICATE"," byte array length is " + bytes.length);
}

This adds two rows the first with null as the byte[] (image), the second has a valid albeit it short byte[].

The rows are inserted without issue.

The Data is extract without issue.

However the log will contain the following :-

2019-01-09 14:15:31.622 2783-2783/ptfc.populatetablefromcursor D/mydb: adding : Test001 TO mytable
2019-01-09 14:15:31.623 2783-2783/ptfc.populatetablefromcursor D/mydb: adding : Test002 TO mytable
2019-01-09 14:15:31.624 2783-2783/ptfc.populatetablefromcursor I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@453edcd
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: 0 {
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: ID=1
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: fn=Test001
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: ln=Test001
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: e_m=email
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: pass=password
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: mobnum=xxc
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: image=null
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: }
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: 1 {
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: ID=2
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: fn=Test002
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: ln=Test002
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: e_m=email
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: pass=password
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: mobnum=xxc
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: image=<unprintable>
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: }
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: 2 {
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: ID=3
2019-01-09 14:15:31.626 2783-2783/ptfc.populatetablefromcursor I/System.out: fn=Test001
2019-01-09 14:15:31.627 2783-2783/ptfc.populatetablefromcursor I/System.out: ln=Test001
2019-01-09 14:15:31.627 2783-2783/ptfc.populatetablefromcursor I/System.out: e_m=email
2019-01-09 14:15:31.627 2783-2783/ptfc.populatetablefromcursor I/System.out: pass=password
2019-01-09 14:15:31.627 2783-2783/ptfc.populatetablefromcursor I/System.out: mobnum=xxc
2019-01-09 14:15:31.627 2783-2783/ptfc.populatetablefromcursor I/System.out: image=null
2019-01-09 14:15:31.627 2783-2783/ptfc.populatetablefromcursor I/System.out: }
2019-01-09 14:15:31.629 2783-2783/ptfc.populatetablefromcursor I/System.out: <<<<<
2019-01-09 14:15:31.629 2783-2783/ptfc.populatetablefromcursor D/OUCH: Row 0 is null
2019-01-09 14:15:31.630 2783-2783/ptfc.populatetablefromcursor D/AndroidRuntime: Shutting down VM
2019-01-09 14:15:31.632 2783-2783/ptfc.populatetablefromcursor E/AndroidRuntime: FATAL EXCEPTION: main
Process: ptfc.populatetablefromcursor, PID: 2783
java.lang.RuntimeException: Unable to start activity ComponentInfo{ptfc.populatetablefromcursor/ptfc.populatetablefromcursor.MainActivity}: java.lang.NullPointerException: Attempt to get length of null array
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2914)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3049)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6680)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException: Attempt to get length of null array
at ptfc.populatetablefromcursor.MainActivity.onCreate(MainActivity.java:40)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2894)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3049) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1809) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:193) 
at android.app.ActivityThread.main(ActivityThread.java:6680) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

The stackTrace is similar. showing that bytes.length results in the failure if a null is inserted.

There are many ways this could be fixed for example you could set the image column to have a DEFAULT value along with skipping the cv.put if the ProfileImage passed to the addData method is null e.g.

in the Database helper change + image + " BLOB ')"; to + image + " BLOB DEFAULT X'00')";

along with the following change in the addData method :-

    if (Profileimg != null) {
cv.put(image, Profileimg);
}
  • I can't recall how this will affect the image in the listview, although I think it handles it.

However, the root cause will be that the picture taking will be returning a null.

Additionally you will likely encounter other issues if the images
themselves are large as there are limitations (1M more recently 2M)
with the size of data that a CursorWindow (used by a Cursor) can
handle exceed or get close to 2M with 1 image and an exception is
guaranteed. With 1M images a CursorWindow will hold 1 at the most if
at all so you'd expect display issues.

If images average around 100k then they can be stored in the DB and a
search could reveal the reasoning behind how SQlite can be more
efficient than a file system.

How to retrieve an image from an ImageView and store it in an Sqlite Database in Android?

SQLITE data base cannot be used to store Image files directly. However the options you have are following:

  1. Save the image that you received to SD card. May be create a separate folder in which you will store all the images. Then Create a column imagePath in your table structure and save the path of the image to this column.

    Rendering: Here you will fetch the corresponding path from the DB, check if the file Exists at that path(might have been deleted by the user), and if found, get Stream from the file write it to a bitmap and associate it to the required container.

  2. Convert the bitmap received to a BASE64 String. Store this as String to the Data Base.

    Rendering: Here you will have to convert the BASE64 back to Bitmap and associate it to the required container.



Related Topics



Leave a reply



Submit