]> Pileus Git - ~andy/freeotp/blob - src/com/google/zxing/common/PerspectiveTransform.java
Add native camera support
[~andy/freeotp] / src / com / google / zxing / common / PerspectiveTransform.java
1 /*
2  * Copyright 2007 ZXing authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.google.zxing.common;
18
19 /**
20  * <p>This class implements a perspective transform in two dimensions. Given four source and four
21  * destination points, it will compute the transformation implied between them. The code is based
22  * directly upon section 3.4.2 of George Wolberg's "Digital Image Warping"; see pages 54-56.</p>
23  *
24  * @author Sean Owen
25  */
26 public final class PerspectiveTransform {
27
28   private final float a11;
29   private final float a12;
30   private final float a13;
31   private final float a21;
32   private final float a22;
33   private final float a23;
34   private final float a31;
35   private final float a32;
36   private final float a33;
37
38   private PerspectiveTransform(float a11, float a21, float a31,
39                                float a12, float a22, float a32,
40                                float a13, float a23, float a33) {
41     this.a11 = a11;
42     this.a12 = a12;
43     this.a13 = a13;
44     this.a21 = a21;
45     this.a22 = a22;
46     this.a23 = a23;
47     this.a31 = a31;
48     this.a32 = a32;
49     this.a33 = a33;
50   }
51
52   public static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0,
53                                                                   float x1, float y1,
54                                                                   float x2, float y2,
55                                                                   float x3, float y3,
56                                                                   float x0p, float y0p,
57                                                                   float x1p, float y1p,
58                                                                   float x2p, float y2p,
59                                                                   float x3p, float y3p) {
60
61     PerspectiveTransform qToS = quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
62     PerspectiveTransform sToQ = squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
63     return sToQ.times(qToS);
64   }
65
66   public void transformPoints(float[] points) {
67     int max = points.length;
68     float a11 = this.a11;
69     float a12 = this.a12;
70     float a13 = this.a13;
71     float a21 = this.a21;
72     float a22 = this.a22;
73     float a23 = this.a23;
74     float a31 = this.a31;
75     float a32 = this.a32;
76     float a33 = this.a33;
77     for (int i = 0; i < max; i += 2) {
78       float x = points[i];
79       float y = points[i + 1];
80       float denominator = a13 * x + a23 * y + a33;
81       points[i] = (a11 * x + a21 * y + a31) / denominator;
82       points[i + 1] = (a12 * x + a22 * y + a32) / denominator;
83     }
84   }
85
86   /** Convenience method, not optimized for performance. */
87   public void transformPoints(float[] xValues, float[] yValues) {
88     int n = xValues.length;
89     for (int i = 0; i < n; i ++) {
90       float x = xValues[i];
91       float y = yValues[i];
92       float denominator = a13 * x + a23 * y + a33;
93       xValues[i] = (a11 * x + a21 * y + a31) / denominator;
94       yValues[i] = (a12 * x + a22 * y + a32) / denominator;
95     }
96   }
97
98   public static PerspectiveTransform squareToQuadrilateral(float x0, float y0,
99                                                            float x1, float y1,
100                                                            float x2, float y2,
101                                                            float x3, float y3) {
102     float dx3 = x0 - x1 + x2 - x3;
103     float dy3 = y0 - y1 + y2 - y3;
104     if (dx3 == 0.0f && dy3 == 0.0f) {
105       // Affine
106       return new PerspectiveTransform(x1 - x0, x2 - x1, x0,
107                                       y1 - y0, y2 - y1, y0,
108                                       0.0f,    0.0f,    1.0f);
109     } else {
110       float dx1 = x1 - x2;
111       float dx2 = x3 - x2;
112       float dy1 = y1 - y2;
113       float dy2 = y3 - y2;
114       float denominator = dx1 * dy2 - dx2 * dy1;
115       float a13 = (dx3 * dy2 - dx2 * dy3) / denominator;
116       float a23 = (dx1 * dy3 - dx3 * dy1) / denominator;
117       return new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0,
118                                       y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0,
119                                       a13,                a23,                1.0f);
120     }
121   }
122
123   public static PerspectiveTransform quadrilateralToSquare(float x0, float y0,
124                                                            float x1, float y1,
125                                                            float x2, float y2,
126                                                            float x3, float y3) {
127     // Here, the adjoint serves as the inverse:
128     return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();
129   }
130
131   PerspectiveTransform buildAdjoint() {
132     // Adjoint is the transpose of the cofactor matrix:
133     return new PerspectiveTransform(a22 * a33 - a23 * a32,
134         a23 * a31 - a21 * a33,
135         a21 * a32 - a22 * a31,
136         a13 * a32 - a12 * a33,
137         a11 * a33 - a13 * a31,
138         a12 * a31 - a11 * a32,
139         a12 * a23 - a13 * a22,
140         a13 * a21 - a11 * a23,
141         a11 * a22 - a12 * a21);
142   }
143
144   PerspectiveTransform times(PerspectiveTransform other) {
145     return new PerspectiveTransform(a11 * other.a11 + a21 * other.a12 + a31 * other.a13,
146         a11 * other.a21 + a21 * other.a22 + a31 * other.a23,
147         a11 * other.a31 + a21 * other.a32 + a31 * other.a33,
148         a12 * other.a11 + a22 * other.a12 + a32 * other.a13,
149         a12 * other.a21 + a22 * other.a22 + a32 * other.a23,
150         a12 * other.a31 + a22 * other.a32 + a32 * other.a33,
151         a13 * other.a11 + a23 * other.a12 + a33 * other.a13,
152         a13 * other.a21 + a23 * other.a22 + a33 * other.a23,
153         a13 * other.a31 + a23 * other.a32 + a33 * other.a33);
154
155   }
156
157 }