Camera Intent Image Preview Orientation - java

I take an image in Android using the following Code:
File image = new File(this.images_object_dir, loadedObjekt.getFilename());
Uri uri = FileProvider.getUriForFile(this, FILE_PROVIDER, image);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, CAMERA_ACTIVITY_CODE);
In the camera intent, the image preview is always in portrait mode on my Huawei P20 Pro. On another test-device the preview image (the one where you can decide if you wanna retake the image) is stuck in the "inital" rotation as well which looks ugly. For instance, if you want to take an image in landscape mode, the preview gets flipped to portrait mode.
Is there a solution for this?

There are ~2 billion Android devices, spread across ~20,000 device models. There are dozens, if not hundreds, of pre-installed camera apps across those device models. There are plenty of other camera apps that the user can download and install.
Your code might start any of them.
In the camera intent, the image preview is always in portrait mode on my Huawei P20 Pro
That is the behavior of that one camera app out of hundreds.
On another test-device the preview image (the one where you can decide if you wanna retake the image) is stuck in the "inital" rotation as well which looks ugly.
That is the behavior of that one camera app out of hundreds.
There is no requirement for a camera app to behave that way. Of course, there is no requirement for a camera app to have preview images at all.
Is there a solution for this?
If you wish to use ACTION_IMAGE_CAPTURE, no. The behavior of those hundreds of camera apps is up to the developers of those camera apps, not you.
There are other options for taking pictures, such as using the camera APIs directly or using third-party libraries like Fotoapparat or CameraKit-Android.

Use ExifInterface to check the orientation of the image while decoding it. Then you rotate the image to get required image in proper orientation.
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
Bitmap decoded = BitmapFactory.decodeFile(filePath, options);
if (decoded == null) return null;
try {
ExifInterface exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
int rotation = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
rotation = 90;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
rotation = 270;
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
rotation = 180;
}
if (rotation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
Bitmap newBitmap = Bitmap.createBitmap(decoded, 0, 0, decoded.getWidth(),
decoded.getHeight(), matrix, true);
decoded.recycle();
Runtime.getRuntime().gc();
decoded = newBitmap;
}
} catch (IOException e) {
e.printStackTrace();
}
If you want to use support library in order to support devices with lower API levels, use the following dependency:
implementation 'com.android.support:exifinterface:27.1.1'
and import android.support.media.ExifInterface

Related

SetImageUri showing no Image

I want to let a image on my phone to show up in the Imageview. But in the ANdroid Studio emulator it is working but not on my own phone.
String imgPath = getIntent().getExtras().getString("imgPath");
System.out.println(imgPath);
if(!imgPath.equals("?"))
{
File img_file = new File(imgPath);
ImageView imgView = findViewById(R.id.show_image_war);
imgView.setImageURI(Uri.fromFile(img_file));
}
The path is /storage/emulated/0/imagesWarranty/img_MyWarranty_ID1.jpg . Both on the image in my phone and the path in my code where I get the image.
It might be issue of resolution. Even I was getting error of resolution while I was displaying image from uri.
I used below code and It worked for me :
Uri imageUri = Uri.parse(imagePath);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(new File(imageUri.getPath()).getAbsolutePath(), options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
if (imageHeight > 4096 || imageWidth > 4096) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(imageUri.toString(), opts);
viewHolder.imgAvatarLogoList3.setImageBitmap(bitmap);
} else {
Picasso.with(context)
.load(new File(imageUri.getPath())) // Uri of the picture
.into(viewHolder.imgAvatarLogoList3);
}
Addition to this answer [https://stackoverflow.com/a/48354307/9255006]
In that rotation bug define the image orientation for the image using ExifInterface.
Here is the code
private void SetOrientation(){
try {
ExifInterface exif=new ExifInterface(photoURI.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_UNDEFINED);
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { orientationInDegrees=90; }
else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { orientationInDegrees=180; }
else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { orientationInDegrees=270; }
else { orientationInDegrees=0; }
Toast.makeText(this, String.valueOf(orientationInDegrees), Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
}
You can then set this orientation to your image.
This happens when the image has a very high resolution that the system needs some additional milliseconds to display, and since this happens in the UI thread onDraw() of the image view will draw it as an empty.
The easiest way I found for this issue is to use the Picasso library this way:
Picasso.get().load(imgUri).fit().centerCrop()
.into(imageview);
The reason behind those two methods (fit(), centerCrop())
Is that fit make sure that the image fit the bound container and then crop the image which force the system to redraw the image but this time with the convenient resolution (because of fit and crop).

Image from ACTION_IMAGE_CAPTURE Rotated

I am trying to simply get an image from a phone's camera. Surprisingly, it returns rotated. I've scoured the internet for fixes and came across many solutions using ExifInterface, but it only works sometimes. It gets the orientation wrong seemingly randomly, as I merely recompile and see different results. I have found some people saying this is a fault of the class itself being bugged.
I found other solutions that require like two additional libraries and more java files to do the job, but that just seems ridiculous (and I am avoiding additional packages). How come images are rotated in the first place (in storage they are perfectly fine), and how hard can it possibly be to fix the issue? Also - rotating the Image View also works (and seems much easier than literally creating a rotated image), but I need to know by how much to rotate the view.
EDIT---- I realized that the image is consistently rotated 270 degrees clockwise from the orientation the image was taken in (inside the intent) if the back camera was used, and 90 degrees if the front camera was used. Thus I only really need a way to find out this orientation.
Intent called here:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = setUpPhotoFile();
mCurrentPhotoPath = photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
} catch (IOException ex) {
// Error occurred while creating the File
photoFile = null;
mCurrentPhotoPath = null;
}
// Continue only if the File was successfully created
if (photoFile != null) {
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
} else {
Toast noStorage = Toast.makeText(this, "Cannot access mounted storage.", Toast.LENGTH_SHORT);
noStorage.show();
}
}
}
Bitmap created here:
private void setPic() {
/* 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 scale = 1;
if (photoH > targetH|| photoW > targetW) {
scale = Math.max(
(int)Math.pow(2, (int) Math.ceil(Math.log(targetW /
(double) photoW)) / Math.log(0.5)),
(int)Math.pow(2, (int) Math.ceil(Math.log(targetH /
(double) photoH)) / Math.log(0.5)));
;
}
/* Set bitmap options to scale the image decode target */
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scale;
/* Decode the JPEG file into a Bitmap */
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
/*-----------How should I rotate bitmap/mImageView to correct orientation?*/
/* Associate the Bitmap to the ImageView */
mImageView.setImageBitmap(bitmap);
mImageView.setVisibility(View.VISIBLE);
}
The best solution I have found is this one:
https://www.samieltamawy.com/how-to-fix-the-camera-intent-rotated-image-in-android/
I post the link because I don't want all the credit.
Sami Eltamawy has written a function that rotate the image if its need to be rotated.
I try the code and is working on my devices that the image got rotated.

