Sanchit Paurush
Sanchit Paurush

Reputation: 6152

Image Straightening in Android

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.

enter image description here

enter image description here

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

Answers (2)

jodag
jodag

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.

enter image description here

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

vilanovi
vilanovi

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

Related Questions