Set the dimensions of image captured in android - android

In my application, I have an activity where we can capture the image from camera on button click using intent and set the captured image into imageview. Its working absolutely fine.
But now i want the image in specific dimensions. For example, in my case the dimensions of my image view is 150dp * 150dp. So i want that the dimensions of image captured by camera should also always be 150dp * 150dp in order to fit perfectly. How can i do this?
Here's my main activity.
public class MainActivity extends Activity implements OnClickListener {
Button btnTackPic;
TextView tvHasCamera, tvHasCameraApp;
ImageView ivThumbnailPhoto;
Bitmap bitMap;
static int TAKE_PICTURE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Get reference to views
tvHasCamera = (TextView) findViewById(R.id.tvHasCamera);
tvHasCameraApp = (TextView) findViewById(R.id.tvHasCameraApp);
btnTackPic = (Button) findViewById(R.id.btnTakePic);
ivThumbnailPhoto = (ImageView) findViewById(R.id.ivThumbnailPhoto);
// Does your device have a camera?
if(hasCamera()){
tvHasCamera.setBackgroundColor(0xFF00CC00);
tvHasCamera.setText("You have Camera");
}
// Do you have Camera Apps?
if(hasDefualtCameraApp(MediaStore.ACTION_IMAGE_CAPTURE)){
tvHasCameraApp.setBackgroundColor(0xFF00CC00);
tvHasCameraApp.setText("You have Camera Apps");
}
// add onclick listener to the button
btnTackPic.setOnClickListener(this);
}
// on button "btnTackPic" is clicked
#Override
public void onClick(View view) {
// create intent with ACTION_IMAGE_CAPTURE action
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//Edit to save picture
File file = new File(Environment.getExternalStorageDirectory(), "my-photo.jpg");
Uri photoPath = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoPath);
// start camera activity
startActivityForResult(intent, TAKE_PICTURE);
}
// The Android Camera application encodes the photo in the return Intent delivered to onActivityResult()
// as a small Bitmap in the extras, under the key "data"
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == TAKE_PICTURE && resultCode== RESULT_OK && intent != null){
// get bundle
Bundle extras = intent.getExtras();
// get
bitMap = (Bitmap) extras.get("data");
ivThumbnailPhoto.setImageBitmap(bitMap);
}
}
// method to check you have a Camera
private boolean hasCamera(){
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
// method to check you have Camera Apps
private boolean hasDefualtCameraApp(String action){
final PackageManager packageManager = getPackageManager();
final Intent intent = new Intent(action);
List<ResolveInfo> list = packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
}
Thanks in advance.

You need to scale your Bitmap like the following code:
Bitmap originalBitmap = <the original bitmap>;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(
originalBitmap, newWidth, newHeight, false);
Hence according to your requirement,the resized bitmap must be generated as:
Bitmap resizedBitmap = Bitmap.createScaledBitmap(
bitMap, 150,150, false);
Note:Here 150 is measured in pixels,so you have to calculate 150dp to pixel and then place it.

Related

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.

Taking a photo and show it in ImageView

i want to take a photo with the android camera like this:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
this.startActivityForResult(intent, Globals.REQUEST_CODE_CAMERA)
And to store it in an ImageView:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == Globals.REQUEST_CODE_CAMERA) {
if(resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data");
this.imageViewPhoto.setImageBitmap(bitmap);
}
}
}
My ImageView is configured like this:
<ImageView
android:id="#+id/nfcresult_imageview_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher"
android:adjustViewBounds="true"
android:clickable="true"
android:contentDescription="#string/imageview_photo_description" />
It all works but the photo shown on the ImageView is much smaller than the
photo taken by the camera. What i want to do is to have a small preview in my
ImageView and to add an OnClickListener to the ImageView to open up a Dialog
which shows the original photo with the original size and resolution. It cant
be that hard to do it but i actually cant find out how.
To create the Dialog and to show the photo i do this:
ImageView clone = new ImageView(this);
clone.setImageBitmap(((BitmapDrawable)this.imageViewPhoto.getDrawable()).getBitmap());
DialogManager.showImageDialog(this, this.getResources().getString(R.string.title_photo), clone);
The showImageDialog:
public static void showImageDialog(Context context, String title, ImageView imageView) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(title);
builder.setCancelable(false);
builder.setView(imageView);
builder.setPositiveButton(context.getResources().getString(R.string.button_back), new DialogInterface.OnClickListener() {
/**
*
*/
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
The dialog now shows the photo with the size of the photo stored in the imageView
but i want to show the original photo with original size and original resolution
but as i already said, the ImageView should show a smaller version of the original
photo.
How can i achieve that?
instead of android:layout_width="wrap_content" set the imageview width and height to specific dp value
<ImageView
android:id="#+id/nfcresult_imageview_photo"
android:layout_width="100dp"
android:layout_height="200dp"
android:src="#drawable/ic_launcher"
android:adjustViewBounds="true"
android:clickable="true"
android:contentDescription="#string/imageview_photo_description" />
maintain the aspect ratio of height and width (instead of 100 and 200, choose right values)
You have to put an extra in your intent called "MediaStore.EXTRA_OUTPUT", where you have to set an uri for the picture to store to.
After your callback function got called, you can load the Picture from the choosen uri.
There you get the picture in full resolution.
The Solution:
/**
*
*/
private void performAddPhoto() {
String timeStamp = Clock.getTimeStamp();
String fileName = "Food_Shot_" + timeStamp + ".jpg";
this.imagePath = Environment.getExternalStorageDirectory() + "/images/" + fileName;
File file = new File(this.imagePath);
file.getParentFile().mkdirs();
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent, Globals.REQUEST_CODE_CAMERA);
}
/**
*
*/
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == Globals.REQUEST_CODE_CAMERA) {
if(resultCode == RESULT_OK) {
this.onPhotoTaken();
}
}
}
/**
*
*/
private void onPhotoTaken() {
this.imageTaken = true;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(this.imagePath, options);
this.imageViewPhoto.setImageBitmap(bitmap);
}
/**
*
*/
private void performShowPhoto() {
ImageView imageView = new ImageView(this);
Bitmap bitmap = BitmapFactory.decodeFile(this.imagePath);
imageView.setImageBitmap(bitmap);
DialogManager.showImageDialog(this, this.getResources().getString(R.string.title_photo), imageView);
}

