git-svn-id: http://zxing.googlecode.com/svn/trunk@6 59b500cc-1b3d-0410-9834-0bbf25fbcc57
[zxing.git] / core / src / com / google / zxing / qrcode / detector / JAIPerspectiveTransform.java
1 package com.google.zxing.qrcode.detector;
2
3 /**
4  * TODO need to reimplement this from scratch. This is derived from jai-core from Sun
5  *  and it is not clear we can redistribute this modification.
6  */
7 final class JAIPerspectiveTransform {
8
9   private float m00, m01, m02, m10, m11, m12, m20, m21, m22;
10
11   JAIPerspectiveTransform() {
12     m00 = m11 = m22 = 1.0f;
13     m01 = m02 = m10 = m12 = m20 = m21 = 0.0f;
14   }
15
16   private void makeAdjoint() {
17     float m00p = m11 * m22 - m12 * m21;
18     float m01p = m12 * m20 - m10 * m22; // flipped sign
19     float m02p = m10 * m21 - m11 * m20;
20     float m10p = m02 * m21 - m01 * m22; // flipped sign
21     float m11p = m00 * m22 - m02 * m20;
22     float m12p = m01 * m20 - m00 * m21; // flipped sign
23     float m20p = m01 * m12 - m02 * m11;
24     float m21p = m02 * m10 - m00 * m12; // flipped sign
25     float m22p = m00 * m11 - m01 * m10;
26     // Transpose and copy sub-determinants
27     m00 = m00p;
28     m01 = m10p;
29     m02 = m20p;
30     m10 = m01p;
31     m11 = m11p;
32     m12 = m21p;
33     m20 = m02p;
34     m21 = m12p;
35     m22 = m22p;
36   }
37
38   private static void getSquareToQuad(float x0, float y0,
39                                       float x1, float y1,
40                                       float x2, float y2,
41                                       float x3, float y3,
42                                       JAIPerspectiveTransform tx) {
43     float dx3 = x0 - x1 + x2 - x3;
44     float dy3 = y0 - y1 + y2 - y3;
45     tx.m22 = 1.0f;
46     if ((dx3 == 0.0f) && (dy3 == 0.0f)) { // to do: use tolerance
47       tx.m00 = x1 - x0;
48       tx.m01 = x2 - x1;
49       tx.m02 = x0;
50       tx.m10 = y1 - y0;
51       tx.m11 = y2 - y1;
52       tx.m12 = y0;
53       tx.m20 = 0.0f;
54       tx.m21 = 0.0f;
55     } else {
56       float dx1 = x1 - x2;
57       float dy1 = y1 - y2;
58       float dx2 = x3 - x2;
59       float dy2 = y3 - y2;
60       float invdet = 1.0f / (dx1 * dy2 - dx2 * dy1);
61       tx.m20 = (dx3 * dy2 - dx2 * dy3) * invdet;
62       tx.m21 = (dx1 * dy3 - dx3 * dy1) * invdet;
63       tx.m00 = x1 - x0 + tx.m20 * x1;
64       tx.m01 = x3 - x0 + tx.m21 * x3;
65       tx.m02 = x0;
66       tx.m10 = y1 - y0 + tx.m20 * y1;
67       tx.m11 = y3 - y0 + tx.m21 * y3;
68       tx.m12 = y0;
69     }
70   }
71
72   private static JAIPerspectiveTransform getSquareToQuad(float x0, float y0,
73                                                          float x1, float y1,
74                                                          float x2, float y2,
75                                                          float x3, float y3) {
76     JAIPerspectiveTransform tx = new JAIPerspectiveTransform();
77     getSquareToQuad(x0, y0, x1, y1, x2, y2, x3, y3, tx);
78     return tx;
79   }
80
81   private static JAIPerspectiveTransform getQuadToSquare(float x0, float y0,
82                                                          float x1, float y1,
83                                                          float x2, float y2,
84                                                          float x3, float y3) {
85     JAIPerspectiveTransform tx = new JAIPerspectiveTransform();
86     getSquareToQuad(x0, y0, x1, y1, x2, y2, x3, y3, tx);
87     tx.makeAdjoint();
88     return tx;
89   }
90
91   static JAIPerspectiveTransform getQuadToQuad(float x0, float y0,
92                                                float x1, float y1,
93                                                float x2, float y2,
94                                                float x3, float y3,
95                                                float x0p, float y0p,
96                                                float x1p, float y1p,
97                                                float x2p, float y2p,
98                                                float x3p, float y3p) {
99     JAIPerspectiveTransform tx1 = getQuadToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
100     JAIPerspectiveTransform tx2 = getSquareToQuad(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
101     tx1.concatenate(tx2);
102     return tx1;
103   }
104
105   private void concatenate(JAIPerspectiveTransform Tx) {
106     float m00p = m00 * Tx.m00 + m10 * Tx.m01 + m20 * Tx.m02;
107     float m10p = m00 * Tx.m10 + m10 * Tx.m11 + m20 * Tx.m12;
108     float m20p = m00 * Tx.m20 + m10 * Tx.m21 + m20 * Tx.m22;
109     float m01p = m01 * Tx.m00 + m11 * Tx.m01 + m21 * Tx.m02;
110     float m11p = m01 * Tx.m10 + m11 * Tx.m11 + m21 * Tx.m12;
111     float m21p = m01 * Tx.m20 + m11 * Tx.m21 + m21 * Tx.m22;
112     float m02p = m02 * Tx.m00 + m12 * Tx.m01 + m22 * Tx.m02;
113     float m12p = m02 * Tx.m10 + m12 * Tx.m11 + m22 * Tx.m12;
114     float m22p = m02 * Tx.m20 + m12 * Tx.m21 + m22 * Tx.m22;
115     m00 = m00p;
116     m10 = m10p;
117     m20 = m20p;
118     m01 = m01p;
119     m11 = m11p;
120     m21 = m21p;
121     m02 = m02p;
122     m12 = m12p;
123     m22 = m22p;
124   }
125
126   void transform(float[] points) {
127     int max = points.length;
128     for (int offset = 0; offset < max; offset += 2) {
129       float x = points[offset];
130       float y = points[offset + 1];
131       float w = m20 * x + m21 * y + m22;
132       if (w == 0.0f) {
133         points[offset] = x;
134         points[offset + 1] = y;
135       } else {
136         float oneOverW = 1.0f / w;
137         points[offset] = (m00 * x + m01 * y + m02) * oneOverW;
138         points[offset + 1] = (m10 * x + m11 * y + m12) * oneOverW;
139       }
140     }
141   }
142 }