Android: Check Number of Faces Before Crop Image in Android

currently I am developing android application. In my application I need to crop image from gallery. However, before I allow the user to crop the image, I want to check whether there is face detected in the image or not.
Here is how I allow user to crop an image from gallery:
Intent pickImageIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickImageIntent.setType("image/*");
pickImageIntent.putExtra("crop", "true");
pickImageIntent.putExtra("noFaceDetection", true);
pickImageIntent.putExtra("aspectX", size);
pickImageIntent.putExtra("aspectY", size);
pickImageIntent.putExtra("outputX", size);
pickImageIntent.putExtra("outputY", size);
pickImageIntent.putExtra("scale", true);
pickImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, getImageUri());
pickImageIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
startActivityForResult(pickImageIntent, RESULT_LOAD_IMAGE);
Before I run above code, I want to do something like this:
imageWidth = myBitmap.getWidth();
imageHeight = myBitmap.getHeight();
myFace = new FaceDetector.Face[numberOfFace];
myFaceDetect = new FaceDetector(imageWidth, imageHeight,
numberOfFace);
numberOfFaceDetected = myFaceDetect.findFaces(myBitmap, myFace);
But I am confuse about how to do it. Anyone can help me? Thanks.

How to get a camera preview's pixels in Android?

I want to know how to get an array of pixels from the preview webcam (which I will run in a service). I've heard that the preview has to be displayed on a surface, but there will be no surface if I use a service.
I am very new to Android development, sorry for any misconceptions.
Thanks.
Parameters parameters = camera.getParameters();
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
parameters.setPreviewSize(640, 480);
camera.setDisplayOrientation(90);
}
camera.setParameters(parameters);
camera.setPreviewDisplay(cameraSurfaceHolder);
camera.startPreview();
previewing = true;

Rotating video taken in portrait mode

My app lets the user capture video:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_VIDEO_REQUEST);
or pics:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
In the case of the pics, I can tell whether they were taken in any mode other than landscape and then rotate them before I upload them to the web:
ExifInterface exif = new ExifInterface(fileName);
int exifOrientation = Integer.parseInt(exif.getAttribute(ExifInterface.TAG_ORIENTATION));
float rotate = 0;
switch (exifOrientation){
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
}
if(rotate > 0){
Bitmap bitmap = BitmapFactory.decodeFile(fileName);
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
OutputStream outStream = context.getContentResolver().openOutputStream(Uri.fromFile(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
}
How do I accomplish the same with video?
I do not seem to fully understand your question. Here are some questions that I thought would at least steer you in the right direction. Hope it helps
Do you want to rotate the video for playback with the MediaPlayer?
Do you want to change the hard code in the video file to make it play rotated everywhere?
Rotate buffered video orientation?
==================================================================================
This answer to question # 1:
//rotating a SurfaceView that contains the MediaPlayer
/*
Create a new MediaPlayer SurfaceView, then use the SurfaceHolder interface
*/
video = new SurfaceView();
video.getHolder().setType(SurfaceHolder.SURFACE_TYPE_NORMAL);
video.getHolder().lockCanvas().rotate(90);
This answer to question # 2:
As for changing the hard code of a video. I would advise to use a nice GUI video codec to rotate the video and it should save its settings. Otherwise you will have to access the source code from the decoder then your SOL with my advice.
This answer to question # 3:
The post below explains how you can rotate a buffered video and/or change its orientation settings for different modes.
Post here: Android VideoView orientation change with buffered video
==================================================================================
If this doesn't help you then I am sure it will help someone else, and good luck.

Categories

Resources