I know it seems like a very basic question, but it's specifically for Android Q.
I just want to get an image from Gallery and compress it and send to the server. But because of the Android Q's Scoped Storage, it's harder than I thought. I'll first explain what I did with code:
First I send out the intent to pick the image.
fun openGallery(fragment: Fragment){
val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
intent.type = "*/*"
val mimeTypes = arrayOf("image/*")
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
fragment.startActivityForResult(intent, REQUEST_IMAGE_PICK)
}
It works fine, and I'm able to get the image in the onActivityResult method
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == REQUEST_IMAGE_PICK && resultCode == Activity.RESULT_OK && null != data) {
val selectedImage = data.data
val source = ImageDecoder.createSource(activity!!.contentResolver, selectedImage)
val bitmap = ImageDecoder.decodeBitmap(source)
mBinding.circularProfileImage.setImageBitmap(bitmap)
}
}
Okay now the question is how can I access this image in File format, so I can further process/compress it.
Following things I've tried:
val mImagePath = getImagePathFromUri(activity!!, selectedImage)
This is the path I've got:
/storage/emulated/0/DCIM/Camera/IMG_20191022_152437.jpg
I created a file from it, in the following way:
val file = File(mImagePath)
And Following is my custom logic to compress and upload image:
val mNewFile = MediaCompressor.compressCapturedImage(activity!!, file, "ProfilePictures")
uploadProfile(mNewFile)
In this custom logic, I have a method to handle sampling and rotation of the image as follows:
fun handleSamplingAndRotationBitmap(context: Context, selectedImage: File, reqWidth: Int, reqHeight: Int): Bitmap {
val mUri = Uri.fromFile(selectedImage)
// First decode with inJustDecodeBounds=true to check dimensions
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
var imageStream = context.contentResolver.openInputStream(mUri)
BitmapFactory.decodeStream(imageStream, null, options)
imageStream!!.close()
// Calculate inSampleSize
options.inSampleSize =
calculateInSampleSize(options, reqWidth, reqHeight)
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false
imageStream = context.contentResolver.openInputStream(mUri)
var img = BitmapFactory.decodeStream(imageStream, null, options)
img = rotateImageIfRequired(context, img!!, mUri)
return img
}
But when I'm trying to open the stream using context.contentResolver.openInputStream
I get the following error:
java.io.FileNotFoundException: /storage/emulated/0/DCIM/Camera/IMG_20191022_152437.jpg: open failed: EACCES (Permission denied)
I know I'm getting this because in Android 10 we don't have the permission to directly access files from external storage.
So, please help me figure this out, how can I use the image from external storage as a file in Android 10.
Note: I've all the required permissions, so that's not the issue
Following things I've tried:
There is no possible reliable getImagePathFromUri() implementation.
In this custom logic, I have a method to handle sampling and rotation of the image as follows:
You do not need a File in that function. After all, your very first statement in that function goes and creates a Uri from that File. So, replace the File parameter with the Uri that you have, and skip the Uri.fromFile() call.
how can I use the image from external storage as a file in Android 10.
You can't. And, as demonstrated above, you do not need it for what you are doing.
If you find yourself in some situation where you are stuck using some library or API that absolutely positively must have a File:
Open an InputStream on the content, using contentResolver.openInputStream(), as you are doing today
Copy the bytes from that InputStream to some FileOutputStream on a file that you can read/write (e.g., getCacheDir() on Context)
Use your copy with the library or API that requires a File
Create a Directory for data to be stored in Android/data/package name by:
private void createDir() {
String timeStamp = utils.currentTimeStamp();
File storageDir = getExternalFilesDir(null);
File image;
try {
image = File.createTempFile(timeStamp, ".png", storageDir);
Log.i("SANJAY ", "createDir: " + image.getPath());
} catch (IOException e) {
e.printStackTrace();
Log.i("SANJAY ", "createDir: " + e.getMessage());
}
}
now call the gallery intent:
intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, 100);
In onActivityResult():
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == 100) {
Uri mediaUri = data.getData();
//display the image
try {
InputStream inputStream = getBaseContext().getContentResolver().openInputStream(mediaUri);
Bitmap bm = BitmapFactory.decodeStream(inputStream);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
byte[] byteArray = stream.toByteArray();
bind.photo.setImageBitmap(bm);
//Log.i("SANJAY ", "onActivityResult: " + saveBitMap(this, bm));
uri = Uri.fromFile(saveBitMap(this, bm));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
the get the Uri from File using this method:
private File saveBitMap(Context context, Bitmap Final_bitmap) {
File pictureFileDir = new File(Environment.getExternalStorageDirectory()
+ "/Android/data/"
+ getApplicationContext().getPackageName()
+ "/"/*Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), ""*/);
if (!pictureFileDir.exists()) {
boolean isDirectoryCreated = pictureFileDir.mkdirs();
if (!isDirectoryCreated)
Log.i("SANJAY ", "Can't create directory to save the image");
return null;
}
String filename = pictureFileDir.getPath() + File.separator + System.currentTimeMillis() + ".jpg";
File pictureFile = new File(filename);
try {
pictureFile.createNewFile();
FileOutputStream oStream = new FileOutputStream(pictureFile);
Final_bitmap.compress(Bitmap.CompressFormat.PNG, 18, oStream);
oStream.flush();
oStream.close();
Log.i("SANJAY ", "saveBitMap :: Save Image Successfully..");
} catch (IOException e) {
e.printStackTrace();
Log.i("SANJAY", "There was an issue saving the image.");
Log.i("SANJAY", "Error :: " + e.getLocalizedMessage());
}
return pictureFile;
}
Related
I am trying to make an app that takes a picture and embed another image like a logo onto the original image. But I have a problem in the initial stages.
I am trying to save the image from the Bitmap received from onActivityResult for the camera intent. But after using the following code, the images are scaled-down and compressed too much and looks bad. Can someone help me retain the picture quality and size?
Here are the pictures that the app saved:
public void saveBitmapToGallery(Bitmap bm,String picturename){
String root = Environment.getExternalStorageDirectory().toString();
File mydir = new File(picturepath);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
displayheight = dm.heightPixels;
displaywidth = dm.widthPixels;
File file = new File(mydir, picturename+".JPG");
try {
FileOutputStream fos = new FileOutputStream(file);
bm.createScaledBitmap(bm,displaywidth,displayheight,true);
bm.compress(Bitmap.CompressFormat.JPEG,100, fos);
fos.flush();
fos.close();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
I expect an image like the general camera app so that I can work on embedding the logo once I can get my app to save good quality images.
the image did not convert into byte output
also, Go for My Github Profile for this
https://github.com/axarlotwala/CafeDelearenter code here
// using intent open file chooser option
private void ShowFileChooser() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Select Picture"),PICK_IMAGE_REQUEST);
}
// show selected and path image in imageview
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
PATH = data.getData();
try {
bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(),PATH);
cat_image.setImageBitmap(bitmap);
tv_path.setText("Path : " .concat(GetPath(PATH)));
} catch (IOException e) {
e.printStackTrace();
}
}
//get correct path of image
private String GetPath(Uri uri){
String result;
Cursor cursor = getActivity().getContentResolver().query(uri,null,null,null,null);
if (cursor == null){
result = uri.getPath();
}else {
cursor.moveToFirst();
int id = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
result = cursor.getString(id);
cursor.close();
}
return result;
}
Well, I figured out what was wrong with the output image. We need to use EXTRA_OUTPUT for the picture to be saved in full size, otherwise only a thumbnail is saved.
Here is what we need to to before starting camera activity for result
if (picturefile != null) {
Uri pictureUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() +
".provider", picturefile);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri); //This makes the image to save in full rather than just a low quality scaled-down thumbnail.
}
startActivityForResult(imageIntent, REQUEST_IMAGE_CAPTURE);
I can save the captured image to Pictures folder however i cannot save it to app folder. I give permissions for camera and write permission dynamically. I write read write camera permission in manifests.xml. I checked permission at debug mode. There is no problem with permissions.
Camera activity starts and i take picture and click OK. Then in onActivityResult() i checked the image file's size.It's zero byte. Image file exists but zero length.
Here is how i retrieve image path :
public static File getImageFile(Context context, int food_id) {
try {
//File storageDir = new File(context.getFilesDir().getAbsolutePath() + File.separator + IMAGES_DIRECTORY); // not works !!!!!!!!!
File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString() + File.separator + IMAGES_DIRECTORY); // works
if (!storageDir.exists()) {
storageDir.mkdirs();
}
File photoFile = new File(storageDir.getAbsolutePath() + File.separator + food_id + ".jpg");
/* if(!photoFile.exists())
photoFile.createNewFile();*/
return photoFile;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
if (Build.VERSION.SDK_INT >= 23) {
hasPermissionCamera = ContextCompat.checkSelfPermission(FoodDetailsActivity.this, Manifest.permission.CAMERA);
if (hasPermissionCamera != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
getErrorDialog(getString(R.string.permission_error_dialog_camera), FoodDetailsActivity.this, true).show();
} else {
requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CODE_ASK_PERMISSIONS_CAMERA);
}
} else { // open camera
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) // intent düzgün mü diye kontrol eder.
{
File photoFile = AppUtil.getImageFile(FoodDetailsActivity.this,food_id);
if (photoFile != null) {
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
}
} else {
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intentx) {
super.onActivityResult(requestCode, resultCode, intentx);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
File imageFile = AppUtil.getImageFile(this,food_id);
try {
mImageBitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath()); // mImageBitmap is null here. imageFile exists.
Log.d("eeffs","size : " + imageFile.length() + " - exists() : " + imageFile.exists()); exists return true. length is zero
int widthBitmap = mImageBitmap.getWidth(); // exception here because bitmap is null
...
} catch (IOException e) {
e.printStackTrace();
}
}
}
i cannot save it to app folder
I am going to guess that you mean:
File storageDir = new File(context.getFilesDir().getAbsolutePath() + File.separator + IMAGES_DIRECTORY); // not works !!!!!!!!!
Third party apps have no ability to write to your app's portion of internal storage, and you are invoking a third-party camera app via ACTION_IMAGE_CAPTURE.
You can use FileProvider and its getUriForFile() method to provide selective access to your app's portion of internal storage. This sample app demonstrates the technique, where I also write to a location inside of getFilesDir().
As a bonus, using FileProvider will allow you to get rid of that ugly StrictMode hack that you are using to try to get past the ban on file Uri schemes.
what is the reason of this error :
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.sqlfirst.AddImage}: java.lang.NullPointerException: uriString
the error is pointing at this line where I am receiving the intent
img.setImageURI(Uri.parse(imagePath ));
I am trying to send a sd card path through an intent to another acitivity and convert it into an image
this is the code:
Here sending the path of the image in sd card
public void openGallery() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), 1);
// startActivityForResult(
// Intent.createChooser(intent, "Complete action using"),2);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == RESULT_OK && data != null && data.getData() != null) {
Bundle extras2 = data.getExtras();
filePath = data.getData();
Intent i = new Intent(this,
AddImage.class);
i.putExtra("imagepath", filePath);
startActivity(i);
here I suppose to recieve the path of the image and decrease the size of the image.
String imagePath = getIntent().getStringExtra("imagePath");
ImageView img=(ImageView) findViewById(R.id.imageView);
img.setImageURI(Uri.parse(imagePath ));
Bitmap bitmap = ((BitmapDrawable)img.getDrawable()).getBitmap();
Bitmap out = Bitmap.createScaledBitmap(bitmap, 500, 500, false);
// bitmap is the image
ByteArrayOutputStream stream = new ByteArrayOutputStream();
out.compress(Bitmap.CompressFormat.JPEG, 60, stream);
bitmap.recycle();
To use the path correctly you should first create it to have somewhere to store it, you can use that and later on delete it or use the data from the result you got.
Here is the code to create a Uri, pass it to your Intent. Once you get the result you can pass the Uri to another class by using getPath from the Uri package.
/**
* Creating file uri to store image/video
*/
public static Uri getOutputMediaFileUri() {
return Uri.fromFile(getOutputMediaFile());
}
/**
* returning image / video
*/
private static File getOutputMediaFile() {
// External sdcard location
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"YOUR DIRECTORY NAME");
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("image upload", "Oops! Failed create "
+ "YOUR DIRECTORY NAME" + " directory");
return null;
}
}
//TODO change naming
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
EDIT 1:
To convert a file to a bitmap you can use this code, provided by #Nikhilreddy Gujjula in this question
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(photoPath, options);
selected_photo.setImageBitmap(bitmap);
You are setting imagepath as an extra and trying to retrieve imagePath.
Also note that setImageURI() is not a good choice, as it will load and decode the image on the main application thread. Use an image-loading library, like Picasso or Universal Image Loader.
I am having a problem while trying to save a photo to storage with an Android app. The app uses the devices camera to take a photo and save it as a PNG to the device.
For some reason no matter what I do or where I store the image the quality is very poor. The app is an existing project that is quite large so I was wondering if there are other factors to consider when saving images to a device or maybe another way of overriding the quality.
This is the function that was coded by the previous dev:
public String saveImageToDevice(Bitmap image) {
saveCanvasImage(image);
String root = Environment.getExternalStorageDirectory().toString()+"/Android/data/com.app.android";
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String fname = "Image-"+ timeStamp +".png";
File file = new File (myDir, fname);
if (file.exists ()){
file.delete ();
}
try {
Toast.makeText(getActivity(), "Saving Image...", Toast.LENGTH_SHORT).show();
Log.i("Image saved", root+"/saved_images/"+fname);
FileOutputStream out = new FileOutputStream(file);
image.compress(CompressFormat.PNG, 100, out);
imageLocations.add(fname);
out.flush();
out.close();
//return myDir.getAbsolutePath() + "/" +fname;
return fname;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
And this is a function I have tried myself from an example online:
public void saveCanvasImage(Bitmap b) {
File f = new File(Environment.getExternalStorageDirectory().toString() + "/img.png");
try {
f.createNewFile(); // your mistake was at here
FileOutputStream fos = new FileOutputStream(f);
b.compress(CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
Both of these produce the same very poor images. I have posted a before and after segment below.
This is what the camera preview looks like.
This is the resulting image once it has saved.
After speaking to a few people i am including my camera intent code:
public void startCameraIntent(){
/*************************** Camera Intent Start ************************/
// Define the file-name to save photo taken by Camera activity
String fileName = "Camera_Example.png";
// Create parameters for Intent with filename
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, fileName);
values.put(MediaStore.Images.Media.DESCRIPTION,"Image capture by camera");
// imageUri is the current activity attribute, define and save it for later usage
#SuppressWarnings("unused")
Uri imageUri = getActivity().getContentResolver().insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
/**** EXTERNAL_CONTENT_URI : style URI for the "primary" external storage volume. ****/
// Standard Intent action that can be sent to have the camera
// application capture an image and return it.
Intent intent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE );
//intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); // set the image file name
startActivityForResult( intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
/*************************** Camera Intent End ************************/
}
As you can see the EXTRA_OUTPUT line is has been commented out due to it causing crashes with the below error:
12-17 13:31:37.339: E/AndroidRuntime(16123): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=65537, result=-1, data=null} to activity {}: java.lang.NullPointerException
I have also included my onActivityresult code too:
public void onActivityResult( int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
int page = mViewPager.getCurrentItem();
NotesPagerFragment note = pages.get(page);
Log.i("Request Code", ""+requestCode);
//For the ImageCapture Activity
if ( requestCode == 1) {
if ( resultCode != 0) {
/*********** Load Captured Image And Data Start ****************/
Bitmap bp = (Bitmap) data.getExtras().get("data");
//add the image to the note through a function call
note.addImage(bp);
note.saveImageToDevice(bp);
//String imageId = convertImageUriToFile( imageUri,CameraActivity);
// Create and excecute AsyncTask to load capture image
// new LoadImagesFromSDCard().execute(""+imageId);
/*********** Load Captured Image And Data End ****************/
} else if ( resultCode == 0) {
Toast.makeText(this.getActivity(), " Picture was not taken ", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this.getActivity(), " Picture was not taken ", Toast.LENGTH_SHORT).show();
}
}
//For the deleting an Image
if (requestCode == 2) {
String location = (String) data.getExtras().get("imageLocation");
if(data.getExtras().get("back") != null){
//just going back, don't mind me
}else {
//Toast.makeText(this.getActivity(), "BOO", Toast.LENGTH_SHORT).show();
note.removeNoteImageFromView(location);
database.removeSingleNoteImageFromSystemByLocation(location);
}
}
}
OK so after a lot of help from MelquiadesI have eventually solved this issue. The problem I had was that my intent and onActivityResult were retrieving the thumbnail of the image and scaling it up (hence the poor quality).
The line below is responsible for getting the thumbnail preview (120px x 160px):
Bitmap bp = (Bitmap) data.getExtras().get("data");
In order to access the full image I need to add EXTRA_OUTPUT to the intent which looks as follows:
public void startCameraIntent(){
/*************************** Camera Intent Start ************************/
File imageFile = new File(imageFilePath);
Uri imageFileUri = Uri.fromFile(imageFile); // convert path to Uri
// Standard Intent action that can be sent to have the camera
// application capture an image and return it.
Intent intent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE );
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri); // set the image file name
startActivityForResult( intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
/*************************** Camera Intent End ************************/
}
I also declared my imageFilePath as a string at the top of my activity:
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFilePath = Environment.getExternalStorageDirectory().toString()+"/Android/data/com.my.app/Image-"+timeStamp+".png";
I then had to change onActivityResult so it could access the full image to use:
public void onActivityResult( int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
int page = mViewPager.getCurrentItem();
NotesPagerFragment note = pages.get(page);
Log.i("Request Code", ""+requestCode);
//For the ImageCapture Activity
if ( requestCode == 1) {
if ( resultCode != 0) {
/*********** Load Captured Image And Data Start ****************/
// Decode it for real
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = false;
//imageFilePath image path which you pass with intent
Bitmap bp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
//rotate image by 90 degrees
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bp, 0, 0, bp.getWidth(), bp.getHeight(), rotateMatrix, false);
//add the image to the note through a function call
note.addImage(rotatedBitmap);
note.saveImageToDevice(rotatedBitmap);
//String imageId = convertImageUriToFile( imageUri,CameraActivity);
// Create and excecute AsyncTask to load capture image
// new LoadImagesFromSDCard().execute(""+imageId);
/*********** Load Captured Image And Data End ****************/
} else if ( resultCode == 0) {
Toast.makeText(this.getActivity(), " Picture was not taken ", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this.getActivity(), " Picture was not taken ", Toast.LENGTH_SHORT).show();
}
}
//For the deleting an Image
if (requestCode == 2) {
String location = (String) data.getExtras().get("imageLocation");
if(data.getExtras().get("back") != null){
//just going back, don't mind me
}else {
//Toast.makeText(this.getActivity(), "BOO", Toast.LENGTH_SHORT).show();
note.removeNoteImageFromView(location);
database.removeSingleNoteImageFromSystemByLocation(location);
}
}
}
The key part here is:
// Decode it for real
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = false;
//imageFilePath image path which you pass with intent
Bitmap bp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
This code decodes the image you saved at imageFilePath into a usable bitmap. From here you can use it as normal.
Sometimes (apparently this is quite common) the image comes in rotated by 90°, the next bit of code will rotate that back if you need it to:
//rotate image by 90 degrees
Matrix rotateMatrix = new Matrix();
rotateMatrix.postRotate(90);
Bitmap rotatedBitmap = Bitmap.createBitmap(bp, 0, 0, bp.getWidth(), bp.getHeight(), rotateMatrix, false);
Im trying to capture an image from the camera, compress it, then store it to the SD card. If I directly save it to the SD card using the code directly below, I get the full image. But if i try and load the image in the system, i get a super small image size such as 320 by 240 instead of a full 5 mp image.
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, getImageUri());
startActivityForResult(intent, CAMERA_PIC_REQUEST);
where getImageURI() is
private Uri getImageUri() {
// Store image in dcim
file = new File(Environment.getExternalStorageDirectory() + "/DCIM","itshelp.jpg");
imgUri = Uri.fromFile(file);
file.deleteOnExit();
Log.e("syS","file is at "+imgUri);
return imgUri;
}
Now when i try to save it to internal memory instead, I use the following code that gets me the tiny image:
public void imageFromCamera() { //code to retrieve image
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
startActivityForResult(intent, CAMERA_PIC_REQUEST);
}
and in my startActivitForResult I have the following:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_PIC_REQUEST && resultCode == RESULT_OK) {
Bitmap bm = (Bitmap) data.getExtras().get("data");
Log.e("sys", "width is "+bm.getWidth()); //im gettting an extremely small width here
OutputStream outStream = null;
file = new File(Environment.getExternalStorageDirectory() + "/DCIM","itshelp.png");
try {
outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.JPEG, 70, outStream);
outStream.flush();
outStream.close();
Log.i("Hub", "OK, Image Saved to SD");
Log.i("Hub", "height = "+ bm.getHeight() + ", width = " + bm.getWidth());
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.i("Hub", "FileNotFoundException: "+ e.toString());
} catch (IOException e) {
e.printStackTrace();
Log.i("Hub", "IOException: "+ e.toString());
}
}
When you call the camera intent without MediaStore.EXTRA_OUTPUT, the camera returns only a small thumbnail since the intent bundle is not designed to pass large memory blocks.
From the SDK documentation for MediaStore:
Standard Intent action that can be sent to have the camera application capture an image and return it.
The caller may pass an extra EXTRA_OUTPUT to control where this image will be written. If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap object in the extra field. This is useful for applications that only need a small image. If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri value of EXTRA_OUTPUT.