New C# port from Suraj Supekar
[zxing.git] / csharp / multi / GenericMultipleBarcodeReader.cs
1 /*\r
2 * Copyright 2009 ZXing authors\r
3 *\r
4 * Licensed under the Apache License, Version 2.0 (the "License");\r
5 * you may not use this file except in compliance with the License.\r
6 * You may obtain a copy of the License at\r
7 *\r
8 *      http://www.apache.org/licenses/LICENSE-2.0\r
9 *\r
10 * Unless required by applicable law or agreed to in writing, software\r
11 * distributed under the License is distributed on an "AS IS" BASIS,\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13 * See the License for the specific language governing permissions and\r
14 * limitations under the License.\r
15 */\r
16 using System;\r
17 using Reader = com.google.zxing.Reader;\r
18 using Result = com.google.zxing.Result;\r
19 using BinaryBitmap = com.google.zxing.BinaryBitmap;\r
20 using ReaderException = com.google.zxing.ReaderException;\r
21 using ResultPoint = com.google.zxing.ResultPoint;\r
22 namespace com.google.zxing.multi\r
23 {\r
24         \r
25         /// <summary> <p>Attempts to locate multiple barcodes in an image by repeatedly decoding portion of the image.\r
26         /// After one barcode is found, the areas left, above, right and below the barcode's\r
27         /// {@link com.google.zxing.ResultPoint}s are scanned, recursively.</p>\r
28         /// \r
29         /// <p>A caller may want to also employ {@link ByQuadrantReader} when attempting to find multiple\r
30         /// 2D barcodes, like QR Codes, in an image, where the presence of multiple barcodes might prevent\r
31         /// detecting any one of them.</p>\r
32         /// \r
33         /// <p>That is, instead of passing a {@link Reader} a caller might pass\r
34         /// <code>new ByQuadrantReader(reader)</code>.</p>\r
35         /// \r
36         /// </summary>\r
37         /// <author>  Sean Owen\r
38         /// </author>\r
39         /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source \r
40         /// </author>\r
41 \r
42         public sealed class GenericMultipleBarcodeReader : MultipleBarcodeReader\r
43         {\r
44                 \r
45                 private const int MIN_DIMENSION_TO_RECUR = 30;\r
46                 \r
47                 //UPGRADE_NOTE: Final was removed from the declaration of 'delegate '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
48                 private Reader delegate_Renamed;\r
49                 \r
50                 public GenericMultipleBarcodeReader(Reader delegate_Renamed)\r
51                 {\r
52                         this.delegate_Renamed = delegate_Renamed;\r
53                 }\r
54                 \r
55                 public Result[] decodeMultiple(BinaryBitmap image)\r
56                 {\r
57                         return decodeMultiple(image, null);\r
58                 }\r
59                 \r
60                 public Result[] decodeMultiple(BinaryBitmap image, System.Collections.Hashtable hints)\r
61                 {\r
62                         System.Collections.ArrayList results = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));\r
63                         doDecodeMultiple(image, hints, results, 0, 0);\r
64                         if ((results.Count == 0))\r
65                         {\r
66                                 throw ReaderException.Instance;\r
67                         }\r
68                         int numResults = results.Count;\r
69                         Result[] resultArray = new Result[numResults];\r
70                         for (int i = 0; i < numResults; i++)\r
71                         {\r
72                                 resultArray[i] = (Result) results[i];\r
73                         }\r
74                         return resultArray;\r
75                 }\r
76                 \r
77                 private void  doDecodeMultiple(BinaryBitmap image, System.Collections.Hashtable hints, System.Collections.ArrayList results, int xOffset, int yOffset)\r
78                 {\r
79                         Result result;\r
80                         try\r
81                         {\r
82                                 result = delegate_Renamed.decode(image, hints);\r
83                         }\r
84                         catch (ReaderException re)\r
85                         {\r
86                                 return ;\r
87                         }\r
88                         bool alreadyFound = false;\r
89                         for (int i = 0; i < results.Count; i++)\r
90                         {\r
91                                 Result existingResult = (Result) results[i];\r
92                                 if (existingResult.Text.Equals(result.Text))\r
93                                 {\r
94                                         alreadyFound = true;\r
95                                         break;\r
96                                 }\r
97                         }\r
98                         if (alreadyFound)\r
99                         {\r
100                                 return ;\r
101                         }\r
102                         results.Add(translateResultPoints(result, xOffset, yOffset));\r
103                         ResultPoint[] resultPoints = result.ResultPoints;\r
104                         if (resultPoints == null || resultPoints.Length == 0)\r
105                         {\r
106                                 return ;\r
107                         }\r
108                         int width = image.Width;\r
109                         int height = image.Height;\r
110                         float minX = width;\r
111                         float minY = height;\r
112                         float maxX = 0.0f;\r
113                         float maxY = 0.0f;\r
114                         for (int i = 0; i < resultPoints.Length; i++)\r
115                         {\r
116                                 ResultPoint point = resultPoints[i];\r
117                                 float x = point.X;\r
118                                 float y = point.Y;\r
119                                 if (x < minX)\r
120                                 {\r
121                                         minX = x;\r
122                                 }\r
123                                 if (y < minY)\r
124                                 {\r
125                                         minY = y;\r
126                                 }\r
127                                 if (x > maxX)\r
128                                 {\r
129                                         maxX = x;\r
130                                 }\r
131                                 if (y > maxY)\r
132                                 {\r
133                                         maxY = y;\r
134                                 }\r
135                         }\r
136                         \r
137                         // Decode left of barcode\r
138                         if (minX > MIN_DIMENSION_TO_RECUR)\r
139                         {\r
140                                 //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"\r
141                                 doDecodeMultiple(image.crop(0, 0, (int) minX, height), hints, results, xOffset, yOffset);\r
142                         }\r
143                         // Decode above barcode\r
144                         if (minY > MIN_DIMENSION_TO_RECUR)\r
145                         {\r
146                                 //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"\r
147                                 doDecodeMultiple(image.crop(0, 0, width, (int) minY), hints, results, xOffset, yOffset);\r
148                         }\r
149                         // Decode right of barcode\r
150                         if (maxX < width - MIN_DIMENSION_TO_RECUR)\r
151                         {\r
152                                 //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"\r
153                                 doDecodeMultiple(image.crop((int) maxX, 0, width - (int) maxX, height), hints, results, xOffset + (int) maxX, yOffset);\r
154                         }\r
155                         // Decode below barcode\r
156                         if (maxY < height - MIN_DIMENSION_TO_RECUR)\r
157                         {\r
158                                 //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"\r
159                                 doDecodeMultiple(image.crop(0, (int) maxY, width, height - (int) maxY), hints, results, xOffset, yOffset + (int) maxY);\r
160                         }\r
161                 }\r
162                 \r
163                 private static Result translateResultPoints(Result result, int xOffset, int yOffset)\r
164                 {\r
165                         ResultPoint[] oldResultPoints = result.ResultPoints;\r
166                         ResultPoint[] newResultPoints = new ResultPoint[oldResultPoints.Length];\r
167                         for (int i = 0; i < oldResultPoints.Length; i++)\r
168                         {\r
169                                 ResultPoint oldPoint = oldResultPoints[i];\r
170                                 newResultPoints[i] = new ResultPoint(oldPoint.X + xOffset, oldPoint.Y + yOffset);\r
171                         }\r
172                         return new Result(result.Text, result.RawBytes, newResultPoints, result.BarcodeFormat);\r
173                 }\r
174         }\r
175 }