Himanshu Shekher Jha
Himanshu Shekher Jha

Reputation: 1344

android Room fetch blob image and show

I am using Room persistent library to store image in the format of Blob.

@Entity(tableName = AppConstants.TABLE_OBSERVATIONS_IMAGE)
public class ImageModel {

    @ColumnInfo(typeAffinity = ColumnInfo.BLOB)
    public byte[] image;

    public ImageModel() {
    }

    @Ignore
    public ImageModel(  byte[] image ) {
         this.image = image;
        }

   public byte[] getImage() {
        return image;
    }

    public void setImage(byte[] image) {
        this.image = image;
    }

}

Now i want to fetch it and show it in image view. But it is giving exception. i am using following code to show image, where model.getImage() is image that i have stored. But it is returning null bitmap and causing app crash.

ImageModel model = observationModelArrayList.get(position).getImageModels().get(i);
ImageView image = new ImageView(context);
image.setLayoutParams(new android.view.ViewGroup.LayoutParams(100, 100));
image.setMaxHeight(100);
image.setMaxWidth(100);

Bitmap bmp = BitmapFactory.decodeByteArray(model.getImage(), 0, model.getImage().length);
//ImageView image = (ImageView) findViewById(R.id.imageView1);

image.setImageBitmap(Bitmap.createScaledBitmap(bmp, image.getWidth(), image.getHeight(), false));

// Adds the view to the layout
holder.llayImages.addView(image);

Please help.

Upvotes: 0

Views: 5600

Answers (2)

Jesús Barrera
Jesús Barrera

Reputation: 459

For Room, in kotlin, adding the following type converter to my database worked for me:

class DataConverters {

  @TypeConverter
  fun fromBitmap(bitmap: Bitmap?): ByteArray {
      return if (bitmap != null) {
          val size = bitmap.byteCount
          val buffer = ByteBuffer.allocate(size)
          bitmap.copyPixelsToBuffer(buffer)
          buffer.rewind()
          ByteArray(size).apply {
            buffer.get(this)
            shortIntToBytesPair(bitmap.width).let {
                this[0] = it.first
                this[1] = it.second
            }
            shortIntToBytesPair(bitmap.height).let {
                this[2] = it.first
                this[3] = it.second
            }
            shortIntToBytesPair(bitmap.density).let {
                this[4] = it.first
                this[5] = it.second
            }
        }
      } else {
        byteArrayOf()
      } 
  }

  @TypeConverter
  fun toBitmap(bytes: ByteArray): Bitmap? {
      return if (bytes.isNotEmpty()) {
        val width = bytesPairToShortInt(bytes[0], bytes[1])
        val height = bytesPairToShortInt(bytes[2], bytes[3])
        val density = bytesPairToShortInt(bytes[4], bytes[5])
        Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
            this.density = density
            val buffer = ByteBuffer.wrap(bytes)
            this.copyPixelsFromBuffer(buffer)
        }
      } else {
        null
      }
  }

  private fun shortIntToBytesPair(value: Int): Pair<Byte, Byte> {
    return ((value ushr 8) and 0x000000FF).toByte() to (value and 0x000000FF).toByte()
  }

  private fun bytesPairToShortInt(high: Byte, low: Byte): Int {
      return ((high.toInt() and 0x000000FF) shl 8) + (low.toInt() and 0x000000FF)
  }
}

Upvotes: 1

Virendra Varma
Virendra Varma

Reputation: 935

You can store the image in internal storage for that it didn't require the storage permission to load the image you can use

private void loadImage(String path){
  try {
    File file = new File(path, "profile.jpg");
    Bitmap b = BitmapFactory.decodeStream(new FileInputStream(file));
        ImageView img=(ImageView)findViewById(R.id.imgPicker);
    img.setImageBitmap(b); // it will display the image in imageview
    String file_path = saveToInternalStorage(b); // store this file_path in db 
  } catch (FileNotFoundException e) {
    e.printStackTrace();
  }
}

for loading the image from the server you can use the glide library like this

GlideApp.with(context)
    .asBitmap()
    .load(url)
    .into(new SimpleTarget<Bitmap>() {
      @Override public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
        String file_path = saveToInternalStorage(resource);  // store the bitmap
        // save this file_path to your db
      }
    });

for saving the image you can use this method

private String saveToInternalStorage(Bitmap bitmapImage){
    ContextWrapper cw = new ContextWrapper(getApplicationContext());
     // path to /data/data/yourapp/app_data/imageDir
    File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
    // Create imageDir
    File mypath=new File(directory,"profile.jpg");

    FileOutputStream fos = null;
    try {           
        fos = new FileOutputStream(mypath);
   // Use the compress method on the BitMap object to write image to the OutputStream
        bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
    } catch (Exception e) {
          e.printStackTrace();
    } finally {
        try {
          fos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
    } 
    return mypath.getAbsolutePath();
}

for loading bitmap, you can use glide get the bitmap from glide and use save method to store bitmap. after saving the image file in the internal storage store the path in your database hope it will help you...

Upvotes: 2

Related Questions