I have few questions about Images, bitmap particularly.
In my app that I currently develop, I have like 15 icons that each has on click function to open the camera and shows the result on those icons (like thumbnails).
On resultCode RESULT_OK, I get the bitmap data that from getExtras.get("data")
Then store it inside bitmap variable. Like below
bitmap1 = (Bitmap) data.getExtras().get("data");
I have another 14 bitmaps variable.
Now what I'm trying to do is saving those bitmaps to internal storage by a save button click. But first I place them into an array to make it easier.
Bitmap[] bitmapArr = {bitmap1,bitmap2,bitmap3,bitmap4,bitmap5,bitmap6,bitmap7,bitmap8,bitmap9,bitmap10,
bitmap11,bitmap12,bitmap13,bitmap14,bitmap15};
Then read each data to format it to PNG and save it to the internal storage.
for(int i=0; i<filename.length; i++){
FileOutputStream outputStream = new FileOutputStream(String.valueOf(filename[i]));
bitmapArr[i].compress(Bitmap.CompressFormat.PNG, 100, outputStream);
outputStream.close();
MediaStore.Images.Media.insertImage(getContentResolver(), filename[i].getAbsolutePath(), filename[i].getName(), filename[i].getName());
DBHandler db = new DBHandler(this);
db.addData(new Foto(fDate,siteid,filename[i].getName(),filename[i].getAbsolutePath()));
}
I successfully save it into the internal storage only if I capture all the 15 images. If I capture less than that...The app will immediately stop and not save the images.
I tried to handle it with declare the 15 bitmaps as null in oncreate method. But that doesn't seem to solve the issues.
There is probably something that I've been missing here.
Related
I have searched online for a tutorial on how to send a bitmap data over to another activity using the putExtra() method in kotlin, but nothing seems to pop up. I do not know how to code in java so all the tutorials and stack overflow threads that talk about converting to a byte array do not help much. Can someone please help me with maybe a solution?
What I did so far (My project is in no regards to this post) is I saved a image using my camera as a bitmap using the code:
val thumbnail : Bitmap = data!!.extras!!.get("data") as Bitmap
(the key word "data" is a intent inside the upper override function (onActivityResult))
This saves a bitmap of the image I took with the camera and now I tried to send it over, using the putExtra() command as so:
var screenSwitch2 = Intent(this#MainActivity,mlscreen::class.java)
screenSwitch2.putExtra("bitmap", thumbnail)
On the other screen "mlscreen" I tried to recover the data using a intent.getStringExtra("bitmap")
val thumbnail = intent.getStringExtra("bitmap")
and then I set my image view in the "mlscreen" using the setImageBitmap method as here:
iv_image.setImageBitmap(thumbnail)
I got the error that I was looking for a bitmap data and not a string data for the method. I knew this would occur though because I had to use intent.getSTRINGExtra which would mean its converting it to a string I presume.
Any help with this would be appreciated! Thanks.
There are 3 ways to do that :
1 - Using Intent (not recommended)
ByteArrayOutputStream baos = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
intent.putExtra("image", b);
startActivity(intent);
2 - Using static (not recommended)
public static Bitmap thumbnail;
3 - Using Path (recommended)
Save your Bitmap as an image file in specific folder (make it invisible to the users).
Get the path from the saved file.
Use intent.putExtrat("imagePath",path);.
Use BitmapFactory.decodeFile(filePath); to get the Bitmap from the path.
Remove the path.
I want to pass my image from one Activity to another. At first I tried to do this with a base64 String of my image. But this only works for small pictures. It worked with 400 kb but not with 600 kb. Is there a better way to do this? By the way, I don't save the image locally, I get the image from a server, so I don't have a real Drawable.
If you only have the remote URL, then you can directly share it, otherwise you can save the image in the local media store and then share its local URL. Something like:
Bitmap bitmap = ...
String path = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Image Description", null);
Uri uri = Uri.parse(path);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(intent, "Share Image"));
Even though it is a bit discouraged to pass large "blocks" of data through intents in android (use a singleton or store the image on the internal memory, etc), you can achieve it by doing :
1 - On your Sender Activity
Intent yourIntent = new Intent(YourActivity.this, DestinationActivity.class);
Bitmap bmp; // store the image in your bitmap
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 50, baos);
yourIntent.putExtra("yourImage", baos.toByteArray());
startActivity(yourIntent);
2 - On your Receiver Activity
// parse the intent onCreate()
if(getIntent().hasExtra("yourImage")) {
ImageView iv = new ImageView(this);
Bitmap bmp = BitmapFactory.decodeByteArray(getIntent().getByteArrayExtra("yourImage"), 0, getIntent().getByteArrayExtra("yourImage").length);
iv.setImageBitmap(bmp);
}
It is strongly discouraged that you do it this way because :
1 - There is a memory limit to the passing of data through an intent.
The maximum amount of data you can transfer using an Intent is 500KB (tested on API 10, 16, 19 and 23). check this external reference
Sometimes, the bitmap might be too large for processing, thus leading to OOM (I have experienced this in the past) or cause a bad UI experience.
2 - If your activity crashes by any reason, thus leading to a crash on the application, you will lose the image because it is stored in temporary memory. If you save it internally, you can persist the image even if the application crashes.
General the best practice is to process the image when you need it, store it on a device folder (can be internal or external memory) and later when you need it retrieve it again for more processing. This way you avoid unnecessary memory allocation throughout the application.
Also, you can use third-party libraries like Picasso or Glide. I personally like Glide as it is better in performance than any other.
My application takes pictures via camera intent. How should I display their small size version in a grid view for viewing purpose. Should I create their thumbnails and store them in cache or external storage Or should I use the thumbnails created by Default Gallery application. My pictures are stored in external storage so I am expecting that Default Gallery Application would make their thumbnails automatically. If yes, then how should I map each image with the thumbnail created by Default Gallery Application.
Well, I have found that Async class could handle the memory usage scenario.
The relevant link is: http://developer.android.com/intl/es/reference/android/os/AsyncTask.html
Well, I have got an answer
public Bitmap getbitpam(String path) {
Bitmap imgthumBitmap = null;
try {
final int THUMBNAIL_SIZE =300 ;
FileInputStream fis = new FileInputStream(path);
imgthumBitmap = BitmapFactory.decodeStream(fis);
imgthumBitmap = Bitmap.createScaledBitmap(imgthumBitmap,
THUMBNAIL_SIZE, THUMBNAIL_SIZE, false);
ByteArrayOutputStream bytearroutstream = new ByteArrayOutputStream();
imgthumBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytearroutstream);
} catch (Exception ex) {
}
return imgthumBitmap;
}
However, this is taking a lot of RAM. I Have also found a strange behavior. That as I am scrolling in grid view, it is taking more RAM. The growth in memory used is cumulative and finally the app is crashing due to Memory_Low exception. Any workaround for it??
Got answer for second problem too:-- Async class.
In my application,I want to download images from an URL and then save them in a safe area in Android device. But I have no idea about storage options in Android. I don't want to use sdcard or another external storages.
Though it's not a good practice to save your application data in the limited internal storage of the device you can do that.
Check the official google documentation for saving data in the internal device storage which will give you lead about storing stuff in the internal.
http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
use iternal storage http://developer.android.com/guide/topics/data/data-storage.html#filesInternal and force app to instal in internal http://developer.android.com/guide/topics/manifest/manifest-element.html#install
on non rooted devices should be enough ...
I suppose this could be useful for you (as it was for me): https://github.com/thest1/LazyList
You can then convert you image > Bitmap > ToBytes and then into Base64 String object. By this you will get a String representation of your Image and you can simply store that into SQLlite DB.
Warnig : This may lose image quality.
TO convert drawable into Base64 String.
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
imgString = Base64.encodeBytes(b);
To convert String back to drawable. Get String from SQLite DB and then
byte[] b = Base64.decode(imgString);
Bitmap bc = BitmapFactory.decodeByteArray(b, 0, b.length);
Drawlable drawabe = new BitmapDrawable(bc).getCurrent();
Simply put I need to capture image using camera and upload it to facebook via my android application. And I successfully did that. The problem is when the photo posted in facebook, it's just too small and in low resolution while the image I took is in high resolution.
I understand that: in order to upload to facebook, i need to convert the captured image which is in bitmap format into byte array. So i have method for that:
public static byte[] convertBitmapToByteArray(Bitmap bm){
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(CompressFormat.PNG, 100, bos);
byte[] bitmapdata = bos.toByteArray();
return bitmapdata;
}
Then to upload the image to facebook, i have code below where byteData is byte array I converted from bitmap image using the method above.
parameters.putString("message", "Test");
parameters.putByteArray("source", byteData);
String facebookResponse = facebookInstance.request(albumId+"/photos",parameters,"POST");
return facebookResponse;
I am pretty sure the problem is my convertBitmapToByteArray method since the method is to compress the bitmap image and turn it into byte array, and this made my image into low resolution image. However I can't seem to find the way to upload the image without converting it into byte array first. Any solution for me?
Alright even this thread is old, i found out the answer. It's not the problem of CompressFormant.JPEG or CompressFormat.JPG. Simply put, intent in android isn't designed to carry big data like image from activity through activity. I need to save the image from intent to sd card first before able to pull it out from there. It's my solution.