Merge to XFA: Use stdint.h types throughout PDFium.
[pdfium.git] / xfa / src / fxbarcode / common / BC_WhiteRectangleDetector.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 // Original code is licensed as follows:\r
7 /*\r
8  * Copyright 2010 ZXing authors\r
9  *\r
10  * Licensed under the Apache License, Version 2.0 (the "License");\r
11  * you may not use this file except in compliance with the License.\r
12  * You may obtain a copy of the License at\r
13  *\r
14  *      http://www.apache.org/licenses/LICENSE-2.0\r
15  *\r
16  * Unless required by applicable law or agreed to in writing, software\r
17  * distributed under the License is distributed on an "AS IS" BASIS,\r
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
19  * See the License for the specific language governing permissions and\r
20  * limitations under the License.\r
21  */\r
22 \r
23 #include "../barcode.h"\r
24 #include "BC_WhiteRectangleDetector.h"\r
25 #include "BC_CommonBitMatrix.h"\r
26 #include "../BC_ResultPoint.h"\r
27 const int32_t CBC_WhiteRectangleDetector::INIT_SIZE = 30;\r
28 const int32_t CBC_WhiteRectangleDetector::CORR = 1;\r
29 CBC_WhiteRectangleDetector::CBC_WhiteRectangleDetector(CBC_CommonBitMatrix *image)\r
30 {\r
31     m_image = image;\r
32     m_height = image->GetHeight();\r
33     m_width = image->GetWidth();\r
34     m_leftInit = (m_width - INIT_SIZE) >> 1;\r
35     m_rightInit = (m_width + INIT_SIZE) >> 1;\r
36     m_upInit = (m_height - INIT_SIZE) >> 1;\r
37     m_downInit = (m_height + INIT_SIZE) >> 1;\r
38 }\r
39 void CBC_WhiteRectangleDetector::Init(int32_t &e)\r
40 {\r
41     if (m_upInit < 0 || m_leftInit < 0 || m_downInit >= m_height || m_rightInit >= m_width) {\r
42         e = BCExceptionNotFound;\r
43         BC_EXCEPTION_CHECK_ReturnVoid(e);\r
44     }\r
45 }\r
46 CBC_WhiteRectangleDetector::CBC_WhiteRectangleDetector(CBC_CommonBitMatrix *image, int32_t initSize, int32_t x, int32_t y)\r
47 {\r
48     m_image = image;\r
49     m_height = image->GetHeight();\r
50     m_width = image->GetWidth();\r
51     int32_t halfsize = initSize >> 1;\r
52     m_leftInit = x - halfsize;\r
53     m_rightInit = x + halfsize;\r
54     m_upInit = y - halfsize;\r
55     m_downInit = y + halfsize;\r
56 }\r
57 CBC_WhiteRectangleDetector::~CBC_WhiteRectangleDetector()\r
58 {\r
59 }\r
60 CFX_PtrArray *CBC_WhiteRectangleDetector::Detect(int32_t &e)\r
61 {\r
62     int32_t left = m_leftInit;\r
63     int32_t right = m_rightInit;\r
64     int32_t up = m_upInit;\r
65     int32_t down = m_downInit;\r
66     FX_BOOL sizeExceeded = FALSE;\r
67     FX_BOOL aBlackPointFoundOnBorder = TRUE;\r
68     FX_BOOL atLeastOneBlackPointFoundOnBorder = FALSE;\r
69     while (aBlackPointFoundOnBorder) {\r
70         aBlackPointFoundOnBorder = FALSE;\r
71         FX_BOOL rightBorderNotWhite = TRUE;\r
72         while (rightBorderNotWhite && right < m_width) {\r
73             rightBorderNotWhite = ContainsBlackPoint(up, down, right, FALSE);\r
74             if (rightBorderNotWhite) {\r
75                 right++;\r
76                 aBlackPointFoundOnBorder = TRUE;\r
77             }\r
78         }\r
79         if (right >= m_width) {\r
80             sizeExceeded = TRUE;\r
81             break;\r
82         }\r
83         FX_BOOL bottomBorderNotWhite = TRUE;\r
84         while (bottomBorderNotWhite && down < m_height) {\r
85             bottomBorderNotWhite = ContainsBlackPoint(left, right, down, TRUE);\r
86             if (bottomBorderNotWhite) {\r
87                 down++;\r
88                 aBlackPointFoundOnBorder = TRUE;\r
89             }\r
90         }\r
91         if (down >= m_height) {\r
92             sizeExceeded = TRUE;\r
93             break;\r
94         }\r
95         FX_BOOL leftBorderNotWhite = TRUE;\r
96         while (leftBorderNotWhite && left >= 0) {\r
97             leftBorderNotWhite = ContainsBlackPoint(up, down, left, FALSE);\r
98             if (leftBorderNotWhite) {\r
99                 left--;\r
100                 aBlackPointFoundOnBorder = TRUE;\r
101             }\r
102         }\r
103         if (left < 0) {\r
104             sizeExceeded = TRUE;\r
105             break;\r
106         }\r
107         FX_BOOL topBorderNotWhite = TRUE;\r
108         while (topBorderNotWhite && up >= 0) {\r
109             topBorderNotWhite = ContainsBlackPoint(left, right, up, TRUE);\r
110             if (topBorderNotWhite) {\r
111                 up--;\r
112                 aBlackPointFoundOnBorder = TRUE;\r
113             }\r
114         }\r
115         if (up < 0) {\r
116             sizeExceeded = TRUE;\r
117             break;\r
118         }\r
119         if (aBlackPointFoundOnBorder) {\r
120             atLeastOneBlackPointFoundOnBorder = TRUE;\r
121         }\r
122     }\r
123     if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) {\r
124         int32_t maxSize = right - left;\r
125         CBC_AutoPtr<CBC_ResultPoint> z(NULL);\r
126         for (int32_t i = 1; i < maxSize; i++) {\r
127             z = CBC_AutoPtr<CBC_ResultPoint>(GetBlackPointOnSegment((FX_FLOAT)left, (FX_FLOAT)(down - i), (FX_FLOAT)(left + i), (FX_FLOAT)(down)) );\r
128             if (z.get() != NULL) {\r
129                 break;\r
130             }\r
131         }\r
132         if (z.get() == NULL) {\r
133             e = BCExceptionNotFound;\r
134             BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
135         }\r
136         CBC_AutoPtr<CBC_ResultPoint> t(NULL);\r
137         for (int32_t j = 1; j < maxSize; j++) {\r
138             t = CBC_AutoPtr<CBC_ResultPoint>(GetBlackPointOnSegment((FX_FLOAT)left, (FX_FLOAT)(up + j), (FX_FLOAT)(left + j), (FX_FLOAT)up));\r
139             if (t.get() != NULL) {\r
140                 break;\r
141             }\r
142         }\r
143         if (t.get() == NULL) {\r
144             e = BCExceptionNotFound;\r
145             BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
146         }\r
147         CBC_AutoPtr<CBC_ResultPoint> x(NULL);\r
148         for (int32_t k = 1; k < maxSize; k++) {\r
149             x = CBC_AutoPtr<CBC_ResultPoint>(GetBlackPointOnSegment((FX_FLOAT)right, (FX_FLOAT)(up + k), (FX_FLOAT)(right - k), (FX_FLOAT)up));\r
150             if (x.get() != NULL) {\r
151                 break;\r
152             }\r
153         }\r
154         if (x.get() == NULL) {\r
155             e = BCExceptionNotFound;\r
156             BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
157         }\r
158         CBC_AutoPtr<CBC_ResultPoint> y(NULL);\r
159         for (int32_t m = 1;     m < maxSize; m++) {\r
160             y = CBC_AutoPtr<CBC_ResultPoint>(GetBlackPointOnSegment((FX_FLOAT)right, (FX_FLOAT)(down - m), (FX_FLOAT)(right - m), (FX_FLOAT) down));\r
161             if (y.get() != NULL) {\r
162                 break;\r
163             }\r
164         }\r
165         if (y.get() == NULL) {\r
166             e = BCExceptionNotFound;\r
167             BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
168         }\r
169         return CenterEdges(y.get(), z.get(), x.get(), t.get());\r
170     } else {\r
171         e = BCExceptionNotFound;\r
172         BC_EXCEPTION_CHECK_ReturnValue(e, NULL);\r
173     }\r
174     return NULL;\r
175 }\r
176 int32_t CBC_WhiteRectangleDetector::Round(FX_FLOAT d)\r
177 {\r
178     return (int32_t) (d + 0.5f);\r
179 }\r
180 CBC_ResultPoint *CBC_WhiteRectangleDetector::GetBlackPointOnSegment(FX_FLOAT aX, FX_FLOAT aY, FX_FLOAT bX, FX_FLOAT bY)\r
181 {\r
182     int32_t dist = DistanceL2(aX, aY, bX, bY);\r
183     float xStep = (bX - aX) / dist;\r
184     float yStep = (bY - aY) / dist;\r
185     for (int32_t i = 0; i < dist; i++) {\r
186         int32_t x = Round(aX + i * xStep);\r
187         int32_t y = Round(aY + i * yStep);\r
188         if (m_image->Get(x, y)) {\r
189             return FX_NEW CBC_ResultPoint((FX_FLOAT)x, (FX_FLOAT) y);\r
190         }\r
191     }\r
192     return NULL;\r
193 }\r
194 int32_t CBC_WhiteRectangleDetector::DistanceL2(FX_FLOAT aX, FX_FLOAT aY, FX_FLOAT bX, FX_FLOAT bY)\r
195 {\r
196     float xDiff = aX - bX;\r
197     float yDiff = aY - bY;\r
198     return Round((float)sqrt(xDiff * xDiff + yDiff * yDiff));\r
199 }\r
200 CFX_PtrArray *CBC_WhiteRectangleDetector::CenterEdges(CBC_ResultPoint *y, CBC_ResultPoint *z, CBC_ResultPoint *x, CBC_ResultPoint *t)\r
201 {\r
202     float yi = y->GetX();\r
203     float yj = y->GetY();\r
204     float zi = z->GetX();\r
205     float zj = z->GetY();\r
206     float xi = x->GetX();\r
207     float xj = x->GetY();\r
208     float ti = t->GetX();\r
209     float tj = t->GetY();\r
210     if (yi < m_width / 2) {\r
211         CFX_PtrArray *result = FX_NEW CFX_PtrArray;\r
212         result->SetSize(4);\r
213         (*result)[0] = FX_NEW CBC_ResultPoint(ti - CORR, tj + CORR);\r
214         (*result)[1] = FX_NEW CBC_ResultPoint(zi + CORR, zj + CORR);\r
215         (*result)[2] = FX_NEW CBC_ResultPoint(xi - CORR, xj - CORR);\r
216         (*result)[3] = FX_NEW CBC_ResultPoint(yi + CORR, yj - CORR);\r
217         return result;\r
218     } else {\r
219         CFX_PtrArray *result = FX_NEW CFX_PtrArray;\r
220         result->SetSize(4);\r
221         (*result)[0] = FX_NEW CBC_ResultPoint(ti + CORR, tj + CORR);\r
222         (*result)[1] = FX_NEW CBC_ResultPoint(zi + CORR, zj - CORR);\r
223         (*result)[2] = FX_NEW CBC_ResultPoint(xi - CORR, xj + CORR);\r
224         (*result)[3] = FX_NEW CBC_ResultPoint(yi - CORR, yj - CORR);\r
225         return result;\r
226     }\r
227 }\r
228 FX_BOOL CBC_WhiteRectangleDetector::ContainsBlackPoint(int32_t a, int32_t b, int32_t fixed, FX_BOOL horizontal)\r
229 {\r
230     if (horizontal) {\r
231         for (int32_t x = a; x <= b; x++) {\r
232             if (m_image->Get(x, fixed)) {\r
233                 return TRUE;\r
234             }\r
235         }\r
236     } else {\r
237         for (int32_t y = a; y <= b; y++) {\r
238             if (m_image->Get(fixed, y)) {\r
239                 return TRUE;\r
240             }\r
241         }\r
242     }\r
243     return FALSE;\r
244 }\r