Get better quality picture from camera - java

I take a picture in Android via
Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePicture, CAMERA_REQUEST);
and show / save it via
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
ImageView theImage = (ImageView) findViewById(R.id.preview);
theImage.setImageBitmap(photo);
// try to save its
try {
File testFile = new File(Environment.getExternalStorageDirectory(), "test.png");
testFile.createNewFile();
FileOutputStream out = new FileOutputStream(testFile);
photo.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
This works fine, however the quality of the image is very bad. I do not know why, since I take the picture with 8 mega pixels.
Is there a way to do this without requiring the camera manually?

Take a closer look at this post: there are two ways to capture an image in Android. First one is designed for taking small and lightweight pictures - that's the approach you use, and the second one captures full-sized pictures and writes them to storage. The post describes both ways of accomplishing this task.

Related

Why does saving this image into an SQLite database lower the quality so much?

So I'm making a list app for wine where you can put in details and an image about wines that you enter and put the data into an SQLite database on the phone.
I just worked out getting the image into the database but it's very low quality, even though I have the quality integer set to 95 (out of 100).
Can anyone give tips on how to do this in a better way?
Here is the relevant info from the AddActivity:
btnAddPicture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, 1888);
}
});
//this method happens after taking the image
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode == 1888 && resultCode == RESULT_OK){
toastMessage("Image has been taken successfully");
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 95, stream);
imageInByte = stream.toByteArray();
}
}
I then put that imageInByte variable into the database.
The reason that the image is such low quality is that it is actually getting the thumbnail version of the picture.
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
This doesn't retrieve the full image. If you want the full image, you need to use the EXTRA_OUTPUT extra to save the full image. Then, you can put the file path into the database to retrieve the full sized image.
For documentation on ACTION_IMAGE_CAPTURE:
https://developer.android.com/reference/android/provider/MediaStore.html#ACTION_IMAGE_CAPTURE
Hope this helps anyone else!

Scaling or proportionally resizing image picked from the gallery

In my app i need to pick image from gallery to my ImageView. If I pick simple image, for example, downloaded from the Internet, it works fine. But if i pick photo made on my phone i get W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (4160x3120, max=4096x4096)
Using Glide to load the photo gives this
Caused by: java.lang.IllegalArgumentException: Unknown type class android.graphics.Bitmap. You must provide a Model of a type for which there is a registered ModelLoader, if you are using a custom model, you must first call Glide#register with a ModelLoaderFactory for your custom model class
This is my code which picks up an image and creates a bitmap out of it.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// When an Image is picked
if (requestCode == SELECT_PHOTO && resultCode == RESULT_OK
&& null != data) {
Uri imageUri = data.getData();
InputStream inputStream;
try {
inputStream = getContentResolver().openInputStream(imageUri);
Bitmap image = BitmapFactory.decodeStream(inputStream);
commentImage = (ImageView) findViewById(R.id.comment_image);
//Glide.with(this).load(image).asBitmap().override(4095, 4095).into(commentImage);
commentImage.setImageBitmap(image);
//commentImage.setImageBitmap(Bitmap.createScaledBitmap(image, 4095, 2048, false));
Toast.makeText(this, "SUCCESS", Toast.LENGTH_LONG).show();
} catch (FileNotFoundException e) {
e.printStackTrace();
// show a message to the user indictating that the image is unavailable.
Toast.makeText(this, "Unable to open image", Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(this, "You haven't picked Image",
Toast.LENGTH_LONG).show();
}
}
How can I scale an Image in case if it is too big?
You can use the following to compress the bitmap, here bitmapImage is your bitmap object. :
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmapImage.compress(Bitmap.CompressFormat.JPEG, 90, byteArrayOutputStream); //90 refers to 90% quality, or 10% compression
byte[] data = byteArrayOutputStream.toByteArray();
Bitmap compressedBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

File is not being deleted even though file.delete() is returning true

I have an activity which allows the user to snap a picture and onActivityResult() will create a temp file in the cache dir to store it before i upload it to the server.
This is how I start the intent:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CODE_CAMERA);
Here is the code inside onActivityResult:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == REQUEST_CODE_CAMERA) {
try {
Bitmap photo = (Bitmap) data.getExtras().get("data");
File photoFile = new File(getActivity().getCacheDir(), "userprofilepic_temp.jpg");
boolean b = false;
if(photoFile.isFile()){
b = photoFile.delete();
}
b = photoFile.createNewFile(); //saves the file in the cache dir, TODO delete this file after account creation
userPhotoFilePath = photoFile.getAbsolutePath();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
FileOutputStream fos = new FileOutputStream(photoFile);
fos.write(bytes.toByteArray());
fos.close();
displayUserPhoto(photoFile);
} catch (IOException e) {
e.printStackTrace();
}
}
else if (requestCode == REQUEST_CODE_PHOTO_LIBRARY) {
}
}
}
And displayUserPhoto is just a simple Glide call:
#Override
public void displayUserPhoto(File photoFile) {
Glide.with(this)
.load(photoFile)
.into(userPhotoView);
}
Since I want to override the previous picture if a user decides to retake the picture, I check if the photoFile is a file. If it is, I delete it. Then create a new file.
The problem is that it always return the same initial picture. The file is never deleted even though I call .delete().
Since I am using the app's cache dir, I don't need write permissions, but just incase I tried including that but it still didn't work.
Edit: added full flow below
I don't really know what to do here since the answer is completely different than what I initially thought it was, so it doesn't really pertain to the question.
Glide was not only saving a cache in memory but also on disk, hence why i kept getting the same image.
The solution is simply this:
Glide.with(this)
.load(photoFile)
.skipMemoryCache(true)//this
.diskCacheStrategy(DiskCacheStrategy.NONE)//and this
.into(userPhotoView);

