6

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);
Sanchit Paurush
  • 6,114
  • 17
  • 68
  • 107

2 Answers2

11

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

jodag
  • 19,885
  • 5
  • 47
  • 66
  • Thanks for your valuable efforts and reply on the post. The application is crashing when I am trying to create bitmap with this scale – Sanchit Paurush Sep 18 '13 at 11:23
  • I'm not very familiar with Android programming, what packages are you using to perform the image rotation/translation? – jodag Sep 18 '13 at 15:38
  • It's possible I'm thinking of things at too low of a level when I say scale using matrix transforms, if you're using tools which already have a zoom features, you want to zoom in so that pixels are enlarged by a factor of `scale` – jodag Sep 18 '13 at 15:45
  • Ok. I have converted your algorithm in to android programming. But still I am not able to get the correct results. The image is getting distorted and changing completely. Not getting the correct image. – Sanchit Paurush Sep 19 '13 at 03:53
  • Just taking a brief look at your code, the ^ operator in Java is the bitwise XOR, I used it to represent power operator. Also, make sure the curRotate is in radians and not degrees. – jodag Sep 19 '13 at 16:29
  • Did anyone succeed using the formula posted above? For me the image is not scaling at all. I have defined a range of +10 to -10 degrees. – SoH Oct 21 '13 at 08:09
  • 2
    @SoH you need to convert your degree to radians theta = (float) Math.toRadians(theta); – user65721 Nov 22 '13 at 12:13
  • @sanchitsingh i have same requirement . im tried alot but not succeeded will you provide your source code? plz. – user512 Apr 11 '15 at 11:43
3

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;
}
vilanovi
  • 2,097
  • 2
  • 21
  • 25