I have an sqlite database which is written to from a service running on windows(C++). I am now trying to read from this same sqlite database which contains some blob data. I have some code as follows:
String tileQuery = "SELECT * FROM '" + layerName + "' WHERE zoom_level=?";
Cursor tileCursor = database.rawQuery(tileQuery, new String[] {zoom_level});
if( tileCursor.moveToFirst() )
{
while( !tileCursor.isAfterLast() )
{
int tileRow = tileCursor.getInt(tileCursor.getColumnIndex("tile_row"));
int tileColumn = tileCursor.getInt(tileCursor.getColumnIndex("tile_column"));
byte[] tileData = tileCursor.getBlob(tileCursor.getColumnIndex("tile_data"));
//Write tile to file
String fileName = layerName + "_" + zoom_level + "_" + tileRow + "_" + tileColumn + ".jpeg";
try {
/*
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + TILE_STORAGE_PATH + "/" + fileName));
bos.write(tileData);
bos.flush();
bos.close();
*/
ByteBuffer bb = ByteBuffer.wrap(tileData);
bb.order(ByteOrder.LITTLE_ENDIAN);
FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + TILE_STORAGE_PATH + "/" + fileName);
byte[] toWrite = new byte[bb.remaining()];
bb.get(toWrite, 0 , toWrite.length);
fos.write(toWrite);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
tileCursor.moveToNext();
}
}
As shown, I am attempting to write the blobs to disk as jpeg images. No matter what I do, the images appear to be corrupt, as in I cannot view them on any image viewer within android. The same images can be written to file on windows and viewed correctly, which made me think that it was an endianess issue(due to the fact that the blob was written to the database via a service running on windows). I have tried changing the byte order and writing to disk again, but I get the same result. Could anyone suggest what I might be doing wrong/missing. Any help is greatly appreciated.
To make this work there are a few different steps. Assuming your database connection is working and those are the correct columns you are looking in with your Cursor
(1) Convert the blob to a Bitmap. You can use the blob you get back, assuming you actually downloaded and stored it to your local database, as the byte[] you will decode.
Bitmap bm = BitmapFactory.decodeByteArray(tileData, 0 ,tileData.length);
(2) Create a new file in the approprite directory and write to that file. You can do that with something like the code below. The idea is to get the local directory
private void storeBitmap(Bitmap myBitmap){
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/your_directory_name");
String fname = "your_file_name.jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
If you want to add the images to gallery or you just want a different (and potentially easier) way to add the file, look into using MediaScanner which will add the files as though you took the picture with your camers
Related
I want to save bitmaps in the gallery.
Currently, I am using the following code:
public void saveBitmap(Bitmap output){
String filepath = Environment.getExternalStorageDirectory().toString() + "/Imverter/ImverterEffectedImage";
File dir = new File(filepath);
if(!dir.exists()){
dir.mkdir();
}
String fileName = "Imverter" + System.currentTimeMillis() + ".jpg";
File image = new File(dir, fileName);
try {
FileOutputStream fileOutputStream = new FileOutputStream(image);
output.compress(Bitmap.CompressFormat.JPEG, 80, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
It saves one single bitmap efficiently, but in my app, I have to deal with multiple bitmaps, and this method results in the slow output.
I want to store every single bitmap in a different files.
Thanks in advance.
I'm new to android and developing an app that saves large images from drawable folder to phone storage. These files have resolution of 2560x2560 and I want to save these files without loosing image quality.
I use following method to save images and it gives me Out of Memory Exception. I have seen many answers how to load a large bitmap efficiently. But I cant really find an answer for this problem.
In my code, I use
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imageId);
File file = new File(root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg");
file.createNewFile();
FileOutputStream oStream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, oStream);
oStream.close();
bitmap.recycle();
Is there anything wrong with my code? This works without any exception for smaller images.
If I use android:largeHeap="true", this does not throw any exception. But I know it is not a good practice to use android:largeHeap="true".
Is there any efficient way to save large images from drawable folder without an exception?
Thank you in advance.
If you just want to copy the image file, you shouldn't decode it into a bitmap in the first place.
You can copy a raw resource file with this for example:
InputStream in = getResources().openRawResource(imageId);
String path = root.getAbsolutePath() + "/Pictures/" + getResources().getString(R.string.app_name) + "/" + timeStamp + ".jpg";
FileOutputStream out = new FileOutputStream(path);
try {
byte[] b = new byte[4096];
int len = 0;
while ((len = in.read(b)) > 0) {
out.write(b, 0, len);
}
}
finally {
in.close();
out.close();
}
Note that you have to store your image in the res/raw/ directory instead of res/drawable/.
I am making a soundboard for practice and I want to give the user the ability to download the sound (that I have included in the app in the res/raw folder) onClick of a menu item but I can only find information about downloading from an internet url, not something that I already included in the apk.
What is the best way to do this? I would like to give them the option to save to an SD card also if this is possible. A point towards the correct class to use in the documentation would be great! I've been googling to no avail.
Thanks!
Try something like this:
public void saveResourceToFile() {
InputStream in = null;
FileOutputStream fout = null;
try {
in = getResources().openRawResource(R.raw.test);
String downloadsDirectoryPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
String filename = "myfile.mp3"
fout = new FileOutputStream(new File(downloadsDirectoryPath + filename));
final byte data[] = new byte[1024];
int count;
while ((count = in.read(data, 0, 1024)) != -1) {
fout.write(data, 0, count);
}
} finally {
if (in != null) {
in.close();
}
if (fout != null) {
fout.close();
}
}
}
I don't know about the raw but I did a similar thing in my app using the assets folder. My files are under the assets/backgrounds folder as you can probably guess from the code below.
You can modify this code and make it work for you (I know I will only have 4 files which is why I have i go from 0 to 4 but you can change this to whatever you want).
This code copies the file starting with prefix_ (like prefix_1.png, prefix_2.png, etc) to my cache directory but you can obviously change the extension, the filename or the path you would like to save the assets to.
public static void copyAssets(final Context context, final String prefix) {
for (Integer i = 0; i < 4; i++) {
String filename = prefix + "_" + i.toString() + ".png";
File f = new File(context.getCacheDir() + "/" + filename);
if (f.exists()) {
f.delete();
}
if (!f.exists())
try {
InputStream is = context.getAssets().open("backgrounds/" + filename);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
FileOutputStream fos = new FileOutputStream(f);
fos.write(buffer);
fos.close();
} catch (Exception e) {
Log.e("Exception occurred while trying to load file from assets.", e.getMessage());
}
}
}
My situation is as follows: I'm saving multiple bitmaps from an arraylist to a specific folder in my devices SD Card (with success), however, the saved file- when clicked- prompts a message from the phone, stating: "Unable to find application to perform this action." The file size of this file is proportional to that of the bitmap image being saved, so I'm a bit confused, as the device has no problems opening image files, yet cannot open (or identifiy) these as a media file.
Question: What would cause the saved image file (presuming that I have saved it correctly) to exhibit this type of behavior in a device, and how should I resolve this issue?
Extra: the thumbnail of the file is the system provided thumbnail of the two papers on top of each other. The arraylist is being passed from one activity to its current one where the method provided is supplied.
Here is the method invoking the saving of the files to the specified folder /filesdestination:
private void saveImages(){
// to retrieve bitmaps
ArrayList<Bitmap> images = getIntent().getParcelableArrayListExtra("images key");
//to retrieve bitmaps and save in specific order, while also naming them in that order
int loopVal = 0;
int postVal = 9;
while ( loopVal < 9) {
Bitmap Image = images.get(loopVal);
try {
String filedestination = new String(Environment.getExternalStorageDirectory() + "/filedestination");
String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date());
File file = new File(filedestination, postVal + ".post_order" + ".jpg" + timeStamp);
File picfile = file;
FileOutputStream fos = new FileOutputStream(picfile);
Image.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Throwable e) {
e.printStackTrace();
}
postVal--;
loopVal++;
}
}
Any insight would be appreciated,
-Lucas
i think it cannot read the file type because the timestamp is after the file extension jpg and you are also compressing it as a png, so you might want to change either or, something like this
File file = new File(filedestination, postVal + timeStamp +".post_order" + ".png");
It seems that you are saving a .jpg file compressed as a PNG. That can make the image reader app to misbehave.
Either change Image.compress(Bitmap.CompressFormat.PNG, 100, fos);
to
Image.compress(Bitmap.CompressFormat.JPEG, 100, fos);
or change
File file = new File(filedestination, postVal + ".post_order" + ".jpg" + timeStamp);
to
File file = new File(filedestination, postVal + ".post_order" + ".png" + timeStamp);
I'm opening an image from the gallery, resizing it, and attempting to save the resized version to the apps data file so I can grab it in future. My problem is I keep getting a FileNotFoundException when I try to write it with an input stream.
This is the file it's trying to write too. "/mnt/sdcard/Android/data/foundcake.myslide/files/IMG_20100918_133128.png"
Am I missing any important steps here?
File storagePath = new File(Environment.getExternalStorageDirectory() + "/Android/data/foundcake.myslide/files/");
storagePath.mkdirs();
Debug.print("STORAGE PATH " + storagePath);
Pattern pattern = Pattern.compile("/([^/]+)\\.[^/]+$");
Matcher matcher = pattern.matcher(filePath);
String fileName = "";
while (matcher.find()) {
fileName = matcher.group(1);
}
Debug.print("FILE NAME " + fileName);
File cached = new File(storagePath, fileName + ".png");
Debug.print("NEW FILE " + cached.toString());
try {
FileOutputStream out = new FileOutputStream(cached);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (Exception e) {
e.printStackTrace();
}
Needed
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Whoops.