Slovenian translation
[zxing.git] / csharp / qrcode / QRCodeReader.cs
1 /*\r
2 * Copyright 2007 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 BarcodeFormat = com.google.zxing.BarcodeFormat;\r
18 using DecodeHintType = com.google.zxing.DecodeHintType;\r
19 using Reader = com.google.zxing.Reader;\r
20 using ReaderException = com.google.zxing.ReaderException;\r
21 using Result = com.google.zxing.Result;\r
22 using ResultPoint = com.google.zxing.ResultPoint;\r
23 using ResultMetadataType = com.google.zxing.ResultMetadataType;\r
24 using BinaryBitmap = com.google.zxing.BinaryBitmap;\r
25 using BitMatrix = com.google.zxing.common.BitMatrix;\r
26 using DecoderResult = com.google.zxing.common.DecoderResult;\r
27 using DetectorResult = com.google.zxing.common.DetectorResult;\r
28 using Decoder = com.google.zxing.qrcode.decoder.Decoder;\r
29 using Detector = com.google.zxing.qrcode.detector.Detector;\r
30 namespace com.google.zxing.qrcode\r
31 {\r
32         \r
33         /// <summary> This implementation can detect and decode QR Codes in an image.\r
34         /// \r
35         /// </summary>\r
36         /// <author>  Sean Owen\r
37         /// </author>\r
38         /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source \r
39         /// </author>\r
40         public class QRCodeReader : Reader\r
41         {\r
42                 virtual protected internal Decoder Decoder\r
43                 {\r
44                         get\r
45                         {\r
46                                 return decoder;\r
47                         }\r
48                         \r
49                 }\r
50                 \r
51                 //UPGRADE_NOTE: Final was removed from the declaration of 'NO_POINTS '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
52                 private static readonly ResultPoint[] NO_POINTS = new ResultPoint[0];\r
53                 \r
54                 //UPGRADE_NOTE: Final was removed from the declaration of 'decoder '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
55                 private Decoder decoder = new Decoder();\r
56                 \r
57                 /// <summary> Locates and decodes a QR code in an image.\r
58                 /// \r
59                 /// </summary>\r
60                 /// <returns> a String representing the content encoded by the QR code\r
61                 /// </returns>\r
62                 /// <throws>  ReaderException if a QR code cannot be found, or cannot be decoded </throws>\r
63                 public virtual Result decode(BinaryBitmap image)\r
64                 {\r
65                         return decode(image, null);\r
66                 }\r
67                 \r
68                 public virtual Result decode(BinaryBitmap image, System.Collections.Hashtable hints)\r
69                 {\r
70                         DecoderResult decoderResult;\r
71                         ResultPoint[] points;\r
72                         if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE))\r
73                         {\r
74                                 BitMatrix bits = extractPureBits(image.BlackMatrix);\r
75                                 decoderResult = decoder.decode(bits);\r
76                                 points = NO_POINTS;\r
77                         }\r
78                         else\r
79                         {\r
80                                 DetectorResult detectorResult = new Detector(image.BlackMatrix).detect(hints);\r
81                                 decoderResult = decoder.decode(detectorResult.Bits);\r
82                                 points = detectorResult.Points;\r
83                         }\r
84                         \r
85                         Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE);\r
86                         if (decoderResult.ByteSegments != null)\r
87                         {\r
88                                 result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.ByteSegments);\r
89                         }\r
90                         if (decoderResult.ECLevel != null)\r
91                         {\r
92                                 result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel.ToString());\r
93                         }\r
94                         return result;\r
95                 }\r
96                 \r
97                 /// <summary> This method detects a barcode in a "pure" image -- that is, pure monochrome image\r
98                 /// which contains only an unrotated, unskewed, image of a barcode, with some white border\r
99                 /// around it. This is a specialized method that works exceptionally fast in this special\r
100                 /// case.\r
101                 /// </summary>\r
102                 private static BitMatrix extractPureBits(BitMatrix image)\r
103                 {\r
104                         // Now need to determine module size in pixels\r
105                         \r
106                         int height = image.Height;\r
107                         int width = image.Width;\r
108                         int minDimension = System.Math.Min(height, width);\r
109                         \r
110                         // First, skip white border by tracking diagonally from the top left down and to the right:\r
111                         int borderWidth = 0;\r
112                         while (borderWidth < minDimension && !image.get_Renamed(borderWidth, borderWidth))\r
113                         {\r
114                                 borderWidth++;\r
115                         }\r
116                         if (borderWidth == minDimension)\r
117                         {\r
118                                 throw ReaderException.Instance;\r
119                         }\r
120                         \r
121                         // And then keep tracking across the top-left black module to determine module size\r
122                         int moduleEnd = borderWidth;\r
123                         while (moduleEnd < minDimension && image.get_Renamed(moduleEnd, moduleEnd))\r
124                         {\r
125                                 moduleEnd++;\r
126                         }\r
127                         if (moduleEnd == minDimension)\r
128                         {\r
129                                 throw ReaderException.Instance;\r
130                         }\r
131                         \r
132                         int moduleSize = moduleEnd - borderWidth;\r
133                         \r
134                         // And now find where the rightmost black module on the first row ends\r
135                         int rowEndOfSymbol = width - 1;\r
136                         while (rowEndOfSymbol >= 0 && !image.get_Renamed(rowEndOfSymbol, borderWidth))\r
137                         {\r
138                                 rowEndOfSymbol--;\r
139                         }\r
140                         if (rowEndOfSymbol < 0)\r
141                         {\r
142                                 throw ReaderException.Instance;\r
143                         }\r
144                         rowEndOfSymbol++;\r
145                         \r
146                         // Make sure width of barcode is a multiple of module size\r
147                         if ((rowEndOfSymbol - borderWidth) % moduleSize != 0)\r
148                         {\r
149                                 throw ReaderException.Instance;\r
150                         }\r
151                         int dimension = (rowEndOfSymbol - borderWidth) / moduleSize;\r
152                         \r
153                         // Push in the "border" by half the module width so that we start\r
154                         // sampling in the middle of the module. Just in case the image is a\r
155                         // little off, this will help recover.\r
156                         borderWidth += (moduleSize >> 1);\r
157                         \r
158                         int sampleDimension = borderWidth + (dimension - 1) * moduleSize;\r
159                         if (sampleDimension >= width || sampleDimension >= height)\r
160                         {\r
161                                 throw ReaderException.Instance;\r
162                         }\r
163                         \r
164                         // Now just read off the bits\r
165                         BitMatrix bits = new BitMatrix(dimension);\r
166                         for (int i = 0; i < dimension; i++)\r
167                         {\r
168                                 int iOffset = borderWidth + i * moduleSize;\r
169                                 for (int j = 0; j < dimension; j++)\r
170                                 {\r
171                                         if (image.get_Renamed(borderWidth + j * moduleSize, iOffset))\r
172                                         {\r
173                                                 bits.set_Renamed(j, i);\r
174                                         }\r
175                                 }\r
176                         }\r
177                         return bits;\r
178                 }\r
179         }\r
180 }