Intent started in onCreate called multiple times

I am making an app that uses the camera and I would like the default camera open as soon as the app is opened. I currently start my image capture intent in the onCreate method of my main activity. This works perfectly fine sometimes, but other times the camera intent is launched 3 consecutive times.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mImageView = (ImageView) findViewById(R.id.imageView1);
mImageBitmap = null;
Button picBtn = (Button) findViewById(R.id.pictureButton);
setBtnListenerOrDisable(
picBtn,
mTakePicOnClickListener,
MediaStore.ACTION_IMAGE_CAPTURE
);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
mAlbumStorageDirFactory = new FroyoAlbumDirFactory();
} else {
mAlbumStorageDirFactory = new BaseAlbumDirFactory();
}
dispatchTakePictureIntent(ACTION_TAKE_PHOTO_B);
}
private void dispatchTakePictureIntent(int actionCode) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f;
try {
f = setUpPhotoFile();
mCurrentPhotoPath = f.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
} catch (IOException e) {
e.printStackTrace();
mCurrentPhotoPath = null;
}
startActivityForResult(takePictureIntent, actionCode);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
handleBigCameraPhoto();
}
}
private void handleBigCameraPhoto() {
if (mCurrentPhotoPath != null) {
setPic();
galleryAddPic();
lastPhotoPath = mCurrentPhotoPath;
mCurrentPhotoPath = null;
}
}
private void setPic() {
/* There isn't enough memory to open up more than a couple camera photos */
/* So pre-scale the target bitmap into which the file is decoded */
/* Get the size of the ImageView */
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
/* Get the size of the image */
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
/* Figure out which way needs to be reduced less */
int scaleFactor = 1;
if ((targetW > 0) || (targetH > 0)) {
scaleFactor = Math.min(photoW / targetW, photoH / targetH);
}
/* Set bitmap options to scale the image decode target */
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
/* Decode the JPEG file into a Bitmap */
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
/* Associate the Bitmap to the ImageView */
mImageView.setImageBitmap(bitmap);
mImageView.setVisibility(View.VISIBLE);
}
I think Nathaniel is giving you good advice to move your camera intent launching into onResume.
However, you'll need to differentiate between an onResume that is your activity starting for the first time from one that is happening because of your activity resuming after the camera intent is finished. If you dont, you'll get the loop you see.
To do this, you can alter your onActivityResult() to set a member variable in your Activity called something like isResumingFromCaptureIntent. Set it to true in onActivityResult when the resultCode matches what you used to start the camera intent. Then, in your onResume, check isResumingFromCaptureIntent, if true you know you dont need to start the camera intent and can set is back to false and proceed with whatever else your activity needs to do.
Look here:
Android: onCreate() getting called multiple times (and not by me)
One piece of guidance I can provide is to try and move that call to
public void onResume(){
}
You'll get the desired behavior of automatically going to the camera, but this might cut down on some of the extra calls, since it only occurs when the activity is actually being shown to the user (including returning from other applications etc..).
In the onCreate method I added logic to check if onCreate had previously been called. I did this by checking if the bundle passed in was null or not
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mImageView = (ImageView) findViewById(R.id.imageView1);
mImageBitmap = null;
Button picBtn = (Button) findViewById(R.id.pictureButton);
setBtnListenerOrDisable(
picBtn,
mTakePicOnClickListener,
MediaStore.ACTION_IMAGE_CAPTURE
);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
mAlbumStorageDirFactory = new FroyoAlbumDirFactory();
} else {
mAlbumStorageDirFactory = new BaseAlbumDirFactory();
}
if(savedInstanceState == null)
dispatchTakePictureIntent(ACTION_TAKE_PHOTO_B);
}

