2 * Copyright 2007 Google Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.google.zxing.qrcode.detector;
19 import com.google.zxing.MonochromeBitmapSource;
20 import com.google.zxing.ReaderException;
21 import com.google.zxing.common.BitMatrix;
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
31 * The implementation used can be controlled by calling {@link #setGridSamplerClassName(String)}
32 * with the name of a class which implements this interface.
34 * @author srowen@google.com (Sean Owen)
36 public abstract class GridSampler {
38 private static final String DEFAULT_IMPL_CLASS = "com.google.zxing.qrcode.detector.DefaultGridSampler";
40 private static String gridSamplerClassName = DEFAULT_IMPL_CLASS;
41 private static GridSampler gridSampler;
44 * <p>Sets the (fully-qualified) name of the implementation of {@link GridSampler} which will be
45 * returned from {@link #getInstance()}.</p>
47 * @param className {@link GridSampler} implementation to instantiate
49 public static void setGridSamplerClassName(String className) {
50 if (className == null) {
51 throw new IllegalArgumentException();
53 gridSamplerClassName = className;
57 * @return the current implementation of {@link GridSampler}, instantiating one if one does
58 * not already exist. The class which is instantied may be set by
59 * {@link #setGridSamplerClassName(String)}
61 public static GridSampler getInstance() {
62 if (gridSampler == null) {
63 // We don't need to synchronize this -- don't really care if two threads initialize at once.
64 // The second one will win.
66 Class gridSamplerClass = Class.forName(gridSamplerClassName);
67 gridSampler = (GridSampler) gridSamplerClass.newInstance();
68 } catch (ClassNotFoundException cnfe) {
69 // The exceptions below would represent bad programming errors;
70 // For J2ME we're punting them out with RuntimeException
71 throw new RuntimeException(cnfe.toString());
72 } catch (IllegalAccessException iae) {
73 throw new RuntimeException(iae.toString());
74 } catch (InstantiationException ie) {
75 throw new RuntimeException(ie.toString());
82 * <p>Given an image, locations of a QR Code's finder patterns and bottom-right alignment pattern,
83 * and the presumed dimension in modules of the QR Code, implemntations of this method extract
84 * the QR Code from the image by sampling the points in the image which should correspond to the
85 * modules of the QR Code.</p>
87 * @param image image to sample
88 * @param topLeft top-left finder pattern location
89 * @param topRight top-right finder pattern location
90 * @param bottomLeft bottom-left finder pattern location
91 * @param alignmentPattern bottom-right alignment pattern location
92 * @param dimension dimension of QR Code
93 * @return {@link BitMatrix} representing QR Code's modules
94 * @throws ReaderException if QR Code cannot be reasonably sampled -- for example if the location
95 * of the finder patterns imply a transformation that would require sampling off the image
97 protected abstract BitMatrix sampleGrid(MonochromeBitmapSource image,
98 FinderPattern topLeft,
99 FinderPattern topRight,
100 FinderPattern bottomLeft,
101 AlignmentPattern alignmentPattern,
102 int dimension) throws ReaderException;
105 * <p>Checks a set of points that have been transformed to sample points on an image against
106 * the image's dimensions to see if the endpoints are even within the image.
107 * This method actually only checks the endpoints since the points are assumed to lie
110 * @param image image into which the points should map
111 * @param points actual points in x1,y1,...,xn,yn form
112 * @throws ReaderException if an endpoint is lies outside the image boundaries
114 protected static void checkEndpoint(MonochromeBitmapSource image, float[] points) throws ReaderException {
115 int x = (int) points[0];
116 int y = (int) points[1];
117 if (x < 0 || x >= image.getWidth() || y < 0 || y >= image.getHeight()) {
118 throw new ReaderException("Transformed point out of bounds at " + x + ',' + y);
120 x = (int) points[points.length - 2];
121 y = (int) points[points.length - 1];
122 if (x < 0 || x >= image.getWidth() || y < 0 || y >= image.getHeight()) {
123 throw new ReaderException("Transformed point out of bounds at " + x + ',' + y);