I am Doing a program in which we are taking photos using camera a storing it in a private folder.From that it fetching images and displaying it in a grid view.on Clicking the grid view it showing the fullscreen image.
The trouble i am facing is when the camera is in portrait mode the image quality is perfect.But If the camera is in landscape mode it showing streched image How can i overcome this.
Hi have a look at this below code. before saving your captured image do the following process. it will save the images in portrait mode. hope this will help you.
int rotation = -1;
rotation = ((WindowManager)getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay().getOrientation();
Matrix rotator = new Matrix();
switch (rotation) {
case (Surface.ROTATION_0):
break;
case (Surface.ROTATION_90):
rotator.postRotate(270);
break;
case (Surface.ROTATION_180):
rotator.postRotate(180);
break;
case (Surface.ROTATION_270):
rotator.postRotate(90);
break;
// screen_{width,height} are applied before the rotate, so we don't
// need to change them based on rotation.
bmp_ss = Bitmap.createBitmap(bmp_ss, 0, 0, screen_width, screen_height, rotator, false);
Related
I don't want to support landscape UI at all across my app, but I want to be able to automatically rotate the photos users take in landscape mode.
Currently if a user takes a photo in landscape mode, it remains on screen as if it was taken in portrait (the horizon in the photo is vertical).
I've tried to get the orientation from the system like this:
val display = (getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
val screenOrientation = display.rotation
Log.d("orientation", screenOrientation.toString())
But it doesn't work and just gives back 0 every time.
I've tried a few other solutions but couldn't get them to work.
I am wondering, am I wasting my time trying to figure this out? Is it even possible to know the orientation in which the photo was captured if my activity only operates in portrait mode?
There are a few articles out there talking about camera orientation but they don't talk about whether the orientation in their activity is locked or not.
Thank you.
//Yes, find the Orientation Using ExifInterface
try{
File imageFile = new File(imagePath);
ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
// dont know exactly but, orientation for landscape may be 180 or 270.
// From the orientation value you can convert image according to orientation and can be set it vertically, horrizentally as below
int rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
Log.e(Common.TAG, "Exif orientation: " + orientation);
}
catch (Exception e) {
e.printStackTrace();
}
// Now Change image as your wish...
// Image rotation //
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
Bitmap cropped = Bitmap.createBitmap(scaled, x, y, width, height, matrix, true);
When we will trying to record the video using MediaRecorder video is recorded properly in android and in device it will display as like recording, but when we can play video in VLC or other player in Desktop that time it will rotate the video and it will not display properly.
and i can set the MediaRecorder setOrientationHint to 90 degree.
what's the problem for changing the orientation and Why?
we Can not directly apply fix orientation while capturing video. I mean to say that you used fix 90 degree orientation in MediaRecorder setOrientationHint. you need to set setOrientationHint(dynamic degree);
First of all you need to get display rotation and get angle using display rotation. after then set That Degree to setOrientationHint method. That will work for all. Here is code.
Display display = getWindowManager().getDefaultDisplay();
int mDisplayRotation = display.getRotation();
public int getDisplayOrientationAngle() {
Log.e("", "setDisplayOrientationAngle is call");
int angle;
// switch (MeasurementNativeActivity.DisplayRotation) {
switch (mDisplayRotation) {
case Surface.ROTATION_0: // This is display orientation
angle = 90; // This is camera orientation
break;
case Surface.ROTATION_90:
angle = 0;
break;
case Surface.ROTATION_180:
angle = 270;
break;
case Surface.ROTATION_270:
angle = 180;
break;
default:
angle = 90;
break;
}
Log.v("", "media recorder displayRotation: " + mDisplayRotation);
Log.v("", "media recorder angle: " + angle);
return angle;
}
mMediaRecorder.setOrientationHint(getDisplayOrientationAngle());
Extracted from the Android Documentation for MediaRecorder's setOrientationHint(int degrees) function:
This method will not trigger the source video frame to rotate during video recording, but to add a composition matrix containing the rotation angle in the output video if the output format is OutputFormat.THREE_GPP or OutputFormat.MPEG_4 so that a video player can choose the proper orientation for playback.
To sum it up, setOrientationHint just adds some sort of header to the video file that "tells" video players that they should rotate the video when playing it. In my experience, VLC player ignores this header and plays the video as it was recorded.
The only workaround I can think of would be to post-process the video by rotating it to your needs, although it seems quite a bad decision resource-wise.
I am having a service in which I have to capture image without a surfaceView, everything is working perfect except the result image orientation, which I found to be miss-angled. On small device like HTC, I found it having issue or rotation so set rotation manually to see it working and it worked.
if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
parameters.setRotation(270);
} else if (camInfo.facing ==
Camera.CameraInfo.CAMERA_FACING_BACK) {
parameters.setRotation(90);
}
But when checking over samsung and HTC one (large devices) it creates problem with the angle. I found some posts where there I have to put the image path and then try to set the rotation, but that didn't work for me i.e. this as I am taking picture without serfaceview and then immediately posting it to the server. I also tried the google portion of code for setCameraOrientation() but it requires the activity view to work and so I am failed there too.
All I need is to fix the angle of the image before sent to the server without any surfaceview or activity thing.
setRotation() may only choose to play with the EXIF flags. The result is an image which is still rotated 90°, but with a "flag" that describes the correct orientation. Not all viewers correctly account for this flag. Specifically, BitmapFactory ignores it. You can draw the bitmap rotated on a canvas, or rotate the bitmap acquired from BitmapFactory.decodeFile(), or manipulate the JPEG data before writing it into outStream using a 3rd party lib, e.g. MediaUtil. The Android port is on GitHub.
You can have access to the image orientation information through the ExifInterface object. It will give you different values depending on the phone and if you capture the image in Landscape or Portrait mode. You can then use a matrix to rotate the image according to the ExifInterface information.And finally send it to your server.
Knowing the path of your image ( imagePath ), use the following code:
Matrix matrix = new Matrix();
try{
ExifInterface exif = new ExifInterface(imagePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
// Change the image orientation
matrix.postRotate(90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
// Change the image orientation
matrix.postRotate(180);
break;
}catch (IOException e) {
e.printStackTrace();
}
Then you use your matrix object in order to rotate your bitmap using:
rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),matrix, true);
You would have to save the bitmap somewhere ( external or internal temp storage ) before sending it to the server.
Hope it helps you.
Your rotation-setting code is a bit too simple, so it's possible that on some devices it'll do the wrong thing. It's not guaranteed that these are the right rotations - the correct answer is a function of your device's current orientation, and the orientation of the sensor on the device.
Take a look at the sample code for Camera.Parameters.setRotation:
public void onOrientationChanged(int orientation) {
if (orientation == ORIENTATION_UNKNOWN) return;
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
orientation = (orientation + 45) / 90 * 90;
int rotation = 0;
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
rotation = (info.orientation - orientation + 360) % 360;
} else { // back-facing camera
rotation = (info.orientation + orientation) % 360;
}
mParameters.setRotation(rotation);
}
If you don't have an activity, you'll have to figure out how to get the device's current orientation some other way, but you do need to include info.orientation in your calculation.
There are several stack overflow questions that deal with keeping the activity in a constant orientation, suggesting either to set android:screenOrientation (or this) or to deal with the configuration changes manually.
However, these answers do not solve the problem if one wants to keep the benefits of automatic layout for most of the views, but to keep one view in a constant orientation. For example I have one main view for the content (a bitmap) and optionally several "toolbars". When the device is rotated from portrait to landscape, I want the toolbars to re-layout automatically. On the other hand, the main content view has a bitmap, and this should rotate with the device. Here is a simple code I use in my onDraw:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Bitmap bm = ... // code to get a bitmap
if (bm != null) {
canvas.drawBitmap(bm,0,0,mPaint);
}
}
This obviously does not work as intended because when the device orientation changes, the view is relayout and its coordinate system rotates in this orientation change by 90 degrees with respect to the physical device. One way to compensate for that would be to use a Matrix-object to draw the bitmap with 90 degrees rotation if the device orientation has changed. However, then also the input coordinates would have to be changed in order to keep the view input points and the point on the bitmap in correspondence.
Therefore my question after this long explanation is: can I keep the view so that its coordinate system with respect to the device is not rotated when the orientation changes.
Here is a picture that expresses what I want and what I currently get (xy coordinate system for the view also illustrated).
Inside your activity in manifest xml use the screen orientation attribut with portrait value
Like
<activity
android:name=".YourActivityName"
android:screenOrientation="portrait" >
</activity>
I am not sure but you should try following
put one xml in layout folder which indicate portrait layout
create one folder named it layout-land
put xml which indicate landscape layout with same name as in layout folder
Android automatically take that layout from land-layout when you will rotate your screen to landscape.
Another way
Activity will be restarted when orientation is changed so make to layout for that activity and you can set layout to your activity as per orientation.
if (getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE)
{
setContentView(R.layout.landscape_layout);
}
else
{
setContentView(R.layout.portrait_layout);
}
Hope it will help you.
You can check the orientation and redraw your View after orientation will be changed
if (getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE)
{
//...
}
else
{
//...
}
Use this code in your Manifest
<uses-permission android:name="android.permission.SET_ORIENTATION"/>
<activity
android:name="com.package.MyActivity"
android:configChanges="keyboardHidden|orientation"
android:screenOrientation="portrait" >
</activity>
Well, first of all, you will not need two layouts.
Create only one xml with an image view and a layout which has property align parent bottom set to true.
Now as per the images you have provided, you want to rotate the image anticlockwise when your device is in landscape. For that , you can use my image rotation code :-
You can always check the rotation of the image using Matrix and rotate it accordingly.
This code goes in onCreate-->
The code below is to rotate the image when taken from camera or gallery. You can modify according to your needs. I have put comments below to simplify understanding.
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = false;
bmOptions.inPurgeable = true;
Bitmap cameraBitmap = BitmapFactory.decodeFile(filePath);//You convert your image view image here in a bitmap
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cameraBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
ExifInterface exif = new ExifInterface(filePath);
float rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
System.out.println(rotation);
float rotationInDegrees = exifToDegrees(rotation);
System.out.println(rotationInDegrees);
//These three lines below set the rotation.
//Put an if condition here to check device rotation and set the rotation of image view as per the device rotation.
//The line below will help you get device rotation.
//getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE
Matrix matrix = new Matrix();
matrix.postRotate(rotationInDegrees);//Here you set the rotation value in which you want your image view to be rotated
//If ends here
Bitmap scaledBitmap = Bitmap.createBitmap(cameraBitmap);
Bitmap rotatedBitmap = Bitmap.createBitmap(cameraBitmap , 0, 0, scaledBitmap .getWidth(), scaledBitmap .getHeight(), matrix, true);
FileOutputStream fos=new FileOutputStream(filePath);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
//this rotatedbitmap you can set in your image view
//onCreate Code Ends here.
//This function below is used to get rotation:-
private static float exifToDegrees(float exifOrientation) {
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) { return 90; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) { return 180; }
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) { return 270; }
return 0;
}
I'm planning to calculate disparity map by taking two pictures from the two back cameras of Evo 3D. However, I'm able to use only one camera. I tried different index.
index
0 gives me left camera (one of the back cameras)
1 gives me front camera
-1 gives me left camera (one of the back cameras).
I once got other camera using -1 index, but it's not working anymore. I'm using CameraBridgeViewBase.
I have seen on Google group of android-opencv that people have successfully used both cameras of Evo 3D phone. I want to know how to do it? Is there some other index? or is there some other way using which I can use this.
P.S. Native Camera doesn't work. (Android 4.0.3).
The stereoscopic camera ID in Android changed from 2 to 100 with the ICS upgrade. This is the constant used by the Android Camera.open call. I don't think there was ever any official way to get one camera or the other. You can only get one image or both images.
As the above answer suggests, I used 100 as the Camera Index, but it didn't work with OpenCV, so I tried using Android's Camera SDK, but got some errors. But as this is a part of HTC Open Sense SDK, I downloaded it on my Eclipse and used http://www.htcdev.com/devcenter/opensense-sdk/stereoscopic-3d/s3d-sample-code/ . I used the base file of S3D Camera Demo and added few more functions so that I could access the Camera image data and convert it to OpenCV Mat.
So I made few changes in onTouchEvent function in that code, and more code there.
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// toggle();
//Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
//startActivityForResult(cameraIntent, 1337);
int bufferSize = width * height * 3;
byte[] mPreviewBuffer = null;
// New preview buffer.
mPreviewBuffer = new byte[bufferSize + 4096];
// with buffer requires addbuffer.
camera.addCallbackBuffer(mPreviewBuffer);
camera.setPreviewCallbackWithBuffer(mCameraCallback);
break;
default:
break;
}
return true;
}
private final Camera.PreviewCallback mCameraCallback = new Camera.PreviewCallback() {
public void onPreviewFrame(byte[] data, Camera c) {
Log.d(TAG, "ON Preview frame");
img = new Mat(height, width, CvType.CV_8UC1);
gray = new Mat(height, width, CvType.CV_8UC1);
img.put(0, 0, data);
Imgproc.cvtColor(img, gray, Imgproc.COLOR_YUV420sp2GRAY);
String pixvalue = String.valueOf(gray.get(300, 400)[0]);
String pixval1 = String.valueOf(gray.get(300, 400+width/2)[0]);
Log.d(TAG, pixvalue);
Log.d(TAG, pixval1);
// to do the camera image split processing using "data"
}
};
The Image that you get from the camera is in YUV420s mode and I was initially having problems accessing the data as I had created a 4 channel Mat. Actually, it needs only 1 channel Mat.