I'm trying to get an image stored as BLOB data in an SQLite database into an Imageview used in a row for a list activity.
This is my code for the two methods I employ to pull regular text data:
private void fillData() {
// TODO Auto-generated method stub
String[] from = new String[] { BorrowMeTable.COLUMN_NAME, BorrowMeTable.COLUMN_DATE };
int[] to = new int[] { R.id.people_list_name, R.id.people_list_borrowed };
getLoaderManager().initLoader(0, null, this);
adapter = new SimpleCursorAdapter(this, R.layout.people_row, null, from,
to, 0);
setListAdapter(adapter);
}
// -----------------------------------------------------------
#Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
BorrowMeContentProvider.distinctSwitch = true;
String[] projection = { BorrowMeTable.COLUMN_ID, BorrowMeTable.COLUMN_NAME, BorrowMeTable.COLUMN_DATE };
CursorLoader cursorLoader = new CursorLoader(this,
BorrowMeContentProvider.CONTENT_URI, projection, null, null, null);
return cursorLoader;
}
I have another column, BorrowMeTable.COLUMN_IMAGE that I would like to load into my imageView (R.id.pic_of_image). I can't add it to my projection as it cannot be converted to a string. To pull it using a single cursor I would use the code:
byte[] imageByteArray = databaseCursor.getBlob(databaseCursor
.getColumnIndex(BorrowMeTable.COLUMN_IMAGE));
ByteArrayInputStream imageStream = new ByteArrayInputStream(
imageByteArray);
bmp = BitmapFactory.decodeStream(imageStream);
window.setImageBitmap(bmp);
As I have done in another part of my program. Can anyone help as to how I would make this work?
Thanks!
I have another column, BorrowMeTable.COLUMN_IMAGE that I would like to
load into my imageView (R.id.pic_of_image). I can't add it to my
projection as it cannot be converted to a string.
Why do you think so?
If you store images in your database as BLOB data, then you may bravely retrieve them from the DB using their column name in the query projection and after getting the cursor obtain them using Cursor.getBlob(int) method.
You also don't need to input gotten byte array to any byte stream to decode it to a bitmap, because BitmapFactory has decodeByteArray(byte[], int, int) method which allows to decode a byte array to bitmap directly.
The only one thing you should care about is the memory consumption which goes in act when you decode your raw byte arrays to bitmaps.
To work with bitmaps correctly, read this lessons for better explanation.
Related
I've been struggling for a while now with this, and i want to be able to store an image to my database. I know storing an image to a database directly is bad practice but i simply do not know enough to be able to do it another way.
So, i'm currently stuck with a few issues.
Firstly, I'm not even sure my path is correct; i want to get a drawable file and store it to my database and there must be an easier way than doing a path straight from the C drive right?
Secondly, I don't know much about this but i need to convert my file to a bitmap so that it can be converted to a byte array? And i'm not sure how to do this exactly.
I've tried several things, wrote this code out about 10 times already in different ways and not getting anywhere. Thanks all for help in advance.
public void insertAvatar(String Email, byte[] head) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
String sql = "INSERT INTO Avatar VALUES (?, ?)";
File head = new File("C:\\Users\\PC\\Desktop\\capaa\\src\\main\\res\\drawable\\head2.png");
Bitmap imageToStoreBitmap = head; // doesn't work as my file isnt a bitmap yet
objectByteArrayOutputStream = new ByteArrayOutputStream();
imageToStoreBitmap.compress(Bitmap.CompressFormat.JPEG, 100, objectByteArrayOutputStream);
imageInBytes = objectByteArrayOutputStream.toByteArray();
contentValues.put("Email", Email);
contentValues.put("head", imageInBytes);
long checkIfQueryRuns = db.insert("Avatar", null, contentValues );
}
You need to use Blob to store images in your SQLite database.
Create a table to store the images
CREATE TABLE " + DB_TABLE_NAME + "("+
KEY_NAME + " TEXT," +
KEY_IMAGE + " BLOB);";
To store an image in the table
public void addImage( String name, byte[] image) throws SQLiteException{
ContentValues cv = new ContentValues();
cv.put(KEY_NAME, name);
cv.put(KEY_IMAGE, image);
database.insert( DB_TABLE_NAME, null, cv );
}
As you can see before inserting the image to the table, you need to convert the bitmap to a byte array.
// To convert from bitmap to byte array
public static byte[] getImageBytes(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0, stream);
return stream.toByteArray();
}
To retrieve image from database
//search your image using the key and get the cursor
............
byte[] image = cursor.getBlob(1);
............
As you can see the image returned is in a byte array. Now you can convert this byte array to bitmap to use in your app.
//To convert from byte array to bitmap
public static Bitmap getImage(byte[] image) {
return BitmapFactory.decodeByteArray(image, 0, image.length);
}
Having written the answer, I myself is not a big fan of storing images in the database. I am not sure what is your need for storing the images but you can check the following libraries to handle images in your app.
https://github.com/bumptech/glide/
https://square.github.io/picasso/
https://github.com/nostra13/Android-Universal-Image-Loader
I am coding an android app using android studio - java , I am facing a problem when picking more than 10 images from gallery and inserting them into Sqlitedatabase table , when inserting the 10th image it takes much longer time than the last 9 images , and when selecting all the images (10) from the table the app crashes with errors
E/SQLiteCursor: onMove() return false. RequiredPos: 9 WindowStartPos: 9 WindowRowCount: 0(original count of query: 10)
Caused by: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 10
Code
Picking and inserting images code
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode== 1 && resultCode == RESULT_OK) {
try {
ClipData clipData = data.getClipData();
if (clipData == null)
return;
for (int i = 0; i < clipData.getItemCount(); i++) {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), clipData.getItemAt(i).getUri());
byte[] myImg = getBitmapAsByteArray(bitmap);
DatabaseHelper databaseHelper = new DatabaseHelper(this);
SQLiteDatabase db = databaseHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("myImage",myImg);
db.insert("myTable",null,contentValues);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
getBitmapAsByteArray()
private static byte[] getBitmapAsByteArray(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, outputStream);
return outputStream.toByteArray();
}
Selecting images from database
public void showImages(View view) {
DatabaseHelper databaseHelper = new DatabaseHelper(this);
SQLiteDatabase db = databaseHelper.getReadableDatabase();
Cursor cursor = db.rawQuery("select * from myTable",null);
cursor.moveToFirst();
Toast.makeText(this, ""+cursor.getCount(), Toast.LENGTH_SHORT).show();
ArrayList<Bitmap> bitmaps = new ArrayList<>();
if (cursor.getCount()>0)
while (!cursor.isAfterLast())
{
bitmaps.add(BitmapFactory.decodeByteArray(cursor.getBlob(0), 0, cursor.getBlob(0).length));
cursor.moveToNext();
}
ViewPagerAdapter adapter = new ViewPagerAdapter(this,bitmaps);
viewPager.setAdapter(adapter);
viewPager.setCurrentItem(0);
cursor.close();
}
any suggestions ?
Not sure about the code, but i would not store image directly in Database. Image can be really huge, it might take some time to write and read multiple images.
Instead, like what backend developers do, i would store image as File on Filesystem (app private directory). They will be deleted when app is deleted. Save the images as Files and store their path or name into DB. So whenever you need image, just do:
List<String> getImageNamesFromDb()
List<File> getImageFiles(List<String>)
processYourImageFiles(List<File>)
It is an index out of bound exception.
Your loop is going in negative , you are accessing a row at index -1 which does not exist.
Try errors in your loop.
Please give your code of java file.
It might help more for finding more errors.
I am working on Android development where once I get byte array from Google Glass frame, I am trying to scan array using Zxing library and trying to detect 1d barcode(UPC code).
I have tried this code snippet.
BufferedImage image = ImageIO.read(game);
BufferedImageLuminanceSource bils = new BufferedImageLuminanceSource(image);
HybridBinarizer hb = new HybridBinarizer(bils);
BitMatrix bm = **hb.getBlackMatrix();**
MultiDetector detector = new MultiDetector(bm);
DetectorResult dResult = detector.detect();
if(dResult == null)
{
System.out.println("Image does not contain any barcode");
}
else
{
BitMatrix QRImageData = dResult.getBits();
Decoder decoder = new Decoder();
DecoderResult decoderResult = decoder.decode(QRImageData);
String QRString = decoderResult.getText();
System.out.println(QRString);
}
It works fine for QRcode, detects and decodes QR code well. But does not detect UPC code.
I also tried this code snippet,
InputStream barCodeInputStream = new FileInputStream(game);
BufferedImage barCodeBufferedImage = ImageIO.read(barCodeInputStream);
BufferedImage image = ImageIO.read(game);
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new GlobalHistogramBinarizer(source));
RSSExpandedReader rssExpandedReader = new RSSExpandedReader();
int rowNumber = bitmap.getHeight()/2;
BitArray row = **bitmap.getBlackRow(0, null);**
Result theResult = rssExpandedReader.decodeRow(rowNumber, row, new Hashtable());
and in both I am getting "Exception in thread "main" com.google.zxing.NotFoundException".
Does anyone know how to fix this issue?
getBlackMatrix() -
Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or may not apply sharpening. Therefore, a row from this matrix may not be identical to one fetched using getBlackRow(), so don't mix and match between them.
getBlackRow()-
Converts one row of luminance data to 1 bit data. May actually do the conversion, or return cached data. Callers should assume this method is expensive and call it as seldom as possible. This method is intended for decoding 1D barcodes and may choose to apply sharpening.
I have an Array of java.lang.Bytes[] in Android and I want to save it to a SQLLite table into a BLOB column.
I created the table and columns etc. I am unsure of how to save the Array as a BLOB as is.
public void AddUpdateKeys(int deviceID, String key, Boolean learned, Byte[] rawKey)
{
... // other code
ContentValues cv = new ContentValues();
cv.put(colKeyDevID, deviceID);
cv.put(colKeyLearned, key);
cv.put(colKeyLearned, learned ? 1 : 0 );
cv.put(colKeyData, rawKey); <-- Here is the issue, how to convert Type Byte[] to byte[]
How do I convert the Raw data that is in java.lang.Byte[] to byte[], I have tried
private byte[] getBytes(Byte[] learnedKey) {
byte[] result = new byte[learnedKey.length];
for(int i=0; i<learnedKey.length; i++){
result[i] = learnedKey[i].byteValue();
}
return result;
}
But is just "crashes", I also checked the the rawKey contains data? I am new to Android SQLLite Java. I want to Save the raw data of Byte[] into a Blob and read it back later and use it again.
actually An SQL BLOB type stores a large array of binary data (bytes) as the value in a column of a database.
so use column value type should specified as blob over table.and then save your byte[] into that.you should have to follow these steps over there(exm. image):
1-convert image to bitmap.
2-convert bitmap to Byte array.
public static byte[] getBytesFromBitmap(Bitmap bitmap) {
if (bitmap!=null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, stream);
return stream.toByteArray();
}
return null;
}
3-make column type as blob.
4-save this byte array to that column.
I have to convert a byte to Bitmap and i set it to imageview
i do have methode that convert Bitmap in ImageView into Byte and i insert it later,
public static byte[] ConvertDrawableToByteArray(Drawable drawableResource) {
Bitmap imageBitmap = ((BitmapDrawable) drawableResource).getBitmap();
ByteArrayOutputStream imageByteStream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageByteStream);
byte[] imageByteData = imageByteStream.toByteArray();
return imageByteData;
}
and when i want to retrieve image from database and show it in an ImageView i do
//--
byte[] image_b = c.getBlob(4);
Bitmap b = BitmapFactory.decodeByteArray(image_b, 0, image_b.length);
img.setImageBitmap(b);
but it return nothing
what is wrong, please help
Thanks a lot
I guess it's because the cursor didn't return anything. Maybe the Blob is too big to be queried in one time because android cursor limit is 1 mb per query please check again your stacktrace/logcat and if the blob size is the problem you can try to split the byte to smaller size and store it in your database
You can play around with the following and let us know if it works:
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = resolver.query(imageUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
return BitmapFactory.decodeFile(picturePath);
I dont understand where is the problèlme i do likee this :String t = image_b.toString(); System.out.println("what it give me" +t); and i find in the logcat this line : 03-19 17:01:28.167: I/System.out(1019): what it give me[B#41f1f5c0
is that mean it return something but dont showin or is the byte [B#41f1f5c0 is not correct