how to crop image to square - android? - android

so i have a profile activity with a profile image. Now the image that was taken vertically. And I have horizontal image views. When i grab images onActivityResult() how do i "square" the image. By square the image, I mean, I want each image's width to be the width of the screen (and since its a square, height = image width = screen width).
In onActivityResult() i get the image from my gallery and camera back as a string path (which i can convert to a bitmap). Additionally, when i get images i get them from my backend using the Glide library and a url.
Glide.with(context).load("www.mybackendToImagePath").centerCrop().into(newImageView);
So, I need to convert that image path into a bitmap and then somehow square that bitmap with my screen's width. I'm not sure what code allows me to:
get the dimensions of the device.
transform's the image's width and height, to the width of the device.
Hope you guys can help!
Heres what my profile activity looks like.

You can use this https://github.com/Yalantis/uCrop library to crop image you get from camera or gallery. Include the library as local library project
allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
Add Dependencies
compile 'com.github.yalantis:ucrop:2.2.1'
or
compile 'com.github.yalantis:ucrop:2.2.1-native'
Add UCropActivity into your AndroidManifest.xml
<activity
android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="portrait"
android:theme="#style/Theme.AppCompat.Light.NoActionBar"/>
Now pass the URI of your image as sourceUri in following code and destinationUri will be where you want to place your cropped image
UCrop.of(sourceUri, destinationUri)
.withAspectRatio(1, 1)//1, 1 is the ratio b/w width and height of image i.e. square you can pass any ratio here
.withMaxResultSize(maxWidth, maxHeight)
.start(context);
Override onActivityResult method and handle uCrop result.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == UCrop.REQUEST_CROP) {
final Uri resultUri = UCrop.getOutput(data);
} else if (resultCode == UCrop.RESULT_ERROR) {
final Throwable cropError = UCrop.getError(data);
}
}

Related

How to rotate picasso url image based on exif

images loaded using picasso.get().load(url) are rotated. I tried to use .apply { rotate(90F) } which does rotation for all images loaded from URL.
if the picture is taken in portait, rotating 90 works fine but if the image is taken in landscape this does not work.
Is there a way I could rotate picasso image based on exif.
this is the code I have at the moment
Picasso.get().load(url)
.apply { placeholderRes?.let { placeholder(it) } }
.apply { if (resizeWidthRes != null && resizeHeightRes != null) resizeDimen(resizeWidthRes, resizeHeightRes) }
.apply { if (convertToCircle) transform(CircleTransformation()) }
.apply { rotate(90F) } //DOES NOT WORK FOR LANDSCAPE PICTURES
.into(imageView)
Picture taken in landscape
Picture loaded in image view which is roatated
Any suggestions on how to use exif and rotate picasso image from url would be very helpful
Thanks
R

Cropped area rectangle show where previously cropped area like whats app

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();
}

Correctly download and display image from server

Now, in my app, each placeholder has size, that was set in xml and after image was downloaded it resizes ImageView height with horrible visual effect.
How can I get image size, that is downloading and should be displayed in
ImageView, to make the same placeholder size like in Facebook application live feed? Maybe I should include image ratio for each link in json file that is downloading from server, or Fresco, Glide or Picasso has some tricks to acheive this?
If you want to resize the placeholder to the actual image dimensions before downloading the image, you have to somehow get this information from your server. You could, like you've already suggested, include the image dimensions / aspect ratio to the request and then use that information to properly size your views upfront.
Because of this horrible visual effect you've mentioned, Fresco doesn't support wrap_content but it supports setting an aspect ratio for the DraweeView that you can set using your server data.
See also http://frescolib.org/docs/wrap-content.html
Try using ResourceTranscoder with glide request as mentioned below:
Glide
.with(this)
.load(imageUrl)
.asBitmap()
.transcode(new BitmapSizeTranscoder(), Size.class)
.into(new SimpleTarget<Size>() {
#Override public void onResourceReady(Size size, GlideAnimation glideAnimation) {
Log.w("SIZE", String.format(Locale.ENGLISH, "%dx%d", size.width, size.height));
}
});
class Size {
int width;
int height;
}
class BitmapSizeTranscoder implements ResourceTranscoder<Bitmap, Size> {
#Override public Resource<Size> transcode(Resource<Bitmap> toTranscode) {
Bitmap bitmap = toTranscode.get();
Size size = new Size();
size.width = bitmap.getWidth();
size.height = bitmap.getHeight();
return new SimpleResource<>(size);
}
#Override public String getId() {
return getClass().getName();
}
}

Image from path wont load

I got this listener:
#Override
public void onClick(View v) {
showDialog();
ImageButton currentButton = (ImageButton)v;
Bitmap bmp = BitmapFactory.decodeFile(mCurrentPhotoPath);
currentButton.setImageBitmap(bmp);
}
Image is successfully taken in showDialog() but after this it wont set to imageButton. It goes white. The path generated is:
file:/storage........../filename.jpg amd its saved in mCurrentPhotoPath
I tried setting image from drawable after shot is made just to try it and it works. For some reason i cant set the image to the ImageButton.Do i have to resize it(photo is made full sized)?
Following THIS tutorial i did this:
#Override
public void onClick(View v) {
showDialog((ImageButton)v);
setPic((ImageButton)v);
}
private void setPic(ImageButton mImageView) {
if (shotFired){
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath,bmOptions);
mImageView.setImageBitmap(bitmap);
mImageView.setTag(mCurrentPhotoPath);
shotFired=false;
}
Seems if i calll setPic() without making a new shot and just call the old one ive made it works. Must be something in timing...I need to get this thing working.
If you are using camera for taking the picture to set it to ImageView, then you need to set the image in onActivityResult() after the image is captured using camera.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
//set the image to imageView
} else if (resultCode == Activity.RESULT_CANCELED) {
//image was not taken
//show some error message
}
}
i believe you problem is because of outOfMEmory problem that normaly happens when loading a bitmap into the memory.
the best practice to load bitmaps in android is to find the bitmap dimensions before you load it. then loading a suitable size of the bitmap depend on your device memory size and screen size.
i highly recommend you to read this great tutorial in develope.android website. this will help you to get a complete sens about how bitmaps works and whats the best practice to load them also source code is included. please go through all these tutorials.
https://developer.android.com/training/displaying-bitmaps/index.html
https://developer.android.com/training/displaying-bitmaps/load-bitmap.html
https://developer.android.com/training/displaying-bitmaps/process-bitmap.html
https://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
https://developer.android.com/training/displaying-bitmaps/manage-memory.html
https://developer.android.com/training/displaying-bitmaps/display-bitmap.html
i suggest you to read these links but if you nor intersted you can use libraries like Glide or Piccasso for loading your bitmap. they will help you to load without an OutOfMemoty Error.

Resizing a bitmap that automatically rotates

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">

Categories

Resources