Retire C# port and point to ZXing .NET port. Any late objections?

git-svn-id: https://zxing.googlecode.com/svn/trunk@2719 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen@gmail.com 2013-05-10 14:41:19 +00:00
parent b4d46efb1e
commit 091c57a0e1
144 changed files with 2 additions and 27523 deletions

View file

@ -307,6 +307,7 @@
2.2 (X May 2013)
- Retire Symbian port
- Retire C# port
- Improved PDF417 decoding, including macro PDF417
- Added Aztec and Data Matrix encoders
- Added RSS Expanded decoder

View file

@ -1,64 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
// TODO: Review the values of the assembly attributes
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Revision
// Build Number
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\..\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
[assembly: ComVisibleAttribute(false)]

View file

@ -1,98 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// Enumerates barcode formats known to this package. Please keep alphabetized.
///
/// @author Sean Owen
/// </summary>
public enum BarcodeFormat
{
/// <summary>
/// Aztec 2D barcode format. </summary>
AZTEC,
/// <summary>
/// CODABAR 1D format. </summary>
CODABAR,
/// <summary>
/// Code 39 1D format. </summary>
CODE_39,
/// <summary>
/// Code 93 1D format. </summary>
CODE_93,
/// <summary>
/// Code 128 1D format. </summary>
CODE_128,
/// <summary>
/// Data Matrix 2D barcode format. </summary>
DATA_MATRIX,
/// <summary>
/// EAN-8 1D format. </summary>
EAN_8,
/// <summary>
/// EAN-13 1D format. </summary>
EAN_13,
/// <summary>
/// ITF (Interleaved Two of Five) 1D format. </summary>
ITF,
/// <summary>
/// MaxiCode 2D barcode format. </summary>
MAXICODE,
/// <summary>
/// PDF417 format. </summary>
PDF_417,
/// <summary>
/// QR Code 2D barcode format. </summary>
QR_CODE,
/// <summary>
/// RSS 14 </summary>
RSS_14,
/// <summary>
/// RSS EXPANDED </summary>
RSS_EXPANDED,
/// <summary>
/// UPC-A 1D format. </summary>
UPC_A,
/// <summary>
/// UPC-E 1D format. </summary>
UPC_E,
/// <summary>
/// UPC/EAN extension format. Not a stand-alone format. </summary>
UPC_EAN_EXTENSION
}
}

View file

@ -1,105 +0,0 @@
using System.Collections;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing
{
using BitArray = com.google.zxing.common.BitArray;
using BitMatrix = com.google.zxing.common.BitMatrix;
/// <summary>
/// This class hierarchy provides a set of methods to convert luminance data to 1 bit data.
/// It allows the algorithm to vary polymorphically, for example allowing a very expensive
/// thresholding technique for servers and a fast one for mobile. It also permits the implementation
/// to vary, e.g. a JNI version for Android and a Java fallback version for other platforms.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public abstract class Binarizer
{
private readonly LuminanceSource source;
protected internal Binarizer(LuminanceSource source)
{
this.source = source;
}
public LuminanceSource LuminanceSource
{
get
{
return source;
}
}
/// <summary>
/// Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
/// cached data. Callers should assume this method is expensive and call it as seldom as possible.
/// This method is intended for decoding 1D barcodes and may choose to apply sharpening.
/// For callers which only examine one row of pixels at a time, the same BitArray should be reused
/// and passed in with each call for performance. However it is legal to keep more than one row
/// at a time if needed.
/// </summary>
/// <param name="y"> The row to fetch, 0 <= y < bitmap height. </param>
/// <param name="row"> An optional preallocated array. If null or too small, it will be ignored.
/// If used, the Binarizer will call BitArray.clear(). Always use the returned object. </param>
/// <returns> The array of bits for this row (true means black). </returns>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public abstract com.google.zxing.common.BitArray getBlackRow(int y, com.google.zxing.common.BitArray row) throws NotFoundException;
public abstract BitArray getBlackRow(int y, BitArray row);
/// <summary>
/// Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive
/// and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or
/// may not apply sharpening. Therefore, a row from this matrix may not be identical to one
/// fetched using getBlackRow(), so don't mix and match between them.
/// </summary>
/// <returns> The 2D array of bits for the image (true means black). </returns>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public abstract com.google.zxing.common.BitMatrix getBlackMatrix() throws NotFoundException;
public abstract BitMatrix BlackMatrix {get;}
/// <summary>
/// Creates a new object with the same type as this Binarizer implementation, but with pristine
/// state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache
/// of 1 bit data. See Effective Java for why we can't use Java's clone() method.
/// </summary>
/// <param name="source"> The LuminanceSource this Binarizer will operate on. </param>
/// <returns> A new concrete Binarizer implementation object. </returns>
public abstract Binarizer createBinarizer(LuminanceSource source);
public int Width
{
get
{
return source.Width;
}
}
public int Height
{
get
{
return source.Height;
}
}
}
}

View file

@ -1,163 +0,0 @@
using System.Collections;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing
{
using BitArray = com.google.zxing.common.BitArray;
using BitMatrix = com.google.zxing.common.BitMatrix;
/// <summary>
/// This class is the core bitmap class used by ZXing to represent 1 bit data. Reader objects
/// accept a BinaryBitmap and attempt to decode it.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public sealed class BinaryBitmap
{
private readonly Binarizer binarizer;
private BitMatrix matrix;
public BinaryBitmap(Binarizer binarizer)
{
if (binarizer == null)
{
throw new System.ArgumentException("Binarizer must be non-null.");
}
this.binarizer = binarizer;
}
/// <returns> The width of the bitmap. </returns>
public int Width
{
get
{
return binarizer.Width;
}
}
/// <returns> The height of the bitmap. </returns>
public int Height
{
get
{
return binarizer.Height;
}
}
/// <summary>
/// Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
/// cached data. Callers should assume this method is expensive and call it as seldom as possible.
/// This method is intended for decoding 1D barcodes and may choose to apply sharpening.
/// </summary>
/// <param name="y"> The row to fetch, 0 <= y < bitmap height. </param>
/// <param name="row"> An optional preallocated array. If null or too small, it will be ignored.
/// If used, the Binarizer will call BitArray.clear(). Always use the returned object. </param>
/// <returns> The array of bits for this row (true means black). </returns>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.BitArray getBlackRow(int y, com.google.zxing.common.BitArray row) throws NotFoundException
public BitArray getBlackRow(int y, BitArray row)
{
return binarizer.getBlackRow(y, row);
}
/// <summary>
/// Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive
/// and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or
/// may not apply sharpening. Therefore, a row from this matrix may not be identical to one
/// fetched using getBlackRow(), so don't mix and match between them.
/// </summary>
/// <returns> The 2D array of bits for the image (true means black). </returns>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.BitMatrix getBlackMatrix() throws NotFoundException
public BitMatrix BlackMatrix
{
get
{
// The matrix is created on demand the first time it is requested, then cached. There are two
// reasons for this:
// 1. This work will never be done if the caller only installs 1D Reader objects, or if a
// 1D Reader finds a barcode before the 2D Readers run.
// 2. This work will only be done once even if the caller installs multiple 2D Readers.
if (matrix == null)
{
matrix = binarizer.BlackMatrix;
}
return matrix;
}
}
/// <returns> Whether this bitmap can be cropped. </returns>
public bool CropSupported
{
get
{
return binarizer.LuminanceSource.CropSupported;
}
}
/// <summary>
/// Returns a new object with cropped image data. Implementations may keep a reference to the
/// original data rather than a copy. Only callable if isCropSupported() is true.
/// </summary>
/// <param name="left"> The left coordinate, 0 <= left < getWidth(). </param>
/// <param name="top"> The top coordinate, 0 <= top <= getHeight(). </param>
/// <param name="width"> The width of the rectangle to crop. </param>
/// <param name="height"> The height of the rectangle to crop. </param>
/// <returns> A cropped version of this object. </returns>
public BinaryBitmap crop(int left, int top, int width, int height)
{
LuminanceSource newSource = binarizer.LuminanceSource.crop(left, top, width, height);
return new BinaryBitmap(binarizer.createBinarizer(newSource));
}
/// <returns> Whether this bitmap supports counter-clockwise rotation. </returns>
public bool RotateSupported
{
get
{
return binarizer.LuminanceSource.RotateSupported;
}
}
/// <summary>
/// Returns a new object with rotated image data by 90 degrees counterclockwise.
/// Only callable if <seealso cref="#isRotateSupported()"/> is true.
/// </summary>
/// <returns> A rotated version of this object. </returns>
public BinaryBitmap rotateCounterClockwise()
{
LuminanceSource newSource = binarizer.LuminanceSource.rotateCounterClockwise();
return new BinaryBitmap(binarizer.createBinarizer(newSource));
}
/// <summary>
/// Returns a new object with rotated image data by 45 degrees counterclockwise.
/// Only callable if <seealso cref="#isRotateSupported()"/> is true.
/// </summary>
/// <returns> A rotated version of this object. </returns>
public BinaryBitmap rotateCounterClockwise45()
{
LuminanceSource newSource = binarizer.LuminanceSource.rotateCounterClockwise45();
return new BinaryBitmap(binarizer.createBinarizer(newSource));
}
}
}

View file

@ -1,77 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// Encapsulates a type of hint that a caller may pass to a barcode reader to help it
/// more quickly or accurately decode it. It is up to implementations to decide what,
/// if anything, to do with the information that is supplied.
///
/// @author Sean Owen
/// @author dswitkin@google.com (Daniel Switkin) </summary>
/// <seealso cref= Reader#decode(BinaryBitmap,java.util.Map) </seealso>
public enum DecodeHintType
{
/// <summary>
/// Unspecified, application-specific hint. Maps to an unspecified <seealso cref="Object"/>.
/// </summary>
OTHER,
/// <summary>
/// Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;
/// use <seealso cref="Boolean#TRUE"/>.
/// </summary>
PURE_BARCODE,
/// <summary>
/// Image is known to be of one of a few possible formats.
/// Maps to a <seealso cref="java.util.List"/> of <seealso cref="BarcodeFormat"/>s.
/// </summary>
POSSIBLE_FORMATS,
/// <summary>
/// Spend more time to try to find a barcode; optimize for accuracy, not speed.
/// Doesn't matter what it maps to; use <seealso cref="Boolean#TRUE"/>.
/// </summary>
TRY_HARDER,
/// <summary>
/// Specifies what character encoding to use when decoding, where applicable (type String)
/// </summary>
CHARACTER_SET,
/// <summary>
/// Allowed lengths of encoded data -- reject anything else. Maps to an int[].
/// </summary>
ALLOWED_LENGTHS,
/// <summary>
/// Assume Code 39 codes employ a check digit. Maps to <seealso cref="Boolean"/>.
/// </summary>
ASSUME_CODE_39_CHECK_DIGIT,
/// <summary>
/// The caller needs to be notified via callback when a possible <seealso cref="ResultPoint"/>
/// is found. Maps to a <seealso cref="ResultPointCallback"/>.
/// </summary>
NEED_RESULT_POINT_CALLBACK,
}
}

View file

@ -1,66 +0,0 @@
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// These are a set of hints that you may pass to Writers to specify their behavior.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public enum EncodeHintType
{
/// <summary>
/// Specifies what degree of error correction to use, for example in QR Codes.
/// Type depends on the encoder. For example for QR codes it's type
/// <seealso cref="com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ErrorCorrectionLevel"/>.
/// </summary>
ERROR_CORRECTION,
/// <summary>
/// Specifies what character encoding to use where applicable (type <seealso cref="String"/>)
/// </summary>
CHARACTER_SET,
/// <summary>
/// Specifies margin, in pixels, to use when generating the barcode. The meaning can vary
/// by format; for example it controls margin before and after the barcode horizontally for
/// most 1D formats. (Type <seealso cref="Integer"/>).
/// </summary>
MARGIN,
/// <summary>
/// Specifies whether to use compact mode for PDF417 (type <seealso cref="Boolean"/>).
/// </summary>
PDF417_COMPACT,
/// <summary>
/// Specifies what compaction mode to use for PDF417 (type
/// <seealso cref="com.google.zxing.pdf417.encoder.Compaction Compaction"/>).
/// </summary>
PDF417_COMPACTION,
/// <summary>
/// Specifies the minimum and maximum number of rows and columns for PDF417 (type
/// <seealso cref="com.google.zxing.pdf417.encoder.Dimensions Dimensions"/>).
/// </summary>
PDF417_DIMENSIONS,
}
}

View file

@ -1,171 +0,0 @@
using System.Text;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// The purpose of this class hierarchy is to abstract different bitmap implementations across
/// platforms into a standard interface for requesting greyscale luminance values. The interface
/// only provides immutable methods; therefore crop and rotation create copies. This is to ensure
/// that one Reader does not modify the original luminance source and leave it in an unknown state
/// for other Readers in the chain.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public abstract class LuminanceSource
{
private readonly int width;
private readonly int height;
protected internal LuminanceSource(int width, int height)
{
this.width = width;
this.height = height;
}
/// <summary>
/// Fetches one row of luminance data from the underlying platform's bitmap. Values range from
/// 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have
/// to bitwise and with 0xff for each value. It is preferable for implementations of this method
/// to only fetch this row rather than the whole image, since no 2D Readers may be installed and
/// getMatrix() may never be called.
/// </summary>
/// <param name="y"> The row to fetch, 0 <= y < getHeight(). </param>
/// <param name="row"> An optional preallocated array. If null or too small, it will be ignored.
/// Always use the returned object, and ignore the .length of the array. </param>
/// <returns> An array containing the luminance data. </returns>
public abstract sbyte[] getRow(int y, sbyte[] row);
/// <summary>
/// Fetches luminance data for the underlying bitmap. Values should be fetched using:
/// int luminance = array[y * width + x] & 0xff;
/// </summary>
/// <returns> A row-major 2D array of luminance values. Do not use result.length as it may be
/// larger than width * height bytes on some platforms. Do not modify the contents
/// of the result. </returns>
public abstract sbyte[] Matrix {get;}
/// <returns> The width of the bitmap. </returns>
public int Width
{
get
{
return width;
}
}
/// <returns> The height of the bitmap. </returns>
public int Height
{
get
{
return height;
}
}
/// <returns> Whether this subclass supports cropping. </returns>
public virtual bool CropSupported
{
get
{
return false;
}
}
/// <summary>
/// Returns a new object with cropped image data. Implementations may keep a reference to the
/// original data rather than a copy. Only callable if isCropSupported() is true.
/// </summary>
/// <param name="left"> The left coordinate, 0 <= left < getWidth(). </param>
/// <param name="top"> The top coordinate, 0 <= top <= getHeight(). </param>
/// <param name="width"> The width of the rectangle to crop. </param>
/// <param name="height"> The height of the rectangle to crop. </param>
/// <returns> A cropped version of this object. </returns>
public virtual LuminanceSource crop(int left, int top, int width, int height)
{
throw new System.NotSupportedException("This luminance source does not support cropping.");
}
/// <returns> Whether this subclass supports counter-clockwise rotation. </returns>
public virtual bool RotateSupported
{
get
{
return false;
}
}
/// <summary>
/// Returns a new object with rotated image data by 90 degrees counterclockwise.
/// Only callable if <seealso cref="#isRotateSupported()"/> is true.
/// </summary>
/// <returns> A rotated version of this object. </returns>
public virtual LuminanceSource rotateCounterClockwise()
{
throw new System.NotSupportedException("This luminance source does not support rotation by 90 degrees.");
}
/// <summary>
/// Returns a new object with rotated image data by 45 degrees counterclockwise.
/// Only callable if <seealso cref="#isRotateSupported()"/> is true.
/// </summary>
/// <returns> A rotated version of this object. </returns>
public virtual LuminanceSource rotateCounterClockwise45()
{
throw new System.NotSupportedException("This luminance source does not support rotation by 45 degrees.");
}
public override string ToString()
{
sbyte[] row = new sbyte[width];
StringBuilder result = new StringBuilder(height * (width + 1));
for (int y = 0; y < height; y++)
{
row = getRow(y, row);
for (int x = 0; x < width; x++)
{
int luminance = row[x] & 0xFF;
char c;
if (luminance < 0x40)
{
c = '#';
}
else if (luminance < 0x80)
{
c = '+';
}
else if (luminance < 0xC0)
{
c = '.';
}
else
{
c = ' ';
}
result.Append(c);
}
result.Append('\n');
}
return result.ToString();
}
}
}

View file

@ -1,207 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing
{
using AztecReader = com.google.zxing.aztec.AztecReader;
using DataMatrixReader = com.google.zxing.datamatrix.DataMatrixReader;
using MaxiCodeReader = com.google.zxing.maxicode.MaxiCodeReader;
using MultiFormatOneDReader = com.google.zxing.oned.MultiFormatOneDReader;
using PDF417Reader = com.google.zxing.pdf417.PDF417Reader;
using QRCodeReader = com.google.zxing.qrcode.QRCodeReader;
/// <summary>
/// MultiFormatReader is a convenience class and the main entry point into the library for most uses.
/// By default it attempts to decode all barcode formats that the library supports. Optionally, you
/// can provide a hints object to request different behavior, for example only decoding QR codes.
///
/// @author Sean Owen
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public sealed class MultiFormatReader : Reader
{
//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
//ORIGINAL LINE: private java.util.Map<DecodeHintType,?> hints;
private IDictionary<DecodeHintType, object> hints;
private Reader[] readers;
/// <summary>
/// This version of decode honors the intent of Reader.decode(BinaryBitmap) in that it
/// passes null as a hint to the decoders. However, that makes it inefficient to call repeatedly.
/// Use setHints() followed by decodeWithState() for continuous scan applications.
/// </summary>
/// <param name="image"> The pixel data to decode </param>
/// <returns> The contents of the image </returns>
/// <exception cref="NotFoundException"> Any errors which occurred </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public Result decode(BinaryBitmap image) throws NotFoundException
public Result decode(BinaryBitmap image)
{
Hints = null;
return decodeInternal(image);
}
/// <summary>
/// Decode an image using the hints provided. Does not honor existing state.
/// </summary>
/// <param name="image"> The pixel data to decode </param>
/// <param name="hints"> The hints to use, clearing the previous state. </param>
/// <returns> The contents of the image </returns>
/// <exception cref="NotFoundException"> Any errors which occurred </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public Result decode(BinaryBitmap image, java.util.Map<DecodeHintType,?> hints) throws NotFoundException
public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
{
Hints = hints;
return decodeInternal(image);
}
/// <summary>
/// Decode an image using the state set up by calling setHints() previously. Continuous scan
/// clients will get a <b>large</b> speed increase by using this instead of decode().
/// </summary>
/// <param name="image"> The pixel data to decode </param>
/// <returns> The contents of the image </returns>
/// <exception cref="NotFoundException"> Any errors which occurred </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public Result decodeWithState(BinaryBitmap image) throws NotFoundException
public Result decodeWithState(BinaryBitmap image)
{
// Make sure to set up the default state so we don't crash
if (readers == null)
{
Hints = null;
}
return decodeInternal(image);
}
/// <summary>
/// This method adds state to the MultiFormatReader. By setting the hints once, subsequent calls
/// to decodeWithState(image) can reuse the same set of readers without reallocating memory. This
/// is important for performance in continuous scan clients.
/// </summary>
/// <param name="hints"> The set of hints to use for subsequent calls to decode(image) </param>
public IDictionary<DecodeHintType, object> Hints
{
set
{
this.hints = value;
bool tryHarder = value != null && value.ContainsKey(DecodeHintType.TRY_HARDER);
//ICollection<BarcodeFormat> formats = value == null ? null : (ICollection<BarcodeFormat>) value[DecodeHintType.POSSIBLE_FORMATS];
ICollection<BarcodeFormat> formats = null;
if (value != null && value.ContainsKey(DecodeHintType.POSSIBLE_FORMATS))
{
formats = (ICollection<BarcodeFormat>)value[DecodeHintType.POSSIBLE_FORMATS];
}
List<Reader> readers = new List<Reader>();
if (formats != null)
{
bool addOneDReader = formats.Contains(BarcodeFormat.UPC_A) || formats.Contains(BarcodeFormat.UPC_E) || formats.Contains(BarcodeFormat.EAN_13) || formats.Contains(BarcodeFormat.EAN_8) || formats.Contains(BarcodeFormat.CODABAR) || formats.Contains(BarcodeFormat.CODE_39) || formats.Contains(BarcodeFormat.CODE_93) || formats.Contains(BarcodeFormat.CODE_128) || formats.Contains(BarcodeFormat.ITF) || formats.Contains(BarcodeFormat.RSS_14) || formats.Contains(BarcodeFormat.RSS_EXPANDED);
// Put 1D readers upfront in "normal" mode
if (addOneDReader && !tryHarder)
{
readers.Add(new MultiFormatOneDReader(value));
}
if (formats.Contains(BarcodeFormat.QR_CODE))
{
readers.Add(new QRCodeReader());
}
if (formats.Contains(BarcodeFormat.DATA_MATRIX))
{
readers.Add(new DataMatrixReader());
}
if (formats.Contains(BarcodeFormat.AZTEC))
{
readers.Add(new AztecReader());
}
if (formats.Contains(BarcodeFormat.PDF_417))
{
readers.Add(new PDF417Reader());
}
if (formats.Contains(BarcodeFormat.MAXICODE))
{
readers.Add(new MaxiCodeReader());
}
// At end in "try harder" mode
if (addOneDReader && tryHarder)
{
readers.Add(new MultiFormatOneDReader(value));
}
}
if (readers.Count == 0)
{
if (!tryHarder)
{
readers.Add(new MultiFormatOneDReader(value));
}
readers.Add(new QRCodeReader());
readers.Add(new DataMatrixReader());
readers.Add(new AztecReader());
readers.Add(new PDF417Reader());
readers.Add(new MaxiCodeReader());
if (tryHarder)
{
readers.Add(new MultiFormatOneDReader(value));
}
}
this.readers = readers.ToArray(/*new Reader[readers.Count]*/);
}
}
public void reset()
{
if (readers != null)
{
foreach (Reader reader in readers)
{
reader.reset();
}
}
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private Result decodeInternal(BinaryBitmap image) throws NotFoundException
private Result decodeInternal(BinaryBitmap image)
{
if (readers != null)
{
foreach (Reader reader in readers)
{
try
{
return reader.decode(image, hints);
}
catch (ReaderException re)
{
// continue
}
}
}
throw NotFoundException.NotFoundInstance;
}
}
}

View file

@ -1,93 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing
{
using BitMatrix = com.google.zxing.common.BitMatrix;
using CodaBarWriter = com.google.zxing.oned.CodaBarWriter;
using Code128Writer = com.google.zxing.oned.Code128Writer;
using Code39Writer = com.google.zxing.oned.Code39Writer;
using EAN13Writer = com.google.zxing.oned.EAN13Writer;
using EAN8Writer = com.google.zxing.oned.EAN8Writer;
using ITFWriter = com.google.zxing.oned.ITFWriter;
using UPCAWriter = com.google.zxing.oned.UPCAWriter;
using PDF417Writer = com.google.zxing.pdf417.encoder.PDF417Writer;
using QRCodeWriter = com.google.zxing.qrcode.QRCodeWriter;
/// <summary>
/// This is a factory class which finds the appropriate Writer subclass for the BarcodeFormat
/// requested and encodes the barcode with the supplied contents.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public sealed class MultiFormatWriter : Writer
{
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.BitMatrix encode(String contents, BarcodeFormat format, int width, int height) throws WriterException
public BitMatrix encode(string contents, BarcodeFormat format, int width, int height)
{
return encode(contents, format, width, height, null);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.BitMatrix encode(String contents, BarcodeFormat format, int width, int height, java.util.Map<EncodeHintType,?> hints) throws WriterException
public BitMatrix encode(string contents, BarcodeFormat format, int width, int height, IDictionary<EncodeHintType, object> hints)
{
Writer writer;
switch (format)
{
case com.google.zxing.BarcodeFormat.EAN_8:
writer = new EAN8Writer();
break;
case com.google.zxing.BarcodeFormat.EAN_13:
writer = new EAN13Writer();
break;
case com.google.zxing.BarcodeFormat.UPC_A:
writer = new UPCAWriter();
break;
case com.google.zxing.BarcodeFormat.QR_CODE:
writer = new QRCodeWriter();
break;
case com.google.zxing.BarcodeFormat.CODE_39:
writer = new Code39Writer();
break;
case com.google.zxing.BarcodeFormat.CODE_128:
writer = new Code128Writer();
break;
case com.google.zxing.BarcodeFormat.ITF:
writer = new ITFWriter();
break;
case com.google.zxing.BarcodeFormat.PDF_417:
writer = new PDF417Writer();
break;
case com.google.zxing.BarcodeFormat.CODABAR:
writer = new CodaBarWriter();
break;
default:
throw new System.ArgumentException("No encoder available for format " + format);
}
return writer.encode(contents, format, width, height, hints);
}
}
}

1
csharp/README.txt Normal file
View file

@ -0,0 +1 @@
For a port to C#, .NET and related Windows frameworks, see ZXing .NET at http://zxingnet.codeplex.com/

View file

@ -1,177 +0,0 @@
using System;
using System.Drawing;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// This class is used to help decode images from files which arrive as RGB data from
/// an ARGB pixel array. It does not support rotation.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// @author Betaminos
/// </summary>
public sealed class RGBLuminanceSource : LuminanceSource
{
private readonly sbyte[] luminances;
private readonly int dataWidth;
private readonly int dataHeight;
private readonly int left;
private readonly int top;
public RGBLuminanceSource(int width, int height, int[] pixels) : base(width, height)
{
dataWidth = width;
dataHeight = height;
left = 0;
top = 0;
// In order to measure pure decoding speed, we convert the entire image to a greyscale array
// up front, which is the same as the Y channel of the YUVLuminanceSource in the real app.
luminances = new sbyte[width * height];
for (int y = 0; y < height; y++)
{
int offset = y * width;
for (int x = 0; x < width; x++)
{
int pixel = pixels[offset + x];
int r = (pixel >> 16) & 0xff;
int g = (pixel >> 8) & 0xff;
int b = pixel & 0xff;
if (r == g && g == b)
{
// Image is already greyscale, so pick any channel.
luminances[offset + x] = (sbyte) r;
}
else
{
// Calculate luminance cheaply, favoring green.
luminances[offset + x] = (sbyte)((r + g + g + b) >> 2);
}
}
}
}
private RGBLuminanceSource(sbyte[] pixels, int dataWidth, int dataHeight, int left, int top, int width, int height) : base(width, height)
{
if (left + width > dataWidth || top + height > dataHeight)
{
throw new System.ArgumentException("Crop rectangle does not fit within image data.");
}
this.luminances = pixels;
this.dataWidth = dataWidth;
this.dataHeight = dataHeight;
this.left = left;
this.top = top;
}
public RGBLuminanceSource(Bitmap d, int W, int H)
: base(W, H)
{
int width = dataWidth = W;
int height = dataHeight = H;
// In order to measure pure decoding speed, we convert the entire image to a greyscale array
// up front, which is the same as the Y channel of the YUVLuminanceSource in the real app.
luminances = new sbyte[width * height];
//if (format == PixelFormat.Format8bppIndexed)
{
Color c;
for (int y = 0; y < height; y++)
{
int offset = y * width;
for (int x = 0; x < width; x++)
{
c = d.GetPixel(x, y);
luminances[offset + x] = (sbyte)(((int)c.R) << 16 | ((int)c.G) << 8 | ((int)c.B));
}
}
}
}
public override sbyte[] getRow(int y, sbyte[] row)
{
if (y < 0 || y >= Height)
{
throw new System.ArgumentException("Requested row is outside the image: " + y);
}
int width = Width;
if (row == null || row.Length < width)
{
row = new sbyte[width];
}
int offset = (y + top) * dataWidth + left;
Array.Copy(luminances, offset, row, 0, width);
return row;
}
public override sbyte[] Matrix
{
get
{
int width = Width;
int height = Height;
// If the caller asks for the entire underlying image, save the copy and give them the
// original data. The docs specifically warn that result.length must be ignored.
if (width == dataWidth && height == dataHeight)
{
return luminances;
}
int area = width * height;
sbyte[] matrix = new sbyte[area];
int inputOffset = top * dataWidth + left;
// If the width matches the full width of the underlying data, perform a single copy.
if (width == dataWidth)
{
Array.Copy(luminances, inputOffset, matrix, 0, area);
return matrix;
}
// Otherwise copy one cropped row at a time.
sbyte[] rgb = luminances;
for (int y = 0; y < height; y++)
{
int outputOffset = y * width;
Array.Copy(rgb, inputOffset, matrix, outputOffset, width);
inputOffset += dataWidth;
}
return matrix;
}
}
public override bool CropSupported
{
get
{
return true;
}
}
public override LuminanceSource crop(int left, int top, int width, int height)
{
return new RGBLuminanceSource(luminances, dataWidth, dataHeight, this.left + left, this.top + top, width, height);
}
}
}

View file

@ -1,70 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// Implementations of this interface can decode an image of a barcode in some format into
/// the String it encodes. For example, <seealso cref="com.google.zxing.qrcode.QRCodeReader"/> can
/// decode a QR code. The decoder may optionally receive hints from the caller which may help
/// it decode more quickly or accurately.
///
/// See <seealso cref="com.google.zxing.MultiFormatReader"/>, which attempts to determine what barcode
/// format is present within the image as well, and then decodes it accordingly.
///
/// @author Sean Owen
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public interface Reader
{
/// <summary>
/// Locates and decodes a barcode in some format within an image.
/// </summary>
/// <param name="image"> image of barcode to decode </param>
/// <returns> String which the barcode encodes </returns>
/// <exception cref="NotFoundException"> if the barcode cannot be located or decoded for any reason </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException;
Result decode(BinaryBitmap image);
/// <summary>
/// Locates and decodes a barcode in some format within an image. This method also accepts
/// hints, each possibly associated to some data, which may help the implementation decode.
/// </summary>
/// <param name="image"> image of barcode to decode </param>
/// <param name="hints"> passed as a <seealso cref="java.util.Map"/> from <seealso cref="com.google.zxing.DecodeHintType"/>
/// to arbitrary data. The
/// meaning of the data depends upon the hint type. The implementation may or may not do
/// anything with these hints. </param>
/// <returns> String which the barcode encodes </returns>
/// <exception cref="NotFoundException"> if the barcode cannot be located or decoded for any reason </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: Result decode(BinaryBitmap image, java.util.Map<DecodeHintType,?> hints) throws NotFoundException, ChecksumException, FormatException;
Result decode(BinaryBitmap image, IDictionary<DecodeHintType,object> hints);
/// <summary>
/// Resets any internal state the implementation has after a decode, to prepare it
/// for reuse.
/// </summary>
void reset();
}
}

View file

@ -1,47 +0,0 @@
using System;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// The general exception class throw when something goes wrong during decoding of a barcode.
/// This includes, but is not limited to, failing checksums / error correction algorithms, being
/// unable to locate finder timing patterns, and so on.
///
/// @author Sean Owen
/// </summary>
public abstract class ReaderException : Exception
{
internal ReaderException()
{
// do nothing
}
// Prevent stack traces from being taken
// srowen says: huh, my IDE is saying this is not an override. native methods can't be overridden?
// This, at least, does not hurt. Because we use a singleton pattern here, it doesn't matter anyhow.
public Exception fillInStackTrace()
{
return null;
}
}
}

View file

@ -1,174 +0,0 @@
using System;
using System.Collections.Generic;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// <p>Encapsulates the result of decoding a barcode within an image.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class Result
{
private readonly string text;
private readonly sbyte[] rawBytes;
private ResultPoint[] resultPoints;
private readonly BarcodeFormat format;
private IDictionary<ResultMetadataType, object> resultMetadata;
private readonly long timestamp;
//public Result(string text, sbyte[] rawBytes, ResultPoint[] resultPoints, BarcodeFormat format)
// : this(text, rawBytes, resultPoints, format, System.currentTimeMillis())
public Result(string text, sbyte[] rawBytes, ResultPoint[] resultPoints, BarcodeFormat format)
: this(text, rawBytes, resultPoints, format, CurrentTimeMillis())
{
}
public Result(string text, sbyte[] rawBytes, ResultPoint[] resultPoints, BarcodeFormat format, long timestamp)
{
this.text = text;
this.rawBytes = rawBytes;
this.resultPoints = resultPoints;
this.format = format;
this.resultMetadata = null;
this.timestamp = timestamp;
}
/// <returns> raw text encoded by the barcode </returns>
public string Text
{
get
{
return text;
}
}
/// <returns> raw bytes encoded by the barcode, if applicable, otherwise {@code null} </returns>
public sbyte[] RawBytes
{
get
{
return rawBytes;
}
}
/// <returns> points related to the barcode in the image. These are typically points
/// identifying finder patterns or the corners of the barcode. The exact meaning is
/// specific to the type of barcode that was decoded. </returns>
public ResultPoint[] ResultPoints
{
get
{
return resultPoints;
}
}
/// <returns> <seealso cref="BarcodeFormat"/> representing the format of the barcode that was decoded </returns>
public BarcodeFormat BarcodeFormat
{
get
{
return format;
}
}
/// <returns> <seealso cref="Map"/> mapping <seealso cref="ResultMetadataType"/> keys to values. May be
/// {@code null}. This contains optional metadata about what was detected about the barcode,
/// like orientation. </returns>
public IDictionary<ResultMetadataType, object> ResultMetadata
{
get
{
return resultMetadata;
}
}
public void putMetadata(ResultMetadataType type, object value)
{
if (resultMetadata == null)
{
//resultMetadata = new EnumMap<ResultMetadataType, object>(typeof(ResultMetadataType));
resultMetadata = new Dictionary<ResultMetadataType, object>();
}
resultMetadata[type] = value;
}
public void putAllMetadata(IDictionary<ResultMetadataType, object> metadata)
{
if (metadata != null)
{
if (resultMetadata == null)
{
resultMetadata = metadata;
}
else
{
//JAVA TO C# CONVERTER TODO TASK: There is no .NET Dictionary equivalent to the Java 'putAll' method:
//resultMetadata.putAll(metadata);
foreach (KeyValuePair<ResultMetadataType, object> kvp in metadata)
{
resultMetadata.Add(kvp);
}
}
}
}
public void addResultPoints(ResultPoint[] newPoints)
{
ResultPoint[] oldPoints = resultPoints;
if (oldPoints == null)
{
resultPoints = newPoints;
}
else if (newPoints != null && newPoints.Length > 0)
{
ResultPoint[] allPoints = new ResultPoint[oldPoints.Length + newPoints.Length];
Array.Copy(oldPoints, 0, allPoints, 0, oldPoints.Length);
Array.Copy(newPoints, 0, allPoints, oldPoints.Length, newPoints.Length);
resultPoints = allPoints;
}
}
public long Timestamp
{
get
{
return timestamp;
}
}
public override string ToString()
{
return text;
}
private static readonly DateTime Jan1st1970 = new DateTime
(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static long CurrentTimeMillis()
{
return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;
}
}
}

View file

@ -1,84 +0,0 @@
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// Represents some type of metadata about the result of the decoding that the decoder
/// wishes to communicate back to the caller.
///
/// @author Sean Owen
/// </summary>
public enum ResultMetadataType
{
/// <summary>
/// Unspecified, application-specific metadata. Maps to an unspecified <seealso cref="Object"/>.
/// </summary>
OTHER,
/// <summary>
/// Denotes the likely approximate orientation of the barcode in the image. This value
/// is given as degrees rotated clockwise from the normal, upright orientation.
/// For example a 1D barcode which was found by reading top-to-bottom would be
/// said to have orientation "90". This key maps to an <seealso cref="Integer"/> whose
/// value is in the range [0,360).
/// </summary>
ORIENTATION,
/// <summary>
/// <p>2D barcode formats typically encode text, but allow for a sort of 'byte mode'
/// which is sometimes used to encode binary data. While <seealso cref="Result"/> makes available
/// the complete raw bytes in the barcode for these formats, it does not offer the bytes
/// from the byte segments alone.</p>
///
/// <p>This maps to a <seealso cref="java.util.List"/> of byte arrays corresponding to the
/// raw bytes in the byte segments in the barcode, in order.</p>
/// </summary>
BYTE_SEGMENTS,
/// <summary>
/// Error correction level used, if applicable. The value type depends on the
/// format, but is typically a String.
/// </summary>
ERROR_CORRECTION_LEVEL,
/// <summary>
/// For some periodicals, indicates the issue number as an <seealso cref="Integer"/>.
/// </summary>
ISSUE_NUMBER,
/// <summary>
/// For some products, indicates the suggested retail price in the barcode as a
/// formatted <seealso cref="String"/>.
/// </summary>
SUGGESTED_PRICE,
/// <summary>
/// For some products, the possible country of manufacture as a <seealso cref="String"/> denoting the
/// ISO country code. Some map to multiple possible countries, like "US/CA".
/// </summary>
POSSIBLE_COUNTRY,
/// <summary>
/// For some products, the extension text
/// </summary>
UPC_EAN_EXTENSION,
}
}

View file

@ -1,160 +0,0 @@
using System;
using System.Text;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing
{
using MathUtils = com.google.zxing.common.detector.MathUtils;
/// <summary>
/// <p>Encapsulates a point of interest in an image containing a barcode. Typically, this
/// would be the location of a finder pattern or the corner of the barcode, for example.</p>
///
/// @author Sean Owen
/// </summary>
public class ResultPoint
{
private readonly float x;
private readonly float y;
public ResultPoint(float x, float y)
{
this.x = x;
this.y = y;
}
public float X
{
get
{
return x;
}
}
public float Y
{
get
{
return y;
}
}
public override bool Equals(object other)
{
if (other is ResultPoint)
{
ResultPoint otherPoint = (ResultPoint) other;
return x == otherPoint.x && y == otherPoint.y;
}
return false;
}
public override int GetHashCode()
{
//return 31 * float.floatToIntBits(x) + float.floatToIntBits(y);
int xbits = BitConverter.ToInt32(BitConverter.GetBytes(x), 0);
int ybits = BitConverter.ToInt32(BitConverter.GetBytes(y), 0);
return 31 * xbits + ybits;
}
public override string ToString()
{
StringBuilder result = new StringBuilder(25);
result.Append('(');
result.Append(x);
result.Append(',');
result.Append(y);
result.Append(')');
return result.ToString();
}
/// <summary>
/// <p>Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and
/// BC < AC and the angle between BC and BA is less than 180 degrees.
/// </summary>
public static void orderBestPatterns(ResultPoint[] patterns)
{
// Find distances between pattern centers
float zeroOneDistance = distance(patterns[0], patterns[1]);
float oneTwoDistance = distance(patterns[1], patterns[2]);
float zeroTwoDistance = distance(patterns[0], patterns[2]);
ResultPoint pointA;
ResultPoint pointB;
ResultPoint pointC;
// Assume one closest to other two is B; A and C will just be guesses at first
if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance)
{
pointB = patterns[0];
pointA = patterns[1];
pointC = patterns[2];
}
else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance)
{
pointB = patterns[1];
pointA = patterns[0];
pointC = patterns[2];
}
else
{
pointB = patterns[2];
pointA = patterns[0];
pointC = patterns[1];
}
// Use cross product to figure out whether A and C are correct or flipped.
// This asks whether BC x BA has a positive z component, which is the arrangement
// we want for A, B, C. If it's negative, then we've got it flipped around and
// should swap A and C.
if (crossProductZ(pointA, pointB, pointC) < 0.0f)
{
ResultPoint temp = pointA;
pointA = pointC;
pointC = temp;
}
patterns[0] = pointA;
patterns[1] = pointB;
patterns[2] = pointC;
}
/// <returns> distance between two points </returns>
public static float distance(ResultPoint pattern1, ResultPoint pattern2)
{
return MathUtils.distance(pattern1.x, pattern1.y, pattern2.x, pattern2.y);
}
/// <summary>
/// Returns the z component of the cross product between vectors BC and BA.
/// </summary>
private static float crossProductZ(ResultPoint pointA, ResultPoint pointB, ResultPoint pointC)
{
float bX = pointB.x;
float bY = pointB.y;
return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));
}
}
}

View file

@ -1,32 +0,0 @@
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// Callback which is invoked when a possible result point (significant
/// point in the barcode image such as a corner) is found.
/// </summary>
/// <seealso cref= DecodeHintType#NEED_RESULT_POINT_CALLBACK </seealso>
public interface ResultPointCallback
{
void foundPossibleResultPoint(ResultPoint point);
}
}

View file

@ -1,56 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing
{
using BitMatrix = com.google.zxing.common.BitMatrix;
/// <summary>
/// The base class for all objects which encode/generate a barcode image.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public interface Writer
{
/// <summary>
/// Encode a barcode using the default settings.
/// </summary>
/// <param name="contents"> The contents to encode in the barcode </param>
/// <param name="format"> The barcode format to generate </param>
/// <param name="width"> The preferred width in pixels </param>
/// <param name="height"> The preferred height in pixels </param>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: com.google.zxing.common.BitMatrix encode(String contents, BarcodeFormat format, int width, int height) throws WriterException;
BitMatrix encode(string contents, BarcodeFormat format, int width, int height);
///
/// <param name="contents"> The contents to encode in the barcode </param>
/// <param name="format"> The barcode format to generate </param>
/// <param name="width"> The preferred width in pixels </param>
/// <param name="height"> The preferred height in pixels </param>
/// <param name="hints"> Additional parameters to supply to the encoder </param>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: com.google.zxing.common.BitMatrix encode(String contents, BarcodeFormat format, int width, int height, java.util.Map<EncodeHintType,?> hints) throws WriterException;
BitMatrix encode(string contents, BarcodeFormat format, int width, int height, IDictionary<EncodeHintType, object> hints);
}
}

View file

@ -1,45 +0,0 @@
using System;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing
{
/// <summary>
/// A base class which covers the range of exceptions which may occur when encoding a barcode using
/// the Writer framework.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public sealed class WriterException : Exception
{
public WriterException()
{
}
public WriterException(string message) : base(message)
{
}
public WriterException(Exception cause) : base(cause.Message,cause)
{
}
}
}

View file

@ -1,45 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// <p>See
/// <a href="http://www.nttdocomo.co.jp/english/service/imode/make/content/barcode/about/s2.html">
/// DoCoMo's documentation</a> about the result types represented by subclasses of this class.</p>
///
/// <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
/// on exception-based mechanisms during parsing.</p>
///
/// @author Sean Owen
/// </summary>
public abstract class AbstractDoCoMoResultParser : ResultParser
{
internal static string[] matchDoCoMoPrefixedField(string prefix, string rawText, bool trim)
{
return matchPrefixedField(prefix, rawText, ';', trim);
}
internal static string matchSingleDoCoMoPrefixedField(string prefix, string rawText, bool trim)
{
return matchSinglePrefixedField(prefix, rawText, ';', trim);
}
}
}

View file

@ -1,83 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Implements KDDI AU's address book format. See
/// <a href="http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html">
/// http://www.au.kddi.com/ezfactory/tec/two_dimensions/index.html</a>.
/// (Thanks to Yuzo for translating!)
///
/// @author Sean Owen
/// </summary>
public sealed class AddressBookAUResultParser : ResultParser
{
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
// MEMORY is mandatory; seems like a decent indicator, as does end-of-record separator CR/LF
if (!rawText.Contains("MEMORY") || !rawText.Contains("\r\n"))
{
return null;
}
// NAME1 and NAME2 have specific uses, namely written name and pronunciation, respectively.
// Therefore we treat them specially instead of as an array of names.
string name = matchSinglePrefixedField("NAME1:", rawText, '\r', true);
string pronunciation = matchSinglePrefixedField("NAME2:", rawText, '\r', true);
string[] phoneNumbers = matchMultipleValuePrefix("TEL", 3, rawText, true);
string[] emails = matchMultipleValuePrefix("MAIL", 3, rawText, true);
string note = matchSinglePrefixedField("MEMORY:", rawText, '\r', false);
string address = matchSinglePrefixedField("ADD:", rawText, '\r', true);
string[] addresses = address == null ? null : new string[] {address};
return new AddressBookParsedResult(maybeWrap(name), pronunciation, phoneNumbers, null, emails, null, null, note, addresses, null, null, null, null, null);
}
private static string[] matchMultipleValuePrefix(string prefix, int max, string rawText, bool trim)
{
List<string> values = null;
for (int i = 1; i <= max; i++)
{
string value = matchSinglePrefixedField(prefix + i + ':', rawText, '\r', trim);
if (value == null)
{
break;
}
if (values == null)
{
values = new List<string>(max); // lazy init
}
values.Add(value);
}
if (values == null)
{
return null;
}
return values.ToArray();
}
}
}

View file

@ -1,86 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Implements the "MECARD" address book entry format.
///
/// Supported keys: N, SOUND, TEL, EMAIL, NOTE, ADR, BDAY, URL, plus ORG
/// Unsupported keys: TEL-AV, NICKNAME
///
/// Except for TEL, multiple values for keys are also not supported;
/// the first one found takes precedence.
///
/// Our understanding of the MECARD format is based on this document:
///
/// http://www.mobicode.org.tw/files/OMIA%20Mobile%20Bar%20Code%20Standard%20v3.2.1.doc
///
/// @author Sean Owen
/// </summary>
public sealed class AddressBookDoCoMoResultParser : AbstractDoCoMoResultParser
{
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
if (!rawText.StartsWith("MECARD:"))
{
return null;
}
string[] rawName = matchDoCoMoPrefixedField("N:", rawText, true);
if (rawName == null)
{
return null;
}
string name = parseName(rawName[0]);
string pronunciation = matchSingleDoCoMoPrefixedField("SOUND:", rawText, true);
string[] phoneNumbers = matchDoCoMoPrefixedField("TEL:", rawText, true);
string[] emails = matchDoCoMoPrefixedField("EMAIL:", rawText, true);
string note = matchSingleDoCoMoPrefixedField("NOTE:", rawText, false);
string[] addresses = matchDoCoMoPrefixedField("ADR:", rawText, true);
string birthday = matchSingleDoCoMoPrefixedField("BDAY:", rawText, true);
if (birthday != null && !isStringOfDigits(birthday, 8))
{
// No reason to throw out the whole card because the birthday is formatted wrong.
birthday = null;
}
string url = matchSingleDoCoMoPrefixedField("URL:", rawText, true);
// Although ORG may not be strictly legal in MECARD, it does exist in VCARD and we might as well
// honor it when found in the wild.
string org = matchSingleDoCoMoPrefixedField("ORG:", rawText, true);
return new AddressBookParsedResult(maybeWrap(name), pronunciation, phoneNumbers, null, emails, null, null, note, addresses, null, org, birthday, null, url);
}
private static string parseName(string name)
{
int comma =(int) name.IndexOf(',');
if (comma >= 0)
{
// Format may be last,first; switch it around
return name.Substring(comma + 1) + ' ' + name.Substring(0, comma);
}
return name;
}
}
}

View file

@ -1,207 +0,0 @@
using System.Text;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// @author Sean Owen
/// </summary>
public sealed class AddressBookParsedResult : ParsedResult
{
private readonly string[] names;
private readonly string pronunciation;
private readonly string[] phoneNumbers;
private readonly string[] phoneTypes;
private readonly string[] emails;
private readonly string[] emailTypes;
private readonly string instantMessenger;
private readonly string note;
private readonly string[] addresses;
private readonly string[] addressTypes;
private readonly string org;
private readonly string birthday;
private readonly string title;
private readonly string url;
public AddressBookParsedResult(string[] names, string pronunciation, string[] phoneNumbers, string[] phoneTypes, string[] emails, string[] emailTypes, string instantMessenger, string note, string[] addresses, string[] addressTypes, string org, string birthday, string title, string url) : base(ParsedResultType.ADDRESSBOOK)
{
this.names = names;
this.pronunciation = pronunciation;
this.phoneNumbers = phoneNumbers;
this.phoneTypes = phoneTypes;
this.emails = emails;
this.emailTypes = emailTypes;
this.instantMessenger = instantMessenger;
this.note = note;
this.addresses = addresses;
this.addressTypes = addressTypes;
this.org = org;
this.birthday = birthday;
this.title = title;
this.url = url;
}
public string[] Names
{
get
{
return names;
}
}
/// <summary>
/// In Japanese, the name is written in kanji, which can have multiple readings. Therefore a hint
/// is often provided, called furigana, which spells the name phonetically.
/// </summary>
/// <returns> The pronunciation of the getNames() field, often in hiragana or katakana. </returns>
public string Pronunciation
{
get
{
return pronunciation;
}
}
public string[] PhoneNumbers
{
get
{
return phoneNumbers;
}
}
/// <returns> optional descriptions of the type of each phone number. It could be like "HOME", but,
/// there is no guaranteed or standard format. </returns>
public string[] PhoneTypes
{
get
{
return phoneTypes;
}
}
public string[] Emails
{
get
{
return emails;
}
}
/// <returns> optional descriptions of the type of each e-mail. It could be like "WORK", but,
/// there is no guaranteed or standard format. </returns>
public string[] EmailTypes
{
get
{
return emailTypes;
}
}
public string InstantMessenger
{
get
{
return instantMessenger;
}
}
public string Note
{
get
{
return note;
}
}
public string[] Addresses
{
get
{
return addresses;
}
}
/// <returns> optional descriptions of the type of each e-mail. It could be like "WORK", but,
/// there is no guaranteed or standard format. </returns>
public string[] AddressTypes
{
get
{
return addressTypes;
}
}
public string Title
{
get
{
return title;
}
}
public string Org
{
get
{
return org;
}
}
public string URL
{
get
{
return url;
}
}
/// <returns> birthday formatted as yyyyMMdd (e.g. 19780917) </returns>
public string Birthday
{
get
{
return birthday;
}
}
public override string DisplayResult
{
get
{
StringBuilder result = new StringBuilder(100);
maybeAppend(names, result);
maybeAppend(pronunciation, result);
maybeAppend(title, result);
maybeAppend(org, result);
maybeAppend(addresses, result);
maybeAppend(phoneNumbers, result);
maybeAppend(emails, result);
maybeAppend(instantMessenger, result);
maybeAppend(url, result);
maybeAppend(birthday, result);
maybeAppend(note, result);
return result.ToString();
}
}
}
}

View file

@ -1,97 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Implements the "BIZCARD" address book entry format, though this has been
/// largely reverse-engineered from examples observed in the wild -- still
/// looking for a definitive reference.
///
/// @author Sean Owen
/// </summary>
public sealed class BizcardResultParser : AbstractDoCoMoResultParser
{
// Yes, we extend AbstractDoCoMoResultParser since the format is very much
// like the DoCoMo MECARD format, but this is not technically one of
// DoCoMo's proposed formats
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
if (!rawText.StartsWith("BIZCARD:"))
{
return null;
}
string firstName = matchSingleDoCoMoPrefixedField("N:", rawText, true);
string lastName = matchSingleDoCoMoPrefixedField("X:", rawText, true);
string fullName = buildName(firstName, lastName);
string title = matchSingleDoCoMoPrefixedField("T:", rawText, true);
string org = matchSingleDoCoMoPrefixedField("C:", rawText, true);
string[] addresses = matchDoCoMoPrefixedField("A:", rawText, true);
string phoneNumber1 = matchSingleDoCoMoPrefixedField("B:", rawText, true);
string phoneNumber2 = matchSingleDoCoMoPrefixedField("M:", rawText, true);
string phoneNumber3 = matchSingleDoCoMoPrefixedField("F:", rawText, true);
string email = matchSingleDoCoMoPrefixedField("E:", rawText, true);
return new AddressBookParsedResult(maybeWrap(fullName), null, buildPhoneNumbers(phoneNumber1, phoneNumber2, phoneNumber3), null, maybeWrap(email), null, null, null, addresses, null, org, null, title, null);
}
private static string[] buildPhoneNumbers(string number1, string number2, string number3)
{
List<string> numbers = new List<string>(3);
if (number1 != null)
{
numbers.Add(number1);
}
if (number2 != null)
{
numbers.Add(number2);
}
if (number3 != null)
{
numbers.Add(number3);
}
int size = numbers.Count;
if (size == 0)
{
return null;
}
return numbers.ToArray();
}
private static string buildName(string firstName, string lastName)
{
if (firstName == null)
{
return lastName;
}
else
{
return lastName == null ? firstName : firstName + ' ' + lastName;
}
}
}
}

View file

@ -1,46 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// @author Sean Owen
/// </summary>
public sealed class BookmarkDoCoMoResultParser : AbstractDoCoMoResultParser
{
public override ParsedResult parse(Result result)
{
string rawText = result.Text;
if (!rawText.StartsWith("MEBKM:"))
{
return null;
}
string title = matchSingleDoCoMoPrefixedField("TITLE:", rawText, true);
string[] rawUri = matchDoCoMoPrefixedField("URL:", rawText, true);
if (rawUri == null)
{
return null;
}
string uri = rawUri[0];
return URIResultParser.isBasicallyValidURI(uri) ? new URIParsedResult(uri, title) : null;
}
}
}

View file

@ -1,300 +0,0 @@
using System;
using System.Text;
using System.Text.RegularExpressions;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// @author Sean Owen
/// </summary>
public sealed class CalendarParsedResult : ParsedResult
{
private static readonly string RFC2445_DURATION = "P(?:(\\d+)W)?(?:(\\d+)D)?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?)?";
private static readonly long[] RFC2445_DURATION_FIELD_UNITS = {7 * 24 * 60 * 60 * 1000L, 24 * 60 * 60 * 1000L, 60 * 60 * 1000L, 60 * 1000L, 1000L};
private static readonly string DATE_TIME = "[0-9]{8}(T[0-9]{6}Z?)?";
private static readonly string DATE_FORMAT = "yyyyMMdd";
static CalendarParsedResult()
{
// For dates without a time, for purposes of interacting with Android, the resulting timestamp
// needs to be midnight of that day in GMT. See:
// http://code.google.com/p/android/issues/detail?id=8330
string DATE_FORMAT_TimeZone = "GMT";
}
private static readonly string DATE_TIME_FORMAT = "yyyyMMdd'T'HHmmss";
private readonly string summary;
private readonly DateTime start;
private readonly bool startAllDay;
private readonly DateTime? end;
private readonly bool endAllDay;
private readonly string location;
private readonly string organizer;
private readonly string[] attendees;
private readonly string description;
private readonly double latitude;
private readonly double longitude;
public CalendarParsedResult(string summary, string startString, string endString, string durationString, string location, string organizer, string[] attendees, string description, double latitude, double longitude) : base(ParsedResultType.CALENDAR)
{
this.summary = summary;
try
{
this.start = parseDate(startString);
}
catch (FormatException pe)
{
throw new System.ArgumentException(pe.ToString());
}
if (endString == null)
{
long durationMS = parseDurationMS(durationString);
end = durationMS < 0L ? null :(DateTime?) start.AddMilliseconds( durationMS);
}
else
{
try
{
this.end = parseDate(endString);
}
catch (FormatException pe)
{
throw new System.ArgumentException(pe.ToString());
}
}
this.startAllDay = startString.Length == 8;
this.endAllDay = endString != null && endString.Length == 8;
this.location = location;
this.organizer = organizer;
this.attendees = attendees;
this.description = description;
this.latitude = latitude;
this.longitude = longitude;
}
public string Summary
{
get
{
return summary;
}
}
/// <returns> start time </returns>
public DateTime Start
{
get
{
return start;
}
}
/// <returns> true if start time was specified as a whole day </returns>
public bool StartAllDay
{
get
{
return startAllDay;
}
}
/// <summary>
/// May return null if the event has no duration. </summary>
/// <seealso cref= #getStart() </seealso>
public DateTime? End
{
get
{
return end;
}
}
/// <returns> true if end time was specified as a whole day </returns>
public bool EndAllDay
{
get
{
return endAllDay;
}
}
public string Location
{
get
{
return location;
}
}
public string Organizer
{
get
{
return organizer;
}
}
public string[] Attendees
{
get
{
return attendees;
}
}
public string Description
{
get
{
return description;
}
}
public double Latitude
{
get
{
return latitude;
}
}
public double Longitude
{
get
{
return longitude;
}
}
public override string DisplayResult
{
get
{
StringBuilder result = new StringBuilder(100);
maybeAppend(summary, result);
maybeAppend(format(startAllDay, start), result);
maybeAppend(format(endAllDay, end), result);
maybeAppend(location, result);
maybeAppend(organizer, result);
maybeAppend(attendees, result);
maybeAppend(description, result);
return result.ToString();
}
}
/// <summary>
/// Parses a string as a date. RFC 2445 allows the start and end fields to be of type DATE (e.g. 20081021)
/// or DATE-TIME (e.g. 20081021T123000 for local time, or 20081021T123000Z for UTC).
/// </summary>
/// <param name="when"> The string to parse </param>
/// <exception cref="FormatException"> if not able to parse as a date </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static java.util.Date parseDate(String when) throws java.text.ParseException
private static DateTime parseDate(string when)
{
if (!(new Regex (DATE_TIME).IsMatch(when)))
{
throw FormatException.FormatInstance;
}
if (when.Length == 8)
{
// Show only year/month/day
return DateTime.Parse(when);
}
else
{
// The when string can be local time, or UTC if it ends with a Z
DateTime date;
if (when.Length == 16 && when[15] == 'Z')
{
date = DateTime.Parse(when.Substring(0, 15));
//DateTime calendar = new GregorianCalendar();
// System.Globalization.GregorianCalendar calendar = new System.Globalization.GregorianCalendar()
//long milliseconds = date;
//// Account for time zone difference
//milliseconds += calendar.get(DateTime.ZONE_OFFSET);
//// Might need to correct for daylight savings time, but use target time since
//// now might be in DST but not then, or vice versa
//calendar = new DateTime(milliseconds);
//milliseconds += calendar.get(DateTime.DST_OFFSET);
TimeSpan offset = TimeZone.CurrentTimeZone.GetUtcOffset(date);
date = date + offset;
}
else
{
date = DateTime.Parse(when);
}
return date;
}
}
private static string format(bool allDay, DateTime? date)
{
if (date == null)
{
return null;
}
//DateFormat format = allDay ? DateFormat.getDateInstance(DateFormat.MEDIUM) : DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
//return format.format(date);
if (allDay)
{
return String.Format("dd-MMM-yyyy",date);
}
else
{
return String.Format("dd-MMM-yyyy hh:mm:ss tt",date);
}
}
private static long parseDurationMS(string durationString)
{
if (durationString == null)
{
return -1L;
}
Regex m = new Regex(RFC2445_DURATION);
Match match = m.Match(durationString);
if (!match.Success)
{
return -1L;
}
long durationMS = 0L;
for (int i = 0; i < RFC2445_DURATION_FIELD_UNITS.Length; i++)
{
string fieldValue = match.Groups[i + 1].Value;
if (fieldValue != null)
{
durationMS += RFC2445_DURATION_FIELD_UNITS[i] * Convert.ToInt32(fieldValue);
}
}
return durationMS;
}
}
}

View file

@ -1,86 +0,0 @@
using System.Text;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// @author Sean Owen
/// </summary>
public sealed class EmailAddressParsedResult : ParsedResult
{
private readonly string emailAddress;
private readonly string subject;
private readonly string body;
private readonly string mailtoURI;
internal EmailAddressParsedResult(string emailAddress, string subject, string body, string mailtoURI) : base(ParsedResultType.EMAIL_ADDRESS)
{
this.emailAddress = emailAddress;
this.subject = subject;
this.body = body;
this.mailtoURI = mailtoURI;
}
public string EmailAddress
{
get
{
return emailAddress;
}
}
public string Subject
{
get
{
return subject;
}
}
public string Body
{
get
{
return body;
}
}
public string MailtoURI
{
get
{
return mailtoURI;
}
}
public override string DisplayResult
{
get
{
StringBuilder result = new StringBuilder(30);
maybeAppend(emailAddress, result);
maybeAppend(subject, result);
maybeAppend(body, result);
return result.ToString();
}
}
}
}

View file

@ -1,73 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Represents a result that encodes an e-mail address, either as a plain address
/// like "joe@example.org" or a mailto: URL like "mailto:joe@example.org".
///
/// @author Sean Owen
/// </summary>
public sealed class EmailAddressResultParser : ResultParser
{
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
string emailAddress;
if (rawText.StartsWith("mailto:") || rawText.StartsWith("MAILTO:"))
{
// If it starts with mailto:, assume it is definitely trying to be an email address
emailAddress = rawText.Substring(7);
int queryStart = emailAddress.IndexOf('?');
if (queryStart >= 0)
{
emailAddress = emailAddress.Substring(0, queryStart);
}
IDictionary<string, string> nameValues = parseNameValuePairs(rawText);
string subject = null;
string body = null;
if (nameValues != null)
{
if (emailAddress.Length == 0)
{
emailAddress = nameValues["to"];
}
subject = nameValues["subject"];
body = nameValues["body"];
}
return new EmailAddressParsedResult(emailAddress, subject, body, rawText);
}
else
{
if (!EmailDoCoMoResultParser.isBasicallyValidEmailAddress(rawText))
{
return null;
}
emailAddress = rawText;
return new EmailAddressParsedResult(emailAddress, null, null, "mailto:" + emailAddress);
}
}
}
}

View file

@ -1,71 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
using System.Text.RegularExpressions;
/// <summary>
/// Implements the "MATMSG" email message entry format.
///
/// Supported keys: TO, SUB, BODY
///
/// @author Sean Owen
/// </summary>
public sealed class EmailDoCoMoResultParser : AbstractDoCoMoResultParser
{
private static readonly string ATEXT_ALPHANUMERIC = "[a-zA-Z0-9@.!#$%&'*+\\-/=?^_`{|}~]+";
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
if (!rawText.StartsWith("MATMSG:"))
{
return null;
}
string[] rawTo = matchDoCoMoPrefixedField("TO:", rawText, true);
if (rawTo == null)
{
return null;
}
string to = rawTo[0];
if (!isBasicallyValidEmailAddress(to))
{
return null;
}
string subject = matchSingleDoCoMoPrefixedField("SUB:", rawText, false);
string body = matchSingleDoCoMoPrefixedField("BODY:", rawText, false);
return new EmailAddressParsedResult(to, subject, body, "mailto:" + to);
}
/// <summary>
/// This implements only the most basic checking for an email address's validity -- that it contains
/// an '@' and contains no characters disallowed by RFC 2822. This is an overly lenient definition of
/// validity. We want to generally be lenient here since this class is only intended to encapsulate what's
/// in a barcode, not "judge" it.
/// </summary>
internal static bool isBasicallyValidEmailAddress(string email)
{
//return email != null && ATEXT_ALPHANUMERIC.matcher(email).matches() && email.IndexOf('@') >= 0;
return email != null && new Regex( ATEXT_ALPHANUMERIC).IsMatch(email) && email.IndexOf('@') >= 0;
}
}
}

View file

@ -1,125 +0,0 @@
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// @author Sean Owen
/// </summary>
public sealed class GeoParsedResult : ParsedResult
{
private readonly double latitude;
private readonly double longitude;
private readonly double altitude;
private readonly string query;
internal GeoParsedResult(double latitude, double longitude, double altitude, string query) : base(ParsedResultType.GEO)
{
this.latitude = latitude;
this.longitude = longitude;
this.altitude = altitude;
this.query = query;
}
public string GeoURI
{
get
{
StringBuilder result = new StringBuilder();
result.Append("geo:");
result.Append(latitude);
result.Append(',');
result.Append(longitude);
if (altitude > 0)
{
result.Append(',');
result.Append(altitude);
}
if (query != null)
{
result.Append('?');
result.Append(query);
}
return result.ToString();
}
}
/// <returns> latitude in degrees </returns>
public double Latitude
{
get
{
return latitude;
}
}
/// <returns> longitude in degrees </returns>
public double Longitude
{
get
{
return longitude;
}
}
/// <returns> altitude in meters. If not specified, in the geo URI, returns 0.0 </returns>
public double Altitude
{
get
{
return altitude;
}
}
/// <returns> query string associated with geo URI or null if none exists </returns>
public string Query
{
get
{
return query;
}
}
public override string DisplayResult
{
get
{
StringBuilder result = new StringBuilder(20);
result.Append(latitude);
result.Append(", ");
result.Append(longitude);
if (altitude > 0.0)
{
result.Append(", ");
result.Append(altitude);
result.Append('m');
}
if (query != null)
{
result.Append(" (");
result.Append(query);
result.Append(')');
}
return result.ToString();
}
}
}
}

View file

@ -1,87 +0,0 @@
using System;
using System.Text.RegularExpressions;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Parses a "geo:" URI result, which specifies a location on the surface of
/// the Earth as well as an optional altitude above the surface. See
/// <a href="http://tools.ietf.org/html/draft-mayrhofer-geo-uri-00">
/// http://tools.ietf.org/html/draft-mayrhofer-geo-uri-00</a>.
///
/// @author Sean Owen
/// </summary>
public sealed class GeoResultParser : ResultParser
{
private static readonly string GEO_URL_PATTERN = "geo:([\\-0-9.]+),([\\-0-9.]+)(?:,([\\-0-9.]+))?(?:\\?(.*))?";
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
Match matcher = Regex.Match(rawText,GEO_URL_PATTERN,RegexOptions.IgnoreCase);
if (!matcher.Success)
{
return null;
}
string query = matcher.Groups[4].Value;
double latitude;
double longitude;
double altitude;
try
{
latitude = Convert.ToDouble(matcher.Groups[1].Value);
if (latitude > 90.0 || latitude < -90.0)
{
return null;
}
longitude = Convert.ToDouble(matcher.Groups[2].Value);
if (longitude > 180.0 || longitude < -180.0)
{
return null;
}
if (matcher.Groups[3].Value == null)
{
altitude = 0.0;
}
else
{
altitude = Convert.ToDouble(matcher.Groups[3].Value);
if (altitude < 0.0)
{
return null;
}
}
}
catch (FormatException nfe)
{
return null;
}
return new GeoParsedResult(latitude, longitude, altitude, query);
}
}
}

View file

@ -1,51 +0,0 @@
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// @author jbreiden@google.com (Jeff Breidenbach)
/// </summary>
public sealed class ISBNParsedResult : ParsedResult
{
private readonly string isbn;
internal ISBNParsedResult(string isbn) : base(ParsedResultType.ISBN)
{
this.isbn = isbn;
}
public string ISBN
{
get
{
return isbn;
}
}
public override string DisplayResult
{
get
{
return isbn;
}
}
}
}

View file

@ -1,57 +0,0 @@
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using Result = com.google.zxing.Result;
/// <summary>
/// Parses strings of digits that represent a ISBN.
///
/// @author jbreiden@google.com (Jeff Breidenbach)
/// </summary>
public sealed class ISBNResultParser : ResultParser
{
/// <summary>
/// See <a href="http://www.bisg.org/isbn-13/for.dummies.html">ISBN-13 For Dummies</a>
/// </summary>
public override ParsedResult parse(Result result)
{
BarcodeFormat format = result.BarcodeFormat;
if (format != BarcodeFormat.EAN_13)
{
return null;
}
string rawText = getMassagedText(result);
int length = rawText.Length;
if (length != 13)
{
return null;
}
if (!rawText.StartsWith("978") && !rawText.StartsWith("979"))
{
return null;
}
return new ISBNParsedResult(rawText);
}
}
}

View file

@ -1,91 +0,0 @@
using System.Text;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// <p>Abstract class representing the result of decoding a barcode, as more than
/// a String -- as some type of structured data. This might be a subclass which represents
/// a URL, or an e-mail address. <seealso cref="ResultParser#parseResult(com.google.zxing.Result)"/> will turn a raw
/// decoded string into the most appropriate type of structured representation.</p>
///
/// <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
/// on exception-based mechanisms during parsing.</p>
///
/// @author Sean Owen
/// </summary>
public abstract class ParsedResult
{
private readonly ParsedResultType type;
protected internal ParsedResult(ParsedResultType type)
{
this.type = type;
}
public ParsedResultType Type
{
get
{
return type;
}
}
public abstract string DisplayResult {get;}
public override string ToString()
{
return DisplayResult;
}
public static void maybeAppend(string value, StringBuilder result)
{
if (value != null && value.Length > 0)
{
// Don't add a newline before the first value
if (result.Length > 0)
{
result.Append('\n');
}
result.Append(value);
}
}
public static void maybeAppend(string[] value, StringBuilder result)
{
if (value != null)
{
foreach (string s in value)
{
if (s != null && s.Length > 0)
{
if (result.Length > 0)
{
result.Append('\n');
}
result.Append(s);
}
}
}
}
}
}

View file

@ -1,43 +0,0 @@
/*
* Copyright 2010 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// Represents the type of data encoded by a barcode -- from plain text, to a
/// URI, to an e-mail address, etc.
///
/// @author Sean Owen
/// </summary>
public enum ParsedResultType
{
ADDRESSBOOK,
EMAIL_ADDRESS,
PRODUCT,
URI,
TEXT,
GEO,
TEL,
SMS,
CALENDAR,
WIFI,
ISBN,
}
}

View file

@ -1,65 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public sealed class ProductParsedResult : ParsedResult
{
private readonly string productID;
private readonly string normalizedProductID;
internal ProductParsedResult(string productID) : this(productID, productID)
{
}
internal ProductParsedResult(string productID, string normalizedProductID) : base(ParsedResultType.PRODUCT)
{
this.productID = productID;
this.normalizedProductID = normalizedProductID;
}
public string ProductID
{
get
{
return productID;
}
}
public string NormalizedProductID
{
get
{
return normalizedProductID;
}
}
public override string DisplayResult
{
get
{
return productID;
}
}
}
}

View file

@ -1,67 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using Result = com.google.zxing.Result;
using UPCEReader = com.google.zxing.oned.UPCEReader;
/// <summary>
/// Parses strings of digits that represent a UPC code.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public sealed class ProductResultParser : ResultParser
{
// Treat all UPC and EAN variants as UPCs, in the sense that they are all product barcodes.
public override ParsedResult parse(Result result)
{
BarcodeFormat format = result.BarcodeFormat;
if (!(format == BarcodeFormat.UPC_A || format == BarcodeFormat.UPC_E || format == BarcodeFormat.EAN_8 || format == BarcodeFormat.EAN_13))
{
return null;
}
string rawText = getMassagedText(result);
int length = rawText.Length;
for (int x = 0; x < length; x++)
{
char c = rawText[x];
if (c < '0' || c > '9')
{
return null;
}
}
// Not actually checking the checksum again here
string normalizedProductID;
// Expand UPC-E for purposes of searching
if (format == BarcodeFormat.UPC_E)
{
normalizedProductID = UPCEReader.convertUPCEtoUPCA(rawText);
}
else
{
normalizedProductID = rawText;
}
return new ProductParsedResult(rawText, normalizedProductID);
}
}
}

View file

@ -1,282 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
using System.Text.RegularExpressions;
/// <summary>
/// <p>Abstract class representing the result of decoding a barcode, as more than
/// a String -- as some type of structured data. This might be a subclass which represents
/// a URL, or an e-mail address. <seealso cref="#parseResult(Result)"/> will turn a raw
/// decoded string into the most appropriate type of structured representation.</p>
///
/// <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
/// on exception-based mechanisms during parsing.</p>
///
/// @author Sean Owen
/// </summary>
public abstract class ResultParser
{
private static readonly ResultParser[] PARSERS = {new BookmarkDoCoMoResultParser(), new AddressBookDoCoMoResultParser(), new EmailDoCoMoResultParser(), new AddressBookAUResultParser(), new VCardResultParser(), new BizcardResultParser(), new VEventResultParser(), new EmailAddressResultParser(), new SMTPResultParser(), new TelResultParser(), new SMSMMSResultParser(), new SMSTOMMSTOResultParser(), new GeoResultParser(), new WifiResultParser(), new URLTOResultParser(), new URIResultParser(), new ISBNResultParser(), new ProductResultParser(), new ExpandedProductResultParser()};
private static readonly string DIGITS = "\\d*";
private static readonly string ALPHANUM = "[a-zA-Z0-9]*";
private static readonly string AMPERSAND = "&";
private static readonly string EQUALS = "=";
private const string BYTE_ORDER_MARK = "\ufeff";
/// <summary>
/// Attempts to parse the raw <seealso cref="Result"/>'s contents as a particular type
/// of information (email, URL, etc.) and return a <seealso cref="ParsedResult"/> encapsulating
/// the result of parsing.
/// </summary>
public abstract ParsedResult parse(Result theResult);
protected internal static string getMassagedText(Result result)
{
string text = result.Text;
if (text.StartsWith(BYTE_ORDER_MARK))
{
text = text.Substring(1);
}
return text;
}
public static ParsedResult parseResult(Result theResult)
{
foreach (ResultParser parser in PARSERS)
{
ParsedResult result = parser.parse(theResult);
if (result != null)
{
return result;
}
}
return new TextParsedResult(theResult.Text, null);
}
protected internal static void maybeAppend(string value, StringBuilder result)
{
if (value != null)
{
result.Append('\n');
result.Append(value);
}
}
protected internal static void maybeAppend(string[] value, StringBuilder result)
{
if (value != null)
{
foreach (string s in value)
{
result.Append('\n');
result.Append(s);
}
}
}
protected internal static string[] maybeWrap(string value)
{
return value == null ? null : new string[] {value};
}
protected internal static string unescapeBackslash(string escaped)
{
int backslash = (int) escaped.IndexOf('\\');
if (backslash < 0)
{
return escaped;
}
int max = escaped.Length;
StringBuilder unescaped = new StringBuilder(max - 1);
unescaped.Append(escaped.ToCharArray(), 0, backslash);
bool nextIsEscaped = false;
for (int i = backslash; i < max; i++)
{
char c = escaped[i];
if (nextIsEscaped || c != '\\')
{
unescaped.Append(c);
nextIsEscaped = false;
}
else
{
nextIsEscaped = true;
}
}
return unescaped.ToString();
}
protected internal static int parseHexDigit(char c)
{
if (c >= '0' && c <= '9')
{
return c - '0';
}
if (c >= 'a' && c <= 'f')
{
return 10 + (c - 'a');
}
if (c >= 'A' && c <= 'F')
{
return 10 + (c - 'A');
}
return -1;
}
protected internal static bool isStringOfDigits(string value, int length)
{
//return value != null && length == value.Length && DIGITS.matcher(value).matches();
return value != null && length == value.Length && new Regex(DIGITS).IsMatch(value);
}
protected internal static bool isSubstringOfDigits(string value, int offset, int length)
{
if (value == null)
{
return false;
}
int max = offset + length;
string s = value.Substring(offset, length);
return isStringOfDigits(s, length);
//return value.Length >= max && DIGITS.matcher(value.subSequence(offset, max)).matches();
}
protected internal static bool isSubstringOfAlphaNumeric(string value, int offset, int length)
{
if (value == null)
{
return false;
}
int max = offset + length;
string s = value.Substring(offset, length);
return length == s.Length && new Regex(ALPHANUM).IsMatch(s);
//return value.Length >= max && ALPHANUM.matcher(value.subSequence(offset, max)).matches();
}
internal static IDictionary<string, string> parseNameValuePairs(string uri)
{
int paramStart = uri.IndexOf('?');
if (paramStart < 0)
{
return null;
}
IDictionary<string, string> result = new Dictionary<string, string>(3);
foreach (string keyValue in AMPERSAND.Split(new string[] {uri.Substring(paramStart + 1)},StringSplitOptions.None))
{
appendKeyValue(keyValue, result);
}
return result;
}
private static void appendKeyValue(string keyValue, IDictionary<string, string> result)
{
string[] keyValueTokens = EQUALS.Split(new string[] {keyValue}, 2,StringSplitOptions.None);
if (keyValueTokens.Length == 2)
{
string key = keyValueTokens[0];
string value = keyValueTokens[1];
try
{
//value = URLDecoder.decode(value, "UTF-8");
value = System.Web.HttpUtility.UrlDecode(value,Encoding.UTF8);
result[key] = value;
}
//catch (UnsupportedEncodingException uee)
//{
// throw new IllegalStateException(uee); // can't happen
//}
catch (System.ArgumentException iae)
{
// continue; invalid data such as an escape like %0t
}
}
}
internal static string[] matchPrefixedField(string prefix, string rawText, char endChar, bool trim)
{
List<string> matches = null;
int i = 0;
int max = rawText.Length;
while (i < max)
{
i = rawText.IndexOf(prefix, i);
if (i < 0)
{
break;
}
i += prefix.Length; // Skip past this prefix we found to start
int start = i; // Found the start of a match here
bool more = true;
while (more)
{
i = (int)rawText.IndexOf( endChar, i);
if (i < 0)
{
// No terminating end character? uh, done. Set i such that loop terminates and break
i = rawText.Length;
more = false;
}
else if (rawText[i - 1] == '\\')
{
// semicolon was escaped so continue
i++;
}
else
{
// found a match
if (matches == null)
{
matches = new List<string>(3); // lazy init
}
string element = unescapeBackslash(rawText.Substring(start, i - start));
if (trim)
{
element = element.Trim();
}
matches.Add(element);
i++;
more = false;
}
}
}
if (matches == null || matches.Count == 0)
{
return null;
}
return matches.ToArray();
}
internal static string matchSinglePrefixedField(string prefix, string rawText, char endChar, bool trim)
{
string[] matches = matchPrefixedField(prefix, rawText, endChar, trim);
return matches == null ? null : matches[0];
}
}
}

View file

@ -1,117 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// <p>Parses an "sms:" URI result, which specifies a number to SMS.
/// See <a href="http://tools.ietf.org/html/rfc5724"> RFC 5724</a> on this.</p>
///
/// <p>This class supports "via" syntax for numbers, which is not part of the spec.
/// For example "+12125551212;via=+12124440101" may appear as a number.
/// It also supports a "subject" query parameter, which is not mentioned in the spec.
/// These are included since they were mentioned in earlier IETF drafts and might be
/// used.</p>
///
/// <p>This actually also parses URIs starting with "mms:" and treats them all the same way,
/// and effectively converts them to an "sms:" URI for purposes of forwarding to the platform.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class SMSMMSResultParser : ResultParser
{
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
if (!(rawText.StartsWith("sms:") || rawText.StartsWith("SMS:") || rawText.StartsWith("mms:") || rawText.StartsWith("MMS:")))
{
return null;
}
// Check up front if this is a URI syntax string with query arguments
IDictionary<string, string> nameValuePairs = parseNameValuePairs(rawText);
string subject = null;
string body = null;
bool querySyntax = false;
if (nameValuePairs != null && nameValuePairs.Count > 0)
{
subject = nameValuePairs["subject"];
body = nameValuePairs["body"];
querySyntax = true;
}
// Drop sms, query portion
int queryStart = rawText.IndexOf('?', 4);
string smsURIWithoutQuery;
// If it's not query syntax, the question mark is part of the subject or message
if (queryStart < 0 || !querySyntax)
{
smsURIWithoutQuery = rawText.Substring(4);
}
else
{
smsURIWithoutQuery = rawText.Substring(4, queryStart - 4);
}
int lastComma = -1;
int comma;
List<string> numbers = new List<string>(1);
List<string> vias = new List<string>(1);
while ((comma = smsURIWithoutQuery.IndexOf(',', lastComma + 1)) > lastComma)
{
string numberPart = smsURIWithoutQuery.Substring(lastComma + 1, comma - (lastComma + 1));
addNumberVia(numbers, vias, numberPart);
lastComma = comma;
}
addNumberVia(numbers, vias, smsURIWithoutQuery.Substring(lastComma + 1));
return new SMSParsedResult(numbers.ToArray(), vias.ToArray(), subject, body);
}
private static void addNumberVia(ICollection<string> numbers, ICollection<string> vias, string numberPart)
{
int numberEnd = numberPart.IndexOf(';');
if (numberEnd < 0)
{
numbers.Add(numberPart);
vias.Add(null);
}
else
{
numbers.Add(numberPart.Substring(0, numberEnd));
string maybeVia = numberPart.Substring(numberEnd + 1);
string via;
if (maybeVia.StartsWith("via="))
{
via = maybeVia.Substring(4);
}
else
{
via = null;
}
vias.Add(via);
}
}
}
}

View file

@ -1,142 +0,0 @@
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// @author Sean Owen
/// </summary>
public sealed class SMSParsedResult : ParsedResult
{
private readonly string[] numbers;
private readonly string[] vias;
private readonly string subject;
private readonly string body;
public SMSParsedResult(string number, string via, string subject, string body) : base(ParsedResultType.SMS)
{
this.numbers = new string[] {number};
this.vias = new string[] {via};
this.subject = subject;
this.body = body;
}
public SMSParsedResult(string[] numbers, string[] vias, string subject, string body) : base(ParsedResultType.SMS)
{
this.numbers = numbers;
this.vias = vias;
this.subject = subject;
this.body = body;
}
public string SMSURI
{
get
{
StringBuilder result = new StringBuilder();
result.Append("sms:");
bool first = true;
for (int i = 0; i < numbers.Length; i++)
{
if (first)
{
first = false;
}
else
{
result.Append(',');
}
result.Append(numbers[i]);
if (vias != null && vias[i] != null)
{
result.Append(";via=");
result.Append(vias[i]);
}
}
bool hasBody = body != null;
bool hasSubject = subject != null;
if (hasBody || hasSubject)
{
result.Append('?');
if (hasBody)
{
result.Append("body=");
result.Append(body);
}
if (hasSubject)
{
if (hasBody)
{
result.Append('&');
}
result.Append("subject=");
result.Append(subject);
}
}
return result.ToString();
}
}
public string[] Numbers
{
get
{
return numbers;
}
}
public string[] Vias
{
get
{
return vias;
}
}
public string Subject
{
get
{
return subject;
}
}
public string Body
{
get
{
return body;
}
}
public override string DisplayResult
{
get
{
StringBuilder result = new StringBuilder(100);
maybeAppend(numbers, result);
maybeAppend(subject, result);
maybeAppend(body, result);
return result.ToString();
}
}
}
}

View file

@ -1,75 +0,0 @@
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// @author Sean Owen
/// </summary>
public sealed class TelParsedResult : ParsedResult
{
private readonly string number;
private readonly string telURI;
private readonly string title;
public TelParsedResult(string number, string telURI, string title) : base(ParsedResultType.TEL)
{
this.number = number;
this.telURI = telURI;
this.title = title;
}
public string Number
{
get
{
return number;
}
}
public string TelURI
{
get
{
return telURI;
}
}
public string Title
{
get
{
return title;
}
}
public override string DisplayResult
{
get
{
StringBuilder result = new StringBuilder(20);
maybeAppend(number, result);
maybeAppend(title, result);
return result.ToString();
}
}
}
}

View file

@ -1,46 +0,0 @@
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Parses a "tel:" URI result, which specifies a phone number.
///
/// @author Sean Owen
/// </summary>
public sealed class TelResultParser : ResultParser
{
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
if (!rawText.StartsWith("tel:") && !rawText.StartsWith("TEL:"))
{
return null;
}
// Normalize "TEL:" to "tel:"
string telURI = rawText.StartsWith("TEL:") ? "tel:" + rawText.Substring(4) : rawText;
// Drop tel, query portion
int queryStart = rawText.IndexOf('?', 4);
string number = queryStart < 0 ? rawText.Substring(4) : rawText.Substring(4, queryStart - 4);
return new TelParsedResult(number, telURI, null);
}
}
}

View file

@ -1,64 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// A simple result type encapsulating a string that has no further
/// interpretation.
///
/// @author Sean Owen
/// </summary>
public sealed class TextParsedResult : ParsedResult
{
private readonly string text;
private readonly string language;
public TextParsedResult(string text, string language) : base(ParsedResultType.TEXT)
{
this.text = text;
this.language = language;
}
public string Text
{
get
{
return text;
}
}
public string Language
{
get
{
return language;
}
}
public override string DisplayResult
{
get
{
return text;
}
}
}
}

View file

@ -1,127 +0,0 @@
using System.Text;
using System.Text.RegularExpressions;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
/// <summary>
/// @author Sean Owen
/// </summary>
public sealed class URIParsedResult : ParsedResult
{
private static readonly string USER_IN_HOST = ":/*([^/@]+)@[^/]+";
private readonly string uri;
private readonly string title;
public URIParsedResult(string uri, string title) : base(ParsedResultType.URI)
{
this.uri = massageURI(uri);
this.title = title;
}
public string URI
{
get
{
return uri;
}
}
public string Title
{
get
{
return title;
}
}
/// <returns> true if the URI contains suspicious patterns that may suggest it intends to
/// mislead the user about its true nature. At the moment this looks for the presence
/// of user/password syntax in the host/authority portion of a URI which may be used
/// in attempts to make the URI's host appear to be other than it is. Example:
/// http://yourbank.com@phisher.com This URI connects to phisher.com but may appear
/// to connect to yourbank.com at first glance. </returns>
public bool PossiblyMaliciousURI
{
get
{
//return USER_IN_HOST.matcher(uri).find();
return new Regex(USER_IN_HOST).IsMatch(uri);
}
}
public override string DisplayResult
{
get
{
StringBuilder result = new StringBuilder(30);
maybeAppend(title, result);
maybeAppend(uri, result);
return result.ToString();
}
}
/// <summary>
/// Transforms a string that represents a URI into something more proper, by adding or canonicalizing
/// the protocol.
/// </summary>
private static string massageURI(string uri)
{
uri = uri.Trim();
int protocolEnd = uri.IndexOf(':');
if (protocolEnd < 0)
{
// No protocol, assume http
uri = "http://" + uri;
}
else if (isColonFollowedByPortNumber(uri, protocolEnd))
{
// Found a colon, but it looks like it is after the host, so the protocol is still missing
uri = "http://" + uri;
}
return uri;
}
private static bool isColonFollowedByPortNumber(string uri, int protocolEnd)
{
int nextSlash = uri.IndexOf('/', protocolEnd + 1);
if (nextSlash < 0)
{
nextSlash = uri.Length;
}
if (nextSlash <= protocolEnd + 1)
{
return false;
}
for (int x = protocolEnd + 1; x < nextSlash; x++)
{
if (uri[x] < '0' || uri[x] > '9')
{
return false;
}
}
return true;
}
}
}

View file

@ -1,62 +0,0 @@
/*
* Copyright 2007 ZXing 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.Text.RegularExpressions;
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Tries to parse results that are a URI of some kind.
///
/// @author Sean Owen
/// </summary>
public sealed class URIResultParser : ResultParser
{
private const string ALPHANUM_PART = "[a-zA-Z0-9\\-]";
private static readonly string URL_WITH_PROTOCOL_PATTERN = "[a-zA-Z0-9]{2,}:";
private static readonly string URL_WITHOUT_PROTOCOL_PATTERN = '(' + ALPHANUM_PART + "+\\.)+" + ALPHANUM_PART + "{2,}" + "(:\\d{1,5})?" + "(/|\\?|$)"; // query, path or nothing - maybe port - host name elements
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
// We specifically handle the odd "URL" scheme here for simplicity and add "URI" for fun
// Assume anything starting this way really means to be a URI
if (rawText.StartsWith("URL:") || rawText.StartsWith("URI:"))
{
return new URIParsedResult(rawText.Substring(4).Trim(), null);
}
rawText = rawText.Trim();
return isBasicallyValidURI(rawText) ? new URIParsedResult(rawText, null) : null;
}
internal static bool isBasicallyValidURI(string uri)
{
Match m = Regex.Match(uri,URL_WITH_PROTOCOL_PATTERN) ;
if (m.Success && m.Index == 0) // match at start only
{
return true;
}
m = Regex.Match(uri,URL_WITHOUT_PROTOCOL_PATTERN);
return m.Success && m.Index == 0;
}
}
}

View file

@ -1,50 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Parses the "URLTO" result format, which is of the form "URLTO:[title]:[url]".
/// This seems to be used sometimes, but I am not able to find documentation
/// on its origin or official format?
///
/// @author Sean Owen
/// </summary>
public sealed class URLTOResultParser : ResultParser
{
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
if (!rawText.StartsWith("urlto:") && !rawText.StartsWith("URLTO:"))
{
return null;
}
int titleEnd = rawText.IndexOf(':', 6);
if (titleEnd < 0)
{
return null;
}
string title = titleEnd <= 6 ? null : rawText.Substring(6, titleEnd - 6);
string uri = rawText.Substring(titleEnd + 1);
return new URIParsedResult(uri, title);
}
}
}

View file

@ -1,403 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using com.google.zxing.common;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Parses contact information formatted according to the VCard (2.1) format. This is not a complete
/// implementation but should parse information as commonly encoded in 2D barcodes.
///
/// @author Sean Owen
/// </summary>
public sealed class VCardResultParser : ResultParser
{
private static readonly string BEGIN_VCARD = "BEGIN:VCARD";
private static readonly string VCARD_LIKE_DATE = "\\d{4}-?\\d{2}-?\\d{2}";
private static readonly string CR_LF_SPACE_TAB = "\r\n[ \t]";
private static readonly string NEWLINE_ESCAPE = "\\\\[nN]";
private static readonly string VCARD_ESCAPES = "\\\\([,;\\\\])";
private static readonly string EQUALS = "=";
private static readonly string SEMICOLON = ";";
private static readonly string UNESCAPED_SEMICOLONS = "(?<!\\\\);+";
public override ParsedResult parse(Result result)
{
// Although we should insist on the raw text ending with "END:VCARD", there's no reason
// to throw out everything else we parsed just because this was omitted. In fact, Eclair
// is doing just that, and we can't parse its contacts without this leniency.
string rawText = getMassagedText(result);
Match m = Regex.Match(rawText, BEGIN_VCARD, RegexOptions.IgnoreCase);
if (!m.Success || m.Index != 0)
{
return null;
}
IList<IList<string>> names = matchVCardPrefixedField("FN", rawText, true, false);
if (names == null)
{
// If no display names found, look for regular name fields and format them
names = matchVCardPrefixedField("N", rawText, true, false);
formatNames(names);
}
IList<IList<string>> phoneNumbers = matchVCardPrefixedField("TEL", rawText, true, false);
IList<IList<string>> emails = matchVCardPrefixedField("EMAIL", rawText, true, false);
IList<string> note = matchSingleVCardPrefixedField("NOTE", rawText, false, false);
IList<IList<string>> addresses = matchVCardPrefixedField("ADR", rawText, true, true);
IList<string> org = matchSingleVCardPrefixedField("ORG", rawText, true, true);
IList<string> birthday = matchSingleVCardPrefixedField("BDAY", rawText, true, false);
if (birthday != null && !isLikeVCardDate(birthday[0]))
{
birthday = null;
}
IList<string> title = matchSingleVCardPrefixedField("TITLE", rawText, true, false);
IList<string> url = matchSingleVCardPrefixedField("URL", rawText, true, false);
IList<string> instantMessenger = matchSingleVCardPrefixedField("IMPP", rawText, true, false);
return new AddressBookParsedResult(toPrimaryValues(names), null, toPrimaryValues(phoneNumbers), toTypes(phoneNumbers), toPrimaryValues(emails), toTypes(emails), toPrimaryValue(instantMessenger), toPrimaryValue(note), toPrimaryValues(addresses), toTypes(addresses), toPrimaryValue(org), toPrimaryValue(birthday), toPrimaryValue(title), toPrimaryValue(url));
}
internal static IList<IList<string>> matchVCardPrefixedField(string prefix, string rawText, bool trim, bool parseFieldDivider)
{
IList<IList<string>> matches = null;
int i = 0;
int max = rawText.Length;
while (i < max)
{
// At start or after newline, match prefix, followed by optional metadata
// (led by ;) ultimately ending in colon
//Matcher matcher = Pattern.compile("(?:^|\n)" + prefix + "(?:;([^:]*))?:", Pattern.CASE_INSENSITIVE).matcher(rawText);
Regex matcher = new Regex("(?:^|\n)" + prefix + "(?:;([^:]*))?:", RegexOptions.IgnoreCase);
//(rawText);
if (i > 0)
{
i--; // Find from i-1 not i since looking at the preceding character
}
//if (!matcher.find(i))
Match match = matcher.Match(rawText);
if (!match.Success)
{
break;
}
//i = matcher.end(0); // group 0 = whole pattern; end(0) is past final colon
i = match.Groups[0].Index + match.Groups[0].Length; // group 0 = whole pattern; end(0) is past final colon
string metadataString = match.Groups[1].Value; // group 1 = metadata substring
IList<string> metadata = null;
bool quotedPrintable = false;
string quotedPrintableCharset = null;
if (metadataString != null)
{
foreach (string metadatum in SEMICOLON.Split(new string[] {metadataString},StringSplitOptions.None))
{
if (metadata == null)
{
metadata = new List<string>(1);
}
metadata.Add(metadatum);
//string[] metadatumTokens = EQUALS.Split(metadatum, 2);
string[] metadatumTokens = EQUALS.Split(new string[] {metadatum},2,StringSplitOptions.None);
if (metadatumTokens.Length > 1)
{
string key = metadatumTokens[0];
string value = metadatumTokens[1];
if ("ENCODING"== key.ToUpper() && "QUOTED-PRINTABLE"==value.ToUpper())
{
quotedPrintable = true;
}
else if ("CHARSET" == key.ToUpper())
{
quotedPrintableCharset = value;
}
}
}
}
int matchStart = i; // Found the start of a match here
while ((i =(int) rawText.IndexOf( '\n', i)) >= 0) // Really, end in \r\n
{
if (i < rawText.Length - 1 && (rawText[i + 1] == ' ' || rawText[i + 1] == '\t')) // this is only a continuation - But if followed by tab or space,
{
i += 2; // Skip \n and continutation whitespace
} // If preceded by = in quoted printable
else if (quotedPrintable && ((i >= 1 && rawText[i - 1] == '=') || (i >= 2 && rawText[i - 2] == '='))) // this is a continuation
{
i++; // Skip \n
}
else
{
break;
}
}
if (i < 0)
{
// No terminating end character? uh, done. Set i such that loop terminates and break
i = max;
}
else if (i > matchStart)
{
// found a match
if (matches == null)
{
matches = new List<IList<string>>(1); // lazy init
}
if (i >= 1 && rawText[i - 1] == '\r')
{
i--; // Back up over \r, which really should be there
}
string element = rawText.Substring(matchStart, i - matchStart);
if (trim)
{
element = element.Trim();
}
if (quotedPrintable)
{
element = decodeQuotedPrintable(element, quotedPrintableCharset);
if (parseFieldDivider)
{
//element = UNESCAPED_SEMICOLONS.matcher(element).replaceAll("\n").Trim();
element = new Regex(UNESCAPED_SEMICOLONS).Replace(element,("\n")).Trim();
}
}
else
{
if (parseFieldDivider)
{
//element = UNESCAPED_SEMICOLONS.matcher(element).replaceAll("\n").Trim();
element = new Regex(UNESCAPED_SEMICOLONS).Replace(element,"\n").Trim();
}
//element = CR_LF_SPACE_TAB.matcher(element).replaceAll("");
element = new Regex(CR_LF_SPACE_TAB).Replace(element,"");
//element = NEWLINE_ESCAPE.matcher(element).replaceAll("\n");
element = new Regex(NEWLINE_ESCAPE).Replace(element,"\n");
//element = VCARD_ESCAPES.matcher(element).replaceAll("$1");
element = new Regex(VCARD_ESCAPES).Replace(element,"$1");
}
if (metadata == null)
{
IList<string> matchList = new List<string>(1);
matchList.Add(element);
matches.Add(matchList);
}
else
{
metadata.Insert(0, element);
matches.Add(metadata);
}
i++;
}
else
{
i++;
}
}
return matches;
}
private static string decodeQuotedPrintable(string value, string charset)
{
int length = value.Length;
StringBuilder result = new StringBuilder(length);
MemoryStream fragmentBuffer = new MemoryStream();
for (int i = 0; i < length; i++)
{
char c = value[i];
switch (c)
{
case '\r':
case '\n':
break;
case '=':
if (i < length - 2)
{
char nextChar = value[i + 1];
if (nextChar != '\r' && nextChar != '\n')
{
char nextNextChar = value[i + 2];
int firstDigit = parseHexDigit(nextChar);
int secondDigit = parseHexDigit(nextNextChar);
if (firstDigit >= 0 && secondDigit >= 0)
{
fragmentBuffer.WriteByte((byte)((firstDigit << 4) + secondDigit));
} // else ignore it, assume it was incorrectly encoded
i += 2;
}
}
break;
default:
maybeAppendFragment(fragmentBuffer, charset, result);
result.Append(c);
break;
}
}
maybeAppendFragment(fragmentBuffer, charset, result);
return result.ToString();
}
private static void maybeAppendFragment(MemoryStream fragmentBuffer, string charset, StringBuilder result)
{
Encoding en = Encoding.GetEncoding(charset);
Encoding enFallback = Encoding.UTF8;
if (fragmentBuffer.Length > 0)
{
sbyte[] fragmentBytes = fragmentBuffer.ToArray().ToSBytes();
string fragment;
if (charset == null)
{
fragment = en.GetString((byte[])(Array)fragmentBytes); ;
}
else
{
try
{
fragment = en.GetString((byte[])(Array)fragmentBytes); ;
}
catch (ArgumentException e)
{
// Yikes, well try anyway:
//fragment = new string(fragmentBytes);
fragment = enFallback.GetString((byte[]) (Array) fragmentBytes);
}
}
fragmentBuffer.Position=0;
result.Append(fragment);
}
}
internal static IList<string> matchSingleVCardPrefixedField(string prefix, string rawText, bool trim, bool parseFieldDivider)
{
IList<IList<string>> values = matchVCardPrefixedField(prefix, rawText, trim, parseFieldDivider);
return values == null || values.Count == 0 ? null : values[0];
}
private static string toPrimaryValue(IList<string> list)
{
return list == null || list.Count == 0 ? null : list[0];
}
private static string[] toPrimaryValues(ICollection<IList<string>> lists)
{
if (lists == null || lists.Count == 0)
{
return null;
}
List<string> result = new List<string>(lists.Count);
foreach (IList<string> list in lists)
{
result.Add(list[0]);
}
return result.ToArray();
}
private static string[] toTypes(ICollection<IList<string>> lists)
{
if (lists == null || lists.Count == 0)
{
return null;
}
List<string> result = new List<string>(lists.Count);
foreach (IList<string> list in lists)
{
string type = null;
for (int i = 1; i < list.Count; i++)
{
string metadatum = list[i];
int equals = metadatum.IndexOf('=');
if (equals < 0)
{
// take the whole thing as a usable label
type = metadatum;
break;
}
if ("TYPE" == (metadatum.Substring(0, equals)).ToUpper())
{
type = metadatum.Substring(equals + 1);
break;
}
}
result.Add(type);
}
return result.ToArray();
}
private static bool isLikeVCardDate(string value)
{
//return value == null || VCARD_LIKE_DATE.matcher(value).matches();
return value == null || new Regex(VCARD_LIKE_DATE).IsMatch(value);
}
/// <summary>
/// Formats name fields of the form "Public;John;Q.;Reverend;III" into a form like
/// "Reverend John Q. Public III".
/// </summary>
/// <param name="names"> name values to format, in place </param>
private static void formatNames(IEnumerable<IList<string>> names)
{
if (names != null)
{
foreach (IList<string> list in names)
{
string name = list[0];
string[] components = new string[5];
int start = 0;
int end;
int componentIndex = 0;
while (componentIndex < components.Length - 1 && (end = name.IndexOf(';', start)) > 0)
{
components[componentIndex] = name.Substring(start, end - start);
componentIndex++;
start = end + 1;
}
components[componentIndex] = name.Substring(start);
StringBuilder newName = new StringBuilder(100);
maybeAppendComponent(components, 3, newName);
maybeAppendComponent(components, 1, newName);
maybeAppendComponent(components, 2, newName);
maybeAppendComponent(components, 0, newName);
maybeAppendComponent(components, 4, newName);
list[0] = newName.ToString().Trim();
}
}
}
private static void maybeAppendComponent(string[] components, int i, StringBuilder newName)
{
if (components[i] != null)
{
newName.Append(' ');
newName.Append(components[i]);
}
}
}
}

View file

@ -1,129 +0,0 @@
using System;
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.client.result
{
using Result = com.google.zxing.Result;
/// <summary>
/// Partially implements the iCalendar format's "VEVENT" format for specifying a
/// calendar event. See RFC 2445. This supports SUMMARY, LOCATION, GEO, DTSTART and DTEND fields.
///
/// @author Sean Owen
/// </summary>
public sealed class VEventResultParser : ResultParser
{
public override ParsedResult parse(Result result)
{
string rawText = getMassagedText(result);
int vEventStart = rawText.IndexOf("BEGIN:VEVENT");
if (vEventStart < 0)
{
return null;
}
string summary = matchSingleVCardPrefixedField("SUMMARY", rawText, true);
string start = matchSingleVCardPrefixedField("DTSTART", rawText, true);
if (start == null)
{
return null;
}
string end = matchSingleVCardPrefixedField("DTEND", rawText, true);
string duration = matchSingleVCardPrefixedField("DURATION", rawText, true);
string location = matchSingleVCardPrefixedField("LOCATION", rawText, true);
string organizer = stripMailto(matchSingleVCardPrefixedField("ORGANIZER", rawText, true));
string[] attendees = matchVCardPrefixedField("ATTENDEE", rawText, true);
if (attendees != null)
{
for (int i = 0; i < attendees.Length; i++)
{
attendees[i] = stripMailto(attendees[i]);
}
}
string description = matchSingleVCardPrefixedField("DESCRIPTION", rawText, true);
string geoString = matchSingleVCardPrefixedField("GEO", rawText, true);
double latitude;
double longitude;
if (geoString == null)
{
latitude = double.NaN;
longitude = double.NaN;
}
else
{
int semicolon = geoString.IndexOf(';');
try
{
latitude = Convert.ToDouble(geoString.Substring(0, semicolon));
longitude = Convert.ToDouble(geoString.Substring(semicolon + 1));
}
catch (FormatException nfe)
{
return null;
}
}
try
{
return new CalendarParsedResult(summary, start, end, duration, location, organizer, attendees, description, latitude, longitude);
}
catch (System.ArgumentException iae)
{
return null;
}
}
private static string matchSingleVCardPrefixedField(string prefix, string rawText, bool trim)
{
IList<string> values = VCardResultParser.matchSingleVCardPrefixedField(prefix, rawText, trim, false);
return values == null || values.Count == 0 ? null : values[0];
}
private static string[] matchVCardPrefixedField(string prefix, string rawText, bool trim)
{
IList<IList<string>> values = VCardResultParser.matchVCardPrefixedField(prefix, rawText, trim, false);
if (values == null || values.Count == 0)
{
return null;
}
int size = values.Count;
string[] result = new string[size];
for (int i = 0; i < size; i++)
{
result[i] = values[i][0];
}
return result;
}
private static string stripMailto(string s)
{
if (s != null && (s.StartsWith("mailto:") || s.StartsWith("MAILTO:")))
{
s = s.Substring(7);
}
return s;
}
}
}

View file

@ -1,382 +0,0 @@
using System;
using System.Collections;
using System.Text;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.common
{
/// <summary>
/// <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class BitArray
{
private int[] bits;
private int size;
public BitArray()
{
this.size = 0;
this.bits = new int[1];
}
public BitArray(int size)
{
this.size = size;
this.bits = makeArray(size);
}
public int Size
{
get
{
return size;
}
}
public int SizeInBytes
{
get
{
return (size + 7) >> 3;
}
}
private void ensureCapacity(int size)
{
if (size > bits.Length << 5)
{
int[] newBits = makeArray(size);
Array.Copy(bits, 0, newBits, 0, bits.Length);
this.bits = newBits;
}
}
/// <param name="i"> bit to get </param>
/// <returns> true iff bit i is set </returns>
public bool get(int i)
{
return (bits[i >> 5] & (1 << (i & 0x1F))) != 0;
}
/// <summary>
/// Sets bit i.
/// </summary>
/// <param name="i"> bit to set </param>
public void set(int i)
{
bits[i >> 5] |= 1 << (i & 0x1F);
}
/// <summary>
/// Flips bit i.
/// </summary>
/// <param name="i"> bit to set </param>
public void flip(int i)
{
bits[i >> 5] ^= 1 << (i & 0x1F);
}
/// <param name="from"> first bit to check </param>
/// <returns> index of first bit that is set, starting from the given index, or size if none are set
/// at or beyond this given index </returns>
/// <seealso cref= #getNextUnset(int) </seealso>
public int getNextSet(int from)
{
if (from >= size)
{
return size;
}
int bitsOffset = from >> 5;
int currentBits = bits[bitsOffset];
// mask off lesser bits first
currentBits &= ~((1 << (from & 0x1F)) - 1);
while (currentBits == 0)
{
if (++bitsOffset == bits.Length)
{
return size;
}
currentBits = bits[bitsOffset];
}
//int result = (bitsOffset << 5) + int.numberOfTrailingZeros(currentBits);
int result = (bitsOffset << 5) + currentBits.NumberOfTrailingZeros();
return result > size ? size : result;
}
/// <seealso cref= #getNextSet(int) </seealso>
public int getNextUnset(int from)
{
if (from >= size)
{
return size;
}
int bitsOffset = from >> 5;
int currentBits = ~bits[bitsOffset];
// mask off lesser bits first
currentBits &= ~((1 << (from & 0x1F)) - 1);
while (currentBits == 0)
{
if (++bitsOffset == bits.Length)
{
return size;
}
currentBits = ~bits[bitsOffset];
}
//int result = (bitsOffset << 5) + int.numberOfTrailingZeros(currentBits);
int result = (bitsOffset << 5) + currentBits.NumberOfTrailingZeros();
return result > size ? size : result;
}
/// <summary>
/// Sets a block of 32 bits, starting at bit i.
/// </summary>
/// <param name="i"> first bit to set </param>
/// <param name="newBits"> the new value of the next 32 bits. Note again that the least-significant bit
/// corresponds to bit i, the next-least-significant to i+1, and so on. </param>
public void setBulk(int i, int newBits)
{
bits[i >> 5] = newBits;
}
/// <summary>
/// Sets a range of bits.
/// </summary>
/// <param name="start"> start of range, inclusive. </param>
/// <param name="end"> end of range, exclusive </param>
public void setRange(int start, int end)
{
if (end < start)
{
throw new System.ArgumentException();
}
if (end == start)
{
return;
}
end--; // will be easier to treat this as the last actually set bit -- inclusive
int firstInt = start >> 5;
int lastInt = end >> 5;
for (int i = firstInt; i <= lastInt; i++)
{
int firstBit = i > firstInt ? 0 : start & 0x1F;
int lastBit = i < lastInt ? 31 : end & 0x1F;
int mask;
if (firstBit == 0 && lastBit == 31)
{
mask = -1;
}
else
{
mask = 0;
for (int j = firstBit; j <= lastBit; j++)
{
mask |= 1 << j;
}
}
bits[i] |= mask;
}
}
/// <summary>
/// Clears all bits (sets to false).
/// </summary>
public void clear()
{
int max = bits.Length;
for (int i = 0; i < max; i++)
{
bits[i] = 0;
}
}
/// <summary>
/// Efficient method to check if a range of bits is set, or not set.
/// </summary>
/// <param name="start"> start of range, inclusive. </param>
/// <param name="end"> end of range, exclusive </param>
/// <param name="value"> if true, checks that bits in range are set, otherwise checks that they are not set </param>
/// <returns> true iff all bits are set or not set in range, according to value argument </returns>
/// <exception cref="IllegalArgumentException"> if end is less than or equal to start </exception>
public bool isRange(int start, int end, bool value)
{
if (end < start)
{
throw new System.ArgumentException();
}
if (end == start)
{
return true; // empty range matches
}
end--; // will be easier to treat this as the last actually set bit -- inclusive
int firstInt = start >> 5;
int lastInt = end >> 5;
for (int i = firstInt; i <= lastInt; i++)
{
int firstBit = i > firstInt ? 0 : start & 0x1F;
int lastBit = i < lastInt ? 31 : end & 0x1F;
int mask;
if (firstBit == 0 && lastBit == 31)
{
mask = -1;
}
else
{
mask = 0;
for (int j = firstBit; j <= lastBit; j++)
{
mask |= 1 << j;
}
}
// Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is,
// equals the mask, or we're looking for 0s and the masked portion is not all 0s
if ((bits[i] & mask) != (value ? mask : 0))
{
return false;
}
}
return true;
}
public void appendBit(bool bit)
{
ensureCapacity(size + 1);
if (bit)
{
bits[size >> 5] |= 1 << (size & 0x1F);
}
size++;
}
/// <summary>
/// Appends the least-significant bits, from value, in order from most-significant to
/// least-significant. For example, appending 6 bits from 0x000001E will append the bits
/// 0, 1, 1, 1, 1, 0 in that order.
/// </summary>
public void appendBits(int value, int numBits)
{
if (numBits < 0 || numBits > 32)
{
throw new System.ArgumentException("Num bits must be between 0 and 32");
}
ensureCapacity(size + numBits);
for (int numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--)
{
appendBit(((value >> (numBitsLeft - 1)) & 0x01) == 1);
}
}
public void appendBitArray(BitArray other)
{
int otherSize = other.size;
ensureCapacity(size + otherSize);
for (int i = 0; i < otherSize; i++)
{
appendBit(other.get(i));
}
}
public void xor(BitArray other)
{
if (bits.Length != other.bits.Length)
{
throw new System.ArgumentException("Sizes don't match");
}
for (int i = 0; i < bits.Length; i++)
{
// The last byte could be incomplete (i.e. not have 8 bits in
// it) but there is no problem since 0 XOR 0 == 0.
bits[i] ^= other.bits[i];
}
}
///
/// <param name="bitOffset"> first bit to start writing </param>
/// <param name="array"> array to write into. Bytes are written most-significant byte first. This is the opposite
/// of the internal representation, which is exposed by <seealso cref="#getBitArray()"/> </param>
/// <param name="offset"> position in array to start writing </param>
/// <param name="numBytes"> how many bytes to write </param>
public void toBytes(int bitOffset, sbyte[] array, int offset, int numBytes)
{
for (int i = 0; i < numBytes; i++)
{
int theByte = 0;
for (int j = 0; j < 8; j++)
{
if (get(bitOffset))
{
theByte |= 1 << (7 - j);
}
bitOffset++;
}
array[offset + i] = (sbyte) theByte;
}
}
/// <returns> underlying array of ints. The first element holds the first 32 bits, and the least
/// significant bit is bit 0. </returns>
public int[] BitArrayBits
{
get
{
return bits;
}
}
/// <summary>
/// Reverses all bits in the array.
/// </summary>
public void reverse()
{
int[] newBits = new int[bits.Length];
int size = this.size;
for (int i = 0; i < size; i++)
{
if (get(size - i - 1))
{
newBits[i >> 5] |= 1 << (i & 0x1F);
}
}
bits = newBits;
}
private static int[] makeArray(int size)
{
return new int[(size + 31) >> 5];
}
public override string ToString()
{
StringBuilder result = new StringBuilder(size);
for (int i = 0; i < size; i++)
{
if ((i & 0x07) == 0)
{
result.Append(' ');
}
result.Append(get(i) ? 'X' : '.');
}
return result.ToString();
}
}
}

View file

@ -1,367 +0,0 @@
using System;
using System.Collections;
using System.Text;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.common
{
/// <summary>
/// <p>Represents a 2D matrix of bits. In function arguments below, and throughout the common
/// module, x is the column position, and y is the row position. The ordering is always x, y.
/// The origin is at the top-left.</p>
///
/// <p>Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins
/// with a new int. This is done intentionally so that we can copy out a row into a BitArray very
/// efficiently.</p>
///
/// <p>The ordering of bits is row-major. Within each int, the least significant bits are used first,
/// meaning they represent lower x values. This is compatible with BitArray's implementation.</p>
///
/// @author Sean Owen
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public sealed class BitMatrix
{
private readonly int width;
private readonly int height;
private readonly int rowSize;
private readonly int[] bits;
// A helper to construct a square matrix.
public BitMatrix(int dimension) : this(dimension, dimension)
{
}
public BitMatrix(int width, int height)
{
if (width < 1 || height < 1)
{
throw new System.ArgumentException("Both dimensions must be greater than 0");
}
this.width = width;
this.height = height;
this.rowSize = (width + 31) >> 5;
bits = new int[rowSize * height];
}
/// <summary>
/// <p>Gets the requested bit, where true means black.</p>
/// </summary>
/// <param name="x"> The horizontal component (i.e. which column) </param>
/// <param name="y"> The vertical component (i.e. which row) </param>
/// <returns> value of given bit in matrix </returns>
public bool get(int x, int y)
{
int offset = y * rowSize + (x >> 5);
return (((int)((uint)bits[offset] >> (x & 0x1f))) & 1) != 0;
}
/// <summary>
/// <p>Sets the given bit to true.</p>
/// </summary>
/// <param name="x"> The horizontal component (i.e. which column) </param>
/// <param name="y"> The vertical component (i.e. which row) </param>
public void set(int x, int y)
{
int offset = y * rowSize + (x >> 5);
bits[offset] |= 1 << (x & 0x1f);
}
/// <summary>
/// <p>Flips the given bit.</p>
/// </summary>
/// <param name="x"> The horizontal component (i.e. which column) </param>
/// <param name="y"> The vertical component (i.e. which row) </param>
public void flip(int x, int y)
{
int offset = y * rowSize + (x >> 5);
bits[offset] ^= 1 << (x & 0x1f);
}
/// <summary>
/// Clears all bits (sets to false).
/// </summary>
public void clear()
{
int max = bits.Length;
for (int i = 0; i < max; i++)
{
bits[i] = 0;
}
}
/// <summary>
/// <p>Sets a square region of the bit matrix to true.</p>
/// </summary>
/// <param name="left"> The horizontal position to begin at (inclusive) </param>
/// <param name="top"> The vertical position to begin at (inclusive) </param>
/// <param name="width"> The width of the region </param>
/// <param name="height"> The height of the region </param>
public void setRegion(int left, int top, int width, int height)
{
if (top < 0 || left < 0)
{
throw new System.ArgumentException("Left and top must be nonnegative");
}
if (height < 1 || width < 1)
{
throw new System.ArgumentException("Height and width must be at least 1");
}
int right = left + width;
int bottom = top + height;
if (bottom > this.height || right > this.width)
{
throw new System.ArgumentException("The region must fit inside the matrix");
}
for (int y = top; y < bottom; y++)
{
int offset = y * rowSize;
for (int x = left; x < right; x++)
{
bits[offset + (x >> 5)] |= 1 << (x & 0x1f);
}
}
}
/// <summary>
/// A fast method to retrieve one row of data from the matrix as a BitArray.
/// </summary>
/// <param name="y"> The row to retrieve </param>
/// <param name="row"> An optional caller-allocated BitArray, will be allocated if null or too small </param>
/// <returns> The resulting BitArray - this reference should always be used even when passing
/// your own row </returns>
public BitArray getRow(int y, BitArray row)
{
if (row == null || row.Size < width)
{
row = new BitArray(width);
}
int offset = y * rowSize;
for (int x = 0; x < rowSize; x++)
{
row.setBulk(x << 5, bits[offset + x]);
}
return row;
}
/// <param name="y"> row to set </param>
/// <param name="row"> <seealso cref="BitArray"/> to copy from </param>
public void setRow(int y, BitArray row)
{
Array.Copy(row.BitArrayBits, 0, bits, y * rowSize, rowSize);
}
/// <summary>
/// This is useful in detecting the enclosing rectangle of a 'pure' barcode.
/// </summary>
/// <returns> {left,top,width,height} enclosing rectangle of all 1 bits, or null if it is all white </returns>
public int[] EnclosingRectangle
{
get
{
int left = this.width;
int top = this.height;
int right = -1;
int bottom = -1;
for (int y = 0; y < this.height; y++)
{
for (int x32 = 0; x32 < rowSize; x32++)
{
int theBits = bits[y * rowSize + x32];
if (theBits != 0)
{
if (y < top)
{
top = y;
}
if (y > bottom)
{
bottom = y;
}
if (x32 * 32 < left)
{
int bit = 0;
while ((theBits << (31 - bit)) == 0)
{
bit++;
}
if ((x32 * 32 + bit) < left)
{
left = x32 * 32 + bit;
}
}
if (x32 * 32 + 31 > right)
{
int bit = 31;
while (((int)((uint)theBits >> bit)) == 0)
{
bit--;
}
if ((x32 * 32 + bit) > right)
{
right = x32 * 32 + bit;
}
}
}
}
}
int width = right - left;
int height = bottom - top;
if (width < 0 || height < 0)
{
return null;
}
return new int[] {left, top, width, height};
}
}
/// <summary>
/// This is useful in detecting a corner of a 'pure' barcode.
/// </summary>
/// <returns> {x,y} coordinate of top-left-most 1 bit, or null if it is all white </returns>
public int[] TopLeftOnBit
{
get
{
int bitsOffset = 0;
while (bitsOffset < bits.Length && bits[bitsOffset] == 0)
{
bitsOffset++;
}
if (bitsOffset == bits.Length)
{
return null;
}
int y = bitsOffset / rowSize;
int x = (bitsOffset % rowSize) << 5;
int theBits = bits[bitsOffset];
int bit = 0;
while ((theBits << (31 - bit)) == 0)
{
bit++;
}
x += bit;
return new int[] {x, y};
}
}
public int[] BottomRightOnBit
{
get
{
int bitsOffset = bits.Length - 1;
while (bitsOffset >= 0 && bits[bitsOffset] == 0)
{
bitsOffset--;
}
if (bitsOffset < 0)
{
return null;
}
int y = bitsOffset / rowSize;
int x = (bitsOffset % rowSize) << 5;
int theBits = bits[bitsOffset];
int bit = 31;
while (((int)((uint)theBits >> bit)) == 0)
{
bit--;
}
x += bit;
return new int[] {x, y};
}
}
/// <returns> The width of the matrix </returns>
public int Width
{
get
{
return width;
}
}
/// <returns> The height of the matrix </returns>
public int Height
{
get
{
return height;
}
}
public override bool Equals(object o)
{
if (!(o is BitMatrix))
{
return false;
}
BitMatrix other = (BitMatrix) o;
if (width != other.width || height != other.height || rowSize != other.rowSize || bits.Length != other.bits.Length)
{
return false;
}
for (int i = 0; i < bits.Length; i++)
{
if (bits[i] != other.bits[i])
{
return false;
}
}
return true;
}
public override int GetHashCode()
{
int hash = width;
hash = 31 * hash + width;
hash = 31 * hash + height;
hash = 31 * hash + rowSize;
foreach (int bit in bits)
{
hash = 31 * hash + bit;
}
return hash;
}
public override string ToString()
{
StringBuilder result = new StringBuilder(height * (width + 1));
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
result.Append(get(x, y) ? "X " : " ");
}
result.Append('\n');
}
return result.ToString();
}
}
}

View file

@ -1,124 +0,0 @@
using System;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.common
{
/// <summary>
/// <p>This provides an easy abstraction to read bits at a time from a sequence of bytes, where the
/// number of bits read is not often a multiple of 8.</p>
///
/// <p>This class is thread-safe but not reentrant -- unless the caller modifies the bytes array
/// it passed in, in which case all bets are off.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class BitSource
{
private readonly sbyte[] bytes;
private int byteOffset;
private int bitOffset;
/// <param name="bytes"> bytes from which this will read bits. Bits will be read from the first byte first.
/// Bits are read within a byte from most-significant to least-significant bit. </param>
public BitSource(sbyte[] bytes)
{
this.bytes = bytes;
}
/// <returns> index of next bit in current byte which would be read by the next call to <seealso cref="#readBits(int)"/>. </returns>
public int BitOffset
{
get
{
return bitOffset;
}
}
/// <returns> index of next byte in input byte array which would be read by the next call to <seealso cref="#readBits(int)"/>. </returns>
public int ByteOffset
{
get
{
return byteOffset;
}
}
/// <param name="numBits"> number of bits to read </param>
/// <returns> int representing the bits read. The bits will appear as the least-significant
/// bits of the int </returns>
/// <exception cref="IllegalArgumentException"> if numBits isn't in [1,32] or more than is available </exception>
public int readBits(int numBits)
{
if (numBits < 1 || numBits > 32 || numBits > available())
{
throw new System.ArgumentException(Convert.ToString(numBits));
}
int result = 0;
// First, read remainder from current byte
if (bitOffset > 0)
{
int bitsLeft = 8 - bitOffset;
int toRead = numBits < bitsLeft ? numBits : bitsLeft;
int bitsToNotRead = bitsLeft - toRead;
int mask = (0xFF >> (8 - toRead)) << bitsToNotRead;
result = (bytes[byteOffset] & mask) >> bitsToNotRead;
numBits -= toRead;
bitOffset += toRead;
if (bitOffset == 8)
{
bitOffset = 0;
byteOffset++;
}
}
// Next read whole bytes
if (numBits > 0)
{
while (numBits >= 8)
{
result = (result << 8) | (bytes[byteOffset] & 0xFF);
byteOffset++;
numBits -= 8;
}
// Finally read a partial byte
if (numBits > 0)
{
int bitsToNotRead = 8 - numBits;
int mask = (0xFF >> bitsToNotRead) << bitsToNotRead;
result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead);
bitOffset += numBits;
}
}
return result;
}
/// <returns> number of bits that can be read successfully </returns>
public int available()
{
return 8 * (bytes.Length - byteOffset) - bitOffset;
}
}
}

View file

@ -1,224 +0,0 @@
/*
* Copyright 2008 ZXing 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;
namespace com.google.zxing.common
{
using FormatException = com.google.zxing.FormatException;
/// <summary>
/// Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1
/// of ISO 18004.
///
/// @author Sean Owen
/// </summary>
public abstract class CharacterSetECI
{
private CharacterSetECI()
{
}
private static object _syncLock;
static CharacterSetECI()
{
lock (_syncLock)
{
addSet((innerCharacterSetECI)Cp437);
addSet((innerCharacterSetECI)ISO8859_1);
addSet((innerCharacterSetECI)ISO8859_2);
addSet((innerCharacterSetECI)ISO8859_3);
addSet((innerCharacterSetECI)ISO8859_4);
addSet((innerCharacterSetECI)ISO8859_5);
addSet((innerCharacterSetECI)ISO8859_6);
addSet((innerCharacterSetECI)ISO8859_7);
addSet((innerCharacterSetECI)ISO8859_8);
addSet((innerCharacterSetECI)ISO8859_9);
addSet((innerCharacterSetECI)ISO8859_10);
addSet((innerCharacterSetECI)ISO8859_11);
addSet((innerCharacterSetECI)ISO8859_13);
addSet((innerCharacterSetECI)ISO8859_14);
addSet((innerCharacterSetECI)ISO8859_15);
addSet((innerCharacterSetECI)ISO8859_16);
addSet((innerCharacterSetECI)SJIS);
addSet((innerCharacterSetECI)Cp1250);
addSet((innerCharacterSetECI)Cp1251);
addSet((innerCharacterSetECI)Cp1252);
addSet((innerCharacterSetECI)Cp1256);
addSet((innerCharacterSetECI)UnicodeBigUnmarked);
addSet((innerCharacterSetECI)UTF8);
addSet((innerCharacterSetECI)ASCII);
addSet((innerCharacterSetECI)Big5);
addSet((innerCharacterSetECI)GB18030);
addSet((innerCharacterSetECI)EUC_KR);
}
}
private static void addSet(innerCharacterSetECI set)
{
foreach (int value in set.Values)
{
VALUE_TO_ECI[value] = set;
}
foreach (string name in set.OtherEncodingNames)
{
NAME_TO_ECI[name] = set;
}
}
private class innerCharacterSetECI : CharacterSetECI
{
private int[] values;
private string[] otherEncodingNames;
//internal Thing(int value)
//{
// setup(value);
//}
internal innerCharacterSetECI(int value, params string[] otherEncodingNames)
{
setup(value, otherEncodingNames);
}
internal innerCharacterSetECI(int[] values, params string[] otherEncodingNames)
{
setup(values, otherEncodingNames);
}
//void setup(int value)
//{
// setup(new int[] { value });
//}
void setup(int value, params string[] otherEncodingNames)
{
this.values = new int[] { value };
this.otherEncodingNames = otherEncodingNames;
}
void setup(int[] values, params string[] otherEncodingNames)
{
this.values = values;
this.otherEncodingNames = otherEncodingNames;
}
public override int Value
{
get { return values[0]; }
}
public override string name()
{
return otherEncodingNames[0];
}
public int[] Values
{
get { return values; }
}
public string[] OtherEncodingNames
{
get { return otherEncodingNames; }
}
}
public abstract string name();
// Enum name is a Java encoding valid for java.lang and java.io
public static readonly CharacterSetECI Cp437 = new innerCharacterSetECI(new int[] { 0, 2 },"Cp437","");
public static readonly CharacterSetECI ISO8859_1 = new innerCharacterSetECI(new int[] { 1, 3 }, "ISO-8859-1","");
public static readonly CharacterSetECI ISO8859_2 = new innerCharacterSetECI(4, "ISO-8859-2","ISO8859_2");
public static readonly CharacterSetECI ISO8859_3 = new innerCharacterSetECI(5, "ISO-8859-3","ISO8859_3");
public static readonly CharacterSetECI ISO8859_4 = new innerCharacterSetECI(6, "ISO-8859-4","ISO8859_4");
public static readonly CharacterSetECI ISO8859_5 = new innerCharacterSetECI(7, "ISO-8859-5","ISO8859_5");
public static readonly CharacterSetECI ISO8859_6 = new innerCharacterSetECI(8, "ISO-8859-6","ISO8859_6");
public static readonly CharacterSetECI ISO8859_7 = new innerCharacterSetECI(9, "ISO-8859-7","ISO8859_7");
public static readonly CharacterSetECI ISO8859_8 = new innerCharacterSetECI(10, "ISO-8859-8","ISO8859_8");
public static readonly CharacterSetECI ISO8859_9 = new innerCharacterSetECI(11, "ISO-8859-9","ISO8859_9");
public static readonly CharacterSetECI ISO8859_10 = new innerCharacterSetECI(12, "ISO-8859-10","ISO8859_10");
public static readonly CharacterSetECI ISO8859_11 = new innerCharacterSetECI(13, "ISO-8859-11","ISO8859_11");
public static readonly CharacterSetECI ISO8859_13 = new innerCharacterSetECI(15, "ISO-8859-13","ISO8859_13");
public static readonly CharacterSetECI ISO8859_14 = new innerCharacterSetECI(16, "ISO-8859-14","ISO8859_14");
public static readonly CharacterSetECI ISO8859_15 = new innerCharacterSetECI(17, "ISO-8859-15","ISO8859_15");
public static readonly CharacterSetECI ISO8859_16 = new innerCharacterSetECI(18, "ISO-8859-16","ISO8859_16");
public static readonly CharacterSetECI SJIS = new innerCharacterSetECI(20, "Shift_JIS","SJIS");
public static readonly CharacterSetECI Cp1250 = new innerCharacterSetECI(21, "windows-1250","Cp1250");
public static readonly CharacterSetECI Cp1251 = new innerCharacterSetECI(22, "windows-1251","Cp1251");
public static readonly CharacterSetECI Cp1252 = new innerCharacterSetECI(23, "windows-1252","Cp1252");
public static readonly CharacterSetECI Cp1256 = new innerCharacterSetECI(24, "windows-1256","Cp1256");
public static readonly CharacterSetECI UnicodeBigUnmarked = new innerCharacterSetECI(25, "UTF-16BE", "UnicodeBig","UnicodeBigUnmarked");
public static readonly CharacterSetECI UTF8 = new innerCharacterSetECI(26, "UTF-8","");
public static readonly CharacterSetECI ASCII = new innerCharacterSetECI(new int[] { 27, 170 }, "US-ASCII","ASCII");
public static readonly CharacterSetECI Big5 = new innerCharacterSetECI(28,"Big5","Big5");
public static readonly CharacterSetECI GB18030 = new innerCharacterSetECI(29, "GB2312", "EUC_CN", "GBK","GB18030");
public static readonly CharacterSetECI EUC_KR = new innerCharacterSetECI(30, "EUC-KR","EUC_KR");
private static readonly Dictionary<int, CharacterSetECI> VALUE_TO_ECI = new Dictionary<int, CharacterSetECI>();
private static readonly Dictionary<string, CharacterSetECI> NAME_TO_ECI = new Dictionary<string, CharacterSetECI>();
/// <param name="value"> character set ECI value </param>
/// <returns> CharacterSetECI representing ECI of given value, or null if it is legal but
/// unsupported </returns>
/// <exception cref="IllegalArgumentException"> if ECI value is invalid </exception>
public static CharacterSetECI getCharacterSetECIByValue(int value)
{
if (value < 0 || value >= 900)
{
throw FormatException.FormatInstance;
}
if (VALUE_TO_ECI.ContainsKey(value))
{
return VALUE_TO_ECI[value];
}
return null;
}
/// <param name="name"> character set ECI encoding name </param>
/// <returns> CharacterSetECI representing ECI for character encoding, or null if it is legal
/// but unsupported </returns>
public static CharacterSetECI getCharacterSetECIByName(string name)
{
if (NAME_TO_ECI.ContainsKey(name))
{
return NAME_TO_ECI[name];
}
return null;
}
public virtual int Value { get { throw new NotImplementedException(); } }
}
//public static partial class EnumExtensionMethods
//{
// public static int getValue(this CharacterSetECI instanceJavaToDotNetTempPropertyGetValue)
// {
// return values[0];
// }
//}
}

View file

@ -1,63 +0,0 @@
/*
* Copyright 2007 ZXing 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;
namespace ZXing.Common
{
/// <summary>
/// Encapsulates the result of decoding a matrix of bits. This typically
/// applies to 2D barcode formats. For now it contains the raw bytes obtained,
/// as well as a String interpretation of those bytes, if applicable.
/// <author>Sean Owen</author>
/// <author>Stephen Furlani (Updated to latest Core version w/ Other)</author>
///
/// </summary>
public sealed class DecoderResult
{
public byte[] RawBytes { get; private set; }
public String Text { get; private set; }
public IList<byte[]> ByteSegments { get; private set; }
public String ECLevel { get; private set; }
public int ErrorsCorrected { get; set; }
public int Erasures { get; set; }
/// <summary>
/// Miscellanseous data value for the various decoders
/// </summary>
/// <value>The other.</value>
public object Other { get; set; }
public DecoderResult(byte[] rawBytes, String text, IList<byte[]> byteSegments, String ecLevel)
{
if (rawBytes == null && text == null)
{
throw new ArgumentException();
}
RawBytes = rawBytes;
Text = text;
ByteSegments = byteSegments;
ECLevel = ecLevel;
}
}
}

View file

@ -1,89 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.common
{
using NotFoundException = com.google.zxing.NotFoundException;
/// <summary>
/// @author Sean Owen
/// </summary>
public sealed class DefaultGridSampler : GridSampler
{
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, float p1ToX, float p1ToY, float p2ToX, float p2ToY, float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX, float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY) throws com.google.zxing.NotFoundException
public override BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, float p1ToX, float p1ToY, float p2ToX, float p2ToY, float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX, float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY)
{
PerspectiveTransform transform = PerspectiveTransform.quadrilateralToQuadrilateral(p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY, p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY);
return sampleGrid(image, dimensionX, dimensionY, transform);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, PerspectiveTransform transform) throws com.google.zxing.NotFoundException
public override BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, PerspectiveTransform transform)
{
if (dimensionX <= 0 || dimensionY <= 0)
{
throw NotFoundException.NotFoundInstance;
}
BitMatrix bits = new BitMatrix(dimensionX, dimensionY);
float[] points = new float[dimensionX << 1];
for (int y = 0; y < dimensionY; y++)
{
int max = points.Length;
float iValue = (float) y + 0.5f;
for (int x = 0; x < max; x += 2)
{
points[x] = (float)(x >> 1) + 0.5f;
points[x + 1] = iValue;
}
transform.transformPoints(points);
// Quick check to see if points transformed to something inside the image;
// sufficient to check the endpoints
checkAndNudgePoints(image, points);
try
{
for (int x = 0; x < max; x += 2)
{
if (image.get((int) points[x], (int) points[x + 1]))
{
// Black(-ish) pixel
bits.set(x >> 1, y);
}
}
}
catch (System.IndexOutOfRangeException aioobe)
{
// This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting
// transform gets "twisted" such that it maps a straight line of points to a set of points
// whose endpoints are in bounds, but others are not. There is probably some mathematical
// way to detect this about the transformation that I don't know yet.
// This results in an ugly runtime exception despite our clever checks above -- can't have
// that. We could check each point's coordinates but that feels duplicative. We settle for
// catching and wrapping ArrayIndexOutOfBoundsException.
throw NotFoundException.NotFoundInstance;
}
}
return bits;
}
}
}

View file

@ -1,58 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.common
{
using ResultPoint = com.google.zxing.ResultPoint;
/// <summary>
/// <p>Encapsulates the result of detecting a barcode in an image. This includes the raw
/// matrix of black/white pixels corresponding to the barcode, and possibly points of interest
/// in the image, like the location of finder patterns or corners of the barcode in the image.</p>
///
/// @author Sean Owen
/// </summary>
public class DetectorResult
{
private readonly BitMatrix bits;
private readonly ResultPoint[] points;
public DetectorResult(BitMatrix bits, ResultPoint[] points)
{
this.bits = bits;
this.points = points;
}
public BitMatrix Bits
{
get
{
return bits;
}
}
public ResultPoint[] Points
{
get
{
return points;
}
}
}
}

View file

@ -1,237 +0,0 @@
using System.Collections;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.common
{
using Binarizer = com.google.zxing.Binarizer;
using LuminanceSource = com.google.zxing.LuminanceSource;
using NotFoundException = com.google.zxing.NotFoundException;
/// <summary>
/// This Binarizer implementation uses the old ZXing global histogram approach. It is suitable
/// for low-end mobile devices which don't have enough CPU or memory to use a local thresholding
/// algorithm. However, because it picks a global black point, it cannot handle difficult shadows
/// and gradients.
///
/// Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// @author Sean Owen
/// </summary>
public class GlobalHistogramBinarizer : com.google.zxing.Binarizer
{
private const int LUMINANCE_BITS = 5;
private static readonly int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
private static readonly int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;
private static readonly sbyte[] EMPTY = new sbyte[0];
private sbyte[] luminances;
private readonly int[] buckets;
public GlobalHistogramBinarizer(LuminanceSource source) : base(source)
{
luminances = EMPTY;
buckets = new int[LUMINANCE_BUCKETS];
}
// Applies simple sharpening to the row data to improve performance of the 1D Readers.
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public BitArray getBlackRow(int y, BitArray row) throws com.google.zxing.NotFoundException
public override BitArray getBlackRow(int y, BitArray row)
{
LuminanceSource source = LuminanceSource;
int width = source.Width;
if (row == null || row.Size < width)
{
row = new BitArray(width);
}
else
{
//row.SetAll(false);
row.clear();
}
initArrays(width);
sbyte[] localLuminances = source.getRow(y, luminances);
int[] localBuckets = buckets;
for (int x = 0; x < width; x++)
{
int pixel = localLuminances[x] & 0xff;
localBuckets[pixel >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimateBlackPoint(localBuckets);
int left = localLuminances[0] & 0xff;
int center = localLuminances[1] & 0xff;
for (int x = 1; x < width - 1; x++)
{
int right = localLuminances[x + 1] & 0xff;
// A simple -1 4 -1 box filter with a weight of 2.
int luminance = ((center << 2) - left - right) >> 1;
if (luminance < blackPoint)
{
//row.Set(x, true);
row.set(x);
}
left = center;
center = right;
}
return row;
}
// Does not sharpen the data, as this call is intended to only be used by 2D Readers.
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public BitMatrix getBlackMatrix() throws com.google.zxing.NotFoundException
public override BitMatrix BlackMatrix
{
get
{
LuminanceSource source = LuminanceSource;
int width = source.Width;
int height = source.Height;
BitMatrix matrix = new BitMatrix(width, height);
// Quickly calculates the histogram by sampling four rows from the image. This proved to be
// more robust on the blackbox tests than sampling a diagonal as we used to do.
initArrays(width);
int[] localBuckets = buckets;
for (int y = 1; y < 5; y++)
{
int row = height * y / 5;
sbyte[] localLuminances1 = source.getRow(row, luminances);
int right = (width << 2) / 5;
for (int x = width / 5; x < right; x++)
{
int pixel = localLuminances1[x] & 0xff;
localBuckets[pixel >> LUMINANCE_SHIFT]++;
}
}
int blackPoint = estimateBlackPoint(localBuckets);
// We delay reading the entire image luminance until the black point estimation succeeds.
// Although we end up reading four rows twice, it is consistent with our motto of
// "fail quickly" which is necessary for continuous scanning.
sbyte[] localLuminances = source.Matrix;
for (int y = 0; y < height; y++)
{
int offset = y * width;
for (int x = 0; x < width; x++)
{
int pixel = localLuminances[offset + x] & 0xff;
if (pixel < blackPoint)
{
matrix.set(x, y);
}
}
}
return matrix;
}
}
public override Binarizer createBinarizer(LuminanceSource source)
{
return new GlobalHistogramBinarizer(source);
}
private void initArrays(int luminanceSize)
{
if (luminances.Length < luminanceSize)
{
luminances = new sbyte[luminanceSize];
}
for (int x = 0; x < LUMINANCE_BUCKETS; x++)
{
buckets[x] = 0;
}
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int estimateBlackPoint(int[] buckets) throws com.google.zxing.NotFoundException
private static int estimateBlackPoint(int[] buckets)
{
// Find the tallest peak in the histogram.
int numBuckets = buckets.Length;
int maxBucketCount = 0;
int firstPeak = 0;
int firstPeakSize = 0;
for (int x = 0; x < numBuckets; x++)
{
if (buckets[x] > firstPeakSize)
{
firstPeak = x;
firstPeakSize = buckets[x];
}
if (buckets[x] > maxBucketCount)
{
maxBucketCount = buckets[x];
}
}
// Find the second-tallest peak which is somewhat far from the tallest peak.
int secondPeak = 0;
int secondPeakScore = 0;
for (int x = 0; x < numBuckets; x++)
{
int distanceToBiggest = x - firstPeak;
// Encourage more distant second peaks by multiplying by square of distance.
int score = buckets[x] * distanceToBiggest * distanceToBiggest;
if (score > secondPeakScore)
{
secondPeak = x;
secondPeakScore = score;
}
}
// Make sure firstPeak corresponds to the black peak.
if (firstPeak > secondPeak)
{
int temp = firstPeak;
firstPeak = secondPeak;
secondPeak = temp;
}
// If there is too little contrast in the image to pick a meaningful black point, throw rather
// than waste time trying to decode the image, and risk false positives.
if (secondPeak - firstPeak <= numBuckets >> 4)
{
throw NotFoundException.NotFoundInstance;
}
// Find a valley between them that is low and closer to the white peak.
int bestValley = secondPeak - 1;
int bestValleyScore = -1;
for (int x = secondPeak - 1; x > firstPeak; x--)
{
int fromFirst = x - firstPeak;
int score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]);
if (score > bestValleyScore)
{
bestValley = x;
bestValleyScore = score;
}
}
return bestValley << LUMINANCE_SHIFT;
}
}
}

View file

@ -1,170 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.common
{
using NotFoundException = com.google.zxing.NotFoundException;
/// <summary>
/// Implementations of this class can, given locations of finder patterns for a QR code in an
/// image, sample the right points in the image to reconstruct the QR code, accounting for
/// perspective distortion. It is abstracted since it is relatively expensive and should be allowed
/// to take advantage of platform-specific optimized implementations, like Sun's Java Advanced
/// Imaging library, but which may not be available in other environments such as J2ME, and vice
/// versa.
///
/// The implementation used can be controlled by calling <seealso cref="#setGridSampler(GridSampler)"/>
/// with an instance of a class which implements this interface.
///
/// @author Sean Owen
/// </summary>
public abstract class GridSampler
{
private static GridSampler gridSampler = new DefaultGridSampler();
/// <summary>
/// Sets the implementation of GridSampler used by the library. One global
/// instance is stored, which may sound problematic. But, the implementation provided
/// ought to be appropriate for the entire platform, and all uses of this library
/// in the whole lifetime of the JVM. For instance, an Android activity can swap in
/// an implementation that takes advantage of native platform libraries.
/// </summary>
/// <param name="newGridSampler"> The platform-specific object to install. </param>
public static GridSampler GridSampler2
{
set
{
gridSampler = value;
}
}
/// <returns> the current implementation of GridSampler </returns>
public static GridSampler Instance
{
get
{
return gridSampler;
}
}
/// <summary>
/// Samples an image for a rectangular matrix of bits of the given dimension. </summary>
/// <param name="image"> image to sample </param>
/// <param name="dimensionX"> width of <seealso cref="BitMatrix"/> to sample from image </param>
/// <param name="dimensionY"> height of <seealso cref="BitMatrix"/> to sample from image </param>
/// <returns> <seealso cref="BitMatrix"/> representing a grid of points sampled from the image within a region
/// defined by the "from" parameters </returns>
/// <exception cref="NotFoundException"> if image can't be sampled, for example, if the transformation defined
/// by the given points is invalid or results in sampling outside the image boundaries </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public abstract BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, float p1ToX, float p1ToY, float p2ToX, float p2ToY, float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX, float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY) throws com.google.zxing.NotFoundException;
public abstract BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, float p1ToX, float p1ToY, float p2ToX, float p2ToY, float p3ToX, float p3ToY, float p4ToX, float p4ToY, float p1FromX, float p1FromY, float p2FromX, float p2FromY, float p3FromX, float p3FromY, float p4FromX, float p4FromY);
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public abstract BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, PerspectiveTransform transform) throws com.google.zxing.NotFoundException;
public abstract BitMatrix sampleGrid(BitMatrix image, int dimensionX, int dimensionY, PerspectiveTransform transform);
/// <summary>
/// <p>Checks a set of points that have been transformed to sample points on an image against
/// the image's dimensions to see if the point are even within the image.</p>
///
/// <p>This method will actually "nudge" the endpoints back onto the image if they are found to be
/// barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder
/// patterns in an image where the QR Code runs all the way to the image border.</p>
///
/// <p>For efficiency, the method will check points from either end of the line until one is found
/// to be within the image. Because the set of points are assumed to be linear, this is valid.</p>
/// </summary>
/// <param name="image"> image into which the points should map </param>
/// <param name="points"> actual points in x1,y1,...,xn,yn form </param>
/// <exception cref="NotFoundException"> if an endpoint is lies outside the image boundaries </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected static void checkAndNudgePoints(BitMatrix image, float[] points) throws com.google.zxing.NotFoundException
protected internal static void checkAndNudgePoints(BitMatrix image, float[] points)
{
int width = image.Width;
int height = image.Height;
// Check and nudge points from start until we see some that are OK:
bool nudged = true;
for (int offset = 0; offset < points.Length && nudged; offset += 2)
{
int x = (int) points[offset];
int y = (int) points[offset + 1];
if (x < -1 || x > width || y < -1 || y > height)
{
throw NotFoundException.NotFoundInstance;
}
nudged = false;
if (x == -1)
{
points[offset] = 0.0f;
nudged = true;
}
else if (x == width)
{
points[offset] = width - 1;
nudged = true;
}
if (y == -1)
{
points[offset + 1] = 0.0f;
nudged = true;
}
else if (y == height)
{
points[offset + 1] = height - 1;
nudged = true;
}
}
// Check and nudge points from end:
nudged = true;
for (int offset = points.Length - 2; offset >= 0 && nudged; offset -= 2)
{
int x = (int) points[offset];
int y = (int) points[offset + 1];
if (x < -1 || x > width || y < -1 || y > height)
{
throw NotFoundException.NotFoundInstance;
}
nudged = false;
if (x == -1)
{
points[offset] = 0.0f;
nudged = true;
}
else if (x == width)
{
points[offset] = width - 1;
nudged = true;
}
if (y == -1)
{
points[offset + 1] = 0.0f;
nudged = true;
}
else if (y == height)
{
points[offset + 1] = height - 1;
nudged = true;
}
}
}
}
}

View file

@ -1,264 +0,0 @@
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.common
{
using Binarizer = com.google.zxing.Binarizer;
using LuminanceSource = com.google.zxing.LuminanceSource;
using NotFoundException = com.google.zxing.NotFoundException;
/// <summary>
/// This class implements a local thresholding algorithm, which while slower than the
/// GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for
/// high frequency images of barcodes with black data on white backgrounds. For this application,
/// it does a much better job than a global blackpoint with severe shadows and gradients.
/// However it tends to produce artifacts on lower frequency images and is therefore not
/// a good general purpose binarizer for uses outside ZXing.
///
/// This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers,
/// and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already
/// inherently local, and only fails for horizontal gradients. We can revisit that problem later,
/// but for now it was not a win to use local blocks for 1D.
///
/// This Binarizer is the default for the unit tests and the recommended class for library users.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// </summary>
public sealed class HybridBinarizer : GlobalHistogramBinarizer
{
// This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.
// So this is the smallest dimension in each axis we can accept.
private const int BLOCK_SIZE_POWER = 3;
private static readonly int BLOCK_SIZE = 1 << BLOCK_SIZE_POWER; // ...0100...00
private static readonly int BLOCK_SIZE_MASK = BLOCK_SIZE - 1; // ...0011...11
private static readonly int MINIMUM_DIMENSION = BLOCK_SIZE * 5;
private const int MIN_DYNAMIC_RANGE = 24;
private BitMatrix matrix;
public HybridBinarizer(LuminanceSource source) : base(source)
{
}
/// <summary>
/// Calculates the final BitMatrix once for all requests. This could be called once from the
/// constructor instead, but there are some advantages to doing it lazily, such as making
/// profiling easier, and not doing heavy lifting when callers don't expect it.
/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public BitMatrix getBlackMatrix() throws com.google.zxing.NotFoundException
public override BitMatrix BlackMatrix
{
get
{
if (matrix != null)
{
return matrix;
}
LuminanceSource source = LuminanceSource;
int width = source.Width;
int height = source.Height;
if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION)
{
sbyte[] luminances = source.Matrix;
int subWidth = width >> BLOCK_SIZE_POWER;
if ((width & BLOCK_SIZE_MASK) != 0)
{
subWidth++;
}
int subHeight = height >> BLOCK_SIZE_POWER;
if ((height & BLOCK_SIZE_MASK) != 0)
{
subHeight++;
}
int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height);
BitMatrix newMatrix = new BitMatrix(width, height);
calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);
matrix = newMatrix;
}
else
{
// If the image is too small, fall back to the global histogram approach.
matrix = base.BlackMatrix;
}
return matrix;
}
}
public override Binarizer createBinarizer(LuminanceSource source)
{
return new HybridBinarizer(source);
}
/// <summary>
/// For each block in the image, calculate the average black point using a 5x5 grid
/// of the blocks around it. Also handles the corner cases (fractional blocks are computed based
/// on the last pixels in the row/column which are also used in the previous block).
/// </summary>
private static void calculateThresholdForBlock(sbyte[] luminances, int subWidth, int subHeight, int width, int height, int[][] blackPoints, BitMatrix matrix)
{
for (int y = 0; y < subHeight; y++)
{
int yoffset = y << BLOCK_SIZE_POWER;
int maxYOffset = height - BLOCK_SIZE;
if (yoffset > maxYOffset)
{
yoffset = maxYOffset;
}
for (int x = 0; x < subWidth; x++)
{
int xoffset = x << BLOCK_SIZE_POWER;
int maxXOffset = width - BLOCK_SIZE;
if (xoffset > maxXOffset)
{
xoffset = maxXOffset;
}
int left = cap(x, 2, subWidth - 3);
int top = cap(y, 2, subHeight - 3);
int sum = 0;
for (int z = -2; z <= 2; z++)
{
int[] blackRow = blackPoints[top + z];
sum += blackRow[left - 2] + blackRow[left - 1] + blackRow[left] + blackRow[left + 1] + blackRow[left + 2];
}
int average = sum / 25;
thresholdBlock(luminances, xoffset, yoffset, average, width, matrix);
}
}
}
private static int cap(int value, int min, int max)
{
return value < min ? min : value > max ? max : value;
}
/// <summary>
/// Applies a single threshold to a block of pixels.
/// </summary>
private static void thresholdBlock(sbyte[] luminances, int xoffset, int yoffset, int threshold, int stride, BitMatrix matrix)
{
for (int y = 0, offset = yoffset * stride + xoffset; y < BLOCK_SIZE; y++, offset += stride)
{
for (int x = 0; x < BLOCK_SIZE; x++)
{
// Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0.
if ((luminances[offset + x] & 0xFF) <= threshold)
{
matrix.set(xoffset + x, yoffset + y);
}
}
}
}
/// <summary>
/// Calculates a single black point for each block of pixels and saves it away.
/// See the following thread for a discussion of this algorithm:
/// http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0
/// </summary>
private static int[][] calculateBlackPoints(sbyte[] luminances, int subWidth, int subHeight, int width, int height)
{
//JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java:
//ORIGINAL LINE: int[][] blackPoints = new int[subHeight][subWidth];
int[][] blackPoints = RectangularArrays.ReturnRectangularIntArray(subHeight, subWidth);
for (int y = 0; y < subHeight; y++)
{
int yoffset = y << BLOCK_SIZE_POWER;
int maxYOffset = height - BLOCK_SIZE;
if (yoffset > maxYOffset)
{
yoffset = maxYOffset;
}
for (int x = 0; x < subWidth; x++)
{
int xoffset = x << BLOCK_SIZE_POWER;
int maxXOffset = width - BLOCK_SIZE;
if (xoffset > maxXOffset)
{
xoffset = maxXOffset;
}
int sum = 0;
int min = 0xFF;
int max = 0;
for (int yy = 0, offset = yoffset * width + xoffset; yy < BLOCK_SIZE; yy++, offset += width)
{
for (int xx = 0; xx < BLOCK_SIZE; xx++)
{
int pixel = luminances[offset + xx] & 0xFF;
sum += pixel;
// still looking for good contrast
if (pixel < min)
{
min = pixel;
}
if (pixel > max)
{
max = pixel;
}
}
// short-circuit min/max tests once dynamic range is met
if (max - min > MIN_DYNAMIC_RANGE)
{
// finish the rest of the rows quickly
for (yy++, offset += width; yy < BLOCK_SIZE; yy++, offset += width)
{
for (int xx = 0; xx < BLOCK_SIZE; xx++)
{
sum += luminances[offset + xx] & 0xFF;
}
}
}
}
// The default estimate is the average of the values in the block.
int average = sum >> (BLOCK_SIZE_POWER * 2);
if (max - min <= MIN_DYNAMIC_RANGE)
{
// If variation within the block is low, assume this is a block with only light or only
// dark pixels. In that case we do not want to use the average, as it would divide this
// low contrast area into black and white pixels, essentially creating data out of noise.
//
// The default assumption is that the block is light/background. Since no estimate for
// the level of dark pixels exists locally, use half the min for the block.
average = min >> 1;
if (y > 0 && x > 0)
{
// Correct the "white background" assumption for blocks that have neighbors by comparing
// the pixels in this block to the previously calculated black points. This is based on
// the fact that dark barcode symbology is always surrounded by some amount of light
// background for which reasonable black point estimates were made. The bp estimated at
// the boundaries is used for the interior.
// The (min < bp) is arbitrary but works better than other heuristics that were tried.
int averageNeighborBlackPoint = (blackPoints[y - 1][x] + (2 * blackPoints[y][x - 1]) + blackPoints[y - 1][x - 1]) >> 2;
if (min < averageNeighborBlackPoint)
{
average = averageNeighborBlackPoint;
}
}
}
blackPoints[y][x] = average;
}
}
return blackPoints;
}
}
}

View file

@ -1,140 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.common
{
/// <summary>
/// <p>This class implements a perspective transform in two dimensions. Given four source and four
/// destination points, it will compute the transformation implied between them. The code is based
/// directly upon section 3.4.2 of George Wolberg's "Digital Image Warping"; see pages 54-56.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class PerspectiveTransform
{
private readonly float a11;
private readonly float a12;
private readonly float a13;
private readonly float a21;
private readonly float a22;
private readonly float a23;
private readonly float a31;
private readonly float a32;
private readonly float a33;
private PerspectiveTransform(float a11, float a21, float a31, float a12, float a22, float a32, float a13, float a23, float a33)
{
this.a11 = a11;
this.a12 = a12;
this.a13 = a13;
this.a21 = a21;
this.a22 = a22;
this.a23 = a23;
this.a31 = a31;
this.a32 = a32;
this.a33 = a33;
}
public static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float x0p, float y0p, float x1p, float y1p, float x2p, float y2p, float x3p, float y3p)
{
PerspectiveTransform qToS = quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
PerspectiveTransform sToQ = squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
return sToQ.times(qToS);
}
public void transformPoints(float[] points)
{
int max = points.Length;
float a11 = this.a11;
float a12 = this.a12;
float a13 = this.a13;
float a21 = this.a21;
float a22 = this.a22;
float a23 = this.a23;
float a31 = this.a31;
float a32 = this.a32;
float a33 = this.a33;
for (int i = 0; i < max; i += 2)
{
float x = points[i];
float y = points[i + 1];
float denominator = a13 * x + a23 * y + a33;
points[i] = (a11 * x + a21 * y + a31) / denominator;
points[i + 1] = (a12 * x + a22 * y + a32) / denominator;
}
}
/// <summary>
/// Convenience method, not optimized for performance. </summary>
public void transformPoints(float[] xValues, float[] yValues)
{
int n = xValues.Length;
for (int i = 0; i < n; i++)
{
float x = xValues[i];
float y = yValues[i];
float denominator = a13 * x + a23 * y + a33;
xValues[i] = (a11 * x + a21 * y + a31) / denominator;
yValues[i] = (a12 * x + a22 * y + a32) / denominator;
}
}
public static PerspectiveTransform squareToQuadrilateral(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
float dx3 = x0 - x1 + x2 - x3;
float dy3 = y0 - y1 + y2 - y3;
if (dx3 == 0.0f && dy3 == 0.0f)
{
// Affine
return new PerspectiveTransform(x1 - x0, x2 - x1, x0, y1 - y0, y2 - y1, y0, 0.0f, 0.0f, 1.0f);
}
else
{
float dx1 = x1 - x2;
float dx2 = x3 - x2;
float dy1 = y1 - y2;
float dy2 = y3 - y2;
float denominator = dx1 * dy2 - dx2 * dy1;
float a13 = (dx3 * dy2 - dx2 * dy3) / denominator;
float a23 = (dx1 * dy3 - dx3 * dy1) / denominator;
return new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0, y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0, a13, a23, 1.0f);
}
}
public static PerspectiveTransform quadrilateralToSquare(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
// Here, the adjoint serves as the inverse:
return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();
}
internal PerspectiveTransform buildAdjoint()
{
// Adjoint is the transpose of the cofactor matrix:
return new PerspectiveTransform(a22 * a33 - a23 * a32, a23 * a31 - a21 * a33, a21 * a32 - a22 * a31, a13 * a32 - a12 * a33, a11 * a33 - a13 * a31, a12 * a31 - a11 * a32, a12 * a23 - a13 * a22, a13 * a21 - a11 * a23, a11 * a22 - a12 * a21);
}
internal PerspectiveTransform times(PerspectiveTransform other)
{
return new PerspectiveTransform(a11 * other.a11 + a21 * other.a12 + a31 * other.a13, a11 * other.a21 + a21 * other.a22 + a31 * other.a23, a11 * other.a31 + a21 * other.a32 + a31 * other.a33, a12 * other.a11 + a22 * other.a12 + a32 * other.a13, a12 * other.a21 + a22 * other.a22 + a32 * other.a23, a12 * other.a31 + a22 * other.a32 + a32 * other.a33, a13 * other.a11 + a23 * other.a12 + a33 * other.a13, a13 * other.a21 + a23 * other.a22 + a33 * other.a23, a13 * other.a31 + a23 * other.a32 + a33 * other.a33);
}
}
}

View file

@ -1,237 +0,0 @@
using System;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.common.detector
{
using NotFoundException = com.google.zxing.NotFoundException;
using ResultPoint = com.google.zxing.ResultPoint;
using BitMatrix = com.google.zxing.common.BitMatrix;
/// <summary>
/// <p>A somewhat generic detector that looks for a barcode-like rectangular region within an image.
/// It looks within a mostly white region of an image for a region of black and white, but mostly
/// black. It returns the four corners of the region, as best it can determine.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class MonochromeRectangleDetector
{
private const int MAX_MODULES = 32;
private readonly BitMatrix image;
public MonochromeRectangleDetector(BitMatrix image)
{
this.image = image;
}
/// <summary>
/// <p>Detects a rectangular region of black and white -- mostly black -- with a region of mostly
/// white, in an image.</p>
/// </summary>
/// <returns> <seealso cref="ResultPoint"/>[] describing the corners of the rectangular region. The first and
/// last points are opposed on the diagonal, as are the second and third. The first point will be
/// the topmost point and the last, the bottommost. The second point will be leftmost and the
/// third, the rightmost </returns>
/// <exception cref="NotFoundException"> if no Data Matrix Code can be found </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.ResultPoint[] detect() throws com.google.zxing.NotFoundException
public ResultPoint[] detect()
{
int height = image.Height;
int width = image.Width;
int halfHeight = height >> 1;
int halfWidth = width >> 1;
int deltaY = Math.Max(1, height / (MAX_MODULES << 3));
int deltaX = Math.Max(1, width / (MAX_MODULES << 3));
int top = 0;
int bottom = height;
int left = 0;
int right = width;
ResultPoint pointA = findCornerFromCenter(halfWidth, 0, left, right, halfHeight, -deltaY, top, bottom, halfWidth >> 1);
top = (int) pointA.Y - 1;
ResultPoint pointB = findCornerFromCenter(halfWidth, -deltaX, left, right, halfHeight, 0, top, bottom, halfHeight >> 1);
left = (int) pointB.X - 1;
ResultPoint pointC = findCornerFromCenter(halfWidth, deltaX, left, right, halfHeight, 0, top, bottom, halfHeight >> 1);
right = (int) pointC.X + 1;
ResultPoint pointD = findCornerFromCenter(halfWidth, 0, left, right, halfHeight, deltaY, top, bottom, halfWidth >> 1);
bottom = (int) pointD.Y + 1;
// Go try to find point A again with better information -- might have been off at first.
pointA = findCornerFromCenter(halfWidth, 0, left, right, halfHeight, -deltaY, top, bottom, halfWidth >> 2);
return new ResultPoint[] {pointA, pointB, pointC, pointD};
}
/// <summary>
/// Attempts to locate a corner of the barcode by scanning up, down, left or right from a center
/// point which should be within the barcode.
/// </summary>
/// <param name="centerX"> center's x component (horizontal) </param>
/// <param name="deltaX"> same as deltaY but change in x per step instead </param>
/// <param name="left"> minimum value of x </param>
/// <param name="right"> maximum value of x </param>
/// <param name="centerY"> center's y component (vertical) </param>
/// <param name="deltaY"> change in y per step. If scanning up this is negative; down, positive;
/// left or right, 0 </param>
/// <param name="top"> minimum value of y to search through (meaningless when di == 0) </param>
/// <param name="bottom"> maximum value of y </param>
/// <param name="maxWhiteRun"> maximum run of white pixels that can still be considered to be within
/// the barcode </param>
/// <returns> a <seealso cref="com.google.zxing.ResultPoint"/> encapsulating the corner that was found </returns>
/// <exception cref="NotFoundException"> if such a point cannot be found </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private com.google.zxing.ResultPoint findCornerFromCenter(int centerX, int deltaX, int left, int right, int centerY, int deltaY, int top, int bottom, int maxWhiteRun) throws com.google.zxing.NotFoundException
private ResultPoint findCornerFromCenter(int centerX, int deltaX, int left, int right, int centerY, int deltaY, int top, int bottom, int maxWhiteRun)
{
int[] lastRange = null;
for (int y = centerY, x = centerX; y < bottom && y >= top && x < right && x >= left; y += deltaY, x += deltaX)
{
int[] range;
if (deltaX == 0)
{
// horizontal slices, up and down
range = blackWhiteRange(y, maxWhiteRun, left, right, true);
}
else
{
// vertical slices, left and right
range = blackWhiteRange(x, maxWhiteRun, top, bottom, false);
}
if (range == null)
{
if (lastRange == null)
{
throw NotFoundException.NotFoundInstance;
}
// lastRange was found
if (deltaX == 0)
{
int lastY = y - deltaY;
if (lastRange[0] < centerX)
{
if (lastRange[1] > centerX)
{
// straddle, choose one or the other based on direction
return new ResultPoint(deltaY > 0 ? lastRange[0] : lastRange[1], lastY);
}
return new ResultPoint(lastRange[0], lastY);
}
else
{
return new ResultPoint(lastRange[1], lastY);
}
}
else
{
int lastX = x - deltaX;
if (lastRange[0] < centerY)
{
if (lastRange[1] > centerY)
{
return new ResultPoint(lastX, deltaX < 0 ? lastRange[0] : lastRange[1]);
}
return new ResultPoint(lastX, lastRange[0]);
}
else
{
return new ResultPoint(lastX, lastRange[1]);
}
}
}
lastRange = range;
}
throw NotFoundException.NotFoundInstance;
}
/// <summary>
/// Computes the start and end of a region of pixels, either horizontally or vertically, that could
/// be part of a Data Matrix barcode.
/// </summary>
/// <param name="fixedDimension"> if scanning horizontally, this is the row (the fixed vertical location)
/// where we are scanning. If scanning vertically it's the column, the fixed horizontal location </param>
/// <param name="maxWhiteRun"> largest run of white pixels that can still be considered part of the
/// barcode region </param>
/// <param name="minDim"> minimum pixel location, horizontally or vertically, to consider </param>
/// <param name="maxDim"> maximum pixel location, horizontally or vertically, to consider </param>
/// <param name="horizontal"> if true, we're scanning left-right, instead of up-down </param>
/// <returns> int[] with start and end of found range, or null if no such range is found
/// (e.g. only white was found) </returns>
private int[] blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim, bool horizontal)
{
int center = (minDim + maxDim) >> 1;
// Scan left/up first
int start = center;
while (start >= minDim)
{
if (horizontal ? image.get(start, fixedDimension) : image.get(fixedDimension, start))
{
start--;
}
else
{
int whiteRunStart = start;
do
{
start--;
} while (start >= minDim && !(horizontal ? image.get(start, fixedDimension) : image.get(fixedDimension, start)));
int whiteRunSize = whiteRunStart - start;
if (start < minDim || whiteRunSize > maxWhiteRun)
{
start = whiteRunStart;
break;
}
}
}
start++;
// Then try right/down
int end = center;
while (end < maxDim)
{
if (horizontal ? image.get(end, fixedDimension) : image.get(fixedDimension, end))
{
end++;
}
else
{
int whiteRunStart = end;
do
{
end++;
} while (end < maxDim && !(horizontal ? image.get(end, fixedDimension) : image.get(fixedDimension, end)));
int whiteRunSize = end - whiteRunStart;
if (end >= maxDim || whiteRunSize > maxWhiteRun)
{
end = whiteRunStart;
break;
}
}
}
end--;
return end > start ? new int[]{start, end} : null;
}
}
}

View file

@ -1,218 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.common.reedsolomon
{
/// <summary>
/// <p>Implements Reed-Solomon decoding, as the name implies.</p>
///
/// <p>The algorithm will not be explained here, but the following references were helpful
/// in creating this implementation:</p>
///
/// <ul>
/// <li>Bruce Maggs.
/// <a href="http://www.cs.cmu.edu/afs/cs.cmu.edu/project/pscico-guyb/realworld/www/rs_decode.ps">
/// "Decoding Reed-Solomon Codes"</a> (see discussion of Forney's Formula)</li>
/// <li>J.I. Hall. <a href="www.mth.msu.edu/~jhall/classes/codenotes/GRS.pdf">
/// "Chapter 5. Generalized Reed-Solomon Codes"</a>
/// (see discussion of Euclidean algorithm)</li>
/// </ul>
///
/// <p>Much credit is due to William Rucklidge since portions of this code are an indirect
/// port of his C++ Reed-Solomon implementation.</p>
///
/// @author Sean Owen
/// @author William Rucklidge
/// @author sanfordsquires
/// </summary>
public sealed class ReedSolomonDecoder
{
private readonly GenericGF field;
public ReedSolomonDecoder(GenericGF field)
{
this.field = field;
}
/// <summary>
/// <p>Decodes given set of received codewords, which include both data and error-correction
/// codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,
/// in the input.</p>
/// </summary>
/// <param name="received"> data and error-correction codewords </param>
/// <param name="twoS"> number of error-correction codewords available </param>
/// <exception cref="ReedSolomonException"> if decoding fails for any reason </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public void decode(int[] received, int twoS) throws ReedSolomonException
public void decode(int[] received, int twoS)
{
GenericGFPoly poly = new GenericGFPoly(field, received);
int[] syndromeCoefficients = new int[twoS];
bool dataMatrix = field.Equals(GenericGF.DATA_MATRIX_FIELD_256);
bool noError = true;
for (int i = 0; i < twoS; i++)
{
// Thanks to sanfordsquires for this fix:
int eval = poly.evaluateAt(field.exp(dataMatrix ? i + 1 : i));
syndromeCoefficients[syndromeCoefficients.Length - 1 - i] = eval;
if (eval != 0)
{
noError = false;
}
}
if (noError)
{
return;
}
GenericGFPoly syndrome = new GenericGFPoly(field, syndromeCoefficients);
GenericGFPoly[] sigmaOmega = runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);
GenericGFPoly sigma = sigmaOmega[0];
GenericGFPoly omega = sigmaOmega[1];
int[] errorLocations = findErrorLocations(sigma);
int[] errorMagnitudes = findErrorMagnitudes(omega, errorLocations, dataMatrix);
for (int i = 0; i < errorLocations.Length; i++)
{
int position = received.Length - 1 - field.log(errorLocations[i]);
if (position < 0)
{
throw new ReedSolomonException("Bad error location");
}
received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]);
}
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private GenericGFPoly[] runEuclideanAlgorithm(GenericGFPoly a, GenericGFPoly b, int R) throws ReedSolomonException
private GenericGFPoly[] runEuclideanAlgorithm(GenericGFPoly a, GenericGFPoly b, int R)
{
// Assume a's degree is >= b's
if (a.Degree < b.Degree)
{
GenericGFPoly temp = a;
a = b;
b = temp;
}
GenericGFPoly rLast = a;
GenericGFPoly r = b;
GenericGFPoly tLast = field.Zero;
GenericGFPoly t = field.One;
// Run Euclidean algorithm until r's degree is less than R/2
while (r.Degree >= R / 2)
{
GenericGFPoly rLastLast = rLast;
GenericGFPoly tLastLast = tLast;
rLast = r;
tLast = t;
// Divide rLastLast by rLast, with quotient in q and remainder in r
if (rLast.Zero)
{
// Oops, Euclidean algorithm already terminated?
throw new ReedSolomonException("r_{i-1} was zero");
}
r = rLastLast;
GenericGFPoly q = field.Zero;
int denominatorLeadingTerm = rLast.getCoefficient(rLast.Degree);
int dltInverse = field.inverse(denominatorLeadingTerm);
while (r.Degree >= rLast.Degree && !r.Zero)
{
int degreeDiff = r.Degree - rLast.Degree;
int scale = field.multiply(r.getCoefficient(r.Degree), dltInverse);
q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));
r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));
}
t = q.multiply(tLast).addOrSubtract(tLastLast);
}
int sigmaTildeAtZero = t.getCoefficient(0);
if (sigmaTildeAtZero == 0)
{
throw new ReedSolomonException("sigmaTilde(0) was zero");
}
int inverse = field.inverse(sigmaTildeAtZero);
GenericGFPoly sigma = t.multiply(inverse);
GenericGFPoly omega = r.multiply(inverse);
return new GenericGFPoly[]{sigma, omega};
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private int[] findErrorLocations(GenericGFPoly errorLocator) throws ReedSolomonException
private int[] findErrorLocations(GenericGFPoly errorLocator)
{
// This is a direct application of Chien's search
int numErrors = errorLocator.Degree;
if (numErrors == 1) // shortcut
{
return new int[] {errorLocator.getCoefficient(1)};
}
int[] result = new int[numErrors];
int e = 0;
for (int i = 1; i < field.Size && e < numErrors; i++)
{
if (errorLocator.evaluateAt(i) == 0)
{
result[e] = field.inverse(i);
e++;
}
}
if (e != numErrors)
{
throw new ReedSolomonException("Error locator degree does not match number of roots");
}
return result;
}
private int[] findErrorMagnitudes(GenericGFPoly errorEvaluator, int[] errorLocations, bool dataMatrix)
{
// This is directly applying Forney's Formula
int s = errorLocations.Length;
int[] result = new int[s];
for (int i = 0; i < s; i++)
{
int xiInverse = field.inverse(errorLocations[i]);
int denominator = 1;
for (int j = 0; j < s; j++)
{
if (i != j)
{
//denominator = field.multiply(denominator,
// GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
// Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.
// Below is a funny-looking workaround from Steven Parkes
int term = field.multiply(errorLocations[j], xiInverse);
int termPlus1 = (term & 0x1) == 0 ? term | 1 : term & ~1;
denominator = field.multiply(denominator, termPlus1);
}
}
result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));
// Thanks to sanfordsquires for this fix:
if (dataMatrix)
{
result[i] = field.multiply(result[i], xiInverse);
}
}
return result;
}
}
}

View file

@ -1,90 +0,0 @@
using System;
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.common.reedsolomon
{
/// <summary>
/// <p>Implements Reed-Solomon enbcoding, as the name implies.</p>
///
/// @author Sean Owen
/// @author William Rucklidge
/// </summary>
public sealed class ReedSolomonEncoder
{
private readonly GenericGF field;
private readonly IList<GenericGFPoly> cachedGenerators;
public ReedSolomonEncoder(GenericGF field)
{
if (!GenericGF.QR_CODE_FIELD_256.Equals(field))
{
throw new System.ArgumentException("Only QR Code is supported at this time");
}
this.field = field;
this.cachedGenerators = new List<GenericGFPoly>();
cachedGenerators.Add(new GenericGFPoly(field, new int[]{1}));
}
private GenericGFPoly buildGenerator(int degree)
{
if (degree >= cachedGenerators.Count)
{
GenericGFPoly lastGenerator = cachedGenerators[cachedGenerators.Count - 1];
for (int d = cachedGenerators.Count; d <= degree; d++)
{
GenericGFPoly nextGenerator = lastGenerator.multiply(new GenericGFPoly(field, new int[] {1, field.exp(d - 1)}));
cachedGenerators.Add(nextGenerator);
lastGenerator = nextGenerator;
}
}
return cachedGenerators[degree];
}
public void encode(int[] toEncode, int ecBytes)
{
if (ecBytes == 0)
{
throw new System.ArgumentException("No error correction bytes");
}
int dataBytes = toEncode.Length - ecBytes;
if (dataBytes <= 0)
{
throw new System.ArgumentException("No data bytes provided");
}
GenericGFPoly generator = buildGenerator(ecBytes);
int[] infoCoefficients = new int[dataBytes];
Array.Copy(toEncode, 0, infoCoefficients, 0, dataBytes);
GenericGFPoly info = new GenericGFPoly(field, infoCoefficients);
info = info.multiplyByMonomial(ecBytes, 1);
GenericGFPoly remainder = info.divide(generator)[1];
int[] coefficients = remainder.Coefficients;
int numZeroCoefficients = ecBytes - coefficients.Length;
for (int i = 0; i < numZeroCoefficients; i++)
{
toEncode[dataBytes + i] = 0;
}
Array.Copy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.Length);
}
}
}

View file

@ -1,36 +0,0 @@
using System;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.common.reedsolomon
{
/// <summary>
/// <p>Thrown when an exception occurs during Reed-Solomon decoding, such as when
/// there are too many errors to correct.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class ReedSolomonException : Exception
{
public ReedSolomonException(string message) : base(message)
{
}
}
}

View file

@ -1,184 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.datamatrix
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using BinaryBitmap = com.google.zxing.BinaryBitmap;
using ChecksumException = com.google.zxing.ChecksumException;
using DecodeHintType = com.google.zxing.DecodeHintType;
using FormatException = com.google.zxing.FormatException;
using NotFoundException = com.google.zxing.NotFoundException;
using Reader = com.google.zxing.Reader;
using Result = com.google.zxing.Result;
using ResultMetadataType = com.google.zxing.ResultMetadataType;
using ResultPoint = com.google.zxing.ResultPoint;
using BitMatrix = com.google.zxing.common.BitMatrix;
using DecoderResult = com.google.zxing.common.DecoderResult;
using DetectorResult = com.google.zxing.common.DetectorResult;
using Decoder = com.google.zxing.datamatrix.decoder.Decoder;
using Detector = com.google.zxing.datamatrix.detector.Detector;
/// <summary>
/// This implementation can detect and decode Data Matrix codes in an image.
///
/// @author bbrown@google.com (Brian Brown)
/// </summary>
public sealed class DataMatrixReader : com.google.zxing.Reader
{
private static readonly ResultPoint[] NO_POINTS = new ResultPoint[0];
private readonly Decoder decoder = new Decoder();
/// <summary>
/// Locates and decodes a Data Matrix code in an image.
/// </summary>
/// <returns> a String representing the content encoded by the Data Matrix code </returns>
/// <exception cref="NotFoundException"> if a Data Matrix code cannot be found </exception>
/// <exception cref="FormatException"> if a Data Matrix code cannot be decoded </exception>
/// <exception cref="ChecksumException"> if error correction fails </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decode(com.google.zxing.BinaryBitmap image) throws com.google.zxing.NotFoundException, com.google.zxing.ChecksumException, com.google.zxing.FormatException
public Result decode(BinaryBitmap image)
{
return decode(image, null);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decode(com.google.zxing.BinaryBitmap image, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.ChecksumException, com.google.zxing.FormatException
public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
{
DecoderResult decoderResult;
ResultPoint[] points;
if (hints != null && hints.ContainsKey(DecodeHintType.PURE_BARCODE))
{
BitMatrix bits = extractPureBits(image.BlackMatrix);
decoderResult = decoder.decode(bits);
points = NO_POINTS;
}
else
{
DetectorResult detectorResult = (new Detector(image.BlackMatrix)).detect();
decoderResult = decoder.decode(detectorResult.Bits);
points = detectorResult.Points;
}
Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.DATA_MATRIX);
IList<sbyte[]> byteSegments = decoderResult.ByteSegments;
if (byteSegments != null)
{
result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments);
}
string ecLevel = decoderResult.ECLevel;
if (ecLevel != null)
{
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
}
return result;
}
public void reset()
{
// do nothing
}
/// <summary>
/// This method detects a code in a "pure" image -- that is, pure monochrome image
/// which contains only an unrotated, unskewed, image of a code, with some white border
/// around it. This is a specialized method that works exceptionally fast in this special
/// case.
/// </summary>
/// <seealso cref= com.google.zxing.pdf417.PDF417Reader#extractPureBits(BitMatrix) </seealso>
/// <seealso cref= com.google.zxing.qrcode.QRCodeReader#extractPureBits(BitMatrix) </seealso>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static com.google.zxing.common.BitMatrix extractPureBits(com.google.zxing.common.BitMatrix image) throws com.google.zxing.NotFoundException
private static BitMatrix extractPureBits(BitMatrix image)
{
int[] leftTopBlack = image.TopLeftOnBit;
int[] rightBottomBlack = image.BottomRightOnBit;
if (leftTopBlack == null || rightBottomBlack == null)
{
throw NotFoundException.NotFoundInstance;
}
int moduleSize = getModuleSize(leftTopBlack, image);
int top = leftTopBlack[1];
int bottom = rightBottomBlack[1];
int left = leftTopBlack[0];
int right = rightBottomBlack[0];
int matrixWidth = (right - left + 1) / moduleSize;
int matrixHeight = (bottom - top + 1) / moduleSize;
if (matrixWidth <= 0 || matrixHeight <= 0)
{
throw NotFoundException.NotFoundInstance;
}
// Push in the "border" by half the module width so that we start
// sampling in the middle of the module. Just in case the image is a
// little off, this will help recover.
int nudge = moduleSize >> 1;
top += nudge;
left += nudge;
// Now just read off the bits
BitMatrix bits = new BitMatrix(matrixWidth, matrixHeight);
for (int y = 0; y < matrixHeight; y++)
{
int iOffset = top + y * moduleSize;
for (int x = 0; x < matrixWidth; x++)
{
if (image.get(left + x * moduleSize, iOffset))
{
bits.set(x, y);
}
}
}
return bits;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int moduleSize(int[] leftTopBlack, com.google.zxing.common.BitMatrix image) throws com.google.zxing.NotFoundException
private static int getModuleSize(int[] leftTopBlack, BitMatrix image)
{
int width = image.Width;
int x = leftTopBlack[0];
int y = leftTopBlack[1];
while (x < width && image.get(x, y))
{
x++;
}
if (x == width)
{
throw NotFoundException.NotFoundInstance;
}
int moduleSize = x - leftTopBlack[0];
if (moduleSize == 0)
{
throw NotFoundException.NotFoundInstance;
}
return moduleSize;
}
}
}

View file

@ -1,516 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.datamatrix.decoder
{
using FormatException = com.google.zxing.FormatException;
using BitMatrix = com.google.zxing.common.BitMatrix;
/// <summary>
/// @author bbrown@google.com (Brian Brown)
/// </summary>
internal sealed class BitMatrixParser
{
private readonly BitMatrix mappingBitMatrix;
private readonly BitMatrix readMappingMatrix;
private readonly Version version;
/// <param name="bitMatrix"> <seealso cref="BitMatrix"/> to parse </param>
/// <exception cref="FormatException"> if dimension is < 8 or > 144 or not 0 mod 2 </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: BitMatrixParser(com.google.zxing.common.BitMatrix bitMatrix) throws com.google.zxing.FormatException
internal BitMatrixParser(BitMatrix bitMatrix)
{
int dimension = bitMatrix.Height;
if (dimension < 8 || dimension > 144 || (dimension & 0x01) != 0)
{
throw FormatException.FormatInstance;
}
version = readVersion(bitMatrix);
this.mappingBitMatrix = extractDataRegion(bitMatrix);
this.readMappingMatrix = new BitMatrix(this.mappingBitMatrix.Width, this.mappingBitMatrix.Height);
}
internal Version Version
{
get
{
return version;
}
}
/// <summary>
/// <p>Creates the version object based on the dimension of the original bit matrix from
/// the datamatrix code.</p>
///
/// <p>See ISO 16022:2006 Table 7 - ECC 200 symbol attributes</p>
/// </summary>
/// <param name="bitMatrix"> Original <seealso cref="BitMatrix"/> including alignment patterns </param>
/// <returns> <seealso cref="Version"/> encapsulating the Data Matrix Code's "version" </returns>
/// <exception cref="FormatException"> if the dimensions of the mapping matrix are not valid
/// Data Matrix dimensions. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static Version readVersion(com.google.zxing.common.BitMatrix bitMatrix) throws com.google.zxing.FormatException
private static Version readVersion(BitMatrix bitMatrix)
{
int numRows = bitMatrix.Height;
int numColumns = bitMatrix.Width;
return Version.getVersionForDimensions(numRows, numColumns);
}
/// <summary>
/// <p>Reads the bits in the <seealso cref="BitMatrix"/> representing the mapping matrix (No alignment patterns)
/// in the correct order in order to reconstitute the codewords bytes contained within the
/// Data Matrix Code.</p>
/// </summary>
/// <returns> bytes encoded within the Data Matrix Code </returns>
/// <exception cref="FormatException"> if the exact number of bytes expected is not read </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: byte[] readCodewords() throws com.google.zxing.FormatException
internal sbyte[] readCodewords()
{
sbyte[] result = new sbyte[version.TotalCodewords];
int resultOffset = 0;
int row = 4;
int column = 0;
int numRows = mappingBitMatrix.Height;
int numColumns = mappingBitMatrix.Width;
bool corner1Read = false;
bool corner2Read = false;
bool corner3Read = false;
bool corner4Read = false;
// Read all of the codewords
do
{
// Check the four corner cases
if ((row == numRows) && (column == 0) && !corner1Read)
{
result[resultOffset++] = (sbyte) readCorner1(numRows, numColumns);
row -= 2;
column += 2;
corner1Read = true;
}
else if ((row == numRows - 2) && (column == 0) && ((numColumns & 0x03) != 0) && !corner2Read)
{
result[resultOffset++] = (sbyte) readCorner2(numRows, numColumns);
row -= 2;
column += 2;
corner2Read = true;
}
else if ((row == numRows + 4) && (column == 2) && ((numColumns & 0x07) == 0) && !corner3Read)
{
result[resultOffset++] = (sbyte) readCorner3(numRows, numColumns);
row -= 2;
column += 2;
corner3Read = true;
}
else if ((row == numRows - 2) && (column == 0) && ((numColumns & 0x07) == 4) && !corner4Read)
{
result[resultOffset++] = (sbyte) readCorner4(numRows, numColumns);
row -= 2;
column += 2;
corner4Read = true;
}
else
{
// Sweep upward diagonally to the right
do
{
if ((row < numRows) && (column >= 0) && !readMappingMatrix.get(column, row))
{
result[resultOffset++] = (sbyte) readUtah(row, column, numRows, numColumns);
}
row -= 2;
column += 2;
} while ((row >= 0) && (column < numColumns));
row += 1;
column += 3;
// Sweep downward diagonally to the left
do
{
if ((row >= 0) && (column < numColumns) && !readMappingMatrix.get(column, row))
{
result[resultOffset++] = (sbyte) readUtah(row, column, numRows, numColumns);
}
row += 2;
column -= 2;
} while ((row < numRows) && (column >= 0));
row += 3;
column += 1;
}
} while ((row < numRows) || (column < numColumns));
if (resultOffset != version.TotalCodewords)
{
throw FormatException.FormatInstance;
}
return result;
}
/// <summary>
/// <p>Reads a bit of the mapping matrix accounting for boundary wrapping.</p>
/// </summary>
/// <param name="row"> Row to read in the mapping matrix </param>
/// <param name="column"> Column to read in the mapping matrix </param>
/// <param name="numRows"> Number of rows in the mapping matrix </param>
/// <param name="numColumns"> Number of columns in the mapping matrix </param>
/// <returns> value of the given bit in the mapping matrix </returns>
internal bool readModule(int row, int column, int numRows, int numColumns)
{
// Adjust the row and column indices based on boundary wrapping
if (row < 0)
{
row += numRows;
column += 4 - ((numRows + 4) & 0x07);
}
if (column < 0)
{
column += numColumns;
row += 4 - ((numColumns + 4) & 0x07);
}
readMappingMatrix.set(column, row);
return mappingBitMatrix.get(column, row);
}
/// <summary>
/// <p>Reads the 8 bits of the standard Utah-shaped pattern.</p>
///
/// <p>See ISO 16022:2006, 5.8.1 Figure 6</p>
/// </summary>
/// <param name="row"> Current row in the mapping matrix, anchored at the 8th bit (LSB) of the pattern </param>
/// <param name="column"> Current column in the mapping matrix, anchored at the 8th bit (LSB) of the pattern </param>
/// <param name="numRows"> Number of rows in the mapping matrix </param>
/// <param name="numColumns"> Number of columns in the mapping matrix </param>
/// <returns> byte from the utah shape </returns>
internal int readUtah(int row, int column, int numRows, int numColumns)
{
int currentByte = 0;
if (readModule(row - 2, column - 2, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(row - 2, column - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(row - 1, column - 2, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(row - 1, column - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(row - 1, column, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(row, column - 2, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(row, column - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(row, column, numRows, numColumns))
{
currentByte |= 1;
}
return currentByte;
}
/// <summary>
/// <p>Reads the 8 bits of the special corner condition 1.</p>
///
/// <p>See ISO 16022:2006, Figure F.3</p>
/// </summary>
/// <param name="numRows"> Number of rows in the mapping matrix </param>
/// <param name="numColumns"> Number of columns in the mapping matrix </param>
/// <returns> byte from the Corner condition 1 </returns>
internal int readCorner1(int numRows, int numColumns)
{
int currentByte = 0;
if (readModule(numRows - 1, 0, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(numRows - 1, 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(numRows - 1, 2, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 2, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(1, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(2, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(3, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
return currentByte;
}
/// <summary>
/// <p>Reads the 8 bits of the special corner condition 2.</p>
///
/// <p>See ISO 16022:2006, Figure F.4</p>
/// </summary>
/// <param name="numRows"> Number of rows in the mapping matrix </param>
/// <param name="numColumns"> Number of columns in the mapping matrix </param>
/// <returns> byte from the Corner condition 2 </returns>
internal int readCorner2(int numRows, int numColumns)
{
int currentByte = 0;
if (readModule(numRows - 3, 0, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(numRows - 2, 0, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(numRows - 1, 0, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 4, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 3, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 2, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(1, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
return currentByte;
}
/// <summary>
/// <p>Reads the 8 bits of the special corner condition 3.</p>
///
/// <p>See ISO 16022:2006, Figure F.5</p>
/// </summary>
/// <param name="numRows"> Number of rows in the mapping matrix </param>
/// <param name="numColumns"> Number of columns in the mapping matrix </param>
/// <returns> byte from the Corner condition 3 </returns>
internal int readCorner3(int numRows, int numColumns)
{
int currentByte = 0;
if (readModule(numRows - 1, 0, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(numRows - 1, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 3, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 2, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(1, numColumns - 3, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(1, numColumns - 2, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(1, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
return currentByte;
}
/// <summary>
/// <p>Reads the 8 bits of the special corner condition 4.</p>
///
/// <p>See ISO 16022:2006, Figure F.6</p>
/// </summary>
/// <param name="numRows"> Number of rows in the mapping matrix </param>
/// <param name="numColumns"> Number of columns in the mapping matrix </param>
/// <returns> byte from the Corner condition 4 </returns>
internal int readCorner4(int numRows, int numColumns)
{
int currentByte = 0;
if (readModule(numRows - 3, 0, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(numRows - 2, 0, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(numRows - 1, 0, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 2, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(0, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(1, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(2, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
currentByte <<= 1;
if (readModule(3, numColumns - 1, numRows, numColumns))
{
currentByte |= 1;
}
return currentByte;
}
/// <summary>
/// <p>Extracts the data region from a <seealso cref="BitMatrix"/> that contains
/// alignment patterns.</p>
/// </summary>
/// <param name="bitMatrix"> Original <seealso cref="BitMatrix"/> with alignment patterns </param>
/// <returns> BitMatrix that has the alignment patterns removed </returns>
internal BitMatrix extractDataRegion(BitMatrix bitMatrix)
{
int symbolSizeRows = version.SymbolSizeRows;
int symbolSizeColumns = version.SymbolSizeColumns;
if (bitMatrix.Height != symbolSizeRows)
{
throw new System.ArgumentException("Dimension of bitMarix must match the version size");
}
int dataRegionSizeRows = version.DataRegionSizeRows;
int dataRegionSizeColumns = version.DataRegionSizeColumns;
int numDataRegionsRow = symbolSizeRows / dataRegionSizeRows;
int numDataRegionsColumn = symbolSizeColumns / dataRegionSizeColumns;
int sizeDataRegionRow = numDataRegionsRow * dataRegionSizeRows;
int sizeDataRegionColumn = numDataRegionsColumn * dataRegionSizeColumns;
BitMatrix bitMatrixWithoutAlignment = new BitMatrix(sizeDataRegionColumn, sizeDataRegionRow);
for (int dataRegionRow = 0; dataRegionRow < numDataRegionsRow; ++dataRegionRow)
{
int dataRegionRowOffset = dataRegionRow * dataRegionSizeRows;
for (int dataRegionColumn = 0; dataRegionColumn < numDataRegionsColumn; ++dataRegionColumn)
{
int dataRegionColumnOffset = dataRegionColumn * dataRegionSizeColumns;
for (int i = 0; i < dataRegionSizeRows; ++i)
{
int readRowOffset = dataRegionRow * (dataRegionSizeRows + 2) + 1 + i;
int writeRowOffset = dataRegionRowOffset + i;
for (int j = 0; j < dataRegionSizeColumns; ++j)
{
int readColumnOffset = dataRegionColumn * (dataRegionSizeColumns + 2) + 1 + j;
if (bitMatrix.get(readColumnOffset, readRowOffset))
{
int writeColumnOffset = dataRegionColumnOffset + j;
bitMatrixWithoutAlignment.set(writeColumnOffset, writeRowOffset);
}
}
}
}
}
return bitMatrixWithoutAlignment;
}
}
}

View file

@ -1,138 +0,0 @@
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.datamatrix.decoder
{
/// <summary>
/// <p>Encapsulates a block of data within a Data Matrix Code. Data Matrix Codes may split their data into
/// multiple blocks, each of which is a unit of data and error-correction codewords. Each
/// is represented by an instance of this class.</p>
///
/// @author bbrown@google.com (Brian Brown)
/// </summary>
internal sealed class DataBlock
{
private readonly int numDataCodewords;
private readonly sbyte[] codewords;
private DataBlock(int numDataCodewords, sbyte[] codewords)
{
this.numDataCodewords = numDataCodewords;
this.codewords = codewords;
}
/// <summary>
/// <p>When Data Matrix Codes use multiple data blocks, they actually interleave the bytes of each of them.
/// That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This
/// method will separate the data into original blocks.</p>
/// </summary>
/// <param name="rawCodewords"> bytes as read directly from the Data Matrix Code </param>
/// <param name="version"> version of the Data Matrix Code </param>
/// <returns> DataBlocks containing original bytes, "de-interleaved" from representation in the
/// Data Matrix Code </returns>
internal static DataBlock[] getDataBlocks(sbyte[] rawCodewords, Version version)
{
// Figure out the number and size of data blocks used by this version
Version.ECBlocks ecBlocks = version.ECBlocks2;
// First count the total number of data blocks
int totalBlocks = 0;
Version.ECB[] ecBlockArray = ecBlocks.GetECB;
foreach (Version.ECB ecBlock in ecBlockArray)
{
totalBlocks += ecBlock.Count;
}
// Now establish DataBlocks of the appropriate size and number of data codewords
DataBlock[] result = new DataBlock[totalBlocks];
int numResultBlocks = 0;
foreach (Version.ECB ecBlock in ecBlockArray)
{
for (int i = 0; i < ecBlock.Count; i++)
{
int numDataCodewords = ecBlock.DataCodewords;
int numBlockCodewords = ecBlocks.ECCodewords + numDataCodewords;
result[numResultBlocks++] = new DataBlock(numDataCodewords, new sbyte[numBlockCodewords]);
}
}
// All blocks have the same amount of data, except that the last n
// (where n may be 0) have 1 less byte. Figure out where these start.
// TODO(bbrown): There is only one case where there is a difference for Data Matrix for size 144
int longerBlocksTotalCodewords = result[0].codewords.Length;
//int shorterBlocksTotalCodewords = longerBlocksTotalCodewords - 1;
int longerBlocksNumDataCodewords = longerBlocksTotalCodewords - ecBlocks.ECCodewords;
int shorterBlocksNumDataCodewords = longerBlocksNumDataCodewords - 1;
// The last elements of result may be 1 element shorter for 144 matrix
// first fill out as many elements as all of them have minus 1
int rawCodewordsOffset = 0;
for (int i = 0; i < shorterBlocksNumDataCodewords; i++)
{
for (int j = 0; j < numResultBlocks; j++)
{
result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];
}
}
// Fill out the last data block in the longer ones
bool specialVersion = version.VersionNumber == 24;
int numLongerBlocks = specialVersion ? 8 : numResultBlocks;
for (int j = 0; j < numLongerBlocks; j++)
{
result[j].codewords[longerBlocksNumDataCodewords - 1] = rawCodewords[rawCodewordsOffset++];
}
// Now add in error correction blocks
int max = result[0].codewords.Length;
for (int i = longerBlocksNumDataCodewords; i < max; i++)
{
for (int j = 0; j < numResultBlocks; j++)
{
int iOffset = specialVersion && j > 7 ? i - 1 : i;
result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];
}
}
if (rawCodewordsOffset != rawCodewords.Length)
{
throw new System.ArgumentException();
}
return result;
}
internal int NumDataCodewords
{
get
{
return numDataCodewords;
}
}
internal sbyte[] Codewords
{
get
{
return codewords;
}
}
}
}

View file

@ -1,644 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using com.google.zxing.common;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.datamatrix.decoder
{
using FormatException = com.google.zxing.FormatException;
using BitSource = com.google.zxing.common.BitSource;
using DecoderResult = com.google.zxing.common.DecoderResult;
/// <summary>
/// <p>Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes
/// in one Data Matrix Code. This class decodes the bits back into text.</p>
///
/// <p>See ISO 16022:2006, 5.2.1 - 5.2.9.2</p>
///
/// @author bbrown@google.com (Brian Brown)
/// @author Sean Owen
/// </summary>
internal sealed class DecodedBitStreamParser
{
private enum Mode
{
PAD_ENCODE, // Not really a mode
ASCII_ENCODE,
C40_ENCODE,
TEXT_ENCODE,
ANSIX12_ENCODE,
EDIFACT_ENCODE,
BASE256_ENCODE
}
/// <summary>
/// See ISO 16022:2006, Annex C Table C.1
/// The C40 Basic Character Set (*'s used for placeholders for the shift values)
/// </summary>
private static readonly char[] C40_BASIC_SET_CHARS = {'*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
private static readonly char[] C40_SHIFT2_SET_CHARS = {'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_'};
/// <summary>
/// See ISO 16022:2006, Annex C Table C.2
/// The Text Basic Character Set (*'s used for placeholders for the shift values)
/// </summary>
private static readonly char[] TEXT_BASIC_SET_CHARS = {'*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
private static readonly char[] TEXT_SHIFT3_SET_CHARS = {'\'', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', (char) 127};
private DecodedBitStreamParser()
{
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: static com.google.zxing.common.DecoderResult decode(byte[] bytes) throws com.google.zxing.FormatException
internal static DecoderResult decode(sbyte[] bytes)
{
BitSource bits = new BitSource(bytes);
StringBuilder result = new StringBuilder(100);
StringBuilder resultTrailer = new StringBuilder(0);
IList<sbyte[]> byteSegments = new List<sbyte[]>(1);
Mode mode = Mode.ASCII_ENCODE;
do
{
if (mode == Mode.ASCII_ENCODE)
{
mode = decodeAsciiSegment(bits, result, resultTrailer);
}
else
{
switch (mode)
{
case com.google.zxing.datamatrix.decoder.DecodedBitStreamParser.Mode.C40_ENCODE:
decodeC40Segment(bits, result);
break;
case com.google.zxing.datamatrix.decoder.DecodedBitStreamParser.Mode.TEXT_ENCODE:
decodeTextSegment(bits, result);
break;
case com.google.zxing.datamatrix.decoder.DecodedBitStreamParser.Mode.ANSIX12_ENCODE:
decodeAnsiX12Segment(bits, result);
break;
case com.google.zxing.datamatrix.decoder.DecodedBitStreamParser.Mode.EDIFACT_ENCODE:
decodeEdifactSegment(bits, result);
break;
case com.google.zxing.datamatrix.decoder.DecodedBitStreamParser.Mode.BASE256_ENCODE:
decodeBase256Segment(bits, result, byteSegments);
break;
default:
throw FormatException.FormatInstance;
}
mode = Mode.ASCII_ENCODE;
}
} while (mode != Mode.PAD_ENCODE && bits.available() > 0);
if (resultTrailer.Length > 0)
{
result.Append(resultTrailer.ToString());
}
return new DecoderResult(bytes, result.ToString(), byteSegments.Count == 0 ? null : byteSegments, null);
}
/// <summary>
/// See ISO 16022:2006, 5.2.3 and Annex C, Table C.2
/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static Mode decodeAsciiSegment(com.google.zxing.common.BitSource bits, StringBuilder result, StringBuilder resultTrailer) throws com.google.zxing.FormatException
private static Mode decodeAsciiSegment(BitSource bits, StringBuilder result, StringBuilder resultTrailer)
{
bool upperShift = false;
do
{
int oneByte = bits.readBits(8);
if (oneByte == 0)
{
throw FormatException.FormatInstance;
} // ASCII data (ASCII value + 1)
else if (oneByte <= 128)
{
if (upperShift)
{
oneByte += 128;
//upperShift = false;
}
result.Append((char)(oneByte - 1));
return Mode.ASCII_ENCODE;
} // Pad
else if (oneByte == 129)
{
return Mode.PAD_ENCODE;
} // 2-digit data 00-99 (Numeric Value + 130)
else if (oneByte <= 229)
{
int value = oneByte - 130;
if (value < 10) // padd with '0' for single digit values
{
result.Append('0');
}
result.Append(value);
} // Latch to C40 encodation
else if (oneByte == 230)
{
return Mode.C40_ENCODE;
} // Latch to Base 256 encodation
else if (oneByte == 231)
{
return Mode.BASE256_ENCODE;
}
else if (oneByte == 232)
{
// FNC1
result.Append((char) 29); // translate as ASCII 29
}
else if (oneByte == 233 || oneByte == 234)
{
// Structured Append, Reader Programming
// Ignore these symbols for now
//throw ReaderException.getInstance();
} // Upper Shift (shift to Extended ASCII)
else if (oneByte == 235)
{
upperShift = true;
} // 05 Macro
else if (oneByte == 236)
{
result.Append("[)>\u001E05\u001D");
resultTrailer.Insert(0, "\u001E\u0004");
} // 06 Macro
else if (oneByte == 237)
{
result.Append("[)>\u001E06\u001D");
resultTrailer.Insert(0, "\u001E\u0004");
} // Latch to ANSI X12 encodation
else if (oneByte == 238)
{
return Mode.ANSIX12_ENCODE;
} // Latch to Text encodation
else if (oneByte == 239)
{
return Mode.TEXT_ENCODE;
} // Latch to EDIFACT encodation
else if (oneByte == 240)
{
return Mode.EDIFACT_ENCODE;
} // ECI Character
else if (oneByte == 241)
{
// TODO(bbrown): I think we need to support ECI
//throw ReaderException.getInstance();
// Ignore this symbol for now
} // Not to be used in ASCII encodation
else if (oneByte >= 242)
{
// ... but work around encoders that end with 254, latch back to ASCII
if (oneByte != 254 || bits.available() != 0)
{
throw FormatException.FormatInstance;
}
}
} while (bits.available() > 0);
return Mode.ASCII_ENCODE;
}
/// <summary>
/// See ISO 16022:2006, 5.2.5 and Annex C, Table C.1
/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static void decodeC40Segment(com.google.zxing.common.BitSource bits, StringBuilder result) throws com.google.zxing.FormatException
private static void decodeC40Segment(BitSource bits, StringBuilder result)
{
// Three C40 values are encoded in a 16-bit value as
// (1600 * C1) + (40 * C2) + C3 + 1
// TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time
bool upperShift = false;
int[] cValues = new int[3];
int shift = 0;
do
{
// If there is only one byte left then it will be encoded as ASCII
if (bits.available() == 8)
{
return;
}
int firstByte = bits.readBits(8);
if (firstByte == 254) // Unlatch codeword
{
return;
}
parseTwoBytes(firstByte, bits.readBits(8), cValues);
for (int i = 0; i < 3; i++)
{
int cValue = cValues[i];
switch (shift)
{
case 0:
if (cValue < 3)
{
shift = cValue + 1;
}
else if (cValue < C40_BASIC_SET_CHARS.Length)
{
char c40char = C40_BASIC_SET_CHARS[cValue];
if (upperShift)
{
result.Append((char)(c40char + 128));
upperShift = false;
}
else
{
result.Append(c40char);
}
}
else
{
throw FormatException.FormatInstance;
}
break;
case 1:
if (upperShift)
{
result.Append((char)(cValue + 128));
upperShift = false;
}
else
{
result.Append((char) cValue);
}
shift = 0;
break;
case 2:
if (cValue < C40_SHIFT2_SET_CHARS.Length)
{
char c40char = C40_SHIFT2_SET_CHARS[cValue];
if (upperShift)
{
result.Append((char)(c40char + 128));
upperShift = false;
}
else
{
result.Append(c40char);
}
} // FNC1
else if (cValue == 27)
{
result.Append((char) 29); // translate as ASCII 29
} // Upper Shift
else if (cValue == 30)
{
upperShift = true;
}
else
{
throw FormatException.FormatInstance;
}
shift = 0;
break;
case 3:
if (upperShift)
{
result.Append((char)(cValue + 224));
upperShift = false;
}
else
{
result.Append((char)(cValue + 96));
}
shift = 0;
break;
default:
throw FormatException.FormatInstance;
}
}
} while (bits.available() > 0);
}
/// <summary>
/// See ISO 16022:2006, 5.2.6 and Annex C, Table C.2
/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static void decodeTextSegment(com.google.zxing.common.BitSource bits, StringBuilder result) throws com.google.zxing.FormatException
private static void decodeTextSegment(BitSource bits, StringBuilder result)
{
// Three Text values are encoded in a 16-bit value as
// (1600 * C1) + (40 * C2) + C3 + 1
// TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time
bool upperShift = false;
int[] cValues = new int[3];
int shift = 0;
do
{
// If there is only one byte left then it will be encoded as ASCII
if (bits.available() == 8)
{
return;
}
int firstByte = bits.readBits(8);
if (firstByte == 254) // Unlatch codeword
{
return;
}
parseTwoBytes(firstByte, bits.readBits(8), cValues);
for (int i = 0; i < 3; i++)
{
int cValue = cValues[i];
switch (shift)
{
case 0:
if (cValue < 3)
{
shift = cValue + 1;
}
else if (cValue < TEXT_BASIC_SET_CHARS.Length)
{
char textChar = TEXT_BASIC_SET_CHARS[cValue];
if (upperShift)
{
result.Append((char)(textChar + 128));
upperShift = false;
}
else
{
result.Append(textChar);
}
}
else
{
throw FormatException.FormatInstance;
}
break;
case 1:
if (upperShift)
{
result.Append((char)(cValue + 128));
upperShift = false;
}
else
{
result.Append((char) cValue);
}
shift = 0;
break;
case 2:
// Shift 2 for Text is the same encoding as C40
if (cValue < C40_SHIFT2_SET_CHARS.Length)
{
char c40char = C40_SHIFT2_SET_CHARS[cValue];
if (upperShift)
{
result.Append((char)(c40char + 128));
upperShift = false;
}
else
{
result.Append(c40char);
}
} // FNC1
else if (cValue == 27)
{
result.Append((char) 29); // translate as ASCII 29
} // Upper Shift
else if (cValue == 30)
{
upperShift = true;
}
else
{
throw FormatException.FormatInstance;
}
shift = 0;
break;
case 3:
if (cValue < TEXT_SHIFT3_SET_CHARS.Length)
{
char textChar = TEXT_SHIFT3_SET_CHARS[cValue];
if (upperShift)
{
result.Append((char)(textChar + 128));
upperShift = false;
}
else
{
result.Append(textChar);
}
shift = 0;
}
else
{
throw FormatException.FormatInstance;
}
break;
default:
throw FormatException.FormatInstance;
}
}
} while (bits.available() > 0);
}
/// <summary>
/// See ISO 16022:2006, 5.2.7
/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static void decodeAnsiX12Segment(com.google.zxing.common.BitSource bits, StringBuilder result) throws com.google.zxing.FormatException
private static void decodeAnsiX12Segment(BitSource bits, StringBuilder result)
{
// Three ANSI X12 values are encoded in a 16-bit value as
// (1600 * C1) + (40 * C2) + C3 + 1
int[] cValues = new int[3];
do
{
// If there is only one byte left then it will be encoded as ASCII
if (bits.available() == 8)
{
return;
}
int firstByte = bits.readBits(8);
if (firstByte == 254) // Unlatch codeword
{
return;
}
parseTwoBytes(firstByte, bits.readBits(8), cValues);
for (int i = 0; i < 3; i++)
{
int cValue = cValues[i];
if (cValue == 0) // X12 segment terminator <CR>
{
result.Append('\r');
} // X12 segment separator *
else if (cValue == 1)
{
result.Append('*');
} // X12 sub-element separator >
else if (cValue == 2)
{
result.Append('>');
} // space
else if (cValue == 3)
{
result.Append(' ');
} // 0 - 9
else if (cValue < 14)
{
result.Append((char)(cValue + 44));
} // A - Z
else if (cValue < 40)
{
result.Append((char)(cValue + 51));
}
else
{
throw FormatException.FormatInstance;
}
}
} while (bits.available() > 0);
}
private static void parseTwoBytes(int firstByte, int secondByte, int[] result)
{
int fullBitValue = (firstByte << 8) + secondByte - 1;
int temp = fullBitValue / 1600;
result[0] = temp;
fullBitValue -= temp * 1600;
temp = fullBitValue / 40;
result[1] = temp;
result[2] = fullBitValue - temp * 40;
}
/// <summary>
/// See ISO 16022:2006, 5.2.8 and Annex C Table C.3
/// </summary>
private static void decodeEdifactSegment(BitSource bits, StringBuilder result)
{
do
{
// If there is only two or less bytes left then it will be encoded as ASCII
if (bits.available() <= 16)
{
return;
}
for (int i = 0; i < 4; i++)
{
int edifactValue = bits.readBits(6);
// Check for the unlatch character
if (edifactValue == 0x1F) // 011111
{
// Read rest of byte, which should be 0, and stop
int bitsLeft = 8 - bits.BitOffset;
if (bitsLeft != 8)
{
bits.readBits(bitsLeft);
}
return;
}
if ((edifactValue & 0x20) == 0) // no 1 in the leading (6th) bit
{
edifactValue |= 0x40; // Add a leading 01 to the 6 bit binary value
}
result.Append((char) edifactValue);
}
} while (bits.available() > 0);
}
/// <summary>
/// See ISO 16022:2006, 5.2.9 and Annex B, B.2
/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static void decodeBase256Segment(com.google.zxing.common.BitSource bits, StringBuilder result, java.util.Collection<byte[]> byteSegments) throws com.google.zxing.FormatException
private static void decodeBase256Segment(BitSource bits, StringBuilder result, ICollection<sbyte[]> byteSegments)
{
// Figure out how long the Base 256 Segment is.
int codewordPosition = 1 + bits.ByteOffset; // position is 1-indexed
int d1 = unrandomize255State(bits.readBits(8), codewordPosition++);
int count;
if (d1 == 0) // Read the remainder of the symbol
{
count = bits.available() / 8;
}
else if (d1 < 250)
{
count = d1;
}
else
{
count = 250 * (d1 - 249) + unrandomize255State(bits.readBits(8), codewordPosition++);
}
// We're seeing NegativeArraySizeException errors from users.
if (count < 0)
{
throw FormatException.FormatInstance;
}
sbyte[] bytes = new sbyte[count];
for (int i = 0; i < count; i++)
{
// Have seen this particular error in the wild, such as at
// http://www.bcgen.com/demo/IDAutomationStreamingDataMatrix.aspx?MODE=3&D=Fred&PFMT=3&PT=F&X=0.3&O=0&LM=0.2
if (bits.available() < 8)
{
throw FormatException.FormatInstance;
}
bytes[i] = (sbyte) unrandomize255State(bits.readBits(8), codewordPosition++);
}
byteSegments.Add(bytes);
try
{
//result.Append(new string(bytes, "ISO8859_1"));
result.Append(GetEncodedStringFromBuffer(bytes, "ISO-8859-1"));
}
catch (System.IO.IOException uee)
{
throw new InvalidOperationException("Platform does not support required encoding: " + uee);
}
}
private static string GetEncodedStringFromBuffer(sbyte[] buffer, string encoding)
{
byte[] bytes = buffer.ToBytes();
Encoding en = Encoding.GetEncoding(encoding);
return en.GetString(bytes);
}
/// <summary>
/// See ISO 16022:2006, Annex B, B.2
/// </summary>
private static int unrandomize255State(int randomizedBase256Codeword, int base256CodewordPosition)
{
int pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;
int tempVariable = randomizedBase256Codeword - pseudoRandomNumber;
return tempVariable >= 0 ? tempVariable : tempVariable + 256;
}
}
}

View file

@ -1,158 +0,0 @@
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.datamatrix.decoder
{
using ChecksumException = com.google.zxing.ChecksumException;
using FormatException = com.google.zxing.FormatException;
using BitMatrix = com.google.zxing.common.BitMatrix;
using DecoderResult = com.google.zxing.common.DecoderResult;
using GenericGF = com.google.zxing.common.reedsolomon.GenericGF;
using ReedSolomonDecoder = com.google.zxing.common.reedsolomon.ReedSolomonDecoder;
using ReedSolomonException = com.google.zxing.common.reedsolomon.ReedSolomonException;
/// <summary>
/// <p>The main class which implements Data Matrix Code decoding -- as opposed to locating and extracting
/// the Data Matrix Code from an image.</p>
///
/// @author bbrown@google.com (Brian Brown)
/// </summary>
public sealed class Decoder
{
private readonly ReedSolomonDecoder rsDecoder;
public Decoder()
{
rsDecoder = new ReedSolomonDecoder(GenericGF.DATA_MATRIX_FIELD_256);
}
/// <summary>
/// <p>Convenience method that can decode a Data Matrix Code represented as a 2D array of booleans.
/// "true" is taken to mean a black module.</p>
/// </summary>
/// <param name="image"> booleans representing white/black Data Matrix Code modules </param>
/// <returns> text and bytes encoded within the Data Matrix Code </returns>
/// <exception cref="FormatException"> if the Data Matrix Code cannot be decoded </exception>
/// <exception cref="ChecksumException"> if error correction fails </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.DecoderResult decode(boolean[][] image) throws com.google.zxing.FormatException, com.google.zxing.ChecksumException
public DecoderResult decode(bool[][] image)
{
int dimension = image.Length;
BitMatrix bits = new BitMatrix(dimension);
for (int i = 0; i < dimension; i++)
{
for (int j = 0; j < dimension; j++)
{
if (image[i][j])
{
bits.set(j, i);
}
}
}
return decode(bits);
}
/// <summary>
/// <p>Decodes a Data Matrix Code represented as a <seealso cref="BitMatrix"/>. A 1 or "true" is taken
/// to mean a black module.</p>
/// </summary>
/// <param name="bits"> booleans representing white/black Data Matrix Code modules </param>
/// <returns> text and bytes encoded within the Data Matrix Code </returns>
/// <exception cref="FormatException"> if the Data Matrix Code cannot be decoded </exception>
/// <exception cref="ChecksumException"> if error correction fails </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.DecoderResult decode(com.google.zxing.common.BitMatrix bits) throws com.google.zxing.FormatException, com.google.zxing.ChecksumException
public DecoderResult decode(BitMatrix bits)
{
// Construct a parser and read version, error-correction level
BitMatrixParser parser = new BitMatrixParser(bits);
Version version = parser.Version;
// Read codewords
sbyte[] codewords = parser.readCodewords();
// Separate into data blocks
DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version);
int dataBlocksCount = dataBlocks.Length;
// Count total number of data bytes
int totalBytes = 0;
foreach (DataBlock db in dataBlocks)
{
totalBytes += db.NumDataCodewords;
}
sbyte[] resultBytes = new sbyte[totalBytes];
// Error-correct and copy data blocks together into a stream of bytes
for (int j = 0; j < dataBlocksCount; j++)
{
DataBlock dataBlock = dataBlocks[j];
sbyte[] codewordBytes = dataBlock.Codewords;
int numDataCodewords = dataBlock.NumDataCodewords;
correctErrors(codewordBytes, numDataCodewords);
for (int i = 0; i < numDataCodewords; i++)
{
// De-interlace data blocks.
resultBytes[i * dataBlocksCount + j] = codewordBytes[i];
}
}
// Decode the contents of that stream of bytes
return DecodedBitStreamParser.decode(resultBytes);
}
/// <summary>
/// <p>Given data and error-correction codewords received, possibly corrupted by errors, attempts to
/// correct the errors in-place using Reed-Solomon error correction.</p>
/// </summary>
/// <param name="codewordBytes"> data and error correction codewords </param>
/// <param name="numDataCodewords"> number of codewords that are data bytes </param>
/// <exception cref="ChecksumException"> if error correction fails </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void correctErrors(byte[] codewordBytes, int numDataCodewords) throws com.google.zxing.ChecksumException
private void correctErrors(sbyte[] codewordBytes, int numDataCodewords)
{
int numCodewords = codewordBytes.Length;
// First read into an array of ints
int[] codewordsInts = new int[numCodewords];
for (int i = 0; i < numCodewords; i++)
{
codewordsInts[i] = codewordBytes[i] & 0xFF;
}
int numECCodewords = codewordBytes.Length - numDataCodewords;
try
{
rsDecoder.decode(codewordsInts, numECCodewords);
}
catch (ReedSolomonException rse)
{
throw ChecksumException.ChecksumInstance;
}
// Copy back into array of bytes -- only need to worry about the bytes that were data
// We don't care about errors in the error-correction codewords
for (int i = 0; i < numDataCodewords; i++)
{
codewordBytes[i] = (sbyte) codewordsInts[i];
}
}
}
}

View file

@ -1,234 +0,0 @@
using System;
/*
* Copyright 2007 ZXing 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.
*/
namespace com.google.zxing.datamatrix.decoder
{
using FormatException = com.google.zxing.FormatException;
/// <summary>
/// The Version object encapsulates attributes about a particular
/// size Data Matrix Code.
///
/// @author bbrown@google.com (Brian Brown)
/// </summary>
public sealed class Version
{
private static readonly Version[] VERSIONS = buildVersions();
private readonly int versionNumber;
private readonly int symbolSizeRows;
private readonly int symbolSizeColumns;
private readonly int dataRegionSizeRows;
private readonly int dataRegionSizeColumns;
private readonly ECBlocks ecBlocks;
private readonly int totalCodewords;
private Version(int versionNumber, int symbolSizeRows, int symbolSizeColumns, int dataRegionSizeRows, int dataRegionSizeColumns, ECBlocks ecBlocks)
{
this.versionNumber = versionNumber;
this.symbolSizeRows = symbolSizeRows;
this.symbolSizeColumns = symbolSizeColumns;
this.dataRegionSizeRows = dataRegionSizeRows;
this.dataRegionSizeColumns = dataRegionSizeColumns;
this.ecBlocks = ecBlocks;
// Calculate the total number of codewords
int total = 0;
int ecCodewords = ecBlocks.ECCodewords;
ECB[] ecbArray = ecBlocks.GetECB;
foreach (ECB ecBlock in ecbArray)
{
total += ecBlock.Count * (ecBlock.DataCodewords + ecCodewords);
}
this.totalCodewords = total;
}
public int VersionNumber
{
get
{
return versionNumber;
}
}
public int SymbolSizeRows
{
get
{
return symbolSizeRows;
}
}
public int SymbolSizeColumns
{
get
{
return symbolSizeColumns;
}
}
public int DataRegionSizeRows
{
get
{
return dataRegionSizeRows;
}
}
public int DataRegionSizeColumns
{
get
{
return dataRegionSizeColumns;
}
}
public int TotalCodewords
{
get
{
return totalCodewords;
}
}
internal ECBlocks ECBlocks2
{
get
{
return ecBlocks;
}
}
/// <summary>
/// <p>Deduces version information from Data Matrix dimensions.</p>
/// </summary>
/// <param name="numRows"> Number of rows in modules </param>
/// <param name="numColumns"> Number of columns in modules </param>
/// <returns> Version for a Data Matrix Code of those dimensions </returns>
/// <exception cref="FormatException"> if dimensions do correspond to a valid Data Matrix size </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static Version getVersionForDimensions(int numRows, int numColumns) throws com.google.zxing.FormatException
public static Version getVersionForDimensions(int numRows, int numColumns)
{
if ((numRows & 0x01) != 0 || (numColumns & 0x01) != 0)
{
throw FormatException.FormatInstance;
}
foreach (Version version in VERSIONS)
{
if (version.symbolSizeRows == numRows && version.symbolSizeColumns == numColumns)
{
return version;
}
}
throw FormatException.FormatInstance;
}
/// <summary>
/// <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
/// use blocks of differing sizes within one version, so, this encapsulates the parameters for
/// each set of blocks. It also holds the number of error-correction codewords per block since it
/// will be the same across all blocks within one version.</p>
/// </summary>
internal sealed class ECBlocks
{
private readonly int ecCodewords;
private readonly ECB[] ecBlocks;
internal ECBlocks(int ecCodewords, ECB ecBlocks)
{
this.ecCodewords = ecCodewords;
this.ecBlocks = new ECB[] {ecBlocks};
}
internal ECBlocks(int ecCodewords, ECB ecBlocks1, ECB ecBlocks2)
{
this.ecCodewords = ecCodewords;
this.ecBlocks = new ECB[] {ecBlocks1, ecBlocks2};
}
internal int ECCodewords
{
get
{
return ecCodewords;
}
}
internal ECB[] GetECB
{
get
{
return ecBlocks;
}
}
}
/// <summary>
/// <p>Encapsualtes the parameters for one error-correction block in one symbol version.
/// This includes the number of data codewords, and the number of times a block with these
/// parameters is used consecutively in the Data Matrix code version's format.</p>
/// </summary>
internal sealed class ECB
{
private readonly int count;
private readonly int dataCodewords;
internal ECB(int count, int dataCodewords)
{
this.count = count;
this.dataCodewords = dataCodewords;
}
internal int Count
{
get
{
return count;
}
}
internal int DataCodewords
{
get
{
return dataCodewords;
}
}
}
public override string ToString()
{
return Convert.ToString(versionNumber);
}
/// <summary>
/// See ISO 16022:2006 5.5.1 Table 7
/// </summary>
private static Version[] buildVersions()
{
return new Version[]{new Version(1, 10, 10, 8, 8, new ECBlocks(5, new ECB(1, 3))), new Version(2, 12, 12, 10, 10, new ECBlocks(7, new ECB(1, 5))), new Version(3, 14, 14, 12, 12, new ECBlocks(10, new ECB(1, 8))), new Version(4, 16, 16, 14, 14, new ECBlocks(12, new ECB(1, 12))), new Version(5, 18, 18, 16, 16, new ECBlocks(14, new ECB(1, 18))), new Version(6, 20, 20, 18, 18, new ECBlocks(18, new ECB(1, 22))), new Version(7, 22, 22, 20, 20, new ECBlocks(20, new ECB(1, 30))), new Version(8, 24, 24, 22, 22, new ECBlocks(24, new ECB(1, 36))), new Version(9, 26, 26, 24, 24, new ECBlocks(28, new ECB(1, 44))), new Version(10, 32, 32, 14, 14, new ECBlocks(36, new ECB(1, 62))), new Version(11, 36, 36, 16, 16, new ECBlocks(42, new ECB(1, 86))), new Version(12, 40, 40, 18, 18, new ECBlocks(48, new ECB(1, 114))), new Version(13, 44, 44, 20, 20, new ECBlocks(56, new ECB(1, 144))), new Version(14, 48, 48, 22, 22, new ECBlocks(68, new ECB(1, 174))), new Version(15, 52, 52, 24, 24, new ECBlocks(42, new ECB(2, 102))), new Version(16, 64, 64, 14, 14, new ECBlocks(56, new ECB(2, 140))), new Version(17, 72, 72, 16, 16, new ECBlocks(36, new ECB(4, 92))), new Version(18, 80, 80, 18, 18, new ECBlocks(48, new ECB(4, 114))), new Version(19, 88, 88, 20, 20, new ECBlocks(56, new ECB(4, 144))), new Version(20, 96, 96, 22, 22, new ECBlocks(68, new ECB(4, 174))), new Version(21, 104, 104, 24, 24, new ECBlocks(56, new ECB(6, 136))), new Version(22, 120, 120, 18, 18, new ECBlocks(68, new ECB(6, 175))), new Version(23, 132, 132, 20, 20, new ECBlocks(62, new ECB(8, 163))), new Version(24, 144, 144, 22, 22, new ECBlocks(62, new ECB(8, 156), new ECB(2, 155))), new Version(25, 8, 18, 6, 16, new ECBlocks(7, new ECB(1, 5))), new Version(26, 8, 32, 6, 14, new ECBlocks(11, new ECB(1, 10))), new Version(27, 12, 26, 10, 24, new ECBlocks(14, new ECB(1, 16))), new Version(28, 12, 36, 10, 16, new ECBlocks(18, new ECB(1, 22))), new Version(29, 16, 36, 14, 16, new ECBlocks(24, new ECB(1, 32))), new Version(30, 16, 48, 14, 22, new ECBlocks(28, new ECB(1, 49)))};
}
}
}

View file

@ -1,466 +0,0 @@
using System;
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.datamatrix.detector
{
using NotFoundException = com.google.zxing.NotFoundException;
using ResultPoint = com.google.zxing.ResultPoint;
using BitMatrix = com.google.zxing.common.BitMatrix;
using DetectorResult = com.google.zxing.common.DetectorResult;
using GridSampler = com.google.zxing.common.GridSampler;
using MathUtils = com.google.zxing.common.detector.MathUtils;
using WhiteRectangleDetector = com.google.zxing.common.detector.WhiteRectangleDetector;
/// <summary>
/// <p>Encapsulates logic that can detect a Data Matrix Code in an image, even if the Data Matrix Code
/// is rotated or skewed, or partially obscured.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class Detector
{
private readonly BitMatrix image;
private readonly WhiteRectangleDetector rectangleDetector;
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public Detector(com.google.zxing.common.BitMatrix image) throws com.google.zxing.NotFoundException
public Detector(BitMatrix image)
{
this.image = image;
rectangleDetector = new WhiteRectangleDetector(image);
}
/// <summary>
/// <p>Detects a Data Matrix Code in an image.</p>
/// </summary>
/// <returns> <seealso cref="DetectorResult"/> encapsulating results of detecting a Data Matrix Code </returns>
/// <exception cref="NotFoundException"> if no Data Matrix Code can be found </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.DetectorResult detect() throws com.google.zxing.NotFoundException
public DetectorResult detect()
{
ResultPoint[] cornerPoints = rectangleDetector.detect();
ResultPoint pointA = cornerPoints[0];
ResultPoint pointB = cornerPoints[1];
ResultPoint pointC = cornerPoints[2];
ResultPoint pointD = cornerPoints[3];
// Point A and D are across the diagonal from one another,
// as are B and C. Figure out which are the solid black lines
// by counting transitions
List<ResultPointsAndTransitions> transitions = new List<ResultPointsAndTransitions>(4);
transitions.Add(transitionsBetween(pointA, pointB));
transitions.Add(transitionsBetween(pointA, pointC));
transitions.Add(transitionsBetween(pointB, pointD));
transitions.Add(transitionsBetween(pointC, pointD));
transitions.Sort(new ResultPointsAndTransitionsComparator());
// Sort by number of transitions. First two will be the two solid sides; last two
// will be the two alternating black/white sides
ResultPointsAndTransitions lSideOne = transitions[0];
ResultPointsAndTransitions lSideTwo = transitions[1];
// Figure out which point is their intersection by tallying up the number of times we see the
// endpoints in the four endpoints. One will show up twice.
IDictionary<ResultPoint, int?> pointCount = new Dictionary<ResultPoint, int?>();
increment(pointCount, lSideOne.From);
increment(pointCount, lSideOne.To);
increment(pointCount, lSideTwo.From);
increment(pointCount, lSideTwo.To);
ResultPoint maybeTopLeft = null;
ResultPoint bottomLeft = null;
ResultPoint maybeBottomRight = null;
foreach (KeyValuePair<ResultPoint, int?> entry in pointCount)
{
ResultPoint point = entry.Key;
int? value = entry.Value;
if (value == 2)
{
bottomLeft = point; // this is definitely the bottom left, then -- end of two L sides
}
else
{
// Otherwise it's either top left or bottom right -- just assign the two arbitrarily now
if (maybeTopLeft == null)
{
maybeTopLeft = point;
}
else
{
maybeBottomRight = point;
}
}
}
if (maybeTopLeft == null || bottomLeft == null || maybeBottomRight == null)
{
throw NotFoundException.NotFoundInstance;
}
// Bottom left is correct but top left and bottom right might be switched
ResultPoint[] corners = {maybeTopLeft, bottomLeft, maybeBottomRight};
// Use the dot product trick to sort them out
ResultPoint.orderBestPatterns(corners);
// Now we know which is which:
ResultPoint bottomRight = corners[0];
bottomLeft = corners[1];
ResultPoint topLeft = corners[2];
// Which point didn't we find in relation to the "L" sides? that's the top right corner
ResultPoint topRight;
if (!pointCount.ContainsKey(pointA))
{
topRight = pointA;
}
else if (!pointCount.ContainsKey(pointB))
{
topRight = pointB;
}
else if (!pointCount.ContainsKey(pointC))
{
topRight = pointC;
}
else
{
topRight = pointD;
}
// Next determine the dimension by tracing along the top or right side and counting black/white
// transitions. Since we start inside a black module, we should see a number of transitions
// equal to 1 less than the code dimension. Well, actually 2 less, because we are going to
// end on a black module:
// The top right point is actually the corner of a module, which is one of the two black modules
// adjacent to the white module at the top right. Tracing to that corner from either the top left
// or bottom right should work here.
int dimensionTop = transitionsBetween(topLeft, topRight).Transitions;
int dimensionRight = transitionsBetween(bottomRight, topRight).Transitions;
if ((dimensionTop & 0x01) == 1)
{
// it can't be odd, so, round... up?
dimensionTop++;
}
dimensionTop += 2;
if ((dimensionRight & 0x01) == 1)
{
// it can't be odd, so, round... up?
dimensionRight++;
}
dimensionRight += 2;
BitMatrix bits;
ResultPoint correctedTopRight;
// Rectanguar symbols are 6x16, 6x28, 10x24, 10x32, 14x32, or 14x44. If one dimension is more
// than twice the other, it's certainly rectangular, but to cut a bit more slack we accept it as
// rectangular if the bigger side is at least 7/4 times the other:
if (4 * dimensionTop >= 7 * dimensionRight || 4 * dimensionRight >= 7 * dimensionTop)
{
// The matrix is rectangular
correctedTopRight = correctTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight, dimensionTop, dimensionRight);
if (correctedTopRight == null)
{
correctedTopRight = topRight;
}
dimensionTop = transitionsBetween(topLeft, correctedTopRight).Transitions;
dimensionRight = transitionsBetween(bottomRight, correctedTopRight).Transitions;
if ((dimensionTop & 0x01) == 1)
{
// it can't be odd, so, round... up?
dimensionTop++;
}
if ((dimensionRight & 0x01) == 1)
{
// it can't be odd, so, round... up?
dimensionRight++;
}
bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionTop, dimensionRight);
}
else
{
// The matrix is square
int dimension = Math.Min(dimensionRight, dimensionTop);
// correct top right point to match the white module
correctedTopRight = correctTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension);
if (correctedTopRight == null)
{
correctedTopRight = topRight;
}
// Redetermine the dimension using the corrected top right point
int dimensionCorrected = Math.Max(transitionsBetween(topLeft, correctedTopRight).Transitions, transitionsBetween(bottomRight, correctedTopRight).Transitions);
dimensionCorrected++;
if ((dimensionCorrected & 0x01) == 1)
{
dimensionCorrected++;
}
bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimensionCorrected, dimensionCorrected);
}
return new DetectorResult(bits, new ResultPoint[]{topLeft, bottomLeft, bottomRight, correctedTopRight});
}
/// <summary>
/// Calculates the position of the white top right module using the output of the rectangle detector
/// for a rectangular matrix
/// </summary>
private ResultPoint correctTopRightRectangular(ResultPoint bottomLeft, ResultPoint bottomRight, ResultPoint topLeft, ResultPoint topRight, int dimensionTop, int dimensionRight)
{
float corr = distance(bottomLeft, bottomRight) / (float)dimensionTop;
int norm = distance(topLeft, topRight);
float cos = (topRight.X - topLeft.X) / norm;
float sin = (topRight.Y - topLeft.Y) / norm;
ResultPoint c1 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin);
corr = distance(bottomLeft, topLeft) / (float)dimensionRight;
norm = distance(bottomRight, topRight);
cos = (topRight.X - bottomRight.X) / norm;
sin = (topRight.Y - bottomRight.Y) / norm;
ResultPoint c2 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin);
if (!isValid(c1))
{
if (isValid(c2))
{
return c2;
}
return null;
}
if (!isValid(c2))
{
return c1;
}
int l1 = Math.Abs(dimensionTop - transitionsBetween(topLeft, c1).Transitions) + Math.Abs(dimensionRight - transitionsBetween(bottomRight, c1).Transitions);
int l2 = Math.Abs(dimensionTop - transitionsBetween(topLeft, c2).Transitions) + Math.Abs(dimensionRight - transitionsBetween(bottomRight, c2).Transitions);
if (l1 <= l2)
{
return c1;
}
return c2;
}
/// <summary>
/// Calculates the position of the white top right module using the output of the rectangle detector
/// for a square matrix
/// </summary>
private ResultPoint correctTopRight(ResultPoint bottomLeft, ResultPoint bottomRight, ResultPoint topLeft, ResultPoint topRight, int dimension)
{
float corr = distance(bottomLeft, bottomRight) / (float) dimension;
int norm = distance(topLeft, topRight);
float cos = (topRight.X - topLeft.X) / norm;
float sin = (topRight.Y - topLeft.Y) / norm;
ResultPoint c1 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin);
corr = distance(bottomLeft, topLeft) / (float) dimension;
norm = distance(bottomRight, topRight);
cos = (topRight.X - bottomRight.X) / norm;
sin = (topRight.Y - bottomRight.Y) / norm;
ResultPoint c2 = new ResultPoint(topRight.X + corr * cos, topRight.Y + corr * sin);
if (!isValid(c1))
{
if (isValid(c2))
{
return c2;
}
return null;
}
if (!isValid(c2))
{
return c1;
}
int l1 = Math.Abs(transitionsBetween(topLeft, c1).Transitions - transitionsBetween(bottomRight, c1).Transitions);
int l2 = Math.Abs(transitionsBetween(topLeft, c2).Transitions - transitionsBetween(bottomRight, c2).Transitions);
return l1 <= l2 ? c1 : c2;
}
private bool isValid(ResultPoint p)
{
return p.X >= 0 && p.X < image.Width && p.Y > 0 && p.Y < image.Height;
}
private static int distance(ResultPoint a, ResultPoint b)
{
return MathUtils.round(ResultPoint.distance(a, b));
}
/// <summary>
/// Increments the Integer associated with a key by one.
/// </summary>
private static void increment(IDictionary<ResultPoint, int?> table, ResultPoint key)
{
int? value = null;
if (table.ContainsKey(key))
{
value = table[key];
}
table[key] = value == null ? 1 : value + 1;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static com.google.zxing.common.BitMatrix sampleGrid(com.google.zxing.common.BitMatrix image, com.google.zxing.ResultPoint topLeft, com.google.zxing.ResultPoint bottomLeft, com.google.zxing.ResultPoint bottomRight, com.google.zxing.ResultPoint topRight, int dimensionX, int dimensionY) throws com.google.zxing.NotFoundException
private static BitMatrix sampleGrid(BitMatrix image, ResultPoint topLeft, ResultPoint bottomLeft, ResultPoint bottomRight, ResultPoint topRight, int dimensionX, int dimensionY)
{
GridSampler sampler = GridSampler.Instance;
return sampler.sampleGrid(image, dimensionX, dimensionY, 0.5f, 0.5f, dimensionX - 0.5f, 0.5f, dimensionX - 0.5f, dimensionY - 0.5f, 0.5f, dimensionY - 0.5f, topLeft.X, topLeft.Y, topRight.X, topRight.Y, bottomRight.X, bottomRight.Y, bottomLeft.X, bottomLeft.Y);
}
/// <summary>
/// Counts the number of black/white transitions between two points, using something like Bresenham's algorithm.
/// </summary>
private ResultPointsAndTransitions transitionsBetween(ResultPoint from, ResultPoint to)
{
// See QR Code Detector, sizeOfBlackWhiteBlackRun()
int fromX = (int) from.X;
int fromY = (int) from.Y;
int toX = (int) to.X;
int toY = (int) to.Y;
bool steep = Math.Abs(toY - fromY) > Math.Abs(toX - fromX);
if (steep)
{
int temp = fromX;
fromX = fromY;
fromY = temp;
temp = toX;
toX = toY;
toY = temp;
}
int dx = Math.Abs(toX - fromX);
int dy = Math.Abs(toY - fromY);
int error = -dx >> 1;
int ystep = fromY < toY ? 1 : -1;
int xstep = fromX < toX ? 1 : -1;
int transitions = 0;
bool inBlack = image.get(steep ? fromY : fromX, steep ? fromX : fromY);
for (int x = fromX, y = fromY; x != toX; x += xstep)
{
bool isBlack = image.get(steep ? y : x, steep ? x : y);
if (isBlack != inBlack)
{
transitions++;
inBlack = isBlack;
}
error += dy;
if (error > 0)
{
if (y == toY)
{
break;
}
y += ystep;
error -= dx;
}
}
return new ResultPointsAndTransitions(from, to, transitions);
}
/// <summary>
/// Simply encapsulates two points and a number of transitions between them.
/// </summary>
private sealed class ResultPointsAndTransitions
{
private readonly ResultPoint from;
private readonly ResultPoint to;
private readonly int transitions;
internal ResultPointsAndTransitions(ResultPoint from, ResultPoint to, int transitions)
{
this.from = from;
this.to = to;
this.transitions = transitions;
}
internal ResultPoint From
{
get
{
return from;
}
}
internal ResultPoint To
{
get
{
return to;
}
}
public int Transitions
{
get
{
return transitions;
}
}
public override string ToString()
{
return from + "/" + to + '/' + transitions;
}
}
/// <summary>
/// Orders ResultPointsAndTransitions by number of transitions, ascending.
/// </summary>
[Serializable]
private sealed class ResultPointsAndTransitionsComparator : IComparer<ResultPointsAndTransitions>
{
public int Compare(ResultPointsAndTransitions o1, ResultPointsAndTransitions o2)
{
return o1.Transitions - o2.Transitions;
}
}
}
}

View file

@ -1,119 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.multi
{
using BinaryBitmap = com.google.zxing.BinaryBitmap;
using ChecksumException = com.google.zxing.ChecksumException;
using DecodeHintType = com.google.zxing.DecodeHintType;
using FormatException = com.google.zxing.FormatException;
using NotFoundException = com.google.zxing.NotFoundException;
using Reader = com.google.zxing.Reader;
using Result = com.google.zxing.Result;
/// <summary>
/// This class attempts to decode a barcode from an image, not by scanning the whole image,
/// but by scanning subsets of the image. This is important when there may be multiple barcodes in
/// an image, and detecting a barcode may find parts of multiple barcode and fail to decode
/// (e.g. QR Codes). Instead this scans the four quadrants of the image -- and also the center
/// 'quadrant' to cover the case where a barcode is found in the center.
/// </summary>
/// <seealso cref= GenericMultipleBarcodeReader </seealso>
public sealed class ByQuadrantReader : com.google.zxing.Reader
{
private readonly Reader @delegate;
public ByQuadrantReader(Reader @delegate)
{
this.@delegate = @delegate;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decode(com.google.zxing.BinaryBitmap image) throws com.google.zxing.NotFoundException, com.google.zxing.ChecksumException, com.google.zxing.FormatException
public Result decode(BinaryBitmap image)
{
return decode(image, null);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decode(com.google.zxing.BinaryBitmap image, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.ChecksumException, com.google.zxing.FormatException
public Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
{
int width = image.Width;
int height = image.Height;
int halfWidth = width / 2;
int halfHeight = height / 2;
BinaryBitmap topLeft = image.crop(0, 0, halfWidth, halfHeight);
try
{
return @delegate.decode(topLeft, hints);
}
catch (NotFoundException re)
{
// continue
}
BinaryBitmap topRight = image.crop(halfWidth, 0, halfWidth, halfHeight);
try
{
return @delegate.decode(topRight, hints);
}
catch (NotFoundException re)
{
// continue
}
BinaryBitmap bottomLeft = image.crop(0, halfHeight, halfWidth, halfHeight);
try
{
return @delegate.decode(bottomLeft, hints);
}
catch (NotFoundException re)
{
// continue
}
BinaryBitmap bottomRight = image.crop(halfWidth, halfHeight, halfWidth, halfHeight);
try
{
return @delegate.decode(bottomRight, hints);
}
catch (NotFoundException re)
{
// continue
}
int quarterWidth = halfWidth / 2;
int quarterHeight = halfHeight / 2;
BinaryBitmap center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
return @delegate.decode(center, hints);
}
public void reset()
{
@delegate.reset();
}
}
}

View file

@ -1,174 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.multi
{
using BinaryBitmap = com.google.zxing.BinaryBitmap;
using DecodeHintType = com.google.zxing.DecodeHintType;
using NotFoundException = com.google.zxing.NotFoundException;
using Reader = com.google.zxing.Reader;
using ReaderException = com.google.zxing.ReaderException;
using Result = com.google.zxing.Result;
using ResultPoint = com.google.zxing.ResultPoint;
/// <summary>
/// <p>Attempts to locate multiple barcodes in an image by repeatedly decoding portion of the image.
/// After one barcode is found, the areas left, above, right and below the barcode's
/// <seealso cref="ResultPoint"/>s are scanned, recursively.</p>
///
/// <p>A caller may want to also employ <seealso cref="ByQuadrantReader"/> when attempting to find multiple
/// 2D barcodes, like QR Codes, in an image, where the presence of multiple barcodes might prevent
/// detecting any one of them.</p>
///
/// <p>That is, instead of passing a <seealso cref="Reader"/> a caller might pass
/// {@code new ByQuadrantReader(reader)}.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class GenericMultipleBarcodeReader : MultipleBarcodeReader
{
private const int MIN_DIMENSION_TO_RECUR = 100;
private readonly Reader @delegate;
public GenericMultipleBarcodeReader(Reader @delegate)
{
this.@delegate = @delegate;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result[] decodeMultiple(com.google.zxing.BinaryBitmap image) throws com.google.zxing.NotFoundException
public Result[] decodeMultiple(BinaryBitmap image)
{
return decodeMultiple(image, null);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result[] decodeMultiple(com.google.zxing.BinaryBitmap image, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException
public Result[] decodeMultiple(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
{
List<Result> results = new List<Result>();
doDecodeMultiple(image, hints, results, 0, 0);
if (results.Count == 0)
{
throw NotFoundException.NotFoundInstance;
}
return results.ToArray();
}
private void doDecodeMultiple(BinaryBitmap image, IDictionary<DecodeHintType, object> hints, IList<Result> results, int xOffset, int yOffset)
{
Result result;
try
{
result = @delegate.decode(image, hints);
}
catch (ReaderException re)
{
return;
}
bool alreadyFound = false;
foreach (Result existingResult in results)
{
if (existingResult.Text.Equals(result.Text))
{
alreadyFound = true;
break;
}
}
if (!alreadyFound)
{
results.Add(translateResultPoints(result, xOffset, yOffset));
}
ResultPoint[] resultPoints = result.ResultPoints;
if (resultPoints == null || resultPoints.Length == 0)
{
return;
}
int width = image.Width;
int height = image.Height;
float minX = width;
float minY = height;
float maxX = 0.0f;
float maxY = 0.0f;
foreach (ResultPoint point in resultPoints)
{
float x = point.X;
float y = point.Y;
if (x < minX)
{
minX = x;
}
if (y < minY)
{
minY = y;
}
if (x > maxX)
{
maxX = x;
}
if (y > maxY)
{
maxY = y;
}
}
// Decode left of barcode
if (minX > MIN_DIMENSION_TO_RECUR)
{
doDecodeMultiple(image.crop(0, 0, (int) minX, height), hints, results, xOffset, yOffset);
}
// Decode above barcode
if (minY > MIN_DIMENSION_TO_RECUR)
{
doDecodeMultiple(image.crop(0, 0, width, (int) minY), hints, results, xOffset, yOffset);
}
// Decode right of barcode
if (maxX < width - MIN_DIMENSION_TO_RECUR)
{
doDecodeMultiple(image.crop((int) maxX, 0, width - (int) maxX, height), hints, results, xOffset + (int) maxX, yOffset);
}
// Decode below barcode
if (maxY < height - MIN_DIMENSION_TO_RECUR)
{
doDecodeMultiple(image.crop(0, (int) maxY, width, height - (int) maxY), hints, results, xOffset, yOffset + (int) maxY);
}
}
private static Result translateResultPoints(Result result, int xOffset, int yOffset)
{
ResultPoint[] oldResultPoints = result.ResultPoints;
if (oldResultPoints == null)
{
return result;
}
ResultPoint[] newResultPoints = new ResultPoint[oldResultPoints.Length];
for (int i = 0; i < oldResultPoints.Length; i++)
{
ResultPoint oldPoint = oldResultPoints[i];
newResultPoints[i] = new ResultPoint(oldPoint.X + xOffset, oldPoint.Y + yOffset);
}
return new Result(result.Text, result.RawBytes, newResultPoints, result.BarcodeFormat);
}
}
}

View file

@ -1,46 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.multi
{
using BinaryBitmap = com.google.zxing.BinaryBitmap;
using DecodeHintType = com.google.zxing.DecodeHintType;
using NotFoundException = com.google.zxing.NotFoundException;
using Result = com.google.zxing.Result;
/// <summary>
/// Implementation of this interface attempt to read several barcodes from one image.
/// </summary>
/// <seealso cref= com.google.zxing.Reader
/// @author Sean Owen </seealso>
public interface MultipleBarcodeReader
{
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: com.google.zxing.Result[] decodeMultiple(com.google.zxing.BinaryBitmap image) throws com.google.zxing.NotFoundException;
Result[] decodeMultiple(BinaryBitmap image);
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: com.google.zxing.Result[] decodeMultiple(com.google.zxing.BinaryBitmap image, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException;
Result[] decodeMultiple(BinaryBitmap image, IDictionary<DecodeHintType, object> hints);
}
}

View file

@ -1,97 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.multi.qrcode
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using BinaryBitmap = com.google.zxing.BinaryBitmap;
using DecodeHintType = com.google.zxing.DecodeHintType;
using NotFoundException = com.google.zxing.NotFoundException;
using ReaderException = com.google.zxing.ReaderException;
using Result = com.google.zxing.Result;
using ResultMetadataType = com.google.zxing.ResultMetadataType;
using ResultPoint = com.google.zxing.ResultPoint;
using DecoderResult = com.google.zxing.common.DecoderResult;
using DetectorResult = com.google.zxing.common.DetectorResult;
using MultipleBarcodeReader = com.google.zxing.multi.MultipleBarcodeReader;
using MultiDetector = com.google.zxing.multi.qrcode.detector.MultiDetector;
using QRCodeReader = com.google.zxing.qrcode.QRCodeReader;
/// <summary>
/// This implementation can detect and decode multiple QR Codes in an image.
///
/// @author Sean Owen
/// @author Hannes Erven
/// </summary>
public sealed class QRCodeMultiReader : com.google.zxing.qrcode.QRCodeReader, com.google.zxing.multi.MultipleBarcodeReader
{
private static readonly Result[] EMPTY_RESULT_ARRAY = new Result[0];
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result[] decodeMultiple(com.google.zxing.BinaryBitmap image) throws com.google.zxing.NotFoundException
public Result[] decodeMultiple(BinaryBitmap image)
{
return decodeMultiple(image, null);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result[] decodeMultiple(com.google.zxing.BinaryBitmap image, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException
public Result[] decodeMultiple(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
{
List<Result> results = new List<Result>();
DetectorResult[] detectorResults = (new MultiDetector(image.BlackMatrix)).detectMulti(hints);
foreach (DetectorResult detectorResult in detectorResults)
{
try
{
DecoderResult decoderResult = Decoder.decode(detectorResult.Bits, hints);
ResultPoint[] points = detectorResult.Points;
Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.QR_CODE);
IList<sbyte[]> byteSegments = decoderResult.ByteSegments;
if (byteSegments != null)
{
result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments);
}
string ecLevel = decoderResult.ECLevel;
if (ecLevel != null)
{
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
}
results.Add(result);
}
catch (ReaderException re)
{
// ignore and continue
}
}
if (results.Count == 0)
{
return EMPTY_RESULT_ARRAY;
}
else
{
return results.ToArray();
}
}
}
}

View file

@ -1,92 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.multi.qrcode.detector
{
using DecodeHintType = com.google.zxing.DecodeHintType;
using NotFoundException = com.google.zxing.NotFoundException;
using ReaderException = com.google.zxing.ReaderException;
using ResultPointCallback = com.google.zxing.ResultPointCallback;
using BitMatrix = com.google.zxing.common.BitMatrix;
using DetectorResult = com.google.zxing.common.DetectorResult;
using Detector = com.google.zxing.qrcode.detector.Detector;
using FinderPatternInfo = com.google.zxing.qrcode.detector.FinderPatternInfo;
/// <summary>
/// <p>Encapsulates logic that can detect one or more QR Codes in an image, even if the QR Code
/// is rotated or skewed, or partially obscured.</p>
///
/// @author Sean Owen
/// @author Hannes Erven
/// </summary>
public sealed class MultiDetector : com.google.zxing.qrcode.detector.Detector
{
private static readonly DetectorResult[] EMPTY_DETECTOR_RESULTS = new DetectorResult[0];
public MultiDetector(BitMatrix image) : base(image)
{
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.DetectorResult[] detectMulti(java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException
public DetectorResult[] detectMulti(IDictionary<DecodeHintType, object> hints)
{
BitMatrix image = Image;
//ResultPointCallback resultPointCallback = hints == null ? null : (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK];
ResultPointCallback resultPointCallback = null;
if (hints !=null && hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK))
{
resultPointCallback = (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK];
}
MultiFinderPatternFinder finder = new MultiFinderPatternFinder(image, resultPointCallback);
FinderPatternInfo[] infos = finder.findMulti(hints);
if (infos.Length == 0)
{
throw NotFoundException.NotFoundInstance;
}
List<DetectorResult> result = new List<DetectorResult>();
foreach (FinderPatternInfo info in infos)
{
try
{
result.Add(processFinderPatternInfo(info));
}
catch (ReaderException e)
{
// ignore
}
}
if (result.Count == 0)
{
return EMPTY_DETECTOR_RESULTS;
}
else
{
return result.ToArray();
}
}
}
}

View file

@ -1,351 +0,0 @@
using System;
using System.Collections.Generic;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.multi.qrcode.detector
{
using DecodeHintType = com.google.zxing.DecodeHintType;
using NotFoundException = com.google.zxing.NotFoundException;
using ResultPoint = com.google.zxing.ResultPoint;
using ResultPointCallback = com.google.zxing.ResultPointCallback;
using BitMatrix = com.google.zxing.common.BitMatrix;
using FinderPattern = com.google.zxing.qrcode.detector.FinderPattern;
using FinderPatternFinder = com.google.zxing.qrcode.detector.FinderPatternFinder;
using FinderPatternInfo = com.google.zxing.qrcode.detector.FinderPatternInfo;
/// <summary>
/// <p>This class attempts to find finder patterns in a QR Code. Finder patterns are the square
/// markers at three corners of a QR Code.</p>
///
/// <p>This class is thread-safe but not reentrant. Each thread must allocate its own object.
///
/// <p>In contrast to <seealso cref="FinderPatternFinder"/>, this class will return an array of all possible
/// QR code locations in the image.</p>
///
/// <p>Use the TRY_HARDER hint to ask for a more thorough detection.</p>
///
/// @author Sean Owen
/// @author Hannes Erven
/// </summary>
internal sealed class MultiFinderPatternFinder : com.google.zxing.qrcode.detector.FinderPatternFinder
{
private static readonly FinderPatternInfo[] EMPTY_RESULT_ARRAY = new FinderPatternInfo[0];
// TODO MIN_MODULE_COUNT and MAX_MODULE_COUNT would be great hints to ask the user for
// since it limits the number of regions to decode
// max. legal count of modules per QR code edge (177)
private const float MAX_MODULE_COUNT_PER_EDGE = 180;
// min. legal count per modules per QR code edge (11)
private const float MIN_MODULE_COUNT_PER_EDGE = 9;
/// <summary>
/// More or less arbitrary cutoff point for determining if two finder patterns might belong
/// to the same code if they differ less than DIFF_MODSIZE_CUTOFF_PERCENT percent in their
/// estimated modules sizes.
/// </summary>
private const float DIFF_MODSIZE_CUTOFF_PERCENT = 0.05f;
/// <summary>
/// More or less arbitrary cutoff point for determining if two finder patterns might belong
/// to the same code if they differ less than DIFF_MODSIZE_CUTOFF pixels/module in their
/// estimated modules sizes.
/// </summary>
private const float DIFF_MODSIZE_CUTOFF = 0.5f;
/// <summary>
/// A comparator that orders FinderPatterns by their estimated module size.
/// </summary>
[Serializable]
private sealed class ModuleSizeComparator : IComparer<com.google.zxing.qrcode.detector.FinderPattern>
{
public int Compare(FinderPattern center1, FinderPattern center2)
{
float value = center2.EstimatedModuleSize - center1.EstimatedModuleSize;
return value < 0.0 ? - 1 : value > 0.0 ? 1 : 0;
}
}
/// <summary>
/// <p>Creates a finder that will search the image for three finder patterns.</p>
/// </summary>
/// <param name="image"> image to search </param>
internal MultiFinderPatternFinder(BitMatrix image) : base(image)
{
}
internal MultiFinderPatternFinder(BitMatrix image, ResultPointCallback resultPointCallback) : base(image, resultPointCallback)
{
}
/// <returns> the 3 best <seealso cref="FinderPattern"/>s from our list of candidates. The "best" are
/// those that have been detected at least <seealso cref="#CENTER_QUORUM"/> times, and whose module
/// size differs from the average among those patterns the least </returns>
/// <exception cref="NotFoundException"> if 3 such finder patterns do not exist </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private com.google.zxing.qrcode.detector.FinderPattern[][] selectMutipleBestPatterns() throws com.google.zxing.NotFoundException
private FinderPattern[][] selectMutipleBestPatterns()
{
List<FinderPattern> possibleCenters = PossibleCenters;
int size = possibleCenters.Count;
if (size < 3)
{
// Couldn't find enough finder patterns
throw NotFoundException.NotFoundInstance;
}
/*
* Begin HE modifications to safely detect multiple codes of equal size
*/
if (size == 3)
{
return new FinderPattern[][]{new FinderPattern[]{possibleCenters[0], possibleCenters[1], possibleCenters[2]}};
}
// Sort by estimated module size to speed up the upcoming checks
possibleCenters.Sort(new ModuleSizeComparator());
/*
* Now lets start: build a list of tuples of three finder locations that
* - feature similar module sizes
* - are placed in a distance so the estimated module count is within the QR specification
* - have similar distance between upper left/right and left top/bottom finder patterns
* - form a triangle with 90° angle (checked by comparing top right/bottom left distance
* with pythagoras)
*
* Note: we allow each point to be used for more than one code region: this might seem
* counterintuitive at first, but the performance penalty is not that big. At this point,
* we cannot make a good quality decision whether the three finders actually represent
* a QR code, or are just by chance layouted so it looks like there might be a QR code there.
* So, if the layout seems right, lets have the decoder try to decode.
*/
List<FinderPattern[]> results = new List<FinderPattern[]>(); // holder for the results
for (int i1 = 0; i1 < (size - 2); i1++)
{
FinderPattern p1 = possibleCenters[i1];
if (p1 == null)
{
continue;
}
for (int i2 = i1 + 1; i2 < (size - 1); i2++)
{
FinderPattern p2 = possibleCenters[i2];
if (p2 == null)
{
continue;
}
// Compare the expected module sizes; if they are really off, skip
float vModSize12 = (p1.EstimatedModuleSize - p2.EstimatedModuleSize) / Math.Min(p1.EstimatedModuleSize, p2.EstimatedModuleSize);
float vModSize12A = Math.Abs(p1.EstimatedModuleSize - p2.EstimatedModuleSize);
if (vModSize12A > DIFF_MODSIZE_CUTOFF && vModSize12 >= DIFF_MODSIZE_CUTOFF_PERCENT)
{
// break, since elements are ordered by the module size deviation there cannot be
// any more interesting elements for the given p1.
break;
}
for (int i3 = i2 + 1; i3 < size; i3++)
{
FinderPattern p3 = possibleCenters[i3];
if (p3 == null)
{
continue;
}
// Compare the expected module sizes; if they are really off, skip
float vModSize23 = (p2.EstimatedModuleSize - p3.EstimatedModuleSize) / Math.Min(p2.EstimatedModuleSize, p3.EstimatedModuleSize);
float vModSize23A = Math.Abs(p2.EstimatedModuleSize - p3.EstimatedModuleSize);
if (vModSize23A > DIFF_MODSIZE_CUTOFF && vModSize23 >= DIFF_MODSIZE_CUTOFF_PERCENT)
{
// break, since elements are ordered by the module size deviation there cannot be
// any more interesting elements for the given p1.
break;
}
FinderPattern[] test = {p1, p2, p3};
ResultPoint.orderBestPatterns(test);
// Calculate the distances: a = topleft-bottomleft, b=topleft-topright, c = diagonal
FinderPatternInfo info = new FinderPatternInfo(test);
float dA = ResultPoint.distance(info.TopLeft, info.BottomLeft);
float dC = ResultPoint.distance(info.TopRight, info.BottomLeft);
float dB = ResultPoint.distance(info.TopLeft, info.TopRight);
// Check the sizes
float estimatedModuleCount = (dA + dB) / (p1.EstimatedModuleSize * 2.0f);
if (estimatedModuleCount > MAX_MODULE_COUNT_PER_EDGE || estimatedModuleCount < MIN_MODULE_COUNT_PER_EDGE)
{
continue;
}
// Calculate the difference of the edge lengths in percent
float vABBC = Math.Abs((dA - dB) / Math.Min(dA, dB));
if (vABBC >= 0.1f)
{
continue;
}
// Calculate the diagonal length by assuming a 90° angle at topleft
float dCpy = (float) Math.Sqrt(dA * dA + dB * dB);
// Compare to the real distance in %
float vPyC = Math.Abs((dC - dCpy) / Math.Min(dC, dCpy));
if (vPyC >= 0.1f)
{
continue;
}
// All tests passed!
results.Add(test);
} // end iterate p3
} // end iterate p2
} // end iterate p1
if (results.Count > 0)
{
return results.ToArray();
}
// Nothing found!
throw NotFoundException.NotFoundInstance;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.qrcode.detector.FinderPatternInfo[] findMulti(java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException
public FinderPatternInfo[] findMulti(IDictionary<DecodeHintType, object> hints)
{
bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
BitMatrix image = Image;
int maxI = image.Height;
int maxJ = image.Width;
// We are looking for black/white/black/white/black modules in
// 1:1:3:1:1 ratio; this tracks the number of such modules seen so far
// Let's assume that the maximum version QR Code we support takes up 1/4 the height of the
// image, and then account for the center being 3 modules in size. This gives the smallest
// number of pixels the center could be, so skip this often. When trying harder, look for all
// QR versions regardless of how dense they are.
int iSkip = (int)(maxI / (MAX_MODULES * 4.0f) * 3);
if (iSkip < MIN_SKIP || tryHarder)
{
iSkip = MIN_SKIP;
}
int[] stateCount = new int[5];
for (int i = iSkip - 1; i < maxI; i += iSkip)
{
// Get a row of black/white values
stateCount[0] = 0;
stateCount[1] = 0;
stateCount[2] = 0;
stateCount[3] = 0;
stateCount[4] = 0;
int currentState = 0;
for (int j = 0; j < maxJ; j++)
{
if (image.get(j, i))
{
// Black pixel
if ((currentState & 1) == 1) // Counting white pixels
{
currentState++;
}
stateCount[currentState]++;
} // White pixel
else
{
if ((currentState & 1) == 0) // Counting black pixels
{
if (currentState == 4) // A winner?
{
if (foundPatternCross(stateCount)) // Yes
{
bool confirmed = handlePossibleCenter(stateCount, i, j);
if (!confirmed)
{
do // Advance to next black pixel
{
j++;
} while (j < maxJ && !image.get(j, i));
j--; // back up to that last white pixel
}
// Clear state to start looking again
currentState = 0;
stateCount[0] = 0;
stateCount[1] = 0;
stateCount[2] = 0;
stateCount[3] = 0;
stateCount[4] = 0;
} // No, shift counts back by two
else
{
stateCount[0] = stateCount[2];
stateCount[1] = stateCount[3];
stateCount[2] = stateCount[4];
stateCount[3] = 1;
stateCount[4] = 0;
currentState = 3;
}
}
else
{
stateCount[++currentState]++;
}
} // Counting white pixels
else
{
stateCount[currentState]++;
}
}
} // for j=...
if (foundPatternCross(stateCount))
{
handlePossibleCenter(stateCount, i, maxJ);
} // end if foundPatternCross
} // for i=iSkip-1 ...
FinderPattern[][] patternInfo = selectMutipleBestPatterns();
List<FinderPatternInfo> result = new List<FinderPatternInfo>();
foreach (FinderPattern[] pattern in patternInfo)
{
ResultPoint.orderBestPatterns(pattern);
result.Add(new FinderPatternInfo(pattern));
}
if (result.Count == 0)
{
return EMPTY_RESULT_ARRAY;
}
else
{
return result.ToArray();
}
}
}
}

View file

@ -1,407 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using ChecksumException = com.google.zxing.ChecksumException;
using DecodeHintType = com.google.zxing.DecodeHintType;
using FormatException = com.google.zxing.FormatException;
using NotFoundException = com.google.zxing.NotFoundException;
using Result = com.google.zxing.Result;
using ResultPoint = com.google.zxing.ResultPoint;
using BitArray = com.google.zxing.common.BitArray;
/// <summary>
/// <p>Decodes Code 128 barcodes.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class Code128Reader : OneDReader
{
internal static readonly int[][] CODE_PATTERNS = {new int[] {2, 1, 2, 2, 2, 2}, new int[] {2, 2, 2, 1, 2, 2}, new int[] {2, 2, 2, 2, 2, 1}, new int[] {1, 2, 1, 2, 2, 3}, new int[] {1, 2, 1, 3, 2, 2}, new int[] {1, 3, 1, 2, 2, 2}, new int[] {1, 2, 2, 2, 1, 3}, new int[] {1, 2, 2, 3, 1, 2}, new int[] {1, 3, 2, 2, 1, 2}, new int[] {2, 2, 1, 2, 1, 3}, new int[] {2, 2, 1, 3, 1, 2}, new int[] {2, 3, 1, 2, 1, 2}, new int[] {1, 1, 2, 2, 3, 2}, new int[] {1, 2, 2, 1, 3, 2}, new int[] {1, 2, 2, 2, 3, 1}, new int[] {1, 1, 3, 2, 2, 2}, new int[] {1, 2, 3, 1, 2, 2}, new int[] {1, 2, 3, 2, 2, 1}, new int[] {2, 2, 3, 2, 1, 1}, new int[] {2, 2, 1, 1, 3, 2}, new int[] {2, 2, 1, 2, 3, 1}, new int[] {2, 1, 3, 2, 1, 2}, new int[] {2, 2, 3, 1, 1, 2}, new int[] {3, 1, 2, 1, 3, 1}, new int[] {3, 1, 1, 2, 2, 2}, new int[] {3, 2, 1, 1, 2, 2}, new int[] {3, 2, 1, 2, 2, 1}, new int[] {3, 1, 2, 2, 1, 2}, new int[] {3, 2, 2, 1, 1, 2}, new int[] {3, 2, 2, 2, 1, 1}, new int[] {2, 1, 2, 1, 2, 3}, new int[] {2, 1, 2, 3, 2, 1}, new int[] {2, 3, 2, 1, 2, 1}, new int[] {1, 1, 1, 3, 2, 3}, new int[] {1, 3, 1, 1, 2, 3}, new int[] {1, 3, 1, 3, 2, 1}, new int[] {1, 1, 2, 3, 1, 3}, new int[] {1, 3, 2, 1, 1, 3}, new int[] {1, 3, 2, 3, 1, 1}, new int[] {2, 1, 1, 3, 1, 3}, new int[] {2, 3, 1, 1, 1, 3}, new int[] {2, 3, 1, 3, 1, 1}, new int[] {1, 1, 2, 1, 3, 3}, new int[] {1, 1, 2, 3, 3, 1}, new int[] {1, 3, 2, 1, 3, 1}, new int[] {1, 1, 3, 1, 2, 3}, new int[] {1, 1, 3, 3, 2, 1}, new int[] {1, 3, 3, 1, 2, 1}, new int[] {3, 1, 3, 1, 2, 1}, new int[] {2, 1, 1, 3, 3, 1}, new int[] {2, 3, 1, 1, 3, 1}, new int[] {2, 1, 3, 1, 1, 3}, new int[] {2, 1, 3, 3, 1, 1}, new int[] {2, 1, 3, 1, 3, 1}, new int[] {3, 1, 1, 1, 2, 3}, new int[] {3, 1, 1, 3, 2, 1}, new int[] {3, 3, 1, 1, 2, 1}, new int[] {3, 1, 2, 1, 1, 3}, new int[] {3, 1, 2, 3, 1, 1}, new int[] {3, 3, 2, 1, 1, 1}, new int[] {3, 1, 4, 1, 1, 1}, new int[] {2, 2, 1, 4, 1, 1}, new int[] {4, 3, 1, 1, 1, 1}, new int[] {1, 1, 1, 2, 2, 4}, new int[] {1, 1, 1, 4, 2, 2}, new int[] {1, 2, 1, 1, 2, 4}, new int[] {1, 2, 1, 4, 2, 1}, new int[] {1, 4, 1, 1, 2, 2}, new int[] {1, 4, 1, 2, 2, 1}, new int[] {1, 1, 2, 2, 1, 4}, new int[] {1, 1, 2, 4, 1, 2}, new int[] {1, 2, 2, 1, 1, 4}, new int[] {1, 2, 2, 4, 1, 1}, new int[] {1, 4, 2, 1, 1, 2}, new int[] {1, 4, 2, 2, 1, 1}, new int[] {2, 4, 1, 2, 1, 1}, new int[] {2, 2, 1, 1, 1, 4}, new int[] {4, 1, 3, 1, 1, 1}, new int[] {2, 4, 1, 1, 1, 2}, new int[] {1, 3, 4, 1, 1, 1}, new int[] {1, 1, 1, 2, 4, 2}, new int[] {1, 2, 1, 1, 4, 2}, new int[] {1, 2, 1, 2, 4, 1}, new int[] {1, 1, 4, 2, 1, 2}, new int[] {1, 2, 4, 1, 1, 2}, new int[] {1, 2, 4, 2, 1, 1}, new int[] {4, 1, 1, 2, 1, 2}, new int[] {4, 2, 1, 1, 1, 2}, new int[] {4, 2, 1, 2, 1, 1}, new int[] {2, 1, 2, 1, 4, 1}, new int[] {2, 1, 4, 1, 2, 1}, new int[] {4, 1, 2, 1, 2, 1}, new int[] {1, 1, 1, 1, 4, 3}, new int[] {1, 1, 1, 3, 4, 1}, new int[] {1, 3, 1, 1, 4, 1}, new int[] {1, 1, 4, 1, 1, 3}, new int[] {1, 1, 4, 3, 1, 1}, new int[] {4, 1, 1, 1, 1, 3}, new int[] {4, 1, 1, 3, 1, 1}, new int[] {1, 1, 3, 1, 4, 1}, new int[] {1, 1, 4, 1, 3, 1}, new int[] {3, 1, 1, 1, 4, 1}, new int[] {4, 1, 1, 1, 3, 1}, new int[] {2, 1, 1, 4, 1, 2}, new int[] {2, 1, 1, 2, 1, 4}, new int[] {2, 1, 1, 2, 3, 2}, new int[] {2, 3, 3, 1, 1, 1, 2}};
private static readonly int MAX_AVG_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.25f);
private static readonly int MAX_INDIVIDUAL_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f);
private const int CODE_SHIFT = 98;
private const int CODE_CODE_C = 99;
private const int CODE_CODE_B = 100;
private const int CODE_CODE_A = 101;
private const int CODE_FNC_1 = 102;
private const int CODE_FNC_2 = 97;
private const int CODE_FNC_3 = 96;
private const int CODE_FNC_4_A = 101;
private const int CODE_FNC_4_B = 100;
private const int CODE_START_A = 103;
private const int CODE_START_B = 104;
private const int CODE_START_C = 105;
private const int CODE_STOP = 106;
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int[] findStartPattern(com.google.zxing.common.BitArray row) throws com.google.zxing.NotFoundException
private static int[] findStartPattern(BitArray row)
{
int width = row.Size;
int rowOffset = row.getNextSet(0);
int counterPosition = 0;
int[] counters = new int[6];
int patternStart = rowOffset;
bool isWhite = false;
int patternLength = counters.Length;
for (int i = rowOffset; i < width; i++)
{
if (row.get(i) ^ isWhite)
{
counters[counterPosition]++;
}
else
{
if (counterPosition == patternLength - 1)
{
int bestVariance = MAX_AVG_VARIANCE;
int bestMatch = -1;
for (int startCode = CODE_START_A; startCode <= CODE_START_C; startCode++)
{
int variance = patternMatchVariance(counters, CODE_PATTERNS[startCode], MAX_INDIVIDUAL_VARIANCE);
if (variance < bestVariance)
{
bestVariance = variance;
bestMatch = startCode;
}
}
// Look for whitespace before start pattern, >= 50% of width of start pattern
if (bestMatch >= 0 && row.isRange(Math.Max(0, patternStart - (i - patternStart) / 2), patternStart, false))
{
return new int[]{patternStart, i, bestMatch};
}
patternStart += counters[0] + counters[1];
Array.Copy(counters, 2, counters, 0, patternLength - 2);
counters[patternLength - 2] = 0;
counters[patternLength - 1] = 0;
counterPosition--;
}
else
{
counterPosition++;
}
counters[counterPosition] = 1;
isWhite = !isWhite;
}
}
throw NotFoundException.NotFoundInstance;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int decodeCode(com.google.zxing.common.BitArray row, int[] counters, int rowOffset) throws com.google.zxing.NotFoundException
private static int decodeCode(BitArray row, int[] counters, int rowOffset)
{
recordPattern(row, rowOffset, counters);
int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
int bestMatch = -1;
for (int d = 0; d < CODE_PATTERNS.Length; d++)
{
int[] pattern = CODE_PATTERNS[d];
int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
if (variance < bestVariance)
{
bestVariance = variance;
bestMatch = d;
}
}
// TODO We're overlooking the fact that the STOP pattern has 7 values, not 6.
if (bestMatch >= 0)
{
return bestMatch;
}
else
{
throw NotFoundException.NotFoundInstance;
}
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException, com.google.zxing.ChecksumException
public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints)
{
int[] startPatternInfo = findStartPattern(row);
int startCode = startPatternInfo[2];
int codeSet;
switch (startCode)
{
case CODE_START_A:
codeSet = CODE_CODE_A;
break;
case CODE_START_B:
codeSet = CODE_CODE_B;
break;
case CODE_START_C:
codeSet = CODE_CODE_C;
break;
default:
throw FormatException.FormatInstance;
}
bool done = false;
bool isNextShifted = false;
StringBuilder result = new StringBuilder(20);
IList<sbyte> rawCodes = new List<sbyte>(20);
int lastStart = startPatternInfo[0];
int nextStart = startPatternInfo[1];
int[] counters = new int[6];
int lastCode = 0;
int code = 0;
int checksumTotal = startCode;
int multiplier = 0;
bool lastCharacterWasPrintable = true;
while (!done)
{
bool unshift = isNextShifted;
isNextShifted = false;
// Save off last code
lastCode = code;
// Decode another code from image
code = decodeCode(row, counters, nextStart);
rawCodes.Add((sbyte) code);
// Remember whether the last code was printable or not (excluding CODE_STOP)
if (code != CODE_STOP)
{
lastCharacterWasPrintable = true;
}
// Add to checksum computation (if not CODE_STOP of course)
if (code != CODE_STOP)
{
multiplier++;
checksumTotal += multiplier * code;
}
// Advance to where the next code will to start
lastStart = nextStart;
foreach (int counter in counters)
{
nextStart += counter;
}
// Take care of illegal start codes
switch (code)
{
case CODE_START_A:
case CODE_START_B:
case CODE_START_C:
throw FormatException.FormatInstance;
}
switch (codeSet)
{
case CODE_CODE_A:
if (code < 64)
{
result.Append((char)(' ' + code));
}
else if (code < 96)
{
result.Append((char)(code - 64));
}
else
{
// Don't let CODE_STOP, which always appears, affect whether whether we think the last
// code was printable or not.
if (code != CODE_STOP)
{
lastCharacterWasPrintable = false;
}
switch (code)
{
case CODE_FNC_1:
case CODE_FNC_2:
case CODE_FNC_3:
case CODE_FNC_4_A:
// do nothing?
break;
case CODE_SHIFT:
isNextShifted = true;
codeSet = CODE_CODE_B;
break;
case CODE_CODE_B:
codeSet = CODE_CODE_B;
break;
case CODE_CODE_C:
codeSet = CODE_CODE_C;
break;
case CODE_STOP:
done = true;
break;
}
}
break;
case CODE_CODE_B:
if (code < 96)
{
result.Append((char)(' ' + code));
}
else
{
if (code != CODE_STOP)
{
lastCharacterWasPrintable = false;
}
switch (code)
{
case CODE_FNC_1:
case CODE_FNC_2:
case CODE_FNC_3:
case CODE_FNC_4_B:
// do nothing?
break;
case CODE_SHIFT:
isNextShifted = true;
codeSet = CODE_CODE_A;
break;
case CODE_CODE_A:
codeSet = CODE_CODE_A;
break;
case CODE_CODE_C:
codeSet = CODE_CODE_C;
break;
case CODE_STOP:
done = true;
break;
}
}
break;
case CODE_CODE_C:
if (code < 100)
{
if (code < 10)
{
result.Append('0');
}
result.Append(code);
}
else
{
if (code != CODE_STOP)
{
lastCharacterWasPrintable = false;
}
switch (code)
{
case CODE_FNC_1:
// do nothing?
break;
case CODE_CODE_A:
codeSet = CODE_CODE_A;
break;
case CODE_CODE_B:
codeSet = CODE_CODE_B;
break;
case CODE_STOP:
done = true;
break;
}
}
break;
}
// Unshift back to another code set if we were shifted
if (unshift)
{
codeSet = codeSet == CODE_CODE_A ? CODE_CODE_B : CODE_CODE_A;
}
}
// Check for ample whitespace following pattern, but, to do this we first need to remember that
// we fudged decoding CODE_STOP since it actually has 7 bars, not 6. There is a black bar left
// to read off. Would be slightly better to properly read. Here we just skip it:
nextStart = row.getNextUnset(nextStart);
if (!row.isRange(nextStart, Math.Min(row.Size, nextStart + (nextStart - lastStart) / 2), false))
{
throw NotFoundException.NotFoundInstance;
}
// Pull out from sum the value of the penultimate check code
checksumTotal -= multiplier * lastCode;
// lastCode is the checksum then:
if (checksumTotal % 103 != lastCode)
{
throw ChecksumException.ChecksumInstance;
}
// Need to pull out the check digits from string
int resultLength = result.Length;
if (resultLength == 0)
{
// false positive
throw NotFoundException.NotFoundInstance;
}
// Only bother if the result had at least one character, and if the checksum digit happened to
// be a printable character. If it was just interpreted as a control code, nothing to remove.
if (resultLength > 0 && lastCharacterWasPrintable)
{
if (codeSet == CODE_CODE_C)
{
result.Remove(resultLength - 2, 2);
}
else
{
result.Remove(resultLength - 1, 1);
}
}
float left = (float)(startPatternInfo[1] + startPatternInfo[0]) / 2.0f;
float right = (float)(nextStart + lastStart) / 2.0f;
int rawCodesSize = rawCodes.Count;
sbyte[] rawBytes = new sbyte[rawCodesSize];
for (int i = 0; i < rawCodesSize; i++)
{
rawBytes[i] = rawCodes[i];
}
return new Result(result.ToString(), rawBytes, new ResultPoint[]{new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, BarcodeFormat.CODE_128);
}
}
}

View file

@ -1,379 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using ChecksumException = com.google.zxing.ChecksumException;
using DecodeHintType = com.google.zxing.DecodeHintType;
using FormatException = com.google.zxing.FormatException;
using NotFoundException = com.google.zxing.NotFoundException;
using Result = com.google.zxing.Result;
using ResultPoint = com.google.zxing.ResultPoint;
using BitArray = com.google.zxing.common.BitArray;
using com.google.zxing.common;
/// <summary>
/// <p>Decodes Code 39 barcodes. This does not support "Full ASCII Code 39" yet.</p>
///
/// @author Sean Owen </summary>
/// <seealso cref= Code93Reader </seealso>
public sealed class Code39Reader : OneDReader
{
internal const string ALPHABET_STRING = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%";
private static readonly char[] ALPHABET = ALPHABET_STRING.ToCharArray();
/// <summary>
/// These represent the encodings of characters, as patterns of wide and narrow bars.
/// The 9 least-significant bits of each int correspond to the pattern of wide and narrow,
/// with 1s representing "wide" and 0s representing narrow.
/// </summary>
internal static readonly int[] CHARACTER_ENCODINGS = {0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, 0x0A8, 0x0A2, 0x08A, 0x02A};
private static readonly int ASTERISK_ENCODING = CHARACTER_ENCODINGS[39];
private readonly bool usingCheckDigit;
private readonly bool extendedMode;
private readonly StringBuilder decodeRowResult;
private readonly int[] counters;
/// <summary>
/// Creates a reader that assumes all encoded data is data, and does not treat the final
/// character as a check digit. It will not decoded "extended Code 39" sequences.
/// </summary>
public Code39Reader() : this(false)
{
}
/// <summary>
/// Creates a reader that can be configured to check the last character as a check digit.
/// It will not decoded "extended Code 39" sequences.
/// </summary>
/// <param name="usingCheckDigit"> if true, treat the last data character as a check digit, not
/// data, and verify that the checksum passes. </param>
public Code39Reader(bool usingCheckDigit) : this(usingCheckDigit, false)
{
}
/// <summary>
/// Creates a reader that can be configured to check the last character as a check digit,
/// or optionally attempt to decode "extended Code 39" sequences that are used to encode
/// the full ASCII character set.
/// </summary>
/// <param name="usingCheckDigit"> if true, treat the last data character as a check digit, not
/// data, and verify that the checksum passes. </param>
/// <param name="extendedMode"> if true, will attempt to decode extended Code 39 sequences in the
/// text. </param>
public Code39Reader(bool usingCheckDigit, bool extendedMode)
{
this.usingCheckDigit = usingCheckDigit;
this.extendedMode = extendedMode;
decodeRowResult = new StringBuilder(20);
counters = new int[9];
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.ChecksumException, com.google.zxing.FormatException
public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints)
{
int[] theCounters = counters;
theCounters.Fill(0);
StringBuilder result = decodeRowResult;
result.Length = 0;
int[] start = findAsteriskPattern(row, theCounters);
// Read off white space
int nextStart = row.getNextSet(start[1]);
int end = row.Size;
char decodedChar;
int lastStart;
do
{
recordPattern(row, nextStart, theCounters);
int pattern = toNarrowWidePattern(theCounters);
if (pattern < 0)
{
throw NotFoundException.NotFoundInstance;
}
decodedChar = patternToChar(pattern);
result.Append(decodedChar);
lastStart = nextStart;
foreach (int counter in theCounters)
{
nextStart += counter;
}
// Read off white space
nextStart = row.getNextSet(nextStart);
} while (decodedChar != '*');
result.Length = result.Length - 1; // remove asterisk
// Look for whitespace after pattern:
int lastPatternSize = 0;
foreach (int counter in theCounters)
{
lastPatternSize += counter;
}
int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;
// If 50% of last pattern size, following last pattern, is not whitespace, fail
// (but if it's whitespace to the very end of the image, that's OK)
if (nextStart != end && (whiteSpaceAfterEnd >> 1) < lastPatternSize)
{
throw NotFoundException.NotFoundInstance;
}
if (usingCheckDigit)
{
int max = result.Length - 1;
int total = 0;
for (int i = 0; i < max; i++)
{
total += ALPHABET_STRING.IndexOf(decodeRowResult[i]);
}
if (result[max] != ALPHABET[total % 43])
{
throw ChecksumException.ChecksumInstance;
}
result.Length = max;
}
if (result.Length == 0)
{
// false positive
throw NotFoundException.NotFoundInstance;
}
string resultString;
if (extendedMode)
{
resultString = decodeExtended(result.ToString());
}
else
{
resultString = result.ToString();
}
float left = (float)(start[1] + start[0]) / 2.0f;
float right = (float)(nextStart + lastStart) / 2.0f;
return new Result(resultString, null, new ResultPoint[]{new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, BarcodeFormat.CODE_39);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int[] findAsteriskPattern(com.google.zxing.common.BitArray row, int[] counters) throws com.google.zxing.NotFoundException
private static int[] findAsteriskPattern(BitArray row, int[] counters)
{
int width = row.Size;
int rowOffset = row.getNextSet(0);
int counterPosition = 0;
int patternStart = rowOffset;
bool isWhite = false;
int patternLength = counters.Length;
for (int i = rowOffset; i < width; i++)
{
if (row.get(i) ^ isWhite)
{
counters[counterPosition]++;
}
else
{
if (counterPosition == patternLength - 1)
{
// Look for whitespace before start pattern, >= 50% of width of start pattern
if (toNarrowWidePattern(counters) == ASTERISK_ENCODING && row.isRange(Math.Max(0, patternStart - ((i - patternStart) >> 1)), patternStart, false))
{
return new int[]{patternStart, i};
}
patternStart += counters[0] + counters[1];
Array.Copy(counters, 2, counters, 0, patternLength - 2);
counters[patternLength - 2] = 0;
counters[patternLength - 1] = 0;
counterPosition--;
}
else
{
counterPosition++;
}
counters[counterPosition] = 1;
isWhite = !isWhite;
}
}
throw NotFoundException.NotFoundInstance;
}
// For efficiency, returns -1 on failure. Not throwing here saved as many as 700 exceptions
// per image when using some of our blackbox images.
private static int toNarrowWidePattern(int[] counters)
{
int numCounters = counters.Length;
int maxNarrowCounter = 0;
int wideCounters;
do
{
int minCounter = int.MaxValue;
foreach (int counter in counters)
{
if (counter < minCounter && counter > maxNarrowCounter)
{
minCounter = counter;
}
}
maxNarrowCounter = minCounter;
wideCounters = 0;
int totalWideCountersWidth = 0;
int pattern = 0;
for (int i = 0; i < numCounters; i++)
{
int counter = counters[i];
if (counter > maxNarrowCounter)
{
pattern |= 1 << (numCounters - 1 - i);
wideCounters++;
totalWideCountersWidth += counter;
}
}
if (wideCounters == 3)
{
// Found 3 wide counters, but are they close enough in width?
// We can perform a cheap, conservative check to see if any individual
// counter is more than 1.5 times the average:
for (int i = 0; i < numCounters && wideCounters > 0; i++)
{
int counter = counters[i];
if (counter > maxNarrowCounter)
{
wideCounters--;
// totalWideCountersWidth = 3 * average, so this checks if counter >= 3/2 * average
if ((counter << 1) >= totalWideCountersWidth)
{
return -1;
}
}
}
return pattern;
}
} while (wideCounters > 3);
return -1;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static char patternToChar(int pattern) throws com.google.zxing.NotFoundException
private static char patternToChar(int pattern)
{
for (int i = 0; i < CHARACTER_ENCODINGS.Length; i++)
{
if (CHARACTER_ENCODINGS[i] == pattern)
{
return ALPHABET[i];
}
}
throw NotFoundException.NotFoundInstance;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static String decodeExtended(CharSequence encoded) throws com.google.zxing.FormatException
private static string decodeExtended(string encoded)
{
int length = encoded.Length;
StringBuilder decoded = new StringBuilder(length);
for (int i = 0; i < length; i++)
{
char c = encoded[i];
if (c == '+' || c == '$' || c == '%' || c == '/')
{
char next = encoded[i + 1];
char decodedChar = '\0';
switch (c)
{
case '+':
// +A to +Z map to a to z
if (next >= 'A' && next <= 'Z')
{
decodedChar = (char)(next + 32);
}
else
{
throw FormatException.FormatInstance;
}
break;
case '$':
// $A to $Z map to control codes SH to SB
if (next >= 'A' && next <= 'Z')
{
decodedChar = (char)(next - 64);
}
else
{
throw FormatException.FormatInstance;
}
break;
case '%':
// %A to %E map to control codes ESC to US
if (next >= 'A' && next <= 'E')
{
decodedChar = (char)(next - 38);
}
else if (next >= 'F' && next <= 'W')
{
decodedChar = (char)(next - 11);
}
else
{
throw FormatException.FormatInstance;
}
break;
case '/':
// /A to /O map to ! to , and /Z maps to :
if (next >= 'A' && next <= 'O')
{
decodedChar = (char)(next - 32);
}
else if (next == 'Z')
{
decodedChar = ':';
}
else
{
throw FormatException.FormatInstance;
}
break;
}
decoded.Append(decodedChar);
// bump up i again since we read two characters
i++;
}
else
{
decoded.Append(c);
}
}
return decoded.ToString();
}
}
}

View file

@ -1,94 +0,0 @@
using System.Collections.Generic;
/*
* Copyright 2010 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using EncodeHintType = com.google.zxing.EncodeHintType;
using WriterException = com.google.zxing.WriterException;
using BitMatrix = com.google.zxing.common.BitMatrix;
/// <summary>
/// This object renders a CODE39 code as a <seealso cref="BitMatrix"/>.
///
/// @author erik.barbara@gmail.com (Erik Barbara)
/// </summary>
public sealed class Code39Writer : OneDimensionalCodeWriter
{
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.BitMatrix encode(String contents, com.google.zxing.BarcodeFormat format, int width, int height, java.util.Map<com.google.zxing.EncodeHintType,?> hints) throws com.google.zxing.WriterException
public override BitMatrix encode(string contents, BarcodeFormat format, int width, int height, IDictionary<EncodeHintType,object> hints)
{
if (format != BarcodeFormat.CODE_39)
{
throw new System.ArgumentException("Can only encode CODE_39, but got " + format);
}
return base.encode(contents, format, width, height, hints);
}
public override bool[] encode(string contents)
{
int length = contents.Length;
if (length > 80)
{
throw new System.ArgumentException("Requested contents should be less than 80 digits long, but got " + length);
}
int[] widths = new int[9];
int codeWidth = 24 + 1 + length;
for (int i = 0; i < length; i++)
{
int indexInString = Code39Reader.ALPHABET_STRING.IndexOf(contents[i]);
toIntArray(Code39Reader.CHARACTER_ENCODINGS[indexInString], widths);
foreach (int width in widths)
{
codeWidth += width;
}
}
bool[] result = new bool[codeWidth];
toIntArray(Code39Reader.CHARACTER_ENCODINGS[39], widths);
int pos = appendPattern(result, 0, widths, true);
int[] narrowWhite = {1};
pos += appendPattern(result, pos, narrowWhite, false);
//append next character to bytematrix
for (int i = length - 1; i >= 0; i--)
{
int indexInString = Code39Reader.ALPHABET_STRING.IndexOf(contents[i]);
toIntArray(Code39Reader.CHARACTER_ENCODINGS[indexInString], widths);
pos += appendPattern(result, pos, widths, true);
pos += appendPattern(result, pos, narrowWhite, false);
}
toIntArray(Code39Reader.CHARACTER_ENCODINGS[39], widths);
pos += appendPattern(result, pos, widths, true);
return result;
}
private static void toIntArray(int a, int[] toReturn)
{
for (int i = 0; i < 9; i++)
{
int temp = a & (1 << i);
toReturn[i] = temp == 0 ? 1 : 2;
}
}
}
}

View file

@ -1,155 +0,0 @@
using System.Collections;
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using NotFoundException = com.google.zxing.NotFoundException;
using BitArray = com.google.zxing.common.BitArray;
/// <summary>
/// <p>Implements decoding of the EAN-13 format.</p>
///
/// @author dswitkin@google.com (Daniel Switkin)
/// @author Sean Owen
/// @author alasdair@google.com (Alasdair Mackintosh)
/// </summary>
public sealed class EAN13Reader : UPCEANReader
{
// For an EAN-13 barcode, the first digit is represented by the parities used
// to encode the next six digits, according to the table below. For example,
// if the barcode is 5 123456 789012 then the value of the first digit is
// signified by using odd for '1', even for '2', even for '3', odd for '4',
// odd for '5', and even for '6'. See http://en.wikipedia.org/wiki/EAN-13
//
// Parity of next 6 digits
// Digit 0 1 2 3 4 5
// 0 Odd Odd Odd Odd Odd Odd
// 1 Odd Odd Even Odd Even Even
// 2 Odd Odd Even Even Odd Even
// 3 Odd Odd Even Even Even Odd
// 4 Odd Even Odd Odd Even Even
// 5 Odd Even Even Odd Odd Even
// 6 Odd Even Even Even Odd Odd
// 7 Odd Even Odd Even Odd Even
// 8 Odd Even Odd Even Even Odd
// 9 Odd Even Even Odd Even Odd
//
// Note that the encoding for '0' uses the same parity as a UPC barcode. Hence
// a UPC barcode can be converted to an EAN-13 barcode by prepending a 0.
//
// The encoding is represented by the following array, which is a bit pattern
// using Odd = 0 and Even = 1. For example, 5 is represented by:
//
// Odd Even Even Odd Odd Even
// in binary:
// 0 1 1 0 0 1 == 0x19
//
internal static readonly int[] FIRST_DIGIT_ENCODINGS = {0x00, 0x0B, 0x0D, 0xE, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A};
private readonly int[] decodeMiddleCounters;
public EAN13Reader()
{
decodeMiddleCounters = new int[4];
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected int decodeMiddle(com.google.zxing.common.BitArray row, int[] startRange, StringBuilder resultString) throws com.google.zxing.NotFoundException
protected internal override int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString)
{
int[] counters = decodeMiddleCounters;
counters[0] = 0;
counters[1] = 0;
counters[2] = 0;
counters[3] = 0;
int end = row.Size;
int rowOffset = startRange[1];
int lgPatternFound = 0;
for (int x = 0; x < 6 && rowOffset < end; x++)
{
int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS);
resultString.Append((char)('0' + bestMatch % 10));
foreach (int counter in counters)
{
rowOffset += counter;
}
if (bestMatch >= 10)
{
lgPatternFound |= 1 << (5 - x);
}
}
determineFirstDigit(resultString, lgPatternFound);
int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN);
rowOffset = middleRange[1];
for (int x = 0; x < 6 && rowOffset < end; x++)
{
int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS);
resultString.Append((char)('0' + bestMatch));
foreach (int counter in counters)
{
rowOffset += counter;
}
}
return rowOffset;
}
internal override BarcodeFormat BarcodeFormat
{
get
{
return BarcodeFormat.EAN_13;
}
}
/// <summary>
/// Based on pattern of odd-even ('L' and 'G') patterns used to encoded the explicitly-encoded
/// digits in a barcode, determines the implicitly encoded first digit and adds it to the
/// result string.
/// </summary>
/// <param name="resultString"> string to insert decoded first digit into </param>
/// <param name="lgPatternFound"> int whose bits indicates the pattern of odd/even L/G patterns used to
/// encode digits </param>
/// <exception cref="NotFoundException"> if first digit cannot be determined </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static void determineFirstDigit(StringBuilder resultString, int lgPatternFound) throws com.google.zxing.NotFoundException
private static void determineFirstDigit(StringBuilder resultString, int lgPatternFound)
{
for (int d = 0; d < 10; d++)
{
if (lgPatternFound == FIRST_DIGIT_ENCODINGS[d])
{
resultString.Insert(0, (char)('0' + d));
return;
}
}
throw NotFoundException.NotFoundInstance;
}
}
}

View file

@ -1,102 +0,0 @@
using System;
using System.Collections.Generic;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using EncodeHintType = com.google.zxing.EncodeHintType;
using FormatException = com.google.zxing.FormatException;
using WriterException = com.google.zxing.WriterException;
using BitMatrix = com.google.zxing.common.BitMatrix;
/// <summary>
/// This object renders an EAN13 code as a <seealso cref="BitMatrix"/>.
///
/// @author aripollak@gmail.com (Ari Pollak)
/// </summary>
public sealed class EAN13Writer : UPCEANWriter
{
private const int CODE_WIDTH = 3 + (7 * 6) + 5 + (7 * 6) + 3; // end guard - right bars - middle guard - left bars - start guard
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.BitMatrix encode(String contents, com.google.zxing.BarcodeFormat format, int width, int height, java.util.Map<com.google.zxing.EncodeHintType,?> hints) throws com.google.zxing.WriterException
public override BitMatrix encode(string contents, BarcodeFormat format, int width, int height, IDictionary<EncodeHintType, object> hints)
{
if (format != BarcodeFormat.EAN_13)
{
throw new System.ArgumentException("Can only encode EAN_13, but got " + format);
}
return base.encode(contents, format, width, height, hints);
}
public override bool[] encode(string contents)
{
if (contents.Length != 13)
{
throw new System.ArgumentException("Requested contents should be 13 digits long, but got " + contents.Length);
}
try
{
if (!UPCEANReader.checkStandardUPCEANChecksum(contents))
{
throw new System.ArgumentException("Contents do not pass checksum");
}
}
catch (FormatException fe)
{
throw new System.ArgumentException("Illegal contents");
}
int firstDigit = Convert.ToInt32(contents.Substring(0, 1));
int parities = EAN13Reader.FIRST_DIGIT_ENCODINGS[firstDigit];
bool[] result = new bool[CODE_WIDTH];
int pos = 0;
pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true);
// See {@link #EAN13Reader} for a description of how the first digit & left bars are encoded
for (int i = 1; i <= 6; i++)
{
int digit = Convert.ToInt32(contents.Substring(i, 1));
if ((parities >> (6 - i) & 1) == 1)
{
digit += 10;
}
pos += appendPattern(result, pos, UPCEANReader.L_AND_G_PATTERNS[digit], false);
}
pos += appendPattern(result, pos, UPCEANReader.MIDDLE_PATTERN, false);
for (int i = 7; i <= 12; i++)
{
int digit = Convert.ToInt32(contents.Substring(i, 1));
pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], true);
}
pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true);
return result;
}
}
}

View file

@ -1,90 +0,0 @@
using System.Collections;
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using NotFoundException = com.google.zxing.NotFoundException;
using BitArray = com.google.zxing.common.BitArray;
/// <summary>
/// <p>Implements decoding of the EAN-8 format.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class EAN8Reader : UPCEANReader
{
private readonly int[] decodeMiddleCounters;
public EAN8Reader()
{
decodeMiddleCounters = new int[4];
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected int decodeMiddle(com.google.zxing.common.BitArray row, int[] startRange, StringBuilder result) throws com.google.zxing.NotFoundException
protected internal override int decodeMiddle(BitArray row, int[] startRange, StringBuilder result)
{
int[] counters = decodeMiddleCounters;
counters[0] = 0;
counters[1] = 0;
counters[2] = 0;
counters[3] = 0;
int end = row.Size;
int rowOffset = startRange[1];
for (int x = 0; x < 4 && rowOffset < end; x++)
{
int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS);
result.Append((char)('0' + bestMatch));
foreach (int counter in counters)
{
rowOffset += counter;
}
}
int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN);
rowOffset = middleRange[1];
for (int x = 0; x < 4 && rowOffset < end; x++)
{
int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS);
result.Append((char)('0' + bestMatch));
foreach (int counter in counters)
{
rowOffset += counter;
}
}
return rowOffset;
}
internal override BarcodeFormat BarcodeFormat
{
get
{
return BarcodeFormat.EAN_8;
}
}
}
}

View file

@ -1,84 +0,0 @@
using System;
using System.Collections.Generic;
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using EncodeHintType = com.google.zxing.EncodeHintType;
using WriterException = com.google.zxing.WriterException;
using BitMatrix = com.google.zxing.common.BitMatrix;
/// <summary>
/// This object renders an EAN8 code as a <seealso cref="BitMatrix"/>.
///
/// @author aripollak@gmail.com (Ari Pollak)
/// </summary>
public sealed class EAN8Writer : UPCEANWriter
{
private const int CODE_WIDTH = 3 + (7 * 4) + 5 + (7 * 4) + 3; // end guard - right bars - middle guard - left bars - start guard
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.common.BitMatrix encode(String contents, com.google.zxing.BarcodeFormat format, int width, int height, java.util.Map<com.google.zxing.EncodeHintType,?> hints) throws com.google.zxing.WriterException
public override BitMatrix encode(string contents, BarcodeFormat format, int width, int height, IDictionary<EncodeHintType, object> hints)
{
if (format != BarcodeFormat.EAN_8)
{
throw new System.ArgumentException("Can only encode EAN_8, but got " + format);
}
return base.encode(contents, format, width, height, hints);
}
/// <returns> a byte array of horizontal pixels (false = white, true = black) </returns>
public override bool[] encode(string contents)
{
if (contents.Length != 8)
{
throw new System.ArgumentException("Requested contents should be 8 digits long, but got " + contents.Length);
}
bool[] result = new bool[CODE_WIDTH];
int pos = 0;
pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true);
for (int i = 0; i <= 3; i++)
{
int digit = Convert.ToInt32(contents.Substring(i, 1));
pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], false);
}
pos += appendPattern(result, pos, UPCEANReader.MIDDLE_PATTERN, false);
for (int i = 4; i <= 7; i++)
{
int digit = Convert.ToInt32(contents.Substring(i, 1));
pos += appendPattern(result, pos, UPCEANReader.L_PATTERNS[digit], true);
}
pos += appendPattern(result, pos, UPCEANReader.START_END_PATTERN, true);
return result;
}
}
}

View file

@ -1,375 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using DecodeHintType = com.google.zxing.DecodeHintType;
using FormatException = com.google.zxing.FormatException;
using NotFoundException = com.google.zxing.NotFoundException;
using Result = com.google.zxing.Result;
using ResultPoint = com.google.zxing.ResultPoint;
using BitArray = com.google.zxing.common.BitArray;
/// <summary>
/// <p>Implements decoding of the ITF format, or Interleaved Two of Five.</p>
///
/// <p>This Reader will scan ITF barcodes of certain lengths only.
/// At the moment it reads length 6, 10, 12, 14, 16, 24, and 44 as these have appeared "in the wild". Not all
/// lengths are scanned, especially shorter ones, to avoid false positives. This in turn is due to a lack of
/// required checksum function.</p>
///
/// <p>The checksum is optional and is not applied by this Reader. The consumer of the decoded
/// value will have to apply a checksum if required.</p>
///
/// <p><a href="http://en.wikipedia.org/wiki/Interleaved_2_of_5">http://en.wikipedia.org/wiki/Interleaved_2_of_5</a>
/// is a great reference for Interleaved 2 of 5 information.</p>
///
/// @author kevin.osullivan@sita.aero, SITA Lab.
/// </summary>
public sealed class ITFReader : OneDReader
{
private static readonly int MAX_AVG_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f);
private static readonly int MAX_INDIVIDUAL_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.8f);
private const int W = 3; // Pixel width of a wide line
private const int N = 1; // Pixed width of a narrow line
private static readonly int[] DEFAULT_ALLOWED_LENGTHS = {44, 24, 20, 18, 16, 14, 12, 10, 8, 6};
// Stores the actual narrow line width of the image being decoded.
private int narrowLineWidth = -1;
/// <summary>
/// Start/end guard pattern.
///
/// Note: The end pattern is reversed because the row is reversed before
/// searching for the END_PATTERN
/// </summary>
private static readonly int[] START_PATTERN = {N, N, N, N};
private static readonly int[] END_PATTERN_REVERSED = {N, N, W};
/// <summary>
/// Patterns of Wide / Narrow lines to indicate each digit
/// </summary>
internal static readonly int[][] PATTERNS = {new int[] {N, N, W, W, N}, new int[] {W, N, N, N, W}, new int[] {N, W, N, N, W}, new int[] {W, W, N, N, N}, new int[] {N, N, W, N, W}, new int[] {W, N, W, N, N}, new int[] {N, W, W, N, N}, new int[] {N, N, N, W, W}, new int[] {W, N, N, W, N}, new int[] {N, W, N, W, N}};
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.FormatException, com.google.zxing.NotFoundException
public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints)
{
// Find out where the Middle section (payload) starts & ends
int[] startRange = decodeStart(row);
int[] endRange = decodeEnd(row);
StringBuilder result = new StringBuilder(20);
decodeMiddle(row, startRange[1], endRange[0], result);
string resultString = result.ToString();
int[] allowedLengths = null;
if (hints != null && hints.ContainsKey(DecodeHintType.ALLOWED_LENGTHS))
{
allowedLengths = (int[]) hints[DecodeHintType.ALLOWED_LENGTHS];
}
if (allowedLengths == null)
{
allowedLengths = DEFAULT_ALLOWED_LENGTHS;
}
// To avoid false positives with 2D barcodes (and other patterns), make
// an assumption that the decoded string must be 6, 10 or 14 digits.
int length = resultString.Length;
bool lengthOK = false;
foreach (int allowedLength in allowedLengths)
{
if (length == allowedLength)
{
lengthOK = true;
break;
}
}
if (!lengthOK)
{
throw FormatException.FormatInstance;
}
return new Result(resultString, null, new ResultPoint[] {new ResultPoint(startRange[1], (float) rowNumber), new ResultPoint(endRange[0], (float) rowNumber)}, BarcodeFormat.ITF); // no natural byte representation for these barcodes
}
/// <param name="row"> row of black/white values to search </param>
/// <param name="payloadStart"> offset of start pattern </param>
/// <param name="resultString"> <seealso cref="StringBuilder"/> to append decoded chars to </param>
/// <exception cref="NotFoundException"> if decoding could not complete successfully </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static void decodeMiddle(com.google.zxing.common.BitArray row, int payloadStart, int payloadEnd, StringBuilder resultString) throws com.google.zxing.NotFoundException
private static void decodeMiddle(BitArray row, int payloadStart, int payloadEnd, StringBuilder resultString)
{
// Digits are interleaved in pairs - 5 black lines for one digit, and the
// 5
// interleaved white lines for the second digit.
// Therefore, need to scan 10 lines and then
// split these into two arrays
int[] counterDigitPair = new int[10];
int[] counterBlack = new int[5];
int[] counterWhite = new int[5];
while (payloadStart < payloadEnd)
{
// Get 10 runs of black/white.
recordPattern(row, payloadStart, counterDigitPair);
// Split them into each array
for (int k = 0; k < 5; k++)
{
int twoK = k << 1;
counterBlack[k] = counterDigitPair[twoK];
counterWhite[k] = counterDigitPair[twoK + 1];
}
int bestMatch = decodeDigit(counterBlack);
resultString.Append((char)('0' + bestMatch));
bestMatch = decodeDigit(counterWhite);
resultString.Append((char)('0' + bestMatch));
foreach (int counterDigit in counterDigitPair)
{
payloadStart += counterDigit;
}
}
}
/// <summary>
/// Identify where the start of the middle / payload section starts.
/// </summary>
/// <param name="row"> row of black/white values to search </param>
/// <returns> Array, containing index of start of 'start block' and end of
/// 'start block' </returns>
/// <exception cref="NotFoundException"> </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: int[] decodeStart(com.google.zxing.common.BitArray row) throws com.google.zxing.NotFoundException
internal int[] decodeStart(BitArray row)
{
int endStart = skipWhiteSpace(row);
int[] startPattern = findGuardPattern(row, endStart, START_PATTERN);
// Determine the width of a narrow line in pixels. We can do this by
// getting the width of the start pattern and dividing by 4 because its
// made up of 4 narrow lines.
this.narrowLineWidth = (startPattern[1] - startPattern[0]) >> 2;
validateQuietZone(row, startPattern[0]);
return startPattern;
}
/// <summary>
/// The start & end patterns must be pre/post fixed by a quiet zone. This
/// zone must be at least 10 times the width of a narrow line. Scan back until
/// we either get to the start of the barcode or match the necessary number of
/// quiet zone pixels.
///
/// Note: Its assumed the row is reversed when using this method to find
/// quiet zone after the end pattern.
///
/// ref: http://www.barcode-1.net/i25code.html
/// </summary>
/// <param name="row"> bit array representing the scanned barcode. </param>
/// <param name="startPattern"> index into row of the start or end pattern. </param>
/// <exception cref="NotFoundException"> if the quiet zone cannot be found, a ReaderException is thrown. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private void validateQuietZone(com.google.zxing.common.BitArray row, int startPattern) throws com.google.zxing.NotFoundException
private void validateQuietZone(BitArray row, int startPattern)
{
int quietCount = this.narrowLineWidth * 10; // expect to find this many pixels of quiet zone
for (int i = startPattern - 1; quietCount > 0 && i >= 0; i--)
{
if (row.get(i))
{
break;
}
quietCount--;
}
if (quietCount != 0)
{
// Unable to find the necessary number of quiet zone pixels.
throw NotFoundException.NotFoundInstance;
}
}
/// <summary>
/// Skip all whitespace until we get to the first black line.
/// </summary>
/// <param name="row"> row of black/white values to search </param>
/// <returns> index of the first black line. </returns>
/// <exception cref="NotFoundException"> Throws exception if no black lines are found in the row </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int skipWhiteSpace(com.google.zxing.common.BitArray row) throws com.google.zxing.NotFoundException
private static int skipWhiteSpace(BitArray row)
{
int width = row.Size;
int endStart = row.getNextSet(0);
if (endStart == width)
{
throw NotFoundException.NotFoundInstance;
}
return endStart;
}
/// <summary>
/// Identify where the end of the middle / payload section ends.
/// </summary>
/// <param name="row"> row of black/white values to search </param>
/// <returns> Array, containing index of start of 'end block' and end of 'end
/// block' </returns>
/// <exception cref="NotFoundException"> </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: int[] decodeEnd(com.google.zxing.common.BitArray row) throws com.google.zxing.NotFoundException
internal int[] decodeEnd(BitArray row)
{
// For convenience, reverse the row and then
// search from 'the start' for the end block
row.reverse();
try
{
int endStart = skipWhiteSpace(row);
int[] endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED);
// The start & end patterns must be pre/post fixed by a quiet zone. This
// zone must be at least 10 times the width of a narrow line.
// ref: http://www.barcode-1.net/i25code.html
validateQuietZone(row, endPattern[0]);
// Now recalculate the indices of where the 'endblock' starts & stops to
// accommodate
// the reversed nature of the search
int temp = endPattern[0];
endPattern[0] = row.Size - endPattern[1];
endPattern[1] = row.Size - temp;
return endPattern;
}
finally
{
// Put the row back the right way.
row.reverse();
}
}
/// <param name="row"> row of black/white values to search </param>
/// <param name="rowOffset"> position to start search </param>
/// <param name="pattern"> pattern of counts of number of black and white pixels that are
/// being searched for as a pattern </param>
/// <returns> start/end horizontal offset of guard pattern, as an array of two
/// ints </returns>
/// <exception cref="NotFoundException"> if pattern is not found </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int[] findGuardPattern(com.google.zxing.common.BitArray row, int rowOffset, int[] pattern) throws com.google.zxing.NotFoundException
private static int[] findGuardPattern(BitArray row, int rowOffset, int[] pattern)
{
// TODO: This is very similar to implementation in UPCEANReader. Consider if they can be
// merged to a single method.
int patternLength = pattern.Length;
int[] counters = new int[patternLength];
int width = row.Size;
bool isWhite = false;
int counterPosition = 0;
int patternStart = rowOffset;
for (int x = rowOffset; x < width; x++)
{
if (row.get(x) ^ isWhite)
{
counters[counterPosition]++;
}
else
{
if (counterPosition == patternLength - 1)
{
if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE)
{
return new int[]{patternStart, x};
}
patternStart += counters[0] + counters[1];
Array.Copy(counters, 2, counters, 0, patternLength - 2);
counters[patternLength - 2] = 0;
counters[patternLength - 1] = 0;
counterPosition--;
}
else
{
counterPosition++;
}
counters[counterPosition] = 1;
isWhite = !isWhite;
}
}
throw NotFoundException.NotFoundInstance;
}
/// <summary>
/// Attempts to decode a sequence of ITF black/white lines into single
/// digit.
/// </summary>
/// <param name="counters"> the counts of runs of observed black/white/black/... values </param>
/// <returns> The decoded digit </returns>
/// <exception cref="NotFoundException"> if digit cannot be decoded </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int decodeDigit(int[] counters) throws com.google.zxing.NotFoundException
private static int decodeDigit(int[] counters)
{
int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
int bestMatch = -1;
int max = PATTERNS.Length;
for (int i = 0; i < max; i++)
{
int[] pattern = PATTERNS[i];
int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
if (variance < bestVariance)
{
bestVariance = variance;
bestMatch = i;
}
}
if (bestMatch >= 0)
{
return bestMatch;
}
else
{
throw NotFoundException.NotFoundInstance;
}
}
}
}

View file

@ -1,133 +0,0 @@
using System.Collections;
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using DecodeHintType = com.google.zxing.DecodeHintType;
using NotFoundException = com.google.zxing.NotFoundException;
using Reader = com.google.zxing.Reader;
using ReaderException = com.google.zxing.ReaderException;
using Result = com.google.zxing.Result;
using BitArray = com.google.zxing.common.BitArray;
using RSS14Reader = com.google.zxing.oned.rss.RSS14Reader;
using RSSExpandedReader = com.google.zxing.oned.rss.expanded.RSSExpandedReader;
/// <summary>
/// @author dswitkin@google.com (Daniel Switkin)
/// @author Sean Owen
/// </summary>
public sealed class MultiFormatOneDReader : OneDReader
{
private readonly OneDReader[] readers;
public MultiFormatOneDReader(IDictionary<DecodeHintType, object> hints)
{
//ICollection<BarcodeFormat> possibleFormats = hints == null ? null : (ICollection<BarcodeFormat>) hints[DecodeHintType.POSSIBLE_FORMATS];
ICollection<BarcodeFormat> possibleFormats = null;
if (hints !=null && hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS))
{
possibleFormats = (ICollection<BarcodeFormat>)hints[DecodeHintType.POSSIBLE_FORMATS];
}
//bool useCode39CheckDigit = hints != null && hints[DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT] != null;
bool useCode39CheckDigit = hints != null && hints.ContainsKey(DecodeHintType.ASSUME_CODE_39_CHECK_DIGIT);
List<OneDReader> readers = new List<OneDReader>();
if (possibleFormats != null)
{
if (possibleFormats.Contains(BarcodeFormat.EAN_13) || possibleFormats.Contains(BarcodeFormat.UPC_A) || possibleFormats.Contains(BarcodeFormat.EAN_8) || possibleFormats.Contains(BarcodeFormat.UPC_E))
{
readers.Add(new MultiFormatUPCEANReader(hints));
}
if (possibleFormats.Contains(BarcodeFormat.CODE_39))
{
readers.Add(new Code39Reader(useCode39CheckDigit));
}
if (possibleFormats.Contains(BarcodeFormat.CODE_93))
{
readers.Add(new Code93Reader());
}
if (possibleFormats.Contains(BarcodeFormat.CODE_128))
{
readers.Add(new Code128Reader());
}
if (possibleFormats.Contains(BarcodeFormat.ITF))
{
readers.Add(new ITFReader());
}
if (possibleFormats.Contains(BarcodeFormat.CODABAR))
{
readers.Add(new CodaBarReader());
}
if (possibleFormats.Contains(BarcodeFormat.RSS_14))
{
readers.Add(new RSS14Reader());
}
if (possibleFormats.Contains(BarcodeFormat.RSS_EXPANDED))
{
readers.Add(new RSSExpandedReader());
}
}
if (readers.Count == 0)
{
readers.Add(new MultiFormatUPCEANReader(hints));
readers.Add(new Code39Reader());
readers.Add(new CodaBarReader());
readers.Add(new Code93Reader());
readers.Add(new Code128Reader());
readers.Add(new ITFReader());
readers.Add(new RSS14Reader());
readers.Add(new RSSExpandedReader());
}
this.readers = readers.ToArray(/*new OneDReader[readers.Count]*/);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException
public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints)
{
foreach (OneDReader reader in readers)
{
try
{
return reader.decodeRow(rowNumber, row, hints);
}
catch (ReaderException re)
{
// continue
}
}
throw NotFoundException.NotFoundInstance;
}
public override void reset()
{
foreach (Reader reader in readers)
{
reader.reset();
}
}
}
}

View file

@ -1,144 +0,0 @@
using System.Collections;
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using DecodeHintType = com.google.zxing.DecodeHintType;
using NotFoundException = com.google.zxing.NotFoundException;
using Reader = com.google.zxing.Reader;
using ReaderException = com.google.zxing.ReaderException;
using Result = com.google.zxing.Result;
using BitArray = com.google.zxing.common.BitArray;
/// <summary>
/// <p>A reader that can read all available UPC/EAN formats. If a caller wants to try to
/// read all such formats, it is most efficient to use this implementation rather than invoke
/// individual readers.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class MultiFormatUPCEANReader : OneDReader
{
private readonly UPCEANReader[] readers;
public MultiFormatUPCEANReader(IDictionary<DecodeHintType, object> hints)
{
//ICollection<BarcodeFormat> possibleFormats = hints == null ? null : (ICollection<BarcodeFormat>) hints[DecodeHintType.POSSIBLE_FORMATS];
ICollection<BarcodeFormat> possibleFormats = null;
if (hints != null && hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS))
{
possibleFormats = (ICollection<BarcodeFormat>)hints[DecodeHintType.POSSIBLE_FORMATS];
}
List<UPCEANReader> readers = new List<UPCEANReader>();
if (possibleFormats != null)
{
if (possibleFormats.Contains(BarcodeFormat.EAN_13))
{
readers.Add(new EAN13Reader());
}
else if (possibleFormats.Contains(BarcodeFormat.UPC_A))
{
readers.Add(new UPCAReader());
}
if (possibleFormats.Contains(BarcodeFormat.EAN_8))
{
readers.Add(new EAN8Reader());
}
if (possibleFormats.Contains(BarcodeFormat.UPC_E))
{
readers.Add(new UPCEReader());
}
}
if (readers.Count == 0)
{
readers.Add(new EAN13Reader());
// UPC-A is covered by EAN-13
readers.Add(new EAN8Reader());
readers.Add(new UPCEReader());
}
this.readers = readers.ToArray(/*new UPCEANReader[readers.Count]*/);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException
public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints)
{
// Compute this location once and reuse it on multiple implementations
int[] startGuardPattern = UPCEANReader.findStartGuardPattern(row);
foreach (UPCEANReader reader in readers)
{
Result result;
try
{
result = reader.decodeRow(rowNumber, row, startGuardPattern, hints);
}
catch (ReaderException re)
{
continue;
}
// Special case: a 12-digit code encoded in UPC-A is identical to a "0"
// followed by those 12 digits encoded as EAN-13. Each will recognize such a code,
// UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0".
// Individually these are correct and their readers will both read such a code
// and correctly call it EAN-13, or UPC-A, respectively.
//
// In this case, if we've been looking for both types, we'd like to call it
// a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read
// UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A
// result if appropriate.
//
// But, don't return UPC-A if UPC-A was not a requested format!
bool ean13MayBeUPCA = result.BarcodeFormat == BarcodeFormat.EAN_13 && result.Text[0] == '0';
//ICollection<BarcodeFormat> possibleFormats = hints == null ? null : (ICollection<BarcodeFormat>) hints[DecodeHintType.POSSIBLE_FORMATS];
ICollection<BarcodeFormat> possibleFormats = null;
if (hints != null && hints.ContainsKey(DecodeHintType.POSSIBLE_FORMATS))
{
possibleFormats = (ICollection<BarcodeFormat>)hints[DecodeHintType.POSSIBLE_FORMATS];
}
bool canReturnUPCA = possibleFormats == null || possibleFormats.Contains(BarcodeFormat.UPC_A);
if (ean13MayBeUPCA && canReturnUPCA)
{
// Transfer the metdata across
Result resultUPCA = new Result(result.Text.Substring(1), result.RawBytes, result.ResultPoints, BarcodeFormat.UPC_A);
resultUPCA.putAllMetadata(result.ResultMetadata);
return resultUPCA;
}
return result;
}
throw NotFoundException.NotFoundInstance;
}
public override void reset()
{
foreach (Reader reader in readers)
{
reader.reset();
}
}
}
}

View file

@ -1,368 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BinaryBitmap = com.google.zxing.BinaryBitmap;
using ChecksumException = com.google.zxing.ChecksumException;
using DecodeHintType = com.google.zxing.DecodeHintType;
using FormatException = com.google.zxing.FormatException;
using NotFoundException = com.google.zxing.NotFoundException;
using Reader = com.google.zxing.Reader;
using ReaderException = com.google.zxing.ReaderException;
using Result = com.google.zxing.Result;
using ResultMetadataType = com.google.zxing.ResultMetadataType;
using ResultPoint = com.google.zxing.ResultPoint;
using BitArray = com.google.zxing.common.BitArray;
/// <summary>
/// Encapsulates functionality and implementation that is common to all families
/// of one-dimensional barcodes.
///
/// @author dswitkin@google.com (Daniel Switkin)
/// @author Sean Owen
/// </summary>
public abstract class OneDReader : com.google.zxing.Reader
{
protected internal const int INTEGER_MATH_SHIFT = 8;
protected internal static readonly int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT;
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decode(com.google.zxing.BinaryBitmap image) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException
public virtual Result decode(BinaryBitmap image)
{
return decode(image, null);
}
// Note that we don't try rotation without the try harder flag, even if rotation was supported.
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decode(com.google.zxing.BinaryBitmap image, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException
public virtual Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
{
try
{
return doDecode(image, hints);
}
catch (NotFoundException nfe)
{
bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
if (tryHarder && image.RotateSupported)
{
BinaryBitmap rotatedImage = image.rotateCounterClockwise();
Result result = doDecode(rotatedImage, hints);
// Record that we found it rotated 90 degrees CCW / 270 degrees CW
//JAVA TO C# CONVERTER TODO TASK: Java wildcard generics are not converted to .NET:
//ORIGINAL LINE: java.util.Map<com.google.zxing.ResultMetadataType,?> metadata = result.getResultMetadata();
IDictionary<ResultMetadataType, object> metadata = result.ResultMetadata;
int orientation = 270;
if (metadata != null && metadata.ContainsKey(ResultMetadataType.ORIENTATION))
{
// But if we found it reversed in doDecode(), add in that result here:
orientation = (orientation + (int) metadata[ResultMetadataType.ORIENTATION]) % 360;
}
result.putMetadata(ResultMetadataType.ORIENTATION, orientation);
// Update result points
ResultPoint[] points = result.ResultPoints;
if (points != null)
{
int height = rotatedImage.Height;
for (int i = 0; i < points.Length; i++)
{
points[i] = new ResultPoint(height - points[i].Y - 1, points[i].X);
}
}
return result;
}
else
{
throw nfe;
}
}
}
public virtual void reset()
{
// do nothing
}
/// <summary>
/// We're going to examine rows from the middle outward, searching alternately above and below the
/// middle, and farther out each time. rowStep is the number of rows between each successive
/// attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then
/// middle + rowStep, then middle - (2 * rowStep), etc.
/// rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily
/// decided that moving up and down by about 1/16 of the image is pretty good; we try more of the
/// image if "trying harder".
/// </summary>
/// <param name="image"> The image to decode </param>
/// <param name="hints"> Any hints that were requested </param>
/// <returns> The contents of the decoded barcode </returns>
/// <exception cref="NotFoundException"> Any spontaneous errors which occur </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private com.google.zxing.Result doDecode(com.google.zxing.BinaryBitmap image, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException
private Result doDecode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
{
int width = image.Width;
int height = image.Height;
BitArray row = new BitArray(width);
int middle = height >> 1;
bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
int rowStep = Math.Max(1, height >> (tryHarder ? 8 : 5));
int maxLines;
if (tryHarder)
{
maxLines = height; // Look at the whole image, not just the center
}
else
{
maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image
}
for (int x = 0; x < maxLines; x++)
{
// Scanning from the middle out. Determine which row we're looking at next:
int rowStepsAboveOrBelow = (x + 1) >> 1;
bool isAbove = (x & 0x01) == 0; // i.e. is x even?
int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
if (rowNumber < 0 || rowNumber >= height)
{
// Oops, if we run off the top or bottom, stop
break;
}
// Estimate black point for this row and load it:
try
{
row = image.getBlackRow(rowNumber, row);
}
catch (NotFoundException nfe)
{
continue;
}
// While we have the image data in a BitArray, it's fairly cheap to reverse it in place to
// handle decoding upside down barcodes.
for (int attempt = 0; attempt < 2; attempt++)
{
if (attempt == 1) // trying again?
{
row.reverse(); // reverse the row and continue
// This means we will only ever draw result points *once* in the life of this method
// since we want to avoid drawing the wrong points after flipping the row, and,
// don't want to clutter with noise from every single row scan -- just the scans
// that start on the center line.
if (hints != null && hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK))
{
//IDictionary<DecodeHintType, object> newHints = new EnumMap<DecodeHintType, object>(typeof(DecodeHintType));
Dictionary<DecodeHintType,object> newHints = new Dictionary<DecodeHintType,object>();
//JAVA TO C# CONVERTER TODO TASK: There is no .NET Dictionary equivalent to the Java 'putAll' method:
//newHints.putAll(hints);
//foreach (DecodeHintType dht in Enum.GetValues(typeof(DecodeHintType)))
//{
// newHints.Add(dht,dht);
//}
foreach (KeyValuePair<DecodeHintType,object> kvp in hints)
{
newHints.Add(kvp.Key,kvp.Value);
}
if (newHints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK))
{
newHints.Remove(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
}
hints = newHints;
}
}
try
{
// Look for a barcode
Result result = decodeRow(rowNumber, row, hints);
// We found our barcode
if (attempt == 1)
{
// But it was upside down, so note that
result.putMetadata(ResultMetadataType.ORIENTATION, 180);
// And remember to flip the result points horizontally.
ResultPoint[] points = result.ResultPoints;
if (points != null)
{
points[0] = new ResultPoint(width - points[0].X - 1, points[0].Y);
points[1] = new ResultPoint(width - points[1].X - 1, points[1].Y);
}
}
return result;
}
catch (ReaderException re)
{
// continue -- just couldn't decode this row
}
}
}
throw NotFoundException.NotFoundInstance;
}
/// <summary>
/// Records the size of successive runs of white and black pixels in a row, starting at a given point.
/// The values are recorded in the given array, and the number of runs recorded is equal to the size
/// of the array. If the row starts on a white pixel at the given start point, then the first count
/// recorded is the run of white pixels starting from that point; likewise it is the count of a run
/// of black pixels if the row begin on a black pixels at that point.
/// </summary>
/// <param name="row"> row to count from </param>
/// <param name="start"> offset into row to start at </param>
/// <param name="counters"> array into which to record counts </param>
/// <exception cref="NotFoundException"> if counters cannot be filled entirely from row before running out
/// of pixels </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected static void recordPattern(com.google.zxing.common.BitArray row, int start, int[] counters) throws com.google.zxing.NotFoundException
protected internal static void recordPattern(BitArray row, int start, int[] counters)
{
int numCounters = counters.Length;
//Arrays.fill(counters, 0, numCounters, 0);
counters.Fill(0);
int end = row.Size;
if (start >= end)
{
throw NotFoundException.NotFoundInstance;
}
bool isWhite = !row.get(start);
int counterPosition = 0;
int i = start;
while (i < end)
{
if (row.get(i) ^ isWhite) // that is, exactly one is true
{
counters[counterPosition]++;
}
else
{
counterPosition++;
if (counterPosition == numCounters)
{
break;
}
else
{
counters[counterPosition] = 1;
isWhite = !isWhite;
}
}
i++;
}
// If we read fully the last section of pixels and filled up our counters -- or filled
// the last counter but ran off the side of the image, OK. Otherwise, a problem.
if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i == end)))
{
throw NotFoundException.NotFoundInstance;
}
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected static void recordPatternInReverse(com.google.zxing.common.BitArray row, int start, int[] counters) throws com.google.zxing.NotFoundException
protected internal static void recordPatternInReverse(BitArray row, int start, int[] counters)
{
// This could be more efficient I guess
int numTransitionsLeft = counters.Length;
bool last = row.get(start);
while (start > 0 && numTransitionsLeft >= 0)
{
if (row.get(--start) != last)
{
numTransitionsLeft--;
last = !last;
}
}
if (numTransitionsLeft >= 0)
{
throw NotFoundException.NotFoundInstance;
}
recordPattern(row, start + 1, counters);
}
/// <summary>
/// Determines how closely a set of observed counts of runs of black/white values matches a given
/// target pattern. This is reported as the ratio of the total variance from the expected pattern
/// proportions across all pattern elements, to the length of the pattern.
/// </summary>
/// <param name="counters"> observed counters </param>
/// <param name="pattern"> expected pattern </param>
/// <param name="maxIndividualVariance"> The most any counter can differ before we give up </param>
/// <returns> ratio of total variance between counters and pattern compared to total pattern size,
/// where the ratio has been multiplied by 256. So, 0 means no variance (perfect match); 256 means
/// the total variance between counters and patterns equals the pattern length, higher values mean
/// even more variance </returns>
protected internal static int patternMatchVariance(int[] counters, int[] pattern, int maxIndividualVariance)
{
int numCounters = counters.Length;
int total = 0;
int patternLength = 0;
for (int i = 0; i < numCounters; i++)
{
total += counters[i];
patternLength += pattern[i];
}
if (total < patternLength)
{
// If we don't even have one pixel per unit of bar width, assume this is too small
// to reliably match, so fail:
return int.MaxValue;
}
// We're going to fake floating-point math in integers. We just need to use more bits.
// Scale up patternLength so that intermediate values below like scaledCounter will have
// more "significant digits"
int unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength;
maxIndividualVariance = (maxIndividualVariance * unitBarWidth) >> INTEGER_MATH_SHIFT;
int totalVariance = 0;
for (int x = 0; x < numCounters; x++)
{
int counter = counters[x] << INTEGER_MATH_SHIFT;
int scaledPattern = pattern[x] * unitBarWidth;
int variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;
if (variance > maxIndividualVariance)
{
return int.MaxValue;
}
totalVariance += variance;
}
return totalVariance / total;
}
/// <summary>
/// <p>Attempts to decode a one-dimensional barcode format given a single row of
/// an image.</p>
/// </summary>
/// <param name="rowNumber"> row number from top of the row </param>
/// <param name="row"> the black/white pixel data of the row </param>
/// <param name="hints"> decode hints </param>
/// <returns> <seealso cref="Result"/> containing encoded string and start/end of barcode </returns>
/// <exception cref="NotFoundException"> if an error occurs or barcode cannot be found </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public abstract com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.ChecksumException, com.google.zxing.FormatException;
public abstract Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints);
}
}

View file

@ -1,105 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using BinaryBitmap = com.google.zxing.BinaryBitmap;
using ChecksumException = com.google.zxing.ChecksumException;
using DecodeHintType = com.google.zxing.DecodeHintType;
using FormatException = com.google.zxing.FormatException;
using NotFoundException = com.google.zxing.NotFoundException;
using Result = com.google.zxing.Result;
using BitArray = com.google.zxing.common.BitArray;
/// <summary>
/// <p>Implements decoding of the UPC-A format.</p>
///
/// @author dswitkin@google.com (Daniel Switkin)
/// @author Sean Owen
/// </summary>
public sealed class UPCAReader : UPCEANReader
{
private readonly UPCEANReader ean13Reader = new EAN13Reader();
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, int[] startGuardRange, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException, com.google.zxing.ChecksumException
public override Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, IDictionary<DecodeHintType, object> hints)
{
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange, hints));
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException, com.google.zxing.ChecksumException
public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints)
{
return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints));
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decode(com.google.zxing.BinaryBitmap image) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException
public override Result decode(BinaryBitmap image)
{
return maybeReturnResult(ean13Reader.decode(image));
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decode(com.google.zxing.BinaryBitmap image, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.FormatException
public override Result decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints)
{
return maybeReturnResult(ean13Reader.decode(image, hints));
}
internal override BarcodeFormat BarcodeFormat
{
get
{
return BarcodeFormat.UPC_A;
}
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected int decodeMiddle(com.google.zxing.common.BitArray row, int[] startRange, StringBuilder resultString) throws com.google.zxing.NotFoundException
protected internal override int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString)
{
return ean13Reader.decodeMiddle(row, startRange, resultString);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static com.google.zxing.Result maybeReturnResult(com.google.zxing.Result result) throws com.google.zxing.FormatException
private static Result maybeReturnResult(Result result)
{
string text = result.Text;
if (text[0] == '0')
{
return new Result(text.Substring(1), null, result.ResultPoints, BarcodeFormat.UPC_A);
}
else
{
throw FormatException.FormatInstance;
}
}
}
}

View file

@ -1,403 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using ChecksumException = com.google.zxing.ChecksumException;
using DecodeHintType = com.google.zxing.DecodeHintType;
using FormatException = com.google.zxing.FormatException;
using NotFoundException = com.google.zxing.NotFoundException;
using ReaderException = com.google.zxing.ReaderException;
using Result = com.google.zxing.Result;
using ResultMetadataType = com.google.zxing.ResultMetadataType;
using ResultPoint = com.google.zxing.ResultPoint;
using ResultPointCallback = com.google.zxing.ResultPointCallback;
using BitArray = com.google.zxing.common.BitArray;
using com.google.zxing.common;
public static class ArrayExtensions
{
public static void Fill(this int[] arr,int value)
{
for (int i = 0; i < arr.Length;i++ )
{
arr.SetValue(value,i);
}
}
}
/// <summary>
/// <p>Encapsulates functionality and implementation that is common to UPC and EAN families
/// of one-dimensional barcodes.</p>
///
/// @author dswitkin@google.com (Daniel Switkin)
/// @author Sean Owen
/// @author alasdair@google.com (Alasdair Mackintosh)
/// </summary>
public abstract class UPCEANReader : OneDReader
{
// These two values are critical for determining how permissive the decoding will be.
// We've arrived at these values through a lot of trial and error. Setting them any higher
// lets false positives creep in quickly.
private static readonly int MAX_AVG_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.48f);
private static readonly int MAX_INDIVIDUAL_VARIANCE = (int)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f);
/// <summary>
/// Start/end guard pattern.
/// </summary>
internal static readonly int[] START_END_PATTERN = {1, 1, 1};
/// <summary>
/// Pattern marking the middle of a UPC/EAN pattern, separating the two halves.
/// </summary>
internal static readonly int[] MIDDLE_PATTERN = {1, 1, 1, 1, 1};
/// <summary>
/// "Odd", or "L" patterns used to encode UPC/EAN digits.
/// </summary>
internal static readonly int[][] L_PATTERNS = {new int[] {3, 2, 1, 1}, new int[] {2, 2, 2, 1}, new int[] {2, 1, 2, 2}, new int[] {1, 4, 1, 1}, new int[] {1, 1, 3, 2}, new int[] {1, 2, 3, 1}, new int[] {1, 1, 1, 4}, new int[] {1, 3, 1, 2}, new int[] {1, 2, 1, 3}, new int[] {3, 1, 1, 2}};
/// <summary>
/// As above but also including the "even", or "G" patterns used to encode UPC/EAN digits.
/// </summary>
internal static readonly int[][] L_AND_G_PATTERNS;
static UPCEANReader()
{
L_AND_G_PATTERNS = new int[20][];
Array.Copy(L_PATTERNS, 0, L_AND_G_PATTERNS, 0, 10);
for (int i = 10; i < 20; i++)
{
int[] widths = L_PATTERNS[i - 10];
int[] reversedWidths = new int[widths.Length];
for (int j = 0; j < widths.Length; j++)
{
reversedWidths[j] = widths[widths.Length - j - 1];
}
L_AND_G_PATTERNS[i] = reversedWidths;
}
}
private readonly StringBuilder decodeRowStringBuffer;
private readonly UPCEANExtensionSupport extensionReader;
private readonly EANManufacturerOrgSupport eanManSupport;
protected internal UPCEANReader()
{
decodeRowStringBuffer = new StringBuilder(20);
extensionReader = new UPCEANExtensionSupport();
eanManSupport = new EANManufacturerOrgSupport();
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: static int[] findStartGuardPattern(com.google.zxing.common.BitArray row) throws com.google.zxing.NotFoundException
internal static int[] findStartGuardPattern(BitArray row)
{
bool foundStart = false;
int[] startRange = null;
int nextStart = 0;
int[] counters = new int[START_END_PATTERN.Length];
while (!foundStart)
{
//Arrays.fill(counters, 0, START_END_PATTERN.Length, 0);
counters.Fill(0);
startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN, counters);
int start = startRange[0];
nextStart = startRange[1];
// Make sure there is a quiet zone at least as big as the start pattern before the barcode.
// If this check would run off the left edge of the image, do not accept this barcode,
// as it is very likely to be a false positive.
int quietStart = start - (nextStart - start);
if (quietStart >= 0)
{
foundStart = row.isRange(quietStart, start, false);
}
}
return startRange;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.ChecksumException, com.google.zxing.FormatException
public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints)
{
return decodeRow(rowNumber, row, findStartGuardPattern(row), hints);
}
/// <summary>
/// <p>Like <seealso cref="#decodeRow(int, BitArray, java.util.Map)"/>, but
/// allows caller to inform method about where the UPC/EAN start pattern is
/// found. This allows this to be computed once and reused across many implementations.</p>
/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, int[] startGuardRange, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.ChecksumException, com.google.zxing.FormatException
public virtual Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange, IDictionary<DecodeHintType, object> hints)
{
//ResultPointCallback resultPointCallback = hints == null ? null : (ResultPointCallback) hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK];
ResultPointCallback resultPointCallback = null;
if (hints != null && hints.ContainsKey(DecodeHintType.NEED_RESULT_POINT_CALLBACK))
{
resultPointCallback = (ResultPointCallback)hints[DecodeHintType.NEED_RESULT_POINT_CALLBACK];
}
if (resultPointCallback != null)
{
resultPointCallback.foundPossibleResultPoint(new ResultPoint((startGuardRange[0] + startGuardRange[1]) / 2.0f, rowNumber));
}
StringBuilder result = decodeRowStringBuffer;
result.Length = 0;
int endStart = decodeMiddle(row, startGuardRange, result);
if (resultPointCallback != null)
{
resultPointCallback.foundPossibleResultPoint(new ResultPoint(endStart, rowNumber));
}
int[] endRange = decodeEnd(row, endStart);
if (resultPointCallback != null)
{
resultPointCallback.foundPossibleResultPoint(new ResultPoint((endRange[0] + endRange[1]) / 2.0f, rowNumber));
}
// Make sure there is a quiet zone at least as big as the end pattern after the barcode. The
// spec might want more whitespace, but in practice this is the maximum we can count on.
int end = endRange[1];
int quietEnd = end + (end - endRange[0]);
if (quietEnd >= row.Size || !row.isRange(end, quietEnd, false))
{
throw NotFoundException.NotFoundInstance;
}
string resultString = result.ToString();
if (!checkChecksum(resultString))
{
throw ChecksumException.ChecksumInstance;
}
float left = (float)(startGuardRange[1] + startGuardRange[0]) / 2.0f;
float right = (float)(endRange[1] + endRange[0]) / 2.0f;
BarcodeFormat format = BarcodeFormat;
Result decodeResult = new Result(resultString, null, new ResultPoint[]{new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, format); // no natural byte representation for these barcodes
try
{
Result extensionResult = extensionReader.decodeRow(rowNumber, row, endRange[1]);
decodeResult.putMetadata(ResultMetadataType.UPC_EAN_EXTENSION, extensionResult.Text);
decodeResult.putAllMetadata(extensionResult.ResultMetadata);
decodeResult.addResultPoints(extensionResult.ResultPoints);
}
catch (ReaderException re)
{
// continue
}
if (format == BarcodeFormat.EAN_13 || format == BarcodeFormat.UPC_A)
{
string countryID = eanManSupport.lookupCountryIdentifier(resultString);
if (countryID != null)
{
decodeResult.putMetadata(ResultMetadataType.POSSIBLE_COUNTRY, countryID);
}
}
return decodeResult;
}
/// <returns> <seealso cref="#checkStandardUPCEANChecksum(string)"/> </returns>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: boolean checkChecksum(String s) throws com.google.zxing.ChecksumException, com.google.zxing.FormatException
protected internal virtual bool checkChecksum(string s)
{
return checkStandardUPCEANChecksum(s);
}
/// <summary>
/// Computes the UPC/EAN checksum on a string of digits, and reports
/// whether the checksum is correct or not.
/// </summary>
/// <param name="s"> string of digits to check </param>
/// <returns> true iff string of digits passes the UPC/EAN checksum algorithm </returns>
/// <exception cref="FormatException"> if the string does not contain only digits </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: static boolean checkStandardUPCEANChecksum(CharSequence s) throws com.google.zxing.FormatException
internal static bool checkStandardUPCEANChecksum(string s)
{
int length = s.Length;
if (length == 0)
{
return false;
}
int sum = 0;
for (int i = length - 2; i >= 0; i -= 2)
{
int digit = (int) s[i] - (int) '0';
if (digit < 0 || digit > 9)
{
throw FormatException.FormatInstance;
}
sum += digit;
}
sum *= 3;
for (int i = length - 1; i >= 0; i -= 2)
{
int digit = (int) s[i] - (int) '0';
if (digit < 0 || digit > 9)
{
throw FormatException.FormatInstance;
}
sum += digit;
}
return sum % 10 == 0;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: int[] decodeEnd(com.google.zxing.common.BitArray row, int endStart) throws com.google.zxing.NotFoundException
protected internal virtual int[] decodeEnd(BitArray row, int endStart)
{
return findGuardPattern(row, endStart, false, START_END_PATTERN);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: static int[] findGuardPattern(com.google.zxing.common.BitArray row, int rowOffset, boolean whiteFirst, int[] pattern) throws com.google.zxing.NotFoundException
internal static int[] findGuardPattern(BitArray row, int rowOffset, bool whiteFirst, int[] pattern)
{
return findGuardPattern(row, rowOffset, whiteFirst, pattern, new int[pattern.Length]);
}
/// <param name="row"> row of black/white values to search </param>
/// <param name="rowOffset"> position to start search </param>
/// <param name="whiteFirst"> if true, indicates that the pattern specifies white/black/white/...
/// pixel counts, otherwise, it is interpreted as black/white/black/... </param>
/// <param name="pattern"> pattern of counts of number of black and white pixels that are being
/// searched for as a pattern </param>
/// <param name="counters"> array of counters, as long as pattern, to re-use </param>
/// <returns> start/end horizontal offset of guard pattern, as an array of two ints </returns>
/// <exception cref="NotFoundException"> if pattern is not found </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static int[] findGuardPattern(com.google.zxing.common.BitArray row, int rowOffset, boolean whiteFirst, int[] pattern, int[] counters) throws com.google.zxing.NotFoundException
private static int[] findGuardPattern(BitArray row, int rowOffset, bool whiteFirst, int[] pattern, int[] counters)
{
int patternLength = pattern.Length;
int width = row.Size;
bool isWhite = whiteFirst;
rowOffset = whiteFirst ? row.getNextUnset(rowOffset) : row.getNextSet(rowOffset);
int counterPosition = 0;
int patternStart = rowOffset;
for (int x = rowOffset; x < width; x++)
{
if (row.get(x) ^ isWhite)
{
counters[counterPosition]++;
}
else
{
if (counterPosition == patternLength - 1)
{
if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE)
{
return new int[]{patternStart, x};
}
patternStart += counters[0] + counters[1];
Array.Copy(counters, 2, counters, 0, patternLength - 2);
counters[patternLength - 2] = 0;
counters[patternLength - 1] = 0;
counterPosition--;
}
else
{
counterPosition++;
}
counters[counterPosition] = 1;
isWhite = !isWhite;
}
}
throw NotFoundException.NotFoundInstance;
}
/// <summary>
/// Attempts to decode a single UPC/EAN-encoded digit.
/// </summary>
/// <param name="row"> row of black/white values to decode </param>
/// <param name="counters"> the counts of runs of observed black/white/black/... values </param>
/// <param name="rowOffset"> horizontal offset to start decoding from </param>
/// <param name="patterns"> the set of patterns to use to decode -- sometimes different encodings
/// for the digits 0-9 are used, and this indicates the encodings for 0 to 9 that should
/// be used </param>
/// <returns> horizontal offset of first pixel beyond the decoded digit </returns>
/// <exception cref="NotFoundException"> if digit cannot be decoded </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: static int decodeDigit(com.google.zxing.common.BitArray row, int[] counters, int rowOffset, int[][] patterns) throws com.google.zxing.NotFoundException
internal static int decodeDigit(BitArray row, int[] counters, int rowOffset, int[][] patterns)
{
recordPattern(row, rowOffset, counters);
int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
int bestMatch = -1;
int max = patterns.Length;
for (int i = 0; i < max; i++)
{
int[] pattern = patterns[i];
int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
if (variance < bestVariance)
{
bestVariance = variance;
bestMatch = i;
}
}
if (bestMatch >= 0)
{
return bestMatch;
}
else
{
throw NotFoundException.NotFoundInstance;
}
}
/// <summary>
/// Get the format of this decoder.
/// </summary>
/// <returns> The 1D format. </returns>
internal abstract BarcodeFormat BarcodeFormat {get;}
/// <summary>
/// Subclasses override this to decode the portion of a barcode between the start
/// and end guard patterns.
/// </summary>
/// <param name="row"> row of black/white values to search </param>
/// <param name="startRange"> start/end offset of start guard pattern </param>
/// <param name="resultString"> <seealso cref="StringBuilder"/> to append decoded chars to </param>
/// <returns> horizontal offset of first pixel after the "middle" that was decoded </returns>
/// <exception cref="NotFoundException"> if decoding could not complete successfully </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected abstract int decodeMiddle(com.google.zxing.common.BitArray row, int[] startRange, StringBuilder resultString) throws com.google.zxing.NotFoundException;
protected internal abstract int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString);
}
}

View file

@ -1,41 +0,0 @@
/*
* Copyright 2009 ZXing 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.
*/
namespace com.google.zxing.oned
{
/// <summary>
/// <p>Encapsulates functionality and implementation that is common to UPC and EAN families
/// of one-dimensional barcodes.</p>
///
/// @author aripollak@gmail.com (Ari Pollak)
/// @author dsbnatut@gmail.com (Kazuki Nishiura)
/// </summary>
public abstract class UPCEANWriter : OneDimensionalCodeWriter
{
public override int DefaultMargin
{
get
{
// Use a different default more appropriate for UPC/EAN
return UPCEANReader.START_END_PATTERN.Length;
}
}
}
}

View file

@ -1,179 +0,0 @@
using System.Collections;
using System.Text;
/*
* Copyright 2008 ZXing 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.
*/
namespace com.google.zxing.oned
{
using BarcodeFormat = com.google.zxing.BarcodeFormat;
using ChecksumException = com.google.zxing.ChecksumException;
using FormatException = com.google.zxing.FormatException;
using NotFoundException = com.google.zxing.NotFoundException;
using BitArray = com.google.zxing.common.BitArray;
/// <summary>
/// <p>Implements decoding of the UPC-E format.</p>
/// <p/>
/// <p><a href="http://www.barcodeisland.com/upce.phtml">This</a> is a great reference for
/// UPC-E information.</p>
///
/// @author Sean Owen
/// </summary>
public sealed class UPCEReader : UPCEANReader
{
/// <summary>
/// The pattern that marks the middle, and end, of a UPC-E pattern.
/// There is no "second half" to a UPC-E barcode.
/// </summary>
private static readonly int[] MIDDLE_END_PATTERN = {1, 1, 1, 1, 1, 1};
/// <summary>
/// See <seealso cref="#L_AND_G_PATTERNS"/>; these values similarly represent patterns of
/// even-odd parity encodings of digits that imply both the number system (0 or 1)
/// used, and the check digit.
/// </summary>
private static readonly int[][] NUMSYS_AND_CHECK_DIGIT_PATTERNS = {new int[] {0x38, 0x34, 0x32, 0x31, 0x2C, 0x26, 0x23, 0x2A, 0x29, 0x25}, new int[] {0x07, 0x0B, 0x0D, 0x0E, 0x13, 0x19, 0x1C, 0x15, 0x16, 0x1A}};
private readonly int[] decodeMiddleCounters;
public UPCEReader()
{
decodeMiddleCounters = new int[4];
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected int decodeMiddle(com.google.zxing.common.BitArray row, int[] startRange, StringBuilder result) throws com.google.zxing.NotFoundException
protected internal override int decodeMiddle(BitArray row, int[] startRange, StringBuilder result)
{
int[] counters = decodeMiddleCounters;
counters[0] = 0;
counters[1] = 0;
counters[2] = 0;
counters[3] = 0;
int end = row.Size;
int rowOffset = startRange[1];
int lgPatternFound = 0;
for (int x = 0; x < 6 && rowOffset < end; x++)
{
int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS);
result.Append((char)('0' + bestMatch % 10));
foreach (int counter in counters)
{
rowOffset += counter;
}
if (bestMatch >= 10)
{
lgPatternFound |= 1 << (5 - x);
}
}
determineNumSysAndCheckDigit(result, lgPatternFound);
return rowOffset;
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected int[] decodeEnd(com.google.zxing.common.BitArray row, int endStart) throws com.google.zxing.NotFoundException
protected internal override int[] decodeEnd(BitArray row, int endStart)
{
return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN);
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: protected boolean checkChecksum(String s) throws com.google.zxing.FormatException, com.google.zxing.ChecksumException
protected internal override bool checkChecksum(string s)
{
return base.checkChecksum(convertUPCEtoUPCA(s));
}
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static void determineNumSysAndCheckDigit(StringBuilder resultString, int lgPatternFound) throws com.google.zxing.NotFoundException
private static void determineNumSysAndCheckDigit(StringBuilder resultString, int lgPatternFound)
{
for (int numSys = 0; numSys <= 1; numSys++)
{
for (int d = 0; d < 10; d++)
{
if (lgPatternFound == NUMSYS_AND_CHECK_DIGIT_PATTERNS[numSys][d])
{
resultString.Insert(0, (char)('0' + numSys));
resultString.Append((char)('0' + d));
return;
}
}
}
throw NotFoundException.NotFoundInstance;
}
internal override BarcodeFormat BarcodeFormat
{
get
{
return BarcodeFormat.UPC_E;
}
}
/// <summary>
/// Expands a UPC-E value back into its full, equivalent UPC-A code value.
/// </summary>
/// <param name="upce"> UPC-E code as string of digits </param>
/// <returns> equivalent UPC-A code as string of digits </returns>
public static string convertUPCEtoUPCA(string upce)
{
char[] upceChars = new char[6];
upce.CopyTo(1, upceChars, 0, 6);
StringBuilder result = new StringBuilder(12);
result.Append(upce[0]);
char lastChar = upceChars[5];
switch (lastChar)
{
case '0':
case '1':
case '2':
result.Append(upceChars, 0, 2);
result.Append(lastChar);
result.Append("0000");
result.Append(upceChars, 2, 3);
break;
case '3':
result.Append(upceChars, 0, 3);
result.Append("00000");
result.Append(upceChars, 3, 2);
break;
case '4':
result.Append(upceChars, 0, 4);
result.Append("00000");
result.Append(upceChars[4]);
break;
default:
result.Append(upceChars, 0, 5);
result.Append("0000");
result.Append(lastChar);
break;
}
result.Append(upce[7]);
return result.ToString();
}
}
}

View file

@ -1,527 +0,0 @@
/*
* Copyright 2009 ZXing 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.Collections.Generic;
using ZXing.Common;
using ZXing.PDF417.Internal;
using System;
namespace ZXing.PDF417
{
/// <summary>
/// <author>SITA Lab (kevin.osullivan@sita.aero) </author>
/// <author>Guenther Grau </author>
/// <author>Stephen Furlani (C# Port)</author>
/// </summary>
public sealed class PDF417Common
{
public static readonly int INVALID_CODEWORD = -1;
public static readonly int NUMBER_OF_CODEWORDS = 929;
/// <summary>
/// Maximum Codewords (Data + Error).
/// </summary>
public static readonly int MAX_CODEWORDS_IN_BARCODE = NUMBER_OF_CODEWORDS - 1;
public static readonly int MIN_ROWS_IN_BARCODE = 3;
public static readonly int MAX_ROWS_IN_BARCODE = 90;
/// <summary>
/// One left row indication column + max 30 data columns + one right row indicator column
/// </summary>
public static readonly int MAX_CODEWORDS_IN_ROW = 32;
public static readonly int MODULES_IN_CODEWORD = 17;
public static readonly int MODULES_IN_STOP_PATTERN = 18;
public static readonly int BARS_IN_MODULE = 8;
private static readonly int[] EMPTY_INT_ARRAY = {};
/// <summary>
/// Initializes a new instance of the <see cref="ZXing.PDF417.PDF417Common"/> class.
/// Private, so as to force this classes singleton-ness
/// </summary>
private PDF417Common()
{
}
/// <summary>
/// Gets the bit count sum.
/// </summary>
/// <returns>The bit count sum.</returns>
/// <param name="moduleBitCount">Module bit count.</param>
public static int GetBitCountSum(int[] moduleBitCount)
{
int bitCountSum = 0;
foreach (int count in moduleBitCount)
{
bitCountSum += count;
}
return bitCountSum;
}
/// <summary>
/// Converts an ICollection<int> to an int[]
/// Carry-over from Java. Will likely remove and replace with the Generic .ToArray() method.
/// </summary>
/// <returns>The int array.</returns>
/// <param name="list">List.</param>
public static int[] ToIntArray(ICollection<int> list)
{
if (list == null || list.Count == 0)
{
return EMPTY_INT_ARRAY;
}
int[] result = new int[list.Count];
int i = 0;
foreach (int integer in list)
{
result[i++] = integer;
}
return result;
}
/// <summary>
/// Translate the symbol into a codeword
/// </summary>
/// <returns>the codeword corresponding to the symbol.</returns>
/// <param name="symbol">the symbol from the barcode..</param>
public static int GetCodeword(long symbol)
{
long sym = symbol & 0x3FFFF;
int i = FindCodewordIndex(sym);
if (i == -1)
{
return INVALID_CODEWORD;
}
return (CODEWORD_TABLE[i] - 1) % NUMBER_OF_CODEWORDS;
}
/// <summary>
/// Use a binary search to find the index of the codeword corresponding to
/// this symbol.
/// </summary>
/// <returns>the index into the codeword table.</returns>
/// <param name="symbol">the symbol from the barcode.</param>
private static int FindCodewordIndex(long symbol)
{
int first = 0;
int upto = SYMBOL_TABLE.Length;
while (first < upto)
{
// NOTE: Converted Java's '>>>' to '(int)((unit)x >>y)' in C#
// http://stackoverflow.com/q/1880172/266252
int mid = (int)((uint)(first + upto) >> 1); // Compute mid point. (i.e. bitshift == divide by 2)
if (symbol < SYMBOL_TABLE[mid])
{
upto = mid; // continue search in bottom half.
} else if (symbol > SYMBOL_TABLE[mid])
{
first = mid + 1; // continue search in top half.
} else
{
return mid; // Found it. return position
}
}
return -1;
}
/// <summary>
/// The sorted table of all possible symbols. Extracted from the PDF417
/// specification. The index of a symbol in this table corresponds to the
/// index into the codeword table.
/// </summary>
public static readonly int[] SYMBOL_TABLE = {
0x1025e, 0x1027a, 0x1029e, 0x102bc, 0x102f2, 0x102f4, 0x1032e, 0x1034e, 0x1035c, 0x10396, 0x103a6, 0x103ac,
0x10422, 0x10428, 0x10436, 0x10442, 0x10444, 0x10448, 0x10450, 0x1045e, 0x10466, 0x1046c, 0x1047a, 0x10482,
0x1049e, 0x104a0, 0x104bc, 0x104c6, 0x104d8, 0x104ee, 0x104f2, 0x104f4, 0x10504, 0x10508, 0x10510, 0x1051e,
0x10520, 0x1053c, 0x10540, 0x10578, 0x10586, 0x1058c, 0x10598, 0x105b0, 0x105be, 0x105ce, 0x105dc, 0x105e2,
0x105e4, 0x105e8, 0x105f6, 0x1062e, 0x1064e, 0x1065c, 0x1068e, 0x1069c, 0x106b8, 0x106de, 0x106fa, 0x10716,
0x10726, 0x1072c, 0x10746, 0x1074c, 0x10758, 0x1076e, 0x10792, 0x10794, 0x107a2, 0x107a4, 0x107a8, 0x107b6,
0x10822, 0x10828, 0x10842, 0x10848, 0x10850, 0x1085e, 0x10866, 0x1086c, 0x1087a, 0x10882, 0x10884, 0x10890,
0x1089e, 0x108a0, 0x108bc, 0x108c6, 0x108cc, 0x108d8, 0x108ee, 0x108f2, 0x108f4, 0x10902, 0x10908, 0x1091e,
0x10920, 0x1093c, 0x10940, 0x10978, 0x10986, 0x10998, 0x109b0, 0x109be, 0x109ce, 0x109dc, 0x109e2, 0x109e4,
0x109e8, 0x109f6, 0x10a08, 0x10a10, 0x10a1e, 0x10a20, 0x10a3c, 0x10a40, 0x10a78, 0x10af0, 0x10b06, 0x10b0c,
0x10b18, 0x10b30, 0x10b3e, 0x10b60, 0x10b7c, 0x10b8e, 0x10b9c, 0x10bb8, 0x10bc2, 0x10bc4, 0x10bc8, 0x10bd0,
0x10bde, 0x10be6, 0x10bec, 0x10c2e, 0x10c4e, 0x10c5c, 0x10c62, 0x10c64, 0x10c68, 0x10c76, 0x10c8e, 0x10c9c,
0x10cb8, 0x10cc2, 0x10cc4, 0x10cc8, 0x10cd0, 0x10cde, 0x10ce6, 0x10cec, 0x10cfa, 0x10d0e, 0x10d1c, 0x10d38,
0x10d70, 0x10d7e, 0x10d82, 0x10d84, 0x10d88, 0x10d90, 0x10d9e, 0x10da0, 0x10dbc, 0x10dc6, 0x10dcc, 0x10dd8,
0x10dee, 0x10df2, 0x10df4, 0x10e16, 0x10e26, 0x10e2c, 0x10e46, 0x10e58, 0x10e6e, 0x10e86, 0x10e8c, 0x10e98,
0x10eb0, 0x10ebe, 0x10ece, 0x10edc, 0x10f0a, 0x10f12, 0x10f14, 0x10f22, 0x10f28, 0x10f36, 0x10f42, 0x10f44,
0x10f48, 0x10f50, 0x10f5e, 0x10f66, 0x10f6c, 0x10fb2, 0x10fb4, 0x11022, 0x11028, 0x11042, 0x11048, 0x11050,
0x1105e, 0x1107a, 0x11082, 0x11084, 0x11090, 0x1109e, 0x110a0, 0x110bc, 0x110c6, 0x110cc, 0x110d8, 0x110ee,
0x110f2, 0x110f4, 0x11102, 0x1111e, 0x11120, 0x1113c, 0x11140, 0x11178, 0x11186, 0x11198, 0x111b0, 0x111be,
0x111ce, 0x111dc, 0x111e2, 0x111e4, 0x111e8, 0x111f6, 0x11208, 0x1121e, 0x11220, 0x11278, 0x112f0, 0x1130c,
0x11330, 0x1133e, 0x11360, 0x1137c, 0x1138e, 0x1139c, 0x113b8, 0x113c2, 0x113c8, 0x113d0, 0x113de, 0x113e6,
0x113ec, 0x11408, 0x11410, 0x1141e, 0x11420, 0x1143c, 0x11440, 0x11478, 0x114f0, 0x115e0, 0x1160c, 0x11618,
0x11630, 0x1163e, 0x11660, 0x1167c, 0x116c0, 0x116f8, 0x1171c, 0x11738, 0x11770, 0x1177e, 0x11782, 0x11784,
0x11788, 0x11790, 0x1179e, 0x117a0, 0x117bc, 0x117c6, 0x117cc, 0x117d8, 0x117ee, 0x1182e, 0x11834, 0x1184e,
0x1185c, 0x11862, 0x11864, 0x11868, 0x11876, 0x1188e, 0x1189c, 0x118b8, 0x118c2, 0x118c8, 0x118d0, 0x118de,
0x118e6, 0x118ec, 0x118fa, 0x1190e, 0x1191c, 0x11938, 0x11970, 0x1197e, 0x11982, 0x11984, 0x11990, 0x1199e,
0x119a0, 0x119bc, 0x119c6, 0x119cc, 0x119d8, 0x119ee, 0x119f2, 0x119f4, 0x11a0e, 0x11a1c, 0x11a38, 0x11a70,
0x11a7e, 0x11ae0, 0x11afc, 0x11b08, 0x11b10, 0x11b1e, 0x11b20, 0x11b3c, 0x11b40, 0x11b78, 0x11b8c, 0x11b98,
0x11bb0, 0x11bbe, 0x11bce, 0x11bdc, 0x11be2, 0x11be4, 0x11be8, 0x11bf6, 0x11c16, 0x11c26, 0x11c2c, 0x11c46,
0x11c4c, 0x11c58, 0x11c6e, 0x11c86, 0x11c98, 0x11cb0, 0x11cbe, 0x11cce, 0x11cdc, 0x11ce2, 0x11ce4, 0x11ce8,
0x11cf6, 0x11d06, 0x11d0c, 0x11d18, 0x11d30, 0x11d3e, 0x11d60, 0x11d7c, 0x11d8e, 0x11d9c, 0x11db8, 0x11dc4,
0x11dc8, 0x11dd0, 0x11dde, 0x11de6, 0x11dec, 0x11dfa, 0x11e0a, 0x11e12, 0x11e14, 0x11e22, 0x11e24, 0x11e28,
0x11e36, 0x11e42, 0x11e44, 0x11e50, 0x11e5e, 0x11e66, 0x11e6c, 0x11e82, 0x11e84, 0x11e88, 0x11e90, 0x11e9e,
0x11ea0, 0x11ebc, 0x11ec6, 0x11ecc, 0x11ed8, 0x11eee, 0x11f1a, 0x11f2e, 0x11f32, 0x11f34, 0x11f4e, 0x11f5c,
0x11f62, 0x11f64, 0x11f68, 0x11f76, 0x12048, 0x1205e, 0x12082, 0x12084, 0x12090, 0x1209e, 0x120a0, 0x120bc,
0x120d8, 0x120f2, 0x120f4, 0x12108, 0x1211e, 0x12120, 0x1213c, 0x12140, 0x12178, 0x12186, 0x12198, 0x121b0,
0x121be, 0x121e2, 0x121e4, 0x121e8, 0x121f6, 0x12204, 0x12210, 0x1221e, 0x12220, 0x12278, 0x122f0, 0x12306,
0x1230c, 0x12330, 0x1233e, 0x12360, 0x1237c, 0x1238e, 0x1239c, 0x123b8, 0x123c2, 0x123c8, 0x123d0, 0x123e6,
0x123ec, 0x1241e, 0x12420, 0x1243c, 0x124f0, 0x125e0, 0x12618, 0x1263e, 0x12660, 0x1267c, 0x126c0, 0x126f8,
0x12738, 0x12770, 0x1277e, 0x12782, 0x12784, 0x12790, 0x1279e, 0x127a0, 0x127bc, 0x127c6, 0x127cc, 0x127d8,
0x127ee, 0x12820, 0x1283c, 0x12840, 0x12878, 0x128f0, 0x129e0, 0x12bc0, 0x12c18, 0x12c30, 0x12c3e, 0x12c60,
0x12c7c, 0x12cc0, 0x12cf8, 0x12df0, 0x12e1c, 0x12e38, 0x12e70, 0x12e7e, 0x12ee0, 0x12efc, 0x12f04, 0x12f08,
0x12f10, 0x12f20, 0x12f3c, 0x12f40, 0x12f78, 0x12f86, 0x12f8c, 0x12f98, 0x12fb0, 0x12fbe, 0x12fce, 0x12fdc,
0x1302e, 0x1304e, 0x1305c, 0x13062, 0x13068, 0x1308e, 0x1309c, 0x130b8, 0x130c2, 0x130c8, 0x130d0, 0x130de,
0x130ec, 0x130fa, 0x1310e, 0x13138, 0x13170, 0x1317e, 0x13182, 0x13184, 0x13190, 0x1319e, 0x131a0, 0x131bc,
0x131c6, 0x131cc, 0x131d8, 0x131f2, 0x131f4, 0x1320e, 0x1321c, 0x13270, 0x1327e, 0x132e0, 0x132fc, 0x13308,
0x1331e, 0x13320, 0x1333c, 0x13340, 0x13378, 0x13386, 0x13398, 0x133b0, 0x133be, 0x133ce, 0x133dc, 0x133e2,
0x133e4, 0x133e8, 0x133f6, 0x1340e, 0x1341c, 0x13438, 0x13470, 0x1347e, 0x134e0, 0x134fc, 0x135c0, 0x135f8,
0x13608, 0x13610, 0x1361e, 0x13620, 0x1363c, 0x13640, 0x13678, 0x136f0, 0x1370c, 0x13718, 0x13730, 0x1373e,
0x13760, 0x1377c, 0x1379c, 0x137b8, 0x137c2, 0x137c4, 0x137c8, 0x137d0, 0x137de, 0x137e6, 0x137ec, 0x13816,
0x13826, 0x1382c, 0x13846, 0x1384c, 0x13858, 0x1386e, 0x13874, 0x13886, 0x13898, 0x138b0, 0x138be, 0x138ce,
0x138dc, 0x138e2, 0x138e4, 0x138e8, 0x13906, 0x1390c, 0x13930, 0x1393e, 0x13960, 0x1397c, 0x1398e, 0x1399c,
0x139b8, 0x139c8, 0x139d0, 0x139de, 0x139e6, 0x139ec, 0x139fa, 0x13a06, 0x13a0c, 0x13a18, 0x13a30, 0x13a3e,
0x13a60, 0x13a7c, 0x13ac0, 0x13af8, 0x13b0e, 0x13b1c, 0x13b38, 0x13b70, 0x13b7e, 0x13b88, 0x13b90, 0x13b9e,
0x13ba0, 0x13bbc, 0x13bcc, 0x13bd8, 0x13bee, 0x13bf2, 0x13bf4, 0x13c12, 0x13c14, 0x13c22, 0x13c24, 0x13c28,
0x13c36, 0x13c42, 0x13c48, 0x13c50, 0x13c5e, 0x13c66, 0x13c6c, 0x13c82, 0x13c84, 0x13c90, 0x13c9e, 0x13ca0,
0x13cbc, 0x13cc6, 0x13ccc, 0x13cd8, 0x13cee, 0x13d02, 0x13d04, 0x13d08, 0x13d10, 0x13d1e, 0x13d20, 0x13d3c,
0x13d40, 0x13d78, 0x13d86, 0x13d8c, 0x13d98, 0x13db0, 0x13dbe, 0x13dce, 0x13ddc, 0x13de4, 0x13de8, 0x13df6,
0x13e1a, 0x13e2e, 0x13e32, 0x13e34, 0x13e4e, 0x13e5c, 0x13e62, 0x13e64, 0x13e68, 0x13e76, 0x13e8e, 0x13e9c,
0x13eb8, 0x13ec2, 0x13ec4, 0x13ec8, 0x13ed0, 0x13ede, 0x13ee6, 0x13eec, 0x13f26, 0x13f2c, 0x13f3a, 0x13f46,
0x13f4c, 0x13f58, 0x13f6e, 0x13f72, 0x13f74, 0x14082, 0x1409e, 0x140a0, 0x140bc, 0x14104, 0x14108, 0x14110,
0x1411e, 0x14120, 0x1413c, 0x14140, 0x14178, 0x1418c, 0x14198, 0x141b0, 0x141be, 0x141e2, 0x141e4, 0x141e8,
0x14208, 0x14210, 0x1421e, 0x14220, 0x1423c, 0x14240, 0x14278, 0x142f0, 0x14306, 0x1430c, 0x14318, 0x14330,
0x1433e, 0x14360, 0x1437c, 0x1438e, 0x143c2, 0x143c4, 0x143c8, 0x143d0, 0x143e6, 0x143ec, 0x14408, 0x14410,
0x1441e, 0x14420, 0x1443c, 0x14440, 0x14478, 0x144f0, 0x145e0, 0x1460c, 0x14618, 0x14630, 0x1463e, 0x14660,
0x1467c, 0x146c0, 0x146f8, 0x1471c, 0x14738, 0x14770, 0x1477e, 0x14782, 0x14784, 0x14788, 0x14790, 0x147a0,
0x147bc, 0x147c6, 0x147cc, 0x147d8, 0x147ee, 0x14810, 0x14820, 0x1483c, 0x14840, 0x14878, 0x148f0, 0x149e0,
0x14bc0, 0x14c30, 0x14c3e, 0x14c60, 0x14c7c, 0x14cc0, 0x14cf8, 0x14df0, 0x14e38, 0x14e70, 0x14e7e, 0x14ee0,
0x14efc, 0x14f04, 0x14f08, 0x14f10, 0x14f1e, 0x14f20, 0x14f3c, 0x14f40, 0x14f78, 0x14f86, 0x14f8c, 0x14f98,
0x14fb0, 0x14fce, 0x14fdc, 0x15020, 0x15040, 0x15078, 0x150f0, 0x151e0, 0x153c0, 0x15860, 0x1587c, 0x158c0,
0x158f8, 0x159f0, 0x15be0, 0x15c70, 0x15c7e, 0x15ce0, 0x15cfc, 0x15dc0, 0x15df8, 0x15e08, 0x15e10, 0x15e20,
0x15e40, 0x15e78, 0x15ef0, 0x15f0c, 0x15f18, 0x15f30, 0x15f60, 0x15f7c, 0x15f8e, 0x15f9c, 0x15fb8, 0x1604e,
0x1605c, 0x1608e, 0x1609c, 0x160b8, 0x160c2, 0x160c4, 0x160c8, 0x160de, 0x1610e, 0x1611c, 0x16138, 0x16170,
0x1617e, 0x16184, 0x16188, 0x16190, 0x1619e, 0x161a0, 0x161bc, 0x161c6, 0x161cc, 0x161d8, 0x161f2, 0x161f4,
0x1620e, 0x1621c, 0x16238, 0x16270, 0x1627e, 0x162e0, 0x162fc, 0x16304, 0x16308, 0x16310, 0x1631e, 0x16320,
0x1633c, 0x16340, 0x16378, 0x16386, 0x1638c, 0x16398, 0x163b0, 0x163be, 0x163ce, 0x163dc, 0x163e2, 0x163e4,
0x163e8, 0x163f6, 0x1640e, 0x1641c, 0x16438, 0x16470, 0x1647e, 0x164e0, 0x164fc, 0x165c0, 0x165f8, 0x16610,
0x1661e, 0x16620, 0x1663c, 0x16640, 0x16678, 0x166f0, 0x16718, 0x16730, 0x1673e, 0x16760, 0x1677c, 0x1678e,
0x1679c, 0x167b8, 0x167c2, 0x167c4, 0x167c8, 0x167d0, 0x167de, 0x167e6, 0x167ec, 0x1681c, 0x16838, 0x16870,
0x168e0, 0x168fc, 0x169c0, 0x169f8, 0x16bf0, 0x16c10, 0x16c1e, 0x16c20, 0x16c3c, 0x16c40, 0x16c78, 0x16cf0,
0x16de0, 0x16e18, 0x16e30, 0x16e3e, 0x16e60, 0x16e7c, 0x16ec0, 0x16ef8, 0x16f1c, 0x16f38, 0x16f70, 0x16f7e,
0x16f84, 0x16f88, 0x16f90, 0x16f9e, 0x16fa0, 0x16fbc, 0x16fc6, 0x16fcc, 0x16fd8, 0x17026, 0x1702c, 0x17046,
0x1704c, 0x17058, 0x1706e, 0x17086, 0x1708c, 0x17098, 0x170b0, 0x170be, 0x170ce, 0x170dc, 0x170e8, 0x17106,
0x1710c, 0x17118, 0x17130, 0x1713e, 0x17160, 0x1717c, 0x1718e, 0x1719c, 0x171b8, 0x171c2, 0x171c4, 0x171c8,
0x171d0, 0x171de, 0x171e6, 0x171ec, 0x171fa, 0x17206, 0x1720c, 0x17218, 0x17230, 0x1723e, 0x17260, 0x1727c,
0x172c0, 0x172f8, 0x1730e, 0x1731c, 0x17338, 0x17370, 0x1737e, 0x17388, 0x17390, 0x1739e, 0x173a0, 0x173bc,
0x173cc, 0x173d8, 0x173ee, 0x173f2, 0x173f4, 0x1740c, 0x17418, 0x17430, 0x1743e, 0x17460, 0x1747c, 0x174c0,
0x174f8, 0x175f0, 0x1760e, 0x1761c, 0x17638, 0x17670, 0x1767e, 0x176e0, 0x176fc, 0x17708, 0x17710, 0x1771e,
0x17720, 0x1773c, 0x17740, 0x17778, 0x17798, 0x177b0, 0x177be, 0x177dc, 0x177e2, 0x177e4, 0x177e8, 0x17822,
0x17824, 0x17828, 0x17836, 0x17842, 0x17844, 0x17848, 0x17850, 0x1785e, 0x17866, 0x1786c, 0x17882, 0x17884,
0x17888, 0x17890, 0x1789e, 0x178a0, 0x178bc, 0x178c6, 0x178cc, 0x178d8, 0x178ee, 0x178f2, 0x178f4, 0x17902,
0x17904, 0x17908, 0x17910, 0x1791e, 0x17920, 0x1793c, 0x17940, 0x17978, 0x17986, 0x1798c, 0x17998, 0x179b0,
0x179be, 0x179ce, 0x179dc, 0x179e2, 0x179e4, 0x179e8, 0x179f6, 0x17a04, 0x17a08, 0x17a10, 0x17a1e, 0x17a20,
0x17a3c, 0x17a40, 0x17a78, 0x17af0, 0x17b06, 0x17b0c, 0x17b18, 0x17b30, 0x17b3e, 0x17b60, 0x17b7c, 0x17b8e,
0x17b9c, 0x17bb8, 0x17bc4, 0x17bc8, 0x17bd0, 0x17bde, 0x17be6, 0x17bec, 0x17c2e, 0x17c32, 0x17c34, 0x17c4e,
0x17c5c, 0x17c62, 0x17c64, 0x17c68, 0x17c76, 0x17c8e, 0x17c9c, 0x17cb8, 0x17cc2, 0x17cc4, 0x17cc8, 0x17cd0,
0x17cde, 0x17ce6, 0x17cec, 0x17d0e, 0x17d1c, 0x17d38, 0x17d70, 0x17d82, 0x17d84, 0x17d88, 0x17d90, 0x17d9e,
0x17da0, 0x17dbc, 0x17dc6, 0x17dcc, 0x17dd8, 0x17dee, 0x17e26, 0x17e2c, 0x17e3a, 0x17e46, 0x17e4c, 0x17e58,
0x17e6e, 0x17e72, 0x17e74, 0x17e86, 0x17e8c, 0x17e98, 0x17eb0, 0x17ece, 0x17edc, 0x17ee2, 0x17ee4, 0x17ee8,
0x17ef6, 0x1813a, 0x18172, 0x18174, 0x18216, 0x18226, 0x1823a, 0x1824c, 0x18258, 0x1826e, 0x18272, 0x18274,
0x18298, 0x182be, 0x182e2, 0x182e4, 0x182e8, 0x182f6, 0x1835e, 0x1837a, 0x183ae, 0x183d6, 0x18416, 0x18426,
0x1842c, 0x1843a, 0x18446, 0x18458, 0x1846e, 0x18472, 0x18474, 0x18486, 0x184b0, 0x184be, 0x184ce, 0x184dc,
0x184e2, 0x184e4, 0x184e8, 0x184f6, 0x18506, 0x1850c, 0x18518, 0x18530, 0x1853e, 0x18560, 0x1857c, 0x1858e,
0x1859c, 0x185b8, 0x185c2, 0x185c4, 0x185c8, 0x185d0, 0x185de, 0x185e6, 0x185ec, 0x185fa, 0x18612, 0x18614,
0x18622, 0x18628, 0x18636, 0x18642, 0x18650, 0x1865e, 0x1867a, 0x18682, 0x18684, 0x18688, 0x18690, 0x1869e,
0x186a0, 0x186bc, 0x186c6, 0x186cc, 0x186d8, 0x186ee, 0x186f2, 0x186f4, 0x1872e, 0x1874e, 0x1875c, 0x18796,
0x187a6, 0x187ac, 0x187d2, 0x187d4, 0x18826, 0x1882c, 0x1883a, 0x18846, 0x1884c, 0x18858, 0x1886e, 0x18872,
0x18874, 0x18886, 0x18898, 0x188b0, 0x188be, 0x188ce, 0x188dc, 0x188e2, 0x188e4, 0x188e8, 0x188f6, 0x1890c,
0x18930, 0x1893e, 0x18960, 0x1897c, 0x1898e, 0x189b8, 0x189c2, 0x189c8, 0x189d0, 0x189de, 0x189e6, 0x189ec,
0x189fa, 0x18a18, 0x18a30, 0x18a3e, 0x18a60, 0x18a7c, 0x18ac0, 0x18af8, 0x18b1c, 0x18b38, 0x18b70, 0x18b7e,
0x18b82, 0x18b84, 0x18b88, 0x18b90, 0x18b9e, 0x18ba0, 0x18bbc, 0x18bc6, 0x18bcc, 0x18bd8, 0x18bee, 0x18bf2,
0x18bf4, 0x18c22, 0x18c24, 0x18c28, 0x18c36, 0x18c42, 0x18c48, 0x18c50, 0x18c5e, 0x18c66, 0x18c7a, 0x18c82,
0x18c84, 0x18c90, 0x18c9e, 0x18ca0, 0x18cbc, 0x18ccc, 0x18cf2, 0x18cf4, 0x18d04, 0x18d08, 0x18d10, 0x18d1e,
0x18d20, 0x18d3c, 0x18d40, 0x18d78, 0x18d86, 0x18d98, 0x18dce, 0x18de2, 0x18de4, 0x18de8, 0x18e2e, 0x18e32,
0x18e34, 0x18e4e, 0x18e5c, 0x18e62, 0x18e64, 0x18e68, 0x18e8e, 0x18e9c, 0x18eb8, 0x18ec2, 0x18ec4, 0x18ec8,
0x18ed0, 0x18efa, 0x18f16, 0x18f26, 0x18f2c, 0x18f46, 0x18f4c, 0x18f58, 0x18f6e, 0x18f8a, 0x18f92, 0x18f94,
0x18fa2, 0x18fa4, 0x18fa8, 0x18fb6, 0x1902c, 0x1903a, 0x19046, 0x1904c, 0x19058, 0x19072, 0x19074, 0x19086,
0x19098, 0x190b0, 0x190be, 0x190ce, 0x190dc, 0x190e2, 0x190e8, 0x190f6, 0x19106, 0x1910c, 0x19130, 0x1913e,
0x19160, 0x1917c, 0x1918e, 0x1919c, 0x191b8, 0x191c2, 0x191c8, 0x191d0, 0x191de, 0x191e6, 0x191ec, 0x191fa,
0x19218, 0x1923e, 0x19260, 0x1927c, 0x192c0, 0x192f8, 0x19338, 0x19370, 0x1937e, 0x19382, 0x19384, 0x19390,
0x1939e, 0x193a0, 0x193bc, 0x193c6, 0x193cc, 0x193d8, 0x193ee, 0x193f2, 0x193f4, 0x19430, 0x1943e, 0x19460,
0x1947c, 0x194c0, 0x194f8, 0x195f0, 0x19638, 0x19670, 0x1967e, 0x196e0, 0x196fc, 0x19702, 0x19704, 0x19708,
0x19710, 0x19720, 0x1973c, 0x19740, 0x19778, 0x19786, 0x1978c, 0x19798, 0x197b0, 0x197be, 0x197ce, 0x197dc,
0x197e2, 0x197e4, 0x197e8, 0x19822, 0x19824, 0x19842, 0x19848, 0x19850, 0x1985e, 0x19866, 0x1987a, 0x19882,
0x19884, 0x19890, 0x1989e, 0x198a0, 0x198bc, 0x198cc, 0x198f2, 0x198f4, 0x19902, 0x19908, 0x1991e, 0x19920,
0x1993c, 0x19940, 0x19978, 0x19986, 0x19998, 0x199ce, 0x199e2, 0x199e4, 0x199e8, 0x19a08, 0x19a10, 0x19a1e,
0x19a20, 0x19a3c, 0x19a40, 0x19a78, 0x19af0, 0x19b18, 0x19b3e, 0x19b60, 0x19b9c, 0x19bc2, 0x19bc4, 0x19bc8,
0x19bd0, 0x19be6, 0x19c2e, 0x19c34, 0x19c4e, 0x19c5c, 0x19c62, 0x19c64, 0x19c68, 0x19c8e, 0x19c9c, 0x19cb8,
0x19cc2, 0x19cc8, 0x19cd0, 0x19ce6, 0x19cfa, 0x19d0e, 0x19d1c, 0x19d38, 0x19d70, 0x19d7e, 0x19d82, 0x19d84,
0x19d88, 0x19d90, 0x19da0, 0x19dcc, 0x19df2, 0x19df4, 0x19e16, 0x19e26, 0x19e2c, 0x19e46, 0x19e4c, 0x19e58,
0x19e74, 0x19e86, 0x19e8c, 0x19e98, 0x19eb0, 0x19ebe, 0x19ece, 0x19ee2, 0x19ee4, 0x19ee8, 0x19f0a, 0x19f12,
0x19f14, 0x19f22, 0x19f24, 0x19f28, 0x19f42, 0x19f44, 0x19f48, 0x19f50, 0x19f5e, 0x19f6c, 0x19f9a, 0x19fae,
0x19fb2, 0x19fb4, 0x1a046, 0x1a04c, 0x1a072, 0x1a074, 0x1a086, 0x1a08c, 0x1a098, 0x1a0b0, 0x1a0be, 0x1a0e2,
0x1a0e4, 0x1a0e8, 0x1a0f6, 0x1a106, 0x1a10c, 0x1a118, 0x1a130, 0x1a13e, 0x1a160, 0x1a17c, 0x1a18e, 0x1a19c,
0x1a1b8, 0x1a1c2, 0x1a1c4, 0x1a1c8, 0x1a1d0, 0x1a1de, 0x1a1e6, 0x1a1ec, 0x1a218, 0x1a230, 0x1a23e, 0x1a260,
0x1a27c, 0x1a2c0, 0x1a2f8, 0x1a31c, 0x1a338, 0x1a370, 0x1a37e, 0x1a382, 0x1a384, 0x1a388, 0x1a390, 0x1a39e,
0x1a3a0, 0x1a3bc, 0x1a3c6, 0x1a3cc, 0x1a3d8, 0x1a3ee, 0x1a3f2, 0x1a3f4, 0x1a418, 0x1a430, 0x1a43e, 0x1a460,
0x1a47c, 0x1a4c0, 0x1a4f8, 0x1a5f0, 0x1a61c, 0x1a638, 0x1a670, 0x1a67e, 0x1a6e0, 0x1a6fc, 0x1a702, 0x1a704,
0x1a708, 0x1a710, 0x1a71e, 0x1a720, 0x1a73c, 0x1a740, 0x1a778, 0x1a786, 0x1a78c, 0x1a798, 0x1a7b0, 0x1a7be,
0x1a7ce, 0x1a7dc, 0x1a7e2, 0x1a7e4, 0x1a7e8, 0x1a830, 0x1a860, 0x1a87c, 0x1a8c0, 0x1a8f8, 0x1a9f0, 0x1abe0,
0x1ac70, 0x1ac7e, 0x1ace0, 0x1acfc, 0x1adc0, 0x1adf8, 0x1ae04, 0x1ae08, 0x1ae10, 0x1ae20, 0x1ae3c, 0x1ae40,
0x1ae78, 0x1aef0, 0x1af06, 0x1af0c, 0x1af18, 0x1af30, 0x1af3e, 0x1af60, 0x1af7c, 0x1af8e, 0x1af9c, 0x1afb8,
0x1afc4, 0x1afc8, 0x1afd0, 0x1afde, 0x1b042, 0x1b05e, 0x1b07a, 0x1b082, 0x1b084, 0x1b088, 0x1b090, 0x1b09e,
0x1b0a0, 0x1b0bc, 0x1b0cc, 0x1b0f2, 0x1b0f4, 0x1b102, 0x1b104, 0x1b108, 0x1b110, 0x1b11e, 0x1b120, 0x1b13c,
0x1b140, 0x1b178, 0x1b186, 0x1b198, 0x1b1ce, 0x1b1e2, 0x1b1e4, 0x1b1e8, 0x1b204, 0x1b208, 0x1b210, 0x1b21e,
0x1b220, 0x1b23c, 0x1b240, 0x1b278, 0x1b2f0, 0x1b30c, 0x1b33e, 0x1b360, 0x1b39c, 0x1b3c2, 0x1b3c4, 0x1b3c8,
0x1b3d0, 0x1b3e6, 0x1b410, 0x1b41e, 0x1b420, 0x1b43c, 0x1b440, 0x1b478, 0x1b4f0, 0x1b5e0, 0x1b618, 0x1b660,
0x1b67c, 0x1b6c0, 0x1b738, 0x1b782, 0x1b784, 0x1b788, 0x1b790, 0x1b79e, 0x1b7a0, 0x1b7cc, 0x1b82e, 0x1b84e,
0x1b85c, 0x1b88e, 0x1b89c, 0x1b8b8, 0x1b8c2, 0x1b8c4, 0x1b8c8, 0x1b8d0, 0x1b8e6, 0x1b8fa, 0x1b90e, 0x1b91c,
0x1b938, 0x1b970, 0x1b97e, 0x1b982, 0x1b984, 0x1b988, 0x1b990, 0x1b99e, 0x1b9a0, 0x1b9cc, 0x1b9f2, 0x1b9f4,
0x1ba0e, 0x1ba1c, 0x1ba38, 0x1ba70, 0x1ba7e, 0x1bae0, 0x1bafc, 0x1bb08, 0x1bb10, 0x1bb20, 0x1bb3c, 0x1bb40,
0x1bb98, 0x1bbce, 0x1bbe2, 0x1bbe4, 0x1bbe8, 0x1bc16, 0x1bc26, 0x1bc2c, 0x1bc46, 0x1bc4c, 0x1bc58, 0x1bc72,
0x1bc74, 0x1bc86, 0x1bc8c, 0x1bc98, 0x1bcb0, 0x1bcbe, 0x1bcce, 0x1bce2, 0x1bce4, 0x1bce8, 0x1bd06, 0x1bd0c,
0x1bd18, 0x1bd30, 0x1bd3e, 0x1bd60, 0x1bd7c, 0x1bd9c, 0x1bdc2, 0x1bdc4, 0x1bdc8, 0x1bdd0, 0x1bde6, 0x1bdfa,
0x1be12, 0x1be14, 0x1be22, 0x1be24, 0x1be28, 0x1be42, 0x1be44, 0x1be48, 0x1be50, 0x1be5e, 0x1be66, 0x1be82,
0x1be84, 0x1be88, 0x1be90, 0x1be9e, 0x1bea0, 0x1bebc, 0x1becc, 0x1bef4, 0x1bf1a, 0x1bf2e, 0x1bf32, 0x1bf34,
0x1bf4e, 0x1bf5c, 0x1bf62, 0x1bf64, 0x1bf68, 0x1c09a, 0x1c0b2, 0x1c0b4, 0x1c11a, 0x1c132, 0x1c134, 0x1c162,
0x1c164, 0x1c168, 0x1c176, 0x1c1ba, 0x1c21a, 0x1c232, 0x1c234, 0x1c24e, 0x1c25c, 0x1c262, 0x1c264, 0x1c268,
0x1c276, 0x1c28e, 0x1c2c2, 0x1c2c4, 0x1c2c8, 0x1c2d0, 0x1c2de, 0x1c2e6, 0x1c2ec, 0x1c2fa, 0x1c316, 0x1c326,
0x1c33a, 0x1c346, 0x1c34c, 0x1c372, 0x1c374, 0x1c41a, 0x1c42e, 0x1c432, 0x1c434, 0x1c44e, 0x1c45c, 0x1c462,
0x1c464, 0x1c468, 0x1c476, 0x1c48e, 0x1c49c, 0x1c4b8, 0x1c4c2, 0x1c4c8, 0x1c4d0, 0x1c4de, 0x1c4e6, 0x1c4ec,
0x1c4fa, 0x1c51c, 0x1c538, 0x1c570, 0x1c57e, 0x1c582, 0x1c584, 0x1c588, 0x1c590, 0x1c59e, 0x1c5a0, 0x1c5bc,
0x1c5c6, 0x1c5cc, 0x1c5d8, 0x1c5ee, 0x1c5f2, 0x1c5f4, 0x1c616, 0x1c626, 0x1c62c, 0x1c63a, 0x1c646, 0x1c64c,
0x1c658, 0x1c66e, 0x1c672, 0x1c674, 0x1c686, 0x1c68c, 0x1c698, 0x1c6b0, 0x1c6be, 0x1c6ce, 0x1c6dc, 0x1c6e2,
0x1c6e4, 0x1c6e8, 0x1c712, 0x1c714, 0x1c722, 0x1c728, 0x1c736, 0x1c742, 0x1c744, 0x1c748, 0x1c750, 0x1c75e,
0x1c766, 0x1c76c, 0x1c77a, 0x1c7ae, 0x1c7d6, 0x1c7ea, 0x1c81a, 0x1c82e, 0x1c832, 0x1c834, 0x1c84e, 0x1c85c,
0x1c862, 0x1c864, 0x1c868, 0x1c876, 0x1c88e, 0x1c89c, 0x1c8b8, 0x1c8c2, 0x1c8c8, 0x1c8d0, 0x1c8de, 0x1c8e6,
0x1c8ec, 0x1c8fa, 0x1c90e, 0x1c938, 0x1c970, 0x1c97e, 0x1c982, 0x1c984, 0x1c990, 0x1c99e, 0x1c9a0, 0x1c9bc,
0x1c9c6, 0x1c9cc, 0x1c9d8, 0x1c9ee, 0x1c9f2, 0x1c9f4, 0x1ca38, 0x1ca70, 0x1ca7e, 0x1cae0, 0x1cafc, 0x1cb02,
0x1cb04, 0x1cb08, 0x1cb10, 0x1cb20, 0x1cb3c, 0x1cb40, 0x1cb78, 0x1cb86, 0x1cb8c, 0x1cb98, 0x1cbb0, 0x1cbbe,
0x1cbce, 0x1cbdc, 0x1cbe2, 0x1cbe4, 0x1cbe8, 0x1cbf6, 0x1cc16, 0x1cc26, 0x1cc2c, 0x1cc3a, 0x1cc46, 0x1cc58,
0x1cc72, 0x1cc74, 0x1cc86, 0x1ccb0, 0x1ccbe, 0x1ccce, 0x1cce2, 0x1cce4, 0x1cce8, 0x1cd06, 0x1cd0c, 0x1cd18,
0x1cd30, 0x1cd3e, 0x1cd60, 0x1cd7c, 0x1cd9c, 0x1cdc2, 0x1cdc4, 0x1cdc8, 0x1cdd0, 0x1cdde, 0x1cde6, 0x1cdfa,
0x1ce22, 0x1ce28, 0x1ce42, 0x1ce50, 0x1ce5e, 0x1ce66, 0x1ce7a, 0x1ce82, 0x1ce84, 0x1ce88, 0x1ce90, 0x1ce9e,
0x1cea0, 0x1cebc, 0x1cecc, 0x1cef2, 0x1cef4, 0x1cf2e, 0x1cf32, 0x1cf34, 0x1cf4e, 0x1cf5c, 0x1cf62, 0x1cf64,
0x1cf68, 0x1cf96, 0x1cfa6, 0x1cfac, 0x1cfca, 0x1cfd2, 0x1cfd4, 0x1d02e, 0x1d032, 0x1d034, 0x1d04e, 0x1d05c,
0x1d062, 0x1d064, 0x1d068, 0x1d076, 0x1d08e, 0x1d09c, 0x1d0b8, 0x1d0c2, 0x1d0c4, 0x1d0c8, 0x1d0d0, 0x1d0de,
0x1d0e6, 0x1d0ec, 0x1d0fa, 0x1d11c, 0x1d138, 0x1d170, 0x1d17e, 0x1d182, 0x1d184, 0x1d188, 0x1d190, 0x1d19e,
0x1d1a0, 0x1d1bc, 0x1d1c6, 0x1d1cc, 0x1d1d8, 0x1d1ee, 0x1d1f2, 0x1d1f4, 0x1d21c, 0x1d238, 0x1d270, 0x1d27e,
0x1d2e0, 0x1d2fc, 0x1d302, 0x1d304, 0x1d308, 0x1d310, 0x1d31e, 0x1d320, 0x1d33c, 0x1d340, 0x1d378, 0x1d386,
0x1d38c, 0x1d398, 0x1d3b0, 0x1d3be, 0x1d3ce, 0x1d3dc, 0x1d3e2, 0x1d3e4, 0x1d3e8, 0x1d3f6, 0x1d470, 0x1d47e,
0x1d4e0, 0x1d4fc, 0x1d5c0, 0x1d5f8, 0x1d604, 0x1d608, 0x1d610, 0x1d620, 0x1d640, 0x1d678, 0x1d6f0, 0x1d706,
0x1d70c, 0x1d718, 0x1d730, 0x1d73e, 0x1d760, 0x1d77c, 0x1d78e, 0x1d79c, 0x1d7b8, 0x1d7c2, 0x1d7c4, 0x1d7c8,
0x1d7d0, 0x1d7de, 0x1d7e6, 0x1d7ec, 0x1d826, 0x1d82c, 0x1d83a, 0x1d846, 0x1d84c, 0x1d858, 0x1d872, 0x1d874,
0x1d886, 0x1d88c, 0x1d898, 0x1d8b0, 0x1d8be, 0x1d8ce, 0x1d8e2, 0x1d8e4, 0x1d8e8, 0x1d8f6, 0x1d90c, 0x1d918,
0x1d930, 0x1d93e, 0x1d960, 0x1d97c, 0x1d99c, 0x1d9c2, 0x1d9c4, 0x1d9c8, 0x1d9d0, 0x1d9e6, 0x1d9fa, 0x1da0c,
0x1da18, 0x1da30, 0x1da3e, 0x1da60, 0x1da7c, 0x1dac0, 0x1daf8, 0x1db38, 0x1db82, 0x1db84, 0x1db88, 0x1db90,
0x1db9e, 0x1dba0, 0x1dbcc, 0x1dbf2, 0x1dbf4, 0x1dc22, 0x1dc42, 0x1dc44, 0x1dc48, 0x1dc50, 0x1dc5e, 0x1dc66,
0x1dc7a, 0x1dc82, 0x1dc84, 0x1dc88, 0x1dc90, 0x1dc9e, 0x1dca0, 0x1dcbc, 0x1dccc, 0x1dcf2, 0x1dcf4, 0x1dd04,
0x1dd08, 0x1dd10, 0x1dd1e, 0x1dd20, 0x1dd3c, 0x1dd40, 0x1dd78, 0x1dd86, 0x1dd98, 0x1ddce, 0x1dde2, 0x1dde4,
0x1dde8, 0x1de2e, 0x1de32, 0x1de34, 0x1de4e, 0x1de5c, 0x1de62, 0x1de64, 0x1de68, 0x1de8e, 0x1de9c, 0x1deb8,
0x1dec2, 0x1dec4, 0x1dec8, 0x1ded0, 0x1dee6, 0x1defa, 0x1df16, 0x1df26, 0x1df2c, 0x1df46, 0x1df4c, 0x1df58,
0x1df72, 0x1df74, 0x1df8a, 0x1df92, 0x1df94, 0x1dfa2, 0x1dfa4, 0x1dfa8, 0x1e08a, 0x1e092, 0x1e094, 0x1e0a2,
0x1e0a4, 0x1e0a8, 0x1e0b6, 0x1e0da, 0x1e10a, 0x1e112, 0x1e114, 0x1e122, 0x1e124, 0x1e128, 0x1e136, 0x1e142,
0x1e144, 0x1e148, 0x1e150, 0x1e166, 0x1e16c, 0x1e17a, 0x1e19a, 0x1e1b2, 0x1e1b4, 0x1e20a, 0x1e212, 0x1e214,
0x1e222, 0x1e224, 0x1e228, 0x1e236, 0x1e242, 0x1e248, 0x1e250, 0x1e25e, 0x1e266, 0x1e26c, 0x1e27a, 0x1e282,
0x1e284, 0x1e288, 0x1e290, 0x1e2a0, 0x1e2bc, 0x1e2c6, 0x1e2cc, 0x1e2d8, 0x1e2ee, 0x1e2f2, 0x1e2f4, 0x1e31a,
0x1e332, 0x1e334, 0x1e35c, 0x1e362, 0x1e364, 0x1e368, 0x1e3ba, 0x1e40a, 0x1e412, 0x1e414, 0x1e422, 0x1e428,
0x1e436, 0x1e442, 0x1e448, 0x1e450, 0x1e45e, 0x1e466, 0x1e46c, 0x1e47a, 0x1e482, 0x1e484, 0x1e490, 0x1e49e,
0x1e4a0, 0x1e4bc, 0x1e4c6, 0x1e4cc, 0x1e4d8, 0x1e4ee, 0x1e4f2, 0x1e4f4, 0x1e502, 0x1e504, 0x1e508, 0x1e510,
0x1e51e, 0x1e520, 0x1e53c, 0x1e540, 0x1e578, 0x1e586, 0x1e58c, 0x1e598, 0x1e5b0, 0x1e5be, 0x1e5ce, 0x1e5dc,
0x1e5e2, 0x1e5e4, 0x1e5e8, 0x1e5f6, 0x1e61a, 0x1e62e, 0x1e632, 0x1e634, 0x1e64e, 0x1e65c, 0x1e662, 0x1e668,
0x1e68e, 0x1e69c, 0x1e6b8, 0x1e6c2, 0x1e6c4, 0x1e6c8, 0x1e6d0, 0x1e6e6, 0x1e6fa, 0x1e716, 0x1e726, 0x1e72c,
0x1e73a, 0x1e746, 0x1e74c, 0x1e758, 0x1e772, 0x1e774, 0x1e792, 0x1e794, 0x1e7a2, 0x1e7a4, 0x1e7a8, 0x1e7b6,
0x1e812, 0x1e814, 0x1e822, 0x1e824, 0x1e828, 0x1e836, 0x1e842, 0x1e844, 0x1e848, 0x1e850, 0x1e85e, 0x1e866,
0x1e86c, 0x1e87a, 0x1e882, 0x1e884, 0x1e888, 0x1e890, 0x1e89e, 0x1e8a0, 0x1e8bc, 0x1e8c6, 0x1e8cc, 0x1e8d8,
0x1e8ee, 0x1e8f2, 0x1e8f4, 0x1e902, 0x1e904, 0x1e908, 0x1e910, 0x1e920, 0x1e93c, 0x1e940, 0x1e978, 0x1e986,
0x1e98c, 0x1e998, 0x1e9b0, 0x1e9be, 0x1e9ce, 0x1e9dc, 0x1e9e2, 0x1e9e4, 0x1e9e8, 0x1e9f6, 0x1ea04, 0x1ea08,
0x1ea10, 0x1ea20, 0x1ea40, 0x1ea78, 0x1eaf0, 0x1eb06, 0x1eb0c, 0x1eb18, 0x1eb30, 0x1eb3e, 0x1eb60, 0x1eb7c,
0x1eb8e, 0x1eb9c, 0x1ebb8, 0x1ebc2, 0x1ebc4, 0x1ebc8, 0x1ebd0, 0x1ebde, 0x1ebe6, 0x1ebec, 0x1ec1a, 0x1ec2e,
0x1ec32, 0x1ec34, 0x1ec4e, 0x1ec5c, 0x1ec62, 0x1ec64, 0x1ec68, 0x1ec8e, 0x1ec9c, 0x1ecb8, 0x1ecc2, 0x1ecc4,
0x1ecc8, 0x1ecd0, 0x1ece6, 0x1ecfa, 0x1ed0e, 0x1ed1c, 0x1ed38, 0x1ed70, 0x1ed7e, 0x1ed82, 0x1ed84, 0x1ed88,
0x1ed90, 0x1ed9e, 0x1eda0, 0x1edcc, 0x1edf2, 0x1edf4, 0x1ee16, 0x1ee26, 0x1ee2c, 0x1ee3a, 0x1ee46, 0x1ee4c,
0x1ee58, 0x1ee6e, 0x1ee72, 0x1ee74, 0x1ee86, 0x1ee8c, 0x1ee98, 0x1eeb0, 0x1eebe, 0x1eece, 0x1eedc, 0x1eee2,
0x1eee4, 0x1eee8, 0x1ef12, 0x1ef22, 0x1ef24, 0x1ef28, 0x1ef36, 0x1ef42, 0x1ef44, 0x1ef48, 0x1ef50, 0x1ef5e,
0x1ef66, 0x1ef6c, 0x1ef7a, 0x1efae, 0x1efb2, 0x1efb4, 0x1efd6, 0x1f096, 0x1f0a6, 0x1f0ac, 0x1f0ba, 0x1f0ca,
0x1f0d2, 0x1f0d4, 0x1f116, 0x1f126, 0x1f12c, 0x1f13a, 0x1f146, 0x1f14c, 0x1f158, 0x1f16e, 0x1f172, 0x1f174,
0x1f18a, 0x1f192, 0x1f194, 0x1f1a2, 0x1f1a4, 0x1f1a8, 0x1f1da, 0x1f216, 0x1f226, 0x1f22c, 0x1f23a, 0x1f246,
0x1f258, 0x1f26e, 0x1f272, 0x1f274, 0x1f286, 0x1f28c, 0x1f298, 0x1f2b0, 0x1f2be, 0x1f2ce, 0x1f2dc, 0x1f2e2,
0x1f2e4, 0x1f2e8, 0x1f2f6, 0x1f30a, 0x1f312, 0x1f314, 0x1f322, 0x1f328, 0x1f342, 0x1f344, 0x1f348, 0x1f350,
0x1f35e, 0x1f366, 0x1f37a, 0x1f39a, 0x1f3ae, 0x1f3b2, 0x1f3b4, 0x1f416, 0x1f426, 0x1f42c, 0x1f43a, 0x1f446,
0x1f44c, 0x1f458, 0x1f46e, 0x1f472, 0x1f474, 0x1f486, 0x1f48c, 0x1f498, 0x1f4b0, 0x1f4be, 0x1f4ce, 0x1f4dc,
0x1f4e2, 0x1f4e4, 0x1f4e8, 0x1f4f6, 0x1f506, 0x1f50c, 0x1f518, 0x1f530, 0x1f53e, 0x1f560, 0x1f57c, 0x1f58e,
0x1f59c, 0x1f5b8, 0x1f5c2, 0x1f5c4, 0x1f5c8, 0x1f5d0, 0x1f5de, 0x1f5e6, 0x1f5ec, 0x1f5fa, 0x1f60a, 0x1f612,
0x1f614, 0x1f622, 0x1f624, 0x1f628, 0x1f636, 0x1f642, 0x1f644, 0x1f648, 0x1f650, 0x1f65e, 0x1f666, 0x1f67a,
0x1f682, 0x1f684, 0x1f688, 0x1f690, 0x1f69e, 0x1f6a0, 0x1f6bc, 0x1f6cc, 0x1f6f2, 0x1f6f4, 0x1f71a, 0x1f72e,
0x1f732, 0x1f734, 0x1f74e, 0x1f75c, 0x1f762, 0x1f764, 0x1f768, 0x1f776, 0x1f796, 0x1f7a6, 0x1f7ac, 0x1f7ba,
0x1f7d2, 0x1f7d4, 0x1f89a, 0x1f8ae, 0x1f8b2, 0x1f8b4, 0x1f8d6, 0x1f8ea, 0x1f91a, 0x1f92e, 0x1f932, 0x1f934,
0x1f94e, 0x1f95c, 0x1f962, 0x1f964, 0x1f968, 0x1f976, 0x1f996, 0x1f9a6, 0x1f9ac, 0x1f9ba, 0x1f9ca, 0x1f9d2,
0x1f9d4, 0x1fa1a, 0x1fa2e, 0x1fa32, 0x1fa34, 0x1fa4e, 0x1fa5c, 0x1fa62, 0x1fa64, 0x1fa68, 0x1fa76, 0x1fa8e,
0x1fa9c, 0x1fab8, 0x1fac2, 0x1fac4, 0x1fac8, 0x1fad0, 0x1fade, 0x1fae6, 0x1faec, 0x1fb16, 0x1fb26, 0x1fb2c,
0x1fb3a, 0x1fb46, 0x1fb4c, 0x1fb58, 0x1fb6e, 0x1fb72, 0x1fb74, 0x1fb8a, 0x1fb92, 0x1fb94, 0x1fba2, 0x1fba4,
0x1fba8, 0x1fbb6, 0x1fbda};
/// <summary>
/// This table contains to codewords for all symbols.
/// </summary>
private static readonly int[] CODEWORD_TABLE = {
2627, 1819, 2622, 2621, 1813, 1812, 2729, 2724, 2723, 2779, 2774, 2773, 902, 896, 908, 868, 865, 861, 859, 2511,
873, 871, 1780, 835, 2493, 825, 2491, 842, 837, 844, 1764, 1762, 811, 810, 809, 2483, 807, 2482, 806, 2480, 815,
814, 813, 812, 2484, 817, 816, 1745, 1744, 1742, 1746, 2655, 2637, 2635, 2626, 2625, 2623, 2628, 1820, 2752,
2739, 2737, 2728, 2727, 2725, 2730, 2785, 2783, 2778, 2777, 2775, 2780, 787, 781, 747, 739, 736, 2413, 754, 752,
1719, 692, 689, 681, 2371, 678, 2369, 700, 697, 694, 703, 1688, 1686, 642, 638, 2343, 631, 2341, 627, 2338, 651,
646, 643, 2345, 654, 652, 1652, 1650, 1647, 1654, 601, 599, 2322, 596, 2321, 594, 2319, 2317, 611, 610, 608, 606,
2324, 603, 2323, 615, 614, 612, 1617, 1616, 1614, 1612, 616, 1619, 1618, 2575, 2538, 2536, 905, 901, 898, 909,
2509, 2507, 2504, 870, 867, 864, 860, 2512, 875, 872, 1781, 2490, 2489, 2487, 2485, 1748, 836, 834, 832, 830,
2494, 827, 2492, 843, 841, 839, 845, 1765, 1763, 2701, 2676, 2674, 2653, 2648, 2656, 2634, 2633, 2631, 2629,
1821, 2638, 2636, 2770, 2763, 2761, 2750, 2745, 2753, 2736, 2735, 2733, 2731, 1848, 2740, 2738, 2786, 2784, 591,
588, 576, 569, 566, 2296, 1590, 537, 534, 526, 2276, 522, 2274, 545, 542, 539, 548, 1572, 1570, 481, 2245, 466,
2242, 462, 2239, 492, 485, 482, 2249, 496, 494, 1534, 1531, 1528, 1538, 413, 2196, 406, 2191, 2188, 425, 419,
2202, 415, 2199, 432, 430, 427, 1472, 1467, 1464, 433, 1476, 1474, 368, 367, 2160, 365, 2159, 362, 2157, 2155,
2152, 378, 377, 375, 2166, 372, 2165, 369, 2162, 383, 381, 379, 2168, 1419, 1418, 1416, 1414, 385, 1411, 384,
1423, 1422, 1420, 1424, 2461, 802, 2441, 2439, 790, 786, 783, 794, 2409, 2406, 2403, 750, 742, 738, 2414, 756,
753, 1720, 2367, 2365, 2362, 2359, 1663, 693, 691, 684, 2373, 680, 2370, 702, 699, 696, 704, 1690, 1687, 2337,
2336, 2334, 2332, 1624, 2329, 1622, 640, 637, 2344, 634, 2342, 630, 2340, 650, 648, 645, 2346, 655, 653, 1653,
1651, 1649, 1655, 2612, 2597, 2595, 2571, 2568, 2565, 2576, 2534, 2529, 2526, 1787, 2540, 2537, 907, 904, 900,
910, 2503, 2502, 2500, 2498, 1768, 2495, 1767, 2510, 2508, 2506, 869, 866, 863, 2513, 876, 874, 1782, 2720, 2713,
2711, 2697, 2694, 2691, 2702, 2672, 2670, 2664, 1828, 2678, 2675, 2647, 2646, 2644, 2642, 1823, 2639, 1822, 2654,
2652, 2650, 2657, 2771, 1855, 2765, 2762, 1850, 1849, 2751, 2749, 2747, 2754, 353, 2148, 344, 342, 336, 2142,
332, 2140, 345, 1375, 1373, 306, 2130, 299, 2128, 295, 2125, 319, 314, 311, 2132, 1354, 1352, 1349, 1356, 262,
257, 2101, 253, 2096, 2093, 274, 273, 267, 2107, 263, 2104, 280, 278, 275, 1316, 1311, 1308, 1320, 1318, 2052,
202, 2050, 2044, 2040, 219, 2063, 212, 2060, 208, 2055, 224, 221, 2066, 1260, 1258, 1252, 231, 1248, 229, 1266,
1264, 1261, 1268, 155, 1998, 153, 1996, 1994, 1991, 1988, 165, 164, 2007, 162, 2006, 159, 2003, 2000, 172, 171,
169, 2012, 166, 2010, 1186, 1184, 1182, 1179, 175, 1176, 173, 1192, 1191, 1189, 1187, 176, 1194, 1193, 2313,
2307, 2305, 592, 589, 2294, 2292, 2289, 578, 572, 568, 2297, 580, 1591, 2272, 2267, 2264, 1547, 538, 536, 529,
2278, 525, 2275, 547, 544, 541, 1574, 1571, 2237, 2235, 2229, 1493, 2225, 1489, 478, 2247, 470, 2244, 465, 2241,
493, 488, 484, 2250, 498, 495, 1536, 1533, 1530, 1539, 2187, 2186, 2184, 2182, 1432, 2179, 1430, 2176, 1427, 414,
412, 2197, 409, 2195, 405, 2193, 2190, 426, 424, 421, 2203, 418, 2201, 431, 429, 1473, 1471, 1469, 1466, 434,
1477, 1475, 2478, 2472, 2470, 2459, 2457, 2454, 2462, 803, 2437, 2432, 2429, 1726, 2443, 2440, 792, 789, 785,
2401, 2399, 2393, 1702, 2389, 1699, 2411, 2408, 2405, 745, 741, 2415, 758, 755, 1721, 2358, 2357, 2355, 2353,
1661, 2350, 1660, 2347, 1657, 2368, 2366, 2364, 2361, 1666, 690, 687, 2374, 683, 2372, 701, 698, 705, 1691, 1689,
2619, 2617, 2610, 2608, 2605, 2613, 2593, 2588, 2585, 1803, 2599, 2596, 2563, 2561, 2555, 1797, 2551, 1795, 2573,
2570, 2567, 2577, 2525, 2524, 2522, 2520, 1786, 2517, 1785, 2514, 1783, 2535, 2533, 2531, 2528, 1788, 2541, 2539,
906, 903, 911, 2721, 1844, 2715, 2712, 1838, 1836, 2699, 2696, 2693, 2703, 1827, 1826, 1824, 2673, 2671, 2669,
2666, 1829, 2679, 2677, 1858, 1857, 2772, 1854, 1853, 1851, 1856, 2766, 2764, 143, 1987, 139, 1986, 135, 133,
131, 1984, 128, 1983, 125, 1981, 138, 137, 136, 1985, 1133, 1132, 1130, 112, 110, 1974, 107, 1973, 104, 1971,
1969, 122, 121, 119, 117, 1977, 114, 1976, 124, 1115, 1114, 1112, 1110, 1117, 1116, 84, 83, 1953, 81, 1952, 78,
1950, 1948, 1945, 94, 93, 91, 1959, 88, 1958, 85, 1955, 99, 97, 95, 1961, 1086, 1085, 1083, 1081, 1078, 100,
1090, 1089, 1087, 1091, 49, 47, 1917, 44, 1915, 1913, 1910, 1907, 59, 1926, 56, 1925, 53, 1922, 1919, 66, 64,
1931, 61, 1929, 1042, 1040, 1038, 71, 1035, 70, 1032, 68, 1048, 1047, 1045, 1043, 1050, 1049, 12, 10, 1869, 1867,
1864, 1861, 21, 1880, 19, 1877, 1874, 1871, 28, 1888, 25, 1886, 22, 1883, 982, 980, 977, 974, 32, 30, 991, 989,
987, 984, 34, 995, 994, 992, 2151, 2150, 2147, 2146, 2144, 356, 355, 354, 2149, 2139, 2138, 2136, 2134, 1359,
343, 341, 338, 2143, 335, 2141, 348, 347, 346, 1376, 1374, 2124, 2123, 2121, 2119, 1326, 2116, 1324, 310, 308,
305, 2131, 302, 2129, 298, 2127, 320, 318, 316, 313, 2133, 322, 321, 1355, 1353, 1351, 1357, 2092, 2091, 2089,
2087, 1276, 2084, 1274, 2081, 1271, 259, 2102, 256, 2100, 252, 2098, 2095, 272, 269, 2108, 266, 2106, 281, 279,
277, 1317, 1315, 1313, 1310, 282, 1321, 1319, 2039, 2037, 2035, 2032, 1203, 2029, 1200, 1197, 207, 2053, 205,
2051, 201, 2049, 2046, 2043, 220, 218, 2064, 215, 2062, 211, 2059, 228, 226, 223, 2069, 1259, 1257, 1254, 232,
1251, 230, 1267, 1265, 1263, 2316, 2315, 2312, 2311, 2309, 2314, 2304, 2303, 2301, 2299, 1593, 2308, 2306, 590,
2288, 2287, 2285, 2283, 1578, 2280, 1577, 2295, 2293, 2291, 579, 577, 574, 571, 2298, 582, 581, 1592, 2263, 2262,
2260, 2258, 1545, 2255, 1544, 2252, 1541, 2273, 2271, 2269, 2266, 1550, 535, 532, 2279, 528, 2277, 546, 543, 549,
1575, 1573, 2224, 2222, 2220, 1486, 2217, 1485, 2214, 1482, 1479, 2238, 2236, 2234, 2231, 1496, 2228, 1492, 480,
477, 2248, 473, 2246, 469, 2243, 490, 487, 2251, 497, 1537, 1535, 1532, 2477, 2476, 2474, 2479, 2469, 2468, 2466,
2464, 1730, 2473, 2471, 2453, 2452, 2450, 2448, 1729, 2445, 1728, 2460, 2458, 2456, 2463, 805, 804, 2428, 2427,
2425, 2423, 1725, 2420, 1724, 2417, 1722, 2438, 2436, 2434, 2431, 1727, 2444, 2442, 793, 791, 788, 795, 2388,
2386, 2384, 1697, 2381, 1696, 2378, 1694, 1692, 2402, 2400, 2398, 2395, 1703, 2392, 1701, 2412, 2410, 2407, 751,
748, 744, 2416, 759, 757, 1807, 2620, 2618, 1806, 1805, 2611, 2609, 2607, 2614, 1802, 1801, 1799, 2594, 2592,
2590, 2587, 1804, 2600, 2598, 1794, 1793, 1791, 1789, 2564, 2562, 2560, 2557, 1798, 2554, 1796, 2574, 2572, 2569,
2578, 1847, 1846, 2722, 1843, 1842, 1840, 1845, 2716, 2714, 1835, 1834, 1832, 1830, 1839, 1837, 2700, 2698, 2695,
2704, 1817, 1811, 1810, 897, 862, 1777, 829, 826, 838, 1760, 1758, 808, 2481, 1741, 1740, 1738, 1743, 2624, 1818,
2726, 2776, 782, 740, 737, 1715, 686, 679, 695, 1682, 1680, 639, 628, 2339, 647, 644, 1645, 1643, 1640, 1648,
602, 600, 597, 595, 2320, 593, 2318, 609, 607, 604, 1611, 1610, 1608, 1606, 613, 1615, 1613, 2328, 926, 924, 892,
886, 899, 857, 850, 2505, 1778, 824, 823, 821, 819, 2488, 818, 2486, 833, 831, 828, 840, 1761, 1759, 2649, 2632,
2630, 2746, 2734, 2732, 2782, 2781, 570, 567, 1587, 531, 527, 523, 540, 1566, 1564, 476, 467, 463, 2240, 486,
483, 1524, 1521, 1518, 1529, 411, 403, 2192, 399, 2189, 423, 416, 1462, 1457, 1454, 428, 1468, 1465, 2210, 366,
363, 2158, 360, 2156, 357, 2153, 376, 373, 370, 2163, 1410, 1409, 1407, 1405, 382, 1402, 380, 1417, 1415, 1412,
1421, 2175, 2174, 777, 774, 771, 784, 732, 725, 722, 2404, 743, 1716, 676, 674, 668, 2363, 665, 2360, 685, 1684,
1681, 626, 624, 622, 2335, 620, 2333, 617, 2330, 641, 635, 649, 1646, 1644, 1642, 2566, 928, 925, 2530, 2527,
894, 891, 888, 2501, 2499, 2496, 858, 856, 854, 851, 1779, 2692, 2668, 2665, 2645, 2643, 2640, 2651, 2768, 2759,
2757, 2744, 2743, 2741, 2748, 352, 1382, 340, 337, 333, 1371, 1369, 307, 300, 296, 2126, 315, 312, 1347, 1342,
1350, 261, 258, 250, 2097, 246, 2094, 271, 268, 264, 1306, 1301, 1298, 276, 1312, 1309, 2115, 203, 2048, 195,
2045, 191, 2041, 213, 209, 2056, 1246, 1244, 1238, 225, 1234, 222, 1256, 1253, 1249, 1262, 2080, 2079, 154, 1997,
150, 1995, 147, 1992, 1989, 163, 160, 2004, 156, 2001, 1175, 1174, 1172, 1170, 1167, 170, 1164, 167, 1185, 1183,
1180, 1177, 174, 1190, 1188, 2025, 2024, 2022, 587, 586, 564, 559, 556, 2290, 573, 1588, 520, 518, 512, 2268,
508, 2265, 530, 1568, 1565, 461, 457, 2233, 450, 2230, 446, 2226, 479, 471, 489, 1526, 1523, 1520, 397, 395,
2185, 392, 2183, 389, 2180, 2177, 410, 2194, 402, 422, 1463, 1461, 1459, 1456, 1470, 2455, 799, 2433, 2430, 779,
776, 773, 2397, 2394, 2390, 734, 728, 724, 746, 1717, 2356, 2354, 2351, 2348, 1658, 677, 675, 673, 670, 667, 688,
1685, 1683, 2606, 2589, 2586, 2559, 2556, 2552, 927, 2523, 2521, 2518, 2515, 1784, 2532, 895, 893, 890, 2718,
2709, 2707, 2689, 2687, 2684, 2663, 2662, 2660, 2658, 1825, 2667, 2769, 1852, 2760, 2758, 142, 141, 1139, 1138,
134, 132, 129, 126, 1982, 1129, 1128, 1126, 1131, 113, 111, 108, 105, 1972, 101, 1970, 120, 118, 115, 1109, 1108,
1106, 1104, 123, 1113, 1111, 82, 79, 1951, 75, 1949, 72, 1946, 92, 89, 86, 1956, 1077, 1076, 1074, 1072, 98,
1069, 96, 1084, 1082, 1079, 1088, 1968, 1967, 48, 45, 1916, 42, 1914, 39, 1911, 1908, 60, 57, 54, 1923, 50, 1920,
1031, 1030, 1028, 1026, 67, 1023, 65, 1020, 62, 1041, 1039, 1036, 1033, 69, 1046, 1044, 1944, 1943, 1941, 11, 9,
1868, 7, 1865, 1862, 1859, 20, 1878, 16, 1875, 13, 1872, 970, 968, 966, 963, 29, 960, 26, 23, 983, 981, 978, 975,
33, 971, 31, 990, 988, 985, 1906, 1904, 1902, 993, 351, 2145, 1383, 331, 330, 328, 326, 2137, 323, 2135, 339,
1372, 1370, 294, 293, 291, 289, 2122, 286, 2120, 283, 2117, 309, 303, 317, 1348, 1346, 1344, 245, 244, 242, 2090,
239, 2088, 236, 2085, 2082, 260, 2099, 249, 270, 1307, 1305, 1303, 1300, 1314, 189, 2038, 186, 2036, 183, 2033,
2030, 2026, 206, 198, 2047, 194, 216, 1247, 1245, 1243, 1240, 227, 1237, 1255, 2310, 2302, 2300, 2286, 2284,
2281, 565, 563, 561, 558, 575, 1589, 2261, 2259, 2256, 2253, 1542, 521, 519, 517, 514, 2270, 511, 533, 1569,
1567, 2223, 2221, 2218, 2215, 1483, 2211, 1480, 459, 456, 453, 2232, 449, 474, 491, 1527, 1525, 1522, 2475, 2467,
2465, 2451, 2449, 2446, 801, 800, 2426, 2424, 2421, 2418, 1723, 2435, 780, 778, 775, 2387, 2385, 2382, 2379,
1695, 2375, 1693, 2396, 735, 733, 730, 727, 749, 1718, 2616, 2615, 2604, 2603, 2601, 2584, 2583, 2581, 2579,
1800, 2591, 2550, 2549, 2547, 2545, 1792, 2542, 1790, 2558, 929, 2719, 1841, 2710, 2708, 1833, 1831, 2690, 2688,
2686, 1815, 1809, 1808, 1774, 1756, 1754, 1737, 1736, 1734, 1739, 1816, 1711, 1676, 1674, 633, 629, 1638, 1636,
1633, 1641, 598, 1605, 1604, 1602, 1600, 605, 1609, 1607, 2327, 887, 853, 1775, 822, 820, 1757, 1755, 1584, 524,
1560, 1558, 468, 464, 1514, 1511, 1508, 1519, 408, 404, 400, 1452, 1447, 1444, 417, 1458, 1455, 2208, 364, 361,
358, 2154, 1401, 1400, 1398, 1396, 374, 1393, 371, 1408, 1406, 1403, 1413, 2173, 2172, 772, 726, 723, 1712, 672,
669, 666, 682, 1678, 1675, 625, 623, 621, 618, 2331, 636, 632, 1639, 1637, 1635, 920, 918, 884, 880, 889, 849,
848, 847, 846, 2497, 855, 852, 1776, 2641, 2742, 2787, 1380, 334, 1367, 1365, 301, 297, 1340, 1338, 1335, 1343,
255, 251, 247, 1296, 1291, 1288, 265, 1302, 1299, 2113, 204, 196, 192, 2042, 1232, 1230, 1224, 214, 1220, 210,
1242, 1239, 1235, 1250, 2077, 2075, 151, 148, 1993, 144, 1990, 1163, 1162, 1160, 1158, 1155, 161, 1152, 157,
1173, 1171, 1168, 1165, 168, 1181, 1178, 2021, 2020, 2018, 2023, 585, 560, 557, 1585, 516, 509, 1562, 1559, 458,
447, 2227, 472, 1516, 1513, 1510, 398, 396, 393, 390, 2181, 386, 2178, 407, 1453, 1451, 1449, 1446, 420, 1460,
2209, 769, 764, 720, 712, 2391, 729, 1713, 664, 663, 661, 659, 2352, 656, 2349, 671, 1679, 1677, 2553, 922, 919,
2519, 2516, 885, 883, 881, 2685, 2661, 2659, 2767, 2756, 2755, 140, 1137, 1136, 130, 127, 1125, 1124, 1122, 1127,
109, 106, 102, 1103, 1102, 1100, 1098, 116, 1107, 1105, 1980, 80, 76, 73, 1947, 1068, 1067, 1065, 1063, 90, 1060,
87, 1075, 1073, 1070, 1080, 1966, 1965, 46, 43, 40, 1912, 36, 1909, 1019, 1018, 1016, 1014, 58, 1011, 55, 1008,
51, 1029, 1027, 1024, 1021, 63, 1037, 1034, 1940, 1939, 1937, 1942, 8, 1866, 4, 1863, 1, 1860, 956, 954, 952,
949, 946, 17, 14, 969, 967, 964, 961, 27, 957, 24, 979, 976, 972, 1901, 1900, 1898, 1896, 986, 1905, 1903, 350,
349, 1381, 329, 327, 324, 1368, 1366, 292, 290, 287, 284, 2118, 304, 1341, 1339, 1337, 1345, 243, 240, 237, 2086,
233, 2083, 254, 1297, 1295, 1293, 1290, 1304, 2114, 190, 187, 184, 2034, 180, 2031, 177, 2027, 199, 1233, 1231,
1229, 1226, 217, 1223, 1241, 2078, 2076, 584, 555, 554, 552, 550, 2282, 562, 1586, 507, 506, 504, 502, 2257, 499,
2254, 515, 1563, 1561, 445, 443, 441, 2219, 438, 2216, 435, 2212, 460, 454, 475, 1517, 1515, 1512, 2447, 798,
797, 2422, 2419, 770, 768, 766, 2383, 2380, 2376, 721, 719, 717, 714, 731, 1714, 2602, 2582, 2580, 2548, 2546,
2543, 923, 921, 2717, 2706, 2705, 2683, 2682, 2680, 1771, 1752, 1750, 1733, 1732, 1731, 1735, 1814, 1707, 1670,
1668, 1631, 1629, 1626, 1634, 1599, 1598, 1596, 1594, 1603, 1601, 2326, 1772, 1753, 1751, 1581, 1554, 1552, 1504,
1501, 1498, 1509, 1442, 1437, 1434, 401, 1448, 1445, 2206, 1392, 1391, 1389, 1387, 1384, 359, 1399, 1397, 1394,
1404, 2171, 2170, 1708, 1672, 1669, 619, 1632, 1630, 1628, 1773, 1378, 1363, 1361, 1333, 1328, 1336, 1286, 1281,
1278, 248, 1292, 1289, 2111, 1218, 1216, 1210, 197, 1206, 193, 1228, 1225, 1221, 1236, 2073, 2071, 1151, 1150,
1148, 1146, 152, 1143, 149, 1140, 145, 1161, 1159, 1156, 1153, 158, 1169, 1166, 2017, 2016, 2014, 2019, 1582,
510, 1556, 1553, 452, 448, 1506, 1500, 394, 391, 387, 1443, 1441, 1439, 1436, 1450, 2207, 765, 716, 713, 1709,
662, 660, 657, 1673, 1671, 916, 914, 879, 878, 877, 882, 1135, 1134, 1121, 1120, 1118, 1123, 1097, 1096, 1094,
1092, 103, 1101, 1099, 1979, 1059, 1058, 1056, 1054, 77, 1051, 74, 1066, 1064, 1061, 1071, 1964, 1963, 1007,
1006, 1004, 1002, 999, 41, 996, 37, 1017, 1015, 1012, 1009, 52, 1025, 1022, 1936, 1935, 1933, 1938, 942, 940,
938, 935, 932, 5, 2, 955, 953, 950, 947, 18, 943, 15, 965, 962, 958, 1895, 1894, 1892, 1890, 973, 1899, 1897,
1379, 325, 1364, 1362, 288, 285, 1334, 1332, 1330, 241, 238, 234, 1287, 1285, 1283, 1280, 1294, 2112, 188, 185,
181, 178, 2028, 1219, 1217, 1215, 1212, 200, 1209, 1227, 2074, 2072, 583, 553, 551, 1583, 505, 503, 500, 513,
1557, 1555, 444, 442, 439, 436, 2213, 455, 451, 1507, 1505, 1502, 796, 763, 762, 760, 767, 711, 710, 708, 706,
2377, 718, 715, 1710, 2544, 917, 915, 2681, 1627, 1597, 1595, 2325, 1769, 1749, 1747, 1499, 1438, 1435, 2204,
1390, 1388, 1385, 1395, 2169, 2167, 1704, 1665, 1662, 1625, 1623, 1620, 1770, 1329, 1282, 1279, 2109, 1214, 1207,
1222, 2068, 2065, 1149, 1147, 1144, 1141, 146, 1157, 1154, 2013, 2011, 2008, 2015, 1579, 1549, 1546, 1495, 1487,
1433, 1431, 1428, 1425, 388, 1440, 2205, 1705, 658, 1667, 1664, 1119, 1095, 1093, 1978, 1057, 1055, 1052, 1062,
1962, 1960, 1005, 1003, 1000, 997, 38, 1013, 1010, 1932, 1930, 1927, 1934, 941, 939, 936, 933, 6, 930, 3, 951,
948, 944, 1889, 1887, 1884, 1881, 959, 1893, 1891, 35, 1377, 1360, 1358, 1327, 1325, 1322, 1331, 1277, 1275,
1272, 1269, 235, 1284, 2110, 1205, 1204, 1201, 1198, 182, 1195, 179, 1213, 2070, 2067, 1580, 501, 1551, 1548,
440, 437, 1497, 1494, 1490, 1503, 761, 709, 707, 1706, 913, 912, 2198, 1386, 2164, 2161, 1621, 1766, 2103, 1208,
2058, 2054, 1145, 1142, 2005, 2002, 1999, 2009, 1488, 1429, 1426, 2200, 1698, 1659, 1656, 1975, 1053, 1957, 1954,
1001, 998, 1924, 1921, 1918, 1928, 937, 934, 931, 1879, 1876, 1873, 1870, 945, 1885, 1882, 1323, 1273, 1270,
2105, 1202, 1199, 1196, 1211, 2061, 2057, 1576, 1543, 1540, 1484, 1481, 1478, 1491, 1700};
}
}

View file

@ -1,366 +0,0 @@
/*
* Copyright 2009 ZXing 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.Collections.Generic;
using ZXing.Common;
using ZXing.PDF417.Internal;
using System;
namespace ZXing.PDF417
{
/// <summary>
/// This implementation can detect and decode PDF417 codes in an image.
///
/// <author>SITA Lab (kevin.osullivan@sita.aero)</author>
/// <author>Guenther Grau (java Core)</author>
/// <author>Stephen Furlani (C# Port)</author>
/// </summary>
public sealed class PDF417Reader : Reader
{
/// <summary>
/// NO_POINTS found.
/// </summary>
private static readonly ResultPoint[] NO_POINTS = new ResultPoint[0];
/// <summary>
/// Locates and decodes a PDF417 code in an image.
///
/// <returns>a String representing the content encoded by the PDF417 code</returns>
/// <exception cref="FormatException">if a PDF417 cannot be decoded</exception>
/// </summary>
public Result Decode(BinaryBitmap image)
{
return Decode(image, null);
}
/// <summary>
/// Locates and decodes a barcode in some format within an image. This method also accepts
/// hints, each possibly associated to some data, which may help the implementation decode.
/// **Note** this will return the FIRST barcode discovered if there are many.
/// </summary>
/// <param name="image">image of barcode to decode</param>
/// <param name="hints">passed as a <see cref="IDictionary{TKey, TValue}"/> from <see cref="DecodeHintType"/>
/// to arbitrary data. The
/// meaning of the data depends upon the hint type. The implementation may or may not do
/// anything with these hints.</param>
/// <returns>
/// String which the barcode encodes
/// </returns>
public Result Decode(BinaryBitmap image,
IDictionary<DecodeHintType, object> hints)
{
Result[] results = Decode(image, hints, false);
if (results.Length == 0)
{
return null;
} else
{
return results[0]; // First barcode discovered.
}
}
/// <summary>
/// Locates and decodes Multiple PDF417 codes in an image.
///
/// <returns>an array of Strings representing the content encoded by the PDF417 codes</returns>
/// </summary>
public Result[] DecodeMultiple(BinaryBitmap image)
{
return DecodeMultiple(image, null);
}
/// <summary>
/// Locates and decodes multiple barcodes in some format within an image. This method also accepts
/// hints, each possibly associated to some data, which may help the implementation decode.
/// </summary>
/// <param name="image">image of barcode to decode</param>
/// <param name="hints">passed as a <see cref="IDictionary{TKey, TValue}"/> from <see cref="DecodeHintType"/>
/// to arbitrary data. The
/// meaning of the data depends upon the hint type. The implementation may or may not do
/// anything with these hints.</param>
/// <returns>
/// String which the barcodes encode
/// </returns>
public Result[] DecodeMultiple(BinaryBitmap image,
IDictionary<DecodeHintType, object> hints)
{
return Decode(image, hints, true);
}
/// <summary>
/// Decode the specified image, with the hints and optionally multiple barcodes.
/// Based on Owen's Comments in <see cref="ZXing.ReaderException"/>, this method has been modified to continue silently
/// if a barcode was not decoded where it was detected instead of throwing a new exception object.
/// </summary>
/// <param name="image">Image.</param>
/// <param name="hints">Hints.</param>
/// <param name="multiple">If set to <c>true</c> multiple.</param>
private static Result[] Decode(BinaryBitmap image, IDictionary<DecodeHintType, object> hints, bool multiple)
{
List<Result> results = new List<Result>();
PDF417DetectorResult detectorResult = Detector.Detect(image, hints, multiple);
foreach (ResultPoint[] points in detectorResult.Points)
{
DecoderResult decoderResult = PDF417ScanningDecoder.Decode(detectorResult.Bits, points[4], points[5],
points[6], points[7], GetMinCodewordWidth(points), GetMaxCodewordWidth(points));
if (decoderResult == null)
{
// See comments re: Exceptions above
// continue;
throw ReaderException.Instance;
}
System.Diagnostics.Debug.WriteLine("Result " + points.ToString() + " > " + decoderResult.Text + " " + decoderResult.RawBytes);
Result result = new Result(decoderResult.Text, decoderResult.RawBytes, points, BarcodeFormat.PDF_417);
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, decoderResult.ECLevel);
PDF417ResultMetadata pdf417ResultMetadata = (PDF417ResultMetadata)decoderResult.Other;
if (pdf417ResultMetadata != null)
{
result.putMetadata(ResultMetadataType.PDF417_EXTRA_METADATA, pdf417ResultMetadata);
}
results.Add(result);
}
return results.ToArray();
}
/// <summary>
/// Gets the maximum width of the barcode
/// </summary>
/// <returns>The max width.</returns>
/// <param name="p1">P1.</param>
/// <param name="p2">P2.</param>
private static int GetMaxWidth(ResultPoint p1, ResultPoint p2)
{
if (p1 == null || p2 == null)
{
return 0;
}
return (int)Math.Abs(p1.X - p2.X);
}
/// <summary>
/// Gets the minimum width of the barcode
/// </summary>
/// <returns>The minimum width.</returns>
/// <param name="p1">P1.</param>
/// <param name="p2">P2.</param>
private static int GetMinWidth(ResultPoint p1, ResultPoint p2)
{
if (p1 == null || p2 == null)
{
return int.MaxValue;
}
return (int)Math.Abs(p1.X - p2.X);
}
/// <summary>
/// Gets the maximum width of the codeword.
/// </summary>
/// <returns>The max codeword width.</returns>
/// <param name="p">P.</param>
private static int GetMaxCodewordWidth(ResultPoint[] p)
{
return Math.Max(
Math.Max(GetMaxWidth(p[0], p[4]), GetMaxWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /
PDF417Common.MODULES_IN_STOP_PATTERN),
Math.Max(GetMaxWidth(p[1], p[5]), GetMaxWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /
PDF417Common.MODULES_IN_STOP_PATTERN));
}
/// <summary>
/// Gets the minimum width of the codeword.
/// </summary>
/// <returns>The minimum codeword width.</returns>
/// <param name="p">P.</param>
private static int GetMinCodewordWidth(ResultPoint[] p)
{
return Math.Min(
Math.Min(GetMinWidth(p[0], p[4]), GetMinWidth(p[6], p[2]) * PDF417Common.MODULES_IN_CODEWORD /
PDF417Common.MODULES_IN_STOP_PATTERN),
Math.Min(GetMinWidth(p[1], p[5]), GetMinWidth(p[7], p[3]) * PDF417Common.MODULES_IN_CODEWORD /
PDF417Common.MODULES_IN_STOP_PATTERN));
}
/// <summary>
/// Resets any internal state the implementation has after a decode, to prepare it
/// for reuse.
/// </summary>
public void Reset()
{
// do nothing
}
/// <summary>
/// This method detects a code in a "pure" image -- that is, pure monochrome image
/// which contains only an unrotated, unskewed, image of a code, with some white border
/// around it. This is a specialized method that works exceptionally fast in this special
/// case.
///
/// <see cref="QrCode.QRCodeReader.extractPureBits(BitMatrix)" />
/// <see cref="Datamatrix.DataMatrixReader.extractPureBits(BitMatrix)" />
/// </summary>
private static BitMatrix ExtractPureBits(BitMatrix image)
{
int[] leftTopBlack = image.getTopLeftOnBit();
int[] rightBottomBlack = image.getBottomRightOnBit();
if (leftTopBlack == null || rightBottomBlack == null)
{
return null;
}
int moduleSize;
if (!PDF417Reader.ModuleSize(leftTopBlack, image, out moduleSize))
return null;
int top = leftTopBlack[1];
int bottom = rightBottomBlack[1];
int left;
if (!FindPatternStart(leftTopBlack[0], top, image, out left))
return null;
int right;
if (!FindPatternEnd(leftTopBlack[0], top, image, out right))
return null;
int matrixWidth = (right - left + 1) / moduleSize;
int matrixHeight = (bottom - top + 1) / moduleSize;
if (matrixWidth <= 0 || matrixHeight <= 0)
{
return null;
}
// Push in the "border" by half the module width so that we start
// sampling in the middle of the module. Just in case the image is a
// little off, this will help recover.
int nudge = moduleSize >> 1;
top += nudge;
left += nudge;
// Now just read off the bits
var bits = new BitMatrix(matrixWidth, matrixHeight);
for (int y = 0; y < matrixHeight; y++)
{
int iOffset = top + y * moduleSize;
for (int x = 0; x < matrixWidth; x++)
{
if (image[left + x * moduleSize, iOffset])
{
bits[x, y] = true;
}
}
}
return bits;
}
/// <summary>
/// Computes the Module Size
/// </summary>
/// <returns><c>true</c>, if size was moduled, <c>false</c> otherwise.</returns>
/// <param name="leftTopBlack">Left top black.</param>
/// <param name="image">Image.</param>
/// <param name="msize">Msize.</param>
private static bool ModuleSize(int[] leftTopBlack, BitMatrix image, out int msize)
{
int x = leftTopBlack[0];
int y = leftTopBlack[1];
int width = image.Width;
while (x < width && image[x, y])
{
x++;
}
if (x == width)
{
msize = 0;
return false;
}
msize = (int)((uint)(x - leftTopBlack[0]) >> 3); // (x - leftTopBlack[0]) >>> 3// We've crossed left first bar, which is 8x
if (msize == 0)
{
return false;
}
return true;
}
/// <summary>
/// Finds the pattern start.
/// </summary>
/// <returns><c>true</c>, if pattern start was found, <c>false</c> otherwise.</returns>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <param name="image">Image.</param>
/// <param name="start">Start.</param>
private static bool FindPatternStart(int x, int y, BitMatrix image, out int start)
{
int width = image.Width;
start = x;
// start should be on black
int transitions = 0;
bool black = true;
while (start < width - 1 && transitions < 8)
{
start++;
bool newBlack = image[start, y];
if (black != newBlack)
{
transitions++;
}
black = newBlack;
}
if (start == width - 1)
{
return false;
}
return true;
}
/// <summary>
/// Finds the pattern end.
/// </summary>
/// <returns><c>true</c>, if pattern end was found, <c>false</c> otherwise.</returns>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <param name="image">Image.</param>
/// <param name="end">End.</param>
private static bool FindPatternEnd(int x, int y, BitMatrix image, out int end)
{
int width = image.Width;
end = width - 1;
// end should be on black
while (end > x && !image[end, y])
{
end--;
}
int transitions = 0;
bool black = true;
while (end > x && transitions < 9)
{
end--;
bool newBlack = image[end, y];
if (black != newBlack)
{
transitions++;
}
black = newBlack;
}
if (end == x)
{
return false;
}
return true;
}
}
}

View file

@ -1,33 +0,0 @@
// /*
// * Copyright 2009 ZXing 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;
namespace ZXing.PDF417
{
/// <summary>
/// PDF 417 result meta data. Skipped private backing stores.
/// <author>Guenther Grau (Java Core)</author>
/// <author>Stephen Furlani (C# Port)</author>
/// </summary>
public sealed class PDF417ResultMetadata
{
public int SegmentIndex { get; set; }
public string FileId { get; set; }
public int[] OptionalData { get; set; }
public bool IsLastSegment { get; set; }
}
}

View file

@ -1,192 +0,0 @@
/*
* Copyright 2012 ZXing 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;
using ZXing.PDF417.Internal;
namespace ZXing.PDF417
{
/// <summary>
/// <author>Jacob Haynes</author>
/// <author>qwandor@google.com (Andrew Walbran)</author>
/// </summary>
public sealed class PDF417Writer : Writer
{
/// <summary>
/// </summary>
/// <param name="contents">The contents to encode in the barcode</param>
/// <param name="format">The barcode format to generate</param>
/// <param name="width">The preferred width in pixels</param>
/// <param name="height">The preferred height in pixels</param>
/// <param name="hints">Additional parameters to supply to the encoder</param>
/// <returns>
/// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
/// </returns>
public BitMatrix encode(String contents,
BarcodeFormat format,
int width,
int height,
IDictionary<EncodeHintType, object> hints)
{
if (format != BarcodeFormat.PDF_417)
{
throw new ArgumentException("Can only encode PDF_417, but got " + format);
}
var encoder = new Internal.PDF417();
if (hints != null)
{
if (hints.ContainsKey(EncodeHintType.PDF417_COMPACT))
{
encoder.setCompact((Boolean)hints[EncodeHintType.PDF417_COMPACT]);
}
if (hints.ContainsKey(EncodeHintType.PDF417_COMPACTION))
{
encoder.setCompaction((Compaction)hints[EncodeHintType.PDF417_COMPACTION]);
}
if (hints.ContainsKey(EncodeHintType.PDF417_DIMENSIONS))
{
Dimensions dimensions = (Dimensions)hints[EncodeHintType.PDF417_DIMENSIONS];
encoder.setDimensions(dimensions.MaxCols,
dimensions.MinCols,
dimensions.MaxRows,
dimensions.MinRows);
}
}
return bitMatrixFromEncoder(encoder, contents, width, height);
}
/// <summary>
/// Encode a barcode using the default settings.
/// </summary>
/// <param name="contents">The contents to encode in the barcode</param>
/// <param name="format">The barcode format to generate</param>
/// <param name="width">The preferred width in pixels</param>
/// <param name="height">The preferred height in pixels</param>
/// <returns>
/// The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
/// </returns>
public BitMatrix encode(String contents,
BarcodeFormat format,
int width,
int height)
{
return encode(contents, format, width, height, null);
}
/// <summary>
/// Takes encoder, accounts for width/height, and retrieves bit matrix
/// </summary>
private static BitMatrix bitMatrixFromEncoder(Internal.PDF417 encoder,
String contents,
int width,
int height)
{
const int errorCorrectionLevel = 2;
encoder.generateBarcodeLogic(contents, errorCorrectionLevel);
const int lineThickness = 2;
const int aspectRatio = 4;
sbyte[][] originalScale = encoder.BarcodeMatrix.getScaledMatrix(lineThickness, aspectRatio * lineThickness);
bool rotated = false;
if ((height > width) ^ (originalScale[0].Length < originalScale.Length))
{
originalScale = rotateArray(originalScale);
rotated = true;
}
int scaleX = width / originalScale[0].Length;
int scaleY = height / originalScale.Length;
int scale;
if (scaleX < scaleY)
{
scale = scaleX;
}
else
{
scale = scaleY;
}
if (scale > 1)
{
sbyte[][] scaledMatrix =
encoder.BarcodeMatrix.getScaledMatrix(scale * lineThickness, scale * aspectRatio * lineThickness);
if (rotated)
{
scaledMatrix = rotateArray(scaledMatrix);
}
return bitMatrixFrombitArray(scaledMatrix);
}
return bitMatrixFrombitArray(originalScale);
}
/// <summary>
/// This takes an array holding the values of the PDF 417
///
/// <param name="input">a byte array of information with 0 is black, and 1 is white</param>
/// <returns>BitMatrix of the input</returns>
/// </summary>
private static BitMatrix bitMatrixFrombitArray(sbyte[][] input)
{
// Creates a small whitespace border around the barcode
const int whiteSpace = 30;
// Creates the bitmatrix with extra space for whitespace
var output = new BitMatrix(input[0].Length + 2 * whiteSpace, input.Length + 2 * whiteSpace);
var yOutput = output.Height - whiteSpace;
for (int y = 0; y < input.Length; y++)
{
for (int x = 0; x < input[0].Length; x++)
{
// Zero is white in the bytematrix
if (input[y][x] == 1)
{
output[x + whiteSpace, yOutput] = true;
}
}
yOutput--;
}
return output;
}
/// <summary>
/// Takes and rotates the it 90 degrees
/// </summary>
private static sbyte[][] rotateArray(sbyte[][] bitarray)
{
sbyte[][] temp = new sbyte[bitarray[0].Length][];
for (int idx = 0; idx < bitarray[0].Length; idx++)
temp[idx] = new sbyte[bitarray.Length];
for (int ii = 0; ii < bitarray.Length; ii++)
{
// This makes the direction consistent on screen when rotating the
// screen;
int inverseii = bitarray.Length - ii - 1;
for (int jj = 0; jj < bitarray[0].Length; jj++)
{
temp[jj][inverseii] = bitarray[ii][jj];
}
}
return temp;
}
}
}

View file

@ -1,45 +0,0 @@
// /*
// * Copyright 2009 ZXing 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 ZXing.Common;
namespace ZXing.PDF417.Internal
{
/// <summary>
/// Metadata about a PDF417 Barcode
/// </summary>
/// <author>Guenther Grau (Java Core)</author>
/// <author>Stephen Furlani (C# Port)</author>
public sealed class BarcodeMetadata
{
public int ColumnCount { get; private set; }
public int ErrorCorrectionLevel { get; private set; }
public int RowCountUpper { get; private set; }
public int RowCountLower { get; private set; }
public int RowCount { get; private set; }
public BarcodeMetadata(int columnCount, int rowCountUpperPart, int rowCountLowerPart, int errorCorrectionLevel)
{
this.ColumnCount = columnCount;
this.ErrorCorrectionLevel = errorCorrectionLevel;
this.RowCountUpper = rowCountUpperPart;
this.RowCountLower = rowCountLowerPart;
this.RowCount = rowCountLowerPart + rowCountUpperPart;
}
}
}

View file

@ -1,97 +0,0 @@
// /*
// * Copyright 2009 ZXing 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.Linq;
using System.Collections.Generic;
using ZXing.Common;
namespace ZXing.PDF417.Internal
{
/// <summary>
/// A Barcode Value for the PDF417 barcode.
/// The scanner will iterate through the bitmatrix,
/// and given the different methods or iterations
/// will increment a given barcode value's confidence.
///
/// When done, this will return the values of highest confidence.
/// </summary>
/// <author>Guenther Grau (Java Core)</author>
/// <author>Stephen Furlani (C# Port)</author>
public sealed class BarcodeValue
{
private readonly IDictionary<int, int> values = new Dictionary<int, int>();
/// <summary>
/// Incremenets the Confidence for a given value. (Adds an occurance of a value)
///
/// </summary>
/// <param name="value">Value.</param>
public void SetValue(int barcodeValue)
{
// ints can't be null in C# - check for containmentship
if (values.ContainsKey(barcodeValue))
{
int confidence = values[barcodeValue];
confidence ++;
values[barcodeValue] = confidence;
} else
{
values.Add(barcodeValue, 1);
}
}
/// <summary>
/// Determines the maximum occurrence of a set value and returns all values which were set with this occurrence.
/// </summary>
/// <returns>an array of int, containing the values with the highest occurrence, or null, if no value was set.</returns>
public int[] GetValue()
{
// if (confidence == null || confidence.Count == 0)
// {
// return new int[0];
// }
// int max = (from pair in confidence select pair.Value).Max();
// return (from pair in confidence where pair.Value == max select pair.Key).ToArray();
int maxConfidence = -1;
List<int> result = new List<int>();
foreach (var entry in values)
{
if (entry.Value > maxConfidence)
{
maxConfidence = entry.Value;
result.Clear();
result.Add(entry.Key);
} else if (entry.Value == maxConfidence)
{
result.Add(entry.Key);
}
}
return result.ToArray();
}
/// <summary>
/// Returns the confience value for a given barcode value
/// </summary>
/// <param name="barcodeValue">Barcode value.</param>
public int GetConfidence(int barcodeValue)
{
return values.ContainsKey(barcodeValue) ? values[barcodeValue] : 0;
}
}
}

View file

@ -1,198 +0,0 @@
// /*
// * Copyright 2009 ZXing 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 ZXing.Common;
namespace ZXing.PDF417.Internal
{
/// <summary>
/// A Bounding Box helper class
/// </summary>
/// <author>Guenther Grau (Java Core)</author>
/// <author>Stephen Furlani (C# Port)</author>
public sealed class BoundingBox
{
private BitMatrix Image { get; set; }
public ResultPoint TopLeft { get; private set; }
public ResultPoint TopRight { get; private set; }
public ResultPoint BottomLeft { get; private set; }
public ResultPoint BottomRight { get; private set; }
public int MinX { get; private set; }
public int MaxX { get; private set; }
public int MinY { get; private set; }
public int MaxY { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.BoundingBox"/> class.
/// Will throw an exception if the corner points don't match up correctly
/// </summary>
/// <param name="image">Image.</param>
/// <param name="topLeft">Top left.</param>
/// <param name="topRight">Top right.</param>
/// <param name="bottomLeft">Bottom left.</param>
/// <param name="bottomRight">Bottom right.</param>
public BoundingBox(BitMatrix image,
ResultPoint topLeft,
ResultPoint bottomLeft,
ResultPoint topRight,
ResultPoint bottomRight)
{
if ((topLeft == null && topRight == null) ||
(bottomLeft == null && bottomRight == null) ||
(topLeft != null && bottomLeft == null) ||
(topRight != null && bottomRight == null))
{
throw ReaderException.Instance;
}
this.Image = image;
this.TopLeft = topLeft;
this.TopRight = topRight;
this.BottomLeft = bottomLeft;
this.BottomRight = bottomRight;
CalculateMinMaxValues();
}
/// <summary>
/// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.BoundingBox"/> class.
/// </summary>
/// <param name="box">Box.</param>
public BoundingBox(BoundingBox box) : this (box.Image, box.TopLeft,box.BottomLeft, box.TopRight, box.BottomRight)
{
}
/// <summary>
/// Calculates the minimum and maximum X & Y values based on the corner points.
/// </summary>
private void CalculateMinMaxValues()
{
// Constructor ensures that either Left or Right is not null
if (TopLeft == null)
{
TopLeft = new ResultPoint(0, TopRight.Y);
BottomLeft = new ResultPoint(0, BottomRight.Y);
} else if (TopRight == null)
{
TopRight = new ResultPoint(Image.Width - 1, TopLeft.Y);
BottomRight = new ResultPoint(Image.Width - 1, TopLeft.Y);
}
MinX = (int)Math.Min(TopLeft.X, BottomLeft.X);
MinY = (int)Math.Min(TopLeft.Y, TopRight.Y);
MaxX = (int)Math.Max(TopRight.X, BottomRight.X);
MaxY = (int)Math.Max(BottomLeft.Y, BottomRight.Y); // Y points down
}
/// <summary>
/// If we adjust the width, set a new right corner coordinate and recalculate
/// </summary>
/// <param name="topRight">Top right.</param>
internal void SetTopRight(ResultPoint topRight)
{
this.TopRight = topRight;
CalculateMinMaxValues();
}
/// <summary>
/// If we adjust the width, set a new right corner coordinate and recalculate
/// </summary>
/// <param name="bottomRight">Bottom right.</param>
internal void SetBottomRight(ResultPoint bottomRight)
{
this.BottomRight = bottomRight;
CalculateMinMaxValues();
}
/// <summary>
/// Merge two Bounding Boxes, getting the left corners of left, and the right corners of right
/// (Images should be the same)
/// </summary>
/// <param name="left">Left.</param>
/// <param name="right">Right.</param>
internal static BoundingBox Merge(BoundingBox left, BoundingBox right)
{
if (left == null)
return right;
if (right == null)
return left;
return new BoundingBox(left.Image, left.TopLeft, left.BottomLeft, right.TopRight, right.BottomRight);
}
/// <summary>
/// Adds the missing rows.
/// </summary>
/// <returns>The missing rows.</returns>
/// <param name="missingStartRows">Missing start rows.</param>
/// <param name="missingEndRows">Missing end rows.</param>
/// <param name="isLeft">If set to <c>true</c> is left.</param>
public BoundingBox AddMissingRows(int missingStartRows, int missingEndRows, bool isLeft)
{
ResultPoint newTopLeft = TopLeft;
ResultPoint newBottomLeft = BottomLeft;
ResultPoint newTopRight = TopRight;
ResultPoint newBottomRight = BottomRight;
if (missingStartRows > 0)
{
ResultPoint top = isLeft ? TopLeft : TopRight;
int newMinY = (int)top.Y - missingStartRows;
if (newMinY < 0)
{
newMinY = 0;
}
// TODO use existing points to better interpolate the new x positions
ResultPoint newTop = new ResultPoint(top.X, newMinY);
if (isLeft)
{
newTopLeft = newTop;
} else
{
newTopRight = newTop;
}
}
if (missingEndRows > 0)
{
ResultPoint bottom = isLeft ? BottomLeft : BottomRight;
int newMaxY = (int)bottom.Y + missingEndRows;
if (newMaxY >= Image.Height)
{
newMaxY = Image.Height - 1;
}
// TODO use existing points to better interpolate the new x positions
ResultPoint newBottom = new ResultPoint(bottom.X, newMaxY);
if (isLeft)
{
newBottomLeft = newBottom;
} else
{
newBottomRight = newBottom;
}
}
CalculateMinMaxValues();
return new BoundingBox(Image, newTopLeft, newBottomLeft, newTopRight, newBottomRight);
}
}
}

View file

@ -1,108 +0,0 @@
// /*
// * Copyright 2009 ZXing 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 ZXing.Common;
namespace ZXing.PDF417.Internal
{
/// <summary>
/// A Codeword in the PDF417 barcode
/// </summary>
/// <author>Guenther Grau (Java Core)</author>
/// <author>Stephen Furlani (C# Port)</author>
public sealed class Codeword
{
/// <summary>
/// Default value for the RowNumber (-1 being an invalid real number)
/// </summary>
private static readonly int BARCODE_ROW_UNKNOWN = -1;
public int StartX { get; private set; }
public int EndX { get; private set; }
public int Bucket { get; private set; }
public int Value { get; private set; }
public int RowNumber { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ZXing.PDF417.Internal.Codeword"/> class.
/// </summary>
/// <param name="startX">Start x.</param>
/// <param name="endX">End x.</param>
/// <param name="bucket">Bucket.</param>
/// <param name="value">Value.</param>
public Codeword(int startX, int endX, int bucket, int value)
{
this.StartX = startX;
this.EndX = endX;
this.Bucket = bucket;
this.Value = value;
this.RowNumber = BARCODE_ROW_UNKNOWN;
}
/// <summary>
/// Gets the width.
/// </summary>
/// <value>The width.</value>
public int Width
{
get
{
return EndX - StartX;
}
}
/// <summary>
/// Gets a value indicating whether this instance has valid row number.
/// </summary>
/// <value><c>true</c> if this instance has valid row number; otherwise, <c>false</c>.</value>
public bool HasValidRowNumber
{
get
{
return IsValidRowNumber(RowNumber);
}
}
/// <summary>
/// Determines whether this instance is valid row number the specified rowNumber.
/// </summary>
/// <returns><c>true</c> if this instance is valid row number the specified rowNumber; otherwise, <c>false</c>.</returns>
/// <param name="rowNumber">Row number.</param>
public bool IsValidRowNumber(int rowNumber)
{
return rowNumber != BARCODE_ROW_UNKNOWN && Bucket == (rowNumber % 3) * 3;
}
/// <summary>
/// Sets the row number as the row's indicator column.
/// </summary>
public void SetRowNumberAsRowIndicatorColumn()
{
this.RowNumber = (Value / 30) * 3 + Bucket / 3;
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents the current <see cref="ZXing.PDF417.Internal.Codeword"/>.
/// </summary>
/// <returns>A <see cref="System.String"/> that represents the current <see cref="ZXing.PDF417.Internal.Codeword"/>.</returns>
public override string ToString()
{
return RowNumber + "|" + Value;
}
}
}

Some files were not shown because too many files have changed in this diff Show more