Changed signature of parse() to take in more general Result
[zxing.git] / core / src / com / google / zxing / qrcode / detector / GridSampler.java
1 /*
2  * Copyright 2007 Google Inc.
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.qrcode.detector;
18
19 import com.google.zxing.MonochromeBitmapSource;
20 import com.google.zxing.ReaderException;
21 import com.google.zxing.common.BitMatrix;
22
23 /**
24  * Implementations of this class can, given locations of finder patterns for a QR code in an
25  * image, sample the right points in the image to reconstruct the QR code, accounting for
26  * perspective distortion. It is abstracted since it is relatively expensive and should be allowed
27  * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced
28  * Imaging library, but which may not be available in other environments such as J2ME, and vice
29  * versa.
30  *
31  * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)}
32  * with an instance of a class which implements this interface.
33  *
34  * @author srowen@google.com (Sean Owen)
35  */
36 public abstract class GridSampler {
37
38   private static GridSampler gridSampler;
39
40   /**
41    * Sets the implementation of {@link GridSampler} used by the library. One global
42    * instance is stored, which may sound problematic. But, the implementation provided
43    * ought to be appropriate for the entire platform, and all uses of this library
44    * in the whole lifetime of the JVM. For instance, an Android activity can swap in
45    * an implementation that takes advantage of native platform libraries.
46    * 
47    * @param newGridSampler
48    */
49   public static void setGridSampler(GridSampler newGridSampler) {
50     if (newGridSampler == null) {
51       throw new IllegalArgumentException();
52     }
53     gridSampler = newGridSampler;
54   }
55
56   /**
57    * @return the current implementation of {@link GridSampler}
58    */
59   public static GridSampler getInstance() {
60     if (gridSampler == null) {
61       gridSampler = new DefaultGridSampler();
62     }
63     return gridSampler;
64   }
65
66   /**
67    * <p>Given an image, locations of a QR Code's finder patterns and bottom-right alignment pattern,
68    * and the presumed dimension in modules of the QR Code, implemntations of this method extract
69    * the QR Code from the image by sampling the points in the image which should correspond to the
70    * modules of the QR Code.</p>
71    *
72    * @param image image to sample
73    * @param topLeft top-left finder pattern location
74    * @param topRight top-right finder pattern location
75    * @param bottomLeft bottom-left finder pattern location
76    * @param alignmentPattern bottom-right alignment pattern location
77    * @param dimension dimension of QR Code
78    * @return {@link BitMatrix} representing QR Code's modules
79    * @throws ReaderException if QR Code cannot be reasonably sampled -- for example if the location
80    * of the finder patterns imply a transformation that would require sampling off the image
81    */
82   protected abstract BitMatrix sampleGrid(MonochromeBitmapSource image,
83                                           FinderPattern topLeft,
84                                           FinderPattern topRight,
85                                           FinderPattern bottomLeft,
86                                           AlignmentPattern alignmentPattern,
87                                           int dimension) throws ReaderException;
88
89   /**
90    * <p>Checks a set of points that have been transformed to sample points on an image against
91    * the image's dimensions to see if the endpoints are even within the image.
92    * This method actually only checks the endpoints since the points are assumed to lie
93    * on a line.</p>
94    *
95    * <p>This method will actually "nudge" the endpoints back onto the image if they are found to be barely
96    * (less than 1 pixel) off the image. This accounts for imperfect detection of finder patterns in an image
97    * where the QR Code runs all the way to the image border.</p>
98    *
99    * @param image image into which the points should map
100    * @param points actual points in x1,y1,...,xn,yn form
101    * @throws ReaderException if an endpoint is lies outside the image boundaries
102    */
103   protected static void checkEndpoint(MonochromeBitmapSource image, float[] points) throws ReaderException {
104     int width = image.getWidth();
105     int height = image.getHeight();
106     checkOneEndpoint(points, (int) points[0], (int) points[1], width, height);
107     checkOneEndpoint(points, (int) points[points.length - 2], (int) points[points.length - 1], width, height);
108   }
109
110   private static void checkOneEndpoint(float[] points, int x, int y, int width, int height) throws ReaderException {
111     if (x < -1 || x > width || y < -1 || y > height) {
112       throw new ReaderException("Transformed point out of bounds at " + x + ',' + y);
113     }
114     if (x == -1) {
115       points[0] = 0.0f;
116     }
117     if (y == -1) {
118       points[1] = 0.0f;
119     }
120     if (x == width) {
121       points[0] = width - 1;
122     }
123     if (y == height) {
124       points[1] = height - 1;
125     }
126   }
127
128 }