I need to crop image, to square. I use that function:
private void crop(Uri imageUri) {
File photoGallery = new File(Environment.getExternalStorageDirectory(), "temp_image.jpg");
checkImageSize(photoGallery);
Intent cropIntentGallery = new Intent("com.android.camera.action.CROP");
cropIntentGallery.setDataAndType(imageUri, "image/*");
cropIntentGallery.putExtra("crop", true);
cropIntentGallery.putExtra("aspectX", 1);
cropIntentGallery.putExtra("aspectY", 1);
cropIntentGallery.putExtra("outputX", PHOTO_SIZE);
cropIntentGallery.putExtra("outputY", PHOTO_SIZE);
cropIntentGallery.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoGallery));
startActivityForResult(cropIntentGallery, REQ_EDIT_CAMERA);
}
And it opens crop activity, but I can change X and Y size.
What I need is to fix smallest dimension, so if image was made in landscape mode - user will be able to cut left or/and right edges, if in portrait - top or/and bottom edges.
Is there are some extra parameter to do this?
BTW, where I can find list of all possible intent extras? (like: "aspectX", "outputX"...)
Related
I'm developing Photoshop type app in which crop tools is using to crop image and i'm using default crop intent, when i cropped image i get bundle in which i got Rect(0,0-2,122) left,top,right,bottom but my point is when i cropped first time and again i cropped the cropper show its previously cropped area not default area and in crop intent.
CropIntent.putExtra("outputX", imageWidth);
CropIntent.putExtra("outputY", imageHeight);
CropIntent.putExtra("aspectX", 100);
CropIntent.putExtra("aspectY", -100);
CropIntent.putExtra("spotlightX", 10);
CropIntent.putExtra("spotlightY", -10);
I pass l,t,r,b like this, i know this is wrong but i tried aspect x and aspect y are ratios but spot light is what, i don't know. can i place cropper at previously cropped area on same image.
You can use this library from here
and use below method two recover the ratio on the image and call it where your image is to be cropped and remember when Activity is switched do not finish it.
public void updateCurrentCropViewOptions() {
CropImageViewOptions options = new CropImageViewOptions();
options.scaleType = mCropImageView.getScaleType();
options.cropShape = mCropImageView.getCropShape();
options.guidelines = mCropImageView.getGuidelines();
options.aspectRatio = mCropImageView.getAspectRatio();
options.fixAspectRatio = mCropImageView.isFixAspectRatio();
options.showCropOverlay = mCropImageView.isShowCropOverlay();
options.showProgressBar = mCropImageView.isShowProgressBar();
options.autoZoomEnabled = mCropImageView.isAutoZoomEnabled();
options.maxZoomLevel = mCropImageView.getMaxZoom();
options.flipHorizontally = mCropImageView.isFlippedHorizontally();
options.flipVertically = mCropImageView.isFlippedVertically();
}
I would like to confirm that what I am doing is indeed the correct way as some elements behave unexpected.
First, I have a landscape and portrait layout, as I understand, doing this will automatically detect if the phone is in portrait/landscape mode:
- layout
- activity_video_player.xml
- layout-land
- activity_video_player.xml
Then when the user selects a video from the gallery, I check if the video was taking in landscape or portrait, by doing this (inside OnCreate):
int w;
int h;
MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
mediaMetadataRetriever.setDataSource(this, videoURI);
String height = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
String width = mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
w = Integer.parseInt(width);
h = Integer.parseInt(height);
if (w > h) {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
} else {
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
I have tested this and it works fine, but I noticed some of my xml elements (play button) is placed incorrectly.
So my app flow is:
MainActivity --> SelectvidButton --> Gallery Intent --> VideoPlayActivity
My Question
Is this the correct way of doing this and if it is, is there any reason why some of the xml elements get placed incorrectly?
EDIT 1:
I noticed that this only happens when the activity is launched for the first time, if I press the back button and select the same video again, the layout is perfectly like I want it to be.
EDIT 2:
I have also noticed that this only happens if the previous activity (MainActivity) was in the same orientation than what the selected video is.
Here is what I ended up doing.
Instead of using MediaMetadataRetriever to get the width and height, I first retrieve a Bitmap from the video file and then setting the orientation according to the width and hight of the Bitmap, as shown below:
private void rotateScreen() {
try {
//Create a new instance of MediaMetadataRetriever
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
//Declare the Bitmap
Bitmap bmp;
//Set the video Uri as data source for MediaMetadataRetriever
retriever.setDataSource(this, mVideoUri);
//Get one "frame"/bitmap - * NOTE - no time was set, so the first available frame will be used
bmp = retriever.getFrameAtTime();
//Get the bitmap width and height
videoWidth = bmp.getWidth();
videoHeight = bmp.getHeight();
//If the width is bigger then the height then it means that the video was taken in landscape mode and we should set the orientation to landscape
if (videoWidth > videoHeight) {
//Set orientation to landscape
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
//If the width is smaller then the height then it means that the video was taken in portrait mode and we should set the orientation to portrait
if (videoWidth < videoHeight) {
//Set orientation to portrait
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
} catch (RuntimeException ex) {
//error occurred
Log.e("MediaMetadataRetriever", "- Failed to rotate the video");
}
}
Am creating a document scanning application in android, am using OpenCV and Scan library in my project for cropping,I have created a rectangle using drawrect in camera view, now I need to capture the images inside that rectangle portion only and display it in another activity.
The image in question:
For me , I will take whole image, then crop.
Your question : "how do I know which part of the image is inside the rectangular portion, then only I can pass it nah, hope u understood". My answer is you can using relativity scaling of whole image dimension and camera display screen dimension. Then you will know which part of rectangular to be cropped.
This is the code example.
Note that you need to fill some codes to make it can save file into jpg, and save it after cropped.
// 1. Save your bitmap to file
public class MyPictureCallback implements Camera.PictureCallback {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
//mPictureFile is a file to save the captured image
FileOutputStream fos = new FileOutputStream(mPictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
}
}
}
// Somewhere in your code
// 2.1 Load bitmap from your .jpg file
Bitmap bitmap = BitmapFactory.decodeFile(path+"/mPictureFile_name.jpg");
// 2.2 Rotate the bitmap to be the same as display, if need.
... Add some bitmap rotate code
// 2.3 Size of rotated bitmap
int bitWidth = bitmap.getWidth();
int bitHeight = bitmap.getHeight();
// 3. Size of camera preview on screen
int preWidth = preview.getWidth();
int preHeight = preview.getHeight();
// 4. Scale it.
// Assume you draw Rect as "canvas.drawRect(60, 50, 210, 297, paint);" command
int startx = 60 * bitWidth / preWidth;
int starty = 50 * bitHeight / preHeight;
int endx = 210 * bitWidth / preWidth;
int endy = 297 * bitHeight / preHeight;
// 5. Crop image
Bitmap blueArea = Bitmap.createBitmap(bitmap, startx, starty, endx, endy);
// 6. Save Crop bitmap to file
This will work for you: How to programmatically take a screenshot in Android?
Make sure that the view (v1 in the code sample's case) passed in Bitmap.createBitmap(v1.getDrawingCache()) is a viewgroup that contains the image you want ot send to the second activity
Edit:
I don't think your intended flow is feasible. As far as I know, camera intents don't take arguments allowing to draw such a rectangle (I could be wrong though).
Instead, I suggest you take a picture, and then edit it with a library such as this one (https://github.com/ArthurHub/Android-Image-Cropper) or programatically as suggested above.
I use camera to click image(object) in the app, after clicking the photo, I want to know the height and width of the object.
Please guide me.
Create Bitmap first in onActivityResult method then get height and width of bitmap
java.io.File file = new java.io.File(
this.application.getDirectory(),
this.application.getFileName());
if (file.exists()) {
Bitmap bitmapPhoto = BitmapFactory.decodeFile(outputPath);
height = bitmapPhoto.getHeight();
width = bitmapPhoto.getWidth()
}
I got what you need,
Firstly you have to integrate Opencv Library into your application, Then use Object detection in OpenCv, You have to click on the object you need to measure(height,width);
By using below formula you can get all you need.
realWorldHeight = rect.size().height / imageMat.size().height * realWorldDistanceToObject * Math.cos( realWorldAngleOfObjectHeight / 2);
I have a code in which I call the gallery to select an image that i show in a imageview . This works fine and maintains the aspect ratio.
The problem is when the image size is larger than 2048 x 2048
I am using this code when it is the case:
uriIsNowAbitmap =
MediaStore.Images.Media.getBitmap(this.getContentResolver(),
selectedImageUri);
//...
int height = uriIsNowAbitmap.getHeight();
int width = uriIsNowAbitmap.getWidth();
if ((width>=2048)||(height>=2048)) {
int newheight = height/10; // height in pixels
int newwidth = width/10; // width in pixels
Bitmap avatarScaled = Bitmap.createScaledBitmap(uriIsNowAbitmap, newwidth, newheight, true);
previewNewAvatar.setImageBitmap(avatarScaled);
}
also works correctly, but with a problem. The images are not of the type shown rotated landscape
to try to explain, I put this example. This is the picture of the gallery:
when I select the picture and assign it to the imageview is shown rotated:
I do not understand why. I've tried a thousand ways and have read a lot of information about resize, i have read threads and sample code for this website (Android: high quality image resizing / scaling) and and many more... but nothing helps.
The intention is to show in this way ...make it with photoshop :)
I appreciate any help, took many hours trying to fix it
Regards
Firstly, you will have to detect the orientation change, and when you detect a change to landscape orientation you just rotate your bitmap accordingly. You will have to declare your Bitmap avatarScaled as a global variable in order to access it in the onConfigurationChanged() method below:
Use the onConfigurationChanged method of Activity to detect change in orientation. See the following code:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotated = Bitmap.createBitmap(avatarScaled, 0, 0, avatarScaled.getWidth(),
avatarScaled.getHeight(), matrix, true);
previewNewAvatar.setImageBitmap(rotated);
}
}
You also have to edit the appropriate element in your manifest file to include the android:configChanges Just see the code below:
<activity android:name=".MyActivity"
android:configChanges="orientation|keyboardHidden"
android:label="#string/app_name">