9e9daa1af6f7d41339ad1cc318d91474f2e68599
[zxing.git] / cpp / core / src / common / GridSampler.cpp
1 /*
2  *  GridSampler.cpp
3  *  zxing
4  *
5  *  Created by Christian Brunschen on 18/05/2008.
6  *  Copyright 2008 ZXing authors All rights reserved.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include "GridSampler.h"
22 #include "PerspectiveTransform.h"
23 #include "ReaderException.h"
24 #include <iostream>
25 #include <sstream>
26
27 namespace common {
28   GridSampler GridSampler::gridSampler;
29   
30   GridSampler::GridSampler() { }
31   
32   Ref<BitMatrix> GridSampler::sampleGrid(Ref<MonochromeBitmapSource> image,
33                                          int dimension,
34                                          float p1ToX, float p1ToY,
35                                          float p2ToX, float p2ToY,
36                                          float p3ToX, float p3ToY,
37                                          float p4ToX, float p4ToY,
38                                          float p1FromX, float p1FromY,
39                                          float p2FromX, float p2FromY,
40                                          float p3FromX, float p3FromY,
41                                          float p4FromX, float p4FromY) {
42     Ref<PerspectiveTransform> transform
43     (PerspectiveTransform::quadrilateralToQuadrilateral
44      (p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY,
45       p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY));
46     
47     Ref<BitMatrix> bits(new BitMatrix(dimension));
48     valarray<float> points(dimension << 1);
49     for (int i = 0; i < dimension; i++) {
50       int max = points.size();
51       float iValue = (float) i + 0.5f;
52       for (int j = 0; j < max; j+= 2) {
53         points[j] = (float) (j >> 1) + 0.5f;
54         points[j + 1] = iValue;
55       }
56       transform->transformPoints(points);
57       checkAndNudgePoints(image, points);
58       for (int j = 0; j < max; j += 2) {
59         if (image->isBlack((int) points[j], (int) points[j + 1])) {
60           bits->set(i, j >> 1);
61         }
62       }
63     }
64     
65     return bits;
66   }
67   
68   void GridSampler::checkAndNudgePoints(Ref<MonochromeBitmapSource> image,
69                                         valarray<float> &points) {
70     int width = image->getWidth();
71     int height = image->getHeight();
72     // Check and nudge points from start until we see some that are OK:
73     bool nudged = true;
74     for (size_t offset = 0; offset < points.size() && nudged; offset += 2) {
75       int x = (int) points[offset];
76       int y = (int) points[offset + 1];
77       if (x < -1 || x > width || y < -1 || y > height) {
78         ostringstream s;
79         s << "Transformed point out of bounds at " << x << "," << y;
80         throw new ReaderException(s.str().c_str());
81       }
82       nudged = false;
83       if (x == -1) {
84         points[offset] = 0.0f;
85         nudged = true;
86       } else if (x == width) {
87         points[offset] = width - 1;
88         nudged = true;
89       }
90       if (y == -1) {
91         points[offset + 1] = 0.0f;
92         nudged = true;
93       } else if (y == height) {
94         points[offset + 1] = height - 1;
95         nudged = true;
96       }
97     }
98     // Check and nudge points from end:
99     nudged = true;
100     for (size_t offset = points.size() - 2; offset >= 0 && nudged; offset -= 2) {
101       int x = (int) points[offset];
102       int y = (int) points[offset + 1];
103       if (x < -1 || x > width || y < -1 || y > height) {
104         ostringstream s;
105         s << "Transformed point out of bounds at " << x << "," << y;
106         throw new ReaderException(s.str().c_str());
107       }
108       nudged = false;
109       if (x == -1) {
110         points[offset] = 0.0f;
111         nudged = true;
112       } else if (x == width) {
113         points[offset] = width - 1;
114         nudged = true;
115       }
116       if (y == -1) {
117         points[offset + 1] = 0.0f;
118         nudged = true;
119       } else if (y == height) {
120         points[offset + 1] = height - 1;
121         nudged = true;
122       }
123     }
124   }
125   
126   GridSampler &GridSampler::getInstance() {
127     return gridSampler;
128   }
129 }