Go ahead and enable Code 93 in android
[zxing.git] / csharp / qrcode / QRCodeWriter.cs
1 /*\r
2 * Copyright 2008 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 EncodeHintType = com.google.zxing.EncodeHintType;\r
19 using Writer = com.google.zxing.Writer;\r
20 using WriterException = com.google.zxing.WriterException;\r
21 using ByteMatrix = com.google.zxing.common.ByteMatrix;\r
22 using Encoder = com.google.zxing.qrcode.encoder.Encoder;\r
23 using QRCode = com.google.zxing.qrcode.encoder.QRCode;\r
24 using ErrorCorrectionLevel = com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;\r
25 namespace com.google.zxing.qrcode\r
26 {\r
27         \r
28         /// <summary> This object renders a QR Code as a ByteMatrix 2D array of greyscale values.\r
29         /// \r
30         /// </summary>\r
31         /// <author>  dswitkin@google.com (Daniel Switkin)\r
32         /// </author>\r
33         /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source \r
34         /// </author>\r
35         public sealed class QRCodeWriter : Writer\r
36         {\r
37                 \r
38                 private const int QUIET_ZONE_SIZE = 4;\r
39                 \r
40                 public ByteMatrix encode(System.String contents, BarcodeFormat format, int width, int height)\r
41                 {\r
42                         \r
43                         return encode(contents, format, width, height, null);\r
44                 }\r
45                 \r
46                 public ByteMatrix encode(System.String contents, BarcodeFormat format, int width, int height, System.Collections.Hashtable hints)\r
47                 {\r
48                         \r
49                         if (contents == null || contents.Length == 0)\r
50                         {\r
51                                 throw new System.ArgumentException("Found empty contents");\r
52                         }\r
53                         \r
54                         if (format != BarcodeFormat.QR_CODE)\r
55                         {\r
56                                 throw new System.ArgumentException("Can only encode QR_CODE, but got " + format);\r
57                         }\r
58                         \r
59                         if (width < 0 || height < 0)\r
60                         {\r
61                                 throw new System.ArgumentException("Requested dimensions are too small: " + width + 'x' + height);\r
62                         }\r
63                         \r
64                         ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.L;\r
65                         if (hints != null)\r
66                         {\r
67                                 ErrorCorrectionLevel requestedECLevel = (ErrorCorrectionLevel) hints[EncodeHintType.ERROR_CORRECTION];\r
68                                 if (requestedECLevel != null)\r
69                                 {\r
70                                         errorCorrectionLevel = requestedECLevel;\r
71                                 }\r
72                         }\r
73                         \r
74                         QRCode code = new QRCode();\r
75                         Encoder.encode(contents, errorCorrectionLevel, hints, code);\r
76                         return renderResult(code, width, height);\r
77                 }\r
78                 \r
79                 // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses\r
80                 // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).\r
81                 private static ByteMatrix renderResult(QRCode code, int width, int height)\r
82                 {\r
83                         ByteMatrix input = code.Matrix;\r
84                         int inputWidth = input.Width;\r
85                         int inputHeight = input.Height;\r
86                         int qrWidth = inputWidth + (QUIET_ZONE_SIZE << 1);\r
87                         int qrHeight = inputHeight + (QUIET_ZONE_SIZE << 1);\r
88                         int outputWidth = System.Math.Max(width, qrWidth);\r
89                         int outputHeight = System.Math.Max(height, qrHeight);\r
90                         \r
91                         int multiple = System.Math.Min(outputWidth / qrWidth, outputHeight / qrHeight);\r
92                         // Padding includes both the quiet zone and the extra white pixels to accommodate the requested\r
93                         // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.\r
94                         // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will\r
95                         // handle all the padding from 100x100 (the actual QR) up to 200x160.\r
96                         int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;\r
97                         int topPadding = (outputHeight - (inputHeight * multiple)) / 2;\r
98                         \r
99                         ByteMatrix output = new ByteMatrix(outputWidth, outputHeight);\r
100                         sbyte[][] outputArray = output.Array;\r
101                         \r
102                         // We could be tricky and use the first row in each set of multiple as the temporary storage,\r
103                         // instead of allocating this separate array.\r
104                         sbyte[] row = new sbyte[outputWidth];\r
105                         \r
106                         // 1. Write the white lines at the top\r
107                         for (int y = 0; y < topPadding; y++)\r
108                         {\r
109                                 setRowColor(outputArray[y], (sbyte) SupportClass.Identity(255));\r
110                         }\r
111                         \r
112                         // 2. Expand the QR image to the multiple\r
113                         sbyte[][] inputArray = input.Array;\r
114                         for (int y = 0; y < inputHeight; y++)\r
115                         {\r
116                                 // a. Write the white pixels at the left of each row\r
117                                 for (int x = 0; x < leftPadding; x++)\r
118                                 {\r
119                                         row[x] = (sbyte) SupportClass.Identity(255);\r
120                                 }\r
121                                 \r
122                                 // b. Write the contents of this row of the barcode\r
123                                 int offset = leftPadding;\r
124                                 for (int x = 0; x < inputWidth; x++)\r
125                                 {\r
126                     // Redivivus.in Java to c# Porting update - Type cased sbyte\r
127                     // 30/01/2010 \r
128                                         // sbyte value_Renamed = (inputArray[y][x] == 1)?0:(sbyte) SupportClass.Identity(255);\r
129                     sbyte value_Renamed = (sbyte)((inputArray[y][x] == 1) ? 0 : SupportClass.Identity(255));\r
130                                         for (int z = 0; z < multiple; z++)\r
131                                         {\r
132                                                 row[offset + z] = value_Renamed;\r
133                                         }\r
134                                         offset += multiple;\r
135                                 }\r
136                                 \r
137                                 // c. Write the white pixels at the right of each row\r
138                                 offset = leftPadding + (inputWidth * multiple);\r
139                                 for (int x = offset; x < outputWidth; x++)\r
140                                 {\r
141                                         row[x] = (sbyte) SupportClass.Identity(255);\r
142                                 }\r
143                                 \r
144                                 // d. Write the completed row multiple times\r
145                                 offset = topPadding + (y * multiple);\r
146                                 for (int z = 0; z < multiple; z++)\r
147                                 {\r
148                                         Array.Copy(row, 0, outputArray[offset + z], 0, outputWidth);\r
149                                 }\r
150                         }\r
151                         \r
152                         // 3. Write the white lines at the bottom\r
153                         int offset2 = topPadding + (inputHeight * multiple);\r
154                         for (int y = offset2; y < outputHeight; y++)\r
155                         {\r
156                                 setRowColor(outputArray[y], (sbyte) SupportClass.Identity(255));\r
157                         }\r
158                         \r
159                         return output;\r
160                 }\r
161                 \r
162                 private static void  setRowColor(sbyte[] row, sbyte value_Renamed)\r
163                 {\r
164                         for (int x = 0; x < row.Length; x++)\r
165                         {\r
166                                 row[x] = value_Renamed;\r
167                         }\r
168                 }\r
169         }\r
170 }