Android camera to take multiple photos [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
The problem class:
public class problem extends Activity {
ImageView iv;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.problem);
iv=(ImageView) findViewById(R.id.imageView1);
Button b=(Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 0);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
Bitmap bm=(Bitmap) data.getExtras().get("data");
iv.setImageBitmap(bm);
}
}
This is what I wanted to do:
Take multiple photos
show them in the screen
store them in the mysql databse.
I am new to android please tell me how to do that.I searched.But I could not find a answer.
From this code IT TAKE ONLY ONE PHOTO.
Show Image on Screen Before Saving :
Use my Code. I am taking a picture using camera intent and before saving it to gallery , it is showed to the user with a Save and Cancel Button :- Call Camera Intent :-
// This code is to call the camera intent. Basically it will start your camera. Put this code in a button or something
String SD_CARD_TEMP_DIR = Environment.getExternalStorageDirectory() + File.separator +CommonFunction.getDateTime()+".jpg"; // Get File Path
Intent takePictureFromCameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
takePictureFromCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(SD_CARD_TEMP_DIR)));
startActivityForResult(takePictureFromCameraIntent, 123);
onActivityResult : -
// This function is called when you come back to your activity after the intent has finished. Do read android documentation on Google. It will Help
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_RESULT)
{
if (resultCode == Activity.RESULT_OK)
{
String galleryImatePath = SD_CARD_TEMP_DIR; // make SD_CARD_TEMP_DIR Global so that you can access it here from camera intent or pass it in put Extra method and retrieve it here
File f = new File(galleryImatePath);
try {//This code will rotate your image if you have taken the image by rotating the camera
Bitmap cameraBitmap = null;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = false;
bmOptions.inPurgeable = true;
bmOptions.inBitmap = cameraBitmap;
bmOptions.inMutable = true;
cameraBitmap = BitmapFactory.decodeFile(galleryImatePath,bmOptions);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cameraBitmap.compress(Bitmap.CompressFormat.JPEG, 50, bos);
//To Rotate image Code
ExifInterface exif = new ExifInterface(galleryImatePath);
float rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
System.out.println(rotation);
float rotationInDegrees = exifToDegrees(rotation);
System.out.println(rotationInDegrees);
Matrix matrix = new Matrix();
matrix.postRotate(rotationInDegrees);
final Bitmap rotatedBitmap = Bitmap.createBitmap(cameraBitmap , 0, 0, cameraBitmap.getWidth(), cameraBitmap.getHeight(), matrix, true);
FileOutputStream fos=new FileOutputStream(galleryImatePath);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 50, fos);
fos.write(bos.toByteArray());
cameraBitmap.recycle();
System.gc();
fos.flush();
fos.close();
// To set image in imageview in dialog. This code will set your image in a custon dialog box "captiondialog". It will contain a full width and height imageview and two textviews - done and cancel. It is upto u what you want to define in the textview's click listener. For example, you can pass the storing image in database in the "Done" textview and "Cancel" textview will dismiss your captiondialog and you app will return to your activity
Capdialog = new Dialog(AddToDo.this,android.R.style.Theme_NoTitleBar_Fullscreen);
Capdialog.setContentView(R.layout.captiondialog);
Capdialog.setCancelable(false);
TextView cancel = (TextView) Capdialog
.findViewById(R.id.cancel);
TextView done = (TextView) Capdialog.findViewById(R.id.done);
Capdialog.getWindow().setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
ImageView img = (ImageView) Capdialog.findViewById(R.id.image);
img.setImageBitmap(rotatedBitmap);
}
catch(Exception e){}
}
}
}
implement your done and cancel on click listener - what you want to do in them. My code will capture your image, rotate it in the right direction irrespective of camera rotation and show it to you in a dialog before saving it
This code will store your image in DB.You have to use "blob" to store image.. Use This Code :-
public void insertImageInDb(int id , Bitmap img ) {
byte[] data = bos.toByteArray(); // Use This or the code in comments below
/* ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 0, outputStream);
byte[] data = outputStream.toByteArray();*/
insertStatement_logo.bindLong(1, id);
insertStatement_logo.bindBlob(2, data);
insertStatement_logo.executeInsert();
insertStatement_logo.clearBindings() ;
}
There's an alternative intent action for the device camera that launches the camera in still image mode and does not exit until the user is finished with the activity:
Intent intent = new Intent(
MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
this.startActivity(intent);
Used with a ContentObserver this was exactly what I needed to accomplish. or Handle this in ActivityResult.
Note :- if you are new to android, this is too hard for you to understand now. Please read the android documentation first on google and read tutorials. Make basic apps. Learn first

Camera Intent result woes

I am attempting to launch the built-in camera to take a picture, a picture that will have a name specified by the activity launching the camera. (code below)
When the camera returns, onActivityResult() goes straight to resultCode == Activity.RESULT_CANCELED. Any explanation for this and solutions would be greatly appreciated.
The camera indeed does take the image, I can see it in my sdcard with a file viewer, but its name is the stock one from the camera. How can I get the name of this taken image to be the one supplied by the activity?
Camera intent code
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File image = new File("Team image.jpg");
camera.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
camera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image));
camera.putExtra(MediaStore.Images.Media.TITLE, "Team image");
startActivityForResult(camera, PICTURE_RESULT);
activityresult code
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == PICTURE_RESULT){
if(resultCode == Activity.RESULT_OK) {
if(data!=null){
Bitmap image = BitmapFactory.decodeFile(data.getExtras().get(MediaStore.Images.Media.TITLE).toString());
grid.add(image);
images.addItem(image);
}
if(data==null){
Toast.makeText(Team_Viewer.this, "no data.", Toast.LENGTH_SHORT).show();
}
}
else if(resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(Team_Viewer.this, "Picture could not be taken.", Toast.LENGTH_SHORT).show();
}
}
}
Have you mark the launch mode of your activity as "singleInstance"?
That may cause your first problem.
My camera goes normal when I remove the "singleInstance".
The two issues are likely related, having to do with the way you are creating the file reference that passes to the camera. If you want your image file to save to the SD Card, you need to create a file reference that includes a full-path to that location, not just a filename. For example, this code would save the image file on the SD card root:
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File image = new File(Environment.getExternalStorageDirectory(),"TeamImage.jpg");
camera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image));
startActivityForResult(camera, PICTURE_RESULT);
I also changed your filename to not include a space; only because I'm not certain that the Camera application won't blow up on that piece also. Since the Camera is getting confused trying to open and write to your file location, that is likely why you always return with RESULT_CANCELED. You don't need the WRITE_EXTERNAL_STORAGE permission here, since the Camera app is doing the SD Card access.
One more note: I don't believe other MediaStore extras can be passed with this Intent. Typically, if you want metadata to be attached to your image, you have to insert the Uri reference with that metadata into the MediaStore ContentProvider prior to saving the image to disk.
Hope that helps!
Not sure what's wrong with your code, here's what works for me:
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAMERA_PIC_REQUEST);
and
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case CAMERA_PIC_REQUEST:
Bitmap b = (Bitmap) data.getExtras().get("data");
if (b != null) {
updateThumbnail(b);
if (mBitmap != b) {
b.recycle();
}
}
break;
}
}

Categories

Resources