How to save an image from an ImageView after taking a picture - android

I am picking the picture from gallery or taking it with the camera.
If I get the picture into my imageView, and click the confirm button, how can I then save that picture?
Do I have to use saveState()?
Please post some comments.
Thanks.
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK) return;
switch (requestCode)
{
case PICK_FROM_CAMERA:
Bitmap selectedImage = (Bitmap) data.getExtras().get("data");
selectedImage = Bitmap.createScaledBitmap(selectedImage, 80, 80, false);
mImageView.setImageBitmap(selectedImage);
break;
case PICK_FROM_GALLERY:
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
System.out.println("Image Path : " + selectedImagePath);
mImageView.setImageURI(selectedImageUri);
break;
}
}
private void saveState()
{
String name = (String) nameEdit.getText().toString();
String category = (String) categoryEdit.getText().toString();
String expired_date = (String) expired_Date_Btn.getText().toString();
ImageView image = (ImageView) mImageView.setImageURI(); //how to edit?
if(mRowId == null)
{
long id = mDbHelper.insertItem(category, name, expired_date);
if(id>0)
{
mRowId = id;
}
}
else
{
mDbHelper.updateItem(mRowId, category, name, expired_date);
}
}
//How can I save image after clicking button?
confirmButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v){
setResult(RESULT_OK);
finish();
}
});

You can save the image of all View (not only ImageView) following these steps:
1.Get the bitmap of your view:
public Bitmap loadBitmapFromView(View v) {
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
v.invalidate();
return b;
}
2.Save it on your SD card file (or wherever you want):
protected String saveBitmap(Bitmap bm, String name) throws Exception {
String tempFilePath = Environment.getExternalStorageDirectory() + "/"
+ getPackageName() + "/" + name + ".jpg";
File tempFile = new File(tempFilePath);
if (!tempFile.exists()) {
if (!tempFile.getParentFile().exists()) {
tempFile.getParentFile().mkdirs();
}
}
tempFile.delete();
tempFile.createNewFile();
int quality = 100;
FileOutputStream fileOutputStream = new FileOutputStream(tempFile);
BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
bm.compress(CompressFormat.JPEG, quality, bos);
bos.flush();
bos.close();
bm.recycle();
return tempFilePath;
}
These code take from one of my project, but I think they are easy to understand and re-use. Hope it will help you.

I'm not sure how to do this from the gallery or why you would want to since the image is already saved to the phone if it is in the gallery. You should be able to re-write the file using the file's URI though.
If you are taking the image with the camera, you can see that you have a Bitmap of the image. It should be relatively easy to save it using the following snippet of code:
outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
You will want the permission
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
For more information, try following this example (it is where I found the code snippets). They are uploading their image but the same concepts should apply.
http://android-er.blogspot.com/2010/07/save-file-to-sd-card.html
Hope this helps!

Related

Capture image from camera return low quality image

I've been developed app to take a picture to be saved in gallery. I've searched online and the easiest way that I could practice was to use data.getExtras().get("data") . So below are the code to take picture from camera. Note that I'm using fragment in this class.
img22a1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,CAMERA_01);
}
});
Get the captured image and convert it to string
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_01) {
if (resultCode == Activity.RESULT_OK) {
Bitmap bitmap = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream output = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
byte[] byte_arr = output.toByteArray();
((SiteProgress) getActivity().getApplication()).seti22a1(Base64.encodeToString(byte_arr, Base64.DEFAULT));
BitmapDrawable ob = new BitmapDrawable(getResources(), bitmap);
img22a1.setBackgroundDrawable(ob);
} else if (resultCode == Activity.RESULT_CANCELED) {
}
}
}
I save the string into global variable so another activity can access it.
In another activity, I have a button to save the image into folder/gallery by accessing the image string.
for(int i=0;i<=namefile.length;i++){
Bitmap[] bitmap = new Bitmap[namefile.length];
FileOutputStream outputStream = new FileOutputStream(String.valueOf(namefile[i]));
bitmap[i] = BitmapFactory.decodeByteArray(decodedString[i],0,decodedString[i].length);
bitmap[i].compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), namefile[i].getAbsolutePath(), namefile[i].getName(), namefile[i].getName());
}
It worked to save the image into folder/gallery....But the quality of image was very low...I could barely see text in the image.
They said data.getExtras().get("data") supposed to return thumbnail and not the actual image. What I want here is to get the full image and not the thumbnail one.
Any answer will be very appreciated.
From: Android - How to get the image using Intent data
if(data != null)
{
Uri selectedImageUri = data.getData();
filestring = selectedImageUri.getPath();
Bitmap thumbnail = BitmapFactory.decodeFile(filestring, options2);
System.out.println(String.format("Bitmap(CAMERA_IMAGES_REQUEST): %s", thumbnail));
System.out.println(String.format("cap_image(CAMERA_IMAGES_REQUEST): %s", cap_image));
cap_image.setImageBitmap(thumbnail);
}

