Files
aistudio-wpf-diagram/zxing.core/xx/oned/PlesseyWriter.cs
2021-07-23 09:42:22 +08:00

150 lines
7.1 KiB
C#

/*
* Copyright 2013 ZXing.Net authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using ZXing.Common;
namespace ZXing.OneD
{
/// <summary>
/// This object renders a Plessey code as a <see cref="BitMatrix"/>.
/// </summary>
public sealed class PlesseyWriter : OneDimensionalCodeWriter
{
private const String ALPHABET_STRING = "0123456789ABCDEF";
private static readonly int[] startWidths = new[] { 14, 11, 14, 11, 5, 20, 14, 11 };
private static readonly int[] terminationWidths = new[] { 25 };
private static readonly int[] endWidths = new[] { 20, 5, 20, 5, 14, 11, 14, 11 };
private static readonly int[][] numberWidths = new[]
{
new[] { 5, 20, 5, 20, 5, 20, 5, 20 }, // 0
new[] { 14, 11, 5, 20, 5, 20, 5, 20 }, // 1
new[] { 5, 20, 14, 11, 5, 20, 5, 20 }, // 2
new[] { 14, 11, 14, 11, 5, 20, 5, 20 }, // 3
new[] { 5, 20, 5, 20, 14, 11, 5, 20 }, // 4
new[] { 14, 11, 5, 20, 14, 11, 5, 20 }, // 5
new[] { 5, 20, 14, 11, 14, 11, 5, 20 }, // 6
new[] { 14, 11, 14, 11, 14, 11, 5, 20 }, // 7
new[] { 5, 20, 5, 20, 5, 20, 14, 11 }, // 8
new[] { 14, 11, 5, 20, 5, 20, 14, 11 }, // 9
new[] { 5, 20, 14, 11, 5, 20, 14, 11 }, // A / 10
new[] { 14, 11, 14, 11, 5, 20, 14, 11 }, // B / 11
new[] { 5, 20, 5, 20, 14, 11, 14, 11 }, // C / 12
new[] { 14, 11, 5, 20, 14, 11, 14, 11 }, // D / 13
new[] { 5, 20, 14, 11, 14, 11, 14, 11 }, // E / 14
new[] { 14, 11, 14, 11, 14, 11, 14, 11 }, // F / 15
};
private static readonly byte[] crcGrid = new byte[] { 1, 1, 1, 1, 0, 1, 0, 0, 1 };
private static readonly int[] crc0Widths = new[] {5, 20};
private static readonly int[] crc1Widths = new[] {14, 11};
/// <summary>
/// Encode the contents following specified format.
/// {@code width} and {@code height} are required size. This method may return bigger size
/// {@code BitMatrix} when specified size is too small. The user can set both {@code width} and
/// {@code height} to zero to get minimum size barcode. If negative value is set to {@code width}
/// or {@code height}, {@code IllegalArgumentException} is thrown.
/// </summary>
/// <param name="contents"></param>
/// <param name="format"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="hints"></param>
/// <returns></returns>
public override BitMatrix encode(String contents,
BarcodeFormat format,
int width,
int height,
IDictionary<EncodeHintType, object> hints)
{
if (format != BarcodeFormat.PLESSEY)
{
throw new ArgumentException("Can only encode Plessey, but got " + format);
}
return base.encode(contents, format, width, height, hints);
}
/// <summary>
/// Encode the contents to byte array expression of one-dimensional barcode.
/// Start code and end code should be included in result, and side margins should not be included.
/// <returns>a {@code boolean[]} of horizontal pixels (false = white, true = black)</returns>
/// </summary>
/// <param name="contents"></param>
/// <returns></returns>
override public bool[] encode(String contents)
{
var length = contents.Length;
for (var i = 0; i < length; i++)
{
int indexInString = ALPHABET_STRING.IndexOf(contents[i]);
if (indexInString < 0)
throw new ArgumentException("Requested contents contains a not encodable character: '" + contents[i] + "'");
}
// quiet zone + start pattern + data + crc + termination bar + end pattern + quiet zone
var codeWidth = 100 + 100 + length * 100 + 25 * 8 + 25 + 100 + 100;
var result = new bool[codeWidth];
var crcBuffer = new byte[4*length + 8];
var crcBufferPos = 0;
var pos = 100;
// start pattern
pos += appendPattern(result, pos, startWidths, true);
// data
for (var i = 0; i < length; i++)
{
var indexInString = ALPHABET_STRING.IndexOf(contents[i]);
var widths = numberWidths[indexInString];
pos += appendPattern(result, pos, widths, true);
// remember the position number for crc calculation
crcBuffer[crcBufferPos++] = (byte)(indexInString & 1);
crcBuffer[crcBufferPos++] = (byte)((indexInString >> 1) & 1);
crcBuffer[crcBufferPos++] = (byte)((indexInString >> 2) & 1);
crcBuffer[crcBufferPos++] = (byte)((indexInString >> 3) & 1);
}
// CRC calculation
for (var i = 0; i < (4 * length); i++)
{
if (crcBuffer[i] != 0)
{
for (var j = 0; j < 9; j++)
{
crcBuffer[i + j] ^= crcGrid[j];
}
}
}
// append CRC pattern
for (var i = 0; i < 8; i++)
{
switch (crcBuffer[length * 4 + i])
{
case 0:
pos += appendPattern(result, pos, crc0Widths, true);
break;
case 1:
pos += appendPattern(result, pos, crc1Widths, true);
break;
}
}
// termination bar
pos += appendPattern(result, pos, terminationWidths, true);
// end pattern
appendPattern(result, pos, endWidths, false);
return result;
}
}
}