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
Related
I'm working on a database application in which I'm inserting images into a database. I'm storing the InputStreams in the database as a BLOB, and I am having issues retrieving them and setting them to an ImageIcon.
try{
// Return a resultset That contains
// the photos from the hashtags the user is following.
preparedStatement = conn.prepareStatement("SELECT * FROM PHOTOS WHERE CARID=?");
preparedStatement.setInt(1, 1);
resultSet = preparedStatement.executeQuery();
while(resultSet.next()){
newPhoto = new Photo(resultSet.getInt(1), resultSet.getInt(2),
resultSet.getLong(3), resultSet.getBinaryStream(4));
System.out.println(resultSet.getBinaryStream(4));
photos.add(newPhoto);
System.out.println("Retrieving a photo");
}
}
photos is an ArrayList using my Photo class, which I am returning. Every time I try to display the images, I am getting the following error...
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at business.appdev.Home.paintEditFrame(Home.java:577)
which is coming from the following code..
editImageLabel[i].setIcon(
new ImageIcon(img.getScaledInstance(imageSize, imageSize, imageSize)));
I have some basic println commands that are showing me what's returning from the MySQL database, which is
java.io.ByteArrayInputStream#2c0213a5
Retrieving a photo
java.io.ByteArrayInputStream#252ab7be
Retrieving a photo
where img is a BufferedImage. Any help would be greatly appreciated, Thanks!
Code for handling of the InputStream returned from the resultSet
for(int i = 0; i < photos.size(); i++){
img = ImageIO.read(photos.get(i).getInputStream());
editImageLabel[i] = new JLabel("");
editImageLabel[i].setIcon(new ImageIcon(img.getScaledInstance(imageSize, imageSize, imageSize)));
updated Photo class with byte[] data
Based on some other posts I've read, I'm storing the byte[] into a varbinary in MySQL. After that, I grab the photo data from my database using
InputStream in = resultSet.getBinaryStream(4);
byte[] photoData = new byte[(int) resultSet.getLong(3)];
ByteArrayOutputStream os = new ByteArrayOutputStream();
for (int len; (len = in.read(photoData)) != -1;)
os.write(photoData, 0, len);
os.flush();
I then create my photo object and return an ArrayList of photos. This has eliminated the NullPointerException, but I now cannot get the ImageIcon JLabels to show up. I use the following code to add them to a JPanel,
InputStream in = new ByteArrayInputStream(photos.get(i).getData());
BufferedImage newImage = ImageIO.read(in);
editImageLabel[i] = new JLabel("");
editImageLabel[i].setIcon(new ImageIcon(newImage.getScaledInstance(imageSize, imageSize, Image.SCALE_DEFAULT)));
and then I place the Label onto the JPanel.
Avoid the trouble of encoding and decoding images by storing the image in the filesystem and just the path to the image in your database. This can help to keep your database size down which, in turn, can help your transactional efficiency. You can write up some quick code to make a numeric filename for the file on your server.
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'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.
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
I have stored some images in database, while retrieving them i want to resize it to 177x122. How can i do that in JAVA?
Here is some code that i have used to retrieve image from database, what changes need to be done to get a image of 177x122.
PreparedStatement pstm1 = con.prepareStatement("select * from image");
ResultSet rs1 = pstm1.executeQuery();
while(rs1.next()) {
InputStream fis1;
FileOutputStream fos;
String image_id;
try {
fis1 = rs1.getBinaryStream("image");
image_id=rs1.getString("image_id");
fos = new FileOutputStream(new File("images" + (image_id) + ".jpg"));
int c;
while ((c = fis1.read()) != -1) {
fos.write(c);
}
fis1.close();
fos.close();
JOptionPane.showMessageDialog(null, "Image Successfully Retrieved");
} catch (Exception ex) {
System.out.println(ex);
}
}
You can use the AWT provided BufferedImage and Graphics2D classes to resize your images. Source
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
Assuming the data in the image column is a image format that the Java Image I/O can read (such as JPEG and PNG), the Thumbnailator library should be able to achieve this.
The code which would retrieve the image data from the ResultSet as an InputStream and write to specified file can be written like this:
// Get the information we need from the database.
String imageId = rs1.getString("image_id");
InputStream is = rs1.getBinaryStream("image");
// Perform the thumbnail generation.
// You may want to substitute variables for the hard-coded 177 and 122.
Thumbnails.of(is)
.size(177, 122)
.toFile("images" + (imageId) + ".jpg");
// Thumbnailator does not automatically close InputStreams
// (which is actually a good thing!), so we'll have to close it.
is.close();
(I should disclaim that I haven't actually run this code against an actual database.)
Thumbnailator will read the image data from the InputStream retrieving binary data from the image column, then resize the image to fit into the 172 x 122 region, and finally output the thumbnail as a JPEG to the specified file.
By default, Thumbnailator will preserve the aspect ratio of the original image when resizing images (to prevent the thumbnail from looking distorted), so the image size will not necessarily be 172 x 122. If this behavior is undesirable, calling the forceSize method instead of the size method can achieve that.
Disclaimer: I maintain the Thumbnailator library.