Save image in original form and without compressing

I want to save the image without compressing it and want to save it in it's original form i.e. when image is compressed the image size decreases and image become small. I am using native camera for this purpose. I am working in android studio. I am making an app in which i am using a camera to save image. But the image is compressed and is very small and very lower quality.
Below is my code for saving image
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
if(requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE)
{
if(resultCode == Activity.RESULT_OK)
{
Bitmap bmp = (Bitmap)data.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
// convert byte array to Bitmap
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
if(isStoragePermissionGranted())
{
SaveImage(bitmap);
}
}
}else {
switch (requestCode) {
case 1000:
switch (resultCode) {
case Activity.RESULT_OK:
// All required changes were successfully made
getLocation();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
Toast.makeText(this, "Location Service not Enabled", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
break;
}
}
}
private void SaveImage(Bitmap finalBitmap) {
File storageDir = new File (String.valueOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)));
String root = storageDir + Environment.getExternalStorageDirectory().getAbsolutePath().toString();
Log.v(LOG_TAG, root);
File myDir = new File(root + "/captured_images");
if (!myDir .exists())
{
myDir .mkdirs();
}
Random generator = new Random();
int n = 1000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
File file = new File(myDir,fname);
try {
file.createNewFile();
MediaScannerConnection.scanFile(getApplicationContext(), new String[] {file.getPath()} , new String[]{"image/*"}, null);
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG,100,out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Update 1
For more understanding i am putting my onClick method
btn_camera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Check permission for camera
if(ActivityCompat.checkSelfPermission(MainActivity.this, CAMERA)
!= PackageManager.PERMISSION_GRANTED)
{
// Check Permissions Now
// Callback onRequestPermissionsResult interceptado na Activity MainActivity
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{CAMERA},
MainActivity.REQUEST_CAMERA);
}
else {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE );
}
}
});
I searched the solution and found that i can use AndroidBitmapUtil
class so i copy and pasted this class into my project i.e. i created a new class. But i don't know how to use it. Although it is described that i can save image by doing new AndroidBmpUtil().save(bmImage, file);. But again i can't match with my code :(
Any help would be highly appreciated
new AndroidBmpUtil().save(source, sdcardBmpPath);
USER ABOVE LINE OF CODE AND FOLLOW BELOW LINK
https://github.com/ultrakain/AndroidBitmapUtil
Open Camera and save image into some specific directory.
solution number 1
private String pictureImagePath = "";
private void openBackCamera() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = timeStamp + ".jpg";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
pictureImagePath = storageDir.getAbsolutePath() + "/" + imageFileName;
File file = new File(pictureImagePath);
Uri outputFileUri = Uri.fromFile(file);
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, 1);}
Handle Image
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
File imgFile = new File(pictureImagePath);
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ImageView myImage = (ImageView) findViewById(R.id.imageviewTest);
myImage.setImageBitmap(myBitmap);
}
}
solution number 2
I have used the following code and this works perfectly fine for me.
values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "New Picture");
values.put(MediaStore.Images.Media.DESCRIPTION, "From your Camera");
imageUri = getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, PICTURE_RESULT);
and also
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case PICTURE_RESULT:
if (requestCode == PICTURE_RESULT)
if (resultCode == Activity.RESULT_OK) {
try {
thumbnail = MediaStore.Images.Media.getBitmap(
getContentResolver(), imageUri);
imgView.setImageBitmap(thumbnail);
imageurl = getRealPathFromURI(imageUri);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
and
public String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
For opening camera use
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(android.os.Environment.getExternalStorageDirectory(), "imagename.jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
startActivityForResult(intent, 1);
and in your onActivityresult method use
if (requestCode == 1) {
File f = new File(Environment.getExternalStorageDirectory().toString());
for (File temp : f.listFiles()) {
if (temp.getName().equals("imagename.jpg")) {
f = temp;
break;
}
}
try {
Bitmap bitmap;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath(),bitmapOptions);
yourimageview.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
}

android compress image size before sending to server

I have tried multiple solutions from the internet with no luck, How do I go about changing the image size when I upload on app?
I want it to be in a way that when I upload a 2MB file,it gets sent to the server with size = 50kb.
Please help me
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//get image thumbnail
if (requestCode == REQUEST_CODE_PICKER && resultCode == RESULT_OK && data != null) {
ArrayList<Image> images = data.getParcelableArrayListExtra(ImagePickerActivity.INTENT_EXTRA_SELECTED_IMAGES);
absolutePath = null;
// do your logic ....
for (Image img : images) {
Log.v(LOG_TAG, img.getName() + " " + img.getPath());
absolutePath = img.getPath();
absolutePath = String.valueOf(Compressor.getDefault(getContext()).compressToFile(imageFile));
Bundle bundleExtras = data.getExtras();
image = (Bitmap) bundleExtras.get("data");
}
consultantProfileImageView.setImageBitmap(getBitmapFromPath(absolutePath));
new UploadConsultantProfileImageTask(getContext(), absolutePath).execute();
postConsultant();
}
}
public File getBitmapFromPath(String filePath) {
File imageFile = new File(filePath);
Bitmap imageBitmap = null;
imageBitmap = BitmapFactory.decodeFile(filePath);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InputStream in = new ByteArrayInputStream(bos.toByteArray());
File compressedImageFile = Compressor.getDefault(getContext()).compressToFile(imageFile);
if (compressedImageFile.exists()) {
imageBitmap = BitmapFactory.decodeFile(compressedImageFile.getAbsolutePath());
}
return compressedImageFile;
}
Try using below it will compress the image to 80 percent. You can change the percentage of compression according to your requirement.
public File getBitmapFromPath(String filePath) {
File imageFile = new File(filePath);
OutputStream fout = new FileOutputStream(file);
Bitmap bitmap= BitmapFactory.decodeFile(filePath);
bitmap.compress(CompressFormat.JPEG, 80, fout);
fout.flush();
fout.close();
return imageFile;
}
Try
int compressionRatio = 2; //1 == originalImage, 2 = 50% compression, 4=25% compress
File file = new File (imageUrl);
try {
Bitmap bitmap = BitmapFactory.decodeFile (file.getPath ());
bitmap.compress (Bitmap.CompressFormat.JPEG, compressionRatio, new FileOutputStream (file));
}
catch (Throwable t) {
Log.e("ERROR", "Error compressing file." + t.toString ());
t.printStackTrace ();
}

Save bitmap when change layout

I've a layout to portrait and a layout to landscape. In those layout, there is a ImageView with onClick listener. My ImageView has a default image (a camera icon)
When I push into ImageView, open a dialog and I can open camera and take a picture or open gallery and select a image.
Then, I save a bitmap and put it in the ImageView. This bitmap is a global variable in my class.
But when I turn my app, load my other layout (main_landscape) and if I took a pic, I lose my bitmap and charge default image.
This is my code:
public void takePicture(View view) {
final CharSequence[] options = { "Take a pic", "Gallery","Cancel" };
//Build an AlertDialog object
AlertDialog.Builder builder = new AlertDialog.Builder(Main.this);
builder.setTitle("Picture");
//onClickListener method
builder.setItems(options, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int selected) {
if(options[selected].equals("Take a pic")){
//open camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(android.os.Environment.getExternalStorageDirectory(), "temp.jpg");
//this is my global bitmap and I put it null when I push take a picture
resized=null;
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
startActivityForResult(intent, 1);
}
else if(options[selected].equals("Gallery")){
Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, 2);
}
else{
dialog.dismiss();
}
//if user doesn't select anything, show default icon
//show picture is my layout ImageView and cameraicon is my default icon
showPicture.setImageResource(R.drawable.cameraicon);
}
});
builder.show();
}
This is my onActivityResult code:
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
//if my resultCode is RESULT_OK
if(resultCode == RESULT_OK){
if(requestCode==1){
File f = new File(Environment.getExternalStorageDirectory().toString());
for(File temp: f.listFiles()){
if(temp.getName().equals("temp.jpg")){
f=temp;
break;
}
}
try{
Bitmap bitmap;
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmap = BitmapFactory.decodeFile(f.getAbsolutePath());
newHeight=600;
newWidth=900;
//resized is my global bitmap
resized = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
//show my new bitmap in my ImageView
showPicture.setImageBitmap(resized);
} catch (Exception e) {
e.printStackTrace();
}
}
//I choose gallery option
else if(requestCode==2){
Uri selectedImage = data.getData();
String[] filePath = {MediaStore.Images.Media.DATA};
Cursor c = getContentResolver().query(selectedImage,filePath,null,null,null);
c.moveToFirst();
int columnIndex = c.getColumnIndex(filePath[0]);
String picturePath = c.getString(columnIndex);
c.close();
Bitmap thumbnail = (BitmapFactory.decodeFile(picturePath));
newHeight=600;
newWidth=900;
//my global bitmap
resized = Bitmap.createScaledBitmap(thumbnail, newHeight, newWidth, true);
//show new bitmap in my ImageView
showPicture.setImageBitmap(resized);
}
}
}
When I turn my phone, I loose my bitmap. What I can do, please?
Thanks a lot!!
I think you save the value of your Bitmap by calling onSaveInstaceState(Bundle bundle) and then restore it when the activity is recreated.
You might want to store the filename to your photo file inside the activity:
class MyActivity {
File imageFile = null;
}
Since your activity will get destroyed on rotation, you need to save that image file name in onSaveInstanceState():
public void onSaveInstanceState(Bundle outState)
{
if (imageFile != null) {
outState.putString("IMAGE_FILENAME", imageFile.getAbsolutePath());
}
}
Bitmaps in android are Parcelable, so instead of storing the filename of the image you could also save the Bitmap itself.
The saved state gets passed to onCreate() when your activity gets re-created:
public void onCreate(Bundle savedState)
{
super.onCreate(savedState);
if (savedState != null) {
String imagePath = saveState.getString("IMAGE_FILENAME");
if (imagePath != null) {
imageFile = new File(imagePath);
}
}
updateImageView();
}
public void updateImageView()
{
// code from onActivityResult() to load the image
}
Side Notes:
File f = new File(Environment.getExternalStorageDirectory().toString());
for (File temp: f.listFiles()) {
if (temp.getName().equals("temp.jpg")) {
f = temp;
break;
}
}
You are writing to the global, external storage directory. Please don't do this, use your application's files' directory. Also, no need to search for a fixed filename in the path, simply check if the file exists.
File imageFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), imageFileName);
if (imageFile.exists()) {
[...]
}
I think better way to do it is using fragment instead activity.
Use method fragment.setRetainInstance(true), and fragment will not be destroyed, when you turn your device.

