Reputation: 6152
I am working on a project where I need to implement Image Straightening. I have got an idea to do this. I am rotating the Image on SeekBar as -10 to +10 degrees. It is working by the white background is visible when I rotate. So, We need to implement zoom functionality also so that it looks like image straighten as shown in below. Please advice with your suggestions.
Sample code
float a = (float) Math.atan(bmpHeight/bmpWidth);
// the length from the center to the corner of the green
float len1 = (float) ((bmpWidth/2)/Math.cos(a-Math.abs(curRotate)));
// the length from the center to the corner of the black (^ = power)
float len2 = (float) Math.sqrt((bmpWidth/2)^2 + (bmpHeight/2)^2);
// compute the scaling factor
curScale = len2 / len1;
Matrix matrix = new Matrix();
matrix.postScale(curScale, curScale);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmaprotate, 0, 0, bmpWidth, bmpHeight, matrix, true);
mainImage.setImageBitmap(resizedBitmap);
Upvotes: 6
Views: 2039
Reputation: 22224
In the diagram below the green rectangle is the valid part of the rotated image. What we need to determine is the scaling factor which will make the green region the same size as the original image. We can see from the figure that this scaling factor is the ratio of len2
to len1
.
Using the diagram and some basic trigonometry we can find len1
and len2
. The following c-like pseudo code describes the solution.
// theta : the angle of rotation of the image
// width : the width (number of columns) of the image
// height : the height (number of rows) of the image
a = atan(height/width);
// the length from the center to the corner of green region
len1 = (width/2)/cos(a-abs(theta));
// the length from the center to the corner of original image
len2 = sqrt(pow(width/2,2) + pow(height/2,2));
// compute the scaling factor
scale = len2 / len1;
That's it. Assuming all the transformations are done with regard to the center of the image then simply scale the image by the value of scale
after performing the rotation.
Note: the equations provided assume height > width
. Otherwise replace width
with height
in the len1
equation.
Update: Amulya Khare has posted an example implementation here
Upvotes: 11
Reputation: 2117
Based on the solution from jodag, here a method to compute the straightening for iOS / OS X:
CG_INLINE CGAffineTransform CGAffineTransformMakeStraightening(CGSize size, CGFloat rotation)
{
CGAffineTransform transform = CGAffineTransformIdentity;
// Apply the rotation
transform = CGAffineTransformRotate(transform, rotation);
// theta : the angle of rotation of the image
// minSide: the min side of the size
CGFloat a = atan(size.height/size.width);
CGFloat minSide = MIN(size.width, size.height);
// the length from the center to the corner of the green
CGFloat len1 = (minSide/2)/cos(a-fabs(rotation));
// the length from the center to the corner of the black
CGFloat len2 = sqrt(pow(size.width/2, 2) + pow(size.height/2, 2));
// compute the scaling factor
CGFloat scale = len2 / len1;
// Apply the scale
transform = CGAffineTransformScale(transform, scale, scale);
return transform;
}
Upvotes: 3