Image not setting in ImageView after taking picture from Camera

I've have develop my own camera app for mandatory configuration, when i try to show the captured image in next activity which displays whether to save it or not?
I'm not able to fetch the image which i captured and displays on my ImageView. I'm absolutely getting absPathUri with proper path.
Code snippets:-
imgView = (ImageView)findViewById(R.id.picView);
Bundle b= getIntent().getExtras();
absPathUri = Uri.parse(b.getString("URI"));
Toast.makeText(getApplicationContext(), ""+absPathUri, Toast.LENGTH_SHORT).show();
if(absPathUri!=null)
{
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE));
imgView.setImageURI(absPathUri);
}
On Further dive in the reason why I'm unable to set the ImageView, throws the Null Pointer Exception which is due to File Not Found. If applicatoin is in debug mode it displays the proper Image on ImageView. It seems that mediaStore get Refreshed till the debugging hits.
File imgFile = new File(getPath(absPathUri));
Toast.makeText(getApplicationContext(), "ImageFile Exists"+imgFile.exists(), Toast.LENGTH_SHORT).show();
if(imgFile.exists())
{
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
imgView.setImageBitmap(myBitmap);
}
public String getPath(Uri photoUri) {
String filePath = "";
if (photoUri != null) {
String[] filePathColumn = { MediaStore.Images.Media.DATA };
try
{
Cursor cursor = getContentResolver().query(photoUri,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
cursor.close();
}catch(Exception e)
{
Toast.makeText(getApplicationContext(), ""+e, Toast.LENGTH_SHORT).show();
}
}
return filePath;
}
Tried Solution:-
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE));
Can anybody guide me where I'm getting wrong in displaying Image on ImageView?
As suggested by gnuanu, setImageURI() is not better to use as reading and decoding on the UI thread, which can cause a latency hiccup.
Better to use the following:-
setImageDrawable(android.graphics.drawable.Drawable) or setImageBitmap(android.graphics.Bitmap) and BitmapFactory instead.
Still these methods didn't solve my problem. As I was taking Picture with Camera and onClick of it sending to Next Activity which may cause latency hiccups.
So better to pass to another activity after some peroid of time . . just a sec is totally convient to get through it.
Snippet which solve my issue:-
final Intent picIntent = new Intent(CameraActivity.this,PicSaveActivity.class);
picIntent.putExtra("URI", pathUri.toString());
Handler handler = new Handler()
{
public void handleMessage(Message msg) {
startActivityForResult(picIntent, PICTAKEN);
};
};
Message msg = handler.obtainMessage();
handler.sendMessageDelayed(msg, 1000);
In Next Activity, catch the URI and rotate the Image as it would be in landscape mode.
if(absPathUri!=null)
{
Bitmap myImg = BitmapFactory.decodeFile(absPathUri.getPath());
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotated = Bitmap.createBitmap(myImg, 0, 0, myImg.getWidth(), myImg.getHeight(),
matrix, true);
imgView.setImageBitmap(rotated);
}
I don't really know what's wrong in your code, and my answer uses a completely different approach to taking a photo with the camera and displaying it in an ImageView, but it's a working solution that might help you.
In your first Activity (call it CameraActivity), you can do the following:
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class CameraActivity extends PortraitActivity {
private static final int CAMERA_REQUEST = 1888;
private ImageView imageView;
private Bitmap photo;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
}
/** Method to open camera and take photo */
public void takePhoto(View v) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
/** Method called after taking photo and coming back to current Activity */
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST) {
photo = (Bitmap) data.getExtras().get("data");
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("BitmapImage", photo);
startActivity(intent);
}
}
}
In the second activity (call it NewActivity), just put the following code in the onCreate method, after having assigned imageView to the corresponding view in the XML layout.
Intent intent = getIntent();
Bitmap bitmap = (Bitmap) intent.getParcelableExtra("BitmapImage");
imageView.setImageBitmap(photo);
The reference clearly states: The path to the file is contained in the Intent.mData field.
Therefore, you need
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, absPathUri));
You probably also need to let the broadcast complete before you get the results; using
imgView.post(new Runnable() { public void run() { imgView.setImageURI(absPathUri); } }
should suffice.

android bitmap from camera is just thumbnail size?

i am making an app of which it can initialize the camera and then after taking the photo, the photo could be imported and the user to further draw on it.
Coding:
Class A:
public OnClickListener cameraButtonListener = new OnClickListener()
{
#Override
public void onClick(View v)
{
vibrate();
Toast.makeText(Doodlz.this, R.string.message_initalize_camera, Toast.LENGTH_SHORT).show();
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
};
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK)
{
Bitmap photo = (Bitmap) data.getExtras().get("data");
Bitmap photocopy = photo.copy(Bitmap.Config.ARGB_8888, true);
doodleView.get_camera_pic(photocopy);
}
}
doodleView:
public void get_camera_pic (Bitmap photocopy)
{
// get screen dimension first
WindowManager wm = (WindowManager) context_new.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
final int screenWidth = display.getWidth();
final int screenHeight = display.getHeight();
bitmap = photocopy;
bitmap = Bitmap.createScaledBitmap(bitmap, screenWidth, screenHeight, true);
bitmapCanvas = new Canvas(bitmap);
invalidate(); // refresh the screen
}
Question:
The photo can be successfully captured using the camera and return to doodleView for user. Yet since the imported image dimension is very small, just a thumbnail size!! (dont know why), so I tired scaling it up and then the resolution is very poor.
My question is that, how modify the above code so as to set the photo taken dimension be fitting to the screen's dimension and the returned photo be 1:1 of the screen instead of getting like a thumbnail one? (best to be fit 1:1 of screen, because if it is then importing as original photo size the photo dimension is then greater then the screen, it then need to scale down and distorted by different ratio of width and height ratio to fit full screen)
Thanks!!
This is normal for the default camera application. The way to get the full size image is to tell the camera activity to put the result into a file. First create a file and then start the camera application as follows:
outputFileName = createImageFile(".tmp");
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outputFileName));
startActivityForResult(takePictureIntent, takePhotoActionCode);
Then in your onActivityResult, you can get this image file back and manipulate it.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == takePhotoActionCode)
{
if (resultCode == RESULT_OK)
{
// NOTE: The intent returned might be NULL if the default camera app was used.
// This is because the image returned is in the file that was passed to the intent.
processPhoto(data);
}
}
}
processPhoto will look a bit like this:
protected void processPhoto(Intent i)
{
int imageExifOrientation = 0;
// Samsung Galaxy Note 2 and S III doesn't return the image in the correct orientation, therefore rotate it based on the data held in the exif.
try
{
ExifInterface exif;
exif = new ExifInterface(outputFileName.getAbsolutePath());
imageExifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
}
catch (IOException e1)
{
e1.printStackTrace();
}
int rotationAmount = 0;
if (imageExifOrientation == ExifInterface.ORIENTATION_ROTATE_270)
{
// Need to do some rotating here...
rotationAmount = 270;
}
if (imageExifOrientation == ExifInterface.ORIENTATION_ROTATE_90)
{
// Need to do some rotating here...
rotationAmount = 90;
}
if (imageExifOrientation == ExifInterface.ORIENTATION_ROTATE_180)
{
// Need to do some rotating here...
rotationAmount = 180;
}
int targetW = 240;
int targetH = 320;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(outputFileName.getAbsolutePath(), bmOptions);
int photoWidth = bmOptions.outWidth;
int photoHeight = bmOptions.outHeight;
int scaleFactor = Math.min(photoWidth/targetW, photoHeight/targetH);
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap scaledDownBitmap = BitmapFactory.decodeFile(outputFileName.getAbsolutePath(), bmOptions);
if (rotationAmount != 0)
{
Matrix mat = new Matrix();
mat.postRotate(rotationAmount);
scaledDownBitmap = Bitmap.createBitmap(scaledDownBitmap, 0, 0, scaledDownBitmap.getWidth(), scaledDownBitmap.getHeight(), mat, true);
}
ImageView iv2 = (ImageView) findViewById(R.id.photoImageView);
iv2.setImageBitmap(scaledDownBitmap);
FileOutputStream outFileStream = null;
try
{
mLastTakenImageAsJPEGFile = createImageFile(".jpg");
outFileStream = new FileOutputStream(mLastTakenImageAsJPEGFile);
scaledDownBitmap.compress(Bitmap.CompressFormat.JPEG, 75, outFileStream);
}
catch (Exception e)
{
e.printStackTrace();
}
}
One thing to note is that on Nexus devices the calling activity is not normally destroyed. However on Samsung Galaxy S III and Note 2 devices the calling activity is destroyed. Therefore the just storing the outputFileName as a member variable in the Activity will result in it being null when the camera app returns unless you remember to save it when the activity dies. It's good practice to do that anyhow, but this is a mistake that I've made before so I thought I'd mention it.
EDIT:
Regarding your comment, the createImageFile is a not in the standard API, it's something I wrote (or I may have borrowed :-), I don't remember), here is the method for createImageFile():
private File createImageFile(String fileExtensionToUse) throws IOException
{
File storageDir = new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES
),
"MyImages"
);
if(!storageDir.exists())
{
if (!storageDir.mkdir())
{
Log.d(TAG,"was not able to create it");
}
}
if (!storageDir.isDirectory())
{
Log.d(TAG,"Don't think there is a dir there.");
}
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "FOO_" + timeStamp + "_image";
File image = File.createTempFile(
imageFileName,
fileExtensionToUse,
storageDir
);
return image;
}
To access the full image, you either need to access the intent URI by using data.getData() in your doodleView, or (better) provide your own URI for storing the image by passing it to the intent by supplying a URI in EXTRA_OUTPUT extra.

Categories

Resources