C# port, add datamatrix code
[zxing.git] / csharp / datamatrix / DataMatrixReader.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.Linq;\r
4 using com.google.zxing;\r
5 using com.google.zxing.common;\r
6 using com.google.zxing.datamatrix.decoder;\r
7 using com.google.zxing.datamatrix.detector;\r
8 \r
9 namespace com.google.zxing.datamatrix\r
10 {\r
11     public sealed class DataMatrixReader\r
12     {\r
13           private static  ResultPoint[] NO_POINTS = new ResultPoint[0];\r
14           private Decoder decoder = new Decoder();\r
15 \r
16           /**\r
17            * Locates and decodes a Data Matrix code in an image.\r
18            *\r
19            * @return a String representing the content encoded by the Data Matrix code\r
20            * @throws ReaderException if a Data Matrix code cannot be found, or cannot be decoded\r
21            */\r
22           public Result decode(MonochromeBitmapSource image) {\r
23             return decode(image, null);\r
24           }\r
25 \r
26           public Result decode(MonochromeBitmapSource image, System.Collections.Hashtable hints)\r
27               {\r
28             DecoderResult decoderResult;\r
29             ResultPoint[] points;\r
30             if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE)) {\r
31               BitMatrix bits = extractPureBits(image);\r
32               decoderResult = decoder.decode(bits);\r
33               points = NO_POINTS;\r
34             } else {\r
35               DetectorResult detectorResult = new Detector(image).detect();\r
36               decoderResult = decoder.decode(detectorResult.getBits());\r
37               points = detectorResult.getPoints();\r
38             }\r
39             Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.DATAMATRIX);\r
40             if (decoderResult.getByteSegments() != null) {\r
41               result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, decoderResult.getByteSegments());\r
42             }\r
43             return result;\r
44           }\r
45 \r
46           /**\r
47            * This method detects a Data Matrix code in a "pure" image -- that is, pure monochrome image\r
48            * which contains only an unrotated, unskewed, image of a Data Matrix code, with some white border\r
49            * around it. This is a specialized method that works exceptionally fast in this special\r
50            * case.\r
51            */\r
52           private static BitMatrix extractPureBits(MonochromeBitmapSource image) {\r
53             // Now need to determine module size in pixels\r
54 \r
55             int height = image.getHeight();\r
56             int width = image.getWidth();\r
57             int minDimension = Math.Min(height, width);\r
58 \r
59             // First, skip white border by tracking diagonally from the top left down and to the right:\r
60             int borderWidth = 0;\r
61             while (borderWidth < minDimension && !image.isBlack(borderWidth, borderWidth)) {\r
62               borderWidth++;\r
63             }\r
64             if (borderWidth == minDimension) {\r
65               throw new ReaderException();\r
66             }\r
67 \r
68             // And then keep tracking across the top-left black module to determine module size\r
69             int moduleEnd = borderWidth + 1;\r
70             while (moduleEnd < width && image.isBlack(moduleEnd, borderWidth)) {\r
71               moduleEnd++;\r
72             }\r
73             if (moduleEnd == width) {\r
74               throw new ReaderException();\r
75             }\r
76 \r
77             int moduleSize = moduleEnd - borderWidth;\r
78 \r
79             // And now find where the bottommost black module on the first column ends\r
80             int columnEndOfSymbol = height - 1;\r
81             while (columnEndOfSymbol >= 0 && !image.isBlack(borderWidth, columnEndOfSymbol)) {\r
82                 columnEndOfSymbol--;\r
83             }\r
84             if (columnEndOfSymbol < 0) {\r
85               throw new ReaderException();\r
86             }\r
87             columnEndOfSymbol++;\r
88 \r
89             // Make sure width of barcode is a multiple of module size\r
90             if ((columnEndOfSymbol - borderWidth) % moduleSize != 0) {\r
91               throw new ReaderException();\r
92             }\r
93             int dimension = (columnEndOfSymbol - borderWidth) / moduleSize;\r
94 \r
95             // Push in the "border" by half the module width so that we start\r
96             // sampling in the middle of the module. Just in case the image is a\r
97             // little off, this will help recover.\r
98             borderWidth += moduleSize >> 1;\r
99 \r
100             int sampleDimension = borderWidth + (dimension - 1) * moduleSize;\r
101             if (sampleDimension >= width || sampleDimension >= height) {\r
102               throw new ReaderException();\r
103             }\r
104 \r
105             // Now just read off the bits\r
106             BitMatrix bits = new BitMatrix(dimension);\r
107             for (int i = 0; i < dimension; i++) {\r
108               int iOffset = borderWidth + i * moduleSize;\r
109               for (int j = 0; j < dimension; j++) {\r
110                 if (image.isBlack(borderWidth + j * moduleSize, iOffset)) {\r
111                   bits.set(i, j);\r
112                 }\r
113               }\r
114             }\r
115             return bits;\r
116           }\r
117     }\r
118 }\r