How to store image in SQLite database

I believe the best way of storing an image to an SQLLite database is to use the Base 64 algorithm. which converts an image to plain text and back again. You can download the full example Android project at: www.developersfound.com/Base64FromStream.zip. This program does not store the image but it does convert the image from image to text and back again. The Download link above contains the Kotlin code version of below.

Here is the class:

package com.example.TestProject;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import android.util.Log;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.FileChannel;

public class Base64CODEC {
    private int IO_BUFFER_SIZE = 64;
    //private int IO_BUFFER_SIZE = 8192;
    private URL urlObject = null;
    private URLConnection myConn = null;
    ByteArrayOutputStream os = null;

    public void Base64CODEC() {}

    public Bitmap Base64ImageFromURL(String url) {
        Bitmap bitmap = null;
        InputStream in = null;
        BufferedOutputStream out = null;

        try {
            urlObject = new URL(url);
            myConn = urlObject.openConnection();
            in = myConn.getInputStream();

            final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
            out = new BufferedOutputStream(dataStream, IO_BUFFER_SIZE);

            copyCompletely(in, out);

            final byte[] data = dataStream.toByteArray();
            BitmapFactory.Options options = new BitmapFactory.Options();

            bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);
        } catch (IOException e) {
            Log.e("TAG", "Could not load Bitmap from: " + url);
        } finally {
            //closeStream(in);
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
            //closeStream(out);
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
        }

        return bitmap;
    }

    private void copyCompletely(InputStream input, OutputStream output) throws IOException {
        // if both are file streams, use channel IO
        if ((output instanceof FileOutputStream) && (input instanceof FileInputStream)) {
            try {
                FileChannel target = ((FileOutputStream) output).getChannel();
                FileChannel source = ((FileInputStream) input).getChannel();

                source.transferTo(0, Integer.MAX_VALUE, target);

                source.close();
                target.close();

                return;
            } catch (Exception e) { /* failover to byte stream version */
            }
        }

        byte[] buf = new byte[8192];
        while (true) {
            int length = input.read(buf);
            if (length < 0)
                break;
            output.write(buf, 0, length);
        }

        try {
            input.close();
        } catch (IOException ignore) {
        }
        try {
            output.close();
        } catch (IOException ignore) {}
    }

    public String convertToBase64(Bitmap bitmap) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG,100,os);
        byte[] byteArray = os.toByteArray();
        return Base64.encodeToString(byteArray, 0);
    }

    public Bitmap convertToBitmap(String base64String) {
        byte[] decodedString = Base64.decode(base64String, Base64.DEFAULT);
        Bitmap bitmapResult = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
        return bitmapResult;
    }

}

And here is the main activity that uses the class:

package com.example.TestProject;

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends Activity implements Runnable {

    private Thread thread = null;
    private Bitmap bitmap = null;
    private Base64CODEC base64CODEC = null;
    private ImageView imgViewSource = null;
    private ImageView imgViewDestination = null;
    private boolean isSourceImageVisible = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    public void CmdLoadImage_Click(View view) {
        try {
            if(isSourceImageVisible == true) {
                imgViewSource.setImageBitmap(null);
                imgViewDestination.setImageBitmap(null);
                isSourceImageVisible = false;
            }
            else {
                base64CODEC = new Base64CODEC();
                thread = new Thread(this);
                thread.start();
            }
        }
        catch (NullPointerException e) {}

    }

    public void CmdEncodeImage_Click(View view) {
        Base64CODEC base64CODEC = new Base64CODEC();
        try {
            String base64String = base64CODEC.convertToBase64(bitmap);
            imgViewDestination = (ImageView) findViewById(R.id.imgViewDestination);
            Bitmap imgViewDestinationBitmap = base64CODEC.convertToBitmap(base64String);
            imgViewDestination.setImageBitmap(imgViewDestinationBitmap);
        }
        catch (NullPointerException e) {
            //
        }
    }

    @Override
    public void run() {
        bitmap = base64CODEC.Base64ImageFromURL("http://developersfound.com/me.png");
        handler.sendEmptyMessage(0);
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            imgViewSource = (ImageView) findViewById(R.id.imgViewSource);
            imgViewSource.setImageBitmap(bitmap);
            isSourceImageVisible = true;
            thread = null;
        }
    };

}

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;
} 

To store any image in sqlite database you need to store that image in byte array instead of string. Convert that image to byte array & store that byte [] to DB. While retrieving that image you will get byte [] convert that byte [] to bitmap by which you will get original image.


Use blob to store your image in your sqlite database. Below is an example on how to to use blob.

Setting Up the database

CREATE TABLE " + DB_TABLE + "("+ 
                   KEY_NAME + " TEXT," + 
                   KEY_IMAGE + " BLOB);";

Insert in the Database:

public void addEntry( String name, byte[] image) throws SQLiteException{
    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);
    }
}