Out of memory in onActivityResult

I have gallery intent that copy imege to folder, and the all that images shown in the ListView. I have an OutOfMemory Exception with bitmap decoding in my compress method - what is the simpliest way to fix it? I have recycle() option, but it's not helped.
here is my onActivityResult and compress:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
selectedImagePath = getPath(selectedImageUri);
//Toast.makeText(this, selectedImagePath, Toast.LENGTH_SHORT).show();
File sdcard = Environment.getExternalStorageDirectory();
String path = "MANUAL/workflow/img" + actions.id() + ".png";
String pathCom = "/MANUAL/workflow/img" + actions.id() + ".png";
File from = new File(selectedImagePath);
File to = new File(sdcard, path);
try {
copy(from, to);
compress(pathCom);
} catch (IOException io){}
//from.renameTo(to);
}
}
}
public void compress(String comp) {
try {
String path = Environment.getExternalStorageDirectory() + comp;
BitmapFactory.Options buffer = new BitmapFactory.Options();
buffer.inSampleSize = 1;
Bitmap bmp = BitmapFactory.decodeFile(path, buffer);
if (bmp.getWidth() > width || bmp.getHeight() > height){
Bitmap resized = Bitmap.createScaledBitmap(bmp,(int)(bmp.getWidth()*0.2), (int)(bmp.getHeight()*0.2), true);
bmp.recycle();
FileOutputStream out = new FileOutputStream(path);
resized.compress(Bitmap.CompressFormat.PNG, 70, out);
resized.recycle();
out.flush();
out.close();
}
} catch (Exception e) {
e.printStackTrace();
Log.e("saveBitmap", e.getMessage());
}
}
herŅƒ is my intent:
switch (item.getItemId()) {
case R.id.gallery:
// in onCreate or any event where your want the user to
// select a file
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE);
Your inSampleSize is set to 1 which means its basically not being used.. 1= no downsampling 2 would be 1/2, 4 a 1/4.
also look into this http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
hope that helps.
also if the purpose of this is to just simply create a scaled image file, perhaps that task should be handled on it's own thread using an AsyncTask for that image resizing

Categories

Resources